Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement GetProcessId() and GetCurrentProcess() #49

Merged
merged 10 commits into from
Jan 25, 2016
2 changes: 2 additions & 0 deletions pywincffi/core/cdefs/headers/functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ VOID SetLastError(DWORD);

// Processes
HANDLE OpenProcess(DWORD, BOOL, DWORD);
HANDLE GetCurrentProcess();
DWORD GetProcessId(HANDLE);

// Pipes
BOOL CreatePipe(PHANDLE, PHANDLE, LPSECURITY_ATTRIBUTES, DWORD);
Expand Down
44 changes: 43 additions & 1 deletion pywincffi/kernel32/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import six

from pywincffi.core import dist
from pywincffi.core.checks import input_check, error_check
from pywincffi.core.checks import Enums, input_check, error_check


def OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId):
Expand Down Expand Up @@ -55,3 +55,45 @@ def OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId):
)
error_check("OpenProcess")
return handle


def GetCurrentProcess():
"""
Returns a handle to the current thread.

.. seealso::

https://msdn.microsoft.com/en-us/library/ms683179

.. note::

Calling :func:`pywincffi.kernel32.io.CloseHandle` on the handle
produced by this function will produce an exception.

:returns:
The handle to the current process.
"""
_, library = dist.load()
return library.GetCurrentProcess()


def GetProcessId(Process): # pylint: disable=invalid-name
"""
Returns the pid of the process handle provided in ``Process``.

.. seealso::

https://msdn.microsoft.com/en-us/library/ms683215

:param handle Process:
The handle of the process to re

:return:
Returns an integer which represents the pid of the given
process handle.
"""
input_check("Process", Process, Enums.HANDLE)
_, library = dist.load()
pid = library.GetProcessId(Process)
error_check("GetProcessId")
return pid
61 changes: 59 additions & 2 deletions tests/test_kernel32/test_process.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import os
import subprocess
import sys

from pywincffi.core import dist
from pywincffi.dev.testutil import TestCase
from pywincffi.exceptions import WindowsAPIError
from pywincffi.kernel32.io import CloseHandle
from pywincffi.kernel32.process import OpenProcess
from pywincffi.kernel32.process import (
OpenProcess, GetCurrentProcess, GetProcessId)


class TestOpenProcess(TestCase):
"""
Tests for :func:`pywincffi.kernel32.OpenProcess`
Tests for :func:`pywincffi.kernel32.process.OpenProcess`
"""
def test_returns_handle(self):
ffi, library = dist.load()
Expand All @@ -31,10 +34,64 @@ def test_access_denied_for_null_desired_access(self):

self.assertEqual(error.exception.code, 5)

def test_get_process_id_current_process(self):
# We should be able to access the pid of the process
# we created a handle to.
_, library = dist.load()

handle = OpenProcess(
library.PROCESS_QUERY_INFORMATION,
False,
os.getpid()
)
self.assertEqual(GetProcessId(handle), os.getpid())
CloseHandle(handle)


class TestGetCurrentProcess(TestCase):
"""
Tests for :func:`pywincffi.kernel32.process.GetCurrentProcess`
"""
def test_returns_handle(self):
ffi, _ = dist.load()
handle = GetCurrentProcess()
typeof = ffi.typeof(handle)
self.assertEqual(typeof.kind, "pointer")
self.assertEqual(typeof.cname, "void *")

def test_returns_same_handle(self):
# GetCurrentProcess is somewhat special in that it will
# always return a handle to the same object. However, __eq__ is not
# opaque so the string representation of the two handles
# should always match since it contains the address of the object
# in memory.
self.assertEqual(repr(GetCurrentProcess()), repr(GetCurrentProcess()))

def test_handle_is_current_process(self):
handle = GetCurrentProcess()
self.assertEqual(GetProcessId(handle), os.getpid())

def test_handle_is_valid(self):
_, library = dist.load()
handle = OpenProcess(
library.PROCESS_QUERY_INFORMATION, False, os.getpid())

# If the handle were invalid, this would fail.
CloseHandle(handle)


class TestGetProcessId(TestCase):
"""
Tests for :func:`pywincffi.kernel32.process.GetProcessId`
"""
def test_get_pid_of_external_process(self):
_, library = dist.load()
python = subprocess.Popen(
[sys.executable, "-c", "import time; time.sleep(3)"]
)
self.addCleanup(python.terminate)
expected_pid = python.pid
handle = OpenProcess(
library.PROCESS_QUERY_INFORMATION, False, expected_pid)
self.assertEqual(GetProcessId(handle), expected_pid)
CloseHandle(handle)