kernel32: FindFirstChangeNotification needs a static IO_STATUS_BLOCK.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdio.h>
22 #include <windows.h>
23 #include <setupapi.h>
24 #include "wine/test.h"
25
26 /* function pointers */
27 static HMODULE hSetupAPI;
28 static void (WINAPI *pSetupCloseInfFile)(HINF);
29 static BOOL (WINAPI *pSetupGetInfInformationA)(LPCVOID,DWORD,PSP_INF_INFORMATION,DWORD,PDWORD);
30 static HINF (WINAPI *pSetupOpenInfFileA)(PCSTR,PCSTR,DWORD,PUINT);
31 static BOOL (WINAPI *pSetupQueryInfFileInformationA)(PSP_INF_INFORMATION,UINT,PSTR,DWORD,PDWORD);
32
33 CHAR CURR_DIR[MAX_PATH];
34 CHAR WIN_DIR[MAX_PATH];
35
36 static void init_function_pointers(void)
37 {
38     hSetupAPI = LoadLibraryA("setupapi.dll");
39
40     if (hSetupAPI)
41     {
42         pSetupCloseInfFile = (void *)GetProcAddress(hSetupAPI, "SetupCloseInfFile");
43         pSetupGetInfInformationA = (void *)GetProcAddress(hSetupAPI, "SetupGetInfInformationA");
44         pSetupOpenInfFileA = (void *)GetProcAddress(hSetupAPI, "SetupOpenInfFileA");
45         pSetupQueryInfFileInformationA = (void *)GetProcAddress(hSetupAPI, "SetupQueryInfFileInformationA");
46     }
47 }
48
49 static void get_directories(void)
50 {
51     int len;
52
53     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
54     len = lstrlenA(CURR_DIR);
55
56     if(len && (CURR_DIR[len-1] == '\\'))
57         CURR_DIR[len-1] = 0;
58
59     GetWindowsDirectoryA(WIN_DIR, MAX_PATH);
60     len = lstrlenA(WIN_DIR);
61
62     if (len && (WIN_DIR[len-1] == '\\'))
63         WIN_DIR[len-1] = 0;
64 }
65
66 static void append_str(char **str, const char *data)
67 {
68     sprintf(*str, data);
69     *str += strlen(*str);
70 }
71
72 static void create_inf_file(LPSTR filename)
73 {
74     char data[1024];
75     char *ptr = data;
76     DWORD dwNumberOfBytesWritten;
77     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
78                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
79
80     append_str(&ptr, "[Version]\n");
81     append_str(&ptr, "Signature=\"$Chicago$\"\n");
82     append_str(&ptr, "AdvancedINF=2.5\n");
83
84     WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
85     CloseHandle(hf);
86 }
87
88 static BOOL check_info_filename(PSP_INF_INFORMATION info, LPSTR test)
89 {
90     LPSTR filename;
91     DWORD size;
92     BOOL ret = FALSE;
93
94     if (!pSetupQueryInfFileInformationA(info, 0, NULL, 0, &size))
95         return FALSE;
96
97     filename = HeapAlloc(GetProcessHeap(), 0, size);
98     if (!filename)
99         return FALSE;
100
101     pSetupQueryInfFileInformationA(info, 0, filename, size, &size);
102
103     if (!lstrcmpiA(test, filename))
104         ret = TRUE;
105
106     HeapFree(GetProcessHeap(), 0, filename);
107     return ret;
108 }
109
110 static PSP_INF_INFORMATION alloc_inf_info(LPSTR filename, DWORD search, PDWORD size)
111 {
112     PSP_INF_INFORMATION info;
113     BOOL ret;
114
115     ret = pSetupGetInfInformationA(filename, search, NULL, 0, size);
116     if (!ret)
117         return NULL;
118
119     info = HeapAlloc(GetProcessHeap(), 0, *size);
120     return info;
121 }
122
123 static void test_SetupGetInfInformation(void)
124 {
125     PSP_INF_INFORMATION info;
126     CHAR inf_filename[MAX_PATH];
127     CHAR inf_one[MAX_PATH], inf_two[MAX_PATH];
128     DWORD size;
129     HINF hinf;
130     BOOL ret;
131
132     lstrcpyA(inf_filename, CURR_DIR);
133     lstrcatA(inf_filename, "\\");
134     lstrcatA(inf_filename, "test.inf");
135
136     /* try an invalid inf handle */
137     size = 0xdeadbeef;
138     SetLastError(0xbeefcafe);
139     ret = pSetupGetInfInformationA(NULL, INFINFO_INF_SPEC_IS_HINF, NULL, 0, &size);
140     todo_wine
141     {
142         ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
143         ok(GetLastError() == ERROR_INVALID_HANDLE,
144            "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
145     }
146     ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
147
148     /* try an invalid inf filename */
149     size = 0xdeadbeef;
150     SetLastError(0xbeefcafe);
151     ret = pSetupGetInfInformationA(NULL, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
152     todo_wine
153     {
154         ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
155         ok(GetLastError() == ERROR_INVALID_PARAMETER,
156            "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
157     }
158     ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
159
160     create_inf_file(inf_filename);
161
162     /* try an invalid search flag */
163     size = 0xdeadbeef;
164     SetLastError(0xbeefcafe);
165     ret = pSetupGetInfInformationA(inf_filename, -1, NULL, 0, &size);
166     todo_wine
167     {
168         ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
169         ok(GetLastError() == ERROR_INVALID_PARAMETER,
170            "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
171     }
172     ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
173
174     /* try a nonexistent inf file */
175     size = 0xdeadbeef;
176     SetLastError(0xbeefcafe);
177     ret = pSetupGetInfInformationA("idontexist", INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
178     todo_wine
179     {
180         ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
181         ok(GetLastError() == ERROR_FILE_NOT_FOUND,
182            "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
183     }
184     ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
185
186     /* successfully open the inf file */
187     size = 0xdeadbeef;
188     ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
189     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
190     todo_wine
191     {
192         ok(size != 0xdeadbeef, "Expected a valid size on return\n");
193     }
194
195     /* set ReturnBuffer to NULL and ReturnBufferSize to non-zero */
196     SetLastError(0xbeefcafe);
197     ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, size, &size);
198     todo_wine
199     {
200         ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
201         ok(GetLastError() == ERROR_INVALID_PARAMETER,
202            "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
203     }
204
205     info = HeapAlloc(GetProcessHeap(), 0, size);
206
207     /* try valid ReturnBuffer but too small size */
208     SetLastError(0xbeefcafe);
209     ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, info, size - 1, &size);
210     todo_wine
211     {
212         ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
213         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
214            "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
215     }
216
217     /* successfully get the inf information */
218     ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, info, size, &size);
219     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
220     todo_wine
221     {
222         ok(check_info_filename(info, inf_filename), "Expected returned filename to be equal\n");
223     }
224
225     /* try the INFINFO_INF_SPEC_IS_HINF search flag */
226     hinf = pSetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
227     ret = pSetupGetInfInformationA(hinf, INFINFO_INF_SPEC_IS_HINF, info, size, &size);
228     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
229     todo_wine
230     {
231         ok(check_info_filename(info, inf_filename), "Expected returned filename to be equal\n");
232     }
233     pSetupCloseInfFile(hinf);
234
235     lstrcpyA(inf_one, WIN_DIR);
236     lstrcatA(inf_one, "\\inf\\");
237     lstrcatA(inf_one, "test.inf");
238     create_inf_file(inf_one);
239
240     lstrcpyA(inf_two, WIN_DIR);
241     lstrcatA(inf_two, "\\system32\\");
242     lstrcatA(inf_two, "test.inf");
243     create_inf_file(inf_two);
244
245     HeapFree(GetProcessHeap(), 0, info);
246     info = alloc_inf_info("test.inf", INFINFO_DEFAULT_SEARCH, &size);
247
248     /* test the INFINFO_DEFAULT_SEARCH search flag */
249     ret = pSetupGetInfInformationA("test.inf", INFINFO_DEFAULT_SEARCH, info, size, &size);
250     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
251     todo_wine
252     {
253         ok(check_info_filename(info, inf_one), "Expected returned filename to be equal\n");
254     }
255
256     HeapFree(GetProcessHeap(), 0, info);
257     info = alloc_inf_info("test.inf", INFINFO_REVERSE_DEFAULT_SEARCH, &size);
258
259     /* test the INFINFO_REVERSE_DEFAULT_SEARCH search flag */
260     ret = pSetupGetInfInformationA("test.inf", INFINFO_REVERSE_DEFAULT_SEARCH, info, size, &size);
261     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
262     todo_wine
263     {
264         ok(check_info_filename(info, inf_two), "Expected returned filename to be equal\n");
265     }
266
267     DeleteFileA(inf_filename);
268     DeleteFileA(inf_one);
269     DeleteFileA(inf_two);
270 }
271
272 START_TEST(query)
273 {
274     init_function_pointers();
275     get_directories();
276
277     test_SetupGetInfInformation();
278 }