@@ -561,7 +561,7 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
561561{
562562 Py_ssize_t i ,j ;
563563 switch (typ ) {
564- case REG_DWORD :
564+ case REG_DWORD :
565565 {
566566 if (value != Py_None && !PyLong_Check (value )) {
567567 return FALSE;
@@ -585,7 +585,7 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
585585 * retDataSize = sizeof (DWORD );
586586 break ;
587587 }
588- case REG_QWORD :
588+ case REG_QWORD :
589589 {
590590 if (value != Py_None && !PyLong_Check (value )) {
591591 return FALSE;
@@ -1488,53 +1488,77 @@ static PyObject *
14881488winreg_QueryValue_impl (PyObject * module , HKEY key , const Py_UNICODE * sub_key )
14891489/*[clinic end generated code: output=c655810ae50c63a9 input=41cafbbf423b21d6]*/
14901490{
1491- long rc ;
1492- PyObject * retStr ;
1493- wchar_t * retBuf ;
1494- DWORD bufSize = 0 ;
1495- DWORD retSize = 0 ;
1496- wchar_t * tmp ;
1491+ LONG rc ;
1492+ HKEY childKey = key ;
1493+ WCHAR buf [256 ], * pbuf = buf ;
1494+ DWORD size = sizeof (buf );
1495+ DWORD type ;
1496+ Py_ssize_t length ;
1497+ PyObject * result = NULL ;
14971498
14981499 if (PySys_Audit ("winreg.QueryValue" , "nuu" ,
1499- (Py_ssize_t )key , sub_key , NULL ) < 0 ) {
1500+ (Py_ssize_t )key , sub_key , NULL ) < 0 )
1501+ {
15001502 return NULL ;
15011503 }
1502- rc = RegQueryValueW (key , sub_key , NULL , & retSize );
1503- if (rc == ERROR_MORE_DATA )
1504- retSize = 256 ;
1505- else if (rc != ERROR_SUCCESS )
1506- return PyErr_SetFromWindowsErrWithFunction (rc ,
1504+
1505+ if (key == HKEY_PERFORMANCE_DATA ) {
1506+ return PyErr_SetFromWindowsErrWithFunction (ERROR_INVALID_HANDLE ,
15071507 "RegQueryValue" );
1508+ }
15081509
1509- bufSize = retSize ;
1510- retBuf = (wchar_t * ) PyMem_Malloc (bufSize );
1511- if (retBuf == NULL )
1512- return PyErr_NoMemory ();
1510+ if (sub_key && sub_key [0 ]) {
1511+ Py_BEGIN_ALLOW_THREADS
1512+ rc = RegOpenKeyExW (key , sub_key , 0 , KEY_QUERY_VALUE , & childKey );
1513+ Py_END_ALLOW_THREADS
1514+ if (rc != ERROR_SUCCESS ) {
1515+ return PyErr_SetFromWindowsErrWithFunction (rc , "RegOpenKeyEx" );
1516+ }
1517+ }
15131518
15141519 while (1 ) {
1515- retSize = bufSize ;
1516- rc = RegQueryValueW (key , sub_key , retBuf , & retSize );
1517- if (rc != ERROR_MORE_DATA )
1520+ Py_BEGIN_ALLOW_THREADS
1521+ rc = RegQueryValueExW (childKey , NULL , NULL , & type , (LPBYTE )pbuf ,
1522+ & size );
1523+ Py_END_ALLOW_THREADS
1524+ if (rc != ERROR_MORE_DATA ) {
15181525 break ;
1519-
1520- bufSize *= 2 ;
1521- tmp = (wchar_t * ) PyMem_Realloc (retBuf , bufSize );
1526+ }
1527+ void * tmp = PyMem_Realloc (pbuf != buf ? pbuf : NULL , size );
15221528 if (tmp == NULL ) {
1523- PyMem_Free ( retBuf );
1524- return PyErr_NoMemory () ;
1529+ PyErr_NoMemory ( );
1530+ goto exit ;
15251531 }
1526- retBuf = tmp ;
1532+ pbuf = tmp ;
15271533 }
15281534
1529- if (rc != ERROR_SUCCESS ) {
1530- PyMem_Free (retBuf );
1531- return PyErr_SetFromWindowsErrWithFunction (rc ,
1532- "RegQueryValue" );
1535+ if (rc == ERROR_SUCCESS ) {
1536+ if (type != REG_SZ ) {
1537+ PyErr_SetFromWindowsErrWithFunction (ERROR_INVALID_DATA ,
1538+ "RegQueryValue" );
1539+ goto exit ;
1540+ }
1541+ length = wcsnlen (pbuf , size / sizeof (WCHAR ));
1542+ }
1543+ else if (rc == ERROR_FILE_NOT_FOUND ) {
1544+ // Return an empty string if there's no default value.
1545+ length = 0 ;
1546+ }
1547+ else {
1548+ PyErr_SetFromWindowsErrWithFunction (rc , "RegQueryValueEx" );
1549+ goto exit ;
15331550 }
15341551
1535- retStr = PyUnicode_FromWideChar (retBuf , wcslen (retBuf ));
1536- PyMem_Free (retBuf );
1537- return retStr ;
1552+ result = PyUnicode_FromWideChar (pbuf , length );
1553+
1554+ exit :
1555+ if (pbuf != buf ) {
1556+ PyMem_Free (pbuf );
1557+ }
1558+ if (childKey != key ) {
1559+ RegCloseKey (childKey );
1560+ }
1561+ return result ;
15381562}
15391563
15401564
@@ -1687,38 +1711,69 @@ winreg_SetValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key,
16871711 DWORD type , PyObject * value_obj )
16881712/*[clinic end generated code: output=d4773dc9c372311a input=bf088494ae2d24fd]*/
16891713{
1690- Py_ssize_t value_length ;
1691- long rc ;
1714+ LONG rc ;
1715+ HKEY childKey = key ;
1716+ LPWSTR value ;
1717+ Py_ssize_t size ;
1718+ Py_ssize_t length ;
1719+ PyObject * result = NULL ;
16921720
16931721 if (type != REG_SZ ) {
16941722 PyErr_SetString (PyExc_TypeError , "type must be winreg.REG_SZ" );
16951723 return NULL ;
16961724 }
16971725
1698- wchar_t * value = PyUnicode_AsWideCharString (value_obj , & value_length );
1726+ value = PyUnicode_AsWideCharString (value_obj , & length );
16991727 if (value == NULL ) {
17001728 return NULL ;
17011729 }
1702- if ((Py_ssize_t )(DWORD )value_length != value_length ) {
1730+
1731+ size = (length + 1 ) * sizeof (WCHAR );
1732+ if ((Py_ssize_t )(DWORD )size != size ) {
17031733 PyErr_SetString (PyExc_OverflowError , "value is too long" );
1704- PyMem_Free (value );
1705- return NULL ;
1734+ goto exit ;
17061735 }
17071736
17081737 if (PySys_Audit ("winreg.SetValue" , "nunu#" ,
17091738 (Py_ssize_t )key , sub_key , (Py_ssize_t )type ,
1710- value , value_length ) < 0 ) {
1711- PyMem_Free (value );
1712- return NULL ;
1739+ value , length ) < 0 )
1740+ {
1741+ goto exit ;
1742+ }
1743+
1744+ if (key == HKEY_PERFORMANCE_DATA ) {
1745+ PyErr_SetFromWindowsErrWithFunction (ERROR_INVALID_HANDLE ,
1746+ "RegSetValue" );
1747+ goto exit ;
1748+ }
1749+
1750+ if (sub_key && sub_key [0 ]) {
1751+ Py_BEGIN_ALLOW_THREADS
1752+ rc = RegCreateKeyExW (key , sub_key , 0 , NULL , 0 , KEY_SET_VALUE , NULL ,
1753+ & childKey , NULL );
1754+ Py_END_ALLOW_THREADS
1755+ if (rc != ERROR_SUCCESS ) {
1756+ PyErr_SetFromWindowsErrWithFunction (rc , "RegCreateKeyEx" );
1757+ goto exit ;
1758+ }
17131759 }
17141760
17151761 Py_BEGIN_ALLOW_THREADS
1716- rc = RegSetValueW ( key , sub_key , REG_SZ , value , (DWORD )( value_length + 1 ) );
1762+ rc = RegSetValueExW ( childKey , NULL , 0 , REG_SZ , ( LPBYTE ) value , (DWORD )size );
17171763 Py_END_ALLOW_THREADS
1764+ if (rc == ERROR_SUCCESS ) {
1765+ result = Py_NewRef (Py_None );
1766+ }
1767+ else {
1768+ PyErr_SetFromWindowsErrWithFunction (rc , "RegSetValueEx" );
1769+ }
1770+
1771+ exit :
17181772 PyMem_Free (value );
1719- if (rc != ERROR_SUCCESS )
1720- return PyErr_SetFromWindowsErrWithFunction (rc , "RegSetValue" );
1721- Py_RETURN_NONE ;
1773+ if (childKey != key ) {
1774+ RegCloseKey (childKey );
1775+ }
1776+ return result ;
17221777}
17231778
17241779/*[clinic input]
@@ -1771,32 +1826,39 @@ winreg_SetValueEx_impl(PyObject *module, HKEY key,
17711826 DWORD type , PyObject * value )
17721827/*[clinic end generated code: output=811b769a66ae11b7 input=900a9e3990bfb196]*/
17731828{
1774- BYTE * data ;
1775- DWORD len ;
1776-
17771829 LONG rc ;
1830+ BYTE * data = NULL ;
1831+ DWORD size ;
1832+ PyObject * result = NULL ;
17781833
1779- if (!Py2Reg (value , type , & data , & len ))
1834+ if (!Py2Reg (value , type , & data , & size ))
17801835 {
1781- if (!PyErr_Occurred ())
1836+ if (!PyErr_Occurred ()) {
17821837 PyErr_SetString (PyExc_ValueError ,
17831838 "Could not convert the data to the specified type." );
1839+ }
17841840 return NULL ;
17851841 }
17861842 if (PySys_Audit ("winreg.SetValue" , "nunO" ,
17871843 (Py_ssize_t )key , value_name , (Py_ssize_t )type ,
1788- value ) < 0 ) {
1789- PyMem_Free ( data );
1790- return NULL ;
1844+ value ) < 0 )
1845+ {
1846+ goto exit ;
17911847 }
1848+
17921849 Py_BEGIN_ALLOW_THREADS
1793- rc = RegSetValueExW (key , value_name , 0 , type , data , len );
1850+ rc = RegSetValueExW (key , value_name , 0 , type , data , size );
17941851 Py_END_ALLOW_THREADS
1852+ if (rc == ERROR_SUCCESS ) {
1853+ result = Py_NewRef (Py_None );
1854+ }
1855+ else {
1856+ PyErr_SetFromWindowsErrWithFunction (rc , "RegSetValueEx" );
1857+ }
1858+
1859+ exit :
17951860 PyMem_Free (data );
1796- if (rc != ERROR_SUCCESS )
1797- return PyErr_SetFromWindowsErrWithFunction (rc ,
1798- "RegSetValueEx" );
1799- Py_RETURN_NONE ;
1861+ return result ;
18001862}
18011863
18021864/*[clinic input]
0 commit comments