You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1331 lines
39 KiB

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