From d83faf7f1ba2de95e98e3eeb5ce9009d9cd62192 Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 18 Apr 2023 02:30:48 +0800 Subject: [PATCH] gh-103092: Isolate winreg (#103250) --- Lib/test/test_winreg.py | 16 +- ...-04-08-00-48-40.gh-issue-103092.5EFts0.rst | 1 + Objects/object.c | 6 - PC/clinic/winreg.c.h | 54 ++-- PC/winreg.c | 271 ++++++++++-------- 5 files changed, 196 insertions(+), 152 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-04-08-00-48-40.gh-issue-103092.5EFts0.rst diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py index 769ab67b0f5..924a962781a 100644 --- a/Lib/test/test_winreg.py +++ b/Lib/test/test_winreg.py @@ -1,11 +1,12 @@ # Test the windows specific win32reg module. # Only win32reg functions not hit here: FlushKey, LoadKey and SaveKey +import gc import os, sys, errno -import unittest -from test.support import import_helper import threading +import unittest from platform import machine, win32_edition +from test.support import cpython_only, import_helper # Do this first so test will be skipped if module doesn't exist import_helper.import_module('winreg', required_on=['win']) @@ -49,6 +50,17 @@ test_data = [ ("Japanese 日本", "日本語", REG_SZ), ] + +@cpython_only +class HeapTypeTests(unittest.TestCase): + def test_have_gc(self): + self.assertTrue(gc.is_tracked(HKEYType)) + + def test_immutable(self): + with self.assertRaisesRegex(TypeError, "immutable"): + HKEYType.foo = "bar" + + class BaseWinregTests(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS.d/next/Library/2023-04-08-00-48-40.gh-issue-103092.5EFts0.rst b/Misc/NEWS.d/next/Library/2023-04-08-00-48-40.gh-issue-103092.5EFts0.rst new file mode 100644 index 00000000000..0f2108fee76 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-08-00-48-40.gh-issue-103092.5EFts0.rst @@ -0,0 +1 @@ +Adapt the :mod:`winreg` extension module to :pep:`687`. diff --git a/Objects/object.c b/Objects/object.c index 56747fa193e..e26f737fccd 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1965,9 +1965,6 @@ PyObject _Py_NotImplementedStruct = { 1, &_PyNotImplemented_Type }; -#ifdef MS_WINDOWS -extern PyTypeObject PyHKEY_Type; -#endif extern PyTypeObject _Py_GenericAliasIterType; extern PyTypeObject _PyMemoryIter_Type; extern PyTypeObject _PyLineIterator; @@ -2018,9 +2015,6 @@ static PyTypeObject* static_types[] = { &PyFunction_Type, &PyGen_Type, &PyGetSetDescr_Type, -#ifdef MS_WINDOWS - &PyHKEY_Type, -#endif &PyInstanceMethod_Type, &PyListIter_Type, &PyListRevIter_Type, diff --git a/PC/clinic/winreg.c.h b/PC/clinic/winreg.c.h index 7a9474301da..4109c85276f 100644 --- a/PC/clinic/winreg.c.h +++ b/PC/clinic/winreg.c.h @@ -219,14 +219,14 @@ winreg_ConnectRegistry(PyObject *module, PyObject *const *args, Py_ssize_t nargs _PyArg_BadArgument("ConnectRegistry", "argument 1", "str or None", args[0]); goto exit; } - if (!clinic_HKEY_converter(args[1], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[1], &key)) { goto exit; } _return_value = winreg_ConnectRegistry_impl(module, computer_name, key); if (_return_value == NULL) { goto exit; } - return_value = PyHKEY_FromHKEY(_return_value); + return_value = PyHKEY_FromHKEY(_PyModule_GetState(module), _return_value); exit: /* Cleanup for computer_name */ @@ -275,7 +275,7 @@ winreg_CreateKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("CreateKey", nargs, 2, 2)) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (args[1] == Py_None) { @@ -295,7 +295,7 @@ winreg_CreateKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (_return_value == NULL) { goto exit; } - return_value = PyHKEY_FromHKEY(_return_value); + return_value = PyHKEY_FromHKEY(_PyModule_GetState(module), _return_value); exit: /* Cleanup for sub_key */ @@ -382,7 +382,7 @@ winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py if (!args) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (args[1] == Py_None) { @@ -419,7 +419,7 @@ skip_optional_pos: if (_return_value == NULL) { goto exit; } - return_value = PyHKEY_FromHKEY(_return_value); + return_value = PyHKEY_FromHKEY(_PyModule_GetState(module), _return_value); exit: /* Cleanup for sub_key */ @@ -466,7 +466,7 @@ winreg_DeleteKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("DeleteKey", nargs, 2, 2)) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (!PyUnicode_Check(args[1])) { @@ -566,7 +566,7 @@ winreg_DeleteKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py if (!args) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (!PyUnicode_Check(args[1])) { @@ -634,7 +634,7 @@ winreg_DeleteValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("DeleteValue", nargs, 2, 2)) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (args[1] == Py_None) { @@ -694,7 +694,7 @@ winreg_EnumKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("EnumKey", nargs, 2, 2)) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } index = _PyLong_AsInt(args[1]); @@ -751,7 +751,7 @@ winreg_EnumValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("EnumValue", nargs, 2, 2)) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } index = _PyLong_AsInt(args[1]); @@ -839,7 +839,7 @@ winreg_FlushKey(PyObject *module, PyObject *arg) PyObject *return_value = NULL; HKEY key; - if (!clinic_HKEY_converter(arg, &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), arg, &key)) { goto exit; } return_value = winreg_FlushKey_impl(module, key); @@ -898,7 +898,7 @@ winreg_LoadKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("LoadKey", nargs, 3, 3)) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (!PyUnicode_Check(args[1])) { @@ -999,7 +999,7 @@ winreg_OpenKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje if (!args) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (args[1] == Py_None) { @@ -1036,7 +1036,7 @@ skip_optional_pos: if (_return_value == NULL) { goto exit; } - return_value = PyHKEY_FromHKEY(_return_value); + return_value = PyHKEY_FromHKEY(_PyModule_GetState(module), _return_value); exit: /* Cleanup for sub_key */ @@ -1116,7 +1116,7 @@ winreg_OpenKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb if (!args) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (args[1] == Py_None) { @@ -1153,7 +1153,7 @@ skip_optional_pos: if (_return_value == NULL) { goto exit; } - return_value = PyHKEY_FromHKEY(_return_value); + return_value = PyHKEY_FromHKEY(_PyModule_GetState(module), _return_value); exit: /* Cleanup for sub_key */ @@ -1193,7 +1193,7 @@ winreg_QueryInfoKey(PyObject *module, PyObject *arg) PyObject *return_value = NULL; HKEY key; - if (!clinic_HKEY_converter(arg, &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), arg, &key)) { goto exit; } return_value = winreg_QueryInfoKey_impl(module, key); @@ -1242,7 +1242,7 @@ winreg_QueryValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("QueryValue", nargs, 2, 2)) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (args[1] == Py_None) { @@ -1303,7 +1303,7 @@ winreg_QueryValueEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("QueryValueEx", nargs, 2, 2)) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (args[1] == Py_None) { @@ -1369,7 +1369,7 @@ winreg_SaveKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("SaveKey", nargs, 2, 2)) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (!PyUnicode_Check(args[1])) { @@ -1438,7 +1438,7 @@ winreg_SetValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("SetValue", nargs, 4, 4)) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (args[1] == Py_None) { @@ -1542,7 +1542,7 @@ winreg_SetValueEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("SetValueEx", nargs, 5, 5)) { goto exit; } - if (!clinic_HKEY_converter(args[0], &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) { goto exit; } if (args[1] == Py_None) { @@ -1603,7 +1603,7 @@ winreg_DisableReflectionKey(PyObject *module, PyObject *arg) PyObject *return_value = NULL; HKEY key; - if (!clinic_HKEY_converter(arg, &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), arg, &key)) { goto exit; } return_value = winreg_DisableReflectionKey_impl(module, key); @@ -1641,7 +1641,7 @@ winreg_EnableReflectionKey(PyObject *module, PyObject *arg) PyObject *return_value = NULL; HKEY key; - if (!clinic_HKEY_converter(arg, &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), arg, &key)) { goto exit; } return_value = winreg_EnableReflectionKey_impl(module, key); @@ -1677,7 +1677,7 @@ winreg_QueryReflectionKey(PyObject *module, PyObject *arg) PyObject *return_value = NULL; HKEY key; - if (!clinic_HKEY_converter(arg, &key)) { + if (!clinic_HKEY_converter(_PyModule_GetState(module), arg, &key)) { goto exit; } return_value = winreg_QueryReflectionKey_impl(module, key); @@ -1795,4 +1795,4 @@ exit: #ifndef WINREG_QUERYREFLECTIONKEY_METHODDEF #define WINREG_QUERYREFLECTIONKEY_METHODDEF #endif /* !defined(WINREG_QUERYREFLECTIONKEY_METHODDEF) */ -/*[clinic end generated code: output=715db416dc1321ee input=a9049054013a1b77]*/ +/*[clinic end generated code: output=15dc2e6c4d4e2ad5 input=a9049054013a1b77]*/ diff --git a/PC/winreg.c b/PC/winreg.c index 15d32e7fcb9..4884125c360 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -15,15 +15,22 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" #include "pycore_object.h" // _PyObject_Init() +#include "pycore_moduleobject.h" #include "structmember.h" // PyMemberDef #include #if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM) || defined(MS_WINDOWS_GAMES) -static BOOL PyHKEY_AsHKEY(PyObject *ob, HKEY *pRes, BOOL bNoneOK); -static BOOL clinic_HKEY_converter(PyObject *ob, void *p); -static PyObject *PyHKEY_FromHKEY(HKEY h); -static BOOL PyHKEY_Close(PyObject *obHandle); +typedef struct { + PyTypeObject *PyHKEY_Type; +} winreg_state; + +/* Forward declares */ + +static BOOL PyHKEY_AsHKEY(winreg_state *st, PyObject *ob, HKEY *pRes, BOOL bNoneOK); +static BOOL clinic_HKEY_converter(winreg_state *st, PyObject *ob, void *p); +static PyObject *PyHKEY_FromHKEY(winreg_state *st, HKEY h); +static BOOL PyHKEY_Close(winreg_state *st, PyObject *obHandle); static char errNotAHandle[] = "Object is not a handle"; @@ -35,8 +42,6 @@ static char errNotAHandle[] = "Object is not a handle"; #define PyErr_SetFromWindowsErrWithFunction(rc, fnname) \ PyErr_SetFromWindowsErr(rc) -/* Forward declares */ - /* Doc strings */ PyDoc_STRVAR(module_doc, "This module provides access to the Windows registry API.\n" @@ -114,7 +119,7 @@ typedef struct { HKEY hkey; } PyHKEYObject; -#define PyHKEY_Check(op) Py_IS_TYPE(op, &PyHKEY_Type) +#define PyHKEY_Check(st, op) Py_IS_TYPE(op, st->PyHKEY_Type) static char *failMsg = "bad operand type"; @@ -147,7 +152,18 @@ PyHKEY_deallocFunc(PyObject *ob) PyHKEYObject *obkey = (PyHKEYObject *)ob; if (obkey->hkey) RegCloseKey((HKEY)obkey->hkey); - PyObject_Free(ob); + + PyTypeObject *tp = Py_TYPE(ob); + PyObject_GC_UnTrack(ob); + PyObject_GC_Del(ob); + Py_DECREF(tp); +} + +static int +PyHKEY_traverseFunc(PyHKEYObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; } static int @@ -189,29 +205,6 @@ PyHKEY_hashFunc(PyObject *ob) } -static PyNumberMethods PyHKEY_NumberMethods = -{ - PyHKEY_binaryFailureFunc, /* nb_add */ - PyHKEY_binaryFailureFunc, /* nb_subtract */ - PyHKEY_binaryFailureFunc, /* nb_multiply */ - PyHKEY_binaryFailureFunc, /* nb_remainder */ - PyHKEY_binaryFailureFunc, /* nb_divmod */ - PyHKEY_ternaryFailureFunc, /* nb_power */ - PyHKEY_unaryFailureFunc, /* nb_negative */ - PyHKEY_unaryFailureFunc, /* nb_positive */ - PyHKEY_unaryFailureFunc, /* nb_absolute */ - PyHKEY_boolFunc, /* nb_bool */ - PyHKEY_unaryFailureFunc, /* nb_invert */ - PyHKEY_binaryFailureFunc, /* nb_lshift */ - PyHKEY_binaryFailureFunc, /* nb_rshift */ - PyHKEY_binaryFailureFunc, /* nb_and */ - PyHKEY_binaryFailureFunc, /* nb_xor */ - PyHKEY_binaryFailureFunc, /* nb_or */ - PyHKEY_intFunc, /* nb_int */ - 0, /* nb_reserved */ - PyHKEY_unaryFailureFunc, /* nb_float */ -}; - /*[clinic input] module winreg class winreg.HKEYType "PyHKEYObject *" "&PyHKEY_Type" @@ -229,6 +222,14 @@ class HKEY_converter(CConverter): type = 'HKEY' converter = 'clinic_HKEY_converter' + def parse_arg(self, argname, displayname): + return """ + if (!{converter}(_PyModule_GetState(module), {argname}, &{paramname})) {{{{ + goto exit; + }}}} + """.format(argname=argname, paramname=self.parser_name, + converter=self.converter) + class HKEY_return_converter(CReturnConverter): type = 'HKEY' @@ -236,7 +237,7 @@ class HKEY_return_converter(CReturnConverter): self.declare(data) self.err_occurred_if_null_pointer("_return_value", data) data.return_conversion.append( - 'return_value = PyHKEY_FromHKEY(_return_value);\n') + 'return_value = PyHKEY_FromHKEY(_PyModule_GetState(module), _return_value);\n') # HACK: this only works for PyHKEYObjects, nothing else. # Should this be generalized and enshrined in clinic.py, @@ -249,7 +250,7 @@ class self_return_converter(CReturnConverter): data.return_conversion.append( 'return_value = (PyObject *)_return_value;\n') [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=2ebb7a4922d408d6]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=17e645060c7b8ae1]*/ #include "clinic/winreg.c.h" @@ -270,8 +271,11 @@ static PyObject * winreg_HKEYType_Close_impl(PyHKEYObject *self) /*[clinic end generated code: output=fced3a624fb0c344 input=6786ac75f6b89de6]*/ { - if (!PyHKEY_Close((PyObject *)self)) + winreg_state *st = _PyType_GetModuleState(Py_TYPE(self)); + assert(st != NULL); + if (!PyHKEY_Close(st, (PyObject *)self)) { return NULL; + } Py_RETURN_NONE; } @@ -327,8 +331,11 @@ winreg_HKEYType___exit___impl(PyHKEYObject *self, PyObject *exc_type, PyObject *exc_value, PyObject *traceback) /*[clinic end generated code: output=923ebe7389e6a263 input=fb32489ee92403c7]*/ { - if (!PyHKEY_Close((PyObject *)self)) + winreg_state *st = _PyType_GetModuleState(Py_TYPE(self)); + assert(st != NULL); + if (!PyHKEY_Close(st, (PyObject *)self)) { return NULL; + } Py_RETURN_NONE; } @@ -350,62 +357,71 @@ static PyMemberDef PyHKEY_memberlist[] = { {NULL} /* Sentinel */ }; -/* The type itself */ -PyTypeObject PyHKEY_Type = -{ - PyVarObject_HEAD_INIT(0, 0) /* fill in type at module init */ - "PyHKEY", - sizeof(PyHKEYObject), - 0, - PyHKEY_deallocFunc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - &PyHKEY_NumberMethods, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - PyHKEY_hashFunc, /* tp_hash */ - 0, /* tp_call */ - PyHKEY_strFunc, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - 0, /* tp_flags */ - PyHKEY_doc, /* tp_doc */ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - PyHKEY_methods, /*tp_methods*/ - PyHKEY_memberlist, /*tp_members*/ +static PyType_Slot pyhkey_type_slots[] = { + {Py_tp_dealloc, PyHKEY_deallocFunc}, + {Py_tp_members, PyHKEY_memberlist}, + {Py_tp_methods, PyHKEY_methods}, + {Py_tp_doc, (char *)PyHKEY_doc}, + {Py_tp_traverse, PyHKEY_traverseFunc}, + {Py_tp_hash, PyHKEY_hashFunc}, + {Py_tp_str, PyHKEY_strFunc}, + + // Number protocol + {Py_nb_add, PyHKEY_binaryFailureFunc}, + {Py_nb_subtract, PyHKEY_binaryFailureFunc}, + {Py_nb_multiply, PyHKEY_binaryFailureFunc}, + {Py_nb_remainder, PyHKEY_binaryFailureFunc}, + {Py_nb_divmod, PyHKEY_binaryFailureFunc}, + {Py_nb_power, PyHKEY_ternaryFailureFunc}, + {Py_nb_negative, PyHKEY_unaryFailureFunc}, + {Py_nb_positive, PyHKEY_unaryFailureFunc}, + {Py_nb_absolute, PyHKEY_unaryFailureFunc}, + {Py_nb_bool, PyHKEY_boolFunc}, + {Py_nb_invert, PyHKEY_unaryFailureFunc}, + {Py_nb_lshift, PyHKEY_binaryFailureFunc}, + {Py_nb_rshift, PyHKEY_binaryFailureFunc}, + {Py_nb_and, PyHKEY_binaryFailureFunc}, + {Py_nb_xor, PyHKEY_binaryFailureFunc}, + {Py_nb_or, PyHKEY_binaryFailureFunc}, + {Py_nb_int, PyHKEY_intFunc}, + {Py_nb_float, PyHKEY_unaryFailureFunc}, + {0, NULL}, +}; + +static PyType_Spec pyhkey_type_spec = { + .name = "winreg.PyHKEY", + .basicsize = sizeof(PyHKEYObject), + .flags = (Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_DISALLOW_INSTANTIATION), + .slots = pyhkey_type_slots, }; /************************************************************************ The public PyHKEY API (well, not public yet :-) ************************************************************************/ PyObject * -PyHKEY_New(HKEY hInit) +PyHKEY_New(PyObject *m, HKEY hInit) { - PyHKEYObject *key = PyObject_New(PyHKEYObject, &PyHKEY_Type); - if (key) - key->hkey = hInit; + winreg_state *st = _PyModule_GetState(m); + PyHKEYObject *key = PyObject_GC_New(PyHKEYObject, st->PyHKEY_Type); + if (key == NULL) { + return NULL; + } + key->hkey = hInit; + PyObject_GC_Track(key); return (PyObject *)key; } BOOL -PyHKEY_Close(PyObject *ob_handle) +PyHKEY_Close(winreg_state *st, PyObject *ob_handle) { LONG rc; HKEY key; - if (!PyHKEY_AsHKEY(ob_handle, &key, TRUE)) { + if (!PyHKEY_AsHKEY(st, ob_handle, &key, TRUE)) { return FALSE; } - if (PyHKEY_Check(ob_handle)) { + if (PyHKEY_Check(st, ob_handle)) { ((PyHKEYObject*)ob_handle)->hkey = 0; } rc = key ? RegCloseKey(key) : ERROR_SUCCESS; @@ -415,7 +431,7 @@ PyHKEY_Close(PyObject *ob_handle) } BOOL -PyHKEY_AsHKEY(PyObject *ob, HKEY *pHANDLE, BOOL bNoneOK) +PyHKEY_AsHKEY(winreg_state *st, PyObject *ob, HKEY *pHANDLE, BOOL bNoneOK) { if (ob == Py_None) { if (!bNoneOK) { @@ -426,7 +442,7 @@ PyHKEY_AsHKEY(PyObject *ob, HKEY *pHANDLE, BOOL bNoneOK) } *pHANDLE = (HKEY)0; } - else if (PyHKEY_Check(ob)) { + else if (PyHKEY_Check(st ,ob)) { PyHKEYObject *pH = (PyHKEYObject *)ob; *pHANDLE = pH->hkey; } @@ -447,23 +463,24 @@ PyHKEY_AsHKEY(PyObject *ob, HKEY *pHANDLE, BOOL bNoneOK) } BOOL -clinic_HKEY_converter(PyObject *ob, void *p) +clinic_HKEY_converter(winreg_state *st, PyObject *ob, void *p) { - if (!PyHKEY_AsHKEY(ob, (HKEY *)p, FALSE)) + if (!PyHKEY_AsHKEY(st, ob, (HKEY *)p, FALSE)) { return FALSE; + } return TRUE; } PyObject * -PyHKEY_FromHKEY(HKEY h) +PyHKEY_FromHKEY(winreg_state *st, HKEY h) { - /* Inline PyObject_New */ - PyHKEYObject *op = (PyHKEYObject *) PyObject_Malloc(sizeof(PyHKEYObject)); + PyHKEYObject *op = (PyHKEYObject *)PyObject_GC_New(PyHKEYObject, + st->PyHKEY_Type); if (op == NULL) { - return PyErr_NoMemory(); + return NULL; } - _PyObject_Init((PyObject*)op, &PyHKEY_Type); op->hkey = h; + PyObject_GC_Track(op); return (PyObject *)op; } @@ -472,11 +489,11 @@ PyHKEY_FromHKEY(HKEY h) The module methods ************************************************************************/ BOOL -PyWinObject_CloseHKEY(PyObject *obHandle) +PyWinObject_CloseHKEY(winreg_state *st, PyObject *obHandle) { BOOL ok; - if (PyHKEY_Check(obHandle)) { - ok = PyHKEY_Close(obHandle); + if (PyHKEY_Check(st, obHandle)) { + ok = PyHKEY_Close(st, obHandle); } #if SIZEOF_LONG >= SIZEOF_HKEY else if (PyLong_Check(obHandle)) { @@ -826,8 +843,9 @@ static PyObject * winreg_CloseKey(PyObject *module, PyObject *hkey) /*[clinic end generated code: output=a4fa537019a80d15 input=5b1aac65ba5127ad]*/ { - if (!PyHKEY_Close(hkey)) + if (!PyHKEY_Close(_PyModule_GetState(module), hkey)) { return NULL; + } Py_RETURN_NONE; } @@ -2061,7 +2079,7 @@ static struct PyMethodDef winreg_methods[] = { #define ADD_INT(VAL) do { \ if (PyModule_AddIntConstant(m, #VAL, VAL) < 0) { \ - goto error; \ + return -1; \ } \ } while (0) @@ -2079,38 +2097,25 @@ inskey(PyObject *mod, char *name, HKEY key) #define ADD_KEY(VAL) do { \ if (inskey(m, #VAL, VAL) < 0) { \ - goto error; \ + return -1; \ } \ } while (0) - -static struct PyModuleDef winregmodule = { - PyModuleDef_HEAD_INIT, - "winreg", - module_doc, - -1, - winreg_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC PyInit_winreg(void) +static int +exec_module(PyObject *m) { - PyObject *m = PyModule_Create(&winregmodule); - if (m == NULL) { - return NULL; + winreg_state *st = (winreg_state *)_PyModule_GetState(m); + + st->PyHKEY_Type = (PyTypeObject *) + PyType_FromModuleAndSpec(m, &pyhkey_type_spec, NULL); + if (st->PyHKEY_Type == NULL) { + return -1; } - PyHKEY_Type.tp_doc = PyHKEY_doc; - if (PyType_Ready(&PyHKEY_Type) < 0) { - goto error; - } - if (PyModule_AddObjectRef(m, "HKEYType", (PyObject *)&PyHKEY_Type) < 0) { - goto error; + if (PyModule_AddObjectRef(m, "HKEYType", (PyObject *)st->PyHKEY_Type) < 0) { + return -1; } if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) { - goto error; + return -1; } /* Add the relevant constants */ @@ -2174,12 +2179,44 @@ PyMODINIT_FUNC PyInit_winreg(void) ADD_INT(REG_RESOURCE_REQUIREMENTS_LIST); #undef ADD_INT + return 0; +} - return m; +static PyModuleDef_Slot winreg_slots[] = { + {Py_mod_exec, exec_module}, + {0, NULL} +}; -error: - Py_DECREF(m); - return NULL; +static int +winreg_traverse(PyObject *module, visitproc visit, void *arg) +{ + winreg_state *state = _PyModule_GetState(module); + Py_VISIT(state->PyHKEY_Type); + return 0; +} + +static int +winreg_clear(PyObject *module) +{ + winreg_state *state = _PyModule_GetState(module); + Py_CLEAR(state->PyHKEY_Type); + return 0; +} + +static struct PyModuleDef winregmodule = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "winreg", + .m_doc = module_doc, + .m_size = sizeof(winreg_state), + .m_methods = winreg_methods, + .m_slots = winreg_slots, + .m_traverse = winreg_traverse, + .m_clear = winreg_clear, +}; + +PyMODINIT_FUNC PyInit_winreg(void) +{ + return PyModuleDef_Init(&winregmodule); } #endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM || MS_WINDOWS_GAMES */