push 6fe5edf8439c19d3885814583531c2f2b1495177
[wine/hacks.git] / dlls / setupapi / tests / devinst.c
blobf3f6c99ca924ebec78803e443161b9e3ad42d5ba
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 static void init_function_pointers(void)
62 hSetupAPI = GetModuleHandleA("setupapi.dll");
64 pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA");
65 pSetupDiCreateDeviceInfoW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoW");
66 pSetupDiCreateDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoList");
67 pSetupDiCreateDeviceInfoListExW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoListExW");
68 pSetupDiCreateDeviceInterfaceA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInterfaceA");
69 pSetupDiDestroyDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiDestroyDeviceInfoList");
70 pSetupDiCallClassInstaller = (void *)GetProcAddress(hSetupAPI, "SetupDiCallClassInstaller");
71 pSetupDiEnumDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInfo");
72 pSetupDiEnumDeviceInterfaces = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInterfaces");
73 pSetupDiGetDeviceInstanceIdA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInstanceIdA");
74 pSetupDiGetDeviceInterfaceDetailA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailA");
75 pSetupDiGetDeviceInterfaceDetailW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailW");
76 pSetupDiInstallClassA = (void *)GetProcAddress(hSetupAPI, "SetupDiInstallClassA");
77 pSetupDiOpenClassRegKeyExA = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenClassRegKeyExA");
78 pSetupDiOpenDevRegKey = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenDevRegKey");
79 pSetupDiCreateDevRegKeyW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDevRegKeyW");
80 pSetupDiRegisterDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiRegisterDeviceInfo");
81 pSetupDiGetClassDevsA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsA");
82 pSetupDiGetClassDevsW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetClassDevsW");
83 pSetupDiSetDeviceRegistryPropertyA = (void *)GetProcAddress(hSetupAPI, "SetupDiSetDeviceRegistryPropertyA");
84 pSetupDiSetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiSetDeviceRegistryPropertyW");
85 pSetupDiGetDeviceRegistryPropertyA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyA");
86 pSetupDiGetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyW");
89 /* RegDeleteTreeW from dlls/advapi32/registry.c */
90 LSTATUS WINAPI devinst_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
92 LONG ret;
93 DWORD dwMaxSubkeyLen, dwMaxValueLen;
94 DWORD dwMaxLen, dwSize;
95 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
96 HKEY hSubKey = hKey;
98 if(lpszSubKey)
100 ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
101 if (ret) return ret;
104 /* Get highest length for keys, values */
105 ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
106 &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
107 if (ret) goto cleanup;
109 dwMaxSubkeyLen++;
110 dwMaxValueLen++;
111 dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
112 if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
114 /* Name too big: alloc a buffer for it */
115 if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
117 ret = ERROR_NOT_ENOUGH_MEMORY;
118 goto cleanup;
123 /* Recursively delete all the subkeys */
124 while (TRUE)
126 dwSize = dwMaxLen;
127 if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
128 NULL, NULL, NULL)) break;
130 ret = devinst_RegDeleteTreeW(hSubKey, lpszName);
131 if (ret) goto cleanup;
134 if (lpszSubKey)
135 ret = RegDeleteKeyW(hKey, lpszSubKey);
136 else
137 while (TRUE)
139 dwSize = dwMaxLen;
140 if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
141 NULL, NULL, NULL, NULL)) break;
143 ret = RegDeleteValueW(hKey, lpszName);
144 if (ret) goto cleanup;
147 cleanup:
148 /* Free buffer if allocated */
149 if (lpszName != szNameBuf)
150 HeapFree( GetProcessHeap(), 0, lpszName);
151 if(lpszSubKey)
152 RegCloseKey(hSubKey);
153 return ret;
157 static void test_SetupDiCreateDeviceInfoListEx(void)
159 HDEVINFO devlist;
160 BOOL ret;
161 DWORD error;
162 static CHAR notnull[] = "NotNull";
163 static const WCHAR machine[] = { 'd','u','m','m','y',0 };
165 SetLastError(0xdeadbeef);
166 /* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */
167 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, notnull);
169 error = GetLastError();
170 if (error == ERROR_CALL_NOT_IMPLEMENTED)
172 skip("SetupDiCreateDeviceInfoListExW is not implemented\n");
173 return;
175 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
176 ok(error == ERROR_INVALID_PARAMETER, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_PARAMETER);
178 SetLastError(0xdeadbeef);
179 /* create empty DeviceInfoList, but set MachineName to something */
180 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL);
182 error = GetLastError();
183 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
184 ok(error == ERROR_INVALID_MACHINENAME, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_MACHINENAME);
186 /* create empty DeviceInfoList */
187 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
188 ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE);
190 /* destroy DeviceInfoList */
191 ret = pSetupDiDestroyDeviceInfoList(devlist);
192 ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error);
195 static void test_SetupDiOpenClassRegKeyExA(void)
197 /* This is a unique guid for testing purposes */
198 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
199 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
200 static const CHAR guidString[] = "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
201 HKEY hkey;
203 /* Check return value for nonexistent key */
204 hkey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
205 DIOCR_INSTALLER, NULL, NULL);
206 ok(hkey == INVALID_HANDLE_VALUE,
207 "returned %p (expected INVALID_HANDLE_VALUE)\n", hkey);
209 /* Test it for a key that exists */
210 hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS);
211 if (hkey != INVALID_HANDLE_VALUE)
213 HKEY classKey;
214 if (RegCreateKeyA(hkey, guidString, &classKey) == ERROR_SUCCESS)
216 RegCloseKey(classKey);
217 SetLastError(0xdeadbeef);
218 classKey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
219 DIOCR_INSTALLER, NULL, NULL);
220 ok(classKey != INVALID_HANDLE_VALUE,
221 "opening class registry key failed with error %d\n",
222 GetLastError());
223 if (classKey != INVALID_HANDLE_VALUE)
224 RegCloseKey(classKey);
225 RegDeleteKeyA(hkey, guidString);
227 else
228 trace("failed to create registry key for test\n");
230 else
231 trace("failed to open classes key\n");
234 static void append_str(char **str, const char *data)
236 sprintf(*str, data);
237 *str += strlen(*str);
240 static void create_inf_file(LPCSTR filename)
242 char data[1024];
243 char *ptr = data;
244 DWORD dwNumberOfBytesWritten;
245 HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
246 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
248 append_str(&ptr, "[Version]\n");
249 append_str(&ptr, "Signature=\"$Chicago$\"\n");
250 append_str(&ptr, "Class=Bogus\n");
251 append_str(&ptr, "ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n");
252 append_str(&ptr, "[ClassInstall32]\n");
253 append_str(&ptr, "AddReg=BogusClass.NT.AddReg\n");
254 append_str(&ptr, "[BogusClass.NT.AddReg]\n");
255 append_str(&ptr, "HKR,,,,\"Wine test devices\"\n");
257 WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
258 CloseHandle(hf);
261 static void get_temp_filename(LPSTR path)
263 static char curr[MAX_PATH] = { 0 };
264 char temp[MAX_PATH];
265 LPSTR ptr;
267 if (!*curr)
268 GetCurrentDirectoryA(MAX_PATH, curr);
269 GetTempFileNameA(curr, "set", 0, temp);
270 ptr = strrchr(temp, '\\');
272 lstrcpyA(path, ptr + 1);
275 static void testInstallClass(void)
277 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
278 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
279 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
280 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
281 '1','1','d','b','-','b','7','0','4','-',
282 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
283 char tmpfile[MAX_PATH];
284 BOOL ret;
286 if (!pSetupDiInstallClassA)
288 skip("No SetupDiInstallClassA\n");
289 return;
291 tmpfile[0] = '.';
292 tmpfile[1] = '\\';
293 get_temp_filename(tmpfile + 2);
294 create_inf_file(tmpfile + 2);
296 ret = pSetupDiInstallClassA(NULL, NULL, 0, NULL);
297 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
298 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
299 ret = pSetupDiInstallClassA(NULL, NULL, DI_NOVCP, NULL);
300 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
301 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
302 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, DI_NOVCP, NULL);
303 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
304 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
305 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, 0, NULL);
306 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
307 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
308 ret = pSetupDiInstallClassA(NULL, tmpfile, 0, NULL);
309 ok(ret, "SetupDiInstallClassA failed: %08x\n", GetLastError());
310 RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey);
311 DeleteFile(tmpfile);
314 static void testCreateDeviceInfo(void)
316 BOOL ret;
317 HDEVINFO set;
318 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
319 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
321 if (!pSetupDiCreateDeviceInfoList || !pSetupDiEnumDeviceInfo ||
322 !pSetupDiDestroyDeviceInfoList || !pSetupDiCreateDeviceInfoA)
324 skip("No SetupDiCreateDeviceInfoA\n");
325 return;
327 SetLastError(0xdeadbeef);
328 ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
329 ok(!ret && GetLastError() == ERROR_INVALID_DEVINST_NAME,
330 "Expected ERROR_INVALID_DEVINST_NAME, got %08x\n", GetLastError());
331 SetLastError(0xdeadbeef);
332 ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL,
333 NULL, NULL, 0, NULL);
334 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
335 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
336 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
337 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
338 GetLastError());
339 if (set)
341 SP_DEVINFO_DATA devInfo = { 0 };
342 DWORD i;
344 SetLastError(0xdeadbeef);
345 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL,
346 NULL, NULL, 0, NULL);
347 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
348 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
349 /* Finally, with all three required parameters, this succeeds: */
350 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
351 NULL, NULL, 0, NULL);
352 ok(ret, "pSetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
353 /* This fails because the device ID already exists.. */
354 SetLastError(0xdeadbeef);
355 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
356 NULL, NULL, 0, &devInfo);
357 ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
358 "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError());
359 /* whereas this "fails" because cbSize is wrong.. */
360 SetLastError(0xdeadbeef);
361 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
362 DICD_GENERATE_ID, &devInfo);
363 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
364 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
365 devInfo.cbSize = sizeof(devInfo);
366 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
367 DICD_GENERATE_ID, &devInfo);
368 /* and this finally succeeds. */
369 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
370 /* There were three devices added, however - the second failure just
371 * resulted in the SP_DEVINFO_DATA not getting copied.
373 SetLastError(0xdeadbeef);
374 i = 0;
375 while (pSetupDiEnumDeviceInfo(set, i, &devInfo))
376 i++;
377 ok(i == 3, "Expected 3 devices, got %d\n", i);
378 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
379 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
380 pSetupDiDestroyDeviceInfoList(set);
384 static void testGetDeviceInstanceId(void)
386 BOOL ret;
387 HDEVINFO set;
388 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
389 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
390 SP_DEVINFO_DATA devInfo = { 0 };
392 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
393 !pSetupDiCreateDeviceInfoA || !pSetupDiGetDeviceInstanceIdA)
395 skip("No SetupDiGetDeviceInstanceIdA\n");
396 return;
398 SetLastError(0xdeadbeef);
399 ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
400 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
401 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
402 SetLastError(0xdeadbeef);
403 ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, 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 char instanceID[MAX_PATH];
412 DWORD size;
414 SetLastError(0xdeadbeef);
415 ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
416 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
417 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
418 SetLastError(0xdeadbeef);
419 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL);
420 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
421 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
422 SetLastError(0xdeadbeef);
423 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
424 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
425 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
426 devInfo.cbSize = sizeof(devInfo);
427 SetLastError(0xdeadbeef);
428 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
429 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
430 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
431 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
432 NULL, NULL, 0, &devInfo);
433 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
434 SetLastError(0xdeadbeef);
435 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
436 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
437 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
438 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
439 sizeof(instanceID), NULL);
440 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
441 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"),
442 "Unexpected instance ID %s\n", instanceID);
443 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid,
444 NULL, NULL, DICD_GENERATE_ID, &devInfo);
445 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
446 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
447 sizeof(instanceID), NULL);
448 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
449 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"),
450 "Unexpected instance ID %s\n", instanceID);
451 pSetupDiDestroyDeviceInfoList(set);
455 static void testRegisterDeviceInfo(void)
457 BOOL ret;
458 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
459 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
460 HDEVINFO set;
462 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
463 !pSetupDiRegisterDeviceInfo)
465 skip("No SetupDiRegisterDeviceInfo\n");
466 return;
468 SetLastError(0xdeadbeef);
469 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
470 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
471 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
472 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
473 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
474 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
475 if (set)
477 SP_DEVINFO_DATA devInfo = { 0 };
479 SetLastError(0xdeadbeef);
480 ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
481 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
482 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
483 SetLastError(0xdeadbeef);
484 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
485 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
486 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
487 devInfo.cbSize = sizeof(devInfo);
488 SetLastError(0xdeadbeef);
489 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
490 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
491 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
492 ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid,
493 NULL, NULL, 0, &devInfo);
494 ok(ret || GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
495 "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
496 if (ret)
498 /* If it already existed, registering it again will fail */
499 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL,
500 NULL);
501 ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
503 /* FIXME: On Win2K+ systems, this is now persisted to registry in
504 * HKLM\System\CCS\Enum\USB\Bogus\0000. I don't check because the
505 * Win9x location is different.
506 * FIXME: the key also becomes undeletable. How to get rid of it?
508 pSetupDiDestroyDeviceInfoList(set);
512 static void testCreateDeviceInterface(void)
514 BOOL ret;
515 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
516 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
517 HDEVINFO set;
519 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
520 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
521 !pSetupDiEnumDeviceInterfaces)
523 skip("No SetupDiCreateDeviceInterfaceA\n");
524 return;
526 SetLastError(0xdeadbeef);
527 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL);
528 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
529 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
530 SetLastError(0xdeadbeef);
531 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL);
532 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
533 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
534 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
535 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
536 if (set)
538 SP_DEVINFO_DATA devInfo = { 0 };
539 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
540 { 0 } };
541 DWORD i;
543 SetLastError(0xdeadbeef);
544 ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL);
545 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
546 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
547 SetLastError(0xdeadbeef);
548 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
549 NULL);
550 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
551 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
552 devInfo.cbSize = sizeof(devInfo);
553 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
554 NULL, NULL, 0, &devInfo);
555 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
556 SetLastError(0xdeadbeef);
557 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
558 NULL);
559 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
560 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
561 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
562 NULL);
563 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
564 /* Creating the same interface a second time succeeds */
565 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
566 NULL);
567 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
568 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0,
569 NULL);
570 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
571 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0,
572 &interfaceData);
573 ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError());
574 i = 0;
575 while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i,
576 &interfaceData))
577 i++;
578 ok(i == 2, "expected 2 interfaces, got %d\n", i);
579 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
580 "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
581 pSetupDiDestroyDeviceInfoList(set);
585 static void testGetDeviceInterfaceDetail(void)
587 BOOL ret;
588 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
589 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
590 HDEVINFO set;
592 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
593 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
594 !pSetupDiGetDeviceInterfaceDetailA)
596 skip("No SetupDiGetDeviceInterfaceDetailA\n");
597 return;
599 SetLastError(0xdeadbeef);
600 ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL);
601 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
602 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
603 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
604 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
605 if (set)
607 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
608 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
609 { 0 } };
610 DWORD size = 0;
612 SetLastError(0xdeadbeef);
613 ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL,
614 NULL);
615 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
616 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
617 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
618 NULL, NULL, 0, &devInfo);
619 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
620 SetLastError(0xdeadbeef);
621 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
622 &interfaceData);
623 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
624 SetLastError(0xdeadbeef);
625 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
626 0, NULL, NULL);
627 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
628 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
629 SetLastError(0xdeadbeef);
630 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
631 100, NULL, NULL);
632 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
633 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
634 SetLastError(0xdeadbeef);
635 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
636 0, &size, NULL);
637 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
638 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
639 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
641 static const char path[] =
642 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
643 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
644 SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail =
645 (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf;
646 DWORD expectedsize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR)*(1 + strlen(path));
648 detail->cbSize = 0;
649 SetLastError(0xdeadbeef);
650 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
651 size, &size, NULL);
652 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
653 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
654 detail->cbSize = size;
655 SetLastError(0xdeadbeef);
656 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
657 size, &size, NULL);
658 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
659 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
660 detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
661 SetLastError(0xdeadbeef);
662 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
663 size, &size, NULL);
664 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
665 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
666 /* Windows 2000 and up check for the exact size. Win9x returns ERROR_INVALID_PARAMETER
667 * on every call (so doesn't get here) and NT4 doesn't have this function.
669 detail->cbSize = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
670 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
671 size, &size, NULL);
672 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n",
673 GetLastError());
674 ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
675 detail->DevicePath);
676 /* Check SetupDiGetDeviceInterfaceDetailW */
677 if (pSetupDiGetDeviceInterfaceDetailW)
679 ret = pSetupDiGetDeviceInterfaceDetailW(set, &interfaceData, NULL, 0, &size, NULL);
680 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got error code: %d\n", GetLastError());
681 ok(expectedsize == size, "SetupDiGetDeviceInterfaceDetailW returned wrong reqsize: expected %d, got %d\n", expectedsize, size);
683 else
684 skip("SetupDiGetDeviceInterfaceDetailW is not available\n");
686 HeapFree(GetProcessHeap(), 0, buf);
688 pSetupDiDestroyDeviceInfoList(set);
692 static void testDevRegKey(void)
694 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
695 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
696 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
697 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
698 '1','1','d','b','-','b','7','0','4','-',
699 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
700 BOOL ret;
701 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
702 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
703 HDEVINFO set;
705 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
706 !pSetupDiCreateDeviceInfoA || !pSetupDiOpenDevRegKey ||
707 !pSetupDiRegisterDeviceInfo || !pSetupDiCreateDevRegKeyW ||
708 !pSetupDiCallClassInstaller)
710 skip("No SetupDiOpenDevRegKey\n");
711 return;
713 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
714 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
715 if (set)
717 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
718 HKEY key = INVALID_HANDLE_VALUE;
720 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
721 NULL, NULL, 0, &devInfo);
722 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
723 SetLastError(0xdeadbeef);
724 key = pSetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0);
725 ok(key == INVALID_HANDLE_VALUE &&
726 GetLastError() == ERROR_INVALID_HANDLE,
727 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
728 SetLastError(0xdeadbeef);
729 key = pSetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0);
730 ok(key == INVALID_HANDLE_VALUE &&
731 GetLastError() == ERROR_INVALID_PARAMETER,
732 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
733 SetLastError(0xdeadbeef);
734 key = pSetupDiOpenDevRegKey(set, &devInfo, 0, 0, 0, 0);
735 ok(key == INVALID_HANDLE_VALUE &&
736 GetLastError() == ERROR_INVALID_FLAGS,
737 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
738 SetLastError(0xdeadbeef);
739 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 0, 0);
740 ok(key == INVALID_HANDLE_VALUE &&
741 GetLastError() == ERROR_INVALID_FLAGS,
742 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
743 SetLastError(0xdeadbeef);
744 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
745 DIREG_BOTH, 0);
746 ok(key == INVALID_HANDLE_VALUE &&
747 GetLastError() == ERROR_INVALID_FLAGS,
748 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
749 SetLastError(0xdeadbeef);
750 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
751 DIREG_DRV, 0);
752 ok(key == INVALID_HANDLE_VALUE &&
753 GetLastError() == ERROR_DEVINFO_NOT_REGISTERED,
754 "Expected ERROR_DEVINFO_NOT_REGISTERED, got %08x\n", GetLastError());
755 SetLastError(0xdeadbeef);
756 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
757 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
758 SetLastError(0xdeadbeef);
759 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
760 DIREG_DRV, 0);
761 /* The software key isn't created by default */
762 todo_wine
763 ok(key == INVALID_HANDLE_VALUE &&
764 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
765 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
766 SetLastError(0xdeadbeef);
767 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
768 DIREG_DEV, 0);
769 todo_wine
770 ok(key == INVALID_HANDLE_VALUE &&
771 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
772 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
773 SetLastError(0xdeadbeef);
774 key = pSetupDiCreateDevRegKeyW(set, &devInfo, DICS_FLAG_GLOBAL, 0,
775 DIREG_DRV, NULL, NULL);
776 ok(key != INVALID_HANDLE_VALUE, "SetupDiCreateDevRegKey failed: %08x\n",
777 GetLastError());
778 RegCloseKey(key);
779 SetLastError(0xdeadbeef);
780 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
781 DIREG_DRV, 0);
782 todo_wine
783 ok(key == INVALID_HANDLE_VALUE &&
784 GetLastError() == ERROR_INVALID_DATA,
785 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
786 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
787 DIREG_DRV, KEY_READ);
788 ok(key != INVALID_HANDLE_VALUE, "SetupDiOpenDevRegKey failed: %08x\n",
789 GetLastError());
790 ret = pSetupDiCallClassInstaller(DIF_REMOVE, set, &devInfo);
791 pSetupDiDestroyDeviceInfoList(set);
793 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
796 static void testRegisterAndGetDetail(void)
798 HDEVINFO set;
799 BOOL ret;
800 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
801 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
802 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
803 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), { 0 } };
804 DWORD dwSize = 0;
806 SetLastError(0xdeadbeef);
807 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_ALLCLASSES);
808 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
809 GetLastError());
811 SetLastError(0xdeadbeef);
812 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, 0,
813 DICD_GENERATE_ID, &devInfo);
814 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
815 SetLastError(0xdeadbeef);
816 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, &interfaceData);
817 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
818 SetLastError(0xdeadbeef);
819 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
820 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
822 pSetupDiDestroyDeviceInfoList(set);
824 SetLastError(0xdeadbeef);
825 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
826 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
827 GetLastError());
829 SetLastError(0xdeadbeef);
830 ret = pSetupDiEnumDeviceInterfaces(set, NULL, &guid, 0, &interfaceData);
831 ok(ret, "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
832 SetLastError(0xdeadbeef);
833 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, 0, &dwSize, NULL);
834 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
835 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
836 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
838 static const char path[] =
839 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
840 PSP_DEVICE_INTERFACE_DETAIL_DATA_A detail = NULL;
842 detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)HeapAlloc(GetProcessHeap(), 0, dwSize);
843 if (detail)
845 detail->cbSize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char);
846 SetLastError(0xdeadbeef);
847 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData,
848 detail, dwSize, &dwSize, NULL);
849 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %08x\n", GetLastError());
850 ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
851 detail->DevicePath);
852 HeapFree(GetProcessHeap(), 0, detail);
856 pSetupDiDestroyDeviceInfoList(set);
859 static void testDeviceRegistryPropertyA()
861 HDEVINFO set;
862 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
863 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
864 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
865 CHAR devName[] = "LEGACY_BOGUS";
866 CHAR friendlyName[] = "Bogus";
867 CHAR buf[6] = "";
868 DWORD buflen = 6;
869 DWORD size;
870 DWORD regType;
871 BOOL ret;
873 SetLastError(0xdeadbeef);
874 set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
875 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n",
876 GetLastError());
877 SetLastError(0xdeadbeef);
878 ret = pSetupDiCreateDeviceInfoA(set, devName, &guid, NULL, NULL,
879 DICD_GENERATE_ID, &devInfo);
880 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
881 SetLastError(0xdeadbeef);
882 ret = pSetupDiSetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, 0);
883 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
884 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
885 SetLastError(0xdeadbeef);
886 ret = pSetupDiSetDeviceRegistryPropertyA(set, NULL, -1, NULL, 0);
887 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
888 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
889 SetLastError(0xdeadbeef);
890 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, 0);
891 todo_wine
892 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
893 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
894 SetLastError(0xdeadbeef);
895 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
896 NULL, 0);
897 todo_wine
898 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
899 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
900 SetLastError(0xdeadbeef);
901 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
902 (PBYTE)friendlyName, buflen);
903 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
904 SetLastError(0xdeadbeef);
905 ret = pSetupDiGetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, NULL, 0, NULL);
906 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
907 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
908 SetLastError(0xdeadbeef);
909 ret = pSetupDiGetDeviceRegistryPropertyA(set, NULL, -1, NULL, NULL, 0, NULL);
910 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
911 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
912 SetLastError(0xdeadbeef);
913 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, -1, NULL, NULL, 0, NULL);
914 todo_wine
915 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
916 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
917 SetLastError(0xdeadbeef);
918 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
919 NULL, NULL, buflen, NULL);
920 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
921 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
922 SetLastError(0xdeadbeef);
923 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
924 NULL, NULL, 0, &size);
925 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
926 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
927 ok(buflen == size, "Unexpected size: %d\n", size);
928 SetLastError(0xdeadbeef);
929 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
930 NULL, (PBYTE)buf, buflen, NULL);
931 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
932 ok(!lstrcmpiA(friendlyName, buf), "Unexpected property\n");
933 SetLastError(0xdeadbeef);
934 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
935 &regType, (PBYTE)buf, buflen, NULL);
936 ok(ret, "SetupDiGetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
937 ok(!lstrcmpiA(friendlyName, buf), "Unexpected value of property\n");
938 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
939 SetLastError(0xdeadbeef);
940 ret = pSetupDiSetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
941 NULL, 0);
942 ok(ret, "SetupDiSetDeviceRegistryPropertyA failed: %08x\n", GetLastError());
943 SetLastError(0xdeadbeef);
944 ret = pSetupDiGetDeviceRegistryPropertyA(set, &devInfo, SPDRP_FRIENDLYNAME,
945 NULL, (PBYTE)buf, buflen, &size);
946 todo_wine
947 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
948 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
949 pSetupDiDestroyDeviceInfoList(set);
952 static void testDeviceRegistryPropertyW()
954 HDEVINFO set;
955 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
956 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
957 SP_DEVINFO_DATA devInfo = { sizeof(SP_DEVINFO_DATA), { 0 } };
958 WCHAR devName[] = {'L','E','G','A','C','Y','_','B','O','G','U','S',0};
959 WCHAR friendlyName[] = {'B','o','g','u','s',0};
960 WCHAR buf[6] = {0};
961 DWORD buflen = 6 * sizeof(WCHAR);
962 DWORD size;
963 DWORD regType;
964 BOOL ret;
966 SetLastError(0xdeadbeef);
967 set = pSetupDiGetClassDevsW(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
968 ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsW failed: %08x\n",
969 GetLastError());
970 SetLastError(0xdeadbeef);
971 ret = pSetupDiCreateDeviceInfoW(set, devName, &guid, NULL, NULL,
972 DICD_GENERATE_ID, &devInfo);
973 ok(ret, "SetupDiCreateDeviceInfoW failed: %08x\n", GetLastError());
974 SetLastError(0xdeadbeef);
975 ret = pSetupDiSetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, 0);
976 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
977 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
978 SetLastError(0xdeadbeef);
979 ret = pSetupDiSetDeviceRegistryPropertyW(set, NULL, -1, NULL, 0);
980 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
981 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
982 SetLastError(0xdeadbeef);
983 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, 0);
984 todo_wine
985 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
986 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
987 SetLastError(0xdeadbeef);
988 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
989 NULL, 0);
990 todo_wine
991 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
992 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
993 SetLastError(0xdeadbeef);
994 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
995 (PBYTE)friendlyName, buflen);
996 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
997 SetLastError(0xdeadbeef);
998 ret = pSetupDiGetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, NULL, 0, NULL);
999 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
1000 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1001 SetLastError(0xdeadbeef);
1002 ret = pSetupDiGetDeviceRegistryPropertyW(set, NULL, -1, NULL, NULL, 0, NULL);
1003 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1004 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1005 SetLastError(0xdeadbeef);
1006 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, -1, NULL, NULL, 0, NULL);
1007 todo_wine
1008 ok(!ret && GetLastError() == ERROR_INVALID_REG_PROPERTY,
1009 "Expected ERROR_INVALID_REG_PROPERTY, got %08x\n", GetLastError());
1010 SetLastError(0xdeadbeef);
1011 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1012 NULL, NULL, buflen, NULL);
1013 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1014 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
1015 SetLastError(0xdeadbeef);
1016 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1017 NULL, NULL, 0, &size);
1018 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1019 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
1020 ok(buflen == size, "Unexpected size: %d\n", size);
1021 SetLastError(0xdeadbeef);
1022 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1023 NULL, (PBYTE)buf, buflen, NULL);
1024 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1025 ok(!lstrcmpiW(friendlyName, buf), "Unexpected property\n");
1026 SetLastError(0xdeadbeef);
1027 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1028 &regType, (PBYTE)buf, buflen, NULL);
1029 ok(ret, "SetupDiGetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1030 ok(!lstrcmpiW(friendlyName, buf), "Unexpected value of property\n");
1031 ok(regType == REG_SZ, "Unexpected type of property: %d\n", regType);
1032 SetLastError(0xdeadbeef);
1033 ret = pSetupDiSetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1034 NULL, 0);
1035 ok(ret, "SetupDiSetDeviceRegistryPropertyW failed: %08x\n", GetLastError());
1036 SetLastError(0xdeadbeef);
1037 ret = pSetupDiGetDeviceRegistryPropertyW(set, &devInfo, SPDRP_FRIENDLYNAME,
1038 NULL, (PBYTE)buf, buflen, &size);
1039 todo_wine
1040 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1041 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
1042 pSetupDiDestroyDeviceInfoList(set);
1045 START_TEST(devinst)
1047 init_function_pointers();
1049 if (pSetupDiCreateDeviceInfoListExW && pSetupDiDestroyDeviceInfoList)
1050 test_SetupDiCreateDeviceInfoListEx();
1051 else
1052 skip("SetupDiCreateDeviceInfoListExW and/or SetupDiDestroyDeviceInfoList not available\n");
1054 if (pSetupDiOpenClassRegKeyExA)
1055 test_SetupDiOpenClassRegKeyExA();
1056 else
1057 skip("SetupDiOpenClassRegKeyExA is not available\n");
1058 testInstallClass();
1059 testCreateDeviceInfo();
1060 testGetDeviceInstanceId();
1061 testRegisterDeviceInfo();
1062 testCreateDeviceInterface();
1063 testGetDeviceInterfaceDetail();
1064 testDevRegKey();
1065 testRegisterAndGetDetail();
1066 testDeviceRegistryPropertyA();
1067 testDeviceRegistryPropertyW();