| Index: third_party/mozprocess/mozprocess/winprocess.py
|
| ===================================================================
|
| --- third_party/mozprocess/mozprocess/winprocess.py (revision 0)
|
| +++ third_party/mozprocess/mozprocess/winprocess.py (revision 0)
|
| @@ -0,0 +1,457 @@
|
| +# A module to expose various thread/process/job related structures and
|
| +# methods from kernel32
|
| +#
|
| +# The MIT License
|
| +#
|
| +# Copyright (c) 2003-2004 by Peter Astrand <astrand@lysator.liu.se>
|
| +#
|
| +# Additions and modifications written by Benjamin Smedberg
|
| +# <benjamin@smedbergs.us> are Copyright (c) 2006 by the Mozilla Foundation
|
| +# <http://www.mozilla.org/>
|
| +#
|
| +# More Modifications
|
| +# Copyright (c) 2006-2007 by Mike Taylor <bear@code-bear.com>
|
| +# Copyright (c) 2007-2008 by Mikeal Rogers <mikeal@mozilla.com>
|
| +#
|
| +# By obtaining, using, and/or copying this software and/or its
|
| +# associated documentation, you agree that you have read, understood,
|
| +# and will comply with the following terms and conditions:
|
| +#
|
| +# Permission to use, copy, modify, and distribute this software and
|
| +# its associated documentation for any purpose and without fee is
|
| +# hereby granted, provided that the above copyright notice appears in
|
| +# all copies, and that both that copyright notice and this permission
|
| +# notice appear in supporting documentation, and that the name of the
|
| +# author not be used in advertising or publicity pertaining to
|
| +# distribution of the software without specific, written prior
|
| +# permission.
|
| +#
|
| +# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
| +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
|
| +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
| +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
| +# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
| +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
| +# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
| +
|
| +from ctypes import c_void_p, POINTER, sizeof, Structure, Union, windll, WinError, WINFUNCTYPE, c_ulong
|
| +from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LPCWSTR, LPWSTR, UINT, WORD, ULONG
|
| +from qijo import QueryInformationJobObject
|
| +
|
| +LPVOID = c_void_p
|
| +LPBYTE = POINTER(BYTE)
|
| +LPDWORD = POINTER(DWORD)
|
| +LPBOOL = POINTER(BOOL)
|
| +LPULONG = POINTER(c_ulong)
|
| +
|
| +def ErrCheckBool(result, func, args):
|
| + """errcheck function for Windows functions that return a BOOL True
|
| + on success"""
|
| + if not result:
|
| + raise WinError()
|
| + return args
|
| +
|
| +
|
| +# AutoHANDLE
|
| +
|
| +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)
|
| +
|
| +# PROCESS_INFORMATION structure
|
| +
|
| +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)
|
| +
|
| +# STARTUPINFO structure
|
| +
|
| +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
|
| +
|
| +# EnvironmentBlock
|
| +
|
| +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))
|
| +
|
| +# Error Messages we need to watch for go here
|
| +# See: http://msdn.microsoft.com/en-us/library/ms681388%28v=vs.85%29.aspx
|
| +ERROR_ABANDONED_WAIT_0 = 735
|
| +
|
| +# GetLastError()
|
| +GetLastErrorProto = WINFUNCTYPE(DWORD # Return Type
|
| + )
|
| +GetLastErrorFlags = ()
|
| +GetLastError = GetLastErrorProto(("GetLastError", windll.kernel32), GetLastErrorFlags)
|
| +
|
| +# CreateProcess()
|
| +
|
| +CreateProcessProto = WINFUNCTYPE(BOOL, # Return type
|
| + LPCWSTR, # lpApplicationName
|
| + LPWSTR, # lpCommandLine
|
| + LPVOID, # lpProcessAttributes
|
| + LPVOID, # lpThreadAttributes
|
| + BOOL, # bInheritHandles
|
| + DWORD, # dwCreationFlags
|
| + LPVOID, # lpEnvironment
|
| + LPCWSTR, # lpCurrentDirectory
|
| + LPSTARTUPINFO, # lpStartupInfo
|
| + LPPROCESS_INFORMATION # lpProcessInformation
|
| + )
|
| +
|
| +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)
|
| + # return a tuple (hProcess, hThread, dwProcessID, dwThreadID)
|
| + pi = args[9]
|
| + return AutoHANDLE(pi.hProcess), AutoHANDLE(pi.hThread), pi.dwProcessID, pi.dwThreadID
|
| +
|
| +CreateProcess = CreateProcessProto(("CreateProcessW", windll.kernel32),
|
| + CreateProcessFlags)
|
| +CreateProcess.errcheck = ErrCheckCreateProcess
|
| +
|
| +# flags for CreateProcess
|
| +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
|
| +
|
| +# Flags for IOCompletion ports (some of these would probably be defined if
|
| +# we used the win32 extensions for python, but we don't want to do that if we
|
| +# can help it.
|
| +INVALID_HANDLE_VALUE = HANDLE(-1) # From winbase.h
|
| +
|
| +# Self Defined Constants for IOPort <--> Job Object communication
|
| +COMPKEY_TERMINATE = c_ulong(0)
|
| +COMPKEY_JOBOBJECT = c_ulong(1)
|
| +
|
| +# flags for job limit information
|
| +# see http://msdn.microsoft.com/en-us/library/ms684147%28VS.85%29.aspx
|
| +JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800
|
| +JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = 0x00001000
|
| +
|
| +# Flags for Job Object Completion Port Message IDs from winnt.h
|
| +# See also: http://msdn.microsoft.com/en-us/library/ms684141%28v=vs.85%29.aspx
|
| +JOB_OBJECT_MSG_END_OF_JOB_TIME = 1
|
| +JOB_OBJECT_MSG_END_OF_PROCESS_TIME = 2
|
| +JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT = 3
|
| +JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO = 4
|
| +JOB_OBJECT_MSG_NEW_PROCESS = 6
|
| +JOB_OBJECT_MSG_EXIT_PROCESS = 7
|
| +JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS = 8
|
| +JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT = 9
|
| +JOB_OBJECT_MSG_JOB_MEMORY_LIMIT = 10
|
| +
|
| +# See winbase.h
|
| +DEBUG_ONLY_THIS_PROCESS = 0x00000002
|
| +DEBUG_PROCESS = 0x00000001
|
| +DETACHED_PROCESS = 0x00000008
|
| +
|
| +# GetQueuedCompletionPortStatus - http://msdn.microsoft.com/en-us/library/aa364986%28v=vs.85%29.aspx
|
| +GetQueuedCompletionStatusProto = WINFUNCTYPE(BOOL, # Return Type
|
| + HANDLE, # Completion Port
|
| + LPDWORD, # Msg ID
|
| + LPULONG, # Completion Key
|
| + LPULONG, # PID Returned from the call (may be null)
|
| + DWORD) # milliseconds to wait
|
| +GetQueuedCompletionStatusFlags = ((1, "CompletionPort", INVALID_HANDLE_VALUE),
|
| + (1, "lpNumberOfBytes", None),
|
| + (1, "lpCompletionKey", None),
|
| + (1, "lpPID", None),
|
| + (1, "dwMilliseconds", 0))
|
| +GetQueuedCompletionStatus = GetQueuedCompletionStatusProto(("GetQueuedCompletionStatus",
|
| + windll.kernel32),
|
| + GetQueuedCompletionStatusFlags)
|
| +
|
| +# CreateIOCompletionPort
|
| +# Note that the completion key is just a number, not a pointer.
|
| +CreateIoCompletionPortProto = WINFUNCTYPE(HANDLE, # Return Type
|
| + HANDLE, # File Handle
|
| + HANDLE, # Existing Completion Port
|
| + c_ulong, # Completion Key
|
| + DWORD # Number of Threads
|
| + )
|
| +CreateIoCompletionPortFlags = ((1, "FileHandle", INVALID_HANDLE_VALUE),
|
| + (1, "ExistingCompletionPort", 0),
|
| + (1, "CompletionKey", c_ulong(0)),
|
| + (1, "NumberOfConcurrentThreads", 0))
|
| +CreateIoCompletionPort = CreateIoCompletionPortProto(("CreateIoCompletionPort",
|
| + windll.kernel32),
|
| + CreateIoCompletionPortFlags)
|
| +CreateIoCompletionPort.errcheck = ErrCheckHandle
|
| +
|
| +# SetInformationJobObject
|
| +SetInformationJobObjectProto = WINFUNCTYPE(BOOL, # Return Type
|
| + HANDLE, # Job Handle
|
| + DWORD, # Type of Class next param is
|
| + LPVOID, # Job Object Class
|
| + DWORD # Job Object Class Length
|
| + )
|
| +SetInformationJobObjectProtoFlags = ((1, "hJob", None),
|
| + (1, "JobObjectInfoClass", None),
|
| + (1, "lpJobObjectInfo", None),
|
| + (1, "cbJobObjectInfoLength", 0))
|
| +SetInformationJobObject = SetInformationJobObjectProto(("SetInformationJobObject",
|
| + windll.kernel32),
|
| + SetInformationJobObjectProtoFlags)
|
| +SetInformationJobObject.errcheck = ErrCheckBool
|
| +
|
| +# CreateJobObject()
|
| +CreateJobObjectProto = WINFUNCTYPE(HANDLE, # Return type
|
| + LPVOID, # lpJobAttributes
|
| + LPCWSTR # lpName
|
| + )
|
| +
|
| +CreateJobObjectFlags = ((1, "lpJobAttributes", None),
|
| + (1, "lpName", None))
|
| +
|
| +CreateJobObject = CreateJobObjectProto(("CreateJobObjectW", windll.kernel32),
|
| + CreateJobObjectFlags)
|
| +CreateJobObject.errcheck = ErrCheckHandle
|
| +
|
| +# AssignProcessToJobObject()
|
| +
|
| +AssignProcessToJobObjectProto = WINFUNCTYPE(BOOL, # Return type
|
| + HANDLE, # hJob
|
| + HANDLE # hProcess
|
| + )
|
| +AssignProcessToJobObjectFlags = ((1, "hJob"),
|
| + (1, "hProcess"))
|
| +AssignProcessToJobObject = AssignProcessToJobObjectProto(
|
| + ("AssignProcessToJobObject", windll.kernel32),
|
| + AssignProcessToJobObjectFlags)
|
| +AssignProcessToJobObject.errcheck = ErrCheckBool
|
| +
|
| +# GetCurrentProcess()
|
| +# because os.getPid() is way too easy
|
| +GetCurrentProcessProto = WINFUNCTYPE(HANDLE # Return type
|
| + )
|
| +GetCurrentProcessFlags = ()
|
| +GetCurrentProcess = GetCurrentProcessProto(
|
| + ("GetCurrentProcess", windll.kernel32),
|
| + GetCurrentProcessFlags)
|
| +GetCurrentProcess.errcheck = ErrCheckHandle
|
| +
|
| +# IsProcessInJob()
|
| +try:
|
| + IsProcessInJobProto = WINFUNCTYPE(BOOL, # Return type
|
| + HANDLE, # Process Handle
|
| + HANDLE, # Job Handle
|
| + LPBOOL # Result
|
| + )
|
| + IsProcessInJobFlags = ((1, "ProcessHandle"),
|
| + (1, "JobHandle", HANDLE(0)),
|
| + (2, "Result"))
|
| + IsProcessInJob = IsProcessInJobProto(
|
| + ("IsProcessInJob", windll.kernel32),
|
| + IsProcessInJobFlags)
|
| + IsProcessInJob.errcheck = ErrCheckBool
|
| +except AttributeError:
|
| + # windows 2k doesn't have this API
|
| + def IsProcessInJob(process):
|
| + return False
|
| +
|
| +
|
| +# ResumeThread()
|
| +
|
| +def ErrCheckResumeThread(result, func, args):
|
| + if result == -1:
|
| + raise WinError()
|
| +
|
| + return args
|
| +
|
| +ResumeThreadProto = WINFUNCTYPE(DWORD, # Return type
|
| + HANDLE # hThread
|
| + )
|
| +ResumeThreadFlags = ((1, "hThread"),)
|
| +ResumeThread = ResumeThreadProto(("ResumeThread", windll.kernel32),
|
| + ResumeThreadFlags)
|
| +ResumeThread.errcheck = ErrCheckResumeThread
|
| +
|
| +# TerminateProcess()
|
| +
|
| +TerminateProcessProto = WINFUNCTYPE(BOOL, # Return type
|
| + HANDLE, # hProcess
|
| + UINT # uExitCode
|
| + )
|
| +TerminateProcessFlags = ((1, "hProcess"),
|
| + (1, "uExitCode", 127))
|
| +TerminateProcess = TerminateProcessProto(
|
| + ("TerminateProcess", windll.kernel32),
|
| + TerminateProcessFlags)
|
| +TerminateProcess.errcheck = ErrCheckBool
|
| +
|
| +# TerminateJobObject()
|
| +
|
| +TerminateJobObjectProto = WINFUNCTYPE(BOOL, # Return type
|
| + HANDLE, # hJob
|
| + UINT # uExitCode
|
| + )
|
| +TerminateJobObjectFlags = ((1, "hJob"),
|
| + (1, "uExitCode", 127))
|
| +TerminateJobObject = TerminateJobObjectProto(
|
| + ("TerminateJobObject", windll.kernel32),
|
| + TerminateJobObjectFlags)
|
| +TerminateJobObject.errcheck = ErrCheckBool
|
| +
|
| +# WaitForSingleObject()
|
| +
|
| +WaitForSingleObjectProto = WINFUNCTYPE(DWORD, # Return type
|
| + HANDLE, # hHandle
|
| + DWORD, # dwMilliseconds
|
| + )
|
| +WaitForSingleObjectFlags = ((1, "hHandle"),
|
| + (1, "dwMilliseconds", -1))
|
| +WaitForSingleObject = WaitForSingleObjectProto(
|
| + ("WaitForSingleObject", windll.kernel32),
|
| + WaitForSingleObjectFlags)
|
| +
|
| +# http://msdn.microsoft.com/en-us/library/ms681381%28v=vs.85%29.aspx
|
| +INFINITE = -1
|
| +WAIT_TIMEOUT = 0x0102
|
| +WAIT_OBJECT_0 = 0x0
|
| +WAIT_ABANDONED = 0x0080
|
| +
|
| +# http://msdn.microsoft.com/en-us/library/ms683189%28VS.85%29.aspx
|
| +STILL_ACTIVE = 259
|
| +
|
| +# Used when we terminate a process.
|
| +ERROR_CONTROL_C_EXIT = 0x23c
|
| +
|
| +# GetExitCodeProcess()
|
| +
|
| +GetExitCodeProcessProto = WINFUNCTYPE(BOOL, # Return type
|
| + HANDLE, # hProcess
|
| + LPDWORD, # lpExitCode
|
| + )
|
| +GetExitCodeProcessFlags = ((1, "hProcess"),
|
| + (2, "lpExitCode"))
|
| +GetExitCodeProcess = GetExitCodeProcessProto(
|
| + ("GetExitCodeProcess", windll.kernel32),
|
| + GetExitCodeProcessFlags)
|
| +GetExitCodeProcess.errcheck = ErrCheckBool
|
| +
|
| +def CanCreateJobObject():
|
| + currentProc = GetCurrentProcess()
|
| + if IsProcessInJob(currentProc):
|
| + jobinfo = QueryInformationJobObject(HANDLE(0), 'JobObjectExtendedLimitInformation')
|
| + limitflags = jobinfo['BasicLimitInformation']['LimitFlags']
|
| + return bool(limitflags & JOB_OBJECT_LIMIT_BREAKAWAY_OK) or bool(limitflags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)
|
| + else:
|
| + return True
|
| +
|
| +### testing functions
|
| +
|
| +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()
|
|
|
| Property changes on: third_party/mozprocess/mozprocess/winprocess.py
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|