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