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