setupapi/tests: Remove leftovers from old tests.
[wine.git] / dlls / setupapi / tests / devinst.c
blobcd72db42168ee16a8454543b1e097b2817f8bf80
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;
187 static void test_SetupDiCreateDeviceInfoListEx(void)
189 HDEVINFO devlist;
190 BOOL ret;
191 DWORD error;
192 static CHAR notnull[] = "NotNull";
193 static const WCHAR machine[] = { 'd','u','m','m','y',0 };
195 SetLastError(0xdeadbeef);
196 /* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */
197 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, notnull);
199 error = GetLastError();
200 if (error == ERROR_CALL_NOT_IMPLEMENTED)
202 skip("SetupDiCreateDeviceInfoListExW is not implemented\n");
203 return;
205 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
206 ok(error == ERROR_INVALID_PARAMETER, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_PARAMETER);
208 SetLastError(0xdeadbeef);
209 /* create empty DeviceInfoList, but set MachineName to something */
210 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL);
212 error = GetLastError();
213 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
214 ok(error == ERROR_INVALID_MACHINENAME, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_MACHINENAME);
216 /* create empty DeviceInfoList */
217 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
218 ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE);
220 /* destroy DeviceInfoList */
221 ret = pSetupDiDestroyDeviceInfoList(devlist);
222 ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error);
225 static void test_SetupDiOpenClassRegKeyExA(void)
227 static const CHAR guidString[] = "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
228 HKEY hkey;
230 /* Check return value for nonexistent key */
231 hkey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
232 DIOCR_INSTALLER, NULL, NULL);
233 ok(hkey == INVALID_HANDLE_VALUE,
234 "returned %p (expected INVALID_HANDLE_VALUE)\n", hkey);
236 /* Test it for a key that exists */
237 hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS);
238 if (hkey != INVALID_HANDLE_VALUE)
240 HKEY classKey;
241 if (RegCreateKeyA(hkey, guidString, &classKey) == ERROR_SUCCESS)
243 RegCloseKey(classKey);
244 SetLastError(0xdeadbeef);
245 classKey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
246 DIOCR_INSTALLER, NULL, NULL);
247 ok(classKey != INVALID_HANDLE_VALUE,
248 "opening class registry key failed with error %d\n",
249 GetLastError());
250 if (classKey != INVALID_HANDLE_VALUE)
251 RegCloseKey(classKey);
252 RegDeleteKeyA(hkey, guidString);
254 else
255 trace("failed to create registry key for test\n");
257 RegCloseKey(hkey);
259 else
260 trace("failed to open classes key\n");
263 static void append_str(char **str, const char *data)
265 sprintf(*str, data);
266 *str += strlen(*str);
269 static void create_inf_file(LPCSTR filename)
271 char data[1024];
272 char *ptr = data;
273 DWORD dwNumberOfBytesWritten;
274 HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
275 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
277 append_str(&ptr, "[Version]\n");
278 append_str(&ptr, "Signature=\"$Chicago$\"\n");
279 append_str(&ptr, "Class=Bogus\n");
280 append_str(&ptr, "ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n");
281 append_str(&ptr, "[ClassInstall32]\n");
282 append_str(&ptr, "AddReg=BogusClass.NT.AddReg\n");
283 append_str(&ptr, "[BogusClass.NT.AddReg]\n");
284 append_str(&ptr, "HKR,,,,\"Wine test devices\"\n");
286 WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
287 CloseHandle(hf);
290 static void get_temp_filename(LPSTR path)
292 static char curr[MAX_PATH] = { 0 };
293 char temp[MAX_PATH];
294 LPSTR ptr;
296 if (!*curr)
297 GetCurrentDirectoryA(MAX_PATH, curr);
298 GetTempFileNameA(curr, "set", 0, temp);
299 ptr = strrchr(temp, '\\');
301 lstrcpyA(path, ptr + 1);
304 static void testInstallClass(void)
306 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
307 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
308 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
309 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
310 '1','1','d','b','-','b','7','0','4','-',
311 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
312 static const CHAR classKey_win9x[] =
313 "System\\CurrentControlSet\\Services\\Class\\"
314 "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
315 static const CHAR bogus_win9x[] =
316 "System\\CurrentControlSet\\Services\\Class\\Bogus";
317 char tmpfile[MAX_PATH];
318 BOOL ret;
319 HKEY hkey;
321 if (!pSetupDiInstallClassA)
323 skip("No SetupDiInstallClassA\n");
324 return;
326 tmpfile[0] = '.';
327 tmpfile[1] = '\\';
328 get_temp_filename(tmpfile + 2);
329 create_inf_file(tmpfile + 2);
331 ret = pSetupDiInstallClassA(NULL, NULL, 0, NULL);
332 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
333 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
334 ret = pSetupDiInstallClassA(NULL, NULL, DI_NOVCP, NULL);
335 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
336 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
337 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, DI_NOVCP, NULL);
338 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
339 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
340 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, 0, NULL);
341 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
342 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
343 /* The next call will succeed. Information is put into the registry but the
344 * location(s) is/are depending on the Windows version.
346 ret = pSetupDiInstallClassA(NULL, tmpfile, 0, NULL);
347 ok(ret, "SetupDiInstallClassA failed: %08x\n", GetLastError());
348 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, classKey_win9x, &hkey))
350 /* We are on win9x */
351 RegCloseKey(hkey);
352 ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, classKey_win9x),
353 "Couldn't delete win9x classkey\n");
354 ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, bogus_win9x),
355 "Couldn't delete win9x bogus services class\n");
357 else
359 /* NT4 and above */
360 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey),
361 "Couldn't delete NT classkey\n");
363 DeleteFile(tmpfile);
366 static void testCreateDeviceInfo(void)
368 BOOL ret;
369 HDEVINFO set;
370 HKEY key;
371 LONG res;
372 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
373 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
374 'E','n','u','m','\\','R','o','o','t','\\',
375 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
377 if (!pSetupDiCreateDeviceInfoList || !pSetupDiEnumDeviceInfo ||
378 !pSetupDiDestroyDeviceInfoList || !pSetupDiCreateDeviceInfoA)
380 skip("No SetupDiCreateDeviceInfoA\n");
381 return;
383 SetLastError(0xdeadbeef);
384 ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
385 ok(!ret, "Expected failure\n");
386 ok(GetLastError() == ERROR_INVALID_DEVINST_NAME ||
387 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */ ||
388 GetLastError() == ERROR_INVALID_HANDLE /* Win9x */,
389 "Unexpected last error, got %08x\n", GetLastError());
391 /* If we are running on win9x we should skip these tests. Win95
392 * fails most tests anyway and win98 pops up the "Add New Hardware
393 * Wizard".
395 if (GetLastError() == ERROR_INVALID_HANDLE)
397 skip("We are on win9x where the tests introduce issues\n");
398 return;
401 SetLastError(0xdeadbeef);
402 ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL,
403 NULL, NULL, 0, NULL);
404 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
405 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
406 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
407 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
408 GetLastError());
409 if (set)
411 SP_DEVINFO_DATA devInfo = { 0 };
412 DWORD i;
413 static GUID deadbeef =
414 {0xdeadbeef, 0xdead, 0xbeef, {0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
416 /* No GUID given */
417 SetLastError(0xdeadbeef);
418 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL,
419 NULL, NULL, 0, NULL);
420 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
421 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
422 /* We can't add device information to the set with a different GUID */
423 SetLastError(0xdeadbeef);
424 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000",
425 &deadbeef, NULL, NULL, 0, NULL);
426 ok(!ret && GetLastError() == ERROR_CLASS_MISMATCH,
427 "Expected ERROR_CLASS_MISMATCH, got %08x\n", GetLastError());
428 /* Finally, with all three required parameters, this succeeds: */
429 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
430 NULL, NULL, 0, NULL);
431 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
432 /* This fails because the device ID already exists.. */
433 SetLastError(0xdeadbeef);
434 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
435 NULL, NULL, 0, &devInfo);
436 ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
437 "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError());
438 /* whereas this "fails" because cbSize is wrong.. */
439 SetLastError(0xdeadbeef);
440 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
441 DICD_GENERATE_ID, &devInfo);
442 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
443 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
444 /* and this finally succeeds. */
445 devInfo.cbSize = sizeof(devInfo);
446 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
447 DICD_GENERATE_ID, &devInfo);
448 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
449 /* There were three devices added, however - the second failure just
450 * resulted in the SP_DEVINFO_DATA not getting copied.
452 SetLastError(0xdeadbeef);
453 i = 0;
454 while (pSetupDiEnumDeviceInfo(set, i, &devInfo))
455 i++;
456 ok(i == 3, "Expected 3 devices, got %d\n", i);
457 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
458 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
459 pSetupDiDestroyDeviceInfoList(set);
462 /* The bogus registry key shouldn't be there after this test. The only
463 * reasons this key would still be present:
465 * - We are running on Wine which has to be fixed
466 * - We have leftovers from old tests
468 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
469 todo_wine
470 ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n");
471 if (res == ERROR_SUCCESS)
473 DWORD subkeys;
475 /* Check if we have subkeys */
476 RegQueryInfoKey(key, NULL, NULL, NULL, &subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
477 if (subkeys > 0)
479 int i;
481 /* Leftovers from old tests */
482 trace("Going to remove %d devices\n", subkeys);
483 for (i = 0; i < subkeys; i++)
485 BOOL ret;
487 ret = remove_device();
488 ok(ret, "Expected a device to be removed\n");
491 else
493 /* Wine doesn't delete the bogus key itself currently */
494 trace("We are most likely on Wine\n");
495 RegDeleteKeyW(HKEY_LOCAL_MACHINE, bogus);
500 static void testGetDeviceInstanceId(void)
502 BOOL ret;
503 HDEVINFO set;
504 SP_DEVINFO_DATA devInfo = { 0 };
506 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
507 !pSetupDiCreateDeviceInfoA || !pSetupDiGetDeviceInstanceIdA)
509 skip("No SetupDiGetDeviceInstanceIdA\n");
510 return;
512 SetLastError(0xdeadbeef);
513 ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
514 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
515 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
516 SetLastError(0xdeadbeef);
517 ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, NULL, 0, NULL);
518 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
519 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
520 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
521 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
522 GetLastError());
523 if (set)
525 char instanceID[MAX_PATH];
526 DWORD size;
528 SetLastError(0xdeadbeef);
529 ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
530 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
531 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
532 SetLastError(0xdeadbeef);
533 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL);
534 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
535 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
536 SetLastError(0xdeadbeef);
537 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
538 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
539 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
540 devInfo.cbSize = sizeof(devInfo);
541 SetLastError(0xdeadbeef);
542 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
543 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
544 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
545 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
546 NULL, NULL, 0, &devInfo);
547 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
548 SetLastError(0xdeadbeef);
549 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
550 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
551 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
552 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
553 sizeof(instanceID), NULL);
554 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
555 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"),
556 "Unexpected instance ID %s\n", instanceID);
557 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid,
558 NULL, NULL, DICD_GENERATE_ID, &devInfo);
559 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
560 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
561 sizeof(instanceID), NULL);
562 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
563 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"),
564 "Unexpected instance ID %s\n", instanceID);
565 pSetupDiDestroyDeviceInfoList(set);
569 static void testRegisterDeviceInfo(void)
571 BOOL ret;
572 HDEVINFO set;
574 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
575 !pSetupDiRegisterDeviceInfo)
577 skip("No SetupDiRegisterDeviceInfo\n");
578 return;
580 SetLastError(0xdeadbeef);
581 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
582 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
583 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
584 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
585 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
586 if (set)
588 SP_DEVINFO_DATA devInfo = { 0 };
590 SetLastError(0xdeadbeef);
591 ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
592 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
593 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
594 SetLastError(0xdeadbeef);
595 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
596 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
597 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
598 devInfo.cbSize = sizeof(devInfo);
599 SetLastError(0xdeadbeef);
600 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
601 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
602 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
603 ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid,
604 NULL, NULL, 0, &devInfo);
605 ok(ret || GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
606 "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
607 if (ret)
609 /* If it already existed, registering it again will fail */
610 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL,
611 NULL);
612 ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
614 /* FIXME: On Win2K+ systems, this is now persisted to registry in
615 * HKLM\System\CCS\Enum\USB\Bogus\0000. I don't check because the
616 * Win9x location is different.
617 * FIXME: the key also becomes undeletable. How to get rid of it?
619 pSetupDiDestroyDeviceInfoList(set);
623 static void testCreateDeviceInterface(void)
625 BOOL ret;
626 HDEVINFO set;
627 HKEY key;
628 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
629 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
630 'E','n','u','m','\\','R','o','o','t','\\',
631 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
632 static const WCHAR devclass[] = {'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 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
635 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
636 '1','1','d','b','-','b','7','0','4','-',
637 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
639 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
640 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
641 !pSetupDiEnumDeviceInterfaces)
643 skip("No SetupDiCreateDeviceInterfaceA\n");
644 return;
646 SetLastError(0xdeadbeef);
647 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL);
648 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
649 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
650 SetLastError(0xdeadbeef);
651 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL);
652 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
653 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
654 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
655 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
656 if (set)
658 SP_DEVINFO_DATA devInfo = { 0 };
659 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
660 { 0 } };
661 DWORD i;
663 SetLastError(0xdeadbeef);
664 ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL);
665 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
666 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
667 SetLastError(0xdeadbeef);
668 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
669 NULL);
670 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
671 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
672 devInfo.cbSize = sizeof(devInfo);
673 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
674 NULL, NULL, 0, &devInfo);
675 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
676 SetLastError(0xdeadbeef);
677 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
678 NULL);
679 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
680 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
681 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
682 NULL);
683 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
684 /* Creating the same interface a second time succeeds */
685 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
686 NULL);
687 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
688 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0,
689 NULL);
690 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
691 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0,
692 &interfaceData);
693 ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError());
694 i = 0;
695 while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i,
696 &interfaceData))
697 i++;
698 ok(i == 2, "expected 2 interfaces, got %d\n", i);
699 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
700 "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
701 pSetupDiDestroyDeviceInfoList(set);
703 /* Cleanup */
704 /* FIXME: On Wine we still have the bogus entry in Enum\Root and
705 * subkeys, as well as the deviceclass key with subkeys.
706 * Only do the RegDeleteKey, once Wine is fixed.
708 if (!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key))
710 /* Wine doesn't delete the information currently */
711 trace("We are most likely on Wine\n");
712 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
713 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
715 else
717 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, devclass),
718 "Couldn't delete deviceclass key\n");
723 static void testGetDeviceInterfaceDetail(void)
725 BOOL ret;
726 HDEVINFO set;
727 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
728 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
729 'E','n','u','m','\\','R','o','o','t','\\',
730 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
731 static const WCHAR devclass[] = {'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 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
734 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
735 '1','1','d','b','-','b','7','0','4','-',
736 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
738 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
739 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
740 !pSetupDiGetDeviceInterfaceDetailA)
742 skip("No SetupDiGetDeviceInterfaceDetailA\n");
743 return;
745 SetLastError(0xdeadbeef);
746 ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL);
747 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
748 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
749 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
750 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
751 if (set)
753 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
754 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
755 { 0 } };
756 DWORD size = 0;
757 HKEY key;
759 SetLastError(0xdeadbeef);
760 ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL,
761 NULL);
762 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
763 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
764 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
765 NULL, NULL, 0, &devInfo);
766 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
767 SetLastError(0xdeadbeef);
768 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
769 &interfaceData);
770 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
771 SetLastError(0xdeadbeef);
772 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
773 0, NULL, NULL);
774 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
775 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
776 SetLastError(0xdeadbeef);
777 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
778 100, NULL, NULL);
779 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
780 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
781 SetLastError(0xdeadbeef);
782 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
783 0, &size, NULL);
784 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
785 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
786 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
788 static const char path[] =
789 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
790 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
791 SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail =
792 (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf;
793 DWORD expectedsize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR)*(1 + strlen(path));
795 detail->cbSize = 0;
796 SetLastError(0xdeadbeef);
797 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
798 size, &size, NULL);
799 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
800 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
801 detail->cbSize = size;
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 = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
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 /* Windows 2000 and up check for the exact size. Win9x returns ERROR_INVALID_PARAMETER
814 * on every call (so doesn't get here) and NT4 doesn't have this function.
816 detail->cbSize = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
817 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
818 size, &size, NULL);
819 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n",
820 GetLastError());
821 ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
822 detail->DevicePath);
823 /* Check SetupDiGetDeviceInterfaceDetailW */
824 if (pSetupDiGetDeviceInterfaceDetailW)
826 ret = pSetupDiGetDeviceInterfaceDetailW(set, &interfaceData, NULL, 0, &size, NULL);
827 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got error code: %d\n", GetLastError());
828 ok(expectedsize == size, "SetupDiGetDeviceInterfaceDetailW returned wrong reqsize: expected %d, got %d\n", expectedsize, size);
830 else
831 skip("SetupDiGetDeviceInterfaceDetailW is not available\n");
833 HeapFree(GetProcessHeap(), 0, buf);
835 pSetupDiDestroyDeviceInfoList(set);
837 /* Cleanup */
838 /* FIXME: On Wine we still have the bogus entry in Enum\Root and
839 * subkeys, as well as the deviceclass key with subkeys.
840 * Only do the RegDeleteKey, once Wine is fixed.
842 if (!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key))
844 /* Wine doesn't delete the information currently */
845 trace("We are most likely on Wine\n");
846 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
847 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
849 else
851 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, devclass),
852 "Couldn't delete deviceclass key\n");
857 static void testDevRegKey(void)
859 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
860 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
861 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
862 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
863 '1','1','d','b','-','b','7','0','4','-',
864 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
865 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
866 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
867 'E','n','u','m','\\','R','o','o','t','\\',
868 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
869 BOOL ret;
870 HDEVINFO set;
871 HKEY key = NULL;
873 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
874 !pSetupDiCreateDeviceInfoA || !pSetupDiOpenDevRegKey ||
875 !pSetupDiRegisterDeviceInfo || !pSetupDiCreateDevRegKeyW ||
876 !pSetupDiCallClassInstaller)
878 skip("No SetupDiOpenDevRegKey\n");
879 return;
882 /* Check if we are on win9x */
883 SetLastError(0xdeadbeef);
884 key = pSetupDiCreateDevRegKeyW(NULL, NULL, 0, 0, 0, NULL, NULL);
885 if (key == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
887 skip("We are on win9x where the tests introduce issues\n");
888 return;
890 ok(key == INVALID_HANDLE_VALUE,
891 "Expected INVALID_HANDLE_VALUE, got %p\n", key);
892 ok(GetLastError() == ERROR_INVALID_HANDLE,
893 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
895 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
896 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
897 if (set)
899 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
900 LONG res;
902 /* The device info key shouldn't be there */
903 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
904 ok(res != ERROR_SUCCESS, "Expected key to not exist\n");
905 RegCloseKey(key);
906 /* Create the device information */
907 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
908 NULL, NULL, 0, &devInfo);
909 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
910 /* The device info key should have been created */
911 ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key),
912 "Expected registry key to exist\n");
913 RegCloseKey(key);
914 SetLastError(0xdeadbeef);
915 key = pSetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0);
916 ok(!key || key == INVALID_HANDLE_VALUE,
917 "Expected INVALID_HANDLE_VALUE or a NULL key (NT4)\n");
918 ok(GetLastError() == ERROR_INVALID_HANDLE,
919 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
920 SetLastError(0xdeadbeef);
921 key = pSetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0);
922 ok(key == INVALID_HANDLE_VALUE &&
923 GetLastError() == ERROR_INVALID_PARAMETER,
924 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
925 SetLastError(0xdeadbeef);
926 key = pSetupDiOpenDevRegKey(set, &devInfo, 0, 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, 0, 0);
932 ok(key == INVALID_HANDLE_VALUE &&
933 GetLastError() == ERROR_INVALID_FLAGS,
934 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
935 SetLastError(0xdeadbeef);
936 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
937 DIREG_BOTH, 0);
938 ok(key == INVALID_HANDLE_VALUE &&
939 GetLastError() == ERROR_INVALID_FLAGS,
940 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
941 SetLastError(0xdeadbeef);
942 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
943 DIREG_DRV, 0);
944 ok(key == INVALID_HANDLE_VALUE &&
945 GetLastError() == ERROR_DEVINFO_NOT_REGISTERED,
946 "Expected ERROR_DEVINFO_NOT_REGISTERED, got %08x\n", GetLastError());
947 SetLastError(0xdeadbeef);
948 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
949 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
950 SetLastError(0xdeadbeef);
951 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
952 DIREG_DRV, 0);
953 /* The software key isn't created by default */
954 todo_wine
955 ok(key == INVALID_HANDLE_VALUE &&
956 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
957 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
958 SetLastError(0xdeadbeef);
959 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
960 DIREG_DEV, 0);
961 todo_wine
962 ok(key == INVALID_HANDLE_VALUE &&
963 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
964 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
965 SetLastError(0xdeadbeef);
966 /* The class key shouldn't be there */
967 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key);
968 todo_wine
969 ok(res != ERROR_SUCCESS, "Expected key to not exist\n");
970 RegCloseKey(key);
971 /* Create the device reg key */
972 key = pSetupDiCreateDevRegKeyW(set, &devInfo, DICS_FLAG_GLOBAL, 0,
973 DIREG_DRV, NULL, NULL);
974 ok(key != INVALID_HANDLE_VALUE, "SetupDiCreateDevRegKey failed: %08x\n",
975 GetLastError());
976 RegCloseKey(key);
977 /* The class key should have been created */
978 ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key),
979 "Expected registry key to exist\n");
980 RegCloseKey(key);
981 SetLastError(0xdeadbeef);
982 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
983 DIREG_DRV, 0);
984 todo_wine
985 ok(key == INVALID_HANDLE_VALUE &&
986 (GetLastError() == ERROR_INVALID_DATA ||
987 GetLastError() == ERROR_ACCESS_DENIED), /* win2k3 */
988 "Expected ERROR_INVALID_DATA or ERROR_ACCESS_DENIED, got %08x\n", GetLastError());
989 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
990 DIREG_DRV, KEY_READ);
991 ok(key != INVALID_HANDLE_VALUE, "SetupDiOpenDevRegKey failed: %08x\n",
992 GetLastError());
993 pSetupDiDestroyDeviceInfoList(set);
995 /* Cleanup */
996 ret = remove_device();
997 todo_wine
998 ok(ret, "Expected the device to be removed: %08x\n", GetLastError());
1000 /* FIXME: Only do the RegDeleteKey, once Wine is fixed */
1001 if (!ret)
1003 /* Wine doesn't delete the information currently */
1004 trace("We are most likely on Wine\n");
1005 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
1006 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
1008 else
1010 /* There should only be a class key entry, so a simple
1011 * RegDeleteKey should work
1013 * This could fail if it's the first time for this new test
1014 * after running the old tests.
1016 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey),
1017 "Couldn't delete classkey\n");
1022 static void testRegisterAndGetDetail(void)
1024 HDEVINFO set;
1025 BOOL ret;
1026 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
1027 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), { 0 } };
1028 DWORD dwSize = 0;
1029 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
1030 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1031 'E','n','u','m','\\','R','o','o','t','\\',
1032 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
1033 static const WCHAR devclass[] = {'S','y','s','t','e','m','\\',
1034 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1035 'C','o','n','t','r','o','l','\\','D','e','v','i','c','e','C','l','a','s','s','e','s','\\',
1036 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
1037 '1','1','d','b','-','b','7','0','4','-',
1038 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
1040 SetLastError(0xdeadbeef);
1041 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_ALLCLASSES);
1042 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
1043 GetLastError());
1045 SetLastError(0xdeadbeef);
1046 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, 0,
1047 DICD_GENERATE_ID, &devInfo);
1048 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
1049 SetLastError(0xdeadbeef);
1050 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, &interfaceData);
1051 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
1052 SetLastError(0xdeadbeef);
1053 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
1054 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
1056 pSetupDiDestroyDeviceInfoList(set);
1058 SetLastError(0xdeadbeef);
1059 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1060 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
1061 GetLastError());
1063 SetLastError(0xdeadbeef);
1064 ret = pSetupDiEnumDeviceInterfaces(set, NULL, &guid, 0, &interfaceData);
1065 ok(ret, "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
1066 SetLastError(0xdeadbeef);
1067 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, 0, &dwSize, NULL);
1068 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1069 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1070 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1072 static const char path[] =
1073 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
1074 PSP_DEVICE_INTERFACE_DETAIL_DATA_A detail = NULL;
1076 detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)HeapAlloc(GetProcessHeap(), 0, dwSize);
1077 if (detail)
1079 detail->cbSize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char);
1080 SetLastError(0xdeadbeef);
1081 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData,
1082 detail, dwSize, &dwSize, NULL);
1083 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %08x\n", GetLastError());
1084 /* FIXME: This one only worked because old data wasn't removed properly. As soon
1085 * as all the tests are cleaned up correctly this has to be (or should be) fixed
1087 todo_wine
1088 ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
1089 detail->DevicePath);
1090 HeapFree(GetProcessHeap(), 0, detail);
1094 pSetupDiDestroyDeviceInfoList(set);
1096 /* Cleanup */
1097 ret = remove_device();
1098 todo_wine
1099 ok(ret, "Expected the device to be removed: %08x\n", GetLastError());
1101 /* FIXME: Only do the RegDeleteKey, once Wine is fixed */
1102 if (!ret)
1104 /* Wine doesn't delete the information currently */
1105 trace("We are most likely on Wine\n");
1106 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus);
1107 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass);
1109 else
1111 /* There should only be a class key entry, so a simple
1112 * RegDeleteKey should work
1114 ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, devclass),
1115 "Couldn't delete classkey\n");
1119 static void testDeviceRegistryPropertyA()
1121 HDEVINFO set;
1122 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
1123 CHAR devName[] = "LEGACY_BOGUS";
1124 CHAR friendlyName[] = "Bogus";
1125 CHAR buf[6] = "";
1126 DWORD buflen = 6;
1127 DWORD size;
1128 DWORD regType;
1129 BOOL ret;
1130 LONG res;
1131 HKEY key;
1132 static const CHAR bogus[] =
1133 "System\\CurrentControlSet\\Enum\\Root\\LEGACY_BOGUS";
1135 SetLastError(0xdeadbeef);
1136 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1137 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
1138 GetLastError());
1139 SetLastError(0xdeadbeef);
1140 ret = pSetupDiCreateDeviceInfoA(set, devName, &guid, NULL, NULL,
1141 DICD_GENERATE_ID, &devInfo);
1142 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
1143 SetLastError(0xdeadbeef);
1144 ret = pSetupDiSetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, 0);
1145 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1146 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1147 SetLastError(0xdeadbeef);
1148 ret = pSetupDiSetDeviceRegistryPropertyA(set, NULL, -1, NULL, 0);
1149 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1150 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1151 SetLastError(0xdeadbeef);
1152 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, 0);
1153 todo_wine
1154 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1155 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1156 /* GetLastError() returns nonsense in win2k3 */
1157 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1158 NULL, 0);
1159 todo_wine
1160 ok(!ret, "Expected failure, got %d\n", ret);
1161 SetLastError(0xdeadbeef);
1162 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1163 (PBYTE)friendlyName, buflen);
1164 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1165 SetLastError(0xdeadbeef);
1166 ret = pSetupDiGetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, NULL, 0, NULL);
1167 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1168 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1169 SetLastError(0xdeadbeef);
1170 ret = pSetupDiGetDeviceRegistryPropertyA(set, NULL, -1, NULL, NULL, 0, NULL);
1171 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1172 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1173 SetLastError(0xdeadbeef);
1174 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, NULL, 0, NULL);
1175 todo_wine
1176 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1177 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1178 /* GetLastError() returns nonsense in win2k3 */
1179 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1180 NULL, NULL, buflen, NULL);
1181 ok(!ret, "Expected failure, got %d\n", ret);
1182 SetLastError(0xdeadbeef);
1183 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1184 NULL, NULL, 0, &size);
1185 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1186 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1187 ok(buflen == size, "Unexpected size: %d\n", size);
1188 SetLastError(0xdeadbeef);
1189 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1190 NULL, (PBYTE)buf, buflen, NULL);
1191 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1192 ok(!lstrcmpiA(friendlyName, buf), "Unexpected property\n");
1193 SetLastError(0xdeadbeef);
1194 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1195 &regType, (PBYTE)buf, buflen, NULL);
1196 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1197 ok(!lstrcmpiA(friendlyName, buf), "Unexpected value of property\n");
1198 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
1199 SetLastError(0xdeadbeef);
1200 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1201 NULL, 0);
1202 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
1203 SetLastError(0xdeadbeef);
1204 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
1205 NULL, (PBYTE)buf, buflen, &size);
1206 todo_wine
1207 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1208 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
1209 pSetupDiDestroyDeviceInfoList(set);
1211 res = RegOpenKeyA(HKEY_LOCAL_MACHINE, bogus, &key);
1212 todo_wine
1213 ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n");
1214 /* FIXME: Remove when Wine is fixed */
1215 if (res == ERROR_SUCCESS)
1217 /* Wine doesn't delete the information currently */
1218 trace("We are most likely on Wine\n");
1219 RegDeleteKeyA(HKEY_LOCAL_MACHINE, bogus);
1223 static void testDeviceRegistryPropertyW()
1225 HDEVINFO set;
1226 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
1227 WCHAR devName[] = {'L','E','G','A','C','Y','_','B','O','G','U','S',0};
1228 WCHAR friendlyName[] = {'B','o','g','u','s',0};
1229 WCHAR buf[6] = {0};
1230 DWORD buflen = 6 * sizeof(WCHAR);
1231 DWORD size;
1232 DWORD regType;
1233 BOOL ret;
1234 LONG res;
1235 HKEY key;
1236 static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
1237 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1238 'E','n','u','m','\\','R','o','o','t','\\',
1239 'L','E','G','A','C','Y','_','B','O','G','U','S',0};
1241 SetLastError(0xdeadbeef);
1242 set = pSetupDiGetClassDevsW(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1243 if (set == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1245 skip("W-functions are not implemented\n");
1246 return;
1248 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsW failed: %08x\n",
1249 GetLastError());
1250 SetLastError(0xdeadbeef);
1251 ret = pSetupDiCreateDeviceInfoW(set, devName, &guid, NULL, NULL,
1252 DICD_GENERATE_ID, &devInfo);
1253 ok(ret, "SetupDiCreateDeviceInfoW failed: %08x\n", GetLastError());
1254 SetLastError(0xdeadbeef);
1255 ret = pSetupDiSetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, 0);
1256 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1257 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1258 SetLastError(0xdeadbeef);
1259 ret = pSetupDiSetDeviceRegistryPropertyW(set, NULL, -1, NULL, 0);
1260 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1261 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1262 SetLastError(0xdeadbeef);
1263 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, 0);
1264 todo_wine
1265 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1266 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1267 /* GetLastError() returns nonsense in win2k3 */
1268 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1269 NULL, 0);
1270 todo_wine
1271 ok(!ret, "Expected failure, got %d\n", ret);
1272 SetLastError(0xdeadbeef);
1273 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1274 (PBYTE)friendlyName, buflen);
1275 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1276 SetLastError(0xdeadbeef);
1277 ret = pSetupDiGetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, NULL, 0, NULL);
1278 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1279 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1280 SetLastError(0xdeadbeef);
1281 ret = pSetupDiGetDeviceRegistryPropertyW(set, NULL, -1, NULL, NULL, 0, NULL);
1282 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1283 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1284 SetLastError(0xdeadbeef);
1285 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, NULL, 0, NULL);
1286 todo_wine
1287 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1288 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1289 /* GetLastError() returns nonsense in win2k3 */
1290 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1291 NULL, NULL, buflen, NULL);
1292 ok(!ret, "Expected failure, got %d\n", ret);
1293 SetLastError(0xdeadbeef);
1294 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1295 NULL, NULL, 0, &size);
1296 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1297 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1298 ok(buflen == size, "Unexpected size: %d\n", size);
1299 SetLastError(0xdeadbeef);
1300 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1301 NULL, (PBYTE)buf, buflen, NULL);
1302 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1303 ok(!lstrcmpiW(friendlyName, buf), "Unexpected property\n");
1304 SetLastError(0xdeadbeef);
1305 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1306 &regType, (PBYTE)buf, buflen, NULL);
1307 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1308 ok(!lstrcmpiW(friendlyName, buf), "Unexpected value of property\n");
1309 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
1310 SetLastError(0xdeadbeef);
1311 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1312 NULL, 0);
1313 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1314 SetLastError(0xdeadbeef);
1315 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1316 NULL, (PBYTE)buf, buflen, &size);
1317 todo_wine
1318 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1319 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
1320 pSetupDiDestroyDeviceInfoList(set);
1322 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
1323 todo_wine
1324 ok(res == ERROR_FILE_NOT_FOUND, "Expected key to not exist\n");
1325 /* FIXME: Remove when Wine is fixed */
1326 if (res == ERROR_SUCCESS)
1328 /* Wine doesn't delete the information currently */
1329 trace("We are most likely on Wine\n");
1330 RegDeleteKeyW(HKEY_LOCAL_MACHINE, bogus);
1334 START_TEST(devinst)
1336 init_function_pointers();
1338 if (pSetupDiCreateDeviceInfoListExW && pSetupDiDestroyDeviceInfoList)
1339 test_SetupDiCreateDeviceInfoListEx();
1340 else
1341 skip("SetupDiCreateDeviceInfoListExW and/or SetupDiDestroyDeviceInfoList not available\n");
1343 if (pSetupDiOpenClassRegKeyExA)
1344 test_SetupDiOpenClassRegKeyExA();
1345 else
1346 skip("SetupDiOpenClassRegKeyExA is not available\n");
1347 testInstallClass();
1348 testCreateDeviceInfo();
1349 testGetDeviceInstanceId();
1350 testRegisterDeviceInfo();
1351 testCreateDeviceInterface();
1352 testGetDeviceInterfaceDetail();
1353 testDevRegKey();
1354 testRegisterAndGetDetail();
1355 testDeviceRegistryPropertyA();
1356 testDeviceRegistryPropertyW();