diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -199,7 +199,7 @@ else: - from _multiprocessing import win32 + import _windows def Pipe(duplex=True): ''' @@ -207,31 +207,31 @@ ''' address = arbitrary_address('AF_PIPE') if duplex: - openmode = win32.PIPE_ACCESS_DUPLEX - access = win32.GENERIC_READ | win32.GENERIC_WRITE + openmode = _windows.PIPE_ACCESS_DUPLEX + access = _windows.GENERIC_READ | _windows.GENERIC_WRITE obsize, ibsize = BUFSIZE, BUFSIZE else: - openmode = win32.PIPE_ACCESS_INBOUND - access = win32.GENERIC_WRITE + openmode = _windows.PIPE_ACCESS_INBOUND + access = _windows.GENERIC_WRITE obsize, ibsize = 0, BUFSIZE - h1 = win32.CreateNamedPipe( + h1 = _windows.CreateNamedPipe( address, openmode, - win32.PIPE_TYPE_MESSAGE | win32.PIPE_READMODE_MESSAGE | - win32.PIPE_WAIT, - 1, obsize, ibsize, win32.NMPWAIT_WAIT_FOREVER, win32.NULL + _windows.PIPE_TYPE_MESSAGE | _windows.PIPE_READMODE_MESSAGE | + _windows.PIPE_WAIT, + 1, obsize, ibsize, _windows.NMPWAIT_WAIT_FOREVER, _windows.NULL ) - h2 = win32.CreateFile( - address, access, 0, win32.NULL, win32.OPEN_EXISTING, 0, win32.NULL + h2 = _windows.CreateFile( + address, access, 0, _windows.NULL, _windows.OPEN_EXISTING, 0, _windows.NULL ) - win32.SetNamedPipeHandleState( - h2, win32.PIPE_READMODE_MESSAGE, None, None + _windows.SetNamedPipeHandleState( + h2, _windows.PIPE_READMODE_MESSAGE, None, None ) try: - win32.ConnectNamedPipe(h1, win32.NULL) + _windows.ConnectNamedPipe(h1, _windows.NULL) except WindowsError as e: - if e.args[0] != win32.ERROR_PIPE_CONNECTED: + if e.args[0] != _windows.ERROR_PIPE_CONNECTED: raise c1 = _multiprocessing.PipeConnection(h1, writable=duplex) @@ -313,12 +313,12 @@ ''' def __init__(self, address, backlog=None): self._address = address - handle = win32.CreateNamedPipe( - address, win32.PIPE_ACCESS_DUPLEX, - win32.PIPE_TYPE_MESSAGE | win32.PIPE_READMODE_MESSAGE | - win32.PIPE_WAIT, - win32.PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, - win32.NMPWAIT_WAIT_FOREVER, win32.NULL + handle = _windows.CreateNamedPipe( + address, _windows.PIPE_ACCESS_DUPLEX, + _windows.PIPE_TYPE_MESSAGE | _windows.PIPE_READMODE_MESSAGE | + _windows.PIPE_WAIT, + _windows.PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, + _windows.NMPWAIT_WAIT_FOREVER, _windows.NULL ) self._handle_queue = [handle] self._last_accepted = None @@ -331,19 +331,19 @@ ) def accept(self): - newhandle = win32.CreateNamedPipe( - self._address, win32.PIPE_ACCESS_DUPLEX, - win32.PIPE_TYPE_MESSAGE | win32.PIPE_READMODE_MESSAGE | - win32.PIPE_WAIT, - win32.PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, - win32.NMPWAIT_WAIT_FOREVER, win32.NULL + newhandle = _windows.CreateNamedPipe( + self._address, _windows.PIPE_ACCESS_DUPLEX, + _windows.PIPE_TYPE_MESSAGE | _windows.PIPE_READMODE_MESSAGE | + _windows.PIPE_WAIT, + _windows.PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, + _windows.NMPWAIT_WAIT_FOREVER, _windows.NULL ) self._handle_queue.append(newhandle) handle = self._handle_queue.pop(0) try: - win32.ConnectNamedPipe(handle, win32.NULL) + _windows.ConnectNamedPipe(handle, _windows.NULL) except WindowsError as e: - if e.args[0] != win32.ERROR_PIPE_CONNECTED: + if e.args[0] != _windows.ERROR_PIPE_CONNECTED: raise return _multiprocessing.PipeConnection(handle) @@ -360,22 +360,22 @@ t = _init_timeout() while 1: try: - win32.WaitNamedPipe(address, 1000) - h = win32.CreateFile( - address, win32.GENERIC_READ | win32.GENERIC_WRITE, - 0, win32.NULL, win32.OPEN_EXISTING, 0, win32.NULL + _windows.WaitNamedPipe(address, 1000) + h = _windows.CreateFile( + address, _windows.GENERIC_READ | _windows.GENERIC_WRITE, + 0, _windows.NULL, _windows.OPEN_EXISTING, 0, _windows.NULL ) except WindowsError as e: - if e.args[0] not in (win32.ERROR_SEM_TIMEOUT, - win32.ERROR_PIPE_BUSY) or _check_timeout(t): + if e.args[0] not in (_windows.ERROR_SEM_TIMEOUT, + _windows.ERROR_PIPE_BUSY) or _check_timeout(t): raise else: break else: raise - win32.SetNamedPipeHandleState( - h, win32.PIPE_READMODE_MESSAGE, None, None + _windows.SetNamedPipeHandleState( + h, _windows.PIPE_READMODE_MESSAGE, None, None ) return _multiprocessing.PipeConnection(h) diff --git a/Lib/multiprocessing/forking.py b/Lib/multiprocessing/forking.py --- a/Lib/multiprocessing/forking.py +++ b/Lib/multiprocessing/forking.py @@ -179,11 +179,11 @@ else: import _thread import msvcrt - import _subprocess import time + import _windows from pickle import dump, load, HIGHEST_PROTOCOL - from _multiprocessing import win32, Connection, PipeConnection + from _multiprocessing import Connection, PipeConnection from .util import Finalize def dump(obj, file, protocol=None): @@ -197,8 +197,8 @@ WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False)) WINSERVICE = sys.executable.lower().endswith("pythonservice.exe") - exit = win32.ExitProcess - close = win32.CloseHandle + exit = _windows.ExitProcess + close = _windows.CloseHandle # # _python_exe is the assumed path to the python executable. @@ -220,10 +220,10 @@ def duplicate(handle, target_process=None, inheritable=False): if target_process is None: - target_process = _subprocess.GetCurrentProcess() - return _subprocess.DuplicateHandle( - _subprocess.GetCurrentProcess(), handle, target_process, - 0, inheritable, _subprocess.DUPLICATE_SAME_ACCESS + target_process = _windows.GetCurrentProcess() + return _windows.DuplicateHandle( + _windows.GetCurrentProcess(), handle, target_process, + 0, inheritable, _windows.DUPLICATE_SAME_ACCESS ).Detach() # @@ -248,7 +248,7 @@ # start process cmd = get_command_line() + [rhandle] cmd = ' '.join('"%s"' % x for x in cmd) - hp, ht, pid, tid = _subprocess.CreateProcess( + hp, ht, pid, tid = _windows.CreateProcess( _python_exe, cmd, None, None, 1, 0, None, None, None ) ht.Close() @@ -281,13 +281,13 @@ def wait(self, timeout=None): if self.returncode is None: if timeout is None: - msecs = _subprocess.INFINITE + msecs = _windows.INFINITE else: msecs = max(0, int(timeout * 1000 + 0.5)) - res = _subprocess.WaitForSingleObject(int(self._handle), msecs) - if res == _subprocess.WAIT_OBJECT_0: - code = _subprocess.GetExitCodeProcess(self._handle) + res = _windows.WaitForSingleObject(int(self._handle), msecs) + if res == _windows.WAIT_OBJECT_0: + code = _windows.GetExitCodeProcess(self._handle) if code == TERMINATE: code = -signal.SIGTERM self.returncode = code @@ -300,7 +300,7 @@ def terminate(self): if self.returncode is None: try: - _subprocess.TerminateProcess(int(self._handle), TERMINATE) + _windows.TerminateProcess(int(self._handle), TERMINATE) except WindowsError: if self.wait(timeout=0.1) is None: raise diff --git a/Lib/multiprocessing/heap.py b/Lib/multiprocessing/heap.py --- a/Lib/multiprocessing/heap.py +++ b/Lib/multiprocessing/heap.py @@ -52,7 +52,7 @@ if sys.platform == 'win32': - from _multiprocessing import win32 + import _windows class Arena(object): @@ -62,7 +62,7 @@ self.size = size self.name = 'pym-%d-%d' % (os.getpid(), next(Arena._counter)) self.buffer = mmap.mmap(-1, self.size, tagname=self.name) - assert win32.GetLastError() == 0, 'tagname already in use' + assert _windows.GetLastError() == 0, 'tagname already in use' self._state = (self.size, self.name) def __getstate__(self): @@ -72,7 +72,7 @@ def __setstate__(self, state): self.size, self.name = self._state = state self.buffer = mmap.mmap(-1, self.size, tagname=self.name) - assert win32.GetLastError() == win32.ERROR_ALREADY_EXISTS + assert _windows.GetLastError() == _windows.ERROR_ALREADY_EXISTS else: diff --git a/Lib/multiprocessing/reduction.py b/Lib/multiprocessing/reduction.py --- a/Lib/multiprocessing/reduction.py +++ b/Lib/multiprocessing/reduction.py @@ -59,12 +59,11 @@ # if sys.platform == 'win32': - import _subprocess - from _multiprocessing import win32 + import _windows def send_handle(conn, handle, destination_pid): - process_handle = win32.OpenProcess( - win32.PROCESS_ALL_ACCESS, False, destination_pid + process_handle = _windows.OpenProcess( + _windows.PROCESS_ALL_ACCESS, False, destination_pid ) try: new_handle = duplicate(handle, process_handle) diff --git a/Lib/subprocess.py b/Lib/subprocess.py --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -385,7 +385,7 @@ if mswindows: import threading import msvcrt - import _subprocess + import _windows class STARTUPINFO: dwFlags = 0 hStdInput = None @@ -435,7 +435,7 @@ "getoutput", "check_output", "CalledProcessError", "DEVNULL"] if mswindows: - from _subprocess import CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP + from _windows import CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP __all__.extend(["CREATE_NEW_CONSOLE", "CREATE_NEW_PROCESS_GROUP"]) try: MAXFD = os.sysconf("SC_OPEN_MAX") @@ -891,11 +891,11 @@ errread, errwrite = -1, -1 if stdin is None: - p2cread = _subprocess.GetStdHandle(_subprocess.STD_INPUT_HANDLE) + p2cread = _windows.GetStdHandle(_windows.STD_INPUT_HANDLE) if p2cread is None: - p2cread, _ = _subprocess.CreatePipe(None, 0) + p2cread, _ = _windows.CreatePipe(None, 0) elif stdin == PIPE: - p2cread, p2cwrite = _subprocess.CreatePipe(None, 0) + p2cread, p2cwrite = _windows.CreatePipe(None, 0) elif stdin == DEVNULL: p2cread = msvcrt.get_osfhandle(self._get_devnull()) elif isinstance(stdin, int): @@ -906,11 +906,11 @@ p2cread = self._make_inheritable(p2cread) if stdout is None: - c2pwrite = _subprocess.GetStdHandle(_subprocess.STD_OUTPUT_HANDLE) + c2pwrite = _windows.GetStdHandle(_windows.STD_OUTPUT_HANDLE) if c2pwrite is None: - _, c2pwrite = _subprocess.CreatePipe(None, 0) + _, c2pwrite = _windows.CreatePipe(None, 0) elif stdout == PIPE: - c2pread, c2pwrite = _subprocess.CreatePipe(None, 0) + c2pread, c2pwrite = _windows.CreatePipe(None, 0) elif stdout == DEVNULL: c2pwrite = msvcrt.get_osfhandle(self._get_devnull()) elif isinstance(stdout, int): @@ -921,11 +921,11 @@ c2pwrite = self._make_inheritable(c2pwrite) if stderr is None: - errwrite = _subprocess.GetStdHandle(_subprocess.STD_ERROR_HANDLE) + errwrite = _windows.GetStdHandle(_windows.STD_ERROR_HANDLE) if errwrite is None: - _, errwrite = _subprocess.CreatePipe(None, 0) + _, errwrite = _windows.CreatePipe(None, 0) elif stderr == PIPE: - errread, errwrite = _subprocess.CreatePipe(None, 0) + errread, errwrite = _windows.CreatePipe(None, 0) elif stderr == STDOUT: errwrite = c2pwrite elif stderr == DEVNULL: @@ -944,15 +944,15 @@ def _make_inheritable(self, handle): """Return a duplicate of handle, which is inheritable""" - return _subprocess.DuplicateHandle(_subprocess.GetCurrentProcess(), - handle, _subprocess.GetCurrentProcess(), 0, 1, - _subprocess.DUPLICATE_SAME_ACCESS) + return _windows.DuplicateHandle(_windows.GetCurrentProcess(), + handle, _windows.GetCurrentProcess(), 0, 1, + _windows.DUPLICATE_SAME_ACCESS) def _find_w9xpopen(self): """Find and return absolut path to w9xpopen.exe""" w9xpopen = os.path.join( - os.path.dirname(_subprocess.GetModuleFileName(0)), + os.path.dirname(_windows.GetModuleFileName(0)), "w9xpopen.exe") if not os.path.exists(w9xpopen): # Eeek - file-not-found - possibly an embedding @@ -984,17 +984,17 @@ if startupinfo is None: startupinfo = STARTUPINFO() if -1 not in (p2cread, c2pwrite, errwrite): - startupinfo.dwFlags |= _subprocess.STARTF_USESTDHANDLES + startupinfo.dwFlags |= _windows.STARTF_USESTDHANDLES startupinfo.hStdInput = p2cread startupinfo.hStdOutput = c2pwrite startupinfo.hStdError = errwrite if shell: - startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW - startupinfo.wShowWindow = _subprocess.SW_HIDE + startupinfo.dwFlags |= _windows.STARTF_USESHOWWINDOW + startupinfo.wShowWindow = _windows.SW_HIDE comspec = os.environ.get("COMSPEC", "cmd.exe") args = '{} /c "{}"'.format (comspec, args) - if (_subprocess.GetVersion() >= 0x80000000 or + if (_windows.GetVersion() >= 0x80000000 or os.path.basename(comspec).lower() == "command.com"): # Win9x, or using command.com on NT. We need to # use the w9xpopen intermediate program. For more @@ -1008,11 +1008,11 @@ # use at xxx" and a hopeful warning about the # stability of your system. Cost is Ctrl+C won't # kill children. - creationflags |= _subprocess.CREATE_NEW_CONSOLE + creationflags |= _windows.CREATE_NEW_CONSOLE # Start the process try: - hp, ht, pid, tid = _subprocess.CreateProcess(executable, args, + hp, ht, pid, tid = _windows.CreateProcess(executable, args, # no special security None, None, int(not close_fds), @@ -1049,9 +1049,9 @@ ht.Close() def _internal_poll(self, _deadstate=None, - _WaitForSingleObject=_subprocess.WaitForSingleObject, - _WAIT_OBJECT_0=_subprocess.WAIT_OBJECT_0, - _GetExitCodeProcess=_subprocess.GetExitCodeProcess): + _WaitForSingleObject=_windows.WaitForSingleObject, + _WAIT_OBJECT_0=_windows.WAIT_OBJECT_0, + _GetExitCodeProcess=_windows.GetExitCodeProcess): """Check if child process has terminated. Returns returncode attribute. @@ -1071,15 +1071,15 @@ if endtime is not None: timeout = self._remaining_time(endtime) if timeout is None: - timeout_millis = _subprocess.INFINITE + timeout_millis = _windows.INFINITE else: timeout_millis = int(timeout * 1000) if self.returncode is None: - result = _subprocess.WaitForSingleObject(self._handle, + result = _windows.WaitForSingleObject(self._handle, timeout_millis) - if result == _subprocess.WAIT_TIMEOUT: + if result == _windows.WAIT_TIMEOUT: raise TimeoutExpired(self.args, timeout) - self.returncode = _subprocess.GetExitCodeProcess(self._handle) + self.returncode = _windows.GetExitCodeProcess(self._handle) return self.returncode @@ -1161,7 +1161,7 @@ def terminate(self): """Terminates the process """ - _subprocess.TerminateProcess(self._handle, 1) + _windows.TerminateProcess(self._handle, 1) kill = terminate diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c --- a/Modules/_multiprocessing/multiprocessing.c +++ b/Modules/_multiprocessing/multiprocessing.c @@ -293,12 +293,6 @@ PyModule_AddObject(module, "PipeConnection", (PyObject*)&PipeConnectionType); - /* Initialize win32 class and add to multiprocessing */ - temp = create_win32_namespace(); - if (!temp) - return NULL; - PyModule_AddObject(module, "win32", temp); - /* Initialize the event handle used to signal Ctrl-C */ sigint_event = CreateEvent(NULL, TRUE, FALSE, NULL); if (!sigint_event) { diff --git a/Modules/_multiprocessing/win32_functions.c b/Modules/_multiprocessing/win32_functions.c deleted file mode 100644 --- a/Modules/_multiprocessing/win32_functions.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Win32 functions used by multiprocessing package - * - * win32_functions.c - * - * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt - */ - -#include "multiprocessing.h" - - -#define WIN32_FUNCTION(func) \ - {#func, (PyCFunction)win32_ ## func, METH_VARARGS | METH_STATIC, ""} - -#define WIN32_CONSTANT(fmt, con) \ - PyDict_SetItemString(Win32Type.tp_dict, #con, Py_BuildValue(fmt, con)) - - -static PyObject * -win32_CloseHandle(PyObject *self, PyObject *args) -{ - HANDLE hObject; - BOOL success; - - if (!PyArg_ParseTuple(args, F_HANDLE, &hObject)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - success = CloseHandle(hObject); - Py_END_ALLOW_THREADS - - if (!success) - return PyErr_SetFromWindowsErr(0); - - Py_RETURN_NONE; -} - -static PyObject * -win32_ConnectNamedPipe(PyObject *self, PyObject *args) -{ - HANDLE hNamedPipe; - LPOVERLAPPED lpOverlapped; - BOOL success; - - if (!PyArg_ParseTuple(args, F_HANDLE F_POINTER, - &hNamedPipe, &lpOverlapped)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - success = ConnectNamedPipe(hNamedPipe, lpOverlapped); - Py_END_ALLOW_THREADS - - if (!success) - return PyErr_SetFromWindowsErr(0); - - Py_RETURN_NONE; -} - -static PyObject * -win32_CreateFile(PyObject *self, PyObject *args) -{ - LPCTSTR lpFileName; - DWORD dwDesiredAccess; - DWORD dwShareMode; - LPSECURITY_ATTRIBUTES lpSecurityAttributes; - DWORD dwCreationDisposition; - DWORD dwFlagsAndAttributes; - HANDLE hTemplateFile; - HANDLE handle; - - if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_POINTER - F_DWORD F_DWORD F_HANDLE, - &lpFileName, &dwDesiredAccess, &dwShareMode, - &lpSecurityAttributes, &dwCreationDisposition, - &dwFlagsAndAttributes, &hTemplateFile)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - handle = CreateFile(lpFileName, dwDesiredAccess, - dwShareMode, lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, hTemplateFile); - Py_END_ALLOW_THREADS - - if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(0); - - return Py_BuildValue(F_HANDLE, handle); -} - -static PyObject * -win32_CreateNamedPipe(PyObject *self, PyObject *args) -{ - LPCTSTR lpName; - DWORD dwOpenMode; - DWORD dwPipeMode; - DWORD nMaxInstances; - DWORD nOutBufferSize; - DWORD nInBufferSize; - DWORD nDefaultTimeOut; - LPSECURITY_ATTRIBUTES lpSecurityAttributes; - HANDLE handle; - - if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_DWORD - F_DWORD F_DWORD F_DWORD F_POINTER, - &lpName, &dwOpenMode, &dwPipeMode, - &nMaxInstances, &nOutBufferSize, - &nInBufferSize, &nDefaultTimeOut, - &lpSecurityAttributes)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - handle = CreateNamedPipe(lpName, dwOpenMode, dwPipeMode, - nMaxInstances, nOutBufferSize, - nInBufferSize, nDefaultTimeOut, - lpSecurityAttributes); - Py_END_ALLOW_THREADS - - if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(0); - - return Py_BuildValue(F_HANDLE, handle); -} - -static PyObject * -win32_ExitProcess(PyObject *self, PyObject *args) -{ - UINT uExitCode; - - if (!PyArg_ParseTuple(args, "I", &uExitCode)) - return NULL; - - #if defined(Py_DEBUG) - SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX); - _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); - #endif - - - ExitProcess(uExitCode); - - return NULL; -} - -static PyObject * -win32_GetLastError(PyObject *self, PyObject *args) -{ - return Py_BuildValue(F_DWORD, GetLastError()); -} - -static PyObject * -win32_OpenProcess(PyObject *self, PyObject *args) -{ - DWORD dwDesiredAccess; - BOOL bInheritHandle; - DWORD dwProcessId; - HANDLE handle; - - if (!PyArg_ParseTuple(args, F_DWORD "i" F_DWORD, - &dwDesiredAccess, &bInheritHandle, &dwProcessId)) - return NULL; - - handle = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); - if (handle == NULL) - return PyErr_SetFromWindowsErr(0); - - return Py_BuildValue(F_HANDLE, handle); -} - -static PyObject * -win32_SetNamedPipeHandleState(PyObject *self, PyObject *args) -{ - HANDLE hNamedPipe; - PyObject *oArgs[3]; - DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL}; - int i; - - if (!PyArg_ParseTuple(args, F_HANDLE "OOO", - &hNamedPipe, &oArgs[0], &oArgs[1], &oArgs[2])) - return NULL; - - PyErr_Clear(); - - for (i = 0 ; i < 3 ; i++) { - if (oArgs[i] != Py_None) { - dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]); - if (PyErr_Occurred()) - return NULL; - pArgs[i] = &dwArgs[i]; - } - } - - if (!SetNamedPipeHandleState(hNamedPipe, pArgs[0], pArgs[1], pArgs[2])) - return PyErr_SetFromWindowsErr(0); - - Py_RETURN_NONE; -} - -static PyObject * -win32_WaitNamedPipe(PyObject *self, PyObject *args) -{ - LPCTSTR lpNamedPipeName; - DWORD nTimeOut; - BOOL success; - - if (!PyArg_ParseTuple(args, "s" F_DWORD, &lpNamedPipeName, &nTimeOut)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - success = WaitNamedPipe(lpNamedPipeName, nTimeOut); - Py_END_ALLOW_THREADS - - if (!success) - return PyErr_SetFromWindowsErr(0); - - Py_RETURN_NONE; -} - -static PyMethodDef win32_methods[] = { - WIN32_FUNCTION(CloseHandle), - WIN32_FUNCTION(GetLastError), - WIN32_FUNCTION(OpenProcess), - WIN32_FUNCTION(ExitProcess), - WIN32_FUNCTION(ConnectNamedPipe), - WIN32_FUNCTION(CreateFile), - WIN32_FUNCTION(CreateNamedPipe), - WIN32_FUNCTION(SetNamedPipeHandleState), - WIN32_FUNCTION(WaitNamedPipe), - {NULL} -}; - - -PyTypeObject Win32Type = { - PyVarObject_HEAD_INIT(NULL, 0) -}; - - -PyObject * -create_win32_namespace(void) -{ - Win32Type.tp_name = "_multiprocessing.win32"; - Win32Type.tp_methods = win32_methods; - if (PyType_Ready(&Win32Type) < 0) - return NULL; - Py_INCREF(&Win32Type); - - WIN32_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS); - WIN32_CONSTANT(F_DWORD, ERROR_PIPE_BUSY); - WIN32_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED); - WIN32_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT); - WIN32_CONSTANT(F_DWORD, GENERIC_READ); - WIN32_CONSTANT(F_DWORD, GENERIC_WRITE); - WIN32_CONSTANT(F_DWORD, INFINITE); - WIN32_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER); - WIN32_CONSTANT(F_DWORD, OPEN_EXISTING); - WIN32_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX); - WIN32_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND); - WIN32_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE); - WIN32_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE); - WIN32_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES); - WIN32_CONSTANT(F_DWORD, PIPE_WAIT); - WIN32_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS); - - WIN32_CONSTANT("i", NULL); - - return (PyObject*)&Win32Type; -} diff --git a/PC/_subprocess.c b/PC/_subprocess.c deleted file mode 100644 --- a/PC/_subprocess.c +++ /dev/null @@ -1,690 +0,0 @@ -/* - * support routines for subprocess module - * - * Currently, this extension module is only required when using the - * subprocess module on Windows, but in the future, stubs for other - * platforms might be added here as well. - * - * Copyright (c) 2004 by Fredrik Lundh - * Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com - * Copyright (c) 2004 by Peter Astrand - * - * 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 - * authors not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. - * - * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. - * IN NO EVENT SHALL THE AUTHORS 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. - * - */ - -/* Licensed to PSF under a Contributor Agreement. */ -/* See http://www.python.org/2.4/license for licensing details. */ - -#include "Python.h" - -#define WINDOWS_LEAN_AND_MEAN -#include "windows.h" - -/* -------------------------------------------------------------------- */ -/* handle wrapper. note that this library uses integers when passing - handles to a function, and handle wrappers when returning handles. - the wrapper is used to provide Detach and Close methods */ - -typedef struct { - PyObject_HEAD - HANDLE handle; -} sp_handle_object; - -static PyTypeObject sp_handle_type; - -static PyObject* -sp_handle_new(HANDLE handle) -{ - sp_handle_object* self; - - self = PyObject_NEW(sp_handle_object, &sp_handle_type); - if (self == NULL) - return NULL; - - self->handle = handle; - - return (PyObject*) self; -} - -#if defined(MS_WIN32) && !defined(MS_WIN64) -#define HANDLE_TO_PYNUM(handle) PyLong_FromLong((long) handle) -#define PY_HANDLE_PARAM "l" -#else -#define HANDLE_TO_PYNUM(handle) PyLong_FromLongLong((long long) handle) -#define PY_HANDLE_PARAM "L" -#endif - -static PyObject* -sp_handle_detach(sp_handle_object* self, PyObject* args) -{ - HANDLE handle; - - if (! PyArg_ParseTuple(args, ":Detach")) - return NULL; - - handle = self->handle; - - self->handle = INVALID_HANDLE_VALUE; - - /* note: return the current handle, as an integer */ - return HANDLE_TO_PYNUM(handle); -} - -static PyObject* -sp_handle_close(sp_handle_object* self, PyObject* args) -{ - if (! PyArg_ParseTuple(args, ":Close")) - return NULL; - - if (self->handle != INVALID_HANDLE_VALUE) { - CloseHandle(self->handle); - self->handle = INVALID_HANDLE_VALUE; - } - Py_INCREF(Py_None); - return Py_None; -} - -static void -sp_handle_dealloc(sp_handle_object* self) -{ - if (self->handle != INVALID_HANDLE_VALUE) - CloseHandle(self->handle); - PyObject_FREE(self); -} - -static PyMethodDef sp_handle_methods[] = { - {"Detach", (PyCFunction) sp_handle_detach, METH_VARARGS}, - {"Close", (PyCFunction) sp_handle_close, METH_VARARGS}, - {NULL, NULL} -}; - -static PyObject* -sp_handle_as_int(sp_handle_object* self) -{ - return HANDLE_TO_PYNUM(self->handle); -} - -static PyNumberMethods sp_handle_as_number; - -static PyTypeObject sp_handle_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_subprocess_handle", sizeof(sp_handle_object), 0, - (destructor) sp_handle_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - &sp_handle_as_number, /*tp_as_number */ - 0, /*tp_as_sequence */ - 0, /*tp_as_mapping */ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - sp_handle_methods, /*tp_methods*/ -}; - -/* -------------------------------------------------------------------- */ -/* windows API functions */ - -PyDoc_STRVAR(GetStdHandle_doc, -"GetStdHandle(handle) -> integer\n\ -\n\ -Return a handle to the specified standard device\n\ -(STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE).\n\ -The integer associated with the handle object is returned."); - -static PyObject * -sp_GetStdHandle(PyObject* self, PyObject* args) -{ - HANDLE handle; - int std_handle; - - if (! PyArg_ParseTuple(args, "i:GetStdHandle", &std_handle)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - handle = GetStdHandle((DWORD) std_handle); - Py_END_ALLOW_THREADS - - if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(GetLastError()); - - if (! handle) { - Py_INCREF(Py_None); - return Py_None; - } - - /* note: returns integer, not handle object */ - return HANDLE_TO_PYNUM(handle); -} - -PyDoc_STRVAR(GetCurrentProcess_doc, -"GetCurrentProcess() -> handle\n\ -\n\ -Return a handle object for the current process."); - -static PyObject * -sp_GetCurrentProcess(PyObject* self, PyObject* args) -{ - if (! PyArg_ParseTuple(args, ":GetCurrentProcess")) - return NULL; - - return sp_handle_new(GetCurrentProcess()); -} - -PyDoc_STRVAR(DuplicateHandle_doc, -"DuplicateHandle(source_proc_handle, source_handle,\n\ - target_proc_handle, target_handle, access,\n\ - inherit[, options]) -> handle\n\ -\n\ -Return a duplicate handle object.\n\ -\n\ -The duplicate handle refers to the same object as the original\n\ -handle. Therefore, any changes to the object are reflected\n\ -through both handles."); - -static PyObject * -sp_DuplicateHandle(PyObject* self, PyObject* args) -{ - HANDLE target_handle; - BOOL result; - - HANDLE source_process_handle; - HANDLE source_handle; - HANDLE target_process_handle; - int desired_access; - int inherit_handle; - int options = 0; - - if (! PyArg_ParseTuple(args, - PY_HANDLE_PARAM PY_HANDLE_PARAM PY_HANDLE_PARAM - "ii|i:DuplicateHandle", - &source_process_handle, - &source_handle, - &target_process_handle, - &desired_access, - &inherit_handle, - &options)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - result = DuplicateHandle( - source_process_handle, - source_handle, - target_process_handle, - &target_handle, - desired_access, - inherit_handle, - options - ); - Py_END_ALLOW_THREADS - - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); - - return sp_handle_new(target_handle); -} - -PyDoc_STRVAR(CreatePipe_doc, -"CreatePipe(pipe_attrs, size) -> (read_handle, write_handle)\n\ -\n\ -Create an anonymous pipe, and return handles to the read and\n\ -write ends of the pipe.\n\ -\n\ -pipe_attrs is ignored internally and can be None."); - -static PyObject * -sp_CreatePipe(PyObject* self, PyObject* args) -{ - HANDLE read_pipe; - HANDLE write_pipe; - BOOL result; - - PyObject* pipe_attributes; /* ignored */ - int size; - - if (! PyArg_ParseTuple(args, "Oi:CreatePipe", &pipe_attributes, &size)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - result = CreatePipe(&read_pipe, &write_pipe, NULL, size); - Py_END_ALLOW_THREADS - - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); - - return Py_BuildValue( - "NN", sp_handle_new(read_pipe), sp_handle_new(write_pipe)); -} - -/* helpers for createprocess */ - -static int -getint(PyObject* obj, char* name) -{ - PyObject* value; - int ret; - - value = PyObject_GetAttrString(obj, name); - if (! value) { - PyErr_Clear(); /* FIXME: propagate error? */ - return 0; - } - ret = (int) PyLong_AsLong(value); - Py_DECREF(value); - return ret; -} - -static HANDLE -gethandle(PyObject* obj, char* name) -{ - sp_handle_object* value; - HANDLE ret; - - value = (sp_handle_object*) PyObject_GetAttrString(obj, name); - if (! value) { - PyErr_Clear(); /* FIXME: propagate error? */ - return NULL; - } - if (Py_TYPE(value) != &sp_handle_type) - ret = NULL; - else - ret = value->handle; - Py_DECREF(value); - return ret; -} - -static PyObject* -getenvironment(PyObject* environment) -{ - int i; - Py_ssize_t envsize; - PyObject* out = NULL; - PyObject* keys; - PyObject* values; - Py_UNICODE* p; - - /* convert environment dictionary to windows enviroment string */ - if (! PyMapping_Check(environment)) { - PyErr_SetString( - PyExc_TypeError, "environment must be dictionary or None"); - return NULL; - } - - envsize = PyMapping_Length(environment); - - keys = PyMapping_Keys(environment); - values = PyMapping_Values(environment); - if (!keys || !values) - goto error; - - out = PyUnicode_FromUnicode(NULL, 2048); - if (! out) - goto error; - - p = PyUnicode_AS_UNICODE(out); - - for (i = 0; i < envsize; i++) { - Py_ssize_t ksize, vsize, totalsize; - PyObject* key = PyList_GET_ITEM(keys, i); - PyObject* value = PyList_GET_ITEM(values, i); - - if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "environment can only contain strings"); - goto error; - } - ksize = PyUnicode_GET_SIZE(key); - vsize = PyUnicode_GET_SIZE(value); - totalsize = (p - PyUnicode_AS_UNICODE(out)) + ksize + 1 + - vsize + 1 + 1; - if (totalsize > PyUnicode_GET_SIZE(out)) { - Py_ssize_t offset = p - PyUnicode_AS_UNICODE(out); - PyUnicode_Resize(&out, totalsize + 1024); - p = PyUnicode_AS_UNICODE(out) + offset; - } - Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(key), ksize); - p += ksize; - *p++ = '='; - Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(value), vsize); - p += vsize; - *p++ = '\0'; - } - - /* add trailing null byte */ - *p++ = '\0'; - PyUnicode_Resize(&out, p - PyUnicode_AS_UNICODE(out)); - - /* PyObject_Print(out, stdout, 0); */ - - Py_XDECREF(keys); - Py_XDECREF(values); - - return out; - - error: - Py_XDECREF(out); - Py_XDECREF(keys); - Py_XDECREF(values); - return NULL; -} - -PyDoc_STRVAR(CreateProcess_doc, -"CreateProcess(app_name, cmd_line, proc_attrs, thread_attrs,\n\ - inherit, flags, env_mapping, curdir,\n\ - startup_info) -> (proc_handle, thread_handle,\n\ - pid, tid)\n\ -\n\ -Create a new process and its primary thread. The return\n\ -value is a tuple of the process handle, thread handle,\n\ -process ID, and thread ID.\n\ -\n\ -proc_attrs and thread_attrs are ignored internally and can be None."); - -static PyObject * -sp_CreateProcess(PyObject* self, PyObject* args) -{ - BOOL result; - PROCESS_INFORMATION pi; - STARTUPINFOW si; - PyObject* environment; - - Py_UNICODE* application_name; - Py_UNICODE* command_line; - PyObject* process_attributes; /* ignored */ - PyObject* thread_attributes; /* ignored */ - int inherit_handles; - int creation_flags; - PyObject* env_mapping; - Py_UNICODE* current_directory; - PyObject* startup_info; - - if (! PyArg_ParseTuple(args, "ZZOOiiOZO:CreateProcess", - &application_name, - &command_line, - &process_attributes, - &thread_attributes, - &inherit_handles, - &creation_flags, - &env_mapping, - ¤t_directory, - &startup_info)) - return NULL; - - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - /* note: we only support a small subset of all SI attributes */ - si.dwFlags = getint(startup_info, "dwFlags"); - si.wShowWindow = getint(startup_info, "wShowWindow"); - si.hStdInput = gethandle(startup_info, "hStdInput"); - si.hStdOutput = gethandle(startup_info, "hStdOutput"); - si.hStdError = gethandle(startup_info, "hStdError"); - - if (PyErr_Occurred()) - return NULL; - - if (env_mapping == Py_None) - environment = NULL; - else { - environment = getenvironment(env_mapping); - if (! environment) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - result = CreateProcessW(application_name, - command_line, - NULL, - NULL, - inherit_handles, - creation_flags | CREATE_UNICODE_ENVIRONMENT, - environment ? PyUnicode_AS_UNICODE(environment) : NULL, - current_directory, - &si, - &pi); - Py_END_ALLOW_THREADS - - Py_XDECREF(environment); - - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); - - return Py_BuildValue("NNii", - sp_handle_new(pi.hProcess), - sp_handle_new(pi.hThread), - pi.dwProcessId, - pi.dwThreadId); -} - -PyDoc_STRVAR(TerminateProcess_doc, -"TerminateProcess(handle, exit_code) -> None\n\ -\n\ -Terminate the specified process and all of its threads."); - -static PyObject * -sp_TerminateProcess(PyObject* self, PyObject* args) -{ - BOOL result; - - HANDLE process; - int exit_code; - if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:TerminateProcess", - &process, &exit_code)) - return NULL; - - result = TerminateProcess(process, exit_code); - - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); - - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(GetExitCodeProcess_doc, -"GetExitCodeProcess(handle) -> Exit code\n\ -\n\ -Return the termination status of the specified process."); - -static PyObject * -sp_GetExitCodeProcess(PyObject* self, PyObject* args) -{ - DWORD exit_code; - BOOL result; - - HANDLE process; - if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetExitCodeProcess", &process)) - return NULL; - - result = GetExitCodeProcess(process, &exit_code); - - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); - - return PyLong_FromLong(exit_code); -} - -PyDoc_STRVAR(WaitForSingleObject_doc, -"WaitForSingleObject(handle, timeout) -> result\n\ -\n\ -Wait until the specified object is in the signaled state or\n\ -the time-out interval elapses. The timeout value is specified\n\ -in milliseconds."); - -static PyObject * -sp_WaitForSingleObject(PyObject* self, PyObject* args) -{ - DWORD result; - - HANDLE handle; - int milliseconds; - if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:WaitForSingleObject", - &handle, - &milliseconds)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - result = WaitForSingleObject(handle, (DWORD) milliseconds); - Py_END_ALLOW_THREADS - - if (result == WAIT_FAILED) - return PyErr_SetFromWindowsErr(GetLastError()); - - return PyLong_FromLong((int) result); -} - -PyDoc_STRVAR(GetVersion_doc, -"GetVersion() -> version\n\ -\n\ -Return the version number of the current operating system."); - -static PyObject * -sp_GetVersion(PyObject* self, PyObject* args) -{ - if (! PyArg_ParseTuple(args, ":GetVersion")) - return NULL; - - return PyLong_FromLong((int) GetVersion()); -} - -PyDoc_STRVAR(GetModuleFileName_doc, -"GetModuleFileName(module) -> path\n\ -\n\ -Return the fully-qualified path for the file that contains\n\ -the specified module. The module must have been loaded by the\n\ -current process.\n\ -\n\ -The module parameter should be a handle to the loaded module\n\ -whose path is being requested. If this parameter is 0, \n\ -GetModuleFileName retrieves the path of the executable file\n\ -of the current process."); - -static PyObject * -sp_GetModuleFileName(PyObject* self, PyObject* args) -{ - BOOL result; - HMODULE module; - WCHAR filename[MAX_PATH]; - - if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetModuleFileName", - &module)) - return NULL; - - result = GetModuleFileNameW(module, filename, MAX_PATH); - filename[MAX_PATH-1] = '\0'; - - if (! result) - return PyErr_SetFromWindowsErr(GetLastError()); - - return PyUnicode_FromUnicode(filename, Py_UNICODE_strlen(filename)); -} - -static PyMethodDef sp_functions[] = { - {"GetStdHandle", sp_GetStdHandle, METH_VARARGS, GetStdHandle_doc}, - {"GetCurrentProcess", sp_GetCurrentProcess, METH_VARARGS, - GetCurrentProcess_doc}, - {"DuplicateHandle", sp_DuplicateHandle, METH_VARARGS, - DuplicateHandle_doc}, - {"CreatePipe", sp_CreatePipe, METH_VARARGS, CreatePipe_doc}, - {"CreateProcess", sp_CreateProcess, METH_VARARGS, CreateProcess_doc}, - {"TerminateProcess", sp_TerminateProcess, METH_VARARGS, - TerminateProcess_doc}, - {"GetExitCodeProcess", sp_GetExitCodeProcess, METH_VARARGS, - GetExitCodeProcess_doc}, - {"WaitForSingleObject", sp_WaitForSingleObject, METH_VARARGS, - WaitForSingleObject_doc}, - {"GetVersion", sp_GetVersion, METH_VARARGS, GetVersion_doc}, - {"GetModuleFileName", sp_GetModuleFileName, METH_VARARGS, - GetModuleFileName_doc}, - {NULL, NULL} -}; - -/* -------------------------------------------------------------------- */ - -static void -defint(PyObject* d, const char* name, int value) -{ - PyObject* v = PyLong_FromLong((long) value); - if (v) { - PyDict_SetItemString(d, (char*) name, v); - Py_DECREF(v); - } -} - -static struct PyModuleDef _subprocessmodule = { - PyModuleDef_HEAD_INIT, - "_subprocess", - NULL, - -1, - sp_functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__subprocess() -{ - PyObject *d; - PyObject *m; - - /* patch up object descriptors */ - sp_handle_as_number.nb_int = (unaryfunc) sp_handle_as_int; - if (PyType_Ready(&sp_handle_type) < 0) - return NULL; - - m = PyModule_Create(&_subprocessmodule); - if (m == NULL) - return NULL; - d = PyModule_GetDict(m); - - /* constants */ - defint(d, "STD_INPUT_HANDLE", STD_INPUT_HANDLE); - defint(d, "STD_OUTPUT_HANDLE", STD_OUTPUT_HANDLE); - defint(d, "STD_ERROR_HANDLE", STD_ERROR_HANDLE); - defint(d, "DUPLICATE_SAME_ACCESS", DUPLICATE_SAME_ACCESS); - defint(d, "STARTF_USESTDHANDLES", STARTF_USESTDHANDLES); - defint(d, "STARTF_USESHOWWINDOW", STARTF_USESHOWWINDOW); - defint(d, "SW_HIDE", SW_HIDE); - defint(d, "INFINITE", INFINITE); - defint(d, "WAIT_OBJECT_0", WAIT_OBJECT_0); - defint(d, "WAIT_TIMEOUT", WAIT_TIMEOUT); - defint(d, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE); - defint(d, "CREATE_NEW_PROCESS_GROUP", CREATE_NEW_PROCESS_GROUP); - - return m; -} diff --git a/PC/_windows.c b/PC/_windows.c new file mode 100644 --- /dev/null +++ b/PC/_windows.c @@ -0,0 +1,965 @@ +/* + * Windows functions used for subprocess, multiprocessing, and others. + * + * Copyright (c) 2004 by Fredrik Lundh + * Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com + * Copyright (c) 2004 by Peter Astrand + * + * 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 + * authors not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL THE AUTHORS 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. + * + */ + +/* Licensed to PSF under a Contributor Agreement. */ +/* See http://www.python.org/2.4/license for licensing details. */ + +#include "Python.h" + +#define WINDOWS_LEAN_AND_MEAN +#include "windows.h" + +#ifdef Py_DEBUG +#include +#endif + +/* -------------------------------------------------------------------- */ +/* handle wrapper. note that this library uses integers when passing + handles to a function, and handle wrappers when returning handles. + the wrapper is used to provide Detach and Close methods */ + +typedef struct { + PyObject_HEAD + HANDLE handle; +} _win_handle_object; + +static PyTypeObject _win_handle_type; + +static PyObject * +_win_handle_new(HANDLE handle) +{ + _win_handle_object *self; + + self = PyObject_NEW(_win_handle_object, &_win_handle_type); + if (self == NULL) + return NULL; + + self->handle = handle; + + return (PyObject*) self; +} + +#if defined(MS_WIN32) && !defined(MS_WIN64) +#define HANDLE_TO_PYNUM(handle) PyLong_FromLong((long) handle) +#define PY_HANDLE_PARAM "l" +#else +#define HANDLE_TO_PYNUM(handle) PyLong_FromLongLong((long long) handle) +#define PY_HANDLE_PARAM "L" +#endif + +static PyObject * +_win_handle_detach(_win_handle_object *self, PyObject *args) +{ + HANDLE handle; + + if (! PyArg_ParseTuple(args, ":Detach")) + return NULL; + + handle = self->handle; + + self->handle = INVALID_HANDLE_VALUE; + + /* note: return the current handle, as an integer */ + return HANDLE_TO_PYNUM(handle); +} + +static PyObject * +_win_handle_close(_win_handle_object *self, PyObject *args) +{ + if (! PyArg_ParseTuple(args, ":Close")) + return NULL; + + if (self->handle != INVALID_HANDLE_VALUE) { + CloseHandle(self->handle); + self->handle = INVALID_HANDLE_VALUE; + } + Py_INCREF(Py_None); + return Py_None; +} + +static void +_win_handle_dealloc(_win_handle_object *self) +{ + if (self->handle != INVALID_HANDLE_VALUE) + CloseHandle(self->handle); + PyObject_FREE(self); +} + +static PyMethodDef _win_handle_methods[] = { + {"Detach", (PyCFunction) _win_handle_detach, METH_VARARGS}, + {"Close", (PyCFunction) _win_handle_close, METH_VARARGS}, + {NULL, NULL} +}; + +static PyObject * +_win_handle_as_int(_win_handle_object *self) +{ + return HANDLE_TO_PYNUM(self->handle); +} + +static PyNumberMethods _win_handle_as_number; + +static PyTypeObject _win_handle_type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_windows_handle", sizeof(_win_handle_object), 0, + (destructor) _win_handle_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_reserved*/ + 0, /*tp_repr*/ + &_win_handle_as_number, /*tp_as_number */ + 0, /*tp_as_sequence */ + 0, /*tp_as_mapping */ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + _win_handle_methods, /*tp_methods*/ +}; + +/* -------------------------------------------------------------------- */ +/* windows API functions */ + +PyDoc_STRVAR(GetStdHandle_doc, +"GetStdHandle(handle) -> integer\n\ +\n\ +Return a handle to the specified standard device\n\ +(STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE).\n\ +The integer associated with the handle object is returned."); + +static PyObject * +_win_GetStdHandle(PyObject *self, PyObject *args) +{ + HANDLE handle; + int std_handle; + + if (! PyArg_ParseTuple(args, "i:GetStdHandle", &std_handle)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + handle = GetStdHandle((DWORD) std_handle); + Py_END_ALLOW_THREADS + + if (handle == INVALID_HANDLE_VALUE) + return PyErr_SetFromWindowsErr(GetLastError()); + + if (! handle) { + Py_INCREF(Py_None); + return Py_None; + } + + /* note: returns integer, not handle object */ + return HANDLE_TO_PYNUM(handle); +} + +PyDoc_STRVAR(GetCurrentProcess_doc, +"GetCurrentProcess() -> handle\n\ +\n\ +Return a handle object for the current process."); + +static PyObject * +_win_GetCurrentProcess(PyObject *self) +{ + return _win_handle_new(GetCurrentProcess()); +} + +PyDoc_STRVAR(DuplicateHandle_doc, +"DuplicateHandle(source_proc_handle, source_handle,\n\ + target_proc_handle, target_handle, access,\n\ + inherit[, options]) -> handle\n\ +\n\ +Return a duplicate handle object.\n\ +\n\ +The duplicate handle refers to the same object as the original\n\ +handle. Therefore, any changes to the object are reflected\n\ +through both handles."); + +static PyObject * +_win_DuplicateHandle(PyObject *self, PyObject *args) +{ + HANDLE target_handle; + BOOL result; + + HANDLE source_process_handle; + HANDLE source_handle; + HANDLE target_process_handle; + int desired_access; + int inherit_handle; + int options = 0; + + if (! PyArg_ParseTuple(args, + PY_HANDLE_PARAM PY_HANDLE_PARAM PY_HANDLE_PARAM + "ii|i:DuplicateHandle", + &source_process_handle, + &source_handle, + &target_process_handle, + &desired_access, + &inherit_handle, + &options)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + result = DuplicateHandle( + source_process_handle, + source_handle, + target_process_handle, + &target_handle, + desired_access, + inherit_handle, + options + ); + Py_END_ALLOW_THREADS + + if (! result) + return PyErr_SetFromWindowsErr(GetLastError()); + + return _win_handle_new(target_handle); +} + +PyDoc_STRVAR(CloseHandle_doc, +"CloseHandle(handle) -> None\n\ +\n\ +Close a handle."); + +static PyObject * +_win_CloseHandle(PyObject *self, PyObject *args) +{ + HANDLE hObject; + BOOL success; + + if (!PyArg_ParseTuple(args, "K:CloseHandle", &hObject)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + success = CloseHandle(hObject); + Py_END_ALLOW_THREADS + + if (!success) + return PyErr_SetFromWindowsErr(0); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(CreateFile_doc, +"CreateFile(name, access, share, security,\n\ + creation, flags, template) -> handle\n\ +\n\ +Create or open a file given a name, access, sharing, etc parameters."); + +static PyObject * +_win_CreateFile(PyObject *self, PyObject *args) +{ + LPCTSTR lpFileName; + DWORD dwDesiredAccess; + DWORD dwShareMode; + LPSECURITY_ATTRIBUTES lpSecurityAttributes; + DWORD dwCreationDisposition; + DWORD dwFlagsAndAttributes; + HANDLE hTemplateFile; + HANDLE handle; + + if (!PyArg_ParseTuple(args, "skkKkkK:CreateFile", + &lpFileName, &dwDesiredAccess, &dwShareMode, + &lpSecurityAttributes, &dwCreationDisposition, + &dwFlagsAndAttributes, &hTemplateFile)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + handle = CreateFile(lpFileName, dwDesiredAccess, + dwShareMode, lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, hTemplateFile); + Py_END_ALLOW_THREADS + + if (handle == INVALID_HANDLE_VALUE) + return PyErr_SetFromWindowsErr(0); + + return Py_BuildValue("K", handle); +} + +PyDoc_STRVAR(CreatePipe_doc, +"CreatePipe(pipe_attrs, size) -> (read_handle, write_handle)\n\ +\n\ +Create an anonymous pipe, and return handles to the read and\n\ +write ends of the pipe.\n\ +\n\ +pipe_attrs is ignored internally and can be None."); + +static PyObject * +_win_CreatePipe(PyObject *self, PyObject *args) +{ + HANDLE read_pipe; + HANDLE write_pipe; + BOOL result; + + PyObject *pipe_attributes; /* ignored */ + int size; + + if (! PyArg_ParseTuple(args, "Oi:CreatePipe", &pipe_attributes, &size)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + result = CreatePipe(&read_pipe, &write_pipe, NULL, size); + Py_END_ALLOW_THREADS + + if (! result) + return PyErr_SetFromWindowsErr(GetLastError()); + + return Py_BuildValue( + "NN", _win_handle_new(read_pipe), _win_handle_new(write_pipe)); +} + +PyDoc_STRVAR(CreateNamedPipe_doc, +"CreateNamedPipe(name, open_mode, pipe_mode,\n\ + instances, out_bufsz, in_bufsz,\n\ + timeout, security) -> handle\n\ +\n\ +Create a named pipe and return a handle to the pipe."); + +static PyObject * +_win_CreateNamedPipe(PyObject *self, PyObject *args) +{ + LPCTSTR lpName; + DWORD dwOpenMode; + DWORD dwPipeMode; + DWORD nMaxInstances; + DWORD nOutBufferSize; + DWORD nInBufferSize; + DWORD nDefaultTimeOut; + LPSECURITY_ATTRIBUTES lpSecurityAttributes; + HANDLE handle; + + if (!PyArg_ParseTuple(args, "skkkkkkK", + &lpName, &dwOpenMode, &dwPipeMode, + &nMaxInstances, &nOutBufferSize, + &nInBufferSize, &nDefaultTimeOut, + &lpSecurityAttributes)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + handle = CreateNamedPipe(lpName, dwOpenMode, dwPipeMode, + nMaxInstances, nOutBufferSize, + nInBufferSize, nDefaultTimeOut, + lpSecurityAttributes); + Py_END_ALLOW_THREADS + + if (handle == INVALID_HANDLE_VALUE) + return PyErr_SetFromWindowsErr(0); + + return Py_BuildValue("K", handle); +} + +PyDoc_STRVAR(ConnectNamedPipe_doc, +"ConnectNamedPipe(pipe, overlapped_io) -> None\n\ +\n\ +Wait for a client to connect to the pipe.\n\ +Raises WindowsError if connection is unsuccessful."); + +static PyObject * +_win_ConnectNamedPipe(PyObject *self, PyObject *args) +{ + HANDLE hNamedPipe; + LPOVERLAPPED lpOverlapped; + BOOL success; + + if (!PyArg_ParseTuple(args, "KK", &hNamedPipe, &lpOverlapped)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + success = ConnectNamedPipe(hNamedPipe, lpOverlapped); + Py_END_ALLOW_THREADS + + if (!success) + return PyErr_SetFromWindowsErr(0); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(SetNamedPipeHandleState_doc, +"SetNamedPipeHandleState(pipe, mode, count, timeout) -> None\n\ +\n\ +Set the read mode and blocking mode of the specified pipe."); + +static PyObject * +_win_SetNamedPipeHandleState(PyObject *self, PyObject *args) +{ + HANDLE hNamedPipe; + PyObject *oArgs[3]; + DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL}; + int i; + + if (!PyArg_ParseTuple(args, "KOOO", + &hNamedPipe, &oArgs[0], &oArgs[1], &oArgs[2])) + return NULL; + + PyErr_Clear(); + + for (i = 0 ; i < 3 ; i++) { + if (oArgs[i] != Py_None) { + dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]); + if (PyErr_Occurred()) + return NULL; + pArgs[i] = &dwArgs[i]; + } + } + + if (!SetNamedPipeHandleState(hNamedPipe, pArgs[0], pArgs[1], pArgs[2])) + return PyErr_SetFromWindowsErr(0); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(WaitNamedPipe_doc, +"WaitNamedPipe(pipe, timeout) -> None\n\ +\n\ +Wait for a timeout or an available instance of the pipe."); + +static PyObject * +_win_WaitNamedPipe(PyObject *self, PyObject *args) +{ + LPCTSTR lpNamedPipeName; + DWORD nTimeOut; + BOOL success; + + if (!PyArg_ParseTuple(args, "sk:WaitNamedPipe", + &lpNamedPipeName, &nTimeOut)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + success = WaitNamedPipe(lpNamedPipeName, nTimeOut); + Py_END_ALLOW_THREADS + + if (!success) + return PyErr_SetFromWindowsErr(0); + + Py_RETURN_NONE; +} + +/* helpers for createprocess */ + +static int +getint(PyObject *obj, char *name) +{ + PyObject *value; + int ret; + + value = PyObject_GetAttrString(obj, name); + if (! value) { + PyErr_Clear(); /* FIXME: propagate error? */ + return 0; + } + ret = (int) PyLong_AsLong(value); + Py_DECREF(value); + return ret; +} + +static HANDLE +gethandle(PyObject *obj, char *name) +{ + _win_handle_object *value; + HANDLE ret; + + value = (_win_handle_object*) PyObject_GetAttrString(obj, name); + if (! value) { + PyErr_Clear(); /* FIXME: propagate error? */ + return NULL; + } + if (Py_TYPE(value) != &_win_handle_type) + ret = NULL; + else + ret = value->handle; + Py_DECREF(value); + return ret; +} + +static PyObject * +getenvironment(PyObject *environment) +{ + int i; + Py_ssize_t envsize; + PyObject *out = NULL; + PyObject *keys; + PyObject *values; + Py_UNICODE *p; + + /* convert environment dictionary to windows enviroment string */ + if (! PyMapping_Check(environment)) { + PyErr_SetString( + PyExc_TypeError, "environment must be dictionary or None"); + return NULL; + } + + envsize = PyMapping_Length(environment); + + keys = PyMapping_Keys(environment); + values = PyMapping_Values(environment); + if (!keys || !values) + goto error; + + out = PyUnicode_FromUnicode(NULL, 2048); + if (! out) + goto error; + + p = PyUnicode_AS_UNICODE(out); + + for (i = 0; i < envsize; i++) { + Py_ssize_t ksize, vsize, totalsize; + PyObject *key = PyList_GET_ITEM(keys, i); + PyObject *value = PyList_GET_ITEM(values, i); + + if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "environment can only contain strings"); + goto error; + } + ksize = PyUnicode_GET_SIZE(key); + vsize = PyUnicode_GET_SIZE(value); + totalsize = (p - PyUnicode_AS_UNICODE(out)) + ksize + 1 + + vsize + 1 + 1; + if (totalsize > PyUnicode_GET_SIZE(out)) { + Py_ssize_t offset = p - PyUnicode_AS_UNICODE(out); + PyUnicode_Resize(&out, totalsize + 1024); + p = PyUnicode_AS_UNICODE(out) + offset; + } + Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(key), ksize); + p += ksize; + *p++ = '='; + Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(value), vsize); + p += vsize; + *p++ = '\0'; + } + + /* add trailing null byte */ + *p++ = '\0'; + PyUnicode_Resize(&out, p - PyUnicode_AS_UNICODE(out)); + + /* PyObject_Print(out, stdout, 0); */ + + Py_XDECREF(keys); + Py_XDECREF(values); + + return out; + + error: + Py_XDECREF(out); + Py_XDECREF(keys); + Py_XDECREF(values); + return NULL; +} + +PyDoc_STRVAR(OpenProcess_doc, +"OpenProcess(access, inherit, pid) -> handle\n\ +\n\ +Open an existing process object."); + +static PyObject * +_win_OpenProcess(PyObject *self, PyObject *args) +{ + DWORD dwDesiredAccess; + BOOL bInheritHandle; + DWORD dwProcessId; + HANDLE handle; + + if (!PyArg_ParseTuple(args, "kik:OpenProcess", + &dwDesiredAccess, &bInheritHandle, &dwProcessId)) + return NULL; + + handle = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); + if (handle == NULL) + return PyErr_SetFromWindowsErr(0); + + return Py_BuildValue("K", handle); +} + +PyDoc_STRVAR(CreateProcess_doc, +"CreateProcess(app_name, cmd_line, proc_attrs, thread_attrs,\n\ + inherit, flags, env_mapping, curdir,\n\ + startup_info) -> (proc_handle, thread_handle,\n\ + pid, tid)\n\ +\n\ +Create a new process and its primary thread. The return\n\ +value is a tuple of the process handle, thread handle,\n\ +process ID, and thread ID.\n\ +\n\ +proc_attrs and thread_attrs are ignored internally and can be None."); + +static PyObject * +_win_CreateProcess(PyObject *self, PyObject *args) +{ + BOOL result; + PROCESS_INFORMATION pi; + STARTUPINFOW si; + PyObject *environment; + + Py_UNICODE *application_name; + Py_UNICODE *command_line; + PyObject *process_attributes; /* ignored */ + PyObject *thread_attributes; /* ignored */ + int inherit_handles; + int creation_flags; + PyObject *env_mapping; + Py_UNICODE *current_directory; + PyObject *startup_info; + + if (! PyArg_ParseTuple(args, "ZZOOiiOZO:CreateProcess", + &application_name, + &command_line, + &process_attributes, + &thread_attributes, + &inherit_handles, + &creation_flags, + &env_mapping, + ¤t_directory, + &startup_info)) + return NULL; + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + + /* note: we only support a small subset of all SI attributes */ + si.dwFlags = getint(startup_info, "dwFlags"); + si.wShowWindow = getint(startup_info, "wShowWindow"); + si.hStdInput = gethandle(startup_info, "hStdInput"); + si.hStdOutput = gethandle(startup_info, "hStdOutput"); + si.hStdError = gethandle(startup_info, "hStdError"); + + if (PyErr_Occurred()) + return NULL; + + if (env_mapping == Py_None) + environment = NULL; + else { + environment = getenvironment(env_mapping); + if (! environment) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + result = CreateProcessW(application_name, + command_line, + NULL, + NULL, + inherit_handles, + creation_flags | CREATE_UNICODE_ENVIRONMENT, + environment ? PyUnicode_AS_UNICODE(environment) : NULL, + current_directory, + &si, + &pi); + Py_END_ALLOW_THREADS + + Py_XDECREF(environment); + + if (! result) + return PyErr_SetFromWindowsErr(GetLastError()); + + return Py_BuildValue("NNii", + _win_handle_new(pi.hProcess), + _win_handle_new(pi.hThread), + pi.dwProcessId, + pi.dwThreadId); +} + +PyDoc_STRVAR(ExitProcess_doc, +"ExitProcess(retval)\n\ +\n\ +Exit the process and all of its threads."); + +static PyObject * +_win_ExitProcess(PyObject *self, PyObject *args) +{ + UINT uExitCode; + + if (!PyArg_ParseTuple(args, "I:ExitProcess", &uExitCode)) + return NULL; + +#if defined(Py_DEBUG) + SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); +#endif + + ExitProcess(uExitCode); + + return NULL; +} + +PyDoc_STRVAR(TerminateProcess_doc, +"TerminateProcess(handle, exit_code) -> None\n\ +\n\ +Terminate the specified process and all of its threads."); + +static PyObject * +_win_TerminateProcess(PyObject *self, PyObject *args) +{ + BOOL result; + + HANDLE process; + int exit_code; + if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:TerminateProcess", + &process, &exit_code)) + return NULL; + + result = TerminateProcess(process, exit_code); + + if (! result) + return PyErr_SetFromWindowsErr(GetLastError()); + + Py_INCREF(Py_None); + return Py_None; +} + +PyDoc_STRVAR(GetExitCodeProcess_doc, +"GetExitCodeProcess(handle) -> Exit code\n\ +\n\ +Return the termination status of the specified process."); + +static PyObject * +_win_GetExitCodeProcess(PyObject *self, PyObject *args) +{ + DWORD exit_code; + BOOL result; + + HANDLE process; + if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetExitCodeProcess", + &process)) + return NULL; + + result = GetExitCodeProcess(process, &exit_code); + + if (! result) + return PyErr_SetFromWindowsErr(GetLastError()); + + return PyLong_FromLong(exit_code); +} + +PyDoc_STRVAR(WaitForSingleObject_doc, +"WaitForSingleObject(handle, timeout) -> result\n\ +\n\ +Wait until the specified object is in the signaled state or\n\ +the time-out interval elapses. The timeout value is specified\n\ +in milliseconds."); + +static PyObject * +_win_WaitForSingleObject(PyObject *self, PyObject *args) +{ + DWORD result; + + HANDLE handle; + int milliseconds; + if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:WaitForSingleObject", + &handle, &milliseconds)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + result = WaitForSingleObject(handle, (DWORD) milliseconds); + Py_END_ALLOW_THREADS + + if (result == WAIT_FAILED) + return PyErr_SetFromWindowsErr(GetLastError()); + + return PyLong_FromLong((int) result); +} + +PyDoc_STRVAR(GetVersion_doc, +"GetVersion() -> version\n\ +\n\ +Return the version number of the current operating system."); + +static PyObject * +_win_GetVersion(PyObject *self) +{ + return PyLong_FromLong((int) GetVersion()); +} + +PyDoc_STRVAR(GetModuleFileName_doc, +"GetModuleFileName(module) -> path\n\ +\n\ +Return the fully-qualified path for the file that contains\n\ +the specified module. The module must have been loaded by the\n\ +current process.\n\ +\n\ +The module parameter should be a handle to the loaded module\n\ +whose path is being requested. If this parameter is 0, \n\ +GetModuleFileName retrieves the path of the executable file\n\ +of the current process."); + +static PyObject * +_win_GetModuleFileName(PyObject *self, PyObject *args) +{ + BOOL result; + HMODULE module; + WCHAR filename[MAX_PATH]; + + if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetModuleFileName", + &module)) + return NULL; + + result = GetModuleFileNameW(module, filename, MAX_PATH); + filename[MAX_PATH-1] = '\0'; + + if (! result) + return PyErr_SetFromWindowsErr(GetLastError()); + + return PyUnicode_FromUnicode(filename, Py_UNICODE_strlen(filename)); +} + +PyDoc_STRVAR(GetLastError_doc, +"GetModuleFileName(module) -> path\n\ +\n\ +Return the fully-qualified path for the file that contains\n\ +the specified module. The module must have been loaded by the\n\ +current process.\n\ +\n\ +The module parameter should be a handle to the loaded module\n\ +whose path is being requested. If this parameter is 0, \n\ +GetModuleFileName retrieves the path of the executable file\n\ +of the current process."); + +static PyObject * +_win_GetLastError(PyObject *self) +{ + return Py_BuildValue("k", GetLastError()); +} + +static PyMethodDef _windows_functions[] = { + {"GetStdHandle", _win_GetStdHandle, METH_VARARGS, GetStdHandle_doc}, + {"GetCurrentProcess", (PyCFunction)_win_GetCurrentProcess, METH_NOARGS, + GetCurrentProcess_doc}, + {"DuplicateHandle", _win_DuplicateHandle, METH_VARARGS, + DuplicateHandle_doc}, + {"CloseHandle", _win_CloseHandle, METH_VARARGS, CloseHandle_doc}, + {"CreateFile", _win_CreateFile, METH_VARARGS, CreateFile_doc}, + {"CreatePipe", _win_CreatePipe, METH_VARARGS, CreatePipe_doc}, + {"CreateNamedPipe", _win_CreateNamedPipe, METH_VARARGS, + CreateNamedPipe_doc}, + {"ConnectNamedPipe", _win_ConnectNamedPipe, METH_VARARGS, + ConnectNamedPipe_doc}, + {"SetNamedPipeHandleState", _win_SetNamedPipeHandleState, METH_VARARGS, + SetNamedPipeHandleState_doc}, + {"WaitNamedPipe", _win_WaitNamedPipe, METH_VARARGS, WaitNamedPipe_doc}, + {"OpenProcess", _win_OpenProcess, METH_VARARGS, OpenProcess_doc}, + {"CreateProcess", _win_CreateProcess, METH_VARARGS, CreateProcess_doc}, + {"ExitProcess", _win_ExitProcess, METH_VARARGS, ExitProcess_doc}, + {"TerminateProcess", _win_TerminateProcess, METH_VARARGS, + TerminateProcess_doc}, + {"GetExitCodeProcess", _win_GetExitCodeProcess, METH_VARARGS, + GetExitCodeProcess_doc}, + {"WaitForSingleObject", _win_WaitForSingleObject, METH_VARARGS, + WaitForSingleObject_doc}, + {"GetVersion", (PyCFunction)_win_GetVersion, METH_NOARGS, GetVersion_doc}, + {"GetModuleFileName", _win_GetModuleFileName, METH_VARARGS, + GetModuleFileName_doc}, + {"GetLastError", (PyCFunction)_win_GetLastError, METH_NOARGS, + GetLastError_doc}, + {NULL, NULL} +}; + +/* -------------------------------------------------------------------- */ + +static void +defint(PyObject *d, const char *name, int value) +{ + PyObject *v = PyLong_FromLong((long) value); + if (v) { + PyDict_SetItemString(d, (char*) name, v); + Py_DECREF(v); + } +} + +static struct PyModuleDef _windows_module= { + PyModuleDef_HEAD_INIT, + "_windows", + NULL, + -1, + _windows_functions, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit__windows() +{ + PyObject *d; + PyObject *m; + + /* patch up object descriptors */ + _win_handle_as_number.nb_int = (unaryfunc) _win_handle_as_int; + if (PyType_Ready(&_win_handle_type) < 0) + return NULL; + + m = PyModule_Create(&_windows_module); + if (m == NULL) + return NULL; + d = PyModule_GetDict(m); + + /* constants */ + defint(d, "STD_INPUT_HANDLE", STD_INPUT_HANDLE); + defint(d, "STD_OUTPUT_HANDLE", STD_OUTPUT_HANDLE); + defint(d, "STD_ERROR_HANDLE", STD_ERROR_HANDLE); + defint(d, "DUPLICATE_SAME_ACCESS", DUPLICATE_SAME_ACCESS); + defint(d, "STARTF_USESTDHANDLES", STARTF_USESTDHANDLES); + defint(d, "STARTF_USESHOWWINDOW", STARTF_USESHOWWINDOW); + defint(d, "SW_HIDE", SW_HIDE); + defint(d, "INFINITE", INFINITE); + defint(d, "WAIT_OBJECT_0", WAIT_OBJECT_0); + defint(d, "WAIT_TIMEOUT", WAIT_TIMEOUT); + defint(d, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE); + defint(d, "CREATE_NEW_PROCESS_GROUP", CREATE_NEW_PROCESS_GROUP); + defint(d, "ERROR_ALREADY_EXISTS", ERROR_ALREADY_EXISTS); + defint(d, "ERROR_PIPE_BUSY", ERROR_PIPE_BUSY); + defint(d, "ERROR_PIPE_CONNECTED", ERROR_PIPE_CONNECTED); + defint(d, "ERROR_SEM_TIMEOUT", ERROR_SEM_TIMEOUT); + defint(d, "GENERIC_READ", GENERIC_READ); + defint(d, "GENERIC_WRITE", GENERIC_WRITE); + defint(d, "NMPWAIT_WAIT_FOREVER", NMPWAIT_WAIT_FOREVER); + defint(d, "OPEN_EXISTING", OPEN_EXISTING); + defint(d, "PIPE_ACCESS_DUPLEX", PIPE_ACCESS_DUPLEX); + defint(d, "PIPE_ACCESS_INBOUND", PIPE_ACCESS_INBOUND); + defint(d, "PIPE_READMODE_MESSAGE", PIPE_READMODE_MESSAGE); + defint(d, "PIPE_TYPE_MESSAGE", PIPE_TYPE_MESSAGE); + defint(d, "PIPE_UNLIMITED_INSTANCES", PIPE_UNLIMITED_INSTANCES); + defint(d, "PIPE_WAIT", PIPE_WAIT); + defint(d, "PROCESS_ALL_ACCESS", PROCESS_ALL_ACCESS); + defint(d, "NULL", (int)NULL); + + return m; +} diff --git a/PC/config.c b/PC/config.c --- a/PC/config.c +++ b/PC/config.c @@ -56,7 +56,7 @@ extern PyObject* PyInit__codecs_jp(void); extern PyObject* PyInit__codecs_kr(void); extern PyObject* PyInit__codecs_tw(void); -extern PyObject* PyInit__subprocess(void); +extern PyObject* PyInit__windows(void); extern PyObject* PyInit__lsprof(void); extern PyObject* PyInit__ast(void); extern PyObject* PyInit__io(void); @@ -102,7 +102,7 @@ {"_locale", PyInit__locale}, #endif /* XXX Should _subprocess go in a WIN32 block? not WIN64? */ - {"_subprocess", PyInit__subprocess}, + {"_windows", PyInit__windows}, {"_codecs", PyInit__codecs}, {"_weakref", PyInit__weakref}, diff --git a/PCbuild/_multiprocessing.vcproj b/PCbuild/_multiprocessing.vcproj --- a/PCbuild/_multiprocessing.vcproj +++ b/PCbuild/_multiprocessing.vcproj @@ -546,10 +546,6 @@ RelativePath="..\Modules\_multiprocessing\socket_connection.c" > - - diff --git a/PCbuild/pythoncore.vcproj b/PCbuild/pythoncore.vcproj --- a/PCbuild/pythoncore.vcproj +++ b/PCbuild/pythoncore.vcproj @@ -1679,7 +1679,7 @@ Name="PC" >