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 *pSetupDiCreateDeviceInterfaceA)(HDEVINFO, PSP_DEVINFO_DATA, const GUID *, PCSTR, DWORD, PSP_DEVICE_INTERFACE_DATA);
39 static BOOL (WINAPI *pSetupDiCallClassInstaller)(DI_FUNCTION, HDEVINFO, PSP_DEVINFO_DATA);
40 static BOOL (WINAPI *pSetupDiDestroyDeviceInfoList)(HDEVINFO);
41 static BOOL (WINAPI *pSetupDiEnumDeviceInfo)(HDEVINFO, DWORD, PSP_DEVINFO_DATA);
42 static BOOL (WINAPI *pSetupDiEnumDeviceInterfaces)(HDEVINFO, PSP_DEVINFO_DATA, const GUID *, DWORD, PSP_DEVICE_INTERFACE_DATA);
43 static BOOL (WINAPI *pSetupDiInstallClassA)(HWND, PCSTR, DWORD, HSPFILEQ);
44 static HKEY (WINAPI *pSetupDiOpenClassRegKeyExA)(GUID*,REGSAM,DWORD,PCSTR,PVOID);
45 static HKEY (WINAPI *pSetupDiOpenDevRegKey)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM);
46 static HKEY (WINAPI *pSetupDiCreateDevRegKeyW)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, HINF, PCWSTR);
47 static BOOL (WINAPI *pSetupDiCreateDeviceInfoA)(HDEVINFO, PCSTR, GUID *, PCSTR, HWND, DWORD, PSP_DEVINFO_DATA);
48 static BOOL (WINAPI *pSetupDiGetDeviceInstanceIdA)(HDEVINFO, PSP_DEVINFO_DATA, PSTR, DWORD, PDWORD);
49 static BOOL (WINAPI *pSetupDiGetDeviceInterfaceDetailA)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA);
50 static BOOL (WINAPI *pSetupDiRegisterDeviceInfo)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PSP_DETSIG_CMPPROC, PVOID, PSP_DEVINFO_DATA);
52 static void init_function_pointers(void)
54 hSetupAPI = GetModuleHandleA("setupapi.dll");
56 pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA");
57 pSetupDiCreateDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoList");
58 pSetupDiCreateDeviceInfoListExW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoListExW");
59 pSetupDiCreateDeviceInterfaceA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInterfaceA");
60 pSetupDiDestroyDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiDestroyDeviceInfoList");
61 pSetupDiCallClassInstaller = (void *)GetProcAddress(hSetupAPI, "SetupDiCallClassInstaller");
62 pSetupDiEnumDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInfo");
63 pSetupDiEnumDeviceInterfaces = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInterfaces");
64 pSetupDiGetDeviceInstanceIdA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInstanceIdA");
65 pSetupDiGetDeviceInterfaceDetailA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailA");
66 pSetupDiInstallClassA = (void *)GetProcAddress(hSetupAPI, "SetupDiInstallClassA");
67 pSetupDiOpenClassRegKeyExA = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenClassRegKeyExA");
68 pSetupDiOpenDevRegKey = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenDevRegKey");
69 pSetupDiCreateDevRegKeyW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDevRegKeyW");
70 pSetupDiRegisterDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiRegisterDeviceInfo");
73 static void test_SetupDiCreateDeviceInfoListEx(void)
78 static CHAR notnull[] = "NotNull";
79 static const WCHAR machine[] = { 'd','u','m','m','y',0 };
81 SetLastError(0xdeadbeef);
82 /* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */
83 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, notnull);
85 error = GetLastError();
86 if (error == ERROR_CALL_NOT_IMPLEMENTED)
88 skip("SetupDiCreateDeviceInfoListExW is not implemented\n");
91 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
92 ok(error == ERROR_INVALID_PARAMETER, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_PARAMETER);
94 SetLastError(0xdeadbeef);
95 /* create empty DeviceInfoList, but set MachineName to something */
96 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL);
98 error = GetLastError();
99 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
100 ok(error == ERROR_INVALID_MACHINENAME, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_MACHINENAME);
102 /* create empty DeviceInfoList */
103 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
104 ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE);
106 /* destroy DeviceInfoList */
107 ret = pSetupDiDestroyDeviceInfoList(devlist);
108 ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error);
111 static void test_SetupDiOpenClassRegKeyExA(void)
113 /* This is a unique guid for testing purposes */
114 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
115 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
116 static const CHAR guidString[] = "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
119 /* Check return value for nonexistent key */
120 hkey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
121 DIOCR_INSTALLER, NULL, NULL);
122 ok(hkey == INVALID_HANDLE_VALUE,
123 "returned %p (expected INVALID_HANDLE_VALUE)\n", hkey);
125 /* Test it for a key that exists */
126 hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS);
127 if (hkey != INVALID_HANDLE_VALUE)
130 if (RegCreateKeyA(hkey, guidString, &classKey) == ERROR_SUCCESS)
132 RegCloseKey(classKey);
133 SetLastError(0xdeadbeef);
134 classKey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
135 DIOCR_INSTALLER, NULL, NULL);
136 ok(classKey != INVALID_HANDLE_VALUE,
137 "opening class registry key failed with error %d\n",
139 if (classKey != INVALID_HANDLE_VALUE)
140 RegCloseKey(classKey);
141 RegDeleteKeyA(hkey, guidString);
144 trace("failed to create registry key for test\n");
147 trace("failed to open classes key\n");
150 static void append_str(char **str, const char *data)
153 *str += strlen(*str);
156 static void create_inf_file(LPCSTR filename)
160 DWORD dwNumberOfBytesWritten;
161 HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
162 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
164 append_str(&ptr, "[Version]\n");
165 append_str(&ptr, "Signature=\"$Chicago$\"\n");
166 append_str(&ptr, "Class=Bogus\n");
167 append_str(&ptr, "ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n");
168 append_str(&ptr, "[ClassInstall32]\n");
169 append_str(&ptr, "AddReg=BogusClass.NT.AddReg\n");
170 append_str(&ptr, "[BogusClass.NT.AddReg]\n");
171 append_str(&ptr, "HKR,,,,\"Wine test devices\"\n");
173 WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
177 static void get_temp_filename(LPSTR path)
179 static char curr[MAX_PATH] = { 0 };
184 GetCurrentDirectoryA(MAX_PATH, curr);
185 GetTempFileNameA(curr, "set", 0, temp);
186 ptr = strrchr(temp, '\\');
188 lstrcpyA(path, ptr + 1);
191 static void testInstallClass(void)
193 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
194 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
195 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
196 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
197 '1','1','d','b','-','b','7','0','4','-',
198 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
199 char tmpfile[MAX_PATH];
202 if (!pSetupDiInstallClassA)
204 skip("No SetupDiInstallClassA\n");
209 get_temp_filename(tmpfile + 2);
210 create_inf_file(tmpfile + 2);
212 ret = pSetupDiInstallClassA(NULL, NULL, 0, NULL);
213 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
214 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
215 ret = pSetupDiInstallClassA(NULL, NULL, DI_NOVCP, NULL);
216 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
217 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
218 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, DI_NOVCP, NULL);
219 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
220 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
221 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, 0, NULL);
222 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
223 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
224 ret = pSetupDiInstallClassA(NULL, tmpfile, 0, NULL);
225 ok(ret, "SetupDiInstallClassA failed: %08x\n", GetLastError());
226 RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey);
230 static void testCreateDeviceInfo(void)
234 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
235 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
237 if (!pSetupDiCreateDeviceInfoList || !pSetupDiEnumDeviceInfo ||
238 !pSetupDiDestroyDeviceInfoList || !pSetupDiCreateDeviceInfoA)
240 skip("No SetupDiCreateDeviceInfoA\n");
243 SetLastError(0xdeadbeef);
244 ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
245 ok(!ret && GetLastError() == ERROR_INVALID_DEVINST_NAME,
246 "Expected ERROR_INVALID_DEVINST_NAME, got %08x\n", GetLastError());
247 SetLastError(0xdeadbeef);
248 ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL,
249 NULL, NULL, 0, NULL);
250 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
251 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
252 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
253 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
257 SP_DEVINFO_DATA devInfo = { 0 };
260 SetLastError(0xdeadbeef);
261 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL,
262 NULL, NULL, 0, NULL);
263 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
264 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
265 /* Finally, with all three required parameters, this succeeds: */
266 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
267 NULL, NULL, 0, NULL);
268 ok(ret, "pSetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
269 /* This fails because the device ID already exists.. */
270 SetLastError(0xdeadbeef);
271 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
272 NULL, NULL, 0, &devInfo);
273 ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
274 "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError());
275 /* whereas this "fails" because cbSize is wrong.. */
276 SetLastError(0xdeadbeef);
277 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
278 DICD_GENERATE_ID, &devInfo);
279 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
280 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
281 devInfo.cbSize = sizeof(devInfo);
282 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
283 DICD_GENERATE_ID, &devInfo);
284 /* and this finally succeeds. */
285 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
286 /* There were three devices added, however - the second failure just
287 * resulted in the SP_DEVINFO_DATA not getting copied.
289 SetLastError(0xdeadbeef);
291 while (pSetupDiEnumDeviceInfo(set, i, &devInfo))
293 ok(i == 3, "Expected 3 devices, got %d\n", i);
294 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
295 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
296 pSetupDiDestroyDeviceInfoList(set);
300 static void testGetDeviceInstanceId(void)
304 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
305 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
306 SP_DEVINFO_DATA devInfo = { 0 };
308 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
309 !pSetupDiCreateDeviceInfoA || !pSetupDiGetDeviceInstanceIdA)
311 skip("No SetupDiGetDeviceInstanceIdA\n");
314 SetLastError(0xdeadbeef);
315 ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
316 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
317 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
318 SetLastError(0xdeadbeef);
319 ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, NULL, 0, NULL);
320 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
321 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
322 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
323 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
327 char instanceID[MAX_PATH];
330 SetLastError(0xdeadbeef);
331 ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
332 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
333 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
334 SetLastError(0xdeadbeef);
335 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL);
336 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
337 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
338 SetLastError(0xdeadbeef);
339 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
340 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
341 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
342 devInfo.cbSize = sizeof(devInfo);
343 SetLastError(0xdeadbeef);
344 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
345 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
346 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
347 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
348 NULL, NULL, 0, &devInfo);
349 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
350 SetLastError(0xdeadbeef);
351 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
352 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
353 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
354 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
355 sizeof(instanceID), NULL);
356 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
357 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"),
358 "Unexpected instance ID %s\n", instanceID);
359 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid,
360 NULL, NULL, DICD_GENERATE_ID, &devInfo);
361 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
362 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
363 sizeof(instanceID), NULL);
364 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
365 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"),
366 "Unexpected instance ID %s\n", instanceID);
367 pSetupDiDestroyDeviceInfoList(set);
371 static void testRegisterDeviceInfo(void)
374 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
375 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
378 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
379 !pSetupDiRegisterDeviceInfo)
381 skip("No SetupDiRegisterDeviceInfo\n");
384 SetLastError(0xdeadbeef);
385 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
386 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
387 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
388 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
389 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
390 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
393 SP_DEVINFO_DATA devInfo = { 0 };
395 SetLastError(0xdeadbeef);
396 ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
397 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
398 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
399 SetLastError(0xdeadbeef);
400 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
401 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
402 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
403 devInfo.cbSize = sizeof(devInfo);
404 SetLastError(0xdeadbeef);
405 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
406 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
407 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
408 ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid,
409 NULL, NULL, 0, &devInfo);
410 ok(ret || GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
411 "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
414 /* If it already existed, registering it again will fail */
415 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL,
417 ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
419 /* FIXME: On Win2K+ systems, this is now persisted to registry in
420 * HKLM\System\CCS\Enum\USB\Bogus\0000. I don't check because the
421 * Win9x location is different.
422 * FIXME: the key also becomes undeletable. How to get rid of it?
424 pSetupDiDestroyDeviceInfoList(set);
428 static void testCreateDeviceInterface(void)
431 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
432 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
435 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
436 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
437 !pSetupDiEnumDeviceInterfaces)
439 skip("No SetupDiCreateDeviceInterfaceA\n");
442 SetLastError(0xdeadbeef);
443 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL);
444 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
445 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
446 SetLastError(0xdeadbeef);
447 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL);
448 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
449 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
450 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
451 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
454 SP_DEVINFO_DATA devInfo = { 0 };
455 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
459 SetLastError(0xdeadbeef);
460 ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL);
461 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
462 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
463 SetLastError(0xdeadbeef);
464 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
466 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
467 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
468 devInfo.cbSize = sizeof(devInfo);
469 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
470 NULL, NULL, 0, &devInfo);
471 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
472 SetLastError(0xdeadbeef);
473 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
475 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
476 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
477 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
479 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
480 /* Creating the same interface a second time succeeds */
481 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
483 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
484 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0,
486 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
487 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0,
489 ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError());
491 while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i,
494 ok(i == 2, "expected 2 interfaces, got %d\n", i);
495 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
496 "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
497 pSetupDiDestroyDeviceInfoList(set);
501 static void testGetDeviceInterfaceDetail(void)
504 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
505 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
508 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
509 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
510 !pSetupDiGetDeviceInterfaceDetailA)
512 skip("No SetupDiGetDeviceInterfaceDetailA\n");
515 SetLastError(0xdeadbeef);
516 ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL);
517 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
518 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
519 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
520 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
523 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
524 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
528 SetLastError(0xdeadbeef);
529 ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL,
531 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
532 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
533 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
534 NULL, NULL, 0, &devInfo);
535 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
536 SetLastError(0xdeadbeef);
537 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
539 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
540 SetLastError(0xdeadbeef);
541 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
543 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
544 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
545 SetLastError(0xdeadbeef);
546 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
548 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
549 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
550 SetLastError(0xdeadbeef);
551 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
553 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
554 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
555 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
557 static const char path[] =
558 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
559 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
560 SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail =
561 (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf;
564 SetLastError(0xdeadbeef);
565 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
567 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
568 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
569 detail->cbSize = size;
570 SetLastError(0xdeadbeef);
571 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
573 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
574 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
575 detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
576 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
578 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n",
580 ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
582 HeapFree(GetProcessHeap(), 0, buf);
584 pSetupDiDestroyDeviceInfoList(set);
588 static void testDevRegKey(void)
590 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
591 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
592 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
593 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
594 '1','1','d','b','-','b','7','0','4','-',
595 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
597 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
598 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
601 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
602 !pSetupDiCreateDeviceInfoA || !pSetupDiOpenDevRegKey ||
603 !pSetupDiRegisterDeviceInfo || !pSetupDiCreateDevRegKeyW ||
604 !pSetupDiCallClassInstaller)
606 skip("No SetupDiOpenDevRegKey\n");
609 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
610 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
613 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
614 HKEY key = INVALID_HANDLE_VALUE;
616 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
617 NULL, NULL, 0, &devInfo);
618 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
619 SetLastError(0xdeadbeef);
620 key = pSetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0);
621 ok(key == INVALID_HANDLE_VALUE &&
622 GetLastError() == ERROR_INVALID_HANDLE,
623 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
624 SetLastError(0xdeadbeef);
625 key = pSetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0);
626 ok(key == INVALID_HANDLE_VALUE &&
627 GetLastError() == ERROR_INVALID_PARAMETER,
628 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
629 SetLastError(0xdeadbeef);
630 key = pSetupDiOpenDevRegKey(set, &devInfo, 0, 0, 0, 0);
631 ok(key == INVALID_HANDLE_VALUE &&
632 GetLastError() == ERROR_INVALID_FLAGS,
633 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
634 SetLastError(0xdeadbeef);
635 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 0, 0);
636 ok(key == INVALID_HANDLE_VALUE &&
637 GetLastError() == ERROR_INVALID_FLAGS,
638 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
639 SetLastError(0xdeadbeef);
640 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
642 ok(key == INVALID_HANDLE_VALUE &&
643 GetLastError() == ERROR_INVALID_FLAGS,
644 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
645 SetLastError(0xdeadbeef);
646 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
648 ok(key == INVALID_HANDLE_VALUE &&
649 GetLastError() == ERROR_DEVINFO_NOT_REGISTERED,
650 "Expected ERROR_DEVINFO_NOT_REGISTERED, got %08x\n", GetLastError());
651 SetLastError(0xdeadbeef);
652 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
653 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
654 SetLastError(0xdeadbeef);
655 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
657 /* The software key isn't created by default */
659 ok(key == INVALID_HANDLE_VALUE &&
660 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
661 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
662 SetLastError(0xdeadbeef);
663 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
666 ok(key == INVALID_HANDLE_VALUE &&
667 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
668 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
669 SetLastError(0xdeadbeef);
670 key = pSetupDiCreateDevRegKeyW(set, &devInfo, DICS_FLAG_GLOBAL, 0,
671 DIREG_DRV, NULL, NULL);
672 ok(key != INVALID_HANDLE_VALUE, "SetupDiCreateDevRegKey failed: %08x\n",
675 SetLastError(0xdeadbeef);
676 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
679 ok(key == INVALID_HANDLE_VALUE &&
680 GetLastError() == ERROR_INVALID_DATA,
681 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
682 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
683 DIREG_DRV, KEY_READ);
684 ok(key != INVALID_HANDLE_VALUE, "SetupDiOpenDevRegKey failed: %08x\n",
686 ret = pSetupDiCallClassInstaller(DIF_REMOVE, set, &devInfo);
687 pSetupDiDestroyDeviceInfoList(set);
689 RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
694 init_function_pointers();
696 if (pSetupDiCreateDeviceInfoListExW && pSetupDiDestroyDeviceInfoList)
697 test_SetupDiCreateDeviceInfoListEx();
699 skip("SetupDiCreateDeviceInfoListExW and/or SetupDiDestroyDeviceInfoList not available\n");
701 if (pSetupDiOpenClassRegKeyExA)
702 test_SetupDiOpenClassRegKeyExA();
704 skip("SetupDiOpenClassRegKeyExA is not available\n");
706 testCreateDeviceInfo();
707 testGetDeviceInstanceId();
708 testRegisterDeviceInfo();
709 testCreateDeviceInterface();
710 testGetDeviceInterfaceDetail();