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