setupapi/tests: Fix string format warnings.
[wine] / dlls / setupapi / tests / query.c
1 /*
2  * Unit tests for setupapi.dll query functions
3  *
4  * Copyright (C) 2006 James Hawkins
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdio.h>
22 #include <windows.h>
23 #include <setupapi.h>
24 #include "wine/test.h"
25
26 CHAR CURR_DIR[MAX_PATH];
27 CHAR WIN_DIR[MAX_PATH];
28
29 static void get_directories(void)
30 {
31     int len;
32
33     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
34     len = lstrlenA(CURR_DIR);
35
36     if(len && (CURR_DIR[len-1] == '\\'))
37         CURR_DIR[len-1] = 0;
38
39     GetWindowsDirectoryA(WIN_DIR, MAX_PATH);
40     len = lstrlenA(WIN_DIR);
41
42     if (len && (WIN_DIR[len-1] == '\\'))
43         WIN_DIR[len-1] = 0;
44 }
45
46 static void create_inf_file(LPSTR filename)
47 {
48     DWORD dwNumberOfBytesWritten;
49     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
50                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
51
52     static const char data[] =
53         "[Version]\n"
54         "Signature=\"$Chicago$\"\n"
55         "AdvancedINF=2.5\n"
56         "[SourceDisksNames]\n"
57         "2 = %SrcDiskName%, LANCOM\\LANtools\\lanconf.cab\n"
58         "[SourceDisksFiles]\n"
59         "lanconf.exe = 2\n"
60         "[DestinationDirs]\n"
61         "DefaultDestDir = 24, %DefaultDest%\n"
62         "[Strings]\n"
63         "LangDir = english\n"
64         "DefaultDest = LANCOM\n"
65         "SrcDiskName = \"LANCOM Software CD\"\n";
66
67     WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
68     CloseHandle(hf);
69 }
70
71 static void create_inf_file2(LPSTR filename)
72 {
73     DWORD dwNumberOfBytesWritten;
74     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
75                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
76
77     static const char data[] =
78         "[SourceFileInfo]\n"
79         "sp1qfe\\bitsinst.exe=250B3702C7CCD7C2F9E4DAA1555C933E,000600060A28062C,27136,SP1QFE\n"
80         "sp1qfe\\bitsprx2.dll=4EBEA67F4BB4EB402E725CA7CA2857AE,000600060A280621,7680,SP1QFE\n"
81         "sp1qfe\\bitsprx3.dll=C788A1D9330DA011EF25E95D3BC7BDE5,000600060A280621,7168,SP1QFE\n"
82         "sp1qfe\\qmgr.dll=696AC82FB290A03F205901442E0E9589,000600060A280621,361984,SP1QFE\n"
83         "sp1qfe\\qmgrprxy.dll=8B5848144829E1BC985EA4C3D8CA7E3F,000600060A280621,17408,SP1QFE\n"
84         "sp1qfe\\winhttp.dll=3EC6F518114606CA59D4160322077437,000500010A280615,331776,SP1QFE\n"
85         "sp1qfe\\xpob2res.dll=DB83156B9F496F20D1EA70E4ABEC0166,000500010A280622,158720,SP1QFE\n";
86
87     WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
88     CloseHandle(hf);
89 }
90
91 static BOOL check_info_filename(PSP_INF_INFORMATION info, LPSTR test)
92 {
93     LPSTR filename;
94     DWORD size;
95     BOOL ret = FALSE;
96
97     if (!SetupQueryInfFileInformationA(info, 0, NULL, 0, &size))
98         return FALSE;
99
100     filename = HeapAlloc(GetProcessHeap(), 0, size);
101     if (!filename)
102         return FALSE;
103
104     SetupQueryInfFileInformationA(info, 0, filename, size, &size);
105
106     if (!lstrcmpiA(test, filename))
107         ret = TRUE;
108
109     HeapFree(GetProcessHeap(), 0, filename);
110     return ret;
111 }
112
113 static PSP_INF_INFORMATION alloc_inf_info(LPCSTR filename, DWORD search, PDWORD size)
114 {
115     PSP_INF_INFORMATION info;
116     BOOL ret;
117
118     ret = SetupGetInfInformationA(filename, search, NULL, 0, size);
119     if (!ret)
120         return NULL;
121
122     info = HeapAlloc(GetProcessHeap(), 0, *size);
123     return info;
124 }
125
126 static void test_SetupGetInfInformation(void)
127 {
128     PSP_INF_INFORMATION info;
129     CHAR inf_filename[MAX_PATH];
130     CHAR inf_one[MAX_PATH], inf_two[MAX_PATH];
131     LPSTR revfile;
132     DWORD size;
133     HINF hinf;
134     BOOL ret;
135
136     lstrcpyA(inf_filename, CURR_DIR);
137     lstrcatA(inf_filename, "\\");
138     lstrcatA(inf_filename, "test.inf");
139
140     /* try an invalid inf handle */
141     size = 0xdeadbeef;
142     SetLastError(0xbeefcafe);
143     ret = SetupGetInfInformationA(NULL, INFINFO_INF_SPEC_IS_HINF, NULL, 0, &size);
144     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
145     ok(GetLastError() == ERROR_INVALID_HANDLE ||
146        broken(GetLastError() == ERROR_BAD_PATHNAME) || /* win95 */
147        broken(GetLastError() == ERROR_FILE_NOT_FOUND) || /* win98 */
148        broken(GetLastError() == ERROR_PATH_NOT_FOUND) || /* NT4 */
149        broken(GetLastError() == ERROR_INVALID_NAME) || /* win2k */
150        broken(GetLastError() == ERROR_GENERAL_SYNTAX), /* another win2k */
151        "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
152     ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
153
154     /* try an invalid inf filename */
155     /* do not use NULL as absolute inf filename on win9x (crash) */
156     if ((GetLastError() != ERROR_BAD_PATHNAME) &&   /* win95 */
157         (GetLastError() != ERROR_FILE_NOT_FOUND))  /* win98 */
158     {
159         size = 0xdeadbeef;
160         SetLastError(0xbeefcafe);
161         ret = SetupGetInfInformationA(NULL, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
162         ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
163         ok(GetLastError() == ERROR_INVALID_PARAMETER,
164            "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
165         ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
166     }
167
168     create_inf_file(inf_filename);
169
170     /* try an invalid search flag */
171     size = 0xdeadbeef;
172     SetLastError(0xbeefcafe);
173     ret = SetupGetInfInformationA(inf_filename, -1, NULL, 0, &size);
174     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
175     ok(GetLastError() == ERROR_INVALID_PARAMETER,
176        "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
177     ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
178
179     /* try a nonexistent inf file */
180     size = 0xdeadbeef;
181     SetLastError(0xbeefcafe);
182     ret = SetupGetInfInformationA("idontexist", INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
183     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
184     ok(GetLastError() == ERROR_FILE_NOT_FOUND,
185        "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
186     ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
187
188     /* successfully open the inf file */
189     size = 0xdeadbeef;
190     ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
191     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
192     ok(size != 0xdeadbeef, "Expected a valid size on return\n");
193
194     /* set ReturnBuffer to NULL and ReturnBufferSize to non-zero value 'size' */
195     SetLastError(0xbeefcafe);
196     ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, size, &size);
197     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
198     ok(GetLastError() == ERROR_INVALID_PARAMETER,
199        "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
200
201     /* set ReturnBuffer to NULL and ReturnBufferSize to non-zero value 'size-1' */
202     ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, size-1, &size);
203     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
204
205     /* some tests for behaviour with a NULL RequiredSize pointer */
206     ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, NULL);
207     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
208     ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, size - 1, NULL);
209     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
210     ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, size, NULL);
211     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
212
213     info = HeapAlloc(GetProcessHeap(), 0, size);
214
215     /* try valid ReturnBuffer but too small size */
216     SetLastError(0xbeefcafe);
217     ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, info, size - 1, &size);
218     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
219     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
220        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
221
222     /* successfully get the inf information */
223     ret = SetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, info, size, &size);
224     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
225     ok(check_info_filename(info, inf_filename), "Expected returned filename to be equal\n");
226
227     HeapFree(GetProcessHeap(), 0, info);
228
229     /* try the INFINFO_INF_SPEC_IS_HINF search flag */
230     hinf = SetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
231     info = alloc_inf_info(hinf, INFINFO_INF_SPEC_IS_HINF, &size);
232     ret = SetupGetInfInformationA(hinf, INFINFO_INF_SPEC_IS_HINF, info, size, &size);
233     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
234     ok(check_info_filename(info, inf_filename), "Expected returned filename to be equal\n");
235     SetupCloseInfFile(hinf);
236
237     lstrcpyA(inf_two, WIN_DIR);
238     lstrcatA(inf_two, "\\system32\\");
239     lstrcatA(inf_two, "test.inf");
240     create_inf_file(inf_two);
241
242     HeapFree(GetProcessHeap(), 0, info);
243     info = alloc_inf_info("test.inf", INFINFO_DEFAULT_SEARCH, &size);
244
245     /* check if system32 is searched for inf */
246     ret = SetupGetInfInformationA("test.inf", INFINFO_DEFAULT_SEARCH, info, size, &size);
247     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
248         revfile = inf_one; /* Vista */
249     else
250         revfile = inf_two;
251
252     lstrcpyA(inf_one, WIN_DIR);
253     lstrcatA(inf_one, "\\inf\\");
254     lstrcatA(inf_one, "test.inf");
255     create_inf_file(inf_one);
256
257     HeapFree(GetProcessHeap(), 0, info);
258     info = alloc_inf_info("test.inf", INFINFO_DEFAULT_SEARCH, &size);
259
260     /* test the INFINFO_DEFAULT_SEARCH search flag */
261     ret = SetupGetInfInformationA("test.inf", INFINFO_DEFAULT_SEARCH, info, size, &size);
262     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed: %d\n", GetLastError());
263     ok(check_info_filename(info, inf_one), "Expected returned filename to be equal\n");
264
265     HeapFree(GetProcessHeap(), 0, info);
266     info = alloc_inf_info("test.inf", INFINFO_REVERSE_DEFAULT_SEARCH, &size);
267
268     /* test the INFINFO_REVERSE_DEFAULT_SEARCH search flag */
269     ret = SetupGetInfInformationA("test.inf", INFINFO_REVERSE_DEFAULT_SEARCH, info, size, &size);
270     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
271     ok(check_info_filename(info, revfile), "Expected returned filename to be equal\n");
272
273     HeapFree(GetProcessHeap(), 0, info);
274
275     DeleteFileA(inf_filename);
276     DeleteFileA(inf_one);
277     DeleteFileA(inf_two);
278 }
279
280 static void test_SetupGetSourceFileLocation(void)
281 {
282     char buffer[MAX_PATH] = "not empty", inf_filename[MAX_PATH];
283     UINT source_id;
284     DWORD required, error;
285     HINF hinf;
286     BOOL ret;
287
288     lstrcpyA(inf_filename, CURR_DIR);
289     lstrcatA(inf_filename, "\\");
290     lstrcatA(inf_filename, "test.inf");
291
292     create_inf_file(inf_filename);
293
294     hinf = SetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
295     ok(hinf != INVALID_HANDLE_VALUE, "could not open inf file\n");
296
297     required = 0;
298     source_id = 0;
299
300     ret = SetupGetSourceFileLocationA(hinf, NULL, "lanconf.exe", &source_id, buffer, sizeof(buffer), &required);
301     ok(ret, "SetupGetSourceFileLocation failed\n");
302
303     ok(required == 1, "unexpected required size: %d\n", required);
304     ok(source_id == 2, "unexpected source id: %d\n", source_id);
305     ok(!lstrcmpA("", buffer), "unexpected result string: %s\n", buffer);
306
307     SetupCloseInfFile(hinf);
308     DeleteFileA(inf_filename);
309
310     create_inf_file2(inf_filename);
311
312     SetLastError(0xdeadbeef);
313     hinf = SetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
314     error = GetLastError();
315     ok(hinf == INVALID_HANDLE_VALUE, "could open inf file\n");
316     ok(error == ERROR_WRONG_INF_STYLE, "got wrong error: %d\n", error);
317
318     hinf = SetupOpenInfFileA(inf_filename, NULL, INF_STYLE_OLDNT, NULL);
319     ok(hinf != INVALID_HANDLE_VALUE, "could not open inf file\n");
320
321     ret = SetupGetSourceFileLocationA(hinf, NULL, "", &source_id, buffer, sizeof(buffer), &required);
322     ok(!ret, "SetupGetSourceFileLocation succeeded\n");
323
324     SetupCloseInfFile(hinf);
325     DeleteFileA(inf_filename);
326 }
327
328 static void test_SetupGetSourceInfo(void)
329 {
330     char buffer[MAX_PATH], inf_filename[MAX_PATH];
331     DWORD required;
332     HINF hinf;
333     BOOL ret;
334
335     lstrcpyA(inf_filename, CURR_DIR);
336     lstrcatA(inf_filename, "\\");
337     lstrcatA(inf_filename, "test.inf");
338
339     create_inf_file(inf_filename);
340
341     hinf = SetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
342     ok(hinf != INVALID_HANDLE_VALUE, "could not open inf file\n");
343
344     required = 0;
345
346     ret = SetupGetSourceInfoA(hinf, 2, SRCINFO_PATH, buffer, sizeof(buffer), &required);
347     ok(ret, "SetupGetSourceInfoA failed\n");
348
349     ok(required == 1, "unexpected required size: %d\n", required);
350     ok(!lstrcmpA("", buffer), "unexpected result string: %s\n", buffer);
351
352     required = 0;
353     buffer[0] = 0;
354
355     ret = SetupGetSourceInfoA(hinf, 2, SRCINFO_TAGFILE, buffer, sizeof(buffer), &required);
356     ok(ret, "SetupGetSourceInfoA failed\n");
357
358     ok(required == 28, "unexpected required size: %d\n", required);
359     ok(!lstrcmpA("LANCOM\\LANtools\\lanconf.cab", buffer), "unexpected result string: %s\n", buffer);
360
361     required = 0;
362     buffer[0] = 0;
363
364     ret = SetupGetSourceInfoA(hinf, 2, SRCINFO_DESCRIPTION, buffer, sizeof(buffer), &required);
365     ok(ret, "SetupGetSourceInfoA failed\n");
366
367     ok(required == 19, "unexpected required size: %d\n", required);
368     ok(!lstrcmpA("LANCOM Software CD", buffer), "unexpected result string: %s\n", buffer);
369
370     SetupCloseInfFile(hinf);
371     DeleteFileA(inf_filename);
372 }
373
374 static void test_SetupGetTargetPath(void)
375 {
376     char buffer[MAX_PATH], inf_filename[MAX_PATH];
377     char destfile[MAX_PATH];
378     DWORD required;
379     HINF hinf;
380     INFCONTEXT ctx;
381     BOOL ret;
382
383     lstrcpyA(inf_filename, CURR_DIR);
384     lstrcatA(inf_filename, "\\");
385     lstrcatA(inf_filename, "test.inf");
386
387     create_inf_file(inf_filename);
388
389     hinf = SetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
390     ok(hinf != INVALID_HANDLE_VALUE, "could not open inf file\n");
391
392     ctx.Inf = hinf;
393     ctx.CurrentInf = hinf;
394     ctx.Section = 7;
395     ctx.Line = 0;
396
397     required = 0;
398
399     ret = SetupGetTargetPathA(hinf, &ctx, NULL, buffer, sizeof(buffer), &required);
400     ok(ret, "SetupGetTargetPathA failed\n");
401     ok(required == 10, "unexpected required size: %d\n", required);
402     /* Retrieve the system drive from the windows directory.
403      * (%SystemDrive% is not available on Win9x)
404      */
405     lstrcpyA(destfile, WIN_DIR);
406     destfile[3] = '\0';
407     lstrcatA(destfile, "LANCOM");
408     ok(!lstrcmpiA(destfile, buffer), "unexpected result string: %s\n", buffer);
409
410     SetupCloseInfFile(hinf);
411     DeleteFileA(inf_filename);
412 }
413
414 START_TEST(query)
415 {
416     get_directories();
417
418     test_SetupGetInfInformation();
419     test_SetupGetSourceFileLocation();
420     test_SetupGetSourceInfo();
421     test_SetupGetTargetPath();
422 }