blob: 1074891ef11aa4ae4d826088b97f6960d3d43722 [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>
43
44#if defined(MS_WIN32) && !defined(MS_WIN64)
45#define HANDLE_TO_PYNUM(handle) \
46 PyLong_FromUnsignedLong((unsigned long) handle)
47#define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLong(obj))
48#define F_POINTER "k"
49#define T_POINTER T_ULONG
50#else
51#define HANDLE_TO_PYNUM(handle) \
52 PyLong_FromUnsignedLongLong((unsigned long long) handle)
53#define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLongLong(obj))
54#define F_POINTER "K"
55#define T_POINTER T_ULONGLONG
56#endif
57
58#define F_HANDLE F_POINTER
59#define F_DWORD "k"
60#define F_BOOL "i"
61#define F_UINT "I"
62
63#define T_HANDLE T_POINTER
64
65/* Grab CancelIoEx dynamically from kernel32 */
66static int has_CancelIoEx = -1;
67static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED);
68
69static int
70check_CancelIoEx()
71{
72 if (has_CancelIoEx == -1)
73 {
74 HINSTANCE hKernel32 = GetModuleHandle("KERNEL32");
75 * (FARPROC *) &Py_CancelIoEx = GetProcAddress(hKernel32,
76 "CancelIoEx");
77 has_CancelIoEx = (Py_CancelIoEx != NULL);
78 }
79 return has_CancelIoEx;
80}
81
82
83/*
84 * A Python object wrapping an OVERLAPPED structure and other useful data
85 * for overlapped I/O
86 */
87
88typedef struct {
89 PyObject_HEAD
90 OVERLAPPED overlapped;
91 /* For convenience, we store the file handle too */
92 HANDLE handle;
93 /* Whether there's I/O in flight */
94 int pending;
95 /* Whether I/O completed successfully */
96 int completed;
97 /* Buffer used for reading (optional) */
98 PyObject *read_buffer;
99 /* Buffer used for writing (optional) */
100 Py_buffer write_buffer;
101} OverlappedObject;
102
103static void
104overlapped_dealloc(OverlappedObject *self)
105{
106 DWORD bytes;
107 int err = GetLastError();
108 if (self->pending) {
109 /* make it a programming error to deallocate while operation
110 is pending, even if we can safely cancel it */
111 if (check_CancelIoEx() &&
112 Py_CancelIoEx(self->handle, &self->overlapped))
113 GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE);
114 PyErr_SetString(PyExc_RuntimeError,
115 "I/O operations still in flight while destroying "
116 "Overlapped object, the process may crash");
117 PyErr_WriteUnraisable(NULL);
118 }
119 CloseHandle(self->overlapped.hEvent);
120 SetLastError(err);
121 if (self->write_buffer.obj)
122 PyBuffer_Release(&self->write_buffer);
123 Py_CLEAR(self->read_buffer);
124 PyObject_Del(self);
125}
126
127static PyObject *
128overlapped_GetOverlappedResult(OverlappedObject *self, PyObject *waitobj)
129{
130 int wait;
131 BOOL res;
132 DWORD transferred = 0;
133 DWORD err;
134
135 wait = PyObject_IsTrue(waitobj);
136 if (wait < 0)
137 return NULL;
138 Py_BEGIN_ALLOW_THREADS
139 res = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
140 wait != 0);
141 Py_END_ALLOW_THREADS
142
143 err = res ? ERROR_SUCCESS : GetLastError();
144 switch (err) {
145 case ERROR_SUCCESS:
146 case ERROR_MORE_DATA:
147 case ERROR_OPERATION_ABORTED:
148 self->completed = 1;
149 self->pending = 0;
150 break;
151 case ERROR_IO_INCOMPLETE:
152 break;
153 default:
154 self->pending = 0;
155 return PyErr_SetExcFromWindowsErr(PyExc_IOError, err);
156 }
157 if (self->completed && self->read_buffer != NULL) {
158 assert(PyBytes_CheckExact(self->read_buffer));
159 if (transferred != PyBytes_GET_SIZE(self->read_buffer) &&
160 _PyBytes_Resize(&self->read_buffer, transferred))
161 return NULL;
162 }
163 return Py_BuildValue("II", (unsigned) transferred, (unsigned) err);
164}
165
166static PyObject *
167overlapped_getbuffer(OverlappedObject *self)
168{
169 PyObject *res;
170 if (!self->completed) {
171 PyErr_SetString(PyExc_ValueError,
172 "can't get read buffer before GetOverlappedResult() "
173 "signals the operation completed");
174 return NULL;
175 }
176 res = self->read_buffer ? self->read_buffer : Py_None;
177 Py_INCREF(res);
178 return res;
179}
180
181static PyObject *
182overlapped_cancel(OverlappedObject *self)
183{
184 BOOL res = TRUE;
185
186 if (self->pending) {
187 Py_BEGIN_ALLOW_THREADS
188 if (check_CancelIoEx())
189 res = Py_CancelIoEx(self->handle, &self->overlapped);
190 else
191 res = CancelIo(self->handle);
192 Py_END_ALLOW_THREADS
193 }
194
195 /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
196 if (!res && GetLastError() != ERROR_NOT_FOUND)
197 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
198 self->pending = 0;
199 Py_RETURN_NONE;
200}
201
202static PyMethodDef overlapped_methods[] = {
203 {"GetOverlappedResult", (PyCFunction) overlapped_GetOverlappedResult,
204 METH_O, NULL},
205 {"getbuffer", (PyCFunction) overlapped_getbuffer, METH_NOARGS, NULL},
206 {"cancel", (PyCFunction) overlapped_cancel, METH_NOARGS, NULL},
207 {NULL}
208};
209
210static PyMemberDef overlapped_members[] = {
211 {"event", T_HANDLE,
212 offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
213 READONLY, "overlapped event handle"},
214 {NULL}
215};
216
217PyTypeObject OverlappedType = {
218 PyVarObject_HEAD_INIT(NULL, 0)
219 /* tp_name */ "_winapi.Overlapped",
220 /* tp_basicsize */ sizeof(OverlappedObject),
221 /* tp_itemsize */ 0,
222 /* tp_dealloc */ (destructor) overlapped_dealloc,
223 /* tp_print */ 0,
224 /* tp_getattr */ 0,
225 /* tp_setattr */ 0,
226 /* tp_reserved */ 0,
227 /* tp_repr */ 0,
228 /* tp_as_number */ 0,
229 /* tp_as_sequence */ 0,
230 /* tp_as_mapping */ 0,
231 /* tp_hash */ 0,
232 /* tp_call */ 0,
233 /* tp_str */ 0,
234 /* tp_getattro */ 0,
235 /* tp_setattro */ 0,
236 /* tp_as_buffer */ 0,
237 /* tp_flags */ Py_TPFLAGS_DEFAULT,
238 /* tp_doc */ "OVERLAPPED structure wrapper",
239 /* tp_traverse */ 0,
240 /* tp_clear */ 0,
241 /* tp_richcompare */ 0,
242 /* tp_weaklistoffset */ 0,
243 /* tp_iter */ 0,
244 /* tp_iternext */ 0,
245 /* tp_methods */ overlapped_methods,
246 /* tp_members */ overlapped_members,
247 /* tp_getset */ 0,
248 /* tp_base */ 0,
249 /* tp_dict */ 0,
250 /* tp_descr_get */ 0,
251 /* tp_descr_set */ 0,
252 /* tp_dictoffset */ 0,
253 /* tp_init */ 0,
254 /* tp_alloc */ 0,
255 /* tp_new */ 0,
256};
257
258static OverlappedObject *
259new_overlapped(HANDLE handle)
260{
261 OverlappedObject *self;
262
263 self = PyObject_New(OverlappedObject, &OverlappedType);
264 if (!self)
265 return NULL;
266 self->handle = handle;
267 self->read_buffer = NULL;
268 self->pending = 0;
269 self->completed = 0;
270 memset(&self->overlapped, 0, sizeof(OVERLAPPED));
271 memset(&self->write_buffer, 0, sizeof(Py_buffer));
272 /* Manual reset, initially non-signalled */
273 self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
274 return self;
275}
276
277/* -------------------------------------------------------------------- */
278/* windows API functions */
279
280PyDoc_STRVAR(CloseHandle_doc,
281"CloseHandle(handle) -> None\n\
282\n\
283Close handle.");
284
285static PyObject *
286winapi_CloseHandle(PyObject *self, PyObject *args)
287{
288 HANDLE hObject;
289 BOOL success;
290
291 if (!PyArg_ParseTuple(args, F_HANDLE ":CloseHandle", &hObject))
292 return NULL;
293
294 Py_BEGIN_ALLOW_THREADS
295 success = CloseHandle(hObject);
296 Py_END_ALLOW_THREADS
297
298 if (!success)
299 return PyErr_SetFromWindowsErr(0);
300
301 Py_RETURN_NONE;
302}
303
304static PyObject *
305winapi_ConnectNamedPipe(PyObject *self, PyObject *args, PyObject *kwds)
306{
307 HANDLE hNamedPipe;
308 int use_overlapped = 0;
309 BOOL success;
310 OverlappedObject *overlapped = NULL;
311 static char *kwlist[] = {"handle", "overlapped", NULL};
312
313 if (!PyArg_ParseTupleAndKeywords(args, kwds,
314 F_HANDLE "|" F_BOOL, kwlist,
315 &hNamedPipe, &use_overlapped))
316 return NULL;
317
318 if (use_overlapped) {
319 overlapped = new_overlapped(hNamedPipe);
320 if (!overlapped)
321 return NULL;
322 }
323
324 Py_BEGIN_ALLOW_THREADS
325 success = ConnectNamedPipe(hNamedPipe,
326 overlapped ? &overlapped->overlapped : NULL);
327 Py_END_ALLOW_THREADS
328
329 if (overlapped) {
330 int err = GetLastError();
331 /* Overlapped ConnectNamedPipe never returns a success code */
332 assert(success == 0);
333 if (err == ERROR_IO_PENDING)
334 overlapped->pending = 1;
335 else if (err == ERROR_PIPE_CONNECTED)
336 SetEvent(overlapped->overlapped.hEvent);
337 else {
338 Py_DECREF(overlapped);
339 return PyErr_SetFromWindowsErr(err);
340 }
341 return (PyObject *) overlapped;
342 }
343 if (!success)
344 return PyErr_SetFromWindowsErr(0);
345
346 Py_RETURN_NONE;
347}
348
349static PyObject *
350winapi_CreateFile(PyObject *self, PyObject *args)
351{
352 LPCTSTR lpFileName;
353 DWORD dwDesiredAccess;
354 DWORD dwShareMode;
355 LPSECURITY_ATTRIBUTES lpSecurityAttributes;
356 DWORD dwCreationDisposition;
357 DWORD dwFlagsAndAttributes;
358 HANDLE hTemplateFile;
359 HANDLE handle;
360
361 if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_POINTER
362 F_DWORD F_DWORD F_HANDLE,
363 &lpFileName, &dwDesiredAccess, &dwShareMode,
364 &lpSecurityAttributes, &dwCreationDisposition,
365 &dwFlagsAndAttributes, &hTemplateFile))
366 return NULL;
367
368 Py_BEGIN_ALLOW_THREADS
369 handle = CreateFile(lpFileName, dwDesiredAccess,
370 dwShareMode, lpSecurityAttributes,
371 dwCreationDisposition,
372 dwFlagsAndAttributes, hTemplateFile);
373 Py_END_ALLOW_THREADS
374
375 if (handle == INVALID_HANDLE_VALUE)
376 return PyErr_SetFromWindowsErr(0);
377
378 return Py_BuildValue(F_HANDLE, handle);
379}
380
381static PyObject *
382winapi_CreateNamedPipe(PyObject *self, PyObject *args)
383{
384 LPCTSTR lpName;
385 DWORD dwOpenMode;
386 DWORD dwPipeMode;
387 DWORD nMaxInstances;
388 DWORD nOutBufferSize;
389 DWORD nInBufferSize;
390 DWORD nDefaultTimeOut;
391 LPSECURITY_ATTRIBUTES lpSecurityAttributes;
392 HANDLE handle;
393
394 if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_DWORD
395 F_DWORD F_DWORD F_DWORD F_POINTER,
396 &lpName, &dwOpenMode, &dwPipeMode,
397 &nMaxInstances, &nOutBufferSize,
398 &nInBufferSize, &nDefaultTimeOut,
399 &lpSecurityAttributes))
400 return NULL;
401
402 Py_BEGIN_ALLOW_THREADS
403 handle = CreateNamedPipe(lpName, dwOpenMode, dwPipeMode,
404 nMaxInstances, nOutBufferSize,
405 nInBufferSize, nDefaultTimeOut,
406 lpSecurityAttributes);
407 Py_END_ALLOW_THREADS
408
409 if (handle == INVALID_HANDLE_VALUE)
410 return PyErr_SetFromWindowsErr(0);
411
412 return Py_BuildValue(F_HANDLE, handle);
413}
414
415PyDoc_STRVAR(CreatePipe_doc,
416"CreatePipe(pipe_attrs, size) -> (read_handle, write_handle)\n\
417\n\
418Create an anonymous pipe, and return handles to the read and\n\
419write ends of the pipe.\n\
420\n\
421pipe_attrs is ignored internally and can be None.");
422
423static PyObject *
424winapi_CreatePipe(PyObject* self, PyObject* args)
425{
426 HANDLE read_pipe;
427 HANDLE write_pipe;
428 BOOL result;
429
430 PyObject* pipe_attributes; /* ignored */
431 DWORD size;
432
433 if (! PyArg_ParseTuple(args, "O" F_DWORD ":CreatePipe",
434 &pipe_attributes, &size))
435 return NULL;
436
437 Py_BEGIN_ALLOW_THREADS
438 result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
439 Py_END_ALLOW_THREADS
440
441 if (! result)
442 return PyErr_SetFromWindowsErr(GetLastError());
443
444 return Py_BuildValue(
445 "NN", HANDLE_TO_PYNUM(read_pipe), HANDLE_TO_PYNUM(write_pipe));
446}
447
448/* helpers for createprocess */
449
450static unsigned long
451getulong(PyObject* obj, char* name)
452{
453 PyObject* value;
454 unsigned long ret;
455
456 value = PyObject_GetAttrString(obj, name);
457 if (! value) {
458 PyErr_Clear(); /* FIXME: propagate error? */
459 return 0;
460 }
461 ret = PyLong_AsUnsignedLong(value);
462 Py_DECREF(value);
463 return ret;
464}
465
466static HANDLE
467gethandle(PyObject* obj, char* name)
468{
469 PyObject* value;
470 HANDLE ret;
471
472 value = PyObject_GetAttrString(obj, name);
473 if (! value) {
474 PyErr_Clear(); /* FIXME: propagate error? */
475 return NULL;
476 }
477 if (value == Py_None)
478 ret = NULL;
479 else
480 ret = PYNUM_TO_HANDLE(value);
481 Py_DECREF(value);
482 return ret;
483}
484
485static PyObject*
486getenvironment(PyObject* environment)
487{
488 Py_ssize_t i, envsize, totalsize;
489 Py_UCS4 *buffer = NULL, *p, *end;
490 PyObject *keys, *values, *res;
491
492 /* convert environment dictionary to windows enviroment string */
493 if (! PyMapping_Check(environment)) {
494 PyErr_SetString(
495 PyExc_TypeError, "environment must be dictionary or None");
496 return NULL;
497 }
498
499 envsize = PyMapping_Length(environment);
500
501 keys = PyMapping_Keys(environment);
502 values = PyMapping_Values(environment);
503 if (!keys || !values)
504 goto error;
505
506 totalsize = 1; /* trailing null character */
507 for (i = 0; i < envsize; i++) {
508 PyObject* key = PyList_GET_ITEM(keys, i);
509 PyObject* value = PyList_GET_ITEM(values, i);
510
511 if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
512 PyErr_SetString(PyExc_TypeError,
513 "environment can only contain strings");
514 goto error;
515 }
516 totalsize += PyUnicode_GET_LENGTH(key) + 1; /* +1 for '=' */
517 totalsize += PyUnicode_GET_LENGTH(value) + 1; /* +1 for '\0' */
518 }
519
520 buffer = PyMem_Malloc(totalsize * sizeof(Py_UCS4));
521 if (! buffer)
522 goto error;
523 p = buffer;
524 end = buffer + totalsize;
525
526 for (i = 0; i < envsize; i++) {
527 PyObject* key = PyList_GET_ITEM(keys, i);
528 PyObject* value = PyList_GET_ITEM(values, i);
529 if (!PyUnicode_AsUCS4(key, p, end - p, 0))
530 goto error;
531 p += PyUnicode_GET_LENGTH(key);
532 *p++ = '=';
533 if (!PyUnicode_AsUCS4(value, p, end - p, 0))
534 goto error;
535 p += PyUnicode_GET_LENGTH(value);
536 *p++ = '\0';
537 }
538
539 /* add trailing null byte */
540 *p++ = '\0';
541 assert(p == end);
542
543 Py_XDECREF(keys);
544 Py_XDECREF(values);
545
546 res = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buffer, p - buffer);
547 PyMem_Free(buffer);
548 return res;
549
550 error:
551 PyMem_Free(buffer);
552 Py_XDECREF(keys);
553 Py_XDECREF(values);
554 return NULL;
555}
556
557PyDoc_STRVAR(CreateProcess_doc,
558"CreateProcess(app_name, cmd_line, proc_attrs, thread_attrs,\n\
559 inherit, flags, env_mapping, curdir,\n\
560 startup_info) -> (proc_handle, thread_handle,\n\
561 pid, tid)\n\
562\n\
563Create a new process and its primary thread. The return\n\
564value is a tuple of the process handle, thread handle,\n\
565process ID, and thread ID.\n\
566\n\
567proc_attrs and thread_attrs are ignored internally and can be None.");
568
569static PyObject *
570winapi_CreateProcess(PyObject* self, PyObject* args)
571{
572 BOOL result;
573 PROCESS_INFORMATION pi;
574 STARTUPINFOW si;
575 PyObject* environment;
576 wchar_t *wenvironment;
577
578 wchar_t* application_name;
579 wchar_t* command_line;
580 PyObject* process_attributes; /* ignored */
581 PyObject* thread_attributes; /* ignored */
582 BOOL inherit_handles;
583 DWORD creation_flags;
584 PyObject* env_mapping;
585 wchar_t* current_directory;
586 PyObject* startup_info;
587
588 if (! PyArg_ParseTuple(args, "ZZOO" F_BOOL F_DWORD "OZO:CreateProcess",
589 &application_name,
590 &command_line,
591 &process_attributes,
592 &thread_attributes,
593 &inherit_handles,
594 &creation_flags,
595 &env_mapping,
596 &current_directory,
597 &startup_info))
598 return NULL;
599
600 ZeroMemory(&si, sizeof(si));
601 si.cb = sizeof(si);
602
603 /* note: we only support a small subset of all SI attributes */
604 si.dwFlags = getulong(startup_info, "dwFlags");
605 si.wShowWindow = (WORD)getulong(startup_info, "wShowWindow");
606 si.hStdInput = gethandle(startup_info, "hStdInput");
607 si.hStdOutput = gethandle(startup_info, "hStdOutput");
608 si.hStdError = gethandle(startup_info, "hStdError");
609 if (PyErr_Occurred())
610 return NULL;
611
612 if (env_mapping != Py_None) {
613 environment = getenvironment(env_mapping);
614 if (! environment)
615 return NULL;
616 wenvironment = PyUnicode_AsUnicode(environment);
617 if (wenvironment == NULL)
618 {
619 Py_XDECREF(environment);
620 return NULL;
621 }
622 }
623 else {
624 environment = NULL;
625 wenvironment = NULL;
626 }
627
628 Py_BEGIN_ALLOW_THREADS
629 result = CreateProcessW(application_name,
630 command_line,
631 NULL,
632 NULL,
633 inherit_handles,
634 creation_flags | CREATE_UNICODE_ENVIRONMENT,
635 wenvironment,
636 current_directory,
637 &si,
638 &pi);
639 Py_END_ALLOW_THREADS
640
641 Py_XDECREF(environment);
642
643 if (! result)
644 return PyErr_SetFromWindowsErr(GetLastError());
645
646 return Py_BuildValue("NNkk",
647 HANDLE_TO_PYNUM(pi.hProcess),
648 HANDLE_TO_PYNUM(pi.hThread),
649 pi.dwProcessId,
650 pi.dwThreadId);
651}
652
653PyDoc_STRVAR(DuplicateHandle_doc,
654"DuplicateHandle(source_proc_handle, source_handle,\n\
655 target_proc_handle, target_handle, access,\n\
656 inherit[, options]) -> handle\n\
657\n\
658Return a duplicate handle object.\n\
659\n\
660The duplicate handle refers to the same object as the original\n\
661handle. Therefore, any changes to the object are reflected\n\
662through both handles.");
663
664static PyObject *
665winapi_DuplicateHandle(PyObject* self, PyObject* args)
666{
667 HANDLE target_handle;
668 BOOL result;
669
670 HANDLE source_process_handle;
671 HANDLE source_handle;
672 HANDLE target_process_handle;
673 DWORD desired_access;
674 BOOL inherit_handle;
675 DWORD options = 0;
676
677 if (! PyArg_ParseTuple(args,
678 F_HANDLE F_HANDLE F_HANDLE F_DWORD F_BOOL F_DWORD
679 ":DuplicateHandle",
680 &source_process_handle,
681 &source_handle,
682 &target_process_handle,
683 &desired_access,
684 &inherit_handle,
685 &options))
686 return NULL;
687
688 Py_BEGIN_ALLOW_THREADS
689 result = DuplicateHandle(
690 source_process_handle,
691 source_handle,
692 target_process_handle,
693 &target_handle,
694 desired_access,
695 inherit_handle,
696 options
697 );
698 Py_END_ALLOW_THREADS
699
700 if (! result)
701 return PyErr_SetFromWindowsErr(GetLastError());
702
703 return HANDLE_TO_PYNUM(target_handle);
704}
705
706static PyObject *
707winapi_ExitProcess(PyObject *self, PyObject *args)
708{
709 UINT uExitCode;
710
711 if (!PyArg_ParseTuple(args, F_UINT, &uExitCode))
712 return NULL;
713
714 #if defined(Py_DEBUG)
715 SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|
716 SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
717 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
718 #endif
719
720 ExitProcess(uExitCode);
721
722 return NULL;
723}
724
725PyDoc_STRVAR(GetCurrentProcess_doc,
726"GetCurrentProcess() -> handle\n\
727\n\
728Return a handle object for the current process.");
729
730static PyObject *
731winapi_GetCurrentProcess(PyObject* self, PyObject* args)
732{
733 if (! PyArg_ParseTuple(args, ":GetCurrentProcess"))
734 return NULL;
735
736 return HANDLE_TO_PYNUM(GetCurrentProcess());
737}
738
739PyDoc_STRVAR(GetExitCodeProcess_doc,
740"GetExitCodeProcess(handle) -> Exit code\n\
741\n\
742Return the termination status of the specified process.");
743
744static PyObject *
745winapi_GetExitCodeProcess(PyObject* self, PyObject* args)
746{
747 DWORD exit_code;
748 BOOL result;
749
750 HANDLE process;
751 if (! PyArg_ParseTuple(args, F_HANDLE ":GetExitCodeProcess", &process))
752 return NULL;
753
754 result = GetExitCodeProcess(process, &exit_code);
755
756 if (! result)
757 return PyErr_SetFromWindowsErr(GetLastError());
758
759 return PyLong_FromUnsignedLong(exit_code);
760}
761
762static PyObject *
763winapi_GetLastError(PyObject *self, PyObject *args)
764{
765 return Py_BuildValue(F_DWORD, GetLastError());
766}
767
768PyDoc_STRVAR(GetModuleFileName_doc,
769"GetModuleFileName(module) -> path\n\
770\n\
771Return the fully-qualified path for the file that contains\n\
772the specified module. The module must have been loaded by the\n\
773current process.\n\
774\n\
775The module parameter should be a handle to the loaded module\n\
776whose path is being requested. If this parameter is 0, \n\
777GetModuleFileName retrieves the path of the executable file\n\
778of the current process.");
779
780static PyObject *
781winapi_GetModuleFileName(PyObject* self, PyObject* args)
782{
783 BOOL result;
784 HMODULE module;
785 WCHAR filename[MAX_PATH];
786
787 if (! PyArg_ParseTuple(args, F_HANDLE ":GetModuleFileName",
788 &module))
789 return NULL;
790
791 result = GetModuleFileNameW(module, filename, MAX_PATH);
792 filename[MAX_PATH-1] = '\0';
793
794 if (! result)
795 return PyErr_SetFromWindowsErr(GetLastError());
796
797 return PyUnicode_FromWideChar(filename, wcslen(filename));
798}
799
800PyDoc_STRVAR(GetStdHandle_doc,
801"GetStdHandle(handle) -> integer\n\
802\n\
803Return a handle to the specified standard device\n\
804(STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE).\n\
805The integer associated with the handle object is returned.");
806
807static PyObject *
808winapi_GetStdHandle(PyObject* self, PyObject* args)
809{
810 HANDLE handle;
811 DWORD std_handle;
812
813 if (! PyArg_ParseTuple(args, F_DWORD ":GetStdHandle", &std_handle))
814 return NULL;
815
816 Py_BEGIN_ALLOW_THREADS
817 handle = GetStdHandle(std_handle);
818 Py_END_ALLOW_THREADS
819
820 if (handle == INVALID_HANDLE_VALUE)
821 return PyErr_SetFromWindowsErr(GetLastError());
822
823 if (! handle) {
824 Py_INCREF(Py_None);
825 return Py_None;
826 }
827
828 /* note: returns integer, not handle object */
829 return HANDLE_TO_PYNUM(handle);
830}
831
832PyDoc_STRVAR(GetVersion_doc,
833"GetVersion() -> version\n\
834\n\
835Return the version number of the current operating system.");
836
837static PyObject *
838winapi_GetVersion(PyObject* self, PyObject* args)
839{
840 if (! PyArg_ParseTuple(args, ":GetVersion"))
841 return NULL;
842
843 return PyLong_FromUnsignedLong(GetVersion());
844}
845
846static PyObject *
847winapi_OpenProcess(PyObject *self, PyObject *args)
848{
849 DWORD dwDesiredAccess;
850 BOOL bInheritHandle;
851 DWORD dwProcessId;
852 HANDLE handle;
853
854 if (!PyArg_ParseTuple(args, F_DWORD F_BOOL F_DWORD,
855 &dwDesiredAccess, &bInheritHandle, &dwProcessId))
856 return NULL;
857
858 handle = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
859 if (handle == NULL)
860 return PyErr_SetFromWindowsErr(0);
861
862 return Py_BuildValue(F_HANDLE, handle);
863}
864
865static PyObject *
866winapi_PeekNamedPipe(PyObject *self, PyObject *args)
867{
868 HANDLE handle;
869 int size = 0;
870 PyObject *buf = NULL;
871 DWORD nread, navail, nleft;
872 BOOL ret;
873
874 if (!PyArg_ParseTuple(args, F_HANDLE "|i:PeekNamedPipe" , &handle, &size))
875 return NULL;
876
877 if (size < 0) {
878 PyErr_SetString(PyExc_ValueError, "negative size");
879 return NULL;
880 }
881
882 if (size) {
883 buf = PyBytes_FromStringAndSize(NULL, size);
884 if (!buf)
885 return NULL;
886 Py_BEGIN_ALLOW_THREADS
887 ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread,
888 &navail, &nleft);
889 Py_END_ALLOW_THREADS
890 if (!ret) {
891 Py_DECREF(buf);
892 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
893 }
894 if (_PyBytes_Resize(&buf, nread))
895 return NULL;
896 return Py_BuildValue("Nii", buf, navail, nleft);
897 }
898 else {
899 Py_BEGIN_ALLOW_THREADS
900 ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft);
901 Py_END_ALLOW_THREADS
902 if (!ret) {
903 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
904 }
905 return Py_BuildValue("ii", navail, nleft);
906 }
907}
908
909static PyObject *
910winapi_ReadFile(PyObject *self, PyObject *args, PyObject *kwds)
911{
912 HANDLE handle;
913 int size;
914 DWORD nread;
915 PyObject *buf;
916 BOOL ret;
917 int use_overlapped = 0;
918 DWORD err;
919 OverlappedObject *overlapped = NULL;
920 static char *kwlist[] = {"handle", "size", "overlapped", NULL};
921
922 if (!PyArg_ParseTupleAndKeywords(args, kwds,
923 F_HANDLE "i|i:ReadFile", kwlist,
924 &handle, &size, &use_overlapped))
925 return NULL;
926
927 buf = PyBytes_FromStringAndSize(NULL, size);
928 if (!buf)
929 return NULL;
930 if (use_overlapped) {
931 overlapped = new_overlapped(handle);
932 if (!overlapped) {
933 Py_DECREF(buf);
934 return NULL;
935 }
936 /* Steals reference to buf */
937 overlapped->read_buffer = buf;
938 }
939
940 Py_BEGIN_ALLOW_THREADS
941 ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread,
942 overlapped ? &overlapped->overlapped : NULL);
943 Py_END_ALLOW_THREADS
944
945 err = ret ? 0 : GetLastError();
946
947 if (overlapped) {
948 if (!ret) {
949 if (err == ERROR_IO_PENDING)
950 overlapped->pending = 1;
951 else if (err != ERROR_MORE_DATA) {
952 Py_DECREF(overlapped);
953 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
954 }
955 }
956 return Py_BuildValue("NI", (PyObject *) overlapped, err);
957 }
958
959 if (!ret && err != ERROR_MORE_DATA) {
960 Py_DECREF(buf);
961 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
962 }
963 if (_PyBytes_Resize(&buf, nread))
964 return NULL;
965 return Py_BuildValue("NI", buf, err);
966}
967
968static PyObject *
969winapi_SetNamedPipeHandleState(PyObject *self, PyObject *args)
970{
971 HANDLE hNamedPipe;
972 PyObject *oArgs[3];
973 DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL};
974 int i;
975
976 if (!PyArg_ParseTuple(args, F_HANDLE "OOO",
977 &hNamedPipe, &oArgs[0], &oArgs[1], &oArgs[2]))
978 return NULL;
979
980 PyErr_Clear();
981
982 for (i = 0 ; i < 3 ; i++) {
983 if (oArgs[i] != Py_None) {
984 dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]);
985 if (PyErr_Occurred())
986 return NULL;
987 pArgs[i] = &dwArgs[i];
988 }
989 }
990
991 if (!SetNamedPipeHandleState(hNamedPipe, pArgs[0], pArgs[1], pArgs[2]))
992 return PyErr_SetFromWindowsErr(0);
993
994 Py_RETURN_NONE;
995}
996
997PyDoc_STRVAR(TerminateProcess_doc,
998"TerminateProcess(handle, exit_code) -> None\n\
999\n\
1000Terminate the specified process and all of its threads.");
1001
1002static PyObject *
1003winapi_TerminateProcess(PyObject* self, PyObject* args)
1004{
1005 BOOL result;
1006
1007 HANDLE process;
1008 UINT exit_code;
1009 if (! PyArg_ParseTuple(args, F_HANDLE F_UINT ":TerminateProcess",
1010 &process, &exit_code))
1011 return NULL;
1012
1013 result = TerminateProcess(process, exit_code);
1014
1015 if (! result)
1016 return PyErr_SetFromWindowsErr(GetLastError());
1017
1018 Py_INCREF(Py_None);
1019 return Py_None;
1020}
1021
1022static PyObject *
1023winapi_WaitNamedPipe(PyObject *self, PyObject *args)
1024{
1025 LPCTSTR lpNamedPipeName;
1026 DWORD nTimeOut;
1027 BOOL success;
1028
1029 if (!PyArg_ParseTuple(args, "s" F_DWORD, &lpNamedPipeName, &nTimeOut))
1030 return NULL;
1031
1032 Py_BEGIN_ALLOW_THREADS
1033 success = WaitNamedPipe(lpNamedPipeName, nTimeOut);
1034 Py_END_ALLOW_THREADS
1035
1036 if (!success)
1037 return PyErr_SetFromWindowsErr(0);
1038
1039 Py_RETURN_NONE;
1040}
1041
1042static PyObject *
1043winapi_WaitForMultipleObjects(PyObject* self, PyObject* args)
1044{
1045 DWORD result;
1046 PyObject *handle_seq;
1047 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
1048 HANDLE sigint_event = NULL;
1049 Py_ssize_t nhandles, i;
1050 BOOL wait_flag;
1051 DWORD milliseconds = INFINITE;
1052
1053 if (!PyArg_ParseTuple(args, "O" F_BOOL "|" F_DWORD
1054 ":WaitForMultipleObjects",
1055 &handle_seq, &wait_flag, &milliseconds))
1056 return NULL;
1057
1058 if (!PySequence_Check(handle_seq)) {
1059 PyErr_Format(PyExc_TypeError,
1060 "sequence type expected, got '%s'",
Richard Oudkerk67339272012-08-21 14:54:22 +01001061 Py_TYPE(handle_seq)->tp_name);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001062 return NULL;
1063 }
1064 nhandles = PySequence_Length(handle_seq);
1065 if (nhandles == -1)
1066 return NULL;
1067 if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS - 1) {
1068 PyErr_Format(PyExc_ValueError,
1069 "need at most %zd handles, got a sequence of length %zd",
1070 MAXIMUM_WAIT_OBJECTS - 1, nhandles);
1071 return NULL;
1072 }
1073 for (i = 0; i < nhandles; i++) {
1074 HANDLE h;
1075 PyObject *v = PySequence_GetItem(handle_seq, i);
1076 if (v == NULL)
1077 return NULL;
1078 if (!PyArg_Parse(v, F_HANDLE, &h)) {
1079 Py_DECREF(v);
1080 return NULL;
1081 }
1082 handles[i] = h;
1083 Py_DECREF(v);
1084 }
1085 /* If this is the main thread then make the wait interruptible
1086 by Ctrl-C unless we are waiting for *all* handles */
1087 if (!wait_flag && _PyOS_IsMainThread()) {
1088 sigint_event = _PyOS_SigintEvent();
1089 assert(sigint_event != NULL);
1090 handles[nhandles++] = sigint_event;
1091 }
1092
1093 Py_BEGIN_ALLOW_THREADS
1094 if (sigint_event != NULL)
1095 ResetEvent(sigint_event);
1096 result = WaitForMultipleObjects((DWORD) nhandles, handles,
1097 wait_flag, milliseconds);
1098 Py_END_ALLOW_THREADS
1099
1100 if (result == WAIT_FAILED)
1101 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1102 else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) {
1103 errno = EINTR;
1104 return PyErr_SetFromErrno(PyExc_IOError);
1105 }
1106
1107 return PyLong_FromLong((int) result);
1108}
1109
1110PyDoc_STRVAR(WaitForSingleObject_doc,
1111"WaitForSingleObject(handle, timeout) -> result\n\
1112\n\
1113Wait until the specified object is in the signaled state or\n\
1114the time-out interval elapses. The timeout value is specified\n\
1115in milliseconds.");
1116
1117static PyObject *
1118winapi_WaitForSingleObject(PyObject* self, PyObject* args)
1119{
1120 DWORD result;
1121
1122 HANDLE handle;
1123 DWORD milliseconds;
1124 if (! PyArg_ParseTuple(args, F_HANDLE F_DWORD ":WaitForSingleObject",
1125 &handle,
1126 &milliseconds))
1127 return NULL;
1128
1129 Py_BEGIN_ALLOW_THREADS
1130 result = WaitForSingleObject(handle, milliseconds);
1131 Py_END_ALLOW_THREADS
1132
1133 if (result == WAIT_FAILED)
1134 return PyErr_SetFromWindowsErr(GetLastError());
1135
1136 return PyLong_FromUnsignedLong(result);
1137}
1138
1139static PyObject *
1140winapi_WriteFile(PyObject *self, PyObject *args, PyObject *kwds)
1141{
1142 HANDLE handle;
1143 Py_buffer _buf, *buf;
1144 PyObject *bufobj;
1145 DWORD written;
1146 BOOL ret;
1147 int use_overlapped = 0;
1148 DWORD err;
1149 OverlappedObject *overlapped = NULL;
1150 static char *kwlist[] = {"handle", "buffer", "overlapped", NULL};
1151
1152 /* First get handle and use_overlapped to know which Py_buffer to use */
1153 if (!PyArg_ParseTupleAndKeywords(args, kwds,
1154 F_HANDLE "O|i:WriteFile", kwlist,
1155 &handle, &bufobj, &use_overlapped))
1156 return NULL;
1157
1158 if (use_overlapped) {
1159 overlapped = new_overlapped(handle);
1160 if (!overlapped)
1161 return NULL;
1162 buf = &overlapped->write_buffer;
1163 }
1164 else
1165 buf = &_buf;
1166
1167 if (!PyArg_Parse(bufobj, "y*", buf)) {
1168 Py_XDECREF(overlapped);
1169 return NULL;
1170 }
1171
1172 Py_BEGIN_ALLOW_THREADS
1173 ret = WriteFile(handle, buf->buf, buf->len, &written,
1174 overlapped ? &overlapped->overlapped : NULL);
1175 Py_END_ALLOW_THREADS
1176
1177 err = ret ? 0 : GetLastError();
1178
1179 if (overlapped) {
1180 if (!ret) {
1181 if (err == ERROR_IO_PENDING)
1182 overlapped->pending = 1;
1183 else {
1184 Py_DECREF(overlapped);
1185 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1186 }
1187 }
1188 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1189 }
1190
1191 PyBuffer_Release(buf);
1192 if (!ret)
1193 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
1194 return Py_BuildValue("II", written, err);
1195}
1196
1197
1198static PyMethodDef winapi_functions[] = {
1199 {"CloseHandle", winapi_CloseHandle, METH_VARARGS,
1200 CloseHandle_doc},
1201 {"ConnectNamedPipe", (PyCFunction)winapi_ConnectNamedPipe,
1202 METH_VARARGS | METH_KEYWORDS, ""},
1203 {"CreateFile", winapi_CreateFile, METH_VARARGS,
1204 ""},
1205 {"CreateNamedPipe", winapi_CreateNamedPipe, METH_VARARGS,
1206 ""},
1207 {"CreatePipe", winapi_CreatePipe, METH_VARARGS,
1208 CreatePipe_doc},
1209 {"CreateProcess", winapi_CreateProcess, METH_VARARGS,
1210 CreateProcess_doc},
1211 {"DuplicateHandle", winapi_DuplicateHandle, METH_VARARGS,
1212 DuplicateHandle_doc},
1213 {"ExitProcess", winapi_ExitProcess, METH_VARARGS,
1214 ""},
1215 {"GetCurrentProcess", winapi_GetCurrentProcess, METH_VARARGS,
1216 GetCurrentProcess_doc},
1217 {"GetExitCodeProcess", winapi_GetExitCodeProcess, METH_VARARGS,
1218 GetExitCodeProcess_doc},
1219 {"GetLastError", winapi_GetLastError, METH_NOARGS,
1220 GetCurrentProcess_doc},
1221 {"GetModuleFileName", winapi_GetModuleFileName, METH_VARARGS,
1222 GetModuleFileName_doc},
1223 {"GetStdHandle", winapi_GetStdHandle, METH_VARARGS,
1224 GetStdHandle_doc},
1225 {"GetVersion", winapi_GetVersion, METH_VARARGS,
1226 GetVersion_doc},
1227 {"OpenProcess", winapi_OpenProcess, METH_VARARGS,
1228 ""},
1229 {"PeekNamedPipe", winapi_PeekNamedPipe, METH_VARARGS,
1230 ""},
1231 {"ReadFile", (PyCFunction)winapi_ReadFile, METH_VARARGS | METH_KEYWORDS,
1232 ""},
1233 {"SetNamedPipeHandleState", winapi_SetNamedPipeHandleState, METH_VARARGS,
1234 ""},
1235 {"TerminateProcess", winapi_TerminateProcess, METH_VARARGS,
1236 TerminateProcess_doc},
1237 {"WaitNamedPipe", winapi_WaitNamedPipe, METH_VARARGS,
1238 ""},
1239 {"WaitForMultipleObjects", winapi_WaitForMultipleObjects, METH_VARARGS,
1240 ""},
1241 {"WaitForSingleObject", winapi_WaitForSingleObject, METH_VARARGS,
1242 WaitForSingleObject_doc},
1243 {"WriteFile", (PyCFunction)winapi_WriteFile, METH_VARARGS | METH_KEYWORDS,
1244 ""},
1245 {NULL, NULL}
1246};
1247
1248static struct PyModuleDef winapi_module = {
1249 PyModuleDef_HEAD_INIT,
1250 "_winapi",
1251 NULL,
1252 -1,
1253 winapi_functions,
1254 NULL,
1255 NULL,
1256 NULL,
1257 NULL
1258};
1259
1260#define WINAPI_CONSTANT(fmt, con) \
1261 PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1262
1263PyMODINIT_FUNC
1264PyInit__winapi(void)
1265{
1266 PyObject *d;
1267 PyObject *m;
1268
1269 if (PyType_Ready(&OverlappedType) < 0)
1270 return NULL;
1271
1272 m = PyModule_Create(&winapi_module);
1273 if (m == NULL)
1274 return NULL;
1275 d = PyModule_GetDict(m);
1276
1277 PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType);
1278
1279 /* constants */
1280 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
1281 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP);
1282 WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001283 WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001284 WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
1285 WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
1286 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1287 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1288 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1289 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001290 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1291 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
Richard Oudkerkfdb8dcf2012-05-05 19:45:37 +01001292 WINAPI_CONSTANT(F_DWORD, ERROR_NO_DATA);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001293 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
1294 WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
1295 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
1296 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
1297 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
1298 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE);
1299 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001300 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ);
1301 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001302 WINAPI_CONSTANT(F_DWORD, GENERIC_READ);
1303 WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE);
1304 WINAPI_CONSTANT(F_DWORD, INFINITE);
1305 WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
1306 WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING);
1307 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
1308 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
1309 WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
1310 WINAPI_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE);
1311 WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES);
1312 WINAPI_CONSTANT(F_DWORD, PIPE_WAIT);
1313 WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001314 WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001315 WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW);
1316 WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES);
1317 WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE);
1318 WINAPI_CONSTANT(F_DWORD, STD_OUTPUT_HANDLE);
1319 WINAPI_CONSTANT(F_DWORD, STD_ERROR_HANDLE);
1320 WINAPI_CONSTANT(F_DWORD, STILL_ACTIVE);
1321 WINAPI_CONSTANT(F_DWORD, SW_HIDE);
1322 WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0);
1323 WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT);
1324
1325 WINAPI_CONSTANT("i", NULL);
1326
1327 return m;
1328}