From 0d928df61a177021a3575932e6ed97831afcc0fe Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Tue, 28 Feb 2023 22:37:41 +0100 Subject: [PATCH 01/10] reimplement QueryValue / SetValue --- PC/winreg.c | 146 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 100 insertions(+), 46 deletions(-) diff --git a/PC/winreg.c b/PC/winreg.c index 63b37be526ab80..4a24cc706a6f13 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -561,7 +561,7 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize) { Py_ssize_t i,j; switch (typ) { - case REG_DWORD: + case REG_DWORD: { if (value != Py_None && !PyLong_Check(value)) { return FALSE; @@ -585,7 +585,7 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize) *retDataSize = sizeof(DWORD); break; } - case REG_QWORD: + case REG_QWORD: { if (value != Py_None && !PyLong_Check(value)) { return FALSE; @@ -1488,53 +1488,76 @@ static PyObject * winreg_QueryValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key) /*[clinic end generated code: output=c655810ae50c63a9 input=41cafbbf423b21d6]*/ { - long rc; - PyObject *retStr; - wchar_t *retBuf; - DWORD bufSize = 0; - DWORD retSize = 0; - wchar_t *tmp; + LONG rc; + HKEY childKey = key; + WCHAR buf[256], *pbuf = buf; + DWORD size = sizeof(buf); + DWORD type; + Py_ssize_t length; + PyObject *result = NULL; if (PySys_Audit("winreg.QueryValue", "nuu", (Py_ssize_t)key, sub_key, NULL) < 0) { 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, + + if (key == HKEY_PERFORMANCE_DATA) { + return PyErr_SetFromWindowsErrWithFunction(ERROR_INVALID_HANDLE, "RegQueryValue"); + } - bufSize = retSize; - retBuf = (wchar_t *) PyMem_Malloc(bufSize); - if (retBuf == NULL) - 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) { - retSize = bufSize; - rc = RegQueryValueW(key, sub_key, retBuf, &retSize); - if (rc != ERROR_MORE_DATA) + Py_BEGIN_ALLOW_THREADS + rc = RegQueryValueExW(childKey, NULL, NULL, &type, (LPBYTE)pbuf, + &size); + Py_END_ALLOW_THREADS + if (rc != ERROR_MORE_DATA) { break; - - bufSize *= 2; - tmp = (wchar_t *) PyMem_Realloc(retBuf, bufSize); + } + void *tmp = PyMem_Realloc(pbuf != buf ? pbuf : NULL, size); if (tmp == NULL) { - PyMem_Free(retBuf); - return PyErr_NoMemory(); + PyErr_NoMemory(); + goto exit; } - retBuf = tmp; + pbuf = tmp; } - if (rc != ERROR_SUCCESS) { - PyMem_Free(retBuf); - return PyErr_SetFromWindowsErrWithFunction(rc, - "RegQueryValue"); + if (rc == ERROR_SUCCESS) { + if (type != REG_SZ) { + PyErr_SetFromWindowsErrWithFunction(ERROR_INVALID_DATA, + "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)); - PyMem_Free(retBuf); - return retStr; + result = PyUnicode_FromWideChar(pbuf, length); + +exit: + if (pbuf != buf) { + PyMem_Free(pbuf); + } + if (childKey != key) { + RegCloseKey(childKey); + } + return result; } @@ -1687,38 +1710,69 @@ winreg_SetValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key, DWORD type, PyObject *value_obj) /*[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) { PyErr_SetString(PyExc_TypeError, "type must be winreg.REG_SZ"); return NULL; } - wchar_t *value = PyUnicode_AsWideCharString(value_obj, &value_length); + value = PyUnicode_AsWideCharString(value_obj, &length); if (value == 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"); - PyMem_Free(value); - return NULL; + goto exit; } if (PySys_Audit("winreg.SetValue", "nunu#", (Py_ssize_t)key, sub_key, (Py_ssize_t)type, - value, value_length) < 0) { - PyMem_Free(value); - return NULL; + value, length) < 0) + { + 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 - 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 + if (rc == ERROR_SUCCESS) { + result = Py_NewRef(Py_None); + } + else { + PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValueEx"); + } + +exit: PyMem_Free(value); - if (rc != ERROR_SUCCESS) - return PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValue"); - Py_RETURN_NONE; + if (childKey != key) { + RegCloseKey(childKey); + } + return result; } /*[clinic input] From e0b256d791073e8133b8cbdf310e1bde1bb40908 Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Tue, 28 Feb 2023 23:11:25 +0100 Subject: [PATCH 02/10] refactor QueryValueEx --- PC/winreg.c | 56 +++++++++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/PC/winreg.c b/PC/winreg.c index 4a24cc706a6f13..d88af1f96b164e 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -1582,54 +1582,50 @@ static PyObject * winreg_QueryValueEx_impl(PyObject *module, HKEY key, const Py_UNICODE *name) /*[clinic end generated code: output=f1b85b1c3d887ec7 input=cf366cada4836891]*/ { - long rc; - BYTE *retBuf, *tmp; + LONG rc; + WCHAR buf[256], *pbuf = buf; + DWORD size = sizeof(buf); DWORD bufSize = 0, retSize; DWORD typ; - PyObject *obData; - PyObject *result; + PyObject *obData = NULL; + PyObject *result = NULL; if (PySys_Audit("winreg.QueryValue", "nuu", (Py_ssize_t)key, NULL, name) < 0) { return NULL; } - rc = RegQueryValueExW(key, name, NULL, NULL, NULL, &bufSize); - if (rc == ERROR_MORE_DATA) - bufSize = 256; - else if (rc != ERROR_SUCCESS) - return PyErr_SetFromWindowsErrWithFunction(rc, - "RegQueryValueEx"); - retBuf = (BYTE *)PyMem_Malloc(bufSize); - if (retBuf == NULL) - return PyErr_NoMemory(); while (1) { - retSize = bufSize; - rc = RegQueryValueExW(key, name, NULL, &typ, - (BYTE *)retBuf, &retSize); - if (rc != ERROR_MORE_DATA) + Py_BEGIN_ALLOW_THREADS + rc = RegQueryValueExW(key, name, NULL, &typ, (LPBYTE)pbuf, + &size); + Py_END_ALLOW_THREADS + if (rc != ERROR_MORE_DATA) { break; - - bufSize *= 2; - tmp = (char *) PyMem_Realloc(retBuf, bufSize); + } + void *tmp = PyMem_Realloc(pbuf != buf ? pbuf : NULL, size); if (tmp == NULL) { - PyMem_Free(retBuf); - return PyErr_NoMemory(); + PyErr_NoMemory(); + goto exit; } - retBuf = tmp; + pbuf = tmp; } if (rc != ERROR_SUCCESS) { - PyMem_Free(retBuf); - return PyErr_SetFromWindowsErrWithFunction(rc, - "RegQueryValueEx"); + PyErr_SetFromWindowsErrWithFunction(rc, "RegQueryValueEx"); + goto exit; + } + obData = Reg2Py(pbuf, length, typ); + if (obData == NULL) { + goto exit; } - obData = Reg2Py(retBuf, bufSize, typ); - PyMem_Free(retBuf); - if (obData == NULL) - return NULL; result = Py_BuildValue("Oi", obData, typ); Py_DECREF(obData); + +exit: + if (pbuf != buf) { + PyMem_Free(pbuf); + } return result; } From 799f380cbc93fefc63340de3d747040bd7bbfd56 Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Tue, 28 Feb 2023 23:22:21 +0100 Subject: [PATCH 03/10] cleanup --- PC/winreg.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/PC/winreg.c b/PC/winreg.c index d88af1f96b164e..d01c1e24dc6441 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -1497,7 +1497,8 @@ winreg_QueryValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key) PyObject *result = NULL; if (PySys_Audit("winreg.QueryValue", "nuu", - (Py_ssize_t)key, sub_key, NULL) < 0) { + (Py_ssize_t)key, sub_key, NULL) < 0) + { return NULL; } @@ -1591,7 +1592,8 @@ winreg_QueryValueEx_impl(PyObject *module, HKEY key, const Py_UNICODE *name) PyObject *result = NULL; if (PySys_Audit("winreg.QueryValue", "nuu", - (Py_ssize_t)key, NULL, name) < 0) { + (Py_ssize_t)key, NULL, name) < 0) + { return NULL; } @@ -1821,32 +1823,39 @@ winreg_SetValueEx_impl(PyObject *module, HKEY key, DWORD type, PyObject *value) /*[clinic end generated code: output=811b769a66ae11b7 input=900a9e3990bfb196]*/ { - BYTE *data; - DWORD len; - LONG rc; + BYTE *value = NULL; + DWORD size; + PyObject *result = NULL; - if (!Py2Reg(value, type, &data, &len)) + if (!Py2Reg(value_obj, type, &value, &size)) { - if (!PyErr_Occurred()) + if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, "Could not convert the data to the specified type."); + } return NULL; } if (PySys_Audit("winreg.SetValue", "nunO", (Py_ssize_t)key, value_name, (Py_ssize_t)type, - value) < 0) { - PyMem_Free(data); - return NULL; + value_obj) < 0) + { + goto exit; } + Py_BEGIN_ALLOW_THREADS - rc = RegSetValueExW(key, value_name, 0, type, data, len); + rc = RegSetValueExW(key, value_name, 0, type, value, size); Py_END_ALLOW_THREADS - PyMem_Free(data); - if (rc != ERROR_SUCCESS) - return PyErr_SetFromWindowsErrWithFunction(rc, - "RegSetValueEx"); - Py_RETURN_NONE; + if (rc == ERROR_SUCCESS) { + result = Py_NewRef(Py_None); + } + else { + PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValueEx"); + } + +exit: + PyMem_Free(value); + return result; } /*[clinic input] From 67ef9f305f91bc5476240f316554ac9606b324e5 Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Tue, 28 Feb 2023 23:25:39 +0100 Subject: [PATCH 04/10] fix type --- PC/winreg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PC/winreg.c b/PC/winreg.c index d01c1e24dc6441..b0862107aeb71b 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -1584,7 +1584,7 @@ winreg_QueryValueEx_impl(PyObject *module, HKEY key, const Py_UNICODE *name) /*[clinic end generated code: output=f1b85b1c3d887ec7 input=cf366cada4836891]*/ { LONG rc; - WCHAR buf[256], *pbuf = buf; + BYTE buf[256], *pbuf = buf; DWORD size = sizeof(buf); DWORD bufSize = 0, retSize; DWORD typ; @@ -1599,7 +1599,7 @@ winreg_QueryValueEx_impl(PyObject *module, HKEY key, const Py_UNICODE *name) while (1) { Py_BEGIN_ALLOW_THREADS - rc = RegQueryValueExW(key, name, NULL, &typ, (LPBYTE)pbuf, + rc = RegQueryValueExW(key, name, NULL, &typ, pbuf, &size); Py_END_ALLOW_THREADS if (rc != ERROR_MORE_DATA) { @@ -1617,7 +1617,7 @@ winreg_QueryValueEx_impl(PyObject *module, HKEY key, const Py_UNICODE *name) PyErr_SetFromWindowsErrWithFunction(rc, "RegQueryValueEx"); goto exit; } - obData = Reg2Py(pbuf, length, typ); + obData = Reg2Py(pbuf, size, typ); if (obData == NULL) { goto exit; } From fbc1a0ea3af02e58f89eacf185fff237737ca9bf Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Tue, 28 Feb 2023 23:27:44 +0100 Subject: [PATCH 05/10] remove unused variables --- PC/winreg.c | 1 - 1 file changed, 1 deletion(-) diff --git a/PC/winreg.c b/PC/winreg.c index b0862107aeb71b..1ed0f2da53c3a8 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -1586,7 +1586,6 @@ winreg_QueryValueEx_impl(PyObject *module, HKEY key, const Py_UNICODE *name) LONG rc; BYTE buf[256], *pbuf = buf; DWORD size = sizeof(buf); - DWORD bufSize = 0, retSize; DWORD typ; PyObject *obData = NULL; PyObject *result = NULL; From de0549bc1d65962ead12f429b535d83dfefdda36 Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Wed, 1 Mar 2023 01:06:59 +0100 Subject: [PATCH 06/10] fix duplicated variable name --- PC/winreg.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PC/winreg.c b/PC/winreg.c index 1ed0f2da53c3a8..12a7a60d2ad469 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -1823,11 +1823,11 @@ winreg_SetValueEx_impl(PyObject *module, HKEY key, /*[clinic end generated code: output=811b769a66ae11b7 input=900a9e3990bfb196]*/ { LONG rc; - BYTE *value = NULL; + BYTE *data = NULL; DWORD size; PyObject *result = NULL; - if (!Py2Reg(value_obj, type, &value, &size)) + if (!Py2Reg(value, type, &data, &size)) { if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, @@ -1837,13 +1837,13 @@ winreg_SetValueEx_impl(PyObject *module, HKEY key, } if (PySys_Audit("winreg.SetValue", "nunO", (Py_ssize_t)key, value_name, (Py_ssize_t)type, - value_obj) < 0) + value) < 0) { goto exit; } Py_BEGIN_ALLOW_THREADS - rc = RegSetValueExW(key, value_name, 0, type, value, size); + rc = RegSetValueExW(key, value_name, 0, type, data, size); Py_END_ALLOW_THREADS if (rc == ERROR_SUCCESS) { result = Py_NewRef(Py_None); @@ -1853,7 +1853,7 @@ winreg_SetValueEx_impl(PyObject *module, HKEY key, } exit: - PyMem_Free(value); + PyMem_Free(data); return result; } From deca441770ef2dcf98a486ce0889420910c841c6 Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Wed, 1 Mar 2023 01:36:49 +0100 Subject: [PATCH 07/10] add news --- .../2023-03-01-01-36-39.gh-issue-102344.Dgfux4.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-03-01-01-36-39.gh-issue-102344.Dgfux4.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-03-01-01-36-39.gh-issue-102344.Dgfux4.rst b/Misc/NEWS.d/next/Core and Builtins/2023-03-01-01-36-39.gh-issue-102344.Dgfux4.rst new file mode 100644 index 00000000000000..4804212be8182c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-03-01-01-36-39.gh-issue-102344.Dgfux4.rst @@ -0,0 +1,2 @@ +Implement ``winreg.QueryValue`` using ``QueryValueEx`` and +``winreg.SetValue`` using ``SetValueEx``. Patch by Max Bachmann. From 2c95f23c9a2f6f4a02262329b7f17104d47d056c Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Wed, 1 Mar 2023 02:36:19 +0100 Subject: [PATCH 08/10] Update PC/winreg.c Co-authored-by: Eryk Sun --- PC/winreg.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/PC/winreg.c b/PC/winreg.c index 12a7a60d2ad469..7dc6abd425ed01 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -1598,8 +1598,7 @@ winreg_QueryValueEx_impl(PyObject *module, HKEY key, const Py_UNICODE *name) while (1) { Py_BEGIN_ALLOW_THREADS - rc = RegQueryValueExW(key, name, NULL, &typ, pbuf, - &size); + rc = RegQueryValueExW(key, name, NULL, &typ, pbuf, &size); Py_END_ALLOW_THREADS if (rc != ERROR_MORE_DATA) { break; From 8a4543b9374d77bd501c089d66f644a82eb91c20 Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Wed, 1 Mar 2023 11:58:54 +0100 Subject: [PATCH 09/10] revert part --- PC/winreg.c | 59 +++++++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/PC/winreg.c b/PC/winreg.c index 7dc6abd425ed01..86efed09855b01 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -1583,49 +1583,54 @@ static PyObject * winreg_QueryValueEx_impl(PyObject *module, HKEY key, const Py_UNICODE *name) /*[clinic end generated code: output=f1b85b1c3d887ec7 input=cf366cada4836891]*/ { - LONG rc; - BYTE buf[256], *pbuf = buf; - DWORD size = sizeof(buf); + long rc; + BYTE *retBuf, *tmp; + DWORD bufSize = 0, retSize; DWORD typ; - PyObject *obData = NULL; - PyObject *result = NULL; + PyObject *obData; + PyObject *result; if (PySys_Audit("winreg.QueryValue", "nuu", - (Py_ssize_t)key, NULL, name) < 0) - { + (Py_ssize_t)key, NULL, name) < 0) { return NULL; } + rc = RegQueryValueExW(key, name, NULL, NULL, NULL, &bufSize); + if (rc == ERROR_MORE_DATA) + bufSize = 256; + else if (rc != ERROR_SUCCESS) + return PyErr_SetFromWindowsErrWithFunction(rc, + "RegQueryValueEx"); + retBuf = (BYTE *)PyMem_Malloc(bufSize); + if (retBuf == NULL) + return PyErr_NoMemory(); while (1) { - Py_BEGIN_ALLOW_THREADS - rc = RegQueryValueExW(key, name, NULL, &typ, pbuf, &size); - Py_END_ALLOW_THREADS - if (rc != ERROR_MORE_DATA) { + retSize = bufSize; + rc = RegQueryValueExW(key, name, NULL, &typ, + (BYTE *)retBuf, &retSize); + if (rc != ERROR_MORE_DATA) break; - } - void *tmp = PyMem_Realloc(pbuf != buf ? pbuf : NULL, size); + + bufSize *= 2; + tmp = (char *) PyMem_Realloc(retBuf, bufSize); if (tmp == NULL) { - PyErr_NoMemory(); - goto exit; + PyMem_Free(retBuf); + return PyErr_NoMemory(); } - pbuf = tmp; + retBuf = tmp; } if (rc != ERROR_SUCCESS) { - PyErr_SetFromWindowsErrWithFunction(rc, "RegQueryValueEx"); - goto exit; - } - obData = Reg2Py(pbuf, size, typ); - if (obData == NULL) { - goto exit; + PyMem_Free(retBuf); + return PyErr_SetFromWindowsErrWithFunction(rc, + "RegQueryValueEx"); } + obData = Reg2Py(retBuf, bufSize, typ); + PyMem_Free(retBuf); + if (obData == NULL) + return NULL; result = Py_BuildValue("Oi", obData, typ); Py_DECREF(obData); - -exit: - if (pbuf != buf) { - PyMem_Free(pbuf); - } return result; } From 8397a2fda74b35b4cc33abff83934461b66b2975 Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Wed, 1 Mar 2023 13:55:28 +0100 Subject: [PATCH 10/10] move news --- .../2023-03-01-01-36-39.gh-issue-102344.Dgfux4.rst | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Misc/NEWS.d/next/{Core and Builtins => Windows}/2023-03-01-01-36-39.gh-issue-102344.Dgfux4.rst (100%) diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-03-01-01-36-39.gh-issue-102344.Dgfux4.rst b/Misc/NEWS.d/next/Windows/2023-03-01-01-36-39.gh-issue-102344.Dgfux4.rst similarity index 100% rename from Misc/NEWS.d/next/Core and Builtins/2023-03-01-01-36-39.gh-issue-102344.Dgfux4.rst rename to Misc/NEWS.d/next/Windows/2023-03-01-01-36-39.gh-issue-102344.Dgfux4.rst