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"
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_RawMalloc(rdb_size);
607 if (rdb == NULL)
608 goto cleanup;
609
610 memset(rdb, 0, rdb_size);
611 rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
612 rdb->ReparseDataLength = rdb_size - _Py_REPARSE_DATA_BUFFER_HEADER_SIZE;
613 rdb->MountPointReparseBuffer.SubstituteNameOffset = 0;
614 rdb->MountPointReparseBuffer.SubstituteNameLength =
615 (prefix_len + print_len) * sizeof(WCHAR);
616 rdb->MountPointReparseBuffer.PrintNameOffset =
617 rdb->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
618 rdb->MountPointReparseBuffer.PrintNameLength = print_len * sizeof(WCHAR);
619
620 /* Store the full native path of link target at the substitute name
621 offset (0). */
622 wcscpy(rdb->MountPointReparseBuffer.PathBuffer, L"\\??\\");
623 if (GetFullPathNameW(src_path, print_len + 1,
624 rdb->MountPointReparseBuffer.PathBuffer + prefix_len,
625 NULL) == 0)
626 goto cleanup;
627
628 /* Copy everything but the native prefix to the print name offset. */
629 wcscpy(rdb->MountPointReparseBuffer.PathBuffer +
630 prefix_len + print_len + 1,
631 rdb->MountPointReparseBuffer.PathBuffer + prefix_len);
632
633 /* Create a directory for the junction point. */
634 if (!CreateDirectoryW(dst_path, NULL))
635 goto cleanup;
636
637 junction = CreateFileW(dst_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
638 OPEN_EXISTING,
639 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
640 if (junction == INVALID_HANDLE_VALUE)
641 goto cleanup;
642
643 /* Make the directory entry a junction point. */
644 if (!DeviceIoControl(junction, FSCTL_SET_REPARSE_POINT, rdb, rdb_size,
645 NULL, 0, &ret, NULL))
646 goto cleanup;
647
648 cleanup:
649 ret = GetLastError();
650
651 CloseHandle(token);
652 CloseHandle(junction);
653 PyMem_RawFree(rdb);
654
655 if (ret != 0)
656 return PyErr_SetFromWindowsErr(ret);
657
658 Py_RETURN_NONE;
659 }
660
661 /*[clinic input]
662 _winapi.CreateNamedPipe -> HANDLE
663
664 name: LPCTSTR
665 open_mode: DWORD
666 pipe_mode: DWORD
667 max_instances: DWORD
668 out_buffer_size: DWORD
669 in_buffer_size: DWORD
670 default_timeout: DWORD
671 security_attributes: LPSECURITY_ATTRIBUTES
672 /
673 [clinic start generated code]*/
674
675 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)676 _winapi_CreateNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD open_mode,
677 DWORD pipe_mode, DWORD max_instances,
678 DWORD out_buffer_size, DWORD in_buffer_size,
679 DWORD default_timeout,
680 LPSECURITY_ATTRIBUTES security_attributes)
681 /*[clinic end generated code: output=80f8c07346a94fbc input=5a73530b84d8bc37]*/
682 {
683 HANDLE handle;
684
685 if (PySys_Audit("_winapi.CreateNamedPipe", "uII",
686 name, open_mode, pipe_mode) < 0) {
687 return INVALID_HANDLE_VALUE;
688 }
689
690 Py_BEGIN_ALLOW_THREADS
691 handle = CreateNamedPipe(name, open_mode, pipe_mode,
692 max_instances, out_buffer_size,
693 in_buffer_size, default_timeout,
694 security_attributes);
695 Py_END_ALLOW_THREADS
696
697 if (handle == INVALID_HANDLE_VALUE)
698 PyErr_SetFromWindowsErr(0);
699
700 return handle;
701 }
702
703 /*[clinic input]
704 _winapi.CreatePipe
705
706 pipe_attrs: object
707 Ignored internally, can be None.
708 size: DWORD
709 /
710
711 Create an anonymous pipe.
712
713 Returns a 2-tuple of handles, to the read and write ends of the pipe.
714 [clinic start generated code]*/
715
716 static PyObject *
_winapi_CreatePipe_impl(PyObject * module,PyObject * pipe_attrs,DWORD size)717 _winapi_CreatePipe_impl(PyObject *module, PyObject *pipe_attrs, DWORD size)
718 /*[clinic end generated code: output=1c4411d8699f0925 input=c4f2cfa56ef68d90]*/
719 {
720 HANDLE read_pipe;
721 HANDLE write_pipe;
722 BOOL result;
723
724 if (PySys_Audit("_winapi.CreatePipe", NULL) < 0) {
725 return NULL;
726 }
727
728 Py_BEGIN_ALLOW_THREADS
729 result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
730 Py_END_ALLOW_THREADS
731
732 if (! result)
733 return PyErr_SetFromWindowsErr(GetLastError());
734
735 return Py_BuildValue(
736 "NN", HANDLE_TO_PYNUM(read_pipe), HANDLE_TO_PYNUM(write_pipe));
737 }
738
739 /* helpers for createprocess */
740
741 static unsigned long
getulong(PyObject * obj,const char * name)742 getulong(PyObject* obj, const char* name)
743 {
744 PyObject* value;
745 unsigned long ret;
746
747 value = PyObject_GetAttrString(obj, name);
748 if (! value) {
749 PyErr_Clear(); /* FIXME: propagate error? */
750 return 0;
751 }
752 ret = PyLong_AsUnsignedLong(value);
753 Py_DECREF(value);
754 return ret;
755 }
756
757 static HANDLE
gethandle(PyObject * obj,const char * name)758 gethandle(PyObject* obj, const char* name)
759 {
760 PyObject* value;
761 HANDLE ret;
762
763 value = PyObject_GetAttrString(obj, name);
764 if (! value) {
765 PyErr_Clear(); /* FIXME: propagate error? */
766 return NULL;
767 }
768 if (value == Py_None)
769 ret = NULL;
770 else
771 ret = PYNUM_TO_HANDLE(value);
772 Py_DECREF(value);
773 return ret;
774 }
775
776 static wchar_t *
getenvironment(PyObject * environment)777 getenvironment(PyObject* environment)
778 {
779 Py_ssize_t i, envsize, totalsize;
780 wchar_t *buffer = NULL, *p, *end;
781 PyObject *keys, *values;
782
783 /* convert environment dictionary to windows environment string */
784 if (! PyMapping_Check(environment)) {
785 PyErr_SetString(
786 PyExc_TypeError, "environment must be dictionary or None");
787 return NULL;
788 }
789
790 keys = PyMapping_Keys(environment);
791 if (!keys) {
792 return NULL;
793 }
794 values = PyMapping_Values(environment);
795 if (!values) {
796 goto error;
797 }
798
799 envsize = PyList_GET_SIZE(keys);
800 if (PyList_GET_SIZE(values) != envsize) {
801 PyErr_SetString(PyExc_RuntimeError,
802 "environment changed size during iteration");
803 goto error;
804 }
805
806 totalsize = 1; /* trailing null character */
807 for (i = 0; i < envsize; i++) {
808 PyObject* key = PyList_GET_ITEM(keys, i);
809 PyObject* value = PyList_GET_ITEM(values, i);
810 Py_ssize_t size;
811
812 if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
813 PyErr_SetString(PyExc_TypeError,
814 "environment can only contain strings");
815 goto error;
816 }
817 if (PyUnicode_FindChar(key, '\0', 0, PyUnicode_GET_LENGTH(key), 1) != -1 ||
818 PyUnicode_FindChar(value, '\0', 0, PyUnicode_GET_LENGTH(value), 1) != -1)
819 {
820 PyErr_SetString(PyExc_ValueError, "embedded null character");
821 goto error;
822 }
823 /* Search from index 1 because on Windows starting '=' is allowed for
824 defining hidden environment variables. */
825 if (PyUnicode_GET_LENGTH(key) == 0 ||
826 PyUnicode_FindChar(key, '=', 1, PyUnicode_GET_LENGTH(key), 1) != -1)
827 {
828 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
829 goto error;
830 }
831
832 size = PyUnicode_AsWideChar(key, NULL, 0);
833 assert(size > 1);
834 if (totalsize > PY_SSIZE_T_MAX - size) {
835 PyErr_SetString(PyExc_OverflowError, "environment too long");
836 goto error;
837 }
838 totalsize += size; /* including '=' */
839
840 size = PyUnicode_AsWideChar(value, NULL, 0);
841 assert(size > 0);
842 if (totalsize > PY_SSIZE_T_MAX - size) {
843 PyErr_SetString(PyExc_OverflowError, "environment too long");
844 goto error;
845 }
846 totalsize += size; /* including trailing '\0' */
847 }
848
849 buffer = PyMem_NEW(wchar_t, totalsize);
850 if (! buffer) {
851 PyErr_NoMemory();
852 goto error;
853 }
854 p = buffer;
855 end = buffer + totalsize;
856
857 for (i = 0; i < envsize; i++) {
858 PyObject* key = PyList_GET_ITEM(keys, i);
859 PyObject* value = PyList_GET_ITEM(values, i);
860 Py_ssize_t size = PyUnicode_AsWideChar(key, p, end - p);
861 assert(1 <= size && size < end - p);
862 p += size;
863 *p++ = L'=';
864 size = PyUnicode_AsWideChar(value, p, end - p);
865 assert(0 <= size && size < end - p);
866 p += size + 1;
867 }
868
869 /* add trailing null character */
870 *p++ = L'\0';
871 assert(p == end);
872
873 error:
874 Py_XDECREF(keys);
875 Py_XDECREF(values);
876 return buffer;
877 }
878
879 static LPHANDLE
gethandlelist(PyObject * mapping,const char * name,Py_ssize_t * size)880 gethandlelist(PyObject *mapping, const char *name, Py_ssize_t *size)
881 {
882 LPHANDLE ret = NULL;
883 PyObject *value_fast = NULL;
884 PyObject *value;
885 Py_ssize_t i;
886
887 value = PyMapping_GetItemString(mapping, name);
888 if (!value) {
889 PyErr_Clear();
890 return NULL;
891 }
892
893 if (value == Py_None) {
894 goto cleanup;
895 }
896
897 value_fast = PySequence_Fast(value, "handle_list must be a sequence or None");
898 if (value_fast == NULL)
899 goto cleanup;
900
901 *size = PySequence_Fast_GET_SIZE(value_fast) * sizeof(HANDLE);
902
903 /* Passing an empty array causes CreateProcess to fail so just don't set it */
904 if (*size == 0) {
905 goto cleanup;
906 }
907
908 ret = PyMem_Malloc(*size);
909 if (ret == NULL)
910 goto cleanup;
911
912 for (i = 0; i < PySequence_Fast_GET_SIZE(value_fast); i++) {
913 ret[i] = PYNUM_TO_HANDLE(PySequence_Fast_GET_ITEM(value_fast, i));
914 if (ret[i] == (HANDLE)-1 && PyErr_Occurred()) {
915 PyMem_Free(ret);
916 ret = NULL;
917 goto cleanup;
918 }
919 }
920
921 cleanup:
922 Py_DECREF(value);
923 Py_XDECREF(value_fast);
924 return ret;
925 }
926
927 typedef struct {
928 LPPROC_THREAD_ATTRIBUTE_LIST attribute_list;
929 LPHANDLE handle_list;
930 } AttributeList;
931
932 static void
freeattributelist(AttributeList * attribute_list)933 freeattributelist(AttributeList *attribute_list)
934 {
935 if (attribute_list->attribute_list != NULL) {
936 DeleteProcThreadAttributeList(attribute_list->attribute_list);
937 PyMem_Free(attribute_list->attribute_list);
938 }
939
940 PyMem_Free(attribute_list->handle_list);
941
942 memset(attribute_list, 0, sizeof(*attribute_list));
943 }
944
945 static int
getattributelist(PyObject * obj,const char * name,AttributeList * attribute_list)946 getattributelist(PyObject *obj, const char *name, AttributeList *attribute_list)
947 {
948 int ret = 0;
949 DWORD err;
950 BOOL result;
951 PyObject *value;
952 Py_ssize_t handle_list_size;
953 DWORD attribute_count = 0;
954 SIZE_T attribute_list_size = 0;
955
956 value = PyObject_GetAttrString(obj, name);
957 if (!value) {
958 PyErr_Clear(); /* FIXME: propagate error? */
959 return 0;
960 }
961
962 if (value == Py_None) {
963 ret = 0;
964 goto cleanup;
965 }
966
967 if (!PyMapping_Check(value)) {
968 ret = -1;
969 PyErr_Format(PyExc_TypeError, "%s must be a mapping or None", name);
970 goto cleanup;
971 }
972
973 attribute_list->handle_list = gethandlelist(value, "handle_list", &handle_list_size);
974 if (attribute_list->handle_list == NULL && PyErr_Occurred()) {
975 ret = -1;
976 goto cleanup;
977 }
978
979 if (attribute_list->handle_list != NULL)
980 ++attribute_count;
981
982 /* Get how many bytes we need for the attribute list */
983 result = InitializeProcThreadAttributeList(NULL, attribute_count, 0, &attribute_list_size);
984 if (result || GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
985 ret = -1;
986 PyErr_SetFromWindowsErr(GetLastError());
987 goto cleanup;
988 }
989
990 attribute_list->attribute_list = PyMem_Malloc(attribute_list_size);
991 if (attribute_list->attribute_list == NULL) {
992 ret = -1;
993 goto cleanup;
994 }
995
996 result = InitializeProcThreadAttributeList(
997 attribute_list->attribute_list,
998 attribute_count,
999 0,
1000 &attribute_list_size);
1001 if (!result) {
1002 err = GetLastError();
1003
1004 /* So that we won't call DeleteProcThreadAttributeList */
1005 PyMem_Free(attribute_list->attribute_list);
1006 attribute_list->attribute_list = NULL;
1007
1008 ret = -1;
1009 PyErr_SetFromWindowsErr(err);
1010 goto cleanup;
1011 }
1012
1013 if (attribute_list->handle_list != NULL) {
1014 result = UpdateProcThreadAttribute(
1015 attribute_list->attribute_list,
1016 0,
1017 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
1018 attribute_list->handle_list,
1019 handle_list_size,
1020 NULL,
1021 NULL);
1022 if (!result) {
1023 ret = -1;
1024 PyErr_SetFromWindowsErr(GetLastError());
1025 goto cleanup;
1026 }
1027 }
1028
1029 cleanup:
1030 Py_DECREF(value);
1031
1032 if (ret < 0)
1033 freeattributelist(attribute_list);
1034
1035 return ret;
1036 }
1037
1038 /*[clinic input]
1039 _winapi.CreateProcess
1040
1041 application_name: Py_UNICODE(accept={str, NoneType})
1042 command_line: object
1043 Can be str or None
1044 proc_attrs: object
1045 Ignored internally, can be None.
1046 thread_attrs: object
1047 Ignored internally, can be None.
1048 inherit_handles: BOOL
1049 creation_flags: DWORD
1050 env_mapping: object
1051 current_directory: Py_UNICODE(accept={str, NoneType})
1052 startup_info: object
1053 /
1054
1055 Create a new process and its primary thread.
1056
1057 The return value is a tuple of the process handle, thread handle,
1058 process ID, and thread ID.
1059 [clinic start generated code]*/
1060
1061 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)1062 _winapi_CreateProcess_impl(PyObject *module,
1063 const Py_UNICODE *application_name,
1064 PyObject *command_line, PyObject *proc_attrs,
1065 PyObject *thread_attrs, BOOL inherit_handles,
1066 DWORD creation_flags, PyObject *env_mapping,
1067 const Py_UNICODE *current_directory,
1068 PyObject *startup_info)
1069 /*[clinic end generated code: output=9b2423a609230132 input=42ac293eaea03fc4]*/
1070 {
1071 PyObject *ret = NULL;
1072 BOOL result;
1073 PROCESS_INFORMATION pi;
1074 STARTUPINFOEXW si;
1075 wchar_t *wenvironment = NULL;
1076 wchar_t *command_line_copy = NULL;
1077 AttributeList attribute_list = {0};
1078
1079 if (PySys_Audit("_winapi.CreateProcess", "uuu", application_name,
1080 command_line, current_directory) < 0) {
1081 return NULL;
1082 }
1083
1084 ZeroMemory(&si, sizeof(si));
1085 si.StartupInfo.cb = sizeof(si);
1086
1087 /* note: we only support a small subset of all SI attributes */
1088 si.StartupInfo.dwFlags = getulong(startup_info, "dwFlags");
1089 si.StartupInfo.wShowWindow = (WORD)getulong(startup_info, "wShowWindow");
1090 si.StartupInfo.hStdInput = gethandle(startup_info, "hStdInput");
1091 si.StartupInfo.hStdOutput = gethandle(startup_info, "hStdOutput");
1092 si.StartupInfo.hStdError = gethandle(startup_info, "hStdError");
1093 if (PyErr_Occurred())
1094 goto cleanup;
1095
1096 if (env_mapping != Py_None) {
1097 wenvironment = getenvironment(env_mapping);
1098 if (wenvironment == NULL) {
1099 goto cleanup;
1100 }
1101 }
1102
1103 if (getattributelist(startup_info, "lpAttributeList", &attribute_list) < 0)
1104 goto cleanup;
1105
1106 si.lpAttributeList = attribute_list.attribute_list;
1107 if (PyUnicode_Check(command_line)) {
1108 command_line_copy = PyUnicode_AsWideCharString(command_line, NULL);
1109 if (command_line_copy == NULL) {
1110 goto cleanup;
1111 }
1112 }
1113 else if (command_line != Py_None) {
1114 PyErr_Format(PyExc_TypeError,
1115 "CreateProcess() argument 2 must be str or None, not %s",
1116 Py_TYPE(command_line)->tp_name);
1117 goto cleanup;
1118 }
1119
1120
1121 Py_BEGIN_ALLOW_THREADS
1122 result = CreateProcessW(application_name,
1123 command_line_copy,
1124 NULL,
1125 NULL,
1126 inherit_handles,
1127 creation_flags | EXTENDED_STARTUPINFO_PRESENT |
1128 CREATE_UNICODE_ENVIRONMENT,
1129 wenvironment,
1130 current_directory,
1131 (LPSTARTUPINFOW)&si,
1132 &pi);
1133 Py_END_ALLOW_THREADS
1134
1135 if (!result) {
1136 PyErr_SetFromWindowsErr(GetLastError());
1137 goto cleanup;
1138 }
1139
1140 ret = Py_BuildValue("NNkk",
1141 HANDLE_TO_PYNUM(pi.hProcess),
1142 HANDLE_TO_PYNUM(pi.hThread),
1143 pi.dwProcessId,
1144 pi.dwThreadId);
1145
1146 cleanup:
1147 PyMem_Free(command_line_copy);
1148 PyMem_Free(wenvironment);
1149 freeattributelist(&attribute_list);
1150
1151 return ret;
1152 }
1153
1154 /*[clinic input]
1155 _winapi.DuplicateHandle -> HANDLE
1156
1157 source_process_handle: HANDLE
1158 source_handle: HANDLE
1159 target_process_handle: HANDLE
1160 desired_access: DWORD
1161 inherit_handle: BOOL
1162 options: DWORD = 0
1163 /
1164
1165 Return a duplicate handle object.
1166
1167 The duplicate handle refers to the same object as the original
1168 handle. Therefore, any changes to the object are reflected
1169 through both handles.
1170 [clinic start generated code]*/
1171
1172 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)1173 _winapi_DuplicateHandle_impl(PyObject *module, HANDLE source_process_handle,
1174 HANDLE source_handle,
1175 HANDLE target_process_handle,
1176 DWORD desired_access, BOOL inherit_handle,
1177 DWORD options)
1178 /*[clinic end generated code: output=ad9711397b5dcd4e input=b933e3f2356a8c12]*/
1179 {
1180 HANDLE target_handle;
1181 BOOL result;
1182
1183 Py_BEGIN_ALLOW_THREADS
1184 result = DuplicateHandle(
1185 source_process_handle,
1186 source_handle,
1187 target_process_handle,
1188 &target_handle,
1189 desired_access,
1190 inherit_handle,
1191 options
1192 );
1193 Py_END_ALLOW_THREADS
1194
1195 if (! result) {
1196 PyErr_SetFromWindowsErr(GetLastError());
1197 return INVALID_HANDLE_VALUE;
1198 }
1199
1200 return target_handle;
1201 }
1202
1203 /*[clinic input]
1204 _winapi.ExitProcess
1205
1206 ExitCode: UINT
1207 /
1208
1209 [clinic start generated code]*/
1210
1211 static PyObject *
_winapi_ExitProcess_impl(PyObject * module,UINT ExitCode)1212 _winapi_ExitProcess_impl(PyObject *module, UINT ExitCode)
1213 /*[clinic end generated code: output=a387deb651175301 input=4f05466a9406c558]*/
1214 {
1215 #if defined(Py_DEBUG)
1216 SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|
1217 SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
1218 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
1219 #endif
1220
1221 ExitProcess(ExitCode);
1222
1223 return NULL;
1224 }
1225
1226 /*[clinic input]
1227 _winapi.GetCurrentProcess -> HANDLE
1228
1229 Return a handle object for the current process.
1230 [clinic start generated code]*/
1231
1232 static HANDLE
_winapi_GetCurrentProcess_impl(PyObject * module)1233 _winapi_GetCurrentProcess_impl(PyObject *module)
1234 /*[clinic end generated code: output=ddeb4dd2ffadf344 input=b213403fd4b96b41]*/
1235 {
1236 return GetCurrentProcess();
1237 }
1238
1239 /*[clinic input]
1240 _winapi.GetExitCodeProcess -> DWORD
1241
1242 process: HANDLE
1243 /
1244
1245 Return the termination status of the specified process.
1246 [clinic start generated code]*/
1247
1248 static DWORD
_winapi_GetExitCodeProcess_impl(PyObject * module,HANDLE process)1249 _winapi_GetExitCodeProcess_impl(PyObject *module, HANDLE process)
1250 /*[clinic end generated code: output=b4620bdf2bccf36b input=61b6bfc7dc2ee374]*/
1251 {
1252 DWORD exit_code;
1253 BOOL result;
1254
1255 result = GetExitCodeProcess(process, &exit_code);
1256
1257 if (! result) {
1258 PyErr_SetFromWindowsErr(GetLastError());
1259 exit_code = PY_DWORD_MAX;
1260 }
1261
1262 return exit_code;
1263 }
1264
1265 /*[clinic input]
1266 _winapi.GetLastError -> DWORD
1267 [clinic start generated code]*/
1268
1269 static DWORD
_winapi_GetLastError_impl(PyObject * module)1270 _winapi_GetLastError_impl(PyObject *module)
1271 /*[clinic end generated code: output=8585b827cb1a92c5 input=62d47fb9bce038ba]*/
1272 {
1273 return GetLastError();
1274 }
1275
1276 /*[clinic input]
1277 _winapi.GetModuleFileName
1278
1279 module_handle: HMODULE
1280 /
1281
1282 Return the fully-qualified path for the file that contains module.
1283
1284 The module must have been loaded by the current process.
1285
1286 The module parameter should be a handle to the loaded module
1287 whose path is being requested. If this parameter is 0,
1288 GetModuleFileName retrieves the path of the executable file
1289 of the current process.
1290 [clinic start generated code]*/
1291
1292 static PyObject *
_winapi_GetModuleFileName_impl(PyObject * module,HMODULE module_handle)1293 _winapi_GetModuleFileName_impl(PyObject *module, HMODULE module_handle)
1294 /*[clinic end generated code: output=85b4b728c5160306 input=6d66ff7deca5d11f]*/
1295 {
1296 BOOL result;
1297 WCHAR filename[MAX_PATH];
1298
1299 Py_BEGIN_ALLOW_THREADS
1300 result = GetModuleFileNameW(module_handle, filename, MAX_PATH);
1301 filename[MAX_PATH-1] = '\0';
1302 Py_END_ALLOW_THREADS
1303
1304 if (! result)
1305 return PyErr_SetFromWindowsErr(GetLastError());
1306
1307 return PyUnicode_FromWideChar(filename, wcslen(filename));
1308 }
1309
1310 /*[clinic input]
1311 _winapi.GetStdHandle -> HANDLE
1312
1313 std_handle: DWORD
1314 One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE.
1315 /
1316
1317 Return a handle to the specified standard device.
1318
1319 The integer associated with the handle object is returned.
1320 [clinic start generated code]*/
1321
1322 static HANDLE
_winapi_GetStdHandle_impl(PyObject * module,DWORD std_handle)1323 _winapi_GetStdHandle_impl(PyObject *module, DWORD std_handle)
1324 /*[clinic end generated code: output=0e613001e73ab614 input=07016b06a2fc8826]*/
1325 {
1326 HANDLE handle;
1327
1328 Py_BEGIN_ALLOW_THREADS
1329 handle = GetStdHandle(std_handle);
1330 Py_END_ALLOW_THREADS
1331
1332 if (handle == INVALID_HANDLE_VALUE)
1333 PyErr_SetFromWindowsErr(GetLastError());
1334
1335 return handle;
1336 }
1337
1338 /*[clinic input]
1339 _winapi.GetVersion -> long
1340
1341 Return the version number of the current operating system.
1342 [clinic start generated code]*/
1343
1344 static long
_winapi_GetVersion_impl(PyObject * module)1345 _winapi_GetVersion_impl(PyObject *module)
1346 /*[clinic end generated code: output=e41f0db5a3b82682 input=e21dff8d0baeded2]*/
1347 /* Disable deprecation warnings about GetVersionEx as the result is
1348 being passed straight through to the caller, who is responsible for
1349 using it correctly. */
1350 #pragma warning(push)
1351 #pragma warning(disable:4996)
1352
1353 {
1354 return GetVersion();
1355 }
1356
1357 #pragma warning(pop)
1358
1359 /*[clinic input]
1360 _winapi.MapViewOfFile -> LPVOID
1361
1362 file_map: HANDLE
1363 desired_access: DWORD
1364 file_offset_high: DWORD
1365 file_offset_low: DWORD
1366 number_bytes: size_t
1367 /
1368 [clinic start generated code]*/
1369
1370 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)1371 _winapi_MapViewOfFile_impl(PyObject *module, HANDLE file_map,
1372 DWORD desired_access, DWORD file_offset_high,
1373 DWORD file_offset_low, size_t number_bytes)
1374 /*[clinic end generated code: output=f23b1ee4823663e3 input=177471073be1a103]*/
1375 {
1376 LPVOID address;
1377
1378 Py_BEGIN_ALLOW_THREADS
1379 address = MapViewOfFile(file_map, desired_access, file_offset_high,
1380 file_offset_low, number_bytes);
1381 Py_END_ALLOW_THREADS
1382
1383 if (address == NULL)
1384 PyErr_SetFromWindowsErr(0);
1385
1386 return address;
1387 }
1388
1389 /*[clinic input]
1390 _winapi.OpenFileMapping -> HANDLE
1391
1392 desired_access: DWORD
1393 inherit_handle: BOOL
1394 name: LPCWSTR
1395 /
1396 [clinic start generated code]*/
1397
1398 static HANDLE
_winapi_OpenFileMapping_impl(PyObject * module,DWORD desired_access,BOOL inherit_handle,LPCWSTR name)1399 _winapi_OpenFileMapping_impl(PyObject *module, DWORD desired_access,
1400 BOOL inherit_handle, LPCWSTR name)
1401 /*[clinic end generated code: output=08cc44def1cb11f1 input=131f2a405359de7f]*/
1402 {
1403 HANDLE handle;
1404
1405 Py_BEGIN_ALLOW_THREADS
1406 handle = OpenFileMappingW(desired_access, inherit_handle, name);
1407 Py_END_ALLOW_THREADS
1408
1409 if (handle == NULL) {
1410 PyObject *temp = PyUnicode_FromWideChar(name, -1);
1411 PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, temp);
1412 Py_XDECREF(temp);
1413 handle = INVALID_HANDLE_VALUE;
1414 }
1415
1416 return handle;
1417 }
1418
1419 /*[clinic input]
1420 _winapi.OpenProcess -> HANDLE
1421
1422 desired_access: DWORD
1423 inherit_handle: BOOL
1424 process_id: DWORD
1425 /
1426 [clinic start generated code]*/
1427
1428 static HANDLE
_winapi_OpenProcess_impl(PyObject * module,DWORD desired_access,BOOL inherit_handle,DWORD process_id)1429 _winapi_OpenProcess_impl(PyObject *module, DWORD desired_access,
1430 BOOL inherit_handle, DWORD process_id)
1431 /*[clinic end generated code: output=b42b6b81ea5a0fc3 input=ec98c4cf4ea2ec36]*/
1432 {
1433 HANDLE handle;
1434
1435 if (PySys_Audit("_winapi.OpenProcess", "II",
1436 process_id, desired_access) < 0) {
1437 return INVALID_HANDLE_VALUE;
1438 }
1439
1440 Py_BEGIN_ALLOW_THREADS
1441 handle = OpenProcess(desired_access, inherit_handle, process_id);
1442 Py_END_ALLOW_THREADS
1443 if (handle == NULL) {
1444 PyErr_SetFromWindowsErr(GetLastError());
1445 handle = INVALID_HANDLE_VALUE;
1446 }
1447
1448 return handle;
1449 }
1450
1451 /*[clinic input]
1452 _winapi.PeekNamedPipe
1453
1454 handle: HANDLE
1455 size: int = 0
1456 /
1457 [clinic start generated code]*/
1458
1459 static PyObject *
_winapi_PeekNamedPipe_impl(PyObject * module,HANDLE handle,int size)1460 _winapi_PeekNamedPipe_impl(PyObject *module, HANDLE handle, int size)
1461 /*[clinic end generated code: output=d0c3e29e49d323dd input=c7aa53bfbce69d70]*/
1462 {
1463 PyObject *buf = NULL;
1464 DWORD nread, navail, nleft;
1465 BOOL ret;
1466
1467 if (size < 0) {
1468 PyErr_SetString(PyExc_ValueError, "negative size");
1469 return NULL;
1470 }
1471
1472 if (size) {
1473 buf = PyBytes_FromStringAndSize(NULL, size);
1474 if (!buf)
1475 return NULL;
1476 Py_BEGIN_ALLOW_THREADS
1477 ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread,
1478 &navail, &nleft);
1479 Py_END_ALLOW_THREADS
1480 if (!ret) {
1481 Py_DECREF(buf);
1482 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1483 }
1484 if (_PyBytes_Resize(&buf, nread))
1485 return NULL;
1486 return Py_BuildValue("NII", buf, navail, nleft);
1487 }
1488 else {
1489 Py_BEGIN_ALLOW_THREADS
1490 ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft);
1491 Py_END_ALLOW_THREADS
1492 if (!ret) {
1493 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1494 }
1495 return Py_BuildValue("II", navail, nleft);
1496 }
1497 }
1498
1499 /*[clinic input]
1500 _winapi.ReadFile
1501
1502 handle: HANDLE
1503 size: DWORD
1504 overlapped as use_overlapped: bool(accept={int}) = False
1505 [clinic start generated code]*/
1506
1507 static PyObject *
_winapi_ReadFile_impl(PyObject * module,HANDLE handle,DWORD size,int use_overlapped)1508 _winapi_ReadFile_impl(PyObject *module, HANDLE handle, DWORD size,
1509 int use_overlapped)
1510 /*[clinic end generated code: output=d3d5b44a8201b944 input=08c439d03a11aac5]*/
1511 {
1512 DWORD nread;
1513 PyObject *buf;
1514 BOOL ret;
1515 DWORD err;
1516 OverlappedObject *overlapped = NULL;
1517
1518 buf = PyBytes_FromStringAndSize(NULL, size);
1519 if (!buf)
1520 return NULL;
1521 if (use_overlapped) {
1522 overlapped = new_overlapped(handle);
1523 if (!overlapped) {
1524 Py_DECREF(buf);
1525 return NULL;
1526 }
1527 /* Steals reference to buf */
1528 overlapped->read_buffer = buf;
1529 }
1530
1531 Py_BEGIN_ALLOW_THREADS
1532 ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread,
1533 overlapped ? &overlapped->overlapped : NULL);
1534 Py_END_ALLOW_THREADS
1535
1536 err = ret ? 0 : GetLastError();
1537
1538 if (overlapped) {
1539 if (!ret) {
1540 if (err == ERROR_IO_PENDING)
1541 overlapped->pending = 1;
1542 else if (err != ERROR_MORE_DATA) {
1543 Py_DECREF(overlapped);
1544 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1545 }
1546 }
1547 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1548 }
1549
1550 if (!ret && err != ERROR_MORE_DATA) {
1551 Py_DECREF(buf);
1552 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1553 }
1554 if (_PyBytes_Resize(&buf, nread))
1555 return NULL;
1556 return Py_BuildValue("NI", buf, err);
1557 }
1558
1559 /*[clinic input]
1560 _winapi.SetNamedPipeHandleState
1561
1562 named_pipe: HANDLE
1563 mode: object
1564 max_collection_count: object
1565 collect_data_timeout: object
1566 /
1567 [clinic start generated code]*/
1568
1569 static PyObject *
_winapi_SetNamedPipeHandleState_impl(PyObject * module,HANDLE named_pipe,PyObject * mode,PyObject * max_collection_count,PyObject * collect_data_timeout)1570 _winapi_SetNamedPipeHandleState_impl(PyObject *module, HANDLE named_pipe,
1571 PyObject *mode,
1572 PyObject *max_collection_count,
1573 PyObject *collect_data_timeout)
1574 /*[clinic end generated code: output=f2129d222cbfa095 input=9142d72163d0faa6]*/
1575 {
1576 PyObject *oArgs[3] = {mode, max_collection_count, collect_data_timeout};
1577 DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL};
1578 int i;
1579 BOOL b;
1580
1581 for (i = 0 ; i < 3 ; i++) {
1582 if (oArgs[i] != Py_None) {
1583 dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]);
1584 if (PyErr_Occurred())
1585 return NULL;
1586 pArgs[i] = &dwArgs[i];
1587 }
1588 }
1589
1590 Py_BEGIN_ALLOW_THREADS
1591 b = SetNamedPipeHandleState(named_pipe, pArgs[0], pArgs[1], pArgs[2]);
1592 Py_END_ALLOW_THREADS
1593
1594 if (!b)
1595 return PyErr_SetFromWindowsErr(0);
1596
1597 Py_RETURN_NONE;
1598 }
1599
1600
1601 /*[clinic input]
1602 _winapi.TerminateProcess
1603
1604 handle: HANDLE
1605 exit_code: UINT
1606 /
1607
1608 Terminate the specified process and all of its threads.
1609 [clinic start generated code]*/
1610
1611 static PyObject *
_winapi_TerminateProcess_impl(PyObject * module,HANDLE handle,UINT exit_code)1612 _winapi_TerminateProcess_impl(PyObject *module, HANDLE handle,
1613 UINT exit_code)
1614 /*[clinic end generated code: output=f4e99ac3f0b1f34a input=d6bc0aa1ee3bb4df]*/
1615 {
1616 BOOL result;
1617
1618 if (PySys_Audit("_winapi.TerminateProcess", "nI",
1619 (Py_ssize_t)handle, exit_code) < 0) {
1620 return NULL;
1621 }
1622
1623 result = TerminateProcess(handle, exit_code);
1624
1625 if (! result)
1626 return PyErr_SetFromWindowsErr(GetLastError());
1627
1628 Py_RETURN_NONE;
1629 }
1630
1631 /*[clinic input]
1632 _winapi.VirtualQuerySize -> size_t
1633
1634 address: LPCVOID
1635 /
1636 [clinic start generated code]*/
1637
1638 static size_t
_winapi_VirtualQuerySize_impl(PyObject * module,LPCVOID address)1639 _winapi_VirtualQuerySize_impl(PyObject *module, LPCVOID address)
1640 /*[clinic end generated code: output=40c8e0ff5ec964df input=6b784a69755d0bb6]*/
1641 {
1642 SIZE_T size_of_buf;
1643 MEMORY_BASIC_INFORMATION mem_basic_info;
1644 SIZE_T region_size;
1645
1646 Py_BEGIN_ALLOW_THREADS
1647 size_of_buf = VirtualQuery(address, &mem_basic_info, sizeof(mem_basic_info));
1648 Py_END_ALLOW_THREADS
1649
1650 if (size_of_buf == 0)
1651 PyErr_SetFromWindowsErr(0);
1652
1653 region_size = mem_basic_info.RegionSize;
1654 return region_size;
1655 }
1656
1657 /*[clinic input]
1658 _winapi.WaitNamedPipe
1659
1660 name: LPCTSTR
1661 timeout: DWORD
1662 /
1663 [clinic start generated code]*/
1664
1665 static PyObject *
_winapi_WaitNamedPipe_impl(PyObject * module,LPCTSTR name,DWORD timeout)1666 _winapi_WaitNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD timeout)
1667 /*[clinic end generated code: output=c2866f4439b1fe38 input=36fc781291b1862c]*/
1668 {
1669 BOOL success;
1670
1671 Py_BEGIN_ALLOW_THREADS
1672 success = WaitNamedPipe(name, timeout);
1673 Py_END_ALLOW_THREADS
1674
1675 if (!success)
1676 return PyErr_SetFromWindowsErr(0);
1677
1678 Py_RETURN_NONE;
1679 }
1680
1681 /*[clinic input]
1682 _winapi.WaitForMultipleObjects
1683
1684 handle_seq: object
1685 wait_flag: BOOL
1686 milliseconds: DWORD(c_default='INFINITE') = _winapi.INFINITE
1687 /
1688 [clinic start generated code]*/
1689
1690 static PyObject *
_winapi_WaitForMultipleObjects_impl(PyObject * module,PyObject * handle_seq,BOOL wait_flag,DWORD milliseconds)1691 _winapi_WaitForMultipleObjects_impl(PyObject *module, PyObject *handle_seq,
1692 BOOL wait_flag, DWORD milliseconds)
1693 /*[clinic end generated code: output=295e3f00b8e45899 input=36f76ca057cd28a0]*/
1694 {
1695 DWORD result;
1696 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
1697 HANDLE sigint_event = NULL;
1698 Py_ssize_t nhandles, i;
1699
1700 if (!PySequence_Check(handle_seq)) {
1701 PyErr_Format(PyExc_TypeError,
1702 "sequence type expected, got '%s'",
1703 Py_TYPE(handle_seq)->tp_name);
1704 return NULL;
1705 }
1706 nhandles = PySequence_Length(handle_seq);
1707 if (nhandles == -1)
1708 return NULL;
1709 if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS - 1) {
1710 PyErr_Format(PyExc_ValueError,
1711 "need at most %zd handles, got a sequence of length %zd",
1712 MAXIMUM_WAIT_OBJECTS - 1, nhandles);
1713 return NULL;
1714 }
1715 for (i = 0; i < nhandles; i++) {
1716 HANDLE h;
1717 PyObject *v = PySequence_GetItem(handle_seq, i);
1718 if (v == NULL)
1719 return NULL;
1720 if (!PyArg_Parse(v, F_HANDLE, &h)) {
1721 Py_DECREF(v);
1722 return NULL;
1723 }
1724 handles[i] = h;
1725 Py_DECREF(v);
1726 }
1727 /* If this is the main thread then make the wait interruptible
1728 by Ctrl-C unless we are waiting for *all* handles */
1729 if (!wait_flag && _PyOS_IsMainThread()) {
1730 sigint_event = _PyOS_SigintEvent();
1731 assert(sigint_event != NULL);
1732 handles[nhandles++] = sigint_event;
1733 }
1734
1735 Py_BEGIN_ALLOW_THREADS
1736 if (sigint_event != NULL)
1737 ResetEvent(sigint_event);
1738 result = WaitForMultipleObjects((DWORD) nhandles, handles,
1739 wait_flag, milliseconds);
1740 Py_END_ALLOW_THREADS
1741
1742 if (result == WAIT_FAILED)
1743 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1744 else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) {
1745 errno = EINTR;
1746 return PyErr_SetFromErrno(PyExc_OSError);
1747 }
1748
1749 return PyLong_FromLong((int) result);
1750 }
1751
1752 /*[clinic input]
1753 _winapi.WaitForSingleObject -> long
1754
1755 handle: HANDLE
1756 milliseconds: DWORD
1757 /
1758
1759 Wait for a single object.
1760
1761 Wait until the specified object is in the signaled state or
1762 the time-out interval elapses. The timeout value is specified
1763 in milliseconds.
1764 [clinic start generated code]*/
1765
1766 static long
_winapi_WaitForSingleObject_impl(PyObject * module,HANDLE handle,DWORD milliseconds)1767 _winapi_WaitForSingleObject_impl(PyObject *module, HANDLE handle,
1768 DWORD milliseconds)
1769 /*[clinic end generated code: output=3c4715d8f1b39859 input=443d1ab076edc7b1]*/
1770 {
1771 DWORD result;
1772
1773 Py_BEGIN_ALLOW_THREADS
1774 result = WaitForSingleObject(handle, milliseconds);
1775 Py_END_ALLOW_THREADS
1776
1777 if (result == WAIT_FAILED) {
1778 PyErr_SetFromWindowsErr(GetLastError());
1779 return -1;
1780 }
1781
1782 return result;
1783 }
1784
1785 /*[clinic input]
1786 _winapi.WriteFile
1787
1788 handle: HANDLE
1789 buffer: object
1790 overlapped as use_overlapped: bool(accept={int}) = False
1791 [clinic start generated code]*/
1792
1793 static PyObject *
_winapi_WriteFile_impl(PyObject * module,HANDLE handle,PyObject * buffer,int use_overlapped)1794 _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
1795 int use_overlapped)
1796 /*[clinic end generated code: output=2ca80f6bf3fa92e3 input=11eae2a03aa32731]*/
1797 {
1798 Py_buffer _buf, *buf;
1799 DWORD len, written;
1800 BOOL ret;
1801 DWORD err;
1802 OverlappedObject *overlapped = NULL;
1803
1804 if (use_overlapped) {
1805 overlapped = new_overlapped(handle);
1806 if (!overlapped)
1807 return NULL;
1808 buf = &overlapped->write_buffer;
1809 }
1810 else
1811 buf = &_buf;
1812
1813 if (!PyArg_Parse(buffer, "y*", buf)) {
1814 Py_XDECREF(overlapped);
1815 return NULL;
1816 }
1817
1818 Py_BEGIN_ALLOW_THREADS
1819 len = (DWORD)Py_MIN(buf->len, PY_DWORD_MAX);
1820 ret = WriteFile(handle, buf->buf, len, &written,
1821 overlapped ? &overlapped->overlapped : NULL);
1822 Py_END_ALLOW_THREADS
1823
1824 err = ret ? 0 : GetLastError();
1825
1826 if (overlapped) {
1827 if (!ret) {
1828 if (err == ERROR_IO_PENDING)
1829 overlapped->pending = 1;
1830 else {
1831 Py_DECREF(overlapped);
1832 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1833 }
1834 }
1835 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1836 }
1837
1838 PyBuffer_Release(buf);
1839 if (!ret)
1840 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
1841 return Py_BuildValue("II", written, err);
1842 }
1843
1844 /*[clinic input]
1845 _winapi.GetACP
1846
1847 Get the current Windows ANSI code page identifier.
1848 [clinic start generated code]*/
1849
1850 static PyObject *
_winapi_GetACP_impl(PyObject * module)1851 _winapi_GetACP_impl(PyObject *module)
1852 /*[clinic end generated code: output=f7ee24bf705dbb88 input=1433c96d03a05229]*/
1853 {
1854 return PyLong_FromUnsignedLong(GetACP());
1855 }
1856
1857 /*[clinic input]
1858 _winapi.GetFileType -> DWORD
1859
1860 handle: HANDLE
1861 [clinic start generated code]*/
1862
1863 static DWORD
_winapi_GetFileType_impl(PyObject * module,HANDLE handle)1864 _winapi_GetFileType_impl(PyObject *module, HANDLE handle)
1865 /*[clinic end generated code: output=92b8466ac76ecc17 input=0058366bc40bbfbf]*/
1866 {
1867 DWORD result;
1868
1869 Py_BEGIN_ALLOW_THREADS
1870 result = GetFileType(handle);
1871 Py_END_ALLOW_THREADS
1872
1873 if (result == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR) {
1874 PyErr_SetFromWindowsErr(0);
1875 return -1;
1876 }
1877
1878 return result;
1879 }
1880
1881
1882 static PyMethodDef winapi_functions[] = {
1883 _WINAPI_CLOSEHANDLE_METHODDEF
1884 _WINAPI_CONNECTNAMEDPIPE_METHODDEF
1885 _WINAPI_CREATEFILE_METHODDEF
1886 _WINAPI_CREATEFILEMAPPING_METHODDEF
1887 _WINAPI_CREATENAMEDPIPE_METHODDEF
1888 _WINAPI_CREATEPIPE_METHODDEF
1889 _WINAPI_CREATEPROCESS_METHODDEF
1890 _WINAPI_CREATEJUNCTION_METHODDEF
1891 _WINAPI_DUPLICATEHANDLE_METHODDEF
1892 _WINAPI_EXITPROCESS_METHODDEF
1893 _WINAPI_GETCURRENTPROCESS_METHODDEF
1894 _WINAPI_GETEXITCODEPROCESS_METHODDEF
1895 _WINAPI_GETLASTERROR_METHODDEF
1896 _WINAPI_GETMODULEFILENAME_METHODDEF
1897 _WINAPI_GETSTDHANDLE_METHODDEF
1898 _WINAPI_GETVERSION_METHODDEF
1899 _WINAPI_MAPVIEWOFFILE_METHODDEF
1900 _WINAPI_OPENFILEMAPPING_METHODDEF
1901 _WINAPI_OPENPROCESS_METHODDEF
1902 _WINAPI_PEEKNAMEDPIPE_METHODDEF
1903 _WINAPI_READFILE_METHODDEF
1904 _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF
1905 _WINAPI_TERMINATEPROCESS_METHODDEF
1906 _WINAPI_VIRTUALQUERYSIZE_METHODDEF
1907 _WINAPI_WAITNAMEDPIPE_METHODDEF
1908 _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF
1909 _WINAPI_WAITFORSINGLEOBJECT_METHODDEF
1910 _WINAPI_WRITEFILE_METHODDEF
1911 _WINAPI_GETACP_METHODDEF
1912 _WINAPI_GETFILETYPE_METHODDEF
1913 {NULL, NULL}
1914 };
1915
1916 static struct PyModuleDef winapi_module = {
1917 PyModuleDef_HEAD_INIT,
1918 "_winapi",
1919 NULL,
1920 -1,
1921 winapi_functions,
1922 NULL,
1923 NULL,
1924 NULL,
1925 NULL
1926 };
1927
1928 #define WINAPI_CONSTANT(fmt, con) \
1929 PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1930
1931 PyMODINIT_FUNC
PyInit__winapi(void)1932 PyInit__winapi(void)
1933 {
1934 PyObject *d;
1935 PyObject *m;
1936
1937 if (PyType_Ready(&OverlappedType) < 0)
1938 return NULL;
1939
1940 m = PyModule_Create(&winapi_module);
1941 if (m == NULL)
1942 return NULL;
1943 d = PyModule_GetDict(m);
1944
1945 PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType);
1946
1947 /* constants */
1948 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
1949 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP);
1950 WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS);
1951 WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE);
1952 WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
1953 WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
1954 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1955 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1956 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1957 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
1958 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1959 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1960 WINAPI_CONSTANT(F_DWORD, ERROR_NO_DATA);
1961 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
1962 WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
1963 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
1964 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
1965 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
1966 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE);
1967 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
1968 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ);
1969 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE);
1970 WINAPI_CONSTANT(F_DWORD, FILE_MAP_ALL_ACCESS);
1971 WINAPI_CONSTANT(F_DWORD, FILE_MAP_COPY);
1972 WINAPI_CONSTANT(F_DWORD, FILE_MAP_EXECUTE);
1973 WINAPI_CONSTANT(F_DWORD, FILE_MAP_READ);
1974 WINAPI_CONSTANT(F_DWORD, FILE_MAP_WRITE);
1975 WINAPI_CONSTANT(F_DWORD, GENERIC_READ);
1976 WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE);
1977 WINAPI_CONSTANT(F_DWORD, INFINITE);
1978 WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE);
1979 WINAPI_CONSTANT(F_DWORD, MEM_COMMIT);
1980 WINAPI_CONSTANT(F_DWORD, MEM_FREE);
1981 WINAPI_CONSTANT(F_DWORD, MEM_IMAGE);
1982 WINAPI_CONSTANT(F_DWORD, MEM_MAPPED);
1983 WINAPI_CONSTANT(F_DWORD, MEM_PRIVATE);
1984 WINAPI_CONSTANT(F_DWORD, MEM_RESERVE);
1985 WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
1986 WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING);
1987 WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE);
1988 WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_READ);
1989 WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_READWRITE);
1990 WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_WRITECOPY);
1991 WINAPI_CONSTANT(F_DWORD, PAGE_GUARD);
1992 WINAPI_CONSTANT(F_DWORD, PAGE_NOACCESS);
1993 WINAPI_CONSTANT(F_DWORD, PAGE_NOCACHE);
1994 WINAPI_CONSTANT(F_DWORD, PAGE_READONLY);
1995 WINAPI_CONSTANT(F_DWORD, PAGE_READWRITE);
1996 WINAPI_CONSTANT(F_DWORD, PAGE_WRITECOMBINE);
1997 WINAPI_CONSTANT(F_DWORD, PAGE_WRITECOPY);
1998 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
1999 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
2000 WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
2001 WINAPI_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE);
2002 WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES);
2003 WINAPI_CONSTANT(F_DWORD, PIPE_WAIT);
2004 WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
2005 WINAPI_CONSTANT(F_DWORD, SYNCHRONIZE);
2006 WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE);
2007 WINAPI_CONSTANT(F_DWORD, SEC_COMMIT);
2008 WINAPI_CONSTANT(F_DWORD, SEC_IMAGE);
2009 WINAPI_CONSTANT(F_DWORD, SEC_LARGE_PAGES);
2010 WINAPI_CONSTANT(F_DWORD, SEC_NOCACHE);
2011 WINAPI_CONSTANT(F_DWORD, SEC_RESERVE);
2012 WINAPI_CONSTANT(F_DWORD, SEC_WRITECOMBINE);
2013 WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW);
2014 WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES);
2015 WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE);
2016 WINAPI_CONSTANT(F_DWORD, STD_OUTPUT_HANDLE);
2017 WINAPI_CONSTANT(F_DWORD, STD_ERROR_HANDLE);
2018 WINAPI_CONSTANT(F_DWORD, STILL_ACTIVE);
2019 WINAPI_CONSTANT(F_DWORD, SW_HIDE);
2020 WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0);
2021 WINAPI_CONSTANT(F_DWORD, WAIT_ABANDONED_0);
2022 WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT);
2023
2024 WINAPI_CONSTANT(F_DWORD, ABOVE_NORMAL_PRIORITY_CLASS);
2025 WINAPI_CONSTANT(F_DWORD, BELOW_NORMAL_PRIORITY_CLASS);
2026 WINAPI_CONSTANT(F_DWORD, HIGH_PRIORITY_CLASS);
2027 WINAPI_CONSTANT(F_DWORD, IDLE_PRIORITY_CLASS);
2028 WINAPI_CONSTANT(F_DWORD, NORMAL_PRIORITY_CLASS);
2029 WINAPI_CONSTANT(F_DWORD, REALTIME_PRIORITY_CLASS);
2030
2031 WINAPI_CONSTANT(F_DWORD, CREATE_NO_WINDOW);
2032 WINAPI_CONSTANT(F_DWORD, DETACHED_PROCESS);
2033 WINAPI_CONSTANT(F_DWORD, CREATE_DEFAULT_ERROR_MODE);
2034 WINAPI_CONSTANT(F_DWORD, CREATE_BREAKAWAY_FROM_JOB);
2035
2036 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_UNKNOWN);
2037 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_DISK);
2038 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_CHAR);
2039 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_PIPE);
2040 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_REMOTE);
2041
2042 WINAPI_CONSTANT("i", NULL);
2043
2044 return m;
2045 }
2046