mirror of https://github.com/python/cpython
gh-102344: Reimplement winreg QueryValue / SetValue using QueryValueEx / SetValueEx (GH-102345)
The newer APIs are more widely available than the old ones, and are called in a way to preserve functionality.
This commit is contained in:
parent
d3d20743ee
commit
c1748ed59d
|
@ -0,0 +1,2 @@
|
||||||
|
Implement ``winreg.QueryValue`` using ``QueryValueEx`` and
|
||||||
|
``winreg.SetValue`` using ``SetValueEx``. Patch by Max Bachmann.
|
178
PC/winreg.c
178
PC/winreg.c
|
@ -1488,53 +1488,77 @@ static PyObject *
|
||||||
winreg_QueryValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key)
|
winreg_QueryValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key)
|
||||||
/*[clinic end generated code: output=c655810ae50c63a9 input=41cafbbf423b21d6]*/
|
/*[clinic end generated code: output=c655810ae50c63a9 input=41cafbbf423b21d6]*/
|
||||||
{
|
{
|
||||||
long rc;
|
LONG rc;
|
||||||
PyObject *retStr;
|
HKEY childKey = key;
|
||||||
wchar_t *retBuf;
|
WCHAR buf[256], *pbuf = buf;
|
||||||
DWORD bufSize = 0;
|
DWORD size = sizeof(buf);
|
||||||
DWORD retSize = 0;
|
DWORD type;
|
||||||
wchar_t *tmp;
|
Py_ssize_t length;
|
||||||
|
PyObject *result = NULL;
|
||||||
|
|
||||||
if (PySys_Audit("winreg.QueryValue", "nuu",
|
if (PySys_Audit("winreg.QueryValue", "nuu",
|
||||||
(Py_ssize_t)key, sub_key, NULL) < 0) {
|
(Py_ssize_t)key, sub_key, NULL) < 0)
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
rc = RegQueryValueW(key, sub_key, NULL, &retSize);
|
|
||||||
if (rc == ERROR_MORE_DATA)
|
|
||||||
retSize = 256;
|
|
||||||
else if (rc != ERROR_SUCCESS)
|
|
||||||
return PyErr_SetFromWindowsErrWithFunction(rc,
|
|
||||||
"RegQueryValue");
|
|
||||||
|
|
||||||
bufSize = retSize;
|
if (key == HKEY_PERFORMANCE_DATA) {
|
||||||
retBuf = (wchar_t *) PyMem_Malloc(bufSize);
|
return PyErr_SetFromWindowsErrWithFunction(ERROR_INVALID_HANDLE,
|
||||||
if (retBuf == NULL)
|
"RegQueryValue");
|
||||||
return PyErr_NoMemory();
|
}
|
||||||
|
|
||||||
|
if (sub_key && sub_key[0]) {
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
rc = RegOpenKeyExW(key, sub_key, 0, KEY_QUERY_VALUE, &childKey);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
if (rc != ERROR_SUCCESS) {
|
||||||
|
return PyErr_SetFromWindowsErrWithFunction(rc, "RegOpenKeyEx");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
retSize = bufSize;
|
Py_BEGIN_ALLOW_THREADS
|
||||||
rc = RegQueryValueW(key, sub_key, retBuf, &retSize);
|
rc = RegQueryValueExW(childKey, NULL, NULL, &type, (LPBYTE)pbuf,
|
||||||
if (rc != ERROR_MORE_DATA)
|
&size);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
if (rc != ERROR_MORE_DATA) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
bufSize *= 2;
|
void *tmp = PyMem_Realloc(pbuf != buf ? pbuf : NULL, size);
|
||||||
tmp = (wchar_t *) PyMem_Realloc(retBuf, bufSize);
|
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
PyMem_Free(retBuf);
|
PyErr_NoMemory();
|
||||||
return PyErr_NoMemory();
|
goto exit;
|
||||||
}
|
}
|
||||||
retBuf = tmp;
|
pbuf = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != ERROR_SUCCESS) {
|
if (rc == ERROR_SUCCESS) {
|
||||||
PyMem_Free(retBuf);
|
if (type != REG_SZ) {
|
||||||
return PyErr_SetFromWindowsErrWithFunction(rc,
|
PyErr_SetFromWindowsErrWithFunction(ERROR_INVALID_DATA,
|
||||||
"RegQueryValue");
|
"RegQueryValue");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
length = wcsnlen(pbuf, size / sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
else if (rc == ERROR_FILE_NOT_FOUND) {
|
||||||
|
// Return an empty string if there's no default value.
|
||||||
|
length = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_SetFromWindowsErrWithFunction(rc, "RegQueryValueEx");
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
retStr = PyUnicode_FromWideChar(retBuf, wcslen(retBuf));
|
result = PyUnicode_FromWideChar(pbuf, length);
|
||||||
PyMem_Free(retBuf);
|
|
||||||
return retStr;
|
exit:
|
||||||
|
if (pbuf != buf) {
|
||||||
|
PyMem_Free(pbuf);
|
||||||
|
}
|
||||||
|
if (childKey != key) {
|
||||||
|
RegCloseKey(childKey);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1687,38 +1711,69 @@ winreg_SetValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key,
|
||||||
DWORD type, PyObject *value_obj)
|
DWORD type, PyObject *value_obj)
|
||||||
/*[clinic end generated code: output=d4773dc9c372311a input=bf088494ae2d24fd]*/
|
/*[clinic end generated code: output=d4773dc9c372311a input=bf088494ae2d24fd]*/
|
||||||
{
|
{
|
||||||
Py_ssize_t value_length;
|
LONG rc;
|
||||||
long rc;
|
HKEY childKey = key;
|
||||||
|
LPWSTR value;
|
||||||
|
Py_ssize_t size;
|
||||||
|
Py_ssize_t length;
|
||||||
|
PyObject *result = NULL;
|
||||||
|
|
||||||
if (type != REG_SZ) {
|
if (type != REG_SZ) {
|
||||||
PyErr_SetString(PyExc_TypeError, "type must be winreg.REG_SZ");
|
PyErr_SetString(PyExc_TypeError, "type must be winreg.REG_SZ");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *value = PyUnicode_AsWideCharString(value_obj, &value_length);
|
value = PyUnicode_AsWideCharString(value_obj, &length);
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if ((Py_ssize_t)(DWORD)value_length != value_length) {
|
|
||||||
|
size = (length + 1) * sizeof(WCHAR);
|
||||||
|
if ((Py_ssize_t)(DWORD)size != size) {
|
||||||
PyErr_SetString(PyExc_OverflowError, "value is too long");
|
PyErr_SetString(PyExc_OverflowError, "value is too long");
|
||||||
PyMem_Free(value);
|
goto exit;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PySys_Audit("winreg.SetValue", "nunu#",
|
if (PySys_Audit("winreg.SetValue", "nunu#",
|
||||||
(Py_ssize_t)key, sub_key, (Py_ssize_t)type,
|
(Py_ssize_t)key, sub_key, (Py_ssize_t)type,
|
||||||
value, value_length) < 0) {
|
value, length) < 0)
|
||||||
PyMem_Free(value);
|
{
|
||||||
return NULL;
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == HKEY_PERFORMANCE_DATA) {
|
||||||
|
PyErr_SetFromWindowsErrWithFunction(ERROR_INVALID_HANDLE,
|
||||||
|
"RegSetValue");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sub_key && sub_key[0]) {
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
rc = RegCreateKeyExW(key, sub_key, 0, NULL, 0, KEY_SET_VALUE, NULL,
|
||||||
|
&childKey, NULL);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
if (rc != ERROR_SUCCESS) {
|
||||||
|
PyErr_SetFromWindowsErrWithFunction(rc, "RegCreateKeyEx");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
rc = RegSetValueW(key, sub_key, REG_SZ, value, (DWORD)(value_length + 1));
|
rc = RegSetValueExW(childKey, NULL, 0, REG_SZ, (LPBYTE)value, (DWORD)size);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
if (rc == ERROR_SUCCESS) {
|
||||||
|
result = Py_NewRef(Py_None);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValueEx");
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
PyMem_Free(value);
|
PyMem_Free(value);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (childKey != key) {
|
||||||
return PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValue");
|
RegCloseKey(childKey);
|
||||||
Py_RETURN_NONE;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
@ -1771,32 +1826,39 @@ winreg_SetValueEx_impl(PyObject *module, HKEY key,
|
||||||
DWORD type, PyObject *value)
|
DWORD type, PyObject *value)
|
||||||
/*[clinic end generated code: output=811b769a66ae11b7 input=900a9e3990bfb196]*/
|
/*[clinic end generated code: output=811b769a66ae11b7 input=900a9e3990bfb196]*/
|
||||||
{
|
{
|
||||||
BYTE *data;
|
|
||||||
DWORD len;
|
|
||||||
|
|
||||||
LONG rc;
|
LONG rc;
|
||||||
|
BYTE *data = NULL;
|
||||||
|
DWORD size;
|
||||||
|
PyObject *result = NULL;
|
||||||
|
|
||||||
if (!Py2Reg(value, type, &data, &len))
|
if (!Py2Reg(value, type, &data, &size))
|
||||||
{
|
{
|
||||||
if (!PyErr_Occurred())
|
if (!PyErr_Occurred()) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"Could not convert the data to the specified type.");
|
"Could not convert the data to the specified type.");
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (PySys_Audit("winreg.SetValue", "nunO",
|
if (PySys_Audit("winreg.SetValue", "nunO",
|
||||||
(Py_ssize_t)key, value_name, (Py_ssize_t)type,
|
(Py_ssize_t)key, value_name, (Py_ssize_t)type,
|
||||||
value) < 0) {
|
value) < 0)
|
||||||
PyMem_Free(data);
|
{
|
||||||
return NULL;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
rc = RegSetValueExW(key, value_name, 0, type, data, len);
|
rc = RegSetValueExW(key, value_name, 0, type, data, size);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
if (rc == ERROR_SUCCESS) {
|
||||||
|
result = Py_NewRef(Py_None);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValueEx");
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
PyMem_Free(data);
|
PyMem_Free(data);
|
||||||
if (rc != ERROR_SUCCESS)
|
return result;
|
||||||
return PyErr_SetFromWindowsErrWithFunction(rc,
|
|
||||||
"RegSetValueEx");
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
|
Loading…
Reference in New Issue