1 /*
2  * Copyright 2007 Bill Medland
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include <wine/test.h>
20 #include <stdarg.h>
21 
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winreg.h"
25 #include "odbcinst.h"
26 
27 static const WCHAR abcd_key[] = {'S','o','f','t','w','a','r','e','\\','O','D','B','C','\\','a','b','c','d','.','I','N','I','\\','w','i','n','e','o','d','b','c',0};
28 static const WCHAR abcdini_key[] = {'S','o','f','t','w','a','r','e','\\','O','D','B','C','\\','a','b','c','d','.','I','N','I',0 };
29 
30 static void check_error_(int line, DWORD expect)
31 {
32     RETCODE ret;
33     DWORD err;
34     ret = SQLInstallerError(1, &err, NULL, 0, NULL);
35     ok_(__FILE__, line)(ret == SQL_SUCCESS_WITH_INFO, "got %d\n", ret);
36     ok_(__FILE__, line)(err == expect, "expected %u, got %u\n", expect, ret);
37 }
38 #define check_error(a) check_error_(__LINE__, a)
39 
40 static void test_SQLConfigMode(void)
41 {
42     BOOL bool_ret;
43     DWORD error_code;
44     RETCODE sql_ret;
45     UWORD config_mode;
46     int i;
47 
48     ok(SQLGetConfigMode(NULL), "SQLGetConfigMode(NULL) should succeed\n");
49 
50     bool_ret = SQLGetConfigMode(&config_mode);
51     ok(bool_ret && config_mode == ODBC_BOTH_DSN, "Failed to get the initial SQLGetConfigMode or it was not both\n");
52 
53     /* try to set invalid mode */
54     bool_ret = SQLSetConfigMode(ODBC_SYSTEM_DSN+1);
55     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
56     ok(!bool_ret && sql_ret == SQL_SUCCESS_WITH_INFO && error_code == ODBC_ERROR_INVALID_PARAM_SEQUENCE, "SQLSetConfigMode with invalid argument did not fail correctly\n");
57 
58     for (i = ODBC_SYSTEM_DSN; i >= ODBC_BOTH_DSN; --i)
59     {
60         ok(SQLSetConfigMode((UWORD)i), "SQLSetConfigMode Failed to set config mode\n");
61         bool_ret = SQLGetConfigMode(&config_mode);
62         ok(bool_ret && config_mode == i, "Failed to confirm SQLSetConfigMode.\n");
63     }
64     /* And that leaves it correctly on BOTH */
65 }
66 
67 static void test_SQLInstallerError(void)
68 {
69     RETCODE sql_ret;
70 
71     /* MSDN states that the error number should be between 1 and 8.  Passing 0 is an error */
72     sql_ret = SQLInstallerError(0, NULL, NULL, 0, NULL);
73     ok(sql_ret == SQL_ERROR, "SQLInstallerError(0...) failed with %d instead of SQL_ERROR\n", sql_ret);
74     /* However numbers greater than 8 do not return SQL_ERROR.
75      * I am currently unsure as to whether it should return SQL_NO_DATA or "the same as for error 8";
76      * I have never been able to generate 8 errors to test it
77      */
78     sql_ret = SQLInstallerError(65535, NULL, NULL, 0, NULL);
79     ok(sql_ret == SQL_NO_DATA, "SQLInstallerError(>8...) failed with %d instead of SQL_NO_DATA\n", sql_ret);
80 
81     /* Force an error to work with.  This should generate ODBC_ERROR_INVALID_BUFF_LEN */
82     ok(!SQLGetInstalledDrivers(0, 0, 0), "Failed to force an error for testing\n");
83     sql_ret = SQLInstallerError(2, NULL, NULL, 0, NULL);
84     ok(sql_ret == SQL_NO_DATA, "Too many errors when forcing an error for testing\n");
85 
86     /* Null pointers are acceptable in all obvious places */
87     sql_ret = SQLInstallerError(1, NULL, NULL, 0, NULL);
88     ok(sql_ret == SQL_SUCCESS_WITH_INFO, "SQLInstallerError(null addresses) failed with %d instead of SQL_SUCCESS_WITH_INFO\n", sql_ret);
89 }
90 
91 static void test_SQLInstallDriverManager(void)
92 {
93     BOOL bool_ret;
94     RETCODE sql_ret;
95     DWORD error_code;
96     CHAR target_path[MAX_PATH];
97     WORD path_out;
98 
99     /* NULL check */
100     bool_ret = SQLInstallDriverManager(NULL, 0, NULL);
101     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
102     ok(!bool_ret, "SQLInstallDriverManager unexpectedly succeeded\n");
103     ok(sql_ret == SQL_SUCCESS_WITH_INFO && error_code == ODBC_ERROR_INVALID_BUFF_LEN,
104         "Expected SQLInstallDriverManager to fail with ODBC_ERROR_INVALID_BUFF_LEN\n");
105 
106     /* Length smaller than MAX_PATH */
107     bool_ret = SQLInstallDriverManager(target_path, MAX_PATH / 2, NULL);
108     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
109     ok(!bool_ret, "SQLInstallDriverManager unexpectedly succeeded\n");
110     ok(sql_ret == SQL_SUCCESS_WITH_INFO && error_code == ODBC_ERROR_INVALID_BUFF_LEN,
111         "Expected SQLInstallDriverManager to fail with ODBC_ERROR_INVALID_BUFF_LEN\n");
112 
113     path_out = 0xcafe;
114     bool_ret = SQLInstallDriverManager(target_path, MAX_PATH / 2, &path_out);
115     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
116     ok(!bool_ret, "SQLInstallDriverManager unexpectedly succeeded\n");
117     ok(sql_ret == SQL_SUCCESS_WITH_INFO && error_code == ODBC_ERROR_INVALID_BUFF_LEN,
118         "Expected SQLInstallDriverManager to fail with ODBC_ERROR_INVALID_BUFF_LEN\n");
119     ok(path_out == 0xcafe, "Expected path_out to not have changed\n");
120 
121     /* Length OK */
122     bool_ret = SQLInstallDriverManager(target_path, MAX_PATH, NULL);
123     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
124     if(!bool_ret && error_code == ODBC_ERROR_WRITING_SYSINFO_FAILED)
125     {
126          win_skip("not enough privileges\n");
127          return;
128     }
129     ok(bool_ret, "SQLInstallDriverManager unexpectedly failed: %d\n",
130         error_code);
131     if (bool_ret)
132         ok(sql_ret == SQL_NO_DATA, "Expected SQL_NO_DATA, got %d\n", sql_ret);
133     else
134         ok(sql_ret == SQL_SUCCESS_WITH_INFO,
135             "Expected SQL_SUCCESS_WITH_INFO, got %d\n", sql_ret);
136 
137     path_out = 0xcafe;
138     bool_ret = SQLInstallDriverManager(target_path, MAX_PATH, &path_out);
139     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
140     ok(bool_ret, "SQLInstallDriverManager unexpectedly failed: %d\n",
141         error_code);
142     if (bool_ret)
143         ok(sql_ret == SQL_NO_DATA, "Expected SQL_NO_DATA, got %d\n", sql_ret);
144     else
145         ok(sql_ret == SQL_SUCCESS_WITH_INFO,
146             "Expected SQL_SUCCESS_WITH_INFO, got %d\n", sql_ret);
147     /* path_out should in practice be less than 0xcafe */
148     ok(path_out != 0xcafe, "Expected path_out to show the correct amount of bytes\n");
149 }
150 
151 static void test_SQLWritePrivateProfileString(void)
152 {
153    static const WCHAR odbc_key[] = {'S','o','f','t','w','a','r','e','\\','O','D','B','C','\\','O','D','B','C','.','I','N','I','\\','w','i','n','e','o','d','b','c',0};
154    BOOL ret;
155    LONG reg_ret;
156    DWORD error_code;
157 
158    ret = SQLWritePrivateProfileString("wineodbc", "testing" , "value", "");
159    ok(!ret, "SQLWritePrivateProfileString passed\n");
160    SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
161    ok(error_code == ODBC_ERROR_INVALID_STR, "SQLInstallerErrorW ret: %d\n", error_code);
162 
163    ret = SQLWritePrivateProfileString("wineodbc", "testing" , "value", NULL);
164    ok(!ret, "SQLWritePrivateProfileString passed\n");
165    SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
166    ok(error_code == ODBC_ERROR_INVALID_STR, "SQLInstallerErrorW ret: %d\n", error_code);
167 
168    ret = SQLWritePrivateProfileString("wineodbc", "testing" , "value", "odbc.ini");
169    ok(ret, "SQLWritePrivateProfileString failed\n");
170    if(ret)
171    {
172         HKEY hkey;
173 
174         ret = SQLWritePrivateProfileString("wineodbc", "testing" , NULL, "odbc.ini");
175         ok(ret, "SQLWritePrivateProfileString failed\n");
176 
177         reg_ret = RegOpenKeyExW(HKEY_CURRENT_USER, odbc_key, 0, KEY_READ, &hkey);
178         ok(reg_ret == ERROR_SUCCESS, "RegOpenKeyExW failed\n");
179         if(reg_ret == ERROR_SUCCESS)
180         {
181             reg_ret = RegDeleteKeyW(HKEY_CURRENT_USER, odbc_key);
182             ok(reg_ret == ERROR_SUCCESS, "RegDeleteKeyW failed\n");
183 
184             RegCloseKey(hkey);
185         }
186    }
187 
188    ret = SQLWritePrivateProfileString("wineodbc", "testing" , "value", "abcd.ini");
189    ok(ret, "SQLWritePrivateProfileString failed\n");
190    if(ret)
191    {
192         HKEY hkey;
193 
194         reg_ret = RegOpenKeyExW(HKEY_CURRENT_USER, abcd_key, 0, KEY_READ, &hkey);
195         ok(reg_ret == ERROR_SUCCESS, "RegOpenKeyExW failed\n");
196         if(reg_ret == ERROR_SUCCESS)
197         {
198             reg_ret = RegDeleteKeyW(HKEY_CURRENT_USER, abcd_key);
199             ok(reg_ret == ERROR_SUCCESS, "RegDeleteKeyW failed\n");
200 
201             RegCloseKey(hkey);
202         }
203 
204         /* Cleanup key */
205         reg_ret = RegDeleteKeyW(HKEY_CURRENT_USER, abcdini_key);
206         ok(reg_ret == ERROR_SUCCESS, "RegDeleteKeyW failed\n");
207    }
208 }
209 
210 static void test_SQLGetPrivateProfileString(void)
211 {
212     int ret;
213     char buffer[256] = {0};
214     LONG reg_ret;
215 
216     strcpy(buffer, "wine");
217     ret = SQLGetPrivateProfileString(NULL, "testing" , "default", buffer, 256, "ODBC.INI");
218     ok(ret == 0, "SQLGetPrivateProfileString returned %d\n", ret);
219     ok(!strcmp(buffer, ""), "incorrect string '%s'\n", buffer);
220 
221     strcpy(buffer, "wine");
222     ret = SQLGetPrivateProfileString("wineodbc", NULL , "default", buffer, 256, "ODBC.INI");
223     ok(ret == 0, "SQLGetPrivateProfileString returned %d\n", ret);
224     ok(!strcmp(buffer, ""), "incorrect string '%s'\n", buffer);
225 
226     strcpy(buffer, "value");
227     ret = SQLGetPrivateProfileString("wineodbc", "testing" , NULL, buffer, 256, "ODBC.INI");
228     ok(ret == 0, "SQLGetPrivateProfileString returned %d\n", ret);
229     ok(!strcmp(buffer, ""), "incorrect string '%s'\n", buffer);
230 
231     ret = SQLGetPrivateProfileString("wineodbc", "testing" , "defaultX", buffer, 256, "ODBC.INI");
232     ok(ret == strlen("defaultX"), "SQLGetPrivateProfileString returned %d\n", ret);
233     ok(!strcmp(buffer, "defaultX"), "incorrect string '%s'\n", buffer);
234 
235     ret = SQLGetPrivateProfileString("wineodbc", "testing" , "defaultX", buffer, 4, "ODBC.INI");
236     ok(ret == strlen("def"), "SQLGetPrivateProfileString returned %d\n", ret);
237     ok(!strcmp(buffer, "def"), "incorrect string '%s'\n", buffer);
238 
239     ret = SQLGetPrivateProfileString("wineodbc", "testing" , "defaultX", buffer, 8, "ODBC.INI");
240     ok(ret == strlen("default"), "SQLGetPrivateProfileString returned %d\n", ret);
241     ok(!strcmp(buffer, "default"), "incorrect string '%s'\n", buffer);
242 
243     ret = SQLGetPrivateProfileString("wineodbc", "testing" , "defaultX", NULL, 256, "ODBC.INI");
244     ok(ret == 0, "SQLGetPrivateProfileString returned %d\n", ret);
245 
246     strcpy(buffer, "value");
247     ret = SQLGetPrivateProfileString("wineodbc", "testing" , "defaultX", buffer, 0, "ODBC.INI");
248     ok(ret == 0, "SQLGetPrivateProfileString returned %d\n", ret);
249     ok(!strcmp(buffer, "value"), "incorrect string '%s'\n", buffer);
250 
251     ret = SQLWritePrivateProfileString("wineodbc", "testing" , "value0123456789", "abcd.ini");
252     ok(ret, "SQLWritePrivateProfileString failed\n");
253     if(ret)
254     {
255         HKEY hkey;
256 
257         ret = SQLGetPrivateProfileString("wineodbc", "testing" , "defaultY", buffer, 256, "abcd.ini");
258         ok(ret == strlen("value0123456789"), "SQLGetPrivateProfileString returned %d\n", ret);
259         ok(!strcmp(buffer, "value0123456789"), "incorrect string '%s'\n", buffer);
260 
261         ret = SQLGetPrivateProfileString("wineodbc", "testing" , "defaultY", NULL, 0, "abcd.ini");
262         ok(ret == 0, "SQLGetPrivateProfileString returned %d\n", ret);
263 
264         ret = SQLGetPrivateProfileString("wineodbc", "testing" , "defaultY", buffer, 7, "abcd.ini");
265         ok(ret == 6, "SQLGetPrivateProfileString returned %d\n", ret);
266 
267         strcpy(buffer, "wine");
268         ret = SQLGetPrivateProfileString("wineodbc", NULL , "", buffer, 10, "abcd.ini");
269         ok(ret == (strlen("testing")+1), "SQLGetPrivateProfileString returned %d\n", ret);
270         ok(!strcmp(buffer, "testing"), "incorrect string '%s'\n", buffer);
271 
272         ret = SQLWritePrivateProfileString("wineodbc", "value" , "0", "abcd.ini");
273         ok(ret, "SQLWritePrivateProfileString failed\n");
274 
275         strcpy(buffer, "wine");
276         ret = SQLGetPrivateProfileString("wineodbc", NULL , "", buffer, 256, "abcd.ini");
277         ok(ret == (strlen("testing") + strlen("value")+2), "SQLGetPrivateProfileString returned %d\n", ret);
278         if(ret >= (strlen("testing") + strlen("value")+2))
279         {
280             ok(memcmp(buffer, "testing\0value\0", 14) == 0, "incorrect string '%s'\n", buffer);
281         }
282 
283         strcpy(buffer, "XXXXXXXXXXXXXXX");
284         ret = SQLGetPrivateProfileString("wineodbc", NULL , "", buffer, 10, "abcd.ini");
285         ok(ret == (strlen("testing")+1), "SQLGetPrivateProfileString returned %d\n", ret);
286         if(ret >= (strlen("testing")+1))
287         {
288             ok(!strcmp(buffer, "testing"), "incorrect string '%s'\n", buffer);
289             /* Show that the buffer is cleared and partial enteries aren't added */
290             ok(memcmp(buffer, "testing\0X", 9) != 0, "incorrect string '%s'\n", buffer);
291         }
292 
293         strcpy(buffer, "wine");
294         ret = SQLGetPrivateProfileString("wineodbc", NULL , "", buffer, 2, "abcd.ini");
295         ok(ret == 0, "SQLGetPrivateProfileString returned %d\n", ret);
296 
297         reg_ret = RegOpenKeyExW(HKEY_CURRENT_USER, abcd_key, 0, KEY_READ, &hkey);
298         ok(reg_ret == ERROR_SUCCESS, "RegOpenKeyExW failed\n");
299         if(reg_ret == ERROR_SUCCESS)
300         {
301             reg_ret = RegDeleteKeyW(HKEY_CURRENT_USER, abcd_key);
302             ok(reg_ret == ERROR_SUCCESS, "RegDeleteKeyW failed\n");
303 
304             RegCloseKey(hkey);
305         }
306 
307         /* Cleanup key */
308         reg_ret = RegDeleteKeyW(HKEY_CURRENT_USER, abcdini_key);
309         ok(reg_ret == ERROR_SUCCESS, "RegDeleteKeyW failed\n");
310     }
311 }
312 
313 static void test_SQLGetPrivateProfileStringW(void)
314 {
315     static WCHAR testing[] = {'t','e','s','t','i','n','g',0};
316     static WCHAR wineodbc[] = {'w','i','n','e','o','d','b','c',0};
317     static WCHAR defaultval[] = {'d','e','f','a','u','l','t',0};
318     static WCHAR odbcini[] = {'O','D','B','C','.','I','N','I',0};
319     static WCHAR abcdini[] = {'a','b','c','d','.','I','N','I',0};
320     static WCHAR wine[] = {'w','i','n','e',0};
321     static WCHAR value[] = {'v','a','l','u','e',0};
322     static WCHAR empty[] = {0};
323     static WCHAR defaultX[] = {'d','e','f','a','u','l','t',0};
324     static WCHAR def[] = {'d','e','f',0};
325     static WCHAR value0[] = {'v','a','l','u','e','0','1','2','3','4','5','6','7','8','9',0};
326     static WCHAR testingvalue[] = {'t','e','s','t','i','n','g',0,'v','a','l','u','e',0};
327     int ret;
328     WCHAR buffer[256] = {0};
329     LONG reg_ret;
330 
331     lstrcpyW(buffer, wine);
332     ret = SQLGetPrivateProfileStringW(NULL, testing , defaultval, buffer, 256, odbcini);
333     ok(ret == 0, "SQLGetPrivateProfileStringW returned %d\n", ret);
334     ok(!lstrcmpW(buffer, wine), "incorrect string '%s'\n", wine_dbgstr_w(buffer));
335 
336     lstrcpyW(buffer, wine);
337     ret = SQLGetPrivateProfileStringW(wineodbc, NULL , defaultval, buffer, 256, odbcini);
338     ok(ret == 0, "SQLGetPrivateProfileStringW returned %d\n", ret);
339     ok(!lstrcmpW(buffer, empty), "incorrect string '%s'\n", wine_dbgstr_w(buffer));
340 
341     lstrcpyW(buffer, value);
342     ret = SQLGetPrivateProfileStringW(wineodbc, testing , NULL, buffer, 256, odbcini);
343     ok(ret == 0, "SQLGetPrivateProfileStringW returned %d\n", ret);
344     ok(!lstrcmpW(buffer, empty), "incorrect string '%s'\n", wine_dbgstr_w(buffer));
345 
346     ret = SQLGetPrivateProfileStringW(wineodbc, testing , defaultX, buffer, 256, odbcini);
347     ok(ret == lstrlenW(defaultX), "SQLGetPrivateProfileStringW returned %d\n", ret);
348     ok(!lstrcmpW(buffer, defaultX), "incorrect string '%s'\n", wine_dbgstr_w(buffer));
349 
350     ret = SQLGetPrivateProfileStringW(wineodbc, testing , defaultX, buffer, 4, odbcini);
351     ok(ret == lstrlenW(def), "SQLGetPrivateProfileStringW returned %d\n", ret);
352     ok(!lstrcmpW(buffer, def), "incorrect string '%s'\n", wine_dbgstr_w(buffer));
353 
354     ret = SQLGetPrivateProfileStringW(wineodbc, testing , defaultX, buffer, 8, odbcini);
355     ok(ret == lstrlenW(defaultX), "SQLGetPrivateProfileStringW returned %d\n", ret);
356     ok(!lstrcmpW(buffer, defaultX), "incorrect string '%s'\n", wine_dbgstr_w(buffer));
357 
358     ret = SQLGetPrivateProfileStringW(wineodbc, testing , defaultX, NULL, 256, odbcini);
359     ok(ret == 0, "SQLGetPrivateProfileStringW returned %d\n", ret);
360 
361     lstrcpyW(buffer, value);
362     ret = SQLGetPrivateProfileStringW(wineodbc, testing , defaultX, buffer, 0, odbcini);
363     ok(ret == 0, "SQLGetPrivateProfileStringW returned %d\n", ret);
364     ok(!lstrcmpW(buffer, value), "incorrect string '%s'\n", wine_dbgstr_w(buffer));
365 
366     ret = SQLWritePrivateProfileString("wineodbc", "testing" , "value0123456789", "abcd.ini");
367     ok(ret, "SQLWritePrivateProfileString failed\n");
368     if(ret)
369     {
370         HKEY hkey;
371 
372         ret = SQLGetPrivateProfileStringW(wineodbc, testing , defaultX, buffer, 256, abcdini);
373         ok(ret == lstrlenW(value0), "SQLGetPrivateProfileStringW returned %d\n", ret);
374         ok(!lstrcmpW(buffer, value0), "incorrect string '%s'\n", wine_dbgstr_w(buffer));
375 
376         ret = SQLGetPrivateProfileStringW(wineodbc, testing , defaultX, NULL, 0, abcdini);
377         ok(ret == 0, "SQLGetPrivateProfileStringW returned %d\n", ret);
378 
379         ret = SQLGetPrivateProfileStringW(wineodbc, testing , defaultX, buffer, 7, abcdini);
380         ok(ret == 6, "SQLGetPrivateProfileStringW returned %d\n", ret);
381 
382         lstrcpyW(buffer, wine);
383         ret = SQLGetPrivateProfileStringW(wineodbc, NULL , empty, buffer, 10, abcdini);
384         ok(ret == lstrlenW(testing)+1, "SQLGetPrivateProfileStringW returned %d\n", ret);
385         ok(!lstrcmpW(buffer, testing), "incorrect string '%s'\n", wine_dbgstr_w(buffer));
386 
387         ret = SQLWritePrivateProfileString("wineodbc", "value" , "0", "abcd.ini");
388         ok(ret, "SQLWritePrivateProfileString failed\n");
389 
390         lstrcpyW(buffer, wine);
391         ret = SQLGetPrivateProfileStringW(wineodbc, NULL , empty, buffer, 256, abcdini);
392         ok(ret == (lstrlenW(testing) + lstrlenW(value)+2), "SQLGetPrivateProfileStringW returned %d\n", ret);
393         if(ret == (lstrlenW(testing) + lstrlenW(value)+2))
394         {
395             ok(!memcmp(buffer, testingvalue, sizeof(testingvalue)),
396                       "incorrect string '%s'\n", wine_dbgstr_wn(buffer, ret));
397         }
398 
399         lstrcpyW(buffer, value);
400         ret = SQLGetPrivateProfileStringW(wineodbc, NULL , empty, buffer, 10, abcdini);
401         ok(ret == lstrlenW(testing)+1, "SQLGetPrivateProfileStringW returned %d\n", ret);
402         if(ret >= lstrlenW(testing)+1)
403         {
404             ok(!lstrcmpW(buffer, testing), "incorrect string '%s'\n", wine_dbgstr_w(buffer));
405         }
406 
407         lstrcpyW(buffer, value);
408         ret = SQLGetPrivateProfileStringW(wineodbc, NULL , empty, buffer, 2, abcdini);
409         ok(ret == 0, "SQLGetPrivateProfileStringW returned %d\n", ret);
410 
411         reg_ret = RegOpenKeyExW(HKEY_CURRENT_USER, abcd_key, 0, KEY_READ, &hkey);
412         ok(reg_ret == ERROR_SUCCESS, "RegOpenKeyExW failed\n");
413         if(reg_ret == ERROR_SUCCESS)
414         {
415             reg_ret = RegDeleteKeyW(HKEY_CURRENT_USER, abcd_key);
416             ok(reg_ret == ERROR_SUCCESS, "RegDeleteKeyW failed\n");
417 
418             RegCloseKey(hkey);
419         }
420 
421         /* Cleanup key */
422         reg_ret = RegDeleteKeyW(HKEY_CURRENT_USER, abcdini_key);
423         ok(reg_ret == ERROR_SUCCESS, "RegDeleteKeyW failed\n");
424     }
425 }
426 
427 static void test_SQLInstallDriverEx(void)
428 {
429     char path[MAX_PATH];
430     char syspath[MAX_PATH];
431     WORD size = 0;
432     BOOL ret, sql_ret;
433     DWORD cnt, error_code = 0;
434     HKEY hkey;
435     LONG res;
436     char error[1000];
437 
438     GetSystemDirectoryA(syspath, MAX_PATH);
439 
440     ret = SQLConfigDriver(NULL, ODBC_CONFIG_DRIVER, "WINE ODBC Driver", "CPTimeout=59", error, sizeof(error), NULL);
441     ok(!ret, "SQLConfigDriver returned %d\n", ret);
442     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
443     ok(sql_ret && error_code == ODBC_ERROR_COMPONENT_NOT_FOUND, "SQLConfigDriver returned %d, %u\n", sql_ret, error_code);
444 
445     ret = SQLInstallDriverEx("WINE ODBC Driver\0Driver=sample.dll\0Setup=sample.dll\0\0", NULL,
446                              path, MAX_PATH, &size, ODBC_INSTALL_COMPLETE, NULL);
447     ok(ret, "SQLInstallDriverEx failed\n");
448     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
449     if (sql_ret && error_code == ODBC_ERROR_WRITING_SYSINFO_FAILED)
450     {
451          win_skip("not enough privileges\n");
452          return;
453     }
454     ok(sql_ret == SQL_NO_DATA || (sql_ret && error_code == SQL_SUCCESS), "SQLInstallDriverEx failed %d, %u\n", sql_ret, error_code);
455     ok(!strcmp(path, syspath), "invalid path %s\n", path);
456 
457 if (0)  /* Crashes on XP. */
458 {
459     sql_ret = 0;
460     ret = SQLConfigDriver(NULL, ODBC_CONFIG_DRIVER, "WINE ODBC Driver", NULL, error, sizeof(error), NULL);
461     ok(!ret, "SQLConfigDriver failed '%s'\n",error);
462 }
463 
464     ret = SQLConfigDriver(NULL, ODBC_CONFIG_DRIVER, "WINE ODBC Driver", "CPTimeout=59\0NoWrite=60\0", error, sizeof(error), NULL);
465     ok(ret, "SQLConfigDriver failed\n");
466     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
467     ok(sql_ret == SQL_NO_DATA || (sql_ret && error_code == SQL_SUCCESS), "SQLConfigDriver failed %d, %u\n", sql_ret, error_code);
468 
469     ret = SQLInstallDriverEx("WINE ODBC Driver Path\0Driver=sample.dll\0Setup=sample.dll\0\0", "c:\\temp", path, MAX_PATH, &size, ODBC_INSTALL_COMPLETE, NULL);
470     ok(ret, "SQLInstallDriverEx failed\n");
471     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
472     ok(sql_ret == SQL_NO_DATA || (sql_ret && error_code == SQL_SUCCESS), "SQLInstallDriverEx failed %d, %u\n", sql_ret, error_code);
473     ok(!strcmp(path, "c:\\temp"), "invalid path %s\n", path);
474 
475     ret = SQLConfigDriver(NULL, ODBC_CONFIG_DRIVER, "WINE ODBC Driver Path", "empty", error, sizeof(error), NULL);
476     ok(!ret, "SQLConfigDriver successful\n");
477     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
478     ok(sql_ret && error_code == ODBC_ERROR_INVALID_KEYWORD_VALUE, "SQLConfigDriver failed %d, %u\n", sql_ret, error_code);
479 
480     ret = SQLConfigDriver(NULL, ODBC_CONFIG_DRIVER, "WINE ODBC Driver Path", "NoWrite=60;xxxx=555", error, sizeof(error), NULL);
481     ok(ret, "SQLConfigDriver failed\n");
482     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
483     ok(sql_ret == SQL_NO_DATA || (sql_ret && error_code == SQL_SUCCESS), "SQLConfigDriver failed %d, %u\n", sql_ret, error_code);
484 
485     if (ret)
486     {
487         DWORD type = 0xdeadbeef, size = MAX_PATH;
488 
489         res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\ODBC\\ODBCINST.INI\\WINE ODBC Driver", 0, KEY_READ, &hkey);
490         ok(res == ERROR_SUCCESS, "RegOpenKeyExW failed\n");
491         if (res == ERROR_SUCCESS)
492         {
493             char driverpath[MAX_PATH];
494 
495             strcpy(driverpath, syspath);
496             strcat(driverpath, "\\sample.dll");
497 
498             memset(path, 0, sizeof(path));
499             res = RegQueryValueExA(hkey, "Driver", NULL, &type, (BYTE *)path, &size);
500             ok(res == ERROR_SUCCESS, "got %d\n", res);
501             ok(type == REG_SZ, "got %u\n", type);
502             ok(size == strlen(driverpath) + 1, "got %u\n", size);
503             ok(!strcmp(path, driverpath), "invalid path %s\n", path);
504 
505             res = RegQueryValueExA(hkey, "CPTimeout", NULL, &type, (BYTE *)&path, &size);
506             ok(res == ERROR_SUCCESS, "got %d\n", res);
507             ok(type == REG_SZ, "got %u\n", type);
508             ok(size == strlen("59") + 1, "got %u\n", size);
509             ok(!strcmp(path, "59"), "invalid value %s\n", path);
510 
511             res = RegQueryValueExA(hkey, "NoWrite", NULL, &type, (BYTE *)&path, &size);
512             ok(res == ERROR_FILE_NOT_FOUND, "got %d\n", res);
513 
514             RegCloseKey(hkey);
515         }
516 
517         res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\ODBC\\ODBCINST.INI\\WINE ODBC Driver Path", 0, KEY_READ, &hkey);
518         ok(res == ERROR_SUCCESS, "RegOpenKeyExW failed\n");
519         if (res == ERROR_SUCCESS)
520         {
521             size = sizeof(path);
522             res = RegQueryValueExA(hkey, "NoWrite", NULL, &type, (BYTE *)&path, &size);
523             ok(res == ERROR_SUCCESS, "got %d\n", res);
524             ok(type == REG_SZ, "got %u\n", type);
525             ok(size == strlen("60;xxxx=555") + 1, "got %u\n", size);
526             ok(!strcmp(path, "60;xxxx=555"), "invalid value %s\n", path);
527 
528             res = RegQueryValueExA(hkey, "CPTimeout", NULL, &type, (BYTE *)&path, &size);
529             ok(res == ERROR_FILE_NOT_FOUND, "got %d\n", res);
530             RegCloseKey(hkey);
531         }
532     }
533 
534     cnt = 100;
535     ret = SQLRemoveDriver("WINE ODBC Driver", FALSE, &cnt);
536     ok(ret, "SQLRemoveDriver failed\n");
537     ok(cnt == 0, "SQLRemoveDriver failed %d\n", cnt);
538 
539     cnt = 100;
540     ret = SQLRemoveDriver("WINE ODBC Driver Path", FALSE, &cnt);
541     ok(ret, "SQLRemoveDriver failed\n");
542     ok(cnt == 0, "SQLRemoveDriver failed %d\n", cnt);
543 }
544 
545 static void test_SQLInstallTranslatorEx(void)
546 {
547     char path[MAX_PATH];
548     char syspath[MAX_PATH];
549     WORD size = 0;
550     BOOL ret, sql_ret;
551     DWORD cnt, error_code = 0;
552     HKEY hkey;
553     LONG res;
554 
555     GetSystemDirectoryA(syspath, MAX_PATH);
556 
557     ret = SQLInstallTranslatorEx("WINE ODBC Translator\0Translator=sample.dll\0Setup=sample.dll\0",
558                                  NULL, path, MAX_PATH, &size, ODBC_INSTALL_COMPLETE, NULL);
559     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
560     if (sql_ret && error_code == ODBC_ERROR_WRITING_SYSINFO_FAILED)
561     {
562          win_skip("not enough privileges\n");
563          return;
564     }
565     ok(sql_ret && error_code == SQL_SUCCESS, "SQLInstallDriverEx failed %d, %u\n", sql_ret, error_code);
566     ok(!strcmp(path, syspath), "invalid path %s\n", path);
567     ok(size == strlen(path), "invalid length %d\n", size);
568 
569     ret = SQLInstallTranslatorEx("WINE ODBC Translator Path\0Translator=sample.dll\0Setup=sample.dll\0",
570                                  "c:\\temp", path, MAX_PATH, &size, ODBC_INSTALL_COMPLETE, NULL);
571     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
572     ok(sql_ret && error_code == SQL_SUCCESS, "SQLInstallTranslatorEx failed %d, %u\n", sql_ret, error_code);
573     ok(!strcmp(path, "c:\\temp"), "invalid path %s\n", path);
574     ok(size == strlen(path), "invalid length %d\n", size);
575 
576     if(ret)
577     {
578         res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\ODBC\\ODBCINST.INI\\WINE ODBC Translator", 0,
579                             KEY_READ, &hkey);
580         ok(res == ERROR_SUCCESS, "RegOpenKeyExW failed\n");
581         if (res == ERROR_SUCCESS)
582         {
583             DWORD type = 0xdeadbeef, size = MAX_PATH;
584             char driverpath[MAX_PATH];
585 
586             strcpy(driverpath, syspath);
587             strcat(driverpath, "\\sample.dll");
588 
589             memset(path, 0, sizeof(path));
590             res = RegQueryValueExA(hkey, "Translator", NULL, &type, (BYTE *)path, &size);
591             ok(res == ERROR_SUCCESS, "RegGetValueA failed\n");
592             ok(type == REG_SZ, "got %u\n", type);
593             ok(size == strlen(driverpath) + 1, "got %u\n", size);
594             ok(!strcmp(path, driverpath), "invalid path %s\n", path);
595 
596             RegCloseKey(hkey);
597         }
598     }
599 
600     cnt = 100;
601     ret = SQLRemoveTranslator("WINE ODBC Translator", &cnt);
602     ok(ret, "SQLRemoveTranslator failed\n");
603     ok(cnt == 0, "SQLRemoveTranslator failed %d\n", cnt);
604 
605     cnt = 100;
606     ret = SQLRemoveTranslator("WINE ODBC Translator Path", &cnt);
607     ok(ret, "SQLRemoveTranslator failed\n");
608     ok(cnt == 0, "SQLRemoveTranslator failed %d\n", cnt);
609 
610     cnt = 100;
611     ret = SQLRemoveTranslator("WINE ODBC Translator NonExist", &cnt);
612     ok(!ret, "SQLRemoveTranslator succeeded\n");
613     ok(cnt == 100, "SQLRemoveTranslator succeeded %d\n", cnt);
614     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
615     ok(sql_ret && error_code == ODBC_ERROR_COMPONENT_NOT_FOUND,
616         "SQLInstallTranslatorEx failed %d, %u\n", sql_ret, error_code);
617 
618 }
619 
620 static void test_SQLGetInstalledDrivers(void)
621 {
622     char buffer[1000], *p;
623     WORD written, len;
624     BOOL ret, sql_ret;
625     DWORD error_code;
626     int found = 0;
627 
628     ret = SQLInstallDriverEx("Wine test\0Driver=test.dll\0\0", NULL, buffer,
629         sizeof(buffer), &written, ODBC_INSTALL_COMPLETE, NULL);
630     ok(ret, "SQLInstallDriverEx failed: %d\n", ret);
631     sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
632     if (sql_ret && error_code == ODBC_ERROR_WRITING_SYSINFO_FAILED)
633     {
634         skip("not enough privileges\n");
635         return;
636     }
637 
638     ret = SQLGetInstalledDrivers(NULL, sizeof(buffer), &written);
639     ok(!ret, "got %d\n", ret);
640     check_error(ODBC_ERROR_INVALID_BUFF_LEN);
641 
642     ret = SQLGetInstalledDrivers(buffer, 0, &written);
643     ok(!ret, "got %d\n", ret);
644     check_error(ODBC_ERROR_INVALID_BUFF_LEN);
645 
646     ret = SQLGetInstalledDrivers(buffer, 10, &written);
647     ok(ret, "got %d\n", ret);
648     ok(strlen(buffer) == 8, "got len %u\n", lstrlenA(buffer));
649     ok(written == 10, "got written %d\n", written);
650     ok(!buffer[9], "buffer not doubly null-terminated\n");
651 
652     ret = SQLGetInstalledDrivers(buffer, sizeof(buffer), &written);
653     ok(ret, "got %d\n", ret);
654     ok(!buffer[written-1] && !buffer[written-2], "buffer not doubly null-terminated\n");
655     len = strlen(buffer);
656 
657     for (p = buffer; *p; p += strlen(p) + 1)
658     {
659         if (!strcmp(p, "Wine test"))
660             found = 1;
661     }
662     ok(found, "installed driver not found\n");
663 
664     ret = SQLGetInstalledDrivers(buffer, len, &written);
665     ok(ret, "got %d\n", ret);
666     ok(strlen(buffer) == len-2, "expected len %d, got %u\n", len-2, lstrlenA(buffer));
667     ok(written == len, "expected written %d, got %d\n", len, written);
668     ok(!buffer[len-1], "buffer not doubly null-terminated\n");
669 
670     ret = SQLGetInstalledDrivers(buffer, len+1, &written);
671     ok(ret, "got %d\n", ret);
672     ok(strlen(buffer) == len-1, "expected len %d, got %u\n", len-1, lstrlenA(buffer));
673     ok(written == len+1, "expected written %d, got %d\n", len+1, written);
674     ok(!buffer[len], "buffer not doubly null-terminated\n");
675 
676     ret = SQLGetInstalledDrivers(buffer, len+2, &written);
677     ok(ret, "got %d\n", ret);
678     ok(strlen(buffer) == len, "expected len %d, got %u\n", len, lstrlenA(buffer));
679     ok(written == len+2, "expected written %d, got %d\n", len+2, written);
680     ok(!buffer[len+1], "buffer not doubly null-terminated\n");
681 
682     SQLRemoveDriver("Wine test", TRUE, NULL);
683 }
684 
685 static void test_SQLValidDSN(void)
686 {
687     static const char *invalid = "[]{}(),;?*=!@\\";
688     char str[10];
689     int i;
690     BOOL ret;
691 
692     strcpy(str, "wine10");
693     for(i = 0; i < strlen(invalid); i++)
694     {
695         str[4] = invalid[i];
696         ret = SQLValidDSN(str);
697         ok(!ret, "got %d\n", ret);
698     }
699 
700     /* Too large */
701     ret = SQLValidDSN("Wine123456789012345678901234567890");
702     ok(!ret, "got %d\n", ret);
703 
704     /* Valid with a space */
705     ret = SQLValidDSN("Wine Vinegar");
706     ok(ret, "got %d\n", ret);
707 
708     /* Max DSN name value */
709     ret = SQLValidDSN("12345678901234567890123456789012");
710     ok(ret, "got %d\n", ret);
711 }
712 
713 static void test_SQLValidDSNW(void)
714 {
715     static const WCHAR invalid[] = {'[',']','{','}','(',')',',',';','?','*','=','!','@','\\',0};
716     static const WCHAR value[] = { 'w','i','n','e','1','0',0};
717     static const WCHAR too_large[] = { 'W','i','n','e','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5',
718                                    '6','7','8','9','0','1','2','3','4','5','6','7','8','9','0', 0};
719     static const WCHAR with_space[] = { 'W','i','n','e',' ','V','i','n','e','g','a','r', 0};
720     static const WCHAR max_dsn[] = { '1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0',
721                                    '1','2','3','4','5','6','7','8','9','0','1','2', 0};
722     WCHAR str[10];
723     int i;
724     BOOL ret;
725 
726     lstrcpyW(str, value);
727     for(i = 0; i < lstrlenW(invalid); i++)
728     {
729         str[4] = invalid[i];
730         ret = SQLValidDSNW(str);
731         ok(!ret, "got %d\n", ret);
732     }
733 
734     ret = SQLValidDSNW(too_large);
735     ok(!ret, "got %d\n", ret);
736 
737     ret = SQLValidDSNW(with_space);
738     ok(ret, "got %d\n", ret);
739 
740     ret = SQLValidDSNW(max_dsn);
741     ok(ret, "got %d\n", ret);
742 }
743 
744 START_TEST(misc)
745 {
746     test_SQLConfigMode();
747     test_SQLInstallerError();
748     test_SQLInstallDriverManager();
749     test_SQLWritePrivateProfileString();
750     test_SQLGetPrivateProfileString();
751     test_SQLGetPrivateProfileStringW();
752     test_SQLInstallDriverEx();
753     test_SQLInstallTranslatorEx();
754     test_SQLGetInstalledDrivers();
755     test_SQLValidDSN();
756     test_SQLValidDSNW();
757 }
758