123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- from ctypes import c_void_p, POINTER, sizeof, Structure, windll, WinError, WINFUNCTYPE
- from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LPCWSTR, LPWSTR, UINT, WORD, \
- c_buffer, c_ulong, byref
- from qijo import QueryInformationJobObject
- LPVOID = c_void_p
- LPBYTE = POINTER(BYTE)
- LPDWORD = POINTER(DWORD)
- LPBOOL = POINTER(BOOL)
- def ErrCheckBool(result, func, args):
- """errcheck function for Windows functions that return a BOOL True
- on success"""
- if not result:
- raise WinError()
- return args
- class AutoHANDLE(HANDLE):
- """Subclass of HANDLE which will call CloseHandle() on deletion."""
-
- CloseHandleProto = WINFUNCTYPE(BOOL, HANDLE)
- CloseHandle = CloseHandleProto(("CloseHandle", windll.kernel32))
- CloseHandle.errcheck = ErrCheckBool
-
- def Close(self):
- if self.value and self.value != HANDLE(-1).value:
- self.CloseHandle(self)
- self.value = 0
-
- def __del__(self):
- self.Close()
- def __int__(self):
- return self.value
- def ErrCheckHandle(result, func, args):
- """errcheck function for Windows functions that return a HANDLE."""
- if not result:
- raise WinError()
- return AutoHANDLE(result)
- class PROCESS_INFORMATION(Structure):
- _fields_ = [("hProcess", HANDLE),
- ("hThread", HANDLE),
- ("dwProcessID", DWORD),
- ("dwThreadID", DWORD)]
- def __init__(self):
- Structure.__init__(self)
-
- self.cb = sizeof(self)
- LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION)
- class STARTUPINFO(Structure):
- _fields_ = [("cb", DWORD),
- ("lpReserved", LPWSTR),
- ("lpDesktop", LPWSTR),
- ("lpTitle", LPWSTR),
- ("dwX", DWORD),
- ("dwY", DWORD),
- ("dwXSize", DWORD),
- ("dwYSize", DWORD),
- ("dwXCountChars", DWORD),
- ("dwYCountChars", DWORD),
- ("dwFillAttribute", DWORD),
- ("dwFlags", DWORD),
- ("wShowWindow", WORD),
- ("cbReserved2", WORD),
- ("lpReserved2", LPBYTE),
- ("hStdInput", HANDLE),
- ("hStdOutput", HANDLE),
- ("hStdError", HANDLE)
- ]
- LPSTARTUPINFO = POINTER(STARTUPINFO)
- SW_HIDE = 0
- STARTF_USESHOWWINDOW = 0x01
- STARTF_USESIZE = 0x02
- STARTF_USEPOSITION = 0x04
- STARTF_USECOUNTCHARS = 0x08
- STARTF_USEFILLATTRIBUTE = 0x10
- STARTF_RUNFULLSCREEN = 0x20
- STARTF_FORCEONFEEDBACK = 0x40
- STARTF_FORCEOFFFEEDBACK = 0x80
- STARTF_USESTDHANDLES = 0x100
- class EnvironmentBlock:
- """An object which can be passed as the lpEnv parameter of CreateProcess.
- It is initialized with a dictionary."""
- def __init__(self, dict):
- if not dict:
- self._as_parameter_ = None
- else:
- values = ["%s=%s" % (key, value)
- for (key, value) in dict.iteritems()]
- values.append("")
- self._as_parameter_ = LPCWSTR("\0".join(values))
-
- CreateProcessProto = WINFUNCTYPE(BOOL,
- LPCWSTR,
- LPWSTR,
- LPVOID,
- LPVOID,
- BOOL,
- DWORD,
- LPVOID,
- LPCWSTR,
- LPSTARTUPINFO,
- LPPROCESS_INFORMATION
- )
- CreateProcessFlags = ((1, "lpApplicationName", None),
- (1, "lpCommandLine"),
- (1, "lpProcessAttributes", None),
- (1, "lpThreadAttributes", None),
- (1, "bInheritHandles", True),
- (1, "dwCreationFlags", 0),
- (1, "lpEnvironment", None),
- (1, "lpCurrentDirectory", None),
- (1, "lpStartupInfo"),
- (2, "lpProcessInformation"))
- def ErrCheckCreateProcess(result, func, args):
- ErrCheckBool(result, func, args)
-
- pi = args[9]
- return AutoHANDLE(pi.hProcess), AutoHANDLE(pi.hThread), pi.dwProcessID, pi.dwThreadID
- CreateProcess = CreateProcessProto(("CreateProcessW", windll.kernel32),
- CreateProcessFlags)
- CreateProcess.errcheck = ErrCheckCreateProcess
- CREATE_BREAKAWAY_FROM_JOB = 0x01000000
- CREATE_DEFAULT_ERROR_MODE = 0x04000000
- CREATE_NEW_CONSOLE = 0x00000010
- CREATE_NEW_PROCESS_GROUP = 0x00000200
- CREATE_NO_WINDOW = 0x08000000
- CREATE_SUSPENDED = 0x00000004
- CREATE_UNICODE_ENVIRONMENT = 0x00000400
- JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800
- JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = 0x00001000
- DEBUG_ONLY_THIS_PROCESS = 0x00000002
- DEBUG_PROCESS = 0x00000001
- DETACHED_PROCESS = 0x00000008
- CreateJobObjectProto = WINFUNCTYPE(HANDLE,
- LPVOID,
- LPCWSTR
- )
- CreateJobObjectFlags = ((1, "lpJobAttributes", None),
- (1, "lpName", None))
- CreateJobObject = CreateJobObjectProto(("CreateJobObjectW", windll.kernel32),
- CreateJobObjectFlags)
- CreateJobObject.errcheck = ErrCheckHandle
- AssignProcessToJobObjectProto = WINFUNCTYPE(BOOL,
- HANDLE,
- HANDLE
- )
- AssignProcessToJobObjectFlags = ((1, "hJob"),
- (1, "hProcess"))
- AssignProcessToJobObject = AssignProcessToJobObjectProto(
- ("AssignProcessToJobObject", windll.kernel32),
- AssignProcessToJobObjectFlags)
- AssignProcessToJobObject.errcheck = ErrCheckBool
- GetCurrentProcessProto = WINFUNCTYPE(HANDLE
- )
- GetCurrentProcessFlags = ()
- GetCurrentProcess = GetCurrentProcessProto(
- ("GetCurrentProcess", windll.kernel32),
- GetCurrentProcessFlags)
- GetCurrentProcess.errcheck = ErrCheckHandle
- try:
- IsProcessInJobProto = WINFUNCTYPE(BOOL,
- HANDLE,
- HANDLE,
- LPBOOL
- )
- IsProcessInJobFlags = ((1, "ProcessHandle"),
- (1, "JobHandle", HANDLE(0)),
- (2, "Result"))
- IsProcessInJob = IsProcessInJobProto(
- ("IsProcessInJob", windll.kernel32),
- IsProcessInJobFlags)
- IsProcessInJob.errcheck = ErrCheckBool
- except AttributeError:
-
- def IsProcessInJob(process):
- return False
- def ErrCheckResumeThread(result, func, args):
- if result == -1:
- raise WinError()
- return args
- ResumeThreadProto = WINFUNCTYPE(DWORD,
- HANDLE
- )
- ResumeThreadFlags = ((1, "hThread"),)
- ResumeThread = ResumeThreadProto(("ResumeThread", windll.kernel32),
- ResumeThreadFlags)
- ResumeThread.errcheck = ErrCheckResumeThread
- TerminateProcessProto = WINFUNCTYPE(BOOL,
- HANDLE,
- UINT
- )
- TerminateProcessFlags = ((1, "hProcess"),
- (1, "uExitCode", 127))
- TerminateProcess = TerminateProcessProto(
- ("TerminateProcess", windll.kernel32),
- TerminateProcessFlags)
- TerminateProcess.errcheck = ErrCheckBool
- TerminateJobObjectProto = WINFUNCTYPE(BOOL,
- HANDLE,
- UINT
- )
- TerminateJobObjectFlags = ((1, "hJob"),
- (1, "uExitCode", 127))
- TerminateJobObject = TerminateJobObjectProto(
- ("TerminateJobObject", windll.kernel32),
- TerminateJobObjectFlags)
- TerminateJobObject.errcheck = ErrCheckBool
- WaitForSingleObjectProto = WINFUNCTYPE(DWORD,
- HANDLE,
- DWORD,
- )
- WaitForSingleObjectFlags = ((1, "hHandle"),
- (1, "dwMilliseconds", -1))
- WaitForSingleObject = WaitForSingleObjectProto(
- ("WaitForSingleObject", windll.kernel32),
- WaitForSingleObjectFlags)
- INFINITE = -1
- WAIT_TIMEOUT = 0x0102
- WAIT_OBJECT_0 = 0x0
- WAIT_ABANDONED = 0x0080
- WAIT_FAILED = 0xFFFFFFFF
- GetExitCodeProcessProto = WINFUNCTYPE(BOOL,
- HANDLE,
- LPDWORD,
- )
- GetExitCodeProcessFlags = ((1, "hProcess"),
- (2, "lpExitCode"))
- GetExitCodeProcess = GetExitCodeProcessProto(
- ("GetExitCodeProcess", windll.kernel32),
- GetExitCodeProcessFlags)
- GetExitCodeProcess.errcheck = ErrCheckBool
- def CanCreateJobObject():
-
-
- return False
- def parent():
- print 'Starting parent'
- currentProc = GetCurrentProcess()
- if IsProcessInJob(currentProc):
- print >> sys.stderr, "You should not be in a job object to test"
- sys.exit(1)
- assert CanCreateJobObject()
- print 'File: %s' % __file__
- command = [sys.executable, __file__, '-child']
- print 'Running command: %s' % command
- process = Popen(command)
- process.kill()
- code = process.returncode
- print 'Child code: %s' % code
- assert code == 127
-
- def child():
- print 'Starting child'
- currentProc = GetCurrentProcess()
- injob = IsProcessInJob(currentProc)
- print "Is in a job?: %s" % injob
- can_create = CanCreateJobObject()
- print 'Can create job?: %s' % can_create
- process = Popen('c:\\windows\\notepad.exe')
- assert process._job
- jobinfo = QueryInformationJobObject(process._job, 'JobObjectExtendedLimitInformation')
- print 'Job info: %s' % jobinfo
- limitflags = jobinfo['BasicLimitInformation']['LimitFlags']
- print 'LimitFlags: %s' % limitflags
- process.kill()
- if __name__ == '__main__':
- import sys
- from killableprocess import Popen
- nargs = len(sys.argv[1:])
- if nargs:
- if nargs != 1 or sys.argv[1] != '-child':
- raise AssertionError('Wrong flags; run like `python /path/to/winprocess.py`')
- child()
- else:
- parent()
|