setupapi/tests: Prevent crash on NT4.
[wine/gsoc_dplay.git] / dlls / setupapi / tests / devinst.c
blob64035d707e188e565c062b35d8c51020b385db66
1 /*
2 * Devinst tests
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
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winreg.h"
29 #include "guiddef.h"
30 #include "setupapi.h"
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 /* This is a unique guid for testing purposes */
61 static GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}};
63 static void init_function_pointers(void)
65 hSetupAPI = GetModuleHandleA("setupapi.dll");
67 pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA");
68 pSetupDiCreateDeviceInfoW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoW");
69 pSetupDiCreateDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoList");
70 pSetupDiCreateDeviceInfoListExW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoListExW");
71 pSetupDiCreateDeviceInterfaceA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInterfaceA");
72 pSetupDiDestroyDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiDestroyDeviceInfoList");
73 pSetupDiCallClassInstaller = (void *)GetProcAddress(hSetupAPI, "SetupDiCallClassInstaller");
74 pSetupDiEnumDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInfo");
75 pSetupDiEnumDeviceInterfaces = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInterfaces");
76 pSetupDiGetDeviceInstanceIdA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInstanceIdA");
77 pSetupDiGetDeviceInterfaceDetailA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailA");
78 pSetupDiGetDeviceInterfaceDetailW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailW");
79 pSetupDiInstallClassA = (void *)GetProcAddress(hSetupAPI, "SetupDiInstallClassA");
80 pSetupDiOpenClassRegKeyExA = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenClassRegKeyExA");
81 pSetupDiOpenDevRegKey = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenDevRegKey");
82 pSetupDiCreateDevRegKeyW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDevRegKeyW");
83 pSetupDiRegisterDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiRegisterDeviceInfo");
84 pSetupDiGetClassDevsA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsA");
85 pSetupDiGetClassDevsW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsW");
86 pSetupDiSetDeviceRegistryPropertyA = (void *)GetProcAddress(hSetupAPI, "SetupDiSetDeviceRegistryPropertyA");
87 pSetupDiSetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiSetDeviceRegistryPropertyW");
88 pSetupDiGetDeviceRegistryPropertyA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyA");
89 pSetupDiGetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyW");
92 static BOOL remove_device(void)
94 HDEVINFO set;
95 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
96 BOOL ret;
98 SetLastError(0xdeadbeef);
99 set = pSetupDiGetClassDevsA(&guid, NULL, 0, 0);
100 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
101 GetLastError());
103 SetLastError(0xdeadbeef);
104 ok(pSetupDiEnumDeviceInfo(set, 0, &devInfo),
105 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
107 SetLastError(0xdeadbeef);
108 ret = pSetupDiCallClassInstaller(DIF_REMOVE, set, &devInfo);
109 todo_wine
110 ok(ret, "SetupDiCallClassInstaller(DIF_REMOVE...) failed: %08x\n", GetLastError());
112 SetLastError(0xdeadbeef);
113 ok(pSetupDiDestroyDeviceInfoList(set),
114 "SetupDiDestroyDeviceInfoList failed: %08x\n", GetLastError());
116 return ret;
119 /* RegDeleteTreeW from dlls/advapi32/registry.c */
120 LSTATUS WINAPI devinst_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
122 LONG ret;
123 DWORD dwMaxSubkeyLen, dwMaxValueLen;
124 DWORD dwMaxLen, dwSize;
125 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
126 HKEY hSubKey = hKey;
128 if(lpszSubKey)
130 ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
131 if (ret) return ret;
134 /* Get highest length for keys, values */
135 ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
136 &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
137 if (ret) goto cleanup;
139 dwMaxSubkeyLen++;
140 dwMaxValueLen++;
141 dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
142 if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
144 /* Name too big: alloc a buffer for it */
145 if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
147 ret = ERROR_NOT_ENOUGH_MEMORY;
148 goto cleanup;
153 /* Recursively delete all the subkeys */
154 while (TRUE)
156 dwSize = dwMaxLen;
157 if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
158 NULL, NULL, NULL)) break;
160 ret = devinst_RegDeleteTreeW(hSubKey, lpszName);
161 if (ret) goto cleanup;
164 if (lpszSubKey)
165 ret = RegDeleteKeyW(hKey, lpszSubKey);
166 else
167 while (TRUE)
169 dwSize = dwMaxLen;
170 if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
171 NULL, NULL, NULL, NULL)) break;
173 ret = RegDeleteValueW(hKey, lpszName);
174 if (ret) goto cleanup;
177 cleanup:
178 /* Free buffer if allocated */
179 if (lpszName != szNameBuf)
180 HeapFree( GetProcessHeap(), 0, lpszName);
181 if(lpszSubKey)
182 RegCloseKey(hSubKey);
183 return ret;
186 static void clean_devclass_key(void)
188 static const WCHAR devclass[] = {'S','y','s','t','e','m','\\',
189 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
190 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
191 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
192 '1','1','d','b','-','b','7','0','4','-',
193 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
194 HKEY key;
195 DWORD subkeys;
197 /* Check if we have subkeys as Windows 2000 doesn't delete
198 * the keys under the DeviceClasses key after a SetupDiDestroyDeviceInfoList.
200 RegOpenKeyW(HKEY_LOCAL_MACHINE, devclass, &key);
201 RegQueryInfoKey(key, NULL, NULL, NULL, &subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
202 if (subkeys > 0)
204 trace("We are most likely on Windows 2000\n");
205 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
207 else
209 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, devclass),
210 "Couldn't delete deviceclass key\n");
214 static void test_SetupDiCreateDeviceInfoListEx(void)
216 HDEVINFO devlist;
217 BOOL ret;
218 DWORD error;
219 static CHAR notnull[] = "NotNull";
220 static const WCHAR machine[] = { 'd','u','m','m','y',0 };
222 SetLastError(0xdeadbeef);
223 /* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */
224 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, notnull);
226 error = GetLastError();
227 if (error == ERROR_CALL_NOT_IMPLEMENTED)
229 skip("SetupDiCreateDeviceInfoListExW is not implemented\n");
230 return;
232 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
233 ok(error == ERROR_INVALID_PARAMETER, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_PARAMETER);
235 SetLastError(0xdeadbeef);
236 /* create empty DeviceInfoList, but set MachineName to something */
237 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL);
239 error = GetLastError();
240 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
241 ok(error == ERROR_INVALID_MACHINENAME, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_MACHINENAME);
243 /* create empty DeviceInfoList */
244 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
245 ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE);
247 /* destroy DeviceInfoList */
248 ret = pSetupDiDestroyDeviceInfoList(devlist);
249 ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error);
252 static void test_SetupDiOpenClassRegKeyExA(void)
254 static const CHAR guidString[] = "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
255 HKEY hkey;
257 /* Check return value for nonexistent key */
258 hkey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
259 DIOCR_INSTALLER, NULL, NULL);
260 ok(hkey == INVALID_HANDLE_VALUE,
261 "returned %p (expected INVALID_HANDLE_VALUE)\n", hkey);
263 /* Test it for a key that exists */
264 hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS);
265 if (hkey != INVALID_HANDLE_VALUE)
267 HKEY classKey;
268 if (RegCreateKeyA(hkey, guidString, &classKey) == ERROR_SUCCESS)
270 RegCloseKey(classKey);
271 SetLastError(0xdeadbeef);
272 classKey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
273 DIOCR_INSTALLER, NULL, NULL);
274 ok(classKey != INVALID_HANDLE_VALUE,
275 "opening class registry key failed with error %d\n",
276 GetLastError());
277 if (classKey != INVALID_HANDLE_VALUE)
278 RegCloseKey(classKey);
279 RegDeleteKeyA(hkey, guidString);
281 else
282 trace("failed to create registry key for test\n");
284 RegCloseKey(hkey);
286 else
287 trace("failed to open classes key\n");
290 static void append_str(char **str, const char *data)
292 sprintf(*str, data);
293 *str += strlen(*str);
296 static void create_inf_file(LPCSTR filename)
298 char data[1024];
299 char *ptr = data;
300 DWORD dwNumberOfBytesWritten;
301 HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
302 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
304 append_str(&ptr, "[Version]\n");
305 append_str(&ptr, "Signature=\"$Chicago$\"\n");
306 append_str(&ptr, "Class=Bogus\n");
307 append_str(&ptr, "ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n");
308 append_str(&ptr, "[ClassInstall32]\n");
309 append_str(&ptr, "AddReg=BogusClass.NT.AddReg\n");
310 append_str(&ptr, "[BogusClass.NT.AddReg]\n");
311 append_str(&ptr, "HKR,,,,\"Wine test devices\"\n");
313 WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
314 CloseHandle(hf);
317 static void get_temp_filename(LPSTR path)
319 static char curr[MAX_PATH] = { 0 };
320 char temp[MAX_PATH];
321 LPSTR ptr;
323 if (!*curr)
324 GetCurrentDirectoryA(MAX_PATH, curr);
325 GetTempFileNameA(curr, "set", 0, temp);
326 ptr = strrchr(temp, '\\');
328 lstrcpyA(path, ptr + 1);
331 static void testInstallClass(void)
333 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
334 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
335 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
336 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
337 '1','1','d','b','-','b','7','0','4','-',
338 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
339 char tmpfile[MAX_PATH];
340 BOOL ret;
342 tmpfile[0] = '.';
343 tmpfile[1] = '\\';
344 get_temp_filename(tmpfile + 2);
345 create_inf_file(tmpfile + 2);
347 ret = pSetupDiInstallClassA(NULL, NULL, 0, NULL);
348 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
349 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
350 ret = pSetupDiInstallClassA(NULL, NULL, DI_NOVCP, NULL);
351 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
352 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
353 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, DI_NOVCP, NULL);
354 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
355 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
356 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, 0, NULL);
357 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
358 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
359 /* The next call will succeed. Information is put into the registry but the
360 * location(s) is/are depending on the Windows version.
362 ret = pSetupDiInstallClassA(NULL, tmpfile, 0, NULL);
363 ok(ret, "SetupDiInstallClassA failed: %08x\n", GetLastError());
365 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey),
366 "Couldn't delete classkey\n");
368 DeleteFile(tmpfile);
371 static void testCreateDeviceInfo(void)
373 BOOL ret;
374 HDEVINFO set;
375 HKEY key;
376 LONG res;
377 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
378 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
379 'E','n','u','m','\\','R','o','o','t','\\',
380 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
382 SetLastError(0xdeadbeef);
383 ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
384 ok(!ret, "Expected failure\n");
385 ok(GetLastError() == ERROR_INVALID_DEVINST_NAME ||
386 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
387 "Unexpected last error, got %08x\n", GetLastError());
389 SetLastError(0xdeadbeef);
390 ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL,
391 NULL, 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",
396 GetLastError());
397 if (set)
399 SP_DEVINFO_DATA devInfo = { 0 };
400 DWORD i;
401 static GUID deadbeef =
402 {0xdeadbeef, 0xdead, 0xbeef, {0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
404 /* No GUID given */
405 SetLastError(0xdeadbeef);
406 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL,
407 NULL, NULL, 0, NULL);
408 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
409 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
410 /* We can't add device information to the set with a different GUID */
411 SetLastError(0xdeadbeef);
412 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000",
413 &deadbeef, NULL, NULL, 0, NULL);
414 ok(!ret && GetLastError() == ERROR_CLASS_MISMATCH,
415 "Expected ERROR_CLASS_MISMATCH, got %08x\n", GetLastError());
416 /* Finally, with all three required parameters, this succeeds: */
417 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
418 NULL, NULL, 0, NULL);
419 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
420 /* This fails because the device ID already exists.. */
421 SetLastError(0xdeadbeef);
422 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
423 NULL, NULL, 0, &devInfo);
424 ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
425 "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError());
426 /* whereas this "fails" because cbSize is wrong.. */
427 SetLastError(0xdeadbeef);
428 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
429 DICD_GENERATE_ID, &devInfo);
430 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
431 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
432 /* and this finally succeeds. */
433 devInfo.cbSize = sizeof(devInfo);
434 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
435 DICD_GENERATE_ID, &devInfo);
436 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
437 /* There were three devices added, however - the second failure just
438 * resulted in the SP_DEVINFO_DATA not getting copied.
440 SetLastError(0xdeadbeef);
441 i = 0;
442 while (pSetupDiEnumDeviceInfo(set, i, &devInfo))
443 i++;
444 ok(i == 3, "Expected 3 devices, got %d\n", i);
445 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
446 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
447 pSetupDiDestroyDeviceInfoList(set);
450 /* The bogus registry key shouldn't be there after this test. The only
451 * reasons this key would still be present:
453 * - We are running on Wine which has to be fixed
454 * - We have leftovers from old tests
456 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
457 todo_wine
458 ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n");
459 if (res == ERROR_SUCCESS)
461 DWORD subkeys;
463 /* Check if we have subkeys */
464 RegQueryInfoKey(key, NULL, NULL, NULL, &subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
465 if (subkeys > 0)
467 int i;
469 /* Leftovers from old tests */
470 trace("Going to remove %d devices\n", subkeys);
471 for (i = 0; i < subkeys; i++)
473 BOOL ret;
475 ret = remove_device();
476 ok(ret, "Expected a device to be removed\n");
479 else
481 /* Wine doesn't delete the bogus key itself currently */
482 trace("We are most likely on Wine\n");
483 RegDeleteKeyW(HKEY_LOCAL_MACHINE, bogus);
488 static void testGetDeviceInstanceId(void)
490 BOOL ret;
491 HDEVINFO set;
492 SP_DEVINFO_DATA devInfo = { 0 };
494 SetLastError(0xdeadbeef);
495 ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
496 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
497 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
498 SetLastError(0xdeadbeef);
499 ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, NULL, 0, NULL);
500 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
501 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
502 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
503 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
504 GetLastError());
505 if (set)
507 char instanceID[MAX_PATH];
508 DWORD size;
510 SetLastError(0xdeadbeef);
511 ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
512 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
513 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
514 SetLastError(0xdeadbeef);
515 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL);
516 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
517 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
518 SetLastError(0xdeadbeef);
519 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
520 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
521 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
522 devInfo.cbSize = sizeof(devInfo);
523 SetLastError(0xdeadbeef);
524 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
525 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
526 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
527 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
528 NULL, NULL, 0, &devInfo);
529 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
530 SetLastError(0xdeadbeef);
531 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
532 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
533 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
534 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
535 sizeof(instanceID), NULL);
536 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
537 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"),
538 "Unexpected instance ID %s\n", instanceID);
539 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid,
540 NULL, NULL, DICD_GENERATE_ID, &devInfo);
541 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
542 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
543 sizeof(instanceID), NULL);
544 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
545 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"),
546 "Unexpected instance ID %s\n", instanceID);
547 pSetupDiDestroyDeviceInfoList(set);
551 static void testRegisterDeviceInfo(void)
553 BOOL ret;
554 HDEVINFO set;
556 SetLastError(0xdeadbeef);
557 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
558 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
559 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
560 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
561 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
562 if (set)
564 SP_DEVINFO_DATA devInfo = { 0 };
566 SetLastError(0xdeadbeef);
567 ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
568 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
569 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
570 SetLastError(0xdeadbeef);
571 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
572 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
573 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
574 devInfo.cbSize = sizeof(devInfo);
575 SetLastError(0xdeadbeef);
576 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
577 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
578 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
579 ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid,
580 NULL, NULL, 0, &devInfo);
581 ok(ret || GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
582 "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
583 if (ret)
585 /* If it already existed, registering it again will fail */
586 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL,
587 NULL);
588 ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
590 /* FIXME: On Win2K+ systems, this is now persisted to registry in
591 * HKLM\System\CCS\Enum\USB\Bogus\0000.
592 * FIXME: the key also becomes undeletable. How to get rid of it?
594 pSetupDiDestroyDeviceInfoList(set);
598 static void testCreateDeviceInterface(void)
600 BOOL ret;
601 HDEVINFO set;
602 HKEY key;
603 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
604 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
605 'E','n','u','m','\\','R','o','o','t','\\',
606 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
607 static const WCHAR devclass[] = {'S','y','s','t','e','m','\\',
608 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
609 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
610 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
611 '1','1','d','b','-','b','7','0','4','-',
612 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
614 if (!pSetupDiCreateDeviceInterfaceA || !pSetupDiEnumDeviceInterfaces)
616 skip("SetupDiCreateDeviceInterfaceA and/or SetupDiEnumDeviceInterfaces are not available\n");
617 return;
619 SetLastError(0xdeadbeef);
620 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL);
621 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
622 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
623 SetLastError(0xdeadbeef);
624 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL);
625 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
626 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
627 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
628 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
629 if (set)
631 SP_DEVINFO_DATA devInfo = { 0 };
632 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
633 { 0 } };
634 DWORD i;
636 SetLastError(0xdeadbeef);
637 ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL);
638 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
639 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
640 SetLastError(0xdeadbeef);
641 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
642 NULL);
643 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
644 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
645 devInfo.cbSize = sizeof(devInfo);
646 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
647 NULL, NULL, 0, &devInfo);
648 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
649 SetLastError(0xdeadbeef);
650 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
651 NULL);
652 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
653 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
654 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
655 NULL);
656 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
657 /* Creating the same interface a second time succeeds */
658 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
659 NULL);
660 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
661 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0,
662 NULL);
663 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
664 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0,
665 &interfaceData);
666 ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError());
667 i = 0;
668 while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i,
669 &interfaceData))
670 i++;
671 ok(i == 2, "expected 2 interfaces, got %d\n", i);
672 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
673 "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
674 ret = pSetupDiDestroyDeviceInfoList(set);
675 ok(ret, "SetupDiDestroyDeviceInfoList failed: %08x\n", GetLastError());
677 /* Cleanup */
678 /* FIXME: On Wine we still have the bogus entry in Enum\Root and
679 * subkeys, as well as the deviceclass key with subkeys.
680 * Only clean the deviceclass key once Wine if fixed.
682 if (!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key))
684 /* Wine doesn't delete the information currently */
685 trace("We are most likely on Wine\n");
686 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
687 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
689 else
691 clean_devclass_key();
696 static void testGetDeviceInterfaceDetail(void)
698 BOOL ret;
699 HDEVINFO set;
700 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
701 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
702 'E','n','u','m','\\','R','o','o','t','\\',
703 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
704 static const WCHAR devclass[] = {'S','y','s','t','e','m','\\',
705 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
706 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
707 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
708 '1','1','d','b','-','b','7','0','4','-',
709 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
711 if (!pSetupDiCreateDeviceInterfaceA || !pSetupDiGetDeviceInterfaceDetailA)
713 skip("SetupDiCreateDeviceInterfaceA and/or SetupDiGetDeviceInterfaceDetailA are not available\n");
714 return;
716 SetLastError(0xdeadbeef);
717 ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL);
718 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
719 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
720 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
721 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
722 if (set)
724 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
725 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
726 { 0 } };
727 DWORD size = 0;
728 HKEY key;
730 SetLastError(0xdeadbeef);
731 ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL,
732 NULL);
733 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
734 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
735 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
736 NULL, NULL, 0, &devInfo);
737 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
738 SetLastError(0xdeadbeef);
739 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
740 &interfaceData);
741 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
742 SetLastError(0xdeadbeef);
743 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
744 0, NULL, NULL);
745 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
746 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
747 SetLastError(0xdeadbeef);
748 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
749 100, NULL, NULL);
750 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
751 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
752 SetLastError(0xdeadbeef);
753 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
754 0, &size, NULL);
755 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
756 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
757 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
759 static const char path[] =
760 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
761 static const char path_w2k[] =
762 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\";
763 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
764 SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail =
765 (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf;
766 DWORD expectedsize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR)*(1 + strlen(path));
768 detail->cbSize = 0;
769 SetLastError(0xdeadbeef);
770 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
771 size, &size, NULL);
772 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
773 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
774 detail->cbSize = size;
775 SetLastError(0xdeadbeef);
776 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
777 size, &size, NULL);
778 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
779 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
780 detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
781 SetLastError(0xdeadbeef);
782 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
783 size, &size, NULL);
784 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
785 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
786 /* Windows 2000 and up check for the exact size */
787 detail->cbSize = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
788 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
789 size, &size, NULL);
790 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n",
791 GetLastError());
792 ok(!lstrcmpiA(path, detail->DevicePath) ||
793 !lstrcmpiA(path_w2k, detail->DevicePath), "Unexpected path %s\n",
794 detail->DevicePath);
795 /* Check SetupDiGetDeviceInterfaceDetailW */
796 ret = pSetupDiGetDeviceInterfaceDetailW(set, &interfaceData, NULL, 0, &size, NULL);
797 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
798 "Expected ERROR_INSUFFICIENT_BUFFER, got error code: %d\n", GetLastError());
799 ok(expectedsize == size ||
800 (expectedsize + sizeof(WCHAR)) == size /* W2K adds a backslash */,
801 "SetupDiGetDeviceInterfaceDetailW returned wrong reqsize, got %d\n",
802 size);
804 HeapFree(GetProcessHeap(), 0, buf);
806 pSetupDiDestroyDeviceInfoList(set);
808 /* Cleanup */
809 /* FIXME: On Wine we still have the bogus entry in Enum\Root and
810 * subkeys, as well as the deviceclass key with subkeys.
811 * Only do the RegDeleteKey, once Wine is fixed.
813 if (!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key))
815 /* Wine doesn't delete the information currently */
816 trace("We are most likely on Wine\n");
817 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
818 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
820 else
822 clean_devclass_key();
827 static void testDevRegKey(void)
829 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
830 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
831 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
832 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
833 '1','1','d','b','-','b','7','0','4','-',
834 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
835 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
836 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
837 'E','n','u','m','\\','R','o','o','t','\\',
838 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
839 BOOL ret;
840 HDEVINFO set;
841 HKEY key = NULL;
843 SetLastError(0xdeadbeef);
844 key = pSetupDiCreateDevRegKeyW(NULL, NULL, 0, 0, 0, NULL, NULL);
845 ok(key == INVALID_HANDLE_VALUE,
846 "Expected INVALID_HANDLE_VALUE, got %p\n", key);
847 ok(GetLastError() == ERROR_INVALID_HANDLE,
848 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
850 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
851 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
852 if (set)
854 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
855 LONG res;
857 /* The device info key shouldn't be there */
858 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
859 ok(res != ERROR_SUCCESS, "Expected key to not exist\n");
860 RegCloseKey(key);
861 /* Create the device information */
862 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
863 NULL, NULL, 0, &devInfo);
864 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
865 /* The device info key should have been created */
866 ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key),
867 "Expected registry key to exist\n");
868 RegCloseKey(key);
869 SetLastError(0xdeadbeef);
870 key = pSetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0);
871 ok(!key || key == INVALID_HANDLE_VALUE,
872 "Expected INVALID_HANDLE_VALUE or a NULL key (NT4)\n");
873 ok(GetLastError() == ERROR_INVALID_HANDLE,
874 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
875 SetLastError(0xdeadbeef);
876 key = pSetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0);
877 ok(key == INVALID_HANDLE_VALUE &&
878 GetLastError() == ERROR_INVALID_PARAMETER,
879 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
880 SetLastError(0xdeadbeef);
881 key = pSetupDiOpenDevRegKey(set, &devInfo, 0, 0, 0, 0);
882 ok(key == INVALID_HANDLE_VALUE &&
883 GetLastError() == ERROR_INVALID_FLAGS,
884 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
885 SetLastError(0xdeadbeef);
886 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 0, 0);
887 ok(key == INVALID_HANDLE_VALUE &&
888 GetLastError() == ERROR_INVALID_FLAGS,
889 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
890 SetLastError(0xdeadbeef);
891 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
892 DIREG_BOTH, 0);
893 ok(key == INVALID_HANDLE_VALUE &&
894 GetLastError() == ERROR_INVALID_FLAGS,
895 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
896 SetLastError(0xdeadbeef);
897 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
898 DIREG_DRV, 0);
899 ok(key == INVALID_HANDLE_VALUE &&
900 GetLastError() == ERROR_DEVINFO_NOT_REGISTERED,
901 "Expected ERROR_DEVINFO_NOT_REGISTERED, got %08x\n", GetLastError());
902 SetLastError(0xdeadbeef);
903 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
904 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
905 SetLastError(0xdeadbeef);
906 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
907 DIREG_DRV, 0);
908 /* The software key isn't created by default */
909 todo_wine
910 ok(key == INVALID_HANDLE_VALUE &&
911 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
912 "Expected ERROR_KEY_DOES_NOT_EXIST, got %08x\n", GetLastError());
913 SetLastError(0xdeadbeef);
914 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
915 DIREG_DEV, 0);
916 todo_wine
917 ok(key == INVALID_HANDLE_VALUE &&
918 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
919 "Expected ERROR_KEY_DOES_NOT_EXIST, got %08x\n", GetLastError());
920 SetLastError(0xdeadbeef);
921 /* The class key shouldn't be there */
922 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key);
923 todo_wine
924 ok(res != ERROR_SUCCESS, "Expected key to not exist\n");
925 RegCloseKey(key);
926 /* Create the device reg key */
927 key = pSetupDiCreateDevRegKeyW(set, &devInfo, DICS_FLAG_GLOBAL, 0,
928 DIREG_DRV, NULL, NULL);
929 ok(key != INVALID_HANDLE_VALUE, "SetupDiCreateDevRegKey failed: %08x\n",
930 GetLastError());
931 RegCloseKey(key);
932 /* The class key should have been created */
933 ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key),
934 "Expected registry key to exist\n");
935 RegCloseKey(key);
936 SetLastError(0xdeadbeef);
937 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
938 DIREG_DRV, 0);
939 todo_wine
940 ok(key == INVALID_HANDLE_VALUE &&
941 (GetLastError() == ERROR_INVALID_DATA ||
942 GetLastError() == ERROR_ACCESS_DENIED), /* win2k3 */
943 "Expected ERROR_INVALID_DATA or ERROR_ACCESS_DENIED, got %08x\n", GetLastError());
944 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
945 DIREG_DRV, KEY_READ);
946 ok(key != INVALID_HANDLE_VALUE, "SetupDiOpenDevRegKey failed: %08x\n",
947 GetLastError());
948 pSetupDiDestroyDeviceInfoList(set);
950 /* Cleanup */
951 ret = remove_device();
952 todo_wine
953 ok(ret, "Expected the device to be removed: %08x\n", GetLastError());
955 /* FIXME: Only do the RegDeleteKey, once Wine is fixed */
956 if (!ret)
958 /* Wine doesn't delete the information currently */
959 trace("We are most likely on Wine\n");
960 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
961 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
963 else
965 /* There should only be a class key entry, so a simple
966 * RegDeleteKey should work
968 * This could fail if it's the first time for this new test
969 * after running the old tests.
971 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey),
972 "Couldn't delete classkey\n");
977 static void testRegisterAndGetDetail(void)
979 HDEVINFO set;
980 BOOL ret;
981 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
982 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), { 0 } };
983 DWORD dwSize = 0;
984 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
985 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
986 'E','n','u','m','\\','R','o','o','t','\\',
987 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
988 static const WCHAR devclass[] = {'S','y','s','t','e','m','\\',
989 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
990 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
991 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
992 '1','1','d','b','-','b','7','0','4','-',
993 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
995 if (!pSetupDiCreateDeviceInterfaceA || !pSetupDiEnumDeviceInterfaces ||
996 !pSetupDiGetDeviceInterfaceDetailA)
998 skip("Needed functions are not available\n");
999 return;
1002 SetLastError(0xdeadbeef);
1003 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_ALLCLASSES);
1004 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
1005 GetLastError());
1007 SetLastError(0xdeadbeef);
1008 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, 0,
1009 DICD_GENERATE_ID, &devInfo);
1010 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
1011 SetLastError(0xdeadbeef);
1012 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, &interfaceData);
1013 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
1014 SetLastError(0xdeadbeef);
1015 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
1016 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
1018 pSetupDiDestroyDeviceInfoList(set);
1020 SetLastError(0xdeadbeef);
1021 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1022 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
1023 GetLastError());
1025 SetLastError(0xdeadbeef);
1026 ret = pSetupDiEnumDeviceInterfaces(set, NULL, &guid, 0, &interfaceData);
1027 ok(ret, "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
1028 SetLastError(0xdeadbeef);
1029 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, 0, &dwSize, NULL);
1030 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1031 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1032 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1034 static const char path[] =
1035 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
1036 static const char path_w2k[] =
1037 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\";
1038 PSP_DEVICE_INTERFACE_DETAIL_DATA_A detail = NULL;
1040 detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)HeapAlloc(GetProcessHeap(), 0, dwSize);
1041 if (detail)
1043 detail->cbSize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char);
1044 SetLastError(0xdeadbeef);
1045 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData,
1046 detail, dwSize, &dwSize, NULL);
1047 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %08x\n", GetLastError());
1048 /* FIXME: This one only worked because old data wasn't removed properly. As soon
1049 * as all the tests are cleaned up correctly this has to be (or should be) fixed
1051 todo_wine
1052 ok(!lstrcmpiA(path, detail->DevicePath) ||
1053 !lstrcmpiA(path_w2k, detail->DevicePath), "Unexpected path %s\n",
1054 detail->DevicePath);
1055 HeapFree(GetProcessHeap(), 0, detail);
1059 pSetupDiDestroyDeviceInfoList(set);
1061 /* Cleanup */
1062 ret = remove_device();
1063 todo_wine
1064 ok(ret, "Expected the device to be removed: %08x\n", GetLastError());
1066 /* FIXME: Only do the RegDeleteKey, once Wine is fixed */
1067 if (!ret)
1069 /* Wine doesn't delete the information currently */
1070 trace("We are most likely on Wine\n");
1071 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
1072 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
1074 else
1076 clean_devclass_key();
1080 static void testDeviceRegistryPropertyA()
1082 HDEVINFO set;
1083 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
1084 CHAR devName[] = "LEGACY_BOGUS";
1085 CHAR friendlyName[] = "Bogus";
1086 CHAR buf[6] = "";
1087 DWORD buflen = 6;
1088 DWORD size;
1089 DWORD regType;
1090 BOOL ret;
1091 LONG res;
1092 HKEY key;
1093 static const CHAR bogus[] =
1094 "System\\CurrentControlSet\\Enum\\Root\\LEGACY_BOGUS";
1096 SetLastError(0xdeadbeef);
1097 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1098 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
1099 GetLastError());
1100 SetLastError(0xdeadbeef);
1101 ret = pSetupDiCreateDeviceInfoA(set, devName, &guid, NULL, NULL,
1102 DICD_GENERATE_ID, &devInfo);
1103 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
1104 SetLastError(0xdeadbeef);
1105 ret = pSetupDiSetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, 0);
1106 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1107 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1108 SetLastError(0xdeadbeef);
1109 ret = pSetupDiSetDeviceRegistryPropertyA(set, NULL, -1, NULL, 0);
1110 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1111 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1112 SetLastError(0xdeadbeef);
1113 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, 0);
1114 todo_wine
1115 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1116 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1117 /* GetLastError() returns nonsense in win2k3 */
1118 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1119 NULL, 0);
1120 todo_wine
1121 ok(!ret, "Expected failure, got %d\n", ret);
1122 SetLastError(0xdeadbeef);
1123 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1124 (PBYTE)friendlyName, buflen);
1125 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1126 SetLastError(0xdeadbeef);
1127 ret = pSetupDiGetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, NULL, 0, NULL);
1128 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1129 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1130 SetLastError(0xdeadbeef);
1131 ret = pSetupDiGetDeviceRegistryPropertyA(set, NULL, -1, NULL, NULL, 0, NULL);
1132 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1133 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1134 SetLastError(0xdeadbeef);
1135 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, NULL, 0, NULL);
1136 todo_wine
1137 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1138 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1139 /* GetLastError() returns nonsense in win2k3 */
1140 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1141 NULL, NULL, buflen, NULL);
1142 ok(!ret, "Expected failure, got %d\n", ret);
1143 SetLastError(0xdeadbeef);
1144 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1145 NULL, NULL, 0, &size);
1146 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1147 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1148 ok(buflen == size, "Unexpected size: %d\n", size);
1149 SetLastError(0xdeadbeef);
1150 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1151 NULL, (PBYTE)buf, buflen, NULL);
1152 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1153 ok(!lstrcmpiA(friendlyName, buf), "Unexpected property\n");
1154 SetLastError(0xdeadbeef);
1155 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1156 &regType, (PBYTE)buf, buflen, NULL);
1157 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1158 ok(!lstrcmpiA(friendlyName, buf), "Unexpected value of property\n");
1159 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
1160 SetLastError(0xdeadbeef);
1161 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1162 NULL, 0);
1163 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1164 SetLastError(0xdeadbeef);
1165 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1166 NULL, (PBYTE)buf, buflen, &size);
1167 todo_wine
1168 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1169 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
1170 pSetupDiDestroyDeviceInfoList(set);
1172 res = RegOpenKeyA(HKEY_LOCAL_MACHINE, bogus, &key);
1173 todo_wine
1174 ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n");
1175 /* FIXME: Remove when Wine is fixed */
1176 if (res == ERROR_SUCCESS)
1178 /* Wine doesn't delete the information currently */
1179 trace("We are most likely on Wine\n");
1180 RegDeleteKeyA(HKEY_LOCAL_MACHINE, bogus);
1184 static void testDeviceRegistryPropertyW()
1186 HDEVINFO set;
1187 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
1188 WCHAR devName[] = {'L','E','G','A','C','Y','_','B','O','G','U','S',0};
1189 WCHAR friendlyName[] = {'B','o','g','u','s',0};
1190 WCHAR buf[6] = {0};
1191 DWORD buflen = 6 * sizeof(WCHAR);
1192 DWORD size;
1193 DWORD regType;
1194 BOOL ret;
1195 LONG res;
1196 HKEY key;
1197 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
1198 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1199 'E','n','u','m','\\','R','o','o','t','\\',
1200 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
1202 SetLastError(0xdeadbeef);
1203 set = pSetupDiGetClassDevsW(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1204 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsW failed: %08x\n",
1205 GetLastError());
1206 SetLastError(0xdeadbeef);
1207 ret = pSetupDiCreateDeviceInfoW(set, devName, &guid, NULL, NULL,
1208 DICD_GENERATE_ID, &devInfo);
1209 ok(ret, "SetupDiCreateDeviceInfoW failed: %08x\n", GetLastError());
1210 SetLastError(0xdeadbeef);
1211 ret = pSetupDiSetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, 0);
1212 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1213 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1214 SetLastError(0xdeadbeef);
1215 ret = pSetupDiSetDeviceRegistryPropertyW(set, NULL, -1, NULL, 0);
1216 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1217 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1218 SetLastError(0xdeadbeef);
1219 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, 0);
1220 todo_wine
1221 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1222 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1223 /* GetLastError() returns nonsense in win2k3 */
1224 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1225 NULL, 0);
1226 todo_wine
1227 ok(!ret, "Expected failure, got %d\n", ret);
1228 SetLastError(0xdeadbeef);
1229 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1230 (PBYTE)friendlyName, buflen);
1231 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1232 SetLastError(0xdeadbeef);
1233 ret = pSetupDiGetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, NULL, 0, NULL);
1234 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1235 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1236 SetLastError(0xdeadbeef);
1237 ret = pSetupDiGetDeviceRegistryPropertyW(set, NULL, -1, NULL, NULL, 0, NULL);
1238 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1239 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1240 SetLastError(0xdeadbeef);
1241 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, NULL, 0, NULL);
1242 todo_wine
1243 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1244 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1245 /* GetLastError() returns nonsense in win2k3 */
1246 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1247 NULL, NULL, buflen, NULL);
1248 ok(!ret, "Expected failure, got %d\n", ret);
1249 SetLastError(0xdeadbeef);
1250 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1251 NULL, NULL, 0, &size);
1252 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1253 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1254 ok(buflen == size, "Unexpected size: %d\n", size);
1255 SetLastError(0xdeadbeef);
1256 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1257 NULL, (PBYTE)buf, buflen, NULL);
1258 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1259 ok(!lstrcmpiW(friendlyName, buf), "Unexpected property\n");
1260 SetLastError(0xdeadbeef);
1261 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1262 &regType, (PBYTE)buf, buflen, NULL);
1263 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1264 ok(!lstrcmpiW(friendlyName, buf), "Unexpected value of property\n");
1265 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
1266 SetLastError(0xdeadbeef);
1267 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1268 NULL, 0);
1269 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1270 SetLastError(0xdeadbeef);
1271 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1272 NULL, (PBYTE)buf, buflen, &size);
1273 todo_wine
1274 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1275 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
1276 pSetupDiDestroyDeviceInfoList(set);
1278 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
1279 todo_wine
1280 ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n");
1281 /* FIXME: Remove when Wine is fixed */
1282 if (res == ERROR_SUCCESS)
1284 /* Wine doesn't delete the information currently */
1285 trace("We are most likely on Wine\n");
1286 RegDeleteKeyW(HKEY_LOCAL_MACHINE, bogus);
1290 START_TEST(devinst)
1292 HDEVINFO set;
1294 init_function_pointers();
1296 /* Win9x/WinMe does things totally different so we skip all the tests
1298 * We don't want to exclude NT4 so hence this check.
1300 SetLastError(0xdeadbeef);
1301 set = pSetupDiGetClassDevsW(NULL, NULL, 0, 0);
1302 if (set == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1304 skip("Win9x/WinMe has totally different behavior\n");
1305 return;
1308 if (pSetupDiCreateDeviceInfoListExW)
1309 test_SetupDiCreateDeviceInfoListEx();
1310 else
1311 skip("SetupDiCreateDeviceInfoListExW is not available\n");
1313 if (pSetupDiOpenClassRegKeyExA)
1314 test_SetupDiOpenClassRegKeyExA();
1315 else
1316 skip("SetupDiOpenClassRegKeyExA is not available\n");
1318 testInstallClass();
1319 testCreateDeviceInfo();
1320 testGetDeviceInstanceId();
1321 testRegisterDeviceInfo();
1322 testCreateDeviceInterface();
1323 testGetDeviceInterfaceDetail();
1324 testDevRegKey();
1325 testRegisterAndGetDetail();
1326 testDeviceRegistryPropertyA();
1327 testDeviceRegistryPropertyW();