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 *pSetupDiCreateDeviceInfoW)(HDEVINFO, PCWSTR, GUID *, PCWSTR, HWND, DWORD, PSP_DEVINFO_DATA);
49 static BOOL (WINAPI *pSetupDiGetDeviceInstanceIdA)(HDEVINFO, PSP_DEVINFO_DATA, PSTR, DWORD, PDWORD);
50 static BOOL (WINAPI *pSetupDiGetDeviceInterfaceDetailA)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA);
51 static BOOL (WINAPI *pSetupDiGetDeviceInterfaceDetailW)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_W, DWORD, PDWORD, PSP_DEVINFO_DATA);
52 static BOOL (WINAPI *pSetupDiRegisterDeviceInfo)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PSP_DETSIG_CMPPROC, PVOID, PSP_DEVINFO_DATA);
53 static HDEVINFO (WINAPI *pSetupDiGetClassDevsA)(CONST GUID *, LPCSTR, HWND, DWORD);
54 static HDEVINFO (WINAPI *pSetupDiGetClassDevsW)(CONST GUID *, LPCWSTR, HWND, DWORD);
55 static BOOL (WINAPI *pSetupDiSetDeviceRegistryPropertyA)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, const BYTE *, DWORD);
56 static BOOL (WINAPI *pSetupDiSetDeviceRegistryPropertyW)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, const BYTE *, DWORD);
57 static BOOL (WINAPI *pSetupDiGetDeviceRegistryPropertyA)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD);
58 static BOOL (WINAPI *pSetupDiGetDeviceRegistryPropertyW)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD);
60 static void init_function_pointers(void)
62 hSetupAPI = GetModuleHandleA("setupapi.dll");
64 pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA");
65 pSetupDiCreateDeviceInfoW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoW");
66 pSetupDiCreateDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoList");
67 pSetupDiCreateDeviceInfoListExW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoListExW");
68 pSetupDiCreateDeviceInterfaceA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInterfaceA");
69 pSetupDiDestroyDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiDestroyDeviceInfoList");
70 pSetupDiCallClassInstaller = (void *)GetProcAddress(hSetupAPI, "SetupDiCallClassInstaller");
71 pSetupDiEnumDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInfo");
72 pSetupDiEnumDeviceInterfaces = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInterfaces");
73 pSetupDiGetDeviceInstanceIdA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInstanceIdA");
74 pSetupDiGetDeviceInterfaceDetailA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailA");
75 pSetupDiGetDeviceInterfaceDetailW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailW");
76 pSetupDiInstallClassA = (void *)GetProcAddress(hSetupAPI, "SetupDiInstallClassA");
77 pSetupDiOpenClassRegKeyExA = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenClassRegKeyExA");
78 pSetupDiOpenDevRegKey = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenDevRegKey");
79 pSetupDiCreateDevRegKeyW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDevRegKeyW");
80 pSetupDiRegisterDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiRegisterDeviceInfo");
81 pSetupDiGetClassDevsA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsA");
82 pSetupDiGetClassDevsW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsW");
83 pSetupDiSetDeviceRegistryPropertyA = (void *)GetProcAddress(hSetupAPI, "SetupDiSetDeviceRegistryPropertyA");
84 pSetupDiSetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiSetDeviceRegistryPropertyW");
85 pSetupDiGetDeviceRegistryPropertyA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyA");
86 pSetupDiGetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyW");
89 /* RegDeleteTreeW from dlls/advapi32/registry.c */
90 LSTATUS WINAPI devinst_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
93 DWORD dwMaxSubkeyLen, dwMaxValueLen;
94 DWORD dwMaxLen, dwSize;
95 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
100 ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
104 /* Get highest length for keys, values */
105 ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
106 &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
107 if (ret) goto cleanup;
111 dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
112 if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
114 /* Name too big: alloc a buffer for it */
115 if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
117 ret = ERROR_NOT_ENOUGH_MEMORY;
123 /* Recursively delete all the subkeys */
127 if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
128 NULL, NULL, NULL)) break;
130 ret = devinst_RegDeleteTreeW(hSubKey, lpszName);
131 if (ret) goto cleanup;
135 ret = RegDeleteKeyW(hKey, lpszSubKey);
140 if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
141 NULL, NULL, NULL, NULL)) break;
143 ret = RegDeleteValueW(hKey, lpszName);
144 if (ret) goto cleanup;
148 /* Free buffer if allocated */
149 if (lpszName != szNameBuf)
150 HeapFree( GetProcessHeap(), 0, lpszName);
152 RegCloseKey(hSubKey);
157 static void test_SetupDiCreateDeviceInfoListEx(void)
162 static CHAR notnull[] = "NotNull";
163 static const WCHAR machine[] = { 'd','u','m','m','y',0 };
165 SetLastError(0xdeadbeef);
166 /* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */
167 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, notnull);
169 error = GetLastError();
170 if (error == ERROR_CALL_NOT_IMPLEMENTED)
172 skip("SetupDiCreateDeviceInfoListExW is not implemented\n");
175 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
176 ok(error == ERROR_INVALID_PARAMETER, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_PARAMETER);
178 SetLastError(0xdeadbeef);
179 /* create empty DeviceInfoList, but set MachineName to something */
180 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL);
182 error = GetLastError();
183 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
184 ok(error == ERROR_INVALID_MACHINENAME, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_MACHINENAME);
186 /* create empty DeviceInfoList */
187 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
188 ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE);
190 /* destroy DeviceInfoList */
191 ret = pSetupDiDestroyDeviceInfoList(devlist);
192 ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error);
195 static void test_SetupDiOpenClassRegKeyExA(void)
197 /* This is a unique guid for testing purposes */
198 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
199 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
200 static const CHAR guidString[] = "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
203 /* Check return value for nonexistent key */
204 hkey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
205 DIOCR_INSTALLER, NULL, NULL);
206 ok(hkey == INVALID_HANDLE_VALUE,
207 "returned %p (expected INVALID_HANDLE_VALUE)\n", hkey);
209 /* Test it for a key that exists */
210 hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS);
211 if (hkey != INVALID_HANDLE_VALUE)
214 if (RegCreateKeyA(hkey, guidString, &classKey) == ERROR_SUCCESS)
216 RegCloseKey(classKey);
217 SetLastError(0xdeadbeef);
218 classKey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
219 DIOCR_INSTALLER, NULL, NULL);
220 ok(classKey != INVALID_HANDLE_VALUE,
221 "opening class registry key failed with error %d\n",
223 if (classKey != INVALID_HANDLE_VALUE)
224 RegCloseKey(classKey);
225 RegDeleteKeyA(hkey, guidString);
228 trace("failed to create registry key for test\n");
231 trace("failed to open classes key\n");
234 static void append_str(char **str, const char *data)
237 *str += strlen(*str);
240 static void create_inf_file(LPCSTR filename)
244 DWORD dwNumberOfBytesWritten;
245 HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
246 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
248 append_str(&ptr, "[Version]\n");
249 append_str(&ptr, "Signature=\"$Chicago$\"\n");
250 append_str(&ptr, "Class=Bogus\n");
251 append_str(&ptr, "ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n");
252 append_str(&ptr, "[ClassInstall32]\n");
253 append_str(&ptr, "AddReg=BogusClass.NT.AddReg\n");
254 append_str(&ptr, "[BogusClass.NT.AddReg]\n");
255 append_str(&ptr, "HKR,,,,\"Wine test devices\"\n");
257 WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
261 static void get_temp_filename(LPSTR path)
263 static char curr[MAX_PATH] = { 0 };
268 GetCurrentDirectoryA(MAX_PATH, curr);
269 GetTempFileNameA(curr, "set", 0, temp);
270 ptr = strrchr(temp, '\\');
272 lstrcpyA(path, ptr + 1);
275 static void testInstallClass(void)
277 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
278 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
279 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
280 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
281 '1','1','d','b','-','b','7','0','4','-',
282 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
283 static const CHAR classKey_win9x[] =
284 "System\\CurrentControlSet\\Services\\Class\\"
285 "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
286 static const CHAR bogus_win9x[] =
287 "System\\CurrentControlSet\\Services\\Class\\Bogus";
288 char tmpfile[MAX_PATH];
292 if (!pSetupDiInstallClassA)
294 skip("No SetupDiInstallClassA\n");
299 get_temp_filename(tmpfile + 2);
300 create_inf_file(tmpfile + 2);
302 ret = pSetupDiInstallClassA(NULL, NULL, 0, NULL);
303 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
304 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
305 ret = pSetupDiInstallClassA(NULL, NULL, DI_NOVCP, NULL);
306 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
307 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
308 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, DI_NOVCP, NULL);
309 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
310 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
311 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, 0, NULL);
312 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
313 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
314 /* The next call will succeed. Information is put into the registry but the
315 * location(s) is/are depending on the Windows version.
317 ret = pSetupDiInstallClassA(NULL, tmpfile, 0, NULL);
318 ok(ret, "SetupDiInstallClassA failed: %08x\n", GetLastError());
319 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, classKey_win9x, &hkey))
321 /* We are on win9x */
323 ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, classKey_win9x),
324 "Couldn't delete win9x classkey\n");
325 ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, bogus_win9x),
326 "Couldn't delete win9x bogus services class\n");
331 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey),
332 "Couldn't delete NT classkey\n");
337 static void testCreateDeviceInfo(void)
341 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
342 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
344 if (!pSetupDiCreateDeviceInfoList || !pSetupDiEnumDeviceInfo ||
345 !pSetupDiDestroyDeviceInfoList || !pSetupDiCreateDeviceInfoA)
347 skip("No SetupDiCreateDeviceInfoA\n");
350 SetLastError(0xdeadbeef);
351 ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
352 ok(!ret, "Expected failure\n");
353 ok(GetLastError() == ERROR_INVALID_DEVINST_NAME ||
354 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */ ||
355 GetLastError() == ERROR_INVALID_HANDLE /* Win9x */,
356 "Unexpected last error, got %08x\n", GetLastError());
358 /* If we are running on win9x we should skip these tests. Win95
359 * fails most tests anyway and win98 pops up the "Add New Hardware
362 if (GetLastError() == ERROR_INVALID_HANDLE)
364 skip("We are on win9x where the tests introduce issues\n");
368 SetLastError(0xdeadbeef);
369 ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL,
370 NULL, NULL, 0, NULL);
371 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
372 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
373 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
374 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
378 SP_DEVINFO_DATA devInfo = { 0 };
381 SetLastError(0xdeadbeef);
382 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL,
383 NULL, NULL, 0, NULL);
384 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
385 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
386 /* Finally, with all three required parameters, this succeeds: */
387 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
388 NULL, NULL, 0, NULL);
389 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
390 /* This fails because the device ID already exists.. */
391 SetLastError(0xdeadbeef);
392 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
393 NULL, NULL, 0, &devInfo);
394 ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
395 "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError());
396 /* whereas this "fails" because cbSize is wrong.. */
397 SetLastError(0xdeadbeef);
398 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
399 DICD_GENERATE_ID, &devInfo);
400 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
401 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
402 devInfo.cbSize = sizeof(devInfo);
403 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
404 DICD_GENERATE_ID, &devInfo);
405 /* and this finally succeeds. */
406 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
407 /* There were three devices added, however - the second failure just
408 * resulted in the SP_DEVINFO_DATA not getting copied.
410 SetLastError(0xdeadbeef);
412 while (pSetupDiEnumDeviceInfo(set, i, &devInfo))
414 ok(i == 3, "Expected 3 devices, got %d\n", i);
415 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
416 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
417 pSetupDiDestroyDeviceInfoList(set);
421 static void testGetDeviceInstanceId(void)
425 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
426 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
427 SP_DEVINFO_DATA devInfo = { 0 };
429 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
430 !pSetupDiCreateDeviceInfoA || !pSetupDiGetDeviceInstanceIdA)
432 skip("No SetupDiGetDeviceInstanceIdA\n");
435 SetLastError(0xdeadbeef);
436 ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
437 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
438 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
439 SetLastError(0xdeadbeef);
440 ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, NULL, 0, NULL);
441 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
442 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
443 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
444 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
448 char instanceID[MAX_PATH];
451 SetLastError(0xdeadbeef);
452 ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
453 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
454 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
455 SetLastError(0xdeadbeef);
456 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL);
457 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
458 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
459 SetLastError(0xdeadbeef);
460 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
461 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
462 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
463 devInfo.cbSize = sizeof(devInfo);
464 SetLastError(0xdeadbeef);
465 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
466 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
467 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
468 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
469 NULL, NULL, 0, &devInfo);
470 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
471 SetLastError(0xdeadbeef);
472 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
473 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
474 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
475 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
476 sizeof(instanceID), NULL);
477 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
478 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"),
479 "Unexpected instance ID %s\n", instanceID);
480 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid,
481 NULL, NULL, DICD_GENERATE_ID, &devInfo);
482 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
483 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
484 sizeof(instanceID), NULL);
485 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
486 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"),
487 "Unexpected instance ID %s\n", instanceID);
488 pSetupDiDestroyDeviceInfoList(set);
492 static void testRegisterDeviceInfo(void)
495 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
496 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
499 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
500 !pSetupDiRegisterDeviceInfo)
502 skip("No SetupDiRegisterDeviceInfo\n");
505 SetLastError(0xdeadbeef);
506 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
507 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
508 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
509 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
510 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
513 SP_DEVINFO_DATA devInfo = { 0 };
515 SetLastError(0xdeadbeef);
516 ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
517 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
518 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
519 SetLastError(0xdeadbeef);
520 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
521 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
522 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
523 devInfo.cbSize = sizeof(devInfo);
524 SetLastError(0xdeadbeef);
525 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
526 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
527 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
528 ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid,
529 NULL, NULL, 0, &devInfo);
530 ok(ret || GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
531 "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
534 /* If it already existed, registering it again will fail */
535 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL,
537 ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
539 /* FIXME: On Win2K+ systems, this is now persisted to registry in
540 * HKLM\System\CCS\Enum\USB\Bogus\0000. I don't check because the
541 * Win9x location is different.
542 * FIXME: the key also becomes undeletable. How to get rid of it?
544 pSetupDiDestroyDeviceInfoList(set);
548 static void testCreateDeviceInterface(void)
551 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
552 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
555 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
556 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
557 !pSetupDiEnumDeviceInterfaces)
559 skip("No SetupDiCreateDeviceInterfaceA\n");
562 SetLastError(0xdeadbeef);
563 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL);
564 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
565 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
566 SetLastError(0xdeadbeef);
567 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL);
568 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
569 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
570 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
571 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
574 SP_DEVINFO_DATA devInfo = { 0 };
575 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
579 SetLastError(0xdeadbeef);
580 ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL);
581 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
582 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
583 SetLastError(0xdeadbeef);
584 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
586 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
587 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
588 devInfo.cbSize = sizeof(devInfo);
589 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
590 NULL, NULL, 0, &devInfo);
591 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
592 SetLastError(0xdeadbeef);
593 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
595 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
596 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
597 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
599 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
600 /* Creating the same interface a second time succeeds */
601 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
603 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
604 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0,
606 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
607 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0,
609 ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError());
611 while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i,
614 ok(i == 2, "expected 2 interfaces, got %d\n", i);
615 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
616 "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
617 pSetupDiDestroyDeviceInfoList(set);
621 static void testGetDeviceInterfaceDetail(void)
624 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
625 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
628 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
629 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
630 !pSetupDiGetDeviceInterfaceDetailA)
632 skip("No SetupDiGetDeviceInterfaceDetailA\n");
635 SetLastError(0xdeadbeef);
636 ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL);
637 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
638 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
639 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
640 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
643 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
644 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
648 SetLastError(0xdeadbeef);
649 ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL,
651 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
652 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
653 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
654 NULL, NULL, 0, &devInfo);
655 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
656 SetLastError(0xdeadbeef);
657 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
659 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
660 SetLastError(0xdeadbeef);
661 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
663 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
664 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
665 SetLastError(0xdeadbeef);
666 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
668 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
669 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
670 SetLastError(0xdeadbeef);
671 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
673 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
674 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
675 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
677 static const char path[] =
678 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
679 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
680 SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail =
681 (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf;
682 DWORD expectedsize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR)*(1 + strlen(path));
685 SetLastError(0xdeadbeef);
686 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
688 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
689 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
690 detail->cbSize = size;
691 SetLastError(0xdeadbeef);
692 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
694 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
695 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
696 detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
697 SetLastError(0xdeadbeef);
698 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
700 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
701 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
702 /* Windows 2000 and up check for the exact size. Win9x returns ERROR_INVALID_PARAMETER
703 * on every call (so doesn't get here) and NT4 doesn't have this function.
705 detail->cbSize = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
706 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
708 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n",
710 ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
712 /* Check SetupDiGetDeviceInterfaceDetailW */
713 if (pSetupDiGetDeviceInterfaceDetailW)
715 ret = pSetupDiGetDeviceInterfaceDetailW(set, &interfaceData, NULL, 0, &size, NULL);
716 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got error code: %d\n", GetLastError());
717 ok(expectedsize == size, "SetupDiGetDeviceInterfaceDetailW returned wrong reqsize: expected %d, got %d\n", expectedsize, size);
720 skip("SetupDiGetDeviceInterfaceDetailW is not available\n");
722 HeapFree(GetProcessHeap(), 0, buf);
724 pSetupDiDestroyDeviceInfoList(set);
728 static void testDevRegKey(void)
730 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
731 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
732 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
733 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
734 '1','1','d','b','-','b','7','0','4','-',
735 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
737 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
738 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
741 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
742 !pSetupDiCreateDeviceInfoA || !pSetupDiOpenDevRegKey ||
743 !pSetupDiRegisterDeviceInfo || !pSetupDiCreateDevRegKeyW ||
744 !pSetupDiCallClassInstaller)
746 skip("No SetupDiOpenDevRegKey\n");
749 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
750 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
753 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
754 HKEY key = INVALID_HANDLE_VALUE;
756 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
757 NULL, NULL, 0, &devInfo);
758 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
759 SetLastError(0xdeadbeef);
760 key = pSetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0);
761 ok(key == INVALID_HANDLE_VALUE &&
762 GetLastError() == ERROR_INVALID_HANDLE,
763 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
764 SetLastError(0xdeadbeef);
765 key = pSetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0);
766 ok(key == INVALID_HANDLE_VALUE &&
767 GetLastError() == ERROR_INVALID_PARAMETER,
768 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
769 SetLastError(0xdeadbeef);
770 key = pSetupDiOpenDevRegKey(set, &devInfo, 0, 0, 0, 0);
771 ok(key == INVALID_HANDLE_VALUE &&
772 GetLastError() == ERROR_INVALID_FLAGS,
773 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
774 SetLastError(0xdeadbeef);
775 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 0, 0);
776 ok(key == INVALID_HANDLE_VALUE &&
777 GetLastError() == ERROR_INVALID_FLAGS,
778 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
779 SetLastError(0xdeadbeef);
780 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
782 ok(key == INVALID_HANDLE_VALUE &&
783 GetLastError() == ERROR_INVALID_FLAGS,
784 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
785 SetLastError(0xdeadbeef);
786 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
788 ok(key == INVALID_HANDLE_VALUE &&
789 GetLastError() == ERROR_DEVINFO_NOT_REGISTERED,
790 "Expected ERROR_DEVINFO_NOT_REGISTERED, got %08x\n", GetLastError());
791 SetLastError(0xdeadbeef);
792 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
793 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
794 SetLastError(0xdeadbeef);
795 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
797 /* The software key isn't created by default */
799 ok(key == INVALID_HANDLE_VALUE &&
800 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
801 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
802 SetLastError(0xdeadbeef);
803 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
806 ok(key == INVALID_HANDLE_VALUE &&
807 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
808 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
809 SetLastError(0xdeadbeef);
810 key = pSetupDiCreateDevRegKeyW(set, &devInfo, DICS_FLAG_GLOBAL, 0,
811 DIREG_DRV, NULL, NULL);
812 ok(key != INVALID_HANDLE_VALUE, "SetupDiCreateDevRegKey failed: %08x\n",
815 SetLastError(0xdeadbeef);
816 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
819 ok(key == INVALID_HANDLE_VALUE &&
820 (GetLastError() == ERROR_INVALID_DATA ||
821 GetLastError() == ERROR_ACCESS_DENIED), /* win2k3 */
822 "Expected ERROR_INVALID_DATA or ERROR_ACCESS_DENIED, got %08x\n", GetLastError());
823 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
824 DIREG_DRV, KEY_READ);
825 ok(key != INVALID_HANDLE_VALUE, "SetupDiOpenDevRegKey failed: %08x\n",
827 ret = pSetupDiCallClassInstaller(DIF_REMOVE, set, &devInfo);
828 pSetupDiDestroyDeviceInfoList(set);
830 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
833 static void testRegisterAndGetDetail(void)
837 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
838 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
839 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
840 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), { 0 } };
843 SetLastError(0xdeadbeef);
844 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_ALLCLASSES);
845 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
848 SetLastError(0xdeadbeef);
849 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, 0,
850 DICD_GENERATE_ID, &devInfo);
851 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
852 SetLastError(0xdeadbeef);
853 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, &interfaceData);
854 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
855 SetLastError(0xdeadbeef);
856 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
857 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
859 pSetupDiDestroyDeviceInfoList(set);
861 SetLastError(0xdeadbeef);
862 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
863 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
866 SetLastError(0xdeadbeef);
867 ret = pSetupDiEnumDeviceInterfaces(set, NULL, &guid, 0, &interfaceData);
868 ok(ret, "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
869 SetLastError(0xdeadbeef);
870 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, 0, &dwSize, NULL);
871 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
872 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
873 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
875 static const char path[] =
876 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
877 PSP_DEVICE_INTERFACE_DETAIL_DATA_A detail = NULL;
879 detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)HeapAlloc(GetProcessHeap(), 0, dwSize);
882 detail->cbSize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char);
883 SetLastError(0xdeadbeef);
884 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData,
885 detail, dwSize, &dwSize, NULL);
886 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %08x\n", GetLastError());
887 ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
889 HeapFree(GetProcessHeap(), 0, detail);
893 pSetupDiDestroyDeviceInfoList(set);
896 static void testDeviceRegistryPropertyA()
899 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
900 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
901 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
902 CHAR devName[] = "LEGACY_BOGUS";
903 CHAR friendlyName[] = "Bogus";
910 SetLastError(0xdeadbeef);
911 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
912 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
914 SetLastError(0xdeadbeef);
915 ret = pSetupDiCreateDeviceInfoA(set, devName, &guid, NULL, NULL,
916 DICD_GENERATE_ID, &devInfo);
917 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
918 SetLastError(0xdeadbeef);
919 ret = pSetupDiSetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, 0);
920 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
921 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
922 SetLastError(0xdeadbeef);
923 ret = pSetupDiSetDeviceRegistryPropertyA(set, NULL, -1, NULL, 0);
924 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
925 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
926 SetLastError(0xdeadbeef);
927 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, 0);
929 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
930 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
931 /* GetLastError() returns nonsense in win2k3 */
932 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
935 ok(!ret, "Expected failure, got %d\n", ret);
936 SetLastError(0xdeadbeef);
937 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
938 (PBYTE)friendlyName, buflen);
939 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
940 SetLastError(0xdeadbeef);
941 ret = pSetupDiGetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, NULL, 0, NULL);
942 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
943 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
944 SetLastError(0xdeadbeef);
945 ret = pSetupDiGetDeviceRegistryPropertyA(set, NULL, -1, NULL, NULL, 0, NULL);
946 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
947 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
948 SetLastError(0xdeadbeef);
949 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, NULL, 0, NULL);
951 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
952 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
953 /* GetLastError() returns nonsense in win2k3 */
954 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
955 NULL, NULL, buflen, NULL);
956 ok(!ret, "Expected failure, got %d\n", ret);
957 SetLastError(0xdeadbeef);
958 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
959 NULL, NULL, 0, &size);
960 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
961 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
962 ok(buflen == size, "Unexpected size: %d\n", size);
963 SetLastError(0xdeadbeef);
964 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
965 NULL, (PBYTE)buf, buflen, NULL);
966 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
967 ok(!lstrcmpiA(friendlyName, buf), "Unexpected property\n");
968 SetLastError(0xdeadbeef);
969 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
970 ®Type, (PBYTE)buf, buflen, NULL);
971 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
972 ok(!lstrcmpiA(friendlyName, buf), "Unexpected value of property\n");
973 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
974 SetLastError(0xdeadbeef);
975 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
977 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
978 SetLastError(0xdeadbeef);
979 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
980 NULL, (PBYTE)buf, buflen, &size);
982 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
983 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
984 pSetupDiDestroyDeviceInfoList(set);
987 static void testDeviceRegistryPropertyW()
990 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
991 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
992 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
993 WCHAR devName[] = {'L','E','G','A','C','Y','_','B','O','G','U','S',0};
994 WCHAR friendlyName[] = {'B','o','g','u','s',0};
996 DWORD buflen = 6 * sizeof(WCHAR);
1001 SetLastError(0xdeadbeef);
1002 set = pSetupDiGetClassDevsW(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1003 if (set == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1005 skip("W-functions are not implemented\n");
1008 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsW failed: %08x\n",
1010 SetLastError(0xdeadbeef);
1011 ret = pSetupDiCreateDeviceInfoW(set, devName, &guid, NULL, NULL,
1012 DICD_GENERATE_ID, &devInfo);
1013 ok(ret, "SetupDiCreateDeviceInfoW failed: %08x\n", GetLastError());
1014 SetLastError(0xdeadbeef);
1015 ret = pSetupDiSetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, 0);
1016 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1017 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1018 SetLastError(0xdeadbeef);
1019 ret = pSetupDiSetDeviceRegistryPropertyW(set, NULL, -1, NULL, 0);
1020 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1021 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1022 SetLastError(0xdeadbeef);
1023 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, 0);
1025 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1026 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1027 /* GetLastError() returns nonsense in win2k3 */
1028 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1031 ok(!ret, "Expected failure, got %d\n", ret);
1032 SetLastError(0xdeadbeef);
1033 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1034 (PBYTE)friendlyName, buflen);
1035 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1036 SetLastError(0xdeadbeef);
1037 ret = pSetupDiGetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, NULL, 0, NULL);
1038 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1039 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1040 SetLastError(0xdeadbeef);
1041 ret = pSetupDiGetDeviceRegistryPropertyW(set, NULL, -1, NULL, NULL, 0, NULL);
1042 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1043 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1044 SetLastError(0xdeadbeef);
1045 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, NULL, 0, NULL);
1047 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1048 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1049 /* GetLastError() returns nonsense in win2k3 */
1050 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1051 NULL, NULL, buflen, NULL);
1052 ok(!ret, "Expected failure, got %d\n", ret);
1053 SetLastError(0xdeadbeef);
1054 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1055 NULL, NULL, 0, &size);
1056 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1057 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1058 ok(buflen == size, "Unexpected size: %d\n", size);
1059 SetLastError(0xdeadbeef);
1060 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1061 NULL, (PBYTE)buf, buflen, NULL);
1062 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1063 ok(!lstrcmpiW(friendlyName, buf), "Unexpected property\n");
1064 SetLastError(0xdeadbeef);
1065 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1066 ®Type, (PBYTE)buf, buflen, NULL);
1067 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1068 ok(!lstrcmpiW(friendlyName, buf), "Unexpected value of property\n");
1069 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
1070 SetLastError(0xdeadbeef);
1071 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1073 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1074 SetLastError(0xdeadbeef);
1075 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1076 NULL, (PBYTE)buf, buflen, &size);
1078 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1079 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
1080 pSetupDiDestroyDeviceInfoList(set);
1085 init_function_pointers();
1087 if (pSetupDiCreateDeviceInfoListExW && pSetupDiDestroyDeviceInfoList)
1088 test_SetupDiCreateDeviceInfoListEx();
1090 skip("SetupDiCreateDeviceInfoListExW and/or SetupDiDestroyDeviceInfoList not available\n");
1092 if (pSetupDiOpenClassRegKeyExA)
1093 test_SetupDiOpenClassRegKeyExA();
1095 skip("SetupDiOpenClassRegKeyExA is not available\n");
1097 testCreateDeviceInfo();
1098 testGetDeviceInstanceId();
1099 testRegisterDeviceInfo();
1100 testCreateDeviceInterface();
1101 testGetDeviceInterfaceDetail();
1103 testRegisterAndGetDetail();
1104 testDeviceRegistryPropertyA();
1105 testDeviceRegistryPropertyW();