Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/PC/msvcrtmodule.c
12 views
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
}
680
681