blob: 44788e5992a0ddfd682824fe5e12c1818f86b46c [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')
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200166create_converter('LPCWSTR', 'u')
Zachary Waref2244ea2015-05-13 01:22:54 -0500167create_converter('LPWSTR', 'u')
168create_converter('UINT', 'I') # F_UINT used previously (always 'I')
169
170class HANDLE_return_converter(CReturnConverter):
171 type = 'HANDLE'
172
173 def render(self, function, data):
174 self.declare(data)
175 self.err_occurred_if("_return_value == INVALID_HANDLE_VALUE", data)
176 data.return_conversion.append(
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300177 'if (_return_value == NULL) {\n Py_RETURN_NONE;\n}\n')
Zachary Waref2244ea2015-05-13 01:22:54 -0500178 data.return_conversion.append(
179 'return_value = HANDLE_TO_PYNUM(_return_value);\n')
180
181class DWORD_return_converter(CReturnConverter):
182 type = 'DWORD'
183
184 def render(self, function, data):
185 self.declare(data)
Victor Stinner850a18e2017-10-24 16:53:32 -0700186 self.err_occurred_if("_return_value == PY_DWORD_MAX", data)
Zachary Waref2244ea2015-05-13 01:22:54 -0500187 data.return_conversion.append(
188 'return_value = Py_BuildValue("k", _return_value);\n')
189[python start generated code]*/
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200190/*[python end generated code: output=da39a3ee5e6b4b0d input=27456f8555228b62]*/
Zachary Waref2244ea2015-05-13 01:22:54 -0500191
192#include "clinic/_winapi.c.h"
193
194/*[clinic input]
195_winapi.Overlapped.GetOverlappedResult
196
197 wait: bool
198 /
199[clinic start generated code]*/
200
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200201static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500202_winapi_Overlapped_GetOverlappedResult_impl(OverlappedObject *self, int wait)
203/*[clinic end generated code: output=bdd0c1ed6518cd03 input=194505ee8e0e3565]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200204{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200205 BOOL res;
206 DWORD transferred = 0;
207 DWORD err;
208
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200209 Py_BEGIN_ALLOW_THREADS
210 res = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
211 wait != 0);
212 Py_END_ALLOW_THREADS
213
214 err = res ? ERROR_SUCCESS : GetLastError();
215 switch (err) {
216 case ERROR_SUCCESS:
217 case ERROR_MORE_DATA:
218 case ERROR_OPERATION_ABORTED:
219 self->completed = 1;
220 self->pending = 0;
221 break;
222 case ERROR_IO_INCOMPLETE:
223 break;
224 default:
225 self->pending = 0;
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300226 return PyErr_SetExcFromWindowsErr(PyExc_OSError, err);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200227 }
228 if (self->completed && self->read_buffer != NULL) {
229 assert(PyBytes_CheckExact(self->read_buffer));
230 if (transferred != PyBytes_GET_SIZE(self->read_buffer) &&
231 _PyBytes_Resize(&self->read_buffer, transferred))
232 return NULL;
233 }
234 return Py_BuildValue("II", (unsigned) transferred, (unsigned) err);
235}
236
Zachary Waref2244ea2015-05-13 01:22:54 -0500237/*[clinic input]
238_winapi.Overlapped.getbuffer
239[clinic start generated code]*/
240
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200241static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500242_winapi_Overlapped_getbuffer_impl(OverlappedObject *self)
243/*[clinic end generated code: output=95a3eceefae0f748 input=347fcfd56b4ceabd]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200244{
245 PyObject *res;
246 if (!self->completed) {
247 PyErr_SetString(PyExc_ValueError,
248 "can't get read buffer before GetOverlappedResult() "
249 "signals the operation completed");
250 return NULL;
251 }
252 res = self->read_buffer ? self->read_buffer : Py_None;
253 Py_INCREF(res);
254 return res;
255}
256
Zachary Waref2244ea2015-05-13 01:22:54 -0500257/*[clinic input]
258_winapi.Overlapped.cancel
259[clinic start generated code]*/
260
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200261static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500262_winapi_Overlapped_cancel_impl(OverlappedObject *self)
263/*[clinic end generated code: output=fcb9ab5df4ebdae5 input=cbf3da142290039f]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200264{
265 BOOL res = TRUE;
266
267 if (self->pending) {
268 Py_BEGIN_ALLOW_THREADS
269 if (check_CancelIoEx())
270 res = Py_CancelIoEx(self->handle, &self->overlapped);
271 else
272 res = CancelIo(self->handle);
273 Py_END_ALLOW_THREADS
274 }
275
276 /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
277 if (!res && GetLastError() != ERROR_NOT_FOUND)
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300278 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200279 self->pending = 0;
280 Py_RETURN_NONE;
281}
282
283static PyMethodDef overlapped_methods[] = {
Zachary Waref2244ea2015-05-13 01:22:54 -0500284 _WINAPI_OVERLAPPED_GETOVERLAPPEDRESULT_METHODDEF
285 _WINAPI_OVERLAPPED_GETBUFFER_METHODDEF
286 _WINAPI_OVERLAPPED_CANCEL_METHODDEF
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200287 {NULL}
288};
289
290static PyMemberDef overlapped_members[] = {
291 {"event", T_HANDLE,
292 offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
293 READONLY, "overlapped event handle"},
294 {NULL}
295};
296
297PyTypeObject OverlappedType = {
298 PyVarObject_HEAD_INIT(NULL, 0)
299 /* tp_name */ "_winapi.Overlapped",
300 /* tp_basicsize */ sizeof(OverlappedObject),
301 /* tp_itemsize */ 0,
302 /* tp_dealloc */ (destructor) overlapped_dealloc,
303 /* tp_print */ 0,
304 /* tp_getattr */ 0,
305 /* tp_setattr */ 0,
306 /* tp_reserved */ 0,
307 /* tp_repr */ 0,
308 /* tp_as_number */ 0,
309 /* tp_as_sequence */ 0,
310 /* tp_as_mapping */ 0,
311 /* tp_hash */ 0,
312 /* tp_call */ 0,
313 /* tp_str */ 0,
314 /* tp_getattro */ 0,
315 /* tp_setattro */ 0,
316 /* tp_as_buffer */ 0,
317 /* tp_flags */ Py_TPFLAGS_DEFAULT,
318 /* tp_doc */ "OVERLAPPED structure wrapper",
319 /* tp_traverse */ 0,
320 /* tp_clear */ 0,
321 /* tp_richcompare */ 0,
322 /* tp_weaklistoffset */ 0,
323 /* tp_iter */ 0,
324 /* tp_iternext */ 0,
325 /* tp_methods */ overlapped_methods,
326 /* tp_members */ overlapped_members,
327 /* tp_getset */ 0,
328 /* tp_base */ 0,
329 /* tp_dict */ 0,
330 /* tp_descr_get */ 0,
331 /* tp_descr_set */ 0,
332 /* tp_dictoffset */ 0,
333 /* tp_init */ 0,
334 /* tp_alloc */ 0,
335 /* tp_new */ 0,
336};
337
338static OverlappedObject *
339new_overlapped(HANDLE handle)
340{
341 OverlappedObject *self;
342
343 self = PyObject_New(OverlappedObject, &OverlappedType);
344 if (!self)
345 return NULL;
346 self->handle = handle;
347 self->read_buffer = NULL;
348 self->pending = 0;
349 self->completed = 0;
350 memset(&self->overlapped, 0, sizeof(OVERLAPPED));
351 memset(&self->write_buffer, 0, sizeof(Py_buffer));
352 /* Manual reset, initially non-signalled */
353 self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
354 return self;
355}
356
357/* -------------------------------------------------------------------- */
358/* windows API functions */
359
Zachary Waref2244ea2015-05-13 01:22:54 -0500360/*[clinic input]
361_winapi.CloseHandle
362
363 handle: HANDLE
364 /
365
366Close handle.
367[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200368
369static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300370_winapi_CloseHandle_impl(PyObject *module, HANDLE handle)
371/*[clinic end generated code: output=7ad37345f07bd782 input=7f0e4ac36e0352b8]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200372{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200373 BOOL success;
374
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200375 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500376 success = CloseHandle(handle);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200377 Py_END_ALLOW_THREADS
378
379 if (!success)
380 return PyErr_SetFromWindowsErr(0);
381
382 Py_RETURN_NONE;
383}
384
Zachary Waref2244ea2015-05-13 01:22:54 -0500385/*[clinic input]
386_winapi.ConnectNamedPipe
387
388 handle: HANDLE
Serhiy Storchaka202fda52017-03-12 10:10:47 +0200389 overlapped as use_overlapped: bool(accept={int}) = False
Zachary Waref2244ea2015-05-13 01:22:54 -0500390[clinic start generated code]*/
391
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200392static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300393_winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle,
Zachary Ware77772c02015-05-13 10:58:35 -0500394 int use_overlapped)
Serhiy Storchaka202fda52017-03-12 10:10:47 +0200395/*[clinic end generated code: output=335a0e7086800671 input=34f937c1c86e5e68]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200396{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200397 BOOL success;
398 OverlappedObject *overlapped = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200399
400 if (use_overlapped) {
Zachary Waref2244ea2015-05-13 01:22:54 -0500401 overlapped = new_overlapped(handle);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200402 if (!overlapped)
403 return NULL;
404 }
405
406 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500407 success = ConnectNamedPipe(handle,
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200408 overlapped ? &overlapped->overlapped : NULL);
409 Py_END_ALLOW_THREADS
410
411 if (overlapped) {
412 int err = GetLastError();
413 /* Overlapped ConnectNamedPipe never returns a success code */
414 assert(success == 0);
415 if (err == ERROR_IO_PENDING)
416 overlapped->pending = 1;
417 else if (err == ERROR_PIPE_CONNECTED)
418 SetEvent(overlapped->overlapped.hEvent);
419 else {
420 Py_DECREF(overlapped);
421 return PyErr_SetFromWindowsErr(err);
422 }
423 return (PyObject *) overlapped;
424 }
425 if (!success)
426 return PyErr_SetFromWindowsErr(0);
427
428 Py_RETURN_NONE;
429}
430
Zachary Waref2244ea2015-05-13 01:22:54 -0500431/*[clinic input]
432_winapi.CreateFile -> HANDLE
433
434 file_name: LPCTSTR
435 desired_access: DWORD
436 share_mode: DWORD
437 security_attributes: LPSECURITY_ATTRIBUTES
438 creation_disposition: DWORD
439 flags_and_attributes: DWORD
440 template_file: HANDLE
441 /
442[clinic start generated code]*/
443
444static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300445_winapi_CreateFile_impl(PyObject *module, LPCTSTR file_name,
Zachary Ware77772c02015-05-13 10:58:35 -0500446 DWORD desired_access, DWORD share_mode,
447 LPSECURITY_ATTRIBUTES security_attributes,
448 DWORD creation_disposition,
449 DWORD flags_and_attributes, HANDLE template_file)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300450/*[clinic end generated code: output=417ddcebfc5a3d53 input=6423c3e40372dbd5]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200451{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200452 HANDLE handle;
453
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200454 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500455 handle = CreateFile(file_name, desired_access,
456 share_mode, security_attributes,
457 creation_disposition,
458 flags_and_attributes, template_file);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200459 Py_END_ALLOW_THREADS
460
461 if (handle == INVALID_HANDLE_VALUE)
Zachary Waref2244ea2015-05-13 01:22:54 -0500462 PyErr_SetFromWindowsErr(0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200463
Zachary Waref2244ea2015-05-13 01:22:54 -0500464 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200465}
466
Zachary Waref2244ea2015-05-13 01:22:54 -0500467/*[clinic input]
468_winapi.CreateJunction
Tim Golden0321cf22014-05-05 19:46:17 +0100469
Zachary Waref2244ea2015-05-13 01:22:54 -0500470 src_path: LPWSTR
471 dst_path: LPWSTR
472 /
473[clinic start generated code]*/
474
475static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300476_winapi_CreateJunction_impl(PyObject *module, LPWSTR src_path,
Zachary Ware77772c02015-05-13 10:58:35 -0500477 LPWSTR dst_path)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300478/*[clinic end generated code: output=66b7eb746e1dfa25 input=8cd1f9964b6e3d36]*/
Zachary Waref2244ea2015-05-13 01:22:54 -0500479{
Tim Golden0321cf22014-05-05 19:46:17 +0100480 /* Privilege adjustment */
481 HANDLE token = NULL;
482 TOKEN_PRIVILEGES tp;
483
484 /* Reparse data buffer */
485 const USHORT prefix_len = 4;
486 USHORT print_len = 0;
487 USHORT rdb_size = 0;
Martin Panter70214ad2016-08-04 02:38:59 +0000488 _Py_PREPARSE_DATA_BUFFER rdb = NULL;
Tim Golden0321cf22014-05-05 19:46:17 +0100489
490 /* Junction point creation */
491 HANDLE junction = NULL;
492 DWORD ret = 0;
493
Tim Golden0321cf22014-05-05 19:46:17 +0100494 if (src_path == NULL || dst_path == NULL)
495 return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
496
497 if (wcsncmp(src_path, L"\\??\\", prefix_len) == 0)
498 return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
499
500 /* Adjust privileges to allow rewriting directory entry as a
501 junction point. */
502 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
503 goto cleanup;
504
505 if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid))
506 goto cleanup;
507
508 tp.PrivilegeCount = 1;
509 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
510 if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
511 NULL, NULL))
512 goto cleanup;
513
514 if (GetFileAttributesW(src_path) == INVALID_FILE_ATTRIBUTES)
515 goto cleanup;
516
517 /* Store the absolute link target path length in print_len. */
518 print_len = (USHORT)GetFullPathNameW(src_path, 0, NULL, NULL);
519 if (print_len == 0)
520 goto cleanup;
521
522 /* NUL terminator should not be part of print_len. */
523 --print_len;
524
525 /* REPARSE_DATA_BUFFER usage is heavily under-documented, especially for
526 junction points. Here's what I've learned along the way:
527 - A junction point has two components: a print name and a substitute
528 name. They both describe the link target, but the substitute name is
529 the physical target and the print name is shown in directory listings.
530 - The print name must be a native name, prefixed with "\??\".
531 - Both names are stored after each other in the same buffer (the
532 PathBuffer) and both must be NUL-terminated.
533 - There are four members defining their respective offset and length
534 inside PathBuffer: SubstituteNameOffset, SubstituteNameLength,
535 PrintNameOffset and PrintNameLength.
536 - The total size we need to allocate for the REPARSE_DATA_BUFFER, thus,
537 is the sum of:
538 - the fixed header size (REPARSE_DATA_BUFFER_HEADER_SIZE)
539 - the size of the MountPointReparseBuffer member without the PathBuffer
540 - the size of the prefix ("\??\") in bytes
541 - the size of the print name in bytes
542 - the size of the substitute name in bytes
543 - the size of two NUL terminators in bytes */
Martin Panter70214ad2016-08-04 02:38:59 +0000544 rdb_size = _Py_REPARSE_DATA_BUFFER_HEADER_SIZE +
Tim Golden0321cf22014-05-05 19:46:17 +0100545 sizeof(rdb->MountPointReparseBuffer) -
546 sizeof(rdb->MountPointReparseBuffer.PathBuffer) +
547 /* Two +1's for NUL terminators. */
548 (prefix_len + print_len + 1 + print_len + 1) * sizeof(WCHAR);
Martin Panter70214ad2016-08-04 02:38:59 +0000549 rdb = (_Py_PREPARSE_DATA_BUFFER)PyMem_RawMalloc(rdb_size);
Tim Golden0321cf22014-05-05 19:46:17 +0100550 if (rdb == NULL)
551 goto cleanup;
552
553 memset(rdb, 0, rdb_size);
554 rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
Martin Panter70214ad2016-08-04 02:38:59 +0000555 rdb->ReparseDataLength = rdb_size - _Py_REPARSE_DATA_BUFFER_HEADER_SIZE;
Tim Golden0321cf22014-05-05 19:46:17 +0100556 rdb->MountPointReparseBuffer.SubstituteNameOffset = 0;
557 rdb->MountPointReparseBuffer.SubstituteNameLength =
558 (prefix_len + print_len) * sizeof(WCHAR);
559 rdb->MountPointReparseBuffer.PrintNameOffset =
560 rdb->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
561 rdb->MountPointReparseBuffer.PrintNameLength = print_len * sizeof(WCHAR);
562
563 /* Store the full native path of link target at the substitute name
564 offset (0). */
565 wcscpy(rdb->MountPointReparseBuffer.PathBuffer, L"\\??\\");
566 if (GetFullPathNameW(src_path, print_len + 1,
567 rdb->MountPointReparseBuffer.PathBuffer + prefix_len,
568 NULL) == 0)
569 goto cleanup;
570
571 /* Copy everything but the native prefix to the print name offset. */
572 wcscpy(rdb->MountPointReparseBuffer.PathBuffer +
573 prefix_len + print_len + 1,
574 rdb->MountPointReparseBuffer.PathBuffer + prefix_len);
575
576 /* Create a directory for the junction point. */
577 if (!CreateDirectoryW(dst_path, NULL))
578 goto cleanup;
579
580 junction = CreateFileW(dst_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
581 OPEN_EXISTING,
582 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
583 if (junction == INVALID_HANDLE_VALUE)
584 goto cleanup;
585
586 /* Make the directory entry a junction point. */
587 if (!DeviceIoControl(junction, FSCTL_SET_REPARSE_POINT, rdb, rdb_size,
588 NULL, 0, &ret, NULL))
589 goto cleanup;
590
591cleanup:
592 ret = GetLastError();
593
594 CloseHandle(token);
595 CloseHandle(junction);
596 PyMem_RawFree(rdb);
597
598 if (ret != 0)
599 return PyErr_SetFromWindowsErr(ret);
600
601 Py_RETURN_NONE;
602}
603
Zachary Waref2244ea2015-05-13 01:22:54 -0500604/*[clinic input]
605_winapi.CreateNamedPipe -> HANDLE
606
607 name: LPCTSTR
608 open_mode: DWORD
609 pipe_mode: DWORD
610 max_instances: DWORD
611 out_buffer_size: DWORD
612 in_buffer_size: DWORD
613 default_timeout: DWORD
614 security_attributes: LPSECURITY_ATTRIBUTES
615 /
616[clinic start generated code]*/
617
618static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300619_winapi_CreateNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD open_mode,
620 DWORD pipe_mode, DWORD max_instances,
621 DWORD out_buffer_size, DWORD in_buffer_size,
622 DWORD default_timeout,
Zachary Ware77772c02015-05-13 10:58:35 -0500623 LPSECURITY_ATTRIBUTES security_attributes)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300624/*[clinic end generated code: output=80f8c07346a94fbc input=5a73530b84d8bc37]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200625{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200626 HANDLE handle;
627
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200628 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500629 handle = CreateNamedPipe(name, open_mode, pipe_mode,
630 max_instances, out_buffer_size,
631 in_buffer_size, default_timeout,
632 security_attributes);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200633 Py_END_ALLOW_THREADS
634
635 if (handle == INVALID_HANDLE_VALUE)
Zachary Waref2244ea2015-05-13 01:22:54 -0500636 PyErr_SetFromWindowsErr(0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200637
Zachary Waref2244ea2015-05-13 01:22:54 -0500638 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200639}
640
Zachary Waref2244ea2015-05-13 01:22:54 -0500641/*[clinic input]
642_winapi.CreatePipe
643
644 pipe_attrs: object
645 Ignored internally, can be None.
646 size: DWORD
647 /
648
649Create an anonymous pipe.
650
651Returns a 2-tuple of handles, to the read and write ends of the pipe.
652[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200653
654static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300655_winapi_CreatePipe_impl(PyObject *module, PyObject *pipe_attrs, DWORD size)
656/*[clinic end generated code: output=1c4411d8699f0925 input=c4f2cfa56ef68d90]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200657{
658 HANDLE read_pipe;
659 HANDLE write_pipe;
660 BOOL result;
661
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200662 Py_BEGIN_ALLOW_THREADS
663 result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
664 Py_END_ALLOW_THREADS
665
666 if (! result)
667 return PyErr_SetFromWindowsErr(GetLastError());
668
669 return Py_BuildValue(
670 "NN", HANDLE_TO_PYNUM(read_pipe), HANDLE_TO_PYNUM(write_pipe));
671}
672
673/* helpers for createprocess */
674
675static unsigned long
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200676getulong(PyObject* obj, const char* name)
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200677{
678 PyObject* value;
679 unsigned long ret;
680
681 value = PyObject_GetAttrString(obj, name);
682 if (! value) {
683 PyErr_Clear(); /* FIXME: propagate error? */
684 return 0;
685 }
686 ret = PyLong_AsUnsignedLong(value);
687 Py_DECREF(value);
688 return ret;
689}
690
691static HANDLE
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200692gethandle(PyObject* obj, const char* name)
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200693{
694 PyObject* value;
695 HANDLE ret;
696
697 value = PyObject_GetAttrString(obj, name);
698 if (! value) {
699 PyErr_Clear(); /* FIXME: propagate error? */
700 return NULL;
701 }
702 if (value == Py_None)
703 ret = NULL;
704 else
705 ret = PYNUM_TO_HANDLE(value);
706 Py_DECREF(value);
707 return ret;
708}
709
710static PyObject*
711getenvironment(PyObject* environment)
712{
713 Py_ssize_t i, envsize, totalsize;
714 Py_UCS4 *buffer = NULL, *p, *end;
715 PyObject *keys, *values, *res;
716
Ezio Melotti85a86292013-08-17 16:57:41 +0300717 /* convert environment dictionary to windows environment string */
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200718 if (! PyMapping_Check(environment)) {
719 PyErr_SetString(
720 PyExc_TypeError, "environment must be dictionary or None");
721 return NULL;
722 }
723
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200724 keys = PyMapping_Keys(environment);
Oren Milman0b3a87e2017-09-14 22:30:28 +0300725 if (!keys) {
726 return NULL;
727 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200728 values = PyMapping_Values(environment);
Oren Milman0b3a87e2017-09-14 22:30:28 +0300729 if (!values) {
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200730 goto error;
Oren Milman0b3a87e2017-09-14 22:30:28 +0300731 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200732
Serhiy Storchakabf623ae2017-04-19 20:03:52 +0300733 envsize = PySequence_Fast_GET_SIZE(keys);
734 if (PySequence_Fast_GET_SIZE(values) != envsize) {
735 PyErr_SetString(PyExc_RuntimeError,
736 "environment changed size during iteration");
737 goto error;
738 }
739
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200740 totalsize = 1; /* trailing null character */
741 for (i = 0; i < envsize; i++) {
Serhiy Storchakabf623ae2017-04-19 20:03:52 +0300742 PyObject* key = PySequence_Fast_GET_ITEM(keys, i);
743 PyObject* value = PySequence_Fast_GET_ITEM(values, i);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200744
745 if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
746 PyErr_SetString(PyExc_TypeError,
747 "environment can only contain strings");
748 goto error;
749 }
Serhiy Storchakad174d242017-06-23 19:39:27 +0300750 if (PyUnicode_FindChar(key, '\0', 0, PyUnicode_GET_LENGTH(key), 1) != -1 ||
751 PyUnicode_FindChar(value, '\0', 0, PyUnicode_GET_LENGTH(value), 1) != -1)
752 {
753 PyErr_SetString(PyExc_ValueError, "embedded null character");
754 goto error;
755 }
756 /* Search from index 1 because on Windows starting '=' is allowed for
757 defining hidden environment variables. */
758 if (PyUnicode_GET_LENGTH(key) == 0 ||
759 PyUnicode_FindChar(key, '=', 1, PyUnicode_GET_LENGTH(key), 1) != -1)
760 {
761 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
762 goto error;
763 }
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500764 if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(key) - 1) {
765 PyErr_SetString(PyExc_OverflowError, "environment too long");
766 goto error;
767 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200768 totalsize += PyUnicode_GET_LENGTH(key) + 1; /* +1 for '=' */
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500769 if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(value) - 1) {
770 PyErr_SetString(PyExc_OverflowError, "environment too long");
771 goto error;
772 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200773 totalsize += PyUnicode_GET_LENGTH(value) + 1; /* +1 for '\0' */
774 }
775
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500776 buffer = PyMem_NEW(Py_UCS4, totalsize);
777 if (! buffer) {
778 PyErr_NoMemory();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200779 goto error;
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500780 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200781 p = buffer;
782 end = buffer + totalsize;
783
784 for (i = 0; i < envsize; i++) {
Serhiy Storchakabf623ae2017-04-19 20:03:52 +0300785 PyObject* key = PySequence_Fast_GET_ITEM(keys, i);
786 PyObject* value = PySequence_Fast_GET_ITEM(values, i);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200787 if (!PyUnicode_AsUCS4(key, p, end - p, 0))
788 goto error;
789 p += PyUnicode_GET_LENGTH(key);
790 *p++ = '=';
791 if (!PyUnicode_AsUCS4(value, p, end - p, 0))
792 goto error;
793 p += PyUnicode_GET_LENGTH(value);
794 *p++ = '\0';
795 }
796
797 /* add trailing null byte */
798 *p++ = '\0';
799 assert(p == end);
800
801 Py_XDECREF(keys);
802 Py_XDECREF(values);
803
804 res = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buffer, p - buffer);
805 PyMem_Free(buffer);
806 return res;
807
808 error:
809 PyMem_Free(buffer);
810 Py_XDECREF(keys);
811 Py_XDECREF(values);
812 return NULL;
813}
814
Segev Finerb2a60832017-12-18 11:28:19 +0200815static LPHANDLE
816gethandlelist(PyObject *mapping, const char *name, Py_ssize_t *size)
817{
818 LPHANDLE ret = NULL;
819 PyObject *value_fast = NULL;
820 PyObject *value;
821 Py_ssize_t i;
822
823 value = PyMapping_GetItemString(mapping, name);
824 if (!value) {
825 PyErr_Clear();
826 return NULL;
827 }
828
829 if (value == Py_None) {
830 goto cleanup;
831 }
832
833 value_fast = PySequence_Fast(value, "handle_list must be a sequence or None");
834 if (value_fast == NULL)
835 goto cleanup;
836
837 *size = PySequence_Fast_GET_SIZE(value_fast) * sizeof(HANDLE);
838
839 /* Passing an empty array causes CreateProcess to fail so just don't set it */
840 if (*size == 0) {
841 goto cleanup;
842 }
843
844 ret = PyMem_Malloc(*size);
845 if (ret == NULL)
846 goto cleanup;
847
848 for (i = 0; i < PySequence_Fast_GET_SIZE(value_fast); i++) {
849 ret[i] = PYNUM_TO_HANDLE(PySequence_Fast_GET_ITEM(value_fast, i));
850 if (ret[i] == (HANDLE)-1 && PyErr_Occurred()) {
851 PyMem_Free(ret);
852 ret = NULL;
853 goto cleanup;
854 }
855 }
856
857cleanup:
858 Py_DECREF(value);
859 Py_XDECREF(value_fast);
860 return ret;
861}
862
863typedef struct {
864 LPPROC_THREAD_ATTRIBUTE_LIST attribute_list;
865 LPHANDLE handle_list;
866} AttributeList;
867
868static void
869freeattributelist(AttributeList *attribute_list)
870{
871 if (attribute_list->attribute_list != NULL) {
872 DeleteProcThreadAttributeList(attribute_list->attribute_list);
873 PyMem_Free(attribute_list->attribute_list);
874 }
875
876 PyMem_Free(attribute_list->handle_list);
877
878 memset(attribute_list, 0, sizeof(*attribute_list));
879}
880
881static int
882getattributelist(PyObject *obj, const char *name, AttributeList *attribute_list)
883{
884 int ret = 0;
885 DWORD err;
886 BOOL result;
887 PyObject *value;
888 Py_ssize_t handle_list_size;
889 DWORD attribute_count = 0;
890 SIZE_T attribute_list_size = 0;
891
892 value = PyObject_GetAttrString(obj, name);
893 if (!value) {
894 PyErr_Clear(); /* FIXME: propagate error? */
895 return 0;
896 }
897
898 if (value == Py_None) {
899 ret = 0;
900 goto cleanup;
901 }
902
903 if (!PyMapping_Check(value)) {
904 ret = -1;
905 PyErr_Format(PyExc_TypeError, "%s must be a mapping or None", name);
906 goto cleanup;
907 }
908
909 attribute_list->handle_list = gethandlelist(value, "handle_list", &handle_list_size);
910 if (attribute_list->handle_list == NULL && PyErr_Occurred()) {
911 ret = -1;
912 goto cleanup;
913 }
914
915 if (attribute_list->handle_list != NULL)
916 ++attribute_count;
917
918 /* Get how many bytes we need for the attribute list */
919 result = InitializeProcThreadAttributeList(NULL, attribute_count, 0, &attribute_list_size);
920 if (result || GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
921 ret = -1;
922 PyErr_SetFromWindowsErr(GetLastError());
923 goto cleanup;
924 }
925
926 attribute_list->attribute_list = PyMem_Malloc(attribute_list_size);
927 if (attribute_list->attribute_list == NULL) {
928 ret = -1;
929 goto cleanup;
930 }
931
932 result = InitializeProcThreadAttributeList(
933 attribute_list->attribute_list,
934 attribute_count,
935 0,
936 &attribute_list_size);
937 if (!result) {
938 err = GetLastError();
939
940 /* So that we won't call DeleteProcThreadAttributeList */
941 PyMem_Free(attribute_list->attribute_list);
942 attribute_list->attribute_list = NULL;
943
944 ret = -1;
945 PyErr_SetFromWindowsErr(err);
946 goto cleanup;
947 }
948
949 if (attribute_list->handle_list != NULL) {
950 result = UpdateProcThreadAttribute(
951 attribute_list->attribute_list,
952 0,
953 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
954 attribute_list->handle_list,
955 handle_list_size,
956 NULL,
957 NULL);
958 if (!result) {
959 ret = -1;
960 PyErr_SetFromWindowsErr(GetLastError());
961 goto cleanup;
962 }
963 }
964
965cleanup:
966 Py_DECREF(value);
967
968 if (ret < 0)
969 freeattributelist(attribute_list);
970
971 return ret;
972}
973
Zachary Waref2244ea2015-05-13 01:22:54 -0500974/*[clinic input]
975_winapi.CreateProcess
976
Zachary Ware77772c02015-05-13 10:58:35 -0500977 application_name: Py_UNICODE(accept={str, NoneType})
978 command_line: Py_UNICODE(accept={str, NoneType})
Zachary Waref2244ea2015-05-13 01:22:54 -0500979 proc_attrs: object
980 Ignored internally, can be None.
981 thread_attrs: object
982 Ignored internally, can be None.
983 inherit_handles: BOOL
984 creation_flags: DWORD
985 env_mapping: object
Zachary Ware77772c02015-05-13 10:58:35 -0500986 current_directory: Py_UNICODE(accept={str, NoneType})
Zachary Waref2244ea2015-05-13 01:22:54 -0500987 startup_info: object
988 /
989
990Create a new process and its primary thread.
991
992The return value is a tuple of the process handle, thread handle,
993process ID, and thread ID.
994[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200995
996static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300997_winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name,
Zachary Ware77772c02015-05-13 10:58:35 -0500998 Py_UNICODE *command_line, PyObject *proc_attrs,
999 PyObject *thread_attrs, BOOL inherit_handles,
1000 DWORD creation_flags, PyObject *env_mapping,
1001 Py_UNICODE *current_directory,
1002 PyObject *startup_info)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001003/*[clinic end generated code: output=4652a33aff4b0ae1 input=4a43b05038d639bb]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001004{
Segev Finerb2a60832017-12-18 11:28:19 +02001005 PyObject *ret = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001006 BOOL result;
1007 PROCESS_INFORMATION pi;
Segev Finerb2a60832017-12-18 11:28:19 +02001008 STARTUPINFOEXW si;
1009 PyObject *environment = NULL;
Serhiy Storchaka0ee32c12017-06-24 16:14:08 +03001010 wchar_t *wenvironment;
Segev Finerb2a60832017-12-18 11:28:19 +02001011 AttributeList attribute_list = {0};
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001012
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001013 ZeroMemory(&si, sizeof(si));
Segev Finerb2a60832017-12-18 11:28:19 +02001014 si.StartupInfo.cb = sizeof(si);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001015
1016 /* note: we only support a small subset of all SI attributes */
Segev Finerb2a60832017-12-18 11:28:19 +02001017 si.StartupInfo.dwFlags = getulong(startup_info, "dwFlags");
1018 si.StartupInfo.wShowWindow = (WORD)getulong(startup_info, "wShowWindow");
1019 si.StartupInfo.hStdInput = gethandle(startup_info, "hStdInput");
1020 si.StartupInfo.hStdOutput = gethandle(startup_info, "hStdOutput");
1021 si.StartupInfo.hStdError = gethandle(startup_info, "hStdError");
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001022 if (PyErr_Occurred())
Segev Finerb2a60832017-12-18 11:28:19 +02001023 goto cleanup;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001024
1025 if (env_mapping != Py_None) {
1026 environment = getenvironment(env_mapping);
Serhiy Storchakad174d242017-06-23 19:39:27 +03001027 if (environment == NULL) {
Segev Finerb2a60832017-12-18 11:28:19 +02001028 goto cleanup;
Serhiy Storchakad174d242017-06-23 19:39:27 +03001029 }
1030 /* contains embedded null characters */
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001031 wenvironment = PyUnicode_AsUnicode(environment);
Serhiy Storchakad174d242017-06-23 19:39:27 +03001032 if (wenvironment == NULL) {
Segev Finerb2a60832017-12-18 11:28:19 +02001033 goto cleanup;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001034 }
1035 }
1036 else {
1037 environment = NULL;
1038 wenvironment = NULL;
1039 }
1040
Segev Finerb2a60832017-12-18 11:28:19 +02001041 if (getattributelist(startup_info, "lpAttributeList", &attribute_list) < 0)
1042 goto cleanup;
1043
1044 si.lpAttributeList = attribute_list.attribute_list;
1045
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001046 Py_BEGIN_ALLOW_THREADS
1047 result = CreateProcessW(application_name,
1048 command_line,
1049 NULL,
1050 NULL,
1051 inherit_handles,
Segev Finerb2a60832017-12-18 11:28:19 +02001052 creation_flags | EXTENDED_STARTUPINFO_PRESENT |
1053 CREATE_UNICODE_ENVIRONMENT,
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001054 wenvironment,
1055 current_directory,
Segev Finerb2a60832017-12-18 11:28:19 +02001056 (LPSTARTUPINFOW)&si,
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001057 &pi);
1058 Py_END_ALLOW_THREADS
1059
Segev Finerb2a60832017-12-18 11:28:19 +02001060 if (!result) {
1061 PyErr_SetFromWindowsErr(GetLastError());
1062 goto cleanup;
1063 }
1064
1065 ret = Py_BuildValue("NNkk",
1066 HANDLE_TO_PYNUM(pi.hProcess),
1067 HANDLE_TO_PYNUM(pi.hThread),
1068 pi.dwProcessId,
1069 pi.dwThreadId);
1070
1071cleanup:
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001072 Py_XDECREF(environment);
Segev Finerb2a60832017-12-18 11:28:19 +02001073 freeattributelist(&attribute_list);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001074
Segev Finerb2a60832017-12-18 11:28:19 +02001075 return ret;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001076}
1077
Zachary Waref2244ea2015-05-13 01:22:54 -05001078/*[clinic input]
1079_winapi.DuplicateHandle -> HANDLE
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001080
Zachary Waref2244ea2015-05-13 01:22:54 -05001081 source_process_handle: HANDLE
1082 source_handle: HANDLE
1083 target_process_handle: HANDLE
1084 desired_access: DWORD
1085 inherit_handle: BOOL
1086 options: DWORD = 0
1087 /
1088
1089Return a duplicate handle object.
1090
1091The duplicate handle refers to the same object as the original
1092handle. Therefore, any changes to the object are reflected
1093through both handles.
1094[clinic start generated code]*/
1095
1096static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001097_winapi_DuplicateHandle_impl(PyObject *module, HANDLE source_process_handle,
Zachary Ware77772c02015-05-13 10:58:35 -05001098 HANDLE source_handle,
1099 HANDLE target_process_handle,
1100 DWORD desired_access, BOOL inherit_handle,
1101 DWORD options)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001102/*[clinic end generated code: output=ad9711397b5dcd4e input=b933e3f2356a8c12]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001103{
1104 HANDLE target_handle;
1105 BOOL result;
1106
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001107 Py_BEGIN_ALLOW_THREADS
1108 result = DuplicateHandle(
1109 source_process_handle,
1110 source_handle,
1111 target_process_handle,
1112 &target_handle,
1113 desired_access,
1114 inherit_handle,
1115 options
1116 );
1117 Py_END_ALLOW_THREADS
1118
Zachary Waref2244ea2015-05-13 01:22:54 -05001119 if (! result) {
1120 PyErr_SetFromWindowsErr(GetLastError());
1121 return INVALID_HANDLE_VALUE;
1122 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001123
Zachary Waref2244ea2015-05-13 01:22:54 -05001124 return target_handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001125}
1126
Zachary Waref2244ea2015-05-13 01:22:54 -05001127/*[clinic input]
1128_winapi.ExitProcess
1129
1130 ExitCode: UINT
1131 /
1132
1133[clinic start generated code]*/
1134
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001135static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001136_winapi_ExitProcess_impl(PyObject *module, UINT ExitCode)
1137/*[clinic end generated code: output=a387deb651175301 input=4f05466a9406c558]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001138{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001139 #if defined(Py_DEBUG)
1140 SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|
1141 SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
1142 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
1143 #endif
1144
Zachary Waref2244ea2015-05-13 01:22:54 -05001145 ExitProcess(ExitCode);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001146
1147 return NULL;
1148}
1149
Zachary Waref2244ea2015-05-13 01:22:54 -05001150/*[clinic input]
1151_winapi.GetCurrentProcess -> HANDLE
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001152
Zachary Waref2244ea2015-05-13 01:22:54 -05001153Return a handle object for the current process.
1154[clinic start generated code]*/
1155
1156static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001157_winapi_GetCurrentProcess_impl(PyObject *module)
1158/*[clinic end generated code: output=ddeb4dd2ffadf344 input=b213403fd4b96b41]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001159{
Zachary Waref2244ea2015-05-13 01:22:54 -05001160 return GetCurrentProcess();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001161}
1162
Zachary Waref2244ea2015-05-13 01:22:54 -05001163/*[clinic input]
1164_winapi.GetExitCodeProcess -> DWORD
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001165
Zachary Waref2244ea2015-05-13 01:22:54 -05001166 process: HANDLE
1167 /
1168
1169Return the termination status of the specified process.
1170[clinic start generated code]*/
1171
1172static DWORD
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001173_winapi_GetExitCodeProcess_impl(PyObject *module, HANDLE process)
1174/*[clinic end generated code: output=b4620bdf2bccf36b input=61b6bfc7dc2ee374]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001175{
1176 DWORD exit_code;
1177 BOOL result;
1178
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001179 result = GetExitCodeProcess(process, &exit_code);
1180
Zachary Waref2244ea2015-05-13 01:22:54 -05001181 if (! result) {
1182 PyErr_SetFromWindowsErr(GetLastError());
Victor Stinner850a18e2017-10-24 16:53:32 -07001183 exit_code = PY_DWORD_MAX;
Zachary Waref2244ea2015-05-13 01:22:54 -05001184 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001185
Zachary Waref2244ea2015-05-13 01:22:54 -05001186 return exit_code;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001187}
1188
Zachary Waref2244ea2015-05-13 01:22:54 -05001189/*[clinic input]
1190_winapi.GetLastError -> DWORD
1191[clinic start generated code]*/
1192
1193static DWORD
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001194_winapi_GetLastError_impl(PyObject *module)
1195/*[clinic end generated code: output=8585b827cb1a92c5 input=62d47fb9bce038ba]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001196{
Zachary Waref2244ea2015-05-13 01:22:54 -05001197 return GetLastError();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001198}
1199
Zachary Waref2244ea2015-05-13 01:22:54 -05001200/*[clinic input]
1201_winapi.GetModuleFileName
1202
1203 module_handle: HMODULE
1204 /
1205
1206Return the fully-qualified path for the file that contains module.
1207
1208The module must have been loaded by the current process.
1209
1210The module parameter should be a handle to the loaded module
1211whose path is being requested. If this parameter is 0,
1212GetModuleFileName retrieves the path of the executable file
1213of the current process.
1214[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001215
1216static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001217_winapi_GetModuleFileName_impl(PyObject *module, HMODULE module_handle)
1218/*[clinic end generated code: output=85b4b728c5160306 input=6d66ff7deca5d11f]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001219{
1220 BOOL result;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001221 WCHAR filename[MAX_PATH];
1222
Zachary Waref2244ea2015-05-13 01:22:54 -05001223 result = GetModuleFileNameW(module_handle, filename, MAX_PATH);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001224 filename[MAX_PATH-1] = '\0';
1225
1226 if (! result)
1227 return PyErr_SetFromWindowsErr(GetLastError());
1228
1229 return PyUnicode_FromWideChar(filename, wcslen(filename));
1230}
1231
Zachary Waref2244ea2015-05-13 01:22:54 -05001232/*[clinic input]
1233_winapi.GetStdHandle -> HANDLE
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001234
Zachary Waref2244ea2015-05-13 01:22:54 -05001235 std_handle: DWORD
1236 One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE.
1237 /
1238
1239Return a handle to the specified standard device.
1240
1241The integer associated with the handle object is returned.
1242[clinic start generated code]*/
1243
1244static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001245_winapi_GetStdHandle_impl(PyObject *module, DWORD std_handle)
1246/*[clinic end generated code: output=0e613001e73ab614 input=07016b06a2fc8826]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001247{
1248 HANDLE handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001249
1250 Py_BEGIN_ALLOW_THREADS
1251 handle = GetStdHandle(std_handle);
1252 Py_END_ALLOW_THREADS
1253
1254 if (handle == INVALID_HANDLE_VALUE)
Zachary Waref2244ea2015-05-13 01:22:54 -05001255 PyErr_SetFromWindowsErr(GetLastError());
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001256
Zachary Waref2244ea2015-05-13 01:22:54 -05001257 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001258}
1259
Zachary Waref2244ea2015-05-13 01:22:54 -05001260/*[clinic input]
1261_winapi.GetVersion -> long
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001262
Zachary Waref2244ea2015-05-13 01:22:54 -05001263Return the version number of the current operating system.
1264[clinic start generated code]*/
1265
1266static long
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001267_winapi_GetVersion_impl(PyObject *module)
1268/*[clinic end generated code: output=e41f0db5a3b82682 input=e21dff8d0baeded2]*/
Steve Dower3e96f322015-03-02 08:01:10 -08001269/* Disable deprecation warnings about GetVersionEx as the result is
1270 being passed straight through to the caller, who is responsible for
1271 using it correctly. */
1272#pragma warning(push)
1273#pragma warning(disable:4996)
1274
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001275{
Zachary Waref2244ea2015-05-13 01:22:54 -05001276 return GetVersion();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001277}
1278
Steve Dower3e96f322015-03-02 08:01:10 -08001279#pragma warning(pop)
1280
Zachary Waref2244ea2015-05-13 01:22:54 -05001281/*[clinic input]
1282_winapi.OpenProcess -> HANDLE
1283
1284 desired_access: DWORD
1285 inherit_handle: BOOL
1286 process_id: DWORD
1287 /
1288[clinic start generated code]*/
1289
1290static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001291_winapi_OpenProcess_impl(PyObject *module, DWORD desired_access,
Zachary Ware77772c02015-05-13 10:58:35 -05001292 BOOL inherit_handle, DWORD process_id)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001293/*[clinic end generated code: output=b42b6b81ea5a0fc3 input=ec98c4cf4ea2ec36]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001294{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001295 HANDLE handle;
1296
Zachary Waref2244ea2015-05-13 01:22:54 -05001297 handle = OpenProcess(desired_access, inherit_handle, process_id);
1298 if (handle == NULL) {
1299 PyErr_SetFromWindowsErr(0);
1300 handle = INVALID_HANDLE_VALUE;
1301 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001302
Zachary Waref2244ea2015-05-13 01:22:54 -05001303 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001304}
1305
Zachary Waref2244ea2015-05-13 01:22:54 -05001306/*[clinic input]
1307_winapi.PeekNamedPipe
1308
1309 handle: HANDLE
1310 size: int = 0
1311 /
1312[clinic start generated code]*/
1313
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001314static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001315_winapi_PeekNamedPipe_impl(PyObject *module, HANDLE handle, int size)
1316/*[clinic end generated code: output=d0c3e29e49d323dd input=c7aa53bfbce69d70]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001317{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001318 PyObject *buf = NULL;
1319 DWORD nread, navail, nleft;
1320 BOOL ret;
1321
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001322 if (size < 0) {
1323 PyErr_SetString(PyExc_ValueError, "negative size");
1324 return NULL;
1325 }
1326
1327 if (size) {
1328 buf = PyBytes_FromStringAndSize(NULL, size);
1329 if (!buf)
1330 return NULL;
1331 Py_BEGIN_ALLOW_THREADS
1332 ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread,
1333 &navail, &nleft);
1334 Py_END_ALLOW_THREADS
1335 if (!ret) {
1336 Py_DECREF(buf);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001337 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001338 }
1339 if (_PyBytes_Resize(&buf, nread))
1340 return NULL;
Alexander Buchkovsky266f4902018-09-04 19:10:28 +03001341 return Py_BuildValue("NII", buf, navail, nleft);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001342 }
1343 else {
1344 Py_BEGIN_ALLOW_THREADS
1345 ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft);
1346 Py_END_ALLOW_THREADS
1347 if (!ret) {
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001348 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001349 }
Alexander Buchkovsky266f4902018-09-04 19:10:28 +03001350 return Py_BuildValue("II", navail, nleft);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001351 }
1352}
1353
Zachary Waref2244ea2015-05-13 01:22:54 -05001354/*[clinic input]
1355_winapi.ReadFile
1356
1357 handle: HANDLE
Alexander Buchkovsky266f4902018-09-04 19:10:28 +03001358 size: DWORD
Serhiy Storchaka202fda52017-03-12 10:10:47 +02001359 overlapped as use_overlapped: bool(accept={int}) = False
Zachary Waref2244ea2015-05-13 01:22:54 -05001360[clinic start generated code]*/
1361
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001362static PyObject *
Alexander Buchkovsky266f4902018-09-04 19:10:28 +03001363_winapi_ReadFile_impl(PyObject *module, HANDLE handle, DWORD size,
Zachary Ware77772c02015-05-13 10:58:35 -05001364 int use_overlapped)
Alexander Buchkovsky266f4902018-09-04 19:10:28 +03001365/*[clinic end generated code: output=d3d5b44a8201b944 input=08c439d03a11aac5]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001366{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001367 DWORD nread;
1368 PyObject *buf;
1369 BOOL ret;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001370 DWORD err;
1371 OverlappedObject *overlapped = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001372
1373 buf = PyBytes_FromStringAndSize(NULL, size);
1374 if (!buf)
1375 return NULL;
1376 if (use_overlapped) {
1377 overlapped = new_overlapped(handle);
1378 if (!overlapped) {
1379 Py_DECREF(buf);
1380 return NULL;
1381 }
1382 /* Steals reference to buf */
1383 overlapped->read_buffer = buf;
1384 }
1385
1386 Py_BEGIN_ALLOW_THREADS
1387 ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread,
1388 overlapped ? &overlapped->overlapped : NULL);
1389 Py_END_ALLOW_THREADS
1390
1391 err = ret ? 0 : GetLastError();
1392
1393 if (overlapped) {
1394 if (!ret) {
1395 if (err == ERROR_IO_PENDING)
1396 overlapped->pending = 1;
1397 else if (err != ERROR_MORE_DATA) {
1398 Py_DECREF(overlapped);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001399 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001400 }
1401 }
1402 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1403 }
1404
1405 if (!ret && err != ERROR_MORE_DATA) {
1406 Py_DECREF(buf);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001407 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001408 }
1409 if (_PyBytes_Resize(&buf, nread))
1410 return NULL;
1411 return Py_BuildValue("NI", buf, err);
1412}
1413
Zachary Waref2244ea2015-05-13 01:22:54 -05001414/*[clinic input]
1415_winapi.SetNamedPipeHandleState
1416
1417 named_pipe: HANDLE
1418 mode: object
1419 max_collection_count: object
1420 collect_data_timeout: object
1421 /
1422[clinic start generated code]*/
1423
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001424static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001425_winapi_SetNamedPipeHandleState_impl(PyObject *module, HANDLE named_pipe,
Zachary Ware77772c02015-05-13 10:58:35 -05001426 PyObject *mode,
1427 PyObject *max_collection_count,
1428 PyObject *collect_data_timeout)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001429/*[clinic end generated code: output=f2129d222cbfa095 input=9142d72163d0faa6]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001430{
Zachary Waref2244ea2015-05-13 01:22:54 -05001431 PyObject *oArgs[3] = {mode, max_collection_count, collect_data_timeout};
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001432 DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL};
1433 int i;
1434
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001435 for (i = 0 ; i < 3 ; i++) {
1436 if (oArgs[i] != Py_None) {
1437 dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]);
1438 if (PyErr_Occurred())
1439 return NULL;
1440 pArgs[i] = &dwArgs[i];
1441 }
1442 }
1443
Zachary Waref2244ea2015-05-13 01:22:54 -05001444 if (!SetNamedPipeHandleState(named_pipe, pArgs[0], pArgs[1], pArgs[2]))
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001445 return PyErr_SetFromWindowsErr(0);
1446
1447 Py_RETURN_NONE;
1448}
1449
Zachary Waref2244ea2015-05-13 01:22:54 -05001450
1451/*[clinic input]
1452_winapi.TerminateProcess
1453
1454 handle: HANDLE
1455 exit_code: UINT
1456 /
1457
1458Terminate the specified process and all of its threads.
1459[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001460
1461static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001462_winapi_TerminateProcess_impl(PyObject *module, HANDLE handle,
Zachary Ware77772c02015-05-13 10:58:35 -05001463 UINT exit_code)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001464/*[clinic end generated code: output=f4e99ac3f0b1f34a input=d6bc0aa1ee3bb4df]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001465{
1466 BOOL result;
1467
Zachary Waref2244ea2015-05-13 01:22:54 -05001468 result = TerminateProcess(handle, exit_code);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001469
1470 if (! result)
1471 return PyErr_SetFromWindowsErr(GetLastError());
1472
Zachary Waref2244ea2015-05-13 01:22:54 -05001473 Py_RETURN_NONE;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001474}
1475
Zachary Waref2244ea2015-05-13 01:22:54 -05001476/*[clinic input]
1477_winapi.WaitNamedPipe
1478
1479 name: LPCTSTR
1480 timeout: DWORD
1481 /
1482[clinic start generated code]*/
1483
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001484static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001485_winapi_WaitNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD timeout)
1486/*[clinic end generated code: output=c2866f4439b1fe38 input=36fc781291b1862c]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001487{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001488 BOOL success;
1489
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001490 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -05001491 success = WaitNamedPipe(name, timeout);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001492 Py_END_ALLOW_THREADS
1493
1494 if (!success)
1495 return PyErr_SetFromWindowsErr(0);
1496
1497 Py_RETURN_NONE;
1498}
1499
Zachary Waref2244ea2015-05-13 01:22:54 -05001500/*[clinic input]
1501_winapi.WaitForMultipleObjects
1502
1503 handle_seq: object
1504 wait_flag: BOOL
1505 milliseconds: DWORD(c_default='INFINITE') = _winapi.INFINITE
1506 /
1507[clinic start generated code]*/
1508
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001509static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001510_winapi_WaitForMultipleObjects_impl(PyObject *module, PyObject *handle_seq,
1511 BOOL wait_flag, DWORD milliseconds)
1512/*[clinic end generated code: output=295e3f00b8e45899 input=36f76ca057cd28a0]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001513{
1514 DWORD result;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001515 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
1516 HANDLE sigint_event = NULL;
1517 Py_ssize_t nhandles, i;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001518
1519 if (!PySequence_Check(handle_seq)) {
1520 PyErr_Format(PyExc_TypeError,
1521 "sequence type expected, got '%s'",
Richard Oudkerk67339272012-08-21 14:54:22 +01001522 Py_TYPE(handle_seq)->tp_name);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001523 return NULL;
1524 }
1525 nhandles = PySequence_Length(handle_seq);
1526 if (nhandles == -1)
1527 return NULL;
1528 if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS - 1) {
1529 PyErr_Format(PyExc_ValueError,
1530 "need at most %zd handles, got a sequence of length %zd",
1531 MAXIMUM_WAIT_OBJECTS - 1, nhandles);
1532 return NULL;
1533 }
1534 for (i = 0; i < nhandles; i++) {
1535 HANDLE h;
1536 PyObject *v = PySequence_GetItem(handle_seq, i);
1537 if (v == NULL)
1538 return NULL;
1539 if (!PyArg_Parse(v, F_HANDLE, &h)) {
1540 Py_DECREF(v);
1541 return NULL;
1542 }
1543 handles[i] = h;
1544 Py_DECREF(v);
1545 }
1546 /* If this is the main thread then make the wait interruptible
1547 by Ctrl-C unless we are waiting for *all* handles */
1548 if (!wait_flag && _PyOS_IsMainThread()) {
1549 sigint_event = _PyOS_SigintEvent();
1550 assert(sigint_event != NULL);
1551 handles[nhandles++] = sigint_event;
1552 }
1553
1554 Py_BEGIN_ALLOW_THREADS
1555 if (sigint_event != NULL)
1556 ResetEvent(sigint_event);
1557 result = WaitForMultipleObjects((DWORD) nhandles, handles,
1558 wait_flag, milliseconds);
1559 Py_END_ALLOW_THREADS
1560
1561 if (result == WAIT_FAILED)
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001562 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001563 else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) {
1564 errno = EINTR;
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001565 return PyErr_SetFromErrno(PyExc_OSError);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001566 }
1567
1568 return PyLong_FromLong((int) result);
1569}
1570
Zachary Waref2244ea2015-05-13 01:22:54 -05001571/*[clinic input]
1572_winapi.WaitForSingleObject -> long
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001573
Zachary Waref2244ea2015-05-13 01:22:54 -05001574 handle: HANDLE
1575 milliseconds: DWORD
1576 /
1577
1578Wait for a single object.
1579
1580Wait until the specified object is in the signaled state or
1581the time-out interval elapses. The timeout value is specified
1582in milliseconds.
1583[clinic start generated code]*/
1584
1585static long
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001586_winapi_WaitForSingleObject_impl(PyObject *module, HANDLE handle,
Zachary Ware77772c02015-05-13 10:58:35 -05001587 DWORD milliseconds)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001588/*[clinic end generated code: output=3c4715d8f1b39859 input=443d1ab076edc7b1]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001589{
1590 DWORD result;
1591
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001592 Py_BEGIN_ALLOW_THREADS
1593 result = WaitForSingleObject(handle, milliseconds);
1594 Py_END_ALLOW_THREADS
1595
Zachary Waref2244ea2015-05-13 01:22:54 -05001596 if (result == WAIT_FAILED) {
1597 PyErr_SetFromWindowsErr(GetLastError());
1598 return -1;
1599 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001600
Zachary Waref2244ea2015-05-13 01:22:54 -05001601 return result;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001602}
1603
Zachary Waref2244ea2015-05-13 01:22:54 -05001604/*[clinic input]
1605_winapi.WriteFile
1606
1607 handle: HANDLE
1608 buffer: object
Serhiy Storchaka202fda52017-03-12 10:10:47 +02001609 overlapped as use_overlapped: bool(accept={int}) = False
Zachary Waref2244ea2015-05-13 01:22:54 -05001610[clinic start generated code]*/
1611
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001612static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001613_winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
Zachary Ware77772c02015-05-13 10:58:35 -05001614 int use_overlapped)
Serhiy Storchaka202fda52017-03-12 10:10:47 +02001615/*[clinic end generated code: output=2ca80f6bf3fa92e3 input=11eae2a03aa32731]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001616{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001617 Py_buffer _buf, *buf;
Victor Stinner71765772013-06-24 23:13:24 +02001618 DWORD len, written;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001619 BOOL ret;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001620 DWORD err;
1621 OverlappedObject *overlapped = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001622
1623 if (use_overlapped) {
1624 overlapped = new_overlapped(handle);
1625 if (!overlapped)
1626 return NULL;
1627 buf = &overlapped->write_buffer;
1628 }
1629 else
1630 buf = &_buf;
1631
Zachary Waref2244ea2015-05-13 01:22:54 -05001632 if (!PyArg_Parse(buffer, "y*", buf)) {
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001633 Py_XDECREF(overlapped);
1634 return NULL;
1635 }
1636
1637 Py_BEGIN_ALLOW_THREADS
Victor Stinner850a18e2017-10-24 16:53:32 -07001638 len = (DWORD)Py_MIN(buf->len, PY_DWORD_MAX);
Victor Stinner71765772013-06-24 23:13:24 +02001639 ret = WriteFile(handle, buf->buf, len, &written,
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001640 overlapped ? &overlapped->overlapped : NULL);
1641 Py_END_ALLOW_THREADS
1642
1643 err = ret ? 0 : GetLastError();
1644
1645 if (overlapped) {
1646 if (!ret) {
1647 if (err == ERROR_IO_PENDING)
1648 overlapped->pending = 1;
1649 else {
1650 Py_DECREF(overlapped);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001651 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001652 }
1653 }
1654 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1655 }
1656
1657 PyBuffer_Release(buf);
1658 if (!ret)
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001659 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001660 return Py_BuildValue("II", written, err);
1661}
1662
Victor Stinner91106cd2017-12-13 12:29:09 +01001663/*[clinic input]
1664_winapi.GetACP
1665
1666Get the current Windows ANSI code page identifier.
1667[clinic start generated code]*/
1668
1669static PyObject *
1670_winapi_GetACP_impl(PyObject *module)
1671/*[clinic end generated code: output=f7ee24bf705dbb88 input=1433c96d03a05229]*/
1672{
1673 return PyLong_FromUnsignedLong(GetACP());
1674}
1675
Segev Finerb2a60832017-12-18 11:28:19 +02001676/*[clinic input]
1677_winapi.GetFileType -> DWORD
1678
1679 handle: HANDLE
1680[clinic start generated code]*/
1681
1682static DWORD
1683_winapi_GetFileType_impl(PyObject *module, HANDLE handle)
1684/*[clinic end generated code: output=92b8466ac76ecc17 input=0058366bc40bbfbf]*/
1685{
1686 DWORD result;
1687
1688 Py_BEGIN_ALLOW_THREADS
1689 result = GetFileType(handle);
1690 Py_END_ALLOW_THREADS
1691
1692 if (result == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR) {
1693 PyErr_SetFromWindowsErr(0);
1694 return -1;
1695 }
1696
1697 return result;
1698}
1699
Victor Stinner91106cd2017-12-13 12:29:09 +01001700
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001701static PyMethodDef winapi_functions[] = {
Zachary Waref2244ea2015-05-13 01:22:54 -05001702 _WINAPI_CLOSEHANDLE_METHODDEF
1703 _WINAPI_CONNECTNAMEDPIPE_METHODDEF
1704 _WINAPI_CREATEFILE_METHODDEF
1705 _WINAPI_CREATENAMEDPIPE_METHODDEF
1706 _WINAPI_CREATEPIPE_METHODDEF
1707 _WINAPI_CREATEPROCESS_METHODDEF
1708 _WINAPI_CREATEJUNCTION_METHODDEF
1709 _WINAPI_DUPLICATEHANDLE_METHODDEF
1710 _WINAPI_EXITPROCESS_METHODDEF
1711 _WINAPI_GETCURRENTPROCESS_METHODDEF
1712 _WINAPI_GETEXITCODEPROCESS_METHODDEF
1713 _WINAPI_GETLASTERROR_METHODDEF
1714 _WINAPI_GETMODULEFILENAME_METHODDEF
1715 _WINAPI_GETSTDHANDLE_METHODDEF
1716 _WINAPI_GETVERSION_METHODDEF
1717 _WINAPI_OPENPROCESS_METHODDEF
1718 _WINAPI_PEEKNAMEDPIPE_METHODDEF
1719 _WINAPI_READFILE_METHODDEF
1720 _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF
1721 _WINAPI_TERMINATEPROCESS_METHODDEF
1722 _WINAPI_WAITNAMEDPIPE_METHODDEF
1723 _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF
1724 _WINAPI_WAITFORSINGLEOBJECT_METHODDEF
1725 _WINAPI_WRITEFILE_METHODDEF
Victor Stinner91106cd2017-12-13 12:29:09 +01001726 _WINAPI_GETACP_METHODDEF
Segev Finerb2a60832017-12-18 11:28:19 +02001727 _WINAPI_GETFILETYPE_METHODDEF
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001728 {NULL, NULL}
1729};
1730
1731static struct PyModuleDef winapi_module = {
1732 PyModuleDef_HEAD_INIT,
1733 "_winapi",
1734 NULL,
1735 -1,
1736 winapi_functions,
1737 NULL,
1738 NULL,
1739 NULL,
1740 NULL
1741};
1742
1743#define WINAPI_CONSTANT(fmt, con) \
1744 PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1745
1746PyMODINIT_FUNC
1747PyInit__winapi(void)
1748{
1749 PyObject *d;
1750 PyObject *m;
1751
1752 if (PyType_Ready(&OverlappedType) < 0)
1753 return NULL;
1754
1755 m = PyModule_Create(&winapi_module);
1756 if (m == NULL)
1757 return NULL;
1758 d = PyModule_GetDict(m);
1759
1760 PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType);
1761
1762 /* constants */
1763 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
1764 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP);
1765 WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001766 WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001767 WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
1768 WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
1769 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1770 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1771 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1772 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001773 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1774 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
Richard Oudkerkfdb8dcf2012-05-05 19:45:37 +01001775 WINAPI_CONSTANT(F_DWORD, ERROR_NO_DATA);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001776 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
1777 WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
1778 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
1779 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
1780 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
1781 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE);
1782 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001783 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ);
1784 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001785 WINAPI_CONSTANT(F_DWORD, GENERIC_READ);
1786 WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE);
1787 WINAPI_CONSTANT(F_DWORD, INFINITE);
1788 WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
1789 WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING);
1790 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
1791 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
1792 WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
1793 WINAPI_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE);
1794 WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES);
1795 WINAPI_CONSTANT(F_DWORD, PIPE_WAIT);
1796 WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001797 WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001798 WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW);
1799 WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES);
1800 WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE);
1801 WINAPI_CONSTANT(F_DWORD, STD_OUTPUT_HANDLE);
1802 WINAPI_CONSTANT(F_DWORD, STD_ERROR_HANDLE);
1803 WINAPI_CONSTANT(F_DWORD, STILL_ACTIVE);
1804 WINAPI_CONSTANT(F_DWORD, SW_HIDE);
1805 WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0);
Victor Stinner373f0a92014-03-20 09:26:55 +01001806 WINAPI_CONSTANT(F_DWORD, WAIT_ABANDONED_0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001807 WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT);
Victor Stinner91106cd2017-12-13 12:29:09 +01001808
Jamesb5d9e082017-11-08 14:18:59 +00001809 WINAPI_CONSTANT(F_DWORD, ABOVE_NORMAL_PRIORITY_CLASS);
1810 WINAPI_CONSTANT(F_DWORD, BELOW_NORMAL_PRIORITY_CLASS);
1811 WINAPI_CONSTANT(F_DWORD, HIGH_PRIORITY_CLASS);
1812 WINAPI_CONSTANT(F_DWORD, IDLE_PRIORITY_CLASS);
1813 WINAPI_CONSTANT(F_DWORD, NORMAL_PRIORITY_CLASS);
1814 WINAPI_CONSTANT(F_DWORD, REALTIME_PRIORITY_CLASS);
Victor Stinner91106cd2017-12-13 12:29:09 +01001815
Jamesb5d9e082017-11-08 14:18:59 +00001816 WINAPI_CONSTANT(F_DWORD, CREATE_NO_WINDOW);
1817 WINAPI_CONSTANT(F_DWORD, DETACHED_PROCESS);
1818 WINAPI_CONSTANT(F_DWORD, CREATE_DEFAULT_ERROR_MODE);
1819 WINAPI_CONSTANT(F_DWORD, CREATE_BREAKAWAY_FROM_JOB);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001820
Segev Finerb2a60832017-12-18 11:28:19 +02001821 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_UNKNOWN);
1822 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_DISK);
1823 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_CHAR);
1824 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_PIPE);
1825 WINAPI_CONSTANT(F_DWORD, FILE_TYPE_REMOTE);
1826
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001827 WINAPI_CONSTANT("i", NULL);
1828
1829 return m;
1830}