diff options
| author | shadchin <[email protected]> | 2022-04-18 12:39:32 +0300 |
|---|---|---|
| committer | shadchin <[email protected]> | 2022-04-18 12:39:32 +0300 |
| commit | d4be68e361f4258cf0848fc70018dfe37a2acc24 (patch) | |
| tree | 153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Modules/_winapi.c | |
| parent | 260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff) | |
IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4
ref:9f96be6d02ee8044fdd6f124b799b270c20ce641
Diffstat (limited to 'contrib/tools/python3/src/Modules/_winapi.c')
| -rw-r--r-- | contrib/tools/python3/src/Modules/_winapi.c | 320 |
1 files changed, 239 insertions, 81 deletions
diff --git a/contrib/tools/python3/src/Modules/_winapi.c b/contrib/tools/python3/src/Modules/_winapi.c index 5b7f075722e..a44a300c0c8 100644 --- a/contrib/tools/python3/src/Modules/_winapi.c +++ b/contrib/tools/python3/src/Modules/_winapi.c @@ -35,8 +35,10 @@ /* See https://www.python.org/2.4/license for licensing details. */ #include "Python.h" +#include "pycore_moduleobject.h" // _PyModule_GetState() #include "structmember.h" // PyMemberDef + #define WINDOWS_LEAN_AND_MEAN #include "windows.h" #include <winioctl.h> @@ -79,6 +81,17 @@ check_CancelIoEx() return has_CancelIoEx; } +typedef struct { + PyTypeObject *overlapped_type; +} WinApiState; + +static inline WinApiState* +winapi_get_state(PyObject *module) +{ + void *state = _PyModule_GetState(module); + assert(state != NULL); + return (WinApiState *)state; +} /* * A Python object wrapping an OVERLAPPED structure and other useful data @@ -100,12 +113,27 @@ typedef struct { Py_buffer write_buffer; } OverlappedObject; +/* +Note: tp_clear (overlapped_clear) is not implemented because it +requires cancelling the IO operation if it's pending and the cancellation is +quite complex and can fail (see: overlapped_dealloc). +*/ +static int +overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->read_buffer); + Py_VISIT(self->write_buffer.obj); + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void overlapped_dealloc(OverlappedObject *self) { DWORD bytes; int err = GetLastError(); + PyObject_GC_UnTrack(self); if (self->pending) { if (check_CancelIoEx() && Py_CancelIoEx(self->handle, &self->overlapped) && @@ -141,12 +169,14 @@ overlapped_dealloc(OverlappedObject *self) if (self->write_buffer.obj) PyBuffer_Release(&self->write_buffer); Py_CLEAR(self->read_buffer); - PyObject_Del(self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(self); + Py_DECREF(tp); } /*[clinic input] module _winapi -class _winapi.Overlapped "OverlappedObject *" "&WinApiOverlappedType" +class _winapi.Overlapped "OverlappedObject *" "&OverlappedType" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=c13d3f5fd1dabb84]*/ @@ -165,10 +195,11 @@ create_converter('LPCVOID', '" F_POINTER "') create_converter('BOOL', 'i') # F_BOOL used previously (always 'i') create_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter) create_converter('LPCTSTR', 's') -create_converter('LPCWSTR', 'u') -create_converter('LPWSTR', 'u') create_converter('UINT', 'I') # F_UINT used previously (always 'I') +class LPCWSTR_converter(Py_UNICODE_converter): + type = 'LPCWSTR' + class HANDLE_return_converter(CReturnConverter): type = 'HANDLE' @@ -198,7 +229,7 @@ class LPVOID_return_converter(CReturnConverter): data.return_conversion.append( 'return_value = HANDLE_TO_PYNUM(_return_value);\n') [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=79464c61a31ae932]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=011ee0c3a2244bfe]*/ #include "clinic/_winapi.c.h" @@ -305,55 +336,31 @@ static PyMemberDef overlapped_members[] = { {NULL} }; -PyTypeObject WinApiOverlappedType = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_winapi.Overlapped", - /* tp_basicsize */ sizeof(OverlappedObject), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor) overlapped_dealloc, - /* tp_vectorcall_offset */ 0, - /* tp_getattr */ 0, - /* tp_setattr */ 0, - /* tp_as_async */ 0, - /* tp_repr */ 0, - /* tp_as_number */ 0, - /* tp_as_sequence */ 0, - /* tp_as_mapping */ 0, - /* tp_hash */ 0, - /* tp_call */ 0, - /* tp_str */ 0, - /* tp_getattro */ 0, - /* tp_setattro */ 0, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT, - /* tp_doc */ "OVERLAPPED structure wrapper", - /* tp_traverse */ 0, - /* tp_clear */ 0, - /* tp_richcompare */ 0, - /* tp_weaklistoffset */ 0, - /* tp_iter */ 0, - /* tp_iternext */ 0, - /* tp_methods */ overlapped_methods, - /* tp_members */ overlapped_members, - /* tp_getset */ 0, - /* tp_base */ 0, - /* tp_dict */ 0, - /* tp_descr_get */ 0, - /* tp_descr_set */ 0, - /* tp_dictoffset */ 0, - /* tp_init */ 0, - /* tp_alloc */ 0, - /* tp_new */ 0, +static PyType_Slot winapi_overlapped_type_slots[] = { + {Py_tp_traverse, overlapped_traverse}, + {Py_tp_dealloc, overlapped_dealloc}, + {Py_tp_doc, "OVERLAPPED structure wrapper"}, + {Py_tp_methods, overlapped_methods}, + {Py_tp_members, overlapped_members}, + {0,0} +}; + +static PyType_Spec winapi_overlapped_type_spec = { + .name = "_winapi.Overlapped", + .basicsize = sizeof(OverlappedObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), + .slots = winapi_overlapped_type_slots, }; static OverlappedObject * -new_overlapped(HANDLE handle) +new_overlapped(PyObject *module, HANDLE handle) { - OverlappedObject *self; - - self = PyObject_New(OverlappedObject, &WinApiOverlappedType); + WinApiState *st = winapi_get_state(module); + OverlappedObject *self = PyObject_GC_New(OverlappedObject, st->overlapped_type); if (!self) return NULL; + self->handle = handle; self->read_buffer = NULL; self->pending = 0; @@ -362,6 +369,8 @@ new_overlapped(HANDLE handle) memset(&self->write_buffer, 0, sizeof(Py_buffer)); /* Manual reset, initially non-signalled */ self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + PyObject_GC_Track(self); return self; } @@ -409,7 +418,7 @@ _winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle, OverlappedObject *overlapped = NULL; if (use_overlapped) { - overlapped = new_overlapped(handle); + overlapped = new_overlapped(module, handle); if (!overlapped) return NULL; } @@ -521,15 +530,15 @@ _winapi_CreateFileMapping_impl(PyObject *module, HANDLE file_handle, /*[clinic input] _winapi.CreateJunction - src_path: LPWSTR - dst_path: LPWSTR + src_path: LPCWSTR + dst_path: LPCWSTR / [clinic start generated code]*/ static PyObject * -_winapi_CreateJunction_impl(PyObject *module, LPWSTR src_path, - LPWSTR dst_path) -/*[clinic end generated code: output=66b7eb746e1dfa25 input=8cd1f9964b6e3d36]*/ +_winapi_CreateJunction_impl(PyObject *module, LPCWSTR src_path, + LPCWSTR dst_path) +/*[clinic end generated code: output=44b3f5e9bbcc4271 input=963d29b44b9384a7]*/ { /* Privilege adjustment */ HANDLE token = NULL; @@ -1527,7 +1536,7 @@ _winapi_ReadFile_impl(PyObject *module, HANDLE handle, DWORD size, if (!buf) return NULL; if (use_overlapped) { - overlapped = new_overlapped(handle); + overlapped = new_overlapped(module, handle); if (!overlapped) { Py_DECREF(buf); return NULL; @@ -1810,7 +1819,7 @@ _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer, OverlappedObject *overlapped = NULL; if (use_overlapped) { - overlapped = new_overlapped(handle); + overlapped = new_overlapped(module, handle); if (!overlapped) return NULL; buf = &overlapped->write_buffer; @@ -1886,6 +1895,113 @@ _winapi_GetFileType_impl(PyObject *module, HANDLE handle) return result; } +/*[clinic input] +_winapi._mimetypes_read_windows_registry + + on_type_read: object + +Optimized function for reading all known MIME types from the registry. + +*on_type_read* is a callable taking *type* and *ext* arguments, as for +MimeTypes.add_type. +[clinic start generated code]*/ + +static PyObject * +_winapi__mimetypes_read_windows_registry_impl(PyObject *module, + PyObject *on_type_read) +/*[clinic end generated code: output=20829f00bebce55b input=cd357896d6501f68]*/ +{ +#define CCH_EXT 128 +#define CB_TYPE 510 + struct { + wchar_t ext[CCH_EXT]; + wchar_t type[CB_TYPE / sizeof(wchar_t) + 1]; + } entries[64]; + int entry = 0; + HKEY hkcr = NULL; + LRESULT err; + + Py_BEGIN_ALLOW_THREADS + err = RegOpenKeyExW(HKEY_CLASSES_ROOT, NULL, 0, KEY_READ, &hkcr); + for (DWORD i = 0; err == ERROR_SUCCESS || err == ERROR_MORE_DATA; ++i) { + LPWSTR ext = entries[entry].ext; + LPWSTR type = entries[entry].type; + DWORD cchExt = CCH_EXT; + DWORD cbType = CB_TYPE; + HKEY subkey; + DWORD regType; + + err = RegEnumKeyExW(hkcr, i, ext, &cchExt, NULL, NULL, NULL, NULL); + if (err != ERROR_SUCCESS || (cchExt && ext[0] != L'.')) { + continue; + } + + err = RegOpenKeyExW(hkcr, ext, 0, KEY_READ, &subkey); + if (err == ERROR_FILE_NOT_FOUND) { + err = ERROR_SUCCESS; + continue; + } else if (err != ERROR_SUCCESS) { + continue; + } + + err = RegQueryValueExW(subkey, L"Content Type", NULL, + ®Type, (LPBYTE)type, &cbType); + RegCloseKey(subkey); + if (err == ERROR_FILE_NOT_FOUND) { + err = ERROR_SUCCESS; + continue; + } else if (err != ERROR_SUCCESS) { + continue; + } else if (regType != REG_SZ || !cbType) { + continue; + } + type[cbType / sizeof(wchar_t)] = L'\0'; + + entry += 1; + + /* Flush our cached entries if we are full */ + if (entry == sizeof(entries) / sizeof(entries[0])) { + Py_BLOCK_THREADS + for (int j = 0; j < entry; ++j) { + PyObject *r = PyObject_CallFunction( + on_type_read, "uu", entries[j].type, entries[j].ext + ); + if (!r) { + /* We blocked threads, so safe to return from here */ + RegCloseKey(hkcr); + return NULL; + } + Py_DECREF(r); + } + Py_UNBLOCK_THREADS + entry = 0; + } + } + if (hkcr) { + RegCloseKey(hkcr); + } + Py_END_ALLOW_THREADS + + if (err != ERROR_SUCCESS && err != ERROR_NO_MORE_ITEMS) { + PyErr_SetFromWindowsErr((int)err); + return NULL; + } + + for (int j = 0; j < entry; ++j) { + PyObject *r = PyObject_CallFunction( + on_type_read, "uu", entries[j].type, entries[j].ext + ); + if (!r) { + return NULL; + } + Py_DECREF(r); + } + + Py_RETURN_NONE; +#undef CCH_EXT +#undef CB_TYPE +} + static PyMethodDef winapi_functions[] = { _WINAPI_CLOSEHANDLE_METHODDEF @@ -1918,39 +2034,37 @@ static PyMethodDef winapi_functions[] = { _WINAPI_WRITEFILE_METHODDEF _WINAPI_GETACP_METHODDEF _WINAPI_GETFILETYPE_METHODDEF + _WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF {NULL, NULL} }; -static struct PyModuleDef winapi_module = { - PyModuleDef_HEAD_INIT, - "_winapi", - NULL, - -1, - winapi_functions, - NULL, - NULL, - NULL, - NULL -}; - #define WINAPI_CONSTANT(fmt, con) \ - PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con)) + do { \ + PyObject *value = Py_BuildValue(fmt, con); \ + if (value == NULL) { \ + return -1; \ + } \ + if (PyDict_SetItemString(d, #con, value) < 0) { \ + Py_DECREF(value); \ + return -1; \ + } \ + Py_DECREF(value); \ + } while (0) -PyMODINIT_FUNC -PyInit__winapi(void) +static int winapi_exec(PyObject *m) { - PyObject *d; - PyObject *m; + WinApiState *st = winapi_get_state(m); - if (PyType_Ready(&WinApiOverlappedType) < 0) - return NULL; + st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec(m, &winapi_overlapped_type_spec, NULL); + if (st->overlapped_type == NULL) { + return -1; + } - m = PyModule_Create(&winapi_module); - if (m == NULL) - return NULL; - d = PyModule_GetDict(m); + if (PyModule_AddType(m, st->overlapped_type) < 0) { + return -1; + } - PyDict_SetItemString(d, "Overlapped", (PyObject *) &WinApiOverlappedType); + PyObject *d = PyModule_GetDict(m); /* constants */ WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE); @@ -2049,5 +2163,49 @@ PyInit__winapi(void) WINAPI_CONSTANT("i", NULL); - return m; + return 0; +} + +static PyModuleDef_Slot winapi_slots[] = { + {Py_mod_exec, winapi_exec}, + {0, NULL} +}; + +static int +winapi_traverse(PyObject *module, visitproc visit, void *arg) +{ + WinApiState *st = winapi_get_state(module); + Py_VISIT(st->overlapped_type); + return 0; +} + +static int +winapi_clear(PyObject *module) +{ + WinApiState *st = winapi_get_state(module); + Py_CLEAR(st->overlapped_type); + return 0; +} + +static void +winapi_free(void *module) +{ + winapi_clear((PyObject *)module); +} + +static struct PyModuleDef winapi_module = { + PyModuleDef_HEAD_INIT, + .m_name = "_winapi", + .m_size = sizeof(WinApiState), + .m_methods = winapi_functions, + .m_slots = winapi_slots, + .m_traverse = winapi_traverse, + .m_clear = winapi_clear, + .m_free = winapi_free, +}; + +PyMODINIT_FUNC +PyInit__winapi(void) +{ + return PyModuleDef_Init(&winapi_module); } |
