/*********************************************************12msvcrtmodule.c34A Python interface to the Microsoft Visual C Runtime5Library, providing access to those non-portable, but6still useful routines.78Only ever compiled with an MS compiler, so no attempt9has been made to avoid MS language extensions, etc...1011This may only work on NT or 95...1213Author: Mark Hammond and Guido van Rossum.14Maintenance: Guido van Rossum.1516***********************************************************/1718#include "Python.h"19#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH20#include "malloc.h"21#include <io.h>22#include <conio.h>23#include <sys/locking.h>24#include <crtdbg.h>25#include <windows.h>2627#ifdef _MSC_VER28#if _MSC_VER >= 1500 && _MSC_VER < 160029#include <crtassem.h>30#elif _MSC_VER >= 160031#include <crtversion.h>32#endif33#endif3435/*[python input]36class HANDLE_converter(CConverter):37type = 'void *'38format_unit = '"_Py_PARSE_UINTPTR"'3940def parse_arg(self, argname, displayname):41return """42{paramname} = PyLong_AsVoidPtr({argname});43if (!{paramname} && PyErr_Occurred()) {{{{44goto exit;45}}}}46""".format(argname=argname, paramname=self.parser_name)4748class HANDLE_return_converter(CReturnConverter):49type = 'void *'5051def render(self, function, data):52self.declare(data)53self.err_occurred_if(54"_return_value == NULL || _return_value == INVALID_HANDLE_VALUE",55data)56data.return_conversion.append(57'return_value = PyLong_FromVoidPtr(_return_value);\n')5859class byte_char_return_converter(CReturnConverter):60type = 'int'6162def render(self, function, data):63data.declarations.append('char s[1];')64data.return_value = 's[0]'65data.return_conversion.append(66'return_value = PyBytes_FromStringAndSize(s, 1);\n')6768class wchar_t_return_converter(CReturnConverter):69type = 'wchar_t'7071def render(self, function, data):72self.declare(data)73data.return_conversion.append(74'return_value = PyUnicode_FromOrdinal(_return_value);\n')75[python start generated code]*/76/*[python end generated code: output=da39a3ee5e6b4b0d input=1e8e9fa3538ec08f]*/7778/*[clinic input]79module msvcrt80[clinic start generated code]*/81/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f31a87a783d036cd]*/8283#include "clinic/msvcrtmodule.c.h"8485/*[clinic input]86msvcrt.heapmin8788Minimize the malloc() heap.8990Force the malloc() heap to clean itself up and return unused blocks91to the operating system. On failure, this raises OSError.92[clinic start generated code]*/9394static PyObject *95msvcrt_heapmin_impl(PyObject *module)96/*[clinic end generated code: output=1ba00f344782dc19 input=82e1771d21bde2d8]*/97{98if (_heapmin() != 0)99return PyErr_SetFromErrno(PyExc_OSError);100101Py_RETURN_NONE;102}103/*[clinic input]104msvcrt.locking105106fd: int107mode: int108nbytes: long109/110111Lock part of a file based on file descriptor fd from the C runtime.112113Raises OSError on failure. The locked region of the file extends from114the current file position for nbytes bytes, and may continue beyond115the end of the file. mode must be one of the LK_* constants listed116below. Multiple regions in a file may be locked at the same time, but117may not overlap. Adjacent regions are not merged; they must be unlocked118individually.119[clinic start generated code]*/120121static PyObject *122msvcrt_locking_impl(PyObject *module, int fd, int mode, long nbytes)123/*[clinic end generated code: output=a4a90deca9785a03 input=e97bd15fc4a04fef]*/124{125int err;126127if (PySys_Audit("msvcrt.locking", "iil", fd, mode, nbytes) < 0) {128return NULL;129}130131Py_BEGIN_ALLOW_THREADS132_Py_BEGIN_SUPPRESS_IPH133err = _locking(fd, mode, nbytes);134_Py_END_SUPPRESS_IPH135Py_END_ALLOW_THREADS136if (err != 0)137return PyErr_SetFromErrno(PyExc_OSError);138139Py_RETURN_NONE;140}141142/*[clinic input]143msvcrt.setmode -> long144145fd: int146mode as flags: int147/148149Set the line-end translation mode for the file descriptor fd.150151To set it to text mode, flags should be os.O_TEXT; for binary, it152should be os.O_BINARY.153154Return value is the previous mode.155[clinic start generated code]*/156157static long158msvcrt_setmode_impl(PyObject *module, int fd, int flags)159/*[clinic end generated code: output=24a9be5ea07ccb9b input=76e7c01f6b137f75]*/160{161_Py_BEGIN_SUPPRESS_IPH162flags = _setmode(fd, flags);163_Py_END_SUPPRESS_IPH164if (flags == -1)165PyErr_SetFromErrno(PyExc_OSError);166167return flags;168}169170/*[clinic input]171msvcrt.open_osfhandle -> long172173handle: HANDLE174flags: int175/176177Create a C runtime file descriptor from the file handle handle.178179The flags parameter should be a bitwise OR of os.O_APPEND, os.O_RDONLY,180and os.O_TEXT. The returned file descriptor may be used as a parameter181to os.fdopen() to create a file object.182[clinic start generated code]*/183184static long185msvcrt_open_osfhandle_impl(PyObject *module, void *handle, int flags)186/*[clinic end generated code: output=b2fb97c4b515e4e6 input=d5db190a307cf4bb]*/187{188if (PySys_Audit("msvcrt.open_osfhandle", "Ki", handle, flags) < 0) {189return -1;190}191192return _Py_open_osfhandle(handle, flags);193}194195/*[clinic input]196msvcrt.get_osfhandle -> HANDLE197198fd: int199/200201Return the file handle for the file descriptor fd.202203Raises OSError if fd is not recognized.204[clinic start generated code]*/205206static void *207msvcrt_get_osfhandle_impl(PyObject *module, int fd)208/*[clinic end generated code: output=aca01dfe24637374 input=5fcfde9b17136aa2]*/209{210if (PySys_Audit("msvcrt.get_osfhandle", "(i)", fd) < 0) {211return NULL;212}213214return _Py_get_osfhandle(fd);215}216217/* Console I/O */218/*[clinic input]219msvcrt.kbhit -> long220221Return true if a keypress is waiting to be read.222[clinic start generated code]*/223224static long225msvcrt_kbhit_impl(PyObject *module)226/*[clinic end generated code: output=940dfce6587c1890 input=e70d678a5c2f6acc]*/227{228return _kbhit();229}230231/*[clinic input]232msvcrt.getch -> byte_char233234Read a keypress and return the resulting character as a byte string.235236Nothing is echoed to the console. This call will block if a keypress is237not already available, but will not wait for Enter to be pressed. If the238pressed key was a special function key, this will return '\000' or239'\xe0'; the next call will return the keycode. The Control-C keypress240cannot be read with this function.241[clinic start generated code]*/242243static int244msvcrt_getch_impl(PyObject *module)245/*[clinic end generated code: output=a4e51f0565064a7d input=37a40cf0ed0d1153]*/246{247int ch;248249Py_BEGIN_ALLOW_THREADS250ch = _getch();251Py_END_ALLOW_THREADS252return ch;253}254255#ifdef MS_WINDOWS_DESKTOP256257/*[clinic input]258msvcrt.getwch -> wchar_t259260Wide char variant of getch(), returning a Unicode value.261[clinic start generated code]*/262263static wchar_t264msvcrt_getwch_impl(PyObject *module)265/*[clinic end generated code: output=be9937494e22f007 input=27b3dec8ad823d7c]*/266{267wchar_t ch;268269Py_BEGIN_ALLOW_THREADS270ch = _getwch();271Py_END_ALLOW_THREADS272return ch;273}274275#endif /* MS_WINDOWS_DESKTOP */276277/*[clinic input]278msvcrt.getche -> byte_char279280Similar to getch(), but the keypress will be echoed if possible.281[clinic start generated code]*/282283static int284msvcrt_getche_impl(PyObject *module)285/*[clinic end generated code: output=d8f7db4fd2990401 input=43311ade9ed4a9c0]*/286{287int ch;288289Py_BEGIN_ALLOW_THREADS290ch = _getche();291Py_END_ALLOW_THREADS292return ch;293}294295#ifdef MS_WINDOWS_DESKTOP296297/*[clinic input]298msvcrt.getwche -> wchar_t299300Wide char variant of getche(), returning a Unicode value.301[clinic start generated code]*/302303static wchar_t304msvcrt_getwche_impl(PyObject *module)305/*[clinic end generated code: output=d0dae5ba3829d596 input=49337d59d1a591f8]*/306{307wchar_t ch;308309Py_BEGIN_ALLOW_THREADS310ch = _getwche();311Py_END_ALLOW_THREADS312return ch;313}314315#endif /* MS_WINDOWS_DESKTOP */316317/*[clinic input]318msvcrt.putch319320char: char321/322323Print the byte string char to the console without buffering.324[clinic start generated code]*/325326static PyObject *327msvcrt_putch_impl(PyObject *module, char char_value)328/*[clinic end generated code: output=92ec9b81012d8f60 input=ec078dd10cb054d6]*/329{330_Py_BEGIN_SUPPRESS_IPH331_putch(char_value);332_Py_END_SUPPRESS_IPH333Py_RETURN_NONE;334}335336#ifdef MS_WINDOWS_DESKTOP337338/*[clinic input]339msvcrt.putwch340341unicode_char: int(accept={str})342/343344Wide char variant of putch(), accepting a Unicode value.345[clinic start generated code]*/346347static PyObject *348msvcrt_putwch_impl(PyObject *module, int unicode_char)349/*[clinic end generated code: output=a3bd1a8951d28eee input=996ccd0bbcbac4c3]*/350{351_Py_BEGIN_SUPPRESS_IPH352_putwch(unicode_char);353_Py_END_SUPPRESS_IPH354Py_RETURN_NONE;355356}357358#endif /* MS_WINDOWS_DESKTOP */359360/*[clinic input]361msvcrt.ungetch362363char: char364/365366Opposite of getch.367368Cause the byte string char to be "pushed back" into the369console buffer; it will be the next character read by370getch() or getche().371[clinic start generated code]*/372373static PyObject *374msvcrt_ungetch_impl(PyObject *module, char char_value)375/*[clinic end generated code: output=c6942a0efa119000 input=22f07ee9001bbf0f]*/376{377int res;378379_Py_BEGIN_SUPPRESS_IPH380res = _ungetch(char_value);381_Py_END_SUPPRESS_IPH382383if (res == EOF)384return PyErr_SetFromErrno(PyExc_OSError);385Py_RETURN_NONE;386}387388#ifdef MS_WINDOWS_DESKTOP389390/*[clinic input]391msvcrt.ungetwch392393unicode_char: int(accept={str})394/395396Wide char variant of ungetch(), accepting a Unicode value.397[clinic start generated code]*/398399static PyObject *400msvcrt_ungetwch_impl(PyObject *module, int unicode_char)401/*[clinic end generated code: output=e63af05438b8ba3d input=83ec0492be04d564]*/402{403int res;404405_Py_BEGIN_SUPPRESS_IPH406res = _ungetwch(unicode_char);407_Py_END_SUPPRESS_IPH408409if (res == WEOF)410return PyErr_SetFromErrno(PyExc_OSError);411Py_RETURN_NONE;412}413414#endif /* MS_WINDOWS_DESKTOP */415416#ifdef _DEBUG417/*[clinic input]418msvcrt.CrtSetReportFile -> HANDLE419420type: int421file: HANDLE422/423424Wrapper around _CrtSetReportFile.425426Only available on Debug builds.427[clinic start generated code]*/428429static void *430msvcrt_CrtSetReportFile_impl(PyObject *module, int type, void *file)431/*[clinic end generated code: output=9393e8c77088bbe9 input=290809b5f19e65b9]*/432{433HANDLE res;434435_Py_BEGIN_SUPPRESS_IPH436res = _CrtSetReportFile(type, file);437_Py_END_SUPPRESS_IPH438439return res;440}441442/*[clinic input]443msvcrt.CrtSetReportMode -> long444445type: int446mode: int447/448449Wrapper around _CrtSetReportMode.450451Only available on Debug builds.452[clinic start generated code]*/453454static long455msvcrt_CrtSetReportMode_impl(PyObject *module, int type, int mode)456/*[clinic end generated code: output=b2863761523de317 input=9319d29b4319426b]*/457{458int res;459460_Py_BEGIN_SUPPRESS_IPH461res = _CrtSetReportMode(type, mode);462_Py_END_SUPPRESS_IPH463if (res == -1)464PyErr_SetFromErrno(PyExc_OSError);465return res;466}467468/*[clinic input]469msvcrt.set_error_mode -> long470471mode: int472/473474Wrapper around _set_error_mode.475476Only available on Debug builds.477[clinic start generated code]*/478479static long480msvcrt_set_error_mode_impl(PyObject *module, int mode)481/*[clinic end generated code: output=ac4a09040d8ac4e3 input=046fca59c0f20872]*/482{483long res;484485_Py_BEGIN_SUPPRESS_IPH486res = _set_error_mode(mode);487_Py_END_SUPPRESS_IPH488489return res;490}491#endif /* _DEBUG */492493#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)494495/*[clinic input]496msvcrt.GetErrorMode497498Wrapper around GetErrorMode.499[clinic start generated code]*/500501static PyObject *502msvcrt_GetErrorMode_impl(PyObject *module)503/*[clinic end generated code: output=3103fc6145913591 input=5a7fb083b6dd71fd]*/504{505unsigned int res;506507_Py_BEGIN_SUPPRESS_IPH508res = GetErrorMode();509_Py_END_SUPPRESS_IPH510511return PyLong_FromUnsignedLong(res);512}513514#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */515516/*[clinic input]517msvcrt.SetErrorMode518519mode: unsigned_int(bitwise=True)520/521522Wrapper around SetErrorMode.523[clinic start generated code]*/524525static PyObject *526msvcrt_SetErrorMode_impl(PyObject *module, unsigned int mode)527/*[clinic end generated code: output=01d529293f00da8f input=d8b167258d32d907]*/528{529unsigned int res;530531_Py_BEGIN_SUPPRESS_IPH532res = SetErrorMode(mode);533_Py_END_SUPPRESS_IPH534535return PyLong_FromUnsignedLong(res);536}537538/*[clinic input]539[clinic start generated code]*/540/*[clinic end generated code: output=da39a3ee5e6b4b0d input=da39a3ee5e6b4b0d]*/541542/* List of functions exported by this module */543static struct PyMethodDef msvcrt_functions[] = {544MSVCRT_HEAPMIN_METHODDEF545MSVCRT_LOCKING_METHODDEF546MSVCRT_SETMODE_METHODDEF547MSVCRT_OPEN_OSFHANDLE_METHODDEF548MSVCRT_GET_OSFHANDLE_METHODDEF549MSVCRT_KBHIT_METHODDEF550MSVCRT_GETCH_METHODDEF551MSVCRT_GETCHE_METHODDEF552MSVCRT_PUTCH_METHODDEF553MSVCRT_UNGETCH_METHODDEF554MSVCRT_GETERRORMODE_METHODDEF555MSVCRT_SETERRORMODE_METHODDEF556MSVCRT_CRTSETREPORTFILE_METHODDEF557MSVCRT_CRTSETREPORTMODE_METHODDEF558MSVCRT_SET_ERROR_MODE_METHODDEF559MSVCRT_GETWCH_METHODDEF560MSVCRT_GETWCHE_METHODDEF561MSVCRT_PUTWCH_METHODDEF562MSVCRT_UNGETWCH_METHODDEF563{NULL, NULL}564};565566static int567insertptr(PyObject *mod, char *name, void *value)568{569PyObject *v = PyLong_FromVoidPtr(value);570if (v == NULL) {571return -1;572}573int rc = PyModule_AddObjectRef(mod, name, v);574Py_DECREF(v);575return rc;576}577578#define INSERTINT(MOD, NAME, VAL) do { \579if (PyModule_AddIntConstant(MOD, NAME, VAL) < 0) { \580return -1; \581} \582} while (0)583584#define INSERTPTR(MOD, NAME, PTR) do { \585if (insertptr(MOD, NAME, PTR) < 0) { \586return -1; \587} \588} while (0)589590#define INSERTSTR(MOD, NAME, CONST) do { \591if (PyModule_AddStringConstant(MOD, NAME, CONST) < 0) { \592return -1; \593} \594} while (0)595596static int597exec_module(PyObject* m)598{599/* constants for the locking() function's mode argument */600INSERTINT(m, "LK_LOCK", _LK_LOCK);601INSERTINT(m, "LK_NBLCK", _LK_NBLCK);602INSERTINT(m, "LK_NBRLCK", _LK_NBRLCK);603INSERTINT(m, "LK_RLCK", _LK_RLCK);604INSERTINT(m, "LK_UNLCK", _LK_UNLCK);605#ifdef MS_WINDOWS_DESKTOP606INSERTINT(m, "SEM_FAILCRITICALERRORS", SEM_FAILCRITICALERRORS);607INSERTINT(m, "SEM_NOALIGNMENTFAULTEXCEPT", SEM_NOALIGNMENTFAULTEXCEPT);608INSERTINT(m, "SEM_NOGPFAULTERRORBOX", SEM_NOGPFAULTERRORBOX);609INSERTINT(m, "SEM_NOOPENFILEERRORBOX", SEM_NOOPENFILEERRORBOX);610#endif611#ifdef _DEBUG612INSERTINT(m, "CRT_WARN", _CRT_WARN);613INSERTINT(m, "CRT_ERROR", _CRT_ERROR);614INSERTINT(m, "CRT_ASSERT", _CRT_ASSERT);615INSERTINT(m, "CRTDBG_MODE_DEBUG", _CRTDBG_MODE_DEBUG);616INSERTINT(m, "CRTDBG_MODE_FILE", _CRTDBG_MODE_FILE);617INSERTINT(m, "CRTDBG_MODE_WNDW", _CRTDBG_MODE_WNDW);618INSERTINT(m, "CRTDBG_REPORT_MODE", _CRTDBG_REPORT_MODE);619INSERTPTR(m, "CRTDBG_FILE_STDERR", _CRTDBG_FILE_STDERR);620INSERTPTR(m, "CRTDBG_FILE_STDOUT", _CRTDBG_FILE_STDOUT);621INSERTPTR(m, "CRTDBG_REPORT_FILE", _CRTDBG_REPORT_FILE);622#endif623624#undef INSERTINT625#undef INSERTPTR626627/* constants for the crt versions */628#ifdef _VC_ASSEMBLY_PUBLICKEYTOKEN629INSERTSTR(m, "VC_ASSEMBLY_PUBLICKEYTOKEN", _VC_ASSEMBLY_PUBLICKEYTOKEN);630#endif631#ifdef _CRT_ASSEMBLY_VERSION632INSERTSTR(m, "CRT_ASSEMBLY_VERSION", _CRT_ASSEMBLY_VERSION);633#endif634#ifdef __LIBRARIES_ASSEMBLY_NAME_PREFIX635INSERTSTR(m, "LIBRARIES_ASSEMBLY_NAME_PREFIX",636__LIBRARIES_ASSEMBLY_NAME_PREFIX);637#endif638639#undef INSERTSTR640641/* 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)643PyObject *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);648if (version == NULL) {649return -1;650}651int st = PyModule_AddObjectRef(m, "CRT_ASSEMBLY_VERSION", version);652Py_DECREF(version);653if (st < 0) {654return -1;655}656#endif657658return 0;659}660661static PyModuleDef_Slot msvcrt_slots[] = {662{Py_mod_exec, exec_module},663{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},664{0, NULL}665};666667static struct PyModuleDef msvcrtmodule = {668.m_base = PyModuleDef_HEAD_INIT,669.m_name = "msvcrt",670.m_methods = msvcrt_functions,671.m_slots = msvcrt_slots,672};673674PyMODINIT_FUNC675PyInit_msvcrt(void)676{677return PyModuleDef_Init(&msvcrtmodule);678}679680681