blob: 00a26d515e0cd3228b4d4ede1ced804d3495f878 [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
Victor Stinner71765772013-06-24 23:13:24 +020064#define DWORD_MAX 4294967295U
65
Antoine Pitrou23bba4c2012-04-18 20:51:15 +020066/* Grab CancelIoEx dynamically from kernel32 */
67static int has_CancelIoEx = -1;
68static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED);
69
70static int
71check_CancelIoEx()
72{
73 if (has_CancelIoEx == -1)
74 {
75 HINSTANCE hKernel32 = GetModuleHandle("KERNEL32");
76 * (FARPROC *) &Py_CancelIoEx = GetProcAddress(hKernel32,
77 "CancelIoEx");
78 has_CancelIoEx = (Py_CancelIoEx != NULL);
79 }
80 return has_CancelIoEx;
81}
82
83
84/*
85 * A Python object wrapping an OVERLAPPED structure and other useful data
86 * for overlapped I/O
87 */
88
89typedef struct {
90 PyObject_HEAD
91 OVERLAPPED overlapped;
92 /* For convenience, we store the file handle too */
93 HANDLE handle;
94 /* Whether there's I/O in flight */
95 int pending;
96 /* Whether I/O completed successfully */
97 int completed;
98 /* Buffer used for reading (optional) */
99 PyObject *read_buffer;
100 /* Buffer used for writing (optional) */
101 Py_buffer write_buffer;
102} OverlappedObject;
103
104static void
105overlapped_dealloc(OverlappedObject *self)
106{
107 DWORD bytes;
108 int err = GetLastError();
Richard Oudkerk633db6f2013-11-17 13:15:51 +0000109
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200110 if (self->pending) {
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200111 if (check_CancelIoEx() &&
Richard Oudkerk633db6f2013-11-17 13:15:51 +0000112 Py_CancelIoEx(self->handle, &self->overlapped) &&
113 GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE))
114 {
115 /* The operation is no longer pending -- nothing to do. */
116 }
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600117 else if (_Py_IsFinalizing())
Richard Oudkerk633db6f2013-11-17 13:15:51 +0000118 {
119 /* The operation is still pending -- give a warning. This
120 will probably only happen on Windows XP. */
121 PyErr_SetString(PyExc_RuntimeError,
122 "I/O operations still in flight while destroying "
123 "Overlapped object, the process may crash");
124 PyErr_WriteUnraisable(NULL);
125 }
126 else
127 {
128 /* The operation is still pending, but the process is
129 probably about to exit, so we need not worry too much
130 about memory leaks. Leaking self prevents a potential
131 crash. This can happen when a daemon thread is cleaned
132 up at exit -- see #19565. We only expect to get here
133 on Windows XP. */
134 CloseHandle(self->overlapped.hEvent);
135 SetLastError(err);
136 return;
137 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200138 }
Richard Oudkerk633db6f2013-11-17 13:15:51 +0000139
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200140 CloseHandle(self->overlapped.hEvent);
141 SetLastError(err);
142 if (self->write_buffer.obj)
143 PyBuffer_Release(&self->write_buffer);
144 Py_CLEAR(self->read_buffer);
145 PyObject_Del(self);
146}
147
Zachary Waref2244ea2015-05-13 01:22:54 -0500148/*[clinic input]
149module _winapi
150class _winapi.Overlapped "OverlappedObject *" "&OverlappedType"
151[clinic start generated code]*/
152/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c13d3f5fd1dabb84]*/
153
154/*[python input]
155def create_converter(type_, format_unit):
156 name = type_ + '_converter'
157 # registered upon creation by CConverter's metaclass
158 type(name, (CConverter,), {'type': type_, 'format_unit': format_unit})
159
160# format unit differs between platforms for these
161create_converter('HANDLE', '" F_HANDLE "')
162create_converter('HMODULE', '" F_HANDLE "')
163create_converter('LPSECURITY_ATTRIBUTES', '" F_POINTER "')
164
165create_converter('BOOL', 'i') # F_BOOL used previously (always 'i')
166create_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter)
167create_converter('LPCTSTR', 's')
168create_converter('LPWSTR', 'u')
169create_converter('UINT', 'I') # F_UINT used previously (always 'I')
170
171class HANDLE_return_converter(CReturnConverter):
172 type = 'HANDLE'
173
174 def render(self, function, data):
175 self.declare(data)
176 self.err_occurred_if("_return_value == INVALID_HANDLE_VALUE", data)
177 data.return_conversion.append(
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300178 'if (_return_value == NULL) {\n Py_RETURN_NONE;\n}\n')
Zachary Waref2244ea2015-05-13 01:22:54 -0500179 data.return_conversion.append(
180 'return_value = HANDLE_TO_PYNUM(_return_value);\n')
181
182class DWORD_return_converter(CReturnConverter):
183 type = 'DWORD'
184
185 def render(self, function, data):
186 self.declare(data)
187 self.err_occurred_if("_return_value == DWORD_MAX", data)
188 data.return_conversion.append(
189 'return_value = Py_BuildValue("k", _return_value);\n')
190[python start generated code]*/
Serhiy Storchaka5dee6552016-06-09 16:16:06 +0300191/*[python end generated code: output=da39a3ee5e6b4b0d input=94819e72d2c6d558]*/
Zachary Waref2244ea2015-05-13 01:22:54 -0500192
193#include "clinic/_winapi.c.h"
194
195/*[clinic input]
196_winapi.Overlapped.GetOverlappedResult
197
198 wait: bool
199 /
200[clinic start generated code]*/
201
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200202static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500203_winapi_Overlapped_GetOverlappedResult_impl(OverlappedObject *self, int wait)
204/*[clinic end generated code: output=bdd0c1ed6518cd03 input=194505ee8e0e3565]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200205{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200206 BOOL res;
207 DWORD transferred = 0;
208 DWORD err;
209
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200210 Py_BEGIN_ALLOW_THREADS
211 res = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
212 wait != 0);
213 Py_END_ALLOW_THREADS
214
215 err = res ? ERROR_SUCCESS : GetLastError();
216 switch (err) {
217 case ERROR_SUCCESS:
218 case ERROR_MORE_DATA:
219 case ERROR_OPERATION_ABORTED:
220 self->completed = 1;
221 self->pending = 0;
222 break;
223 case ERROR_IO_INCOMPLETE:
224 break;
225 default:
226 self->pending = 0;
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300227 return PyErr_SetExcFromWindowsErr(PyExc_OSError, err);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200228 }
229 if (self->completed && self->read_buffer != NULL) {
230 assert(PyBytes_CheckExact(self->read_buffer));
231 if (transferred != PyBytes_GET_SIZE(self->read_buffer) &&
232 _PyBytes_Resize(&self->read_buffer, transferred))
233 return NULL;
234 }
235 return Py_BuildValue("II", (unsigned) transferred, (unsigned) err);
236}
237
Zachary Waref2244ea2015-05-13 01:22:54 -0500238/*[clinic input]
239_winapi.Overlapped.getbuffer
240[clinic start generated code]*/
241
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200242static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500243_winapi_Overlapped_getbuffer_impl(OverlappedObject *self)
244/*[clinic end generated code: output=95a3eceefae0f748 input=347fcfd56b4ceabd]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200245{
246 PyObject *res;
247 if (!self->completed) {
248 PyErr_SetString(PyExc_ValueError,
249 "can't get read buffer before GetOverlappedResult() "
250 "signals the operation completed");
251 return NULL;
252 }
253 res = self->read_buffer ? self->read_buffer : Py_None;
254 Py_INCREF(res);
255 return res;
256}
257
Zachary Waref2244ea2015-05-13 01:22:54 -0500258/*[clinic input]
259_winapi.Overlapped.cancel
260[clinic start generated code]*/
261
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200262static PyObject *
Zachary Waref2244ea2015-05-13 01:22:54 -0500263_winapi_Overlapped_cancel_impl(OverlappedObject *self)
264/*[clinic end generated code: output=fcb9ab5df4ebdae5 input=cbf3da142290039f]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200265{
266 BOOL res = TRUE;
267
268 if (self->pending) {
269 Py_BEGIN_ALLOW_THREADS
270 if (check_CancelIoEx())
271 res = Py_CancelIoEx(self->handle, &self->overlapped);
272 else
273 res = CancelIo(self->handle);
274 Py_END_ALLOW_THREADS
275 }
276
277 /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
278 if (!res && GetLastError() != ERROR_NOT_FOUND)
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300279 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200280 self->pending = 0;
281 Py_RETURN_NONE;
282}
283
284static PyMethodDef overlapped_methods[] = {
Zachary Waref2244ea2015-05-13 01:22:54 -0500285 _WINAPI_OVERLAPPED_GETOVERLAPPEDRESULT_METHODDEF
286 _WINAPI_OVERLAPPED_GETBUFFER_METHODDEF
287 _WINAPI_OVERLAPPED_CANCEL_METHODDEF
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200288 {NULL}
289};
290
291static PyMemberDef overlapped_members[] = {
292 {"event", T_HANDLE,
293 offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
294 READONLY, "overlapped event handle"},
295 {NULL}
296};
297
298PyTypeObject OverlappedType = {
299 PyVarObject_HEAD_INIT(NULL, 0)
300 /* tp_name */ "_winapi.Overlapped",
301 /* tp_basicsize */ sizeof(OverlappedObject),
302 /* tp_itemsize */ 0,
303 /* tp_dealloc */ (destructor) overlapped_dealloc,
304 /* tp_print */ 0,
305 /* tp_getattr */ 0,
306 /* tp_setattr */ 0,
307 /* tp_reserved */ 0,
308 /* tp_repr */ 0,
309 /* tp_as_number */ 0,
310 /* tp_as_sequence */ 0,
311 /* tp_as_mapping */ 0,
312 /* tp_hash */ 0,
313 /* tp_call */ 0,
314 /* tp_str */ 0,
315 /* tp_getattro */ 0,
316 /* tp_setattro */ 0,
317 /* tp_as_buffer */ 0,
318 /* tp_flags */ Py_TPFLAGS_DEFAULT,
319 /* tp_doc */ "OVERLAPPED structure wrapper",
320 /* tp_traverse */ 0,
321 /* tp_clear */ 0,
322 /* tp_richcompare */ 0,
323 /* tp_weaklistoffset */ 0,
324 /* tp_iter */ 0,
325 /* tp_iternext */ 0,
326 /* tp_methods */ overlapped_methods,
327 /* tp_members */ overlapped_members,
328 /* tp_getset */ 0,
329 /* tp_base */ 0,
330 /* tp_dict */ 0,
331 /* tp_descr_get */ 0,
332 /* tp_descr_set */ 0,
333 /* tp_dictoffset */ 0,
334 /* tp_init */ 0,
335 /* tp_alloc */ 0,
336 /* tp_new */ 0,
337};
338
339static OverlappedObject *
340new_overlapped(HANDLE handle)
341{
342 OverlappedObject *self;
343
344 self = PyObject_New(OverlappedObject, &OverlappedType);
345 if (!self)
346 return NULL;
347 self->handle = handle;
348 self->read_buffer = NULL;
349 self->pending = 0;
350 self->completed = 0;
351 memset(&self->overlapped, 0, sizeof(OVERLAPPED));
352 memset(&self->write_buffer, 0, sizeof(Py_buffer));
353 /* Manual reset, initially non-signalled */
354 self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
355 return self;
356}
357
358/* -------------------------------------------------------------------- */
359/* windows API functions */
360
Zachary Waref2244ea2015-05-13 01:22:54 -0500361/*[clinic input]
362_winapi.CloseHandle
363
364 handle: HANDLE
365 /
366
367Close handle.
368[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200369
370static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300371_winapi_CloseHandle_impl(PyObject *module, HANDLE handle)
372/*[clinic end generated code: output=7ad37345f07bd782 input=7f0e4ac36e0352b8]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200373{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200374 BOOL success;
375
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200376 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500377 success = CloseHandle(handle);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200378 Py_END_ALLOW_THREADS
379
380 if (!success)
381 return PyErr_SetFromWindowsErr(0);
382
383 Py_RETURN_NONE;
384}
385
Zachary Waref2244ea2015-05-13 01:22:54 -0500386/*[clinic input]
387_winapi.ConnectNamedPipe
388
389 handle: HANDLE
Serhiy Storchaka202fda52017-03-12 10:10:47 +0200390 overlapped as use_overlapped: bool(accept={int}) = False
Zachary Waref2244ea2015-05-13 01:22:54 -0500391[clinic start generated code]*/
392
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200393static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300394_winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle,
Zachary Ware77772c02015-05-13 10:58:35 -0500395 int use_overlapped)
Serhiy Storchaka202fda52017-03-12 10:10:47 +0200396/*[clinic end generated code: output=335a0e7086800671 input=34f937c1c86e5e68]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200397{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200398 BOOL success;
399 OverlappedObject *overlapped = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200400
401 if (use_overlapped) {
Zachary Waref2244ea2015-05-13 01:22:54 -0500402 overlapped = new_overlapped(handle);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200403 if (!overlapped)
404 return NULL;
405 }
406
407 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500408 success = ConnectNamedPipe(handle,
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200409 overlapped ? &overlapped->overlapped : NULL);
410 Py_END_ALLOW_THREADS
411
412 if (overlapped) {
413 int err = GetLastError();
414 /* Overlapped ConnectNamedPipe never returns a success code */
415 assert(success == 0);
416 if (err == ERROR_IO_PENDING)
417 overlapped->pending = 1;
418 else if (err == ERROR_PIPE_CONNECTED)
419 SetEvent(overlapped->overlapped.hEvent);
420 else {
421 Py_DECREF(overlapped);
422 return PyErr_SetFromWindowsErr(err);
423 }
424 return (PyObject *) overlapped;
425 }
426 if (!success)
427 return PyErr_SetFromWindowsErr(0);
428
429 Py_RETURN_NONE;
430}
431
Zachary Waref2244ea2015-05-13 01:22:54 -0500432/*[clinic input]
433_winapi.CreateFile -> HANDLE
434
435 file_name: LPCTSTR
436 desired_access: DWORD
437 share_mode: DWORD
438 security_attributes: LPSECURITY_ATTRIBUTES
439 creation_disposition: DWORD
440 flags_and_attributes: DWORD
441 template_file: HANDLE
442 /
443[clinic start generated code]*/
444
445static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300446_winapi_CreateFile_impl(PyObject *module, LPCTSTR file_name,
Zachary Ware77772c02015-05-13 10:58:35 -0500447 DWORD desired_access, DWORD share_mode,
448 LPSECURITY_ATTRIBUTES security_attributes,
449 DWORD creation_disposition,
450 DWORD flags_and_attributes, HANDLE template_file)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300451/*[clinic end generated code: output=417ddcebfc5a3d53 input=6423c3e40372dbd5]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200452{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200453 HANDLE handle;
454
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200455 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500456 handle = CreateFile(file_name, desired_access,
457 share_mode, security_attributes,
458 creation_disposition,
459 flags_and_attributes, template_file);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200460 Py_END_ALLOW_THREADS
461
462 if (handle == INVALID_HANDLE_VALUE)
Zachary Waref2244ea2015-05-13 01:22:54 -0500463 PyErr_SetFromWindowsErr(0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200464
Zachary Waref2244ea2015-05-13 01:22:54 -0500465 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200466}
467
Zachary Waref2244ea2015-05-13 01:22:54 -0500468/*[clinic input]
469_winapi.CreateJunction
Tim Golden0321cf22014-05-05 19:46:17 +0100470
Zachary Waref2244ea2015-05-13 01:22:54 -0500471 src_path: LPWSTR
472 dst_path: LPWSTR
473 /
474[clinic start generated code]*/
475
476static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300477_winapi_CreateJunction_impl(PyObject *module, LPWSTR src_path,
Zachary Ware77772c02015-05-13 10:58:35 -0500478 LPWSTR dst_path)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300479/*[clinic end generated code: output=66b7eb746e1dfa25 input=8cd1f9964b6e3d36]*/
Zachary Waref2244ea2015-05-13 01:22:54 -0500480{
Tim Golden0321cf22014-05-05 19:46:17 +0100481 /* Privilege adjustment */
482 HANDLE token = NULL;
483 TOKEN_PRIVILEGES tp;
484
485 /* Reparse data buffer */
486 const USHORT prefix_len = 4;
487 USHORT print_len = 0;
488 USHORT rdb_size = 0;
Martin Panter70214ad2016-08-04 02:38:59 +0000489 _Py_PREPARSE_DATA_BUFFER rdb = NULL;
Tim Golden0321cf22014-05-05 19:46:17 +0100490
491 /* Junction point creation */
492 HANDLE junction = NULL;
493 DWORD ret = 0;
494
Tim Golden0321cf22014-05-05 19:46:17 +0100495 if (src_path == NULL || dst_path == NULL)
496 return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
497
498 if (wcsncmp(src_path, L"\\??\\", prefix_len) == 0)
499 return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
500
501 /* Adjust privileges to allow rewriting directory entry as a
502 junction point. */
503 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
504 goto cleanup;
505
506 if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid))
507 goto cleanup;
508
509 tp.PrivilegeCount = 1;
510 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
511 if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
512 NULL, NULL))
513 goto cleanup;
514
515 if (GetFileAttributesW(src_path) == INVALID_FILE_ATTRIBUTES)
516 goto cleanup;
517
518 /* Store the absolute link target path length in print_len. */
519 print_len = (USHORT)GetFullPathNameW(src_path, 0, NULL, NULL);
520 if (print_len == 0)
521 goto cleanup;
522
523 /* NUL terminator should not be part of print_len. */
524 --print_len;
525
526 /* REPARSE_DATA_BUFFER usage is heavily under-documented, especially for
527 junction points. Here's what I've learned along the way:
528 - A junction point has two components: a print name and a substitute
529 name. They both describe the link target, but the substitute name is
530 the physical target and the print name is shown in directory listings.
531 - The print name must be a native name, prefixed with "\??\".
532 - Both names are stored after each other in the same buffer (the
533 PathBuffer) and both must be NUL-terminated.
534 - There are four members defining their respective offset and length
535 inside PathBuffer: SubstituteNameOffset, SubstituteNameLength,
536 PrintNameOffset and PrintNameLength.
537 - The total size we need to allocate for the REPARSE_DATA_BUFFER, thus,
538 is the sum of:
539 - the fixed header size (REPARSE_DATA_BUFFER_HEADER_SIZE)
540 - the size of the MountPointReparseBuffer member without the PathBuffer
541 - the size of the prefix ("\??\") in bytes
542 - the size of the print name in bytes
543 - the size of the substitute name in bytes
544 - the size of two NUL terminators in bytes */
Martin Panter70214ad2016-08-04 02:38:59 +0000545 rdb_size = _Py_REPARSE_DATA_BUFFER_HEADER_SIZE +
Tim Golden0321cf22014-05-05 19:46:17 +0100546 sizeof(rdb->MountPointReparseBuffer) -
547 sizeof(rdb->MountPointReparseBuffer.PathBuffer) +
548 /* Two +1's for NUL terminators. */
549 (prefix_len + print_len + 1 + print_len + 1) * sizeof(WCHAR);
Martin Panter70214ad2016-08-04 02:38:59 +0000550 rdb = (_Py_PREPARSE_DATA_BUFFER)PyMem_RawMalloc(rdb_size);
Tim Golden0321cf22014-05-05 19:46:17 +0100551 if (rdb == NULL)
552 goto cleanup;
553
554 memset(rdb, 0, rdb_size);
555 rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
Martin Panter70214ad2016-08-04 02:38:59 +0000556 rdb->ReparseDataLength = rdb_size - _Py_REPARSE_DATA_BUFFER_HEADER_SIZE;
Tim Golden0321cf22014-05-05 19:46:17 +0100557 rdb->MountPointReparseBuffer.SubstituteNameOffset = 0;
558 rdb->MountPointReparseBuffer.SubstituteNameLength =
559 (prefix_len + print_len) * sizeof(WCHAR);
560 rdb->MountPointReparseBuffer.PrintNameOffset =
561 rdb->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
562 rdb->MountPointReparseBuffer.PrintNameLength = print_len * sizeof(WCHAR);
563
564 /* Store the full native path of link target at the substitute name
565 offset (0). */
566 wcscpy(rdb->MountPointReparseBuffer.PathBuffer, L"\\??\\");
567 if (GetFullPathNameW(src_path, print_len + 1,
568 rdb->MountPointReparseBuffer.PathBuffer + prefix_len,
569 NULL) == 0)
570 goto cleanup;
571
572 /* Copy everything but the native prefix to the print name offset. */
573 wcscpy(rdb->MountPointReparseBuffer.PathBuffer +
574 prefix_len + print_len + 1,
575 rdb->MountPointReparseBuffer.PathBuffer + prefix_len);
576
577 /* Create a directory for the junction point. */
578 if (!CreateDirectoryW(dst_path, NULL))
579 goto cleanup;
580
581 junction = CreateFileW(dst_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
582 OPEN_EXISTING,
583 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
584 if (junction == INVALID_HANDLE_VALUE)
585 goto cleanup;
586
587 /* Make the directory entry a junction point. */
588 if (!DeviceIoControl(junction, FSCTL_SET_REPARSE_POINT, rdb, rdb_size,
589 NULL, 0, &ret, NULL))
590 goto cleanup;
591
592cleanup:
593 ret = GetLastError();
594
595 CloseHandle(token);
596 CloseHandle(junction);
597 PyMem_RawFree(rdb);
598
599 if (ret != 0)
600 return PyErr_SetFromWindowsErr(ret);
601
602 Py_RETURN_NONE;
603}
604
Zachary Waref2244ea2015-05-13 01:22:54 -0500605/*[clinic input]
606_winapi.CreateNamedPipe -> HANDLE
607
608 name: LPCTSTR
609 open_mode: DWORD
610 pipe_mode: DWORD
611 max_instances: DWORD
612 out_buffer_size: DWORD
613 in_buffer_size: DWORD
614 default_timeout: DWORD
615 security_attributes: LPSECURITY_ATTRIBUTES
616 /
617[clinic start generated code]*/
618
619static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300620_winapi_CreateNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD open_mode,
621 DWORD pipe_mode, DWORD max_instances,
622 DWORD out_buffer_size, DWORD in_buffer_size,
623 DWORD default_timeout,
Zachary Ware77772c02015-05-13 10:58:35 -0500624 LPSECURITY_ATTRIBUTES security_attributes)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300625/*[clinic end generated code: output=80f8c07346a94fbc input=5a73530b84d8bc37]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200626{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200627 HANDLE handle;
628
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200629 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -0500630 handle = CreateNamedPipe(name, open_mode, pipe_mode,
631 max_instances, out_buffer_size,
632 in_buffer_size, default_timeout,
633 security_attributes);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200634 Py_END_ALLOW_THREADS
635
636 if (handle == INVALID_HANDLE_VALUE)
Zachary Waref2244ea2015-05-13 01:22:54 -0500637 PyErr_SetFromWindowsErr(0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200638
Zachary Waref2244ea2015-05-13 01:22:54 -0500639 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200640}
641
Zachary Waref2244ea2015-05-13 01:22:54 -0500642/*[clinic input]
643_winapi.CreatePipe
644
645 pipe_attrs: object
646 Ignored internally, can be None.
647 size: DWORD
648 /
649
650Create an anonymous pipe.
651
652Returns a 2-tuple of handles, to the read and write ends of the pipe.
653[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200654
655static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300656_winapi_CreatePipe_impl(PyObject *module, PyObject *pipe_attrs, DWORD size)
657/*[clinic end generated code: output=1c4411d8699f0925 input=c4f2cfa56ef68d90]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200658{
659 HANDLE read_pipe;
660 HANDLE write_pipe;
661 BOOL result;
662
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200663 Py_BEGIN_ALLOW_THREADS
664 result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
665 Py_END_ALLOW_THREADS
666
667 if (! result)
668 return PyErr_SetFromWindowsErr(GetLastError());
669
670 return Py_BuildValue(
671 "NN", HANDLE_TO_PYNUM(read_pipe), HANDLE_TO_PYNUM(write_pipe));
672}
673
674/* helpers for createprocess */
675
676static unsigned long
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200677getulong(PyObject* obj, const char* name)
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200678{
679 PyObject* value;
680 unsigned long ret;
681
682 value = PyObject_GetAttrString(obj, name);
683 if (! value) {
684 PyErr_Clear(); /* FIXME: propagate error? */
685 return 0;
686 }
687 ret = PyLong_AsUnsignedLong(value);
688 Py_DECREF(value);
689 return ret;
690}
691
692static HANDLE
Serhiy Storchakaef1585e2015-12-25 20:01:53 +0200693gethandle(PyObject* obj, const char* name)
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200694{
695 PyObject* value;
696 HANDLE ret;
697
698 value = PyObject_GetAttrString(obj, name);
699 if (! value) {
700 PyErr_Clear(); /* FIXME: propagate error? */
701 return NULL;
702 }
703 if (value == Py_None)
704 ret = NULL;
705 else
706 ret = PYNUM_TO_HANDLE(value);
707 Py_DECREF(value);
708 return ret;
709}
710
711static PyObject*
712getenvironment(PyObject* environment)
713{
714 Py_ssize_t i, envsize, totalsize;
715 Py_UCS4 *buffer = NULL, *p, *end;
716 PyObject *keys, *values, *res;
717
Ezio Melotti85a86292013-08-17 16:57:41 +0300718 /* convert environment dictionary to windows environment string */
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200719 if (! PyMapping_Check(environment)) {
720 PyErr_SetString(
721 PyExc_TypeError, "environment must be dictionary or None");
722 return NULL;
723 }
724
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200725 keys = PyMapping_Keys(environment);
Oren Milman0b3a87e2017-09-14 22:30:28 +0300726 if (!keys) {
727 return NULL;
728 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200729 values = PyMapping_Values(environment);
Oren Milman0b3a87e2017-09-14 22:30:28 +0300730 if (!values) {
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200731 goto error;
Oren Milman0b3a87e2017-09-14 22:30:28 +0300732 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200733
Serhiy Storchakabf623ae2017-04-19 20:03:52 +0300734 envsize = PySequence_Fast_GET_SIZE(keys);
735 if (PySequence_Fast_GET_SIZE(values) != envsize) {
736 PyErr_SetString(PyExc_RuntimeError,
737 "environment changed size during iteration");
738 goto error;
739 }
740
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200741 totalsize = 1; /* trailing null character */
742 for (i = 0; i < envsize; i++) {
Serhiy Storchakabf623ae2017-04-19 20:03:52 +0300743 PyObject* key = PySequence_Fast_GET_ITEM(keys, i);
744 PyObject* value = PySequence_Fast_GET_ITEM(values, i);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200745
746 if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
747 PyErr_SetString(PyExc_TypeError,
748 "environment can only contain strings");
749 goto error;
750 }
Serhiy Storchakad174d242017-06-23 19:39:27 +0300751 if (PyUnicode_FindChar(key, '\0', 0, PyUnicode_GET_LENGTH(key), 1) != -1 ||
752 PyUnicode_FindChar(value, '\0', 0, PyUnicode_GET_LENGTH(value), 1) != -1)
753 {
754 PyErr_SetString(PyExc_ValueError, "embedded null character");
755 goto error;
756 }
757 /* Search from index 1 because on Windows starting '=' is allowed for
758 defining hidden environment variables. */
759 if (PyUnicode_GET_LENGTH(key) == 0 ||
760 PyUnicode_FindChar(key, '=', 1, PyUnicode_GET_LENGTH(key), 1) != -1)
761 {
762 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
763 goto error;
764 }
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500765 if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(key) - 1) {
766 PyErr_SetString(PyExc_OverflowError, "environment too long");
767 goto error;
768 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200769 totalsize += PyUnicode_GET_LENGTH(key) + 1; /* +1 for '=' */
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500770 if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(value) - 1) {
771 PyErr_SetString(PyExc_OverflowError, "environment too long");
772 goto error;
773 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200774 totalsize += PyUnicode_GET_LENGTH(value) + 1; /* +1 for '\0' */
775 }
776
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500777 buffer = PyMem_NEW(Py_UCS4, totalsize);
778 if (! buffer) {
779 PyErr_NoMemory();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200780 goto error;
Benjamin Peterson8ce68062015-02-09 20:58:12 -0500781 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200782 p = buffer;
783 end = buffer + totalsize;
784
785 for (i = 0; i < envsize; i++) {
Serhiy Storchakabf623ae2017-04-19 20:03:52 +0300786 PyObject* key = PySequence_Fast_GET_ITEM(keys, i);
787 PyObject* value = PySequence_Fast_GET_ITEM(values, i);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200788 if (!PyUnicode_AsUCS4(key, p, end - p, 0))
789 goto error;
790 p += PyUnicode_GET_LENGTH(key);
791 *p++ = '=';
792 if (!PyUnicode_AsUCS4(value, p, end - p, 0))
793 goto error;
794 p += PyUnicode_GET_LENGTH(value);
795 *p++ = '\0';
796 }
797
798 /* add trailing null byte */
799 *p++ = '\0';
800 assert(p == end);
801
802 Py_XDECREF(keys);
803 Py_XDECREF(values);
804
805 res = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buffer, p - buffer);
806 PyMem_Free(buffer);
807 return res;
808
809 error:
810 PyMem_Free(buffer);
811 Py_XDECREF(keys);
812 Py_XDECREF(values);
813 return NULL;
814}
815
Zachary Waref2244ea2015-05-13 01:22:54 -0500816/*[clinic input]
817_winapi.CreateProcess
818
Zachary Ware77772c02015-05-13 10:58:35 -0500819 application_name: Py_UNICODE(accept={str, NoneType})
820 command_line: Py_UNICODE(accept={str, NoneType})
Zachary Waref2244ea2015-05-13 01:22:54 -0500821 proc_attrs: object
822 Ignored internally, can be None.
823 thread_attrs: object
824 Ignored internally, can be None.
825 inherit_handles: BOOL
826 creation_flags: DWORD
827 env_mapping: object
Zachary Ware77772c02015-05-13 10:58:35 -0500828 current_directory: Py_UNICODE(accept={str, NoneType})
Zachary Waref2244ea2015-05-13 01:22:54 -0500829 startup_info: object
830 /
831
832Create a new process and its primary thread.
833
834The return value is a tuple of the process handle, thread handle,
835process ID, and thread ID.
836[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200837
838static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300839_winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name,
Zachary Ware77772c02015-05-13 10:58:35 -0500840 Py_UNICODE *command_line, PyObject *proc_attrs,
841 PyObject *thread_attrs, BOOL inherit_handles,
842 DWORD creation_flags, PyObject *env_mapping,
843 Py_UNICODE *current_directory,
844 PyObject *startup_info)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300845/*[clinic end generated code: output=4652a33aff4b0ae1 input=4a43b05038d639bb]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200846{
847 BOOL result;
848 PROCESS_INFORMATION pi;
849 STARTUPINFOW si;
850 PyObject* environment;
Serhiy Storchaka0ee32c12017-06-24 16:14:08 +0300851 wchar_t *wenvironment;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200852
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200853 ZeroMemory(&si, sizeof(si));
854 si.cb = sizeof(si);
855
856 /* note: we only support a small subset of all SI attributes */
857 si.dwFlags = getulong(startup_info, "dwFlags");
858 si.wShowWindow = (WORD)getulong(startup_info, "wShowWindow");
859 si.hStdInput = gethandle(startup_info, "hStdInput");
860 si.hStdOutput = gethandle(startup_info, "hStdOutput");
861 si.hStdError = gethandle(startup_info, "hStdError");
862 if (PyErr_Occurred())
863 return NULL;
864
865 if (env_mapping != Py_None) {
866 environment = getenvironment(env_mapping);
Serhiy Storchakad174d242017-06-23 19:39:27 +0300867 if (environment == NULL) {
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200868 return NULL;
Serhiy Storchakad174d242017-06-23 19:39:27 +0300869 }
870 /* contains embedded null characters */
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200871 wenvironment = PyUnicode_AsUnicode(environment);
Serhiy Storchakad174d242017-06-23 19:39:27 +0300872 if (wenvironment == NULL) {
873 Py_DECREF(environment);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200874 return NULL;
875 }
876 }
877 else {
878 environment = NULL;
879 wenvironment = NULL;
880 }
881
882 Py_BEGIN_ALLOW_THREADS
883 result = CreateProcessW(application_name,
884 command_line,
885 NULL,
886 NULL,
887 inherit_handles,
888 creation_flags | CREATE_UNICODE_ENVIRONMENT,
889 wenvironment,
890 current_directory,
891 &si,
892 &pi);
893 Py_END_ALLOW_THREADS
894
895 Py_XDECREF(environment);
896
897 if (! result)
898 return PyErr_SetFromWindowsErr(GetLastError());
899
900 return Py_BuildValue("NNkk",
901 HANDLE_TO_PYNUM(pi.hProcess),
902 HANDLE_TO_PYNUM(pi.hThread),
903 pi.dwProcessId,
904 pi.dwThreadId);
905}
906
Zachary Waref2244ea2015-05-13 01:22:54 -0500907/*[clinic input]
908_winapi.DuplicateHandle -> HANDLE
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200909
Zachary Waref2244ea2015-05-13 01:22:54 -0500910 source_process_handle: HANDLE
911 source_handle: HANDLE
912 target_process_handle: HANDLE
913 desired_access: DWORD
914 inherit_handle: BOOL
915 options: DWORD = 0
916 /
917
918Return a duplicate handle object.
919
920The duplicate handle refers to the same object as the original
921handle. Therefore, any changes to the object are reflected
922through both handles.
923[clinic start generated code]*/
924
925static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300926_winapi_DuplicateHandle_impl(PyObject *module, HANDLE source_process_handle,
Zachary Ware77772c02015-05-13 10:58:35 -0500927 HANDLE source_handle,
928 HANDLE target_process_handle,
929 DWORD desired_access, BOOL inherit_handle,
930 DWORD options)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300931/*[clinic end generated code: output=ad9711397b5dcd4e input=b933e3f2356a8c12]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200932{
933 HANDLE target_handle;
934 BOOL result;
935
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200936 Py_BEGIN_ALLOW_THREADS
937 result = DuplicateHandle(
938 source_process_handle,
939 source_handle,
940 target_process_handle,
941 &target_handle,
942 desired_access,
943 inherit_handle,
944 options
945 );
946 Py_END_ALLOW_THREADS
947
Zachary Waref2244ea2015-05-13 01:22:54 -0500948 if (! result) {
949 PyErr_SetFromWindowsErr(GetLastError());
950 return INVALID_HANDLE_VALUE;
951 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200952
Zachary Waref2244ea2015-05-13 01:22:54 -0500953 return target_handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200954}
955
Zachary Waref2244ea2015-05-13 01:22:54 -0500956/*[clinic input]
957_winapi.ExitProcess
958
959 ExitCode: UINT
960 /
961
962[clinic start generated code]*/
963
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200964static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300965_winapi_ExitProcess_impl(PyObject *module, UINT ExitCode)
966/*[clinic end generated code: output=a387deb651175301 input=4f05466a9406c558]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200967{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200968 #if defined(Py_DEBUG)
969 SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|
970 SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
971 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
972 #endif
973
Zachary Waref2244ea2015-05-13 01:22:54 -0500974 ExitProcess(ExitCode);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200975
976 return NULL;
977}
978
Zachary Waref2244ea2015-05-13 01:22:54 -0500979/*[clinic input]
980_winapi.GetCurrentProcess -> HANDLE
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200981
Zachary Waref2244ea2015-05-13 01:22:54 -0500982Return a handle object for the current process.
983[clinic start generated code]*/
984
985static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300986_winapi_GetCurrentProcess_impl(PyObject *module)
987/*[clinic end generated code: output=ddeb4dd2ffadf344 input=b213403fd4b96b41]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200988{
Zachary Waref2244ea2015-05-13 01:22:54 -0500989 return GetCurrentProcess();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200990}
991
Zachary Waref2244ea2015-05-13 01:22:54 -0500992/*[clinic input]
993_winapi.GetExitCodeProcess -> DWORD
Antoine Pitrou23bba4c2012-04-18 20:51:15 +0200994
Zachary Waref2244ea2015-05-13 01:22:54 -0500995 process: HANDLE
996 /
997
998Return the termination status of the specified process.
999[clinic start generated code]*/
1000
1001static DWORD
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001002_winapi_GetExitCodeProcess_impl(PyObject *module, HANDLE process)
1003/*[clinic end generated code: output=b4620bdf2bccf36b input=61b6bfc7dc2ee374]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001004{
1005 DWORD exit_code;
1006 BOOL result;
1007
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001008 result = GetExitCodeProcess(process, &exit_code);
1009
Zachary Waref2244ea2015-05-13 01:22:54 -05001010 if (! result) {
1011 PyErr_SetFromWindowsErr(GetLastError());
1012 exit_code = DWORD_MAX;
1013 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001014
Zachary Waref2244ea2015-05-13 01:22:54 -05001015 return exit_code;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001016}
1017
Zachary Waref2244ea2015-05-13 01:22:54 -05001018/*[clinic input]
1019_winapi.GetLastError -> DWORD
1020[clinic start generated code]*/
1021
1022static DWORD
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001023_winapi_GetLastError_impl(PyObject *module)
1024/*[clinic end generated code: output=8585b827cb1a92c5 input=62d47fb9bce038ba]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001025{
Zachary Waref2244ea2015-05-13 01:22:54 -05001026 return GetLastError();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001027}
1028
Zachary Waref2244ea2015-05-13 01:22:54 -05001029/*[clinic input]
1030_winapi.GetModuleFileName
1031
1032 module_handle: HMODULE
1033 /
1034
1035Return the fully-qualified path for the file that contains module.
1036
1037The module must have been loaded by the current process.
1038
1039The module parameter should be a handle to the loaded module
1040whose path is being requested. If this parameter is 0,
1041GetModuleFileName retrieves the path of the executable file
1042of the current process.
1043[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001044
1045static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001046_winapi_GetModuleFileName_impl(PyObject *module, HMODULE module_handle)
1047/*[clinic end generated code: output=85b4b728c5160306 input=6d66ff7deca5d11f]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001048{
1049 BOOL result;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001050 WCHAR filename[MAX_PATH];
1051
Zachary Waref2244ea2015-05-13 01:22:54 -05001052 result = GetModuleFileNameW(module_handle, filename, MAX_PATH);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001053 filename[MAX_PATH-1] = '\0';
1054
1055 if (! result)
1056 return PyErr_SetFromWindowsErr(GetLastError());
1057
1058 return PyUnicode_FromWideChar(filename, wcslen(filename));
1059}
1060
Zachary Waref2244ea2015-05-13 01:22:54 -05001061/*[clinic input]
1062_winapi.GetStdHandle -> HANDLE
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001063
Zachary Waref2244ea2015-05-13 01:22:54 -05001064 std_handle: DWORD
1065 One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE.
1066 /
1067
1068Return a handle to the specified standard device.
1069
1070The integer associated with the handle object is returned.
1071[clinic start generated code]*/
1072
1073static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001074_winapi_GetStdHandle_impl(PyObject *module, DWORD std_handle)
1075/*[clinic end generated code: output=0e613001e73ab614 input=07016b06a2fc8826]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001076{
1077 HANDLE handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001078
1079 Py_BEGIN_ALLOW_THREADS
1080 handle = GetStdHandle(std_handle);
1081 Py_END_ALLOW_THREADS
1082
1083 if (handle == INVALID_HANDLE_VALUE)
Zachary Waref2244ea2015-05-13 01:22:54 -05001084 PyErr_SetFromWindowsErr(GetLastError());
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001085
Zachary Waref2244ea2015-05-13 01:22:54 -05001086 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001087}
1088
Zachary Waref2244ea2015-05-13 01:22:54 -05001089/*[clinic input]
1090_winapi.GetVersion -> long
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001091
Zachary Waref2244ea2015-05-13 01:22:54 -05001092Return the version number of the current operating system.
1093[clinic start generated code]*/
1094
1095static long
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001096_winapi_GetVersion_impl(PyObject *module)
1097/*[clinic end generated code: output=e41f0db5a3b82682 input=e21dff8d0baeded2]*/
Steve Dower3e96f322015-03-02 08:01:10 -08001098/* Disable deprecation warnings about GetVersionEx as the result is
1099 being passed straight through to the caller, who is responsible for
1100 using it correctly. */
1101#pragma warning(push)
1102#pragma warning(disable:4996)
1103
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001104{
Zachary Waref2244ea2015-05-13 01:22:54 -05001105 return GetVersion();
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001106}
1107
Steve Dower3e96f322015-03-02 08:01:10 -08001108#pragma warning(pop)
1109
Zachary Waref2244ea2015-05-13 01:22:54 -05001110/*[clinic input]
1111_winapi.OpenProcess -> HANDLE
1112
1113 desired_access: DWORD
1114 inherit_handle: BOOL
1115 process_id: DWORD
1116 /
1117[clinic start generated code]*/
1118
1119static HANDLE
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001120_winapi_OpenProcess_impl(PyObject *module, DWORD desired_access,
Zachary Ware77772c02015-05-13 10:58:35 -05001121 BOOL inherit_handle, DWORD process_id)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001122/*[clinic end generated code: output=b42b6b81ea5a0fc3 input=ec98c4cf4ea2ec36]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001123{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001124 HANDLE handle;
1125
Zachary Waref2244ea2015-05-13 01:22:54 -05001126 handle = OpenProcess(desired_access, inherit_handle, process_id);
1127 if (handle == NULL) {
1128 PyErr_SetFromWindowsErr(0);
1129 handle = INVALID_HANDLE_VALUE;
1130 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001131
Zachary Waref2244ea2015-05-13 01:22:54 -05001132 return handle;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001133}
1134
Zachary Waref2244ea2015-05-13 01:22:54 -05001135/*[clinic input]
1136_winapi.PeekNamedPipe
1137
1138 handle: HANDLE
1139 size: int = 0
1140 /
1141[clinic start generated code]*/
1142
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001143static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001144_winapi_PeekNamedPipe_impl(PyObject *module, HANDLE handle, int size)
1145/*[clinic end generated code: output=d0c3e29e49d323dd input=c7aa53bfbce69d70]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001146{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001147 PyObject *buf = NULL;
1148 DWORD nread, navail, nleft;
1149 BOOL ret;
1150
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001151 if (size < 0) {
1152 PyErr_SetString(PyExc_ValueError, "negative size");
1153 return NULL;
1154 }
1155
1156 if (size) {
1157 buf = PyBytes_FromStringAndSize(NULL, size);
1158 if (!buf)
1159 return NULL;
1160 Py_BEGIN_ALLOW_THREADS
1161 ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread,
1162 &navail, &nleft);
1163 Py_END_ALLOW_THREADS
1164 if (!ret) {
1165 Py_DECREF(buf);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001166 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001167 }
1168 if (_PyBytes_Resize(&buf, nread))
1169 return NULL;
1170 return Py_BuildValue("Nii", buf, navail, nleft);
1171 }
1172 else {
1173 Py_BEGIN_ALLOW_THREADS
1174 ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft);
1175 Py_END_ALLOW_THREADS
1176 if (!ret) {
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001177 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001178 }
1179 return Py_BuildValue("ii", navail, nleft);
1180 }
1181}
1182
Zachary Waref2244ea2015-05-13 01:22:54 -05001183/*[clinic input]
1184_winapi.ReadFile
1185
1186 handle: HANDLE
1187 size: int
Serhiy Storchaka202fda52017-03-12 10:10:47 +02001188 overlapped as use_overlapped: bool(accept={int}) = False
Zachary Waref2244ea2015-05-13 01:22:54 -05001189[clinic start generated code]*/
1190
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001191static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001192_winapi_ReadFile_impl(PyObject *module, HANDLE handle, int size,
Zachary Ware77772c02015-05-13 10:58:35 -05001193 int use_overlapped)
Serhiy Storchaka202fda52017-03-12 10:10:47 +02001194/*[clinic end generated code: output=492029ca98161d84 input=3f0fde92f74de59a]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001195{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001196 DWORD nread;
1197 PyObject *buf;
1198 BOOL ret;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001199 DWORD err;
1200 OverlappedObject *overlapped = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001201
1202 buf = PyBytes_FromStringAndSize(NULL, size);
1203 if (!buf)
1204 return NULL;
1205 if (use_overlapped) {
1206 overlapped = new_overlapped(handle);
1207 if (!overlapped) {
1208 Py_DECREF(buf);
1209 return NULL;
1210 }
1211 /* Steals reference to buf */
1212 overlapped->read_buffer = buf;
1213 }
1214
1215 Py_BEGIN_ALLOW_THREADS
1216 ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread,
1217 overlapped ? &overlapped->overlapped : NULL);
1218 Py_END_ALLOW_THREADS
1219
1220 err = ret ? 0 : GetLastError();
1221
1222 if (overlapped) {
1223 if (!ret) {
1224 if (err == ERROR_IO_PENDING)
1225 overlapped->pending = 1;
1226 else if (err != ERROR_MORE_DATA) {
1227 Py_DECREF(overlapped);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001228 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001229 }
1230 }
1231 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1232 }
1233
1234 if (!ret && err != ERROR_MORE_DATA) {
1235 Py_DECREF(buf);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001236 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001237 }
1238 if (_PyBytes_Resize(&buf, nread))
1239 return NULL;
1240 return Py_BuildValue("NI", buf, err);
1241}
1242
Zachary Waref2244ea2015-05-13 01:22:54 -05001243/*[clinic input]
1244_winapi.SetNamedPipeHandleState
1245
1246 named_pipe: HANDLE
1247 mode: object
1248 max_collection_count: object
1249 collect_data_timeout: object
1250 /
1251[clinic start generated code]*/
1252
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001253static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001254_winapi_SetNamedPipeHandleState_impl(PyObject *module, HANDLE named_pipe,
Zachary Ware77772c02015-05-13 10:58:35 -05001255 PyObject *mode,
1256 PyObject *max_collection_count,
1257 PyObject *collect_data_timeout)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001258/*[clinic end generated code: output=f2129d222cbfa095 input=9142d72163d0faa6]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001259{
Zachary Waref2244ea2015-05-13 01:22:54 -05001260 PyObject *oArgs[3] = {mode, max_collection_count, collect_data_timeout};
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001261 DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL};
1262 int i;
1263
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001264 PyErr_Clear();
1265
1266 for (i = 0 ; i < 3 ; i++) {
1267 if (oArgs[i] != Py_None) {
1268 dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]);
1269 if (PyErr_Occurred())
1270 return NULL;
1271 pArgs[i] = &dwArgs[i];
1272 }
1273 }
1274
Zachary Waref2244ea2015-05-13 01:22:54 -05001275 if (!SetNamedPipeHandleState(named_pipe, pArgs[0], pArgs[1], pArgs[2]))
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001276 return PyErr_SetFromWindowsErr(0);
1277
1278 Py_RETURN_NONE;
1279}
1280
Zachary Waref2244ea2015-05-13 01:22:54 -05001281
1282/*[clinic input]
1283_winapi.TerminateProcess
1284
1285 handle: HANDLE
1286 exit_code: UINT
1287 /
1288
1289Terminate the specified process and all of its threads.
1290[clinic start generated code]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001291
1292static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001293_winapi_TerminateProcess_impl(PyObject *module, HANDLE handle,
Zachary Ware77772c02015-05-13 10:58:35 -05001294 UINT exit_code)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001295/*[clinic end generated code: output=f4e99ac3f0b1f34a input=d6bc0aa1ee3bb4df]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001296{
1297 BOOL result;
1298
Zachary Waref2244ea2015-05-13 01:22:54 -05001299 result = TerminateProcess(handle, exit_code);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001300
1301 if (! result)
1302 return PyErr_SetFromWindowsErr(GetLastError());
1303
Zachary Waref2244ea2015-05-13 01:22:54 -05001304 Py_RETURN_NONE;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001305}
1306
Zachary Waref2244ea2015-05-13 01:22:54 -05001307/*[clinic input]
1308_winapi.WaitNamedPipe
1309
1310 name: LPCTSTR
1311 timeout: DWORD
1312 /
1313[clinic start generated code]*/
1314
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001315static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001316_winapi_WaitNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD timeout)
1317/*[clinic end generated code: output=c2866f4439b1fe38 input=36fc781291b1862c]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001318{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001319 BOOL success;
1320
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001321 Py_BEGIN_ALLOW_THREADS
Zachary Waref2244ea2015-05-13 01:22:54 -05001322 success = WaitNamedPipe(name, timeout);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001323 Py_END_ALLOW_THREADS
1324
1325 if (!success)
1326 return PyErr_SetFromWindowsErr(0);
1327
1328 Py_RETURN_NONE;
1329}
1330
Zachary Waref2244ea2015-05-13 01:22:54 -05001331/*[clinic input]
1332_winapi.WaitForMultipleObjects
1333
1334 handle_seq: object
1335 wait_flag: BOOL
1336 milliseconds: DWORD(c_default='INFINITE') = _winapi.INFINITE
1337 /
1338[clinic start generated code]*/
1339
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001340static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001341_winapi_WaitForMultipleObjects_impl(PyObject *module, PyObject *handle_seq,
1342 BOOL wait_flag, DWORD milliseconds)
1343/*[clinic end generated code: output=295e3f00b8e45899 input=36f76ca057cd28a0]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001344{
1345 DWORD result;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001346 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
1347 HANDLE sigint_event = NULL;
1348 Py_ssize_t nhandles, i;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001349
1350 if (!PySequence_Check(handle_seq)) {
1351 PyErr_Format(PyExc_TypeError,
1352 "sequence type expected, got '%s'",
Richard Oudkerk67339272012-08-21 14:54:22 +01001353 Py_TYPE(handle_seq)->tp_name);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001354 return NULL;
1355 }
1356 nhandles = PySequence_Length(handle_seq);
1357 if (nhandles == -1)
1358 return NULL;
1359 if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS - 1) {
1360 PyErr_Format(PyExc_ValueError,
1361 "need at most %zd handles, got a sequence of length %zd",
1362 MAXIMUM_WAIT_OBJECTS - 1, nhandles);
1363 return NULL;
1364 }
1365 for (i = 0; i < nhandles; i++) {
1366 HANDLE h;
1367 PyObject *v = PySequence_GetItem(handle_seq, i);
1368 if (v == NULL)
1369 return NULL;
1370 if (!PyArg_Parse(v, F_HANDLE, &h)) {
1371 Py_DECREF(v);
1372 return NULL;
1373 }
1374 handles[i] = h;
1375 Py_DECREF(v);
1376 }
1377 /* If this is the main thread then make the wait interruptible
1378 by Ctrl-C unless we are waiting for *all* handles */
1379 if (!wait_flag && _PyOS_IsMainThread()) {
1380 sigint_event = _PyOS_SigintEvent();
1381 assert(sigint_event != NULL);
1382 handles[nhandles++] = sigint_event;
1383 }
1384
1385 Py_BEGIN_ALLOW_THREADS
1386 if (sigint_event != NULL)
1387 ResetEvent(sigint_event);
1388 result = WaitForMultipleObjects((DWORD) nhandles, handles,
1389 wait_flag, milliseconds);
1390 Py_END_ALLOW_THREADS
1391
1392 if (result == WAIT_FAILED)
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001393 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001394 else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) {
1395 errno = EINTR;
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001396 return PyErr_SetFromErrno(PyExc_OSError);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001397 }
1398
1399 return PyLong_FromLong((int) result);
1400}
1401
Zachary Waref2244ea2015-05-13 01:22:54 -05001402/*[clinic input]
1403_winapi.WaitForSingleObject -> long
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001404
Zachary Waref2244ea2015-05-13 01:22:54 -05001405 handle: HANDLE
1406 milliseconds: DWORD
1407 /
1408
1409Wait for a single object.
1410
1411Wait until the specified object is in the signaled state or
1412the time-out interval elapses. The timeout value is specified
1413in milliseconds.
1414[clinic start generated code]*/
1415
1416static long
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001417_winapi_WaitForSingleObject_impl(PyObject *module, HANDLE handle,
Zachary Ware77772c02015-05-13 10:58:35 -05001418 DWORD milliseconds)
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001419/*[clinic end generated code: output=3c4715d8f1b39859 input=443d1ab076edc7b1]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001420{
1421 DWORD result;
1422
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001423 Py_BEGIN_ALLOW_THREADS
1424 result = WaitForSingleObject(handle, milliseconds);
1425 Py_END_ALLOW_THREADS
1426
Zachary Waref2244ea2015-05-13 01:22:54 -05001427 if (result == WAIT_FAILED) {
1428 PyErr_SetFromWindowsErr(GetLastError());
1429 return -1;
1430 }
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001431
Zachary Waref2244ea2015-05-13 01:22:54 -05001432 return result;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001433}
1434
Zachary Waref2244ea2015-05-13 01:22:54 -05001435/*[clinic input]
1436_winapi.WriteFile
1437
1438 handle: HANDLE
1439 buffer: object
Serhiy Storchaka202fda52017-03-12 10:10:47 +02001440 overlapped as use_overlapped: bool(accept={int}) = False
Zachary Waref2244ea2015-05-13 01:22:54 -05001441[clinic start generated code]*/
1442
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001443static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +03001444_winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
Zachary Ware77772c02015-05-13 10:58:35 -05001445 int use_overlapped)
Serhiy Storchaka202fda52017-03-12 10:10:47 +02001446/*[clinic end generated code: output=2ca80f6bf3fa92e3 input=11eae2a03aa32731]*/
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001447{
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001448 Py_buffer _buf, *buf;
Victor Stinner71765772013-06-24 23:13:24 +02001449 DWORD len, written;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001450 BOOL ret;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001451 DWORD err;
1452 OverlappedObject *overlapped = NULL;
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001453
1454 if (use_overlapped) {
1455 overlapped = new_overlapped(handle);
1456 if (!overlapped)
1457 return NULL;
1458 buf = &overlapped->write_buffer;
1459 }
1460 else
1461 buf = &_buf;
1462
Zachary Waref2244ea2015-05-13 01:22:54 -05001463 if (!PyArg_Parse(buffer, "y*", buf)) {
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001464 Py_XDECREF(overlapped);
1465 return NULL;
1466 }
1467
1468 Py_BEGIN_ALLOW_THREADS
Victor Stinner71765772013-06-24 23:13:24 +02001469 len = (DWORD)Py_MIN(buf->len, DWORD_MAX);
1470 ret = WriteFile(handle, buf->buf, len, &written,
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001471 overlapped ? &overlapped->overlapped : NULL);
1472 Py_END_ALLOW_THREADS
1473
1474 err = ret ? 0 : GetLastError();
1475
1476 if (overlapped) {
1477 if (!ret) {
1478 if (err == ERROR_IO_PENDING)
1479 overlapped->pending = 1;
1480 else {
1481 Py_DECREF(overlapped);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001482 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001483 }
1484 }
1485 return Py_BuildValue("NI", (PyObject *) overlapped, err);
1486 }
1487
1488 PyBuffer_Release(buf);
1489 if (!ret)
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +03001490 return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001491 return Py_BuildValue("II", written, err);
1492}
1493
1494
1495static PyMethodDef winapi_functions[] = {
Zachary Waref2244ea2015-05-13 01:22:54 -05001496 _WINAPI_CLOSEHANDLE_METHODDEF
1497 _WINAPI_CONNECTNAMEDPIPE_METHODDEF
1498 _WINAPI_CREATEFILE_METHODDEF
1499 _WINAPI_CREATENAMEDPIPE_METHODDEF
1500 _WINAPI_CREATEPIPE_METHODDEF
1501 _WINAPI_CREATEPROCESS_METHODDEF
1502 _WINAPI_CREATEJUNCTION_METHODDEF
1503 _WINAPI_DUPLICATEHANDLE_METHODDEF
1504 _WINAPI_EXITPROCESS_METHODDEF
1505 _WINAPI_GETCURRENTPROCESS_METHODDEF
1506 _WINAPI_GETEXITCODEPROCESS_METHODDEF
1507 _WINAPI_GETLASTERROR_METHODDEF
1508 _WINAPI_GETMODULEFILENAME_METHODDEF
1509 _WINAPI_GETSTDHANDLE_METHODDEF
1510 _WINAPI_GETVERSION_METHODDEF
1511 _WINAPI_OPENPROCESS_METHODDEF
1512 _WINAPI_PEEKNAMEDPIPE_METHODDEF
1513 _WINAPI_READFILE_METHODDEF
1514 _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF
1515 _WINAPI_TERMINATEPROCESS_METHODDEF
1516 _WINAPI_WAITNAMEDPIPE_METHODDEF
1517 _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF
1518 _WINAPI_WAITFORSINGLEOBJECT_METHODDEF
1519 _WINAPI_WRITEFILE_METHODDEF
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001520 {NULL, NULL}
1521};
1522
1523static struct PyModuleDef winapi_module = {
1524 PyModuleDef_HEAD_INIT,
1525 "_winapi",
1526 NULL,
1527 -1,
1528 winapi_functions,
1529 NULL,
1530 NULL,
1531 NULL,
1532 NULL
1533};
1534
1535#define WINAPI_CONSTANT(fmt, con) \
1536 PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1537
1538PyMODINIT_FUNC
1539PyInit__winapi(void)
1540{
1541 PyObject *d;
1542 PyObject *m;
1543
1544 if (PyType_Ready(&OverlappedType) < 0)
1545 return NULL;
1546
1547 m = PyModule_Create(&winapi_module);
1548 if (m == NULL)
1549 return NULL;
1550 d = PyModule_GetDict(m);
1551
1552 PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType);
1553
1554 /* constants */
1555 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
1556 WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP);
1557 WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001558 WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001559 WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
1560 WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
1561 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1562 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1563 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
1564 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001565 WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
1566 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
Richard Oudkerkfdb8dcf2012-05-05 19:45:37 +01001567 WINAPI_CONSTANT(F_DWORD, ERROR_NO_DATA);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001568 WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
1569 WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
1570 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
1571 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
1572 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
1573 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE);
1574 WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001575 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ);
1576 WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001577 WINAPI_CONSTANT(F_DWORD, GENERIC_READ);
1578 WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE);
1579 WINAPI_CONSTANT(F_DWORD, INFINITE);
1580 WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
1581 WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING);
1582 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
1583 WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
1584 WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
1585 WINAPI_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE);
1586 WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES);
1587 WINAPI_CONSTANT(F_DWORD, PIPE_WAIT);
1588 WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
Antoine Pitrou5438ed12012-04-24 22:56:57 +02001589 WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001590 WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW);
1591 WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES);
1592 WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE);
1593 WINAPI_CONSTANT(F_DWORD, STD_OUTPUT_HANDLE);
1594 WINAPI_CONSTANT(F_DWORD, STD_ERROR_HANDLE);
1595 WINAPI_CONSTANT(F_DWORD, STILL_ACTIVE);
1596 WINAPI_CONSTANT(F_DWORD, SW_HIDE);
1597 WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0);
Victor Stinner373f0a92014-03-20 09:26:55 +01001598 WINAPI_CONSTANT(F_DWORD, WAIT_ABANDONED_0);
Antoine Pitrou23bba4c2012-04-18 20:51:15 +02001599 WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT);
1600
1601 WINAPI_CONSTANT("i", NULL);
1602
1603 return m;
1604}