Port #7347 to py3k.

Add CreateKeyEx and DeleteKeyEx, along with test improvements.
diff --git a/PC/winreg.c b/PC/winreg.c
index 7e8ea10..e37256d 100644
--- a/PC/winreg.c
+++ b/PC/winreg.c
@@ -88,7 +88,7 @@
 "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"
@@ -103,6 +103,21 @@
 "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"
@@ -113,7 +128,22 @@
 "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"
@@ -128,7 +158,7 @@
 "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,
@@ -137,7 +167,7 @@
 "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"
@@ -191,7 +221,7 @@
 " 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()");
 
@@ -957,6 +987,29 @@
 }
 
 static PyObject *
+PyCreateKeyEx(PyObject *self, PyObject *args)
+{
+	HKEY hKey;
+	PyObject *obKey;
+	wchar_t *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 = RegCreateKeyExW(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)
 {
 	HKEY hKey;
@@ -975,6 +1028,46 @@
 }
 
 static PyObject *
+PyDeleteKeyEx(PyObject *self, PyObject *args)
+{
+	HKEY hKey;
+	PyObject *obKey;
+	HMODULE hMod;
+	typedef LONG (WINAPI *RDKEFunc)(HKEY, const wchar_t*, REGSAM, int);
+	RDKEFunc pfn = NULL;
+	wchar_t *subKey;
+	long rc;
+	int res = 0;
+	REGSAM sam = KEY_WOW64_64KEY;
+
+	if (!PyArg_ParseTuple(args, "Ou|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,
+									   "RegDeleteKeyExW");
+	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)
 {
 	HKEY hKey;
@@ -1412,8 +1505,8 @@
 	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,
@@ -1448,8 +1541,8 @@
 	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,
@@ -1485,8 +1578,8 @@
 	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,
@@ -1502,14 +1595,16 @@
 	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},