setupapi: Handle the INFINFO_REVERSE_DEFAULT_SEARCH search flag.
[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     ok(GetLastError() == ERROR_FILE_NOT_FOUND,
171        "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
172     ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
173
174     /* successfully open the inf file */
175     size = 0xdeadbeef;
176     ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, 0, &size);
177     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
178     ok(size != 0xdeadbeef, "Expected a valid size on return\n");
179
180     /* set ReturnBuffer to NULL and ReturnBufferSize to non-zero */
181     SetLastError(0xbeefcafe);
182     ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, NULL, size, &size);
183     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
184     ok(GetLastError() == ERROR_INVALID_PARAMETER,
185        "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
186
187     info = HeapAlloc(GetProcessHeap(), 0, size);
188
189     /* try valid ReturnBuffer but too small size */
190     SetLastError(0xbeefcafe);
191     ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, info, size - 1, &size);
192     ok(ret == FALSE, "Expected SetupGetInfInformation to fail\n");
193     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
194        "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
195
196     /* successfully get the inf information */
197     ret = pSetupGetInfInformationA(inf_filename, INFINFO_INF_NAME_IS_ABSOLUTE, info, size, &size);
198     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
199     ok(check_info_filename(info, inf_filename), "Expected returned filename to be equal\n");
200
201     HeapFree(GetProcessHeap(), 0, info);
202
203     /* try the INFINFO_INF_SPEC_IS_HINF search flag */
204     hinf = pSetupOpenInfFileA(inf_filename, NULL, INF_STYLE_WIN4, NULL);
205     info = alloc_inf_info(hinf, INFINFO_INF_SPEC_IS_HINF, &size);
206     ret = pSetupGetInfInformationA(hinf, INFINFO_INF_SPEC_IS_HINF, info, size, &size);
207     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
208     ok(check_info_filename(info, inf_filename), "Expected returned filename to be equal\n");
209     pSetupCloseInfFile(hinf);
210
211     lstrcpyA(inf_one, WIN_DIR);
212     lstrcatA(inf_one, "\\inf\\");
213     lstrcatA(inf_one, "test.inf");
214     create_inf_file(inf_one);
215
216     lstrcpyA(inf_two, WIN_DIR);
217     lstrcatA(inf_two, "\\system32\\");
218     lstrcatA(inf_two, "test.inf");
219     create_inf_file(inf_two);
220
221     HeapFree(GetProcessHeap(), 0, info);
222     info = alloc_inf_info("test.inf", INFINFO_DEFAULT_SEARCH, &size);
223
224     /* test the INFINFO_DEFAULT_SEARCH search flag */
225     ret = pSetupGetInfInformationA("test.inf", INFINFO_DEFAULT_SEARCH, info, size, &size);
226     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
227     ok(check_info_filename(info, inf_one), "Expected returned filename to be equal\n");
228
229     HeapFree(GetProcessHeap(), 0, info);
230     info = alloc_inf_info("test.inf", INFINFO_REVERSE_DEFAULT_SEARCH, &size);
231
232     /* test the INFINFO_REVERSE_DEFAULT_SEARCH search flag */
233     ret = pSetupGetInfInformationA("test.inf", INFINFO_REVERSE_DEFAULT_SEARCH, info, size, &size);
234     ok(ret == TRUE, "Expected SetupGetInfInformation to succeed\n");
235     ok(check_info_filename(info, inf_two), "Expected returned filename to be equal\n");
236
237     DeleteFileA(inf_filename);
238     DeleteFileA(inf_one);
239     DeleteFileA(inf_two);
240 }
241
242 START_TEST(query)
243 {
244     init_function_pointers();
245     get_directories();
246
247     test_SetupGetInfInformation();
248 }