| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Support routines from the Windows API | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This module was originally created by merging PC/_subprocess.c with | 
					
						
							|  |  |  |  * Modules/_multiprocessing/win32_functions.c. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2004 by Fredrik Lundh <fredrik@pythonware.com> | 
					
						
							|  |  |  |  * Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com
 | 
					
						
							|  |  |  |  * Copyright (c) 2004 by Peter Astrand <astrand@lysator.liu.se> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * By obtaining, using, and/or copying this software and/or its | 
					
						
							|  |  |  |  * associated documentation, you agree that you have read, understood, | 
					
						
							|  |  |  |  * and will comply with the following terms and conditions: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Permission to use, copy, modify, and distribute this software and | 
					
						
							|  |  |  |  * its associated documentation for any purpose and without fee is | 
					
						
							|  |  |  |  * hereby granted, provided that the above copyright notice appears in | 
					
						
							|  |  |  |  * all copies, and that both that copyright notice and this permission | 
					
						
							|  |  |  |  * notice appear in supporting documentation, and that the name of the | 
					
						
							|  |  |  |  * authors not be used in advertising or publicity pertaining to | 
					
						
							|  |  |  |  * distribution of the software without specific, written prior | 
					
						
							|  |  |  |  * permission. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | 
					
						
							|  |  |  |  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. | 
					
						
							|  |  |  |  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | 
					
						
							|  |  |  |  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS | 
					
						
							|  |  |  |  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, | 
					
						
							|  |  |  |  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION | 
					
						
							|  |  |  |  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Licensed to PSF under a Contributor Agreement. */ | 
					
						
							| 
									
										
										
										
											2021-07-30 06:54:46 -07:00
										 |  |  | /* See https://www.python.org/2.4/license for licensing details. */ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2021-04-22 00:52:52 +02:00
										 |  |  | #include "pycore_moduleobject.h"  // _PyModule_GetState()
 | 
					
						
							| 
									
										
										
										
											2023-07-04 17:19:20 +03:00
										 |  |  | #include "pycore_pylifecycle.h"   // _Py_IsInterpreterFinalizing()
 | 
					
						
							| 
									
										
										
										
											2023-07-02 18:37:37 +02:00
										 |  |  | #include "pycore_pystate.h"       // _PyInterpreterState_GET
 | 
					
						
							| 
									
										
										
										
											2023-07-25 15:28:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-09 22:09:12 +01:00
										 |  |  | #ifndef WINDOWS_LEAN_AND_MEAN
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | #define WINDOWS_LEAN_AND_MEAN
 | 
					
						
							| 
									
										
										
										
											2023-03-09 22:09:12 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | #include "windows.h"
 | 
					
						
							| 
									
										
										
										
											2023-03-09 22:09:12 +01:00
										 |  |  | #include <winioctl.h>
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | #include <crtdbg.h>
 | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  | #include "winreparse.h"
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined(MS_WIN32) && !defined(MS_WIN64)
 | 
					
						
							|  |  |  | #define HANDLE_TO_PYNUM(handle) \
 | 
					
						
							|  |  |  |     PyLong_FromUnsignedLong((unsigned long) handle) | 
					
						
							|  |  |  | #define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLong(obj))
 | 
					
						
							|  |  |  | #define F_POINTER "k"
 | 
					
						
							| 
									
										
										
										
											2023-07-25 15:28:30 +02:00
										 |  |  | #define T_POINTER Py_T_ULONG
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | #else
 | 
					
						
							|  |  |  | #define HANDLE_TO_PYNUM(handle) \
 | 
					
						
							|  |  |  |     PyLong_FromUnsignedLongLong((unsigned long long) handle) | 
					
						
							|  |  |  | #define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLongLong(obj))
 | 
					
						
							|  |  |  | #define F_POINTER "K"
 | 
					
						
							| 
									
										
										
										
											2023-07-25 15:28:30 +02:00
										 |  |  | #define T_POINTER Py_T_ULONGLONG
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define F_HANDLE F_POINTER
 | 
					
						
							|  |  |  | #define F_DWORD "k"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define T_HANDLE T_POINTER
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-09 22:09:12 +01:00
										 |  |  | // winbase.h limits the STARTF_* flags to the desktop API as of 10.0.19041.
 | 
					
						
							|  |  |  | #ifndef STARTF_USESHOWWINDOW
 | 
					
						
							|  |  |  | #define STARTF_USESHOWWINDOW 0x00000001
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2024-04-28 23:10:44 +02:00
										 |  |  | #ifndef STARTF_USESIZE
 | 
					
						
							|  |  |  | #define STARTF_USESIZE 0x00000002
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef STARTF_USEPOSITION
 | 
					
						
							|  |  |  | #define STARTF_USEPOSITION 0x00000004
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef STARTF_USECOUNTCHARS
 | 
					
						
							|  |  |  | #define STARTF_USECOUNTCHARS 0x00000008
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef STARTF_USEFILLATTRIBUTE
 | 
					
						
							|  |  |  | #define STARTF_USEFILLATTRIBUTE 0x00000010
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef STARTF_RUNFULLSCREEN
 | 
					
						
							|  |  |  | #define STARTF_RUNFULLSCREEN 0x00000020
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef STARTF_FORCEONFEEDBACK
 | 
					
						
							|  |  |  | #define STARTF_FORCEONFEEDBACK 0x00000040
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef STARTF_FORCEOFFFEEDBACK
 | 
					
						
							|  |  |  | #define STARTF_FORCEOFFFEEDBACK 0x00000080
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2023-03-09 22:09:12 +01:00
										 |  |  | #ifndef STARTF_USESTDHANDLES
 | 
					
						
							|  |  |  | #define STARTF_USESTDHANDLES 0x00000100
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2024-04-28 23:10:44 +02:00
										 |  |  | #ifndef STARTF_USEHOTKEY
 | 
					
						
							|  |  |  | #define STARTF_USEHOTKEY 0x00000200
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef STARTF_TITLEISLINKNAME
 | 
					
						
							|  |  |  | #define STARTF_TITLEISLINKNAME 0x00000800
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef STARTF_TITLEISAPPID
 | 
					
						
							|  |  |  | #define STARTF_TITLEISAPPID 0x00001000
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef STARTF_PREVENTPINNING
 | 
					
						
							|  |  |  | #define STARTF_PREVENTPINNING 0x00002000
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef STARTF_UNTRUSTEDSOURCE
 | 
					
						
							|  |  |  | #define STARTF_UNTRUSTEDSOURCE 0x00008000
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2023-03-09 22:09:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     PyTypeObject *overlapped_type; | 
					
						
							|  |  |  | } WinApiState; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline WinApiState* | 
					
						
							|  |  |  | winapi_get_state(PyObject *module) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-04-22 00:52:52 +02:00
										 |  |  |     void *state = _PyModule_GetState(module); | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |     assert(state != NULL); | 
					
						
							|  |  |  |     return (WinApiState *)state; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * A Python object wrapping an OVERLAPPED structure and other useful data | 
					
						
							|  |  |  |  * for overlapped I/O | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     PyObject_HEAD | 
					
						
							|  |  |  |     OVERLAPPED overlapped; | 
					
						
							|  |  |  |     /* For convenience, we store the file handle too */ | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  |     /* Whether there's I/O in flight */ | 
					
						
							|  |  |  |     int pending; | 
					
						
							|  |  |  |     /* Whether I/O completed successfully */ | 
					
						
							|  |  |  |     int completed; | 
					
						
							|  |  |  |     /* Buffer used for reading (optional) */ | 
					
						
							|  |  |  |     PyObject *read_buffer; | 
					
						
							|  |  |  |     /* Buffer used for writing (optional) */ | 
					
						
							|  |  |  |     Py_buffer write_buffer; | 
					
						
							|  |  |  | } OverlappedObject; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 17:06:46 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  | Note: tp_clear (overlapped_clear) is not implemented because it | 
					
						
							|  |  |  | requires cancelling the IO operation if it's pending and the cancellation is | 
					
						
							|  |  |  | quite complex and can fail (see: overlapped_dealloc). | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_VISIT(self->read_buffer); | 
					
						
							|  |  |  |     Py_VISIT(self->write_buffer.obj); | 
					
						
							|  |  |  |     Py_VISIT(Py_TYPE(self)); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | static void | 
					
						
							|  |  |  | overlapped_dealloc(OverlappedObject *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DWORD bytes; | 
					
						
							|  |  |  |     int err = GetLastError(); | 
					
						
							| 
									
										
										
										
											2013-11-17 13:15:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-29 00:29:19 +08:00
										 |  |  |     PyObject_GC_UnTrack(self); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     if (self->pending) { | 
					
						
							| 
									
										
										
										
											2023-03-01 01:31:21 +01:00
										 |  |  |         if (CancelIoEx(self->handle, &self->overlapped) && | 
					
						
							| 
									
										
										
										
											2013-11-17 13:15:51 +00:00
										 |  |  |             GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             /* The operation is no longer pending -- nothing to do. */ | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-07-02 18:37:37 +02:00
										 |  |  |         else if (_Py_IsInterpreterFinalizing(_PyInterpreterState_GET())) | 
					
						
							| 
									
										
										
										
											2013-11-17 13:15:51 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             /* The operation is still pending -- give a warning.  This
 | 
					
						
							|  |  |  |                will probably only happen on Windows XP. */ | 
					
						
							| 
									
										
										
										
											2024-02-14 23:35:06 +01:00
										 |  |  |             PyErr_SetString(PyExc_PythonFinalizationError, | 
					
						
							| 
									
										
										
										
											2013-11-17 13:15:51 +00:00
										 |  |  |                             "I/O operations still in flight while destroying " | 
					
						
							|  |  |  |                             "Overlapped object, the process may crash"); | 
					
						
							|  |  |  |             PyErr_WriteUnraisable(NULL); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             /* The operation is still pending, but the process is
 | 
					
						
							|  |  |  |                probably about to exit, so we need not worry too much | 
					
						
							|  |  |  |                about memory leaks.  Leaking self prevents a potential | 
					
						
							|  |  |  |                crash.  This can happen when a daemon thread is cleaned | 
					
						
							|  |  |  |                up at exit -- see #19565.  We only expect to get here | 
					
						
							|  |  |  |                on Windows XP. */ | 
					
						
							|  |  |  |             CloseHandle(self->overlapped.hEvent); | 
					
						
							|  |  |  |             SetLastError(err); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-11-17 13:15:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     CloseHandle(self->overlapped.hEvent); | 
					
						
							|  |  |  |     SetLastError(err); | 
					
						
							|  |  |  |     if (self->write_buffer.obj) | 
					
						
							|  |  |  |         PyBuffer_Release(&self->write_buffer); | 
					
						
							|  |  |  |     Py_CLEAR(self->read_buffer); | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |     PyTypeObject *tp = Py_TYPE(self); | 
					
						
							|  |  |  |     tp->tp_free(self); | 
					
						
							|  |  |  |     Py_DECREF(tp); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | module _winapi | 
					
						
							|  |  |  | class _winapi.Overlapped "OverlappedObject *" "&OverlappedType" | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=c13d3f5fd1dabb84]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*[python input]
 | 
					
						
							|  |  |  | def create_converter(type_, format_unit): | 
					
						
							|  |  |  |     name = type_ + '_converter' | 
					
						
							|  |  |  |     # registered upon creation by CConverter's metaclass
 | 
					
						
							|  |  |  |     type(name, (CConverter,), {'type': type_, 'format_unit': format_unit}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # format unit differs between platforms for these
 | 
					
						
							|  |  |  | create_converter('HANDLE', '" F_HANDLE "') | 
					
						
							|  |  |  | create_converter('HMODULE', '" F_HANDLE "') | 
					
						
							|  |  |  | create_converter('LPSECURITY_ATTRIBUTES', '" F_POINTER "') | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  | create_converter('LPCVOID', '" F_POINTER "') | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | create_converter('BOOL', 'i') # F_BOOL used previously (always 'i') | 
					
						
							|  |  |  | create_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter) | 
					
						
							|  |  |  | create_converter('UINT', 'I') # F_UINT used previously (always 'I') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-10 23:26:06 +03:00
										 |  |  | class LPCWSTR_converter(Py_UNICODE_converter): | 
					
						
							|  |  |  |     type = 'LPCWSTR' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | class HANDLE_return_converter(CReturnConverter): | 
					
						
							|  |  |  |     type = 'HANDLE' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def render(self, function, data): | 
					
						
							|  |  |  |         self.declare(data) | 
					
						
							|  |  |  |         self.err_occurred_if("_return_value == INVALID_HANDLE_VALUE", data) | 
					
						
							|  |  |  |         data.return_conversion.append( | 
					
						
							| 
									
										
										
										
											2016-06-09 16:16:06 +03:00
										 |  |  |             'if (_return_value == NULL) {\n    Py_RETURN_NONE;\n}\n') | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |         data.return_conversion.append( | 
					
						
							|  |  |  |             'return_value = HANDLE_TO_PYNUM(_return_value);\n') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class DWORD_return_converter(CReturnConverter): | 
					
						
							|  |  |  |     type = 'DWORD' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def render(self, function, data): | 
					
						
							|  |  |  |         self.declare(data) | 
					
						
							| 
									
										
										
										
											2017-10-24 16:53:32 -07:00
										 |  |  |         self.err_occurred_if("_return_value == PY_DWORD_MAX", data) | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |         data.return_conversion.append( | 
					
						
							| 
									
										
										
										
											2023-10-20 18:08:41 +03:00
										 |  |  |             'return_value = PyLong_FromUnsignedLong(_return_value);\n') | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | class LPVOID_return_converter(CReturnConverter): | 
					
						
							|  |  |  |     type = 'LPVOID' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def render(self, function, data): | 
					
						
							|  |  |  |         self.declare(data) | 
					
						
							|  |  |  |         self.err_occurred_if("_return_value == NULL", data) | 
					
						
							|  |  |  |         data.return_conversion.append( | 
					
						
							|  |  |  |             'return_value = HANDLE_TO_PYNUM(_return_value);\n') | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | [python start generated code]*/ | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  | /*[python end generated code: output=da39a3ee5e6b4b0d input=da0a4db751936ee7]*/ | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "clinic/_winapi.c.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.Overlapped.GetOverlappedResult | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     wait: bool | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | _winapi_Overlapped_GetOverlappedResult_impl(OverlappedObject *self, int wait) | 
					
						
							|  |  |  | /*[clinic end generated code: output=bdd0c1ed6518cd03 input=194505ee8e0e3565]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     BOOL res; | 
					
						
							|  |  |  |     DWORD transferred = 0; | 
					
						
							|  |  |  |     DWORD err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     res = GetOverlappedResult(self->handle, &self->overlapped, &transferred, | 
					
						
							|  |  |  |                               wait != 0); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     err = res ? ERROR_SUCCESS : GetLastError(); | 
					
						
							|  |  |  |     switch (err) { | 
					
						
							|  |  |  |         case ERROR_SUCCESS: | 
					
						
							|  |  |  |         case ERROR_MORE_DATA: | 
					
						
							|  |  |  |         case ERROR_OPERATION_ABORTED: | 
					
						
							|  |  |  |             self->completed = 1; | 
					
						
							|  |  |  |             self->pending = 0; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ERROR_IO_INCOMPLETE: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             self->pending = 0; | 
					
						
							| 
									
										
										
										
											2017-04-16 10:46:38 +03:00
										 |  |  |             return PyErr_SetExcFromWindowsErr(PyExc_OSError, err); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (self->completed && self->read_buffer != NULL) { | 
					
						
							|  |  |  |         assert(PyBytes_CheckExact(self->read_buffer)); | 
					
						
							|  |  |  |         if (transferred != PyBytes_GET_SIZE(self->read_buffer) && | 
					
						
							|  |  |  |             _PyBytes_Resize(&self->read_buffer, transferred)) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return Py_BuildValue("II", (unsigned) transferred, (unsigned) err); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.Overlapped.getbuffer | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | _winapi_Overlapped_getbuffer_impl(OverlappedObject *self) | 
					
						
							|  |  |  | /*[clinic end generated code: output=95a3eceefae0f748 input=347fcfd56b4ceabd]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject *res; | 
					
						
							|  |  |  |     if (!self->completed) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  |                         "can't get read buffer before GetOverlappedResult() " | 
					
						
							|  |  |  |                         "signals the operation completed"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     res = self->read_buffer ? self->read_buffer : Py_None; | 
					
						
							| 
									
										
										
										
											2022-11-14 13:44:56 +01:00
										 |  |  |     return Py_NewRef(res); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.Overlapped.cancel | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | _winapi_Overlapped_cancel_impl(OverlappedObject *self) | 
					
						
							|  |  |  | /*[clinic end generated code: output=fcb9ab5df4ebdae5 input=cbf3da142290039f]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     BOOL res = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (self->pending) { | 
					
						
							|  |  |  |         Py_BEGIN_ALLOW_THREADS | 
					
						
							| 
									
										
										
										
											2023-03-01 13:01:39 +01:00
										 |  |  |         res = CancelIoEx(self->handle, &self->overlapped); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */ | 
					
						
							|  |  |  |     if (!res && GetLastError() != ERROR_NOT_FOUND) | 
					
						
							| 
									
										
										
										
											2017-04-16 10:46:38 +03:00
										 |  |  |         return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     self->pending = 0; | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef overlapped_methods[] = { | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     _WINAPI_OVERLAPPED_GETOVERLAPPEDRESULT_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_OVERLAPPED_GETBUFFER_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_OVERLAPPED_CANCEL_METHODDEF | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     {NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMemberDef overlapped_members[] = { | 
					
						
							|  |  |  |     {"event", T_HANDLE, | 
					
						
							|  |  |  |      offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent), | 
					
						
							| 
									
										
										
										
											2023-07-25 15:28:30 +02:00
										 |  |  |      Py_READONLY, "overlapped event handle"}, | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     {NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  | static PyType_Slot winapi_overlapped_type_slots[] = { | 
					
						
							| 
									
										
										
										
											2021-05-28 17:06:46 +08:00
										 |  |  |     {Py_tp_traverse, overlapped_traverse}, | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |     {Py_tp_dealloc, overlapped_dealloc}, | 
					
						
							|  |  |  |     {Py_tp_doc, "OVERLAPPED structure wrapper"}, | 
					
						
							|  |  |  |     {Py_tp_methods, overlapped_methods}, | 
					
						
							|  |  |  |     {Py_tp_members, overlapped_members}, | 
					
						
							|  |  |  |     {0,0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyType_Spec winapi_overlapped_type_spec = { | 
					
						
							|  |  |  |     .name = "_winapi.Overlapped", | 
					
						
							|  |  |  |     .basicsize = sizeof(OverlappedObject), | 
					
						
							| 
									
										
										
										
											2021-05-28 17:06:46 +08:00
										 |  |  |     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | | 
					
						
							| 
									
										
										
										
											2021-06-17 12:06:09 +02:00
										 |  |  |               Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |     .slots = winapi_overlapped_type_slots, | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static OverlappedObject * | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  | new_overlapped(PyObject *module, HANDLE handle) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |     WinApiState *st = winapi_get_state(module); | 
					
						
							| 
									
										
										
										
											2021-05-28 17:06:46 +08:00
										 |  |  |     OverlappedObject *self = PyObject_GC_New(OverlappedObject, st->overlapped_type); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     if (!self) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     self->handle = handle; | 
					
						
							|  |  |  |     self->read_buffer = NULL; | 
					
						
							|  |  |  |     self->pending = 0; | 
					
						
							|  |  |  |     self->completed = 0; | 
					
						
							|  |  |  |     memset(&self->overlapped, 0, sizeof(OVERLAPPED)); | 
					
						
							|  |  |  |     memset(&self->write_buffer, 0, sizeof(Py_buffer)); | 
					
						
							|  |  |  |     /* Manual reset, initially non-signalled */ | 
					
						
							|  |  |  |     self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); | 
					
						
							| 
									
										
										
										
											2021-05-28 17:06:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     PyObject_GC_Track(self); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     return self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* windows API functions */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.CloseHandle | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     handle: HANDLE | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Close handle. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_CloseHandle_impl(PyObject *module, HANDLE handle) | 
					
						
							|  |  |  | /*[clinic end generated code: output=7ad37345f07bd782 input=7f0e4ac36e0352b8]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     BOOL success; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     success = CloseHandle(handle); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!success) | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.ConnectNamedPipe | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     handle: HANDLE | 
					
						
							| 
									
										
										
										
											2022-12-03 21:52:21 +02:00
										 |  |  |     overlapped as use_overlapped: bool = False | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle, | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |                               int use_overlapped) | 
					
						
							| 
									
										
										
										
											2022-12-03 21:52:21 +02:00
										 |  |  | /*[clinic end generated code: output=335a0e7086800671 input=a80e56e8bd370e31]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     BOOL success; | 
					
						
							|  |  |  |     OverlappedObject *overlapped = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (use_overlapped) { | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |         overlapped = new_overlapped(module, handle); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         if (!overlapped) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     success = ConnectNamedPipe(handle, | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |                                overlapped ? &overlapped->overlapped : NULL); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (overlapped) { | 
					
						
							|  |  |  |         int err = GetLastError(); | 
					
						
							|  |  |  |         /* Overlapped ConnectNamedPipe never returns a success code */ | 
					
						
							|  |  |  |         assert(success == 0); | 
					
						
							|  |  |  |         if (err == ERROR_IO_PENDING) | 
					
						
							|  |  |  |             overlapped->pending = 1; | 
					
						
							|  |  |  |         else if (err == ERROR_PIPE_CONNECTED) | 
					
						
							|  |  |  |             SetEvent(overlapped->overlapped.hEvent); | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             Py_DECREF(overlapped); | 
					
						
							|  |  |  |             return PyErr_SetFromWindowsErr(err); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return (PyObject *) overlapped; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!success) | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.CreateEventW -> HANDLE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     security_attributes: LPSECURITY_ATTRIBUTES | 
					
						
							|  |  |  |     manual_reset: BOOL | 
					
						
							|  |  |  |     initial_state: BOOL | 
					
						
							|  |  |  |     name: LPCWSTR(accept={str, NoneType}) | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HANDLE | 
					
						
							|  |  |  | _winapi_CreateEventW_impl(PyObject *module, | 
					
						
							|  |  |  |                           LPSECURITY_ATTRIBUTES security_attributes, | 
					
						
							|  |  |  |                           BOOL manual_reset, BOOL initial_state, | 
					
						
							|  |  |  |                           LPCWSTR name) | 
					
						
							|  |  |  | /*[clinic end generated code: output=2d4c7d5852ecb298 input=4187cee28ac763f8]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PySys_Audit("_winapi.CreateEventW", "bbu", manual_reset, initial_state, name) < 0) { | 
					
						
							|  |  |  |         return INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     handle = CreateEventW(security_attributes, manual_reset, initial_state, name); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (handle == INVALID_HANDLE_VALUE) { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return handle; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.CreateFile -> HANDLE | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-26 17:27:29 +00:00
										 |  |  |     file_name: LPCWSTR | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     desired_access: DWORD | 
					
						
							|  |  |  |     share_mode: DWORD | 
					
						
							|  |  |  |     security_attributes: LPSECURITY_ATTRIBUTES | 
					
						
							|  |  |  |     creation_disposition: DWORD | 
					
						
							|  |  |  |     flags_and_attributes: DWORD | 
					
						
							|  |  |  |     template_file: HANDLE | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HANDLE | 
					
						
							| 
									
										
										
										
											2024-01-26 17:27:29 +00:00
										 |  |  | _winapi_CreateFile_impl(PyObject *module, LPCWSTR file_name, | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |                         DWORD desired_access, DWORD share_mode, | 
					
						
							|  |  |  |                         LPSECURITY_ATTRIBUTES security_attributes, | 
					
						
							|  |  |  |                         DWORD creation_disposition, | 
					
						
							|  |  |  |                         DWORD flags_and_attributes, HANDLE template_file) | 
					
						
							| 
									
										
										
										
											2024-01-26 17:27:29 +00:00
										 |  |  | /*[clinic end generated code: output=818c811e5e04d550 input=1fa870ed1c2e3d69]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  |     if (PySys_Audit("_winapi.CreateFile", "ukkkk", | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |                     file_name, desired_access, share_mode, | 
					
						
							|  |  |  |                     creation_disposition, flags_and_attributes) < 0) { | 
					
						
							|  |  |  |         return INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							| 
									
										
										
										
											2024-01-26 17:27:29 +00:00
										 |  |  |     handle = CreateFileW(file_name, desired_access, | 
					
						
							|  |  |  |                          share_mode, security_attributes, | 
					
						
							|  |  |  |                          creation_disposition, | 
					
						
							|  |  |  |                          flags_and_attributes, template_file); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-26 17:27:29 +00:00
										 |  |  |     if (handle == INVALID_HANDLE_VALUE) { | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |         PyErr_SetFromWindowsErr(0); | 
					
						
							| 
									
										
										
										
											2024-01-26 17:27:29 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     return handle; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.CreateFileMapping -> HANDLE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     file_handle: HANDLE | 
					
						
							|  |  |  |     security_attributes: LPSECURITY_ATTRIBUTES | 
					
						
							|  |  |  |     protect: DWORD | 
					
						
							|  |  |  |     max_size_high: DWORD | 
					
						
							|  |  |  |     max_size_low: DWORD | 
					
						
							|  |  |  |     name: LPCWSTR | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) | 
					
						
							|  |  |  | /*[clinic end generated code: output=6c0a4d5cf7f6fcc6 input=3dc5cf762a74dee8]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     handle = CreateFileMappingW(file_handle, security_attributes, | 
					
						
							|  |  |  |                                 protect, max_size_high, max_size_low, | 
					
						
							|  |  |  |                                 name); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (handle == NULL) { | 
					
						
							| 
									
										
										
										
											2019-05-30 01:58:50 -06:00
										 |  |  |         PyObject *temp = PyUnicode_FromWideChar(name, -1); | 
					
						
							|  |  |  |         PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, temp); | 
					
						
							|  |  |  |         Py_XDECREF(temp); | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  |         handle = INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return handle; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.CreateJunction | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-10 23:26:06 +03:00
										 |  |  |     src_path: LPCWSTR | 
					
						
							|  |  |  |     dst_path: LPCWSTR | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2020-07-10 23:26:06 +03:00
										 |  |  | _winapi_CreateJunction_impl(PyObject *module, LPCWSTR src_path, | 
					
						
							|  |  |  |                             LPCWSTR dst_path) | 
					
						
							|  |  |  | /*[clinic end generated code: output=44b3f5e9bbcc4271 input=963d29b44b9384a7]*/ | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     /* Privilege adjustment */ | 
					
						
							|  |  |  |     HANDLE token = NULL; | 
					
						
							| 
									
										
										
										
											2024-01-16 16:40:02 +00:00
										 |  |  |     struct { | 
					
						
							|  |  |  |         TOKEN_PRIVILEGES base; | 
					
						
							|  |  |  |         /* overallocate by a few array elements */ | 
					
						
							|  |  |  |         LUID_AND_ATTRIBUTES privs[4]; | 
					
						
							|  |  |  |     } tp, previousTp; | 
					
						
							|  |  |  |     int previousTpSize = 0; | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Reparse data buffer */ | 
					
						
							|  |  |  |     const USHORT prefix_len = 4; | 
					
						
							|  |  |  |     USHORT print_len = 0; | 
					
						
							|  |  |  |     USHORT rdb_size = 0; | 
					
						
							| 
									
										
										
										
											2016-08-04 02:38:59 +00:00
										 |  |  |     _Py_PREPARSE_DATA_BUFFER rdb = NULL; | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Junction point creation */ | 
					
						
							|  |  |  |     HANDLE junction = NULL; | 
					
						
							|  |  |  |     DWORD ret = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (src_path == NULL || dst_path == NULL) | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (wcsncmp(src_path, L"\\??\\", prefix_len) == 0) | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |     if (PySys_Audit("_winapi.CreateJunction", "uu", src_path, dst_path) < 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  |     /* Adjust privileges to allow rewriting directory entry as a
 | 
					
						
							|  |  |  |        junction point. */ | 
					
						
							| 
									
										
										
										
											2024-01-16 16:40:02 +00:00
										 |  |  |     if (!OpenProcessToken(GetCurrentProcess(), | 
					
						
							|  |  |  |                           TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  |         goto cleanup; | 
					
						
							| 
									
										
										
										
											2024-01-16 16:40:02 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-16 16:40:02 +00:00
										 |  |  |     if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.base.Privileges[0].Luid)) { | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  |         goto cleanup; | 
					
						
							| 
									
										
										
										
											2024-01-16 16:40:02 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-16 16:40:02 +00:00
										 |  |  |     tp.base.PrivilegeCount = 1; | 
					
						
							|  |  |  |     tp.base.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; | 
					
						
							|  |  |  |     if (!AdjustTokenPrivileges(token, FALSE, &tp.base, sizeof(previousTp), | 
					
						
							|  |  |  |                                &previousTp.base, &previousTpSize)) { | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  |         goto cleanup; | 
					
						
							| 
									
										
										
										
											2024-01-16 16:40:02 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (GetFileAttributesW(src_path) == INVALID_FILE_ATTRIBUTES) | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Store the absolute link target path length in print_len. */ | 
					
						
							|  |  |  |     print_len = (USHORT)GetFullPathNameW(src_path, 0, NULL, NULL); | 
					
						
							|  |  |  |     if (print_len == 0) | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* NUL terminator should not be part of print_len. */ | 
					
						
							|  |  |  |     --print_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* REPARSE_DATA_BUFFER usage is heavily under-documented, especially for
 | 
					
						
							|  |  |  |        junction points. Here's what I've learned along the way: | 
					
						
							|  |  |  |        - A junction point has two components: a print name and a substitute | 
					
						
							|  |  |  |          name. They both describe the link target, but the substitute name is | 
					
						
							|  |  |  |          the physical target and the print name is shown in directory listings. | 
					
						
							|  |  |  |        - The print name must be a native name, prefixed with "\??\". | 
					
						
							|  |  |  |        - Both names are stored after each other in the same buffer (the | 
					
						
							|  |  |  |          PathBuffer) and both must be NUL-terminated. | 
					
						
							|  |  |  |        - There are four members defining their respective offset and length | 
					
						
							|  |  |  |          inside PathBuffer: SubstituteNameOffset, SubstituteNameLength, | 
					
						
							|  |  |  |          PrintNameOffset and PrintNameLength. | 
					
						
							|  |  |  |        - The total size we need to allocate for the REPARSE_DATA_BUFFER, thus, | 
					
						
							|  |  |  |          is the sum of: | 
					
						
							|  |  |  |          - the fixed header size (REPARSE_DATA_BUFFER_HEADER_SIZE) | 
					
						
							|  |  |  |          - the size of the MountPointReparseBuffer member without the PathBuffer | 
					
						
							|  |  |  |          - the size of the prefix ("\??\") in bytes | 
					
						
							|  |  |  |          - the size of the print name in bytes | 
					
						
							|  |  |  |          - the size of the substitute name in bytes | 
					
						
							|  |  |  |          - the size of two NUL terminators in bytes */ | 
					
						
							| 
									
										
										
										
											2016-08-04 02:38:59 +00:00
										 |  |  |     rdb_size = _Py_REPARSE_DATA_BUFFER_HEADER_SIZE + | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  |         sizeof(rdb->MountPointReparseBuffer) - | 
					
						
							|  |  |  |         sizeof(rdb->MountPointReparseBuffer.PathBuffer) + | 
					
						
							|  |  |  |         /* Two +1's for NUL terminators. */ | 
					
						
							|  |  |  |         (prefix_len + print_len + 1 + print_len + 1) * sizeof(WCHAR); | 
					
						
							| 
									
										
										
										
											2020-03-24 23:26:44 -05:00
										 |  |  |     rdb = (_Py_PREPARSE_DATA_BUFFER)PyMem_RawCalloc(1, rdb_size); | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  |     if (rdb == NULL) | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; | 
					
						
							| 
									
										
										
										
											2016-08-04 02:38:59 +00:00
										 |  |  |     rdb->ReparseDataLength = rdb_size - _Py_REPARSE_DATA_BUFFER_HEADER_SIZE; | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  |     rdb->MountPointReparseBuffer.SubstituteNameOffset = 0; | 
					
						
							|  |  |  |     rdb->MountPointReparseBuffer.SubstituteNameLength = | 
					
						
							|  |  |  |         (prefix_len + print_len) * sizeof(WCHAR); | 
					
						
							|  |  |  |     rdb->MountPointReparseBuffer.PrintNameOffset = | 
					
						
							|  |  |  |         rdb->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR); | 
					
						
							|  |  |  |     rdb->MountPointReparseBuffer.PrintNameLength = print_len * sizeof(WCHAR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Store the full native path of link target at the substitute name
 | 
					
						
							|  |  |  |        offset (0). */ | 
					
						
							|  |  |  |     wcscpy(rdb->MountPointReparseBuffer.PathBuffer, L"\\??\\"); | 
					
						
							|  |  |  |     if (GetFullPathNameW(src_path, print_len + 1, | 
					
						
							|  |  |  |                          rdb->MountPointReparseBuffer.PathBuffer + prefix_len, | 
					
						
							|  |  |  |                          NULL) == 0) | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Copy everything but the native prefix to the print name offset. */ | 
					
						
							|  |  |  |     wcscpy(rdb->MountPointReparseBuffer.PathBuffer + | 
					
						
							|  |  |  |              prefix_len + print_len + 1, | 
					
						
							|  |  |  |              rdb->MountPointReparseBuffer.PathBuffer + prefix_len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Create a directory for the junction point. */ | 
					
						
							|  |  |  |     if (!CreateDirectoryW(dst_path, NULL)) | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     junction = CreateFileW(dst_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, | 
					
						
							|  |  |  |         OPEN_EXISTING, | 
					
						
							|  |  |  |         FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); | 
					
						
							|  |  |  |     if (junction == INVALID_HANDLE_VALUE) | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Make the directory entry a junction point. */ | 
					
						
							|  |  |  |     if (!DeviceIoControl(junction, FSCTL_SET_REPARSE_POINT, rdb, rdb_size, | 
					
						
							|  |  |  |                          NULL, 0, &ret, NULL)) | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cleanup: | 
					
						
							|  |  |  |     ret = GetLastError(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-16 16:40:02 +00:00
										 |  |  |     if (previousTpSize) { | 
					
						
							|  |  |  |         AdjustTokenPrivileges(token, FALSE, &previousTp.base, previousTpSize, | 
					
						
							|  |  |  |                               NULL, NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-01 01:31:21 +01:00
										 |  |  |     if (token != NULL) | 
					
						
							|  |  |  |         CloseHandle(token); | 
					
						
							|  |  |  |     if (junction != NULL) | 
					
						
							|  |  |  |         CloseHandle(junction); | 
					
						
							| 
									
										
										
										
											2014-05-05 19:46:17 +01:00
										 |  |  |     PyMem_RawFree(rdb); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ret != 0) | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(ret); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.CreateMutexW -> HANDLE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     security_attributes: LPSECURITY_ATTRIBUTES | 
					
						
							|  |  |  |     initial_owner: BOOL | 
					
						
							|  |  |  |     name: LPCWSTR(accept={str, NoneType}) | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HANDLE | 
					
						
							|  |  |  | _winapi_CreateMutexW_impl(PyObject *module, | 
					
						
							|  |  |  |                           LPSECURITY_ATTRIBUTES security_attributes, | 
					
						
							|  |  |  |                           BOOL initial_owner, LPCWSTR name) | 
					
						
							|  |  |  | /*[clinic end generated code: output=31b9ee8fc37e49a5 input=7d54b921e723254a]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PySys_Audit("_winapi.CreateMutexW", "bu", initial_owner, name) < 0) { | 
					
						
							|  |  |  |         return INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     handle = CreateMutexW(security_attributes, initial_owner, name); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (handle == INVALID_HANDLE_VALUE) { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return handle; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.CreateNamedPipe -> HANDLE | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  |     name: LPCWSTR | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     open_mode: DWORD | 
					
						
							|  |  |  |     pipe_mode: DWORD | 
					
						
							|  |  |  |     max_instances: DWORD | 
					
						
							|  |  |  |     out_buffer_size: DWORD | 
					
						
							|  |  |  |     in_buffer_size: DWORD | 
					
						
							|  |  |  |     default_timeout: DWORD | 
					
						
							|  |  |  |     security_attributes: LPSECURITY_ATTRIBUTES | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HANDLE | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  | _winapi_CreateNamedPipe_impl(PyObject *module, LPCWSTR name, DWORD open_mode, | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  |                              DWORD pipe_mode, DWORD max_instances, | 
					
						
							|  |  |  |                              DWORD out_buffer_size, DWORD in_buffer_size, | 
					
						
							|  |  |  |                              DWORD default_timeout, | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |                              LPSECURITY_ATTRIBUTES security_attributes) | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  | /*[clinic end generated code: output=7d6fde93227680ba input=5bd4e4a55639ee02]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  |     if (PySys_Audit("_winapi.CreateNamedPipe", "ukk", | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |                     name, open_mode, pipe_mode) < 0) { | 
					
						
							|  |  |  |         return INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  |     handle = CreateNamedPipeW(name, open_mode, pipe_mode, | 
					
						
							|  |  |  |                               max_instances, out_buffer_size, | 
					
						
							|  |  |  |                               in_buffer_size, default_timeout, | 
					
						
							|  |  |  |                               security_attributes); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (handle == INVALID_HANDLE_VALUE) | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |         PyErr_SetFromWindowsErr(0); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     return handle; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.CreatePipe | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pipe_attrs: object | 
					
						
							|  |  |  |         Ignored internally, can be None. | 
					
						
							|  |  |  |     size: DWORD | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Create an anonymous pipe. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Returns a 2-tuple of handles, to the read and write ends of the pipe. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_CreatePipe_impl(PyObject *module, PyObject *pipe_attrs, DWORD size) | 
					
						
							|  |  |  | /*[clinic end generated code: output=1c4411d8699f0925 input=c4f2cfa56ef68d90]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     HANDLE read_pipe; | 
					
						
							|  |  |  |     HANDLE write_pipe; | 
					
						
							|  |  |  |     BOOL result; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |     if (PySys_Audit("_winapi.CreatePipe", NULL) < 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     result = CreatePipe(&read_pipe, &write_pipe, NULL, size); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (! result) | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(GetLastError()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return Py_BuildValue( | 
					
						
							|  |  |  |         "NN", HANDLE_TO_PYNUM(read_pipe), HANDLE_TO_PYNUM(write_pipe)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* helpers for createprocess */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned long | 
					
						
							| 
									
										
										
										
											2015-12-25 20:01:53 +02:00
										 |  |  | getulong(PyObject* obj, const char* name) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject* value; | 
					
						
							|  |  |  |     unsigned long ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     value = PyObject_GetAttrString(obj, name); | 
					
						
							|  |  |  |     if (! value) { | 
					
						
							|  |  |  |         PyErr_Clear(); /* FIXME: propagate error? */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ret = PyLong_AsUnsignedLong(value); | 
					
						
							|  |  |  |     Py_DECREF(value); | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HANDLE | 
					
						
							| 
									
										
										
										
											2015-12-25 20:01:53 +02:00
										 |  |  | gethandle(PyObject* obj, const char* name) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject* value; | 
					
						
							|  |  |  |     HANDLE ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     value = PyObject_GetAttrString(obj, name); | 
					
						
							|  |  |  |     if (! value) { | 
					
						
							|  |  |  |         PyErr_Clear(); /* FIXME: propagate error? */ | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (value == Py_None) | 
					
						
							|  |  |  |         ret = NULL; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         ret = PYNUM_TO_HANDLE(value); | 
					
						
							|  |  |  |     Py_DECREF(value); | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-09 23:58:26 +08:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | sortenvironmentkey(PyObject *module, PyObject *item) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _winapi_LCMapStringEx_impl(NULL, LOCALE_NAME_INVARIANT, | 
					
						
							|  |  |  |                                       LCMAP_UPPERCASE, item); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef sortenvironmentkey_def = { | 
					
						
							|  |  |  |     "sortenvironmentkey", _PyCFunction_CAST(sortenvironmentkey), METH_O, "", | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | sort_environment_keys(PyObject *keys) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *keyfunc = PyCFunction_New(&sortenvironmentkey_def, NULL); | 
					
						
							|  |  |  |     if (keyfunc == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject *kwnames = Py_BuildValue("(s)", "key"); | 
					
						
							|  |  |  |     if (kwnames == NULL) { | 
					
						
							|  |  |  |         Py_DECREF(keyfunc); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject *args[] = { keys, keyfunc }; | 
					
						
							|  |  |  |     PyObject *ret = PyObject_VectorcallMethod(&_Py_ID(sort), args, 1, kwnames); | 
					
						
							|  |  |  |     Py_DECREF(keyfunc); | 
					
						
							|  |  |  |     Py_DECREF(kwnames); | 
					
						
							|  |  |  |     if (ret == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_DECREF(ret); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | compare_string_ordinal(PyObject *str1, PyObject *str2, int *result) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     wchar_t *s1 = PyUnicode_AsWideCharString(str1, NULL); | 
					
						
							|  |  |  |     if (s1 == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     wchar_t *s2 = PyUnicode_AsWideCharString(str2, NULL); | 
					
						
							|  |  |  |     if (s2 == NULL) { | 
					
						
							|  |  |  |         PyMem_Free(s1); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     *result = CompareStringOrdinal(s1, -1, s2, -1, TRUE); | 
					
						
							|  |  |  |     PyMem_Free(s1); | 
					
						
							|  |  |  |     PyMem_Free(s2); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | dedup_environment_keys(PyObject *keys) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *result = PyList_New(0); | 
					
						
							|  |  |  |     if (result == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Iterate over the pre-ordered keys, check whether the current key is equal
 | 
					
						
							|  |  |  |     // to the next key (ignoring case), if different, insert the current value
 | 
					
						
							|  |  |  |     // into the result list. If they are equal, do nothing because we always
 | 
					
						
							|  |  |  |     // want to keep the last inserted one.
 | 
					
						
							|  |  |  |     for (Py_ssize_t i = 0; i < PyList_GET_SIZE(keys); i++) { | 
					
						
							|  |  |  |         PyObject *key = PyList_GET_ITEM(keys, i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // The last key will always be kept.
 | 
					
						
							|  |  |  |         if (i + 1 == PyList_GET_SIZE(keys)) { | 
					
						
							|  |  |  |             if (PyList_Append(result, key) < 0) { | 
					
						
							|  |  |  |                 Py_DECREF(result); | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         PyObject *next_key = PyList_GET_ITEM(keys, i + 1); | 
					
						
							|  |  |  |         int compare_result; | 
					
						
							|  |  |  |         if (compare_string_ordinal(key, next_key, &compare_result) < 0) { | 
					
						
							|  |  |  |             Py_DECREF(result); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (compare_result == CSTR_EQUAL) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (PyList_Append(result, key) < 0) { | 
					
						
							|  |  |  |             Py_DECREF(result); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | normalize_environment(PyObject *environment) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *keys = PyMapping_Keys(environment); | 
					
						
							|  |  |  |     if (keys == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (sort_environment_keys(keys) < 0) { | 
					
						
							|  |  |  |         Py_DECREF(keys); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *normalized_keys = dedup_environment_keys(keys); | 
					
						
							|  |  |  |     Py_DECREF(keys); | 
					
						
							|  |  |  |     if (normalized_keys == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *result = PyDict_New(); | 
					
						
							|  |  |  |     if (result == NULL) { | 
					
						
							|  |  |  |         Py_DECREF(normalized_keys); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int i = 0; i < PyList_GET_SIZE(normalized_keys); i++) { | 
					
						
							|  |  |  |         PyObject *key = PyList_GET_ITEM(normalized_keys, i); | 
					
						
							|  |  |  |         PyObject *value = PyObject_GetItem(environment, key); | 
					
						
							|  |  |  |         if (value == NULL) { | 
					
						
							|  |  |  |             Py_DECREF(normalized_keys); | 
					
						
							|  |  |  |             Py_DECREF(result); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         int ret = PyObject_SetItem(result, key, value); | 
					
						
							|  |  |  |         Py_DECREF(value); | 
					
						
							|  |  |  |         if (ret < 0) { | 
					
						
							|  |  |  |             Py_DECREF(normalized_keys); | 
					
						
							|  |  |  |             Py_DECREF(result); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_DECREF(normalized_keys); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  | static wchar_t * | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | getenvironment(PyObject* environment) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t i, envsize, totalsize; | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |     wchar_t *buffer = NULL, *p, *end; | 
					
						
							| 
									
										
										
										
											2024-01-09 23:58:26 +08:00
										 |  |  |     PyObject *normalized_environment = NULL; | 
					
						
							|  |  |  |     PyObject *keys = NULL; | 
					
						
							|  |  |  |     PyObject *values = NULL; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-17 16:57:41 +03:00
										 |  |  |     /* convert environment dictionary to windows environment string */ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     if (! PyMapping_Check(environment)) { | 
					
						
							|  |  |  |         PyErr_SetString( | 
					
						
							|  |  |  |             PyExc_TypeError, "environment must be dictionary or None"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-09 23:58:26 +08:00
										 |  |  |     normalized_environment = normalize_environment(environment); | 
					
						
							| 
									
										
										
										
											2024-12-24 16:06:41 +03:00
										 |  |  |     if (normalized_environment == NULL) { | 
					
						
							| 
									
										
										
										
											2017-09-14 22:30:28 +03:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-01-09 23:58:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     keys = PyMapping_Keys(normalized_environment); | 
					
						
							|  |  |  |     if (!keys) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     values = PyMapping_Values(normalized_environment); | 
					
						
							| 
									
										
										
										
											2017-09-14 22:30:28 +03:00
										 |  |  |     if (!values) { | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         goto error; | 
					
						
							| 
									
										
										
										
											2017-09-14 22:30:28 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |     envsize = PyList_GET_SIZE(keys); | 
					
						
							| 
									
										
										
										
											2023-06-13 00:14:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (envsize == 0) { | 
					
						
							|  |  |  |         // A environment block must be terminated by two null characters --
 | 
					
						
							|  |  |  |         // one for the last string and one for the block.
 | 
					
						
							|  |  |  |         buffer = PyMem_Calloc(2, sizeof(wchar_t)); | 
					
						
							|  |  |  |         if (!buffer) { | 
					
						
							|  |  |  |             PyErr_NoMemory(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |     if (PyList_GET_SIZE(values) != envsize) { | 
					
						
							| 
									
										
										
										
											2017-04-19 20:03:52 +03:00
										 |  |  |         PyErr_SetString(PyExc_RuntimeError, | 
					
						
							|  |  |  |             "environment changed size during iteration"); | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     totalsize = 1; /* trailing null character */ | 
					
						
							|  |  |  |     for (i = 0; i < envsize; i++) { | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |         PyObject* key = PyList_GET_ITEM(keys, i); | 
					
						
							|  |  |  |         PyObject* value = PyList_GET_ITEM(values, i); | 
					
						
							|  |  |  |         Py_ssize_t size; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) { | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  |                 "environment can only contain strings"); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-06-23 19:39:27 +03:00
										 |  |  |         if (PyUnicode_FindChar(key, '\0', 0, PyUnicode_GET_LENGTH(key), 1) != -1 || | 
					
						
							|  |  |  |             PyUnicode_FindChar(value, '\0', 0, PyUnicode_GET_LENGTH(value), 1) != -1) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_ValueError, "embedded null character"); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /* Search from index 1 because on Windows starting '=' is allowed for
 | 
					
						
							|  |  |  |            defining hidden environment variables. */ | 
					
						
							|  |  |  |         if (PyUnicode_GET_LENGTH(key) == 0 || | 
					
						
							|  |  |  |             PyUnicode_FindChar(key, '=', 1, PyUnicode_GET_LENGTH(key), 1) != -1) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         size = PyUnicode_AsWideChar(key, NULL, 0); | 
					
						
							|  |  |  |         assert(size > 1); | 
					
						
							|  |  |  |         if (totalsize > PY_SSIZE_T_MAX - size) { | 
					
						
							| 
									
										
										
										
											2015-02-09 20:58:12 -05:00
										 |  |  |             PyErr_SetString(PyExc_OverflowError, "environment too long"); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |         totalsize += size;    /* including '=' */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         size = PyUnicode_AsWideChar(value, NULL, 0); | 
					
						
							|  |  |  |         assert(size > 0); | 
					
						
							|  |  |  |         if (totalsize > PY_SSIZE_T_MAX - size) { | 
					
						
							| 
									
										
										
										
											2015-02-09 20:58:12 -05:00
										 |  |  |             PyErr_SetString(PyExc_OverflowError, "environment too long"); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |         totalsize += size;  /* including trailing '\0' */ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |     buffer = PyMem_NEW(wchar_t, totalsize); | 
					
						
							| 
									
										
										
										
											2015-02-09 20:58:12 -05:00
										 |  |  |     if (! buffer) { | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         goto error; | 
					
						
							| 
									
										
										
										
											2015-02-09 20:58:12 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     p = buffer; | 
					
						
							|  |  |  |     end = buffer + totalsize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < envsize; i++) { | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |         PyObject* key = PyList_GET_ITEM(keys, i); | 
					
						
							|  |  |  |         PyObject* value = PyList_GET_ITEM(values, i); | 
					
						
							|  |  |  |         Py_ssize_t size = PyUnicode_AsWideChar(key, p, end - p); | 
					
						
							|  |  |  |         assert(1 <= size && size < end - p); | 
					
						
							|  |  |  |         p += size; | 
					
						
							|  |  |  |         *p++ = L'='; | 
					
						
							|  |  |  |         size = PyUnicode_AsWideChar(value, p, end - p); | 
					
						
							|  |  |  |         assert(0 <= size && size < end - p); | 
					
						
							|  |  |  |         p += size + 1; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |     /* add trailing null character */ | 
					
						
							|  |  |  |     *p++ = L'\0'; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     assert(p == end); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-13 00:14:55 +08:00
										 |  |  | cleanup: | 
					
						
							|  |  |  | error: | 
					
						
							| 
									
										
										
										
											2024-01-09 23:58:26 +08:00
										 |  |  |     Py_XDECREF(normalized_environment); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     Py_XDECREF(keys); | 
					
						
							|  |  |  |     Py_XDECREF(values); | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |     return buffer; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  | static LPHANDLE | 
					
						
							|  |  |  | gethandlelist(PyObject *mapping, const char *name, Py_ssize_t *size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     LPHANDLE ret = NULL; | 
					
						
							|  |  |  |     PyObject *value_fast = NULL; | 
					
						
							|  |  |  |     PyObject *value; | 
					
						
							|  |  |  |     Py_ssize_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     value = PyMapping_GetItemString(mapping, name); | 
					
						
							|  |  |  |     if (!value) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (value == Py_None) { | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     value_fast = PySequence_Fast(value, "handle_list must be a sequence or None"); | 
					
						
							|  |  |  |     if (value_fast == NULL) | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *size = PySequence_Fast_GET_SIZE(value_fast) * sizeof(HANDLE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Passing an empty array causes CreateProcess to fail so just don't set it */ | 
					
						
							|  |  |  |     if (*size == 0) { | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ret = PyMem_Malloc(*size); | 
					
						
							|  |  |  |     if (ret == NULL) | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < PySequence_Fast_GET_SIZE(value_fast); i++) { | 
					
						
							|  |  |  |         ret[i] = PYNUM_TO_HANDLE(PySequence_Fast_GET_ITEM(value_fast, i)); | 
					
						
							|  |  |  |         if (ret[i] == (HANDLE)-1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |             PyMem_Free(ret); | 
					
						
							|  |  |  |             ret = NULL; | 
					
						
							|  |  |  |             goto cleanup; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cleanup: | 
					
						
							|  |  |  |     Py_DECREF(value); | 
					
						
							|  |  |  |     Py_XDECREF(value_fast); | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     LPPROC_THREAD_ATTRIBUTE_LIST attribute_list; | 
					
						
							|  |  |  |     LPHANDLE handle_list; | 
					
						
							|  |  |  | } AttributeList; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | freeattributelist(AttributeList *attribute_list) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (attribute_list->attribute_list != NULL) { | 
					
						
							|  |  |  |         DeleteProcThreadAttributeList(attribute_list->attribute_list); | 
					
						
							|  |  |  |         PyMem_Free(attribute_list->attribute_list); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyMem_Free(attribute_list->handle_list); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memset(attribute_list, 0, sizeof(*attribute_list)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | getattributelist(PyObject *obj, const char *name, AttributeList *attribute_list) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret = 0; | 
					
						
							|  |  |  |     DWORD err; | 
					
						
							|  |  |  |     BOOL result; | 
					
						
							|  |  |  |     PyObject *value; | 
					
						
							|  |  |  |     Py_ssize_t handle_list_size; | 
					
						
							|  |  |  |     DWORD attribute_count = 0; | 
					
						
							|  |  |  |     SIZE_T attribute_list_size = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     value = PyObject_GetAttrString(obj, name); | 
					
						
							|  |  |  |     if (!value) { | 
					
						
							|  |  |  |         PyErr_Clear(); /* FIXME: propagate error? */ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (value == Py_None) { | 
					
						
							|  |  |  |         ret = 0; | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyMapping_Check(value)) { | 
					
						
							|  |  |  |         ret = -1; | 
					
						
							|  |  |  |         PyErr_Format(PyExc_TypeError, "%s must be a mapping or None", name); | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     attribute_list->handle_list = gethandlelist(value, "handle_list", &handle_list_size); | 
					
						
							|  |  |  |     if (attribute_list->handle_list == NULL && PyErr_Occurred()) { | 
					
						
							|  |  |  |         ret = -1; | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (attribute_list->handle_list != NULL) | 
					
						
							|  |  |  |         ++attribute_count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Get how many bytes we need for the attribute list */ | 
					
						
							|  |  |  |     result = InitializeProcThreadAttributeList(NULL, attribute_count, 0, &attribute_list_size); | 
					
						
							|  |  |  |     if (result || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { | 
					
						
							|  |  |  |         ret = -1; | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(GetLastError()); | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     attribute_list->attribute_list = PyMem_Malloc(attribute_list_size); | 
					
						
							|  |  |  |     if (attribute_list->attribute_list == NULL) { | 
					
						
							|  |  |  |         ret = -1; | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = InitializeProcThreadAttributeList( | 
					
						
							|  |  |  |         attribute_list->attribute_list, | 
					
						
							|  |  |  |         attribute_count, | 
					
						
							|  |  |  |         0, | 
					
						
							|  |  |  |         &attribute_list_size); | 
					
						
							|  |  |  |     if (!result) { | 
					
						
							|  |  |  |         err = GetLastError(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* So that we won't call DeleteProcThreadAttributeList */ | 
					
						
							|  |  |  |         PyMem_Free(attribute_list->attribute_list); | 
					
						
							|  |  |  |         attribute_list->attribute_list = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ret = -1; | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(err); | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (attribute_list->handle_list != NULL) { | 
					
						
							|  |  |  |         result = UpdateProcThreadAttribute( | 
					
						
							|  |  |  |             attribute_list->attribute_list, | 
					
						
							|  |  |  |             0, | 
					
						
							|  |  |  |             PROC_THREAD_ATTRIBUTE_HANDLE_LIST, | 
					
						
							|  |  |  |             attribute_list->handle_list, | 
					
						
							|  |  |  |             handle_list_size, | 
					
						
							|  |  |  |             NULL, | 
					
						
							|  |  |  |             NULL); | 
					
						
							|  |  |  |         if (!result) { | 
					
						
							|  |  |  |             ret = -1; | 
					
						
							|  |  |  |             PyErr_SetFromWindowsErr(GetLastError()); | 
					
						
							|  |  |  |             goto cleanup; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cleanup: | 
					
						
							|  |  |  |     Py_DECREF(value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ret < 0) | 
					
						
							|  |  |  |         freeattributelist(attribute_list); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.CreateProcess | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |     application_name: Py_UNICODE(accept={str, NoneType}) | 
					
						
							| 
									
										
										
										
											2018-12-14 00:30:51 -08:00
										 |  |  |     command_line: object | 
					
						
							|  |  |  |         Can be str or None | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     proc_attrs: object | 
					
						
							|  |  |  |         Ignored internally, can be None. | 
					
						
							|  |  |  |     thread_attrs: object | 
					
						
							|  |  |  |         Ignored internally, can be None. | 
					
						
							|  |  |  |     inherit_handles: BOOL | 
					
						
							|  |  |  |     creation_flags: DWORD | 
					
						
							|  |  |  |     env_mapping: object | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |     current_directory: Py_UNICODE(accept={str, NoneType}) | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     startup_info: object | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Create a new process and its primary thread. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The return value is a tuple of the process handle, thread handle, | 
					
						
							|  |  |  | process ID, and thread ID. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2023-05-31 19:52:33 +02:00
										 |  |  | _winapi_CreateProcess_impl(PyObject *module, const wchar_t *application_name, | 
					
						
							| 
									
										
										
										
											2018-12-14 00:30:51 -08:00
										 |  |  |                            PyObject *command_line, PyObject *proc_attrs, | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |                            PyObject *thread_attrs, BOOL inherit_handles, | 
					
						
							|  |  |  |                            DWORD creation_flags, PyObject *env_mapping, | 
					
						
							| 
									
										
										
										
											2023-05-31 19:52:33 +02:00
										 |  |  |                            const wchar_t *current_directory, | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |                            PyObject *startup_info) | 
					
						
							| 
									
										
										
										
											2023-05-31 19:52:33 +02:00
										 |  |  | /*[clinic end generated code: output=a25c8e49ea1d6427 input=42ac293eaea03fc4]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |     PyObject *ret = NULL; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     BOOL result; | 
					
						
							|  |  |  |     PROCESS_INFORMATION pi; | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |     STARTUPINFOEXW si; | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |     wchar_t *wenvironment = NULL; | 
					
						
							| 
									
										
										
										
											2018-12-14 00:30:51 -08:00
										 |  |  |     wchar_t *command_line_copy = NULL; | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |     AttributeList attribute_list = {0}; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |     if (PySys_Audit("_winapi.CreateProcess", "uuu", application_name, | 
					
						
							|  |  |  |                     command_line, current_directory) < 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     ZeroMemory(&si, sizeof(si)); | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |     si.StartupInfo.cb = sizeof(si); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* note: we only support a small subset of all SI attributes */ | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |     si.StartupInfo.dwFlags = getulong(startup_info, "dwFlags"); | 
					
						
							|  |  |  |     si.StartupInfo.wShowWindow = (WORD)getulong(startup_info, "wShowWindow"); | 
					
						
							|  |  |  |     si.StartupInfo.hStdInput = gethandle(startup_info, "hStdInput"); | 
					
						
							|  |  |  |     si.StartupInfo.hStdOutput = gethandle(startup_info, "hStdOutput"); | 
					
						
							|  |  |  |     si.StartupInfo.hStdError = gethandle(startup_info, "hStdError"); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     if (PyErr_Occurred()) | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |         goto cleanup; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (env_mapping != Py_None) { | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |         wenvironment = getenvironment(env_mapping); | 
					
						
							| 
									
										
										
										
											2017-06-23 19:39:27 +03:00
										 |  |  |         if (wenvironment == NULL) { | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |             goto cleanup; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |     if (getattributelist(startup_info, "lpAttributeList", &attribute_list) < 0) | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     si.lpAttributeList = attribute_list.attribute_list; | 
					
						
							| 
									
										
										
										
											2018-12-14 00:30:51 -08:00
										 |  |  |     if (PyUnicode_Check(command_line)) { | 
					
						
							|  |  |  |         command_line_copy = PyUnicode_AsWideCharString(command_line, NULL); | 
					
						
							|  |  |  |         if (command_line_copy == NULL) { | 
					
						
							|  |  |  |             goto cleanup; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (command_line != Py_None) { | 
					
						
							| 
									
										
										
										
											2020-04-15 02:35:41 +02:00
										 |  |  |         PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                      "CreateProcess() argument 2 must be str or None, not %s", | 
					
						
							| 
									
										
										
										
											2018-12-14 00:30:51 -08:00
										 |  |  |                      Py_TYPE(command_line)->tp_name); | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     result = CreateProcessW(application_name, | 
					
						
							| 
									
										
										
										
											2018-12-14 00:30:51 -08:00
										 |  |  |                            command_line_copy, | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |                            NULL, | 
					
						
							|  |  |  |                            NULL, | 
					
						
							|  |  |  |                            inherit_handles, | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |                            creation_flags | EXTENDED_STARTUPINFO_PRESENT | | 
					
						
							|  |  |  |                            CREATE_UNICODE_ENVIRONMENT, | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |                            wenvironment, | 
					
						
							|  |  |  |                            current_directory, | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |                            (LPSTARTUPINFOW)&si, | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |                            &pi); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |     if (!result) { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(GetLastError()); | 
					
						
							|  |  |  |         goto cleanup; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |     ret = Py_BuildValue("NNkk", | 
					
						
							|  |  |  |                         HANDLE_TO_PYNUM(pi.hProcess), | 
					
						
							|  |  |  |                         HANDLE_TO_PYNUM(pi.hThread), | 
					
						
							|  |  |  |                         pi.dwProcessId, | 
					
						
							|  |  |  |                         pi.dwThreadId); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  | cleanup: | 
					
						
							| 
									
										
										
										
											2018-12-14 00:30:51 -08:00
										 |  |  |     PyMem_Free(command_line_copy); | 
					
						
							| 
									
										
										
										
											2019-03-28 16:01:34 +02:00
										 |  |  |     PyMem_Free(wenvironment); | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |     freeattributelist(&attribute_list); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.DuplicateHandle -> HANDLE | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     source_process_handle: HANDLE | 
					
						
							|  |  |  |     source_handle: HANDLE | 
					
						
							|  |  |  |     target_process_handle: HANDLE | 
					
						
							|  |  |  |     desired_access: DWORD | 
					
						
							|  |  |  |     inherit_handle: BOOL | 
					
						
							|  |  |  |     options: DWORD = 0 | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Return a duplicate handle object. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The duplicate handle refers to the same object as the original | 
					
						
							|  |  |  | handle. Therefore, any changes to the object are reflected | 
					
						
							|  |  |  | through both handles. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HANDLE | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_DuplicateHandle_impl(PyObject *module, HANDLE source_process_handle, | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |                              HANDLE source_handle, | 
					
						
							|  |  |  |                              HANDLE target_process_handle, | 
					
						
							|  |  |  |                              DWORD desired_access, BOOL inherit_handle, | 
					
						
							|  |  |  |                              DWORD options) | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | /*[clinic end generated code: output=ad9711397b5dcd4e input=b933e3f2356a8c12]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     HANDLE target_handle; | 
					
						
							|  |  |  |     BOOL result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     result = DuplicateHandle( | 
					
						
							|  |  |  |         source_process_handle, | 
					
						
							|  |  |  |         source_handle, | 
					
						
							|  |  |  |         target_process_handle, | 
					
						
							|  |  |  |         &target_handle, | 
					
						
							|  |  |  |         desired_access, | 
					
						
							|  |  |  |         inherit_handle, | 
					
						
							|  |  |  |         options | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     if (! result) { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(GetLastError()); | 
					
						
							|  |  |  |         return INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     return target_handle; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.ExitProcess | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     ExitCode: UINT | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_ExitProcess_impl(PyObject *module, UINT ExitCode) | 
					
						
							|  |  |  | /*[clinic end generated code: output=a387deb651175301 input=4f05466a9406c558]*/ | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     #if defined(Py_DEBUG)
 | 
					
						
							| 
									
										
										
										
											2023-03-09 22:09:12 +01:00
										 |  |  | #ifdef MS_WINDOWS_DESKTOP
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT| | 
					
						
							|  |  |  |                      SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX); | 
					
						
							| 
									
										
										
										
											2023-03-09 22:09:12 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); | 
					
						
							|  |  |  |     #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     ExitProcess(ExitCode); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.GetCurrentProcess -> HANDLE | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | Return a handle object for the current process. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | static HANDLE | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_GetCurrentProcess_impl(PyObject *module) | 
					
						
							|  |  |  | /*[clinic end generated code: output=ddeb4dd2ffadf344 input=b213403fd4b96b41]*/ | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | { | 
					
						
							|  |  |  |     return GetCurrentProcess(); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.GetExitCodeProcess -> DWORD | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     process: HANDLE | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Return the termination status of the specified process. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static DWORD | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_GetExitCodeProcess_impl(PyObject *module, HANDLE process) | 
					
						
							|  |  |  | /*[clinic end generated code: output=b4620bdf2bccf36b input=61b6bfc7dc2ee374]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     DWORD exit_code; | 
					
						
							|  |  |  |     BOOL result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = GetExitCodeProcess(process, &exit_code); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     if (! result) { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(GetLastError()); | 
					
						
							| 
									
										
										
										
											2017-10-24 16:53:32 -07:00
										 |  |  |         exit_code = PY_DWORD_MAX; | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     return exit_code; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.GetLastError -> DWORD | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static DWORD | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_GetLastError_impl(PyObject *module) | 
					
						
							|  |  |  | /*[clinic end generated code: output=8585b827cb1a92c5 input=62d47fb9bce038ba]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     return GetLastError(); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-15 15:36:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.GetLongPathName | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     path: LPCWSTR | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Return the long version of the provided path. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If the path is already in its long form, returns the same value. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The path must already be a 'str'. If the type is not known, use | 
					
						
							|  |  |  | os.fsdecode before calling this function. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _winapi_GetLongPathName_impl(PyObject *module, LPCWSTR path) | 
					
						
							|  |  |  | /*[clinic end generated code: output=c4774b080275a2d0 input=9872e211e3a4a88f]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DWORD cchBuffer; | 
					
						
							|  |  |  |     PyObject *result = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     cchBuffer = GetLongPathNameW(path, NULL, 0); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |     if (cchBuffer) { | 
					
						
							|  |  |  |         WCHAR *buffer = (WCHAR *)PyMem_Malloc(cchBuffer * sizeof(WCHAR)); | 
					
						
							|  |  |  |         if (buffer) { | 
					
						
							|  |  |  |             Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |             cchBuffer = GetLongPathNameW(path, buffer, cchBuffer); | 
					
						
							|  |  |  |             Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |             if (cchBuffer) { | 
					
						
							|  |  |  |                 result = PyUnicode_FromWideChar(buffer, cchBuffer); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             PyMem_Free((void *)buffer); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.GetModuleFileName | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     module_handle: HMODULE | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Return the fully-qualified path for the file that contains module. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The module must have been loaded by the current process. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The module parameter should be a handle to the loaded module | 
					
						
							|  |  |  | whose path is being requested. If this parameter is 0, | 
					
						
							|  |  |  | GetModuleFileName retrieves the path of the executable file | 
					
						
							|  |  |  | of the current process. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_GetModuleFileName_impl(PyObject *module, HMODULE module_handle) | 
					
						
							|  |  |  | /*[clinic end generated code: output=85b4b728c5160306 input=6d66ff7deca5d11f]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     BOOL result; | 
					
						
							|  |  |  |     WCHAR filename[MAX_PATH]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     result = GetModuleFileNameW(module_handle, filename, MAX_PATH); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     filename[MAX_PATH-1] = '\0'; | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |     Py_END_ALLOW_THREADS | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (! result) | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(GetLastError()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return PyUnicode_FromWideChar(filename, wcslen(filename)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-15 15:36:06 +01:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.GetShortPathName | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     path: LPCWSTR | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Return the short version of the provided path. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If the path is already in its short form, returns the same value. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The path must already be a 'str'. If the type is not known, use | 
					
						
							|  |  |  | os.fsdecode before calling this function. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _winapi_GetShortPathName_impl(PyObject *module, LPCWSTR path) | 
					
						
							|  |  |  | /*[clinic end generated code: output=dab6ae494c621e81 input=43fa349aaf2ac718]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DWORD cchBuffer; | 
					
						
							|  |  |  |     PyObject *result = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     cchBuffer = GetShortPathNameW(path, NULL, 0); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |     if (cchBuffer) { | 
					
						
							|  |  |  |         WCHAR *buffer = (WCHAR *)PyMem_Malloc(cchBuffer * sizeof(WCHAR)); | 
					
						
							|  |  |  |         if (buffer) { | 
					
						
							|  |  |  |             Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |             cchBuffer = GetShortPathNameW(path, buffer, cchBuffer); | 
					
						
							|  |  |  |             Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |             if (cchBuffer) { | 
					
						
							|  |  |  |                 result = PyUnicode_FromWideChar(buffer, cchBuffer); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             PyMem_Free((void *)buffer); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.GetStdHandle -> HANDLE | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     std_handle: DWORD | 
					
						
							|  |  |  |         One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE. | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Return a handle to the specified standard device. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The integer associated with the handle object is returned. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HANDLE | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_GetStdHandle_impl(PyObject *module, DWORD std_handle) | 
					
						
							|  |  |  | /*[clinic end generated code: output=0e613001e73ab614 input=07016b06a2fc8826]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     handle = GetStdHandle(std_handle); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (handle == INVALID_HANDLE_VALUE) | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |         PyErr_SetFromWindowsErr(GetLastError()); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     return handle; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.GetVersion -> long | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Return the version number of the current operating system. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | static long | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_GetVersion_impl(PyObject *module) | 
					
						
							|  |  |  | /*[clinic end generated code: output=e41f0db5a3b82682 input=e21dff8d0baeded2]*/ | 
					
						
							| 
									
										
										
										
											2015-03-02 08:01:10 -08:00
										 |  |  | /* Disable deprecation warnings about GetVersionEx as the result is
 | 
					
						
							|  |  |  |    being passed straight through to the caller, who is responsible for | 
					
						
							|  |  |  |    using it correctly. */ | 
					
						
							|  |  |  | #pragma warning(push)
 | 
					
						
							|  |  |  | #pragma warning(disable:4996)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     return GetVersion(); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-02 08:01:10 -08:00
										 |  |  | #pragma warning(pop)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.MapViewOfFile -> LPVOID | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     file_map: HANDLE | 
					
						
							|  |  |  |     desired_access: DWORD | 
					
						
							|  |  |  |     file_offset_high: DWORD | 
					
						
							|  |  |  |     file_offset_low: DWORD | 
					
						
							|  |  |  |     number_bytes: size_t | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) | 
					
						
							|  |  |  | /*[clinic end generated code: output=f23b1ee4823663e3 input=177471073be1a103]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     LPVOID address; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     address = MapViewOfFile(file_map, desired_access, file_offset_high, | 
					
						
							|  |  |  |                             file_offset_low, number_bytes); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (address == NULL) | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return address; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-25 09:39:48 -08:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.UnmapViewOfFile | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     address: LPCVOID | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _winapi_UnmapViewOfFile_impl(PyObject *module, LPCVOID address) | 
					
						
							|  |  |  | /*[clinic end generated code: output=4f7e18ac75d19744 input=8c4b6119ad9288a3]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BOOL success; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     success = UnmapViewOfFile(address); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!success) { | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.OpenEventW -> HANDLE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     desired_access: DWORD | 
					
						
							|  |  |  |     inherit_handle: BOOL | 
					
						
							|  |  |  |     name: LPCWSTR | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HANDLE | 
					
						
							|  |  |  | _winapi_OpenEventW_impl(PyObject *module, DWORD desired_access, | 
					
						
							|  |  |  |                         BOOL inherit_handle, LPCWSTR name) | 
					
						
							|  |  |  | /*[clinic end generated code: output=c4a45e95545a4bd2 input=dec26598748d35aa]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  |     if (PySys_Audit("_winapi.OpenEventW", "ku", desired_access, name) < 0) { | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  |         return INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     handle = OpenEventW(desired_access, inherit_handle, name); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (handle == INVALID_HANDLE_VALUE) { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return handle; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.OpenMutexW -> HANDLE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     desired_access: DWORD | 
					
						
							|  |  |  |     inherit_handle: BOOL | 
					
						
							|  |  |  |     name: LPCWSTR | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HANDLE | 
					
						
							|  |  |  | _winapi_OpenMutexW_impl(PyObject *module, DWORD desired_access, | 
					
						
							|  |  |  |                         BOOL inherit_handle, LPCWSTR name) | 
					
						
							|  |  |  | /*[clinic end generated code: output=dda39d7844397bf0 input=f3a7b466c5307712]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  |     if (PySys_Audit("_winapi.OpenMutexW", "ku", desired_access, name) < 0) { | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  |         return INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     handle = OpenMutexW(desired_access, inherit_handle, name); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (handle == INVALID_HANDLE_VALUE) { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return handle; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.OpenFileMapping -> HANDLE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     desired_access: DWORD | 
					
						
							|  |  |  |     inherit_handle: BOOL | 
					
						
							|  |  |  |     name: LPCWSTR | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HANDLE | 
					
						
							|  |  |  | _winapi_OpenFileMapping_impl(PyObject *module, DWORD desired_access, | 
					
						
							|  |  |  |                              BOOL inherit_handle, LPCWSTR name) | 
					
						
							|  |  |  | /*[clinic end generated code: output=08cc44def1cb11f1 input=131f2a405359de7f]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     handle = OpenFileMappingW(desired_access, inherit_handle, name); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (handle == NULL) { | 
					
						
							| 
									
										
										
										
											2019-05-30 01:58:50 -06:00
										 |  |  |         PyObject *temp = PyUnicode_FromWideChar(name, -1); | 
					
						
							|  |  |  |         PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, temp); | 
					
						
							|  |  |  |         Py_XDECREF(temp); | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  |         handle = INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return handle; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.OpenProcess -> HANDLE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     desired_access: DWORD | 
					
						
							|  |  |  |     inherit_handle: BOOL | 
					
						
							|  |  |  |     process_id: DWORD | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static HANDLE | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_OpenProcess_impl(PyObject *module, DWORD desired_access, | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |                          BOOL inherit_handle, DWORD process_id) | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | /*[clinic end generated code: output=b42b6b81ea5a0fc3 input=ec98c4cf4ea2ec36]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  |     if (PySys_Audit("_winapi.OpenProcess", "kk", | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |                     process_id, desired_access) < 0) { | 
					
						
							|  |  |  |         return INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     handle = OpenProcess(desired_access, inherit_handle, process_id); | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |     Py_END_ALLOW_THREADS | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     if (handle == NULL) { | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |         PyErr_SetFromWindowsErr(GetLastError()); | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |         handle = INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     return handle; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.PeekNamedPipe | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     handle: HANDLE | 
					
						
							|  |  |  |     size: int = 0 | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_PeekNamedPipe_impl(PyObject *module, HANDLE handle, int size) | 
					
						
							|  |  |  | /*[clinic end generated code: output=d0c3e29e49d323dd input=c7aa53bfbce69d70]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject *buf = NULL; | 
					
						
							|  |  |  |     DWORD nread, navail, nleft; | 
					
						
							|  |  |  |     BOOL ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (size < 0) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, "negative size"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (size) { | 
					
						
							|  |  |  |         buf = PyBytes_FromStringAndSize(NULL, size); | 
					
						
							|  |  |  |         if (!buf) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |         ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread, | 
					
						
							|  |  |  |                             &navail, &nleft); | 
					
						
							|  |  |  |         Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |         if (!ret) { | 
					
						
							|  |  |  |             Py_DECREF(buf); | 
					
						
							| 
									
										
										
										
											2017-04-16 10:46:38 +03:00
										 |  |  |             return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (_PyBytes_Resize(&buf, nread)) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2018-09-04 19:10:28 +03:00
										 |  |  |         return Py_BuildValue("NII", buf, navail, nleft); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |         ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft); | 
					
						
							|  |  |  |         Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |         if (!ret) { | 
					
						
							| 
									
										
										
										
											2017-04-16 10:46:38 +03:00
										 |  |  |             return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-09-04 19:10:28 +03:00
										 |  |  |         return Py_BuildValue("II", navail, nleft); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-07 07:47:27 +08:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.LCMapStringEx | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     locale: LPCWSTR | 
					
						
							|  |  |  |     flags: DWORD | 
					
						
							| 
									
										
										
										
											2023-08-11 21:13:46 +03:00
										 |  |  |     src: unicode | 
					
						
							| 
									
										
										
										
											2022-06-07 07:47:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _winapi_LCMapStringEx_impl(PyObject *module, LPCWSTR locale, DWORD flags, | 
					
						
							| 
									
										
										
										
											2023-08-11 21:13:46 +03:00
										 |  |  |                            PyObject *src) | 
					
						
							|  |  |  | /*[clinic end generated code: output=b90e6b26e028ff0a input=3e3dcd9b8164012f]*/ | 
					
						
							| 
									
										
										
										
											2022-06-07 07:47:27 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     if (flags & (LCMAP_SORTHANDLE | LCMAP_HASH | LCMAP_BYTEREV | | 
					
						
							|  |  |  |                  LCMAP_SORTKEY)) { | 
					
						
							|  |  |  |         return PyErr_Format(PyExc_ValueError, "unsupported flags"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 21:13:46 +03:00
										 |  |  |     Py_ssize_t src_size; | 
					
						
							|  |  |  |     wchar_t *src_ = PyUnicode_AsWideCharString(src, &src_size); | 
					
						
							|  |  |  |     if (!src_) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (src_size > INT_MAX) { | 
					
						
							|  |  |  |         PyMem_Free(src_); | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_OverflowError, "input string is too long"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int dest_size = LCMapStringEx(locale, flags, src_, (int)src_size, NULL, 0, | 
					
						
							| 
									
										
										
										
											2022-06-07 07:47:27 +08:00
										 |  |  |                                   NULL, NULL, 0); | 
					
						
							| 
									
										
										
										
											2023-08-11 21:13:46 +03:00
										 |  |  |     if (dest_size <= 0) { | 
					
						
							|  |  |  |         DWORD error = GetLastError(); | 
					
						
							|  |  |  |         PyMem_Free(src_); | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(error); | 
					
						
							| 
									
										
										
										
											2022-06-07 07:47:27 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     wchar_t* dest = PyMem_NEW(wchar_t, dest_size); | 
					
						
							|  |  |  |     if (dest == NULL) { | 
					
						
							| 
									
										
										
										
											2023-08-11 21:13:46 +03:00
										 |  |  |         PyMem_Free(src_); | 
					
						
							| 
									
										
										
										
											2022-06-07 07:47:27 +08:00
										 |  |  |         return PyErr_NoMemory(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 21:13:46 +03:00
										 |  |  |     int nmapped = LCMapStringEx(locale, flags, src_, (int)src_size, dest, dest_size, | 
					
						
							| 
									
										
										
										
											2022-06-07 07:47:27 +08:00
										 |  |  |                                 NULL, NULL, 0); | 
					
						
							| 
									
										
										
										
											2023-08-11 21:13:46 +03:00
										 |  |  |     if (nmapped <= 0) { | 
					
						
							| 
									
										
										
										
											2022-06-07 07:47:27 +08:00
										 |  |  |         DWORD error = GetLastError(); | 
					
						
							| 
									
										
										
										
											2023-08-11 21:13:46 +03:00
										 |  |  |         PyMem_Free(src_); | 
					
						
							| 
									
										
										
										
											2022-06-07 07:47:27 +08:00
										 |  |  |         PyMem_DEL(dest); | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(error); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 21:13:46 +03:00
										 |  |  |     PyMem_Free(src_); | 
					
						
							|  |  |  |     PyObject *ret = PyUnicode_FromWideChar(dest, nmapped); | 
					
						
							| 
									
										
										
										
											2022-06-07 07:47:27 +08:00
										 |  |  |     PyMem_DEL(dest); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.ReadFile | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     handle: HANDLE | 
					
						
							| 
									
										
										
										
											2018-09-04 19:10:28 +03:00
										 |  |  |     size: DWORD | 
					
						
							| 
									
										
										
										
											2022-12-03 21:52:21 +02:00
										 |  |  |     overlapped as use_overlapped: bool = False | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2018-09-04 19:10:28 +03:00
										 |  |  | _winapi_ReadFile_impl(PyObject *module, HANDLE handle, DWORD size, | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |                       int use_overlapped) | 
					
						
							| 
									
										
										
										
											2022-12-03 21:52:21 +02:00
										 |  |  | /*[clinic end generated code: output=d3d5b44a8201b944 input=4f82f8e909ad91ad]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     DWORD nread; | 
					
						
							|  |  |  |     PyObject *buf; | 
					
						
							|  |  |  |     BOOL ret; | 
					
						
							|  |  |  |     DWORD err; | 
					
						
							|  |  |  |     OverlappedObject *overlapped = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     buf = PyBytes_FromStringAndSize(NULL, size); | 
					
						
							|  |  |  |     if (!buf) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     if (use_overlapped) { | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |         overlapped = new_overlapped(module, handle); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         if (!overlapped) { | 
					
						
							|  |  |  |             Py_DECREF(buf); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /* Steals reference to buf */ | 
					
						
							|  |  |  |         overlapped->read_buffer = buf; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread, | 
					
						
							|  |  |  |                    overlapped ? &overlapped->overlapped : NULL); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     err = ret ? 0 : GetLastError(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (overlapped) { | 
					
						
							|  |  |  |         if (!ret) { | 
					
						
							|  |  |  |             if (err == ERROR_IO_PENDING) | 
					
						
							|  |  |  |                 overlapped->pending = 1; | 
					
						
							|  |  |  |             else if (err != ERROR_MORE_DATA) { | 
					
						
							|  |  |  |                 Py_DECREF(overlapped); | 
					
						
							| 
									
										
										
										
											2017-04-16 10:46:38 +03:00
										 |  |  |                 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return Py_BuildValue("NI", (PyObject *) overlapped, err); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!ret && err != ERROR_MORE_DATA) { | 
					
						
							|  |  |  |         Py_DECREF(buf); | 
					
						
							| 
									
										
										
										
											2017-04-16 10:46:38 +03:00
										 |  |  |         return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (_PyBytes_Resize(&buf, nread)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     return Py_BuildValue("NI", buf, err); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.ReleaseMutex | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mutex: HANDLE | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _winapi_ReleaseMutex_impl(PyObject *module, HANDLE mutex) | 
					
						
							|  |  |  | /*[clinic end generated code: output=5b9001a72dd8af37 input=49e9d20de3559d84]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int err = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     if (!ReleaseMutex(mutex)) { | 
					
						
							|  |  |  |         err = GetLastError(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |     if (err) { | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(err); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.ResetEvent | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     event: HANDLE | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _winapi_ResetEvent_impl(PyObject *module, HANDLE event) | 
					
						
							|  |  |  | /*[clinic end generated code: output=81c8501d57c0530d input=e2d42d990322e87a]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int err = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     if (!ResetEvent(event)) { | 
					
						
							|  |  |  |         err = GetLastError(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |     if (err) { | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(err); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.SetEvent | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     event: HANDLE | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _winapi_SetEvent_impl(PyObject *module, HANDLE event) | 
					
						
							|  |  |  | /*[clinic end generated code: output=c18ba09eb9aa774d input=e660e830a37c09f8]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int err = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     if (!SetEvent(event)) { | 
					
						
							|  |  |  |         err = GetLastError(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |     if (err) { | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(err); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.SetNamedPipeHandleState | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     named_pipe: HANDLE | 
					
						
							|  |  |  |     mode: object | 
					
						
							|  |  |  |     max_collection_count: object | 
					
						
							|  |  |  |     collect_data_timeout: object | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_SetNamedPipeHandleState_impl(PyObject *module, HANDLE named_pipe, | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |                                      PyObject *mode, | 
					
						
							|  |  |  |                                      PyObject *max_collection_count, | 
					
						
							|  |  |  |                                      PyObject *collect_data_timeout) | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | /*[clinic end generated code: output=f2129d222cbfa095 input=9142d72163d0faa6]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     PyObject *oArgs[3] = {mode, max_collection_count, collect_data_timeout}; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL}; | 
					
						
							|  |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |     BOOL b; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0 ; i < 3 ; i++) { | 
					
						
							|  |  |  |         if (oArgs[i] != Py_None) { | 
					
						
							|  |  |  |             dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]); | 
					
						
							|  |  |  |             if (PyErr_Occurred()) | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             pArgs[i] = &dwArgs[i]; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     b = SetNamedPipeHandleState(named_pipe, pArgs[0], pArgs[1], pArgs[2]); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!b) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         return PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.TerminateProcess | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     handle: HANDLE | 
					
						
							|  |  |  |     exit_code: UINT | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Terminate the specified process and all of its threads. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_TerminateProcess_impl(PyObject *module, HANDLE handle, | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |                               UINT exit_code) | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | /*[clinic end generated code: output=f4e99ac3f0b1f34a input=d6bc0aa1ee3bb4df]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     BOOL result; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-23 08:45:22 -07:00
										 |  |  |     if (PySys_Audit("_winapi.TerminateProcess", "nI", | 
					
						
							|  |  |  |                     (Py_ssize_t)handle, exit_code) < 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     result = TerminateProcess(handle, exit_code); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (! result) | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(GetLastError()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.VirtualQuerySize -> size_t | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     address: LPCVOID | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static size_t | 
					
						
							|  |  |  | _winapi_VirtualQuerySize_impl(PyObject *module, LPCVOID address) | 
					
						
							|  |  |  | /*[clinic end generated code: output=40c8e0ff5ec964df input=6b784a69755d0bb6]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     SIZE_T size_of_buf; | 
					
						
							|  |  |  |     MEMORY_BASIC_INFORMATION mem_basic_info; | 
					
						
							|  |  |  |     SIZE_T region_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     size_of_buf = VirtualQuery(address, &mem_basic_info, sizeof(mem_basic_info)); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (size_of_buf == 0) | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     region_size = mem_basic_info.RegionSize; | 
					
						
							|  |  |  |     return region_size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.WaitNamedPipe | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  |     name: LPCWSTR | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     timeout: DWORD | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  | _winapi_WaitNamedPipe_impl(PyObject *module, LPCWSTR name, DWORD timeout) | 
					
						
							|  |  |  | /*[clinic end generated code: output=e161e2e630b3e9c2 input=099a4746544488fa]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     BOOL success; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  |     success = WaitNamedPipeW(name, timeout); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!success) | 
					
						
							|  |  |  |         return PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     HANDLE handles[MAXIMUM_WAIT_OBJECTS]; | 
					
						
							|  |  |  |     HANDLE cancel_event; | 
					
						
							|  |  |  |     DWORD handle_base; | 
					
						
							|  |  |  |     DWORD handle_count; | 
					
						
							|  |  |  |     HANDLE thread; | 
					
						
							|  |  |  |     volatile DWORD result; | 
					
						
							|  |  |  | } BatchedWaitData; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static DWORD WINAPI | 
					
						
							|  |  |  | _batched_WaitForMultipleObjects_thread(LPVOID param) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BatchedWaitData *data = (BatchedWaitData *)param; | 
					
						
							|  |  |  |     data->result = WaitForMultipleObjects( | 
					
						
							|  |  |  |         data->handle_count, | 
					
						
							|  |  |  |         data->handles, | 
					
						
							|  |  |  |         FALSE, | 
					
						
							|  |  |  |         INFINITE | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     if (data->result == WAIT_FAILED) { | 
					
						
							|  |  |  |         DWORD err = GetLastError(); | 
					
						
							|  |  |  |         SetEvent(data->cancel_event); | 
					
						
							|  |  |  |         return err; | 
					
						
							|  |  |  |     } else if (data->result >= WAIT_ABANDONED_0 && data->result < WAIT_ABANDONED_0 + MAXIMUM_WAIT_OBJECTS) { | 
					
						
							|  |  |  |         data->result = WAIT_FAILED; | 
					
						
							|  |  |  |         SetEvent(data->cancel_event); | 
					
						
							|  |  |  |         return ERROR_ABANDONED_WAIT_0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.BatchedWaitForMultipleObjects | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     handle_seq: object | 
					
						
							|  |  |  |     wait_all: BOOL | 
					
						
							|  |  |  |     milliseconds: DWORD(c_default='INFINITE') = _winapi.INFINITE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Supports a larger number of handles than WaitForMultipleObjects | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Note that the handles may be waited on other threads, which could cause | 
					
						
							|  |  |  | issues for objects like mutexes that become associated with the thread | 
					
						
							|  |  |  | that was waiting for them. Objects may also be left signalled, even if | 
					
						
							|  |  |  | the wait fails. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | It is recommended to use WaitForMultipleObjects whenever possible, and | 
					
						
							|  |  |  | only switch to BatchedWaitForMultipleObjects for scenarios where you | 
					
						
							|  |  |  | control all the handles involved, such as your own thread pool or | 
					
						
							|  |  |  | files, and all wait objects are left unmodified by a wait (for example, | 
					
						
							|  |  |  | manual reset events, threads, and files/pipes). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Overlapped handles returned from this module use manual reset events. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _winapi_BatchedWaitForMultipleObjects_impl(PyObject *module, | 
					
						
							|  |  |  |                                            PyObject *handle_seq, | 
					
						
							|  |  |  |                                            BOOL wait_all, DWORD milliseconds) | 
					
						
							|  |  |  | /*[clinic end generated code: output=d21c1a4ad0a252fd input=7e196f29005dc77b]*/ | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-11-05 16:05:13 +01:00
										 |  |  |     Py_ssize_t thread_count = 0, handle_count = 0, i; | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  |     Py_ssize_t nhandles; | 
					
						
							|  |  |  |     BatchedWaitData *thread_data[MAXIMUM_WAIT_OBJECTS]; | 
					
						
							|  |  |  |     HANDLE handles[MAXIMUM_WAIT_OBJECTS]; | 
					
						
							|  |  |  |     HANDLE sigint_event = NULL; | 
					
						
							|  |  |  |     HANDLE cancel_event = NULL; | 
					
						
							|  |  |  |     DWORD result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const Py_ssize_t _MAXIMUM_TOTAL_OBJECTS = (MAXIMUM_WAIT_OBJECTS - 1) * (MAXIMUM_WAIT_OBJECTS - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PySequence_Check(handle_seq)) { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                      "sequence type expected, got '%s'", | 
					
						
							|  |  |  |                      Py_TYPE(handle_seq)->tp_name); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     nhandles = PySequence_Length(handle_seq); | 
					
						
							|  |  |  |     if (nhandles == -1) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (nhandles == 0) { | 
					
						
							|  |  |  |         return wait_all ? Py_NewRef(Py_None) : PyList_New(0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* If this is the main thread then make the wait interruptible
 | 
					
						
							|  |  |  |        by Ctrl-C. When waiting for *all* handles, it is only checked | 
					
						
							|  |  |  |        in between batches. */ | 
					
						
							|  |  |  |     if (_PyOS_IsMainThread()) { | 
					
						
							|  |  |  |         sigint_event = _PyOS_SigintEvent(); | 
					
						
							|  |  |  |         assert(sigint_event != NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (nhandles < 0 || nhandles > _MAXIMUM_TOTAL_OBJECTS) { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  |                      "need at most %zd handles, got a sequence of length %zd", | 
					
						
							|  |  |  |                      _MAXIMUM_TOTAL_OBJECTS, nhandles); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!wait_all) { | 
					
						
							|  |  |  |         cancel_event = CreateEventW(NULL, TRUE, FALSE, NULL); | 
					
						
							|  |  |  |         if (!cancel_event) { | 
					
						
							|  |  |  |             PyErr_SetExcFromWindowsErr(PyExc_OSError, 0); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     i = 0; | 
					
						
							|  |  |  |     while (i < nhandles) { | 
					
						
							|  |  |  |         BatchedWaitData *data = (BatchedWaitData*)PyMem_Malloc(sizeof(BatchedWaitData)); | 
					
						
							|  |  |  |         if (!data) { | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         thread_data[thread_count++] = data; | 
					
						
							|  |  |  |         data->thread = NULL; | 
					
						
							|  |  |  |         data->cancel_event = cancel_event; | 
					
						
							|  |  |  |         data->handle_base = Py_SAFE_DOWNCAST(i, Py_ssize_t, DWORD); | 
					
						
							|  |  |  |         data->handle_count = Py_SAFE_DOWNCAST(nhandles - i, Py_ssize_t, DWORD); | 
					
						
							|  |  |  |         if (data->handle_count > MAXIMUM_WAIT_OBJECTS - 1) { | 
					
						
							|  |  |  |             data->handle_count = MAXIMUM_WAIT_OBJECTS - 1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-11-05 16:05:13 +01:00
										 |  |  |         for (DWORD j = 0; j < data->handle_count; ++i, ++j) { | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  |             PyObject *v = PySequence_GetItem(handle_seq, i); | 
					
						
							|  |  |  |             if (!v || !PyArg_Parse(v, F_HANDLE, &data->handles[j])) { | 
					
						
							|  |  |  |                 Py_XDECREF(v); | 
					
						
							|  |  |  |                 goto error; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             Py_DECREF(v); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!wait_all) { | 
					
						
							|  |  |  |             data->handles[data->handle_count++] = cancel_event; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DWORD err = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* We need to use different strategies when waiting for ALL handles
 | 
					
						
							|  |  |  |        as opposed to ANY handle. This is because there is no way to | 
					
						
							|  |  |  |        (safely) interrupt a thread that is waiting for all handles in a | 
					
						
							|  |  |  |        group. So for ALL handles, we loop over each set and wait. For | 
					
						
							|  |  |  |        ANY handle, we use threads and wait on them. */ | 
					
						
							|  |  |  |     if (wait_all) { | 
					
						
							|  |  |  |         Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |         long long deadline = 0; | 
					
						
							|  |  |  |         if (milliseconds != INFINITE) { | 
					
						
							|  |  |  |             deadline = (long long)GetTickCount64() + milliseconds; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (i = 0; !err && i < thread_count; ++i) { | 
					
						
							|  |  |  |             DWORD timeout = milliseconds; | 
					
						
							|  |  |  |             if (deadline) { | 
					
						
							|  |  |  |                 long long time_to_deadline = deadline - GetTickCount64(); | 
					
						
							|  |  |  |                 if (time_to_deadline <= 0) { | 
					
						
							|  |  |  |                     err = WAIT_TIMEOUT; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } else if (time_to_deadline < UINT_MAX) { | 
					
						
							|  |  |  |                     timeout = (DWORD)time_to_deadline; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             result = WaitForMultipleObjects(thread_data[i]->handle_count, | 
					
						
							|  |  |  |                                             thread_data[i]->handles, TRUE, timeout); | 
					
						
							|  |  |  |             // ABANDONED is not possible here because we own all the handles
 | 
					
						
							|  |  |  |             if (result == WAIT_FAILED) { | 
					
						
							|  |  |  |                 err = GetLastError(); | 
					
						
							|  |  |  |             } else if (result == WAIT_TIMEOUT) { | 
					
						
							|  |  |  |                 err = WAIT_TIMEOUT; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!err && sigint_event) { | 
					
						
							|  |  |  |                 result = WaitForSingleObject(sigint_event, 0); | 
					
						
							|  |  |  |                 if (result == WAIT_OBJECT_0) { | 
					
						
							|  |  |  |                     err = ERROR_CONTROL_C_EXIT; | 
					
						
							|  |  |  |                 } else if (result == WAIT_FAILED) { | 
					
						
							|  |  |  |                     err = GetLastError(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         CloseHandle(cancel_event); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Py_END_ALLOW_THREADS | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (i = 0; i < thread_count; ++i) { | 
					
						
							|  |  |  |             BatchedWaitData *data = thread_data[i]; | 
					
						
							|  |  |  |             data->thread = CreateThread( | 
					
						
							|  |  |  |                 NULL, | 
					
						
							|  |  |  |                 1,  // smallest possible initial stack
 | 
					
						
							|  |  |  |                 _batched_WaitForMultipleObjects_thread, | 
					
						
							|  |  |  |                 (LPVOID)data, | 
					
						
							|  |  |  |                 CREATE_SUSPENDED, | 
					
						
							|  |  |  |                 NULL | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |             if (!data->thread) { | 
					
						
							|  |  |  |                 err = GetLastError(); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             handles[handle_count++] = data->thread; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (err) { | 
					
						
							|  |  |  |             PyErr_SetExcFromWindowsErr(PyExc_OSError, err); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (handle_count > MAXIMUM_WAIT_OBJECTS - 1) { | 
					
						
							|  |  |  |             // basically an assert, but stronger
 | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_SystemError, "allocated too many wait objects"); | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Once we start resuming threads, can no longer "goto error"
 | 
					
						
							|  |  |  |         for (i = 0; i < thread_count; ++i) { | 
					
						
							|  |  |  |             ResumeThread(thread_data[i]->thread); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (sigint_event) { | 
					
						
							|  |  |  |             handles[handle_count++] = sigint_event; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         result = WaitForMultipleObjects((DWORD)handle_count, handles, wait_all, milliseconds); | 
					
						
							|  |  |  |         // ABANDONED is not possible here because we own all the handles
 | 
					
						
							|  |  |  |         if (result == WAIT_FAILED) { | 
					
						
							|  |  |  |             err = GetLastError(); | 
					
						
							|  |  |  |         } else if (result == WAIT_TIMEOUT) { | 
					
						
							|  |  |  |             err = WAIT_TIMEOUT; | 
					
						
							|  |  |  |         } else if (sigint_event && result == WAIT_OBJECT_0 + handle_count) { | 
					
						
							|  |  |  |             err = ERROR_CONTROL_C_EXIT; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         SetEvent(cancel_event); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Wait for all threads to finish before we start freeing their memory
 | 
					
						
							|  |  |  |         if (sigint_event) { | 
					
						
							|  |  |  |             handle_count -= 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         WaitForMultipleObjects((DWORD)handle_count, handles, TRUE, INFINITE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (i = 0; i < thread_count; ++i) { | 
					
						
							|  |  |  |             if (!err && thread_data[i]->result == WAIT_FAILED) { | 
					
						
							|  |  |  |                 if (!GetExitCodeThread(thread_data[i]->thread, &err)) { | 
					
						
							|  |  |  |                     err = GetLastError(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             CloseHandle(thread_data[i]->thread); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         CloseHandle(cancel_event); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *triggered_indices; | 
					
						
							|  |  |  |     if (sigint_event != NULL && err == ERROR_CONTROL_C_EXIT) { | 
					
						
							|  |  |  |         errno = EINTR; | 
					
						
							|  |  |  |         PyErr_SetFromErrno(PyExc_OSError); | 
					
						
							|  |  |  |         triggered_indices = NULL; | 
					
						
							|  |  |  |     } else if (err) { | 
					
						
							|  |  |  |         PyErr_SetExcFromWindowsErr(PyExc_OSError, err); | 
					
						
							|  |  |  |         triggered_indices = NULL; | 
					
						
							|  |  |  |     } else if (wait_all) { | 
					
						
							|  |  |  |         triggered_indices = Py_NewRef(Py_None); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         triggered_indices = PyList_New(0); | 
					
						
							|  |  |  |         if (triggered_indices) { | 
					
						
							|  |  |  |             for (i = 0; i < thread_count; ++i) { | 
					
						
							|  |  |  |                 Py_ssize_t triggered = (Py_ssize_t)thread_data[i]->result - WAIT_OBJECT_0; | 
					
						
							| 
									
										
										
										
											2024-11-05 16:05:13 +01:00
										 |  |  |                 if (triggered >= 0 && (size_t)triggered < thread_data[i]->handle_count - 1) { | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  |                     PyObject *v = PyLong_FromSsize_t(thread_data[i]->handle_base + triggered); | 
					
						
							|  |  |  |                     if (!v || PyList_Append(triggered_indices, v) < 0) { | 
					
						
							|  |  |  |                         Py_XDECREF(v); | 
					
						
							|  |  |  |                         Py_CLEAR(triggered_indices); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     Py_DECREF(v); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < thread_count; ++i) { | 
					
						
							|  |  |  |         PyMem_Free((void *)thread_data[i]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return triggered_indices; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | error: | 
					
						
							|  |  |  |     // We should only enter here before any threads start running.
 | 
					
						
							|  |  |  |     // Once we start resuming threads, different cleanup is required
 | 
					
						
							|  |  |  |     CloseHandle(cancel_event); | 
					
						
							|  |  |  |     while (--thread_count >= 0) { | 
					
						
							|  |  |  |         HANDLE t = thread_data[thread_count]->thread; | 
					
						
							|  |  |  |         if (t) { | 
					
						
							|  |  |  |             TerminateThread(t, WAIT_ABANDONED_0); | 
					
						
							|  |  |  |             CloseHandle(t); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         PyMem_Free((void *)thread_data[thread_count]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.WaitForMultipleObjects | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     handle_seq: object | 
					
						
							|  |  |  |     wait_flag: BOOL | 
					
						
							|  |  |  |     milliseconds: DWORD(c_default='INFINITE') = _winapi.INFINITE | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_WaitForMultipleObjects_impl(PyObject *module, PyObject *handle_seq, | 
					
						
							|  |  |  |                                     BOOL wait_flag, DWORD milliseconds) | 
					
						
							|  |  |  | /*[clinic end generated code: output=295e3f00b8e45899 input=36f76ca057cd28a0]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     DWORD result; | 
					
						
							|  |  |  |     HANDLE handles[MAXIMUM_WAIT_OBJECTS]; | 
					
						
							|  |  |  |     HANDLE sigint_event = NULL; | 
					
						
							|  |  |  |     Py_ssize_t nhandles, i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PySequence_Check(handle_seq)) { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                      "sequence type expected, got '%s'", | 
					
						
							| 
									
										
										
										
											2012-08-21 14:54:22 +01:00
										 |  |  |                      Py_TYPE(handle_seq)->tp_name); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     nhandles = PySequence_Length(handle_seq); | 
					
						
							|  |  |  |     if (nhandles == -1) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2021-07-28 20:58:05 +01:00
										 |  |  |     if (nhandles < 0 || nhandles > MAXIMUM_WAIT_OBJECTS - 1) { | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  |                      "need at most %zd handles, got a sequence of length %zd", | 
					
						
							|  |  |  |                      MAXIMUM_WAIT_OBJECTS - 1, nhandles); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (i = 0; i < nhandles; i++) { | 
					
						
							|  |  |  |         HANDLE h; | 
					
						
							|  |  |  |         PyObject *v = PySequence_GetItem(handle_seq, i); | 
					
						
							|  |  |  |         if (v == NULL) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         if (!PyArg_Parse(v, F_HANDLE, &h)) { | 
					
						
							|  |  |  |             Py_DECREF(v); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         handles[i] = h; | 
					
						
							|  |  |  |         Py_DECREF(v); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* If this is the main thread then make the wait interruptible
 | 
					
						
							|  |  |  |        by Ctrl-C unless we are waiting for *all* handles */ | 
					
						
							|  |  |  |     if (!wait_flag && _PyOS_IsMainThread()) { | 
					
						
							|  |  |  |         sigint_event = _PyOS_SigintEvent(); | 
					
						
							|  |  |  |         assert(sigint_event != NULL); | 
					
						
							|  |  |  |         handles[nhandles++] = sigint_event; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     if (sigint_event != NULL) | 
					
						
							|  |  |  |         ResetEvent(sigint_event); | 
					
						
							|  |  |  |     result = WaitForMultipleObjects((DWORD) nhandles, handles, | 
					
						
							|  |  |  |                                     wait_flag, milliseconds); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (result == WAIT_FAILED) | 
					
						
							| 
									
										
										
										
											2017-04-16 10:46:38 +03:00
										 |  |  |         return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) { | 
					
						
							|  |  |  |         errno = EINTR; | 
					
						
							| 
									
										
										
										
											2017-04-16 10:46:38 +03:00
										 |  |  |         return PyErr_SetFromErrno(PyExc_OSError); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return PyLong_FromLong((int) result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.WaitForSingleObject -> long | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     handle: HANDLE | 
					
						
							|  |  |  |     milliseconds: DWORD | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Wait for a single object. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Wait until the specified object is in the signaled state or | 
					
						
							|  |  |  | the time-out interval elapses. The timeout value is specified | 
					
						
							|  |  |  | in milliseconds. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static long | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_WaitForSingleObject_impl(PyObject *module, HANDLE handle, | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |                                  DWORD milliseconds) | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | /*[clinic end generated code: output=3c4715d8f1b39859 input=443d1ab076edc7b1]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     DWORD result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     result = WaitForSingleObject(handle, milliseconds); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     if (result == WAIT_FAILED) { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(GetLastError()); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.WriteFile | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     handle: HANDLE | 
					
						
							|  |  |  |     buffer: object | 
					
						
							| 
									
										
										
										
											2022-12-03 21:52:21 +02:00
										 |  |  |     overlapped as use_overlapped: bool = False | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2016-07-07 17:35:15 +03:00
										 |  |  | _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer, | 
					
						
							| 
									
										
										
										
											2015-05-13 10:58:35 -05:00
										 |  |  |                        int use_overlapped) | 
					
						
							| 
									
										
										
										
											2022-12-03 21:52:21 +02:00
										 |  |  | /*[clinic end generated code: output=2ca80f6bf3fa92e3 input=2badb008c8a2e2a0]*/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     Py_buffer _buf, *buf; | 
					
						
							| 
									
										
										
										
											2013-06-24 23:13:24 +02:00
										 |  |  |     DWORD len, written; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     BOOL ret; | 
					
						
							|  |  |  |     DWORD err; | 
					
						
							|  |  |  |     OverlappedObject *overlapped = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (use_overlapped) { | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |         overlapped = new_overlapped(module, handle); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         if (!overlapped) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         buf = &overlapped->write_buffer; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         buf = &_buf; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     if (!PyArg_Parse(buffer, "y*", buf)) { | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         Py_XDECREF(overlapped); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							| 
									
										
										
										
											2017-10-24 16:53:32 -07:00
										 |  |  |     len = (DWORD)Py_MIN(buf->len, PY_DWORD_MAX); | 
					
						
							| 
									
										
										
										
											2013-06-24 23:13:24 +02:00
										 |  |  |     ret = WriteFile(handle, buf->buf, len, &written, | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |                     overlapped ? &overlapped->overlapped : NULL); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     err = ret ? 0 : GetLastError(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (overlapped) { | 
					
						
							|  |  |  |         if (!ret) { | 
					
						
							|  |  |  |             if (err == ERROR_IO_PENDING) | 
					
						
							|  |  |  |                 overlapped->pending = 1; | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 Py_DECREF(overlapped); | 
					
						
							| 
									
										
										
										
											2017-04-16 10:46:38 +03:00
										 |  |  |                 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return Py_BuildValue("NI", (PyObject *) overlapped, err); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyBuffer_Release(buf); | 
					
						
							|  |  |  |     if (!ret) | 
					
						
							| 
									
										
										
										
											2017-04-16 10:46:38 +03:00
										 |  |  |         return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     return Py_BuildValue("II", written, err); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-13 12:29:09 +01:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.GetACP | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Get the current Windows ANSI code page identifier. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _winapi_GetACP_impl(PyObject *module) | 
					
						
							|  |  |  | /*[clinic end generated code: output=f7ee24bf705dbb88 input=1433c96d03a05229]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return PyLong_FromUnsignedLong(GetACP()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.GetFileType -> DWORD | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     handle: HANDLE | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static DWORD | 
					
						
							|  |  |  | _winapi_GetFileType_impl(PyObject *module, HANDLE handle) | 
					
						
							|  |  |  | /*[clinic end generated code: output=92b8466ac76ecc17 input=0058366bc40bbfbf]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DWORD result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     result = GetFileType(handle); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (result == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR) { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(0); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-30 11:00:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-08 16:48:42 +01:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi._mimetypes_read_windows_registry | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     on_type_read: object | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Optimized function for reading all known MIME types from the registry. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | *on_type_read* is a callable taking *type* and *ext* arguments, as for | 
					
						
							|  |  |  | MimeTypes.add_type. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _winapi__mimetypes_read_windows_registry_impl(PyObject *module, | 
					
						
							|  |  |  |                                               PyObject *on_type_read) | 
					
						
							|  |  |  | /*[clinic end generated code: output=20829f00bebce55b input=cd357896d6501f68]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #define CCH_EXT 128
 | 
					
						
							|  |  |  | #define CB_TYPE 510
 | 
					
						
							|  |  |  |     struct { | 
					
						
							|  |  |  |         wchar_t ext[CCH_EXT]; | 
					
						
							|  |  |  |         wchar_t type[CB_TYPE / sizeof(wchar_t) + 1]; | 
					
						
							|  |  |  |     } entries[64]; | 
					
						
							|  |  |  |     int entry = 0; | 
					
						
							|  |  |  |     HKEY hkcr = NULL; | 
					
						
							|  |  |  |     LRESULT err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     err = RegOpenKeyExW(HKEY_CLASSES_ROOT, NULL, 0, KEY_READ, &hkcr); | 
					
						
							|  |  |  |     for (DWORD i = 0; err == ERROR_SUCCESS || err == ERROR_MORE_DATA; ++i) { | 
					
						
							|  |  |  |         LPWSTR ext = entries[entry].ext; | 
					
						
							|  |  |  |         LPWSTR type = entries[entry].type; | 
					
						
							|  |  |  |         DWORD cchExt = CCH_EXT; | 
					
						
							|  |  |  |         DWORD cbType = CB_TYPE; | 
					
						
							|  |  |  |         HKEY subkey; | 
					
						
							|  |  |  |         DWORD regType; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         err = RegEnumKeyExW(hkcr, i, ext, &cchExt, NULL, NULL, NULL, NULL); | 
					
						
							|  |  |  |         if (err != ERROR_SUCCESS || (cchExt && ext[0] != L'.')) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         err = RegOpenKeyExW(hkcr, ext, 0, KEY_READ, &subkey); | 
					
						
							| 
									
										
										
										
											2024-08-07 17:07:26 +02:00
										 |  |  |         if (err == ERROR_FILE_NOT_FOUND || err == ERROR_ACCESS_DENIED) { | 
					
						
							| 
									
										
										
										
											2021-07-08 16:48:42 +01:00
										 |  |  |             err = ERROR_SUCCESS; | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } else if (err != ERROR_SUCCESS) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         err = RegQueryValueExW(subkey, L"Content Type", NULL, | 
					
						
							|  |  |  |                               ®Type, (LPBYTE)type, &cbType); | 
					
						
							|  |  |  |         RegCloseKey(subkey); | 
					
						
							|  |  |  |         if (err == ERROR_FILE_NOT_FOUND) { | 
					
						
							|  |  |  |             err = ERROR_SUCCESS; | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } else if (err != ERROR_SUCCESS) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } else if (regType != REG_SZ || !cbType) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         type[cbType / sizeof(wchar_t)] = L'\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         entry += 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* Flush our cached entries if we are full */ | 
					
						
							|  |  |  |         if (entry == sizeof(entries) / sizeof(entries[0])) { | 
					
						
							|  |  |  |             Py_BLOCK_THREADS | 
					
						
							|  |  |  |             for (int j = 0; j < entry; ++j) { | 
					
						
							|  |  |  |                 PyObject *r = PyObject_CallFunction( | 
					
						
							|  |  |  |                     on_type_read, "uu", entries[j].type, entries[j].ext | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |                 if (!r) { | 
					
						
							|  |  |  |                     /* We blocked threads, so safe to return from here */ | 
					
						
							|  |  |  |                     RegCloseKey(hkcr); | 
					
						
							|  |  |  |                     return NULL; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 Py_DECREF(r); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             Py_UNBLOCK_THREADS | 
					
						
							|  |  |  |             entry = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (hkcr) { | 
					
						
							|  |  |  |         RegCloseKey(hkcr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (err != ERROR_SUCCESS && err != ERROR_NO_MORE_ITEMS) { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr((int)err); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int j = 0; j < entry; ++j) { | 
					
						
							|  |  |  |         PyObject *r = PyObject_CallFunction( | 
					
						
							|  |  |  |             on_type_read, "uu", entries[j].type, entries[j].ext | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |         if (!r) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_DECREF(r); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | #undef CCH_EXT
 | 
					
						
							|  |  |  | #undef CB_TYPE
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-04 15:24:13 -07:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.NeedCurrentDirectoryForExePath -> bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     exe_name: LPCWSTR | 
					
						
							|  |  |  |     / | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | _winapi_NeedCurrentDirectoryForExePath_impl(PyObject *module, | 
					
						
							|  |  |  |                                             LPCWSTR exe_name) | 
					
						
							|  |  |  | /*[clinic end generated code: output=a65ec879502b58fc input=972aac88a1ec2f00]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BOOL result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     result = NeedCurrentDirectoryForExePathW(exe_name); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-12-13 12:29:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-30 11:00:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _winapi.CopyFile2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     existing_file_name: LPCWSTR | 
					
						
							|  |  |  |     new_file_name: LPCWSTR | 
					
						
							|  |  |  |     flags: DWORD | 
					
						
							|  |  |  |     progress_routine: object = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Copies a file from one name to a new name. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This is implemented using the CopyFile2 API, which preserves all stat | 
					
						
							|  |  |  | and metadata information apart from security attributes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | progress_routine is reserved for future use, but is currently not | 
					
						
							|  |  |  | implemented. Its value is ignored. | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _winapi_CopyFile2_impl(PyObject *module, LPCWSTR existing_file_name, | 
					
						
							|  |  |  |                        LPCWSTR new_file_name, DWORD flags, | 
					
						
							|  |  |  |                        PyObject *progress_routine) | 
					
						
							|  |  |  | /*[clinic end generated code: output=43d960d9df73d984 input=fb976b8d1492d130]*/ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     HRESULT hr; | 
					
						
							|  |  |  |     COPYFILE2_EXTENDED_PARAMETERS params = { sizeof(COPYFILE2_EXTENDED_PARAMETERS) }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-29 16:51:09 +01:00
										 |  |  |     if (PySys_Audit("_winapi.CopyFile2", "uuk", | 
					
						
							| 
									
										
										
										
											2023-05-30 11:00:29 +01:00
										 |  |  |                     existing_file_name, new_file_name, flags) < 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     params.dwCopyFlags = flags; | 
					
						
							|  |  |  |     /* For future implementation. We ignore the value for now so that
 | 
					
						
							|  |  |  |        users only have to test for 'CopyFile2' existing and not whether | 
					
						
							|  |  |  |        the additional parameter exists. | 
					
						
							|  |  |  |     if (progress_routine != Py_None) { | 
					
						
							|  |  |  |         params.pProgressRoutine = _winapi_CopyFile2ProgressRoutine; | 
					
						
							|  |  |  |         params.pvCallbackContext = Py_NewRef(progress_routine); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS; | 
					
						
							|  |  |  |     hr = CopyFile2(existing_file_name, new_file_name, ¶ms); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS; | 
					
						
							|  |  |  |     /* For future implementation.
 | 
					
						
							|  |  |  |     if (progress_routine != Py_None) { | 
					
						
							|  |  |  |         Py_DECREF(progress_routine); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         if ((hr & 0xFFFF0000) == 0x80070000) { | 
					
						
							|  |  |  |             PyErr_SetFromWindowsErr(hr & 0xFFFF); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             PyErr_SetFromWindowsErr(hr); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | static PyMethodDef winapi_functions[] = { | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     _WINAPI_CLOSEHANDLE_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_CONNECTNAMEDPIPE_METHODDEF | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  |     _WINAPI_CREATEEVENTW_METHODDEF | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     _WINAPI_CREATEFILE_METHODDEF | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  |     _WINAPI_CREATEFILEMAPPING_METHODDEF | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  |     _WINAPI_CREATEMUTEXW_METHODDEF | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     _WINAPI_CREATENAMEDPIPE_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_CREATEPIPE_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_CREATEPROCESS_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_CREATEJUNCTION_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_DUPLICATEHANDLE_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_EXITPROCESS_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_GETCURRENTPROCESS_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_GETEXITCODEPROCESS_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_GETLASTERROR_METHODDEF | 
					
						
							| 
									
										
										
										
											2024-04-15 15:36:06 +01:00
										 |  |  |     _WINAPI_GETLONGPATHNAME_METHODDEF | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     _WINAPI_GETMODULEFILENAME_METHODDEF | 
					
						
							| 
									
										
										
										
											2024-04-15 15:36:06 +01:00
										 |  |  |     _WINAPI_GETSHORTPATHNAME_METHODDEF | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     _WINAPI_GETSTDHANDLE_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_GETVERSION_METHODDEF | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  |     _WINAPI_MAPVIEWOFFILE_METHODDEF | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  |     _WINAPI_OPENEVENTW_METHODDEF | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  |     _WINAPI_OPENFILEMAPPING_METHODDEF | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  |     _WINAPI_OPENMUTEXW_METHODDEF | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     _WINAPI_OPENPROCESS_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_PEEKNAMEDPIPE_METHODDEF | 
					
						
							| 
									
										
										
										
											2022-06-07 07:47:27 +08:00
										 |  |  |     _WINAPI_LCMAPSTRINGEX_METHODDEF | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     _WINAPI_READFILE_METHODDEF | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  |     _WINAPI_RELEASEMUTEX_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_RESETEVENT_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_SETEVENT_METHODDEF | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_TERMINATEPROCESS_METHODDEF | 
					
						
							| 
									
										
										
										
											2022-11-25 09:39:48 -08:00
										 |  |  |     _WINAPI_UNMAPVIEWOFFILE_METHODDEF | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  |     _WINAPI_VIRTUALQUERYSIZE_METHODDEF | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     _WINAPI_WAITNAMEDPIPE_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF | 
					
						
							| 
									
										
										
										
											2024-02-13 00:28:35 +00:00
										 |  |  |     _WINAPI_BATCHEDWAITFORMULTIPLEOBJECTS_METHODDEF | 
					
						
							| 
									
										
										
										
											2015-05-13 01:22:54 -05:00
										 |  |  |     _WINAPI_WAITFORSINGLEOBJECT_METHODDEF | 
					
						
							|  |  |  |     _WINAPI_WRITEFILE_METHODDEF | 
					
						
							| 
									
										
										
										
											2017-12-13 12:29:09 +01:00
										 |  |  |     _WINAPI_GETACP_METHODDEF | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |     _WINAPI_GETFILETYPE_METHODDEF | 
					
						
							| 
									
										
										
										
											2021-07-08 16:48:42 +01:00
										 |  |  |     _WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF | 
					
						
							| 
									
										
										
										
											2023-04-04 15:24:13 -07:00
										 |  |  |     _WINAPI_NEEDCURRENTDIRECTORYFOREXEPATH_METHODDEF | 
					
						
							| 
									
										
										
										
											2023-05-30 11:00:29 +01:00
										 |  |  |     _WINAPI_COPYFILE2_METHODDEF | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     {NULL, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define WINAPI_CONSTANT(fmt, con) \
 | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |     do { \ | 
					
						
							|  |  |  |         PyObject *value = Py_BuildValue(fmt, con); \ | 
					
						
							|  |  |  |         if (value == NULL) { \ | 
					
						
							|  |  |  |             return -1; \ | 
					
						
							|  |  |  |         } \ | 
					
						
							|  |  |  |         if (PyDict_SetItemString(d, #con, value) < 0) { \ | 
					
						
							|  |  |  |             Py_DECREF(value); \ | 
					
						
							|  |  |  |             return -1; \ | 
					
						
							|  |  |  |         } \ | 
					
						
							|  |  |  |         Py_DECREF(value); \ | 
					
						
							|  |  |  |     } while (0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int winapi_exec(PyObject *m) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |     WinApiState *st = winapi_get_state(m); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |     st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec(m, &winapi_overlapped_type_spec, NULL); | 
					
						
							|  |  |  |     if (st->overlapped_type == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |     if (PyModule_AddType(m, st->overlapped_type) < 0) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |     PyObject *d = PyModule_GetDict(m); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* constants */ | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS); | 
					
						
							| 
									
										
										
										
											2012-04-24 22:56:57 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE); | 
					
						
							| 
									
										
										
										
											2023-05-30 11:00:29 +01:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_ACCESS_DENIED); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); | 
					
						
							| 
									
										
										
										
											2012-05-05 19:45:37 +01:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_NO_DATA); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED); | 
					
						
							| 
									
										
										
										
											2023-05-30 11:00:29 +01:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_PRIVILEGE_NOT_HELD); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED); | 
					
						
							| 
									
										
										
										
											2012-04-24 22:56:57 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE); | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_MAP_ALL_ACCESS); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_MAP_COPY); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_MAP_EXECUTE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_MAP_READ); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_MAP_WRITE); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, GENERIC_READ); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, INFINITE); | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  |     WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, MEM_COMMIT); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, MEM_FREE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, MEM_IMAGE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, MEM_MAPPED); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, MEM_PRIVATE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, MEM_RESERVE); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING); | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_READ); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_READWRITE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_WRITECOPY); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PAGE_GUARD); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PAGE_NOACCESS); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PAGE_NOCACHE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PAGE_READONLY); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PAGE_READWRITE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PAGE_WRITECOMBINE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PAGE_WRITECOPY); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PIPE_WAIT); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS); | 
					
						
							| 
									
										
										
										
											2019-05-20 21:37:05 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, SYNCHRONIZE); | 
					
						
							| 
									
										
										
										
											2012-04-24 22:56:57 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE); | 
					
						
							| 
									
										
										
										
											2019-02-23 22:08:16 -06:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, SEC_COMMIT); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, SEC_IMAGE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, SEC_LARGE_PAGES); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, SEC_NOCACHE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, SEC_RESERVE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, SEC_WRITECOMBINE); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW); | 
					
						
							| 
									
										
										
										
											2024-04-28 23:10:44 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_USESIZE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_USEPOSITION); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_USECOUNTCHARS); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_USEFILLATTRIBUTE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_RUNFULLSCREEN); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_FORCEONFEEDBACK); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_FORCEOFFFEEDBACK); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES); | 
					
						
							| 
									
										
										
										
											2024-04-28 23:10:44 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_USEHOTKEY); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_TITLEISLINKNAME); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_TITLEISAPPID); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_PREVENTPINNING); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STARTF_UNTRUSTEDSOURCE); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STD_OUTPUT_HANDLE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STD_ERROR_HANDLE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, STILL_ACTIVE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, SW_HIDE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0); | 
					
						
							| 
									
										
										
										
											2014-03-20 09:26:55 +01:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, WAIT_ABANDONED_0); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT); | 
					
						
							| 
									
										
										
										
											2017-12-13 12:29:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 14:18:59 +00:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, ABOVE_NORMAL_PRIORITY_CLASS); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, BELOW_NORMAL_PRIORITY_CLASS); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, HIGH_PRIORITY_CLASS); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, IDLE_PRIORITY_CLASS); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, NORMAL_PRIORITY_CLASS); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, REALTIME_PRIORITY_CLASS); | 
					
						
							| 
									
										
										
										
											2017-12-13 12:29:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 14:18:59 +00:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, CREATE_NO_WINDOW); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, DETACHED_PROCESS); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, CREATE_DEFAULT_ERROR_MODE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, CREATE_BREAKAWAY_FROM_JOB); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-18 11:28:19 +02:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_TYPE_UNKNOWN); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_TYPE_DISK); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_TYPE_CHAR); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_TYPE_PIPE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, FILE_TYPE_REMOTE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-07 07:47:27 +08:00
										 |  |  |     WINAPI_CONSTANT("u", LOCALE_NAME_INVARIANT); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, LOCALE_NAME_MAX_LENGTH); | 
					
						
							|  |  |  |     WINAPI_CONSTANT("u", LOCALE_NAME_SYSTEM_DEFAULT); | 
					
						
							|  |  |  |     WINAPI_CONSTANT("u", LOCALE_NAME_USER_DEFAULT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, LCMAP_FULLWIDTH); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, LCMAP_HALFWIDTH); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, LCMAP_HIRAGANA); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, LCMAP_KATAKANA); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, LCMAP_LINGUISTIC_CASING); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, LCMAP_LOWERCASE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, LCMAP_SIMPLIFIED_CHINESE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, LCMAP_TITLECASE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, LCMAP_TRADITIONAL_CHINESE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, LCMAP_UPPERCASE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-30 11:00:29 +01:00
										 |  |  |     WINAPI_CONSTANT(F_DWORD, COPY_FILE_ALLOW_DECRYPTED_DESTINATION); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPY_FILE_COPY_SYMLINK); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPY_FILE_FAIL_IF_EXISTS); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPY_FILE_NO_BUFFERING); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPY_FILE_NO_OFFLOAD); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPY_FILE_OPEN_SOURCE_FOR_WRITE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPY_FILE_RESTARTABLE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPY_FILE_REQUEST_SECURITY_PRIVILEGES); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPY_FILE_RESUME_FROM_PAUSE); | 
					
						
							|  |  |  | #ifndef COPY_FILE_REQUEST_COMPRESSED_TRAFFIC
 | 
					
						
							|  |  |  |     // Only defined in newer WinSDKs
 | 
					
						
							|  |  |  |     #define COPY_FILE_REQUEST_COMPRESSED_TRAFFIC 0x10000000
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPY_FILE_REQUEST_COMPRESSED_TRAFFIC); | 
					
						
							| 
									
										
										
										
											2024-06-19 01:59:54 +01:00
										 |  |  | #ifndef COPY_FILE_DIRECTORY
 | 
					
						
							|  |  |  |     // Only defined in newer WinSDKs
 | 
					
						
							|  |  |  |     #define COPY_FILE_DIRECTORY 0x00000080
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPY_FILE_DIRECTORY); | 
					
						
							| 
									
										
										
										
											2023-05-30 11:00:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_CHUNK_STARTED); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_CHUNK_FINISHED); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_STREAM_STARTED); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_STREAM_FINISHED); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_POLL_CONTINUE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_ERROR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_CONTINUE); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_CANCEL); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_STOP); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_QUIET); | 
					
						
							|  |  |  |     WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_PAUSE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     WINAPI_CONSTANT("i", NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyModuleDef_Slot winapi_slots[] = { | 
					
						
							|  |  |  |     {Py_mod_exec, winapi_exec}, | 
					
						
							| 
									
										
										
										
											2023-05-05 15:11:27 -06:00
										 |  |  |     {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, | 
					
						
							| 
									
										
										
										
											2024-05-03 08:30:55 -07:00
										 |  |  |     {Py_mod_gil, Py_MOD_GIL_NOT_USED}, | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  |     {0, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 17:06:46 +08:00
										 |  |  | static int | 
					
						
							|  |  |  | winapi_traverse(PyObject *module, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     WinApiState *st = winapi_get_state(module); | 
					
						
							|  |  |  |     Py_VISIT(st->overlapped_type); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | winapi_clear(PyObject *module) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     WinApiState *st = winapi_get_state(module); | 
					
						
							|  |  |  |     Py_CLEAR(st->overlapped_type); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | winapi_free(void *module) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     winapi_clear((PyObject *)module); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  | static struct PyModuleDef winapi_module = { | 
					
						
							|  |  |  |     PyModuleDef_HEAD_INIT, | 
					
						
							|  |  |  |     .m_name = "_winapi", | 
					
						
							|  |  |  |     .m_size = sizeof(WinApiState), | 
					
						
							|  |  |  |     .m_methods = winapi_functions, | 
					
						
							|  |  |  |     .m_slots = winapi_slots, | 
					
						
							| 
									
										
										
										
											2021-05-28 17:06:46 +08:00
										 |  |  |     .m_traverse = winapi_traverse, | 
					
						
							|  |  |  |     .m_clear = winapi_clear, | 
					
						
							|  |  |  |     .m_free = winapi_free, | 
					
						
							| 
									
										
										
										
											2020-08-13 09:22:48 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyMODINIT_FUNC | 
					
						
							|  |  |  | PyInit__winapi(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return PyModuleDef_Init(&winapi_module); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | } |