blob: 12dc0cd8478208cbf8c5e76e5335327132f4ff94 [file] [log] [blame]
Benjamin Petersonfa268032008-06-13 19:28:21 +00001/*
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{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000022 HANDLE hObject;
23 BOOL success;
Benjamin Petersonfa268032008-06-13 19:28:21 +000024
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000025 if (!PyArg_ParseTuple(args, F_HANDLE, &hObject))
26 return NULL;
Benjamin Petersonfa268032008-06-13 19:28:21 +000027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000028 Py_BEGIN_ALLOW_THREADS
29 success = CloseHandle(hObject);
30 Py_END_ALLOW_THREADS
Benjamin Petersonfa268032008-06-13 19:28:21 +000031
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000032 if (!success)
33 return PyErr_SetFromWindowsErr(0);
Benjamin Petersonfa268032008-06-13 19:28:21 +000034
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000035 Py_RETURN_NONE;
Benjamin Petersonfa268032008-06-13 19:28:21 +000036}
37
38static PyObject *
39win32_ConnectNamedPipe(PyObject *self, PyObject *args)
40{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000041 HANDLE hNamedPipe;
42 LPOVERLAPPED lpOverlapped;
43 BOOL success;
Benjamin Petersonfa268032008-06-13 19:28:21 +000044
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000045 if (!PyArg_ParseTuple(args, F_HANDLE F_POINTER,
46 &hNamedPipe, &lpOverlapped))
47 return NULL;
Benjamin Petersonfa268032008-06-13 19:28:21 +000048
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000049 Py_BEGIN_ALLOW_THREADS
50 success = ConnectNamedPipe(hNamedPipe, lpOverlapped);
51 Py_END_ALLOW_THREADS
Benjamin Petersonfa268032008-06-13 19:28:21 +000052
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000053 if (!success)
54 return PyErr_SetFromWindowsErr(0);
Benjamin Petersonfa268032008-06-13 19:28:21 +000055
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000056 Py_RETURN_NONE;
Benjamin Petersonfa268032008-06-13 19:28:21 +000057}
58
59static PyObject *
60win32_CreateFile(PyObject *self, PyObject *args)
61{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000062 LPCTSTR lpFileName;
63 DWORD dwDesiredAccess;
64 DWORD dwShareMode;
65 LPSECURITY_ATTRIBUTES lpSecurityAttributes;
66 DWORD dwCreationDisposition;
67 DWORD dwFlagsAndAttributes;
68 HANDLE hTemplateFile;
69 HANDLE handle;
Benjamin Petersonfa268032008-06-13 19:28:21 +000070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 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;
Benjamin Petersonfa268032008-06-13 19:28:21 +000077
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000078 Py_BEGIN_ALLOW_THREADS
79 handle = CreateFile(lpFileName, dwDesiredAccess,
80 dwShareMode, lpSecurityAttributes,
81 dwCreationDisposition,
82 dwFlagsAndAttributes, hTemplateFile);
83 Py_END_ALLOW_THREADS
Benjamin Petersonfa268032008-06-13 19:28:21 +000084
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000085 if (handle == INVALID_HANDLE_VALUE)
86 return PyErr_SetFromWindowsErr(0);
Benjamin Petersonfa268032008-06-13 19:28:21 +000087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000088 return Py_BuildValue(F_HANDLE, handle);
Benjamin Petersonfa268032008-06-13 19:28:21 +000089}
90
91static PyObject *
92win32_CreateNamedPipe(PyObject *self, PyObject *args)
93{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000094 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;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000104 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;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000112 Py_BEGIN_ALLOW_THREADS
113 handle = CreateNamedPipe(lpName, dwOpenMode, dwPipeMode,
114 nMaxInstances, nOutBufferSize,
115 nInBufferSize, nDefaultTimeOut,
116 lpSecurityAttributes);
117 Py_END_ALLOW_THREADS
Benjamin Petersonfa268032008-06-13 19:28:21 +0000118
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000119 if (handle == INVALID_HANDLE_VALUE)
120 return PyErr_SetFromWindowsErr(0);
Benjamin Petersonfa268032008-06-13 19:28:21 +0000121
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000122 return Py_BuildValue(F_HANDLE, handle);
Benjamin Petersonfa268032008-06-13 19:28:21 +0000123}
124
125static PyObject *
126win32_ExitProcess(PyObject *self, PyObject *args)
127{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000128 UINT uExitCode;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000129
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000130 if (!PyArg_ParseTuple(args, "I", &uExitCode))
131 return NULL;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000132
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000133 #if defined(Py_DEBUG)
134 SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
135 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
136 #endif
Kristján Valur Jónssonb8e138a2009-07-04 15:16:38 +0000137
138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000139 ExitProcess(uExitCode);
Benjamin Petersonfa268032008-06-13 19:28:21 +0000140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 return NULL;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000142}
143
144static PyObject *
145win32_GetLastError(PyObject *self, PyObject *args)
146{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 return Py_BuildValue(F_DWORD, GetLastError());
Benjamin Petersonfa268032008-06-13 19:28:21 +0000148}
149
150static PyObject *
151win32_OpenProcess(PyObject *self, PyObject *args)
152{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000153 DWORD dwDesiredAccess;
154 BOOL bInheritHandle;
155 DWORD dwProcessId;
156 HANDLE handle;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000157
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000158 if (!PyArg_ParseTuple(args, F_DWORD "i" F_DWORD,
159 &dwDesiredAccess, &bInheritHandle, &dwProcessId))
160 return NULL;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000161
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000162 handle = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
163 if (handle == NULL)
164 return PyErr_SetFromWindowsErr(0);
Benjamin Petersonfa268032008-06-13 19:28:21 +0000165
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000166 return Py_BuildValue(F_HANDLE, handle);
Benjamin Petersonfa268032008-06-13 19:28:21 +0000167}
168
169static PyObject *
170win32_SetNamedPipeHandleState(PyObject *self, PyObject *args)
171{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172 HANDLE hNamedPipe;
173 PyObject *oArgs[3];
174 DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL};
175 int i;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000176
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 if (!PyArg_ParseTuple(args, F_HANDLE "OOO",
178 &hNamedPipe, &oArgs[0], &oArgs[1], &oArgs[2]))
179 return NULL;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000180
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 PyErr_Clear();
Benjamin Petersonfa268032008-06-13 19:28:21 +0000182
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000183 for (i = 0 ; i < 3 ; i++) {
184 if (oArgs[i] != Py_None) {
185 dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]);
186 if (PyErr_Occurred())
187 return NULL;
188 pArgs[i] = &dwArgs[i];
189 }
190 }
Benjamin Petersonfa268032008-06-13 19:28:21 +0000191
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000192 if (!SetNamedPipeHandleState(hNamedPipe, pArgs[0], pArgs[1], pArgs[2]))
193 return PyErr_SetFromWindowsErr(0);
Benjamin Petersonfa268032008-06-13 19:28:21 +0000194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 Py_RETURN_NONE;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000196}
197
198static PyObject *
199win32_WaitNamedPipe(PyObject *self, PyObject *args)
200{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000201 LPCTSTR lpNamedPipeName;
202 DWORD nTimeOut;
203 BOOL success;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000204
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 if (!PyArg_ParseTuple(args, "s" F_DWORD, &lpNamedPipeName, &nTimeOut))
206 return NULL;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000207
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 Py_BEGIN_ALLOW_THREADS
209 success = WaitNamedPipe(lpNamedPipeName, nTimeOut);
210 Py_END_ALLOW_THREADS
Benjamin Petersonfa268032008-06-13 19:28:21 +0000211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000212 if (!success)
213 return PyErr_SetFromWindowsErr(0);
Benjamin Petersonfa268032008-06-13 19:28:21 +0000214
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000215 Py_RETURN_NONE;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000216}
217
Antoine Pitrou87cf2202011-05-09 17:04:27 +0200218static PyObject *
219win32_closesocket(PyObject *self, PyObject *args)
220{
221 HANDLE handle;
222 int ret;
223
224 if (!PyArg_ParseTuple(args, F_HANDLE ":closesocket" , &handle))
225 return NULL;
226
227 Py_BEGIN_ALLOW_THREADS
228 ret = closesocket((SOCKET) handle);
229 Py_END_ALLOW_THREADS
230
231 if (ret)
232 return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError());
233 Py_RETURN_NONE;
234}
235
236static PyObject *
237win32_recv(PyObject *self, PyObject *args)
238{
239 HANDLE handle;
240 int size, nread;
241 PyObject *buf;
242
243 if (!PyArg_ParseTuple(args, F_HANDLE "i:recv" , &handle, &size))
244 return NULL;
245
246 buf = PyBytes_FromStringAndSize(NULL, size);
247 if (!buf)
248 return NULL;
249
250 Py_BEGIN_ALLOW_THREADS
251 nread = recv((SOCKET) handle, PyBytes_AS_STRING(buf), size, 0);
252 Py_END_ALLOW_THREADS
253
254 if (nread < 0) {
255 Py_DECREF(buf);
256 return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError());
257 }
258 _PyBytes_Resize(&buf, nread);
259 return buf;
260}
261
262static PyObject *
263win32_send(PyObject *self, PyObject *args)
264{
265 HANDLE handle;
266 Py_buffer buf;
267 int ret;
268
269 if (!PyArg_ParseTuple(args, F_HANDLE "y*:send" , &handle, &buf))
270 return NULL;
271
272 Py_BEGIN_ALLOW_THREADS
273 ret = send((SOCKET) handle, buf.buf, buf.len, 0);
274 Py_END_ALLOW_THREADS
275
276 PyBuffer_Release(&buf);
277 if (ret < 0)
278 return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError());
279 return PyLong_FromLong(ret);
280}
281
282static PyObject *
283win32_WriteFile(PyObject *self, PyObject *args)
284{
285 HANDLE handle;
286 Py_buffer buf;
287 int written;
288 BOOL ret;
289
290 if (!PyArg_ParseTuple(args, F_HANDLE "y*:WriteFile" , &handle, &buf))
291 return NULL;
292
293 Py_BEGIN_ALLOW_THREADS
294 ret = WriteFile(handle, buf.buf, buf.len, &written, NULL);
295 Py_END_ALLOW_THREADS
296
297 PyBuffer_Release(&buf);
298 if (!ret)
299 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
300 return PyLong_FromLong(written);
301}
302
303static PyObject *
304win32_ReadFile(PyObject *self, PyObject *args)
305{
306 HANDLE handle;
307 int size;
308 DWORD nread;
309 PyObject *buf;
310 BOOL ret;
311
312 if (!PyArg_ParseTuple(args, F_HANDLE "i:ReadFile" , &handle, &size))
313 return NULL;
314
315 buf = PyBytes_FromStringAndSize(NULL, size);
316 if (!buf)
317 return NULL;
318
319 Py_BEGIN_ALLOW_THREADS
320 ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread, NULL);
321 Py_END_ALLOW_THREADS
322
323 if (!ret && GetLastError() != ERROR_MORE_DATA) {
324 Py_DECREF(buf);
325 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
326 }
327 if (_PyBytes_Resize(&buf, nread))
328 return NULL;
329 return Py_BuildValue("NN", buf, PyBool_FromLong(ret));
330}
331
332static PyObject *
333win32_PeekNamedPipe(PyObject *self, PyObject *args)
334{
335 HANDLE handle;
336 int size = 0;
337 PyObject *buf = NULL;
338 DWORD nread, navail, nleft;
339 BOOL ret;
340
341 if (!PyArg_ParseTuple(args, F_HANDLE "|i:PeekNamedPipe" , &handle, &size))
342 return NULL;
343
344 if (size < 0) {
345 PyErr_SetString(PyExc_ValueError, "negative size");
346 return NULL;
347 }
348
349 if (size) {
350 buf = PyBytes_FromStringAndSize(NULL, size);
351 if (!buf)
352 return NULL;
353 Py_BEGIN_ALLOW_THREADS
354 ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread,
355 &navail, &nleft);
356 Py_END_ALLOW_THREADS
357 if (!ret) {
358 Py_DECREF(buf);
359 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
360 }
361 if (_PyBytes_Resize(&buf, nread))
362 return NULL;
363 return Py_BuildValue("Nii", buf, navail, nleft);
364 }
365 else {
366 Py_BEGIN_ALLOW_THREADS
367 ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft);
368 Py_END_ALLOW_THREADS
369 if (!ret) {
370 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
371 }
372 return Py_BuildValue("ii", navail, nleft);
373 }
374}
375
Benjamin Petersonfa268032008-06-13 19:28:21 +0000376static PyMethodDef win32_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000377 WIN32_FUNCTION(CloseHandle),
378 WIN32_FUNCTION(GetLastError),
379 WIN32_FUNCTION(OpenProcess),
380 WIN32_FUNCTION(ExitProcess),
381 WIN32_FUNCTION(ConnectNamedPipe),
382 WIN32_FUNCTION(CreateFile),
383 WIN32_FUNCTION(CreateNamedPipe),
Antoine Pitrou87cf2202011-05-09 17:04:27 +0200384 WIN32_FUNCTION(ReadFile),
385 WIN32_FUNCTION(PeekNamedPipe),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000386 WIN32_FUNCTION(SetNamedPipeHandleState),
387 WIN32_FUNCTION(WaitNamedPipe),
Antoine Pitrou87cf2202011-05-09 17:04:27 +0200388 WIN32_FUNCTION(WriteFile),
389 WIN32_FUNCTION(closesocket),
390 WIN32_FUNCTION(recv),
391 WIN32_FUNCTION(send),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000392 {NULL}
Benjamin Petersonfa268032008-06-13 19:28:21 +0000393};
394
395
396PyTypeObject Win32Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000397 PyVarObject_HEAD_INIT(NULL, 0)
Benjamin Petersonfa268032008-06-13 19:28:21 +0000398};
399
400
401PyObject *
402create_win32_namespace(void)
403{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000404 Win32Type.tp_name = "_multiprocessing.win32";
405 Win32Type.tp_methods = win32_methods;
406 if (PyType_Ready(&Win32Type) < 0)
407 return NULL;
408 Py_INCREF(&Win32Type);
Benjamin Petersonfa268032008-06-13 19:28:21 +0000409
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000410 WIN32_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
Antoine Pitrou87cf2202011-05-09 17:04:27 +0200411 WIN32_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
412 WIN32_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000413 WIN32_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
414 WIN32_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
415 WIN32_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
416 WIN32_CONSTANT(F_DWORD, GENERIC_READ);
417 WIN32_CONSTANT(F_DWORD, GENERIC_WRITE);
418 WIN32_CONSTANT(F_DWORD, INFINITE);
419 WIN32_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
420 WIN32_CONSTANT(F_DWORD, OPEN_EXISTING);
421 WIN32_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
422 WIN32_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
423 WIN32_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
424 WIN32_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE);
425 WIN32_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES);
426 WIN32_CONSTANT(F_DWORD, PIPE_WAIT);
427 WIN32_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
Benjamin Petersonfa268032008-06-13 19:28:21 +0000428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000429 WIN32_CONSTANT("i", NULL);
Benjamin Petersonfa268032008-06-13 19:28:21 +0000430
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000431 return (PyObject*)&Win32Type;
Benjamin Petersonfa268032008-06-13 19:28:21 +0000432}