blob: c596cba3cbc3607ae8958c03ac7d0d2058e6167e [file] [log] [blame]
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001/*
2 * Support routines from the Windows API
3 *
4 * This module was originally created by merging PC/_subprocess.c with
5 * Modules/_multiprocessing/win32_functions.c.
6 *
7 * Copyright (c) 2004 by Fredrik Lundh <fredrik@pythonware.com>
8 * Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com
9 * Copyright (c) 2004 by Peter Astrand <astrand@lysator.liu.se>
10 *
11 * By obtaining, using, and/or copying this software and/or its
12 * associated documentation, you agree that you have read, understood,
13 * and will comply with the following terms and conditions:
14 *
15 * Permission to use, copy, modify, and distribute this software and
16 * its associated documentation for any purpose and without fee is
17 * hereby granted, provided that the above copyright notice appears in
18 * all copies, and that both that copyright notice and this permission
19 * notice appear in supporting documentation, and that the name of the
20 * authors not be used in advertising or publicity pertaining to
21 * distribution of the software without specific, written prior
22 * permission.
23 *
24 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
25 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
26 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
27 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
28 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
29 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
30 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 *
32 */
33
34/* Licensed to PSF under a Contributor Agreement. */
35/* See http://www.python.org/2.4/license for licensing details. */
36
37#include "Python.h"
38#include "structmember.h"
39
40#define WINDOWS_LEAN_AND_MEAN
41#include "windows.h"
42#include <crtdbg.h>
Tim Golden0321cf22014-05-05 19:46:17 +010043#include "winreparse.h"
Antoine Pitrou23bba4c2012-04-18 20:51:15 +020044
45#if defined(MS_WIN32) && !defined(MS_WIN64)
46#define HANDLE_TO_PYNUM(handle) \
47 PyLong_FromUnsignedLong((unsigned long) handle)
48#define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLong(obj))
49#define F_POINTER "k"
50#define T_POINTER T_ULONG
51#else
52#define HANDLE_TO_PYNUM(handle) \
53 PyLong_FromUnsignedLongLong((unsigned long long) handle)
54#define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLongLong(obj))
55#define F_POINTER "K"
56#define T_POINTER T_ULONGLONG
57#endif
58
59#define F_HANDLE F_POINTER
60#define F_DWORD "k"
Antoine Pitrou23bba4c2012-04-18 20:51:15 +020061
62#define T_HANDLE T_POINTER
63
64/* Grab CancelIoEx dynamically from kernel32 */
65static int has_CancelIoEx = -1;
66static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED);
67
68static int
69check_CancelIoEx()
70{
71 if (has_CancelIoEx == -1)
72 {
73 HINSTANCE hKernel32 = GetModuleHandle("KERNEL32");
74 * (FARPROC *) &Py_CancelIoEx = GetProcAddress(hKernel32,
75 "CancelIoEx");
76 has_CancelIoEx = (Py_CancelIoEx != NULL);
77 }
78 return has_CancelIoEx;
79}
80
81
82/*
83 * A Python object wrapping an OVERLAPPED structure and other useful data
84 * for overlapped I/O
85 */
86
87typedef struct {
88 PyObject_HEAD
89 OVERLAPPED overlapped;
90 /* For convenience, we store the file handle too */
91 HANDLE handle;
92 /* Whether there's I/O in flight */
93 int pending;
94 /* Whether I/O completed successfully */
95 int completed;
96 /* Buffer used for reading (optional) */
97 PyObject *read_buffer;
98 /* Buffer used for writing (optional) */
99 Py_buffer write_buffer;
100} OverlappedObject;
101
102static void
103overlapped_dealloc(OverlappedObject *self)
104{
105 DWORD bytes;
106 int err = GetLastError();
Richard Oudkerk633db6f2013-11-17 13:15:51 +0000107
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200108 if (self->pending) {
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200109 if (check_CancelIoEx() &&
Richard Oudkerk633db6f2013-11-17 13:15:51 +0000110 Py_CancelIoEx(self->handle, &self->overlapped) &&
111 GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE))
112 {
113 /* The operation is no longer pending -- nothing to do. */
114 }
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600115 else if (_Py_IsFinalizing())
Richard Oudkerk633db6f2013-11-17 13:15:51 +0000116 {
117 /* The operation is still pending -- give a warning. This
118 will probably only happen on Windows XP. */
119 PyErr_SetString(PyExc_RuntimeError,
120 "I/O operations still in flight while destroying "
121 "Overlapped object, the process may crash");
122 PyErr_WriteUnraisable(NULL);
123 }
124 else
125 {
126 /* The operation is still pending, but the process is
127 probably about to exit, so we need not worry too much
128 about memory leaks. Leaking self prevents a potential
129 crash. This can happen when a daemon thread is cleaned
130 up at exit -- see #19565. We only expect to get here
131 on Windows XP. */
132 CloseHandle(self->overlapped.hEvent);
133 SetLastError(err);
134 return;
135 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200136 }
Richard Oudkerk633db6f2013-11-17 13:15:51 +0000137
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200138 CloseHandle(self->overlapped.hEvent);
139 SetLastError(err);
140 if (self->write_buffer.obj)
141 PyBuffer_Release(&self->write_buffer);
142 Py_CLEAR(self->read_buffer);
143 PyObject_Del(self);
144}
145
Zachary Waref2244ea2015-05-13 01:22:54 -0500146/*[clinic input]
147module _winapi
148class _winapi.Overlapped "OverlappedObject *" "&OverlappedType"
149[clinic start generated code]*/
150/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c13d3f5fd1dabb84]*/
151
152/*[python input]
153def create_converter(type_, format_unit):
154 name = type_ + '_converter'
155 # registered upon creation by CConverter's metaclass
156 type(name, (CConverter,), {'type': type_, 'format_unit': format_unit})
157
158# format unit differs between platforms for these
159create_converter('HANDLE', '" F_HANDLE "')
160create_converter('HMODULE', '" F_HANDLE "')
161create_converter('LPSECURITY_ATTRIBUTES', '" F_POINTER "')
162
163create_converter('BOOL', 'i') # F_BOOL used previously (always 'i')
164create_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter)
165create_converter('LPCTSTR', 's')
166create_converter('LPWSTR', 'u')
167create_converter('UINT', 'I') # F_UINT used previously (always 'I')
168
169class HANDLE_return_converter(CReturnConverter):
170 type = 'HANDLE'
171
172 def render(self, function, data):
173 self.declare(data)
174 self.err_occurred_if("_return_value == INVALID_HANDLE_VALUE", data)
175 data.return_conversion.append(
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300176 'if (_return_value == NULL) {\n Py_RETURN_NONE;\n}\n')
Zachary Waref2244ea2015-05-13 01:22:54 -0500177 data.return_conversion.append(
178 'return_value = HANDLE_TO_PYNUM(_return_value);\n')
179
180class DWORD_return_converter(CReturnConverter):
181 type = 'DWORD'
182
183 def render(self, function, data):
184 self.declare(data)
Victor Stinner850a18e2017-10-24 16:53:32 -0700185 self.err_occurred_if("_return_value == PY_DWORD_MAX", data)
Zachary Waref2244ea2015-05-13 01:22:54 -0500186 data.return_conversion.append(
187 'return_value = Py_BuildValue("k", _return_value);\n')
188[python start generated code]*/
Victor Stinner850a18e2017-10-24 16:53:32 -0700189/*[python end generated code: output=da39a3ee5e6b4b0d input=4527052fe06e5823]*/
Zachary Waref2244ea2015-05-13 01:22:54 -0500190
191#include "clinic/_winapi.c.h"
192
193/*[clinic input]
194_winapi.Overlapped.GetOverlappedResult
195
196 wait: bool
197 /
198[clinic start generated code]*/
199
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200200static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500201_winapi_Overlapped_GetOverlappedResult_impl(OverlappedObject *self, int wait)
202/*[clinic end generated code: output=bdd0c1ed6518cd03 input=194505ee8e0e3565]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200203{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200204 BOOL res;
205 DWORD transferred = 0;
206 DWORD err;
207
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200208 Py_BEGIN_ALLOW_THREADS
209 res = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
210 wait != 0);
211 Py_END_ALLOW_THREADS
212
213 err = res ? ERROR_SUCCESS : GetLastError();
214 switch (err) {
215 case ERROR_SUCCESS:
216 case ERROR_MORE_DATA:
217 case ERROR_OPERATION_ABORTED:
218 self->completed = 1;
219 self->pending = 0;
220 break;
221 case ERROR_IO_INCOMPLETE:
222 break;
223 default:
224 self->pending = 0;
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300225 return PyErr_SetExcFromWindowsErr(PyExc_OSError, err);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200226 }
227 if (self->completed && self->read_buffer != NULL) {
228 assert(PyBytes_CheckExact(self->read_buffer));
229 if (transferred != PyBytes_GET_SIZE(self->read_buffer) &&
230 _PyBytes_Resize(&self->read_buffer, transferred))
231 return NULL;
232 }
233 return Py_BuildValue("II", (unsigned) transferred, (unsigned) err);
234}
235
Zachary Waref2244ea2015-05-13 01:22:54 -0500236/*[clinic input]
237_winapi.Overlapped.getbuffer
238[clinic start generated code]*/
239
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200240static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500241_winapi_Overlapped_getbuffer_impl(OverlappedObject *self)
242/*[clinic end generated code: output=95a3eceefae0f748 input=347fcfd56b4ceabd]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200243{
244 PyObject *res;
245 if (!self->completed) {
246 PyErr_SetString(PyExc_ValueError,
247 "can't get read buffer before GetOverlappedResult() "
248 "signals the operation completed");
249 return NULL;
250 }
251 res = self->read_buffer ? self->read_buffer : Py_None;
252 Py_INCREF(res);
253 return res;
254}
255
Zachary Waref2244ea2015-05-13 01:22:54 -0500256/*[clinic input]
257_winapi.Overlapped.cancel
258[clinic start generated code]*/
259
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200260static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500261_winapi_Overlapped_cancel_impl(OverlappedObject *self)
262/*[clinic end generated code: output=fcb9ab5df4ebdae5 input=cbf3da142290039f]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200263{
264 BOOL res = TRUE;
265
266 if (self->pending) {
267 Py_BEGIN_ALLOW_THREADS
268 if (check_CancelIoEx())
269 res = Py_CancelIoEx(self->handle, &self->overlapped);
270 else
271 res = CancelIo(self->handle);
272 Py_END_ALLOW_THREADS
273 }
274
275 /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
276 if (!res && GetLastError() != ERROR_NOT_FOUND)
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300277 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200278 self->pending = 0;
279 Py_RETURN_NONE;
280}
281
282static PyMethodDef overlapped_methods[] = {
Zachary Waref2244ea2015-05-13 01:22:54 -0500283 _WINAPI_OVERLAPPED_GETOVERLAPPEDRESULT_METHODDEF
284 _WINAPI_OVERLAPPED_GETBUFFER_METHODDEF
285 _WINAPI_OVERLAPPED_CANCEL_METHODDEF
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200286 {NULL}
287};
288
289static PyMemberDef overlapped_members[] = {
290 {"event", T_HANDLE,
291 offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
292 READONLY, "overlapped event handle"},
293 {NULL}
294};
295
296PyTypeObject OverlappedType = {
297 PyVarObject_HEAD_INIT(NULL, 0)
298 /* tp_name */ "_winapi.Overlapped",
299 /* tp_basicsize */ sizeof(OverlappedObject),
300 /* tp_itemsize */ 0,
301 /* tp_dealloc */ (destructor) overlapped_dealloc,
302 /* tp_print */ 0,
303 /* tp_getattr */ 0,
304 /* tp_setattr */ 0,
305 /* tp_reserved */ 0,
306 /* tp_repr */ 0,
307 /* tp_as_number */ 0,
308 /* tp_as_sequence */ 0,
309 /* tp_as_mapping */ 0,
310 /* tp_hash */ 0,
311 /* tp_call */ 0,
312 /* tp_str */ 0,
313 /* tp_getattro */ 0,
314 /* tp_setattro */ 0,
315 /* tp_as_buffer */ 0,
316 /* tp_flags */ Py_TPFLAGS_DEFAULT,
317 /* tp_doc */ "OVERLAPPED structure wrapper",
318 /* tp_traverse */ 0,
319 /* tp_clear */ 0,
320 /* tp_richcompare */ 0,
321 /* tp_weaklistoffset */ 0,
322 /* tp_iter */ 0,
323 /* tp_iternext */ 0,
324 /* tp_methods */ overlapped_methods,
325 /* tp_members */ overlapped_members,
326 /* tp_getset */ 0,
327 /* tp_base */ 0,
328 /* tp_dict */ 0,
329 /* tp_descr_get */ 0,
330 /* tp_descr_set */ 0,
331 /* tp_dictoffset */ 0,
332 /* tp_init */ 0,
333 /* tp_alloc */ 0,
334 /* tp_new */ 0,
335};
336
337static OverlappedObject *
338new_overlapped(HANDLE handle)
339{
340 OverlappedObject *self;
341
342 self = PyObject_New(OverlappedObject, &OverlappedType);
343 if (!self)
344 return NULL;
345 self->handle = handle;
346 self->read_buffer = NULL;
347 self->pending = 0;
348 self->completed = 0;
349 memset(&self->overlapped, 0, sizeof(OVERLAPPED));
350 memset(&self->write_buffer, 0, sizeof(Py_buffer));
351 /* Manual reset, initially non-signalled */
352 self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
353 return self;
354}
355
356/* -------------------------------------------------------------------- */
357/* windows API functions */
358
Zachary Waref2244ea2015-05-13 01:22:54 -0500359/*[clinic input]
360_winapi.CloseHandle
361
362 handle: HANDLE
363 /
364
365Close handle.
366[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200367
368static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300369_winapi_CloseHandle_impl(PyObject *module, HANDLE handle)
370/*[clinic end generated code: output=7ad37345f07bd782 input=7f0e4ac36e0352b8]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200371{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200372 BOOL success;
373
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200374 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500375 success = CloseHandle(handle);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200376 Py_END_ALLOW_THREADS
377
378 if (!success)
379 return PyErr_SetFromWindowsErr(0);
380
381 Py_RETURN_NONE;
382}
383
Zachary Waref2244ea2015-05-13 01:22:54 -0500384/*[clinic input]
385_winapi.ConnectNamedPipe
386
387 handle: HANDLE
Serhiy Storchaka202fda52017-03-12 10:10:47 +0200388 overlapped as use_overlapped: bool(accept={int}) = False
Zachary Waref2244ea2015-05-13 01:22:54 -0500389[clinic start generated code]*/
390
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200391static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300392_winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle,
Zachary Ware77772c02015-05-13 10:58:35 -0500393 int use_overlapped)
Serhiy Storchaka202fda52017-03-12 10:10:47 +0200394/*[clinic end generated code: output=335a0e7086800671 input=34f937c1c86e5e68]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200395{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200396 BOOL success;
397 OverlappedObject *overlapped = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200398
399 if (use_overlapped) {
Zachary Waref2244ea2015-05-13 01:22:54 -0500400 overlapped = new_overlapped(handle);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200401 if (!overlapped)
402 return NULL;
403 }
404
405 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500406 success = ConnectNamedPipe(handle,
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200407 overlapped ? &overlapped->overlapped : NULL);
408 Py_END_ALLOW_THREADS
409
410 if (overlapped) {
411 int err = GetLastError();
412 /* Overlapped ConnectNamedPipe never returns a success code */
413 assert(success == 0);
414 if (err == ERROR_IO_PENDING)
415 overlapped->pending = 1;
416 else if (err == ERROR_PIPE_CONNECTED)
417 SetEvent(overlapped->overlapped.hEvent);
418 else {
419 Py_DECREF(overlapped);
420 return PyErr_SetFromWindowsErr(err);
421 }
422 return (PyObject *) overlapped;
423 }
424 if (!success)
425 return PyErr_SetFromWindowsErr(0);
426
427 Py_RETURN_NONE;
428}
429
Zachary Waref2244ea2015-05-13 01:22:54 -0500430/*[clinic input]
431_winapi.CreateFile -> HANDLE
432
433 file_name: LPCTSTR
434 desired_access: DWORD
435 share_mode: DWORD
436 security_attributes: LPSECURITY_ATTRIBUTES
437 creation_disposition: DWORD
438 flags_and_attributes: DWORD
439 template_file: HANDLE
440 /
441[clinic start generated code]*/
442
443static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300444_winapi_CreateFile_impl(PyObject *module, LPCTSTR file_name,
Zachary Ware77772c02015-05-13 10:58:35 -0500445 DWORD desired_access, DWORD share_mode,
446 LPSECURITY_ATTRIBUTES security_attributes,
447 DWORD creation_disposition,
448 DWORD flags_and_attributes, HANDLE template_file)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300449/*[clinic end generated code: output=417ddcebfc5a3d53 input=6423c3e40372dbd5]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200450{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200451 HANDLE handle;
452
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200453 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500454 handle = CreateFile(file_name, desired_access,
455 share_mode, security_attributes,
456 creation_disposition,
457 flags_and_attributes, template_file);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200458 Py_END_ALLOW_THREADS
459
460 if (handle == INVALID_HANDLE_VALUE)
Zachary Waref2244ea2015-05-13 01:22:54 -0500461 PyErr_SetFromWindowsErr(0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200462
Zachary Waref2244ea2015-05-13 01:22:54 -0500463 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200464}
465
Zachary Waref2244ea2015-05-13 01:22:54 -0500466/*[clinic input]
467_winapi.CreateJunction
Tim Golden0321cf22014-05-05 19:46:17 +0100468
Zachary Waref2244ea2015-05-13 01:22:54 -0500469 src_path: LPWSTR
470 dst_path: LPWSTR
471 /
472[clinic start generated code]*/
473
474static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300475_winapi_CreateJunction_impl(PyObject *module, LPWSTR src_path,
Zachary Ware77772c02015-05-13 10:58:35 -0500476 LPWSTR dst_path)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300477/*[clinic end generated code: output=66b7eb746e1dfa25 input=8cd1f9964b6e3d36]*/
Zachary Waref2244ea2015-05-13 01:22:54 -0500478{
Tim Golden0321cf22014-05-05 19:46:17 +0100479 /* Privilege adjustment */
480 HANDLE token = NULL;
481 TOKEN_PRIVILEGES tp;
482
483 /* Reparse data buffer */
484 const USHORT prefix_len = 4;
485 USHORT print_len = 0;
486 USHORT rdb_size = 0;
Martin Panter70214ad2016-08-04 02:38:59 +0000487 _Py_PREPARSE_DATA_BUFFER rdb = NULL;
Tim Golden0321cf22014-05-05 19:46:17 +0100488
489 /* Junction point creation */
490 HANDLE junction = NULL;
491 DWORD ret = 0;
492
Tim Golden0321cf22014-05-05 19:46:17 +0100493 if (src_path == NULL || dst_path == NULL)
494 return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
495
496 if (wcsncmp(src_path, L"\\??\\", prefix_len) == 0)
497 return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
498
499 /* Adjust privileges to allow rewriting directory entry as a
500 junction point. */
501 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
502 goto cleanup;
503
504 if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid))
505 goto cleanup;
506
507 tp.PrivilegeCount = 1;
508 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
509 if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
510 NULL, NULL))
511 goto cleanup;
512
513 if (GetFileAttributesW(src_path) == INVALID_FILE_ATTRIBUTES)
514 goto cleanup;
515
516 /* Store the absolute link target path length in print_len. */
517 print_len = (USHORT)GetFullPathNameW(src_path, 0, NULL, NULL);
518 if (print_len == 0)
519 goto cleanup;
520
521 /* NUL terminator should not be part of print_len. */
522 --print_len;
523
524 /* REPARSE_DATA_BUFFER usage is heavily under-documented, especially for
525 junction points. Here's what I've learned along the way:
526 - A junction point has two components: a print name and a substitute
527 name. They both describe the link target, but the substitute name is
528 the physical target and the print name is shown in directory listings.
529 - The print name must be a native name, prefixed with "\??\".
530 - Both names are stored after each other in the same buffer (the
531 PathBuffer) and both must be NUL-terminated.
532 - There are four members defining their respective offset and length
533 inside PathBuffer: SubstituteNameOffset, SubstituteNameLength,
534 PrintNameOffset and PrintNameLength.
535 - The total size we need to allocate for the REPARSE_DATA_BUFFER, thus,
536 is the sum of:
537 - the fixed header size (REPARSE_DATA_BUFFER_HEADER_SIZE)
538 - the size of the MountPointReparseBuffer member without the PathBuffer
539 - the size of the prefix ("\??\") in bytes
540 - the size of the print name in bytes
541 - the size of the substitute name in bytes
542 - the size of two NUL terminators in bytes */
Martin Panter70214ad2016-08-04 02:38:59 +0000543 rdb_size = _Py_REPARSE_DATA_BUFFER_HEADER_SIZE +
Tim Golden0321cf22014-05-05 19:46:17 +0100544 sizeof(rdb->MountPointReparseBuffer) -
545 sizeof(rdb->MountPointReparseBuffer.PathBuffer) +
546 /* Two +1's for NUL terminators. */
547 (prefix_len + print_len + 1 + print_len + 1) * sizeof(WCHAR);
Martin Panter70214ad2016-08-04 02:38:59 +0000548 rdb = (_Py_PREPARSE_DATA_BUFFER)PyMem_RawMalloc(rdb_size);
Tim Golden0321cf22014-05-05 19:46:17 +0100549 if (rdb == NULL)
550 goto cleanup;
551
552 memset(rdb, 0, rdb_size);
553 rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
Martin Panter70214ad2016-08-04 02:38:59 +0000554 rdb->ReparseDataLength = rdb_size - _Py_REPARSE_DATA_BUFFER_HEADER_SIZE;
Tim Golden0321cf22014-05-05 19:46:17 +0100555 rdb->MountPointReparseBuffer.SubstituteNameOffset = 0;
556 rdb->MountPointReparseBuffer.SubstituteNameLength =
557 (prefix_len + print_len) * sizeof(WCHAR);
558 rdb->MountPointReparseBuffer.PrintNameOffset =
559 rdb->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
560 rdb->MountPointReparseBuffer.PrintNameLength = print_len * sizeof(WCHAR);
561
562 /* Store the full native path of link target at the substitute name
563 offset (0). */
564 wcscpy(rdb->MountPointReparseBuffer.PathBuffer, L"\\??\\");
565 if (GetFullPathNameW(src_path, print_len + 1,
566 rdb->MountPointReparseBuffer.PathBuffer + prefix_len,
567 NULL) == 0)
568 goto cleanup;
569
570 /* Copy everything but the native prefix to the print name offset. */
571 wcscpy(rdb->MountPointReparseBuffer.PathBuffer +
572 prefix_len + print_len + 1,
573 rdb->MountPointReparseBuffer.PathBuffer + prefix_len);
574
575 /* Create a directory for the junction point. */
576 if (!CreateDirectoryW(dst_path, NULL))
577 goto cleanup;
578
579 junction = CreateFileW(dst_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
580 OPEN_EXISTING,
581 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
582 if (junction == INVALID_HANDLE_VALUE)
583 goto cleanup;
584
585 /* Make the directory entry a junction point. */
586 if (!DeviceIoControl(junction, FSCTL_SET_REPARSE_POINT, rdb, rdb_size,
587 NULL, 0, &ret, NULL))
588 goto cleanup;
589
590cleanup:
591 ret = GetLastError();
592
593 CloseHandle(token);
594 CloseHandle(junction);
595 PyMem_RawFree(rdb);
596
597 if (ret != 0)
598 return PyErr_SetFromWindowsErr(ret);
599
600 Py_RETURN_NONE;
601}
602
Zachary Waref2244ea2015-05-13 01:22:54 -0500603/*[clinic input]
604_winapi.CreateNamedPipe -> HANDLE
605
606 name: LPCTSTR
607 open_mode: DWORD
608 pipe_mode: DWORD
609 max_instances: DWORD
610 out_buffer_size: DWORD
611 in_buffer_size: DWORD
612 default_timeout: DWORD
613 security_attributes: LPSECURITY_ATTRIBUTES
614 /
615[clinic start generated code]*/
616
617static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300618_winapi_CreateNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD open_mode,
619 DWORD pipe_mode, DWORD max_instances,
620 DWORD out_buffer_size, DWORD in_buffer_size,
621 DWORD default_timeout,
Zachary Ware77772c02015-05-13 10:58:35 -0500622 LPSECURITY_ATTRIBUTES security_attributes)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300623/*[clinic end generated code: output=80f8c07346a94fbc input=5a73530b84d8bc37]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200624{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200625 HANDLE handle;
626
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200627 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500628 handle = CreateNamedPipe(name, open_mode, pipe_mode,
629 max_instances, out_buffer_size,
630 in_buffer_size, default_timeout,
631 security_attributes);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200632 Py_END_ALLOW_THREADS
633
634 if (handle == INVALID_HANDLE_VALUE)
Zachary Waref2244ea2015-05-13 01:22:54 -0500635 PyErr_SetFromWindowsErr(0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200636
Zachary Waref2244ea2015-05-13 01:22:54 -0500637 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200638}
639
Zachary Waref2244ea2015-05-13 01:22:54 -0500640/*[clinic input]
641_winapi.CreatePipe
642
643 pipe_attrs: object
644 Ignored internally, can be None.
645 size: DWORD
646 /
647
648Create an anonymous pipe.
649
650Returns a 2-tuple of handles, to the read and write ends of the pipe.
651[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200652
653static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300654_winapi_CreatePipe_impl(PyObject *module, PyObject *pipe_attrs, DWORD size)
655/*[clinic end generated code: output=1c4411d8699f0925 input=c4f2cfa56ef68d90]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200656{
657 HANDLE read_pipe;
658 HANDLE write_pipe;
659 BOOL result;
660
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200661 Py_BEGIN_ALLOW_THREADS
662 result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
663 Py_END_ALLOW_THREADS
664
665 if (! result)
666 return PyErr_SetFromWindowsErr(GetLastError());
667
668 return Py_BuildValue(
669 "NN", HANDLE_TO_PYNUM(read_pipe), HANDLE_TO_PYNUM(write_pipe));
670}
671
672/* helpers for createprocess */
673
674static unsigned long
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200675getulong(PyObject* obj, const char* name)
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200676{
677 PyObject* value;
678 unsigned long ret;
679
680 value = PyObject_GetAttrString(obj, name);
681 if (! value) {
682 PyErr_Clear(); /* FIXME: propagate error? */
683 return 0;
684 }
685 ret = PyLong_AsUnsignedLong(value);
686 Py_DECREF(value);
687 return ret;
688}
689
690static HANDLE
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200691gethandle(PyObject* obj, const char* name)
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200692{
693 PyObject* value;
694 HANDLE ret;
695
696 value = PyObject_GetAttrString(obj, name);
697 if (! value) {
698 PyErr_Clear(); /* FIXME: propagate error? */
699 return NULL;
700 }
701 if (value == Py_None)
702 ret = NULL;
703 else
704 ret = PYNUM_TO_HANDLE(value);
705 Py_DECREF(value);
706 return ret;
707}
708
709static PyObject*
710getenvironment(PyObject* environment)
711{
712 Py_ssize_t i, envsize, totalsize;
713 Py_UCS4 *buffer = NULL, *p, *end;
714 PyObject *keys, *values, *res;
715
Ezio Melotti85a86292013-08-17 16:57:41 +0300716 /* convert environment dictionary to windows environment string */
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200717 if (! PyMapping_Check(environment)) {
718 PyErr_SetString(
719 PyExc_TypeError, "environment must be dictionary or None");
720 return NULL;
721 }
722
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200723 keys = PyMapping_Keys(environment);
Oren Milman0b3a87e2017-09-14 22:30:28 +0300724 if (!keys) {
725 return NULL;
726 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200727 values = PyMapping_Values(environment);
Oren Milman0b3a87e2017-09-14 22:30:28 +0300728 if (!values) {
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200729 goto error;
Oren Milman0b3a87e2017-09-14 22:30:28 +0300730 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200731
Serhiy Storchakabf623ae2017-04-19 20:03:52 +0300732 envsize = PySequence_Fast_GET_SIZE(keys);
733 if (PySequence_Fast_GET_SIZE(values) != envsize) {
734 PyErr_SetString(PyExc_RuntimeError,
735 "environment changed size during iteration");
736 goto error;
737 }
738
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200739 totalsize = 1; /* trailing null character */
740 for (i = 0; i < envsize; i++) {
Serhiy Storchakabf623ae2017-04-19 20:03:52 +0300741 PyObject* key = PySequence_Fast_GET_ITEM(keys, i);
742 PyObject* value = PySequence_Fast_GET_ITEM(values, i);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200743
744 if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
745 PyErr_SetString(PyExc_TypeError,
746 "environment can only contain strings");
747 goto error;
748 }
Serhiy Storchakad174d242017-06-23 19:39:27 +0300749 if (PyUnicode_FindChar(key, '\0', 0, PyUnicode_GET_LENGTH(key), 1) != -1 ||
750 PyUnicode_FindChar(value, '\0', 0, PyUnicode_GET_LENGTH(value), 1) != -1)
751 {
752 PyErr_SetString(PyExc_ValueError, "embedded null character");
753 goto error;
754 }
755 /* Search from index 1 because on Windows starting '=' is allowed for
756 defining hidden environment variables. */
757 if (PyUnicode_GET_LENGTH(key) == 0 ||
758 PyUnicode_FindChar(key, '=', 1, PyUnicode_GET_LENGTH(key), 1) != -1)
759 {
760 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
761 goto error;
762 }
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500763 if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(key) - 1) {
764 PyErr_SetString(PyExc_OverflowError, "environment too long");
765 goto error;
766 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200767 totalsize += PyUnicode_GET_LENGTH(key) + 1; /* +1 for '=' */
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500768 if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(value) - 1) {
769 PyErr_SetString(PyExc_OverflowError, "environment too long");
770 goto error;
771 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200772 totalsize += PyUnicode_GET_LENGTH(value) + 1; /* +1 for '\0' */
773 }
774
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500775 buffer = PyMem_NEW(Py_UCS4, totalsize);
776 if (! buffer) {
777 PyErr_NoMemory();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200778 goto error;
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500779 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200780 p = buffer;
781 end = buffer + totalsize;
782
783 for (i = 0; i < envsize; i++) {
Serhiy Storchakabf623ae2017-04-19 20:03:52 +0300784 PyObject* key = PySequence_Fast_GET_ITEM(keys, i);
785 PyObject* value = PySequence_Fast_GET_ITEM(values, i);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200786 if (!PyUnicode_AsUCS4(key, p, end - p, 0))
787 goto error;
788 p += PyUnicode_GET_LENGTH(key);
789 *p++ = '=';
790 if (!PyUnicode_AsUCS4(value, p, end - p, 0))
791 goto error;
792 p += PyUnicode_GET_LENGTH(value);
793 *p++ = '\0';
794 }
795
796 /* add trailing null byte */
797 *p++ = '\0';
798 assert(p == end);
799
800 Py_XDECREF(keys);
801 Py_XDECREF(values);
802
803 res = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buffer, p - buffer);
804 PyMem_Free(buffer);
805 return res;
806
807 error:
808 PyMem_Free(buffer);
809 Py_XDECREF(keys);
810 Py_XDECREF(values);
811 return NULL;
812}
813
Segev Finerb2a60832017-12-18 11:28:19 +0200814static LPHANDLE
815gethandlelist(PyObject *mapping, const char *name, Py_ssize_t *size)
816{
817 LPHANDLE ret = NULL;
818 PyObject *value_fast = NULL;
819 PyObject *value;
820 Py_ssize_t i;
821
822 value = PyMapping_GetItemString(mapping, name);
823 if (!value) {
824 PyErr_Clear();
825 return NULL;
826 }
827
828 if (value == Py_None) {
829 goto cleanup;
830 }
831
832 value_fast = PySequence_Fast(value, "handle_list must be a sequence or None");
833 if (value_fast == NULL)
834 goto cleanup;
835
836 *size = PySequence_Fast_GET_SIZE(value_fast) * sizeof(HANDLE);
837
838 /* Passing an empty array causes CreateProcess to fail so just don't set it */
839 if (*size == 0) {
840 goto cleanup;
841 }
842
843 ret = PyMem_Malloc(*size);
844 if (ret == NULL)
845 goto cleanup;
846
847 for (i = 0; i < PySequence_Fast_GET_SIZE(value_fast); i++) {
848 ret[i] = PYNUM_TO_HANDLE(PySequence_Fast_GET_ITEM(value_fast, i));
849 if (ret[i] == (HANDLE)-1 && PyErr_Occurred()) {
850 PyMem_Free(ret);
851 ret = NULL;
852 goto cleanup;
853 }
854 }
855
856cleanup:
857 Py_DECREF(value);
858 Py_XDECREF(value_fast);
859 return ret;
860}
861
862typedef struct {
863 LPPROC_THREAD_ATTRIBUTE_LIST attribute_list;
864 LPHANDLE handle_list;
865} AttributeList;
866
867static void
868freeattributelist(AttributeList *attribute_list)
869{
870 if (attribute_list->attribute_list != NULL) {
871 DeleteProcThreadAttributeList(attribute_list->attribute_list);
872 PyMem_Free(attribute_list->attribute_list);
873 }
874
875 PyMem_Free(attribute_list->handle_list);
876
877 memset(attribute_list, 0, sizeof(*attribute_list));
878}
879
880static int
881getattributelist(PyObject *obj, const char *name, AttributeList *attribute_list)
882{
883 int ret = 0;
884 DWORD err;
885 BOOL result;
886 PyObject *value;
887 Py_ssize_t handle_list_size;
888 DWORD attribute_count = 0;
889 SIZE_T attribute_list_size = 0;
890
891 value = PyObject_GetAttrString(obj, name);
892 if (!value) {
893 PyErr_Clear(); /* FIXME: propagate error? */
894 return 0;
895 }
896
897 if (value == Py_None) {
898 ret = 0;
899 goto cleanup;
900 }
901
902 if (!PyMapping_Check(value)) {
903 ret = -1;
904 PyErr_Format(PyExc_TypeError, "%s must be a mapping or None", name);
905 goto cleanup;
906 }
907
908 attribute_list->handle_list = gethandlelist(value, "handle_list", &handle_list_size);
909 if (attribute_list->handle_list == NULL && PyErr_Occurred()) {
910 ret = -1;
911 goto cleanup;
912 }
913
914 if (attribute_list->handle_list != NULL)
915 ++attribute_count;
916
917 /* Get how many bytes we need for the attribute list */
918 result = InitializeProcThreadAttributeList(NULL, attribute_count, 0, &attribute_list_size);
919 if (result || GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
920 ret = -1;
921 PyErr_SetFromWindowsErr(GetLastError());
922 goto cleanup;
923 }
924
925 attribute_list->attribute_list = PyMem_Malloc(attribute_list_size);
926 if (attribute_list->attribute_list == NULL) {
927 ret = -1;
928 goto cleanup;
929 }
930
931 result = InitializeProcThreadAttributeList(
932 attribute_list->attribute_list,
933 attribute_count,
934 0,
935 &attribute_list_size);
936 if (!result) {
937 err = GetLastError();
938
939 /* So that we won't call DeleteProcThreadAttributeList */
940 PyMem_Free(attribute_list->attribute_list);
941 attribute_list->attribute_list = NULL;
942
943 ret = -1;
944 PyErr_SetFromWindowsErr(err);
945 goto cleanup;
946 }
947
948 if (attribute_list->handle_list != NULL) {
949 result = UpdateProcThreadAttribute(
950 attribute_list->attribute_list,
951 0,
952 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
953 attribute_list->handle_list,
954 handle_list_size,
955 NULL,
956 NULL);
957 if (!result) {
958 ret = -1;
959 PyErr_SetFromWindowsErr(GetLastError());
960 goto cleanup;
961 }
962 }
963
964cleanup:
965 Py_DECREF(value);
966
967 if (ret < 0)
968 freeattributelist(attribute_list);
969
970 return ret;
971}
972
Zachary Waref2244ea2015-05-13 01:22:54 -0500973/*[clinic input]
974_winapi.CreateProcess
975
Zachary Ware77772c02015-05-13 10:58:35 -0500976 application_name: Py_UNICODE(accept={str, NoneType})
977 command_line: Py_UNICODE(accept={str, NoneType})
Zachary Waref2244ea2015-05-13 01:22:54 -0500978 proc_attrs: object
979 Ignored internally, can be None.
980 thread_attrs: object
981 Ignored internally, can be None.
982 inherit_handles: BOOL
983 creation_flags: DWORD
984 env_mapping: object
Zachary Ware77772c02015-05-13 10:58:35 -0500985 current_directory: Py_UNICODE(accept={str, NoneType})
Zachary Waref2244ea2015-05-13 01:22:54 -0500986 startup_info: object
987 /
988
989Create a new process and its primary thread.
990
991The return value is a tuple of the process handle, thread handle,
992process ID, and thread ID.
993[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200994
995static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300996_winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name,
Zachary Ware77772c02015-05-13 10:58:35 -0500997 Py_UNICODE *command_line, PyObject *proc_attrs,
998 PyObject *thread_attrs, BOOL inherit_handles,
999 DWORD creation_flags, PyObject *env_mapping,
1000 Py_UNICODE *current_directory,
1001 PyObject *startup_info)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001002/*[clinic end generated code: output=4652a33aff4b0ae1 input=4a43b05038d639bb]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001003{
Segev Finerb2a60832017-12-18 11:28:19 +02001004 PyObject *ret = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001005 BOOL result;
1006 PROCESS_INFORMATION pi;
Segev Finerb2a60832017-12-18 11:28:19 +02001007 STARTUPINFOEXW si;
1008 PyObject *environment = NULL;
Serhiy Storchaka0ee32c12017-06-24 16:14:08 +03001009 wchar_t *wenvironment;
Segev Finerb2a60832017-12-18 11:28:19 +02001010 AttributeList attribute_list = {0};
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001011
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001012 ZeroMemory(&si, sizeof(si));
Segev Finerb2a60832017-12-18 11:28:19 +02001013 si.StartupInfo.cb = sizeof(si);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001014
1015 /* note: we only support a small subset of all SI attributes */
Segev Finerb2a60832017-12-18 11:28:19 +02001016 si.StartupInfo.dwFlags = getulong(startup_info, "dwFlags");
1017 si.StartupInfo.wShowWindow = (WORD)getulong(startup_info, "wShowWindow");
1018 si.StartupInfo.hStdInput = gethandle(startup_info, "hStdInput");
1019 si.StartupInfo.hStdOutput = gethandle(startup_info, "hStdOutput");
1020 si.StartupInfo.hStdError = gethandle(startup_info, "hStdError");
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001021 if (PyErr_Occurred())
Segev Finerb2a60832017-12-18 11:28:19 +02001022 goto cleanup;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001023
1024 if (env_mapping != Py_None) {
1025 environment = getenvironment(env_mapping);
Serhiy Storchakad174d242017-06-23 19:39:27 +03001026 if (environment == NULL) {
Segev Finerb2a60832017-12-18 11:28:19 +02001027 goto cleanup;
Serhiy Storchakad174d242017-06-23 19:39:27 +03001028 }
1029 /* contains embedded null characters */
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001030 wenvironment = PyUnicode_AsUnicode(environment);
Serhiy Storchakad174d242017-06-23 19:39:27 +03001031 if (wenvironment == NULL) {
Segev Finerb2a60832017-12-18 11:28:19 +02001032 goto cleanup;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001033 }
1034 }
1035 else {
1036 environment = NULL;
1037 wenvironment = NULL;
1038 }
1039
Segev Finerb2a60832017-12-18 11:28:19 +02001040 if (getattributelist(startup_info, "lpAttributeList", &attribute_list) < 0)
1041 goto cleanup;
1042
1043 si.lpAttributeList = attribute_list.attribute_list;
1044
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001045 Py_BEGIN_ALLOW_THREADS
1046 result = CreateProcessW(application_name,
1047 command_line,
1048 NULL,
1049 NULL,
1050 inherit_handles,
Segev Finerb2a60832017-12-18 11:28:19 +02001051 creation_flags | EXTENDED_STARTUPINFO_PRESENT |
1052 CREATE_UNICODE_ENVIRONMENT,
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001053 wenvironment,
1054 current_directory,
Segev Finerb2a60832017-12-18 11:28:19 +02001055 (LPSTARTUPINFOW)&si,
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001056 &pi);
1057 Py_END_ALLOW_THREADS
1058
Segev Finerb2a60832017-12-18 11:28:19 +02001059 if (!result) {
1060 PyErr_SetFromWindowsErr(GetLastError());
1061 goto cleanup;
1062 }
1063
1064 ret = Py_BuildValue("NNkk",
1065 HANDLE_TO_PYNUM(pi.hProcess),
1066 HANDLE_TO_PYNUM(pi.hThread),
1067 pi.dwProcessId,
1068 pi.dwThreadId);
1069
1070cleanup:
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001071 Py_XDECREF(environment);
Segev Finerb2a60832017-12-18 11:28:19 +02001072 freeattributelist(&attribute_list);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001073
Segev Finerb2a60832017-12-18 11:28:19 +02001074 return ret;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001075}
1076
Zachary Waref2244ea2015-05-13 01:22:54 -05001077/*[clinic input]
1078_winapi.DuplicateHandle -> HANDLE
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001079
Zachary Waref2244ea2015-05-13 01:22:54 -05001080 source_process_handle: HANDLE
1081 source_handle: HANDLE
1082 target_process_handle: HANDLE
1083 desired_access: DWORD
1084 inherit_handle: BOOL
1085 options: DWORD = 0
1086 /
1087
1088Return a duplicate handle object.
1089
1090The duplicate handle refers to the same object as the original
1091handle. Therefore, any changes to the object are reflected
1092through both handles.
1093[clinic start generated code]*/
1094
1095static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001096_winapi_DuplicateHandle_impl(PyObject *module, HANDLE source_process_handle,
Zachary Ware77772c02015-05-13 10:58:35 -05001097 HANDLE source_handle,
1098 HANDLE target_process_handle,
1099 DWORD desired_access, BOOL inherit_handle,
1100 DWORD options)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001101/*[clinic end generated code: output=ad9711397b5dcd4e input=b933e3f2356a8c12]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001102{
1103 HANDLE target_handle;
1104 BOOL result;
1105
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001106 Py_BEGIN_ALLOW_THREADS
1107 result = DuplicateHandle(
1108 source_process_handle,
1109 source_handle,
1110 target_process_handle,
1111 &target_handle,
1112 desired_access,
1113 inherit_handle,
1114 options
1115 );
1116 Py_END_ALLOW_THREADS
1117
Zachary Waref2244ea2015-05-13 01:22:54 -05001118 if (! result) {
1119 PyErr_SetFromWindowsErr(GetLastError());
1120 return INVALID_HANDLE_VALUE;
1121 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001122
Zachary Waref2244ea2015-05-13 01:22:54 -05001123 return target_handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001124}
1125
Zachary Waref2244ea2015-05-13 01:22:54 -05001126/*[clinic input]
1127_winapi.ExitProcess
1128
1129 ExitCode: UINT
1130 /
1131
1132[clinic start generated code]*/
1133
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001134static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001135_winapi_ExitProcess_impl(PyObject *module, UINT ExitCode)
1136/*[clinic end generated code: output=a387deb651175301 input=4f05466a9406c558]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001137{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001138 #if defined(Py_DEBUG)
1139 SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|
1140 SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
1141 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
1142 #endif
1143
Zachary Waref2244ea2015-05-13 01:22:54 -05001144 ExitProcess(ExitCode);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001145
1146 return NULL;
1147}
1148
Zachary Waref2244ea2015-05-13 01:22:54 -05001149/*[clinic input]
1150_winapi.GetCurrentProcess -> HANDLE
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001151
Zachary Waref2244ea2015-05-13 01:22:54 -05001152Return a handle object for the current process.
1153[clinic start generated code]*/
1154
1155static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001156_winapi_GetCurrentProcess_impl(PyObject *module)
1157/*[clinic end generated code: output=ddeb4dd2ffadf344 input=b213403fd4b96b41]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001158{
Zachary Waref2244ea2015-05-13 01:22:54 -05001159 return GetCurrentProcess();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001160}
1161
Zachary Waref2244ea2015-05-13 01:22:54 -05001162/*[clinic input]
1163_winapi.GetExitCodeProcess -> DWORD
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001164
Zachary Waref2244ea2015-05-13 01:22:54 -05001165 process: HANDLE
1166 /
1167
1168Return the termination status of the specified process.
1169[clinic start generated code]*/
1170
1171static DWORD
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001172_winapi_GetExitCodeProcess_impl(PyObject *module, HANDLE process)
1173/*[clinic end generated code: output=b4620bdf2bccf36b input=61b6bfc7dc2ee374]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001174{
1175 DWORD exit_code;
1176 BOOL result;
1177
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001178 result = GetExitCodeProcess(process, &exit_code);
1179
Zachary Waref2244ea2015-05-13 01:22:54 -05001180 if (! result) {
1181 PyErr_SetFromWindowsErr(GetLastError());
Victor Stinner850a18e2017-10-24 16:53:32 -07001182 exit_code = PY_DWORD_MAX;
Zachary Waref2244ea2015-05-13 01:22:54 -05001183 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001184
Zachary Waref2244ea2015-05-13 01:22:54 -05001185 return exit_code;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001186}
1187
Zachary Waref2244ea2015-05-13 01:22:54 -05001188/*[clinic input]
1189_winapi.GetLastError -> DWORD
1190[clinic start generated code]*/
1191
1192static DWORD
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001193_winapi_GetLastError_impl(PyObject *module)
1194/*[clinic end generated code: output=8585b827cb1a92c5 input=62d47fb9bce038ba]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001195{
Zachary Waref2244ea2015-05-13 01:22:54 -05001196 return GetLastError();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001197}
1198
Zachary Waref2244ea2015-05-13 01:22:54 -05001199/*[clinic input]
1200_winapi.GetModuleFileName
1201
1202 module_handle: HMODULE
1203 /
1204
1205Return the fully-qualified path for the file that contains module.
1206
1207The module must have been loaded by the current process.
1208
1209The module parameter should be a handle to the loaded module
1210whose path is being requested. If this parameter is 0,
1211GetModuleFileName retrieves the path of the executable file
1212of the current process.
1213[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001214
1215static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001216_winapi_GetModuleFileName_impl(PyObject *module, HMODULE module_handle)
1217/*[clinic end generated code: output=85b4b728c5160306 input=6d66ff7deca5d11f]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001218{
1219 BOOL result;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001220 WCHAR filename[MAX_PATH];
1221
Zachary Waref2244ea2015-05-13 01:22:54 -05001222 result = GetModuleFileNameW(module_handle, filename, MAX_PATH);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001223 filename[MAX_PATH-1] = '\0';
1224
1225 if (! result)
1226 return PyErr_SetFromWindowsErr(GetLastError());
1227
1228 return PyUnicode_FromWideChar(filename, wcslen(filename));
1229}
1230
Zachary Waref2244ea2015-05-13 01:22:54 -05001231/*[clinic input]
1232_winapi.GetStdHandle -> HANDLE
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001233
Zachary Waref2244ea2015-05-13 01:22:54 -05001234 std_handle: DWORD
1235 One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE.
1236 /
1237
1238Return a handle to the specified standard device.
1239
1240The integer associated with the handle object is returned.
1241[clinic start generated code]*/
1242
1243static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001244_winapi_GetStdHandle_impl(PyObject *module, DWORD std_handle)
1245/*[clinic end generated code: output=0e613001e73ab614 input=07016b06a2fc8826]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001246{
1247 HANDLE handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001248
1249 Py_BEGIN_ALLOW_THREADS
1250 handle = GetStdHandle(std_handle);
1251 Py_END_ALLOW_THREADS
1252
1253 if (handle == INVALID_HANDLE_VALUE)
Zachary Waref2244ea2015-05-13 01:22:54 -05001254 PyErr_SetFromWindowsErr(GetLastError());
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001255
Zachary Waref2244ea2015-05-13 01:22:54 -05001256 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001257}
1258
Zachary Waref2244ea2015-05-13 01:22:54 -05001259/*[clinic input]
1260_winapi.GetVersion -> long
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001261
Zachary Waref2244ea2015-05-13 01:22:54 -05001262Return the version number of the current operating system.
1263[clinic start generated code]*/
1264
1265static long
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001266_winapi_GetVersion_impl(PyObject *module)
1267/*[clinic end generated code: output=e41f0db5a3b82682 input=e21dff8d0baeded2]*/
Steve Dower3e96f322015-03-02 08:01:10 -08001268/* Disable deprecation warnings about GetVersionEx as the result is
1269 being passed straight through to the caller, who is responsible for
1270 using it correctly. */
1271#pragma warning(push)
1272#pragma warning(disable:4996)
1273
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001274{
Zachary Waref2244ea2015-05-13 01:22:54 -05001275 return GetVersion();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001276}
1277
Steve Dower3e96f322015-03-02 08:01:10 -08001278#pragma warning(pop)
1279
Zachary Waref2244ea2015-05-13 01:22:54 -05001280/*[clinic input]
1281_winapi.OpenProcess -> HANDLE
1282
1283 desired_access: DWORD
1284 inherit_handle: BOOL
1285 process_id: DWORD
1286 /
1287[clinic start generated code]*/
1288
1289static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001290_winapi_OpenProcess_impl(PyObject *module, DWORD desired_access,
Zachary Ware77772c02015-05-13 10:58:35 -05001291 BOOL inherit_handle, DWORD process_id)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001292/*[clinic end generated code: output=b42b6b81ea5a0fc3 input=ec98c4cf4ea2ec36]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001293{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001294 HANDLE handle;
1295
Zachary Waref2244ea2015-05-13 01:22:54 -05001296 handle = OpenProcess(desired_access, inherit_handle, process_id);
1297 if (handle == NULL) {
1298 PyErr_SetFromWindowsErr(0);
1299 handle = INVALID_HANDLE_VALUE;
1300 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001301
Zachary Waref2244ea2015-05-13 01:22:54 -05001302 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001303}
1304
Zachary Waref2244ea2015-05-13 01:22:54 -05001305/*[clinic input]
1306_winapi.PeekNamedPipe
1307
1308 handle: HANDLE
1309 size: int = 0
1310 /
1311[clinic start generated code]*/
1312
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001313static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001314_winapi_PeekNamedPipe_impl(PyObject *module, HANDLE handle, int size)
1315/*[clinic end generated code: output=d0c3e29e49d323dd input=c7aa53bfbce69d70]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001316{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001317 PyObject *buf = NULL;
1318 DWORD nread, navail, nleft;
1319 BOOL ret;
1320
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001321 if (size < 0) {
1322 PyErr_SetString(PyExc_ValueError, "negative size");
1323 return NULL;
1324 }
1325
1326 if (size) {
1327 buf = PyBytes_FromStringAndSize(NULL, size);
1328 if (!buf)
1329 return NULL;
1330 Py_BEGIN_ALLOW_THREADS
1331 ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread,
1332 &navail, &nleft);
1333 Py_END_ALLOW_THREADS
1334 if (!ret) {
1335 Py_DECREF(buf);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001336 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001337 }
1338 if (_PyBytes_Resize(&buf, nread))
1339 return NULL;
1340 return Py_BuildValue("Nii", buf, navail, nleft);
1341 }
1342 else {
1343 Py_BEGIN_ALLOW_THREADS
1344 ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft);
1345 Py_END_ALLOW_THREADS
1346 if (!ret) {
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001347 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001348 }
1349 return Py_BuildValue("ii", navail, nleft);
1350 }
1351}
1352
Zachary Waref2244ea2015-05-13 01:22:54 -05001353/*[clinic input]
1354_winapi.ReadFile
1355
1356 handle: HANDLE
1357 size: int
Serhiy Storchaka202fda52017-03-12 10:10:47 +02001358 overlapped as use_overlapped: bool(accept={int}) = False
Zachary Waref2244ea2015-05-13 01:22:54 -05001359[clinic start generated code]*/
1360
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001361static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001362_winapi_ReadFile_impl(PyObject *module, HANDLE handle, int size,
Zachary Ware77772c02015-05-13 10:58:35 -05001363 int use_overlapped)
Serhiy Storchaka202fda52017-03-12 10:10:47 +02001364/*[clinic end generated code: output=492029ca98161d84 input=3f0fde92f74de59a]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001365{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001366 DWORD nread;
1367 PyObject *buf;
1368 BOOL ret;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001369 DWORD err;
1370 OverlappedObject *overlapped = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001371
1372 buf = PyBytes_FromStringAndSize(NULL, size);
1373 if (!buf)
1374 return NULL;
1375 if (use_overlapped) {
1376 overlapped = new_overlapped(handle);
1377 if (!overlapped) {
1378 Py_DECREF(buf);
1379 return NULL;
1380 }
1381 /* Steals reference to buf */
1382 overlapped->read_buffer = buf;
1383 }
1384
1385 Py_BEGIN_ALLOW_THREADS
1386 ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread,
1387 overlapped ? &overlapped->overlapped : NULL);
1388 Py_END_ALLOW_THREADS
1389
1390 err = ret ? 0 : GetLastError();
1391
1392 if (overlapped) {
1393 if (!ret) {
1394 if (err == ERROR_IO_PENDING)
1395 overlapped->pending = 1;
1396 else if (err != ERROR_MORE_DATA) {
1397 Py_DECREF(overlapped);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001398 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001399 }
1400 }
1401 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1402 }
1403
1404 if (!ret && err != ERROR_MORE_DATA) {
1405 Py_DECREF(buf);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001406 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001407 }
1408 if (_PyBytes_Resize(&buf, nread))
1409 return NULL;
1410 return Py_BuildValue("NI", buf, err);
1411}
1412
Zachary Waref2244ea2015-05-13 01:22:54 -05001413/*[clinic input]
1414_winapi.SetNamedPipeHandleState
1415
1416 named_pipe: HANDLE
1417 mode: object
1418 max_collection_count: object
1419 collect_data_timeout: object
1420 /
1421[clinic start generated code]*/
1422
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001423static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001424_winapi_SetNamedPipeHandleState_impl(PyObject *module, HANDLE named_pipe,
Zachary Ware77772c02015-05-13 10:58:35 -05001425 PyObject *mode,
1426 PyObject *max_collection_count,
1427 PyObject *collect_data_timeout)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001428/*[clinic end generated code: output=f2129d222cbfa095 input=9142d72163d0faa6]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001429{
Zachary Waref2244ea2015-05-13 01:22:54 -05001430 PyObject *oArgs[3] = {mode, max_collection_count, collect_data_timeout};
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001431 DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL};
1432 int i;
1433
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001434 PyErr_Clear();
1435
1436 for (i = 0 ; i < 3 ; i++) {
1437 if (oArgs[i] != Py_None) {
1438 dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]);
1439 if (PyErr_Occurred())
1440 return NULL;
1441 pArgs[i] = &dwArgs[i];
1442 }
1443 }
1444
Zachary Waref2244ea2015-05-13 01:22:54 -05001445 if (!SetNamedPipeHandleState(named_pipe, pArgs[0], pArgs[1], pArgs[2]))
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001446 return PyErr_SetFromWindowsErr(0);
1447
1448 Py_RETURN_NONE;
1449}
1450
Zachary Waref2244ea2015-05-13 01:22:54 -05001451
1452/*[clinic input]
1453_winapi.TerminateProcess
1454
1455 handle: HANDLE
1456 exit_code: UINT
1457 /
1458
1459Terminate the specified process and all of its threads.
1460[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001461
1462static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001463_winapi_TerminateProcess_impl(PyObject *module, HANDLE handle,
Zachary Ware77772c02015-05-13 10:58:35 -05001464 UINT exit_code)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001465/*[clinic end generated code: output=f4e99ac3f0b1f34a input=d6bc0aa1ee3bb4df]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001466{
1467 BOOL result;
1468
Zachary Waref2244ea2015-05-13 01:22:54 -05001469 result = TerminateProcess(handle, exit_code);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001470
1471 if (! result)
1472 return PyErr_SetFromWindowsErr(GetLastError());
1473
Zachary Waref2244ea2015-05-13 01:22:54 -05001474 Py_RETURN_NONE;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001475}
1476
Zachary Waref2244ea2015-05-13 01:22:54 -05001477/*[clinic input]
1478_winapi.WaitNamedPipe
1479
1480 name: LPCTSTR
1481 timeout: DWORD
1482 /
1483[clinic start generated code]*/
1484
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001485static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001486_winapi_WaitNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD timeout)
1487/*[clinic end generated code: output=c2866f4439b1fe38 input=36fc781291b1862c]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001488{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001489 BOOL success;
1490
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001491 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -05001492 success = WaitNamedPipe(name, timeout);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001493 Py_END_ALLOW_THREADS
1494
1495 if (!success)
1496 return PyErr_SetFromWindowsErr(0);
1497
1498 Py_RETURN_NONE;
1499}
1500
Zachary Waref2244ea2015-05-13 01:22:54 -05001501/*[clinic input]
1502_winapi.WaitForMultipleObjects
1503
1504 handle_seq: object
1505 wait_flag: BOOL
1506 milliseconds: DWORD(c_default='INFINITE') = _winapi.INFINITE
1507 /
1508[clinic start generated code]*/
1509
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001510static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001511_winapi_WaitForMultipleObjects_impl(PyObject *module, PyObject *handle_seq,
1512 BOOL wait_flag, DWORD milliseconds)
1513/*[clinic end generated code: output=295e3f00b8e45899 input=36f76ca057cd28a0]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001514{
1515 DWORD result;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001516 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
1517 HANDLE sigint_event = NULL;
1518 Py_ssize_t nhandles, i;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001519
1520 if (!PySequence_Check(handle_seq)) {
1521 PyErr_Format(PyExc_TypeError,
1522 "sequence type expected, got '%s'",
Richard Oudkerk67339272012-08-21 14:54:22 +01001523 Py_TYPE(handle_seq)->tp_name);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001524 return NULL;
1525 }
1526 nhandles = PySequence_Length(handle_seq);
1527 if (nhandles == -1)
1528 return NULL;
1529 if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS - 1) {
1530 PyErr_Format(PyExc_ValueError,
1531 "need at most %zd handles, got a sequence of length %zd",
1532 MAXIMUM_WAIT_OBJECTS - 1, nhandles);
1533 return NULL;
1534 }
1535 for (i = 0; i < nhandles; i++) {
1536 HANDLE h;
1537 PyObject *v = PySequence_GetItem(handle_seq, i);
1538 if (v == NULL)
1539 return NULL;
1540 if (!PyArg_Parse(v, F_HANDLE, &h)) {
1541 Py_DECREF(v);
1542 return NULL;
1543 }
1544 handles[i] = h;
1545 Py_DECREF(v);
1546 }
1547 /* If this is the main thread then make the wait interruptible
1548 by Ctrl-C unless we are waiting for *all* handles */
1549 if (!wait_flag && _PyOS_IsMainThread()) {
1550 sigint_event = _PyOS_SigintEvent();
1551 assert(sigint_event != NULL);
1552 handles[nhandles++] = sigint_event;
1553 }
1554
1555 Py_BEGIN_ALLOW_THREADS
1556 if (sigint_event != NULL)
1557 ResetEvent(sigint_event);
1558 result = WaitForMultipleObjects((DWORD) nhandles, handles,
1559 wait_flag, milliseconds);
1560 Py_END_ALLOW_THREADS
1561
1562 if (result == WAIT_FAILED)
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001563 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001564 else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) {
1565 errno = EINTR;
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001566 return PyErr_SetFromErrno(PyExc_OSError);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001567 }
1568
1569 return PyLong_FromLong((int) result);
1570}
1571
Zachary Waref2244ea2015-05-13 01:22:54 -05001572/*[clinic input]
1573_winapi.WaitForSingleObject -> long
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001574
Zachary Waref2244ea2015-05-13 01:22:54 -05001575 handle: HANDLE
1576 milliseconds: DWORD
1577 /
1578
1579Wait for a single object.
1580
1581Wait until the specified object is in the signaled state or
1582the time-out interval elapses. The timeout value is specified
1583in milliseconds.
1584[clinic start generated code]*/
1585
1586static long
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001587_winapi_WaitForSingleObject_impl(PyObject *module, HANDLE handle,
Zachary Ware77772c02015-05-13 10:58:35 -05001588 DWORD milliseconds)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001589/*[clinic end generated code: output=3c4715d8f1b39859 input=443d1ab076edc7b1]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001590{
1591 DWORD result;
1592
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001593 Py_BEGIN_ALLOW_THREADS
1594 result = WaitForSingleObject(handle, milliseconds);
1595 Py_END_ALLOW_THREADS
1596
Zachary Waref2244ea2015-05-13 01:22:54 -05001597 if (result == WAIT_FAILED) {
1598 PyErr_SetFromWindowsErr(GetLastError());
1599 return -1;
1600 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001601
Zachary Waref2244ea2015-05-13 01:22:54 -05001602 return result;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001603}
1604
Zachary Waref2244ea2015-05-13 01:22:54 -05001605/*[clinic input]
1606_winapi.WriteFile
1607
1608 handle: HANDLE
1609 buffer: object
Serhiy Storchaka202fda52017-03-12 10:10:47 +02001610 overlapped as use_overlapped: bool(accept={int}) = False
Zachary Waref2244ea2015-05-13 01:22:54 -05001611[clinic start generated code]*/
1612
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001613static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001614_winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
Zachary Ware77772c02015-05-13 10:58:35 -05001615 int use_overlapped)
Serhiy Storchaka202fda52017-03-12 10:10:47 +02001616/*[clinic end generated code: output=2ca80f6bf3fa92e3 input=11eae2a03aa32731]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001617{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001618 Py_buffer _buf, *buf;
Victor Stinner71765772013-06-24 23:13:24 +02001619 DWORD len, written;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001620 BOOL ret;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001621 DWORD err;
1622 OverlappedObject *overlapped = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001623
1624 if (use_overlapped) {
1625 overlapped = new_overlapped(handle);
1626 if (!overlapped)
1627 return NULL;
1628 buf = &overlapped->write_buffer;
1629 }
1630 else
1631 buf = &_buf;
1632
Zachary Waref2244ea2015-05-13 01:22:54 -05001633 if (!PyArg_Parse(buffer, "y*", buf)) {
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001634 Py_XDECREF(overlapped);
1635 return NULL;
1636 }
1637
1638 Py_BEGIN_ALLOW_THREADS
Victor Stinner850a18e2017-10-24 16:53:32 -07001639 len = (DWORD)Py_MIN(buf->len, PY_DWORD_MAX);
Victor Stinner71765772013-06-24 23:13:24 +02001640 ret = WriteFile(handle, buf->buf, len, &written,
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001641 overlapped ? &overlapped->overlapped : NULL);
1642 Py_END_ALLOW_THREADS
1643
1644 err = ret ? 0 : GetLastError();
1645
1646 if (overlapped) {
1647 if (!ret) {
1648 if (err == ERROR_IO_PENDING)
1649 overlapped->pending = 1;
1650 else {
1651 Py_DECREF(overlapped);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001652 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001653 }
1654 }
1655 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1656 }
1657
1658 PyBuffer_Release(buf);
1659 if (!ret)
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001660 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001661 return Py_BuildValue("II", written, err);
1662}
1663
Victor Stinner91106cd2017-12-13 12:29:09 +01001664/*[clinic input]
1665_winapi.GetACP
1666
1667Get the current Windows ANSI code page identifier.
1668[clinic start generated code]*/
1669
1670static PyObject *
1671_winapi_GetACP_impl(PyObject *module)
1672/*[clinic end generated code: output=f7ee24bf705dbb88 input=1433c96d03a05229]*/
1673{
1674 return PyLong_FromUnsignedLong(GetACP());
1675}
1676
Segev Finerb2a60832017-12-18 11:28:19 +02001677/*[clinic input]
1678_winapi.GetFileType -> DWORD
1679
1680 handle: HANDLE
1681[clinic start generated code]*/
1682
1683static DWORD
1684_winapi_GetFileType_impl(PyObject *module, HANDLE handle)
1685/*[clinic end generated code: output=92b8466ac76ecc17 input=0058366bc40bbfbf]*/
1686{
1687 DWORD result;
1688
1689 Py_BEGIN_ALLOW_THREADS
1690 result = GetFileType(handle);
1691 Py_END_ALLOW_THREADS
1692
1693 if (result == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR) {
1694 PyErr_SetFromWindowsErr(0);
1695 return -1;
1696 }
1697
1698 return result;
1699}
1700
Victor Stinner91106cd2017-12-13 12:29:09 +01001701
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001702static PyMethodDef winapi_functions[] = {
Zachary Waref2244ea2015-05-13 01:22:54 -05001703 _WINAPI_CLOSEHANDLE_METHODDEF
1704 _WINAPI_CONNECTNAMEDPIPE_METHODDEF
1705 _WINAPI_CREATEFILE_METHODDEF
1706 _WINAPI_CREATENAMEDPIPE_METHODDEF
1707 _WINAPI_CREATEPIPE_METHODDEF
1708 _WINAPI_CREATEPROCESS_METHODDEF
1709 _WINAPI_CREATEJUNCTION_METHODDEF
1710 _WINAPI_DUPLICATEHANDLE_METHODDEF
1711 _WINAPI_EXITPROCESS_METHODDEF
1712 _WINAPI_GETCURRENTPROCESS_METHODDEF
1713 _WINAPI_GETEXITCODEPROCESS_METHODDEF
1714 _WINAPI_GETLASTERROR_METHODDEF
1715 _WINAPI_GETMODULEFILENAME_METHODDEF
1716 _WINAPI_GETSTDHANDLE_METHODDEF
1717 _WINAPI_GETVERSION_METHODDEF
1718 _WINAPI_OPENPROCESS_METHODDEF
1719 _WINAPI_PEEKNAMEDPIPE_METHODDEF
1720 _WINAPI_READFILE_METHODDEF
1721 _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF
1722 _WINAPI_TERMINATEPROCESS_METHODDEF
1723 _WINAPI_WAITNAMEDPIPE_METHODDEF
1724 _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF
1725 _WINAPI_WAITFORSINGLEOBJECT_METHODDEF
1726 _WINAPI_WRITEFILE_METHODDEF
Victor Stinner91106cd2017-12-13 12:29:09 +01001727 _WINAPI_GETACP_METHODDEF
Segev Finerb2a60832017-12-18 11:28:19 +02001728 _WINAPI_GETFILETYPE_METHODDEF
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001729 {NULL, NULL}
1730};
1731
1732static struct PyModuleDef winapi_module = {
1733 PyModuleDef_HEAD_INIT,
1734 "_winapi",
1735 NULL,
1736 -1,
1737 winapi_functions,
1738 NULL,
1739 NULL,
1740 NULL,
1741 NULL
1742};
1743
1744#define WINAPI_CONSTANT(fmt, con) \
1745 PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1746
1747PyMODINIT_FUNC
1748PyInit__winapi(void)
1749{
1750 PyObject *d;
1751 PyObject *m;
1752
1753 if (PyType_Ready(&OverlappedType) < 0)
1754 return NULL;
1755
1756 m = PyModule_Create(&winapi_module);
1757 if (m == NULL)
1758 return NULL;
1759 d = PyModule_GetDict(m);
1760
1761 PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType);
1762
1763 /* constants */
1764 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
1765 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP);
1766 WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001767 WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001768 WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
1769 WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
1770 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1771 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1772 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1773 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001774 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1775 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
Richard Oudkerkfdb8dcf2012-05-05 19:45:37 +01001776 WINAPI_CONSTANT(F_DWORD, ERROR_NO_DATA);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001777 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
1778 WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
1779 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
1780 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
1781 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
1782 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE);
1783 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001784 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ);
1785 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001786 WINAPI_CONSTANT(F_DWORD, GENERIC_READ);
1787 WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE);
1788 WINAPI_CONSTANT(F_DWORD, INFINITE);
1789 WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
1790 WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING);
1791 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
1792 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
1793 WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
1794 WINAPI_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE);
1795 WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES);
1796 WINAPI_CONSTANT(F_DWORD, PIPE_WAIT);
1797 WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001798 WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001799 WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW);
1800 WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES);
1801 WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE);
1802 WINAPI_CONSTANT(F_DWORD, STD_OUTPUT_HANDLE);
1803 WINAPI_CONSTANT(F_DWORD, STD_ERROR_HANDLE);
1804 WINAPI_CONSTANT(F_DWORD, STILL_ACTIVE);
1805 WINAPI_CONSTANT(F_DWORD, SW_HIDE);
1806 WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0);
Victor Stinner373f0a92014-03-20 09:26:55 +01001807 WINAPI_CONSTANT(F_DWORD, WAIT_ABANDONED_0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001808 WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT);
Victor Stinner91106cd2017-12-13 12:29:09 +01001809
Jamesb5d9e082017-11-08 14:18:59 +00001810 WINAPI_CONSTANT(F_DWORD, ABOVE_NORMAL_PRIORITY_CLASS);
1811 WINAPI_CONSTANT(F_DWORD, BELOW_NORMAL_PRIORITY_CLASS);
1812 WINAPI_CONSTANT(F_DWORD, HIGH_PRIORITY_CLASS);
1813 WINAPI_CONSTANT(F_DWORD, IDLE_PRIORITY_CLASS);
1814 WINAPI_CONSTANT(F_DWORD, NORMAL_PRIORITY_CLASS);
1815 WINAPI_CONSTANT(F_DWORD, REALTIME_PRIORITY_CLASS);
Victor Stinner91106cd2017-12-13 12:29:09 +01001816
Jamesb5d9e082017-11-08 14:18:59 +00001817 WINAPI_CONSTANT(F_DWORD, CREATE_NO_WINDOW);
1818 WINAPI_CONSTANT(F_DWORD, DETACHED_PROCESS);
1819 WINAPI_CONSTANT(F_DWORD, CREATE_DEFAULT_ERROR_MODE);
1820 WINAPI_CONSTANT(F_DWORD, CREATE_BREAKAWAY_FROM_JOB);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001821
Segev Finerb2a60832017-12-18 11:28:19 +02001822 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_UNKNOWN);
1823 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_DISK);
1824 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_CHAR);
1825 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_PIPE);
1826 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_REMOTE);
1827
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001828 WINAPI_CONSTANT("i", NULL);
1829
1830 return m;
1831}