blob: 83c3a3bb3526f38eb6fd2c3bfe9bfd2f4c1827d3 [file] [log] [blame]
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001/*
2 * Support routines from the Windows API
3 *
4 * This module was originally created by merging PC/_subprocess.c with
5 * Modules/_multiprocessing/win32_functions.c.
6 *
7 * Copyright (c) 2004 by Fredrik Lundh <fredrik@pythonware.com>
8 * Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com
9 * Copyright (c) 2004 by Peter Astrand <astrand@lysator.liu.se>
10 *
11 * By obtaining, using, and/or copying this software and/or its
12 * associated documentation, you agree that you have read, understood,
13 * and will comply with the following terms and conditions:
14 *
15 * Permission to use, copy, modify, and distribute this software and
16 * its associated documentation for any purpose and without fee is
17 * hereby granted, provided that the above copyright notice appears in
18 * all copies, and that both that copyright notice and this permission
19 * notice appear in supporting documentation, and that the name of the
20 * authors not be used in advertising or publicity pertaining to
21 * distribution of the software without specific, written prior
22 * permission.
23 *
24 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
25 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
26 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
27 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
28 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
29 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
30 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 *
32 */
33
34/* Licensed to PSF under a Contributor Agreement. */
35/* See http://www.python.org/2.4/license for licensing details. */
36
37#include "Python.h"
38#include "structmember.h"
39
40#define WINDOWS_LEAN_AND_MEAN
41#include "windows.h"
42#include <crtdbg.h>
Tim Golden0321cf22014-05-05 19:46:17 +010043#include "winreparse.h"
Antoine Pitrou23bba4c2012-04-18 20:51:15 +020044
45#if defined(MS_WIN32) && !defined(MS_WIN64)
46#define HANDLE_TO_PYNUM(handle) \
47 PyLong_FromUnsignedLong((unsigned long) handle)
48#define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLong(obj))
49#define F_POINTER "k"
50#define T_POINTER T_ULONG
51#else
52#define HANDLE_TO_PYNUM(handle) \
53 PyLong_FromUnsignedLongLong((unsigned long long) handle)
54#define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLongLong(obj))
55#define F_POINTER "K"
56#define T_POINTER T_ULONGLONG
57#endif
58
59#define F_HANDLE F_POINTER
60#define F_DWORD "k"
Antoine Pitrou23bba4c2012-04-18 20:51:15 +020061
62#define T_HANDLE T_POINTER
63
Victor Stinner71765772013-06-24 23:13:24 +020064#define DWORD_MAX 4294967295U
65
Antoine Pitrou23bba4c2012-04-18 20:51:15 +020066/* Grab CancelIoEx dynamically from kernel32 */
67static int has_CancelIoEx = -1;
68static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED);
69
70static int
71check_CancelIoEx()
72{
73 if (has_CancelIoEx == -1)
74 {
75 HINSTANCE hKernel32 = GetModuleHandle("KERNEL32");
76 * (FARPROC *) &Py_CancelIoEx = GetProcAddress(hKernel32,
77 "CancelIoEx");
78 has_CancelIoEx = (Py_CancelIoEx != NULL);
79 }
80 return has_CancelIoEx;
81}
82
83
84/*
85 * A Python object wrapping an OVERLAPPED structure and other useful data
86 * for overlapped I/O
87 */
88
89typedef struct {
90 PyObject_HEAD
91 OVERLAPPED overlapped;
92 /* For convenience, we store the file handle too */
93 HANDLE handle;
94 /* Whether there's I/O in flight */
95 int pending;
96 /* Whether I/O completed successfully */
97 int completed;
98 /* Buffer used for reading (optional) */
99 PyObject *read_buffer;
100 /* Buffer used for writing (optional) */
101 Py_buffer write_buffer;
102} OverlappedObject;
103
104static void
105overlapped_dealloc(OverlappedObject *self)
106{
107 DWORD bytes;
108 int err = GetLastError();
Richard Oudkerk633db6f2013-11-17 13:15:51 +0000109
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200110 if (self->pending) {
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200111 if (check_CancelIoEx() &&
Richard Oudkerk633db6f2013-11-17 13:15:51 +0000112 Py_CancelIoEx(self->handle, &self->overlapped) &&
113 GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE))
114 {
115 /* The operation is no longer pending -- nothing to do. */
116 }
117 else if (_Py_Finalizing == NULL)
118 {
119 /* The operation is still pending -- give a warning. This
120 will probably only happen on Windows XP. */
121 PyErr_SetString(PyExc_RuntimeError,
122 "I/O operations still in flight while destroying "
123 "Overlapped object, the process may crash");
124 PyErr_WriteUnraisable(NULL);
125 }
126 else
127 {
128 /* The operation is still pending, but the process is
129 probably about to exit, so we need not worry too much
130 about memory leaks. Leaking self prevents a potential
131 crash. This can happen when a daemon thread is cleaned
132 up at exit -- see #19565. We only expect to get here
133 on Windows XP. */
134 CloseHandle(self->overlapped.hEvent);
135 SetLastError(err);
136 return;
137 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200138 }
Richard Oudkerk633db6f2013-11-17 13:15:51 +0000139
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200140 CloseHandle(self->overlapped.hEvent);
141 SetLastError(err);
142 if (self->write_buffer.obj)
143 PyBuffer_Release(&self->write_buffer);
144 Py_CLEAR(self->read_buffer);
145 PyObject_Del(self);
146}
147
Zachary Waref2244ea2015-05-13 01:22:54 -0500148/*[clinic input]
149module _winapi
150class _winapi.Overlapped "OverlappedObject *" "&OverlappedType"
151[clinic start generated code]*/
152/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c13d3f5fd1dabb84]*/
153
154/*[python input]
155def create_converter(type_, format_unit):
156 name = type_ + '_converter'
157 # registered upon creation by CConverter's metaclass
158 type(name, (CConverter,), {'type': type_, 'format_unit': format_unit})
159
160# format unit differs between platforms for these
161create_converter('HANDLE', '" F_HANDLE "')
162create_converter('HMODULE', '" F_HANDLE "')
163create_converter('LPSECURITY_ATTRIBUTES', '" F_POINTER "')
164
165create_converter('BOOL', 'i') # F_BOOL used previously (always 'i')
166create_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter)
167create_converter('LPCTSTR', 's')
168create_converter('LPWSTR', 'u')
169create_converter('UINT', 'I') # F_UINT used previously (always 'I')
170
171class HANDLE_return_converter(CReturnConverter):
172 type = 'HANDLE'
173
174 def render(self, function, data):
175 self.declare(data)
176 self.err_occurred_if("_return_value == INVALID_HANDLE_VALUE", data)
177 data.return_conversion.append(
178 'if (_return_value == NULL)\n Py_RETURN_NONE;\n')
179 data.return_conversion.append(
180 'return_value = HANDLE_TO_PYNUM(_return_value);\n')
181
182class DWORD_return_converter(CReturnConverter):
183 type = 'DWORD'
184
185 def render(self, function, data):
186 self.declare(data)
187 self.err_occurred_if("_return_value == DWORD_MAX", data)
188 data.return_conversion.append(
189 'return_value = Py_BuildValue("k", _return_value);\n')
190[python start generated code]*/
191/*[python end generated code: output=da39a3ee5e6b4b0d input=374076979596ebba]*/
192
193#include "clinic/_winapi.c.h"
194
195/*[clinic input]
196_winapi.Overlapped.GetOverlappedResult
197
198 wait: bool
199 /
200[clinic start generated code]*/
201
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200202static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500203_winapi_Overlapped_GetOverlappedResult_impl(OverlappedObject *self, int wait)
204/*[clinic end generated code: output=bdd0c1ed6518cd03 input=194505ee8e0e3565]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200205{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200206 BOOL res;
207 DWORD transferred = 0;
208 DWORD err;
209
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200210 Py_BEGIN_ALLOW_THREADS
211 res = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
212 wait != 0);
213 Py_END_ALLOW_THREADS
214
215 err = res ? ERROR_SUCCESS : GetLastError();
216 switch (err) {
217 case ERROR_SUCCESS:
218 case ERROR_MORE_DATA:
219 case ERROR_OPERATION_ABORTED:
220 self->completed = 1;
221 self->pending = 0;
222 break;
223 case ERROR_IO_INCOMPLETE:
224 break;
225 default:
226 self->pending = 0;
227 return PyErr_SetExcFromWindowsErr(PyExc_IOError, err);
228 }
229 if (self->completed && self->read_buffer != NULL) {
230 assert(PyBytes_CheckExact(self->read_buffer));
231 if (transferred != PyBytes_GET_SIZE(self->read_buffer) &&
232 _PyBytes_Resize(&self->read_buffer, transferred))
233 return NULL;
234 }
235 return Py_BuildValue("II", (unsigned) transferred, (unsigned) err);
236}
237
Zachary Waref2244ea2015-05-13 01:22:54 -0500238/*[clinic input]
239_winapi.Overlapped.getbuffer
240[clinic start generated code]*/
241
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200242static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500243_winapi_Overlapped_getbuffer_impl(OverlappedObject *self)
244/*[clinic end generated code: output=95a3eceefae0f748 input=347fcfd56b4ceabd]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200245{
246 PyObject *res;
247 if (!self->completed) {
248 PyErr_SetString(PyExc_ValueError,
249 "can't get read buffer before GetOverlappedResult() "
250 "signals the operation completed");
251 return NULL;
252 }
253 res = self->read_buffer ? self->read_buffer : Py_None;
254 Py_INCREF(res);
255 return res;
256}
257
Zachary Waref2244ea2015-05-13 01:22:54 -0500258/*[clinic input]
259_winapi.Overlapped.cancel
260[clinic start generated code]*/
261
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200262static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500263_winapi_Overlapped_cancel_impl(OverlappedObject *self)
264/*[clinic end generated code: output=fcb9ab5df4ebdae5 input=cbf3da142290039f]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200265{
266 BOOL res = TRUE;
267
268 if (self->pending) {
269 Py_BEGIN_ALLOW_THREADS
270 if (check_CancelIoEx())
271 res = Py_CancelIoEx(self->handle, &self->overlapped);
272 else
273 res = CancelIo(self->handle);
274 Py_END_ALLOW_THREADS
275 }
276
277 /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
278 if (!res && GetLastError() != ERROR_NOT_FOUND)
279 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
280 self->pending = 0;
281 Py_RETURN_NONE;
282}
283
284static PyMethodDef overlapped_methods[] = {
Zachary Waref2244ea2015-05-13 01:22:54 -0500285 _WINAPI_OVERLAPPED_GETOVERLAPPEDRESULT_METHODDEF
286 _WINAPI_OVERLAPPED_GETBUFFER_METHODDEF
287 _WINAPI_OVERLAPPED_CANCEL_METHODDEF
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200288 {NULL}
289};
290
291static PyMemberDef overlapped_members[] = {
292 {"event", T_HANDLE,
293 offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
294 READONLY, "overlapped event handle"},
295 {NULL}
296};
297
298PyTypeObject OverlappedType = {
299 PyVarObject_HEAD_INIT(NULL, 0)
300 /* tp_name */ "_winapi.Overlapped",
301 /* tp_basicsize */ sizeof(OverlappedObject),
302 /* tp_itemsize */ 0,
303 /* tp_dealloc */ (destructor) overlapped_dealloc,
304 /* tp_print */ 0,
305 /* tp_getattr */ 0,
306 /* tp_setattr */ 0,
307 /* tp_reserved */ 0,
308 /* tp_repr */ 0,
309 /* tp_as_number */ 0,
310 /* tp_as_sequence */ 0,
311 /* tp_as_mapping */ 0,
312 /* tp_hash */ 0,
313 /* tp_call */ 0,
314 /* tp_str */ 0,
315 /* tp_getattro */ 0,
316 /* tp_setattro */ 0,
317 /* tp_as_buffer */ 0,
318 /* tp_flags */ Py_TPFLAGS_DEFAULT,
319 /* tp_doc */ "OVERLAPPED structure wrapper",
320 /* tp_traverse */ 0,
321 /* tp_clear */ 0,
322 /* tp_richcompare */ 0,
323 /* tp_weaklistoffset */ 0,
324 /* tp_iter */ 0,
325 /* tp_iternext */ 0,
326 /* tp_methods */ overlapped_methods,
327 /* tp_members */ overlapped_members,
328 /* tp_getset */ 0,
329 /* tp_base */ 0,
330 /* tp_dict */ 0,
331 /* tp_descr_get */ 0,
332 /* tp_descr_set */ 0,
333 /* tp_dictoffset */ 0,
334 /* tp_init */ 0,
335 /* tp_alloc */ 0,
336 /* tp_new */ 0,
337};
338
339static OverlappedObject *
340new_overlapped(HANDLE handle)
341{
342 OverlappedObject *self;
343
344 self = PyObject_New(OverlappedObject, &OverlappedType);
345 if (!self)
346 return NULL;
347 self->handle = handle;
348 self->read_buffer = NULL;
349 self->pending = 0;
350 self->completed = 0;
351 memset(&self->overlapped, 0, sizeof(OVERLAPPED));
352 memset(&self->write_buffer, 0, sizeof(Py_buffer));
353 /* Manual reset, initially non-signalled */
354 self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
355 return self;
356}
357
358/* -------------------------------------------------------------------- */
359/* windows API functions */
360
Zachary Waref2244ea2015-05-13 01:22:54 -0500361/*[clinic input]
362_winapi.CloseHandle
363
364 handle: HANDLE
365 /
366
367Close handle.
368[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200369
370static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500371_winapi_CloseHandle_impl(PyModuleDef *module, HANDLE handle)
372/*[clinic end generated code: output=0548595c71cb4bf7 input=7f0e4ac36e0352b8]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200373{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200374 BOOL success;
375
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200376 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500377 success = CloseHandle(handle);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200378 Py_END_ALLOW_THREADS
379
380 if (!success)
381 return PyErr_SetFromWindowsErr(0);
382
383 Py_RETURN_NONE;
384}
385
Zachary Waref2244ea2015-05-13 01:22:54 -0500386/*[clinic input]
387_winapi.ConnectNamedPipe
388
389 handle: HANDLE
390 overlapped as use_overlapped: int(c_default='0') = False
391[clinic start generated code]*/
392
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200393static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500394_winapi_ConnectNamedPipe_impl(PyModuleDef *module, HANDLE handle, int use_overlapped)
395/*[clinic end generated code: output=d9a64e59c27e10f6 input=edc83da007ebf3be]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200396{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200397 BOOL success;
398 OverlappedObject *overlapped = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200399
400 if (use_overlapped) {
Zachary Waref2244ea2015-05-13 01:22:54 -0500401 overlapped = new_overlapped(handle);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200402 if (!overlapped)
403 return NULL;
404 }
405
406 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500407 success = ConnectNamedPipe(handle,
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200408 overlapped ? &overlapped->overlapped : NULL);
409 Py_END_ALLOW_THREADS
410
411 if (overlapped) {
412 int err = GetLastError();
413 /* Overlapped ConnectNamedPipe never returns a success code */
414 assert(success == 0);
415 if (err == ERROR_IO_PENDING)
416 overlapped->pending = 1;
417 else if (err == ERROR_PIPE_CONNECTED)
418 SetEvent(overlapped->overlapped.hEvent);
419 else {
420 Py_DECREF(overlapped);
421 return PyErr_SetFromWindowsErr(err);
422 }
423 return (PyObject *) overlapped;
424 }
425 if (!success)
426 return PyErr_SetFromWindowsErr(0);
427
428 Py_RETURN_NONE;
429}
430
Zachary Waref2244ea2015-05-13 01:22:54 -0500431/*[clinic input]
432_winapi.CreateFile -> HANDLE
433
434 file_name: LPCTSTR
435 desired_access: DWORD
436 share_mode: DWORD
437 security_attributes: LPSECURITY_ATTRIBUTES
438 creation_disposition: DWORD
439 flags_and_attributes: DWORD
440 template_file: HANDLE
441 /
442[clinic start generated code]*/
443
444static HANDLE
445_winapi_CreateFile_impl(PyModuleDef *module, LPCTSTR file_name, DWORD desired_access, DWORD share_mode, LPSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD flags_and_attributes, HANDLE template_file)
446/*[clinic end generated code: output=f8649129a4959288 input=6423c3e40372dbd5]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200447{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200448 HANDLE handle;
449
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200450 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500451 handle = CreateFile(file_name, desired_access,
452 share_mode, security_attributes,
453 creation_disposition,
454 flags_and_attributes, template_file);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200455 Py_END_ALLOW_THREADS
456
457 if (handle == INVALID_HANDLE_VALUE)
Zachary Waref2244ea2015-05-13 01:22:54 -0500458 PyErr_SetFromWindowsErr(0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200459
Zachary Waref2244ea2015-05-13 01:22:54 -0500460 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200461}
462
Zachary Waref2244ea2015-05-13 01:22:54 -0500463/*[clinic input]
464_winapi.CreateJunction
Tim Golden0321cf22014-05-05 19:46:17 +0100465
Zachary Waref2244ea2015-05-13 01:22:54 -0500466 src_path: LPWSTR
467 dst_path: LPWSTR
468 /
469[clinic start generated code]*/
470
471static PyObject *
472_winapi_CreateJunction_impl(PyModuleDef *module, LPWSTR src_path, LPWSTR dst_path)
473/*[clinic end generated code: output=df22af7be7045584 input=8cd1f9964b6e3d36]*/
474{
Tim Golden0321cf22014-05-05 19:46:17 +0100475 /* Privilege adjustment */
476 HANDLE token = NULL;
477 TOKEN_PRIVILEGES tp;
478
479 /* Reparse data buffer */
480 const USHORT prefix_len = 4;
481 USHORT print_len = 0;
482 USHORT rdb_size = 0;
483 PREPARSE_DATA_BUFFER rdb = NULL;
484
485 /* Junction point creation */
486 HANDLE junction = NULL;
487 DWORD ret = 0;
488
Tim Golden0321cf22014-05-05 19:46:17 +0100489 if (src_path == NULL || dst_path == NULL)
490 return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
491
492 if (wcsncmp(src_path, L"\\??\\", prefix_len) == 0)
493 return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
494
495 /* Adjust privileges to allow rewriting directory entry as a
496 junction point. */
497 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
498 goto cleanup;
499
500 if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid))
501 goto cleanup;
502
503 tp.PrivilegeCount = 1;
504 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
505 if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
506 NULL, NULL))
507 goto cleanup;
508
509 if (GetFileAttributesW(src_path) == INVALID_FILE_ATTRIBUTES)
510 goto cleanup;
511
512 /* Store the absolute link target path length in print_len. */
513 print_len = (USHORT)GetFullPathNameW(src_path, 0, NULL, NULL);
514 if (print_len == 0)
515 goto cleanup;
516
517 /* NUL terminator should not be part of print_len. */
518 --print_len;
519
520 /* REPARSE_DATA_BUFFER usage is heavily under-documented, especially for
521 junction points. Here's what I've learned along the way:
522 - A junction point has two components: a print name and a substitute
523 name. They both describe the link target, but the substitute name is
524 the physical target and the print name is shown in directory listings.
525 - The print name must be a native name, prefixed with "\??\".
526 - Both names are stored after each other in the same buffer (the
527 PathBuffer) and both must be NUL-terminated.
528 - There are four members defining their respective offset and length
529 inside PathBuffer: SubstituteNameOffset, SubstituteNameLength,
530 PrintNameOffset and PrintNameLength.
531 - The total size we need to allocate for the REPARSE_DATA_BUFFER, thus,
532 is the sum of:
533 - the fixed header size (REPARSE_DATA_BUFFER_HEADER_SIZE)
534 - the size of the MountPointReparseBuffer member without the PathBuffer
535 - the size of the prefix ("\??\") in bytes
536 - the size of the print name in bytes
537 - the size of the substitute name in bytes
538 - the size of two NUL terminators in bytes */
539 rdb_size = REPARSE_DATA_BUFFER_HEADER_SIZE +
540 sizeof(rdb->MountPointReparseBuffer) -
541 sizeof(rdb->MountPointReparseBuffer.PathBuffer) +
542 /* Two +1's for NUL terminators. */
543 (prefix_len + print_len + 1 + print_len + 1) * sizeof(WCHAR);
544 rdb = (PREPARSE_DATA_BUFFER)PyMem_RawMalloc(rdb_size);
545 if (rdb == NULL)
546 goto cleanup;
547
548 memset(rdb, 0, rdb_size);
549 rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
550 rdb->ReparseDataLength = rdb_size - REPARSE_DATA_BUFFER_HEADER_SIZE;
551 rdb->MountPointReparseBuffer.SubstituteNameOffset = 0;
552 rdb->MountPointReparseBuffer.SubstituteNameLength =
553 (prefix_len + print_len) * sizeof(WCHAR);
554 rdb->MountPointReparseBuffer.PrintNameOffset =
555 rdb->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
556 rdb->MountPointReparseBuffer.PrintNameLength = print_len * sizeof(WCHAR);
557
558 /* Store the full native path of link target at the substitute name
559 offset (0). */
560 wcscpy(rdb->MountPointReparseBuffer.PathBuffer, L"\\??\\");
561 if (GetFullPathNameW(src_path, print_len + 1,
562 rdb->MountPointReparseBuffer.PathBuffer + prefix_len,
563 NULL) == 0)
564 goto cleanup;
565
566 /* Copy everything but the native prefix to the print name offset. */
567 wcscpy(rdb->MountPointReparseBuffer.PathBuffer +
568 prefix_len + print_len + 1,
569 rdb->MountPointReparseBuffer.PathBuffer + prefix_len);
570
571 /* Create a directory for the junction point. */
572 if (!CreateDirectoryW(dst_path, NULL))
573 goto cleanup;
574
575 junction = CreateFileW(dst_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
576 OPEN_EXISTING,
577 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
578 if (junction == INVALID_HANDLE_VALUE)
579 goto cleanup;
580
581 /* Make the directory entry a junction point. */
582 if (!DeviceIoControl(junction, FSCTL_SET_REPARSE_POINT, rdb, rdb_size,
583 NULL, 0, &ret, NULL))
584 goto cleanup;
585
586cleanup:
587 ret = GetLastError();
588
589 CloseHandle(token);
590 CloseHandle(junction);
591 PyMem_RawFree(rdb);
592
593 if (ret != 0)
594 return PyErr_SetFromWindowsErr(ret);
595
596 Py_RETURN_NONE;
597}
598
Zachary Waref2244ea2015-05-13 01:22:54 -0500599/*[clinic input]
600_winapi.CreateNamedPipe -> HANDLE
601
602 name: LPCTSTR
603 open_mode: DWORD
604 pipe_mode: DWORD
605 max_instances: DWORD
606 out_buffer_size: DWORD
607 in_buffer_size: DWORD
608 default_timeout: DWORD
609 security_attributes: LPSECURITY_ATTRIBUTES
610 /
611[clinic start generated code]*/
612
613static HANDLE
614_winapi_CreateNamedPipe_impl(PyModuleDef *module, LPCTSTR name, DWORD open_mode, DWORD pipe_mode, DWORD max_instances, DWORD out_buffer_size, DWORD in_buffer_size, DWORD default_timeout, LPSECURITY_ATTRIBUTES security_attributes)
615/*[clinic end generated code: output=711e231639c25c24 input=5a73530b84d8bc37]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200616{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200617 HANDLE handle;
618
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200619 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500620 handle = CreateNamedPipe(name, open_mode, pipe_mode,
621 max_instances, out_buffer_size,
622 in_buffer_size, default_timeout,
623 security_attributes);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200624 Py_END_ALLOW_THREADS
625
626 if (handle == INVALID_HANDLE_VALUE)
Zachary Waref2244ea2015-05-13 01:22:54 -0500627 PyErr_SetFromWindowsErr(0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200628
Zachary Waref2244ea2015-05-13 01:22:54 -0500629 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200630}
631
Zachary Waref2244ea2015-05-13 01:22:54 -0500632/*[clinic input]
633_winapi.CreatePipe
634
635 pipe_attrs: object
636 Ignored internally, can be None.
637 size: DWORD
638 /
639
640Create an anonymous pipe.
641
642Returns a 2-tuple of handles, to the read and write ends of the pipe.
643[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200644
645static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500646_winapi_CreatePipe_impl(PyModuleDef *module, PyObject *pipe_attrs, DWORD size)
647/*[clinic end generated code: output=ed09baf1d43086df input=c4f2cfa56ef68d90]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200648{
649 HANDLE read_pipe;
650 HANDLE write_pipe;
651 BOOL result;
652
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200653 Py_BEGIN_ALLOW_THREADS
654 result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
655 Py_END_ALLOW_THREADS
656
657 if (! result)
658 return PyErr_SetFromWindowsErr(GetLastError());
659
660 return Py_BuildValue(
661 "NN", HANDLE_TO_PYNUM(read_pipe), HANDLE_TO_PYNUM(write_pipe));
662}
663
664/* helpers for createprocess */
665
666static unsigned long
667getulong(PyObject* obj, char* name)
668{
669 PyObject* value;
670 unsigned long ret;
671
672 value = PyObject_GetAttrString(obj, name);
673 if (! value) {
674 PyErr_Clear(); /* FIXME: propagate error? */
675 return 0;
676 }
677 ret = PyLong_AsUnsignedLong(value);
678 Py_DECREF(value);
679 return ret;
680}
681
682static HANDLE
683gethandle(PyObject* obj, char* name)
684{
685 PyObject* value;
686 HANDLE ret;
687
688 value = PyObject_GetAttrString(obj, name);
689 if (! value) {
690 PyErr_Clear(); /* FIXME: propagate error? */
691 return NULL;
692 }
693 if (value == Py_None)
694 ret = NULL;
695 else
696 ret = PYNUM_TO_HANDLE(value);
697 Py_DECREF(value);
698 return ret;
699}
700
701static PyObject*
702getenvironment(PyObject* environment)
703{
704 Py_ssize_t i, envsize, totalsize;
705 Py_UCS4 *buffer = NULL, *p, *end;
706 PyObject *keys, *values, *res;
707
Ezio Melotti85a86292013-08-17 16:57:41 +0300708 /* convert environment dictionary to windows environment string */
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200709 if (! PyMapping_Check(environment)) {
710 PyErr_SetString(
711 PyExc_TypeError, "environment must be dictionary or None");
712 return NULL;
713 }
714
715 envsize = PyMapping_Length(environment);
716
717 keys = PyMapping_Keys(environment);
718 values = PyMapping_Values(environment);
719 if (!keys || !values)
720 goto error;
721
722 totalsize = 1; /* trailing null character */
723 for (i = 0; i < envsize; i++) {
724 PyObject* key = PyList_GET_ITEM(keys, i);
725 PyObject* value = PyList_GET_ITEM(values, i);
726
727 if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
728 PyErr_SetString(PyExc_TypeError,
729 "environment can only contain strings");
730 goto error;
731 }
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500732 if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(key) - 1) {
733 PyErr_SetString(PyExc_OverflowError, "environment too long");
734 goto error;
735 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200736 totalsize += PyUnicode_GET_LENGTH(key) + 1; /* +1 for '=' */
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500737 if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(value) - 1) {
738 PyErr_SetString(PyExc_OverflowError, "environment too long");
739 goto error;
740 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200741 totalsize += PyUnicode_GET_LENGTH(value) + 1; /* +1 for '\0' */
742 }
743
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500744 buffer = PyMem_NEW(Py_UCS4, totalsize);
745 if (! buffer) {
746 PyErr_NoMemory();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200747 goto error;
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500748 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200749 p = buffer;
750 end = buffer + totalsize;
751
752 for (i = 0; i < envsize; i++) {
753 PyObject* key = PyList_GET_ITEM(keys, i);
754 PyObject* value = PyList_GET_ITEM(values, i);
755 if (!PyUnicode_AsUCS4(key, p, end - p, 0))
756 goto error;
757 p += PyUnicode_GET_LENGTH(key);
758 *p++ = '=';
759 if (!PyUnicode_AsUCS4(value, p, end - p, 0))
760 goto error;
761 p += PyUnicode_GET_LENGTH(value);
762 *p++ = '\0';
763 }
764
765 /* add trailing null byte */
766 *p++ = '\0';
767 assert(p == end);
768
769 Py_XDECREF(keys);
770 Py_XDECREF(values);
771
772 res = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buffer, p - buffer);
773 PyMem_Free(buffer);
774 return res;
775
776 error:
777 PyMem_Free(buffer);
778 Py_XDECREF(keys);
779 Py_XDECREF(values);
780 return NULL;
781}
782
Zachary Waref2244ea2015-05-13 01:22:54 -0500783/*[clinic input]
784_winapi.CreateProcess
785
786 application_name: Py_UNICODE(nullable=True)
787 command_line: Py_UNICODE(nullable=True)
788 proc_attrs: object
789 Ignored internally, can be None.
790 thread_attrs: object
791 Ignored internally, can be None.
792 inherit_handles: BOOL
793 creation_flags: DWORD
794 env_mapping: object
795 current_directory: Py_UNICODE(nullable=True)
796 startup_info: object
797 /
798
799Create a new process and its primary thread.
800
801The return value is a tuple of the process handle, thread handle,
802process ID, and thread ID.
803[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200804
805static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500806_winapi_CreateProcess_impl(PyModuleDef *module, Py_UNICODE *application_name, Py_UNICODE *command_line, PyObject *proc_attrs, PyObject *thread_attrs, BOOL inherit_handles, DWORD creation_flags, PyObject *env_mapping, Py_UNICODE *current_directory, PyObject *startup_info)
807/*[clinic end generated code: output=c279c1271b4c45cf input=6667ea0bc7036472]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200808{
809 BOOL result;
810 PROCESS_INFORMATION pi;
811 STARTUPINFOW si;
812 PyObject* environment;
813 wchar_t *wenvironment;
814
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200815 ZeroMemory(&si, sizeof(si));
816 si.cb = sizeof(si);
817
818 /* note: we only support a small subset of all SI attributes */
819 si.dwFlags = getulong(startup_info, "dwFlags");
820 si.wShowWindow = (WORD)getulong(startup_info, "wShowWindow");
821 si.hStdInput = gethandle(startup_info, "hStdInput");
822 si.hStdOutput = gethandle(startup_info, "hStdOutput");
823 si.hStdError = gethandle(startup_info, "hStdError");
824 if (PyErr_Occurred())
825 return NULL;
826
827 if (env_mapping != Py_None) {
828 environment = getenvironment(env_mapping);
829 if (! environment)
830 return NULL;
831 wenvironment = PyUnicode_AsUnicode(environment);
832 if (wenvironment == NULL)
833 {
834 Py_XDECREF(environment);
835 return NULL;
836 }
837 }
838 else {
839 environment = NULL;
840 wenvironment = NULL;
841 }
842
843 Py_BEGIN_ALLOW_THREADS
844 result = CreateProcessW(application_name,
845 command_line,
846 NULL,
847 NULL,
848 inherit_handles,
849 creation_flags | CREATE_UNICODE_ENVIRONMENT,
850 wenvironment,
851 current_directory,
852 &si,
853 &pi);
854 Py_END_ALLOW_THREADS
855
856 Py_XDECREF(environment);
857
858 if (! result)
859 return PyErr_SetFromWindowsErr(GetLastError());
860
861 return Py_BuildValue("NNkk",
862 HANDLE_TO_PYNUM(pi.hProcess),
863 HANDLE_TO_PYNUM(pi.hThread),
864 pi.dwProcessId,
865 pi.dwThreadId);
866}
867
Zachary Waref2244ea2015-05-13 01:22:54 -0500868/*[clinic input]
869_winapi.DuplicateHandle -> HANDLE
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200870
Zachary Waref2244ea2015-05-13 01:22:54 -0500871 source_process_handle: HANDLE
872 source_handle: HANDLE
873 target_process_handle: HANDLE
874 desired_access: DWORD
875 inherit_handle: BOOL
876 options: DWORD = 0
877 /
878
879Return a duplicate handle object.
880
881The duplicate handle refers to the same object as the original
882handle. Therefore, any changes to the object are reflected
883through both handles.
884[clinic start generated code]*/
885
886static HANDLE
887_winapi_DuplicateHandle_impl(PyModuleDef *module, HANDLE source_process_handle, HANDLE source_handle, HANDLE target_process_handle, DWORD desired_access, BOOL inherit_handle, DWORD options)
888/*[clinic end generated code: output=24a7836ca4d94aba input=b933e3f2356a8c12]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200889{
890 HANDLE target_handle;
891 BOOL result;
892
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200893 Py_BEGIN_ALLOW_THREADS
894 result = DuplicateHandle(
895 source_process_handle,
896 source_handle,
897 target_process_handle,
898 &target_handle,
899 desired_access,
900 inherit_handle,
901 options
902 );
903 Py_END_ALLOW_THREADS
904
Zachary Waref2244ea2015-05-13 01:22:54 -0500905 if (! result) {
906 PyErr_SetFromWindowsErr(GetLastError());
907 return INVALID_HANDLE_VALUE;
908 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200909
Zachary Waref2244ea2015-05-13 01:22:54 -0500910 return target_handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200911}
912
Zachary Waref2244ea2015-05-13 01:22:54 -0500913/*[clinic input]
914_winapi.ExitProcess
915
916 ExitCode: UINT
917 /
918
919[clinic start generated code]*/
920
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200921static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500922_winapi_ExitProcess_impl(PyModuleDef *module, UINT ExitCode)
923/*[clinic end generated code: output=25f3b499c24cedc8 input=4f05466a9406c558]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200924{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200925 #if defined(Py_DEBUG)
926 SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|
927 SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
928 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
929 #endif
930
Zachary Waref2244ea2015-05-13 01:22:54 -0500931 ExitProcess(ExitCode);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200932
933 return NULL;
934}
935
Zachary Waref2244ea2015-05-13 01:22:54 -0500936/*[clinic input]
937_winapi.GetCurrentProcess -> HANDLE
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200938
Zachary Waref2244ea2015-05-13 01:22:54 -0500939Return a handle object for the current process.
940[clinic start generated code]*/
941
942static HANDLE
943_winapi_GetCurrentProcess_impl(PyModuleDef *module)
944/*[clinic end generated code: output=be29ac3ad5f8291e input=b213403fd4b96b41]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200945{
Zachary Waref2244ea2015-05-13 01:22:54 -0500946 return GetCurrentProcess();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200947}
948
Zachary Waref2244ea2015-05-13 01:22:54 -0500949/*[clinic input]
950_winapi.GetExitCodeProcess -> DWORD
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200951
Zachary Waref2244ea2015-05-13 01:22:54 -0500952 process: HANDLE
953 /
954
955Return the termination status of the specified process.
956[clinic start generated code]*/
957
958static DWORD
959_winapi_GetExitCodeProcess_impl(PyModuleDef *module, HANDLE process)
960/*[clinic end generated code: output=0b10f0848a410f65 input=61b6bfc7dc2ee374]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200961{
962 DWORD exit_code;
963 BOOL result;
964
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200965 result = GetExitCodeProcess(process, &exit_code);
966
Zachary Waref2244ea2015-05-13 01:22:54 -0500967 if (! result) {
968 PyErr_SetFromWindowsErr(GetLastError());
969 exit_code = DWORD_MAX;
970 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200971
Zachary Waref2244ea2015-05-13 01:22:54 -0500972 return exit_code;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200973}
974
Zachary Waref2244ea2015-05-13 01:22:54 -0500975/*[clinic input]
976_winapi.GetLastError -> DWORD
977[clinic start generated code]*/
978
979static DWORD
980_winapi_GetLastError_impl(PyModuleDef *module)
981/*[clinic end generated code: output=0ea00d8e67bdd056 input=62d47fb9bce038ba]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200982{
Zachary Waref2244ea2015-05-13 01:22:54 -0500983 return GetLastError();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200984}
985
Zachary Waref2244ea2015-05-13 01:22:54 -0500986/*[clinic input]
987_winapi.GetModuleFileName
988
989 module_handle: HMODULE
990 /
991
992Return the fully-qualified path for the file that contains module.
993
994The module must have been loaded by the current process.
995
996The module parameter should be a handle to the loaded module
997whose path is being requested. If this parameter is 0,
998GetModuleFileName retrieves the path of the executable file
999of the current process.
1000[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001001
1002static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -05001003_winapi_GetModuleFileName_impl(PyModuleDef *module, HMODULE module_handle)
1004/*[clinic end generated code: output=90063dc63bdbfa18 input=6d66ff7deca5d11f]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001005{
1006 BOOL result;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001007 WCHAR filename[MAX_PATH];
1008
Zachary Waref2244ea2015-05-13 01:22:54 -05001009 result = GetModuleFileNameW(module_handle, filename, MAX_PATH);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001010 filename[MAX_PATH-1] = '\0';
1011
1012 if (! result)
1013 return PyErr_SetFromWindowsErr(GetLastError());
1014
1015 return PyUnicode_FromWideChar(filename, wcslen(filename));
1016}
1017
Zachary Waref2244ea2015-05-13 01:22:54 -05001018/*[clinic input]
1019_winapi.GetStdHandle -> HANDLE
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001020
Zachary Waref2244ea2015-05-13 01:22:54 -05001021 std_handle: DWORD
1022 One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE.
1023 /
1024
1025Return a handle to the specified standard device.
1026
1027The integer associated with the handle object is returned.
1028[clinic start generated code]*/
1029
1030static HANDLE
1031_winapi_GetStdHandle_impl(PyModuleDef *module, DWORD std_handle)
1032/*[clinic end generated code: output=5f5ca28b28c6fad2 input=07016b06a2fc8826]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001033{
1034 HANDLE handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001035
1036 Py_BEGIN_ALLOW_THREADS
1037 handle = GetStdHandle(std_handle);
1038 Py_END_ALLOW_THREADS
1039
1040 if (handle == INVALID_HANDLE_VALUE)
Zachary Waref2244ea2015-05-13 01:22:54 -05001041 PyErr_SetFromWindowsErr(GetLastError());
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001042
Zachary Waref2244ea2015-05-13 01:22:54 -05001043 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001044}
1045
Zachary Waref2244ea2015-05-13 01:22:54 -05001046/*[clinic input]
1047_winapi.GetVersion -> long
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001048
Zachary Waref2244ea2015-05-13 01:22:54 -05001049Return the version number of the current operating system.
1050[clinic start generated code]*/
1051
1052static long
1053_winapi_GetVersion_impl(PyModuleDef *module)
1054/*[clinic end generated code: output=95a2f8ad3b948ca8 input=e21dff8d0baeded2]*/
Steve Dower3e96f322015-03-02 08:01:10 -08001055/* Disable deprecation warnings about GetVersionEx as the result is
1056 being passed straight through to the caller, who is responsible for
1057 using it correctly. */
1058#pragma warning(push)
1059#pragma warning(disable:4996)
1060
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001061{
Zachary Waref2244ea2015-05-13 01:22:54 -05001062 return GetVersion();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001063}
1064
Steve Dower3e96f322015-03-02 08:01:10 -08001065#pragma warning(pop)
1066
Zachary Waref2244ea2015-05-13 01:22:54 -05001067/*[clinic input]
1068_winapi.OpenProcess -> HANDLE
1069
1070 desired_access: DWORD
1071 inherit_handle: BOOL
1072 process_id: DWORD
1073 /
1074[clinic start generated code]*/
1075
1076static HANDLE
1077_winapi_OpenProcess_impl(PyModuleDef *module, DWORD desired_access, BOOL inherit_handle, DWORD process_id)
1078/*[clinic end generated code: output=2a7be5336f16f63c input=ec98c4cf4ea2ec36]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001079{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001080 HANDLE handle;
1081
Zachary Waref2244ea2015-05-13 01:22:54 -05001082 handle = OpenProcess(desired_access, inherit_handle, process_id);
1083 if (handle == NULL) {
1084 PyErr_SetFromWindowsErr(0);
1085 handle = INVALID_HANDLE_VALUE;
1086 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001087
Zachary Waref2244ea2015-05-13 01:22:54 -05001088 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001089}
1090
Zachary Waref2244ea2015-05-13 01:22:54 -05001091/*[clinic input]
1092_winapi.PeekNamedPipe
1093
1094 handle: HANDLE
1095 size: int = 0
1096 /
1097[clinic start generated code]*/
1098
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001099static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -05001100_winapi_PeekNamedPipe_impl(PyModuleDef *module, HANDLE handle, int size)
1101/*[clinic end generated code: output=e6c908e2fb63c798 input=c7aa53bfbce69d70]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001102{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001103 PyObject *buf = NULL;
1104 DWORD nread, navail, nleft;
1105 BOOL ret;
1106
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001107 if (size < 0) {
1108 PyErr_SetString(PyExc_ValueError, "negative size");
1109 return NULL;
1110 }
1111
1112 if (size) {
1113 buf = PyBytes_FromStringAndSize(NULL, size);
1114 if (!buf)
1115 return NULL;
1116 Py_BEGIN_ALLOW_THREADS
1117 ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread,
1118 &navail, &nleft);
1119 Py_END_ALLOW_THREADS
1120 if (!ret) {
1121 Py_DECREF(buf);
1122 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1123 }
1124 if (_PyBytes_Resize(&buf, nread))
1125 return NULL;
1126 return Py_BuildValue("Nii", buf, navail, nleft);
1127 }
1128 else {
1129 Py_BEGIN_ALLOW_THREADS
1130 ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft);
1131 Py_END_ALLOW_THREADS
1132 if (!ret) {
1133 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1134 }
1135 return Py_BuildValue("ii", navail, nleft);
1136 }
1137}
1138
Zachary Waref2244ea2015-05-13 01:22:54 -05001139/*[clinic input]
1140_winapi.ReadFile
1141
1142 handle: HANDLE
1143 size: int
1144 overlapped as use_overlapped: int(c_default='0') = False
1145[clinic start generated code]*/
1146
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001147static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -05001148_winapi_ReadFile_impl(PyModuleDef *module, HANDLE handle, int size, int use_overlapped)
1149/*[clinic end generated code: output=5a087be0ff44479a input=8dd810194e86ac7d]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001150{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001151 DWORD nread;
1152 PyObject *buf;
1153 BOOL ret;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001154 DWORD err;
1155 OverlappedObject *overlapped = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001156
1157 buf = PyBytes_FromStringAndSize(NULL, size);
1158 if (!buf)
1159 return NULL;
1160 if (use_overlapped) {
1161 overlapped = new_overlapped(handle);
1162 if (!overlapped) {
1163 Py_DECREF(buf);
1164 return NULL;
1165 }
1166 /* Steals reference to buf */
1167 overlapped->read_buffer = buf;
1168 }
1169
1170 Py_BEGIN_ALLOW_THREADS
1171 ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread,
1172 overlapped ? &overlapped->overlapped : NULL);
1173 Py_END_ALLOW_THREADS
1174
1175 err = ret ? 0 : GetLastError();
1176
1177 if (overlapped) {
1178 if (!ret) {
1179 if (err == ERROR_IO_PENDING)
1180 overlapped->pending = 1;
1181 else if (err != ERROR_MORE_DATA) {
1182 Py_DECREF(overlapped);
1183 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1184 }
1185 }
1186 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1187 }
1188
1189 if (!ret && err != ERROR_MORE_DATA) {
1190 Py_DECREF(buf);
1191 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1192 }
1193 if (_PyBytes_Resize(&buf, nread))
1194 return NULL;
1195 return Py_BuildValue("NI", buf, err);
1196}
1197
Zachary Waref2244ea2015-05-13 01:22:54 -05001198/*[clinic input]
1199_winapi.SetNamedPipeHandleState
1200
1201 named_pipe: HANDLE
1202 mode: object
1203 max_collection_count: object
1204 collect_data_timeout: object
1205 /
1206[clinic start generated code]*/
1207
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001208static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -05001209_winapi_SetNamedPipeHandleState_impl(PyModuleDef *module, HANDLE named_pipe, PyObject *mode, PyObject *max_collection_count, PyObject *collect_data_timeout)
1210/*[clinic end generated code: output=327efd18ff0c30ec input=9142d72163d0faa6]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001211{
Zachary Waref2244ea2015-05-13 01:22:54 -05001212 PyObject *oArgs[3] = {mode, max_collection_count, collect_data_timeout};
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001213 DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL};
1214 int i;
1215
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001216 PyErr_Clear();
1217
1218 for (i = 0 ; i < 3 ; i++) {
1219 if (oArgs[i] != Py_None) {
1220 dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]);
1221 if (PyErr_Occurred())
1222 return NULL;
1223 pArgs[i] = &dwArgs[i];
1224 }
1225 }
1226
Zachary Waref2244ea2015-05-13 01:22:54 -05001227 if (!SetNamedPipeHandleState(named_pipe, pArgs[0], pArgs[1], pArgs[2]))
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001228 return PyErr_SetFromWindowsErr(0);
1229
1230 Py_RETURN_NONE;
1231}
1232
Zachary Waref2244ea2015-05-13 01:22:54 -05001233
1234/*[clinic input]
1235_winapi.TerminateProcess
1236
1237 handle: HANDLE
1238 exit_code: UINT
1239 /
1240
1241Terminate the specified process and all of its threads.
1242[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001243
1244static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -05001245_winapi_TerminateProcess_impl(PyModuleDef *module, HANDLE handle, UINT exit_code)
1246/*[clinic end generated code: output=1559f0f6500c2283 input=d6bc0aa1ee3bb4df]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001247{
1248 BOOL result;
1249
Zachary Waref2244ea2015-05-13 01:22:54 -05001250 result = TerminateProcess(handle, exit_code);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001251
1252 if (! result)
1253 return PyErr_SetFromWindowsErr(GetLastError());
1254
Zachary Waref2244ea2015-05-13 01:22:54 -05001255 Py_RETURN_NONE;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001256}
1257
Zachary Waref2244ea2015-05-13 01:22:54 -05001258/*[clinic input]
1259_winapi.WaitNamedPipe
1260
1261 name: LPCTSTR
1262 timeout: DWORD
1263 /
1264[clinic start generated code]*/
1265
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001266static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -05001267_winapi_WaitNamedPipe_impl(PyModuleDef *module, LPCTSTR name, DWORD timeout)
1268/*[clinic end generated code: output=5bca5e02f448c9d7 input=36fc781291b1862c]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001269{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001270 BOOL success;
1271
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001272 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -05001273 success = WaitNamedPipe(name, timeout);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001274 Py_END_ALLOW_THREADS
1275
1276 if (!success)
1277 return PyErr_SetFromWindowsErr(0);
1278
1279 Py_RETURN_NONE;
1280}
1281
Zachary Waref2244ea2015-05-13 01:22:54 -05001282/*[clinic input]
1283_winapi.WaitForMultipleObjects
1284
1285 handle_seq: object
1286 wait_flag: BOOL
1287 milliseconds: DWORD(c_default='INFINITE') = _winapi.INFINITE
1288 /
1289[clinic start generated code]*/
1290
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001291static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -05001292_winapi_WaitForMultipleObjects_impl(PyModuleDef *module, PyObject *handle_seq, BOOL wait_flag, DWORD milliseconds)
1293/*[clinic end generated code: output=e3efee6b505dd48e input=36f76ca057cd28a0]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001294{
1295 DWORD result;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001296 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
1297 HANDLE sigint_event = NULL;
1298 Py_ssize_t nhandles, i;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001299
1300 if (!PySequence_Check(handle_seq)) {
1301 PyErr_Format(PyExc_TypeError,
1302 "sequence type expected, got '%s'",
Richard Oudkerk67339272012-08-21 14:54:22 +01001303 Py_TYPE(handle_seq)->tp_name);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001304 return NULL;
1305 }
1306 nhandles = PySequence_Length(handle_seq);
1307 if (nhandles == -1)
1308 return NULL;
1309 if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS - 1) {
1310 PyErr_Format(PyExc_ValueError,
1311 "need at most %zd handles, got a sequence of length %zd",
1312 MAXIMUM_WAIT_OBJECTS - 1, nhandles);
1313 return NULL;
1314 }
1315 for (i = 0; i < nhandles; i++) {
1316 HANDLE h;
1317 PyObject *v = PySequence_GetItem(handle_seq, i);
1318 if (v == NULL)
1319 return NULL;
1320 if (!PyArg_Parse(v, F_HANDLE, &h)) {
1321 Py_DECREF(v);
1322 return NULL;
1323 }
1324 handles[i] = h;
1325 Py_DECREF(v);
1326 }
1327 /* If this is the main thread then make the wait interruptible
1328 by Ctrl-C unless we are waiting for *all* handles */
1329 if (!wait_flag && _PyOS_IsMainThread()) {
1330 sigint_event = _PyOS_SigintEvent();
1331 assert(sigint_event != NULL);
1332 handles[nhandles++] = sigint_event;
1333 }
1334
1335 Py_BEGIN_ALLOW_THREADS
1336 if (sigint_event != NULL)
1337 ResetEvent(sigint_event);
1338 result = WaitForMultipleObjects((DWORD) nhandles, handles,
1339 wait_flag, milliseconds);
1340 Py_END_ALLOW_THREADS
1341
1342 if (result == WAIT_FAILED)
1343 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1344 else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) {
1345 errno = EINTR;
1346 return PyErr_SetFromErrno(PyExc_IOError);
1347 }
1348
1349 return PyLong_FromLong((int) result);
1350}
1351
Zachary Waref2244ea2015-05-13 01:22:54 -05001352/*[clinic input]
1353_winapi.WaitForSingleObject -> long
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001354
Zachary Waref2244ea2015-05-13 01:22:54 -05001355 handle: HANDLE
1356 milliseconds: DWORD
1357 /
1358
1359Wait for a single object.
1360
1361Wait until the specified object is in the signaled state or
1362the time-out interval elapses. The timeout value is specified
1363in milliseconds.
1364[clinic start generated code]*/
1365
1366static long
1367_winapi_WaitForSingleObject_impl(PyModuleDef *module, HANDLE handle, DWORD milliseconds)
1368/*[clinic end generated code: output=0c75bcc6eec6b973 input=443d1ab076edc7b1]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001369{
1370 DWORD result;
1371
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001372 Py_BEGIN_ALLOW_THREADS
1373 result = WaitForSingleObject(handle, milliseconds);
1374 Py_END_ALLOW_THREADS
1375
Zachary Waref2244ea2015-05-13 01:22:54 -05001376 if (result == WAIT_FAILED) {
1377 PyErr_SetFromWindowsErr(GetLastError());
1378 return -1;
1379 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001380
Zachary Waref2244ea2015-05-13 01:22:54 -05001381 return result;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001382}
1383
Zachary Waref2244ea2015-05-13 01:22:54 -05001384/*[clinic input]
1385_winapi.WriteFile
1386
1387 handle: HANDLE
1388 buffer: object
1389 overlapped as use_overlapped: int(c_default='0') = False
1390[clinic start generated code]*/
1391
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001392static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -05001393_winapi_WriteFile_impl(PyModuleDef *module, HANDLE handle, PyObject *buffer, int use_overlapped)
1394/*[clinic end generated code: output=37bd88e293079b2c input=51846a5af52053fd]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001395{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001396 Py_buffer _buf, *buf;
Victor Stinner71765772013-06-24 23:13:24 +02001397 DWORD len, written;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001398 BOOL ret;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001399 DWORD err;
1400 OverlappedObject *overlapped = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001401
1402 if (use_overlapped) {
1403 overlapped = new_overlapped(handle);
1404 if (!overlapped)
1405 return NULL;
1406 buf = &overlapped->write_buffer;
1407 }
1408 else
1409 buf = &_buf;
1410
Zachary Waref2244ea2015-05-13 01:22:54 -05001411 if (!PyArg_Parse(buffer, "y*", buf)) {
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001412 Py_XDECREF(overlapped);
1413 return NULL;
1414 }
1415
1416 Py_BEGIN_ALLOW_THREADS
Victor Stinner71765772013-06-24 23:13:24 +02001417 len = (DWORD)Py_MIN(buf->len, DWORD_MAX);
1418 ret = WriteFile(handle, buf->buf, len, &written,
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001419 overlapped ? &overlapped->overlapped : NULL);
1420 Py_END_ALLOW_THREADS
1421
1422 err = ret ? 0 : GetLastError();
1423
1424 if (overlapped) {
1425 if (!ret) {
1426 if (err == ERROR_IO_PENDING)
1427 overlapped->pending = 1;
1428 else {
1429 Py_DECREF(overlapped);
1430 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1431 }
1432 }
1433 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1434 }
1435
1436 PyBuffer_Release(buf);
1437 if (!ret)
1438 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1439 return Py_BuildValue("II", written, err);
1440}
1441
1442
1443static PyMethodDef winapi_functions[] = {
Zachary Waref2244ea2015-05-13 01:22:54 -05001444 _WINAPI_CLOSEHANDLE_METHODDEF
1445 _WINAPI_CONNECTNAMEDPIPE_METHODDEF
1446 _WINAPI_CREATEFILE_METHODDEF
1447 _WINAPI_CREATENAMEDPIPE_METHODDEF
1448 _WINAPI_CREATEPIPE_METHODDEF
1449 _WINAPI_CREATEPROCESS_METHODDEF
1450 _WINAPI_CREATEJUNCTION_METHODDEF
1451 _WINAPI_DUPLICATEHANDLE_METHODDEF
1452 _WINAPI_EXITPROCESS_METHODDEF
1453 _WINAPI_GETCURRENTPROCESS_METHODDEF
1454 _WINAPI_GETEXITCODEPROCESS_METHODDEF
1455 _WINAPI_GETLASTERROR_METHODDEF
1456 _WINAPI_GETMODULEFILENAME_METHODDEF
1457 _WINAPI_GETSTDHANDLE_METHODDEF
1458 _WINAPI_GETVERSION_METHODDEF
1459 _WINAPI_OPENPROCESS_METHODDEF
1460 _WINAPI_PEEKNAMEDPIPE_METHODDEF
1461 _WINAPI_READFILE_METHODDEF
1462 _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF
1463 _WINAPI_TERMINATEPROCESS_METHODDEF
1464 _WINAPI_WAITNAMEDPIPE_METHODDEF
1465 _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF
1466 _WINAPI_WAITFORSINGLEOBJECT_METHODDEF
1467 _WINAPI_WRITEFILE_METHODDEF
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001468 {NULL, NULL}
1469};
1470
1471static struct PyModuleDef winapi_module = {
1472 PyModuleDef_HEAD_INIT,
1473 "_winapi",
1474 NULL,
1475 -1,
1476 winapi_functions,
1477 NULL,
1478 NULL,
1479 NULL,
1480 NULL
1481};
1482
1483#define WINAPI_CONSTANT(fmt, con) \
1484 PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1485
1486PyMODINIT_FUNC
1487PyInit__winapi(void)
1488{
1489 PyObject *d;
1490 PyObject *m;
1491
1492 if (PyType_Ready(&OverlappedType) < 0)
1493 return NULL;
1494
1495 m = PyModule_Create(&winapi_module);
1496 if (m == NULL)
1497 return NULL;
1498 d = PyModule_GetDict(m);
1499
1500 PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType);
1501
1502 /* constants */
1503 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
1504 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP);
1505 WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001506 WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001507 WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
1508 WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
1509 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1510 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1511 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1512 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001513 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1514 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
Richard Oudkerkfdb8dcf2012-05-05 19:45:37 +01001515 WINAPI_CONSTANT(F_DWORD, ERROR_NO_DATA);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001516 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
1517 WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
1518 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
1519 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
1520 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
1521 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE);
1522 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001523 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ);
1524 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001525 WINAPI_CONSTANT(F_DWORD, GENERIC_READ);
1526 WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE);
1527 WINAPI_CONSTANT(F_DWORD, INFINITE);
1528 WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
1529 WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING);
1530 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
1531 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
1532 WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
1533 WINAPI_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE);
1534 WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES);
1535 WINAPI_CONSTANT(F_DWORD, PIPE_WAIT);
1536 WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001537 WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001538 WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW);
1539 WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES);
1540 WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE);
1541 WINAPI_CONSTANT(F_DWORD, STD_OUTPUT_HANDLE);
1542 WINAPI_CONSTANT(F_DWORD, STD_ERROR_HANDLE);
1543 WINAPI_CONSTANT(F_DWORD, STILL_ACTIVE);
1544 WINAPI_CONSTANT(F_DWORD, SW_HIDE);
1545 WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0);
Victor Stinner373f0a92014-03-20 09:26:55 +01001546 WINAPI_CONSTANT(F_DWORD, WAIT_ABANDONED_0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001547 WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT);
1548
1549 WINAPI_CONSTANT("i", NULL);
1550
1551 return m;
1552}