setupapi/tests: Remove win9x specifics from testCreateDeviceInfo.
[wine/gsoc_dplay.git] / dlls / setupapi / tests / devinst.c
blob346257e1ebe788bd20d597a855e5017b64bc1d60
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 SetLastError(0xdeadbeef);
405 ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
406 ok(!ret, "Expected failure\n");
407 ok(GetLastError() == ERROR_INVALID_DEVINST_NAME ||
408 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
409 "Unexpected last error, got %08x\n", GetLastError());
411 SetLastError(0xdeadbeef);
412 ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL,
413 NULL, NULL, 0, NULL);
414 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
415 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
416 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
417 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
418 GetLastError());
419 if (set)
421 SP_DEVINFO_DATA devInfo = { 0 };
422 DWORD i;
423 static GUID deadbeef =
424 {0xdeadbeef, 0xdead, 0xbeef, {0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
426 /* No GUID given */
427 SetLastError(0xdeadbeef);
428 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL,
429 NULL, NULL, 0, NULL);
430 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
431 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
432 /* We can't add device information to the set with a different GUID */
433 SetLastError(0xdeadbeef);
434 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000",
435 &deadbeef, NULL, NULL, 0, NULL);
436 ok(!ret && GetLastError() == ERROR_CLASS_MISMATCH,
437 "Expected ERROR_CLASS_MISMATCH, got %08x\n", GetLastError());
438 /* Finally, with all three required parameters, this succeeds: */
439 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
440 NULL, NULL, 0, NULL);
441 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
442 /* This fails because the device ID already exists.. */
443 SetLastError(0xdeadbeef);
444 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
445 NULL, NULL, 0, &devInfo);
446 ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
447 "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError());
448 /* whereas this "fails" because cbSize is wrong.. */
449 SetLastError(0xdeadbeef);
450 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
451 DICD_GENERATE_ID, &devInfo);
452 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
453 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
454 /* and this finally succeeds. */
455 devInfo.cbSize = sizeof(devInfo);
456 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
457 DICD_GENERATE_ID, &devInfo);
458 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
459 /* There were three devices added, however - the second failure just
460 * resulted in the SP_DEVINFO_DATA not getting copied.
462 SetLastError(0xdeadbeef);
463 i = 0;
464 while (pSetupDiEnumDeviceInfo(set, i, &devInfo))
465 i++;
466 ok(i == 3, "Expected 3 devices, got %d\n", i);
467 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
468 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
469 pSetupDiDestroyDeviceInfoList(set);
472 /* The bogus registry key shouldn't be there after this test. The only
473 * reasons this key would still be present:
475 * - We are running on Wine which has to be fixed
476 * - We have leftovers from old tests
478 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
479 todo_wine
480 ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n");
481 if (res == ERROR_SUCCESS)
483 DWORD subkeys;
485 /* Check if we have subkeys */
486 RegQueryInfoKey(key, NULL, NULL, NULL, &subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
487 if (subkeys > 0)
489 int i;
491 /* Leftovers from old tests */
492 trace("Going to remove %d devices\n", subkeys);
493 for (i = 0; i < subkeys; i++)
495 BOOL ret;
497 ret = remove_device();
498 ok(ret, "Expected a device to be removed\n");
501 else
503 /* Wine doesn't delete the bogus key itself currently */
504 trace("We are most likely on Wine\n");
505 RegDeleteKeyW(HKEY_LOCAL_MACHINE, bogus);
510 static void testGetDeviceInstanceId(void)
512 BOOL ret;
513 HDEVINFO set;
514 SP_DEVINFO_DATA devInfo = { 0 };
516 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
517 !pSetupDiCreateDeviceInfoA || !pSetupDiGetDeviceInstanceIdA)
519 skip("No SetupDiGetDeviceInstanceIdA\n");
520 return;
522 SetLastError(0xdeadbeef);
523 ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
524 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
525 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
526 SetLastError(0xdeadbeef);
527 ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, NULL, 0, NULL);
528 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
529 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
530 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
531 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
532 GetLastError());
533 if (set)
535 char instanceID[MAX_PATH];
536 DWORD size;
538 SetLastError(0xdeadbeef);
539 ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
540 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
541 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
542 SetLastError(0xdeadbeef);
543 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL);
544 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
545 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
546 SetLastError(0xdeadbeef);
547 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
548 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
549 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
550 devInfo.cbSize = sizeof(devInfo);
551 SetLastError(0xdeadbeef);
552 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
553 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
554 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
555 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
556 NULL, NULL, 0, &devInfo);
557 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
558 SetLastError(0xdeadbeef);
559 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
560 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
561 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
562 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
563 sizeof(instanceID), NULL);
564 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
565 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"),
566 "Unexpected instance ID %s\n", instanceID);
567 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid,
568 NULL, NULL, DICD_GENERATE_ID, &devInfo);
569 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
570 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
571 sizeof(instanceID), NULL);
572 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
573 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"),
574 "Unexpected instance ID %s\n", instanceID);
575 pSetupDiDestroyDeviceInfoList(set);
579 static void testRegisterDeviceInfo(void)
581 BOOL ret;
582 HDEVINFO set;
584 SetLastError(0xdeadbeef);
585 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
586 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
587 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
588 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
589 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
590 if (set)
592 SP_DEVINFO_DATA devInfo = { 0 };
594 SetLastError(0xdeadbeef);
595 ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
596 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
597 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
598 SetLastError(0xdeadbeef);
599 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
600 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
601 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
602 devInfo.cbSize = sizeof(devInfo);
603 SetLastError(0xdeadbeef);
604 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
605 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
606 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
607 ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid,
608 NULL, NULL, 0, &devInfo);
609 ok(ret || GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
610 "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
611 if (ret)
613 /* If it already existed, registering it again will fail */
614 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL,
615 NULL);
616 ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
618 /* FIXME: On Win2K+ systems, this is now persisted to registry in
619 * HKLM\System\CCS\Enum\USB\Bogus\0000. I don't check because the
620 * Win9x location is different.
621 * FIXME: the key also becomes undeletable. How to get rid of it?
623 pSetupDiDestroyDeviceInfoList(set);
627 static void testCreateDeviceInterface(void)
629 BOOL ret;
630 HDEVINFO set;
631 HKEY key;
632 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
633 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
634 'E','n','u','m','\\','R','o','o','t','\\',
635 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
636 static const WCHAR devclass[] = {'S','y','s','t','e','m','\\',
637 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
638 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
639 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
640 '1','1','d','b','-','b','7','0','4','-',
641 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
643 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
644 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
645 !pSetupDiEnumDeviceInterfaces)
647 skip("No SetupDiCreateDeviceInterfaceA\n");
648 return;
650 SetLastError(0xdeadbeef);
651 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL);
652 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
653 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
654 SetLastError(0xdeadbeef);
655 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL);
656 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
657 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
658 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
659 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
660 if (set)
662 SP_DEVINFO_DATA devInfo = { 0 };
663 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
664 { 0 } };
665 DWORD i;
667 SetLastError(0xdeadbeef);
668 ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL);
669 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
670 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
671 SetLastError(0xdeadbeef);
672 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
673 NULL);
674 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
675 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
676 devInfo.cbSize = sizeof(devInfo);
677 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
678 NULL, NULL, 0, &devInfo);
679 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
680 SetLastError(0xdeadbeef);
681 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
682 NULL);
683 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
684 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
685 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
686 NULL);
687 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
688 /* Creating the same interface a second time succeeds */
689 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
690 NULL);
691 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
692 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0,
693 NULL);
694 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
695 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0,
696 &interfaceData);
697 ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError());
698 i = 0;
699 while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i,
700 &interfaceData))
701 i++;
702 ok(i == 2, "expected 2 interfaces, got %d\n", i);
703 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
704 "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
705 ret = pSetupDiDestroyDeviceInfoList(set);
706 ok(ret, "SetupDiDestroyDeviceInfoList failed: %08x\n", GetLastError());
708 /* Cleanup */
709 /* FIXME: On Wine we still have the bogus entry in Enum\Root and
710 * subkeys, as well as the deviceclass key with subkeys.
711 * Only clean the deviceclass key once Wine if fixed.
713 if (!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key))
715 /* Wine doesn't delete the information currently */
716 trace("We are most likely on Wine\n");
717 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
718 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
720 else
722 clean_devclass_key();
727 static void testGetDeviceInterfaceDetail(void)
729 BOOL ret;
730 HDEVINFO set;
731 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
732 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
733 'E','n','u','m','\\','R','o','o','t','\\',
734 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
735 static const WCHAR devclass[] = {'S','y','s','t','e','m','\\',
736 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
737 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
738 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
739 '1','1','d','b','-','b','7','0','4','-',
740 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
742 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
743 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
744 !pSetupDiGetDeviceInterfaceDetailA)
746 skip("No SetupDiGetDeviceInterfaceDetailA\n");
747 return;
749 SetLastError(0xdeadbeef);
750 ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL);
751 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
752 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
753 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
754 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
755 if (set)
757 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
758 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
759 { 0 } };
760 DWORD size = 0;
761 HKEY key;
763 SetLastError(0xdeadbeef);
764 ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL,
765 NULL);
766 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
767 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
768 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
769 NULL, NULL, 0, &devInfo);
770 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
771 SetLastError(0xdeadbeef);
772 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
773 &interfaceData);
774 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
775 SetLastError(0xdeadbeef);
776 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
777 0, NULL, NULL);
778 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
779 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
780 SetLastError(0xdeadbeef);
781 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
782 100, NULL, NULL);
783 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
784 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
785 SetLastError(0xdeadbeef);
786 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
787 0, &size, NULL);
788 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
789 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
790 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
792 static const char path[] =
793 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
794 static const char path_w2k[] =
795 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\";
796 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
797 SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail =
798 (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf;
799 DWORD expectedsize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR)*(1 + strlen(path));
801 detail->cbSize = 0;
802 SetLastError(0xdeadbeef);
803 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
804 size, &size, NULL);
805 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
806 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
807 detail->cbSize = size;
808 SetLastError(0xdeadbeef);
809 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
810 size, &size, NULL);
811 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
812 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
813 detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
814 SetLastError(0xdeadbeef);
815 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
816 size, &size, NULL);
817 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
818 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
819 /* Windows 2000 and up check for the exact size. Win9x returns ERROR_INVALID_PARAMETER
820 * on every call (so doesn't get here) and NT4 doesn't have this function.
822 detail->cbSize = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
823 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
824 size, &size, NULL);
825 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n",
826 GetLastError());
827 ok(!lstrcmpiA(path, detail->DevicePath) ||
828 !lstrcmpiA(path_w2k, detail->DevicePath), "Unexpected path %s\n",
829 detail->DevicePath);
830 /* Check SetupDiGetDeviceInterfaceDetailW */
831 if (pSetupDiGetDeviceInterfaceDetailW)
833 ret = pSetupDiGetDeviceInterfaceDetailW(set, &interfaceData, NULL, 0, &size, NULL);
834 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
835 "Expected ERROR_INSUFFICIENT_BUFFER, got error code: %d\n", GetLastError());
836 ok(expectedsize == size ||
837 (expectedsize + sizeof(WCHAR)) == size /* W2K adds a backslash */,
838 "SetupDiGetDeviceInterfaceDetailW returned wrong reqsize, got %d\n",
839 size);
841 else
842 skip("SetupDiGetDeviceInterfaceDetailW is not available\n");
844 HeapFree(GetProcessHeap(), 0, buf);
846 pSetupDiDestroyDeviceInfoList(set);
848 /* Cleanup */
849 /* FIXME: On Wine we still have the bogus entry in Enum\Root and
850 * subkeys, as well as the deviceclass key with subkeys.
851 * Only do the RegDeleteKey, once Wine is fixed.
853 if (!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key))
855 /* Wine doesn't delete the information currently */
856 trace("We are most likely on Wine\n");
857 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
858 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
860 else
862 clean_devclass_key();
867 static void testDevRegKey(void)
869 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
870 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
871 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
872 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
873 '1','1','d','b','-','b','7','0','4','-',
874 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
875 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
876 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
877 'E','n','u','m','\\','R','o','o','t','\\',
878 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
879 BOOL ret;
880 HDEVINFO set;
881 HKEY key = NULL;
883 SetLastError(0xdeadbeef);
884 key = pSetupDiCreateDevRegKeyW(NULL, NULL, 0, 0, 0, NULL, NULL);
885 ok(key == INVALID_HANDLE_VALUE,
886 "Expected INVALID_HANDLE_VALUE, got %p\n", key);
887 ok(GetLastError() == ERROR_INVALID_HANDLE,
888 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
890 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
891 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
892 if (set)
894 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
895 LONG res;
897 /* The device info key shouldn't be there */
898 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
899 ok(res != ERROR_SUCCESS, "Expected key to not exist\n");
900 RegCloseKey(key);
901 /* Create the device information */
902 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
903 NULL, NULL, 0, &devInfo);
904 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
905 /* The device info key should have been created */
906 ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key),
907 "Expected registry key to exist\n");
908 RegCloseKey(key);
909 SetLastError(0xdeadbeef);
910 key = pSetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0);
911 ok(!key || key == INVALID_HANDLE_VALUE,
912 "Expected INVALID_HANDLE_VALUE or a NULL key (NT4)\n");
913 ok(GetLastError() == ERROR_INVALID_HANDLE,
914 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
915 SetLastError(0xdeadbeef);
916 key = pSetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0);
917 ok(key == INVALID_HANDLE_VALUE &&
918 GetLastError() == ERROR_INVALID_PARAMETER,
919 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
920 SetLastError(0xdeadbeef);
921 key = pSetupDiOpenDevRegKey(set, &devInfo, 0, 0, 0, 0);
922 ok(key == INVALID_HANDLE_VALUE &&
923 GetLastError() == ERROR_INVALID_FLAGS,
924 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
925 SetLastError(0xdeadbeef);
926 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 0, 0);
927 ok(key == INVALID_HANDLE_VALUE &&
928 GetLastError() == ERROR_INVALID_FLAGS,
929 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
930 SetLastError(0xdeadbeef);
931 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
932 DIREG_BOTH, 0);
933 ok(key == INVALID_HANDLE_VALUE &&
934 GetLastError() == ERROR_INVALID_FLAGS,
935 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
936 SetLastError(0xdeadbeef);
937 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
938 DIREG_DRV, 0);
939 ok(key == INVALID_HANDLE_VALUE &&
940 GetLastError() == ERROR_DEVINFO_NOT_REGISTERED,
941 "Expected ERROR_DEVINFO_NOT_REGISTERED, got %08x\n", GetLastError());
942 SetLastError(0xdeadbeef);
943 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
944 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
945 SetLastError(0xdeadbeef);
946 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
947 DIREG_DRV, 0);
948 /* The software key isn't created by default */
949 todo_wine
950 ok(key == INVALID_HANDLE_VALUE &&
951 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
952 "Expected ERROR_KEY_DOES_NOT_EXIST, got %08x\n", GetLastError());
953 SetLastError(0xdeadbeef);
954 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
955 DIREG_DEV, 0);
956 todo_wine
957 ok(key == INVALID_HANDLE_VALUE &&
958 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
959 "Expected ERROR_KEY_DOES_NOT_EXIST, got %08x\n", GetLastError());
960 SetLastError(0xdeadbeef);
961 /* The class key shouldn't be there */
962 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key);
963 todo_wine
964 ok(res != ERROR_SUCCESS, "Expected key to not exist\n");
965 RegCloseKey(key);
966 /* Create the device reg key */
967 key = pSetupDiCreateDevRegKeyW(set, &devInfo, DICS_FLAG_GLOBAL, 0,
968 DIREG_DRV, NULL, NULL);
969 ok(key != INVALID_HANDLE_VALUE, "SetupDiCreateDevRegKey failed: %08x\n",
970 GetLastError());
971 RegCloseKey(key);
972 /* The class key should have been created */
973 ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key),
974 "Expected registry key to exist\n");
975 RegCloseKey(key);
976 SetLastError(0xdeadbeef);
977 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
978 DIREG_DRV, 0);
979 todo_wine
980 ok(key == INVALID_HANDLE_VALUE &&
981 (GetLastError() == ERROR_INVALID_DATA ||
982 GetLastError() == ERROR_ACCESS_DENIED), /* win2k3 */
983 "Expected ERROR_INVALID_DATA or ERROR_ACCESS_DENIED, got %08x\n", GetLastError());
984 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
985 DIREG_DRV, KEY_READ);
986 ok(key != INVALID_HANDLE_VALUE, "SetupDiOpenDevRegKey failed: %08x\n",
987 GetLastError());
988 pSetupDiDestroyDeviceInfoList(set);
990 /* Cleanup */
991 ret = remove_device();
992 todo_wine
993 ok(ret, "Expected the device to be removed: %08x\n", GetLastError());
995 /* FIXME: Only do the RegDeleteKey, once Wine is fixed */
996 if (!ret)
998 /* Wine doesn't delete the information currently */
999 trace("We are most likely on Wine\n");
1000 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
1001 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
1003 else
1005 /* There should only be a class key entry, so a simple
1006 * RegDeleteKey should work
1008 * This could fail if it's the first time for this new test
1009 * after running the old tests.
1011 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey),
1012 "Couldn't delete classkey\n");
1017 static void testRegisterAndGetDetail(void)
1019 HDEVINFO set;
1020 BOOL ret;
1021 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
1022 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), { 0 } };
1023 DWORD dwSize = 0;
1024 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
1025 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1026 'E','n','u','m','\\','R','o','o','t','\\',
1027 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
1028 static const WCHAR devclass[] = {'S','y','s','t','e','m','\\',
1029 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1030 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
1031 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
1032 '1','1','d','b','-','b','7','0','4','-',
1033 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
1035 SetLastError(0xdeadbeef);
1036 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_ALLCLASSES);
1037 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
1038 GetLastError());
1040 SetLastError(0xdeadbeef);
1041 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, 0,
1042 DICD_GENERATE_ID, &devInfo);
1043 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
1044 SetLastError(0xdeadbeef);
1045 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, &interfaceData);
1046 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
1047 SetLastError(0xdeadbeef);
1048 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
1049 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
1051 pSetupDiDestroyDeviceInfoList(set);
1053 SetLastError(0xdeadbeef);
1054 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1055 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
1056 GetLastError());
1058 SetLastError(0xdeadbeef);
1059 ret = pSetupDiEnumDeviceInterfaces(set, NULL, &guid, 0, &interfaceData);
1060 ok(ret, "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
1061 SetLastError(0xdeadbeef);
1062 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, 0, &dwSize, NULL);
1063 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1064 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1065 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1067 static const char path[] =
1068 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
1069 static const char path_w2k[] =
1070 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\";
1071 PSP_DEVICE_INTERFACE_DETAIL_DATA_A detail = NULL;
1073 detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)HeapAlloc(GetProcessHeap(), 0, dwSize);
1074 if (detail)
1076 detail->cbSize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char);
1077 SetLastError(0xdeadbeef);
1078 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData,
1079 detail, dwSize, &dwSize, NULL);
1080 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %08x\n", GetLastError());
1081 /* FIXME: This one only worked because old data wasn't removed properly. As soon
1082 * as all the tests are cleaned up correctly this has to be (or should be) fixed
1084 todo_wine
1085 ok(!lstrcmpiA(path, detail->DevicePath) ||
1086 !lstrcmpiA(path_w2k, detail->DevicePath), "Unexpected path %s\n",
1087 detail->DevicePath);
1088 HeapFree(GetProcessHeap(), 0, detail);
1092 pSetupDiDestroyDeviceInfoList(set);
1094 /* Cleanup */
1095 ret = remove_device();
1096 todo_wine
1097 ok(ret, "Expected the device to be removed: %08x\n", GetLastError());
1099 /* FIXME: Only do the RegDeleteKey, once Wine is fixed */
1100 if (!ret)
1102 /* Wine doesn't delete the information currently */
1103 trace("We are most likely on Wine\n");
1104 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
1105 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
1107 else
1109 clean_devclass_key();
1113 static void testDeviceRegistryPropertyA()
1115 HDEVINFO set;
1116 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
1117 CHAR devName[] = "LEGACY_BOGUS";
1118 CHAR friendlyName[] = "Bogus";
1119 CHAR buf[6] = "";
1120 DWORD buflen = 6;
1121 DWORD size;
1122 DWORD regType;
1123 BOOL ret;
1124 LONG res;
1125 HKEY key;
1126 static const CHAR bogus[] =
1127 "System\\CurrentControlSet\\Enum\\Root\\LEGACY_BOGUS";
1129 SetLastError(0xdeadbeef);
1130 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1131 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
1132 GetLastError());
1133 SetLastError(0xdeadbeef);
1134 ret = pSetupDiCreateDeviceInfoA(set, devName, &guid, NULL, NULL,
1135 DICD_GENERATE_ID, &devInfo);
1136 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
1137 SetLastError(0xdeadbeef);
1138 ret = pSetupDiSetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, 0);
1139 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1140 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1141 SetLastError(0xdeadbeef);
1142 ret = pSetupDiSetDeviceRegistryPropertyA(set, NULL, -1, NULL, 0);
1143 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1144 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1145 SetLastError(0xdeadbeef);
1146 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, 0);
1147 todo_wine
1148 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1149 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1150 /* GetLastError() returns nonsense in win2k3 */
1151 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1152 NULL, 0);
1153 todo_wine
1154 ok(!ret, "Expected failure, got %d\n", ret);
1155 SetLastError(0xdeadbeef);
1156 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1157 (PBYTE)friendlyName, buflen);
1158 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1159 SetLastError(0xdeadbeef);
1160 ret = pSetupDiGetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, NULL, 0, NULL);
1161 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1162 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1163 SetLastError(0xdeadbeef);
1164 ret = pSetupDiGetDeviceRegistryPropertyA(set, NULL, -1, NULL, NULL, 0, NULL);
1165 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1166 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1167 SetLastError(0xdeadbeef);
1168 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, NULL, 0, NULL);
1169 todo_wine
1170 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1171 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1172 /* GetLastError() returns nonsense in win2k3 */
1173 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1174 NULL, NULL, buflen, NULL);
1175 ok(!ret, "Expected failure, got %d\n", ret);
1176 SetLastError(0xdeadbeef);
1177 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1178 NULL, NULL, 0, &size);
1179 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1180 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1181 ok(buflen == size, "Unexpected size: %d\n", size);
1182 SetLastError(0xdeadbeef);
1183 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1184 NULL, (PBYTE)buf, buflen, NULL);
1185 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1186 ok(!lstrcmpiA(friendlyName, buf), "Unexpected property\n");
1187 SetLastError(0xdeadbeef);
1188 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1189 &regType, (PBYTE)buf, buflen, NULL);
1190 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1191 ok(!lstrcmpiA(friendlyName, buf), "Unexpected value of property\n");
1192 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
1193 SetLastError(0xdeadbeef);
1194 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1195 NULL, 0);
1196 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1197 SetLastError(0xdeadbeef);
1198 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1199 NULL, (PBYTE)buf, buflen, &size);
1200 todo_wine
1201 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1202 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
1203 pSetupDiDestroyDeviceInfoList(set);
1205 res = RegOpenKeyA(HKEY_LOCAL_MACHINE, bogus, &key);
1206 todo_wine
1207 ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n");
1208 /* FIXME: Remove when Wine is fixed */
1209 if (res == ERROR_SUCCESS)
1211 /* Wine doesn't delete the information currently */
1212 trace("We are most likely on Wine\n");
1213 RegDeleteKeyA(HKEY_LOCAL_MACHINE, bogus);
1217 static void testDeviceRegistryPropertyW()
1219 HDEVINFO set;
1220 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
1221 WCHAR devName[] = {'L','E','G','A','C','Y','_','B','O','G','U','S',0};
1222 WCHAR friendlyName[] = {'B','o','g','u','s',0};
1223 WCHAR buf[6] = {0};
1224 DWORD buflen = 6 * sizeof(WCHAR);
1225 DWORD size;
1226 DWORD regType;
1227 BOOL ret;
1228 LONG res;
1229 HKEY key;
1230 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
1231 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1232 'E','n','u','m','\\','R','o','o','t','\\',
1233 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
1235 SetLastError(0xdeadbeef);
1236 set = pSetupDiGetClassDevsW(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1237 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsW failed: %08x\n",
1238 GetLastError());
1239 SetLastError(0xdeadbeef);
1240 ret = pSetupDiCreateDeviceInfoW(set, devName, &guid, NULL, NULL,
1241 DICD_GENERATE_ID, &devInfo);
1242 ok(ret, "SetupDiCreateDeviceInfoW failed: %08x\n", GetLastError());
1243 SetLastError(0xdeadbeef);
1244 ret = pSetupDiSetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, 0);
1245 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1246 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1247 SetLastError(0xdeadbeef);
1248 ret = pSetupDiSetDeviceRegistryPropertyW(set, NULL, -1, NULL, 0);
1249 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1250 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1251 SetLastError(0xdeadbeef);
1252 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, 0);
1253 todo_wine
1254 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1255 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1256 /* GetLastError() returns nonsense in win2k3 */
1257 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1258 NULL, 0);
1259 todo_wine
1260 ok(!ret, "Expected failure, got %d\n", ret);
1261 SetLastError(0xdeadbeef);
1262 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1263 (PBYTE)friendlyName, buflen);
1264 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1265 SetLastError(0xdeadbeef);
1266 ret = pSetupDiGetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, NULL, 0, NULL);
1267 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1268 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1269 SetLastError(0xdeadbeef);
1270 ret = pSetupDiGetDeviceRegistryPropertyW(set, NULL, -1, NULL, NULL, 0, NULL);
1271 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1272 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1273 SetLastError(0xdeadbeef);
1274 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, NULL, 0, NULL);
1275 todo_wine
1276 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1277 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1278 /* GetLastError() returns nonsense in win2k3 */
1279 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1280 NULL, NULL, buflen, NULL);
1281 ok(!ret, "Expected failure, got %d\n", ret);
1282 SetLastError(0xdeadbeef);
1283 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1284 NULL, NULL, 0, &size);
1285 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1286 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1287 ok(buflen == size, "Unexpected size: %d\n", size);
1288 SetLastError(0xdeadbeef);
1289 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1290 NULL, (PBYTE)buf, buflen, NULL);
1291 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1292 ok(!lstrcmpiW(friendlyName, buf), "Unexpected property\n");
1293 SetLastError(0xdeadbeef);
1294 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1295 &regType, (PBYTE)buf, buflen, NULL);
1296 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1297 ok(!lstrcmpiW(friendlyName, buf), "Unexpected value of property\n");
1298 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
1299 SetLastError(0xdeadbeef);
1300 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1301 NULL, 0);
1302 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1303 SetLastError(0xdeadbeef);
1304 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1305 NULL, (PBYTE)buf, buflen, &size);
1306 todo_wine
1307 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1308 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
1309 pSetupDiDestroyDeviceInfoList(set);
1311 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
1312 todo_wine
1313 ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n");
1314 /* FIXME: Remove when Wine is fixed */
1315 if (res == ERROR_SUCCESS)
1317 /* Wine doesn't delete the information currently */
1318 trace("We are most likely on Wine\n");
1319 RegDeleteKeyW(HKEY_LOCAL_MACHINE, bogus);
1323 START_TEST(devinst)
1325 HDEVINFO set;
1327 init_function_pointers();
1329 /* Win9x/WinMe does things totally different so we skip all the tests
1331 * We don't want to exclude NT4 so hence this check.
1333 SetLastError(0xdeadbeef);
1334 set = pSetupDiGetClassDevsW(NULL, NULL, 0, 0);
1335 if (set == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1337 skip("Win9x/WinMe has totally different behavior\n");
1338 return;
1341 if (pSetupDiCreateDeviceInfoListExW && pSetupDiDestroyDeviceInfoList)
1342 test_SetupDiCreateDeviceInfoListEx();
1343 else
1344 skip("SetupDiCreateDeviceInfoListExW and/or SetupDiDestroyDeviceInfoList not available\n");
1346 if (pSetupDiOpenClassRegKeyExA)
1347 test_SetupDiOpenClassRegKeyExA();
1348 else
1349 skip("SetupDiOpenClassRegKeyExA is not available\n");
1351 testInstallClass();
1352 testCreateDeviceInfo();
1353 testGetDeviceInstanceId();
1354 testRegisterDeviceInfo();
1355 testCreateDeviceInterface();
1356 testGetDeviceInterfaceDetail();
1357 testDevRegKey();
1358 testRegisterAndGetDetail();
1359 testDeviceRegistryPropertyA();
1360 testDeviceRegistryPropertyW();