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