diff --git a/Doc/library/winreg.rst b/Doc/library/winreg.rst index b3a824fb69a49f..a566855ecaa42c 100644 --- a/Doc/library/winreg.rst +++ b/Doc/library/winreg.rst @@ -85,7 +85,7 @@ This module offers the following functions: See :ref:`above `. -.. function:: CreateKeyEx(key, sub_key, reserved=0, access=KEY_WRITE) +.. function:: CreateKeyEx(key, sub_key, reserved=0, access=KEY_WRITE, options=0, create_only=False) Creates or opens the specified key, returning a :ref:`handle object `. @@ -101,6 +101,13 @@ This module offers the following functions: security access for the key. Default is :const:`KEY_WRITE`. See :ref:`Access Rights ` for other allowed values. + *options* is an interger and can be zero or one of the predefined + :ref:`REG_OPTION_* constants `. + + *create_only* is a boolean. + When set to True, a :exc:`FileExistsError` will be raised + if the key is already exists. Default is ``False``. + If *key* is one of the predefined keys, *sub_key* may be ``None``. In that case, the handle returned is the same key handle passed in to the function. @@ -300,7 +307,6 @@ This module offers the following functions: .. function:: OpenKey(key, sub_key, reserved=0, access=KEY_READ) - OpenKeyEx(key, sub_key, reserved=0, access=KEY_READ) Opens the specified key, returning a :ref:`handle object `. @@ -309,7 +315,11 @@ This module offers the following functions: *sub_key* is a string that identifies the sub_key to open. - *reserved* is a reserved integer, and must be zero. The default is zero. + *reserved* is a reserved integer and should be zero. If it is not zero, + it will be treated as the options parameter in :func:`OpenKeyEx`. + You should use the :func:`OpenKeyEx` directly instead in this case, + this parameter is only included for compatibility reasons. + The default value is zero. *access* is an integer that specifies an access mask that describes the desired security access for the key. Default is :const:`KEY_READ`. See :ref:`Access @@ -329,6 +339,54 @@ This module offers the following functions: .. versionchanged:: 3.3 See :ref:`above `. + .. deprecated-removed:: 3.14 3.16 + *reserved* is deprecated and will be removed in the future. + Please use :func:`OpenKeyEx` instead. + +.. function:: OpenKeyEx(key, sub_key, options=0, access=KEY_READ, reserved=0) + + Opens the specified key, returning a :ref:`handle object `. + + *key* is an already open key, or one of the predefined + :ref:`HKEY_* constants `. + + *sub_key* is a string that identifies the sub_key to open. + + *access* is an integer that specifies an access mask that describes the desired + security access for the key. Default is :const:`KEY_READ`. See :ref:`Access + Rights ` for other allowed values. + + *options* specifies the option to apply when opening the key. + Can be zero or one of the predefined + :ref:`REG_OPTION_* constants `. + + *reserved* is a reserved integer and should be zero. + If it is not zero, it will be treated as the options parameter. + You should use the *options* parameter directly instead, + this parameter is only included for compatibility reasons. + The default value is zero. + + The result is a new handle to the specified key. + + If the function fails, :exc:`OSError` is raised. + + .. audit-event:: winreg.OpenKey key,sub_key,access winreg.OpenKey + + .. audit-event:: winreg.OpenKey/result key winreg.OpenKey + + .. versionchanged:: 3.2 + Allow the use of named arguments. + + .. versionchanged:: 3.3 + See :ref:`above `. + + .. versionchanged:: 3.14 + Added *options* parameter. + + .. deprecated-removed:: 3.14 3.16 + *reserved* is deprecated and will be removed in the future. + Please use *options* instead. + .. function:: QueryInfoKey(key) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 90214a314031d1..187c978375b539 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -873,6 +873,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(coro)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(count)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(covariant)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(create_only)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cwd)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(data)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(database)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 97a75d0c46c867..79819df7e7d9b0 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -362,6 +362,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(coro) STRUCT_FOR_ID(count) STRUCT_FOR_ID(covariant) + STRUCT_FOR_ID(create_only) STRUCT_FOR_ID(cwd) STRUCT_FOR_ID(data) STRUCT_FOR_ID(database) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 4f928cc050bf8e..2a103937a721b8 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -871,6 +871,7 @@ extern "C" { INIT_ID(coro), \ INIT_ID(count), \ INIT_ID(covariant), \ + INIT_ID(create_only), \ INIT_ID(cwd), \ INIT_ID(data), \ INIT_ID(database), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 5b78d038fc1192..e55abacac68adb 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -1244,6 +1244,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(create_only); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(cwd); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py index 924a962781a75b..7fb706f6b3577a 100644 --- a/Lib/test/test_winreg.py +++ b/Lib/test/test_winreg.py @@ -228,6 +228,33 @@ def test_registry_works_extended_functions(self): self._delete_test_data(HKEY_CURRENT_USER) + def test_registry_works_with_options(self): + ckeo = lambda key, sub_key: CreateKeyEx(key, sub_key, 0, KEY_ALL_ACCESS, + options=REG_OPTION_VOLATILE) + self._write_test_data(HKEY_CURRENT_USER, CreateKey=ckeo) + + okeo = lambda key, sub_key: OpenKeyEx(key, sub_key, REG_OPTION_VOLATILE, + KEY_READ) + self._read_test_data(HKEY_CURRENT_USER, OpenKey=okeo) + + with self.assertWarns(DeprecationWarning): + okeo = lambda key, sub_key: OpenKeyEx(key, sub_key, + reserved=REG_OPTION_VOLATILE) + self._read_test_data(HKEY_CURRENT_USER, OpenKey=okeo) + + with self.assertWarns(DeprecationWarning): + ok = lambda key, sub_key: OpenKey(key, sub_key, + reserved=REG_OPTION_VOLATILE) + self._read_test_data(HKEY_CURRENT_USER, OpenKey=ok) + + self._delete_test_data(HKEY_CURRENT_USER) + + def test_create_only(self): + CreateKeyEx(HKEY_CURRENT_USER, test_key_name) + with self.assertRaises(FileExistsError): + CreateKeyEx(HKEY_CURRENT_USER, test_key_name, create_only=True) + DeleteKey(HKEY_CURRENT_USER, test_key_name) + def test_named_arguments(self): self._test_named_args(HKEY_CURRENT_USER, test_key_name) # Use the regular DeleteKey to clean up diff --git a/Misc/NEWS.d/next/Windows/2025-02-10-00-00-00.gh-issue-95461.rBmMaH.rst b/Misc/NEWS.d/next/Windows/2025-02-10-00-00-00.gh-issue-95461.rBmMaH.rst new file mode 100644 index 00000000000000..5861aab1f47b06 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2025-02-10-00-00-00.gh-issue-95461.rBmMaH.rst @@ -0,0 +1,2 @@ +Add *options* and *create_only* parameters to :meth:`winreg.CreateKeyEx`. +Add *options* parameter to :meth:`winreg.OpenKeyEx`. diff --git a/PC/clinic/winreg.c.h b/PC/clinic/winreg.c.h index 00fa6a75ec113e..5c806b8e27da15 100644 --- a/PC/clinic/winreg.c.h +++ b/PC/clinic/winreg.c.h @@ -284,7 +284,7 @@ winreg_CreateKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs) PyDoc_STRVAR(winreg_CreateKeyEx__doc__, "CreateKeyEx($module, /, key, sub_key, reserved=0,\n" -" access=winreg.KEY_WRITE)\n" +" access=winreg.KEY_WRITE, options=0, create_only=False)\n" "--\n" "\n" "Creates or opens the specified key.\n" @@ -298,6 +298,11 @@ PyDoc_STRVAR(winreg_CreateKeyEx__doc__, " access\n" " An integer that specifies an access mask that describes the\n" " desired security access for the key. Default is KEY_WRITE.\n" +" options\n" +" Can be one of the REG_OPTION_* constants.\n" +" create_only\n" +" When set to True, raise FileExistsError if the key is already exists.\n" +" Default is False.\n" "\n" "If key is one of the predefined keys, sub_key may be None. In that case,\n" "the handle returned is the same key handle passed in to the function.\n" @@ -312,7 +317,8 @@ PyDoc_STRVAR(winreg_CreateKeyEx__doc__, static HKEY winreg_CreateKeyEx_impl(PyObject *module, HKEY key, const wchar_t *sub_key, - int reserved, REGSAM access); + int reserved, REGSAM access, int options, + int create_only); static PyObject * winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -320,14 +326,14 @@ winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 4 + #define NUM_KEYWORDS 6 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD PyObject *ob_item[NUM_KEYWORDS]; } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(key), &_Py_ID(sub_key), &_Py_ID(reserved), &_Py_ID(access), }, + .ob_item = { &_Py_ID(key), &_Py_ID(sub_key), &_Py_ID(reserved), &_Py_ID(access), &_Py_ID(options), &_Py_ID(create_only), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -336,23 +342,25 @@ winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL}; + static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", "options", "create_only", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "CreateKeyEx", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[4]; + PyObject *argsbuf[6]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; HKEY key; const wchar_t *sub_key = NULL; int reserved = 0; REGSAM access = KEY_WRITE; + int options = 0; + int create_only = 0; HKEY _return_value; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, - /*minpos*/ 2, /*maxpos*/ 4, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + /*minpos*/ 2, /*maxpos*/ 6, /*minkw*/ 0, /*varpos*/ 0, argsbuf); if (!args) { goto exit; } @@ -384,12 +392,30 @@ winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py goto skip_optional_pos; } } - access = PyLong_AsInt(args[3]); - if (access == -1 && PyErr_Occurred()) { + if (args[3]) { + access = PyLong_AsInt(args[3]); + if (access == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[4]) { + options = PyLong_AsInt(args[4]); + if (options == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + create_only = PyObject_IsTrue(args[5]); + if (create_only < 0) { goto exit; } skip_optional_pos: - _return_value = winreg_CreateKeyEx_impl(module, key, sub_key, reserved, access); + _return_value = winreg_CreateKeyEx_impl(module, key, sub_key, reserved, access, options, create_only); if (_return_value == NULL) { goto exit; } @@ -916,7 +942,9 @@ PyDoc_STRVAR(winreg_OpenKey__doc__, " sub_key\n" " A string that identifies the sub_key to open.\n" " reserved\n" -" A reserved integer that must be zero. Default is zero.\n" +" A reserved integer that be should zero. If it is not zero,\n" +" it will be used as the options parameter in OpenKeyEx.\n" +" You should use OpenKeyEx directly in this case.\n" " access\n" " An integer that specifies an access mask that describes the desired\n" " security access for the key. Default is KEY_READ.\n" @@ -1024,7 +1052,8 @@ winreg_OpenKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #if (defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM) || defined(MS_WINDOWS_GAMES)) PyDoc_STRVAR(winreg_OpenKeyEx__doc__, -"OpenKeyEx($module, /, key, sub_key, reserved=0, access=winreg.KEY_READ)\n" +"OpenKeyEx($module, /, key, sub_key, options=0, access=winreg.KEY_READ,\n" +" reserved=0)\n" "--\n" "\n" "Opens the specified key.\n" @@ -1033,11 +1062,15 @@ PyDoc_STRVAR(winreg_OpenKeyEx__doc__, " An already open key, or any one of the predefined HKEY_* constants.\n" " sub_key\n" " A string that identifies the sub_key to open.\n" -" reserved\n" -" A reserved integer that must be zero. Default is zero.\n" +" options\n" +" Can be one of the REG_OPTION_* constants.\n" " access\n" " An integer that specifies an access mask that describes the desired\n" " security access for the key. Default is KEY_READ.\n" +" reserved\n" +" A reserved integer that be should zero. If it is not zero,\n" +" it will be used as the options parameter for compatibility reasons.\n" +" Default is zero.\n" "\n" "The result is a new handle to the specified key.\n" "If the function fails, an OSError exception is raised."); @@ -1047,7 +1080,7 @@ PyDoc_STRVAR(winreg_OpenKeyEx__doc__, static HKEY winreg_OpenKeyEx_impl(PyObject *module, HKEY key, const wchar_t *sub_key, - int reserved, REGSAM access); + int options, REGSAM access, int reserved); static PyObject * winreg_OpenKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1055,14 +1088,14 @@ winreg_OpenKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 4 + #define NUM_KEYWORDS 5 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD PyObject *ob_item[NUM_KEYWORDS]; } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(key), &_Py_ID(sub_key), &_Py_ID(reserved), &_Py_ID(access), }, + .ob_item = { &_Py_ID(key), &_Py_ID(sub_key), &_Py_ID(options), &_Py_ID(access), &_Py_ID(reserved), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -1071,23 +1104,24 @@ winreg_OpenKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL}; + static const char * const _keywords[] = {"key", "sub_key", "options", "access", "reserved", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "OpenKeyEx", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[4]; + PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; HKEY key; const wchar_t *sub_key = NULL; - int reserved = 0; + int options = 0; REGSAM access = KEY_READ; + int reserved = 0; HKEY _return_value; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, - /*minpos*/ 2, /*maxpos*/ 4, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + /*minpos*/ 2, /*maxpos*/ 5, /*minkw*/ 0, /*varpos*/ 0, argsbuf); if (!args) { goto exit; } @@ -1111,20 +1145,29 @@ winreg_OpenKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } if (args[2]) { - reserved = PyLong_AsInt(args[2]); - if (reserved == -1 && PyErr_Occurred()) { + options = PyLong_AsInt(args[2]); + if (options == -1 && PyErr_Occurred()) { goto exit; } if (!--noptargs) { goto skip_optional_pos; } } - access = PyLong_AsInt(args[3]); - if (access == -1 && PyErr_Occurred()) { + if (args[3]) { + access = PyLong_AsInt(args[3]); + if (access == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + reserved = PyLong_AsInt(args[4]); + if (reserved == -1 && PyErr_Occurred()) { goto exit; } skip_optional_pos: - _return_value = winreg_OpenKeyEx_impl(module, key, sub_key, reserved, access); + _return_value = winreg_OpenKeyEx_impl(module, key, sub_key, options, access, reserved); if (_return_value == NULL) { goto exit; } @@ -1766,4 +1809,4 @@ winreg_QueryReflectionKey(PyObject *module, PyObject *arg) #ifndef WINREG_QUERYREFLECTIONKEY_METHODDEF #define WINREG_QUERYREFLECTIONKEY_METHODDEF #endif /* !defined(WINREG_QUERYREFLECTIONKEY_METHODDEF) */ -/*[clinic end generated code: output=fbe9b075cd2fa833 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=67346bb47df95b6b input=a9049054013a1b77]*/ diff --git a/PC/winreg.c b/PC/winreg.c index efdf8addc06186..3ecac8a5df78a7 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -950,6 +950,11 @@ winreg.CreateKeyEx -> HKEY access: REGSAM(c_default='KEY_WRITE') = winreg.KEY_WRITE An integer that specifies an access mask that describes the desired security access for the key. Default is KEY_WRITE. + options: int = 0 + Can be one of the REG_OPTION_* constants. + create_only: bool = False + When set to True, raise FileExistsError if the key is already exists. + Default is False. Creates or opens the specified key. @@ -964,23 +969,35 @@ If the function fails, an OSError exception is raised. static HKEY winreg_CreateKeyEx_impl(PyObject *module, HKEY key, const wchar_t *sub_key, - int reserved, REGSAM access) -/*[clinic end generated code: output=51b53e38d5e00d4b input=42c2b03f98406b66]*/ + int reserved, REGSAM access, int options, + int create_only) +/*[clinic end generated code: output=10c0a5f7beea07e3 input=23d740b8cd7fb0df]*/ { HKEY retKey; long rc; + DWORD disposition; if (PySys_Audit("winreg.CreateKey", "nun", (Py_ssize_t)key, sub_key, (Py_ssize_t)access) < 0) { return NULL; } - rc = RegCreateKeyExW(key, sub_key, reserved, NULL, 0, - access, NULL, &retKey, NULL); + rc = RegCreateKeyExW(key, sub_key, reserved, NULL, options, + access, NULL, &retKey, &disposition); if (rc != ERROR_SUCCESS) { PyErr_SetFromWindowsErrWithFunction(rc, "CreateKeyEx"); return NULL; } + if (create_only) { + if (disposition == REG_OPENED_EXISTING_KEY) { + PyErr_SetFromWindowsErrWithFunction(ERROR_ALREADY_EXISTS, "CreateKeyEx"); + if (retKey != key) { + // This is not a predefined key and needs to be closed. + RegCloseKey(key); + } + return NULL; + } + } if (PySys_Audit("winreg.OpenKey/result", "n", (Py_ssize_t)retKey) < 0) { return NULL; @@ -1394,7 +1411,9 @@ winreg.OpenKey -> HKEY sub_key: Py_UNICODE(accept={str, NoneType}) A string that identifies the sub_key to open. reserved: int = 0 - A reserved integer that must be zero. Default is zero. + A reserved integer that be should zero. If it is not zero, + it will be used as the options parameter in OpenKeyEx. + You should use OpenKeyEx directly in this case. access: REGSAM(c_default='KEY_READ') = winreg.KEY_READ An integer that specifies an access mask that describes the desired security access for the key. Default is KEY_READ. @@ -1408,7 +1427,38 @@ If the function fails, an OSError exception is raised. static HKEY winreg_OpenKey_impl(PyObject *module, HKEY key, const wchar_t *sub_key, int reserved, REGSAM access) -/*[clinic end generated code: output=5efbad23b3ffe2e7 input=098505ac36a9ae28]*/ +/*[clinic end generated code: output=5efbad23b3ffe2e7 input=8bafb91546317c8e]*/ +{ + return winreg_OpenKeyEx_impl(module, key, sub_key, 0, access, reserved); +} + +/*[clinic input] +winreg.OpenKeyEx -> HKEY + + key: HKEY + An already open key, or any one of the predefined HKEY_* constants. + sub_key: Py_UNICODE(accept={str, NoneType}) + A string that identifies the sub_key to open. + options: int = 0 + Can be one of the REG_OPTION_* constants. + access: REGSAM(c_default='KEY_READ') = winreg.KEY_READ + An integer that specifies an access mask that describes the desired + security access for the key. Default is KEY_READ. + reserved: int = 0 + A reserved integer that be should zero. If it is not zero, + it will be used as the options parameter for compatibility reasons. + Default is zero. + +Opens the specified key. + +The result is a new handle to the specified key. +If the function fails, an OSError exception is raised. +[clinic start generated code]*/ + +static HKEY +winreg_OpenKeyEx_impl(PyObject *module, HKEY key, const wchar_t *sub_key, + int options, REGSAM access, int reserved) +/*[clinic end generated code: output=db8d3dc70876a046 input=d997970b48ac2e30]*/ { HKEY retKey; long rc; @@ -1418,6 +1468,14 @@ winreg_OpenKey_impl(PyObject *module, HKEY key, const wchar_t *sub_key, (Py_ssize_t)access) < 0) { return NULL; } + if (reserved != 0) { + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "reserved is deprecated, use options instead.", 1)) + { + return NULL; + } + options = reserved; + } Py_BEGIN_ALLOW_THREADS rc = RegOpenKeyExW(key, sub_key, reserved, access, &retKey); Py_END_ALLOW_THREADS @@ -1432,23 +1490,6 @@ winreg_OpenKey_impl(PyObject *module, HKEY key, const wchar_t *sub_key, return retKey; } -/*[clinic input] -winreg.OpenKeyEx = winreg.OpenKey - -Opens the specified key. - -The result is a new handle to the specified key. -If the function fails, an OSError exception is raised. -[clinic start generated code]*/ - -static HKEY -winreg_OpenKeyEx_impl(PyObject *module, HKEY key, const wchar_t *sub_key, - int reserved, REGSAM access) -/*[clinic end generated code: output=435e675800fa78c2 input=c6c4972af8622959]*/ -{ - return winreg_OpenKey_impl(module, key, sub_key, reserved, access); -} - /*[clinic input] winreg.QueryInfoKey