Home | History | Annotate | Download | only in Modules
      1 /*
      2  * Support routines from the Windows API
      3  *
      4  * This module was originally created by merging PC/_subprocess.c with
      5  * Modules/_multiprocessing/win32_functions.c.
      6  *
      7  * Copyright (c) 2004 by Fredrik Lundh <fredrik (at) pythonware.com>
      8  * Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com
      9  * Copyright (c) 2004 by Peter Astrand <astrand (at) lysator.liu.se>
     10  *
     11  * By obtaining, using, and/or copying this software and/or its
     12  * associated documentation, you agree that you have read, understood,
     13  * and will comply with the following terms and conditions:
     14  *
     15  * Permission to use, copy, modify, and distribute this software and
     16  * its associated documentation for any purpose and without fee is
     17  * hereby granted, provided that the above copyright notice appears in
     18  * all copies, and that both that copyright notice and this permission
     19  * notice appear in supporting documentation, and that the name of the
     20  * authors not be used in advertising or publicity pertaining to
     21  * distribution of the software without specific, written prior
     22  * permission.
     23  *
     24  * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     25  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
     26  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     27  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
     28  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
     29  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
     30  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     31  *
     32  */
     33 
     34 /* Licensed to PSF under a Contributor Agreement. */
     35 /* See http://www.python.org/2.4/license for licensing details. */
     36 
     37 #include "Python.h"
     38 #include "structmember.h"
     39 
     40 #define WINDOWS_LEAN_AND_MEAN
     41 #include "windows.h"
     42 #include <crtdbg.h>
     43 #include "winreparse.h"
     44 
     45 #if defined(MS_WIN32) && !defined(MS_WIN64)
     46 #define HANDLE_TO_PYNUM(handle) \
     47     PyLong_FromUnsignedLong((unsigned long) handle)
     48 #define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLong(obj))
     49 #define F_POINTER "k"
     50 #define T_POINTER T_ULONG
     51 #else
     52 #define HANDLE_TO_PYNUM(handle) \
     53     PyLong_FromUnsignedLongLong((unsigned long long) handle)
     54 #define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLongLong(obj))
     55 #define F_POINTER "K"
     56 #define T_POINTER T_ULONGLONG
     57 #endif
     58 
     59 #define F_HANDLE F_POINTER
     60 #define F_DWORD "k"
     61 
     62 #define T_HANDLE T_POINTER
     63 
     64 #define DWORD_MAX 4294967295U
     65 
     66 /* Grab CancelIoEx dynamically from kernel32 */
     67 static int has_CancelIoEx = -1;
     68 static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED);
     69 
     70 static int
     71 check_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 
     89 typedef 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 
    104 static void
    105 overlapped_dealloc(OverlappedObject *self)
    106 {
    107     DWORD bytes;
    108     int err = GetLastError();
    109 
    110     if (self->pending) {
    111         if (check_CancelIoEx() &&
    112             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         }
    117         else if (_Py_Finalizing == NULL)
    118         {
    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         }
    138     }
    139 
    140     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 
    148 /*[clinic input]
    149 module _winapi
    150 class _winapi.Overlapped "OverlappedObject *" "&OverlappedType"
    151 [clinic start generated code]*/
    152 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=c13d3f5fd1dabb84]*/
    153 
    154 /*[python input]
    155 def 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
    161 create_converter('HANDLE', '" F_HANDLE "')
    162 create_converter('HMODULE', '" F_HANDLE "')
    163 create_converter('LPSECURITY_ATTRIBUTES', '" F_POINTER "')
    164 
    165 create_converter('BOOL', 'i') # F_BOOL used previously (always 'i')
    166 create_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter)
    167 create_converter('LPCTSTR', 's')
    168 create_converter('LPWSTR', 'u')
    169 create_converter('UINT', 'I') # F_UINT used previously (always 'I')
    170 
    171 class HANDLE_return_converter(CReturnConverter):
    172     type = 'HANDLE'
    173 
    174     def render(self, function, data):
    175         self.declare(data)
    176         self.err_occurred_if("_return_value == INVALID_HANDLE_VALUE", data)
    177         data.return_conversion.append(
    178             'if (_return_value == NULL) {\n    Py_RETURN_NONE;\n}\n')
    179         data.return_conversion.append(
    180             'return_value = HANDLE_TO_PYNUM(_return_value);\n')
    181 
    182 class DWORD_return_converter(CReturnConverter):
    183     type = 'DWORD'
    184 
    185     def render(self, function, data):
    186         self.declare(data)
    187         self.err_occurred_if("_return_value == DWORD_MAX", data)
    188         data.return_conversion.append(
    189             'return_value = Py_BuildValue("k", _return_value);\n')
    190 [python start generated code]*/
    191 /*[python end generated code: output=da39a3ee5e6b4b0d input=94819e72d2c6d558]*/
    192 
    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 
    202 static PyObject *
    203 _winapi_Overlapped_GetOverlappedResult_impl(OverlappedObject *self, int wait)
    204 /*[clinic end generated code: output=bdd0c1ed6518cd03 input=194505ee8e0e3565]*/
    205 {
    206     BOOL res;
    207     DWORD transferred = 0;
    208     DWORD err;
    209 
    210     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;
    227             return PyErr_SetExcFromWindowsErr(PyExc_IOError, err);
    228     }
    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 
    238 /*[clinic input]
    239 _winapi.Overlapped.getbuffer
    240 [clinic start generated code]*/
    241 
    242 static PyObject *
    243 _winapi_Overlapped_getbuffer_impl(OverlappedObject *self)
    244 /*[clinic end generated code: output=95a3eceefae0f748 input=347fcfd56b4ceabd]*/
    245 {
    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 
    258 /*[clinic input]
    259 _winapi.Overlapped.cancel
    260 [clinic start generated code]*/
    261 
    262 static PyObject *
    263 _winapi_Overlapped_cancel_impl(OverlappedObject *self)
    264 /*[clinic end generated code: output=fcb9ab5df4ebdae5 input=cbf3da142290039f]*/
    265 {
    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)
    279         return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
    280     self->pending = 0;
    281     Py_RETURN_NONE;
    282 }
    283 
    284 static PyMethodDef overlapped_methods[] = {
    285     _WINAPI_OVERLAPPED_GETOVERLAPPEDRESULT_METHODDEF
    286     _WINAPI_OVERLAPPED_GETBUFFER_METHODDEF
    287     _WINAPI_OVERLAPPED_CANCEL_METHODDEF
    288     {NULL}
    289 };
    290 
    291 static PyMemberDef overlapped_members[] = {
    292     {"event", T_HANDLE,
    293      offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
    294      READONLY, "overlapped event handle"},
    295     {NULL}
    296 };
    297 
    298 PyTypeObject 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 
    339 static OverlappedObject *
    340 new_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 
    361 /*[clinic input]
    362 _winapi.CloseHandle
    363 
    364     handle: HANDLE
    365     /
    366 
    367 Close handle.
    368 [clinic start generated code]*/
    369 
    370 static PyObject *
    371 _winapi_CloseHandle_impl(PyObject *module, HANDLE handle)
    372 /*[clinic end generated code: output=7ad37345f07bd782 input=7f0e4ac36e0352b8]*/
    373 {
    374     BOOL success;
    375 
    376     Py_BEGIN_ALLOW_THREADS
    377     success = CloseHandle(handle);
    378     Py_END_ALLOW_THREADS
    379 
    380     if (!success)
    381         return PyErr_SetFromWindowsErr(0);
    382 
    383     Py_RETURN_NONE;
    384 }
    385 
    386 /*[clinic input]
    387 _winapi.ConnectNamedPipe
    388 
    389     handle: HANDLE
    390     overlapped as use_overlapped: int(c_default='0') = False
    391 [clinic start generated code]*/
    392 
    393 static PyObject *
    394 _winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle,
    395                               int use_overlapped)
    396 /*[clinic end generated code: output=335a0e7086800671 input=edc83da007ebf3be]*/
    397 {
    398     BOOL success;
    399     OverlappedObject *overlapped = NULL;
    400 
    401     if (use_overlapped) {
    402         overlapped = new_overlapped(handle);
    403         if (!overlapped)
    404             return NULL;
    405     }
    406 
    407     Py_BEGIN_ALLOW_THREADS
    408     success = ConnectNamedPipe(handle,
    409                                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 
    432 /*[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 
    445 static HANDLE
    446 _winapi_CreateFile_impl(PyObject *module, LPCTSTR file_name,
    447                         DWORD desired_access, DWORD share_mode,
    448                         LPSECURITY_ATTRIBUTES security_attributes,
    449                         DWORD creation_disposition,
    450                         DWORD flags_and_attributes, HANDLE template_file)
    451 /*[clinic end generated code: output=417ddcebfc5a3d53 input=6423c3e40372dbd5]*/
    452 {
    453     HANDLE handle;
    454 
    455     Py_BEGIN_ALLOW_THREADS
    456     handle = CreateFile(file_name, desired_access,
    457                         share_mode, security_attributes,
    458                         creation_disposition,
    459                         flags_and_attributes, template_file);
    460     Py_END_ALLOW_THREADS
    461 
    462     if (handle == INVALID_HANDLE_VALUE)
    463         PyErr_SetFromWindowsErr(0);
    464 
    465     return handle;
    466 }
    467 
    468 /*[clinic input]
    469 _winapi.CreateJunction
    470 
    471     src_path: LPWSTR
    472     dst_path: LPWSTR
    473     /
    474 [clinic start generated code]*/
    475 
    476 static PyObject *
    477 _winapi_CreateJunction_impl(PyObject *module, LPWSTR src_path,
    478                             LPWSTR dst_path)
    479 /*[clinic end generated code: output=66b7eb746e1dfa25 input=8cd1f9964b6e3d36]*/
    480 {
    481     /* 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;
    489     _Py_PREPARSE_DATA_BUFFER rdb = NULL;
    490 
    491     /* Junction point creation */
    492     HANDLE junction = NULL;
    493     DWORD ret = 0;
    494 
    495     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 */
    545     rdb_size = _Py_REPARSE_DATA_BUFFER_HEADER_SIZE +
    546         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);
    550     rdb = (_Py_PREPARSE_DATA_BUFFER)PyMem_RawMalloc(rdb_size);
    551     if (rdb == NULL)
    552         goto cleanup;
    553 
    554     memset(rdb, 0, rdb_size);
    555     rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
    556     rdb->ReparseDataLength = rdb_size - _Py_REPARSE_DATA_BUFFER_HEADER_SIZE;
    557     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 
    592 cleanup:
    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 
    605 /*[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 
    619 static HANDLE
    620 _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,
    624                              LPSECURITY_ATTRIBUTES security_attributes)
    625 /*[clinic end generated code: output=80f8c07346a94fbc input=5a73530b84d8bc37]*/
    626 {
    627     HANDLE handle;
    628 
    629     Py_BEGIN_ALLOW_THREADS
    630     handle = CreateNamedPipe(name, open_mode, pipe_mode,
    631                              max_instances, out_buffer_size,
    632                              in_buffer_size, default_timeout,
    633                              security_attributes);
    634     Py_END_ALLOW_THREADS
    635 
    636     if (handle == INVALID_HANDLE_VALUE)
    637         PyErr_SetFromWindowsErr(0);
    638 
    639     return handle;
    640 }
    641 
    642 /*[clinic input]
    643 _winapi.CreatePipe
    644 
    645     pipe_attrs: object
    646         Ignored internally, can be None.
    647     size: DWORD
    648     /
    649 
    650 Create an anonymous pipe.
    651 
    652 Returns a 2-tuple of handles, to the read and write ends of the pipe.
    653 [clinic start generated code]*/
    654 
    655 static PyObject *
    656 _winapi_CreatePipe_impl(PyObject *module, PyObject *pipe_attrs, DWORD size)
    657 /*[clinic end generated code: output=1c4411d8699f0925 input=c4f2cfa56ef68d90]*/
    658 {
    659     HANDLE read_pipe;
    660     HANDLE write_pipe;
    661     BOOL result;
    662 
    663     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 
    676 static unsigned long
    677 getulong(PyObject* obj, const char* name)
    678 {
    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 
    692 static HANDLE
    693 gethandle(PyObject* obj, const char* name)
    694 {
    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 
    711 static PyObject*
    712 getenvironment(PyObject* environment)
    713 {
    714     Py_ssize_t i, envsize, totalsize;
    715     Py_UCS4 *buffer = NULL, *p, *end;
    716     PyObject *keys, *values, *res;
    717 
    718     /* convert environment dictionary to windows environment string */
    719     if (! PyMapping_Check(environment)) {
    720         PyErr_SetString(
    721             PyExc_TypeError, "environment must be dictionary or None");
    722         return NULL;
    723     }
    724 
    725     envsize = PyMapping_Length(environment);
    726 
    727     keys = PyMapping_Keys(environment);
    728     values = PyMapping_Values(environment);
    729     if (!keys || !values)
    730         goto error;
    731 
    732     totalsize = 1; /* trailing null character */
    733     for (i = 0; i < envsize; i++) {
    734         PyObject* key = PyList_GET_ITEM(keys, i);
    735         PyObject* value = PyList_GET_ITEM(values, i);
    736 
    737         if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
    738             PyErr_SetString(PyExc_TypeError,
    739                 "environment can only contain strings");
    740             goto error;
    741         }
    742         if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(key) - 1) {
    743             PyErr_SetString(PyExc_OverflowError, "environment too long");
    744             goto error;
    745         }
    746         totalsize += PyUnicode_GET_LENGTH(key) + 1;    /* +1 for '=' */
    747         if (totalsize > PY_SSIZE_T_MAX - PyUnicode_GET_LENGTH(value) - 1) {
    748             PyErr_SetString(PyExc_OverflowError, "environment too long");
    749             goto error;
    750         }
    751         totalsize += PyUnicode_GET_LENGTH(value) + 1;  /* +1 for '\0' */
    752     }
    753 
    754     buffer = PyMem_NEW(Py_UCS4, totalsize);
    755     if (! buffer) {
    756         PyErr_NoMemory();
    757         goto error;
    758     }
    759     p = buffer;
    760     end = buffer + totalsize;
    761 
    762     for (i = 0; i < envsize; i++) {
    763         PyObject* key = PyList_GET_ITEM(keys, i);
    764         PyObject* value = PyList_GET_ITEM(values, i);
    765         if (!PyUnicode_AsUCS4(key, p, end - p, 0))
    766             goto error;
    767         p += PyUnicode_GET_LENGTH(key);
    768         *p++ = '=';
    769         if (!PyUnicode_AsUCS4(value, p, end - p, 0))
    770             goto error;
    771         p += PyUnicode_GET_LENGTH(value);
    772         *p++ = '\0';
    773     }
    774 
    775     /* add trailing null byte */
    776     *p++ = '\0';
    777     assert(p == end);
    778 
    779     Py_XDECREF(keys);
    780     Py_XDECREF(values);
    781 
    782     res = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buffer, p - buffer);
    783     PyMem_Free(buffer);
    784     return res;
    785 
    786  error:
    787     PyMem_Free(buffer);
    788     Py_XDECREF(keys);
    789     Py_XDECREF(values);
    790     return NULL;
    791 }
    792 
    793 /*[clinic input]
    794 _winapi.CreateProcess
    795 
    796     application_name: Py_UNICODE(accept={str, NoneType})
    797     command_line: Py_UNICODE(accept={str, NoneType})
    798     proc_attrs: object
    799         Ignored internally, can be None.
    800     thread_attrs: object
    801         Ignored internally, can be None.
    802     inherit_handles: BOOL
    803     creation_flags: DWORD
    804     env_mapping: object
    805     current_directory: Py_UNICODE(accept={str, NoneType})
    806     startup_info: object
    807     /
    808 
    809 Create a new process and its primary thread.
    810 
    811 The return value is a tuple of the process handle, thread handle,
    812 process ID, and thread ID.
    813 [clinic start generated code]*/
    814 
    815 static PyObject *
    816 _winapi_CreateProcess_impl(PyObject *module, Py_UNICODE *application_name,
    817                            Py_UNICODE *command_line, PyObject *proc_attrs,
    818                            PyObject *thread_attrs, BOOL inherit_handles,
    819                            DWORD creation_flags, PyObject *env_mapping,
    820                            Py_UNICODE *current_directory,
    821                            PyObject *startup_info)
    822 /*[clinic end generated code: output=4652a33aff4b0ae1 input=4a43b05038d639bb]*/
    823 {
    824     BOOL result;
    825     PROCESS_INFORMATION pi;
    826     STARTUPINFOW si;
    827     PyObject* environment;
    828     wchar_t *wenvironment;
    829 
    830     ZeroMemory(&si, sizeof(si));
    831     si.cb = sizeof(si);
    832 
    833     /* note: we only support a small subset of all SI attributes */
    834     si.dwFlags = getulong(startup_info, "dwFlags");
    835     si.wShowWindow = (WORD)getulong(startup_info, "wShowWindow");
    836     si.hStdInput = gethandle(startup_info, "hStdInput");
    837     si.hStdOutput = gethandle(startup_info, "hStdOutput");
    838     si.hStdError = gethandle(startup_info, "hStdError");
    839     if (PyErr_Occurred())
    840         return NULL;
    841 
    842     if (env_mapping != Py_None) {
    843         environment = getenvironment(env_mapping);
    844         if (! environment)
    845             return NULL;
    846         wenvironment = PyUnicode_AsUnicode(environment);
    847         if (wenvironment == NULL)
    848         {
    849             Py_XDECREF(environment);
    850             return NULL;
    851         }
    852     }
    853     else {
    854         environment = NULL;
    855         wenvironment = NULL;
    856     }
    857 
    858     Py_BEGIN_ALLOW_THREADS
    859     result = CreateProcessW(application_name,
    860                            command_line,
    861                            NULL,
    862                            NULL,
    863                            inherit_handles,
    864                            creation_flags | CREATE_UNICODE_ENVIRONMENT,
    865                            wenvironment,
    866                            current_directory,
    867                            &si,
    868                            &pi);
    869     Py_END_ALLOW_THREADS
    870 
    871     Py_XDECREF(environment);
    872 
    873     if (! result)
    874         return PyErr_SetFromWindowsErr(GetLastError());
    875 
    876     return Py_BuildValue("NNkk",
    877                          HANDLE_TO_PYNUM(pi.hProcess),
    878                          HANDLE_TO_PYNUM(pi.hThread),
    879                          pi.dwProcessId,
    880                          pi.dwThreadId);
    881 }
    882 
    883 /*[clinic input]
    884 _winapi.DuplicateHandle -> HANDLE
    885 
    886     source_process_handle: HANDLE
    887     source_handle: HANDLE
    888     target_process_handle: HANDLE
    889     desired_access: DWORD
    890     inherit_handle: BOOL
    891     options: DWORD = 0
    892     /
    893 
    894 Return a duplicate handle object.
    895 
    896 The duplicate handle refers to the same object as the original
    897 handle. Therefore, any changes to the object are reflected
    898 through both handles.
    899 [clinic start generated code]*/
    900 
    901 static HANDLE
    902 _winapi_DuplicateHandle_impl(PyObject *module, HANDLE source_process_handle,
    903                              HANDLE source_handle,
    904                              HANDLE target_process_handle,
    905                              DWORD desired_access, BOOL inherit_handle,
    906                              DWORD options)
    907 /*[clinic end generated code: output=ad9711397b5dcd4e input=b933e3f2356a8c12]*/
    908 {
    909     HANDLE target_handle;
    910     BOOL result;
    911 
    912     Py_BEGIN_ALLOW_THREADS
    913     result = DuplicateHandle(
    914         source_process_handle,
    915         source_handle,
    916         target_process_handle,
    917         &target_handle,
    918         desired_access,
    919         inherit_handle,
    920         options
    921     );
    922     Py_END_ALLOW_THREADS
    923 
    924     if (! result) {
    925         PyErr_SetFromWindowsErr(GetLastError());
    926         return INVALID_HANDLE_VALUE;
    927     }
    928 
    929     return target_handle;
    930 }
    931 
    932 /*[clinic input]
    933 _winapi.ExitProcess
    934 
    935     ExitCode: UINT
    936     /
    937 
    938 [clinic start generated code]*/
    939 
    940 static PyObject *
    941 _winapi_ExitProcess_impl(PyObject *module, UINT ExitCode)
    942 /*[clinic end generated code: output=a387deb651175301 input=4f05466a9406c558]*/
    943 {
    944     #if defined(Py_DEBUG)
    945         SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|
    946                      SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
    947         _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
    948     #endif
    949 
    950     ExitProcess(ExitCode);
    951 
    952     return NULL;
    953 }
    954 
    955 /*[clinic input]
    956 _winapi.GetCurrentProcess -> HANDLE
    957 
    958 Return a handle object for the current process.
    959 [clinic start generated code]*/
    960 
    961 static HANDLE
    962 _winapi_GetCurrentProcess_impl(PyObject *module)
    963 /*[clinic end generated code: output=ddeb4dd2ffadf344 input=b213403fd4b96b41]*/
    964 {
    965     return GetCurrentProcess();
    966 }
    967 
    968 /*[clinic input]
    969 _winapi.GetExitCodeProcess -> DWORD
    970 
    971     process: HANDLE
    972     /
    973 
    974 Return the termination status of the specified process.
    975 [clinic start generated code]*/
    976 
    977 static DWORD
    978 _winapi_GetExitCodeProcess_impl(PyObject *module, HANDLE process)
    979 /*[clinic end generated code: output=b4620bdf2bccf36b input=61b6bfc7dc2ee374]*/
    980 {
    981     DWORD exit_code;
    982     BOOL result;
    983 
    984     result = GetExitCodeProcess(process, &exit_code);
    985 
    986     if (! result) {
    987         PyErr_SetFromWindowsErr(GetLastError());
    988         exit_code = DWORD_MAX;
    989     }
    990 
    991     return exit_code;
    992 }
    993 
    994 /*[clinic input]
    995 _winapi.GetLastError -> DWORD
    996 [clinic start generated code]*/
    997 
    998 static DWORD
    999 _winapi_GetLastError_impl(PyObject *module)
   1000 /*[clinic end generated code: output=8585b827cb1a92c5 input=62d47fb9bce038ba]*/
   1001 {
   1002     return GetLastError();
   1003 }
   1004 
   1005 /*[clinic input]
   1006 _winapi.GetModuleFileName
   1007 
   1008     module_handle: HMODULE
   1009     /
   1010 
   1011 Return the fully-qualified path for the file that contains module.
   1012 
   1013 The module must have been loaded by the current process.
   1014 
   1015 The module parameter should be a handle to the loaded module
   1016 whose path is being requested. If this parameter is 0,
   1017 GetModuleFileName retrieves the path of the executable file
   1018 of the current process.
   1019 [clinic start generated code]*/
   1020 
   1021 static PyObject *
   1022 _winapi_GetModuleFileName_impl(PyObject *module, HMODULE module_handle)
   1023 /*[clinic end generated code: output=85b4b728c5160306 input=6d66ff7deca5d11f]*/
   1024 {
   1025     BOOL result;
   1026     WCHAR filename[MAX_PATH];
   1027 
   1028     result = GetModuleFileNameW(module_handle, filename, MAX_PATH);
   1029     filename[MAX_PATH-1] = '\0';
   1030 
   1031     if (! result)
   1032         return PyErr_SetFromWindowsErr(GetLastError());
   1033 
   1034     return PyUnicode_FromWideChar(filename, wcslen(filename));
   1035 }
   1036 
   1037 /*[clinic input]
   1038 _winapi.GetStdHandle -> HANDLE
   1039 
   1040     std_handle: DWORD
   1041         One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE.
   1042     /
   1043 
   1044 Return a handle to the specified standard device.
   1045 
   1046 The integer associated with the handle object is returned.
   1047 [clinic start generated code]*/
   1048 
   1049 static HANDLE
   1050 _winapi_GetStdHandle_impl(PyObject *module, DWORD std_handle)
   1051 /*[clinic end generated code: output=0e613001e73ab614 input=07016b06a2fc8826]*/
   1052 {
   1053     HANDLE handle;
   1054 
   1055     Py_BEGIN_ALLOW_THREADS
   1056     handle = GetStdHandle(std_handle);
   1057     Py_END_ALLOW_THREADS
   1058 
   1059     if (handle == INVALID_HANDLE_VALUE)
   1060         PyErr_SetFromWindowsErr(GetLastError());
   1061 
   1062     return handle;
   1063 }
   1064 
   1065 /*[clinic input]
   1066 _winapi.GetVersion -> long
   1067 
   1068 Return the version number of the current operating system.
   1069 [clinic start generated code]*/
   1070 
   1071 static long
   1072 _winapi_GetVersion_impl(PyObject *module)
   1073 /*[clinic end generated code: output=e41f0db5a3b82682 input=e21dff8d0baeded2]*/
   1074 /* Disable deprecation warnings about GetVersionEx as the result is
   1075    being passed straight through to the caller, who is responsible for
   1076    using it correctly. */
   1077 #pragma warning(push)
   1078 #pragma warning(disable:4996)
   1079 
   1080 {
   1081     return GetVersion();
   1082 }
   1083 
   1084 #pragma warning(pop)
   1085 
   1086 /*[clinic input]
   1087 _winapi.OpenProcess -> HANDLE
   1088 
   1089     desired_access: DWORD
   1090     inherit_handle: BOOL
   1091     process_id: DWORD
   1092     /
   1093 [clinic start generated code]*/
   1094 
   1095 static HANDLE
   1096 _winapi_OpenProcess_impl(PyObject *module, DWORD desired_access,
   1097                          BOOL inherit_handle, DWORD process_id)
   1098 /*[clinic end generated code: output=b42b6b81ea5a0fc3 input=ec98c4cf4ea2ec36]*/
   1099 {
   1100     HANDLE handle;
   1101 
   1102     handle = OpenProcess(desired_access, inherit_handle, process_id);
   1103     if (handle == NULL) {
   1104         PyErr_SetFromWindowsErr(0);
   1105         handle = INVALID_HANDLE_VALUE;
   1106     }
   1107 
   1108     return handle;
   1109 }
   1110 
   1111 /*[clinic input]
   1112 _winapi.PeekNamedPipe
   1113 
   1114     handle: HANDLE
   1115     size: int = 0
   1116     /
   1117 [clinic start generated code]*/
   1118 
   1119 static PyObject *
   1120 _winapi_PeekNamedPipe_impl(PyObject *module, HANDLE handle, int size)
   1121 /*[clinic end generated code: output=d0c3e29e49d323dd input=c7aa53bfbce69d70]*/
   1122 {
   1123     PyObject *buf = NULL;
   1124     DWORD nread, navail, nleft;
   1125     BOOL ret;
   1126 
   1127     if (size < 0) {
   1128         PyErr_SetString(PyExc_ValueError, "negative size");
   1129         return NULL;
   1130     }
   1131 
   1132     if (size) {
   1133         buf = PyBytes_FromStringAndSize(NULL, size);
   1134         if (!buf)
   1135             return NULL;
   1136         Py_BEGIN_ALLOW_THREADS
   1137         ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread,
   1138                             &navail, &nleft);
   1139         Py_END_ALLOW_THREADS
   1140         if (!ret) {
   1141             Py_DECREF(buf);
   1142             return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
   1143         }
   1144         if (_PyBytes_Resize(&buf, nread))
   1145             return NULL;
   1146         return Py_BuildValue("Nii", buf, navail, nleft);
   1147     }
   1148     else {
   1149         Py_BEGIN_ALLOW_THREADS
   1150         ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft);
   1151         Py_END_ALLOW_THREADS
   1152         if (!ret) {
   1153             return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
   1154         }
   1155         return Py_BuildValue("ii", navail, nleft);
   1156     }
   1157 }
   1158 
   1159 /*[clinic input]
   1160 _winapi.ReadFile
   1161 
   1162     handle: HANDLE
   1163     size: int
   1164     overlapped as use_overlapped: int(c_default='0') = False
   1165 [clinic start generated code]*/
   1166 
   1167 static PyObject *
   1168 _winapi_ReadFile_impl(PyObject *module, HANDLE handle, int size,
   1169                       int use_overlapped)
   1170 /*[clinic end generated code: output=492029ca98161d84 input=8dd810194e86ac7d]*/
   1171 {
   1172     DWORD nread;
   1173     PyObject *buf;
   1174     BOOL ret;
   1175     DWORD err;
   1176     OverlappedObject *overlapped = NULL;
   1177 
   1178     buf = PyBytes_FromStringAndSize(NULL, size);
   1179     if (!buf)
   1180         return NULL;
   1181     if (use_overlapped) {
   1182         overlapped = new_overlapped(handle);
   1183         if (!overlapped) {
   1184             Py_DECREF(buf);
   1185             return NULL;
   1186         }
   1187         /* Steals reference to buf */
   1188         overlapped->read_buffer = buf;
   1189     }
   1190 
   1191     Py_BEGIN_ALLOW_THREADS
   1192     ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread,
   1193                    overlapped ? &overlapped->overlapped : NULL);
   1194     Py_END_ALLOW_THREADS
   1195 
   1196     err = ret ? 0 : GetLastError();
   1197 
   1198     if (overlapped) {
   1199         if (!ret) {
   1200             if (err == ERROR_IO_PENDING)
   1201                 overlapped->pending = 1;
   1202             else if (err != ERROR_MORE_DATA) {
   1203                 Py_DECREF(overlapped);
   1204                 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
   1205             }
   1206         }
   1207         return Py_BuildValue("NI", (PyObject *) overlapped, err);
   1208     }
   1209 
   1210     if (!ret && err != ERROR_MORE_DATA) {
   1211         Py_DECREF(buf);
   1212         return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
   1213     }
   1214     if (_PyBytes_Resize(&buf, nread))
   1215         return NULL;
   1216     return Py_BuildValue("NI", buf, err);
   1217 }
   1218 
   1219 /*[clinic input]
   1220 _winapi.SetNamedPipeHandleState
   1221 
   1222     named_pipe: HANDLE
   1223     mode: object
   1224     max_collection_count: object
   1225     collect_data_timeout: object
   1226     /
   1227 [clinic start generated code]*/
   1228 
   1229 static PyObject *
   1230 _winapi_SetNamedPipeHandleState_impl(PyObject *module, HANDLE named_pipe,
   1231                                      PyObject *mode,
   1232                                      PyObject *max_collection_count,
   1233                                      PyObject *collect_data_timeout)
   1234 /*[clinic end generated code: output=f2129d222cbfa095 input=9142d72163d0faa6]*/
   1235 {
   1236     PyObject *oArgs[3] = {mode, max_collection_count, collect_data_timeout};
   1237     DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL};
   1238     int i;
   1239 
   1240     PyErr_Clear();
   1241 
   1242     for (i = 0 ; i < 3 ; i++) {
   1243         if (oArgs[i] != Py_None) {
   1244             dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]);
   1245             if (PyErr_Occurred())
   1246                 return NULL;
   1247             pArgs[i] = &dwArgs[i];
   1248         }
   1249     }
   1250 
   1251     if (!SetNamedPipeHandleState(named_pipe, pArgs[0], pArgs[1], pArgs[2]))
   1252         return PyErr_SetFromWindowsErr(0);
   1253 
   1254     Py_RETURN_NONE;
   1255 }
   1256 
   1257 
   1258 /*[clinic input]
   1259 _winapi.TerminateProcess
   1260 
   1261     handle: HANDLE
   1262     exit_code: UINT
   1263     /
   1264 
   1265 Terminate the specified process and all of its threads.
   1266 [clinic start generated code]*/
   1267 
   1268 static PyObject *
   1269 _winapi_TerminateProcess_impl(PyObject *module, HANDLE handle,
   1270                               UINT exit_code)
   1271 /*[clinic end generated code: output=f4e99ac3f0b1f34a input=d6bc0aa1ee3bb4df]*/
   1272 {
   1273     BOOL result;
   1274 
   1275     result = TerminateProcess(handle, exit_code);
   1276 
   1277     if (! result)
   1278         return PyErr_SetFromWindowsErr(GetLastError());
   1279 
   1280     Py_RETURN_NONE;
   1281 }
   1282 
   1283 /*[clinic input]
   1284 _winapi.WaitNamedPipe
   1285 
   1286     name: LPCTSTR
   1287     timeout: DWORD
   1288     /
   1289 [clinic start generated code]*/
   1290 
   1291 static PyObject *
   1292 _winapi_WaitNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD timeout)
   1293 /*[clinic end generated code: output=c2866f4439b1fe38 input=36fc781291b1862c]*/
   1294 {
   1295     BOOL success;
   1296 
   1297     Py_BEGIN_ALLOW_THREADS
   1298     success = WaitNamedPipe(name, timeout);
   1299     Py_END_ALLOW_THREADS
   1300 
   1301     if (!success)
   1302         return PyErr_SetFromWindowsErr(0);
   1303 
   1304     Py_RETURN_NONE;
   1305 }
   1306 
   1307 /*[clinic input]
   1308 _winapi.WaitForMultipleObjects
   1309 
   1310     handle_seq: object
   1311     wait_flag: BOOL
   1312     milliseconds: DWORD(c_default='INFINITE') = _winapi.INFINITE
   1313     /
   1314 [clinic start generated code]*/
   1315 
   1316 static PyObject *
   1317 _winapi_WaitForMultipleObjects_impl(PyObject *module, PyObject *handle_seq,
   1318                                     BOOL wait_flag, DWORD milliseconds)
   1319 /*[clinic end generated code: output=295e3f00b8e45899 input=36f76ca057cd28a0]*/
   1320 {
   1321     DWORD result;
   1322     HANDLE handles[MAXIMUM_WAIT_OBJECTS];
   1323     HANDLE sigint_event = NULL;
   1324     Py_ssize_t nhandles, i;
   1325 
   1326     if (!PySequence_Check(handle_seq)) {
   1327         PyErr_Format(PyExc_TypeError,
   1328                      "sequence type expected, got '%s'",
   1329                      Py_TYPE(handle_seq)->tp_name);
   1330         return NULL;
   1331     }
   1332     nhandles = PySequence_Length(handle_seq);
   1333     if (nhandles == -1)
   1334         return NULL;
   1335     if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS - 1) {
   1336         PyErr_Format(PyExc_ValueError,
   1337                      "need at most %zd handles, got a sequence of length %zd",
   1338                      MAXIMUM_WAIT_OBJECTS - 1, nhandles);
   1339         return NULL;
   1340     }
   1341     for (i = 0; i < nhandles; i++) {
   1342         HANDLE h;
   1343         PyObject *v = PySequence_GetItem(handle_seq, i);
   1344         if (v == NULL)
   1345             return NULL;
   1346         if (!PyArg_Parse(v, F_HANDLE, &h)) {
   1347             Py_DECREF(v);
   1348             return NULL;
   1349         }
   1350         handles[i] = h;
   1351         Py_DECREF(v);
   1352     }
   1353     /* If this is the main thread then make the wait interruptible
   1354        by Ctrl-C unless we are waiting for *all* handles */
   1355     if (!wait_flag && _PyOS_IsMainThread()) {
   1356         sigint_event = _PyOS_SigintEvent();
   1357         assert(sigint_event != NULL);
   1358         handles[nhandles++] = sigint_event;
   1359     }
   1360 
   1361     Py_BEGIN_ALLOW_THREADS
   1362     if (sigint_event != NULL)
   1363         ResetEvent(sigint_event);
   1364     result = WaitForMultipleObjects((DWORD) nhandles, handles,
   1365                                     wait_flag, milliseconds);
   1366     Py_END_ALLOW_THREADS
   1367 
   1368     if (result == WAIT_FAILED)
   1369         return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
   1370     else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) {
   1371         errno = EINTR;
   1372         return PyErr_SetFromErrno(PyExc_IOError);
   1373     }
   1374 
   1375     return PyLong_FromLong((int) result);
   1376 }
   1377 
   1378 /*[clinic input]
   1379 _winapi.WaitForSingleObject -> long
   1380 
   1381     handle: HANDLE
   1382     milliseconds: DWORD
   1383     /
   1384 
   1385 Wait for a single object.
   1386 
   1387 Wait until the specified object is in the signaled state or
   1388 the time-out interval elapses. The timeout value is specified
   1389 in milliseconds.
   1390 [clinic start generated code]*/
   1391 
   1392 static long
   1393 _winapi_WaitForSingleObject_impl(PyObject *module, HANDLE handle,
   1394                                  DWORD milliseconds)
   1395 /*[clinic end generated code: output=3c4715d8f1b39859 input=443d1ab076edc7b1]*/
   1396 {
   1397     DWORD result;
   1398 
   1399     Py_BEGIN_ALLOW_THREADS
   1400     result = WaitForSingleObject(handle, milliseconds);
   1401     Py_END_ALLOW_THREADS
   1402 
   1403     if (result == WAIT_FAILED) {
   1404         PyErr_SetFromWindowsErr(GetLastError());
   1405         return -1;
   1406     }
   1407 
   1408     return result;
   1409 }
   1410 
   1411 /*[clinic input]
   1412 _winapi.WriteFile
   1413 
   1414     handle: HANDLE
   1415     buffer: object
   1416     overlapped as use_overlapped: int(c_default='0') = False
   1417 [clinic start generated code]*/
   1418 
   1419 static PyObject *
   1420 _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
   1421                        int use_overlapped)
   1422 /*[clinic end generated code: output=2ca80f6bf3fa92e3 input=51846a5af52053fd]*/
   1423 {
   1424     Py_buffer _buf, *buf;
   1425     DWORD len, written;
   1426     BOOL ret;
   1427     DWORD err;
   1428     OverlappedObject *overlapped = NULL;
   1429 
   1430     if (use_overlapped) {
   1431         overlapped = new_overlapped(handle);
   1432         if (!overlapped)
   1433             return NULL;
   1434         buf = &overlapped->write_buffer;
   1435     }
   1436     else
   1437         buf = &_buf;
   1438 
   1439     if (!PyArg_Parse(buffer, "y*", buf)) {
   1440         Py_XDECREF(overlapped);
   1441         return NULL;
   1442     }
   1443 
   1444     Py_BEGIN_ALLOW_THREADS
   1445     len = (DWORD)Py_MIN(buf->len, DWORD_MAX);
   1446     ret = WriteFile(handle, buf->buf, len, &written,
   1447                     overlapped ? &overlapped->overlapped : NULL);
   1448     Py_END_ALLOW_THREADS
   1449 
   1450     err = ret ? 0 : GetLastError();
   1451 
   1452     if (overlapped) {
   1453         if (!ret) {
   1454             if (err == ERROR_IO_PENDING)
   1455                 overlapped->pending = 1;
   1456             else {
   1457                 Py_DECREF(overlapped);
   1458                 return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
   1459             }
   1460         }
   1461         return Py_BuildValue("NI", (PyObject *) overlapped, err);
   1462     }
   1463 
   1464     PyBuffer_Release(buf);
   1465     if (!ret)
   1466         return PyErr_SetExcFromWindowsErr(PyExc_IOError, 0);
   1467     return Py_BuildValue("II", written, err);
   1468 }
   1469 
   1470 
   1471 static PyMethodDef winapi_functions[] = {
   1472     _WINAPI_CLOSEHANDLE_METHODDEF
   1473     _WINAPI_CONNECTNAMEDPIPE_METHODDEF
   1474     _WINAPI_CREATEFILE_METHODDEF
   1475     _WINAPI_CREATENAMEDPIPE_METHODDEF
   1476     _WINAPI_CREATEPIPE_METHODDEF
   1477     _WINAPI_CREATEPROCESS_METHODDEF
   1478     _WINAPI_CREATEJUNCTION_METHODDEF
   1479     _WINAPI_DUPLICATEHANDLE_METHODDEF
   1480     _WINAPI_EXITPROCESS_METHODDEF
   1481     _WINAPI_GETCURRENTPROCESS_METHODDEF
   1482     _WINAPI_GETEXITCODEPROCESS_METHODDEF
   1483     _WINAPI_GETLASTERROR_METHODDEF
   1484     _WINAPI_GETMODULEFILENAME_METHODDEF
   1485     _WINAPI_GETSTDHANDLE_METHODDEF
   1486     _WINAPI_GETVERSION_METHODDEF
   1487     _WINAPI_OPENPROCESS_METHODDEF
   1488     _WINAPI_PEEKNAMEDPIPE_METHODDEF
   1489     _WINAPI_READFILE_METHODDEF
   1490     _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF
   1491     _WINAPI_TERMINATEPROCESS_METHODDEF
   1492     _WINAPI_WAITNAMEDPIPE_METHODDEF
   1493     _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF
   1494     _WINAPI_WAITFORSINGLEOBJECT_METHODDEF
   1495     _WINAPI_WRITEFILE_METHODDEF
   1496     {NULL, NULL}
   1497 };
   1498 
   1499 static struct PyModuleDef winapi_module = {
   1500     PyModuleDef_HEAD_INIT,
   1501     "_winapi",
   1502     NULL,
   1503     -1,
   1504     winapi_functions,
   1505     NULL,
   1506     NULL,
   1507     NULL,
   1508     NULL
   1509 };
   1510 
   1511 #define WINAPI_CONSTANT(fmt, con) \
   1512     PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
   1513 
   1514 PyMODINIT_FUNC
   1515 PyInit__winapi(void)
   1516 {
   1517     PyObject *d;
   1518     PyObject *m;
   1519 
   1520     if (PyType_Ready(&OverlappedType) < 0)
   1521         return NULL;
   1522 
   1523     m = PyModule_Create(&winapi_module);
   1524     if (m == NULL)
   1525         return NULL;
   1526     d = PyModule_GetDict(m);
   1527 
   1528     PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType);
   1529 
   1530     /* constants */
   1531     WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
   1532     WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP);
   1533     WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS);
   1534     WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE);
   1535     WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
   1536     WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
   1537     WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
   1538     WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
   1539     WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
   1540     WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
   1541     WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
   1542     WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
   1543     WINAPI_CONSTANT(F_DWORD, ERROR_NO_DATA);
   1544     WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
   1545     WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
   1546     WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
   1547     WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
   1548     WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
   1549     WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE);
   1550     WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
   1551     WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ);
   1552     WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE);
   1553     WINAPI_CONSTANT(F_DWORD, GENERIC_READ);
   1554     WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE);
   1555     WINAPI_CONSTANT(F_DWORD, INFINITE);
   1556     WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
   1557     WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING);
   1558     WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
   1559     WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
   1560     WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
   1561     WINAPI_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE);
   1562     WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES);
   1563     WINAPI_CONSTANT(F_DWORD, PIPE_WAIT);
   1564     WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
   1565     WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE);
   1566     WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW);
   1567     WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES);
   1568     WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE);
   1569     WINAPI_CONSTANT(F_DWORD, STD_OUTPUT_HANDLE);
   1570     WINAPI_CONSTANT(F_DWORD, STD_ERROR_HANDLE);
   1571     WINAPI_CONSTANT(F_DWORD, STILL_ACTIVE);
   1572     WINAPI_CONSTANT(F_DWORD, SW_HIDE);
   1573     WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0);
   1574     WINAPI_CONSTANT(F_DWORD, WAIT_ABANDONED_0);
   1575     WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT);
   1576 
   1577     WINAPI_CONSTANT("i", NULL);
   1578 
   1579     return m;
   1580 }
   1581