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);
52 static HDEVINFO (WINAPI *pSetupDiGetClassDevsA)(CONST GUID *, LPCSTR, HWND, DWORD);
54 static void init_function_pointers(void)
56 hSetupAPI = GetModuleHandleA("setupapi.dll");
58 pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA");
59 pSetupDiCreateDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoList");
60 pSetupDiCreateDeviceInfoListExW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoListExW");
61 pSetupDiCreateDeviceInterfaceA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInterfaceA");
62 pSetupDiDestroyDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiDestroyDeviceInfoList");
63 pSetupDiCallClassInstaller = (void *)GetProcAddress(hSetupAPI, "SetupDiCallClassInstaller");
64 pSetupDiEnumDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInfo");
65 pSetupDiEnumDeviceInterfaces = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInterfaces");
66 pSetupDiGetDeviceInstanceIdA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInstanceIdA");
67 pSetupDiGetDeviceInterfaceDetailA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailA");
68 pSetupDiGetDeviceInterfaceDetailW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailW");
69 pSetupDiInstallClassA = (void *)GetProcAddress(hSetupAPI, "SetupDiInstallClassA");
70 pSetupDiOpenClassRegKeyExA = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenClassRegKeyExA");
71 pSetupDiOpenDevRegKey = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenDevRegKey");
72 pSetupDiCreateDevRegKeyW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDevRegKeyW");
73 pSetupDiRegisterDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiRegisterDeviceInfo");
74 pSetupDiGetClassDevsA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsA");
77 /* RegDeleteTreeW from dlls/advapi32/registry.c */
78 LSTATUS WINAPI devinst_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
81 DWORD dwMaxSubkeyLen, dwMaxValueLen;
82 DWORD dwMaxLen, dwSize;
83 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
88 ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
92 /* Get highest length for keys, values */
93 ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
94 &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
95 if (ret) goto cleanup;
99 dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
100 if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
102 /* Name too big: alloc a buffer for it */
103 if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
105 ret = ERROR_NOT_ENOUGH_MEMORY;
111 /* Recursively delete all the subkeys */
115 if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
116 NULL, NULL, NULL)) break;
118 ret = devinst_RegDeleteTreeW(hSubKey, lpszName);
119 if (ret) goto cleanup;
123 ret = RegDeleteKeyW(hKey, lpszSubKey);
128 if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
129 NULL, NULL, NULL, NULL)) break;
131 ret = RegDeleteValueW(hKey, lpszName);
132 if (ret) goto cleanup;
136 /* Free buffer if allocated */
137 if (lpszName != szNameBuf)
138 HeapFree( GetProcessHeap(), 0, lpszName);
140 RegCloseKey(hSubKey);
145 static void test_SetupDiCreateDeviceInfoListEx(void)
150 static CHAR notnull[] = "NotNull";
151 static const WCHAR machine[] = { 'd','u','m','m','y',0 };
153 SetLastError(0xdeadbeef);
154 /* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */
155 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, notnull);
157 error = GetLastError();
158 if (error == ERROR_CALL_NOT_IMPLEMENTED)
160 skip("SetupDiCreateDeviceInfoListExW is not implemented\n");
163 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
164 ok(error == ERROR_INVALID_PARAMETER, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_PARAMETER);
166 SetLastError(0xdeadbeef);
167 /* create empty DeviceInfoList, but set MachineName to something */
168 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL);
170 error = GetLastError();
171 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
172 ok(error == ERROR_INVALID_MACHINENAME, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_MACHINENAME);
174 /* create empty DeviceInfoList */
175 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
176 ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE);
178 /* destroy DeviceInfoList */
179 ret = pSetupDiDestroyDeviceInfoList(devlist);
180 ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error);
183 static void test_SetupDiOpenClassRegKeyExA(void)
185 /* This is a unique guid for testing purposes */
186 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
187 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
188 static const CHAR guidString[] = "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
191 /* Check return value for nonexistent key */
192 hkey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
193 DIOCR_INSTALLER, NULL, NULL);
194 ok(hkey == INVALID_HANDLE_VALUE,
195 "returned %p (expected INVALID_HANDLE_VALUE)\n", hkey);
197 /* Test it for a key that exists */
198 hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS);
199 if (hkey != INVALID_HANDLE_VALUE)
202 if (RegCreateKeyA(hkey, guidString, &classKey) == ERROR_SUCCESS)
204 RegCloseKey(classKey);
205 SetLastError(0xdeadbeef);
206 classKey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
207 DIOCR_INSTALLER, NULL, NULL);
208 ok(classKey != INVALID_HANDLE_VALUE,
209 "opening class registry key failed with error %d\n",
211 if (classKey != INVALID_HANDLE_VALUE)
212 RegCloseKey(classKey);
213 RegDeleteKeyA(hkey, guidString);
216 trace("failed to create registry key for test\n");
219 trace("failed to open classes key\n");
222 static void append_str(char **str, const char *data)
225 *str += strlen(*str);
228 static void create_inf_file(LPCSTR filename)
232 DWORD dwNumberOfBytesWritten;
233 HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
234 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
236 append_str(&ptr, "[Version]\n");
237 append_str(&ptr, "Signature=\"$Chicago$\"\n");
238 append_str(&ptr, "Class=Bogus\n");
239 append_str(&ptr, "ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n");
240 append_str(&ptr, "[ClassInstall32]\n");
241 append_str(&ptr, "AddReg=BogusClass.NT.AddReg\n");
242 append_str(&ptr, "[BogusClass.NT.AddReg]\n");
243 append_str(&ptr, "HKR,,,,\"Wine test devices\"\n");
245 WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
249 static void get_temp_filename(LPSTR path)
251 static char curr[MAX_PATH] = { 0 };
256 GetCurrentDirectoryA(MAX_PATH, curr);
257 GetTempFileNameA(curr, "set", 0, temp);
258 ptr = strrchr(temp, '\\');
260 lstrcpyA(path, ptr + 1);
263 static void testInstallClass(void)
265 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
266 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
267 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
268 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
269 '1','1','d','b','-','b','7','0','4','-',
270 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
271 char tmpfile[MAX_PATH];
274 if (!pSetupDiInstallClassA)
276 skip("No SetupDiInstallClassA\n");
281 get_temp_filename(tmpfile + 2);
282 create_inf_file(tmpfile + 2);
284 ret = pSetupDiInstallClassA(NULL, NULL, 0, NULL);
285 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
286 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
287 ret = pSetupDiInstallClassA(NULL, NULL, DI_NOVCP, NULL);
288 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
289 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
290 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, DI_NOVCP, NULL);
291 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
292 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
293 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, 0, NULL);
294 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
295 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
296 ret = pSetupDiInstallClassA(NULL, tmpfile, 0, NULL);
297 ok(ret, "SetupDiInstallClassA failed: %08x\n", GetLastError());
298 RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey);
302 static void testCreateDeviceInfo(void)
306 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
307 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
309 if (!pSetupDiCreateDeviceInfoList || !pSetupDiEnumDeviceInfo ||
310 !pSetupDiDestroyDeviceInfoList || !pSetupDiCreateDeviceInfoA)
312 skip("No SetupDiCreateDeviceInfoA\n");
315 SetLastError(0xdeadbeef);
316 ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
317 ok(!ret && GetLastError() == ERROR_INVALID_DEVINST_NAME,
318 "Expected ERROR_INVALID_DEVINST_NAME, got %08x\n", GetLastError());
319 SetLastError(0xdeadbeef);
320 ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL,
321 NULL, NULL, 0, NULL);
322 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
323 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
324 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
325 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
329 SP_DEVINFO_DATA devInfo = { 0 };
332 SetLastError(0xdeadbeef);
333 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL,
334 NULL, NULL, 0, NULL);
335 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
336 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
337 /* Finally, with all three required parameters, this succeeds: */
338 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
339 NULL, NULL, 0, NULL);
340 ok(ret, "pSetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
341 /* This fails because the device ID already exists.. */
342 SetLastError(0xdeadbeef);
343 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
344 NULL, NULL, 0, &devInfo);
345 ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
346 "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError());
347 /* whereas this "fails" because cbSize is wrong.. */
348 SetLastError(0xdeadbeef);
349 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
350 DICD_GENERATE_ID, &devInfo);
351 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
352 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
353 devInfo.cbSize = sizeof(devInfo);
354 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
355 DICD_GENERATE_ID, &devInfo);
356 /* and this finally succeeds. */
357 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
358 /* There were three devices added, however - the second failure just
359 * resulted in the SP_DEVINFO_DATA not getting copied.
361 SetLastError(0xdeadbeef);
363 while (pSetupDiEnumDeviceInfo(set, i, &devInfo))
365 ok(i == 3, "Expected 3 devices, got %d\n", i);
366 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
367 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
368 pSetupDiDestroyDeviceInfoList(set);
372 static void testGetDeviceInstanceId(void)
376 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
377 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
378 SP_DEVINFO_DATA devInfo = { 0 };
380 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
381 !pSetupDiCreateDeviceInfoA || !pSetupDiGetDeviceInstanceIdA)
383 skip("No SetupDiGetDeviceInstanceIdA\n");
386 SetLastError(0xdeadbeef);
387 ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
388 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
389 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
390 SetLastError(0xdeadbeef);
391 ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, NULL, 0, NULL);
392 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
393 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
394 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
395 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
399 char instanceID[MAX_PATH];
402 SetLastError(0xdeadbeef);
403 ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
404 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
405 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
406 SetLastError(0xdeadbeef);
407 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL);
408 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
409 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
410 SetLastError(0xdeadbeef);
411 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
412 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
413 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
414 devInfo.cbSize = sizeof(devInfo);
415 SetLastError(0xdeadbeef);
416 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
417 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
418 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
419 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
420 NULL, NULL, 0, &devInfo);
421 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
422 SetLastError(0xdeadbeef);
423 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
424 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
425 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
426 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
427 sizeof(instanceID), NULL);
428 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
429 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"),
430 "Unexpected instance ID %s\n", instanceID);
431 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid,
432 NULL, NULL, DICD_GENERATE_ID, &devInfo);
433 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
434 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
435 sizeof(instanceID), NULL);
436 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
437 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"),
438 "Unexpected instance ID %s\n", instanceID);
439 pSetupDiDestroyDeviceInfoList(set);
443 static void testRegisterDeviceInfo(void)
446 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
447 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
450 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
451 !pSetupDiRegisterDeviceInfo)
453 skip("No SetupDiRegisterDeviceInfo\n");
456 SetLastError(0xdeadbeef);
457 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
458 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
459 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
460 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
461 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
462 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
465 SP_DEVINFO_DATA devInfo = { 0 };
467 SetLastError(0xdeadbeef);
468 ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
469 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
470 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
471 SetLastError(0xdeadbeef);
472 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
473 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
474 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
475 devInfo.cbSize = sizeof(devInfo);
476 SetLastError(0xdeadbeef);
477 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
478 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
479 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
480 ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid,
481 NULL, NULL, 0, &devInfo);
482 ok(ret || GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
483 "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
486 /* If it already existed, registering it again will fail */
487 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL,
489 ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
491 /* FIXME: On Win2K+ systems, this is now persisted to registry in
492 * HKLM\System\CCS\Enum\USB\Bogus\0000. I don't check because the
493 * Win9x location is different.
494 * FIXME: the key also becomes undeletable. How to get rid of it?
496 pSetupDiDestroyDeviceInfoList(set);
500 static void testCreateDeviceInterface(void)
503 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
504 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
507 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
508 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
509 !pSetupDiEnumDeviceInterfaces)
511 skip("No SetupDiCreateDeviceInterfaceA\n");
514 SetLastError(0xdeadbeef);
515 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL);
516 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
517 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
518 SetLastError(0xdeadbeef);
519 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL);
520 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
521 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
522 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
523 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
526 SP_DEVINFO_DATA devInfo = { 0 };
527 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
531 SetLastError(0xdeadbeef);
532 ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL);
533 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
534 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
535 SetLastError(0xdeadbeef);
536 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
538 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
539 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
540 devInfo.cbSize = sizeof(devInfo);
541 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
542 NULL, NULL, 0, &devInfo);
543 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
544 SetLastError(0xdeadbeef);
545 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
547 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
548 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
549 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
551 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
552 /* Creating the same interface a second time succeeds */
553 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
555 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
556 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0,
558 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
559 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0,
561 ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError());
563 while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i,
566 ok(i == 2, "expected 2 interfaces, got %d\n", i);
567 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
568 "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
569 pSetupDiDestroyDeviceInfoList(set);
573 static void testGetDeviceInterfaceDetail(void)
576 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
577 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
580 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
581 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
582 !pSetupDiGetDeviceInterfaceDetailA)
584 skip("No SetupDiGetDeviceInterfaceDetailA\n");
587 SetLastError(0xdeadbeef);
588 ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL);
589 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
590 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
591 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
592 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
595 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
596 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
600 SetLastError(0xdeadbeef);
601 ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL,
603 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
604 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
605 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
606 NULL, NULL, 0, &devInfo);
607 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
608 SetLastError(0xdeadbeef);
609 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
611 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
612 SetLastError(0xdeadbeef);
613 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
615 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
616 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
617 SetLastError(0xdeadbeef);
618 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
620 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
621 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
622 SetLastError(0xdeadbeef);
623 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
625 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
626 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
627 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
629 static const char path[] =
630 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
631 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
632 SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail =
633 (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf;
634 DWORD expectedsize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR)*(1 + strlen(path));
637 SetLastError(0xdeadbeef);
638 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
640 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
641 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
642 detail->cbSize = size;
643 SetLastError(0xdeadbeef);
644 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
646 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
647 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
648 detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
649 SetLastError(0xdeadbeef);
650 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
652 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
653 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
654 /* Windows 2000 and up check for the exact size. Win9x returns ERROR_INVALID_PARAMETER
655 * on every call (so doesn't get here) and NT4 doesn't have this function.
657 detail->cbSize = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
658 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
660 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n",
662 ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
664 /* Check SetupDiGetDeviceInterfaceDetailW */
665 if (pSetupDiGetDeviceInterfaceDetailW)
667 ret = pSetupDiGetDeviceInterfaceDetailW(set, &interfaceData, NULL, 0, &size, NULL);
668 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got error code: %d\n", GetLastError());
669 ok(expectedsize == size, "SetupDiGetDeviceInterfaceDetailW returned wrong reqsize: expected %d, got %d\n", expectedsize, size);
672 skip("SetupDiGetDeviceInterfaceDetailW is not available\n");
674 HeapFree(GetProcessHeap(), 0, buf);
676 pSetupDiDestroyDeviceInfoList(set);
680 static void testDevRegKey(void)
682 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
683 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
684 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
685 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
686 '1','1','d','b','-','b','7','0','4','-',
687 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
689 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
690 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
693 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
694 !pSetupDiCreateDeviceInfoA || !pSetupDiOpenDevRegKey ||
695 !pSetupDiRegisterDeviceInfo || !pSetupDiCreateDevRegKeyW ||
696 !pSetupDiCallClassInstaller)
698 skip("No SetupDiOpenDevRegKey\n");
701 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
702 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
705 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
706 HKEY key = INVALID_HANDLE_VALUE;
708 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
709 NULL, NULL, 0, &devInfo);
710 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
711 SetLastError(0xdeadbeef);
712 key = pSetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0);
713 ok(key == INVALID_HANDLE_VALUE &&
714 GetLastError() == ERROR_INVALID_HANDLE,
715 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
716 SetLastError(0xdeadbeef);
717 key = pSetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0);
718 ok(key == INVALID_HANDLE_VALUE &&
719 GetLastError() == ERROR_INVALID_PARAMETER,
720 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
721 SetLastError(0xdeadbeef);
722 key = pSetupDiOpenDevRegKey(set, &devInfo, 0, 0, 0, 0);
723 ok(key == INVALID_HANDLE_VALUE &&
724 GetLastError() == ERROR_INVALID_FLAGS,
725 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
726 SetLastError(0xdeadbeef);
727 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 0, 0);
728 ok(key == INVALID_HANDLE_VALUE &&
729 GetLastError() == ERROR_INVALID_FLAGS,
730 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
731 SetLastError(0xdeadbeef);
732 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
734 ok(key == INVALID_HANDLE_VALUE &&
735 GetLastError() == ERROR_INVALID_FLAGS,
736 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
737 SetLastError(0xdeadbeef);
738 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
740 ok(key == INVALID_HANDLE_VALUE &&
741 GetLastError() == ERROR_DEVINFO_NOT_REGISTERED,
742 "Expected ERROR_DEVINFO_NOT_REGISTERED, got %08x\n", GetLastError());
743 SetLastError(0xdeadbeef);
744 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
745 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
746 SetLastError(0xdeadbeef);
747 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
749 /* The software key isn't created by default */
751 ok(key == INVALID_HANDLE_VALUE &&
752 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
753 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
754 SetLastError(0xdeadbeef);
755 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
758 ok(key == INVALID_HANDLE_VALUE &&
759 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
760 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
761 SetLastError(0xdeadbeef);
762 key = pSetupDiCreateDevRegKeyW(set, &devInfo, DICS_FLAG_GLOBAL, 0,
763 DIREG_DRV, NULL, NULL);
764 ok(key != INVALID_HANDLE_VALUE, "SetupDiCreateDevRegKey failed: %08x\n",
767 SetLastError(0xdeadbeef);
768 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
771 ok(key == INVALID_HANDLE_VALUE &&
772 GetLastError() == ERROR_INVALID_DATA,
773 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
774 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
775 DIREG_DRV, KEY_READ);
776 ok(key != INVALID_HANDLE_VALUE, "SetupDiOpenDevRegKey failed: %08x\n",
778 ret = pSetupDiCallClassInstaller(DIF_REMOVE, set, &devInfo);
779 pSetupDiDestroyDeviceInfoList(set);
781 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
784 static void testRegisterAndGetDetail(void)
788 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
789 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
790 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
791 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), { 0 } };
794 SetLastError(0xdeadbeef);
795 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_ALLCLASSES);
796 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
799 SetLastError(0xdeadbeef);
800 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, 0,
801 DICD_GENERATE_ID, &devInfo);
802 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
803 SetLastError(0xdeadbeef);
804 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, &interfaceData);
805 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
806 SetLastError(0xdeadbeef);
807 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
808 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
810 pSetupDiDestroyDeviceInfoList(set);
812 SetLastError(0xdeadbeef);
813 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
814 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
817 SetLastError(0xdeadbeef);
818 ret = pSetupDiEnumDeviceInterfaces(set, NULL, &guid, 0, &interfaceData);
819 ok(ret, "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
820 SetLastError(0xdeadbeef);
821 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, 0, &dwSize, NULL);
822 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
823 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
824 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
826 static const char path[] =
827 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
828 PSP_DEVICE_INTERFACE_DETAIL_DATA_A detail = NULL;
830 detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)HeapAlloc(GetProcessHeap(), 0, dwSize);
833 detail->cbSize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char);
834 SetLastError(0xdeadbeef);
835 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData,
836 detail, dwSize, &dwSize, NULL);
837 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %08x\n", GetLastError());
838 ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
840 HeapFree(GetProcessHeap(), 0, detail);
844 pSetupDiDestroyDeviceInfoList(set);
849 init_function_pointers();
851 if (pSetupDiCreateDeviceInfoListExW && pSetupDiDestroyDeviceInfoList)
852 test_SetupDiCreateDeviceInfoListEx();
854 skip("SetupDiCreateDeviceInfoListExW and/or SetupDiDestroyDeviceInfoList not available\n");
856 if (pSetupDiOpenClassRegKeyExA)
857 test_SetupDiOpenClassRegKeyExA();
859 skip("SetupDiOpenClassRegKeyExA is not available\n");
861 testCreateDeviceInfo();
862 testGetDeviceInstanceId();
863 testRegisterDeviceInfo();
864 testCreateDeviceInterface();
865 testGetDeviceInterfaceDetail();
867 testRegisterAndGetDetail();