setupapi/tests: Skip all tests on Win9x and WinMe.
[wine/gsoc_dplay.git] / dlls / setupapi / tests / devinst.c
blob2a24891fec038cb9193da1cbb92736f402669e64
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 static const CHAR classKey_win9x[] =
340 "System\\CurrentControlSet\\Services\\Class\\"
341 "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
342 static const CHAR bogus_win9x[] =
343 "System\\CurrentControlSet\\Services\\Class\\Bogus";
344 char tmpfile[MAX_PATH];
345 BOOL ret;
346 HKEY hkey;
348 if (!pSetupDiInstallClassA)
350 skip("No SetupDiInstallClassA\n");
351 return;
353 tmpfile[0] = '.';
354 tmpfile[1] = '\\';
355 get_temp_filename(tmpfile + 2);
356 create_inf_file(tmpfile + 2);
358 ret = pSetupDiInstallClassA(NULL, NULL, 0, NULL);
359 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
360 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
361 ret = pSetupDiInstallClassA(NULL, NULL, DI_NOVCP, NULL);
362 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
363 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
364 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, DI_NOVCP, NULL);
365 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
366 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
367 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, 0, NULL);
368 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
369 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
370 /* The next call will succeed. Information is put into the registry but the
371 * location(s) is/are depending on the Windows version.
373 ret = pSetupDiInstallClassA(NULL, tmpfile, 0, NULL);
374 ok(ret, "SetupDiInstallClassA failed: %08x\n", GetLastError());
375 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, classKey_win9x, &hkey))
377 /* We are on win9x */
378 RegCloseKey(hkey);
379 ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, classKey_win9x),
380 "Couldn't delete win9x classkey\n");
381 ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, bogus_win9x),
382 "Couldn't delete win9x bogus services class\n");
384 else
386 /* NT4 and above */
387 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey),
388 "Couldn't delete NT classkey\n");
390 DeleteFile(tmpfile);
393 static void testCreateDeviceInfo(void)
395 BOOL ret;
396 HDEVINFO set;
397 HKEY key;
398 LONG res;
399 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
400 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
401 'E','n','u','m','\\','R','o','o','t','\\',
402 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
404 if (!pSetupDiCreateDeviceInfoList || !pSetupDiEnumDeviceInfo ||
405 !pSetupDiDestroyDeviceInfoList || !pSetupDiCreateDeviceInfoA)
407 skip("No SetupDiCreateDeviceInfoA\n");
408 return;
410 SetLastError(0xdeadbeef);
411 ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
412 ok(!ret, "Expected failure\n");
413 ok(GetLastError() == ERROR_INVALID_DEVINST_NAME ||
414 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */ ||
415 GetLastError() == ERROR_INVALID_HANDLE /* Win9x */,
416 "Unexpected last error, got %08x\n", GetLastError());
418 /* If we are running on win9x we should skip these tests. Win95
419 * fails most tests anyway and win98 pops up the "Add New Hardware
420 * Wizard".
422 if (GetLastError() == ERROR_INVALID_HANDLE)
424 skip("We are on win9x where the tests introduce issues\n");
425 return;
428 SetLastError(0xdeadbeef);
429 ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL,
430 NULL, NULL, 0, NULL);
431 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
432 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
433 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
434 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
435 GetLastError());
436 if (set)
438 SP_DEVINFO_DATA devInfo = { 0 };
439 DWORD i;
440 static GUID deadbeef =
441 {0xdeadbeef, 0xdead, 0xbeef, {0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
443 /* No GUID given */
444 SetLastError(0xdeadbeef);
445 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL,
446 NULL, NULL, 0, NULL);
447 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
448 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
449 /* We can't add device information to the set with a different GUID */
450 SetLastError(0xdeadbeef);
451 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000",
452 &deadbeef, NULL, NULL, 0, NULL);
453 ok(!ret && GetLastError() == ERROR_CLASS_MISMATCH,
454 "Expected ERROR_CLASS_MISMATCH, got %08x\n", GetLastError());
455 /* Finally, with all three required parameters, this succeeds: */
456 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
457 NULL, NULL, 0, NULL);
458 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
459 /* This fails because the device ID already exists.. */
460 SetLastError(0xdeadbeef);
461 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
462 NULL, NULL, 0, &devInfo);
463 ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
464 "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError());
465 /* whereas this "fails" because cbSize is wrong.. */
466 SetLastError(0xdeadbeef);
467 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
468 DICD_GENERATE_ID, &devInfo);
469 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
470 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
471 /* and this finally succeeds. */
472 devInfo.cbSize = sizeof(devInfo);
473 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
474 DICD_GENERATE_ID, &devInfo);
475 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
476 /* There were three devices added, however - the second failure just
477 * resulted in the SP_DEVINFO_DATA not getting copied.
479 SetLastError(0xdeadbeef);
480 i = 0;
481 while (pSetupDiEnumDeviceInfo(set, i, &devInfo))
482 i++;
483 ok(i == 3, "Expected 3 devices, got %d\n", i);
484 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
485 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
486 pSetupDiDestroyDeviceInfoList(set);
489 /* The bogus registry key shouldn't be there after this test. The only
490 * reasons this key would still be present:
492 * - We are running on Wine which has to be fixed
493 * - We have leftovers from old tests
495 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
496 todo_wine
497 ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n");
498 if (res == ERROR_SUCCESS)
500 DWORD subkeys;
502 /* Check if we have subkeys */
503 RegQueryInfoKey(key, NULL, NULL, NULL, &subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
504 if (subkeys > 0)
506 int i;
508 /* Leftovers from old tests */
509 trace("Going to remove %d devices\n", subkeys);
510 for (i = 0; i < subkeys; i++)
512 BOOL ret;
514 ret = remove_device();
515 ok(ret, "Expected a device to be removed\n");
518 else
520 /* Wine doesn't delete the bogus key itself currently */
521 trace("We are most likely on Wine\n");
522 RegDeleteKeyW(HKEY_LOCAL_MACHINE, bogus);
527 static void testGetDeviceInstanceId(void)
529 BOOL ret;
530 HDEVINFO set;
531 SP_DEVINFO_DATA devInfo = { 0 };
533 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
534 !pSetupDiCreateDeviceInfoA || !pSetupDiGetDeviceInstanceIdA)
536 skip("No SetupDiGetDeviceInstanceIdA\n");
537 return;
539 SetLastError(0xdeadbeef);
540 ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
541 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
542 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
543 SetLastError(0xdeadbeef);
544 ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, NULL, 0, NULL);
545 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
546 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
547 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
548 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
549 GetLastError());
550 if (set)
552 char instanceID[MAX_PATH];
553 DWORD size;
555 SetLastError(0xdeadbeef);
556 ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
557 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
558 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
559 SetLastError(0xdeadbeef);
560 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL);
561 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
562 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
563 SetLastError(0xdeadbeef);
564 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
565 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
566 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
567 devInfo.cbSize = sizeof(devInfo);
568 SetLastError(0xdeadbeef);
569 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
570 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
571 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
572 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
573 NULL, NULL, 0, &devInfo);
574 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
575 SetLastError(0xdeadbeef);
576 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
577 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
578 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
579 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
580 sizeof(instanceID), NULL);
581 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
582 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"),
583 "Unexpected instance ID %s\n", instanceID);
584 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid,
585 NULL, NULL, DICD_GENERATE_ID, &devInfo);
586 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
587 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
588 sizeof(instanceID), NULL);
589 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
590 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"),
591 "Unexpected instance ID %s\n", instanceID);
592 pSetupDiDestroyDeviceInfoList(set);
596 static void testRegisterDeviceInfo(void)
598 BOOL ret;
599 HDEVINFO set;
601 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
602 !pSetupDiRegisterDeviceInfo)
604 skip("No SetupDiRegisterDeviceInfo\n");
605 return;
607 SetLastError(0xdeadbeef);
608 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
609 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
610 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
611 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
612 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
613 if (set)
615 SP_DEVINFO_DATA devInfo = { 0 };
617 SetLastError(0xdeadbeef);
618 ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
619 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
620 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
621 SetLastError(0xdeadbeef);
622 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
623 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
624 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
625 devInfo.cbSize = sizeof(devInfo);
626 SetLastError(0xdeadbeef);
627 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
628 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
629 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
630 ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid,
631 NULL, NULL, 0, &devInfo);
632 ok(ret || GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
633 "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
634 if (ret)
636 /* If it already existed, registering it again will fail */
637 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL,
638 NULL);
639 ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
641 /* FIXME: On Win2K+ systems, this is now persisted to registry in
642 * HKLM\System\CCS\Enum\USB\Bogus\0000. I don't check because the
643 * Win9x location is different.
644 * FIXME: the key also becomes undeletable. How to get rid of it?
646 pSetupDiDestroyDeviceInfoList(set);
650 static void testCreateDeviceInterface(void)
652 BOOL ret;
653 HDEVINFO set;
654 HKEY key;
655 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
656 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
657 'E','n','u','m','\\','R','o','o','t','\\',
658 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
659 static const WCHAR devclass[] = {'S','y','s','t','e','m','\\',
660 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
661 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
662 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
663 '1','1','d','b','-','b','7','0','4','-',
664 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
666 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
667 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
668 !pSetupDiEnumDeviceInterfaces)
670 skip("No SetupDiCreateDeviceInterfaceA\n");
671 return;
673 SetLastError(0xdeadbeef);
674 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL);
675 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
676 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
677 SetLastError(0xdeadbeef);
678 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL);
679 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
680 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
681 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
682 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
683 if (set)
685 SP_DEVINFO_DATA devInfo = { 0 };
686 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
687 { 0 } };
688 DWORD i;
690 SetLastError(0xdeadbeef);
691 ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL);
692 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
693 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
694 SetLastError(0xdeadbeef);
695 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
696 NULL);
697 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
698 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
699 devInfo.cbSize = sizeof(devInfo);
700 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
701 NULL, NULL, 0, &devInfo);
702 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
703 SetLastError(0xdeadbeef);
704 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
705 NULL);
706 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
707 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
708 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
709 NULL);
710 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
711 /* Creating the same interface a second time succeeds */
712 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
713 NULL);
714 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
715 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0,
716 NULL);
717 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
718 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0,
719 &interfaceData);
720 ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError());
721 i = 0;
722 while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i,
723 &interfaceData))
724 i++;
725 ok(i == 2, "expected 2 interfaces, got %d\n", i);
726 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
727 "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
728 ret = pSetupDiDestroyDeviceInfoList(set);
729 ok(ret, "SetupDiDestroyDeviceInfoList failed: %08x\n", GetLastError());
731 /* Cleanup */
732 /* FIXME: On Wine we still have the bogus entry in Enum\Root and
733 * subkeys, as well as the deviceclass key with subkeys.
734 * Only clean the deviceclass key once Wine if fixed.
736 if (!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key))
738 /* Wine doesn't delete the information currently */
739 trace("We are most likely on Wine\n");
740 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
741 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
743 else
745 clean_devclass_key();
750 static void testGetDeviceInterfaceDetail(void)
752 BOOL ret;
753 HDEVINFO set;
754 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
755 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
756 'E','n','u','m','\\','R','o','o','t','\\',
757 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
758 static const WCHAR devclass[] = {'S','y','s','t','e','m','\\',
759 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
760 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
761 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
762 '1','1','d','b','-','b','7','0','4','-',
763 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
765 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
766 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
767 !pSetupDiGetDeviceInterfaceDetailA)
769 skip("No SetupDiGetDeviceInterfaceDetailA\n");
770 return;
772 SetLastError(0xdeadbeef);
773 ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL);
774 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
775 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
776 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
777 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
778 if (set)
780 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
781 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
782 { 0 } };
783 DWORD size = 0;
784 HKEY key;
786 SetLastError(0xdeadbeef);
787 ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL,
788 NULL);
789 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
790 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
791 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
792 NULL, NULL, 0, &devInfo);
793 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
794 SetLastError(0xdeadbeef);
795 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
796 &interfaceData);
797 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
798 SetLastError(0xdeadbeef);
799 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
800 0, NULL, NULL);
801 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
802 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
803 SetLastError(0xdeadbeef);
804 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
805 100, NULL, NULL);
806 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
807 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
808 SetLastError(0xdeadbeef);
809 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
810 0, &size, NULL);
811 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
812 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
813 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
815 static const char path[] =
816 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
817 static const char path_w2k[] =
818 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\";
819 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
820 SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail =
821 (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf;
822 DWORD expectedsize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR)*(1 + strlen(path));
824 detail->cbSize = 0;
825 SetLastError(0xdeadbeef);
826 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
827 size, &size, NULL);
828 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
829 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
830 detail->cbSize = size;
831 SetLastError(0xdeadbeef);
832 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
833 size, &size, NULL);
834 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
835 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
836 detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
837 SetLastError(0xdeadbeef);
838 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
839 size, &size, NULL);
840 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
841 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
842 /* Windows 2000 and up check for the exact size. Win9x returns ERROR_INVALID_PARAMETER
843 * on every call (so doesn't get here) and NT4 doesn't have this function.
845 detail->cbSize = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
846 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
847 size, &size, NULL);
848 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n",
849 GetLastError());
850 ok(!lstrcmpiA(path, detail->DevicePath) ||
851 !lstrcmpiA(path_w2k, detail->DevicePath), "Unexpected path %s\n",
852 detail->DevicePath);
853 /* Check SetupDiGetDeviceInterfaceDetailW */
854 if (pSetupDiGetDeviceInterfaceDetailW)
856 ret = pSetupDiGetDeviceInterfaceDetailW(set, &interfaceData, NULL, 0, &size, NULL);
857 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
858 "Expected ERROR_INSUFFICIENT_BUFFER, got error code: %d\n", GetLastError());
859 ok(expectedsize == size ||
860 (expectedsize + sizeof(WCHAR)) == size /* W2K adds a backslash */,
861 "SetupDiGetDeviceInterfaceDetailW returned wrong reqsize, got %d\n",
862 size);
864 else
865 skip("SetupDiGetDeviceInterfaceDetailW is not available\n");
867 HeapFree(GetProcessHeap(), 0, buf);
869 pSetupDiDestroyDeviceInfoList(set);
871 /* Cleanup */
872 /* FIXME: On Wine we still have the bogus entry in Enum\Root and
873 * subkeys, as well as the deviceclass key with subkeys.
874 * Only do the RegDeleteKey, once Wine is fixed.
876 if (!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key))
878 /* Wine doesn't delete the information currently */
879 trace("We are most likely on Wine\n");
880 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
881 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
883 else
885 clean_devclass_key();
890 static void testDevRegKey(void)
892 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
893 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
894 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
895 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
896 '1','1','d','b','-','b','7','0','4','-',
897 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
898 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
899 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
900 'E','n','u','m','\\','R','o','o','t','\\',
901 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
902 BOOL ret;
903 HDEVINFO set;
904 HKEY key = NULL;
906 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
907 !pSetupDiCreateDeviceInfoA || !pSetupDiOpenDevRegKey ||
908 !pSetupDiRegisterDeviceInfo || !pSetupDiCreateDevRegKeyW ||
909 !pSetupDiCallClassInstaller)
911 skip("No SetupDiOpenDevRegKey\n");
912 return;
915 /* Check if we are on win9x */
916 SetLastError(0xdeadbeef);
917 key = pSetupDiCreateDevRegKeyW(NULL, NULL, 0, 0, 0, NULL, NULL);
918 if (key == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
920 skip("We are on win9x where the tests introduce issues\n");
921 return;
923 ok(key == INVALID_HANDLE_VALUE,
924 "Expected INVALID_HANDLE_VALUE, got %p\n", key);
925 ok(GetLastError() == ERROR_INVALID_HANDLE,
926 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
928 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
929 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
930 if (set)
932 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
933 LONG res;
935 /* The device info key shouldn't be there */
936 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
937 ok(res != ERROR_SUCCESS, "Expected key to not exist\n");
938 RegCloseKey(key);
939 /* Create the device information */
940 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
941 NULL, NULL, 0, &devInfo);
942 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
943 /* The device info key should have been created */
944 ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key),
945 "Expected registry key to exist\n");
946 RegCloseKey(key);
947 SetLastError(0xdeadbeef);
948 key = pSetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0);
949 ok(!key || key == INVALID_HANDLE_VALUE,
950 "Expected INVALID_HANDLE_VALUE or a NULL key (NT4)\n");
951 ok(GetLastError() == ERROR_INVALID_HANDLE,
952 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
953 SetLastError(0xdeadbeef);
954 key = pSetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0);
955 ok(key == INVALID_HANDLE_VALUE &&
956 GetLastError() == ERROR_INVALID_PARAMETER,
957 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
958 SetLastError(0xdeadbeef);
959 key = pSetupDiOpenDevRegKey(set, &devInfo, 0, 0, 0, 0);
960 ok(key == INVALID_HANDLE_VALUE &&
961 GetLastError() == ERROR_INVALID_FLAGS,
962 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
963 SetLastError(0xdeadbeef);
964 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 0, 0);
965 ok(key == INVALID_HANDLE_VALUE &&
966 GetLastError() == ERROR_INVALID_FLAGS,
967 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
968 SetLastError(0xdeadbeef);
969 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
970 DIREG_BOTH, 0);
971 ok(key == INVALID_HANDLE_VALUE &&
972 GetLastError() == ERROR_INVALID_FLAGS,
973 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
974 SetLastError(0xdeadbeef);
975 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
976 DIREG_DRV, 0);
977 ok(key == INVALID_HANDLE_VALUE &&
978 GetLastError() == ERROR_DEVINFO_NOT_REGISTERED,
979 "Expected ERROR_DEVINFO_NOT_REGISTERED, got %08x\n", GetLastError());
980 SetLastError(0xdeadbeef);
981 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
982 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
983 SetLastError(0xdeadbeef);
984 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
985 DIREG_DRV, 0);
986 /* The software key isn't created by default */
987 todo_wine
988 ok(key == INVALID_HANDLE_VALUE &&
989 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
990 "Expected ERROR_KEY_DOES_NOT_EXIST, got %08x\n", GetLastError());
991 SetLastError(0xdeadbeef);
992 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
993 DIREG_DEV, 0);
994 todo_wine
995 ok(key == INVALID_HANDLE_VALUE &&
996 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
997 "Expected ERROR_KEY_DOES_NOT_EXIST, got %08x\n", GetLastError());
998 SetLastError(0xdeadbeef);
999 /* The class key shouldn't be there */
1000 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key);
1001 todo_wine
1002 ok(res != ERROR_SUCCESS, "Expected key to not exist\n");
1003 RegCloseKey(key);
1004 /* Create the device reg key */
1005 key = pSetupDiCreateDevRegKeyW(set, &devInfo, DICS_FLAG_GLOBAL, 0,
1006 DIREG_DRV, NULL, NULL);
1007 ok(key != INVALID_HANDLE_VALUE, "SetupDiCreateDevRegKey failed: %08x\n",
1008 GetLastError());
1009 RegCloseKey(key);
1010 /* The class key should have been created */
1011 ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key),
1012 "Expected registry key to exist\n");
1013 RegCloseKey(key);
1014 SetLastError(0xdeadbeef);
1015 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
1016 DIREG_DRV, 0);
1017 todo_wine
1018 ok(key == INVALID_HANDLE_VALUE &&
1019 (GetLastError() == ERROR_INVALID_DATA ||
1020 GetLastError() == ERROR_ACCESS_DENIED), /* win2k3 */
1021 "Expected ERROR_INVALID_DATA or ERROR_ACCESS_DENIED, got %08x\n", GetLastError());
1022 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
1023 DIREG_DRV, KEY_READ);
1024 ok(key != INVALID_HANDLE_VALUE, "SetupDiOpenDevRegKey failed: %08x\n",
1025 GetLastError());
1026 pSetupDiDestroyDeviceInfoList(set);
1028 /* Cleanup */
1029 ret = remove_device();
1030 todo_wine
1031 ok(ret, "Expected the device to be removed: %08x\n", GetLastError());
1033 /* FIXME: Only do the RegDeleteKey, once Wine is fixed */
1034 if (!ret)
1036 /* Wine doesn't delete the information currently */
1037 trace("We are most likely on Wine\n");
1038 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
1039 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
1041 else
1043 /* There should only be a class key entry, so a simple
1044 * RegDeleteKey should work
1046 * This could fail if it's the first time for this new test
1047 * after running the old tests.
1049 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey),
1050 "Couldn't delete classkey\n");
1055 static void testRegisterAndGetDetail(void)
1057 HDEVINFO set;
1058 BOOL ret;
1059 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
1060 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), { 0 } };
1061 DWORD dwSize = 0;
1062 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
1063 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1064 'E','n','u','m','\\','R','o','o','t','\\',
1065 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
1066 static const WCHAR devclass[] = {'S','y','s','t','e','m','\\',
1067 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1068 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
1069 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
1070 '1','1','d','b','-','b','7','0','4','-',
1071 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
1073 SetLastError(0xdeadbeef);
1074 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_ALLCLASSES);
1075 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
1076 GetLastError());
1078 SetLastError(0xdeadbeef);
1079 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, 0,
1080 DICD_GENERATE_ID, &devInfo);
1081 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
1082 SetLastError(0xdeadbeef);
1083 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, &interfaceData);
1084 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
1085 SetLastError(0xdeadbeef);
1086 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
1087 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
1089 pSetupDiDestroyDeviceInfoList(set);
1091 SetLastError(0xdeadbeef);
1092 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1093 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
1094 GetLastError());
1096 SetLastError(0xdeadbeef);
1097 ret = pSetupDiEnumDeviceInterfaces(set, NULL, &guid, 0, &interfaceData);
1098 ok(ret, "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
1099 SetLastError(0xdeadbeef);
1100 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, 0, &dwSize, NULL);
1101 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1102 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1103 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1105 static const char path[] =
1106 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
1107 static const char path_w2k[] =
1108 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\";
1109 PSP_DEVICE_INTERFACE_DETAIL_DATA_A detail = NULL;
1111 detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)HeapAlloc(GetProcessHeap(), 0, dwSize);
1112 if (detail)
1114 detail->cbSize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char);
1115 SetLastError(0xdeadbeef);
1116 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData,
1117 detail, dwSize, &dwSize, NULL);
1118 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %08x\n", GetLastError());
1119 /* FIXME: This one only worked because old data wasn't removed properly. As soon
1120 * as all the tests are cleaned up correctly this has to be (or should be) fixed
1122 todo_wine
1123 ok(!lstrcmpiA(path, detail->DevicePath) ||
1124 !lstrcmpiA(path_w2k, detail->DevicePath), "Unexpected path %s\n",
1125 detail->DevicePath);
1126 HeapFree(GetProcessHeap(), 0, detail);
1130 pSetupDiDestroyDeviceInfoList(set);
1132 /* Cleanup */
1133 ret = remove_device();
1134 todo_wine
1135 ok(ret, "Expected the device to be removed: %08x\n", GetLastError());
1137 /* FIXME: Only do the RegDeleteKey, once Wine is fixed */
1138 if (!ret)
1140 /* Wine doesn't delete the information currently */
1141 trace("We are most likely on Wine\n");
1142 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
1143 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
1145 else
1147 clean_devclass_key();
1151 static void testDeviceRegistryPropertyA()
1153 HDEVINFO set;
1154 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
1155 CHAR devName[] = "LEGACY_BOGUS";
1156 CHAR friendlyName[] = "Bogus";
1157 CHAR buf[6] = "";
1158 DWORD buflen = 6;
1159 DWORD size;
1160 DWORD regType;
1161 BOOL ret;
1162 LONG res;
1163 HKEY key;
1164 static const CHAR bogus[] =
1165 "System\\CurrentControlSet\\Enum\\Root\\LEGACY_BOGUS";
1167 SetLastError(0xdeadbeef);
1168 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1169 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
1170 GetLastError());
1171 SetLastError(0xdeadbeef);
1172 ret = pSetupDiCreateDeviceInfoA(set, devName, &guid, NULL, NULL,
1173 DICD_GENERATE_ID, &devInfo);
1174 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
1175 SetLastError(0xdeadbeef);
1176 ret = pSetupDiSetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, 0);
1177 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1178 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1179 SetLastError(0xdeadbeef);
1180 ret = pSetupDiSetDeviceRegistryPropertyA(set, NULL, -1, NULL, 0);
1181 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1182 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1183 SetLastError(0xdeadbeef);
1184 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, 0);
1185 todo_wine
1186 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1187 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1188 /* GetLastError() returns nonsense in win2k3 */
1189 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1190 NULL, 0);
1191 todo_wine
1192 ok(!ret, "Expected failure, got %d\n", ret);
1193 SetLastError(0xdeadbeef);
1194 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1195 (PBYTE)friendlyName, buflen);
1196 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1197 SetLastError(0xdeadbeef);
1198 ret = pSetupDiGetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, NULL, 0, NULL);
1199 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1200 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1201 SetLastError(0xdeadbeef);
1202 ret = pSetupDiGetDeviceRegistryPropertyA(set, NULL, -1, NULL, NULL, 0, NULL);
1203 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1204 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1205 SetLastError(0xdeadbeef);
1206 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, NULL, 0, NULL);
1207 todo_wine
1208 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1209 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1210 /* GetLastError() returns nonsense in win2k3 */
1211 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1212 NULL, NULL, buflen, NULL);
1213 ok(!ret, "Expected failure, got %d\n", ret);
1214 SetLastError(0xdeadbeef);
1215 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1216 NULL, NULL, 0, &size);
1217 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1218 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1219 ok(buflen == size, "Unexpected size: %d\n", size);
1220 SetLastError(0xdeadbeef);
1221 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1222 NULL, (PBYTE)buf, buflen, NULL);
1223 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1224 ok(!lstrcmpiA(friendlyName, buf), "Unexpected property\n");
1225 SetLastError(0xdeadbeef);
1226 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1227 &regType, (PBYTE)buf, buflen, NULL);
1228 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1229 ok(!lstrcmpiA(friendlyName, buf), "Unexpected value of property\n");
1230 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
1231 SetLastError(0xdeadbeef);
1232 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1233 NULL, 0);
1234 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1235 SetLastError(0xdeadbeef);
1236 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1237 NULL, (PBYTE)buf, buflen, &size);
1238 todo_wine
1239 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1240 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
1241 pSetupDiDestroyDeviceInfoList(set);
1243 res = RegOpenKeyA(HKEY_LOCAL_MACHINE, bogus, &key);
1244 todo_wine
1245 ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n");
1246 /* FIXME: Remove when Wine is fixed */
1247 if (res == ERROR_SUCCESS)
1249 /* Wine doesn't delete the information currently */
1250 trace("We are most likely on Wine\n");
1251 RegDeleteKeyA(HKEY_LOCAL_MACHINE, bogus);
1255 static void testDeviceRegistryPropertyW()
1257 HDEVINFO set;
1258 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
1259 WCHAR devName[] = {'L','E','G','A','C','Y','_','B','O','G','U','S',0};
1260 WCHAR friendlyName[] = {'B','o','g','u','s',0};
1261 WCHAR buf[6] = {0};
1262 DWORD buflen = 6 * sizeof(WCHAR);
1263 DWORD size;
1264 DWORD regType;
1265 BOOL ret;
1266 LONG res;
1267 HKEY key;
1268 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
1269 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1270 'E','n','u','m','\\','R','o','o','t','\\',
1271 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
1273 SetLastError(0xdeadbeef);
1274 set = pSetupDiGetClassDevsW(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1275 if (set == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1277 skip("W-functions are not implemented\n");
1278 return;
1280 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsW failed: %08x\n",
1281 GetLastError());
1282 SetLastError(0xdeadbeef);
1283 ret = pSetupDiCreateDeviceInfoW(set, devName, &guid, NULL, NULL,
1284 DICD_GENERATE_ID, &devInfo);
1285 ok(ret, "SetupDiCreateDeviceInfoW failed: %08x\n", GetLastError());
1286 SetLastError(0xdeadbeef);
1287 ret = pSetupDiSetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, 0);
1288 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1289 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1290 SetLastError(0xdeadbeef);
1291 ret = pSetupDiSetDeviceRegistryPropertyW(set, NULL, -1, NULL, 0);
1292 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1293 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1294 SetLastError(0xdeadbeef);
1295 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, 0);
1296 todo_wine
1297 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1298 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1299 /* GetLastError() returns nonsense in win2k3 */
1300 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1301 NULL, 0);
1302 todo_wine
1303 ok(!ret, "Expected failure, got %d\n", ret);
1304 SetLastError(0xdeadbeef);
1305 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1306 (PBYTE)friendlyName, buflen);
1307 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1308 SetLastError(0xdeadbeef);
1309 ret = pSetupDiGetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, NULL, 0, NULL);
1310 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1311 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1312 SetLastError(0xdeadbeef);
1313 ret = pSetupDiGetDeviceRegistryPropertyW(set, NULL, -1, NULL, NULL, 0, NULL);
1314 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1315 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1316 SetLastError(0xdeadbeef);
1317 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, NULL, 0, NULL);
1318 todo_wine
1319 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1320 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1321 /* GetLastError() returns nonsense in win2k3 */
1322 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1323 NULL, NULL, buflen, NULL);
1324 ok(!ret, "Expected failure, got %d\n", ret);
1325 SetLastError(0xdeadbeef);
1326 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1327 NULL, NULL, 0, &size);
1328 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1329 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1330 ok(buflen == size, "Unexpected size: %d\n", size);
1331 SetLastError(0xdeadbeef);
1332 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1333 NULL, (PBYTE)buf, buflen, NULL);
1334 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1335 ok(!lstrcmpiW(friendlyName, buf), "Unexpected property\n");
1336 SetLastError(0xdeadbeef);
1337 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1338 &regType, (PBYTE)buf, buflen, NULL);
1339 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1340 ok(!lstrcmpiW(friendlyName, buf), "Unexpected value of property\n");
1341 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
1342 SetLastError(0xdeadbeef);
1343 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1344 NULL, 0);
1345 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1346 SetLastError(0xdeadbeef);
1347 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1348 NULL, (PBYTE)buf, buflen, &size);
1349 todo_wine
1350 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1351 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
1352 pSetupDiDestroyDeviceInfoList(set);
1354 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
1355 todo_wine
1356 ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n");
1357 /* FIXME: Remove when Wine is fixed */
1358 if (res == ERROR_SUCCESS)
1360 /* Wine doesn't delete the information currently */
1361 trace("We are most likely on Wine\n");
1362 RegDeleteKeyW(HKEY_LOCAL_MACHINE, bogus);
1366 START_TEST(devinst)
1368 HDEVINFO set;
1370 init_function_pointers();
1372 /* Win9x/WinMe does things totally different so we skip all the tests
1374 * We don't want to exclude NT4 so hence this check.
1376 SetLastError(0xdeadbeef);
1377 set = pSetupDiGetClassDevsW(NULL, NULL, 0, 0);
1378 if (set == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1380 skip("Win9x/WinMe has totally different behavior\n");
1381 return;
1384 if (pSetupDiCreateDeviceInfoListExW && pSetupDiDestroyDeviceInfoList)
1385 test_SetupDiCreateDeviceInfoListEx();
1386 else
1387 skip("SetupDiCreateDeviceInfoListExW and/or SetupDiDestroyDeviceInfoList not available\n");
1389 if (pSetupDiOpenClassRegKeyExA)
1390 test_SetupDiOpenClassRegKeyExA();
1391 else
1392 skip("SetupDiOpenClassRegKeyExA is not available\n");
1394 testInstallClass();
1395 testCreateDeviceInfo();
1396 testGetDeviceInstanceId();
1397 testRegisterDeviceInfo();
1398 testCreateDeviceInterface();
1399 testGetDeviceInterfaceDetail();
1400 testDevRegKey();
1401 testRegisterAndGetDetail();
1402 testDeviceRegistryPropertyA();
1403 testDeviceRegistryPropertyW();