See :ref:`above <exception-changed>`.
+.. function:: DeleteTree(key, sub_key=None)
+
+ Deletes the specified key and all its subkeys and values recursively.
+
+ *key* is an already open key, or one of the predefined
+ :ref:`HKEY_* constants <hkey-constants>`.
+
+ *sub_key* is a string that names the subkey to delete. If ``None``,
+ deletes all subkeys and values of the specified key.
+
+ This function deletes a key and all its descendants. If *sub_key* is
+ ``None``, all subkeys and values of the specified key are deleted.
+
+ .. audit-event:: winreg.DeleteTree key,sub_key winreg.DeleteTree
+
+ .. versionadded:: next
+
+
.. function:: DeleteValue(key, value)
Removes a named value from a registry key.
with self.assertRaises(FileNotFoundError) as ctx:
QueryValue(HKEY_CLASSES_ROOT, 'some_value_that_does_not_exist')
+ def test_delete_tree(self):
+ with CreateKey(HKEY_CURRENT_USER, test_key_name) as main_key:
+ with CreateKey(main_key, "subkey1") as subkey1:
+ SetValueEx(subkey1, "value1", 0, REG_SZ, "test_value1")
+ with CreateKey(subkey1, "subsubkey1") as subsubkey1:
+ SetValueEx(subsubkey1, "value2", 0, REG_DWORD, 42)
+
+ with CreateKey(main_key, "subkey2") as subkey2:
+ SetValueEx(subkey2, "value3", 0, REG_SZ, "test_value3")
+
+ DeleteTree(HKEY_CURRENT_USER, test_key_name)
+
+ with self.assertRaises(OSError):
+ OpenKey(HKEY_CURRENT_USER, test_key_name)
+
if __name__ == "__main__":
if not REMOTE_NAME:
--- /dev/null
+Add :func:`winreg.DeleteTree`.
#if (defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM) || defined(MS_WINDOWS_GAMES)) && (defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM))
+PyDoc_STRVAR(winreg_DeleteTree__doc__,
+"DeleteTree($module, key, sub_key=None, /)\n"
+"--\n"
+"\n"
+"Deletes the specified key and all its subkeys and values recursively.\n"
+"\n"
+" key\n"
+" An already open key, or any one of the predefined HKEY_* constants.\n"
+" sub_key\n"
+" A string that names the subkey to delete. If None, deletes all subkeys\n"
+" and values of the specified key.\n"
+"\n"
+"This function deletes a key and all its descendants. If sub_key is None,\n"
+"all subkeys and values of the specified key are deleted.");
+
+#define WINREG_DELETETREE_METHODDEF \
+ {"DeleteTree", _PyCFunction_CAST(winreg_DeleteTree), METH_FASTCALL, winreg_DeleteTree__doc__},
+
+static PyObject *
+winreg_DeleteTree_impl(PyObject *module, HKEY key, const wchar_t *sub_key);
+
+static PyObject *
+winreg_DeleteTree(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ HKEY key;
+ const wchar_t *sub_key = NULL;
+
+ if (!_PyArg_CheckPositional("DeleteTree", nargs, 1, 2)) {
+ goto exit;
+ }
+ if (!clinic_HKEY_converter(_PyModule_GetState(module), args[0], &key)) {
+ goto exit;
+ }
+ if (nargs < 2) {
+ goto skip_optional;
+ }
+ if (args[1] == Py_None) {
+ sub_key = NULL;
+ }
+ else if (PyUnicode_Check(args[1])) {
+ sub_key = PyUnicode_AsWideCharString(args[1], NULL);
+ if (sub_key == NULL) {
+ goto exit;
+ }
+ }
+ else {
+ _PyArg_BadArgument("DeleteTree", "argument 2", "str or None", args[1]);
+ goto exit;
+ }
+skip_optional:
+ return_value = winreg_DeleteTree_impl(module, key, sub_key);
+
+exit:
+ /* Cleanup for sub_key */
+ PyMem_Free((void *)sub_key);
+
+ return return_value;
+}
+
+#endif /* (defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM) || defined(MS_WINDOWS_GAMES)) && (defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)) */
+
+#if (defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM) || defined(MS_WINDOWS_GAMES)) && (defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM))
+
PyDoc_STRVAR(winreg_QueryReflectionKey__doc__,
"QueryReflectionKey($module, key, /)\n"
"--\n"
#define WINREG_ENABLEREFLECTIONKEY_METHODDEF
#endif /* !defined(WINREG_ENABLEREFLECTIONKEY_METHODDEF) */
+#ifndef WINREG_DELETETREE_METHODDEF
+ #define WINREG_DELETETREE_METHODDEF
+#endif /* !defined(WINREG_DELETETREE_METHODDEF) */
+
#ifndef WINREG_QUERYREFLECTIONKEY_METHODDEF
#define WINREG_QUERYREFLECTIONKEY_METHODDEF
#endif /* !defined(WINREG_QUERYREFLECTIONKEY_METHODDEF) */
-/*[clinic end generated code: output=be4b6857b95558b5 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=ce7e8e38884851fb input=a9049054013a1b77]*/
Py_RETURN_NONE;
}
+/*[clinic input]
+winreg.DeleteTree
+
+ key: HKEY
+ An already open key, or any one of the predefined HKEY_* constants.
+ sub_key: Py_UNICODE(accept={str, NoneType}) = None
+ A string that names the subkey to delete. If None, deletes all subkeys
+ and values of the specified key.
+ /
+
+Deletes the specified key and all its subkeys and values recursively.
+
+This function deletes a key and all its descendants. If sub_key is None,
+all subkeys and values of the specified key are deleted.
+[clinic start generated code]*/
+
+static PyObject *
+winreg_DeleteTree_impl(PyObject *module, HKEY key, const wchar_t *sub_key)
+/*[clinic end generated code: output=c34395ee59290501 input=419ef9bb8b06e4bf]*/
+{
+ LONG rc;
+
+ if (PySys_Audit("winreg.DeleteTree", "nu",
+ (Py_ssize_t)key, sub_key) < 0) {
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegDeleteTreeW(key, sub_key);
+ Py_END_ALLOW_THREADS
+
+ if (rc != ERROR_SUCCESS) {
+ PyErr_SetFromWindowsErrWithFunction(rc, "RegDeleteTreeW");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
/*[clinic input]
winreg.QueryReflectionKey
WINREG_DELETEKEY_METHODDEF
WINREG_DELETEKEYEX_METHODDEF
WINREG_DELETEVALUE_METHODDEF
+ WINREG_DELETETREE_METHODDEF
WINREG_DISABLEREFLECTIONKEY_METHODDEF
WINREG_ENABLEREFLECTIONKEY_METHODDEF
WINREG_ENUMKEY_METHODDEF