odbccp32: Implement SQLInstallDriverEx.
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair@hotmail.com> Signed-off-by: Vincent Povirk <vincent@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
17b34a2e08
commit
27482bce73
|
@ -29,6 +29,7 @@
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "winreg.h"
|
#include "winreg.h"
|
||||||
#include "winnls.h"
|
#include "winnls.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
#include "odbcinst.h"
|
#include "odbcinst.h"
|
||||||
|
@ -38,6 +39,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(odbc);
|
||||||
/* Registry key names */
|
/* Registry key names */
|
||||||
static const WCHAR drivers_key[] = {'S','o','f','t','w','a','r','e','\\','O','D','B','C','\\','O','D','B','C','I','N','S','T','.','I','N','I','\\','O','D','B','C',' ','D','r','i','v','e','r','s',0};
|
static const WCHAR drivers_key[] = {'S','o','f','t','w','a','r','e','\\','O','D','B','C','\\','O','D','B','C','I','N','S','T','.','I','N','I','\\','O','D','B','C',' ','D','r','i','v','e','r','s',0};
|
||||||
static const WCHAR odbcW[] = {'S','o','f','t','w','a','r','e','\\','O','D','B','C',0};
|
static const WCHAR odbcW[] = {'S','o','f','t','w','a','r','e','\\','O','D','B','C',0};
|
||||||
|
static const WCHAR odbcini[] = {'S','o','f','t','w','a','r','e','\\','O','D','B','C','\\','O','D','B','C','I','N','S','T','.','I','N','I','\\',0};
|
||||||
|
static const WCHAR odbcdrivers[] = {'O','D','B','C',' ','D','r','i','v','e','r','s',0};
|
||||||
|
|
||||||
/* This config mode is known to be process-wide.
|
/* This config mode is known to be process-wide.
|
||||||
* MSDN documentation suggests that the value is hidden somewhere in the registry but I haven't found it yet.
|
* MSDN documentation suggests that the value is hidden somewhere in the registry but I haven't found it yet.
|
||||||
|
@ -626,12 +629,115 @@ BOOL WINAPI SQLInstallDriver(LPCSTR lpszInfFile, LPCSTR lpszDriver,
|
||||||
pcbPathOut, ODBC_INSTALL_COMPLETE, &usage);
|
pcbPathOut, ODBC_INSTALL_COMPLETE, &usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void write_registry_values(const WCHAR *regkey, const WCHAR *driver, const WCHAR *path_in, WCHAR *path,
|
||||||
|
DWORD *usage_count)
|
||||||
|
{
|
||||||
|
static const WCHAR installed[] = {'I','n','s','t','a','l','l','e','d',0};
|
||||||
|
static const WCHAR slash[] = {'\\', 0};
|
||||||
|
static const WCHAR driverW[] = {'D','r','i','v','e','r',0};
|
||||||
|
static const WCHAR setupW[] = {'S','e','t','u','p',0};
|
||||||
|
HKEY hkey, hkeydriver;
|
||||||
|
|
||||||
|
if (RegCreateKeyW(HKEY_LOCAL_MACHINE, odbcini, &hkey) == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
if (RegCreateKeyW(hkey, regkey, &hkeydriver) == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
if(RegSetValueExW(hkeydriver, driver, 0, REG_SZ, (BYTE*)installed, sizeof(installed)) != ERROR_SUCCESS)
|
||||||
|
ERR("Failed to write registry installed key\n");
|
||||||
|
|
||||||
|
RegCloseKey(hkeydriver);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RegCreateKeyW(hkey, driver, &hkeydriver) == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
WCHAR entry[1024];
|
||||||
|
const WCHAR *p;
|
||||||
|
DWORD usagecount = 0;
|
||||||
|
DWORD type, size;
|
||||||
|
|
||||||
|
/* Skip name entry */
|
||||||
|
p = driver;
|
||||||
|
p += lstrlenW(p) + 1;
|
||||||
|
|
||||||
|
if (!path_in)
|
||||||
|
GetSystemDirectoryW(path, MAX_PATH);
|
||||||
|
else
|
||||||
|
lstrcpyW(path, path_in);
|
||||||
|
|
||||||
|
/* Store Usage */
|
||||||
|
size = sizeof(usagecount);
|
||||||
|
RegGetValueA(hkeydriver, NULL, "UsageCount", RRF_RT_DWORD, &type, &usagecount, &size);
|
||||||
|
TRACE("Usage count %d\n", usagecount);
|
||||||
|
|
||||||
|
for (; *p; p += lstrlenW(p) + 1)
|
||||||
|
{
|
||||||
|
WCHAR *divider = strchrW(p,'=');
|
||||||
|
|
||||||
|
if (divider)
|
||||||
|
{
|
||||||
|
WCHAR *value;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/* Write pair values to the registry. */
|
||||||
|
lstrcpynW(entry, p, divider - p + 1);
|
||||||
|
|
||||||
|
divider++;
|
||||||
|
TRACE("Writing pair %s,%s\n", debugstr_w(entry), debugstr_w(divider));
|
||||||
|
|
||||||
|
/* Driver and Setup entries use the system path unless a path is specified. */
|
||||||
|
if(lstrcmpiW(driverW, entry) == 0 || lstrcmpiW(setupW, entry) == 0)
|
||||||
|
{
|
||||||
|
len = lstrlenW(path) + lstrlenW(slash) + lstrlenW(divider) + 1;
|
||||||
|
value = heap_alloc(len * sizeof(WCHAR));
|
||||||
|
if(!value)
|
||||||
|
{
|
||||||
|
ERR("Out of memory\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lstrcpyW(value, path);
|
||||||
|
lstrcatW(value, slash);
|
||||||
|
lstrcatW(value, divider);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len = lstrlenW(divider) + 1;
|
||||||
|
value = heap_alloc(len * sizeof(WCHAR));
|
||||||
|
lstrcpyW(value, divider);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RegSetValueExW(hkeydriver, entry, 0, REG_SZ, (BYTE*)value,
|
||||||
|
(lstrlenW(value)+1)*sizeof(WCHAR)) != ERROR_SUCCESS)
|
||||||
|
ERR("Failed to write registry data %s %s\n", debugstr_w(entry), debugstr_w(value));
|
||||||
|
heap_free(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("No pair found. %s\n", debugstr_w(p));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set Usage Count */
|
||||||
|
usagecount++;
|
||||||
|
if (RegSetValueExA(hkeydriver, "UsageCount", 0, REG_DWORD, (BYTE*)&usagecount, sizeof(usagecount)) != ERROR_SUCCESS)
|
||||||
|
ERR("Failed to write registry UsageCount key\n");
|
||||||
|
|
||||||
|
if (usage_count)
|
||||||
|
*usage_count = usagecount;
|
||||||
|
|
||||||
|
RegCloseKey(hkeydriver);
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOL WINAPI SQLInstallDriverExW(LPCWSTR lpszDriver, LPCWSTR lpszPathIn,
|
BOOL WINAPI SQLInstallDriverExW(LPCWSTR lpszDriver, LPCWSTR lpszPathIn,
|
||||||
LPWSTR lpszPathOut, WORD cbPathOutMax, WORD *pcbPathOut,
|
LPWSTR lpszPathOut, WORD cbPathOutMax, WORD *pcbPathOut,
|
||||||
WORD fRequest, LPDWORD lpdwUsageCount)
|
WORD fRequest, LPDWORD lpdwUsageCount)
|
||||||
{
|
{
|
||||||
UINT len;
|
UINT len;
|
||||||
LPCWSTR p;
|
|
||||||
WCHAR path[MAX_PATH];
|
WCHAR path[MAX_PATH];
|
||||||
|
|
||||||
clear_errors();
|
clear_errors();
|
||||||
|
@ -639,16 +745,13 @@ BOOL WINAPI SQLInstallDriverExW(LPCWSTR lpszDriver, LPCWSTR lpszPathIn,
|
||||||
debugstr_w(lpszPathIn), lpszPathOut, cbPathOutMax, pcbPathOut,
|
debugstr_w(lpszPathIn), lpszPathOut, cbPathOutMax, pcbPathOut,
|
||||||
fRequest, lpdwUsageCount);
|
fRequest, lpdwUsageCount);
|
||||||
|
|
||||||
for (p = lpszDriver; *p; p += lstrlenW(p) + 1)
|
write_registry_values(odbcdrivers, lpszDriver, lpszPathIn, path, lpdwUsageCount);
|
||||||
TRACE("%s\n", debugstr_w(p));
|
|
||||||
|
|
||||||
len = GetSystemDirectoryW(path, MAX_PATH);
|
len = lstrlenW(path);
|
||||||
|
|
||||||
if (pcbPathOut)
|
if (pcbPathOut)
|
||||||
*pcbPathOut = len;
|
*pcbPathOut = len;
|
||||||
|
|
||||||
len = GetSystemDirectoryW(path, MAX_PATH);
|
|
||||||
|
|
||||||
if (lpszPathOut && cbPathOutMax > len)
|
if (lpszPathOut && cbPathOutMax > len)
|
||||||
{
|
{
|
||||||
lstrcpyW(lpszPathOut, path);
|
lstrcpyW(lpszPathOut, path);
|
||||||
|
@ -661,7 +764,6 @@ BOOL WINAPI SQLInstallDriverEx(LPCSTR lpszDriver, LPCSTR lpszPathIn,
|
||||||
LPSTR lpszPathOut, WORD cbPathOutMax, WORD *pcbPathOut,
|
LPSTR lpszPathOut, WORD cbPathOutMax, WORD *pcbPathOut,
|
||||||
WORD fRequest, LPDWORD lpdwUsageCount)
|
WORD fRequest, LPDWORD lpdwUsageCount)
|
||||||
{
|
{
|
||||||
LPCSTR p;
|
|
||||||
LPWSTR driver, pathin;
|
LPWSTR driver, pathin;
|
||||||
WCHAR pathout[MAX_PATH];
|
WCHAR pathout[MAX_PATH];
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
@ -672,9 +774,6 @@ BOOL WINAPI SQLInstallDriverEx(LPCSTR lpszDriver, LPCSTR lpszPathIn,
|
||||||
debugstr_a(lpszPathIn), lpszPathOut, cbPathOutMax, pcbPathOut,
|
debugstr_a(lpszPathIn), lpszPathOut, cbPathOutMax, pcbPathOut,
|
||||||
fRequest, lpdwUsageCount);
|
fRequest, lpdwUsageCount);
|
||||||
|
|
||||||
for (p = lpszDriver; *p; p += lstrlenA(p) + 1)
|
|
||||||
TRACE("%s\n", debugstr_a(p));
|
|
||||||
|
|
||||||
driver = SQLInstall_strdup_multi(lpszDriver);
|
driver = SQLInstall_strdup_multi(lpszDriver);
|
||||||
pathin = SQLInstall_strdup(lpszPathIn);
|
pathin = SQLInstall_strdup(lpszPathIn);
|
||||||
|
|
||||||
|
|
|
@ -412,6 +412,64 @@ static void test_SQLGetPrivateProfileStringW(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_SQLInstallDriverEx(void)
|
||||||
|
{
|
||||||
|
char path[MAX_PATH];
|
||||||
|
char syspath[MAX_PATH];
|
||||||
|
WORD size = 0;
|
||||||
|
BOOL ret, sql_ret;
|
||||||
|
DWORD cnt, error_code = 0;
|
||||||
|
HKEY hkey;
|
||||||
|
DWORD reg_ret;
|
||||||
|
|
||||||
|
GetSystemDirectoryA(syspath, MAX_PATH);
|
||||||
|
|
||||||
|
SQLInstallDriverEx("WINE ODBC Driver\0Driver=sample.dll\0Setup=sample.dll\0\0", NULL, path, MAX_PATH, &size, ODBC_INSTALL_COMPLETE, NULL);
|
||||||
|
sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
|
||||||
|
if (sql_ret && error_code == ODBC_ERROR_WRITING_SYSINFO_FAILED)
|
||||||
|
{
|
||||||
|
win_skip("not enough privileges\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ok(sql_ret && error_code == SQL_SUCCESS, "SQLInstallDriverEx failed %d, %u\n", sql_ret, error_code);
|
||||||
|
ok(!strcmp(path, syspath), "invalid path %s\n", path);
|
||||||
|
|
||||||
|
ret = SQLInstallDriverEx("WINE ODBC Driver Path\0Driver=sample.dll\0Setup=sample.dll\0\0", "c:\\temp", path, MAX_PATH, &size, ODBC_INSTALL_COMPLETE, NULL);
|
||||||
|
sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
|
||||||
|
ok(sql_ret && error_code == SQL_SUCCESS, "SQLInstallDriverEx failed %d, %u\n", sql_ret, error_code);
|
||||||
|
ok(!strcmp(path, "c:\\temp"), "invalid path %s\n", path);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
reg_ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\ODBC\\ODBCINST.INI\\WINE ODBC Driver", 0, KEY_READ, &hkey);
|
||||||
|
ok(reg_ret == ERROR_SUCCESS, "RegOpenKeyExW failed\n");
|
||||||
|
if (reg_ret == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
DWORD type, size = MAX_PATH;
|
||||||
|
char driverpath[MAX_PATH];
|
||||||
|
|
||||||
|
strcpy(driverpath, syspath);
|
||||||
|
strcat(driverpath, "\\sample.dll");
|
||||||
|
|
||||||
|
reg_ret = RegGetValueA(hkey, NULL, "Driver", RRF_RT_REG_SZ, &type, &path, &size);
|
||||||
|
ok(reg_ret == ERROR_SUCCESS, "RegGetValueA failed\n");
|
||||||
|
ok(!strcmp(path, driverpath), "invalid path %s\n", path);
|
||||||
|
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt = 100;
|
||||||
|
ret = SQLRemoveDriver("WINE ODBC Driver", FALSE, &cnt);
|
||||||
|
ok(ret, "SQLRemoveDriver failed\n");
|
||||||
|
todo_wine ok(cnt == 0, "SQLRemoveDriver failed %d\n", cnt);
|
||||||
|
|
||||||
|
cnt = 100;
|
||||||
|
ret = SQLRemoveDriver("WINE ODBC Driver Path", FALSE, &cnt);
|
||||||
|
ok(ret, "SQLRemoveDriver failed\n");
|
||||||
|
todo_wine ok(cnt == 0, "SQLRemoveDriver failed %d\n", cnt);
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(misc)
|
START_TEST(misc)
|
||||||
{
|
{
|
||||||
test_SQLConfigMode();
|
test_SQLConfigMode();
|
||||||
|
@ -420,4 +478,5 @@ START_TEST(misc)
|
||||||
test_SQLWritePrivateProfileString();
|
test_SQLWritePrivateProfileString();
|
||||||
test_SQLGetPrivateProfileString();
|
test_SQLGetPrivateProfileString();
|
||||||
test_SQLGetPrivateProfileStringW();
|
test_SQLGetPrivateProfileStringW();
|
||||||
|
test_SQLInstallDriverEx();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue