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 *pSetupDiGetDeviceInterfaceDetailW)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_W, DWORD, PDWORD, PSP_DEVINFO_DATA);
51 static BOOL (WINAPI *pSetupDiRegisterDeviceInfo)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PSP_DETSIG_CMPPROC, PVOID, PSP_DEVINFO_DATA);
53 static void init_function_pointers(void)
55 hSetupAPI = GetModuleHandleA("setupapi.dll");
57 pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA");
58 pSetupDiCreateDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoList");
59 pSetupDiCreateDeviceInfoListExW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoListExW");
60 pSetupDiCreateDeviceInterfaceA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInterfaceA");
61 pSetupDiDestroyDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiDestroyDeviceInfoList");
62 pSetupDiCallClassInstaller = (void *)GetProcAddress(hSetupAPI, "SetupDiCallClassInstaller");
63 pSetupDiEnumDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInfo");
64 pSetupDiEnumDeviceInterfaces = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInterfaces");
65 pSetupDiGetDeviceInstanceIdA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInstanceIdA");
66 pSetupDiGetDeviceInterfaceDetailA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailA");
67 pSetupDiGetDeviceInterfaceDetailW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailW");
68 pSetupDiInstallClassA = (void *)GetProcAddress(hSetupAPI, "SetupDiInstallClassA");
69 pSetupDiOpenClassRegKeyExA = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenClassRegKeyExA");
70 pSetupDiOpenDevRegKey = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenDevRegKey");
71 pSetupDiCreateDevRegKeyW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDevRegKeyW");
72 pSetupDiRegisterDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiRegisterDeviceInfo");
75 /* RegDeleteTreeW from dlls/advapi32/registry.c */
76 LSTATUS WINAPI devinst_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
79 DWORD dwMaxSubkeyLen, dwMaxValueLen;
80 DWORD dwMaxLen, dwSize;
81 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
86 ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
90 /* Get highest length for keys, values */
91 ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
92 &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
93 if (ret) goto cleanup;
97 dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
98 if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
100 /* Name too big: alloc a buffer for it */
101 if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
103 ret = ERROR_NOT_ENOUGH_MEMORY;
109 /* Recursively delete all the subkeys */
113 if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
114 NULL, NULL, NULL)) break;
116 ret = devinst_RegDeleteTreeW(hSubKey, lpszName);
117 if (ret) goto cleanup;
121 ret = RegDeleteKeyW(hKey, lpszSubKey);
126 if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
127 NULL, NULL, NULL, NULL)) break;
129 ret = RegDeleteValueW(hKey, lpszName);
130 if (ret) goto cleanup;
134 /* Free buffer if allocated */
135 if (lpszName != szNameBuf)
136 HeapFree( GetProcessHeap(), 0, lpszName);
138 RegCloseKey(hSubKey);
143 static void test_SetupDiCreateDeviceInfoListEx(void)
148 static CHAR notnull[] = "NotNull";
149 static const WCHAR machine[] = { 'd','u','m','m','y',0 };
151 SetLastError(0xdeadbeef);
152 /* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */
153 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, notnull);
155 error = GetLastError();
156 if (error == ERROR_CALL_NOT_IMPLEMENTED)
158 skip("SetupDiCreateDeviceInfoListExW is not implemented\n");
161 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
162 ok(error == ERROR_INVALID_PARAMETER, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_PARAMETER);
164 SetLastError(0xdeadbeef);
165 /* create empty DeviceInfoList, but set MachineName to something */
166 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL);
168 error = GetLastError();
169 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
170 ok(error == ERROR_INVALID_MACHINENAME, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_MACHINENAME);
172 /* create empty DeviceInfoList */
173 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
174 ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE);
176 /* destroy DeviceInfoList */
177 ret = pSetupDiDestroyDeviceInfoList(devlist);
178 ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error);
181 static void test_SetupDiOpenClassRegKeyExA(void)
183 /* This is a unique guid for testing purposes */
184 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
185 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
186 static const CHAR guidString[] = "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
189 /* Check return value for nonexistent key */
190 hkey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
191 DIOCR_INSTALLER, NULL, NULL);
192 ok(hkey == INVALID_HANDLE_VALUE,
193 "returned %p (expected INVALID_HANDLE_VALUE)\n", hkey);
195 /* Test it for a key that exists */
196 hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS);
197 if (hkey != INVALID_HANDLE_VALUE)
200 if (RegCreateKeyA(hkey, guidString, &classKey) == ERROR_SUCCESS)
202 RegCloseKey(classKey);
203 SetLastError(0xdeadbeef);
204 classKey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
205 DIOCR_INSTALLER, NULL, NULL);
206 ok(classKey != INVALID_HANDLE_VALUE,
207 "opening class registry key failed with error %d\n",
209 if (classKey != INVALID_HANDLE_VALUE)
210 RegCloseKey(classKey);
211 RegDeleteKeyA(hkey, guidString);
214 trace("failed to create registry key for test\n");
217 trace("failed to open classes key\n");
220 static void append_str(char **str, const char *data)
223 *str += strlen(*str);
226 static void create_inf_file(LPCSTR filename)
230 DWORD dwNumberOfBytesWritten;
231 HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
232 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
234 append_str(&ptr, "[Version]\n");
235 append_str(&ptr, "Signature=\"$Chicago$\"\n");
236 append_str(&ptr, "Class=Bogus\n");
237 append_str(&ptr, "ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n");
238 append_str(&ptr, "[ClassInstall32]\n");
239 append_str(&ptr, "AddReg=BogusClass.NT.AddReg\n");
240 append_str(&ptr, "[BogusClass.NT.AddReg]\n");
241 append_str(&ptr, "HKR,,,,\"Wine test devices\"\n");
243 WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
247 static void get_temp_filename(LPSTR path)
249 static char curr[MAX_PATH] = { 0 };
254 GetCurrentDirectoryA(MAX_PATH, curr);
255 GetTempFileNameA(curr, "set", 0, temp);
256 ptr = strrchr(temp, '\\');
258 lstrcpyA(path, ptr + 1);
261 static void testInstallClass(void)
263 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
264 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
265 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
266 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
267 '1','1','d','b','-','b','7','0','4','-',
268 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
269 char tmpfile[MAX_PATH];
272 if (!pSetupDiInstallClassA)
274 skip("No SetupDiInstallClassA\n");
279 get_temp_filename(tmpfile + 2);
280 create_inf_file(tmpfile + 2);
282 ret = pSetupDiInstallClassA(NULL, NULL, 0, NULL);
283 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
284 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
285 ret = pSetupDiInstallClassA(NULL, NULL, DI_NOVCP, NULL);
286 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
287 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
288 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, DI_NOVCP, NULL);
289 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
290 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
291 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, 0, NULL);
292 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
293 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
294 ret = pSetupDiInstallClassA(NULL, tmpfile, 0, NULL);
295 ok(ret, "SetupDiInstallClassA failed: %08x\n", GetLastError());
296 RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey);
300 static void testCreateDeviceInfo(void)
304 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
305 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
307 if (!pSetupDiCreateDeviceInfoList || !pSetupDiEnumDeviceInfo ||
308 !pSetupDiDestroyDeviceInfoList || !pSetupDiCreateDeviceInfoA)
310 skip("No SetupDiCreateDeviceInfoA\n");
313 SetLastError(0xdeadbeef);
314 ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
315 ok(!ret && GetLastError() == ERROR_INVALID_DEVINST_NAME,
316 "Expected ERROR_INVALID_DEVINST_NAME, got %08x\n", GetLastError());
317 SetLastError(0xdeadbeef);
318 ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL,
319 NULL, 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 SP_DEVINFO_DATA devInfo = { 0 };
330 SetLastError(0xdeadbeef);
331 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL,
332 NULL, NULL, 0, NULL);
333 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
334 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
335 /* Finally, with all three required parameters, this succeeds: */
336 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
337 NULL, NULL, 0, NULL);
338 ok(ret, "pSetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
339 /* This fails because the device ID already exists.. */
340 SetLastError(0xdeadbeef);
341 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
342 NULL, NULL, 0, &devInfo);
343 ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
344 "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError());
345 /* whereas this "fails" because cbSize is wrong.. */
346 SetLastError(0xdeadbeef);
347 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
348 DICD_GENERATE_ID, &devInfo);
349 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
350 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
351 devInfo.cbSize = sizeof(devInfo);
352 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
353 DICD_GENERATE_ID, &devInfo);
354 /* and this finally succeeds. */
355 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
356 /* There were three devices added, however - the second failure just
357 * resulted in the SP_DEVINFO_DATA not getting copied.
359 SetLastError(0xdeadbeef);
361 while (pSetupDiEnumDeviceInfo(set, i, &devInfo))
363 ok(i == 3, "Expected 3 devices, got %d\n", i);
364 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
365 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
366 pSetupDiDestroyDeviceInfoList(set);
370 static void testGetDeviceInstanceId(void)
374 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
375 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
376 SP_DEVINFO_DATA devInfo = { 0 };
378 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
379 !pSetupDiCreateDeviceInfoA || !pSetupDiGetDeviceInstanceIdA)
381 skip("No SetupDiGetDeviceInstanceIdA\n");
384 SetLastError(0xdeadbeef);
385 ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
386 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
387 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
388 SetLastError(0xdeadbeef);
389 ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, NULL, 0, NULL);
390 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
391 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
392 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
393 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
397 char instanceID[MAX_PATH];
400 SetLastError(0xdeadbeef);
401 ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
402 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
403 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
404 SetLastError(0xdeadbeef);
405 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL);
406 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
407 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
408 SetLastError(0xdeadbeef);
409 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
410 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
411 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
412 devInfo.cbSize = sizeof(devInfo);
413 SetLastError(0xdeadbeef);
414 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
415 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
416 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
417 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
418 NULL, NULL, 0, &devInfo);
419 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
420 SetLastError(0xdeadbeef);
421 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
422 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
423 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
424 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
425 sizeof(instanceID), NULL);
426 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
427 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"),
428 "Unexpected instance ID %s\n", instanceID);
429 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid,
430 NULL, NULL, DICD_GENERATE_ID, &devInfo);
431 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
432 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
433 sizeof(instanceID), NULL);
434 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
435 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"),
436 "Unexpected instance ID %s\n", instanceID);
437 pSetupDiDestroyDeviceInfoList(set);
441 static void testRegisterDeviceInfo(void)
444 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
445 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
448 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
449 !pSetupDiRegisterDeviceInfo)
451 skip("No SetupDiRegisterDeviceInfo\n");
454 SetLastError(0xdeadbeef);
455 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
456 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
457 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
458 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
459 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
460 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
463 SP_DEVINFO_DATA devInfo = { 0 };
465 SetLastError(0xdeadbeef);
466 ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
467 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
468 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
469 SetLastError(0xdeadbeef);
470 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
471 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
472 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
473 devInfo.cbSize = sizeof(devInfo);
474 SetLastError(0xdeadbeef);
475 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
476 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
477 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
478 ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid,
479 NULL, NULL, 0, &devInfo);
480 ok(ret || GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
481 "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
484 /* If it already existed, registering it again will fail */
485 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL,
487 ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
489 /* FIXME: On Win2K+ systems, this is now persisted to registry in
490 * HKLM\System\CCS\Enum\USB\Bogus\0000. I don't check because the
491 * Win9x location is different.
492 * FIXME: the key also becomes undeletable. How to get rid of it?
494 pSetupDiDestroyDeviceInfoList(set);
498 static void testCreateDeviceInterface(void)
501 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
502 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
505 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
506 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
507 !pSetupDiEnumDeviceInterfaces)
509 skip("No SetupDiCreateDeviceInterfaceA\n");
512 SetLastError(0xdeadbeef);
513 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL);
514 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
515 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
516 SetLastError(0xdeadbeef);
517 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL);
518 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
519 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
520 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
521 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
524 SP_DEVINFO_DATA devInfo = { 0 };
525 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
529 SetLastError(0xdeadbeef);
530 ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL);
531 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
532 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
533 SetLastError(0xdeadbeef);
534 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
536 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
537 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
538 devInfo.cbSize = sizeof(devInfo);
539 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
540 NULL, NULL, 0, &devInfo);
541 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
542 SetLastError(0xdeadbeef);
543 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
545 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
546 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
547 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
549 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
550 /* Creating the same interface a second time succeeds */
551 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
553 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
554 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0,
556 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
557 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0,
559 ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError());
561 while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i,
564 ok(i == 2, "expected 2 interfaces, got %d\n", i);
565 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
566 "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
567 pSetupDiDestroyDeviceInfoList(set);
571 static void testGetDeviceInterfaceDetail(void)
574 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
575 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
578 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
579 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
580 !pSetupDiGetDeviceInterfaceDetailA)
582 skip("No SetupDiGetDeviceInterfaceDetailA\n");
585 SetLastError(0xdeadbeef);
586 ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL);
587 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
588 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
589 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
590 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
593 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
594 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
598 SetLastError(0xdeadbeef);
599 ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL,
601 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
602 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
603 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
604 NULL, NULL, 0, &devInfo);
605 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
606 SetLastError(0xdeadbeef);
607 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
609 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
610 SetLastError(0xdeadbeef);
611 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
613 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
614 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
615 SetLastError(0xdeadbeef);
616 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
618 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
619 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
620 SetLastError(0xdeadbeef);
621 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
623 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
624 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
625 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
627 static const char path[] =
628 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
629 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
630 SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail =
631 (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf;
632 DWORD expectedsize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR)*(1 + strlen(path));
635 SetLastError(0xdeadbeef);
636 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
638 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
639 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
640 detail->cbSize = size;
641 SetLastError(0xdeadbeef);
642 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
644 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
645 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
646 detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
647 SetLastError(0xdeadbeef);
648 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
650 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
651 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
652 /* Windows 2000 and up check for the exact size. Win9x returns ERROR_INVALID_PARAMETER
653 * on every call (so doesn't get here) and NT4 doesn't have this function.
655 detail->cbSize = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
656 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
658 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n",
660 ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
662 /* Check SetupDiGetDeviceInterfaceDetailW */
663 if (pSetupDiGetDeviceInterfaceDetailW)
665 ret = pSetupDiGetDeviceInterfaceDetailW(set, &interfaceData, NULL, 0, &size, NULL);
666 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got error code: %d\n", GetLastError());
667 ok(expectedsize == size, "SetupDiGetDeviceInterfaceDetailW returned wrong reqsize: expected %d, got %d\n", expectedsize, size);
670 skip("SetupDiGetDeviceInterfaceDetailW is not available\n");
672 HeapFree(GetProcessHeap(), 0, buf);
674 pSetupDiDestroyDeviceInfoList(set);
678 static void testDevRegKey(void)
680 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
681 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
682 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
683 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
684 '1','1','d','b','-','b','7','0','4','-',
685 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
687 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
688 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
691 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
692 !pSetupDiCreateDeviceInfoA || !pSetupDiOpenDevRegKey ||
693 !pSetupDiRegisterDeviceInfo || !pSetupDiCreateDevRegKeyW ||
694 !pSetupDiCallClassInstaller)
696 skip("No SetupDiOpenDevRegKey\n");
699 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
700 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
703 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
704 HKEY key = INVALID_HANDLE_VALUE;
706 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
707 NULL, NULL, 0, &devInfo);
708 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
709 SetLastError(0xdeadbeef);
710 key = pSetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0);
711 ok(key == INVALID_HANDLE_VALUE &&
712 GetLastError() == ERROR_INVALID_HANDLE,
713 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
714 SetLastError(0xdeadbeef);
715 key = pSetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0);
716 ok(key == INVALID_HANDLE_VALUE &&
717 GetLastError() == ERROR_INVALID_PARAMETER,
718 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
719 SetLastError(0xdeadbeef);
720 key = pSetupDiOpenDevRegKey(set, &devInfo, 0, 0, 0, 0);
721 ok(key == INVALID_HANDLE_VALUE &&
722 GetLastError() == ERROR_INVALID_FLAGS,
723 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
724 SetLastError(0xdeadbeef);
725 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 0, 0);
726 ok(key == INVALID_HANDLE_VALUE &&
727 GetLastError() == ERROR_INVALID_FLAGS,
728 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
729 SetLastError(0xdeadbeef);
730 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
732 ok(key == INVALID_HANDLE_VALUE &&
733 GetLastError() == ERROR_INVALID_FLAGS,
734 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
735 SetLastError(0xdeadbeef);
736 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
738 ok(key == INVALID_HANDLE_VALUE &&
739 GetLastError() == ERROR_DEVINFO_NOT_REGISTERED,
740 "Expected ERROR_DEVINFO_NOT_REGISTERED, got %08x\n", GetLastError());
741 SetLastError(0xdeadbeef);
742 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
743 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
744 SetLastError(0xdeadbeef);
745 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
747 /* The software key isn't created by default */
749 ok(key == INVALID_HANDLE_VALUE &&
750 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
751 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
752 SetLastError(0xdeadbeef);
753 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
756 ok(key == INVALID_HANDLE_VALUE &&
757 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
758 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
759 SetLastError(0xdeadbeef);
760 key = pSetupDiCreateDevRegKeyW(set, &devInfo, DICS_FLAG_GLOBAL, 0,
761 DIREG_DRV, NULL, NULL);
762 ok(key != INVALID_HANDLE_VALUE, "SetupDiCreateDevRegKey failed: %08x\n",
765 SetLastError(0xdeadbeef);
766 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
769 ok(key == INVALID_HANDLE_VALUE &&
770 GetLastError() == ERROR_INVALID_DATA,
771 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
772 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
773 DIREG_DRV, KEY_READ);
774 ok(key != INVALID_HANDLE_VALUE, "SetupDiOpenDevRegKey failed: %08x\n",
776 ret = pSetupDiCallClassInstaller(DIF_REMOVE, set, &devInfo);
777 pSetupDiDestroyDeviceInfoList(set);
779 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
784 init_function_pointers();
786 if (pSetupDiCreateDeviceInfoListExW && pSetupDiDestroyDeviceInfoList)
787 test_SetupDiCreateDeviceInfoListEx();
789 skip("SetupDiCreateDeviceInfoListExW and/or SetupDiDestroyDeviceInfoList not available\n");
791 if (pSetupDiOpenClassRegKeyExA)
792 test_SetupDiOpenClassRegKeyExA();
794 skip("SetupDiOpenClassRegKeyExA is not available\n");
796 testCreateDeviceInfo();
797 testGetDeviceInstanceId();
798 testRegisterDeviceInfo();
799 testCreateDeviceInterface();
800 testGetDeviceInterfaceDetail();