Patch #1076: Use wide API for registry functions.

This commit is contained in:
Martin v. Löwis 2007-09-03 07:43:05 +00:00
parent 5d12abe0b1
commit f82d9b52fa
2 changed files with 128 additions and 182 deletions

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# Test the windows specific win32reg module. # Test the windows specific win32reg module.
# Only win32reg functions not hit here: FlushKey, LoadKey and SaveKey # Only win32reg functions not hit here: FlushKey, LoadKey and SaveKey
@ -17,17 +18,19 @@ test_data = [
("Raw Data", b"binary\x00data", REG_BINARY), ("Raw Data", b"binary\x00data", REG_BINARY),
("Big String", "x"*(2**14-1), REG_SZ), ("Big String", "x"*(2**14-1), REG_SZ),
("Big Binary", b"x"*(2**14), REG_BINARY), ("Big Binary", b"x"*(2**14), REG_BINARY),
# Two and three kanjis, meaning: "Japan" and "Japanese")
("Japanese 日本", "日本語", REG_SZ),
] ]
class WinregTests(unittest.TestCase): class WinregTests(unittest.TestCase):
remote_name = None remote_name = None
def WriteTestData(self, root_key): def WriteTestData(self, root_key, subkeystr="sub_key"):
# Set the default value for this key. # Set the default value for this key.
SetValue(root_key, test_key_name, REG_SZ, "Default value") SetValue(root_key, test_key_name, REG_SZ, "Default value")
key = CreateKey(root_key, test_key_name) key = CreateKey(root_key, test_key_name)
# Create a sub-key # Create a sub-key
sub_key = CreateKey(key, "sub_key") sub_key = CreateKey(key, subkeystr)
# Give the sub-key some named values # Give the sub-key some named values
for value_name, value_data, value_type in test_data: for value_name, value_data, value_type in test_data:
@ -62,7 +65,7 @@ class WinregTests(unittest.TestCase):
except EnvironmentError: except EnvironmentError:
pass pass
def ReadTestData(self, root_key): def ReadTestData(self, root_key, subkeystr="sub_key"):
# Check we can get default value for this key. # Check we can get default value for this key.
val = QueryValue(root_key, test_key_name) val = QueryValue(root_key, test_key_name)
self.assertEquals(val, "Default value", self.assertEquals(val, "Default value",
@ -70,7 +73,7 @@ class WinregTests(unittest.TestCase):
key = OpenKey(root_key, test_key_name) key = OpenKey(root_key, test_key_name)
# Read the sub-keys # Read the sub-keys
sub_key = OpenKey(key, "sub_key") sub_key = OpenKey(key, subkeystr)
# Check I can enumerate over the values. # Check I can enumerate over the values.
index = 0 index = 0
while 1: while 1:
@ -93,7 +96,7 @@ class WinregTests(unittest.TestCase):
sub_key.Close() sub_key.Close()
# Enumerate our main key. # Enumerate our main key.
read_val = EnumKey(key, 0) 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: try:
EnumKey(key, 1) EnumKey(key, 1)
self.fail("Was able to get a second key when I only have one!") self.fail("Was able to get a second key when I only have one!")
@ -102,9 +105,9 @@ class WinregTests(unittest.TestCase):
key.Close() 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) 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 # It is not necessary to delete the values before deleting
# the key (although subkeys must not exist). We delete them # the key (although subkeys must not exist). We delete them
# manually just to prove we can :-) # 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(nkeys, 0, "subkey not empty before delete")
self.assertEquals(nvalues, 0, "subkey not empty before delete") self.assertEquals(nvalues, 0, "subkey not empty before delete")
sub_key.Close() sub_key.Close()
DeleteKey(key, "sub_key") DeleteKey(key, subkeystr)
try: try:
# Shouldnt be able to delete it twice! # Shouldnt be able to delete it twice!
DeleteKey(key, "sub_key") DeleteKey(key, subkeystr)
self.fail("Deleting the key twice succeeded") self.fail("Deleting the key twice succeeded")
except EnvironmentError: except EnvironmentError:
pass pass
@ -132,13 +135,14 @@ class WinregTests(unittest.TestCase):
except WindowsError: # Use this error name this time except WindowsError: # Use this error name this time
pass pass
def TestAll(self, root_key): def TestAll(self, root_key, subkeystr="sub_key"):
self.WriteTestData(root_key) self.WriteTestData(root_key, subkeystr)
self.ReadTestData(root_key) self.ReadTestData(root_key, subkeystr)
self.DeleteTestData(root_key) self.DeleteTestData(root_key, subkeystr)
def testLocalMachineRegistryWorks(self): def testLocalMachineRegistryWorks(self):
self.TestAll(HKEY_CURRENT_USER) self.TestAll(HKEY_CURRENT_USER)
self.TestAll(HKEY_CURRENT_USER, "日本-subkey")
def testConnectRegistryToLocalMachineWorks(self): def testConnectRegistryToLocalMachineWorks(self):
# perform minimal ConnectRegistry test which just invokes it # perform minimal ConnectRegistry test which just invokes it

View File

@ -14,7 +14,6 @@
#include "Python.h" #include "Python.h"
#include "structmember.h" #include "structmember.h"
#include "malloc.h" /* for alloca */
#include "windows.h" #include "windows.h"
static BOOL PyHKEY_AsHKEY(PyObject *ob, HKEY *pRes, BOOL bNoneOK); static BOOL PyHKEY_AsHKEY(PyObject *ob, HKEY *pRes, BOOL bNoneOK);
@ -391,9 +390,7 @@ static PyObject *
PyHKEY_strFunc(PyObject *ob) PyHKEY_strFunc(PyObject *ob)
{ {
PyHKEYObject *pyhkey = (PyHKEYObject *)ob; PyHKEYObject *pyhkey = (PyHKEYObject *)ob;
char resBuf[160]; return PyUnicode_FromFormat("<PyHKEY:%p>", pyhkey->hkey);
wsprintf(resBuf, "<PyHKEY:%p>", pyhkey->hkey);
return PyUnicode_FromString(resBuf);
} }
static int static int
@ -652,11 +649,11 @@ PyWinObject_CloseHKEY(PyObject *obHandle)
** with these strings (ie only we dont!). ** with these strings (ie only we dont!).
*/ */
static void 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; int i;
char *Q; wchar_t *Q;
Q = data + len; Q = data + len;
for (P = data, i = 0; P < Q && *P != '\0'; P++, i++) { for (P = data, i = 0; P < Q && *P != '\0'; P++, i++) {
@ -667,11 +664,11 @@ fixupMultiSZ(char **str, char *data, int len)
} }
static int static int
countStrings(char *data, int len) countStrings(wchar_t *data, int len)
{ {
int strings; int strings;
char *P; wchar_t *P;
char *Q = data + len; wchar_t *Q = data + len;
for (P = data, strings = 0; P < Q && *P != '\0'; P++, strings++) for (P = data, strings = 0; P < Q && *P != '\0'; P++, strings++)
for (; P < Q && *P != '\0'; P++) for (; P < Q && *P != '\0'; P++)
@ -684,8 +681,6 @@ countStrings(char *data, int len)
static BOOL static BOOL
Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize) Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
{ {
int i,j;
DWORD d;
switch (typ) { switch (typ) {
case REG_DWORD: case REG_DWORD:
if (value != Py_None && !PyLong_Check(value)) 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)); memcpy(*retDataBuf, &zero, sizeof(DWORD));
} }
else { else {
d = PyLong_AsLong(value); DWORD d = PyLong_AsLong(value);
memcpy(*retDataBuf, &d, sizeof(DWORD)); memcpy(*retDataBuf, &d, sizeof(DWORD));
} }
break; break;
case REG_SZ: case REG_SZ:
case REG_EXPAND_SZ: case REG_EXPAND_SZ:
{ {
int need_decref = 0;
if (value == Py_None) if (value == Py_None)
*retDataSize = 1; *retDataSize = 1;
else { else {
if (PyUnicode_Check(value)) { if (!PyUnicode_Check(value))
value = PyUnicode_AsEncodedString(
value,
"mbcs",
NULL);
if (value==NULL)
return FALSE; return FALSE;
need_decref = 1;
} *retDataSize = 2 + PyUnicode_GET_DATA_SIZE(value);
if (!PyBytes_Check(value))
return FALSE;
*retDataSize = 1 + strlen(
PyBytes_AS_STRING(value));
} }
*retDataBuf = (BYTE *)PyMem_NEW(DWORD, *retDataSize); *retDataBuf = (BYTE *)PyMem_NEW(DWORD, *retDataSize);
if (*retDataBuf==NULL){ if (*retDataBuf==NULL){
@ -732,19 +717,17 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
return FALSE; return FALSE;
} }
if (value == Py_None) if (value == Py_None)
strcpy((char *)*retDataBuf, ""); wcscpy((wchar_t *)*retDataBuf, L"");
else else
strcpy((char *)*retDataBuf, wcscpy((wchar_t *)*retDataBuf,
PyBytes_AS_STRING(value)); PyUnicode_AS_UNICODE(value));
if (need_decref)
Py_DECREF(value);
break; break;
} }
case REG_MULTI_SZ: case REG_MULTI_SZ:
{ {
DWORD size = 0; DWORD size = 0;
char *P; wchar_t *P;
PyObject **obs = NULL; int i,j;
if (value == Py_None) if (value == Py_None)
i = 0; i = 0;
@ -753,59 +736,35 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
return FALSE; return FALSE;
i = PyList_Size(value); i = PyList_Size(value);
} }
obs = malloc(sizeof(PyObject *) * i);
memset(obs, 0, sizeof(PyObject *) * i);
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
{ {
PyObject *t; PyObject *t;
t = PyList_GET_ITEM( t = PyList_GET_ITEM(value, j);
(PyListObject *)value,j); if (!PyUnicode_Check(t))
if (PyBytes_Check(t)) { return FALSE;
obs[j] = t; size += 2 + PyUnicode_GET_DATA_SIZE(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]));
} }
*retDataSize = size + 1; *retDataSize = size + 2;
*retDataBuf = (BYTE *)PyMem_NEW(char, *retDataBuf = (BYTE *)PyMem_NEW(char,
*retDataSize); *retDataSize);
if (*retDataBuf==NULL){ if (*retDataBuf==NULL){
PyErr_NoMemory(); PyErr_NoMemory();
goto reg_multi_fail; return FALSE;
} }
P = (char *)*retDataBuf; P = (wchar_t *)*retDataBuf;
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
{ {
PyObject *t; PyObject *t;
t = obs[j]; t = PyList_GET_ITEM(value, j);
strcpy(P, PyBytes_AS_STRING(t)); wcscpy(P, PyUnicode_AS_UNICODE(t));
P += 1 + strlen( P += 1 + wcslen(
PyBytes_AS_STRING(t)); PyUnicode_AS_UNICODE(t));
Py_DECREF(obs[j]);
} }
/* And doubly-terminate the list... */ /* And doubly-terminate the list... */
*P = '\0'; *P = '\0';
free(obs);
break; break;
reg_multi_fail:
if (obs) {
for (j = 0; j < i; j++)
Py_XDECREF(obs[j]);
free(obs);
}
return FALSE;
} }
case REG_BINARY: case REG_BINARY:
/* ALSO handle ALL unknown data types here. Even if we can't /* 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*/ /* Convert Registry data into PyObject*/
static PyObject * static PyObject *
Reg2Py(char *retDataBuf, DWORD retDataSize, DWORD typ) Reg2Py(BYTE *retDataBuf, DWORD retDataSize, DWORD typ)
{ {
PyObject *obData; PyObject *obData;
switch (typ) { switch (typ) {
case REG_DWORD: case REG_DWORD:
if (retDataSize == 0) if (retDataSize == 0)
obData = Py_BuildValue("i", 0); obData = PyInt_FromLong(0);
else else
obData = Py_BuildValue("i", obData = PyInt_FromLong(*(int *)retDataBuf);
*(int *)retDataBuf);
break; break;
case REG_SZ: case REG_SZ:
case REG_EXPAND_SZ: case REG_EXPAND_SZ:
/* retDataBuf may or may not have a trailing NULL in {
the buffer. */ /* the buffer may or may not have a trailing NULL */
if (retDataSize && retDataBuf[retDataSize-1] == '\0') wchar_t *data = (wchar_t *)retDataBuf;
--retDataSize; int len = retDataSize / 2;
if (retDataSize ==0) if (retDataSize && data[len-1] == '\0')
retDataBuf = ""; retDataSize -= 2;
obData = PyUnicode_DecodeMBCS(retDataBuf, if (retDataSize <= 0)
retDataSize, data = L"";
NULL); obData = PyUnicode_FromUnicode(data, retDataSize/2);
break; break;
}
case REG_MULTI_SZ: case REG_MULTI_SZ:
if (retDataSize == 0) if (retDataSize == 0)
obData = PyList_New(0); obData = PyList_New(0);
else else
{ {
int index = 0; int index = 0;
int s = countStrings(retDataBuf, retDataSize); wchar_t *data = (wchar_t *)retDataBuf;
char **str = (char **)malloc(sizeof(char *)*s); int len = retDataSize / 2;
int s = countStrings(data, len);
wchar_t **str = (wchar_t **)malloc(sizeof(wchar_t *)*s);
if (str == NULL) if (str == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
fixupMultiSZ(str, retDataBuf, retDataSize); fixupMultiSZ(str, data, len);
obData = PyList_New(s); obData = PyList_New(s);
if (obData == NULL) if (obData == NULL)
return NULL; return NULL;
for (index = 0; index < s; index++) for (index = 0; index < s; index++)
{ {
size_t len = _mbstrlen(str[index]); size_t len = wcslen(str[index]);
if (len > INT_MAX) { if (len > INT_MAX) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"registry string is too long for a Python string"); "registry string is too long for a Python string");
@ -894,11 +855,7 @@ Reg2Py(char *retDataBuf, DWORD retDataSize, DWORD typ)
} }
PyList_SetItem(obData, PyList_SetItem(obData,
index, index,
PyUnicode_DecodeMBCS( PyUnicode_FromUnicode(str[index], len));
(const char *)str[index],
(int)len,
NULL)
);
} }
free(str); free(str);
@ -913,14 +870,10 @@ Reg2Py(char *retDataBuf, DWORD retDataSize, DWORD typ)
obData = Py_None; obData = Py_None;
} }
else else
obData = Py_BuildValue("y#", obData = PyBytes_FromStringAndSize(
(char *)retDataBuf, (char *)retDataBuf, retDataSize);
retDataSize);
break; break;
} }
if (obData == NULL)
return NULL;
else
return obData; return obData;
} }
@ -943,15 +896,15 @@ PyConnectRegistry(PyObject *self, PyObject *args)
{ {
HKEY hKey; HKEY hKey;
PyObject *obKey; PyObject *obKey;
char *szCompName = NULL; wchar_t *szCompName = NULL;
HKEY retKey; HKEY retKey;
long rc; long rc;
if (!PyArg_ParseTuple(args, "zO:ConnectRegistry", &szCompName, &obKey)) if (!PyArg_ParseTuple(args, "ZO:ConnectRegistry", &szCompName, &obKey))
return NULL; return NULL;
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
rc = RegConnectRegistry(szCompName, hKey, &retKey); rc = RegConnectRegistryW(szCompName, hKey, &retKey);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, return PyErr_SetFromWindowsErrWithFunction(rc,
@ -964,14 +917,14 @@ PyCreateKey(PyObject *self, PyObject *args)
{ {
HKEY hKey; HKEY hKey;
PyObject *obKey; PyObject *obKey;
char *subKey; wchar_t *subKey;
HKEY retKey; HKEY retKey;
long rc; long rc;
if (!PyArg_ParseTuple(args, "Oz:CreateKey", &obKey, &subKey)) if (!PyArg_ParseTuple(args, "OZ:CreateKey", &obKey, &subKey))
return NULL; return NULL;
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL; return NULL;
rc = RegCreateKey(hKey, subKey, &retKey); rc = RegCreateKeyW(hKey, subKey, &retKey);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, "CreateKey"); return PyErr_SetFromWindowsErrWithFunction(rc, "CreateKey");
return PyHKEY_FromHKEY(retKey); return PyHKEY_FromHKEY(retKey);
@ -982,13 +935,13 @@ PyDeleteKey(PyObject *self, PyObject *args)
{ {
HKEY hKey; HKEY hKey;
PyObject *obKey; PyObject *obKey;
char *subKey; wchar_t *subKey;
long rc; long rc;
if (!PyArg_ParseTuple(args, "Os:DeleteKey", &obKey, &subKey)) if (!PyArg_ParseTuple(args, "Ou:DeleteKey", &obKey, &subKey))
return NULL; return NULL;
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL; return NULL;
rc = RegDeleteKey(hKey, subKey ); rc = RegDeleteKeyW(hKey, subKey );
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, "RegDeleteKey"); return PyErr_SetFromWindowsErrWithFunction(rc, "RegDeleteKey");
Py_INCREF(Py_None); Py_INCREF(Py_None);
@ -1000,14 +953,14 @@ PyDeleteValue(PyObject *self, PyObject *args)
{ {
HKEY hKey; HKEY hKey;
PyObject *obKey; PyObject *obKey;
char *subKey; wchar_t *subKey;
long rc; long rc;
if (!PyArg_ParseTuple(args, "Oz:DeleteValue", &obKey, &subKey)) if (!PyArg_ParseTuple(args, "OZ:DeleteValue", &obKey, &subKey))
return NULL; return NULL;
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
rc = RegDeleteValue(hKey, subKey); rc = RegDeleteValueW(hKey, subKey);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (rc !=ERROR_SUCCESS) if (rc !=ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, return PyErr_SetFromWindowsErrWithFunction(rc,
@ -1024,7 +977,7 @@ PyEnumKey(PyObject *self, PyObject *args)
int index; int index;
long rc; long rc;
PyObject *retStr; 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 */ DWORD len = sizeof(tmpbuf); /* includes NULL terminator */
if (!PyArg_ParseTuple(args, "Oi:EnumKey", &obKey, &index)) if (!PyArg_ParseTuple(args, "Oi:EnumKey", &obKey, &index))
@ -1033,12 +986,12 @@ PyEnumKey(PyObject *self, PyObject *args)
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS 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 Py_END_ALLOW_THREADS
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, "RegEnumKeyEx"); return PyErr_SetFromWindowsErrWithFunction(rc, "RegEnumKeyEx");
retStr = PyUnicode_FromStringAndSize(tmpbuf, len); retStr = PyUnicode_FromUnicode(tmpbuf, len);
return retStr; /* can be NULL */ return retStr; /* can be NULL */
} }
@ -1049,8 +1002,8 @@ PyEnumValue(PyObject *self, PyObject *args)
PyObject *obKey; PyObject *obKey;
int index; int index;
long rc; long rc;
char *retValueBuf; wchar_t *retValueBuf;
char *retDataBuf; BYTE *retDataBuf;
DWORD retValueSize; DWORD retValueSize;
DWORD retDataSize; DWORD retDataSize;
DWORD typ; DWORD typ;
@ -1062,7 +1015,7 @@ PyEnumValue(PyObject *self, PyObject *args)
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL; return NULL;
if ((rc = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, if ((rc = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL,
&retValueSize, &retDataSize, NULL, NULL)) &retValueSize, &retDataSize, NULL, NULL))
!= ERROR_SUCCESS) != ERROR_SUCCESS)
@ -1070,23 +1023,23 @@ PyEnumValue(PyObject *self, PyObject *args)
"RegQueryInfoKey"); "RegQueryInfoKey");
++retValueSize; /* include null terminators */ ++retValueSize; /* include null terminators */
++retDataSize; ++retDataSize;
retValueBuf = (char *)PyMem_Malloc(retValueSize); retValueBuf = (wchar_t *)PyMem_Malloc(sizeof(wchar_t) * retValueSize);
if (retValueBuf == NULL) if (retValueBuf == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
retDataBuf = (char *)PyMem_Malloc(retDataSize); retDataBuf = (BYTE *)PyMem_Malloc(retDataSize);
if (retDataBuf == NULL) { if (retDataBuf == NULL) {
PyMem_Free(retValueBuf); PyMem_Free(retValueBuf);
return PyErr_NoMemory(); return PyErr_NoMemory();
} }
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
rc = RegEnumValue(hKey, rc = RegEnumValueW(hKey,
index, index,
retValueBuf, retValueBuf,
&retValueSize, &retValueSize,
NULL, NULL,
&typ, &typ,
(BYTE *)retDataBuf, retDataBuf,
&retDataSize); &retDataSize);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
@ -1100,7 +1053,7 @@ PyEnumValue(PyObject *self, PyObject *args)
retVal = NULL; retVal = NULL;
goto fail; goto fail;
} }
retVal = Py_BuildValue("UOi", retValueBuf, obData, typ); retVal = Py_BuildValue("uOi", retValueBuf, obData, typ);
Py_DECREF(obData); Py_DECREF(obData);
fail: fail:
PyMem_Free(retValueBuf); PyMem_Free(retValueBuf);
@ -1131,16 +1084,16 @@ PyLoadKey(PyObject *self, PyObject *args)
{ {
HKEY hKey; HKEY hKey;
PyObject *obKey; PyObject *obKey;
char *subKey; wchar_t *subKey;
char *fileName; wchar_t *fileName;
long rc; long rc;
if (!PyArg_ParseTuple(args, "Oss:LoadKey", &obKey, &subKey, &fileName)) if (!PyArg_ParseTuple(args, "Ouu:LoadKey", &obKey, &subKey, &fileName))
return NULL; return NULL;
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
rc = RegLoadKey(hKey, subKey, fileName ); rc = RegLoadKeyW(hKey, subKey, fileName );
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, "RegLoadKey"); return PyErr_SetFromWindowsErrWithFunction(rc, "RegLoadKey");
@ -1154,19 +1107,19 @@ PyOpenKey(PyObject *self, PyObject *args)
HKEY hKey; HKEY hKey;
PyObject *obKey; PyObject *obKey;
char *subKey; wchar_t *subKey;
int res = 0; int res = 0;
HKEY retKey; HKEY retKey;
long rc; long rc;
REGSAM sam = KEY_READ; REGSAM sam = KEY_READ;
if (!PyArg_ParseTuple(args, "Oz|ii:OpenKey", &obKey, &subKey, if (!PyArg_ParseTuple(args, "OZ|ii:OpenKey", &obKey, &subKey,
&res, &sam)) &res, &sam))
return NULL; return NULL;
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
rc = RegOpenKeyEx(hKey, subKey, res, sam, &retKey); rc = RegOpenKeyExW(hKey, subKey, res, sam, &retKey);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, "RegOpenKeyEx"); return PyErr_SetFromWindowsErrWithFunction(rc, "RegOpenKeyEx");
@ -1208,33 +1161,33 @@ PyQueryValue(PyObject *self, PyObject *args)
{ {
HKEY hKey; HKEY hKey;
PyObject *obKey; PyObject *obKey;
char *subKey; wchar_t *subKey;
long rc; long rc;
PyObject *retStr; PyObject *retStr;
char *retBuf; wchar_t *retBuf;
long bufSize = 0; long bufSize = 0;
if (!PyArg_ParseTuple(args, "Oz:QueryValue", &obKey, &subKey)) if (!PyArg_ParseTuple(args, "OZ:QueryValue", &obKey, &subKey))
return NULL; return NULL;
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL; return NULL;
if ((rc = RegQueryValue(hKey, subKey, NULL, &bufSize)) if ((rc = RegQueryValueW(hKey, subKey, NULL, &bufSize))
!= ERROR_SUCCESS) != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryValue"); "RegQueryValue");
retBuf = (char *)PyMem_Malloc(bufSize); retBuf = (wchar_t *)PyMem_Malloc(bufSize);
if (retBuf == NULL) if (retBuf == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
if ((rc = RegQueryValue(hKey, subKey, retBuf, &bufSize)) if ((rc = RegQueryValueW(hKey, subKey, retBuf, &bufSize))
!= ERROR_SUCCESS) { != ERROR_SUCCESS) {
PyMem_Free(retBuf); PyMem_Free(retBuf);
return PyErr_SetFromWindowsErrWithFunction(rc, return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryValue"); "RegQueryValue");
} }
retStr = PyUnicode_DecodeMBCS(retBuf, strlen(retBuf), NULL); retStr = PyUnicode_FromUnicode(retBuf, wcslen(retBuf));
PyMem_Free(retBuf); PyMem_Free(retBuf);
return retStr; return retStr;
} }
@ -1244,38 +1197,38 @@ PyQueryValueEx(PyObject *self, PyObject *args)
{ {
HKEY hKey; HKEY hKey;
PyObject *obKey; PyObject *obKey;
char *valueName; wchar_t *valueName;
long rc; long rc;
char *retBuf; BYTE *retBuf;
DWORD bufSize = 0; DWORD bufSize = 0;
DWORD typ; DWORD typ;
PyObject *obData; PyObject *obData;
PyObject *result; PyObject *result;
if (!PyArg_ParseTuple(args, "Oz:QueryValueEx", &obKey, &valueName)) if (!PyArg_ParseTuple(args, "OZ:QueryValueEx", &obKey, &valueName))
return NULL; return NULL;
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL; return NULL;
if ((rc = RegQueryValueEx(hKey, valueName, if ((rc = RegQueryValueExW(hKey, valueName,
NULL, NULL, NULL, NULL, NULL, NULL,
&bufSize)) &bufSize))
!= ERROR_SUCCESS) != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryValueEx"); "RegQueryValueEx");
retBuf = (char *)PyMem_Malloc(bufSize); retBuf = (BYTE *)PyMem_Malloc(bufSize);
if (retBuf == NULL) if (retBuf == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
if ((rc = RegQueryValueEx(hKey, valueName, NULL, if ((rc = RegQueryValueExW(hKey, valueName, NULL,
&typ, (BYTE *)retBuf, &bufSize)) &typ, retBuf, &bufSize))
!= ERROR_SUCCESS) { != ERROR_SUCCESS) {
PyMem_Free(retBuf); PyMem_Free(retBuf);
return PyErr_SetFromWindowsErrWithFunction(rc, return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryValueEx"); "RegQueryValueEx");
} }
obData = Reg2Py(retBuf, bufSize, typ); obData = Reg2Py(retBuf, bufSize, typ);
PyMem_Free((void *)retBuf); PyMem_Free(retBuf);
if (obData == NULL) if (obData == NULL)
return NULL; return NULL;
result = Py_BuildValue("Oi", obData, typ); result = Py_BuildValue("Oi", obData, typ);
@ -1289,11 +1242,11 @@ PySaveKey(PyObject *self, PyObject *args)
{ {
HKEY hKey; HKEY hKey;
PyObject *obKey; PyObject *obKey;
char *fileName; wchar_t *fileName;
LPSECURITY_ATTRIBUTES pSA = NULL; LPSECURITY_ATTRIBUTES pSA = NULL;
long rc; long rc;
if (!PyArg_ParseTuple(args, "Os:SaveKey", &obKey, &fileName)) if (!PyArg_ParseTuple(args, "Ou:SaveKey", &obKey, &fileName))
return NULL; return NULL;
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL; return NULL;
@ -1302,7 +1255,7 @@ PySaveKey(PyObject *self, PyObject *args)
return NULL; return NULL;
*/ */
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
rc = RegSaveKey(hKey, fileName, pSA ); rc = RegSaveKeyW(hKey, fileName, pSA );
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, "RegSaveKey"); return PyErr_SetFromWindowsErrWithFunction(rc, "RegSaveKey");
@ -1315,18 +1268,17 @@ PySetValue(PyObject *self, PyObject *args)
{ {
HKEY hKey; HKEY hKey;
PyObject *obKey; PyObject *obKey;
char *subKey; wchar_t *subKey;
char *str; wchar_t *str;
DWORD typ; DWORD typ;
DWORD len; DWORD len;
long rc; long rc;
PyObject *obStrVal; if (!PyArg_ParseTuple(args, "OZiu#:SetValue",
PyObject *obSubKey;
if (!PyArg_ParseTuple(args, "OOiO:SetValue",
&obKey, &obKey,
&obSubKey, &subKey,
&typ, &typ,
&obStrVal)) &str,
&len))
return NULL; return NULL;
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE)) if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
return NULL; return NULL;
@ -1335,20 +1287,9 @@ PySetValue(PyObject *self, PyObject *args)
"Type must be _winreg.REG_SZ"); "Type must be _winreg.REG_SZ");
return NULL; 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 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 Py_END_ALLOW_THREADS
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValue"); return PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValue");
@ -1361,7 +1302,7 @@ PySetValueEx(PyObject *self, PyObject *args)
{ {
HKEY hKey; HKEY hKey;
PyObject *obKey; PyObject *obKey;
char *valueName; Py_UNICODE *valueName;
PyObject *obRes; PyObject *obRes;
PyObject *value; PyObject *value;
BYTE *data; BYTE *data;
@ -1370,7 +1311,7 @@ PySetValueEx(PyObject *self, PyObject *args)
LONG rc; LONG rc;
if (!PyArg_ParseTuple(args, "OzOiO:SetValueEx", if (!PyArg_ParseTuple(args, "OZOiO:SetValueEx",
&obKey, &obKey,
&valueName, &valueName,
&obRes, &obRes,
@ -1387,7 +1328,7 @@ PySetValueEx(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
rc = RegSetValueEx(hKey, valueName, 0, typ, data, len); rc = RegSetValueExW(hKey, valueName, 0, typ, data, len);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
PyMem_DEL(data); PyMem_DEL(data);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
@ -1511,3 +1452,4 @@ PyMODINIT_FUNC init_winreg(void)
ADD_INT(REG_RESOURCE_REQUIREMENTS_LIST); ADD_INT(REG_RESOURCE_REQUIREMENTS_LIST);
} }