From d52f5b708bf6e0c8a364a7bb0433f98bfc19708b Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Mon, 4 Jun 2018 03:44:04 +0100 Subject: [PATCH] [ODBCCP32] Sync with Wine Staging 3.9. CORE-14656 --- dll/win32/odbccp32/odbccp32.c | 144 +++++++++++++++++----------------- media/doc/README.WINE | 2 +- 2 files changed, 75 insertions(+), 71 deletions(-) diff --git a/dll/win32/odbccp32/odbccp32.c b/dll/win32/odbccp32/odbccp32.c index f9a22693456..862237c6776 100644 --- a/dll/win32/odbccp32/odbccp32.c +++ b/dll/win32/odbccp32/odbccp32.c @@ -482,99 +482,103 @@ BOOL WINAPI SQLGetConfigMode(UWORD *pwConfigMode) return TRUE; } -/* This is implemented sensibly rather than according to exact conformance to Microsoft's buggy implementations - * e.g. The Microsoft one occasionally actually adds a third nul character (possibly beyond the buffer). - * e.g. If the key has no drivers then version 3.525.1117.0 does not modify the buffer at all, not even a nul character. - */ -BOOL WINAPI SQLGetInstalledDriversW(LPWSTR lpszBuf, WORD cbBufMax, - WORD *pcbBufOut) +BOOL WINAPI SQLGetInstalledDriversW(WCHAR *buf, WORD size, WORD *sizeout) { - HKEY hDrivers; /* Registry handle to the Drivers key */ - LONG reg_ret; /* Return code from registry functions */ - BOOL success = FALSE; /* The value we will return */ + WORD written = 0; + DWORD index = 0; + BOOL ret = TRUE; + DWORD valuelen; + WCHAR *value; + HKEY drivers; + DWORD len; + LONG res; clear_errors(); - TRACE("%p %d %p\n", lpszBuf, cbBufMax, pcbBufOut); + TRACE("%p %d %p\n", buf, size, sizeout); - if (!lpszBuf || cbBufMax == 0) + if (!buf || !size) { push_error(ODBC_ERROR_INVALID_BUFF_LEN, odbc_error_invalid_buff_len); + return FALSE; } - else if ((reg_ret = RegOpenKeyExW (HKEY_LOCAL_MACHINE /* The drivers does not depend on the config mode */, - drivers_key, 0, KEY_READ /* Maybe overkill */, - &hDrivers)) == ERROR_SUCCESS) + + res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, drivers_key, 0, KEY_QUERY_VALUE, &drivers); + if (res) { - DWORD index = 0; - cbBufMax--; - success = TRUE; - while (cbBufMax > 0) - { - DWORD size_name; - size_name = cbBufMax; - if ((reg_ret = RegEnumValueW(hDrivers, index, lpszBuf, &size_name, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS) - { - index++; - assert (size_name < cbBufMax && *(lpszBuf + size_name) == 0); - size_name++; - cbBufMax-= size_name; - lpszBuf+=size_name; - } - else - { - if (reg_ret != ERROR_NO_MORE_ITEMS) - { - success = FALSE; - push_error(ODBC_ERROR_GENERAL_ERR, odbc_error_general_err); - } - break; - } - } - *lpszBuf = 0; - if ((reg_ret = RegCloseKey (hDrivers)) != ERROR_SUCCESS) - TRACE ("Error %d closing ODBC Drivers key\n", reg_ret); + push_error(ODBC_ERROR_COMPONENT_NOT_FOUND, odbc_error_component_not_found); + return FALSE; } - else + + valuelen = 256; + value = heap_alloc(valuelen * sizeof(WCHAR)); + + size--; + + while (1) { - /* MSDN states that it returns failure with COMPONENT_NOT_FOUND in this case. - * Version 3.525.1117.0 (Windows 2000) does not; it actually returns success. - * I doubt if it will actually be an issue. - */ - push_error(ODBC_ERROR_COMPONENT_NOT_FOUND, odbc_error_component_not_found); + len = valuelen; + res = RegEnumValueW(drivers, index, value, &len, NULL, NULL, NULL, NULL); + while (res == ERROR_MORE_DATA) + { + value = heap_realloc(value, ++len * sizeof(WCHAR)); + res = RegEnumValueW(drivers, index, value, &len, NULL, NULL, NULL, NULL); + } + if (res == ERROR_SUCCESS) + { + lstrcpynW(buf + written, value, size - written); + written += min(len + 1, size - written); + } + else if (res == ERROR_NO_MORE_ITEMS) + break; + else + { + push_error(ODBC_ERROR_GENERAL_ERR, odbc_error_general_err); + ret = FALSE; + break; + } + index++; } - return success; + + buf[written++] = 0; + + heap_free(value); + RegCloseKey(drivers); + if (sizeout) + *sizeout = written; + return ret; } -BOOL WINAPI SQLGetInstalledDrivers(LPSTR lpszBuf, WORD cbBufMax, - WORD *pcbBufOut) +BOOL WINAPI SQLGetInstalledDrivers(char *buf, WORD size, WORD *sizeout) { + WORD written; + WCHAR *wbuf; BOOL ret; - int size_wbuf = cbBufMax; - LPWSTR wbuf; - WORD size_used; - TRACE("%p %d %p\n", lpszBuf, cbBufMax, pcbBufOut); + TRACE("%p %d %p\n", buf, size, sizeout); - wbuf = HeapAlloc(GetProcessHeap(), 0, size_wbuf*sizeof(WCHAR)); - if (wbuf) + if (!buf || !size) { - ret = SQLGetInstalledDriversW(wbuf, size_wbuf, &size_used); - if (ret) - { - if (!(ret = SQLInstall_narrow(2, lpszBuf, wbuf, size_used, cbBufMax, pcbBufOut))) - { - push_error(ODBC_ERROR_GENERAL_ERR, odbc_error_general_err); - } - } - HeapFree(GetProcessHeap(), 0, wbuf); - /* ignore failure; we have achieved the aim */ + push_error(ODBC_ERROR_INVALID_BUFF_LEN, odbc_error_invalid_buff_len); + return FALSE; } - else + + wbuf = heap_alloc(size * sizeof(WCHAR)); + if (!wbuf) { push_error(ODBC_ERROR_OUT_OF_MEM, odbc_error_out_of_mem); - ret = FALSE; + return FALSE; } - return ret; + + ret = SQLGetInstalledDriversW(wbuf, size, &written); + if (!ret) + return FALSE; + + *sizeout = WideCharToMultiByte(CP_ACP, 0, wbuf, written, NULL, 0, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, wbuf, written, buf, size, NULL, NULL); + + heap_free(wbuf); + return TRUE; } static HKEY get_privateprofile_sectionkey(LPCWSTR section, LPCWSTR filename) diff --git a/media/doc/README.WINE b/media/doc/README.WINE index 969d46559e0..829a9882a58 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -138,7 +138,7 @@ reactos/dll/win32/npptools # Synced to WineStaging-3.3 reactos/dll/win32/ntdsapi # Synced to WineStaging-3.9 reactos/dll/win32/objsel # Synced to WineStaging-3.3 reactos/dll/win32/odbc32 # Synced to WineStaging-3.3. Depends on port of Linux ODBC. -reactos/dll/win32/odbccp32 # Synced to WineStaging-3.3 +reactos/dll/win32/odbccp32 # Synced to WineStaging-3.9 reactos/dll/win32/ole32 # Synced to WineStaging-3.3 reactos/dll/win32/oleacc # Synced to WineStaging-3.3 reactos/dll/win32/oleaut32 # Synced to WineStaging-3.3 -- 2.17.1