summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Modules/_winapi.c
diff options
context:
space:
mode:
authorshadchin <[email protected]>2022-04-18 12:39:32 +0300
committershadchin <[email protected]>2022-04-18 12:39:32 +0300
commitd4be68e361f4258cf0848fc70018dfe37a2acc24 (patch)
tree153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Modules/_winapi.c
parent260c02f5ccf242d9d9b8a873afaf6588c00237d6 (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.c320
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,
+ &regType, (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);
}