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
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" // PyMemberDef
39
40 #define WINDOWS_LEAN_AND_MEAN
41 #include "windows.h"
42 #include <crtdbg.h>
43 #include "winreparse.h"
44
45 #if defined(MS_WIN32) && !defined(MS_WIN64)
46 #define HANDLE_TO_PYNUM(handle) \
47 PyLong_FromUnsignedLong((unsigned long) handle)
48 #define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLong(obj))
49 #define F_POINTER "k"
50 #define T_POINTER T_ULONG
51 #else
52 #define HANDLE_TO_PYNUM(handle) \
53 PyLong_FromUnsignedLongLong((unsigned long long) handle)
54 #define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLongLong(obj))
55 #define F_POINTER "K"
56 #define T_POINTER T_ULONGLONG
57 #endif
58
59 #define F_HANDLE F_POINTER
60 #define F_DWORD "k"
61
62 #define T_HANDLE T_POINTER
63
64 /* Grab CancelIoEx dynamically from kernel32 */
65 static int has_CancelIoEx = -1;
66 static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED);
67
68 static int
check_CancelIoEx()69 check_CancelIoEx()
70 {
71 if (has_CancelIoEx == -1)
72 {
73 HINSTANCE hKernel32 = GetModuleHandle("KERNEL32");
74 * (FARPROC *) &Py_CancelIoEx = GetProcAddress(hKernel32,
75 "CancelIoEx");
76 has_CancelIoEx = (Py_CancelIoEx != NULL);
77 }
78 return has_CancelIoEx;
79 }
80
81
82 /*
83 * A Python object wrapping an OVERLAPPED structure and other useful data
84 * for overlapped I/O
85 */
86
87 typedef struct {
88 PyObject_HEAD
89 OVERLAPPED overlapped;
90 /* For convenience, we store the file handle too */
91 HANDLE handle;
92 /* Whether there's I/O in flight */
93 int pending;
94 /* Whether I/O completed successfully */
95 int completed;
96 /* Buffer used for reading (optional) */
97 PyObject *read_buffer;
98 /* Buffer used for writing (optional) */
99 Py_buffer write_buffer;
100 } OverlappedObject;
101
102 static void
overlapped_dealloc(OverlappedObject * self)103 overlapped_dealloc(OverlappedObject *self)
104 {
105 DWORD bytes;
106 int err = GetLastError();
107
108 if (self->pending) {
109 if (check_CancelIoEx() &&
110 Py_CancelIoEx(self->handle, &self->overlapped) &&
111 GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE))
112 {
113 /* The operation is no longer pending -- nothing to do. */
114 }
115 else if (_Py_IsFinalizing())
116 {
117 /* The operation is still pending -- give a warning. This
118 will probably only happen on Windows XP. */
119 PyErr_SetString(PyExc_RuntimeError,
120 "I/O operations still in flight while destroying "
121 "Overlapped object, the process may crash");
122 PyErr_WriteUnraisable(NULL);
123 }
124 else
125 {
126 /* The operation is still pending, but the process is
127 probably about to exit, so we need not worry too much
128 about memory leaks. Leaking self prevents a potential
129 crash. This can happen when a daemon thread is cleaned
130 up at exit -- see #19565. We only expect to get here
131 on Windows XP. */
132 CloseHandle(self->overlapped.hEvent);
133 SetLastError(err);
134 return;
135 }
136 }
137
138 CloseHandle(self->overlapped.hEvent);
139 SetLastError(err);
140 if (self->write_buffer.obj)
141 PyBuffer_Release(&self->write_buffer);
142 Py_CLEAR(self->read_buffer);
143 PyObject_Del(self);
144 }
145
146 /*[clinic input]
147 module _winapi
148 class _winapi.Overlapped "OverlappedObject *" "&OverlappedType"
149 [clinic start generated code]*/
150 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=c13d3f5fd1dabb84]*/
151
152 /*[python input]
153 def create_converter(type_, format_unit):
154 name = type_ + '_converter'
155 # registered upon creation by CConverter's metaclass
156 type(name, (CConverter,), {'type': type_, 'format_unit': format_unit})
157
158 # format unit differs between platforms for these
159 create_converter('HANDLE', '" F_HANDLE "')
160 create_converter('HMODULE', '" F_HANDLE "')
161 create_converter('LPSECURITY_ATTRIBUTES', '" F_POINTER "')
162 create_converter('LPCVOID', '" F_POINTER "')
163
164 create_converter('BOOL', 'i') # F_BOOL used previously (always 'i')
165 create_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter)
166 create_converter('LPCTSTR', 's')
167 create_converter('LPCWSTR', 'u')
168 create_converter('LPWSTR', 'u')
169 create_converter('UINT', 'I') # F_UINT used previously (always 'I')
170
171 class HANDLE_return_converter(CReturnConverter):
172 type = 'HANDLE'
173
174 def render(self, function, data):
175 self.declare(data)
176 self.err_occurred_if("_return_value == INVALID_HANDLE_VALUE", data)
177 data.return_conversion.append(
178 'if (_return_value == NULL) {\n Py_RETURN_NONE;\n}\n')
179 data.return_conversion.append(
180 'return_value = HANDLE_TO_PYNUM(_return_value);\n')
181
182 class DWORD_return_converter(CReturnConverter):
183 type = 'DWORD'
184
185 def render(self, function, data):
186 self.declare(data)
187 self.err_occurred_if("_return_value == PY_DWORD_MAX", data)
188 data.return_conversion.append(
189 'return_value = Py_BuildValue("k", _return_value);\n')
190
191 class LPVOID_return_converter(CReturnConverter):
192 type = 'LPVOID'
193
194 def render(self, function, data):
195 self.declare(data)
196 self.err_occurred_if("_return_value == NULL", data)
197 data.return_conversion.append(
198 'return_value = HANDLE_TO_PYNUM(_return_value);\n')
199 [python start generated code]*/
200 /*[python end generated code: output=da39a3ee5e6b4b0d input=79464c61a31ae932]*/
201
202 #include "clinic/_winapi.c.h"
203
204 /*[clinic input]
205 _winapi.Overlapped.GetOverlappedResult
206
207 wait: bool
208 /
209 [clinic start generated code]*/
210
211 static PyObject *
_winapi_Overlapped_GetOverlappedResult_impl(OverlappedObject * self,int wait)212 _winapi_Overlapped_GetOverlappedResult_impl(OverlappedObject *self, int wait)
213 /*[clinic end generated code: output=bdd0c1ed6518cd03 input=194505ee8e0e3565]*/
214 {
215 BOOL res;
216 DWORD transferred = 0;
217 DWORD err;
218
219 Py_BEGIN_ALLOW_THREADS
220 res = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
221 wait != 0);
222 Py_END_ALLOW_THREADS
223
224 err = res ? ERROR_SUCCESS : GetLastError();
225 switch (err) {
226 case ERROR_SUCCESS:
227 case ERROR_MORE_DATA:
228 case ERROR_OPERATION_ABORTED:
229 self->completed = 1;
230 self->pending = 0;
231 break;
232 case ERROR_IO_INCOMPLETE:
233 break;
234 default:
235 self->pending = 0;
236 return PyErr_SetExcFromWindowsErr(PyExc_OSError, err);
237 }
238 if (self->completed && self->read_buffer != NULL) {
239 assert(PyBytes_CheckExact(self->read_buffer));
240 if (transferred != PyBytes_GET_SIZE(self->read_buffer) &&
241 _PyBytes_Resize(&self->read_buffer, transferred))
242 return NULL;
243 }
244 return Py_BuildValue("II", (unsigned) transferred, (unsigned) err);
245 }
246
247 /*[clinic input]
248 _winapi.Overlapped.getbuffer
249 [clinic start generated code]*/
250
251 static PyObject *
_winapi_Overlapped_getbuffer_impl(OverlappedObject * self)252 _winapi_Overlapped_getbuffer_impl(OverlappedObject *self)
253 /*[clinic end generated code: output=95a3eceefae0f748 input=347fcfd56b4ceabd]*/
254 {
255 PyObject *res;
256 if (!self->completed) {
257 PyErr_SetString(PyExc_ValueError,
258 "can't get read buffer before GetOverlappedResult() "
259 "signals the operation completed");
260 return NULL;
261 }
262 res = self->read_buffer ? self->read_buffer : Py_None;
263 Py_INCREF(res);
264 return res;
265 }
266
267 /*[clinic input]
268 _winapi.Overlapped.cancel
269 [clinic start generated code]*/
270
271 static PyObject *
_winapi_Overlapped_cancel_impl(OverlappedObject * self)272 _winapi_Overlapped_cancel_impl(OverlappedObject *self)
273 /*[clinic end generated code: output=fcb9ab5df4ebdae5 input=cbf3da142290039f]*/
274 {
275 BOOL res = TRUE;
276
277 if (self->pending) {
278 Py_BEGIN_ALLOW_THREADS
279 if (check_CancelIoEx())
280 res = Py_CancelIoEx(self->handle, &self->overlapped);
281 else
282 res = CancelIo(self->handle);
283 Py_END_ALLOW_THREADS
284 }
285
286 /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
287 if (!res && GetLastError() != ERROR_NOT_FOUND)
288 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
289 self->pending = 0;
290 Py_RETURN_NONE;
291 }
292
293 static PyMethodDef overlapped_methods[] = {
294 _WINAPI_OVERLAPPED_GETOVERLAPPEDRESULT_METHODDEF
295 _WINAPI_OVERLAPPED_GETBUFFER_METHODDEF
296 _WINAPI_OVERLAPPED_CANCEL_METHODDEF
297 {NULL}
298 };
299
300 static PyMemberDef overlapped_members[] = {
301 {"event", T_HANDLE,
302 offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
303 READONLY, "overlapped event handle"},
304 {NULL}
305 };
306
307 PyTypeObject OverlappedType = {
308 PyVarObject_HEAD_INIT(NULL, 0)
309 /* tp_name */ "_winapi.Overlapped",
310 /* tp_basicsize */ sizeof(OverlappedObject),
311 /* tp_itemsize */ 0,
312 /* tp_dealloc */ (destructor) overlapped_dealloc,
313 /* tp_vectorcall_offset */ 0,
314 /* tp_getattr */ 0,
315 /* tp_setattr */ 0,
316 /* tp_as_async */ 0,
317 /* tp_repr */ 0,
318 /* tp_as_number */ 0,
319 /* tp_as_sequence */ 0,
320 /* tp_as_mapping */ 0,
321 /* tp_hash */ 0,
322 /* tp_call */ 0,
323 /* tp_str */ 0,
324 /* tp_getattro */ 0,
325 /* tp_setattro */ 0,
326 /* tp_as_buffer */ 0,
327 /* tp_flags */ Py_TPFLAGS_DEFAULT,
328 /* tp_doc */ "OVERLAPPED structure wrapper",
329 /* tp_traverse */ 0,
330 /* tp_clear */ 0,
331 /* tp_richcompare */ 0,
332 /* tp_weaklistoffset */ 0,
333 /* tp_iter */ 0,
334 /* tp_iternext */ 0,
335 /* tp_methods */ overlapped_methods,
336 /* tp_members */ overlapped_members,
337 /* tp_getset */ 0,
338 /* tp_base */ 0,
339 /* tp_dict */ 0,
340 /* tp_descr_get */ 0,
341 /* tp_descr_set */ 0,
342 /* tp_dictoffset */ 0,
343 /* tp_init */ 0,
344 /* tp_alloc */ 0,
345 /* tp_new */ 0,
346 };
347
348 static OverlappedObject *
new_overlapped(HANDLE handle)349 new_overlapped(HANDLE handle)
350 {
351 OverlappedObject *self;
352
353 self = PyObject_New(OverlappedObject, &OverlappedType);
354 if (!self)
355 return NULL;
356 self->handle = handle;
357 self->read_buffer = NULL;
358 self->pending = 0;
359 self->completed = 0;
360 memset(&self->overlapped, 0, sizeof(OVERLAPPED));
361 memset(&self->write_buffer, 0, sizeof(Py_buffer));
362 /* Manual reset, initially non-signalled */
363 self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
364 return self;
365 }
366
367 /* -------------------------------------------------------------------- */
368 /* windows API functions */
369
370 /*[clinic input]
371 _winapi.CloseHandle
372
373 handle: HANDLE
374 /
375
376 Close handle.
377 [clinic start generated code]*/
378
379 static PyObject *
_winapi_CloseHandle_impl(PyObject * module,HANDLE handle)380 _winapi_CloseHandle_impl(PyObject *module, HANDLE handle)
381 /*[clinic end generated code: output=7ad37345f07bd782 input=7f0e4ac36e0352b8]*/
382 {
383 BOOL success;
384
385 Py_BEGIN_ALLOW_THREADS
386 success = CloseHandle(handle);
387 Py_END_ALLOW_THREADS
388
389 if (!success)
390 return PyErr_SetFromWindowsErr(0);
391
392 Py_RETURN_NONE;
393 }
394
395 /*[clinic input]
396 _winapi.ConnectNamedPipe
397
398 handle: HANDLE
399 overlapped as use_overlapped: bool(accept={int}) = False
400 [clinic start generated code]*/
401
402 static PyObject *
_winapi_ConnectNamedPipe_impl(PyObject * module,HANDLE handle,int use_overlapped)403 _winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle,
404 int use_overlapped)
405 /*[clinic end generated code: output=335a0e7086800671 input=34f937c1c86e5e68]*/
406 {
407 BOOL success;
408 OverlappedObject *overlapped = NULL;
409
410 if (use_overlapped) {
411 overlapped = new_overlapped(handle);
412 if (!overlapped)
413 return NULL;
414 }
415
416 Py_BEGIN_ALLOW_THREADS
417 success = ConnectNamedPipe(handle,
418 overlapped ? &overlapped->overlapped : NULL);
419 Py_END_ALLOW_THREADS
420
421 if (overlapped) {
422 int err = GetLastError();
423 /* Overlapped ConnectNamedPipe never returns a success code */
424 assert(success == 0);
425 if (err == ERROR_IO_PENDING)
426 overlapped->pending = 1;
427 else if (err == ERROR_PIPE_CONNECTED)
428 SetEvent(overlapped->overlapped.hEvent);
429 else {
430 Py_DECREF(overlapped);
431 return PyErr_SetFromWindowsErr(err);
432 }
433 return (PyObject *) overlapped;
434 }
435 if (!success)
436 return PyErr_SetFromWindowsErr(0);
437
438 Py_RETURN_NONE;
439 }
440
441 /*[clinic input]
442 _winapi.CreateFile -> HANDLE
443
444 file_name: LPCTSTR
445 desired_access: DWORD
446 share_mode: DWORD
447 security_attributes: LPSECURITY_ATTRIBUTES
448 creation_disposition: DWORD
449 flags_and_attributes: DWORD
450 template_file: HANDLE
451 /
452 [clinic start generated code]*/
453
454 static HANDLE
_winapi_CreateFile_impl(PyObject * module,LPCTSTR file_name,DWORD desired_access,DWORD share_mode,LPSECURITY_ATTRIBUTES security_attributes,DWORD creation_disposition,DWORD flags_and_attributes,HANDLE template_file)455 _winapi_CreateFile_impl(PyObject *module, LPCTSTR file_name,
456 DWORD desired_access, DWORD share_mode,
457 LPSECURITY_ATTRIBUTES security_attributes,
458 DWORD creation_disposition,
459 DWORD flags_and_attributes, HANDLE template_file)
460 /*[clinic end generated code: output=417ddcebfc5a3d53 input=6423c3e40372dbd5]*/
461 {
462 HANDLE handle;
463
464 if (PySys_Audit("_winapi.CreateFile", "uIIII",
465 file_name, desired_access, share_mode,
466 creation_disposition, flags_and_attributes) < 0) {
467 return INVALID_HANDLE_VALUE;
468 }
469
470 Py_BEGIN_ALLOW_THREADS
471 handle = CreateFile(file_name, desired_access,
472 share_mode, security_attributes,
473 creation_disposition,
474 flags_and_attributes, template_file);
475 Py_END_ALLOW_THREADS
476
477 if (handle == INVALID_HANDLE_VALUE)
478 PyErr_SetFromWindowsErr(0);
479
480 return handle;
481 }
482
483 /*[clinic input]
484 _winapi.CreateFileMapping -> HANDLE
485
486 file_handle: HANDLE
487 security_attributes: LPSECURITY_ATTRIBUTES
488 protect: DWORD
489 max_size_high: DWORD
490 max_size_low: DWORD
491 name: LPCWSTR
492 /
493 [clinic start generated code]*/
494
495 static HANDLE
_winapi_CreateFileMapping_impl(PyObject * module,HANDLE file_handle,LPSECURITY_ATTRIBUTES security_attributes,DWORD protect,DWORD max_size_high,DWORD max_size_low,LPCWSTR name)496 _winapi_CreateFileMapping_impl(PyObject *module, HANDLE file_handle,
497 LPSECURITY_ATTRIBUTES security_attributes,
498 DWORD protect, DWORD max_size_high,
499 DWORD max_size_low, LPCWSTR name)
500 /*[clinic end generated code: output=6c0a4d5cf7f6fcc6 input=3dc5cf762a74dee8]*/
501 {
502 HANDLE handle;
503
504 Py_BEGIN_ALLOW_THREADS
505 handle = CreateFileMappingW(file_handle, security_attributes,
506 protect, max_size_high, max_size_low,
507 name);
508 Py_END_ALLOW_THREADS
509
510 if (handle == NULL) {
511 PyObject *temp = PyUnicode_FromWideChar(name, -1);
512 PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, temp);
513 Py_XDECREF(temp);
514 handle = INVALID_HANDLE_VALUE;
515 }
516
517 return handle;
518 }
519
520 /*[clinic input]
521 _winapi.CreateJunction
522
523 src_path: LPWSTR
524 dst_path: LPWSTR
525 /
526 [clinic start generated code]*/
527
528 static PyObject *
_winapi_CreateJunction_impl(PyObject * module,LPWSTR src_path,LPWSTR dst_path)529 _winapi_CreateJunction_impl(PyObject *module, LPWSTR src_path,
530 LPWSTR dst_path)
531 /*[clinic end generated code: output=66b7eb746e1dfa25 input=8cd1f9964b6e3d36]*/
532 {
533 /* Privilege adjustment */
534 HANDLE token = NULL;
535 TOKEN_PRIVILEGES tp;
536
537 /* Reparse data buffer */
538 const USHORT prefix_len = 4;
539 USHORT print_len = 0;
540 USHORT rdb_size = 0;
541 _Py_PREPARSE_DATA_BUFFER rdb = NULL;
542
543 /* Junction point creation */
544 HANDLE junction = NULL;
545 DWORD ret = 0;
546
547 if (src_path == NULL || dst_path == NULL)
548 return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
549
550 if (wcsncmp(src_path, L"\\??\\", prefix_len) == 0)
551 return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
552
553 if (PySys_Audit("_winapi.CreateJunction", "uu", src_path, dst_path) < 0) {
554 return NULL;
555 }
556
557 /* Adjust privileges to allow rewriting directory entry as a
558 junction point. */
559 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
560 goto cleanup;
561
562 if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid))
563 goto cleanup;
564
565 tp.PrivilegeCount = 1;
566 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
567 if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
568 NULL, NULL))
569 goto cleanup;
570
571 if (GetFileAttributesW(src_path) == INVALID_FILE_ATTRIBUTES)
572 goto cleanup;
573
574 /* Store the absolute link target path length in print_len. */
575 print_len = (USHORT)GetFullPathNameW(src_path, 0, NULL, NULL);
576 if (print_len == 0)
577 goto cleanup;
578
579 /* NUL terminator should not be part of print_len. */
580 --print_len;
581
582 /* REPARSE_DATA_BUFFER usage is heavily under-documented, especially for
583 junction points. Here's what I've learned along the way:
584 - A junction point has two components: a print name and a substitute
585 name. They both describe the link target, but the substitute name is
586 the physical target and the print name is shown in directory listings.
587 - The print name must be a native name, prefixed with "\??\".
588 - Both names are stored after each other in the same buffer (the
589 PathBuffer) and both must be NUL-terminated.
590 - There are four members defining their respective offset and length
591 inside PathBuffer: SubstituteNameOffset, SubstituteNameLength,
592 PrintNameOffset and PrintNameLength.
593 - The total size we need to allocate for the REPARSE_DATA_BUFFER, thus,
594 is the sum of:
595 - the fixed header size (REPARSE_DATA_BUFFER_HEADER_SIZE)
596 - the size of the MountPointReparseBuffer member without the PathBuffer
597 - the size of the prefix ("\??\") in bytes
598 - the size of the print name in bytes
599 - the size of the substitute name in bytes
600 - the size of two NUL terminators in bytes */
601 rdb_size = _Py_REPARSE_DATA_BUFFER_HEADER_SIZE +
602 sizeof(rdb->MountPointReparseBuffer) -
603 sizeof(rdb->MountPointReparseBuffer.PathBuffer) +
604 /* Two +1's for NUL terminators. */
605 (prefix_len + print_len + 1 + print_len + 1) * sizeof(WCHAR);
606 rdb = (_Py_PREPARSE_DATA_BUFFER)PyMem_RawCalloc(1, rdb_size);
607 if (rdb == NULL)
608 goto cleanup;
609
610 rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
611 rdb->ReparseDataLength = rdb_size - _Py_REPARSE_DATA_BUFFER_HEADER_SIZE;
612 rdb->MountPointReparseBuffer.SubstituteNameOffset = 0;
613 rdb->MountPointReparseBuffer.SubstituteNameLength =
614 (prefix_len + print_len) * sizeof(WCHAR);
615 rdb->MountPointReparseBuffer.PrintNameOffset =
616 rdb->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
617 rdb->MountPointReparseBuffer.PrintNameLength = print_len * sizeof(WCHAR);
618
619 /* Store the full native path of link target at the substitute name
620 offset (0). */
621 wcscpy(rdb->MountPointReparseBuffer.PathBuffer, L"\\??\\");
622 if (GetFullPathNameW(src_path, print_len + 1,
623 rdb->MountPointReparseBuffer.PathBuffer + prefix_len,
624 NULL) == 0)
625 goto cleanup;
626
627 /* Copy everything but the native prefix to the print name offset. */
628 wcscpy(rdb->MountPointReparseBuffer.PathBuffer +
629 prefix_len + print_len + 1,
630 rdb->MountPointReparseBuffer.PathBuffer + prefix_len);
631
632 /* Create a directory for the junction point. */
633 if (!CreateDirectoryW(dst_path, NULL))
634 goto cleanup;
635
636 junction = CreateFileW(dst_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
637 OPEN_EXISTING,
638 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
639 if (junction == INVALID_HANDLE_VALUE)
640 goto cleanup;
641
642 /* Make the directory entry a junction point. */
643 if (!DeviceIoControl(junction, FSCTL_SET_REPARSE_POINT, rdb, rdb_size,
644 NULL, 0, &ret, NULL))
645 goto cleanup;
646
647 cleanup:
648 ret = GetLastError();
649
650 CloseHandle(token);
651 CloseHandle(junction);
652 PyMem_RawFree(rdb);
653
654 if (ret != 0)
655 return PyErr_SetFromWindowsErr(ret);
656
657 Py_RETURN_NONE;
658 }
659
660 /*[clinic input]
661 _winapi.CreateNamedPipe -> HANDLE
662
663 name: LPCTSTR
664 open_mode: DWORD
665 pipe_mode: DWORD
666 max_instances: DWORD
667 out_buffer_size: DWORD
668 in_buffer_size: DWORD
669 default_timeout: DWORD
670 security_attributes: LPSECURITY_ATTRIBUTES
671 /
672 [clinic start generated code]*/
673
674 static HANDLE
_winapi_CreateNamedPipe_impl(PyObject * module,LPCTSTR name,DWORD open_mode,DWORD pipe_mode,DWORD max_instances,DWORD out_buffer_size,DWORD in_buffer_size,DWORD default_timeout,LPSECURITY_ATTRIBUTES security_attributes)675 _winapi_CreateNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD open_mode,
676 DWORD pipe_mode, DWORD max_instances,
677 DWORD out_buffer_size, DWORD in_buffer_size,
678 DWORD default_timeout,
679 LPSECURITY_ATTRIBUTES security_attributes)
680 /*[clinic end generated code: output=80f8c07346a94fbc input=5a73530b84d8bc37]*/
681 {
682 HANDLE handle;
683
684 if (PySys_Audit("_winapi.CreateNamedPipe", "uII",
685 name, open_mode, pipe_mode) < 0) {
686 return INVALID_HANDLE_VALUE;
687 }
688
689 Py_BEGIN_ALLOW_THREADS
690 handle = CreateNamedPipe(name, open_mode, pipe_mode,
691 max_instances, out_buffer_size,
692 in_buffer_size, default_timeout,
693 security_attributes);
694 Py_END_ALLOW_THREADS
695
696 if (handle == INVALID_HANDLE_VALUE)
697 PyErr_SetFromWindowsErr(0);
698
699 return handle;
700 }
701
702 /*[clinic input]
703 _winapi.CreatePipe
704
705 pipe_attrs: object
706 Ignored internally, can be None.
707 size: DWORD
708 /
709
710 Create an anonymous pipe.
711
712 Returns a 2-tuple of handles, to the read and write ends of the pipe.
713 [clinic start generated code]*/
714
715 static PyObject *
_winapi_CreatePipe_impl(PyObject * module,PyObject * pipe_attrs,DWORD size)716 _winapi_CreatePipe_impl(PyObject *module, PyObject *pipe_attrs, DWORD size)
717 /*[clinic end generated code: output=1c4411d8699f0925 input=c4f2cfa56ef68d90]*/
718 {
719 HANDLE read_pipe;
720 HANDLE write_pipe;
721 BOOL result;
722
723 if (PySys_Audit("_winapi.CreatePipe", NULL) < 0) {
724 return NULL;
725 }
726
727 Py_BEGIN_ALLOW_THREADS
728 result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
729 Py_END_ALLOW_THREADS
730
731 if (! result)
732 return PyErr_SetFromWindowsErr(GetLastError());
733
734 return Py_BuildValue(
735 "NN", HANDLE_TO_PYNUM(read_pipe), HANDLE_TO_PYNUM(write_pipe));
736 }
737
738 /* helpers for createprocess */
739
740 static unsigned long
getulong(PyObject * obj,const char * name)741 getulong(PyObject* obj, const char* name)
742 {
743 PyObject* value;
744 unsigned long ret;
745
746 value = PyObject_GetAttrString(obj, name);
747 if (! value) {
748 PyErr_Clear(); /* FIXME: propagate error? */
749 return 0;
750 }
751 ret = PyLong_AsUnsignedLong(value);
752 Py_DECREF(value);
753 return ret;
754 }
755
756 static HANDLE
gethandle(PyObject * obj,const char * name)757 gethandle(PyObject* obj, const char* name)
758 {
759 PyObject* value;
760 HANDLE ret;
761
762 value = PyObject_GetAttrString(obj, name);
763 if (! value) {
764 PyErr_Clear(); /* FIXME: propagate error? */
765 return NULL;
766 }
767 if (value == Py_None)
768 ret = NULL;
769 else
770 ret = PYNUM_TO_HANDLE(value);
771 Py_DECREF(value);
772 return ret;
773 }
774
775 static wchar_t *
getenvironment(PyObject * environment)776 getenvironment(PyObject* environment)
777 {
778 Py_ssize_t i, envsize, totalsize;
779 wchar_t *buffer = NULL, *p, *end;
780 PyObject *keys, *values;
781
782 /* convert environment dictionary to windows environment string */
783 if (! PyMapping_Check(environment)) {
784 PyErr_SetString(
785 PyExc_TypeError, "environment must be dictionary or None");
786 return NULL;
787 }
788
789 keys = PyMapping_Keys(environment);
790 if (!keys) {
791 return NULL;
792 }
793 values = PyMapping_Values(environment);
794 if (!values) {
795 goto error;
796 }
797
798 envsize = PyList_GET_SIZE(keys);
799 if (PyList_GET_SIZE(values) != envsize) {
800 PyErr_SetString(PyExc_RuntimeError,
801 "environment changed size during iteration");
802 goto error;
803 }
804
805 totalsize = 1; /* trailing null character */
806 for (i = 0; i < envsize; i++) {
807 PyObject* key = PyList_GET_ITEM(keys, i);
808 PyObject* value = PyList_GET_ITEM(values, i);
809 Py_ssize_t size;
810
811 if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
812 PyErr_SetString(PyExc_TypeError,
813 "environment can only contain strings");
814 goto error;
815 }
816 if (PyUnicode_FindChar(key, '\0', 0, PyUnicode_GET_LENGTH(key), 1) != -1 ||
817 PyUnicode_FindChar(value, '\0', 0, PyUnicode_GET_LENGTH(value), 1) != -1)
818 {
819 PyErr_SetString(PyExc_ValueError, "embedded null character");
820 goto error;
821 }
822 /* Search from index 1 because on Windows starting '=' is allowed for
823 defining hidden environment variables. */
824 if (PyUnicode_GET_LENGTH(key) == 0 ||
825 PyUnicode_FindChar(key, '=', 1, PyUnicode_GET_LENGTH(key), 1) != -1)
826 {
827 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
828 goto error;
829 }
830
831 size = PyUnicode_AsWideChar(key, NULL, 0);
832 assert(size > 1);
833 if (totalsize > PY_SSIZE_T_MAX - size) {
834 PyErr_SetString(PyExc_OverflowError, "environment too long");
835 goto error;
836 }
837 totalsize += size; /* including '=' */
838
839 size = PyUnicode_AsWideChar(value, NULL, 0);
840 assert(size > 0);
841 if (totalsize > PY_SSIZE_T_MAX - size) {
842 PyErr_SetString(PyExc_OverflowError, "environment too long");
843 goto error;
844 }
845 totalsize += size; /* including trailing '\0' */
846 }
847
848 buffer = PyMem_NEW(wchar_t, totalsize);
849 if (! buffer) {
850 PyErr_NoMemory();
851 goto error;
852 }
853 p = buffer;
854 end = buffer + totalsize;
855
856 for (i = 0; i < envsize; i++) {
857 PyObject* key = PyList_GET_ITEM(keys, i);
858 PyObject* value = PyList_GET_ITEM(values, i);
859 Py_ssize_t size = PyUnicode_AsWideChar(key, p, end - p);
860 assert(1 <= size && size < end - p);
861 p += size;
862 *p++ = L'=';
863 size = PyUnicode_AsWideChar(value, p, end - p);
864 assert(0 <= size && size < end - p);
865 p += size + 1;
866 }
867
868 /* add trailing null character */
869 *p++ = L'\0';
870 assert(p == end);
871
872 error:
873 Py_XDECREF(keys);
874 Py_XDECREF(values);
875 return buffer;
876 }
877
878 static LPHANDLE
gethandlelist(PyObject * mapping,const char * name,Py_ssize_t * size)879 gethandlelist(PyObject *mapping, const char *name, Py_ssize_t *size)
880 {
881 LPHANDLE ret = NULL;
882 PyObject *value_fast = NULL;
883 PyObject *value;
884 Py_ssize_t i;
885
886 value = PyMapping_GetItemString(mapping, name);
887 if (!value) {
888 PyErr_Clear();
889 return NULL;
890 }
891
892 if (value == Py_None) {
893 goto cleanup;
894 }
895
896 value_fast = PySequence_Fast(value, "handle_list must be a sequence or None");
897 if (value_fast == NULL)
898 goto cleanup;
899
900 *size = PySequence_Fast_GET_SIZE(value_fast) * sizeof(HANDLE);
901
902 /* Passing an empty array causes CreateProcess to fail so just don't set it */
903 if (*size == 0) {
904 goto cleanup;
905 }
906
907 ret = PyMem_Malloc(*size);
908 if (ret == NULL)
909 goto cleanup;
910
911 for (i = 0; i < PySequence_Fast_GET_SIZE(value_fast); i++) {
912 ret[i] = PYNUM_TO_HANDLE(PySequence_Fast_GET_ITEM(value_fast, i));
913 if (ret[i] == (HANDLE)-1 && PyErr_Occurred()) {
914 PyMem_Free(ret);
915 ret = NULL;
916 goto cleanup;
917 }
918 }
919
920 cleanup:
921 Py_DECREF(value);
922 Py_XDECREF(value_fast);
923 return ret;
924 }
925
926 typedef struct {
927 LPPROC_THREAD_ATTRIBUTE_LIST attribute_list;
928 LPHANDLE handle_list;
929 } AttributeList;
930
931 static void
freeattributelist(AttributeList * attribute_list)932 freeattributelist(AttributeList *attribute_list)
933 {
934 if (attribute_list->attribute_list != NULL) {
935 DeleteProcThreadAttributeList(attribute_list->attribute_list);
936 PyMem_Free(attribute_list->attribute_list);
937 }
938
939 PyMem_Free(attribute_list->handle_list);
940
941 memset(attribute_list, 0, sizeof(*attribute_list));
942 }
943
944 static int
getattributelist(PyObject * obj,const char * name,AttributeList * attribute_list)945 getattributelist(PyObject *obj, const char *name, AttributeList *attribute_list)
946 {
947 int ret = 0;
948 DWORD err;
949 BOOL result;
950 PyObject *value;
951 Py_ssize_t handle_list_size;
952 DWORD attribute_count = 0;
953 SIZE_T attribute_list_size = 0;
954
955 value = PyObject_GetAttrString(obj, name);
956 if (!value) {
957 PyErr_Clear(); /* FIXME: propagate error? */
958 return 0;
959 }
960
961 if (value == Py_None) {
962 ret = 0;
963 goto cleanup;
964 }
965
966 if (!PyMapping_Check(value)) {
967 ret = -1;
968 PyErr_Format(PyExc_TypeError, "%s must be a mapping or None", name);
969 goto cleanup;
970 }
971
972 attribute_list->handle_list = gethandlelist(value, "handle_list", &handle_list_size);
973 if (attribute_list->handle_list == NULL && PyErr_Occurred()) {
974 ret = -1;
975 goto cleanup;
976 }
977
978 if (attribute_list->handle_list != NULL)
979 ++attribute_count;
980
981 /* Get how many bytes we need for the attribute list */
982 result = InitializeProcThreadAttributeList(NULL, attribute_count, 0, &attribute_list_size);
983 if (result || GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
984 ret = -1;
985 PyErr_SetFromWindowsErr(GetLastError());
986 goto cleanup;
987 }
988
989 attribute_list->attribute_list = PyMem_Malloc(attribute_list_size);
990 if (attribute_list->attribute_list == NULL) {
991 ret = -1;
992 goto cleanup;
993 }
994
995 result = InitializeProcThreadAttributeList(
996 attribute_list->attribute_list,
997 attribute_count,
998 0,
999 &attribute_list_size);
1000 if (!result) {
1001 err = GetLastError();
1002
1003 /* So that we won't call DeleteProcThreadAttributeList */
1004 PyMem_Free(attribute_list->attribute_list);
1005 attribute_list->attribute_list = NULL;
1006
1007 ret = -1;
1008 PyErr_SetFromWindowsErr(err);
1009 goto cleanup;
1010 }
1011
1012 if (attribute_list->handle_list != NULL) {
1013 result = UpdateProcThreadAttribute(
1014 attribute_list->attribute_list,
1015 0,
1016 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
1017 attribute_list->handle_list,
1018 handle_list_size,
1019 NULL,
1020 NULL);
1021 if (!result) {
1022 ret = -1;
1023 PyErr_SetFromWindowsErr(GetLastError());
1024 goto cleanup;
1025 }
1026 }
1027
1028 cleanup:
1029 Py_DECREF(value);
1030
1031 if (ret < 0)
1032 freeattributelist(attribute_list);
1033
1034 return ret;
1035 }
1036
1037 /*[clinic input]
1038 _winapi.CreateProcess
1039
1040 application_name: Py_UNICODE(accept={str, NoneType})
1041 command_line: object
1042 Can be str or None
1043 proc_attrs: object
1044 Ignored internally, can be None.
1045 thread_attrs: object
1046 Ignored internally, can be None.
1047 inherit_handles: BOOL
1048 creation_flags: DWORD
1049 env_mapping: object
1050 current_directory: Py_UNICODE(accept={str, NoneType})
1051 startup_info: object
1052 /
1053
1054 Create a new process and its primary thread.
1055
1056 The return value is a tuple of the process handle, thread handle,
1057 process ID, and thread ID.
1058 [clinic start generated code]*/
1059
1060 static PyObject *
_winapi_CreateProcess_impl(PyObject * module,const Py_UNICODE * application_name,PyObject * command_line,PyObject * proc_attrs,PyObject * thread_attrs,BOOL inherit_handles,DWORD creation_flags,PyObject * env_mapping,const Py_UNICODE * current_directory,PyObject * startup_info)1061 _winapi_CreateProcess_impl(PyObject *module,
1062 const Py_UNICODE *application_name,
1063 PyObject *command_line, PyObject *proc_attrs,
1064 PyObject *thread_attrs, BOOL inherit_handles,
1065 DWORD creation_flags, PyObject *env_mapping,
1066 const Py_UNICODE *current_directory,
1067 PyObject *startup_info)
1068 /*[clinic end generated code: output=9b2423a609230132 input=42ac293eaea03fc4]*/
1069 {
1070 PyObject *ret = NULL;
1071 BOOL result;
1072 PROCESS_INFORMATION pi;
1073 STARTUPINFOEXW si;
1074 wchar_t *wenvironment = NULL;
1075 wchar_t *command_line_copy = NULL;
1076 AttributeList attribute_list = {0};
1077
1078 if (PySys_Audit("_winapi.CreateProcess", "uuu", application_name,
1079 command_line, current_directory) < 0) {
1080 return NULL;
1081 }
1082
1083 PyInterpreterState *interp = PyInterpreterState_Get();
1084 const PyConfig *config = _PyInterpreterState_GetConfig(interp);
1085 if (config->_isolated_interpreter) {
1086 PyErr_SetString(PyExc_RuntimeError,
1087 "subprocess not supported for isolated subinterpreters");
1088 return NULL;
1089 }
1090
1091 ZeroMemory(&si, sizeof(si));
1092 si.StartupInfo.cb = sizeof(si);
1093
1094 /* note: we only support a small subset of all SI attributes */
1095 si.StartupInfo.dwFlags = getulong(startup_info, "dwFlags");
1096 si.StartupInfo.wShowWindow = (WORD)getulong(startup_info, "wShowWindow");
1097 si.StartupInfo.hStdInput = gethandle(startup_info, "hStdInput");
1098 si.StartupInfo.hStdOutput = gethandle(startup_info, "hStdOutput");
1099 si.StartupInfo.hStdError = gethandle(startup_info, "hStdError");
1100 if (PyErr_Occurred())
1101 goto cleanup;
1102
1103 if (env_mapping != Py_None) {
1104 wenvironment = getenvironment(env_mapping);
1105 if (wenvironment == NULL) {
1106 goto cleanup;
1107 }
1108 }
1109
1110 if (getattributelist(startup_info, "lpAttributeList", &attribute_list) < 0)
1111 goto cleanup;
1112
1113 si.lpAttributeList = attribute_list.attribute_list;
1114 if (PyUnicode_Check(command_line)) {
1115 command_line_copy = PyUnicode_AsWideCharString(command_line, NULL);
1116 if (command_line_copy == NULL) {
1117 goto cleanup;
1118 }
1119 }
1120 else if (command_line != Py_None) {
1121 PyErr_Format(PyExc_TypeError,
1122 "CreateProcess() argument 2 must be str or None, not %s",
1123 Py_TYPE(command_line)->tp_name);
1124 goto cleanup;
1125 }
1126
1127
1128 Py_BEGIN_ALLOW_THREADS
1129 result = CreateProcessW(application_name,
1130 command_line_copy,
1131 NULL,
1132 NULL,
1133 inherit_handles,
1134 creation_flags | EXTENDED_STARTUPINFO_PRESENT |
1135 CREATE_UNICODE_ENVIRONMENT,
1136 wenvironment,
1137 current_directory,
1138 (LPSTARTUPINFOW)&si,
1139 &pi);
1140 Py_END_ALLOW_THREADS
1141
1142 if (!result) {
1143 PyErr_SetFromWindowsErr(GetLastError());
1144 goto cleanup;
1145 }
1146
1147 ret = Py_BuildValue("NNkk",
1148 HANDLE_TO_PYNUM(pi.hProcess),
1149 HANDLE_TO_PYNUM(pi.hThread),
1150 pi.dwProcessId,
1151 pi.dwThreadId);
1152
1153 cleanup:
1154 PyMem_Free(command_line_copy);
1155 PyMem_Free(wenvironment);
1156 freeattributelist(&attribute_list);
1157
1158 return ret;
1159 }
1160
1161 /*[clinic input]
1162 _winapi.DuplicateHandle -> HANDLE
1163
1164 source_process_handle: HANDLE
1165 source_handle: HANDLE
1166 target_process_handle: HANDLE
1167 desired_access: DWORD
1168 inherit_handle: BOOL
1169 options: DWORD = 0
1170 /
1171
1172 Return a duplicate handle object.
1173
1174 The duplicate handle refers to the same object as the original
1175 handle. Therefore, any changes to the object are reflected
1176 through both handles.
1177 [clinic start generated code]*/
1178
1179 static HANDLE
_winapi_DuplicateHandle_impl(PyObject * module,HANDLE source_process_handle,HANDLE source_handle,HANDLE target_process_handle,DWORD desired_access,BOOL inherit_handle,DWORD options)1180 _winapi_DuplicateHandle_impl(PyObject *module, HANDLE source_process_handle,
1181 HANDLE source_handle,
1182 HANDLE target_process_handle,
1183 DWORD desired_access, BOOL inherit_handle,
1184 DWORD options)
1185 /*[clinic end generated code: output=ad9711397b5dcd4e input=b933e3f2356a8c12]*/
1186 {
1187 HANDLE target_handle;
1188 BOOL result;
1189
1190 Py_BEGIN_ALLOW_THREADS
1191 result = DuplicateHandle(
1192 source_process_handle,
1193 source_handle,
1194 target_process_handle,
1195 &target_handle,
1196 desired_access,
1197 inherit_handle,
1198 options
1199 );
1200 Py_END_ALLOW_THREADS
1201
1202 if (! result) {
1203 PyErr_SetFromWindowsErr(GetLastError());
1204 return INVALID_HANDLE_VALUE;
1205 }
1206
1207 return target_handle;
1208 }
1209
1210 /*[clinic input]
1211 _winapi.ExitProcess
1212
1213 ExitCode: UINT
1214 /
1215
1216 [clinic start generated code]*/
1217
1218 static PyObject *
_winapi_ExitProcess_impl(PyObject * module,UINT ExitCode)1219 _winapi_ExitProcess_impl(PyObject *module, UINT ExitCode)
1220 /*[clinic end generated code: output=a387deb651175301 input=4f05466a9406c558]*/
1221 {
1222 #if defined(Py_DEBUG)
1223 SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|
1224 SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
1225 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
1226 #endif
1227
1228 ExitProcess(ExitCode);
1229
1230 return NULL;
1231 }
1232
1233 /*[clinic input]
1234 _winapi.GetCurrentProcess -> HANDLE
1235
1236 Return a handle object for the current process.
1237 [clinic start generated code]*/
1238
1239 static HANDLE
_winapi_GetCurrentProcess_impl(PyObject * module)1240 _winapi_GetCurrentProcess_impl(PyObject *module)
1241 /*[clinic end generated code: output=ddeb4dd2ffadf344 input=b213403fd4b96b41]*/
1242 {
1243 return GetCurrentProcess();
1244 }
1245
1246 /*[clinic input]
1247 _winapi.GetExitCodeProcess -> DWORD
1248
1249 process: HANDLE
1250 /
1251
1252 Return the termination status of the specified process.
1253 [clinic start generated code]*/
1254
1255 static DWORD
_winapi_GetExitCodeProcess_impl(PyObject * module,HANDLE process)1256 _winapi_GetExitCodeProcess_impl(PyObject *module, HANDLE process)
1257 /*[clinic end generated code: output=b4620bdf2bccf36b input=61b6bfc7dc2ee374]*/
1258 {
1259 DWORD exit_code;
1260 BOOL result;
1261
1262 result = GetExitCodeProcess(process, &exit_code);
1263
1264 if (! result) {
1265 PyErr_SetFromWindowsErr(GetLastError());
1266 exit_code = PY_DWORD_MAX;
1267 }
1268
1269 return exit_code;
1270 }
1271
1272 /*[clinic input]
1273 _winapi.GetLastError -> DWORD
1274 [clinic start generated code]*/
1275
1276 static DWORD
_winapi_GetLastError_impl(PyObject * module)1277 _winapi_GetLastError_impl(PyObject *module)
1278 /*[clinic end generated code: output=8585b827cb1a92c5 input=62d47fb9bce038ba]*/
1279 {
1280 return GetLastError();
1281 }
1282
1283 /*[clinic input]
1284 _winapi.GetModuleFileName
1285
1286 module_handle: HMODULE
1287 /
1288
1289 Return the fully-qualified path for the file that contains module.
1290
1291 The module must have been loaded by the current process.
1292
1293 The module parameter should be a handle to the loaded module
1294 whose path is being requested. If this parameter is 0,
1295 GetModuleFileName retrieves the path of the executable file
1296 of the current process.
1297 [clinic start generated code]*/
1298
1299 static PyObject *
_winapi_GetModuleFileName_impl(PyObject * module,HMODULE module_handle)1300 _winapi_GetModuleFileName_impl(PyObject *module, HMODULE module_handle)
1301 /*[clinic end generated code: output=85b4b728c5160306 input=6d66ff7deca5d11f]*/
1302 {
1303 BOOL result;
1304 WCHAR filename[MAX_PATH];
1305
1306 Py_BEGIN_ALLOW_THREADS
1307 result = GetModuleFileNameW(module_handle, filename, MAX_PATH);
1308 filename[MAX_PATH-1] = '\0';
1309 Py_END_ALLOW_THREADS
1310
1311 if (! result)
1312 return PyErr_SetFromWindowsErr(GetLastError());
1313
1314 return PyUnicode_FromWideChar(filename, wcslen(filename));
1315 }
1316
1317 /*[clinic input]
1318 _winapi.GetStdHandle -> HANDLE
1319
1320 std_handle: DWORD
1321 One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE.
1322 /
1323
1324 Return a handle to the specified standard device.
1325
1326 The integer associated with the handle object is returned.
1327 [clinic start generated code]*/
1328
1329 static HANDLE
_winapi_GetStdHandle_impl(PyObject * module,DWORD std_handle)1330 _winapi_GetStdHandle_impl(PyObject *module, DWORD std_handle)
1331 /*[clinic end generated code: output=0e613001e73ab614 input=07016b06a2fc8826]*/
1332 {
1333 HANDLE handle;
1334
1335 Py_BEGIN_ALLOW_THREADS
1336 handle = GetStdHandle(std_handle);
1337 Py_END_ALLOW_THREADS
1338
1339 if (handle == INVALID_HANDLE_VALUE)
1340 PyErr_SetFromWindowsErr(GetLastError());
1341
1342 return handle;
1343 }
1344
1345 /*[clinic input]
1346 _winapi.GetVersion -> long
1347
1348 Return the version number of the current operating system.
1349 [clinic start generated code]*/
1350
1351 static long
_winapi_GetVersion_impl(PyObject * module)1352 _winapi_GetVersion_impl(PyObject *module)
1353 /*[clinic end generated code: output=e41f0db5a3b82682 input=e21dff8d0baeded2]*/
1354 /* Disable deprecation warnings about GetVersionEx as the result is
1355 being passed straight through to the caller, who is responsible for
1356 using it correctly. */
1357 #pragma warning(push)
1358 #pragma warning(disable:4996)
1359
1360 {
1361 return GetVersion();
1362 }
1363
1364 #pragma warning(pop)
1365
1366 /*[clinic input]
1367 _winapi.MapViewOfFile -> LPVOID
1368
1369 file_map: HANDLE
1370 desired_access: DWORD
1371 file_offset_high: DWORD
1372 file_offset_low: DWORD
1373 number_bytes: size_t
1374 /
1375 [clinic start generated code]*/
1376
1377 static LPVOID
_winapi_MapViewOfFile_impl(PyObject * module,HANDLE file_map,DWORD desired_access,DWORD file_offset_high,DWORD file_offset_low,size_t number_bytes)1378 _winapi_MapViewOfFile_impl(PyObject *module, HANDLE file_map,
1379 DWORD desired_access, DWORD file_offset_high,
1380 DWORD file_offset_low, size_t number_bytes)
1381 /*[clinic end generated code: output=f23b1ee4823663e3 input=177471073be1a103]*/
1382 {
1383 LPVOID address;
1384
1385 Py_BEGIN_ALLOW_THREADS
1386 address = MapViewOfFile(file_map, desired_access, file_offset_high,
1387 file_offset_low, number_bytes);
1388 Py_END_ALLOW_THREADS
1389
1390 if (address == NULL)
1391 PyErr_SetFromWindowsErr(0);
1392
1393 return address;
1394 }
1395
1396 /*[clinic input]
1397 _winapi.OpenFileMapping -> HANDLE
1398
1399 desired_access: DWORD
1400 inherit_handle: BOOL
1401 name: LPCWSTR
1402 /
1403 [clinic start generated code]*/
1404
1405 static HANDLE
_winapi_OpenFileMapping_impl(PyObject * module,DWORD desired_access,BOOL inherit_handle,LPCWSTR name)1406 _winapi_OpenFileMapping_impl(PyObject *module, DWORD desired_access,
1407 BOOL inherit_handle, LPCWSTR name)
1408 /*[clinic end generated code: output=08cc44def1cb11f1 input=131f2a405359de7f]*/
1409 {
1410 HANDLE handle;
1411
1412 Py_BEGIN_ALLOW_THREADS
1413 handle = OpenFileMappingW(desired_access, inherit_handle, name);
1414 Py_END_ALLOW_THREADS
1415
1416 if (handle == NULL) {
1417 PyObject *temp = PyUnicode_FromWideChar(name, -1);
1418 PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, temp);
1419 Py_XDECREF(temp);
1420 handle = INVALID_HANDLE_VALUE;
1421 }
1422
1423 return handle;
1424 }
1425
1426 /*[clinic input]
1427 _winapi.OpenProcess -> HANDLE
1428
1429 desired_access: DWORD
1430 inherit_handle: BOOL
1431 process_id: DWORD
1432 /
1433 [clinic start generated code]*/
1434
1435 static HANDLE
_winapi_OpenProcess_impl(PyObject * module,DWORD desired_access,BOOL inherit_handle,DWORD process_id)1436 _winapi_OpenProcess_impl(PyObject *module, DWORD desired_access,
1437 BOOL inherit_handle, DWORD process_id)
1438 /*[clinic end generated code: output=b42b6b81ea5a0fc3 input=ec98c4cf4ea2ec36]*/
1439 {
1440 HANDLE handle;
1441
1442 if (PySys_Audit("_winapi.OpenProcess", "II",
1443 process_id, desired_access) < 0) {
1444 return INVALID_HANDLE_VALUE;
1445 }
1446
1447 Py_BEGIN_ALLOW_THREADS
1448 handle = OpenProcess(desired_access, inherit_handle, process_id);
1449 Py_END_ALLOW_THREADS
1450 if (handle == NULL) {
1451 PyErr_SetFromWindowsErr(GetLastError());
1452 handle = INVALID_HANDLE_VALUE;
1453 }
1454
1455 return handle;
1456 }
1457
1458 /*[clinic input]
1459 _winapi.PeekNamedPipe
1460
1461 handle: HANDLE
1462 size: int = 0
1463 /
1464 [clinic start generated code]*/
1465
1466 static PyObject *
_winapi_PeekNamedPipe_impl(PyObject * module,HANDLE handle,int size)1467 _winapi_PeekNamedPipe_impl(PyObject *module, HANDLE handle, int size)
1468 /*[clinic end generated code: output=d0c3e29e49d323dd input=c7aa53bfbce69d70]*/
1469 {
1470 PyObject *buf = NULL;
1471 DWORD nread, navail, nleft;
1472 BOOL ret;
1473
1474 if (size < 0) {
1475 PyErr_SetString(PyExc_ValueError, "negative size");
1476 return NULL;
1477 }
1478
1479 if (size) {
1480 buf = PyBytes_FromStringAndSize(NULL, size);
1481 if (!buf)
1482 return NULL;
1483 Py_BEGIN_ALLOW_THREADS
1484 ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread,
1485 &navail, &nleft);
1486 Py_END_ALLOW_THREADS
1487 if (!ret) {
1488 Py_DECREF(buf);
1489 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1490 }
1491 if (_PyBytes_Resize(&buf, nread))
1492 return NULL;
1493 return Py_BuildValue("NII", buf, navail, nleft);
1494 }
1495 else {
1496 Py_BEGIN_ALLOW_THREADS
1497 ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft);
1498 Py_END_ALLOW_THREADS
1499 if (!ret) {
1500 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1501 }
1502 return Py_BuildValue("II", navail, nleft);
1503 }
1504 }
1505
1506 /*[clinic input]
1507 _winapi.ReadFile
1508
1509 handle: HANDLE
1510 size: DWORD
1511 overlapped as use_overlapped: bool(accept={int}) = False
1512 [clinic start generated code]*/
1513
1514 static PyObject *
_winapi_ReadFile_impl(PyObject * module,HANDLE handle,DWORD size,int use_overlapped)1515 _winapi_ReadFile_impl(PyObject *module, HANDLE handle, DWORD size,
1516 int use_overlapped)
1517 /*[clinic end generated code: output=d3d5b44a8201b944 input=08c439d03a11aac5]*/
1518 {
1519 DWORD nread;
1520 PyObject *buf;
1521 BOOL ret;
1522 DWORD err;
1523 OverlappedObject *overlapped = NULL;
1524
1525 buf = PyBytes_FromStringAndSize(NULL, size);
1526 if (!buf)
1527 return NULL;
1528 if (use_overlapped) {
1529 overlapped = new_overlapped(handle);
1530 if (!overlapped) {
1531 Py_DECREF(buf);
1532 return NULL;
1533 }
1534 /* Steals reference to buf */
1535 overlapped->read_buffer = buf;
1536 }
1537
1538 Py_BEGIN_ALLOW_THREADS
1539 ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread,
1540 overlapped ? &overlapped->overlapped : NULL);
1541 Py_END_ALLOW_THREADS
1542
1543 err = ret ? 0 : GetLastError();
1544
1545 if (overlapped) {
1546 if (!ret) {
1547 if (err == ERROR_IO_PENDING)
1548 overlapped->pending = 1;
1549 else if (err != ERROR_MORE_DATA) {
1550 Py_DECREF(overlapped);
1551 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1552 }
1553 }
1554 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1555 }
1556
1557 if (!ret && err != ERROR_MORE_DATA) {
1558 Py_DECREF(buf);
1559 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1560 }
1561 if (_PyBytes_Resize(&buf, nread))
1562 return NULL;
1563 return Py_BuildValue("NI", buf, err);
1564 }
1565
1566 /*[clinic input]
1567 _winapi.SetNamedPipeHandleState
1568
1569 named_pipe: HANDLE
1570 mode: object
1571 max_collection_count: object
1572 collect_data_timeout: object
1573 /
1574 [clinic start generated code]*/
1575
1576 static PyObject *
_winapi_SetNamedPipeHandleState_impl(PyObject * module,HANDLE named_pipe,PyObject * mode,PyObject * max_collection_count,PyObject * collect_data_timeout)1577 _winapi_SetNamedPipeHandleState_impl(PyObject *module, HANDLE named_pipe,
1578 PyObject *mode,
1579 PyObject *max_collection_count,
1580 PyObject *collect_data_timeout)
1581 /*[clinic end generated code: output=f2129d222cbfa095 input=9142d72163d0faa6]*/
1582 {
1583 PyObject *oArgs[3] = {mode, max_collection_count, collect_data_timeout};
1584 DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL};
1585 int i;
1586 BOOL b;
1587
1588 for (i = 0 ; i < 3 ; i++) {
1589 if (oArgs[i] != Py_None) {
1590 dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]);
1591 if (PyErr_Occurred())
1592 return NULL;
1593 pArgs[i] = &dwArgs[i];
1594 }
1595 }
1596
1597 Py_BEGIN_ALLOW_THREADS
1598 b = SetNamedPipeHandleState(named_pipe, pArgs[0], pArgs[1], pArgs[2]);
1599 Py_END_ALLOW_THREADS
1600
1601 if (!b)
1602 return PyErr_SetFromWindowsErr(0);
1603
1604 Py_RETURN_NONE;
1605 }
1606
1607
1608 /*[clinic input]
1609 _winapi.TerminateProcess
1610
1611 handle: HANDLE
1612 exit_code: UINT
1613 /
1614
1615 Terminate the specified process and all of its threads.
1616 [clinic start generated code]*/
1617
1618 static PyObject *
_winapi_TerminateProcess_impl(PyObject * module,HANDLE handle,UINT exit_code)1619 _winapi_TerminateProcess_impl(PyObject *module, HANDLE handle,
1620 UINT exit_code)
1621 /*[clinic end generated code: output=f4e99ac3f0b1f34a input=d6bc0aa1ee3bb4df]*/
1622 {
1623 BOOL result;
1624
1625 if (PySys_Audit("_winapi.TerminateProcess", "nI",
1626 (Py_ssize_t)handle, exit_code) < 0) {
1627 return NULL;
1628 }
1629
1630 result = TerminateProcess(handle, exit_code);
1631
1632 if (! result)
1633 return PyErr_SetFromWindowsErr(GetLastError());
1634
1635 Py_RETURN_NONE;
1636 }
1637
1638 /*[clinic input]
1639 _winapi.VirtualQuerySize -> size_t
1640
1641 address: LPCVOID
1642 /
1643 [clinic start generated code]*/
1644
1645 static size_t
_winapi_VirtualQuerySize_impl(PyObject * module,LPCVOID address)1646 _winapi_VirtualQuerySize_impl(PyObject *module, LPCVOID address)
1647 /*[clinic end generated code: output=40c8e0ff5ec964df input=6b784a69755d0bb6]*/
1648 {
1649 SIZE_T size_of_buf;
1650 MEMORY_BASIC_INFORMATION mem_basic_info;
1651 SIZE_T region_size;
1652
1653 Py_BEGIN_ALLOW_THREADS
1654 size_of_buf = VirtualQuery(address, &mem_basic_info, sizeof(mem_basic_info));
1655 Py_END_ALLOW_THREADS
1656
1657 if (size_of_buf == 0)
1658 PyErr_SetFromWindowsErr(0);
1659
1660 region_size = mem_basic_info.RegionSize;
1661 return region_size;
1662 }
1663
1664 /*[clinic input]
1665 _winapi.WaitNamedPipe
1666
1667 name: LPCTSTR
1668 timeout: DWORD
1669 /
1670 [clinic start generated code]*/
1671
1672 static PyObject *
_winapi_WaitNamedPipe_impl(PyObject * module,LPCTSTR name,DWORD timeout)1673 _winapi_WaitNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD timeout)
1674 /*[clinic end generated code: output=c2866f4439b1fe38 input=36fc781291b1862c]*/
1675 {
1676 BOOL success;
1677
1678 Py_BEGIN_ALLOW_THREADS
1679 success = WaitNamedPipe(name, timeout);
1680 Py_END_ALLOW_THREADS
1681
1682 if (!success)
1683 return PyErr_SetFromWindowsErr(0);
1684
1685 Py_RETURN_NONE;
1686 }
1687
1688 /*[clinic input]
1689 _winapi.WaitForMultipleObjects
1690
1691 handle_seq: object
1692 wait_flag: BOOL
1693 milliseconds: DWORD(c_default='INFINITE') = _winapi.INFINITE
1694 /
1695 [clinic start generated code]*/
1696
1697 static PyObject *
_winapi_WaitForMultipleObjects_impl(PyObject * module,PyObject * handle_seq,BOOL wait_flag,DWORD milliseconds)1698 _winapi_WaitForMultipleObjects_impl(PyObject *module, PyObject *handle_seq,
1699 BOOL wait_flag, DWORD milliseconds)
1700 /*[clinic end generated code: output=295e3f00b8e45899 input=36f76ca057cd28a0]*/
1701 {
1702 DWORD result;
1703 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
1704 HANDLE sigint_event = NULL;
1705 Py_ssize_t nhandles, i;
1706
1707 if (!PySequence_Check(handle_seq)) {
1708 PyErr_Format(PyExc_TypeError,
1709 "sequence type expected, got '%s'",
1710 Py_TYPE(handle_seq)->tp_name);
1711 return NULL;
1712 }
1713 nhandles = PySequence_Length(handle_seq);
1714 if (nhandles == -1)
1715 return NULL;
1716 if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS - 1) {
1717 PyErr_Format(PyExc_ValueError,
1718 "need at most %zd handles, got a sequence of length %zd",
1719 MAXIMUM_WAIT_OBJECTS - 1, nhandles);
1720 return NULL;
1721 }
1722 for (i = 0; i < nhandles; i++) {
1723 HANDLE h;
1724 PyObject *v = PySequence_GetItem(handle_seq, i);
1725 if (v == NULL)
1726 return NULL;
1727 if (!PyArg_Parse(v, F_HANDLE, &h)) {
1728 Py_DECREF(v);
1729 return NULL;
1730 }
1731 handles[i] = h;
1732 Py_DECREF(v);
1733 }
1734 /* If this is the main thread then make the wait interruptible
1735 by Ctrl-C unless we are waiting for *all* handles */
1736 if (!wait_flag && _PyOS_IsMainThread()) {
1737 sigint_event = _PyOS_SigintEvent();
1738 assert(sigint_event != NULL);
1739 handles[nhandles++] = sigint_event;
1740 }
1741
1742 Py_BEGIN_ALLOW_THREADS
1743 if (sigint_event != NULL)
1744 ResetEvent(sigint_event);
1745 result = WaitForMultipleObjects((DWORD) nhandles, handles,
1746 wait_flag, milliseconds);
1747 Py_END_ALLOW_THREADS
1748
1749 if (result == WAIT_FAILED)
1750 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1751 else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) {
1752 errno = EINTR;
1753 return PyErr_SetFromErrno(PyExc_OSError);
1754 }
1755
1756 return PyLong_FromLong((int) result);
1757 }
1758
1759 /*[clinic input]
1760 _winapi.WaitForSingleObject -> long
1761
1762 handle: HANDLE
1763 milliseconds: DWORD
1764 /
1765
1766 Wait for a single object.
1767
1768 Wait until the specified object is in the signaled state or
1769 the time-out interval elapses. The timeout value is specified
1770 in milliseconds.
1771 [clinic start generated code]*/
1772
1773 static long
_winapi_WaitForSingleObject_impl(PyObject * module,HANDLE handle,DWORD milliseconds)1774 _winapi_WaitForSingleObject_impl(PyObject *module, HANDLE handle,
1775 DWORD milliseconds)
1776 /*[clinic end generated code: output=3c4715d8f1b39859 input=443d1ab076edc7b1]*/
1777 {
1778 DWORD result;
1779
1780 Py_BEGIN_ALLOW_THREADS
1781 result = WaitForSingleObject(handle, milliseconds);
1782 Py_END_ALLOW_THREADS
1783
1784 if (result == WAIT_FAILED) {
1785 PyErr_SetFromWindowsErr(GetLastError());
1786 return -1;
1787 }
1788
1789 return result;
1790 }
1791
1792 /*[clinic input]
1793 _winapi.WriteFile
1794
1795 handle: HANDLE
1796 buffer: object
1797 overlapped as use_overlapped: bool(accept={int}) = False
1798 [clinic start generated code]*/
1799
1800 static PyObject *
_winapi_WriteFile_impl(PyObject * module,HANDLE handle,PyObject * buffer,int use_overlapped)1801 _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
1802 int use_overlapped)
1803 /*[clinic end generated code: output=2ca80f6bf3fa92e3 input=11eae2a03aa32731]*/
1804 {
1805 Py_buffer _buf, *buf;
1806 DWORD len, written;
1807 BOOL ret;
1808 DWORD err;
1809 OverlappedObject *overlapped = NULL;
1810
1811 if (use_overlapped) {
1812 overlapped = new_overlapped(handle);
1813 if (!overlapped)
1814 return NULL;
1815 buf = &overlapped->write_buffer;
1816 }
1817 else
1818 buf = &_buf;
1819
1820 if (!PyArg_Parse(buffer, "y*", buf)) {
1821 Py_XDECREF(overlapped);
1822 return NULL;
1823 }
1824
1825 Py_BEGIN_ALLOW_THREADS
1826 len = (DWORD)Py_MIN(buf->len, PY_DWORD_MAX);
1827 ret = WriteFile(handle, buf->buf, len, &written,
1828 overlapped ? &overlapped->overlapped : NULL);
1829 Py_END_ALLOW_THREADS
1830
1831 err = ret ? 0 : GetLastError();
1832
1833 if (overlapped) {
1834 if (!ret) {
1835 if (err == ERROR_IO_PENDING)
1836 overlapped->pending = 1;
1837 else {
1838 Py_DECREF(overlapped);
1839 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1840 }
1841 }
1842 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1843 }
1844
1845 PyBuffer_Release(buf);
1846 if (!ret)
1847 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1848 return Py_BuildValue("II", written, err);
1849 }
1850
1851 /*[clinic input]
1852 _winapi.GetACP
1853
1854 Get the current Windows ANSI code page identifier.
1855 [clinic start generated code]*/
1856
1857 static PyObject *
_winapi_GetACP_impl(PyObject * module)1858 _winapi_GetACP_impl(PyObject *module)
1859 /*[clinic end generated code: output=f7ee24bf705dbb88 input=1433c96d03a05229]*/
1860 {
1861 return PyLong_FromUnsignedLong(GetACP());
1862 }
1863
1864 /*[clinic input]
1865 _winapi.GetFileType -> DWORD
1866
1867 handle: HANDLE
1868 [clinic start generated code]*/
1869
1870 static DWORD
_winapi_GetFileType_impl(PyObject * module,HANDLE handle)1871 _winapi_GetFileType_impl(PyObject *module, HANDLE handle)
1872 /*[clinic end generated code: output=92b8466ac76ecc17 input=0058366bc40bbfbf]*/
1873 {
1874 DWORD result;
1875
1876 Py_BEGIN_ALLOW_THREADS
1877 result = GetFileType(handle);
1878 Py_END_ALLOW_THREADS
1879
1880 if (result == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR) {
1881 PyErr_SetFromWindowsErr(0);
1882 return -1;
1883 }
1884
1885 return result;
1886 }
1887
1888
1889 static PyMethodDef winapi_functions[] = {
1890 _WINAPI_CLOSEHANDLE_METHODDEF
1891 _WINAPI_CONNECTNAMEDPIPE_METHODDEF
1892 _WINAPI_CREATEFILE_METHODDEF
1893 _WINAPI_CREATEFILEMAPPING_METHODDEF
1894 _WINAPI_CREATENAMEDPIPE_METHODDEF
1895 _WINAPI_CREATEPIPE_METHODDEF
1896 _WINAPI_CREATEPROCESS_METHODDEF
1897 _WINAPI_CREATEJUNCTION_METHODDEF
1898 _WINAPI_DUPLICATEHANDLE_METHODDEF
1899 _WINAPI_EXITPROCESS_METHODDEF
1900 _WINAPI_GETCURRENTPROCESS_METHODDEF
1901 _WINAPI_GETEXITCODEPROCESS_METHODDEF
1902 _WINAPI_GETLASTERROR_METHODDEF
1903 _WINAPI_GETMODULEFILENAME_METHODDEF
1904 _WINAPI_GETSTDHANDLE_METHODDEF
1905 _WINAPI_GETVERSION_METHODDEF
1906 _WINAPI_MAPVIEWOFFILE_METHODDEF
1907 _WINAPI_OPENFILEMAPPING_METHODDEF
1908 _WINAPI_OPENPROCESS_METHODDEF
1909 _WINAPI_PEEKNAMEDPIPE_METHODDEF
1910 _WINAPI_READFILE_METHODDEF
1911 _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF
1912 _WINAPI_TERMINATEPROCESS_METHODDEF
1913 _WINAPI_VIRTUALQUERYSIZE_METHODDEF
1914 _WINAPI_WAITNAMEDPIPE_METHODDEF
1915 _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF
1916 _WINAPI_WAITFORSINGLEOBJECT_METHODDEF
1917 _WINAPI_WRITEFILE_METHODDEF
1918 _WINAPI_GETACP_METHODDEF
1919 _WINAPI_GETFILETYPE_METHODDEF
1920 {NULL, NULL}
1921 };
1922
1923 static struct PyModuleDef winapi_module = {
1924 PyModuleDef_HEAD_INIT,
1925 "_winapi",
1926 NULL,
1927 -1,
1928 winapi_functions,
1929 NULL,
1930 NULL,
1931 NULL,
1932 NULL
1933 };
1934
1935 #define WINAPI_CONSTANT(fmt, con) \
1936 PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1937
1938 PyMODINIT_FUNC
PyInit__winapi(void)1939 PyInit__winapi(void)
1940 {
1941 PyObject *d;
1942 PyObject *m;
1943
1944 if (PyType_Ready(&OverlappedType) < 0)
1945 return NULL;
1946
1947 m = PyModule_Create(&winapi_module);
1948 if (m == NULL)
1949 return NULL;
1950 d = PyModule_GetDict(m);
1951
1952 PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType);
1953
1954 /* constants */
1955 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
1956 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP);
1957 WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS);
1958 WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE);
1959 WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
1960 WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
1961 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1962 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1963 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1964 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
1965 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1966 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1967 WINAPI_CONSTANT(F_DWORD, ERROR_NO_DATA);
1968 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
1969 WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
1970 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
1971 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
1972 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
1973 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE);
1974 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
1975 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ);
1976 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE);
1977 WINAPI_CONSTANT(F_DWORD, FILE_MAP_ALL_ACCESS);
1978 WINAPI_CONSTANT(F_DWORD, FILE_MAP_COPY);
1979 WINAPI_CONSTANT(F_DWORD, FILE_MAP_EXECUTE);
1980 WINAPI_CONSTANT(F_DWORD, FILE_MAP_READ);
1981 WINAPI_CONSTANT(F_DWORD, FILE_MAP_WRITE);
1982 WINAPI_CONSTANT(F_DWORD, GENERIC_READ);
1983 WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE);
1984 WINAPI_CONSTANT(F_DWORD, INFINITE);
1985 WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE);
1986 WINAPI_CONSTANT(F_DWORD, MEM_COMMIT);
1987 WINAPI_CONSTANT(F_DWORD, MEM_FREE);
1988 WINAPI_CONSTANT(F_DWORD, MEM_IMAGE);
1989 WINAPI_CONSTANT(F_DWORD, MEM_MAPPED);
1990 WINAPI_CONSTANT(F_DWORD, MEM_PRIVATE);
1991 WINAPI_CONSTANT(F_DWORD, MEM_RESERVE);
1992 WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
1993 WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING);
1994 WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE);
1995 WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_READ);
1996 WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_READWRITE);
1997 WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_WRITECOPY);
1998 WINAPI_CONSTANT(F_DWORD, PAGE_GUARD);
1999 WINAPI_CONSTANT(F_DWORD, PAGE_NOACCESS);
2000 WINAPI_CONSTANT(F_DWORD, PAGE_NOCACHE);
2001 WINAPI_CONSTANT(F_DWORD, PAGE_READONLY);
2002 WINAPI_CONSTANT(F_DWORD, PAGE_READWRITE);
2003 WINAPI_CONSTANT(F_DWORD, PAGE_WRITECOMBINE);
2004 WINAPI_CONSTANT(F_DWORD, PAGE_WRITECOPY);
2005 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
2006 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
2007 WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
2008 WINAPI_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE);
2009 WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES);
2010 WINAPI_CONSTANT(F_DWORD, PIPE_WAIT);
2011 WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
2012 WINAPI_CONSTANT(F_DWORD, SYNCHRONIZE);
2013 WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE);
2014 WINAPI_CONSTANT(F_DWORD, SEC_COMMIT);
2015 WINAPI_CONSTANT(F_DWORD, SEC_IMAGE);
2016 WINAPI_CONSTANT(F_DWORD, SEC_LARGE_PAGES);
2017 WINAPI_CONSTANT(F_DWORD, SEC_NOCACHE);
2018 WINAPI_CONSTANT(F_DWORD, SEC_RESERVE);
2019 WINAPI_CONSTANT(F_DWORD, SEC_WRITECOMBINE);
2020 WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW);
2021 WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES);
2022 WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE);
2023 WINAPI_CONSTANT(F_DWORD, STD_OUTPUT_HANDLE);
2024 WINAPI_CONSTANT(F_DWORD, STD_ERROR_HANDLE);
2025 WINAPI_CONSTANT(F_DWORD, STILL_ACTIVE);
2026 WINAPI_CONSTANT(F_DWORD, SW_HIDE);
2027 WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0);
2028 WINAPI_CONSTANT(F_DWORD, WAIT_ABANDONED_0);
2029 WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT);
2030
2031 WINAPI_CONSTANT(F_DWORD, ABOVE_NORMAL_PRIORITY_CLASS);
2032 WINAPI_CONSTANT(F_DWORD, BELOW_NORMAL_PRIORITY_CLASS);
2033 WINAPI_CONSTANT(F_DWORD, HIGH_PRIORITY_CLASS);
2034 WINAPI_CONSTANT(F_DWORD, IDLE_PRIORITY_CLASS);
2035 WINAPI_CONSTANT(F_DWORD, NORMAL_PRIORITY_CLASS);
2036 WINAPI_CONSTANT(F_DWORD, REALTIME_PRIORITY_CLASS);
2037
2038 WINAPI_CONSTANT(F_DWORD, CREATE_NO_WINDOW);
2039 WINAPI_CONSTANT(F_DWORD, DETACHED_PROCESS);
2040 WINAPI_CONSTANT(F_DWORD, CREATE_DEFAULT_ERROR_MODE);
2041 WINAPI_CONSTANT(F_DWORD, CREATE_BREAKAWAY_FROM_JOB);
2042
2043 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_UNKNOWN);
2044 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_DISK);
2045 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_CHAR);
2046 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_PIPE);
2047 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_REMOTE);
2048
2049 WINAPI_CONSTANT("i", NULL);
2050
2051 return m;
2052 }
2053