Skip to content

Commit

Permalink
Merge pull request #49 from opalmer/get_current_process
Browse files Browse the repository at this point in the history
Implement GetProcessId() and GetCurrentProcess()
  • Loading branch information
opalmer committed Jan 25, 2016
2 parents 593d856 + 0c762aa commit a601416
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 3 deletions.
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)

0 comments on commit a601416

Please sign in to comment.