(root)/
Python-3.12.0/
PC/
msvcrtmodule.c
       1  /*********************************************************
       2  
       3      msvcrtmodule.c
       4  
       5      A Python interface to the Microsoft Visual C Runtime
       6      Library, providing access to those non-portable, but
       7      still useful routines.
       8  
       9      Only ever compiled with an MS compiler, so no attempt
      10      has been made to avoid MS language extensions, etc...
      11  
      12      This may only work on NT or 95...
      13  
      14      Author: Mark Hammond and Guido van Rossum.
      15      Maintenance: Guido van Rossum.
      16  
      17  ***********************************************************/
      18  
      19  #include "Python.h"
      20  #include "pycore_fileutils.h"     // _Py_BEGIN_SUPPRESS_IPH
      21  #include "malloc.h"
      22  #include <io.h>
      23  #include <conio.h>
      24  #include <sys/locking.h>
      25  #include <crtdbg.h>
      26  #include <windows.h>
      27  
      28  #ifdef _MSC_VER
      29  #if _MSC_VER >= 1500 && _MSC_VER < 1600
      30  #include <crtassem.h>
      31  #elif _MSC_VER >= 1600
      32  #include <crtversion.h>
      33  #endif
      34  #endif
      35  
      36  /*[python input]
      37  class HANDLE_converter(CConverter):
      38      type = 'void *'
      39      format_unit = '"_Py_PARSE_UINTPTR"'
      40  
      41      def parse_arg(self, argname, displayname):
      42          return """
      43              {paramname} = PyLong_AsVoidPtr({argname});
      44              if (!{paramname} && PyErr_Occurred()) {{{{
      45                  goto exit;
      46              }}}}
      47              """.format(argname=argname, paramname=self.parser_name)
      48  
      49  class HANDLE_return_converter(CReturnConverter):
      50      type = 'void *'
      51  
      52      def render(self, function, data):
      53          self.declare(data)
      54          self.err_occurred_if(
      55              "_return_value == NULL || _return_value == INVALID_HANDLE_VALUE",
      56              data)
      57          data.return_conversion.append(
      58              'return_value = PyLong_FromVoidPtr(_return_value);\n')
      59  
      60  class byte_char_return_converter(CReturnConverter):
      61      type = 'int'
      62  
      63      def render(self, function, data):
      64          data.declarations.append('char s[1];')
      65          data.return_value = 's[0]'
      66          data.return_conversion.append(
      67              'return_value = PyBytes_FromStringAndSize(s, 1);\n')
      68  
      69  class wchar_t_return_converter(CReturnConverter):
      70      type = 'wchar_t'
      71  
      72      def render(self, function, data):
      73          self.declare(data)
      74          data.return_conversion.append(
      75              'return_value = PyUnicode_FromOrdinal(_return_value);\n')
      76  [python start generated code]*/
      77  /*[python end generated code: output=da39a3ee5e6b4b0d input=1e8e9fa3538ec08f]*/
      78  
      79  /*[clinic input]
      80  module msvcrt
      81  [clinic start generated code]*/
      82  /*[clinic end generated code: output=da39a3ee5e6b4b0d input=f31a87a783d036cd]*/
      83  
      84  #include "clinic/msvcrtmodule.c.h"
      85  
      86  /*[clinic input]
      87  msvcrt.heapmin
      88  
      89  Minimize the malloc() heap.
      90  
      91  Force the malloc() heap to clean itself up and return unused blocks
      92  to the operating system. On failure, this raises OSError.
      93  [clinic start generated code]*/
      94  
      95  static PyObject *
      96  msvcrt_heapmin_impl(PyObject *module)
      97  /*[clinic end generated code: output=1ba00f344782dc19 input=82e1771d21bde2d8]*/
      98  {
      99      if (_heapmin() != 0)
     100          return PyErr_SetFromErrno(PyExc_OSError);
     101  
     102      Py_RETURN_NONE;
     103  }
     104  /*[clinic input]
     105  msvcrt.locking
     106  
     107      fd: int
     108      mode: int
     109      nbytes: long
     110      /
     111  
     112  Lock part of a file based on file descriptor fd from the C runtime.
     113  
     114  Raises OSError on failure. The locked region of the file extends from
     115  the current file position for nbytes bytes, and may continue beyond
     116  the end of the file. mode must be one of the LK_* constants listed
     117  below. Multiple regions in a file may be locked at the same time, but
     118  may not overlap. Adjacent regions are not merged; they must be unlocked
     119  individually.
     120  [clinic start generated code]*/
     121  
     122  static PyObject *
     123  msvcrt_locking_impl(PyObject *module, int fd, int mode, long nbytes)
     124  /*[clinic end generated code: output=a4a90deca9785a03 input=e97bd15fc4a04fef]*/
     125  {
     126      int err;
     127  
     128      if (PySys_Audit("msvcrt.locking", "iil", fd, mode, nbytes) < 0) {
     129          return NULL;
     130      }
     131  
     132      Py_BEGIN_ALLOW_THREADS
     133      _Py_BEGIN_SUPPRESS_IPH
     134      err = _locking(fd, mode, nbytes);
     135      _Py_END_SUPPRESS_IPH
     136      Py_END_ALLOW_THREADS
     137      if (err != 0)
     138          return PyErr_SetFromErrno(PyExc_OSError);
     139  
     140      Py_RETURN_NONE;
     141  }
     142  
     143  /*[clinic input]
     144  msvcrt.setmode -> long
     145  
     146      fd: int
     147      mode as flags: int
     148      /
     149  
     150  Set the line-end translation mode for the file descriptor fd.
     151  
     152  To set it to text mode, flags should be os.O_TEXT; for binary, it
     153  should be os.O_BINARY.
     154  
     155  Return value is the previous mode.
     156  [clinic start generated code]*/
     157  
     158  static long
     159  msvcrt_setmode_impl(PyObject *module, int fd, int flags)
     160  /*[clinic end generated code: output=24a9be5ea07ccb9b input=76e7c01f6b137f75]*/
     161  {
     162      _Py_BEGIN_SUPPRESS_IPH
     163      flags = _setmode(fd, flags);
     164      _Py_END_SUPPRESS_IPH
     165      if (flags == -1)
     166          PyErr_SetFromErrno(PyExc_OSError);
     167  
     168      return flags;
     169  }
     170  
     171  /*[clinic input]
     172  msvcrt.open_osfhandle -> long
     173  
     174      handle: HANDLE
     175      flags: int
     176      /
     177  
     178  Create a C runtime file descriptor from the file handle handle.
     179  
     180  The flags parameter should be a bitwise OR of os.O_APPEND, os.O_RDONLY,
     181  and os.O_TEXT. The returned file descriptor may be used as a parameter
     182  to os.fdopen() to create a file object.
     183  [clinic start generated code]*/
     184  
     185  static long
     186  msvcrt_open_osfhandle_impl(PyObject *module, void *handle, int flags)
     187  /*[clinic end generated code: output=b2fb97c4b515e4e6 input=d5db190a307cf4bb]*/
     188  {
     189      if (PySys_Audit("msvcrt.open_osfhandle", "Ki", handle, flags) < 0) {
     190          return -1;
     191      }
     192  
     193      return _Py_open_osfhandle(handle, flags);
     194  }
     195  
     196  /*[clinic input]
     197  msvcrt.get_osfhandle -> HANDLE
     198  
     199      fd: int
     200      /
     201  
     202  Return the file handle for the file descriptor fd.
     203  
     204  Raises OSError if fd is not recognized.
     205  [clinic start generated code]*/
     206  
     207  static void *
     208  msvcrt_get_osfhandle_impl(PyObject *module, int fd)
     209  /*[clinic end generated code: output=aca01dfe24637374 input=5fcfde9b17136aa2]*/
     210  {
     211      if (PySys_Audit("msvcrt.get_osfhandle", "(i)", fd) < 0) {
     212          return NULL;
     213      }
     214  
     215      return _Py_get_osfhandle(fd);
     216  }
     217  
     218  /* Console I/O */
     219  /*[clinic input]
     220  msvcrt.kbhit -> long
     221  
     222  Return true if a keypress is waiting to be read.
     223  [clinic start generated code]*/
     224  
     225  static long
     226  msvcrt_kbhit_impl(PyObject *module)
     227  /*[clinic end generated code: output=940dfce6587c1890 input=e70d678a5c2f6acc]*/
     228  {
     229      return _kbhit();
     230  }
     231  
     232  /*[clinic input]
     233  msvcrt.getch -> byte_char
     234  
     235  Read a keypress and return the resulting character as a byte string.
     236  
     237  Nothing is echoed to the console. This call will block if a keypress is
     238  not already available, but will not wait for Enter to be pressed. If the
     239  pressed key was a special function key, this will return '\000' or
     240  '\xe0'; the next call will return the keycode. The Control-C keypress
     241  cannot be read with this function.
     242  [clinic start generated code]*/
     243  
     244  static int
     245  msvcrt_getch_impl(PyObject *module)
     246  /*[clinic end generated code: output=a4e51f0565064a7d input=37a40cf0ed0d1153]*/
     247  {
     248      int ch;
     249  
     250      Py_BEGIN_ALLOW_THREADS
     251      ch = _getch();
     252      Py_END_ALLOW_THREADS
     253      return ch;
     254  }
     255  
     256  #ifdef MS_WINDOWS_DESKTOP
     257  
     258  /*[clinic input]
     259  msvcrt.getwch -> wchar_t
     260  
     261  Wide char variant of getch(), returning a Unicode value.
     262  [clinic start generated code]*/
     263  
     264  static wchar_t
     265  msvcrt_getwch_impl(PyObject *module)
     266  /*[clinic end generated code: output=be9937494e22f007 input=27b3dec8ad823d7c]*/
     267  {
     268      wchar_t ch;
     269  
     270      Py_BEGIN_ALLOW_THREADS
     271      ch = _getwch();
     272      Py_END_ALLOW_THREADS
     273      return ch;
     274  }
     275  
     276  #endif /* MS_WINDOWS_DESKTOP */
     277  
     278  /*[clinic input]
     279  msvcrt.getche -> byte_char
     280  
     281  Similar to getch(), but the keypress will be echoed if possible.
     282  [clinic start generated code]*/
     283  
     284  static int
     285  msvcrt_getche_impl(PyObject *module)
     286  /*[clinic end generated code: output=d8f7db4fd2990401 input=43311ade9ed4a9c0]*/
     287  {
     288      int ch;
     289  
     290      Py_BEGIN_ALLOW_THREADS
     291      ch = _getche();
     292      Py_END_ALLOW_THREADS
     293      return ch;
     294  }
     295  
     296  #ifdef MS_WINDOWS_DESKTOP
     297  
     298  /*[clinic input]
     299  msvcrt.getwche -> wchar_t
     300  
     301  Wide char variant of getche(), returning a Unicode value.
     302  [clinic start generated code]*/
     303  
     304  static wchar_t
     305  msvcrt_getwche_impl(PyObject *module)
     306  /*[clinic end generated code: output=d0dae5ba3829d596 input=49337d59d1a591f8]*/
     307  {
     308      wchar_t ch;
     309  
     310      Py_BEGIN_ALLOW_THREADS
     311      ch = _getwche();
     312      Py_END_ALLOW_THREADS
     313      return ch;
     314  }
     315  
     316  #endif /* MS_WINDOWS_DESKTOP */
     317  
     318  /*[clinic input]
     319  msvcrt.putch
     320  
     321      char: char
     322      /
     323  
     324  Print the byte string char to the console without buffering.
     325  [clinic start generated code]*/
     326  
     327  static PyObject *
     328  msvcrt_putch_impl(PyObject *module, char char_value)
     329  /*[clinic end generated code: output=92ec9b81012d8f60 input=ec078dd10cb054d6]*/
     330  {
     331      _Py_BEGIN_SUPPRESS_IPH
     332      _putch(char_value);
     333      _Py_END_SUPPRESS_IPH
     334      Py_RETURN_NONE;
     335  }
     336  
     337  #ifdef MS_WINDOWS_DESKTOP
     338  
     339  /*[clinic input]
     340  msvcrt.putwch
     341  
     342      unicode_char: int(accept={str})
     343      /
     344  
     345  Wide char variant of putch(), accepting a Unicode value.
     346  [clinic start generated code]*/
     347  
     348  static PyObject *
     349  msvcrt_putwch_impl(PyObject *module, int unicode_char)
     350  /*[clinic end generated code: output=a3bd1a8951d28eee input=996ccd0bbcbac4c3]*/
     351  {
     352      _Py_BEGIN_SUPPRESS_IPH
     353      _putwch(unicode_char);
     354      _Py_END_SUPPRESS_IPH
     355      Py_RETURN_NONE;
     356  
     357  }
     358  
     359  #endif /* MS_WINDOWS_DESKTOP */
     360  
     361  /*[clinic input]
     362  msvcrt.ungetch
     363  
     364      char: char
     365      /
     366  
     367  Opposite of getch.
     368  
     369  Cause the byte string char to be "pushed back" into the
     370  console buffer; it will be the next character read by
     371  getch() or getche().
     372  [clinic start generated code]*/
     373  
     374  static PyObject *
     375  msvcrt_ungetch_impl(PyObject *module, char char_value)
     376  /*[clinic end generated code: output=c6942a0efa119000 input=22f07ee9001bbf0f]*/
     377  {
     378      int res;
     379  
     380      _Py_BEGIN_SUPPRESS_IPH
     381      res = _ungetch(char_value);
     382      _Py_END_SUPPRESS_IPH
     383  
     384      if (res == EOF)
     385          return PyErr_SetFromErrno(PyExc_OSError);
     386      Py_RETURN_NONE;
     387  }
     388  
     389  #ifdef MS_WINDOWS_DESKTOP
     390  
     391  /*[clinic input]
     392  msvcrt.ungetwch
     393  
     394      unicode_char: int(accept={str})
     395      /
     396  
     397  Wide char variant of ungetch(), accepting a Unicode value.
     398  [clinic start generated code]*/
     399  
     400  static PyObject *
     401  msvcrt_ungetwch_impl(PyObject *module, int unicode_char)
     402  /*[clinic end generated code: output=e63af05438b8ba3d input=83ec0492be04d564]*/
     403  {
     404      int res;
     405  
     406      _Py_BEGIN_SUPPRESS_IPH
     407      res = _ungetwch(unicode_char);
     408      _Py_END_SUPPRESS_IPH
     409  
     410      if (res == WEOF)
     411          return PyErr_SetFromErrno(PyExc_OSError);
     412      Py_RETURN_NONE;
     413  }
     414  
     415  #endif /* MS_WINDOWS_DESKTOP */
     416  
     417  #ifdef _DEBUG
     418  /*[clinic input]
     419  msvcrt.CrtSetReportFile -> HANDLE
     420  
     421      type: int
     422      file: HANDLE
     423      /
     424  
     425  Wrapper around _CrtSetReportFile.
     426  
     427  Only available on Debug builds.
     428  [clinic start generated code]*/
     429  
     430  static void *
     431  msvcrt_CrtSetReportFile_impl(PyObject *module, int type, void *file)
     432  /*[clinic end generated code: output=9393e8c77088bbe9 input=290809b5f19e65b9]*/
     433  {
     434      HANDLE res;
     435  
     436      _Py_BEGIN_SUPPRESS_IPH
     437      res = _CrtSetReportFile(type, file);
     438      _Py_END_SUPPRESS_IPH
     439  
     440      return res;
     441  }
     442  
     443  /*[clinic input]
     444  msvcrt.CrtSetReportMode -> long
     445  
     446      type: int
     447      mode: int
     448      /
     449  
     450  Wrapper around _CrtSetReportMode.
     451  
     452  Only available on Debug builds.
     453  [clinic start generated code]*/
     454  
     455  static long
     456  msvcrt_CrtSetReportMode_impl(PyObject *module, int type, int mode)
     457  /*[clinic end generated code: output=b2863761523de317 input=9319d29b4319426b]*/
     458  {
     459      int res;
     460  
     461      _Py_BEGIN_SUPPRESS_IPH
     462      res = _CrtSetReportMode(type, mode);
     463      _Py_END_SUPPRESS_IPH
     464      if (res == -1)
     465          PyErr_SetFromErrno(PyExc_OSError);
     466      return res;
     467  }
     468  
     469  /*[clinic input]
     470  msvcrt.set_error_mode -> long
     471  
     472      mode: int
     473      /
     474  
     475  Wrapper around _set_error_mode.
     476  
     477  Only available on Debug builds.
     478  [clinic start generated code]*/
     479  
     480  static long
     481  msvcrt_set_error_mode_impl(PyObject *module, int mode)
     482  /*[clinic end generated code: output=ac4a09040d8ac4e3 input=046fca59c0f20872]*/
     483  {
     484      long res;
     485  
     486      _Py_BEGIN_SUPPRESS_IPH
     487      res = _set_error_mode(mode);
     488      _Py_END_SUPPRESS_IPH
     489  
     490      return res;
     491  }
     492  #endif /* _DEBUG */
     493  
     494  #if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
     495  
     496  /*[clinic input]
     497  msvcrt.GetErrorMode
     498  
     499  Wrapper around GetErrorMode.
     500  [clinic start generated code]*/
     501  
     502  static PyObject *
     503  msvcrt_GetErrorMode_impl(PyObject *module)
     504  /*[clinic end generated code: output=3103fc6145913591 input=5a7fb083b6dd71fd]*/
     505  {
     506      unsigned int res;
     507  
     508      _Py_BEGIN_SUPPRESS_IPH
     509      res = GetErrorMode();
     510      _Py_END_SUPPRESS_IPH
     511  
     512      return PyLong_FromUnsignedLong(res);
     513  }
     514  
     515  #endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
     516  
     517  /*[clinic input]
     518  msvcrt.SetErrorMode
     519  
     520      mode: unsigned_int(bitwise=True)
     521      /
     522  
     523  Wrapper around SetErrorMode.
     524  [clinic start generated code]*/
     525  
     526  static PyObject *
     527  msvcrt_SetErrorMode_impl(PyObject *module, unsigned int mode)
     528  /*[clinic end generated code: output=01d529293f00da8f input=d8b167258d32d907]*/
     529  {
     530      unsigned int res;
     531  
     532      _Py_BEGIN_SUPPRESS_IPH
     533      res = SetErrorMode(mode);
     534      _Py_END_SUPPRESS_IPH
     535  
     536      return PyLong_FromUnsignedLong(res);
     537  }
     538  
     539  /*[clinic input]
     540  [clinic start generated code]*/
     541  /*[clinic end generated code: output=da39a3ee5e6b4b0d input=da39a3ee5e6b4b0d]*/
     542  
     543  /* List of functions exported by this module */
     544  static struct PyMethodDef msvcrt_functions[] = {
     545      MSVCRT_HEAPMIN_METHODDEF
     546      MSVCRT_LOCKING_METHODDEF
     547      MSVCRT_SETMODE_METHODDEF
     548      MSVCRT_OPEN_OSFHANDLE_METHODDEF
     549      MSVCRT_GET_OSFHANDLE_METHODDEF
     550      MSVCRT_KBHIT_METHODDEF
     551      MSVCRT_GETCH_METHODDEF
     552      MSVCRT_GETCHE_METHODDEF
     553      MSVCRT_PUTCH_METHODDEF
     554      MSVCRT_UNGETCH_METHODDEF
     555      MSVCRT_GETERRORMODE_METHODDEF
     556      MSVCRT_SETERRORMODE_METHODDEF
     557      MSVCRT_CRTSETREPORTFILE_METHODDEF
     558      MSVCRT_CRTSETREPORTMODE_METHODDEF
     559      MSVCRT_SET_ERROR_MODE_METHODDEF
     560      MSVCRT_GETWCH_METHODDEF
     561      MSVCRT_GETWCHE_METHODDEF
     562      MSVCRT_PUTWCH_METHODDEF
     563      MSVCRT_UNGETWCH_METHODDEF
     564      {NULL,                      NULL}
     565  };
     566  
     567  static int
     568  insertptr(PyObject *mod, char *name, void *value)
     569  {
     570      PyObject *v = PyLong_FromVoidPtr(value);
     571      if (v == NULL) {
     572          return -1;
     573      }
     574      int rc = PyModule_AddObjectRef(mod, name, v);
     575      Py_DECREF(v);
     576      return rc;
     577  }
     578  
     579  #define INSERTINT(MOD, NAME, VAL) do {                  \
     580      if (PyModule_AddIntConstant(MOD, NAME, VAL) < 0) {  \
     581          return -1;                                      \
     582      }                                                   \
     583  } while (0)
     584  
     585  #define INSERTPTR(MOD, NAME, PTR) do {      \
     586      if (insertptr(MOD, NAME, PTR) < 0) {    \
     587          return -1;                          \
     588      }                                       \
     589  } while (0)
     590  
     591  #define INSERTSTR(MOD, NAME, CONST) do {                    \
     592      if (PyModule_AddStringConstant(MOD, NAME, CONST) < 0) { \
     593          return -1;                                          \
     594      }                                                       \
     595  } while (0)
     596  
     597  static int
     598  exec_module(PyObject* m)
     599  {
     600      /* constants for the locking() function's mode argument */
     601      INSERTINT(m, "LK_LOCK", _LK_LOCK);
     602      INSERTINT(m, "LK_NBLCK", _LK_NBLCK);
     603      INSERTINT(m, "LK_NBRLCK", _LK_NBRLCK);
     604      INSERTINT(m, "LK_RLCK", _LK_RLCK);
     605      INSERTINT(m, "LK_UNLCK", _LK_UNLCK);
     606  #ifdef MS_WINDOWS_DESKTOP
     607      INSERTINT(m, "SEM_FAILCRITICALERRORS", SEM_FAILCRITICALERRORS);
     608      INSERTINT(m, "SEM_NOALIGNMENTFAULTEXCEPT", SEM_NOALIGNMENTFAULTEXCEPT);
     609      INSERTINT(m, "SEM_NOGPFAULTERRORBOX", SEM_NOGPFAULTERRORBOX);
     610      INSERTINT(m, "SEM_NOOPENFILEERRORBOX", SEM_NOOPENFILEERRORBOX);
     611  #endif
     612  #ifdef _DEBUG
     613      INSERTINT(m, "CRT_WARN", _CRT_WARN);
     614      INSERTINT(m, "CRT_ERROR", _CRT_ERROR);
     615      INSERTINT(m, "CRT_ASSERT", _CRT_ASSERT);
     616      INSERTINT(m, "CRTDBG_MODE_DEBUG", _CRTDBG_MODE_DEBUG);
     617      INSERTINT(m, "CRTDBG_MODE_FILE", _CRTDBG_MODE_FILE);
     618      INSERTINT(m, "CRTDBG_MODE_WNDW", _CRTDBG_MODE_WNDW);
     619      INSERTINT(m, "CRTDBG_REPORT_MODE", _CRTDBG_REPORT_MODE);
     620      INSERTPTR(m, "CRTDBG_FILE_STDERR", _CRTDBG_FILE_STDERR);
     621      INSERTPTR(m, "CRTDBG_FILE_STDOUT", _CRTDBG_FILE_STDOUT);
     622      INSERTPTR(m, "CRTDBG_REPORT_FILE", _CRTDBG_REPORT_FILE);
     623  #endif
     624  
     625  #undef INSERTINT
     626  #undef INSERTPTR
     627  
     628      /* constants for the crt versions */
     629  #ifdef _VC_ASSEMBLY_PUBLICKEYTOKEN
     630      INSERTSTR(m, "VC_ASSEMBLY_PUBLICKEYTOKEN", _VC_ASSEMBLY_PUBLICKEYTOKEN);
     631  #endif
     632  #ifdef _CRT_ASSEMBLY_VERSION
     633      INSERTSTR(m, "CRT_ASSEMBLY_VERSION", _CRT_ASSEMBLY_VERSION);
     634  #endif
     635  #ifdef __LIBRARIES_ASSEMBLY_NAME_PREFIX
     636      INSERTSTR(m, "LIBRARIES_ASSEMBLY_NAME_PREFIX",
     637                __LIBRARIES_ASSEMBLY_NAME_PREFIX);
     638  #endif
     639  
     640  #undef INSERTSTR
     641  
     642      /* constants for the 2010 crt versions */
     643  #if defined(_VC_CRT_MAJOR_VERSION) && defined (_VC_CRT_MINOR_VERSION) && defined(_VC_CRT_BUILD_VERSION) && defined(_VC_CRT_RBUILD_VERSION)
     644      PyObject *version = PyUnicode_FromFormat("%d.%d.%d.%d",
     645                                               _VC_CRT_MAJOR_VERSION,
     646                                               _VC_CRT_MINOR_VERSION,
     647                                               _VC_CRT_BUILD_VERSION,
     648                                               _VC_CRT_RBUILD_VERSION);
     649      if (version == NULL) {
     650          return -1;
     651      }
     652      int st = PyModule_AddObjectRef(m, "CRT_ASSEMBLY_VERSION", version);
     653      Py_DECREF(version);
     654      if (st < 0) {
     655          return -1;
     656      }
     657  #endif
     658  
     659      return 0;
     660  }
     661  
     662  static PyModuleDef_Slot msvcrt_slots[] = {
     663      {Py_mod_exec, exec_module},
     664      {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
     665      {0, NULL}
     666  };
     667  
     668  static struct PyModuleDef msvcrtmodule = {
     669      .m_base = PyModuleDef_HEAD_INIT,
     670      .m_name = "msvcrt",
     671      .m_methods = msvcrt_functions,
     672      .m_slots = msvcrt_slots,
     673  };
     674  
     675  PyMODINIT_FUNC
     676  PyInit_msvcrt(void)
     677  {
     678      return PyModuleDef_Init(&msvcrtmodule);
     679  }