]> granicus.if.org Git - python/commitdiff
Patch #1076: Use wide API for registry functions.
authorMartin v. Löwis <martin@v.loewis.de>
Mon, 3 Sep 2007 07:43:05 +0000 (07:43 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Mon, 3 Sep 2007 07:43:05 +0000 (07:43 +0000)
Lib/test/test_winreg.py
PC/_winreg.c

index aaa57c974477ca3c18b6324c93dfb5e6b974f456..7b1baf89e733d848271a4a7f9801fcdc986a456a 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Test the windows specific win32reg module.
 # Only win32reg functions not hit here: FlushKey, LoadKey and SaveKey
 
@@ -17,17 +18,19 @@ test_data = [
     ("Raw Data",      b"binary\x00data",                       REG_BINARY),
     ("Big String",    "x"*(2**14-1),                           REG_SZ),
     ("Big Binary",    b"x"*(2**14),                            REG_BINARY),
+    # Two and three kanjis, meaning: "Japan" and "Japanese")
+    ("Japanese 日本", "日本語", REG_SZ),
 ]
 
 class WinregTests(unittest.TestCase):
     remote_name = None
 
-    def WriteTestData(self, root_key):
+    def WriteTestData(self, root_key, subkeystr="sub_key"):
         # Set the default value for this key.
         SetValue(root_key, test_key_name, REG_SZ, "Default value")
         key = CreateKey(root_key, test_key_name)
         # Create a sub-key
-        sub_key = CreateKey(key, "sub_key")
+        sub_key = CreateKey(key, subkeystr)
         # Give the sub-key some named values
 
         for value_name, value_data, value_type in test_data:
@@ -62,7 +65,7 @@ class WinregTests(unittest.TestCase):
         except EnvironmentError:
             pass
 
-    def ReadTestData(self, root_key):
+    def ReadTestData(self, root_key, subkeystr="sub_key"):
         # Check we can get default value for this key.
         val = QueryValue(root_key, test_key_name)
         self.assertEquals(val, "Default value",
@@ -70,7 +73,7 @@ class WinregTests(unittest.TestCase):
 
         key = OpenKey(root_key, test_key_name)
         # Read the sub-keys
-        sub_key = OpenKey(key, "sub_key")
+        sub_key = OpenKey(key, subkeystr)
         # Check I can enumerate over the values.
         index = 0
         while 1:
@@ -93,7 +96,7 @@ class WinregTests(unittest.TestCase):
         sub_key.Close()
         # Enumerate our main key.
         read_val = EnumKey(key, 0)
-        self.assertEquals(read_val, "sub_key", "Read subkey value wrong")
+        self.assertEquals(read_val, subkeystr, "Read subkey value wrong")
         try:
             EnumKey(key, 1)
             self.fail("Was able to get a second key when I only have one!")
@@ -102,9 +105,9 @@ class WinregTests(unittest.TestCase):
 
         key.Close()
 
-    def DeleteTestData(self, root_key):
+    def DeleteTestData(self, root_key, subkeystr="sub_key"):
         key = OpenKey(root_key, test_key_name, 0, KEY_ALL_ACCESS)
-        sub_key = OpenKey(key, "sub_key", 0, KEY_ALL_ACCESS)
+        sub_key = OpenKey(key, subkeystr, 0, KEY_ALL_ACCESS)
         # It is not necessary to delete the values before deleting
         # the key (although subkeys must not exist).  We delete them
         # manually just to prove we can :-)
@@ -115,11 +118,11 @@ class WinregTests(unittest.TestCase):
         self.assertEquals(nkeys, 0, "subkey not empty before delete")
         self.assertEquals(nvalues, 0, "subkey not empty before delete")
         sub_key.Close()
-        DeleteKey(key, "sub_key")
+        DeleteKey(key, subkeystr)
 
         try:
             # Shouldnt be able to delete it twice!
-            DeleteKey(key, "sub_key")
+            DeleteKey(key, subkeystr)
             self.fail("Deleting the key twice succeeded")
         except EnvironmentError:
             pass
@@ -132,13 +135,14 @@ class WinregTests(unittest.TestCase):
         except WindowsError: # Use this error name this time
             pass
 
-    def TestAll(self, root_key):
-        self.WriteTestData(root_key)
-        self.ReadTestData(root_key)
-        self.DeleteTestData(root_key)
+    def TestAll(self, root_key, subkeystr="sub_key"):
+        self.WriteTestData(root_key, subkeystr)
+        self.ReadTestData(root_key, subkeystr)
+        self.DeleteTestData(root_key, subkeystr)
 
     def testLocalMachineRegistryWorks(self):
         self.TestAll(HKEY_CURRENT_USER)
+        self.TestAll(HKEY_CURRENT_USER, "日本-subkey")
 
     def testConnectRegistryToLocalMachineWorks(self):
         # perform minimal ConnectRegistry test which just invokes it
index ddb6b2c985f1d92addc8c9354424bb625bd46c93..a1af710a0248e4286efdcba48a9226715d776ba2 100644 (file)
@@ -14,7 +14,6 @@
 
 #include "Python.h"
 #include "structmember.h"
-#include "malloc.h" /* for alloca */
 #include "windows.h"
 
 static BOOL PyHKEY_AsHKEY(PyObject *ob, HKEY *pRes, BOOL bNoneOK);
@@ -391,9 +390,7 @@ static PyObject *
 PyHKEY_strFunc(PyObject *ob)
 {
        PyHKEYObject *pyhkey = (PyHKEYObject *)ob;
-       char resBuf[160];
-       wsprintf(resBuf, "<PyHKEY:%p>", pyhkey->hkey);
-       return PyUnicode_FromString(resBuf);
+       return PyUnicode_FromFormat("<PyHKEY:%p>", pyhkey->hkey);
 }
 
 static int
@@ -652,11 +649,11 @@ PyWinObject_CloseHKEY(PyObject *obHandle)
 ** with these strings (ie only we dont!).
 */
 static void
-fixupMultiSZ(char **str, char *data, int len)
+fixupMultiSZ(wchar_t **str, wchar_t *data, int len)
 {
-       char *P;
+       wchar_t *P;
        int i;
-       char *Q;
+       wchar_t *Q;
 
        Q = data + len;
        for (P = data, i = 0; P < Q && *P != '\0'; P++, i++) {
@@ -667,11 +664,11 @@ fixupMultiSZ(char **str, char *data, int len)
 }
 
 static int
-countStrings(char *data, int len)
+countStrings(wchar_t *data, int len)
 {
        int strings;
-       char *P;
-       char *Q = data + len;
+       wchar_t *P;
+       wchar_t *Q = data + len;
 
        for (P = data, strings = 0; P < Q && *P != '\0'; P++, strings++)
                for (; P < Q && *P != '\0'; P++)
@@ -684,8 +681,6 @@ countStrings(char *data, int len)
 static BOOL
 Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
 {
-       int i,j;
-       DWORD d;
        switch (typ) {
                case REG_DWORD:
                        if (value != Py_None && !PyLong_Check(value))
@@ -701,30 +696,20 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
                                memcpy(*retDataBuf, &zero, sizeof(DWORD));
                        }
                        else {
-                               d = PyLong_AsLong(value);
+                               DWORD d = PyLong_AsLong(value);
                                memcpy(*retDataBuf, &d, sizeof(DWORD));
                        }
                        break;
                case REG_SZ:
                case REG_EXPAND_SZ:
                        {
-                       int need_decref = 0;
                        if (value == Py_None)
                                *retDataSize = 1;
                        else {
-                               if (PyUnicode_Check(value)) {
-                                       value = PyUnicode_AsEncodedString(
-                                                     value,
-                                                     "mbcs",
-                                                     NULL);
-                                       if (value==NULL)
-                                               return FALSE;
-                                       need_decref = 1;
-                               }
-                               if (!PyBytes_Check(value))
+                               if (!PyUnicode_Check(value))
                                        return FALSE;
-                               *retDataSize = 1 + strlen(
-                                       PyBytes_AS_STRING(value));
+
+                               *retDataSize = 2 + PyUnicode_GET_DATA_SIZE(value);
                        }
                        *retDataBuf = (BYTE *)PyMem_NEW(DWORD, *retDataSize);
                        if (*retDataBuf==NULL){
@@ -732,19 +717,17 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
                                return FALSE;
                        }
                        if (value == Py_None)
-                               strcpy((char *)*retDataBuf, "");
+                               wcscpy((wchar_t *)*retDataBuf, L"");
                        else
-                               strcpy((char *)*retDataBuf,
-                                      PyBytes_AS_STRING(value));
-                       if (need_decref)
-                               Py_DECREF(value);
+                               wcscpy((wchar_t *)*retDataBuf,
+                                      PyUnicode_AS_UNICODE(value));
                        break;
                        }
                case REG_MULTI_SZ:
                        {
                                DWORD size = 0;
-                               char *P;
-                               PyObject **obs = NULL;
+                               wchar_t *P;
+                               int i,j;
 
                                if (value == Py_None)
                                        i = 0;
@@ -753,59 +736,35 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
                                                return FALSE;
                                        i = PyList_Size(value);
                                }
-                               obs = malloc(sizeof(PyObject *) * i);
-                               memset(obs, 0, sizeof(PyObject *) * i);
                                for (j = 0; j < i; j++)
                                {
                                        PyObject *t;
-                                       t = PyList_GET_ITEM(
-                                               (PyListObject *)value,j);
-                                       if (PyBytes_Check(t)) {
-                                               obs[j] = t;
-                                               Py_INCREF(t);
-                                       } else if (PyUnicode_Check(t)) {
-                                               obs[j] = PyUnicode_AsEncodedString(
-                                                               t,
-                                                               "mbcs",
-                                                               NULL);
-                                               if (obs[j]==NULL)
-                                                       goto reg_multi_fail;
-                                       } else
-                                               goto reg_multi_fail;
-                                       size += 1 + strlen(
-                                               PyBytes_AS_STRING(obs[j]));
+                                       t = PyList_GET_ITEM(value, j);
+                                       if (!PyUnicode_Check(t))
+                                               return FALSE;
+                                       size += 2 + PyUnicode_GET_DATA_SIZE(t);
                                }
 
-                               *retDataSize = size + 1;
+                               *retDataSize = size + 2;
                                *retDataBuf = (BYTE *)PyMem_NEW(char,
                                                                *retDataSize);
                                if (*retDataBuf==NULL){
                                        PyErr_NoMemory();
-                                       goto reg_multi_fail;
+                                       return FALSE;
                                }
-                               P = (char *)*retDataBuf;
+                               P = (wchar_t *)*retDataBuf;
 
                                for (j = 0; j < i; j++)
                                {
                                        PyObject *t;
-                                       t = obs[j];
-                                       strcpy(P, PyBytes_AS_STRING(t));
-                                       P += 1 + strlen(
-                                               PyBytes_AS_STRING(t));
-                                       Py_DECREF(obs[j]);
+                                       t = PyList_GET_ITEM(value, j);
+                                       wcscpy(P, PyUnicode_AS_UNICODE(t));
+                                       P += 1 + wcslen(
+                                               PyUnicode_AS_UNICODE(t));
                                }
                                /* And doubly-terminate the list... */
                                *P = '\0';
-                               free(obs);
                                break;
-                       reg_multi_fail:
-                               if (obs) {
-                                       for (j = 0; j < i; j++)
-                                               Py_XDECREF(obs[j]);
-
-                                       free(obs);
-                               }
-                               return FALSE;
                        }
                case REG_BINARY:
                /* ALSO handle ALL unknown data types here.  Even if we can't
@@ -844,48 +803,50 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
 
 /* Convert Registry data into PyObject*/
 static PyObject *
-Reg2Py(char *retDataBuf, DWORD retDataSize, DWORD typ)
+Reg2Py(BYTE *retDataBuf, DWORD retDataSize, DWORD typ)
 {
        PyObject *obData;
 
        switch (typ) {
                case REG_DWORD:
                        if (retDataSize == 0)
-                               obData = Py_BuildValue("i", 0);
+                               obData = PyInt_FromLong(0);
                        else
-                               obData = Py_BuildValue("i",
-                                                      *(int *)retDataBuf);
+                               obData = PyInt_FromLong(*(int *)retDataBuf);
                        break;
                case REG_SZ:
                case REG_EXPAND_SZ:
-                       /* retDataBuf may or may not have a trailing NULL in
-                          the buffer. */
-                       if (retDataSize && retDataBuf[retDataSize-1] == '\0')
-                               --retDataSize;
-                       if (retDataSize ==0)
-                               retDataBuf = "";
-                       obData = PyUnicode_DecodeMBCS(retDataBuf,
-                                                     retDataSize,
-                                                     NULL);
-                       break;
+                       {
+                               /* the buffer may or may not have a trailing NULL */
+                               wchar_t *data = (wchar_t *)retDataBuf;
+                               int len = retDataSize / 2;
+                               if (retDataSize && data[len-1] == '\0')
+                                       retDataSize -= 2;
+                               if (retDataSize <= 0)
+                                       data = L"";
+                               obData = PyUnicode_FromUnicode(data, retDataSize/2);
+                               break;
+                       }
                case REG_MULTI_SZ:
                        if (retDataSize == 0)
                                obData = PyList_New(0);
                        else
                        {
                                int index = 0;
-                               int s = countStrings(retDataBuf, retDataSize);
-                               char **str = (char **)malloc(sizeof(char *)*s);
+                               wchar_t *data = (wchar_t *)retDataBuf;
+                               int len = retDataSize / 2;
+                               int s = countStrings(data, len);
+                               wchar_t **str = (wchar_t **)malloc(sizeof(wchar_t *)*s);
                                if (str == NULL)
                                        return PyErr_NoMemory();
 
-                               fixupMultiSZ(str, retDataBuf, retDataSize);
+                               fixupMultiSZ(str, data, len);
                                obData = PyList_New(s);
                                if (obData == NULL)
                                        return NULL;
                                for (index = 0; index < s; index++)
                                {
-                                       size_t len = _mbstrlen(str[index]);
+                                       size_t len = wcslen(str[index]);
                                        if (len > INT_MAX) {
                                                PyErr_SetString(PyExc_OverflowError,
                                                        "registry string is too long for a Python string");
@@ -894,11 +855,7 @@ Reg2Py(char *retDataBuf, DWORD retDataSize, DWORD typ)
                                        }
                                        PyList_SetItem(obData,
                                                       index,
-                                                      PyUnicode_DecodeMBCS(
-                                                           (const char *)str[index],
-                                                          (int)len,
-                                                           NULL)
-                                                      );
+                                                      PyUnicode_FromUnicode(str[index], len));
                                }
                                free(str);
 
@@ -913,15 +870,11 @@ Reg2Py(char *retDataBuf, DWORD retDataSize, DWORD typ)
                                obData = Py_None;
                        }
                        else
-                               obData = Py_BuildValue("y#",
-                                                      (char *)retDataBuf,
-                                                      retDataSize);
+                               obData = PyBytes_FromStringAndSize(
+                                            (char *)retDataBuf, retDataSize);
                        break;
        }
-       if (obData == NULL)
-               return NULL;
-       else
-               return obData;
+       return obData;
 }
 
 /* The Python methods */
@@ -943,15 +896,15 @@ PyConnectRegistry(PyObject *self, PyObject *args)
 {
        HKEY hKey;
        PyObject *obKey;
-       char *szCompName = NULL;
+       wchar_t *szCompName = NULL;
        HKEY retKey;
        long rc;
-       if (!PyArg_ParseTuple(args, "zO:ConnectRegistry", &szCompName, &obKey))
+       if (!PyArg_ParseTuple(args, "ZO:ConnectRegistry", &szCompName, &obKey))
                return NULL;
        if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
                return NULL;
        Py_BEGIN_ALLOW_THREADS
-       rc = RegConnectRegistry(szCompName, hKey, &retKey);
+       rc = RegConnectRegistryW(szCompName, hKey, &retKey);
        Py_END_ALLOW_THREADS
        if (rc != ERROR_SUCCESS)
                return PyErr_SetFromWindowsErrWithFunction(rc,
@@ -964,14 +917,14 @@ PyCreateKey(PyObject *self, PyObject *args)
 {
        HKEY hKey;
        PyObject *obKey;
-       char *subKey;
+       wchar_t *subKey;
        HKEY retKey;
        long rc;
-       if (!PyArg_ParseTuple(args, "Oz:CreateKey", &obKey, &subKey))
+       if (!PyArg_ParseTuple(args, "OZ:CreateKey", &obKey, &subKey))
                return NULL;
        if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
                return NULL;
-       rc = RegCreateKey(hKey, subKey, &retKey);
+       rc = RegCreateKeyW(hKey, subKey, &retKey);
        if (rc != ERROR_SUCCESS)
                return PyErr_SetFromWindowsErrWithFunction(rc, "CreateKey");
        return PyHKEY_FromHKEY(retKey);
@@ -982,13 +935,13 @@ PyDeleteKey(PyObject *self, PyObject *args)
 {
        HKEY hKey;
        PyObject *obKey;
-       char *subKey;
+       wchar_t *subKey;
        long rc;
-       if (!PyArg_ParseTuple(args, "Os:DeleteKey", &obKey, &subKey))
+       if (!PyArg_ParseTuple(args, "Ou:DeleteKey", &obKey, &subKey))
                return NULL;
        if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
                return NULL;
-       rc = RegDeleteKey(hKey, subKey );
+       rc = RegDeleteKeyW(hKey, subKey );
        if (rc != ERROR_SUCCESS)
                return PyErr_SetFromWindowsErrWithFunction(rc, "RegDeleteKey");
        Py_INCREF(Py_None);
@@ -1000,14 +953,14 @@ PyDeleteValue(PyObject *self, PyObject *args)
 {
        HKEY hKey;
        PyObject *obKey;
-       char *subKey;
+       wchar_t *subKey;
        long rc;
-       if (!PyArg_ParseTuple(args, "Oz:DeleteValue", &obKey, &subKey))
+       if (!PyArg_ParseTuple(args, "OZ:DeleteValue", &obKey, &subKey))
                return NULL;
        if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
                return NULL;
        Py_BEGIN_ALLOW_THREADS
-       rc = RegDeleteValue(hKey, subKey);
+       rc = RegDeleteValueW(hKey, subKey);
        Py_END_ALLOW_THREADS
        if (rc !=ERROR_SUCCESS)
                return PyErr_SetFromWindowsErrWithFunction(rc,
@@ -1024,7 +977,7 @@ PyEnumKey(PyObject *self, PyObject *args)
        int index;
        long rc;
        PyObject *retStr;
-       char tmpbuf[256]; /* max key name length is 255 */
+       wchar_t tmpbuf[256]; /* max key name length is 255 */
        DWORD len = sizeof(tmpbuf); /* includes NULL terminator */
 
        if (!PyArg_ParseTuple(args, "Oi:EnumKey", &obKey, &index))
@@ -1033,12 +986,12 @@ PyEnumKey(PyObject *self, PyObject *args)
                return NULL;
 
        Py_BEGIN_ALLOW_THREADS
-       rc = RegEnumKeyEx(hKey, index, tmpbuf, &len, NULL, NULL, NULL, NULL);
+       rc = RegEnumKeyExW(hKey, index, tmpbuf, &len, NULL, NULL, NULL, NULL);
        Py_END_ALLOW_THREADS
        if (rc != ERROR_SUCCESS)
                return PyErr_SetFromWindowsErrWithFunction(rc, "RegEnumKeyEx");
 
-       retStr = PyUnicode_FromStringAndSize(tmpbuf, len);
+       retStr = PyUnicode_FromUnicode(tmpbuf, len);
        return retStr;  /* can be NULL */
 }
 
@@ -1049,8 +1002,8 @@ PyEnumValue(PyObject *self, PyObject *args)
        PyObject *obKey;
        int index;
        long rc;
-       char *retValueBuf;
-       char *retDataBuf;
+       wchar_t *retValueBuf;
+       BYTE *retDataBuf;
        DWORD retValueSize;
        DWORD retDataSize;
        DWORD typ;
@@ -1062,7 +1015,7 @@ PyEnumValue(PyObject *self, PyObject *args)
        if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
                return NULL;
 
-       if ((rc = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
+       if ((rc = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
                                  NULL,
                                  &retValueSize, &retDataSize, NULL, NULL))
            != ERROR_SUCCESS)
@@ -1070,23 +1023,23 @@ PyEnumValue(PyObject *self, PyObject *args)
                                                           "RegQueryInfoKey");
        ++retValueSize;    /* include null terminators */
        ++retDataSize;
-       retValueBuf = (char *)PyMem_Malloc(retValueSize);
+       retValueBuf = (wchar_t *)PyMem_Malloc(sizeof(wchar_t) * retValueSize);
        if (retValueBuf == NULL)
                return PyErr_NoMemory();
-       retDataBuf = (char *)PyMem_Malloc(retDataSize);
+       retDataBuf = (BYTE *)PyMem_Malloc(retDataSize);
        if (retDataBuf == NULL) {
                PyMem_Free(retValueBuf);
                return PyErr_NoMemory();
        }
 
        Py_BEGIN_ALLOW_THREADS
-       rc = RegEnumValue(hKey,
+       rc = RegEnumValueW(hKey,
                          index,
                          retValueBuf,
                          &retValueSize,
                          NULL,
                          &typ,
-                         (BYTE *)retDataBuf,
+                         retDataBuf,
                          &retDataSize);
        Py_END_ALLOW_THREADS
 
@@ -1100,7 +1053,7 @@ PyEnumValue(PyObject *self, PyObject *args)
                retVal = NULL;
                goto fail;
        }
-       retVal = Py_BuildValue("UOi", retValueBuf, obData, typ);
+       retVal = Py_BuildValue("uOi", retValueBuf, obData, typ);
        Py_DECREF(obData);
   fail:
        PyMem_Free(retValueBuf);
@@ -1131,16 +1084,16 @@ PyLoadKey(PyObject *self, PyObject *args)
 {
        HKEY hKey;
        PyObject *obKey;
-       char *subKey;
-       char *fileName;
+       wchar_t *subKey;
+       wchar_t *fileName;
 
        long rc;
-       if (!PyArg_ParseTuple(args, "Oss:LoadKey", &obKey, &subKey, &fileName))
+       if (!PyArg_ParseTuple(args, "Ouu:LoadKey", &obKey, &subKey, &fileName))
                return NULL;
        if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
                return NULL;
        Py_BEGIN_ALLOW_THREADS
-       rc = RegLoadKey(hKey, subKey, fileName );
+       rc = RegLoadKeyW(hKey, subKey, fileName );
        Py_END_ALLOW_THREADS
        if (rc != ERROR_SUCCESS)
                return PyErr_SetFromWindowsErrWithFunction(rc, "RegLoadKey");
@@ -1154,19 +1107,19 @@ PyOpenKey(PyObject *self, PyObject *args)
        HKEY hKey;
        PyObject *obKey;
 
-       char *subKey;
+       wchar_t *subKey;
        int res = 0;
        HKEY retKey;
        long rc;
        REGSAM sam = KEY_READ;
-       if (!PyArg_ParseTuple(args, "Oz|ii:OpenKey", &obKey, &subKey,
+       if (!PyArg_ParseTuple(args, "OZ|ii:OpenKey", &obKey, &subKey,
                              &res, &sam))
                return NULL;
        if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
                return NULL;
 
        Py_BEGIN_ALLOW_THREADS
-       rc = RegOpenKeyEx(hKey, subKey, res, sam, &retKey);
+       rc = RegOpenKeyExW(hKey, subKey, res, sam, &retKey);
        Py_END_ALLOW_THREADS
        if (rc != ERROR_SUCCESS)
                return PyErr_SetFromWindowsErrWithFunction(rc, "RegOpenKeyEx");
@@ -1208,33 +1161,33 @@ PyQueryValue(PyObject *self, PyObject *args)
 {
        HKEY hKey;
        PyObject *obKey;
-       char *subKey;
+       wchar_t *subKey;
        long rc;
        PyObject *retStr;
-       char *retBuf;
+       wchar_t *retBuf;
        long bufSize = 0;
 
-       if (!PyArg_ParseTuple(args, "Oz:QueryValue", &obKey, &subKey))
+       if (!PyArg_ParseTuple(args, "OZ:QueryValue", &obKey, &subKey))
                return NULL;
 
        if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
                return NULL;
-       if ((rc = RegQueryValue(hKey, subKey, NULL, &bufSize))
+       if ((rc = RegQueryValueW(hKey, subKey, NULL, &bufSize))
            != ERROR_SUCCESS)
                return PyErr_SetFromWindowsErrWithFunction(rc,
                                                           "RegQueryValue");
-       retBuf = (char *)PyMem_Malloc(bufSize);
+       retBuf = (wchar_t *)PyMem_Malloc(bufSize);
        if (retBuf == NULL)
                return PyErr_NoMemory();
 
-       if ((rc = RegQueryValue(hKey, subKey, retBuf, &bufSize))
+       if ((rc = RegQueryValueW(hKey, subKey, retBuf, &bufSize))
            != ERROR_SUCCESS) {
                PyMem_Free(retBuf);
                return PyErr_SetFromWindowsErrWithFunction(rc,
                                                           "RegQueryValue");
        }
 
-       retStr = PyUnicode_DecodeMBCS(retBuf, strlen(retBuf), NULL);
+       retStr = PyUnicode_FromUnicode(retBuf, wcslen(retBuf));
        PyMem_Free(retBuf);
        return retStr;
 }
@@ -1244,38 +1197,38 @@ PyQueryValueEx(PyObject *self, PyObject *args)
 {
        HKEY hKey;
        PyObject *obKey;
-       char *valueName;
+       wchar_t *valueName;
 
        long rc;
-       char *retBuf;
+       BYTE *retBuf;
        DWORD bufSize = 0;
        DWORD typ;
        PyObject *obData;
        PyObject *result;
 
-       if (!PyArg_ParseTuple(args, "Oz:QueryValueEx", &obKey, &valueName))
+       if (!PyArg_ParseTuple(args, "OZ:QueryValueEx", &obKey, &valueName))
                return NULL;
 
        if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
                return NULL;
-       if ((rc = RegQueryValueEx(hKey, valueName,
+       if ((rc = RegQueryValueExW(hKey, valueName,
                                  NULL, NULL, NULL,
                                  &bufSize))
            != ERROR_SUCCESS)
                return PyErr_SetFromWindowsErrWithFunction(rc,
                                                           "RegQueryValueEx");
-       retBuf = (char *)PyMem_Malloc(bufSize);
+       retBuf = (BYTE *)PyMem_Malloc(bufSize);
        if (retBuf == NULL)
                return PyErr_NoMemory();
-       if ((rc = RegQueryValueEx(hKey, valueName, NULL,
-                                 &typ, (BYTE *)retBuf, &bufSize))
+       if ((rc = RegQueryValueExW(hKey, valueName, NULL,
+                                 &typ, retBuf, &bufSize))
            != ERROR_SUCCESS) {
                PyMem_Free(retBuf);
                return PyErr_SetFromWindowsErrWithFunction(rc,
                                                           "RegQueryValueEx");
        }
        obData = Reg2Py(retBuf, bufSize, typ);
-       PyMem_Free((void *)retBuf);
+       PyMem_Free(retBuf);
        if (obData == NULL)
                return NULL;
        result = Py_BuildValue("Oi", obData, typ);
@@ -1289,11 +1242,11 @@ PySaveKey(PyObject *self, PyObject *args)
 {
        HKEY hKey;
        PyObject *obKey;
-       char *fileName;
+       wchar_t *fileName;
        LPSECURITY_ATTRIBUTES pSA = NULL;
 
        long rc;
-       if (!PyArg_ParseTuple(args, "Os:SaveKey", &obKey, &fileName))
+       if (!PyArg_ParseTuple(args, "Ou:SaveKey", &obKey, &fileName))
                return NULL;
        if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
                return NULL;
@@ -1302,7 +1255,7 @@ PySaveKey(PyObject *self, PyObject *args)
                return NULL;
 */
        Py_BEGIN_ALLOW_THREADS
-       rc = RegSaveKey(hKey, fileName, pSA );
+       rc = RegSaveKeyW(hKey, fileName, pSA );
        Py_END_ALLOW_THREADS
        if (rc != ERROR_SUCCESS)
                return PyErr_SetFromWindowsErrWithFunction(rc, "RegSaveKey");
@@ -1315,18 +1268,17 @@ PySetValue(PyObject *self, PyObject *args)
 {
        HKEY hKey;
        PyObject *obKey;
-       char *subKey;
-       char *str;
+       wchar_t *subKey;
+       wchar_t *str;
        DWORD typ;
        DWORD len;
        long rc;
-       PyObject *obStrVal;
-       PyObject *obSubKey;
-       if (!PyArg_ParseTuple(args, "OOiO:SetValue",
+       if (!PyArg_ParseTuple(args, "OZiu#:SetValue",
                              &obKey,
-                             &obSubKey,
+                             &subKey,
                              &typ,
-                             &obStrVal))
+                             &str,
+                             &len))
                return NULL;
        if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
                return NULL;
@@ -1335,20 +1287,9 @@ PySetValue(PyObject *self, PyObject *args)
                                "Type must be _winreg.REG_SZ");
                return NULL;
        }
-       /* XXX - need Unicode support */
-       str = PyString_AsString(obStrVal);
-       if (str == NULL)
-               return NULL;
-       len = PyString_Size(obStrVal);
-       if (obSubKey == Py_None)
-               subKey = NULL;
-       else {
-               subKey = PyString_AsString(obSubKey);
-               if (subKey == NULL)
-                       return NULL;
-       }
+
        Py_BEGIN_ALLOW_THREADS
-       rc = RegSetValue(hKey, subKey, REG_SZ, str, len+1);
+       rc = RegSetValueW(hKey, subKey, REG_SZ, str, len+1);
        Py_END_ALLOW_THREADS
        if (rc != ERROR_SUCCESS)
                return PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValue");
@@ -1361,7 +1302,7 @@ PySetValueEx(PyObject *self, PyObject *args)
 {
        HKEY hKey;
        PyObject *obKey;
-       char *valueName;
+       Py_UNICODE *valueName;
        PyObject *obRes;
        PyObject *value;
        BYTE *data;
@@ -1370,7 +1311,7 @@ PySetValueEx(PyObject *self, PyObject *args)
 
        LONG rc;
 
-       if (!PyArg_ParseTuple(args, "OzOiO:SetValueEx",
+       if (!PyArg_ParseTuple(args, "OZOiO:SetValueEx",
                              &obKey,
                              &valueName,
                              &obRes,
@@ -1387,7 +1328,7 @@ PySetValueEx(PyObject *self, PyObject *args)
                return NULL;
        }
        Py_BEGIN_ALLOW_THREADS
-       rc = RegSetValueEx(hKey, valueName, 0, typ, data, len);
+       rc = RegSetValueExW(hKey, valueName, 0, typ, data, len);
        Py_END_ALLOW_THREADS
        PyMem_DEL(data);
        if (rc != ERROR_SUCCESS)
@@ -1511,3 +1452,4 @@ PyMODINIT_FUNC init_winreg(void)
        ADD_INT(REG_RESOURCE_REQUIREMENTS_LIST);
 }
 
+