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.

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