setupapi: Add an initial implementation of SetupGetInfInformation.
[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     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
141     ok(GetLastError() == ERROR_INVALID_HANDLE,
142        "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
143     ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
144
145     /* try an invalid inf filename */
146     size = 0xdeadbeef;
147     SetLastError(0xbeefcafe);
148     ret = pSetupGetInfInformationA(NULL, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
149     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
150     ok(GetLastError() == ERROR_INVALID_PARAMETER,
151        "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
152     ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
153
154     create_inf_file(inf_filename);
155
156     /* try an invalid search flag */
157     size = 0xdeadbeef;
158     SetLastError(0xbeefcafe);
159     ret = pSetupGetInfInformationA(inf_filename, -1, NULL, 0, &size);
160     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
161     ok(GetLastError() == ERROR_INVALID_PARAMETER,
162        "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
163     ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
164
165     /* try a nonexistent inf file */
166     size = 0xdeadbeef;
167     SetLastError(0xbeefcafe);
168     ret = pSetupGetInfInformationA("idontexist", INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
169     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
170     todo_wine
171     {
172         ok(GetLastError() == ERROR_FILE_NOT_FOUND,
173            "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
174         ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
175     }
176
177     /* successfully open the inf file */
178     size = 0xdeadbeef;
179     ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
180     todo_wine
181     {
182         ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
183     }
184     ok(size != 0xdeadbeef, "Expected a valid size on return\n");
185
186     /* set ReturnBuffer to NULL and ReturnBufferSize to non-zero */
187     SetLastError(0xbeefcafe);
188     ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, size, &size);
189     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
190     todo_wine
191     {
192         ok(GetLastError() == ERROR_INVALID_PARAMETER,
193            "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
194     }
195
196     info = HeapAlloc(GetProcessHeap(), 0, size);
197
198     /* try valid ReturnBuffer but too small size */
199     SetLastError(0xbeefcafe);
200     ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, info, size - 1, &size);
201     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
202     todo_wine
203     {
204         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
205            "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
206     }
207
208     /* successfully get the inf information */
209     ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, info, size, &size);
210     todo_wine
211     {
212         ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
213         ok(check_info_filename(info, inf_filename), "Expected returned filename to be equal\n");
214     }
215
216     HeapFree(GetProcessHeap(), 0, info);
217
218     /* try the INFINFO_INF_SPEC_IS_HINF search flag */
219     hinf = pSetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
220     info = alloc_inf_info(hinf, INFINFO_INF_SPEC_IS_HINF, &size);
221     ret = pSetupGetInfInformationA(hinf, INFINFO_INF_SPEC_IS_HINF, info, size, &size);
222     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
223     ok(check_info_filename(info, inf_filename), "Expected returned filename to be equal\n");
224     pSetupCloseInfFile(hinf);
225
226     lstrcpyA(inf_one, WIN_DIR);
227     lstrcatA(inf_one, "\\inf\\");
228     lstrcatA(inf_one, "test.inf");
229     create_inf_file(inf_one);
230
231     lstrcpyA(inf_two, WIN_DIR);
232     lstrcatA(inf_two, "\\system32\\");
233     lstrcatA(inf_two, "test.inf");
234     create_inf_file(inf_two);
235
236     HeapFree(GetProcessHeap(), 0, info);
237     info = alloc_inf_info("test.inf", INFINFO_DEFAULT_SEARCH, &size);
238
239     /* test the INFINFO_DEFAULT_SEARCH search flag */
240     ret = pSetupGetInfInformationA("test.inf", INFINFO_DEFAULT_SEARCH, info, size, &size);
241     todo_wine
242     {
243         ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
244         ok(check_info_filename(info, inf_one), "Expected returned filename to be equal\n");
245     }
246
247     HeapFree(GetProcessHeap(), 0, info);
248     info = alloc_inf_info("test.inf", INFINFO_REVERSE_DEFAULT_SEARCH, &size);
249
250     /* test the INFINFO_REVERSE_DEFAULT_SEARCH search flag */
251     ret = pSetupGetInfInformationA("test.inf", INFINFO_REVERSE_DEFAULT_SEARCH, info, size, &size);
252     todo_wine
253     {
254         ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
255         ok(check_info_filename(info, inf_two), "Expected returned filename to be equal\n");
256     }
257
258     DeleteFileA(inf_filename);
259     DeleteFileA(inf_one);
260     DeleteFileA(inf_two);
261 }
262
263 START_TEST(query)
264 {
265     init_function_pointers();
266     get_directories();
267
268     test_SetupGetInfInformation();
269 }