4 * Copyright 2006 Christian Gmeiner
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.
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.
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
32 #include "wine/test.h"
34 /* function pointers */
35 static HMODULE hSetupAPI;
36 static HDEVINFO (WINAPI *pSetupDiCreateDeviceInfoList)(GUID*,HWND);
37 static HDEVINFO (WINAPI *pSetupDiCreateDeviceInfoListExW)(GUID*,HWND,PCWSTR,PVOID);
38 static BOOL (WINAPI *pSetupDiDestroyDeviceInfoList)(HDEVINFO);
39 static BOOL (WINAPI *pSetupDiEnumDeviceInfo)(HDEVINFO, DWORD, PSP_DEVINFO_DATA);
40 static HKEY (WINAPI *pSetupDiOpenClassRegKeyExA)(GUID*,REGSAM,DWORD,PCSTR,PVOID);
41 static BOOL (WINAPI *pSetupDiCreateDeviceInfoA)(HDEVINFO, PCSTR, GUID *, PCSTR, HWND, DWORD, PSP_DEVINFO_DATA);
42 static BOOL (WINAPI *pSetupDiGetDeviceInstanceIdA)(HDEVINFO, PSP_DEVINFO_DATA, PSTR, DWORD, PDWORD);
43 static BOOL (WINAPI *pSetupDiRegisterDeviceInfo)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PSP_DETSIG_CMPPROC, PVOID, PSP_DEVINFO_DATA);
45 static void init_function_pointers(void)
47 hSetupAPI = GetModuleHandleA("setupapi.dll");
49 pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA");
50 pSetupDiCreateDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoList");
51 pSetupDiCreateDeviceInfoListExW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoListExW");
52 pSetupDiDestroyDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiDestroyDeviceInfoList");
53 pSetupDiEnumDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInfo");
54 pSetupDiGetDeviceInstanceIdA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInstanceIdA");
55 pSetupDiOpenClassRegKeyExA = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenClassRegKeyExA");
56 pSetupDiRegisterDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiRegisterDeviceInfo");
59 static void test_SetupDiCreateDeviceInfoListEx(void)
64 static CHAR notnull[] = "NotNull";
65 static const WCHAR machine[] = { 'd','u','m','m','y',0 };
67 SetLastError(0xdeadbeef);
68 /* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */
69 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, notnull);
71 error = GetLastError();
72 if (error == ERROR_CALL_NOT_IMPLEMENTED)
74 skip("SetupDiCreateDeviceInfoListExW is not implemented\n");
77 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
78 ok(error == ERROR_INVALID_PARAMETER, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_PARAMETER);
80 SetLastError(0xdeadbeef);
81 /* create empty DeviceInfoList, but set MachineName to something */
82 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL);
84 error = GetLastError();
85 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
86 ok(error == ERROR_INVALID_MACHINENAME, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_MACHINENAME);
88 /* create empty DeviceInfoList */
89 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
90 ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE);
92 /* destroy DeviceInfoList */
93 ret = pSetupDiDestroyDeviceInfoList(devlist);
94 ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error);
97 static void test_SetupDiOpenClassRegKeyExA(void)
99 /* This is a unique guid for testing purposes */
100 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
101 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
102 static const CHAR guidString[] = "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
105 /* Check return value for nonexistent key */
106 hkey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
107 DIOCR_INSTALLER, NULL, NULL);
108 ok(hkey == INVALID_HANDLE_VALUE,
109 "returned %p (expected INVALID_HANDLE_VALUE)\n", hkey);
111 /* Test it for a key that exists */
112 hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS);
113 if (hkey != INVALID_HANDLE_VALUE)
116 if (RegCreateKeyA(hkey, guidString, &classKey) == ERROR_SUCCESS)
118 RegCloseKey(classKey);
119 SetLastError(0xdeadbeef);
120 classKey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
121 DIOCR_INSTALLER, NULL, NULL);
122 ok(classKey != INVALID_HANDLE_VALUE,
123 "opening class registry key failed with error %d\n",
125 if (classKey != INVALID_HANDLE_VALUE)
126 RegCloseKey(classKey);
127 RegDeleteKeyA(hkey, guidString);
130 trace("failed to create registry key for test\n");
133 trace("failed to open classes key\n");
136 static void testCreateDeviceInfo(void)
140 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
141 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
143 if (!pSetupDiCreateDeviceInfoList || !pSetupDiEnumDeviceInfo ||
144 !pSetupDiDestroyDeviceInfoList || !pSetupDiCreateDeviceInfoA)
146 skip("No SetupDiCreateDeviceInfoA\n");
149 SetLastError(0xdeadbeef);
150 ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
151 ok(!ret && GetLastError() == ERROR_INVALID_DEVINST_NAME,
152 "Expected ERROR_INVALID_DEVINST_NAME, got %08x\n", GetLastError());
153 SetLastError(0xdeadbeef);
154 ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL,
155 NULL, NULL, 0, NULL);
156 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
157 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
158 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
159 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
163 SP_DEVINFO_DATA devInfo = { 0 };
166 SetLastError(0xdeadbeef);
167 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL,
168 NULL, NULL, 0, NULL);
169 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
170 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
171 /* Finally, with all three required parameters, this succeeds: */
172 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
173 NULL, NULL, 0, NULL);
174 ok(ret, "pSetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
175 /* This fails because the device ID already exists.. */
176 SetLastError(0xdeadbeef);
177 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
178 NULL, NULL, 0, &devInfo);
179 ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
180 "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError());
181 /* whereas this "fails" because cbSize is wrong.. */
182 SetLastError(0xdeadbeef);
183 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
184 DICD_GENERATE_ID, &devInfo);
185 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
186 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
187 devInfo.cbSize = sizeof(devInfo);
188 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
189 DICD_GENERATE_ID, &devInfo);
190 /* and this finally succeeds. */
191 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
192 /* There were three devices added, however - the second failure just
193 * resulted in the SP_DEVINFO_DATA not getting copied.
195 SetLastError(0xdeadbeef);
197 while (pSetupDiEnumDeviceInfo(set, i, &devInfo))
199 ok(i == 3, "Expected 3 devices, got %d\n", i);
200 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
201 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
202 pSetupDiDestroyDeviceInfoList(set);
206 static void testGetDeviceInstanceId(void)
210 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
211 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
212 SP_DEVINFO_DATA devInfo = { 0 };
214 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
215 !pSetupDiCreateDeviceInfoA || !pSetupDiGetDeviceInstanceIdA)
217 skip("No SetupDiGetDeviceInstanceIdA\n");
220 SetLastError(0xdeadbeef);
221 ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
222 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
223 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
224 SetLastError(0xdeadbeef);
225 ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, NULL, 0, NULL);
226 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
227 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
228 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
229 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
233 char instanceID[MAX_PATH];
236 SetLastError(0xdeadbeef);
237 ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
238 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
239 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
240 SetLastError(0xdeadbeef);
241 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL);
242 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
243 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
244 SetLastError(0xdeadbeef);
245 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
246 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
247 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
248 devInfo.cbSize = sizeof(devInfo);
249 SetLastError(0xdeadbeef);
250 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
251 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
252 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
253 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
254 NULL, NULL, 0, &devInfo);
255 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
256 SetLastError(0xdeadbeef);
257 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
258 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
259 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
260 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
261 sizeof(instanceID), NULL);
262 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
263 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"),
264 "Unexpected instance ID %s\n", instanceID);
265 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid,
266 NULL, NULL, DICD_GENERATE_ID, &devInfo);
267 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
268 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
269 sizeof(instanceID), NULL);
270 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
271 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"),
272 "Unexpected instance ID %s\n", instanceID);
273 pSetupDiDestroyDeviceInfoList(set);
277 static void testRegisterDeviceInfo(void)
280 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
281 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
284 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
285 !pSetupDiRegisterDeviceInfo)
287 skip("No SetupDiRegisterDeviceInfo\n");
290 SetLastError(0xdeadbeef);
291 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
292 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
293 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
294 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
295 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
296 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
299 SP_DEVINFO_DATA devInfo = { 0 };
301 SetLastError(0xdeadbeef);
302 ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
303 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
304 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
305 SetLastError(0xdeadbeef);
306 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
307 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
308 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
309 devInfo.cbSize = sizeof(devInfo);
310 SetLastError(0xdeadbeef);
311 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
312 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
313 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
314 ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid,
315 NULL, NULL, 0, &devInfo);
316 ok(ret || GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
317 "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
320 /* If it already existed, registering it again will fail */
321 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL,
323 ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
325 /* FIXME: On Win2K+ systems, this is now persisted to registry in
326 * HKLM\System\CCS\Enum\USB\Bogus\0000. I don't check because the
327 * Win9x location is different.
328 * FIXME: the key also becomes undeletable. How to get rid of it?
330 pSetupDiDestroyDeviceInfoList(set);
336 init_function_pointers();
338 if (pSetupDiCreateDeviceInfoListExW && pSetupDiDestroyDeviceInfoList)
339 test_SetupDiCreateDeviceInfoListEx();
341 skip("SetupDiCreateDeviceInfoListExW and/or SetupDiDestroyDeviceInfoList not available\n");
343 if (pSetupDiOpenClassRegKeyExA)
344 test_SetupDiOpenClassRegKeyExA();
346 skip("SetupDiOpenClassRegKeyExA is not available\n");
347 testCreateDeviceInfo();
348 testGetDeviceInstanceId();
349 testRegisterDeviceInfo();