| /********************************************************* | 
 |  | 
 |     msvcrtmodule.c | 
 |  | 
 |     A Python interface to the Microsoft Visual C Runtime | 
 |     Library, providing access to those non-portable, but | 
 |     still useful routines. | 
 |  | 
 |     Only ever compiled with an MS compiler, so no attempt | 
 |     has been made to avoid MS language extensions, etc... | 
 |  | 
 |     This may only work on NT or 95... | 
 |  | 
 |     Author: Mark Hammond and Guido van Rossum. | 
 |     Maintenance: Guido van Rossum. | 
 |  | 
 | ***********************************************************/ | 
 |  | 
 | #include "Python.h" | 
 | #include "malloc.h" | 
 | #include <io.h> | 
 | #include <conio.h> | 
 | #include <sys/locking.h> | 
 | #include <crtdbg.h> | 
 | #include <windows.h> | 
 |  | 
 | #ifdef _MSC_VER | 
 | #if _MSC_VER >= 1500 && _MSC_VER < 1600 | 
 | #include <crtassem.h> | 
 | #elif _MSC_VER >= 1600 | 
 | #include <crtversion.h> | 
 | #endif | 
 | #endif | 
 |  | 
 | /*[python input] | 
 | class HANDLE_converter(CConverter): | 
 |     type = 'void *' | 
 |     format_unit = '"_Py_PARSE_UINTPTR"' | 
 |  | 
 | class HANDLE_return_converter(CReturnConverter): | 
 |     type = 'void *' | 
 |  | 
 |     def render(self, function, data): | 
 |         self.declare(data) | 
 |         self.err_occurred_if( | 
 |             "_return_value == NULL || _return_value == INVALID_HANDLE_VALUE", | 
 |             data) | 
 |         data.return_conversion.append( | 
 |             'return_value = PyLong_FromVoidPtr(_return_value);\n') | 
 |  | 
 | class byte_char_return_converter(CReturnConverter): | 
 |     type = 'int' | 
 |  | 
 |     def render(self, function, data): | 
 |         data.declarations.append('char s[1];') | 
 |         data.return_value = 's[0]' | 
 |         data.return_conversion.append( | 
 |             'return_value = PyBytes_FromStringAndSize(s, 1);\n') | 
 |  | 
 | class wchar_t_return_converter(CReturnConverter): | 
 |     type = 'wchar_t' | 
 |  | 
 |     def render(self, function, data): | 
 |         self.declare(data) | 
 |         data.return_conversion.append( | 
 |             'return_value = PyUnicode_FromOrdinal(_return_value);\n') | 
 | [python start generated code]*/ | 
 | /*[python end generated code: output=da39a3ee5e6b4b0d input=d102511df3cda2eb]*/ | 
 |  | 
 | /*[clinic input] | 
 | module msvcrt | 
 | [clinic start generated code]*/ | 
 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=f31a87a783d036cd]*/ | 
 |  | 
 | #include "clinic/msvcrtmodule.c.h" | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.heapmin | 
 |  | 
 | Minimize the malloc() heap. | 
 |  | 
 | Force the malloc() heap to clean itself up and return unused blocks | 
 | to the operating system. On failure, this raises OSError. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | msvcrt_heapmin_impl(PyObject *module) | 
 | /*[clinic end generated code: output=1ba00f344782dc19 input=82e1771d21bde2d8]*/ | 
 | { | 
 |     if (_heapmin() != 0) | 
 |         return PyErr_SetFromErrno(PyExc_OSError); | 
 |  | 
 |     Py_RETURN_NONE; | 
 | } | 
 | /*[clinic input] | 
 | msvcrt.locking | 
 |  | 
 |     fd: int | 
 |     mode: int | 
 |     nbytes: long | 
 |     / | 
 |  | 
 | Lock part of a file based on file descriptor fd from the C runtime. | 
 |  | 
 | Raises OSError on failure. The locked region of the file extends from | 
 | the current file position for nbytes bytes, and may continue beyond | 
 | the end of the file. mode must be one of the LK_* constants listed | 
 | below. Multiple regions in a file may be locked at the same time, but | 
 | may not overlap. Adjacent regions are not merged; they must be unlocked | 
 | individually. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | msvcrt_locking_impl(PyObject *module, int fd, int mode, long nbytes) | 
 | /*[clinic end generated code: output=a4a90deca9785a03 input=e97bd15fc4a04fef]*/ | 
 | { | 
 |     int err; | 
 |  | 
 |     Py_BEGIN_ALLOW_THREADS | 
 |     _Py_BEGIN_SUPPRESS_IPH | 
 |     err = _locking(fd, mode, nbytes); | 
 |     _Py_END_SUPPRESS_IPH | 
 |     Py_END_ALLOW_THREADS | 
 |     if (err != 0) | 
 |         return PyErr_SetFromErrno(PyExc_OSError); | 
 |  | 
 |     Py_RETURN_NONE; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.setmode -> long | 
 |  | 
 |     fd: int | 
 |     mode as flags: int | 
 |     / | 
 |  | 
 | Set the line-end translation mode for the file descriptor fd. | 
 |  | 
 | To set it to text mode, flags should be os.O_TEXT; for binary, it | 
 | should be os.O_BINARY. | 
 |  | 
 | Return value is the previous mode. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static long | 
 | msvcrt_setmode_impl(PyObject *module, int fd, int flags) | 
 | /*[clinic end generated code: output=24a9be5ea07ccb9b input=76e7c01f6b137f75]*/ | 
 | { | 
 |     _Py_BEGIN_SUPPRESS_IPH | 
 |     flags = _setmode(fd, flags); | 
 |     _Py_END_SUPPRESS_IPH | 
 |     if (flags == -1) | 
 |         PyErr_SetFromErrno(PyExc_OSError); | 
 |  | 
 |     return flags; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.open_osfhandle -> long | 
 |  | 
 |     handle: HANDLE | 
 |     flags: int | 
 |     / | 
 |  | 
 | Create a C runtime file descriptor from the file handle handle. | 
 |  | 
 | The flags parameter should be a bitwise OR of os.O_APPEND, os.O_RDONLY, | 
 | and os.O_TEXT. The returned file descriptor may be used as a parameter | 
 | to os.fdopen() to create a file object. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static long | 
 | msvcrt_open_osfhandle_impl(PyObject *module, void *handle, int flags) | 
 | /*[clinic end generated code: output=b2fb97c4b515e4e6 input=d5db190a307cf4bb]*/ | 
 | { | 
 |     int fd; | 
 |  | 
 |     _Py_BEGIN_SUPPRESS_IPH | 
 |     fd = _open_osfhandle((intptr_t)handle, flags); | 
 |     _Py_END_SUPPRESS_IPH | 
 |     if (fd == -1) | 
 |         PyErr_SetFromErrno(PyExc_OSError); | 
 |  | 
 |     return fd; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.get_osfhandle -> HANDLE | 
 |  | 
 |     fd: int | 
 |     / | 
 |  | 
 | Return the file handle for the file descriptor fd. | 
 |  | 
 | Raises OSError if fd is not recognized. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static void * | 
 | msvcrt_get_osfhandle_impl(PyObject *module, int fd) | 
 | /*[clinic end generated code: output=aca01dfe24637374 input=5fcfde9b17136aa2]*/ | 
 | { | 
 |     intptr_t handle = -1; | 
 |  | 
 |     _Py_BEGIN_SUPPRESS_IPH | 
 |     handle = _get_osfhandle(fd); | 
 |     _Py_END_SUPPRESS_IPH | 
 |     if (handle == -1) | 
 |         PyErr_SetFromErrno(PyExc_OSError); | 
 |  | 
 |     return (HANDLE)handle; | 
 | } | 
 |  | 
 | /* Console I/O */ | 
 | /*[clinic input] | 
 | msvcrt.kbhit -> long | 
 |  | 
 | Return true if a keypress is waiting to be read. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static long | 
 | msvcrt_kbhit_impl(PyObject *module) | 
 | /*[clinic end generated code: output=940dfce6587c1890 input=e70d678a5c2f6acc]*/ | 
 | { | 
 |     return _kbhit(); | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.getch -> byte_char | 
 |  | 
 | Read a keypress and return the resulting character as a byte string. | 
 |  | 
 | Nothing is echoed to the console. This call will block if a keypress is | 
 | not already available, but will not wait for Enter to be pressed. If the | 
 | pressed key was a special function key, this will return '\000' or | 
 | '\xe0'; the next call will return the keycode. The Control-C keypress | 
 | cannot be read with this function. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static int | 
 | msvcrt_getch_impl(PyObject *module) | 
 | /*[clinic end generated code: output=a4e51f0565064a7d input=37a40cf0ed0d1153]*/ | 
 | { | 
 |     int ch; | 
 |  | 
 |     Py_BEGIN_ALLOW_THREADS | 
 |     ch = _getch(); | 
 |     Py_END_ALLOW_THREADS | 
 |     return ch; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.getwch -> wchar_t | 
 |  | 
 | Wide char variant of getch(), returning a Unicode value. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static wchar_t | 
 | msvcrt_getwch_impl(PyObject *module) | 
 | /*[clinic end generated code: output=be9937494e22f007 input=27b3dec8ad823d7c]*/ | 
 | { | 
 |     wchar_t ch; | 
 |  | 
 |     Py_BEGIN_ALLOW_THREADS | 
 |     ch = _getwch(); | 
 |     Py_END_ALLOW_THREADS | 
 |     return ch; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.getche -> byte_char | 
 |  | 
 | Similar to getch(), but the keypress will be echoed if possible. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static int | 
 | msvcrt_getche_impl(PyObject *module) | 
 | /*[clinic end generated code: output=d8f7db4fd2990401 input=43311ade9ed4a9c0]*/ | 
 | { | 
 |     int ch; | 
 |  | 
 |     Py_BEGIN_ALLOW_THREADS | 
 |     ch = _getche(); | 
 |     Py_END_ALLOW_THREADS | 
 |     return ch; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.getwche -> wchar_t | 
 |  | 
 | Wide char variant of getche(), returning a Unicode value. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static wchar_t | 
 | msvcrt_getwche_impl(PyObject *module) | 
 | /*[clinic end generated code: output=d0dae5ba3829d596 input=49337d59d1a591f8]*/ | 
 | { | 
 |     wchar_t ch; | 
 |  | 
 |     Py_BEGIN_ALLOW_THREADS | 
 |     ch = _getwche(); | 
 |     Py_END_ALLOW_THREADS | 
 |     return ch; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.putch | 
 |  | 
 |     char: char | 
 |     / | 
 |  | 
 | Print the byte string char to the console without buffering. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | msvcrt_putch_impl(PyObject *module, char char_value) | 
 | /*[clinic end generated code: output=92ec9b81012d8f60 input=ec078dd10cb054d6]*/ | 
 | { | 
 |     _Py_BEGIN_SUPPRESS_IPH | 
 |     _putch(char_value); | 
 |     _Py_END_SUPPRESS_IPH | 
 |     Py_RETURN_NONE; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.putwch | 
 |  | 
 |     unicode_char: int(accept={str}) | 
 |     / | 
 |  | 
 | Wide char variant of putch(), accepting a Unicode value. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | msvcrt_putwch_impl(PyObject *module, int unicode_char) | 
 | /*[clinic end generated code: output=a3bd1a8951d28eee input=996ccd0bbcbac4c3]*/ | 
 | { | 
 |     _Py_BEGIN_SUPPRESS_IPH | 
 |     _putwch(unicode_char); | 
 |     _Py_END_SUPPRESS_IPH | 
 |     Py_RETURN_NONE; | 
 |  | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.ungetch | 
 |  | 
 |     char: char | 
 |     / | 
 |  | 
 | Opposite of getch. | 
 |  | 
 | Cause the byte string char to be "pushed back" into the | 
 | console buffer; it will be the next character read by | 
 | getch() or getche(). | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | msvcrt_ungetch_impl(PyObject *module, char char_value) | 
 | /*[clinic end generated code: output=c6942a0efa119000 input=22f07ee9001bbf0f]*/ | 
 | { | 
 |     int res; | 
 |  | 
 |     _Py_BEGIN_SUPPRESS_IPH | 
 |     res = _ungetch(char_value); | 
 |     _Py_END_SUPPRESS_IPH | 
 |  | 
 |     if (res == EOF) | 
 |         return PyErr_SetFromErrno(PyExc_OSError); | 
 |     Py_RETURN_NONE; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.ungetwch | 
 |  | 
 |     unicode_char: int(accept={str}) | 
 |     / | 
 |  | 
 | Wide char variant of ungetch(), accepting a Unicode value. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | msvcrt_ungetwch_impl(PyObject *module, int unicode_char) | 
 | /*[clinic end generated code: output=e63af05438b8ba3d input=83ec0492be04d564]*/ | 
 | { | 
 |     int res; | 
 |  | 
 |     _Py_BEGIN_SUPPRESS_IPH | 
 |     res = _ungetwch(unicode_char); | 
 |     _Py_END_SUPPRESS_IPH | 
 |  | 
 |     if (res == WEOF) | 
 |         return PyErr_SetFromErrno(PyExc_OSError); | 
 |     Py_RETURN_NONE; | 
 | } | 
 |  | 
 | #ifdef _DEBUG | 
 | /*[clinic input] | 
 | msvcrt.CrtSetReportFile -> HANDLE | 
 |  | 
 |     type: int | 
 |     file: HANDLE | 
 |     / | 
 |  | 
 | Wrapper around _CrtSetReportFile. | 
 |  | 
 | Only available on Debug builds. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static void * | 
 | msvcrt_CrtSetReportFile_impl(PyObject *module, int type, void *file) | 
 | /*[clinic end generated code: output=9393e8c77088bbe9 input=290809b5f19e65b9]*/ | 
 | { | 
 |     HANDLE res; | 
 |  | 
 |     _Py_BEGIN_SUPPRESS_IPH | 
 |     res = _CrtSetReportFile(type, file); | 
 |     _Py_END_SUPPRESS_IPH | 
 |  | 
 |     return res; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.CrtSetReportMode -> long | 
 |  | 
 |     type: int | 
 |     mode: int | 
 |     / | 
 |  | 
 | Wrapper around _CrtSetReportMode. | 
 |  | 
 | Only available on Debug builds. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static long | 
 | msvcrt_CrtSetReportMode_impl(PyObject *module, int type, int mode) | 
 | /*[clinic end generated code: output=b2863761523de317 input=9319d29b4319426b]*/ | 
 | { | 
 |     int res; | 
 |  | 
 |     _Py_BEGIN_SUPPRESS_IPH | 
 |     res = _CrtSetReportMode(type, mode); | 
 |     _Py_END_SUPPRESS_IPH | 
 |     if (res == -1) | 
 |         PyErr_SetFromErrno(PyExc_OSError); | 
 |     return res; | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.set_error_mode -> long | 
 |  | 
 |     mode: int | 
 |     / | 
 |  | 
 | Wrapper around _set_error_mode. | 
 |  | 
 | Only available on Debug builds. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static long | 
 | msvcrt_set_error_mode_impl(PyObject *module, int mode) | 
 | /*[clinic end generated code: output=ac4a09040d8ac4e3 input=046fca59c0f20872]*/ | 
 | { | 
 |     long res; | 
 |  | 
 |     _Py_BEGIN_SUPPRESS_IPH | 
 |     res = _set_error_mode(mode); | 
 |     _Py_END_SUPPRESS_IPH | 
 |  | 
 |     return res; | 
 | } | 
 | #endif /* _DEBUG */ | 
 |  | 
 | /*[clinic input] | 
 | msvcrt.SetErrorMode | 
 |  | 
 |     mode: unsigned_int(bitwise=True) | 
 |     / | 
 |  | 
 | Wrapper around SetErrorMode. | 
 | [clinic start generated code]*/ | 
 |  | 
 | static PyObject * | 
 | msvcrt_SetErrorMode_impl(PyObject *module, unsigned int mode) | 
 | /*[clinic end generated code: output=01d529293f00da8f input=d8b167258d32d907]*/ | 
 | { | 
 |     unsigned int res; | 
 |  | 
 |     _Py_BEGIN_SUPPRESS_IPH | 
 |     res = SetErrorMode(mode); | 
 |     _Py_END_SUPPRESS_IPH | 
 |  | 
 |     return PyLong_FromUnsignedLong(res); | 
 | } | 
 |  | 
 | /*[clinic input] | 
 | [clinic start generated code]*/ | 
 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=da39a3ee5e6b4b0d]*/ | 
 |  | 
 | /* List of functions exported by this module */ | 
 | static struct PyMethodDef msvcrt_functions[] = { | 
 |     MSVCRT_HEAPMIN_METHODDEF | 
 |     MSVCRT_LOCKING_METHODDEF | 
 |     MSVCRT_SETMODE_METHODDEF | 
 |     MSVCRT_OPEN_OSFHANDLE_METHODDEF | 
 |     MSVCRT_GET_OSFHANDLE_METHODDEF | 
 |     MSVCRT_KBHIT_METHODDEF | 
 |     MSVCRT_GETCH_METHODDEF | 
 |     MSVCRT_GETCHE_METHODDEF | 
 |     MSVCRT_PUTCH_METHODDEF | 
 |     MSVCRT_UNGETCH_METHODDEF | 
 |     MSVCRT_SETERRORMODE_METHODDEF | 
 |     MSVCRT_CRTSETREPORTFILE_METHODDEF | 
 |     MSVCRT_CRTSETREPORTMODE_METHODDEF | 
 |     MSVCRT_SET_ERROR_MODE_METHODDEF | 
 |     MSVCRT_GETWCH_METHODDEF | 
 |     MSVCRT_GETWCHE_METHODDEF | 
 |     MSVCRT_PUTWCH_METHODDEF | 
 |     MSVCRT_UNGETWCH_METHODDEF | 
 |     {NULL,                      NULL} | 
 | }; | 
 |  | 
 |  | 
 | static struct PyModuleDef msvcrtmodule = { | 
 |     PyModuleDef_HEAD_INIT, | 
 |     "msvcrt", | 
 |     NULL, | 
 |     -1, | 
 |     msvcrt_functions, | 
 |     NULL, | 
 |     NULL, | 
 |     NULL, | 
 |     NULL | 
 | }; | 
 |  | 
 | static void | 
 | insertint(PyObject *d, char *name, int value) | 
 | { | 
 |     PyObject *v = PyLong_FromLong((long) value); | 
 |     if (v == NULL) { | 
 |         /* Don't bother reporting this error */ | 
 |         PyErr_Clear(); | 
 |     } | 
 |     else { | 
 |         PyDict_SetItemString(d, name, v); | 
 |         Py_DECREF(v); | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | insertptr(PyObject *d, char *name, void *value) | 
 | { | 
 |     PyObject *v = PyLong_FromVoidPtr(value); | 
 |     if (v == NULL) { | 
 |         /* Don't bother reporting this error */ | 
 |         PyErr_Clear(); | 
 |     } | 
 |     else { | 
 |         PyDict_SetItemString(d, name, v); | 
 |         Py_DECREF(v); | 
 |     } | 
 | } | 
 |  | 
 | PyMODINIT_FUNC | 
 | PyInit_msvcrt(void) | 
 | { | 
 |     int st; | 
 |     PyObject *d, *version; | 
 |     PyObject *m = PyModule_Create(&msvcrtmodule); | 
 |     if (m == NULL) | 
 |         return NULL; | 
 |     d = PyModule_GetDict(m); | 
 |  | 
 |     /* constants for the locking() function's mode argument */ | 
 |     insertint(d, "LK_LOCK", _LK_LOCK); | 
 |     insertint(d, "LK_NBLCK", _LK_NBLCK); | 
 |     insertint(d, "LK_NBRLCK", _LK_NBRLCK); | 
 |     insertint(d, "LK_RLCK", _LK_RLCK); | 
 |     insertint(d, "LK_UNLCK", _LK_UNLCK); | 
 |     insertint(d, "SEM_FAILCRITICALERRORS", SEM_FAILCRITICALERRORS); | 
 |     insertint(d, "SEM_NOALIGNMENTFAULTEXCEPT", SEM_NOALIGNMENTFAULTEXCEPT); | 
 |     insertint(d, "SEM_NOGPFAULTERRORBOX", SEM_NOGPFAULTERRORBOX); | 
 |     insertint(d, "SEM_NOOPENFILEERRORBOX", SEM_NOOPENFILEERRORBOX); | 
 | #ifdef _DEBUG | 
 |     insertint(d, "CRT_WARN", _CRT_WARN); | 
 |     insertint(d, "CRT_ERROR", _CRT_ERROR); | 
 |     insertint(d, "CRT_ASSERT", _CRT_ASSERT); | 
 |     insertint(d, "CRTDBG_MODE_DEBUG", _CRTDBG_MODE_DEBUG); | 
 |     insertint(d, "CRTDBG_MODE_FILE", _CRTDBG_MODE_FILE); | 
 |     insertint(d, "CRTDBG_MODE_WNDW", _CRTDBG_MODE_WNDW); | 
 |     insertint(d, "CRTDBG_REPORT_MODE", _CRTDBG_REPORT_MODE); | 
 |     insertptr(d, "CRTDBG_FILE_STDERR", _CRTDBG_FILE_STDERR); | 
 |     insertptr(d, "CRTDBG_FILE_STDOUT", _CRTDBG_FILE_STDOUT); | 
 |     insertptr(d, "CRTDBG_REPORT_FILE", _CRTDBG_REPORT_FILE); | 
 | #endif | 
 |  | 
 |     /* constants for the crt versions */ | 
 | #ifdef _VC_ASSEMBLY_PUBLICKEYTOKEN | 
 |     st = PyModule_AddStringConstant(m, "VC_ASSEMBLY_PUBLICKEYTOKEN", | 
 |                                     _VC_ASSEMBLY_PUBLICKEYTOKEN); | 
 |     if (st < 0) return NULL; | 
 | #endif | 
 | #ifdef _CRT_ASSEMBLY_VERSION | 
 |     st = PyModule_AddStringConstant(m, "CRT_ASSEMBLY_VERSION", | 
 |                                     _CRT_ASSEMBLY_VERSION); | 
 |     if (st < 0) return NULL; | 
 | #endif | 
 | #ifdef __LIBRARIES_ASSEMBLY_NAME_PREFIX | 
 |     st = PyModule_AddStringConstant(m, "LIBRARIES_ASSEMBLY_NAME_PREFIX", | 
 |                                     __LIBRARIES_ASSEMBLY_NAME_PREFIX); | 
 |     if (st < 0) return NULL; | 
 | #endif | 
 |  | 
 |     /* constants for the 2010 crt versions */ | 
 | #if defined(_VC_CRT_MAJOR_VERSION) && defined (_VC_CRT_MINOR_VERSION) && defined(_VC_CRT_BUILD_VERSION) && defined(_VC_CRT_RBUILD_VERSION) | 
 |     version = PyUnicode_FromFormat("%d.%d.%d.%d", _VC_CRT_MAJOR_VERSION, | 
 |                                                   _VC_CRT_MINOR_VERSION, | 
 |                                                   _VC_CRT_BUILD_VERSION, | 
 |                                                   _VC_CRT_RBUILD_VERSION); | 
 |     st = PyModule_AddObject(m, "CRT_ASSEMBLY_VERSION", version); | 
 |     if (st < 0) return NULL; | 
 | #endif | 
 |     /* make compiler warning quiet if st is unused */ | 
 |     (void)st; | 
 |  | 
 |     return m; | 
 | } |