1/*
2 * Win32 functions used by multiprocessing package
3 *
4 * win32_functions.c
5 *
6 * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
7 */
8
9#include "multiprocessing.h"
10
11
12#define WIN32_FUNCTION(func) \
13    {#func, (PyCFunction)win32_ ## func, METH_VARARGS | METH_STATIC, ""}
14
15#define WIN32_CONSTANT(fmt, con) \
16    PyDict_SetItemString(Win32Type.tp_dict, #con, Py_BuildValue(fmt, con))
17
18
19static PyObject *
20win32_CloseHandle(PyObject *self, PyObject *args)
21{
22    HANDLE hObject;
23    BOOL success;
24
25    if (!PyArg_ParseTuple(args, F_HANDLE, &hObject))
26        return NULL;
27
28    Py_BEGIN_ALLOW_THREADS
29    success = CloseHandle(hObject);
30    Py_END_ALLOW_THREADS
31
32    if (!success)
33        return PyErr_SetFromWindowsErr(0);
34
35    Py_RETURN_NONE;
36}
37
38static PyObject *
39win32_ConnectNamedPipe(PyObject *self, PyObject *args)
40{
41    HANDLE hNamedPipe;
42    LPOVERLAPPED lpOverlapped;
43    BOOL success;
44
45    if (!PyArg_ParseTuple(args, F_HANDLE F_POINTER,
46                          &hNamedPipe, &lpOverlapped))
47        return NULL;
48
49    Py_BEGIN_ALLOW_THREADS
50    success = ConnectNamedPipe(hNamedPipe, lpOverlapped);
51    Py_END_ALLOW_THREADS
52
53    if (!success)
54        return PyErr_SetFromWindowsErr(0);
55
56    Py_RETURN_NONE;
57}
58
59static PyObject *
60win32_CreateFile(PyObject *self, PyObject *args)
61{
62    LPCTSTR lpFileName;
63    DWORD dwDesiredAccess;
64    DWORD dwShareMode;
65    LPSECURITY_ATTRIBUTES lpSecurityAttributes;
66    DWORD dwCreationDisposition;
67    DWORD dwFlagsAndAttributes;
68    HANDLE hTemplateFile;
69    HANDLE handle;
70
71    if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_POINTER
72                          F_DWORD F_DWORD F_HANDLE,
73                          &lpFileName, &dwDesiredAccess, &dwShareMode,
74                          &lpSecurityAttributes, &dwCreationDisposition,
75                          &dwFlagsAndAttributes, &hTemplateFile))
76        return NULL;
77
78    Py_BEGIN_ALLOW_THREADS
79    handle = CreateFile(lpFileName, dwDesiredAccess,
80                        dwShareMode, lpSecurityAttributes,
81                        dwCreationDisposition,
82                        dwFlagsAndAttributes, hTemplateFile);
83    Py_END_ALLOW_THREADS
84
85    if (handle == INVALID_HANDLE_VALUE)
86        return PyErr_SetFromWindowsErr(0);
87
88    return Py_BuildValue(F_HANDLE, handle);
89}
90
91static PyObject *
92win32_CreateNamedPipe(PyObject *self, PyObject *args)
93{
94    LPCTSTR lpName;
95    DWORD dwOpenMode;
96    DWORD dwPipeMode;
97    DWORD nMaxInstances;
98    DWORD nOutBufferSize;
99    DWORD nInBufferSize;
100    DWORD nDefaultTimeOut;
101    LPSECURITY_ATTRIBUTES lpSecurityAttributes;
102    HANDLE handle;
103
104    if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_DWORD
105                          F_DWORD F_DWORD F_DWORD F_POINTER,
106                          &lpName, &dwOpenMode, &dwPipeMode,
107                          &nMaxInstances, &nOutBufferSize,
108                          &nInBufferSize, &nDefaultTimeOut,
109                          &lpSecurityAttributes))
110        return NULL;
111
112    Py_BEGIN_ALLOW_THREADS
113    handle = CreateNamedPipe(lpName, dwOpenMode, dwPipeMode,
114                             nMaxInstances, nOutBufferSize,
115                             nInBufferSize, nDefaultTimeOut,
116                             lpSecurityAttributes);
117    Py_END_ALLOW_THREADS
118
119    if (handle == INVALID_HANDLE_VALUE)
120        return PyErr_SetFromWindowsErr(0);
121
122    return Py_BuildValue(F_HANDLE, handle);
123}
124
125static PyObject *
126win32_ExitProcess(PyObject *self, PyObject *args)
127{
128    UINT uExitCode;
129
130    if (!PyArg_ParseTuple(args, "I", &uExitCode))
131        return NULL;
132
133    #if defined(Py_DEBUG)
134        SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
135        _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
136    #endif
137
138
139    ExitProcess(uExitCode);
140
141    return NULL;
142}
143
144static PyObject *
145win32_GetLastError(PyObject *self, PyObject *args)
146{
147    return Py_BuildValue(F_DWORD, GetLastError());
148}
149
150static PyObject *
151win32_OpenProcess(PyObject *self, PyObject *args)
152{
153    DWORD dwDesiredAccess;
154    BOOL bInheritHandle;
155    DWORD dwProcessId;
156    HANDLE handle;
157
158    if (!PyArg_ParseTuple(args, F_DWORD "i" F_DWORD,
159                          &dwDesiredAccess, &bInheritHandle, &dwProcessId))
160        return NULL;
161
162    handle = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
163    if (handle == NULL)
164        return PyErr_SetFromWindowsErr(0);
165
166    return Py_BuildValue(F_HANDLE, handle);
167}
168
169static PyObject *
170win32_SetNamedPipeHandleState(PyObject *self, PyObject *args)
171{
172    HANDLE hNamedPipe;
173    PyObject *oArgs[3];
174    DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL};
175    int i;
176
177    if (!PyArg_ParseTuple(args, F_HANDLE "OOO",
178                          &hNamedPipe, &oArgs[0], &oArgs[1], &oArgs[2]))
179        return NULL;
180
181    PyErr_Clear();
182
183    for (i = 0 ; i < 3 ; i++) {
184        if (oArgs[i] != Py_None) {
185            dwArgs[i] = PyInt_AsUnsignedLongMask(oArgs[i]);
186            if (PyErr_Occurred())
187                return NULL;
188            pArgs[i] = &dwArgs[i];
189        }
190    }
191
192    if (!SetNamedPipeHandleState(hNamedPipe, pArgs[0], pArgs[1], pArgs[2]))
193        return PyErr_SetFromWindowsErr(0);
194
195    Py_RETURN_NONE;
196}
197
198static PyObject *
199win32_WaitNamedPipe(PyObject *self, PyObject *args)
200{
201    LPCTSTR lpNamedPipeName;
202    DWORD nTimeOut;
203    BOOL success;
204
205    if (!PyArg_ParseTuple(args, "s" F_DWORD, &lpNamedPipeName, &nTimeOut))
206        return NULL;
207
208    Py_BEGIN_ALLOW_THREADS
209    success = WaitNamedPipe(lpNamedPipeName, nTimeOut);
210    Py_END_ALLOW_THREADS
211
212    if (!success)
213        return PyErr_SetFromWindowsErr(0);
214
215    Py_RETURN_NONE;
216}
217
218static PyMethodDef win32_methods[] = {
219    WIN32_FUNCTION(CloseHandle),
220    WIN32_FUNCTION(GetLastError),
221    WIN32_FUNCTION(OpenProcess),
222    WIN32_FUNCTION(ExitProcess),
223    WIN32_FUNCTION(ConnectNamedPipe),
224    WIN32_FUNCTION(CreateFile),
225    WIN32_FUNCTION(CreateNamedPipe),
226    WIN32_FUNCTION(SetNamedPipeHandleState),
227    WIN32_FUNCTION(WaitNamedPipe),
228    {NULL}
229};
230
231
232PyTypeObject Win32Type = {
233    PyVarObject_HEAD_INIT(NULL, 0)
234};
235
236
237PyObject *
238create_win32_namespace(void)
239{
240    Win32Type.tp_name = "_multiprocessing.win32";
241    Win32Type.tp_methods = win32_methods;
242    if (PyType_Ready(&Win32Type) < 0)
243        return NULL;
244    Py_INCREF(&Win32Type);
245
246    WIN32_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
247    WIN32_CONSTANT(F_DWORD, ERROR_NO_DATA);
248    WIN32_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
249    WIN32_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
250    WIN32_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
251    WIN32_CONSTANT(F_DWORD, GENERIC_READ);
252    WIN32_CONSTANT(F_DWORD, GENERIC_WRITE);
253    WIN32_CONSTANT(F_DWORD, INFINITE);
254    WIN32_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
255    WIN32_CONSTANT(F_DWORD, OPEN_EXISTING);
256    WIN32_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
257    WIN32_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
258    WIN32_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
259    WIN32_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE);
260    WIN32_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES);
261    WIN32_CONSTANT(F_DWORD, PIPE_WAIT);
262    WIN32_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
263
264    WIN32_CONSTANT("i", NULL);
265
266    return (PyObject*)&Win32Type;
267}
268