Implement #7347. Add CreateKeyEx, DeleteKeyEx, and update _winreg tests.

*ReflectionKey functions used to not be documented or tested, but they are
now sufficiently documented and tested on platforms where they apply.
Additionally, fixed a bug in QueryReflectionKey which was returning an
incorrect value.

All tests pass from XP through Windows 7, on 32 and 64-bit platforms.
This commit is contained in:
Brian Curtin 2010-04-02 21:18:14 +00:00
parent ef253ac84e
commit e33fa887d3
3 changed files with 386 additions and 38 deletions

View file

@ -89,7 +89,7 @@ PyDoc_STRVAR(ConnectRegistry_doc,
"key is the predefined handle to connect to.\n"
"\n"
"The return value is the handle of the opened key.\n"
"If the function fails, an EnvironmentError exception is raised.");
"If the function fails, a WindowsError exception is raised.");
PyDoc_STRVAR(CreateKey_doc,
"key = CreateKey(key, sub_key) - Creates or opens the specified key.\n"
@ -104,6 +104,21 @@ PyDoc_STRVAR(CreateKey_doc,
"The return value is the handle of the opened key.\n"
"If the function fails, an exception is raised.");
PyDoc_STRVAR(CreateKeyEx_doc,
"key = CreateKeyEx(key, sub_key, res, sam) - Creates or opens the specified key.\n"
"\n"
"key is an already open key, or one of the predefined HKEY_* constants\n"
"sub_key is a string that names the key this method opens or creates.\n"
"res is a reserved integer, and must be zero. Default is zero.\n"
"sam is an integer that specifies an access mask that describes the desired\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"
"\n"
"If the key already exists, this function opens the existing key\n"
"\n"
"The return value is the handle of the opened key.\n"
"If the function fails, an exception is raised.");
PyDoc_STRVAR(DeleteKey_doc,
"DeleteKey(key, sub_key) - Deletes the specified key.\n"
"\n"
@ -114,7 +129,22 @@ PyDoc_STRVAR(DeleteKey_doc,
"This method can not delete keys with subkeys.\n"
"\n"
"If the method succeeds, the entire key, including all of its values,\n"
"is removed. If the method fails, an EnvironmentError exception is raised.");
"is removed. If the method fails, a WindowsError exception is raised.");
PyDoc_STRVAR(DeleteKeyEx_doc,
"DeleteKeyEx(key, sub_key, sam, res) - Deletes the specified key.\n"
"\n"
"key is an already open key, or any one of the predefined HKEY_* constants.\n"
"sub_key is a string that must be a subkey of the key identified by the key parameter.\n"
"res is a reserved integer, and must be zero. Default is zero.\n"
"sam is an integer that specifies an access mask that describes the desired\n"
" This value must not be None, and the key may not have subkeys.\n"
"\n"
"This method can not delete keys with subkeys.\n"
"\n"
"If the method succeeds, the entire key, including all of its values,\n"
"is removed. If the method fails, a WindowsError exception is raised.\n"
"On unsupported Windows versions, NotImplementedError is raised.");
PyDoc_STRVAR(DeleteValue_doc,
"DeleteValue(key, value) - Removes a named value from a registry key.\n"
@ -129,7 +159,7 @@ PyDoc_STRVAR(EnumKey_doc,
"index is an integer that identifies the index of the key to retrieve.\n"
"\n"
"The function retrieves the name of one subkey each time it is called.\n"
"It is typically called repeatedly until an EnvironmentError exception is\n"
"It is typically called repeatedly until a WindowsError exception is\n"
"raised, indicating no more values are available.");
PyDoc_STRVAR(EnumValue_doc,
@ -138,7 +168,7 @@ PyDoc_STRVAR(EnumValue_doc,
"index is an integer that identifies the index of the value to retrieve.\n"
"\n"
"The function retrieves the name of one subkey each time it is called.\n"
"It is typically called repeatedly, until an EnvironmentError exception\n"
"It is typically called repeatedly, until a WindowsError exception\n"
"is raised, indicating no more values.\n"
"\n"
"The result is a tuple of 3 items:\n"
@ -192,7 +222,7 @@ PyDoc_STRVAR(OpenKey_doc,
" security access for the key. Default is KEY_READ\n"
"\n"
"The result is a new handle to the specified key\n"
"If the function fails, an EnvironmentError exception is raised.");
"If the function fails, a WindowsError exception is raised.");
PyDoc_STRVAR(OpenKeyEx_doc, "See OpenKey()");
@ -1013,6 +1043,29 @@ PyCreateKey(PyObject *self, PyObject *args)
return PyHKEY_FromHKEY(retKey);
}
static PyObject *
PyCreateKeyEx(PyObject *self, PyObject *args)
{
HKEY hKey;
PyObject *obKey;
char *subKey;
HKEY retKey;
int res = 0;
REGSAM sam = KEY_WRITE;
long rc;
if (!PyArg_ParseTuple(args, "Oz|ii:CreateKeyEx", &obKey, &subKey,
&res, &sam))
return NULL;
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL;
rc = RegCreateKeyEx(hKey, subKey, res, NULL, (DWORD)NULL,
sam, NULL, &retKey, NULL);
if (rc != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, "CreateKeyEx");
return PyHKEY_FromHKEY(retKey);
}
static PyObject *
PyDeleteKey(PyObject *self, PyObject *args)
{
@ -1031,6 +1084,46 @@ PyDeleteKey(PyObject *self, PyObject *args)
return Py_None;
}
static PyObject *
PyDeleteKeyEx(PyObject *self, PyObject *args)
{
HKEY hKey;
PyObject *obKey;
HMODULE hMod;
typedef LONG (WINAPI *RDKEFunc)(HKEY, const char*, REGSAM, int);
RDKEFunc pfn = NULL;
char *subKey;
long rc;
int res = 0;
REGSAM sam = KEY_WOW64_64KEY;
if (!PyArg_ParseTuple(args, "Os|ii:DeleteKeyEx",
&obKey, &subKey, &sam, &res))
return NULL;
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL;
/* Only available on 64bit platforms, so we must load it
dynamically. */
hMod = GetModuleHandle("advapi32.dll");
if (hMod)
pfn = (RDKEFunc)GetProcAddress(hMod,
"RegDeleteKeyExA");
if (!pfn) {
PyErr_SetString(PyExc_NotImplementedError,
"not implemented on this platform");
return NULL;
}
Py_BEGIN_ALLOW_THREADS
rc = (*pfn)(hKey, subKey, sam, res);
Py_END_ALLOW_THREADS
if (rc != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, "RegDeleteKeyEx");
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
PyDeleteValue(PyObject *self, PyObject *args)
{
@ -1479,8 +1572,8 @@ PyDisableReflectionKey(PyObject *self, PyObject *args)
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL;
// Only available on 64bit platforms, so we must load it
// dynamically.
/* Only available on 64bit platforms, so we must load it
dynamically. */
hMod = GetModuleHandle("advapi32.dll");
if (hMod)
pfn = (RDRKFunc)GetProcAddress(hMod,
@ -1515,8 +1608,8 @@ PyEnableReflectionKey(PyObject *self, PyObject *args)
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL;
// Only available on 64bit platforms, so we must load it
// dynamically.
/* Only available on 64bit platforms, so we must load it
dynamically. */
hMod = GetModuleHandle("advapi32.dll");
if (hMod)
pfn = (RERKFunc)GetProcAddress(hMod,
@ -1552,8 +1645,8 @@ PyQueryReflectionKey(PyObject *self, PyObject *args)
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL;
// Only available on 64bit platforms, so we must load it
// dynamically.
/* Only available on 64bit platforms, so we must load it
dynamically. */
hMod = GetModuleHandle("advapi32.dll");
if (hMod)
pfn = (RQRKFunc)GetProcAddress(hMod,
@ -1569,14 +1662,16 @@ PyQueryReflectionKey(PyObject *self, PyObject *args)
if (rc != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryReflectionKey");
return PyBool_FromLong(rc);
return PyBool_FromLong(result);
}
static struct PyMethodDef winreg_methods[] = {
{"CloseKey", PyCloseKey, METH_VARARGS, CloseKey_doc},
{"ConnectRegistry", PyConnectRegistry, METH_VARARGS, ConnectRegistry_doc},
{"CreateKey", PyCreateKey, METH_VARARGS, CreateKey_doc},
{"CreateKeyEx", PyCreateKeyEx, METH_VARARGS, CreateKeyEx_doc},
{"DeleteKey", PyDeleteKey, METH_VARARGS, DeleteKey_doc},
{"DeleteKeyEx", PyDeleteKeyEx, METH_VARARGS, DeleteKeyEx_doc},
{"DeleteValue", PyDeleteValue, METH_VARARGS, DeleteValue_doc},
{"DisableReflectionKey", PyDisableReflectionKey, METH_VARARGS, DisableReflectionKey_doc},
{"EnableReflectionKey", PyEnableReflectionKey, METH_VARARGS, EnableReflectionKey_doc},