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