(root)/
Python-3.12.0/
Modules/
_winapi.c
       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@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 https://www.python.org/2.4/license for licensing details. */
      36  
      37  #include "Python.h"
      38  #include "pycore_moduleobject.h"  // _PyModule_GetState()
      39  #include "structmember.h"         // PyMemberDef
      40  
      41  
      42  #ifndef WINDOWS_LEAN_AND_MEAN
      43  #define WINDOWS_LEAN_AND_MEAN
      44  #endif
      45  #include "windows.h"
      46  #include <winioctl.h>
      47  #include <crtdbg.h>
      48  #include "winreparse.h"
      49  
      50  #if defined(MS_WIN32) && !defined(MS_WIN64)
      51  #define HANDLE_TO_PYNUM(handle) \
      52      PyLong_FromUnsignedLong((unsigned long) handle)
      53  #define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLong(obj))
      54  #define F_POINTER "k"
      55  #define T_POINTER T_ULONG
      56  #else
      57  #define HANDLE_TO_PYNUM(handle) \
      58      PyLong_FromUnsignedLongLong((unsigned long long) handle)
      59  #define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLongLong(obj))
      60  #define F_POINTER "K"
      61  #define T_POINTER T_ULONGLONG
      62  #endif
      63  
      64  #define F_HANDLE F_POINTER
      65  #define F_DWORD "k"
      66  
      67  #define T_HANDLE T_POINTER
      68  
      69  // winbase.h limits the STARTF_* flags to the desktop API as of 10.0.19041.
      70  #ifndef STARTF_USESHOWWINDOW
      71  #define STARTF_USESHOWWINDOW 0x00000001
      72  #endif
      73  #ifndef STARTF_USESTDHANDLES
      74  #define STARTF_USESTDHANDLES 0x00000100
      75  #endif
      76  
      77  typedef struct {
      78      PyTypeObject *overlapped_type;
      79  } WinApiState;
      80  
      81  static inline WinApiState*
      82  winapi_get_state(PyObject *module)
      83  {
      84      void *state = _PyModule_GetState(module);
      85      assert(state != NULL);
      86      return (WinApiState *)state;
      87  }
      88  
      89  /*
      90   * A Python object wrapping an OVERLAPPED structure and other useful data
      91   * for overlapped I/O
      92   */
      93  
      94  typedef struct {
      95      PyObject_HEAD
      96      OVERLAPPED overlapped;
      97      /* For convenience, we store the file handle too */
      98      HANDLE handle;
      99      /* Whether there's I/O in flight */
     100      int pending;
     101      /* Whether I/O completed successfully */
     102      int completed;
     103      /* Buffer used for reading (optional) */
     104      PyObject *read_buffer;
     105      /* Buffer used for writing (optional) */
     106      Py_buffer write_buffer;
     107  } OverlappedObject;
     108  
     109  /*
     110  Note: tp_clear (overlapped_clear) is not implemented because it
     111  requires cancelling the IO operation if it's pending and the cancellation is
     112  quite complex and can fail (see: overlapped_dealloc).
     113  */
     114  static int
     115  overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg)
     116  {
     117      Py_VISIT(self->read_buffer);
     118      Py_VISIT(self->write_buffer.obj);
     119      Py_VISIT(Py_TYPE(self));
     120      return 0;
     121  }
     122  
     123  static void
     124  overlapped_dealloc(OverlappedObject *self)
     125  {
     126      DWORD bytes;
     127      int err = GetLastError();
     128  
     129      PyObject_GC_UnTrack(self);
     130      if (self->pending) {
     131          if (CancelIoEx(self->handle, &self->overlapped) &&
     132              GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE))
     133          {
     134              /* The operation is no longer pending -- nothing to do. */
     135          }
     136          else if (_Py_IsInterpreterFinalizing(PyInterpreterState_Get()))
     137          {
     138              /* The operation is still pending -- give a warning.  This
     139                 will probably only happen on Windows XP. */
     140              PyErr_SetString(PyExc_RuntimeError,
     141                              "I/O operations still in flight while destroying "
     142                              "Overlapped object, the process may crash");
     143              PyErr_WriteUnraisable(NULL);
     144          }
     145          else
     146          {
     147              /* The operation is still pending, but the process is
     148                 probably about to exit, so we need not worry too much
     149                 about memory leaks.  Leaking self prevents a potential
     150                 crash.  This can happen when a daemon thread is cleaned
     151                 up at exit -- see #19565.  We only expect to get here
     152                 on Windows XP. */
     153              CloseHandle(self->overlapped.hEvent);
     154              SetLastError(err);
     155              return;
     156          }
     157      }
     158  
     159      CloseHandle(self->overlapped.hEvent);
     160      SetLastError(err);
     161      if (self->write_buffer.obj)
     162          PyBuffer_Release(&self->write_buffer);
     163      Py_CLEAR(self->read_buffer);
     164      PyTypeObject *tp = Py_TYPE(self);
     165      tp->tp_free(self);
     166      Py_DECREF(tp);
     167  }
     168  
     169  /*[clinic input]
     170  module _winapi
     171  class _winapi.Overlapped "OverlappedObject *" "&OverlappedType"
     172  [clinic start generated code]*/
     173  /*[clinic end generated code: output=da39a3ee5e6b4b0d input=c13d3f5fd1dabb84]*/
     174  
     175  /*[python input]
     176  def create_converter(type_, format_unit):
     177      name = type_ + '_converter'
     178      # registered upon creation by CConverter's metaclass
     179      type(name, (CConverter,), {'type': type_, 'format_unit': format_unit})
     180  
     181  # format unit differs between platforms for these
     182  create_converter('HANDLE', '" F_HANDLE "')
     183  create_converter('HMODULE', '" F_HANDLE "')
     184  create_converter('LPSECURITY_ATTRIBUTES', '" F_POINTER "')
     185  create_converter('LPCVOID', '" F_POINTER "')
     186  
     187  create_converter('BOOL', 'i') # F_BOOL used previously (always 'i')
     188  create_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter)
     189  create_converter('LPCTSTR', 's')
     190  create_converter('UINT', 'I') # F_UINT used previously (always 'I')
     191  
     192  class LPCWSTR_converter(Py_UNICODE_converter):
     193      type = 'LPCWSTR'
     194  
     195  class HANDLE_return_converter(CReturnConverter):
     196      type = 'HANDLE'
     197  
     198      def render(self, function, data):
     199          self.declare(data)
     200          self.err_occurred_if("_return_value == INVALID_HANDLE_VALUE", data)
     201          data.return_conversion.append(
     202              'if (_return_value == NULL) {\n    Py_RETURN_NONE;\n}\n')
     203          data.return_conversion.append(
     204              'return_value = HANDLE_TO_PYNUM(_return_value);\n')
     205  
     206  class DWORD_return_converter(CReturnConverter):
     207      type = 'DWORD'
     208  
     209      def render(self, function, data):
     210          self.declare(data)
     211          self.err_occurred_if("_return_value == PY_DWORD_MAX", data)
     212          data.return_conversion.append(
     213              'return_value = Py_BuildValue("k", _return_value);\n')
     214  
     215  class LPVOID_return_converter(CReturnConverter):
     216      type = 'LPVOID'
     217  
     218      def render(self, function, data):
     219          self.declare(data)
     220          self.err_occurred_if("_return_value == NULL", data)
     221          data.return_conversion.append(
     222              'return_value = HANDLE_TO_PYNUM(_return_value);\n')
     223  [python start generated code]*/
     224  /*[python end generated code: output=da39a3ee5e6b4b0d input=011ee0c3a2244bfe]*/
     225  
     226  #include "clinic/_winapi.c.h"
     227  
     228  /*[clinic input]
     229  _winapi.Overlapped.GetOverlappedResult
     230  
     231      wait: bool
     232      /
     233  [clinic start generated code]*/
     234  
     235  static PyObject *
     236  _winapi_Overlapped_GetOverlappedResult_impl(OverlappedObject *self, int wait)
     237  /*[clinic end generated code: output=bdd0c1ed6518cd03 input=194505ee8e0e3565]*/
     238  {
     239      BOOL res;
     240      DWORD transferred = 0;
     241      DWORD err;
     242  
     243      Py_BEGIN_ALLOW_THREADS
     244      res = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
     245                                wait != 0);
     246      Py_END_ALLOW_THREADS
     247  
     248      err = res ? ERROR_SUCCESS : GetLastError();
     249      switch (err) {
     250          case ERROR_SUCCESS:
     251          case ERROR_MORE_DATA:
     252          case ERROR_OPERATION_ABORTED:
     253              self->completed = 1;
     254              self->pending = 0;
     255              break;
     256          case ERROR_IO_INCOMPLETE:
     257              break;
     258          default:
     259              self->pending = 0;
     260              return PyErr_SetExcFromWindowsErr(PyExc_OSError, err);
     261      }
     262      if (self->completed && self->read_buffer != NULL) {
     263          assert(PyBytes_CheckExact(self->read_buffer));
     264          if (transferred != PyBytes_GET_SIZE(self->read_buffer) &&
     265              _PyBytes_Resize(&self->read_buffer, transferred))
     266              return NULL;
     267      }
     268      return Py_BuildValue("II", (unsigned) transferred, (unsigned) err);
     269  }
     270  
     271  /*[clinic input]
     272  _winapi.Overlapped.getbuffer
     273  [clinic start generated code]*/
     274  
     275  static PyObject *
     276  _winapi_Overlapped_getbuffer_impl(OverlappedObject *self)
     277  /*[clinic end generated code: output=95a3eceefae0f748 input=347fcfd56b4ceabd]*/
     278  {
     279      PyObject *res;
     280      if (!self->completed) {
     281          PyErr_SetString(PyExc_ValueError,
     282                          "can't get read buffer before GetOverlappedResult() "
     283                          "signals the operation completed");
     284          return NULL;
     285      }
     286      res = self->read_buffer ? self->read_buffer : Py_None;
     287      return Py_NewRef(res);
     288  }
     289  
     290  /*[clinic input]
     291  _winapi.Overlapped.cancel
     292  [clinic start generated code]*/
     293  
     294  static PyObject *
     295  _winapi_Overlapped_cancel_impl(OverlappedObject *self)
     296  /*[clinic end generated code: output=fcb9ab5df4ebdae5 input=cbf3da142290039f]*/
     297  {
     298      BOOL res = TRUE;
     299  
     300      if (self->pending) {
     301          Py_BEGIN_ALLOW_THREADS
     302          res = CancelIoEx(self->handle, &self->overlapped);
     303          Py_END_ALLOW_THREADS
     304      }
     305  
     306      /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
     307      if (!res && GetLastError() != ERROR_NOT_FOUND)
     308          return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
     309      self->pending = 0;
     310      Py_RETURN_NONE;
     311  }
     312  
     313  static PyMethodDef overlapped_methods[] = {
     314      _WINAPI_OVERLAPPED_GETOVERLAPPEDRESULT_METHODDEF
     315      _WINAPI_OVERLAPPED_GETBUFFER_METHODDEF
     316      _WINAPI_OVERLAPPED_CANCEL_METHODDEF
     317      {NULL}
     318  };
     319  
     320  static PyMemberDef overlapped_members[] = {
     321      {"event", T_HANDLE,
     322       offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
     323       READONLY, "overlapped event handle"},
     324      {NULL}
     325  };
     326  
     327  static PyType_Slot winapi_overlapped_type_slots[] = {
     328      {Py_tp_traverse, overlapped_traverse},
     329      {Py_tp_dealloc, overlapped_dealloc},
     330      {Py_tp_doc, "OVERLAPPED structure wrapper"},
     331      {Py_tp_methods, overlapped_methods},
     332      {Py_tp_members, overlapped_members},
     333      {0,0}
     334  };
     335  
     336  static PyType_Spec winapi_overlapped_type_spec = {
     337      .name = "_winapi.Overlapped",
     338      .basicsize = sizeof(OverlappedObject),
     339      .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
     340                Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
     341      .slots = winapi_overlapped_type_slots,
     342  };
     343  
     344  static OverlappedObject *
     345  new_overlapped(PyObject *module, HANDLE handle)
     346  {
     347      WinApiState *st = winapi_get_state(module);
     348      OverlappedObject *self = PyObject_GC_New(OverlappedObject, st->overlapped_type);
     349      if (!self)
     350          return NULL;
     351  
     352      self->handle = handle;
     353      self->read_buffer = NULL;
     354      self->pending = 0;
     355      self->completed = 0;
     356      memset(&self->overlapped, 0, sizeof(OVERLAPPED));
     357      memset(&self->write_buffer, 0, sizeof(Py_buffer));
     358      /* Manual reset, initially non-signalled */
     359      self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
     360  
     361      PyObject_GC_Track(self);
     362      return self;
     363  }
     364  
     365  /* -------------------------------------------------------------------- */
     366  /* windows API functions */
     367  
     368  /*[clinic input]
     369  _winapi.CloseHandle
     370  
     371      handle: HANDLE
     372      /
     373  
     374  Close handle.
     375  [clinic start generated code]*/
     376  
     377  static PyObject *
     378  _winapi_CloseHandle_impl(PyObject *module, HANDLE handle)
     379  /*[clinic end generated code: output=7ad37345f07bd782 input=7f0e4ac36e0352b8]*/
     380  {
     381      BOOL success;
     382  
     383      Py_BEGIN_ALLOW_THREADS
     384      success = CloseHandle(handle);
     385      Py_END_ALLOW_THREADS
     386  
     387      if (!success)
     388          return PyErr_SetFromWindowsErr(0);
     389  
     390      Py_RETURN_NONE;
     391  }
     392  
     393  /*[clinic input]
     394  _winapi.ConnectNamedPipe
     395  
     396      handle: HANDLE
     397      overlapped as use_overlapped: bool = False
     398  [clinic start generated code]*/
     399  
     400  static PyObject *
     401  _winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle,
     402                                int use_overlapped)
     403  /*[clinic end generated code: output=335a0e7086800671 input=a80e56e8bd370e31]*/
     404  {
     405      BOOL success;
     406      OverlappedObject *overlapped = NULL;
     407  
     408      if (use_overlapped) {
     409          overlapped = new_overlapped(module, handle);
     410          if (!overlapped)
     411              return NULL;
     412      }
     413  
     414      Py_BEGIN_ALLOW_THREADS
     415      success = ConnectNamedPipe(handle,
     416                                 overlapped ? &overlapped->overlapped : NULL);
     417      Py_END_ALLOW_THREADS
     418  
     419      if (overlapped) {
     420          int err = GetLastError();
     421          /* Overlapped ConnectNamedPipe never returns a success code */
     422          assert(success == 0);
     423          if (err == ERROR_IO_PENDING)
     424              overlapped->pending = 1;
     425          else if (err == ERROR_PIPE_CONNECTED)
     426              SetEvent(overlapped->overlapped.hEvent);
     427          else {
     428              Py_DECREF(overlapped);
     429              return PyErr_SetFromWindowsErr(err);
     430          }
     431          return (PyObject *) overlapped;
     432      }
     433      if (!success)
     434          return PyErr_SetFromWindowsErr(0);
     435  
     436      Py_RETURN_NONE;
     437  }
     438  
     439  /*[clinic input]
     440  _winapi.CreateFile -> HANDLE
     441  
     442      file_name: LPCTSTR
     443      desired_access: DWORD
     444      share_mode: DWORD
     445      security_attributes: LPSECURITY_ATTRIBUTES
     446      creation_disposition: DWORD
     447      flags_and_attributes: DWORD
     448      template_file: HANDLE
     449      /
     450  [clinic start generated code]*/
     451  
     452  static HANDLE
     453  _winapi_CreateFile_impl(PyObject *module, LPCTSTR file_name,
     454                          DWORD desired_access, DWORD share_mode,
     455                          LPSECURITY_ATTRIBUTES security_attributes,
     456                          DWORD creation_disposition,
     457                          DWORD flags_and_attributes, HANDLE template_file)
     458  /*[clinic end generated code: output=417ddcebfc5a3d53 input=6423c3e40372dbd5]*/
     459  {
     460      HANDLE handle;
     461  
     462      if (PySys_Audit("_winapi.CreateFile", "uIIII",
     463                      file_name, desired_access, share_mode,
     464                      creation_disposition, flags_and_attributes) < 0) {
     465          return INVALID_HANDLE_VALUE;
     466      }
     467  
     468      Py_BEGIN_ALLOW_THREADS
     469      handle = CreateFile(file_name, desired_access,
     470                          share_mode, security_attributes,
     471                          creation_disposition,
     472                          flags_and_attributes, template_file);
     473      Py_END_ALLOW_THREADS
     474  
     475      if (handle == INVALID_HANDLE_VALUE)
     476          PyErr_SetFromWindowsErr(0);
     477  
     478      return handle;
     479  }
     480  
     481  /*[clinic input]
     482  _winapi.CreateFileMapping -> HANDLE
     483  
     484      file_handle: HANDLE
     485      security_attributes: LPSECURITY_ATTRIBUTES
     486      protect: DWORD
     487      max_size_high: DWORD
     488      max_size_low: DWORD
     489      name: LPCWSTR
     490      /
     491  [clinic start generated code]*/
     492  
     493  static HANDLE
     494  _winapi_CreateFileMapping_impl(PyObject *module, HANDLE file_handle,
     495                                 LPSECURITY_ATTRIBUTES security_attributes,
     496                                 DWORD protect, DWORD max_size_high,
     497                                 DWORD max_size_low, LPCWSTR name)
     498  /*[clinic end generated code: output=6c0a4d5cf7f6fcc6 input=3dc5cf762a74dee8]*/
     499  {
     500      HANDLE handle;
     501  
     502      Py_BEGIN_ALLOW_THREADS
     503      handle = CreateFileMappingW(file_handle, security_attributes,
     504                                  protect, max_size_high, max_size_low,
     505                                  name);
     506      Py_END_ALLOW_THREADS
     507  
     508      if (handle == NULL) {
     509          PyObject *temp = PyUnicode_FromWideChar(name, -1);
     510          PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, temp);
     511          Py_XDECREF(temp);
     512          handle = INVALID_HANDLE_VALUE;
     513      }
     514  
     515      return handle;
     516  }
     517  
     518  /*[clinic input]
     519  _winapi.CreateJunction
     520  
     521      src_path: LPCWSTR
     522      dst_path: LPCWSTR
     523      /
     524  [clinic start generated code]*/
     525  
     526  static PyObject *
     527  _winapi_CreateJunction_impl(PyObject *module, LPCWSTR src_path,
     528                              LPCWSTR dst_path)
     529  /*[clinic end generated code: output=44b3f5e9bbcc4271 input=963d29b44b9384a7]*/
     530  {
     531      /* Privilege adjustment */
     532      HANDLE token = NULL;
     533      TOKEN_PRIVILEGES tp;
     534  
     535      /* Reparse data buffer */
     536      const USHORT prefix_len = 4;
     537      USHORT print_len = 0;
     538      USHORT rdb_size = 0;
     539      _Py_PREPARSE_DATA_BUFFER rdb = NULL;
     540  
     541      /* Junction point creation */
     542      HANDLE junction = NULL;
     543      DWORD ret = 0;
     544  
     545      if (src_path == NULL || dst_path == NULL)
     546          return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
     547  
     548      if (wcsncmp(src_path, L"\\??\\", prefix_len) == 0)
     549          return PyErr_SetFromWindowsErr(ERROR_INVALID_PARAMETER);
     550  
     551      if (PySys_Audit("_winapi.CreateJunction", "uu", src_path, dst_path) < 0) {
     552          return NULL;
     553      }
     554  
     555      /* Adjust privileges to allow rewriting directory entry as a
     556         junction point. */
     557      if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
     558          goto cleanup;
     559  
     560      if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid))
     561          goto cleanup;
     562  
     563      tp.PrivilegeCount = 1;
     564      tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
     565      if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
     566                                 NULL, NULL))
     567          goto cleanup;
     568  
     569      if (GetFileAttributesW(src_path) == INVALID_FILE_ATTRIBUTES)
     570          goto cleanup;
     571  
     572      /* Store the absolute link target path length in print_len. */
     573      print_len = (USHORT)GetFullPathNameW(src_path, 0, NULL, NULL);
     574      if (print_len == 0)
     575          goto cleanup;
     576  
     577      /* NUL terminator should not be part of print_len. */
     578      --print_len;
     579  
     580      /* REPARSE_DATA_BUFFER usage is heavily under-documented, especially for
     581         junction points. Here's what I've learned along the way:
     582         - A junction point has two components: a print name and a substitute
     583           name. They both describe the link target, but the substitute name is
     584           the physical target and the print name is shown in directory listings.
     585         - The print name must be a native name, prefixed with "\??\".
     586         - Both names are stored after each other in the same buffer (the
     587           PathBuffer) and both must be NUL-terminated.
     588         - There are four members defining their respective offset and length
     589           inside PathBuffer: SubstituteNameOffset, SubstituteNameLength,
     590           PrintNameOffset and PrintNameLength.
     591         - The total size we need to allocate for the REPARSE_DATA_BUFFER, thus,
     592           is the sum of:
     593           - the fixed header size (REPARSE_DATA_BUFFER_HEADER_SIZE)
     594           - the size of the MountPointReparseBuffer member without the PathBuffer
     595           - the size of the prefix ("\??\") in bytes
     596           - the size of the print name in bytes
     597           - the size of the substitute name in bytes
     598           - the size of two NUL terminators in bytes */
     599      rdb_size = _Py_REPARSE_DATA_BUFFER_HEADER_SIZE +
     600          sizeof(rdb->MountPointReparseBuffer) -
     601          sizeof(rdb->MountPointReparseBuffer.PathBuffer) +
     602          /* Two +1's for NUL terminators. */
     603          (prefix_len + print_len + 1 + print_len + 1) * sizeof(WCHAR);
     604      rdb = (_Py_PREPARSE_DATA_BUFFER)PyMem_RawCalloc(1, rdb_size);
     605      if (rdb == NULL)
     606          goto cleanup;
     607  
     608      rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
     609      rdb->ReparseDataLength = rdb_size - _Py_REPARSE_DATA_BUFFER_HEADER_SIZE;
     610      rdb->MountPointReparseBuffer.SubstituteNameOffset = 0;
     611      rdb->MountPointReparseBuffer.SubstituteNameLength =
     612          (prefix_len + print_len) * sizeof(WCHAR);
     613      rdb->MountPointReparseBuffer.PrintNameOffset =
     614          rdb->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
     615      rdb->MountPointReparseBuffer.PrintNameLength = print_len * sizeof(WCHAR);
     616  
     617      /* Store the full native path of link target at the substitute name
     618         offset (0). */
     619      wcscpy(rdb->MountPointReparseBuffer.PathBuffer, L"\\??\\");
     620      if (GetFullPathNameW(src_path, print_len + 1,
     621                           rdb->MountPointReparseBuffer.PathBuffer + prefix_len,
     622                           NULL) == 0)
     623          goto cleanup;
     624  
     625      /* Copy everything but the native prefix to the print name offset. */
     626      wcscpy(rdb->MountPointReparseBuffer.PathBuffer +
     627               prefix_len + print_len + 1,
     628               rdb->MountPointReparseBuffer.PathBuffer + prefix_len);
     629  
     630      /* Create a directory for the junction point. */
     631      if (!CreateDirectoryW(dst_path, NULL))
     632          goto cleanup;
     633  
     634      junction = CreateFileW(dst_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
     635          OPEN_EXISTING,
     636          FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
     637      if (junction == INVALID_HANDLE_VALUE)
     638          goto cleanup;
     639  
     640      /* Make the directory entry a junction point. */
     641      if (!DeviceIoControl(junction, FSCTL_SET_REPARSE_POINT, rdb, rdb_size,
     642                           NULL, 0, &ret, NULL))
     643          goto cleanup;
     644  
     645  cleanup:
     646      ret = GetLastError();
     647  
     648      if (token != NULL)
     649          CloseHandle(token);
     650      if (junction != NULL)
     651          CloseHandle(junction);
     652      PyMem_RawFree(rdb);
     653  
     654      if (ret != 0)
     655          return PyErr_SetFromWindowsErr(ret);
     656  
     657      Py_RETURN_NONE;
     658  }
     659  
     660  /*[clinic input]
     661  _winapi.CreateNamedPipe -> HANDLE
     662  
     663      name: LPCTSTR
     664      open_mode: DWORD
     665      pipe_mode: DWORD
     666      max_instances: DWORD
     667      out_buffer_size: DWORD
     668      in_buffer_size: DWORD
     669      default_timeout: DWORD
     670      security_attributes: LPSECURITY_ATTRIBUTES
     671      /
     672  [clinic start generated code]*/
     673  
     674  static HANDLE
     675  _winapi_CreateNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD open_mode,
     676                               DWORD pipe_mode, DWORD max_instances,
     677                               DWORD out_buffer_size, DWORD in_buffer_size,
     678                               DWORD default_timeout,
     679                               LPSECURITY_ATTRIBUTES security_attributes)
     680  /*[clinic end generated code: output=80f8c07346a94fbc input=5a73530b84d8bc37]*/
     681  {
     682      HANDLE handle;
     683  
     684      if (PySys_Audit("_winapi.CreateNamedPipe", "uII",
     685                      name, open_mode, pipe_mode) < 0) {
     686          return INVALID_HANDLE_VALUE;
     687      }
     688  
     689      Py_BEGIN_ALLOW_THREADS
     690      handle = CreateNamedPipe(name, open_mode, pipe_mode,
     691                               max_instances, out_buffer_size,
     692                               in_buffer_size, default_timeout,
     693                               security_attributes);
     694      Py_END_ALLOW_THREADS
     695  
     696      if (handle == INVALID_HANDLE_VALUE)
     697          PyErr_SetFromWindowsErr(0);
     698  
     699      return handle;
     700  }
     701  
     702  /*[clinic input]
     703  _winapi.CreatePipe
     704  
     705      pipe_attrs: object
     706          Ignored internally, can be None.
     707      size: DWORD
     708      /
     709  
     710  Create an anonymous pipe.
     711  
     712  Returns a 2-tuple of handles, to the read and write ends of the pipe.
     713  [clinic start generated code]*/
     714  
     715  static PyObject *
     716  _winapi_CreatePipe_impl(PyObject *module, PyObject *pipe_attrs, DWORD size)
     717  /*[clinic end generated code: output=1c4411d8699f0925 input=c4f2cfa56ef68d90]*/
     718  {
     719      HANDLE read_pipe;
     720      HANDLE write_pipe;
     721      BOOL result;
     722  
     723      if (PySys_Audit("_winapi.CreatePipe", NULL) < 0) {
     724          return NULL;
     725      }
     726  
     727      Py_BEGIN_ALLOW_THREADS
     728      result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
     729      Py_END_ALLOW_THREADS
     730  
     731      if (! result)
     732          return PyErr_SetFromWindowsErr(GetLastError());
     733  
     734      return Py_BuildValue(
     735          "NN", HANDLE_TO_PYNUM(read_pipe), HANDLE_TO_PYNUM(write_pipe));
     736  }
     737  
     738  /* helpers for createprocess */
     739  
     740  static unsigned long
     741  getulong(PyObject* obj, const char* name)
     742  {
     743      PyObject* value;
     744      unsigned long ret;
     745  
     746      value = PyObject_GetAttrString(obj, name);
     747      if (! value) {
     748          PyErr_Clear(); /* FIXME: propagate error? */
     749          return 0;
     750      }
     751      ret = PyLong_AsUnsignedLong(value);
     752      Py_DECREF(value);
     753      return ret;
     754  }
     755  
     756  static HANDLE
     757  gethandle(PyObject* obj, const char* name)
     758  {
     759      PyObject* value;
     760      HANDLE ret;
     761  
     762      value = PyObject_GetAttrString(obj, name);
     763      if (! value) {
     764          PyErr_Clear(); /* FIXME: propagate error? */
     765          return NULL;
     766      }
     767      if (value == Py_None)
     768          ret = NULL;
     769      else
     770          ret = PYNUM_TO_HANDLE(value);
     771      Py_DECREF(value);
     772      return ret;
     773  }
     774  
     775  static wchar_t *
     776  getenvironment(PyObject* environment)
     777  {
     778      Py_ssize_t i, envsize, totalsize;
     779      wchar_t *buffer = NULL, *p, *end;
     780      PyObject *keys, *values;
     781  
     782      /* convert environment dictionary to windows environment string */
     783      if (! PyMapping_Check(environment)) {
     784          PyErr_SetString(
     785              PyExc_TypeError, "environment must be dictionary or None");
     786          return NULL;
     787      }
     788  
     789      keys = PyMapping_Keys(environment);
     790      if (!keys) {
     791          return NULL;
     792      }
     793      values = PyMapping_Values(environment);
     794      if (!values) {
     795          goto error;
     796      }
     797  
     798      envsize = PyList_GET_SIZE(keys);
     799  
     800      if (envsize == 0) {
     801          // A environment block must be terminated by two null characters --
     802          // one for the last string and one for the block.
     803          buffer = PyMem_Calloc(2, sizeof(wchar_t));
     804          if (!buffer) {
     805              PyErr_NoMemory();
     806          }
     807          goto cleanup;
     808      }
     809  
     810      if (PyList_GET_SIZE(values) != envsize) {
     811          PyErr_SetString(PyExc_RuntimeError,
     812              "environment changed size during iteration");
     813          goto error;
     814      }
     815  
     816      totalsize = 1; /* trailing null character */
     817      for (i = 0; i < envsize; i++) {
     818          PyObject* key = PyList_GET_ITEM(keys, i);
     819          PyObject* value = PyList_GET_ITEM(values, i);
     820          Py_ssize_t size;
     821  
     822          if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
     823              PyErr_SetString(PyExc_TypeError,
     824                  "environment can only contain strings");
     825              goto error;
     826          }
     827          if (PyUnicode_FindChar(key, '\0', 0, PyUnicode_GET_LENGTH(key), 1) != -1 ||
     828              PyUnicode_FindChar(value, '\0', 0, PyUnicode_GET_LENGTH(value), 1) != -1)
     829          {
     830              PyErr_SetString(PyExc_ValueError, "embedded null character");
     831              goto error;
     832          }
     833          /* Search from index 1 because on Windows starting '=' is allowed for
     834             defining hidden environment variables. */
     835          if (PyUnicode_GET_LENGTH(key) == 0 ||
     836              PyUnicode_FindChar(key, '=', 1, PyUnicode_GET_LENGTH(key), 1) != -1)
     837          {
     838              PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
     839              goto error;
     840          }
     841  
     842          size = PyUnicode_AsWideChar(key, NULL, 0);
     843          assert(size > 1);
     844          if (totalsize > PY_SSIZE_T_MAX - size) {
     845              PyErr_SetString(PyExc_OverflowError, "environment too long");
     846              goto error;
     847          }
     848          totalsize += size;    /* including '=' */
     849  
     850          size = PyUnicode_AsWideChar(value, NULL, 0);
     851          assert(size > 0);
     852          if (totalsize > PY_SSIZE_T_MAX - size) {
     853              PyErr_SetString(PyExc_OverflowError, "environment too long");
     854              goto error;
     855          }
     856          totalsize += size;  /* including trailing '\0' */
     857      }
     858  
     859      buffer = PyMem_NEW(wchar_t, totalsize);
     860      if (! buffer) {
     861          PyErr_NoMemory();
     862          goto error;
     863      }
     864      p = buffer;
     865      end = buffer + totalsize;
     866  
     867      for (i = 0; i < envsize; i++) {
     868          PyObject* key = PyList_GET_ITEM(keys, i);
     869          PyObject* value = PyList_GET_ITEM(values, i);
     870          Py_ssize_t size = PyUnicode_AsWideChar(key, p, end - p);
     871          assert(1 <= size && size < end - p);
     872          p += size;
     873          *p++ = L'=';
     874          size = PyUnicode_AsWideChar(value, p, end - p);
     875          assert(0 <= size && size < end - p);
     876          p += size + 1;
     877      }
     878  
     879      /* add trailing null character */
     880      *p++ = L'\0';
     881      assert(p == end);
     882  
     883  cleanup:
     884  error:
     885      Py_XDECREF(keys);
     886      Py_XDECREF(values);
     887      return buffer;
     888  }
     889  
     890  static LPHANDLE
     891  gethandlelist(PyObject *mapping, const char *name, Py_ssize_t *size)
     892  {
     893      LPHANDLE ret = NULL;
     894      PyObject *value_fast = NULL;
     895      PyObject *value;
     896      Py_ssize_t i;
     897  
     898      value = PyMapping_GetItemString(mapping, name);
     899      if (!value) {
     900          PyErr_Clear();
     901          return NULL;
     902      }
     903  
     904      if (value == Py_None) {
     905          goto cleanup;
     906      }
     907  
     908      value_fast = PySequence_Fast(value, "handle_list must be a sequence or None");
     909      if (value_fast == NULL)
     910          goto cleanup;
     911  
     912      *size = PySequence_Fast_GET_SIZE(value_fast) * sizeof(HANDLE);
     913  
     914      /* Passing an empty array causes CreateProcess to fail so just don't set it */
     915      if (*size == 0) {
     916          goto cleanup;
     917      }
     918  
     919      ret = PyMem_Malloc(*size);
     920      if (ret == NULL)
     921          goto cleanup;
     922  
     923      for (i = 0; i < PySequence_Fast_GET_SIZE(value_fast); i++) {
     924          ret[i] = PYNUM_TO_HANDLE(PySequence_Fast_GET_ITEM(value_fast, i));
     925          if (ret[i] == (HANDLE)-1 && PyErr_Occurred()) {
     926              PyMem_Free(ret);
     927              ret = NULL;
     928              goto cleanup;
     929          }
     930      }
     931  
     932  cleanup:
     933      Py_DECREF(value);
     934      Py_XDECREF(value_fast);
     935      return ret;
     936  }
     937  
     938  typedef struct {
     939      LPPROC_THREAD_ATTRIBUTE_LIST attribute_list;
     940      LPHANDLE handle_list;
     941  } AttributeList;
     942  
     943  static void
     944  freeattributelist(AttributeList *attribute_list)
     945  {
     946      if (attribute_list->attribute_list != NULL) {
     947          DeleteProcThreadAttributeList(attribute_list->attribute_list);
     948          PyMem_Free(attribute_list->attribute_list);
     949      }
     950  
     951      PyMem_Free(attribute_list->handle_list);
     952  
     953      memset(attribute_list, 0, sizeof(*attribute_list));
     954  }
     955  
     956  static int
     957  getattributelist(PyObject *obj, const char *name, AttributeList *attribute_list)
     958  {
     959      int ret = 0;
     960      DWORD err;
     961      BOOL result;
     962      PyObject *value;
     963      Py_ssize_t handle_list_size;
     964      DWORD attribute_count = 0;
     965      SIZE_T attribute_list_size = 0;
     966  
     967      value = PyObject_GetAttrString(obj, name);
     968      if (!value) {
     969          PyErr_Clear(); /* FIXME: propagate error? */
     970          return 0;
     971      }
     972  
     973      if (value == Py_None) {
     974          ret = 0;
     975          goto cleanup;
     976      }
     977  
     978      if (!PyMapping_Check(value)) {
     979          ret = -1;
     980          PyErr_Format(PyExc_TypeError, "%s must be a mapping or None", name);
     981          goto cleanup;
     982      }
     983  
     984      attribute_list->handle_list = gethandlelist(value, "handle_list", &handle_list_size);
     985      if (attribute_list->handle_list == NULL && PyErr_Occurred()) {
     986          ret = -1;
     987          goto cleanup;
     988      }
     989  
     990      if (attribute_list->handle_list != NULL)
     991          ++attribute_count;
     992  
     993      /* Get how many bytes we need for the attribute list */
     994      result = InitializeProcThreadAttributeList(NULL, attribute_count, 0, &attribute_list_size);
     995      if (result || GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
     996          ret = -1;
     997          PyErr_SetFromWindowsErr(GetLastError());
     998          goto cleanup;
     999      }
    1000  
    1001      attribute_list->attribute_list = PyMem_Malloc(attribute_list_size);
    1002      if (attribute_list->attribute_list == NULL) {
    1003          ret = -1;
    1004          goto cleanup;
    1005      }
    1006  
    1007      result = InitializeProcThreadAttributeList(
    1008          attribute_list->attribute_list,
    1009          attribute_count,
    1010          0,
    1011          &attribute_list_size);
    1012      if (!result) {
    1013          err = GetLastError();
    1014  
    1015          /* So that we won't call DeleteProcThreadAttributeList */
    1016          PyMem_Free(attribute_list->attribute_list);
    1017          attribute_list->attribute_list = NULL;
    1018  
    1019          ret = -1;
    1020          PyErr_SetFromWindowsErr(err);
    1021          goto cleanup;
    1022      }
    1023  
    1024      if (attribute_list->handle_list != NULL) {
    1025          result = UpdateProcThreadAttribute(
    1026              attribute_list->attribute_list,
    1027              0,
    1028              PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
    1029              attribute_list->handle_list,
    1030              handle_list_size,
    1031              NULL,
    1032              NULL);
    1033          if (!result) {
    1034              ret = -1;
    1035              PyErr_SetFromWindowsErr(GetLastError());
    1036              goto cleanup;
    1037          }
    1038      }
    1039  
    1040  cleanup:
    1041      Py_DECREF(value);
    1042  
    1043      if (ret < 0)
    1044          freeattributelist(attribute_list);
    1045  
    1046      return ret;
    1047  }
    1048  
    1049  /*[clinic input]
    1050  _winapi.CreateProcess
    1051  
    1052      application_name: Py_UNICODE(accept={str, NoneType})
    1053      command_line: object
    1054          Can be str or None
    1055      proc_attrs: object
    1056          Ignored internally, can be None.
    1057      thread_attrs: object
    1058          Ignored internally, can be None.
    1059      inherit_handles: BOOL
    1060      creation_flags: DWORD
    1061      env_mapping: object
    1062      current_directory: Py_UNICODE(accept={str, NoneType})
    1063      startup_info: object
    1064      /
    1065  
    1066  Create a new process and its primary thread.
    1067  
    1068  The return value is a tuple of the process handle, thread handle,
    1069  process ID, and thread ID.
    1070  [clinic start generated code]*/
    1071  
    1072  static PyObject *
    1073  _winapi_CreateProcess_impl(PyObject *module,
    1074                             const Py_UNICODE *application_name,
    1075                             PyObject *command_line, PyObject *proc_attrs,
    1076                             PyObject *thread_attrs, BOOL inherit_handles,
    1077                             DWORD creation_flags, PyObject *env_mapping,
    1078                             const Py_UNICODE *current_directory,
    1079                             PyObject *startup_info)
    1080  /*[clinic end generated code: output=9b2423a609230132 input=42ac293eaea03fc4]*/
    1081  {
    1082      PyObject *ret = NULL;
    1083      BOOL result;
    1084      PROCESS_INFORMATION pi;
    1085      STARTUPINFOEXW si;
    1086      wchar_t *wenvironment = NULL;
    1087      wchar_t *command_line_copy = NULL;
    1088      AttributeList attribute_list = {0};
    1089  
    1090      if (PySys_Audit("_winapi.CreateProcess", "uuu", application_name,
    1091                      command_line, current_directory) < 0) {
    1092          return NULL;
    1093      }
    1094  
    1095      ZeroMemory(&si, sizeof(si));
    1096      si.StartupInfo.cb = sizeof(si);
    1097  
    1098      /* note: we only support a small subset of all SI attributes */
    1099      si.StartupInfo.dwFlags = getulong(startup_info, "dwFlags");
    1100      si.StartupInfo.wShowWindow = (WORD)getulong(startup_info, "wShowWindow");
    1101      si.StartupInfo.hStdInput = gethandle(startup_info, "hStdInput");
    1102      si.StartupInfo.hStdOutput = gethandle(startup_info, "hStdOutput");
    1103      si.StartupInfo.hStdError = gethandle(startup_info, "hStdError");
    1104      if (PyErr_Occurred())
    1105          goto cleanup;
    1106  
    1107      if (env_mapping != Py_None) {
    1108          wenvironment = getenvironment(env_mapping);
    1109          if (wenvironment == NULL) {
    1110              goto cleanup;
    1111          }
    1112      }
    1113  
    1114      if (getattributelist(startup_info, "lpAttributeList", &attribute_list) < 0)
    1115          goto cleanup;
    1116  
    1117      si.lpAttributeList = attribute_list.attribute_list;
    1118      if (PyUnicode_Check(command_line)) {
    1119          command_line_copy = PyUnicode_AsWideCharString(command_line, NULL);
    1120          if (command_line_copy == NULL) {
    1121              goto cleanup;
    1122          }
    1123      }
    1124      else if (command_line != Py_None) {
    1125          PyErr_Format(PyExc_TypeError,
    1126                       "CreateProcess() argument 2 must be str or None, not %s",
    1127                       Py_TYPE(command_line)->tp_name);
    1128          goto cleanup;
    1129      }
    1130  
    1131  
    1132      Py_BEGIN_ALLOW_THREADS
    1133      result = CreateProcessW(application_name,
    1134                             command_line_copy,
    1135                             NULL,
    1136                             NULL,
    1137                             inherit_handles,
    1138                             creation_flags | EXTENDED_STARTUPINFO_PRESENT |
    1139                             CREATE_UNICODE_ENVIRONMENT,
    1140                             wenvironment,
    1141                             current_directory,
    1142                             (LPSTARTUPINFOW)&si,
    1143                             &pi);
    1144      Py_END_ALLOW_THREADS
    1145  
    1146      if (!result) {
    1147          PyErr_SetFromWindowsErr(GetLastError());
    1148          goto cleanup;
    1149      }
    1150  
    1151      ret = Py_BuildValue("NNkk",
    1152                          HANDLE_TO_PYNUM(pi.hProcess),
    1153                          HANDLE_TO_PYNUM(pi.hThread),
    1154                          pi.dwProcessId,
    1155                          pi.dwThreadId);
    1156  
    1157  cleanup:
    1158      PyMem_Free(command_line_copy);
    1159      PyMem_Free(wenvironment);
    1160      freeattributelist(&attribute_list);
    1161  
    1162      return ret;
    1163  }
    1164  
    1165  /*[clinic input]
    1166  _winapi.DuplicateHandle -> HANDLE
    1167  
    1168      source_process_handle: HANDLE
    1169      source_handle: HANDLE
    1170      target_process_handle: HANDLE
    1171      desired_access: DWORD
    1172      inherit_handle: BOOL
    1173      options: DWORD = 0
    1174      /
    1175  
    1176  Return a duplicate handle object.
    1177  
    1178  The duplicate handle refers to the same object as the original
    1179  handle. Therefore, any changes to the object are reflected
    1180  through both handles.
    1181  [clinic start generated code]*/
    1182  
    1183  static HANDLE
    1184  _winapi_DuplicateHandle_impl(PyObject *module, HANDLE source_process_handle,
    1185                               HANDLE source_handle,
    1186                               HANDLE target_process_handle,
    1187                               DWORD desired_access, BOOL inherit_handle,
    1188                               DWORD options)
    1189  /*[clinic end generated code: output=ad9711397b5dcd4e input=b933e3f2356a8c12]*/
    1190  {
    1191      HANDLE target_handle;
    1192      BOOL result;
    1193  
    1194      Py_BEGIN_ALLOW_THREADS
    1195      result = DuplicateHandle(
    1196          source_process_handle,
    1197          source_handle,
    1198          target_process_handle,
    1199          &target_handle,
    1200          desired_access,
    1201          inherit_handle,
    1202          options
    1203      );
    1204      Py_END_ALLOW_THREADS
    1205  
    1206      if (! result) {
    1207          PyErr_SetFromWindowsErr(GetLastError());
    1208          return INVALID_HANDLE_VALUE;
    1209      }
    1210  
    1211      return target_handle;
    1212  }
    1213  
    1214  /*[clinic input]
    1215  _winapi.ExitProcess
    1216  
    1217      ExitCode: UINT
    1218      /
    1219  
    1220  [clinic start generated code]*/
    1221  
    1222  static PyObject *
    1223  _winapi_ExitProcess_impl(PyObject *module, UINT ExitCode)
    1224  /*[clinic end generated code: output=a387deb651175301 input=4f05466a9406c558]*/
    1225  {
    1226      #if defined(Py_DEBUG)
    1227  #ifdef MS_WINDOWS_DESKTOP
    1228          SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|
    1229                       SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
    1230  #endif
    1231          _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
    1232      #endif
    1233  
    1234      ExitProcess(ExitCode);
    1235  
    1236      return NULL;
    1237  }
    1238  
    1239  /*[clinic input]
    1240  _winapi.GetCurrentProcess -> HANDLE
    1241  
    1242  Return a handle object for the current process.
    1243  [clinic start generated code]*/
    1244  
    1245  static HANDLE
    1246  _winapi_GetCurrentProcess_impl(PyObject *module)
    1247  /*[clinic end generated code: output=ddeb4dd2ffadf344 input=b213403fd4b96b41]*/
    1248  {
    1249      return GetCurrentProcess();
    1250  }
    1251  
    1252  /*[clinic input]
    1253  _winapi.GetExitCodeProcess -> DWORD
    1254  
    1255      process: HANDLE
    1256      /
    1257  
    1258  Return the termination status of the specified process.
    1259  [clinic start generated code]*/
    1260  
    1261  static DWORD
    1262  _winapi_GetExitCodeProcess_impl(PyObject *module, HANDLE process)
    1263  /*[clinic end generated code: output=b4620bdf2bccf36b input=61b6bfc7dc2ee374]*/
    1264  {
    1265      DWORD exit_code;
    1266      BOOL result;
    1267  
    1268      result = GetExitCodeProcess(process, &exit_code);
    1269  
    1270      if (! result) {
    1271          PyErr_SetFromWindowsErr(GetLastError());
    1272          exit_code = PY_DWORD_MAX;
    1273      }
    1274  
    1275      return exit_code;
    1276  }
    1277  
    1278  /*[clinic input]
    1279  _winapi.GetLastError -> DWORD
    1280  [clinic start generated code]*/
    1281  
    1282  static DWORD
    1283  _winapi_GetLastError_impl(PyObject *module)
    1284  /*[clinic end generated code: output=8585b827cb1a92c5 input=62d47fb9bce038ba]*/
    1285  {
    1286      return GetLastError();
    1287  }
    1288  
    1289  /*[clinic input]
    1290  _winapi.GetModuleFileName
    1291  
    1292      module_handle: HMODULE
    1293      /
    1294  
    1295  Return the fully-qualified path for the file that contains module.
    1296  
    1297  The module must have been loaded by the current process.
    1298  
    1299  The module parameter should be a handle to the loaded module
    1300  whose path is being requested. If this parameter is 0,
    1301  GetModuleFileName retrieves the path of the executable file
    1302  of the current process.
    1303  [clinic start generated code]*/
    1304  
    1305  static PyObject *
    1306  _winapi_GetModuleFileName_impl(PyObject *module, HMODULE module_handle)
    1307  /*[clinic end generated code: output=85b4b728c5160306 input=6d66ff7deca5d11f]*/
    1308  {
    1309      BOOL result;
    1310      WCHAR filename[MAX_PATH];
    1311  
    1312      Py_BEGIN_ALLOW_THREADS
    1313      result = GetModuleFileNameW(module_handle, filename, MAX_PATH);
    1314      filename[MAX_PATH-1] = '\0';
    1315      Py_END_ALLOW_THREADS
    1316  
    1317      if (! result)
    1318          return PyErr_SetFromWindowsErr(GetLastError());
    1319  
    1320      return PyUnicode_FromWideChar(filename, wcslen(filename));
    1321  }
    1322  
    1323  /*[clinic input]
    1324  _winapi.GetStdHandle -> HANDLE
    1325  
    1326      std_handle: DWORD
    1327          One of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, or STD_ERROR_HANDLE.
    1328      /
    1329  
    1330  Return a handle to the specified standard device.
    1331  
    1332  The integer associated with the handle object is returned.
    1333  [clinic start generated code]*/
    1334  
    1335  static HANDLE
    1336  _winapi_GetStdHandle_impl(PyObject *module, DWORD std_handle)
    1337  /*[clinic end generated code: output=0e613001e73ab614 input=07016b06a2fc8826]*/
    1338  {
    1339      HANDLE handle;
    1340  
    1341      Py_BEGIN_ALLOW_THREADS
    1342      handle = GetStdHandle(std_handle);
    1343      Py_END_ALLOW_THREADS
    1344  
    1345      if (handle == INVALID_HANDLE_VALUE)
    1346          PyErr_SetFromWindowsErr(GetLastError());
    1347  
    1348      return handle;
    1349  }
    1350  
    1351  /*[clinic input]
    1352  _winapi.GetVersion -> long
    1353  
    1354  Return the version number of the current operating system.
    1355  [clinic start generated code]*/
    1356  
    1357  static long
    1358  _winapi_GetVersion_impl(PyObject *module)
    1359  /*[clinic end generated code: output=e41f0db5a3b82682 input=e21dff8d0baeded2]*/
    1360  /* Disable deprecation warnings about GetVersionEx as the result is
    1361     being passed straight through to the caller, who is responsible for
    1362     using it correctly. */
    1363  #pragma warning(push)
    1364  #pragma warning(disable:4996)
    1365  
    1366  {
    1367      return GetVersion();
    1368  }
    1369  
    1370  #pragma warning(pop)
    1371  
    1372  /*[clinic input]
    1373  _winapi.MapViewOfFile -> LPVOID
    1374  
    1375      file_map: HANDLE
    1376      desired_access: DWORD
    1377      file_offset_high: DWORD
    1378      file_offset_low: DWORD
    1379      number_bytes: size_t
    1380      /
    1381  [clinic start generated code]*/
    1382  
    1383  static LPVOID
    1384  _winapi_MapViewOfFile_impl(PyObject *module, HANDLE file_map,
    1385                             DWORD desired_access, DWORD file_offset_high,
    1386                             DWORD file_offset_low, size_t number_bytes)
    1387  /*[clinic end generated code: output=f23b1ee4823663e3 input=177471073be1a103]*/
    1388  {
    1389      LPVOID address;
    1390  
    1391      Py_BEGIN_ALLOW_THREADS
    1392      address = MapViewOfFile(file_map, desired_access, file_offset_high,
    1393                              file_offset_low, number_bytes);
    1394      Py_END_ALLOW_THREADS
    1395  
    1396      if (address == NULL)
    1397          PyErr_SetFromWindowsErr(0);
    1398  
    1399      return address;
    1400  }
    1401  
    1402  /*[clinic input]
    1403  _winapi.UnmapViewOfFile
    1404  
    1405      address: LPCVOID
    1406      /
    1407  [clinic start generated code]*/
    1408  
    1409  static PyObject *
    1410  _winapi_UnmapViewOfFile_impl(PyObject *module, LPCVOID address)
    1411  /*[clinic end generated code: output=4f7e18ac75d19744 input=8c4b6119ad9288a3]*/
    1412  {
    1413      BOOL success;
    1414  
    1415      Py_BEGIN_ALLOW_THREADS
    1416      success = UnmapViewOfFile(address);
    1417      Py_END_ALLOW_THREADS
    1418  
    1419      if (!success) {
    1420          return PyErr_SetFromWindowsErr(0);
    1421      }
    1422  
    1423      Py_RETURN_NONE;
    1424  }
    1425  
    1426  /*[clinic input]
    1427  _winapi.OpenFileMapping -> HANDLE
    1428  
    1429      desired_access: DWORD
    1430      inherit_handle: BOOL
    1431      name: LPCWSTR
    1432      /
    1433  [clinic start generated code]*/
    1434  
    1435  static HANDLE
    1436  _winapi_OpenFileMapping_impl(PyObject *module, DWORD desired_access,
    1437                               BOOL inherit_handle, LPCWSTR name)
    1438  /*[clinic end generated code: output=08cc44def1cb11f1 input=131f2a405359de7f]*/
    1439  {
    1440      HANDLE handle;
    1441  
    1442      Py_BEGIN_ALLOW_THREADS
    1443      handle = OpenFileMappingW(desired_access, inherit_handle, name);
    1444      Py_END_ALLOW_THREADS
    1445  
    1446      if (handle == NULL) {
    1447          PyObject *temp = PyUnicode_FromWideChar(name, -1);
    1448          PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 0, temp);
    1449          Py_XDECREF(temp);
    1450          handle = INVALID_HANDLE_VALUE;
    1451      }
    1452  
    1453      return handle;
    1454  }
    1455  
    1456  /*[clinic input]
    1457  _winapi.OpenProcess -> HANDLE
    1458  
    1459      desired_access: DWORD
    1460      inherit_handle: BOOL
    1461      process_id: DWORD
    1462      /
    1463  [clinic start generated code]*/
    1464  
    1465  static HANDLE
    1466  _winapi_OpenProcess_impl(PyObject *module, DWORD desired_access,
    1467                           BOOL inherit_handle, DWORD process_id)
    1468  /*[clinic end generated code: output=b42b6b81ea5a0fc3 input=ec98c4cf4ea2ec36]*/
    1469  {
    1470      HANDLE handle;
    1471  
    1472      if (PySys_Audit("_winapi.OpenProcess", "II",
    1473                      process_id, desired_access) < 0) {
    1474          return INVALID_HANDLE_VALUE;
    1475      }
    1476  
    1477      Py_BEGIN_ALLOW_THREADS
    1478      handle = OpenProcess(desired_access, inherit_handle, process_id);
    1479      Py_END_ALLOW_THREADS
    1480      if (handle == NULL) {
    1481          PyErr_SetFromWindowsErr(GetLastError());
    1482          handle = INVALID_HANDLE_VALUE;
    1483      }
    1484  
    1485      return handle;
    1486  }
    1487  
    1488  /*[clinic input]
    1489  _winapi.PeekNamedPipe
    1490  
    1491      handle: HANDLE
    1492      size: int = 0
    1493      /
    1494  [clinic start generated code]*/
    1495  
    1496  static PyObject *
    1497  _winapi_PeekNamedPipe_impl(PyObject *module, HANDLE handle, int size)
    1498  /*[clinic end generated code: output=d0c3e29e49d323dd input=c7aa53bfbce69d70]*/
    1499  {
    1500      PyObject *buf = NULL;
    1501      DWORD nread, navail, nleft;
    1502      BOOL ret;
    1503  
    1504      if (size < 0) {
    1505          PyErr_SetString(PyExc_ValueError, "negative size");
    1506          return NULL;
    1507      }
    1508  
    1509      if (size) {
    1510          buf = PyBytes_FromStringAndSize(NULL, size);
    1511          if (!buf)
    1512              return NULL;
    1513          Py_BEGIN_ALLOW_THREADS
    1514          ret = PeekNamedPipe(handle, PyBytes_AS_STRING(buf), size, &nread,
    1515                              &navail, &nleft);
    1516          Py_END_ALLOW_THREADS
    1517          if (!ret) {
    1518              Py_DECREF(buf);
    1519              return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
    1520          }
    1521          if (_PyBytes_Resize(&buf, nread))
    1522              return NULL;
    1523          return Py_BuildValue("NII", buf, navail, nleft);
    1524      }
    1525      else {
    1526          Py_BEGIN_ALLOW_THREADS
    1527          ret = PeekNamedPipe(handle, NULL, 0, NULL, &navail, &nleft);
    1528          Py_END_ALLOW_THREADS
    1529          if (!ret) {
    1530              return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
    1531          }
    1532          return Py_BuildValue("II", navail, nleft);
    1533      }
    1534  }
    1535  
    1536  /*[clinic input]
    1537  _winapi.LCMapStringEx
    1538  
    1539      locale: LPCWSTR
    1540      flags: DWORD
    1541      src: unicode
    1542  
    1543  [clinic start generated code]*/
    1544  
    1545  static PyObject *
    1546  _winapi_LCMapStringEx_impl(PyObject *module, LPCWSTR locale, DWORD flags,
    1547                             PyObject *src)
    1548  /*[clinic end generated code: output=b90e6b26e028ff0a input=3e3dcd9b8164012f]*/
    1549  {
    1550      if (flags & (LCMAP_SORTHANDLE | LCMAP_HASH | LCMAP_BYTEREV |
    1551                   LCMAP_SORTKEY)) {
    1552          return PyErr_Format(PyExc_ValueError, "unsupported flags");
    1553      }
    1554  
    1555      Py_ssize_t src_size;
    1556      wchar_t *src_ = PyUnicode_AsWideCharString(src, &src_size);
    1557      if (!src_) {
    1558          return NULL;
    1559      }
    1560      if (src_size > INT_MAX) {
    1561          PyMem_Free(src_);
    1562          PyErr_SetString(PyExc_OverflowError, "input string is too long");
    1563          return NULL;
    1564      }
    1565  
    1566      int dest_size = LCMapStringEx(locale, flags, src_, (int)src_size, NULL, 0,
    1567                                    NULL, NULL, 0);
    1568      if (dest_size <= 0) {
    1569          DWORD error = GetLastError();
    1570          PyMem_Free(src_);
    1571          return PyErr_SetFromWindowsErr(error);
    1572      }
    1573  
    1574      wchar_t* dest = PyMem_NEW(wchar_t, dest_size);
    1575      if (dest == NULL) {
    1576          PyMem_Free(src_);
    1577          return PyErr_NoMemory();
    1578      }
    1579  
    1580      int nmapped = LCMapStringEx(locale, flags, src_, (int)src_size, dest, dest_size,
    1581                                  NULL, NULL, 0);
    1582      if (nmapped <= 0) {
    1583          DWORD error = GetLastError();
    1584          PyMem_Free(src_);
    1585          PyMem_DEL(dest);
    1586          return PyErr_SetFromWindowsErr(error);
    1587      }
    1588  
    1589      PyMem_Free(src_);
    1590      PyObject *ret = PyUnicode_FromWideChar(dest, nmapped);
    1591      PyMem_DEL(dest);
    1592  
    1593      return ret;
    1594  }
    1595  
    1596  /*[clinic input]
    1597  _winapi.ReadFile
    1598  
    1599      handle: HANDLE
    1600      size: DWORD
    1601      overlapped as use_overlapped: bool = False
    1602  [clinic start generated code]*/
    1603  
    1604  static PyObject *
    1605  _winapi_ReadFile_impl(PyObject *module, HANDLE handle, DWORD size,
    1606                        int use_overlapped)
    1607  /*[clinic end generated code: output=d3d5b44a8201b944 input=4f82f8e909ad91ad]*/
    1608  {
    1609      DWORD nread;
    1610      PyObject *buf;
    1611      BOOL ret;
    1612      DWORD err;
    1613      OverlappedObject *overlapped = NULL;
    1614  
    1615      buf = PyBytes_FromStringAndSize(NULL, size);
    1616      if (!buf)
    1617          return NULL;
    1618      if (use_overlapped) {
    1619          overlapped = new_overlapped(module, handle);
    1620          if (!overlapped) {
    1621              Py_DECREF(buf);
    1622              return NULL;
    1623          }
    1624          /* Steals reference to buf */
    1625          overlapped->read_buffer = buf;
    1626      }
    1627  
    1628      Py_BEGIN_ALLOW_THREADS
    1629      ret = ReadFile(handle, PyBytes_AS_STRING(buf), size, &nread,
    1630                     overlapped ? &overlapped->overlapped : NULL);
    1631      Py_END_ALLOW_THREADS
    1632  
    1633      err = ret ? 0 : GetLastError();
    1634  
    1635      if (overlapped) {
    1636          if (!ret) {
    1637              if (err == ERROR_IO_PENDING)
    1638                  overlapped->pending = 1;
    1639              else if (err != ERROR_MORE_DATA) {
    1640                  Py_DECREF(overlapped);
    1641                  return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
    1642              }
    1643          }
    1644          return Py_BuildValue("NI", (PyObject *) overlapped, err);
    1645      }
    1646  
    1647      if (!ret && err != ERROR_MORE_DATA) {
    1648          Py_DECREF(buf);
    1649          return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
    1650      }
    1651      if (_PyBytes_Resize(&buf, nread))
    1652          return NULL;
    1653      return Py_BuildValue("NI", buf, err);
    1654  }
    1655  
    1656  /*[clinic input]
    1657  _winapi.SetNamedPipeHandleState
    1658  
    1659      named_pipe: HANDLE
    1660      mode: object
    1661      max_collection_count: object
    1662      collect_data_timeout: object
    1663      /
    1664  [clinic start generated code]*/
    1665  
    1666  static PyObject *
    1667  _winapi_SetNamedPipeHandleState_impl(PyObject *module, HANDLE named_pipe,
    1668                                       PyObject *mode,
    1669                                       PyObject *max_collection_count,
    1670                                       PyObject *collect_data_timeout)
    1671  /*[clinic end generated code: output=f2129d222cbfa095 input=9142d72163d0faa6]*/
    1672  {
    1673      PyObject *oArgs[3] = {mode, max_collection_count, collect_data_timeout};
    1674      DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL};
    1675      int i;
    1676      BOOL b;
    1677  
    1678      for (i = 0 ; i < 3 ; i++) {
    1679          if (oArgs[i] != Py_None) {
    1680              dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]);
    1681              if (PyErr_Occurred())
    1682                  return NULL;
    1683              pArgs[i] = &dwArgs[i];
    1684          }
    1685      }
    1686  
    1687      Py_BEGIN_ALLOW_THREADS
    1688      b = SetNamedPipeHandleState(named_pipe, pArgs[0], pArgs[1], pArgs[2]);
    1689      Py_END_ALLOW_THREADS
    1690  
    1691      if (!b)
    1692          return PyErr_SetFromWindowsErr(0);
    1693  
    1694      Py_RETURN_NONE;
    1695  }
    1696  
    1697  
    1698  /*[clinic input]
    1699  _winapi.TerminateProcess
    1700  
    1701      handle: HANDLE
    1702      exit_code: UINT
    1703      /
    1704  
    1705  Terminate the specified process and all of its threads.
    1706  [clinic start generated code]*/
    1707  
    1708  static PyObject *
    1709  _winapi_TerminateProcess_impl(PyObject *module, HANDLE handle,
    1710                                UINT exit_code)
    1711  /*[clinic end generated code: output=f4e99ac3f0b1f34a input=d6bc0aa1ee3bb4df]*/
    1712  {
    1713      BOOL result;
    1714  
    1715      if (PySys_Audit("_winapi.TerminateProcess", "nI",
    1716                      (Py_ssize_t)handle, exit_code) < 0) {
    1717          return NULL;
    1718      }
    1719  
    1720      result = TerminateProcess(handle, exit_code);
    1721  
    1722      if (! result)
    1723          return PyErr_SetFromWindowsErr(GetLastError());
    1724  
    1725      Py_RETURN_NONE;
    1726  }
    1727  
    1728  /*[clinic input]
    1729  _winapi.VirtualQuerySize -> size_t
    1730  
    1731      address: LPCVOID
    1732      /
    1733  [clinic start generated code]*/
    1734  
    1735  static size_t
    1736  _winapi_VirtualQuerySize_impl(PyObject *module, LPCVOID address)
    1737  /*[clinic end generated code: output=40c8e0ff5ec964df input=6b784a69755d0bb6]*/
    1738  {
    1739      SIZE_T size_of_buf;
    1740      MEMORY_BASIC_INFORMATION mem_basic_info;
    1741      SIZE_T region_size;
    1742  
    1743      Py_BEGIN_ALLOW_THREADS
    1744      size_of_buf = VirtualQuery(address, &mem_basic_info, sizeof(mem_basic_info));
    1745      Py_END_ALLOW_THREADS
    1746  
    1747      if (size_of_buf == 0)
    1748          PyErr_SetFromWindowsErr(0);
    1749  
    1750      region_size = mem_basic_info.RegionSize;
    1751      return region_size;
    1752  }
    1753  
    1754  /*[clinic input]
    1755  _winapi.WaitNamedPipe
    1756  
    1757      name: LPCTSTR
    1758      timeout: DWORD
    1759      /
    1760  [clinic start generated code]*/
    1761  
    1762  static PyObject *
    1763  _winapi_WaitNamedPipe_impl(PyObject *module, LPCTSTR name, DWORD timeout)
    1764  /*[clinic end generated code: output=c2866f4439b1fe38 input=36fc781291b1862c]*/
    1765  {
    1766      BOOL success;
    1767  
    1768      Py_BEGIN_ALLOW_THREADS
    1769      success = WaitNamedPipe(name, timeout);
    1770      Py_END_ALLOW_THREADS
    1771  
    1772      if (!success)
    1773          return PyErr_SetFromWindowsErr(0);
    1774  
    1775      Py_RETURN_NONE;
    1776  }
    1777  
    1778  /*[clinic input]
    1779  _winapi.WaitForMultipleObjects
    1780  
    1781      handle_seq: object
    1782      wait_flag: BOOL
    1783      milliseconds: DWORD(c_default='INFINITE') = _winapi.INFINITE
    1784      /
    1785  [clinic start generated code]*/
    1786  
    1787  static PyObject *
    1788  _winapi_WaitForMultipleObjects_impl(PyObject *module, PyObject *handle_seq,
    1789                                      BOOL wait_flag, DWORD milliseconds)
    1790  /*[clinic end generated code: output=295e3f00b8e45899 input=36f76ca057cd28a0]*/
    1791  {
    1792      DWORD result;
    1793      HANDLE handles[MAXIMUM_WAIT_OBJECTS];
    1794      HANDLE sigint_event = NULL;
    1795      Py_ssize_t nhandles, i;
    1796  
    1797      if (!PySequence_Check(handle_seq)) {
    1798          PyErr_Format(PyExc_TypeError,
    1799                       "sequence type expected, got '%s'",
    1800                       Py_TYPE(handle_seq)->tp_name);
    1801          return NULL;
    1802      }
    1803      nhandles = PySequence_Length(handle_seq);
    1804      if (nhandles == -1)
    1805          return NULL;
    1806      if (nhandles < 0 || nhandles > MAXIMUM_WAIT_OBJECTS - 1) {
    1807          PyErr_Format(PyExc_ValueError,
    1808                       "need at most %zd handles, got a sequence of length %zd",
    1809                       MAXIMUM_WAIT_OBJECTS - 1, nhandles);
    1810          return NULL;
    1811      }
    1812      for (i = 0; i < nhandles; i++) {
    1813          HANDLE h;
    1814          PyObject *v = PySequence_GetItem(handle_seq, i);
    1815          if (v == NULL)
    1816              return NULL;
    1817          if (!PyArg_Parse(v, F_HANDLE, &h)) {
    1818              Py_DECREF(v);
    1819              return NULL;
    1820          }
    1821          handles[i] = h;
    1822          Py_DECREF(v);
    1823      }
    1824      /* If this is the main thread then make the wait interruptible
    1825         by Ctrl-C unless we are waiting for *all* handles */
    1826      if (!wait_flag && _PyOS_IsMainThread()) {
    1827          sigint_event = _PyOS_SigintEvent();
    1828          assert(sigint_event != NULL);
    1829          handles[nhandles++] = sigint_event;
    1830      }
    1831  
    1832      Py_BEGIN_ALLOW_THREADS
    1833      if (sigint_event != NULL)
    1834          ResetEvent(sigint_event);
    1835      result = WaitForMultipleObjects((DWORD) nhandles, handles,
    1836                                      wait_flag, milliseconds);
    1837      Py_END_ALLOW_THREADS
    1838  
    1839      if (result == WAIT_FAILED)
    1840          return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
    1841      else if (sigint_event != NULL && result == WAIT_OBJECT_0 + nhandles - 1) {
    1842          errno = EINTR;
    1843          return PyErr_SetFromErrno(PyExc_OSError);
    1844      }
    1845  
    1846      return PyLong_FromLong((int) result);
    1847  }
    1848  
    1849  /*[clinic input]
    1850  _winapi.WaitForSingleObject -> long
    1851  
    1852      handle: HANDLE
    1853      milliseconds: DWORD
    1854      /
    1855  
    1856  Wait for a single object.
    1857  
    1858  Wait until the specified object is in the signaled state or
    1859  the time-out interval elapses. The timeout value is specified
    1860  in milliseconds.
    1861  [clinic start generated code]*/
    1862  
    1863  static long
    1864  _winapi_WaitForSingleObject_impl(PyObject *module, HANDLE handle,
    1865                                   DWORD milliseconds)
    1866  /*[clinic end generated code: output=3c4715d8f1b39859 input=443d1ab076edc7b1]*/
    1867  {
    1868      DWORD result;
    1869  
    1870      Py_BEGIN_ALLOW_THREADS
    1871      result = WaitForSingleObject(handle, milliseconds);
    1872      Py_END_ALLOW_THREADS
    1873  
    1874      if (result == WAIT_FAILED) {
    1875          PyErr_SetFromWindowsErr(GetLastError());
    1876          return -1;
    1877      }
    1878  
    1879      return result;
    1880  }
    1881  
    1882  /*[clinic input]
    1883  _winapi.WriteFile
    1884  
    1885      handle: HANDLE
    1886      buffer: object
    1887      overlapped as use_overlapped: bool = False
    1888  [clinic start generated code]*/
    1889  
    1890  static PyObject *
    1891  _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
    1892                         int use_overlapped)
    1893  /*[clinic end generated code: output=2ca80f6bf3fa92e3 input=2badb008c8a2e2a0]*/
    1894  {
    1895      Py_buffer _buf, *buf;
    1896      DWORD len, written;
    1897      BOOL ret;
    1898      DWORD err;
    1899      OverlappedObject *overlapped = NULL;
    1900  
    1901      if (use_overlapped) {
    1902          overlapped = new_overlapped(module, handle);
    1903          if (!overlapped)
    1904              return NULL;
    1905          buf = &overlapped->write_buffer;
    1906      }
    1907      else
    1908          buf = &_buf;
    1909  
    1910      if (!PyArg_Parse(buffer, "y*", buf)) {
    1911          Py_XDECREF(overlapped);
    1912          return NULL;
    1913      }
    1914  
    1915      Py_BEGIN_ALLOW_THREADS
    1916      len = (DWORD)Py_MIN(buf->len, PY_DWORD_MAX);
    1917      ret = WriteFile(handle, buf->buf, len, &written,
    1918                      overlapped ? &overlapped->overlapped : NULL);
    1919      Py_END_ALLOW_THREADS
    1920  
    1921      err = ret ? 0 : GetLastError();
    1922  
    1923      if (overlapped) {
    1924          if (!ret) {
    1925              if (err == ERROR_IO_PENDING)
    1926                  overlapped->pending = 1;
    1927              else {
    1928                  Py_DECREF(overlapped);
    1929                  return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
    1930              }
    1931          }
    1932          return Py_BuildValue("NI", (PyObject *) overlapped, err);
    1933      }
    1934  
    1935      PyBuffer_Release(buf);
    1936      if (!ret)
    1937          return PyErr_SetExcFromWindowsErr(PyExc_OSError, 0);
    1938      return Py_BuildValue("II", written, err);
    1939  }
    1940  
    1941  /*[clinic input]
    1942  _winapi.GetACP
    1943  
    1944  Get the current Windows ANSI code page identifier.
    1945  [clinic start generated code]*/
    1946  
    1947  static PyObject *
    1948  _winapi_GetACP_impl(PyObject *module)
    1949  /*[clinic end generated code: output=f7ee24bf705dbb88 input=1433c96d03a05229]*/
    1950  {
    1951      return PyLong_FromUnsignedLong(GetACP());
    1952  }
    1953  
    1954  /*[clinic input]
    1955  _winapi.GetFileType -> DWORD
    1956  
    1957      handle: HANDLE
    1958  [clinic start generated code]*/
    1959  
    1960  static DWORD
    1961  _winapi_GetFileType_impl(PyObject *module, HANDLE handle)
    1962  /*[clinic end generated code: output=92b8466ac76ecc17 input=0058366bc40bbfbf]*/
    1963  {
    1964      DWORD result;
    1965  
    1966      Py_BEGIN_ALLOW_THREADS
    1967      result = GetFileType(handle);
    1968      Py_END_ALLOW_THREADS
    1969  
    1970      if (result == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR) {
    1971          PyErr_SetFromWindowsErr(0);
    1972          return -1;
    1973      }
    1974  
    1975      return result;
    1976  }
    1977  
    1978  
    1979  /*[clinic input]
    1980  _winapi._mimetypes_read_windows_registry
    1981  
    1982      on_type_read: object
    1983  
    1984  Optimized function for reading all known MIME types from the registry.
    1985  
    1986  *on_type_read* is a callable taking *type* and *ext* arguments, as for
    1987  MimeTypes.add_type.
    1988  [clinic start generated code]*/
    1989  
    1990  static PyObject *
    1991  _winapi__mimetypes_read_windows_registry_impl(PyObject *module,
    1992                                                PyObject *on_type_read)
    1993  /*[clinic end generated code: output=20829f00bebce55b input=cd357896d6501f68]*/
    1994  {
    1995  #define CCH_EXT 128
    1996  #define CB_TYPE 510
    1997      struct {
    1998          wchar_t ext[CCH_EXT];
    1999          wchar_t type[CB_TYPE / sizeof(wchar_t) + 1];
    2000      } entries[64];
    2001      int entry = 0;
    2002      HKEY hkcr = NULL;
    2003      LRESULT err;
    2004  
    2005      Py_BEGIN_ALLOW_THREADS
    2006      err = RegOpenKeyExW(HKEY_CLASSES_ROOT, NULL, 0, KEY_READ, &hkcr);
    2007      for (DWORD i = 0; err == ERROR_SUCCESS || err == ERROR_MORE_DATA; ++i) {
    2008          LPWSTR ext = entries[entry].ext;
    2009          LPWSTR type = entries[entry].type;
    2010          DWORD cchExt = CCH_EXT;
    2011          DWORD cbType = CB_TYPE;
    2012          HKEY subkey;
    2013          DWORD regType;
    2014  
    2015          err = RegEnumKeyExW(hkcr, i, ext, &cchExt, NULL, NULL, NULL, NULL);
    2016          if (err != ERROR_SUCCESS || (cchExt && ext[0] != L'.')) {
    2017              continue;
    2018          }
    2019  
    2020          err = RegOpenKeyExW(hkcr, ext, 0, KEY_READ, &subkey);
    2021          if (err == ERROR_FILE_NOT_FOUND) {
    2022              err = ERROR_SUCCESS;
    2023              continue;
    2024          } else if (err != ERROR_SUCCESS) {
    2025              continue;
    2026          }
    2027  
    2028          err = RegQueryValueExW(subkey, L"Content Type", NULL,
    2029                                &regType, (LPBYTE)type, &cbType);
    2030          RegCloseKey(subkey);
    2031          if (err == ERROR_FILE_NOT_FOUND) {
    2032              err = ERROR_SUCCESS;
    2033              continue;
    2034          } else if (err != ERROR_SUCCESS) {
    2035              continue;
    2036          } else if (regType != REG_SZ || !cbType) {
    2037              continue;
    2038          }
    2039          type[cbType / sizeof(wchar_t)] = L'\0';
    2040  
    2041          entry += 1;
    2042  
    2043          /* Flush our cached entries if we are full */
    2044          if (entry == sizeof(entries) / sizeof(entries[0])) {
    2045              Py_BLOCK_THREADS
    2046              for (int j = 0; j < entry; ++j) {
    2047                  PyObject *r = PyObject_CallFunction(
    2048                      on_type_read, "uu", entries[j].type, entries[j].ext
    2049                  );
    2050                  if (!r) {
    2051                      /* We blocked threads, so safe to return from here */
    2052                      RegCloseKey(hkcr);
    2053                      return NULL;
    2054                  }
    2055                  Py_DECREF(r);
    2056              }
    2057              Py_UNBLOCK_THREADS
    2058              entry = 0;
    2059          }
    2060      }
    2061      if (hkcr) {
    2062          RegCloseKey(hkcr);
    2063      }
    2064      Py_END_ALLOW_THREADS
    2065  
    2066      if (err != ERROR_SUCCESS && err != ERROR_NO_MORE_ITEMS) {
    2067          PyErr_SetFromWindowsErr((int)err);
    2068          return NULL;
    2069      }
    2070  
    2071      for (int j = 0; j < entry; ++j) {
    2072          PyObject *r = PyObject_CallFunction(
    2073              on_type_read, "uu", entries[j].type, entries[j].ext
    2074          );
    2075          if (!r) {
    2076              return NULL;
    2077          }
    2078          Py_DECREF(r);
    2079      }
    2080  
    2081      Py_RETURN_NONE;
    2082  #undef CCH_EXT
    2083  #undef CB_TYPE
    2084  }
    2085  
    2086  /*[clinic input]
    2087  _winapi.NeedCurrentDirectoryForExePath -> bool
    2088  
    2089      exe_name: LPCWSTR
    2090      /
    2091  [clinic start generated code]*/
    2092  
    2093  static int
    2094  _winapi_NeedCurrentDirectoryForExePath_impl(PyObject *module,
    2095                                              LPCWSTR exe_name)
    2096  /*[clinic end generated code: output=a65ec879502b58fc input=972aac88a1ec2f00]*/
    2097  {
    2098      BOOL result;
    2099  
    2100      Py_BEGIN_ALLOW_THREADS
    2101      result = NeedCurrentDirectoryForExePathW(exe_name);
    2102      Py_END_ALLOW_THREADS
    2103  
    2104      return result;
    2105  }
    2106  
    2107  
    2108  /*[clinic input]
    2109  _winapi.CopyFile2
    2110  
    2111      existing_file_name: LPCWSTR
    2112      new_file_name: LPCWSTR
    2113      flags: DWORD
    2114      progress_routine: object = None
    2115  
    2116  Copies a file from one name to a new name.
    2117  
    2118  This is implemented using the CopyFile2 API, which preserves all stat
    2119  and metadata information apart from security attributes.
    2120  
    2121  progress_routine is reserved for future use, but is currently not
    2122  implemented. Its value is ignored.
    2123  [clinic start generated code]*/
    2124  
    2125  static PyObject *
    2126  _winapi_CopyFile2_impl(PyObject *module, LPCWSTR existing_file_name,
    2127                         LPCWSTR new_file_name, DWORD flags,
    2128                         PyObject *progress_routine)
    2129  /*[clinic end generated code: output=43d960d9df73d984 input=fb976b8d1492d130]*/
    2130  {
    2131      HRESULT hr;
    2132      COPYFILE2_EXTENDED_PARAMETERS params = { sizeof(COPYFILE2_EXTENDED_PARAMETERS) };
    2133  
    2134      if (PySys_Audit("_winapi.CopyFile2", "uuI",
    2135                      existing_file_name, new_file_name, flags) < 0) {
    2136          return NULL;
    2137      }
    2138  
    2139      params.dwCopyFlags = flags;
    2140      /* For future implementation. We ignore the value for now so that
    2141         users only have to test for 'CopyFile2' existing and not whether
    2142         the additional parameter exists.
    2143      if (progress_routine != Py_None) {
    2144          params.pProgressRoutine = _winapi_CopyFile2ProgressRoutine;
    2145          params.pvCallbackContext = Py_NewRef(progress_routine);
    2146      }
    2147      */
    2148      Py_BEGIN_ALLOW_THREADS;
    2149      hr = CopyFile2(existing_file_name, new_file_name, &params);
    2150      Py_END_ALLOW_THREADS;
    2151      /* For future implementation.
    2152      if (progress_routine != Py_None) {
    2153          Py_DECREF(progress_routine);
    2154      }
    2155      */
    2156      if (FAILED(hr)) {
    2157          if ((hr & 0xFFFF0000) == 0x80070000) {
    2158              PyErr_SetFromWindowsErr(hr & 0xFFFF);
    2159          } else {
    2160              PyErr_SetFromWindowsErr(hr);
    2161          }
    2162          return NULL;
    2163      }
    2164      Py_RETURN_NONE;
    2165  }
    2166  
    2167  
    2168  static PyMethodDef winapi_functions[] = {
    2169      _WINAPI_CLOSEHANDLE_METHODDEF
    2170      _WINAPI_CONNECTNAMEDPIPE_METHODDEF
    2171      _WINAPI_CREATEFILE_METHODDEF
    2172      _WINAPI_CREATEFILEMAPPING_METHODDEF
    2173      _WINAPI_CREATENAMEDPIPE_METHODDEF
    2174      _WINAPI_CREATEPIPE_METHODDEF
    2175      _WINAPI_CREATEPROCESS_METHODDEF
    2176      _WINAPI_CREATEJUNCTION_METHODDEF
    2177      _WINAPI_DUPLICATEHANDLE_METHODDEF
    2178      _WINAPI_EXITPROCESS_METHODDEF
    2179      _WINAPI_GETCURRENTPROCESS_METHODDEF
    2180      _WINAPI_GETEXITCODEPROCESS_METHODDEF
    2181      _WINAPI_GETLASTERROR_METHODDEF
    2182      _WINAPI_GETMODULEFILENAME_METHODDEF
    2183      _WINAPI_GETSTDHANDLE_METHODDEF
    2184      _WINAPI_GETVERSION_METHODDEF
    2185      _WINAPI_MAPVIEWOFFILE_METHODDEF
    2186      _WINAPI_OPENFILEMAPPING_METHODDEF
    2187      _WINAPI_OPENPROCESS_METHODDEF
    2188      _WINAPI_PEEKNAMEDPIPE_METHODDEF
    2189      _WINAPI_LCMAPSTRINGEX_METHODDEF
    2190      _WINAPI_READFILE_METHODDEF
    2191      _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF
    2192      _WINAPI_TERMINATEPROCESS_METHODDEF
    2193      _WINAPI_UNMAPVIEWOFFILE_METHODDEF
    2194      _WINAPI_VIRTUALQUERYSIZE_METHODDEF
    2195      _WINAPI_WAITNAMEDPIPE_METHODDEF
    2196      _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF
    2197      _WINAPI_WAITFORSINGLEOBJECT_METHODDEF
    2198      _WINAPI_WRITEFILE_METHODDEF
    2199      _WINAPI_GETACP_METHODDEF
    2200      _WINAPI_GETFILETYPE_METHODDEF
    2201      _WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF
    2202      _WINAPI_NEEDCURRENTDIRECTORYFOREXEPATH_METHODDEF
    2203      _WINAPI_COPYFILE2_METHODDEF
    2204      {NULL, NULL}
    2205  };
    2206  
    2207  #define WINAPI_CONSTANT(fmt, con) \
    2208      do { \
    2209          PyObject *value = Py_BuildValue(fmt, con); \
    2210          if (value == NULL) { \
    2211              return -1; \
    2212          } \
    2213          if (PyDict_SetItemString(d, #con, value) < 0) { \
    2214              Py_DECREF(value); \
    2215              return -1; \
    2216          } \
    2217          Py_DECREF(value); \
    2218      } while (0)
    2219  
    2220  static int winapi_exec(PyObject *m)
    2221  {
    2222      WinApiState *st = winapi_get_state(m);
    2223  
    2224      st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec(m, &winapi_overlapped_type_spec, NULL);
    2225      if (st->overlapped_type == NULL) {
    2226          return -1;
    2227      }
    2228  
    2229      if (PyModule_AddType(m, st->overlapped_type) < 0) {
    2230          return -1;
    2231      }
    2232  
    2233      PyObject *d = PyModule_GetDict(m);
    2234  
    2235      /* constants */
    2236      WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
    2237      WINAPI_CONSTANT(F_DWORD, CREATE_NEW_PROCESS_GROUP);
    2238      WINAPI_CONSTANT(F_DWORD, DUPLICATE_SAME_ACCESS);
    2239      WINAPI_CONSTANT(F_DWORD, DUPLICATE_CLOSE_SOURCE);
    2240      WINAPI_CONSTANT(F_DWORD, ERROR_ACCESS_DENIED);
    2241      WINAPI_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS);
    2242      WINAPI_CONSTANT(F_DWORD, ERROR_BROKEN_PIPE);
    2243      WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
    2244      WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
    2245      WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
    2246      WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
    2247      WINAPI_CONSTANT(F_DWORD, ERROR_MORE_DATA);
    2248      WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
    2249      WINAPI_CONSTANT(F_DWORD, ERROR_NO_DATA);
    2250      WINAPI_CONSTANT(F_DWORD, ERROR_NO_SYSTEM_RESOURCES);
    2251      WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
    2252      WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
    2253      WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED);
    2254      WINAPI_CONSTANT(F_DWORD, ERROR_PRIVILEGE_NOT_HELD);
    2255      WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
    2256      WINAPI_CONSTANT(F_DWORD, FILE_FLAG_FIRST_PIPE_INSTANCE);
    2257      WINAPI_CONSTANT(F_DWORD, FILE_FLAG_OVERLAPPED);
    2258      WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_READ);
    2259      WINAPI_CONSTANT(F_DWORD, FILE_GENERIC_WRITE);
    2260      WINAPI_CONSTANT(F_DWORD, FILE_MAP_ALL_ACCESS);
    2261      WINAPI_CONSTANT(F_DWORD, FILE_MAP_COPY);
    2262      WINAPI_CONSTANT(F_DWORD, FILE_MAP_EXECUTE);
    2263      WINAPI_CONSTANT(F_DWORD, FILE_MAP_READ);
    2264      WINAPI_CONSTANT(F_DWORD, FILE_MAP_WRITE);
    2265      WINAPI_CONSTANT(F_DWORD, GENERIC_READ);
    2266      WINAPI_CONSTANT(F_DWORD, GENERIC_WRITE);
    2267      WINAPI_CONSTANT(F_DWORD, INFINITE);
    2268      WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE);
    2269      WINAPI_CONSTANT(F_DWORD, MEM_COMMIT);
    2270      WINAPI_CONSTANT(F_DWORD, MEM_FREE);
    2271      WINAPI_CONSTANT(F_DWORD, MEM_IMAGE);
    2272      WINAPI_CONSTANT(F_DWORD, MEM_MAPPED);
    2273      WINAPI_CONSTANT(F_DWORD, MEM_PRIVATE);
    2274      WINAPI_CONSTANT(F_DWORD, MEM_RESERVE);
    2275      WINAPI_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER);
    2276      WINAPI_CONSTANT(F_DWORD, OPEN_EXISTING);
    2277      WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE);
    2278      WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_READ);
    2279      WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_READWRITE);
    2280      WINAPI_CONSTANT(F_DWORD, PAGE_EXECUTE_WRITECOPY);
    2281      WINAPI_CONSTANT(F_DWORD, PAGE_GUARD);
    2282      WINAPI_CONSTANT(F_DWORD, PAGE_NOACCESS);
    2283      WINAPI_CONSTANT(F_DWORD, PAGE_NOCACHE);
    2284      WINAPI_CONSTANT(F_DWORD, PAGE_READONLY);
    2285      WINAPI_CONSTANT(F_DWORD, PAGE_READWRITE);
    2286      WINAPI_CONSTANT(F_DWORD, PAGE_WRITECOMBINE);
    2287      WINAPI_CONSTANT(F_DWORD, PAGE_WRITECOPY);
    2288      WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX);
    2289      WINAPI_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND);
    2290      WINAPI_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE);
    2291      WINAPI_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE);
    2292      WINAPI_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES);
    2293      WINAPI_CONSTANT(F_DWORD, PIPE_WAIT);
    2294      WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS);
    2295      WINAPI_CONSTANT(F_DWORD, SYNCHRONIZE);
    2296      WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE);
    2297      WINAPI_CONSTANT(F_DWORD, SEC_COMMIT);
    2298      WINAPI_CONSTANT(F_DWORD, SEC_IMAGE);
    2299      WINAPI_CONSTANT(F_DWORD, SEC_LARGE_PAGES);
    2300      WINAPI_CONSTANT(F_DWORD, SEC_NOCACHE);
    2301      WINAPI_CONSTANT(F_DWORD, SEC_RESERVE);
    2302      WINAPI_CONSTANT(F_DWORD, SEC_WRITECOMBINE);
    2303      WINAPI_CONSTANT(F_DWORD, STARTF_USESHOWWINDOW);
    2304      WINAPI_CONSTANT(F_DWORD, STARTF_USESTDHANDLES);
    2305      WINAPI_CONSTANT(F_DWORD, STD_INPUT_HANDLE);
    2306      WINAPI_CONSTANT(F_DWORD, STD_OUTPUT_HANDLE);
    2307      WINAPI_CONSTANT(F_DWORD, STD_ERROR_HANDLE);
    2308      WINAPI_CONSTANT(F_DWORD, STILL_ACTIVE);
    2309      WINAPI_CONSTANT(F_DWORD, SW_HIDE);
    2310      WINAPI_CONSTANT(F_DWORD, WAIT_OBJECT_0);
    2311      WINAPI_CONSTANT(F_DWORD, WAIT_ABANDONED_0);
    2312      WINAPI_CONSTANT(F_DWORD, WAIT_TIMEOUT);
    2313  
    2314      WINAPI_CONSTANT(F_DWORD, ABOVE_NORMAL_PRIORITY_CLASS);
    2315      WINAPI_CONSTANT(F_DWORD, BELOW_NORMAL_PRIORITY_CLASS);
    2316      WINAPI_CONSTANT(F_DWORD, HIGH_PRIORITY_CLASS);
    2317      WINAPI_CONSTANT(F_DWORD, IDLE_PRIORITY_CLASS);
    2318      WINAPI_CONSTANT(F_DWORD, NORMAL_PRIORITY_CLASS);
    2319      WINAPI_CONSTANT(F_DWORD, REALTIME_PRIORITY_CLASS);
    2320  
    2321      WINAPI_CONSTANT(F_DWORD, CREATE_NO_WINDOW);
    2322      WINAPI_CONSTANT(F_DWORD, DETACHED_PROCESS);
    2323      WINAPI_CONSTANT(F_DWORD, CREATE_DEFAULT_ERROR_MODE);
    2324      WINAPI_CONSTANT(F_DWORD, CREATE_BREAKAWAY_FROM_JOB);
    2325  
    2326      WINAPI_CONSTANT(F_DWORD, FILE_TYPE_UNKNOWN);
    2327      WINAPI_CONSTANT(F_DWORD, FILE_TYPE_DISK);
    2328      WINAPI_CONSTANT(F_DWORD, FILE_TYPE_CHAR);
    2329      WINAPI_CONSTANT(F_DWORD, FILE_TYPE_PIPE);
    2330      WINAPI_CONSTANT(F_DWORD, FILE_TYPE_REMOTE);
    2331  
    2332      WINAPI_CONSTANT("u", LOCALE_NAME_INVARIANT);
    2333      WINAPI_CONSTANT(F_DWORD, LOCALE_NAME_MAX_LENGTH);
    2334      WINAPI_CONSTANT("u", LOCALE_NAME_SYSTEM_DEFAULT);
    2335      WINAPI_CONSTANT("u", LOCALE_NAME_USER_DEFAULT);
    2336  
    2337      WINAPI_CONSTANT(F_DWORD, LCMAP_FULLWIDTH);
    2338      WINAPI_CONSTANT(F_DWORD, LCMAP_HALFWIDTH);
    2339      WINAPI_CONSTANT(F_DWORD, LCMAP_HIRAGANA);
    2340      WINAPI_CONSTANT(F_DWORD, LCMAP_KATAKANA);
    2341      WINAPI_CONSTANT(F_DWORD, LCMAP_LINGUISTIC_CASING);
    2342      WINAPI_CONSTANT(F_DWORD, LCMAP_LOWERCASE);
    2343      WINAPI_CONSTANT(F_DWORD, LCMAP_SIMPLIFIED_CHINESE);
    2344      WINAPI_CONSTANT(F_DWORD, LCMAP_TITLECASE);
    2345      WINAPI_CONSTANT(F_DWORD, LCMAP_TRADITIONAL_CHINESE);
    2346      WINAPI_CONSTANT(F_DWORD, LCMAP_UPPERCASE);
    2347  
    2348      WINAPI_CONSTANT(F_DWORD, COPY_FILE_ALLOW_DECRYPTED_DESTINATION);
    2349      WINAPI_CONSTANT(F_DWORD, COPY_FILE_COPY_SYMLINK);
    2350      WINAPI_CONSTANT(F_DWORD, COPY_FILE_FAIL_IF_EXISTS);
    2351      WINAPI_CONSTANT(F_DWORD, COPY_FILE_NO_BUFFERING);
    2352      WINAPI_CONSTANT(F_DWORD, COPY_FILE_NO_OFFLOAD);
    2353      WINAPI_CONSTANT(F_DWORD, COPY_FILE_OPEN_SOURCE_FOR_WRITE);
    2354      WINAPI_CONSTANT(F_DWORD, COPY_FILE_RESTARTABLE);
    2355      WINAPI_CONSTANT(F_DWORD, COPY_FILE_REQUEST_SECURITY_PRIVILEGES);
    2356      WINAPI_CONSTANT(F_DWORD, COPY_FILE_RESUME_FROM_PAUSE);
    2357  #ifndef COPY_FILE_REQUEST_COMPRESSED_TRAFFIC
    2358      // Only defined in newer WinSDKs
    2359      #define COPY_FILE_REQUEST_COMPRESSED_TRAFFIC 0x10000000
    2360  #endif
    2361      WINAPI_CONSTANT(F_DWORD, COPY_FILE_REQUEST_COMPRESSED_TRAFFIC);
    2362  
    2363      WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_CHUNK_STARTED);
    2364      WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_CHUNK_FINISHED);
    2365      WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_STREAM_STARTED);
    2366      WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_STREAM_FINISHED);
    2367      WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_POLL_CONTINUE);
    2368      WINAPI_CONSTANT(F_DWORD, COPYFILE2_CALLBACK_ERROR);
    2369  
    2370      WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_CONTINUE);
    2371      WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_CANCEL);
    2372      WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_STOP);
    2373      WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_QUIET);
    2374      WINAPI_CONSTANT(F_DWORD, COPYFILE2_PROGRESS_PAUSE);
    2375  
    2376      WINAPI_CONSTANT("i", NULL);
    2377  
    2378      return 0;
    2379  }
    2380  
    2381  static PyModuleDef_Slot winapi_slots[] = {
    2382      {Py_mod_exec, winapi_exec},
    2383      {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
    2384      {0, NULL}
    2385  };
    2386  
    2387  static int
    2388  winapi_traverse(PyObject *module, visitproc visit, void *arg)
    2389  {
    2390      WinApiState *st = winapi_get_state(module);
    2391      Py_VISIT(st->overlapped_type);
    2392      return 0;
    2393  }
    2394  
    2395  static int
    2396  winapi_clear(PyObject *module)
    2397  {
    2398      WinApiState *st = winapi_get_state(module);
    2399      Py_CLEAR(st->overlapped_type);
    2400      return 0;
    2401  }
    2402  
    2403  static void
    2404  winapi_free(void *module)
    2405  {
    2406      winapi_clear((PyObject *)module);
    2407  }
    2408  
    2409  static struct PyModuleDef winapi_module = {
    2410      PyModuleDef_HEAD_INIT,
    2411      .m_name = "_winapi",
    2412      .m_size = sizeof(WinApiState),
    2413      .m_methods = winapi_functions,
    2414      .m_slots = winapi_slots,
    2415      .m_traverse = winapi_traverse,
    2416      .m_clear = winapi_clear,
    2417      .m_free = winapi_free,
    2418  };
    2419  
    2420  PyMODINIT_FUNC
    2421  PyInit__winapi(void)
    2422  {
    2423      return PyModuleDef_Init(&winapi_module);
    2424  }