push ad05fa8ea86b4a1581adad6c24ad723042d385d2
[wine/hacks.git] / dlls / setupapi / tests / devinst.c
blob5dda333e98ce24bb02b4db32f0e6a60f206ef0b1
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 *pSetupDiGetDeviceInstanceIdA)(HDEVINFO, PSP_DEVINFO_DATA, PSTR, DWORD, PDWORD);
49 static BOOL (WINAPI *pSetupDiGetDeviceInterfaceDetailA)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA);
50 static BOOL (WINAPI *pSetupDiRegisterDeviceInfo)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PSP_DETSIG_CMPPROC, PVOID, PSP_DEVINFO_DATA);
52 static void init_function_pointers(void)
54 hSetupAPI = GetModuleHandleA("setupapi.dll");
56 pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA");
57 pSetupDiCreateDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoList");
58 pSetupDiCreateDeviceInfoListExW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoListExW");
59 pSetupDiCreateDeviceInterfaceA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInterfaceA");
60 pSetupDiDestroyDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiDestroyDeviceInfoList");
61 pSetupDiCallClassInstaller = (void *)GetProcAddress(hSetupAPI, "SetupDiCallClassInstaller");
62 pSetupDiEnumDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInfo");
63 pSetupDiEnumDeviceInterfaces = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInterfaces");
64 pSetupDiGetDeviceInstanceIdA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInstanceIdA");
65 pSetupDiGetDeviceInterfaceDetailA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailA");
66 pSetupDiInstallClassA = (void *)GetProcAddress(hSetupAPI, "SetupDiInstallClassA");
67 pSetupDiOpenClassRegKeyExA = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenClassRegKeyExA");
68 pSetupDiOpenDevRegKey = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenDevRegKey");
69 pSetupDiCreateDevRegKeyW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDevRegKeyW");
70 pSetupDiRegisterDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiRegisterDeviceInfo");
73 /* RegDeleteTreeW from dlls/advapi32/registry.c */
74 LSTATUS WINAPI devinst_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
76 LONG ret;
77 DWORD dwMaxSubkeyLen, dwMaxValueLen;
78 DWORD dwMaxLen, dwSize;
79 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
80 HKEY hSubKey = hKey;
82 if(lpszSubKey)
84 ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
85 if (ret) return ret;
88 /* Get highest length for keys, values */
89 ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
90 &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
91 if (ret) goto cleanup;
93 dwMaxSubkeyLen++;
94 dwMaxValueLen++;
95 dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
96 if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
98 /* Name too big: alloc a buffer for it */
99 if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
101 ret = ERROR_NOT_ENOUGH_MEMORY;
102 goto cleanup;
107 /* Recursively delete all the subkeys */
108 while (TRUE)
110 dwSize = dwMaxLen;
111 if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
112 NULL, NULL, NULL)) break;
114 ret = devinst_RegDeleteTreeW(hSubKey, lpszName);
115 if (ret) goto cleanup;
118 if (lpszSubKey)
119 ret = RegDeleteKeyW(hKey, lpszSubKey);
120 else
121 while (TRUE)
123 dwSize = dwMaxLen;
124 if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
125 NULL, NULL, NULL, NULL)) break;
127 ret = RegDeleteValueW(hKey, lpszName);
128 if (ret) goto cleanup;
131 cleanup:
132 /* Free buffer if allocated */
133 if (lpszName != szNameBuf)
134 HeapFree( GetProcessHeap(), 0, lpszName);
135 if(lpszSubKey)
136 RegCloseKey(hSubKey);
137 return ret;
141 static void test_SetupDiCreateDeviceInfoListEx(void)
143 HDEVINFO devlist;
144 BOOL ret;
145 DWORD error;
146 static CHAR notnull[] = "NotNull";
147 static const WCHAR machine[] = { 'd','u','m','m','y',0 };
149 SetLastError(0xdeadbeef);
150 /* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */
151 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, notnull);
153 error = GetLastError();
154 if (error == ERROR_CALL_NOT_IMPLEMENTED)
156 skip("SetupDiCreateDeviceInfoListExW is not implemented\n");
157 return;
159 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
160 ok(error == ERROR_INVALID_PARAMETER, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_PARAMETER);
162 SetLastError(0xdeadbeef);
163 /* create empty DeviceInfoList, but set MachineName to something */
164 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL);
166 error = GetLastError();
167 ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
168 ok(error == ERROR_INVALID_MACHINENAME, "GetLastError returned wrong value : %d, (expected %d)\n", error, ERROR_INVALID_MACHINENAME);
170 /* create empty DeviceInfoList */
171 devlist = pSetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
172 ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %d (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE);
174 /* destroy DeviceInfoList */
175 ret = pSetupDiDestroyDeviceInfoList(devlist);
176 ok(ret, "SetupDiDestroyDeviceInfoList failed : %d\n", error);
179 static void test_SetupDiOpenClassRegKeyExA(void)
181 /* This is a unique guid for testing purposes */
182 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
183 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
184 static const CHAR guidString[] = "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
185 HKEY hkey;
187 /* Check return value for nonexistent key */
188 hkey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
189 DIOCR_INSTALLER, NULL, NULL);
190 ok(hkey == INVALID_HANDLE_VALUE,
191 "returned %p (expected INVALID_HANDLE_VALUE)\n", hkey);
193 /* Test it for a key that exists */
194 hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS);
195 if (hkey != INVALID_HANDLE_VALUE)
197 HKEY classKey;
198 if (RegCreateKeyA(hkey, guidString, &classKey) == ERROR_SUCCESS)
200 RegCloseKey(classKey);
201 SetLastError(0xdeadbeef);
202 classKey = pSetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS,
203 DIOCR_INSTALLER, NULL, NULL);
204 ok(classKey != INVALID_HANDLE_VALUE,
205 "opening class registry key failed with error %d\n",
206 GetLastError());
207 if (classKey != INVALID_HANDLE_VALUE)
208 RegCloseKey(classKey);
209 RegDeleteKeyA(hkey, guidString);
211 else
212 trace("failed to create registry key for test\n");
214 else
215 trace("failed to open classes key\n");
218 static void append_str(char **str, const char *data)
220 sprintf(*str, data);
221 *str += strlen(*str);
224 static void create_inf_file(LPCSTR filename)
226 char data[1024];
227 char *ptr = data;
228 DWORD dwNumberOfBytesWritten;
229 HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
230 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
232 append_str(&ptr, "[Version]\n");
233 append_str(&ptr, "Signature=\"$Chicago$\"\n");
234 append_str(&ptr, "Class=Bogus\n");
235 append_str(&ptr, "ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n");
236 append_str(&ptr, "[ClassInstall32]\n");
237 append_str(&ptr, "AddReg=BogusClass.NT.AddReg\n");
238 append_str(&ptr, "[BogusClass.NT.AddReg]\n");
239 append_str(&ptr, "HKR,,,,\"Wine test devices\"\n");
241 WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
242 CloseHandle(hf);
245 static void get_temp_filename(LPSTR path)
247 static char curr[MAX_PATH] = { 0 };
248 char temp[MAX_PATH];
249 LPSTR ptr;
251 if (!*curr)
252 GetCurrentDirectoryA(MAX_PATH, curr);
253 GetTempFileNameA(curr, "set", 0, temp);
254 ptr = strrchr(temp, '\\');
256 lstrcpyA(path, ptr + 1);
259 static void testInstallClass(void)
261 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
262 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
263 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
264 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
265 '1','1','d','b','-','b','7','0','4','-',
266 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
267 char tmpfile[MAX_PATH];
268 BOOL ret;
270 if (!pSetupDiInstallClassA)
272 skip("No SetupDiInstallClassA\n");
273 return;
275 tmpfile[0] = '.';
276 tmpfile[1] = '\\';
277 get_temp_filename(tmpfile + 2);
278 create_inf_file(tmpfile + 2);
280 ret = pSetupDiInstallClassA(NULL, NULL, 0, NULL);
281 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
282 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
283 ret = pSetupDiInstallClassA(NULL, NULL, DI_NOVCP, NULL);
284 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
285 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
286 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, DI_NOVCP, NULL);
287 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
288 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
289 ret = pSetupDiInstallClassA(NULL, tmpfile + 2, 0, NULL);
290 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
291 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
292 ret = pSetupDiInstallClassA(NULL, tmpfile, 0, NULL);
293 ok(ret, "SetupDiInstallClassA failed: %08x\n", GetLastError());
294 RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey);
295 DeleteFile(tmpfile);
298 static void testCreateDeviceInfo(void)
300 BOOL ret;
301 HDEVINFO set;
302 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
303 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
305 if (!pSetupDiCreateDeviceInfoList || !pSetupDiEnumDeviceInfo ||
306 !pSetupDiDestroyDeviceInfoList || !pSetupDiCreateDeviceInfoA)
308 skip("No SetupDiCreateDeviceInfoA\n");
309 return;
311 SetLastError(0xdeadbeef);
312 ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
313 ok(!ret && GetLastError() == ERROR_INVALID_DEVINST_NAME,
314 "Expected ERROR_INVALID_DEVINST_NAME, got %08x\n", GetLastError());
315 SetLastError(0xdeadbeef);
316 ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL,
317 NULL, NULL, 0, NULL);
318 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
319 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
320 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
321 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
322 GetLastError());
323 if (set)
325 SP_DEVINFO_DATA devInfo = { 0 };
326 DWORD i;
328 SetLastError(0xdeadbeef);
329 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL,
330 NULL, NULL, 0, NULL);
331 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
332 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
333 /* Finally, with all three required parameters, this succeeds: */
334 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
335 NULL, NULL, 0, NULL);
336 ok(ret, "pSetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
337 /* This fails because the device ID already exists.. */
338 SetLastError(0xdeadbeef);
339 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
340 NULL, NULL, 0, &devInfo);
341 ok(!ret && GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
342 "Expected ERROR_DEVINST_ALREADY_EXISTS, got %08x\n", GetLastError());
343 /* whereas this "fails" because cbSize is wrong.. */
344 SetLastError(0xdeadbeef);
345 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
346 DICD_GENERATE_ID, &devInfo);
347 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
348 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
349 devInfo.cbSize = sizeof(devInfo);
350 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL,
351 DICD_GENERATE_ID, &devInfo);
352 /* and this finally succeeds. */
353 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
354 /* There were three devices added, however - the second failure just
355 * resulted in the SP_DEVINFO_DATA not getting copied.
357 SetLastError(0xdeadbeef);
358 i = 0;
359 while (pSetupDiEnumDeviceInfo(set, i, &devInfo))
360 i++;
361 ok(i == 3, "Expected 3 devices, got %d\n", i);
362 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
363 "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
364 pSetupDiDestroyDeviceInfoList(set);
368 static void testGetDeviceInstanceId(void)
370 BOOL ret;
371 HDEVINFO set;
372 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
373 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
374 SP_DEVINFO_DATA devInfo = { 0 };
376 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
377 !pSetupDiCreateDeviceInfoA || !pSetupDiGetDeviceInstanceIdA)
379 skip("No SetupDiGetDeviceInstanceIdA\n");
380 return;
382 SetLastError(0xdeadbeef);
383 ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
384 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
385 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
386 SetLastError(0xdeadbeef);
387 ret = pSetupDiGetDeviceInstanceIdA(NULL, &devInfo, NULL, 0, NULL);
388 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
389 "Expected ERROR_INVALID_HANDLEHANDLE, got %08x\n", GetLastError());
390 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
391 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %08x\n",
392 GetLastError());
393 if (set)
395 char instanceID[MAX_PATH];
396 DWORD size;
398 SetLastError(0xdeadbeef);
399 ret = pSetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
400 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
401 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
402 SetLastError(0xdeadbeef);
403 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, NULL);
404 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
405 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
406 SetLastError(0xdeadbeef);
407 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
408 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
409 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
410 devInfo.cbSize = sizeof(devInfo);
411 SetLastError(0xdeadbeef);
412 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
413 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
414 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
415 ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid,
416 NULL, NULL, 0, &devInfo);
417 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
418 SetLastError(0xdeadbeef);
419 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, NULL, 0, &size);
420 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
421 "Expected ERROR_INSUFFICIENT_BUFFER, got %08x\n", GetLastError());
422 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
423 sizeof(instanceID), NULL);
424 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
425 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0000"),
426 "Unexpected instance ID %s\n", instanceID);
427 ret = pSetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid,
428 NULL, NULL, DICD_GENERATE_ID, &devInfo);
429 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
430 ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID,
431 sizeof(instanceID), NULL);
432 ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError());
433 ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"),
434 "Unexpected instance ID %s\n", instanceID);
435 pSetupDiDestroyDeviceInfoList(set);
439 static void testRegisterDeviceInfo(void)
441 BOOL ret;
442 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
443 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
444 HDEVINFO set;
446 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
447 !pSetupDiRegisterDeviceInfo)
449 skip("No SetupDiRegisterDeviceInfo\n");
450 return;
452 SetLastError(0xdeadbeef);
453 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
454 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
455 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
456 ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
457 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
458 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
459 if (set)
461 SP_DEVINFO_DATA devInfo = { 0 };
463 SetLastError(0xdeadbeef);
464 ret = pSetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
465 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
466 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
467 SetLastError(0xdeadbeef);
468 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
469 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
470 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
471 devInfo.cbSize = sizeof(devInfo);
472 SetLastError(0xdeadbeef);
473 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
474 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
475 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
476 ret = pSetupDiCreateDeviceInfoA(set, "USB\\BOGUS\\0000", &guid,
477 NULL, NULL, 0, &devInfo);
478 ok(ret || GetLastError() == ERROR_DEVINST_ALREADY_EXISTS,
479 "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
480 if (ret)
482 /* If it already existed, registering it again will fail */
483 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL,
484 NULL);
485 ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError());
487 /* FIXME: On Win2K+ systems, this is now persisted to registry in
488 * HKLM\System\CCS\Enum\USB\Bogus\0000. I don't check because the
489 * Win9x location is different.
490 * FIXME: the key also becomes undeletable. How to get rid of it?
492 pSetupDiDestroyDeviceInfoList(set);
496 static void testCreateDeviceInterface(void)
498 BOOL ret;
499 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
500 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
501 HDEVINFO set;
503 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
504 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
505 !pSetupDiEnumDeviceInterfaces)
507 skip("No SetupDiCreateDeviceInterfaceA\n");
508 return;
510 SetLastError(0xdeadbeef);
511 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL);
512 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
513 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
514 SetLastError(0xdeadbeef);
515 ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL);
516 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
517 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
518 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
519 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
520 if (set)
522 SP_DEVINFO_DATA devInfo = { 0 };
523 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
524 { 0 } };
525 DWORD i;
527 SetLastError(0xdeadbeef);
528 ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL);
529 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
530 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
531 SetLastError(0xdeadbeef);
532 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
533 NULL);
534 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
535 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
536 devInfo.cbSize = sizeof(devInfo);
537 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
538 NULL, NULL, 0, &devInfo);
539 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
540 SetLastError(0xdeadbeef);
541 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0,
542 NULL);
543 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
544 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
545 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
546 NULL);
547 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
548 /* Creating the same interface a second time succeeds */
549 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
550 NULL);
551 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
552 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0,
553 NULL);
554 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
555 ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0,
556 &interfaceData);
557 ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError());
558 i = 0;
559 while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i,
560 &interfaceData))
561 i++;
562 ok(i == 2, "expected 2 interfaces, got %d\n", i);
563 ok(GetLastError() == ERROR_NO_MORE_ITEMS,
564 "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError());
565 pSetupDiDestroyDeviceInfoList(set);
569 static void testGetDeviceInterfaceDetail(void)
571 BOOL ret;
572 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
573 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
574 HDEVINFO set;
576 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
577 !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA ||
578 !pSetupDiGetDeviceInterfaceDetailA)
580 skip("No SetupDiGetDeviceInterfaceDetailA\n");
581 return;
583 SetLastError(0xdeadbeef);
584 ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL);
585 ok(!ret && GetLastError() == ERROR_INVALID_HANDLE,
586 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
587 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
588 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
589 if (set)
591 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
592 SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData),
593 { 0 } };
594 DWORD size = 0;
596 SetLastError(0xdeadbeef);
597 ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL,
598 NULL);
599 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
600 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
601 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
602 NULL, NULL, 0, &devInfo);
603 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
604 SetLastError(0xdeadbeef);
605 ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0,
606 &interfaceData);
607 ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError());
608 SetLastError(0xdeadbeef);
609 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
610 0, NULL, NULL);
611 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
612 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
613 SetLastError(0xdeadbeef);
614 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
615 100, NULL, NULL);
616 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
617 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
618 SetLastError(0xdeadbeef);
619 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL,
620 0, &size, NULL);
621 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
622 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
623 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
625 static const char path[] =
626 "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
627 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
628 SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail =
629 (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf;
631 detail->cbSize = 0;
632 SetLastError(0xdeadbeef);
633 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
634 size, &size, NULL);
635 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
636 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
637 detail->cbSize = size;
638 SetLastError(0xdeadbeef);
639 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
640 size, &size, NULL);
641 ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER,
642 "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError());
643 detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
644 ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail,
645 size, &size, NULL);
646 ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n",
647 GetLastError());
648 ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n",
649 detail->DevicePath);
650 HeapFree(GetProcessHeap(), 0, buf);
652 pSetupDiDestroyDeviceInfoList(set);
656 static void testDevRegKey(void)
658 static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
659 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
660 'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
661 '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
662 '1','1','d','b','-','b','7','0','4','-',
663 '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
664 BOOL ret;
665 GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,
666 0x00,0x11,0x95,0x5c,0x2b,0xdb}};
667 HDEVINFO set;
669 if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList ||
670 !pSetupDiCreateDeviceInfoA || !pSetupDiOpenDevRegKey ||
671 !pSetupDiRegisterDeviceInfo || !pSetupDiCreateDevRegKeyW ||
672 !pSetupDiCallClassInstaller)
674 skip("No SetupDiOpenDevRegKey\n");
675 return;
677 set = pSetupDiCreateDeviceInfoList(&guid, NULL);
678 ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError());
679 if (set)
681 SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
682 HKEY key = INVALID_HANDLE_VALUE;
684 ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid,
685 NULL, NULL, 0, &devInfo);
686 ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
687 SetLastError(0xdeadbeef);
688 key = pSetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0);
689 ok(key == INVALID_HANDLE_VALUE &&
690 GetLastError() == ERROR_INVALID_HANDLE,
691 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
692 SetLastError(0xdeadbeef);
693 key = pSetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0);
694 ok(key == INVALID_HANDLE_VALUE &&
695 GetLastError() == ERROR_INVALID_PARAMETER,
696 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
697 SetLastError(0xdeadbeef);
698 key = pSetupDiOpenDevRegKey(set, &devInfo, 0, 0, 0, 0);
699 ok(key == INVALID_HANDLE_VALUE &&
700 GetLastError() == ERROR_INVALID_FLAGS,
701 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
702 SetLastError(0xdeadbeef);
703 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0, 0, 0);
704 ok(key == INVALID_HANDLE_VALUE &&
705 GetLastError() == ERROR_INVALID_FLAGS,
706 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
707 SetLastError(0xdeadbeef);
708 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
709 DIREG_BOTH, 0);
710 ok(key == INVALID_HANDLE_VALUE &&
711 GetLastError() == ERROR_INVALID_FLAGS,
712 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
713 SetLastError(0xdeadbeef);
714 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
715 DIREG_DRV, 0);
716 ok(key == INVALID_HANDLE_VALUE &&
717 GetLastError() == ERROR_DEVINFO_NOT_REGISTERED,
718 "Expected ERROR_DEVINFO_NOT_REGISTERED, got %08x\n", GetLastError());
719 SetLastError(0xdeadbeef);
720 ret = pSetupDiRegisterDeviceInfo(set, &devInfo, 0, NULL, NULL, NULL);
721 ok(ret, "SetupDiRegisterDeviceInfo failed: %08x\n", GetLastError());
722 SetLastError(0xdeadbeef);
723 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
724 DIREG_DRV, 0);
725 /* The software key isn't created by default */
726 todo_wine
727 ok(key == INVALID_HANDLE_VALUE &&
728 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
729 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
730 SetLastError(0xdeadbeef);
731 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
732 DIREG_DEV, 0);
733 todo_wine
734 ok(key == INVALID_HANDLE_VALUE &&
735 GetLastError() == ERROR_KEY_DOES_NOT_EXIST,
736 "Expected ERROR_KEY_DOES_NOT_EXIST_EXIST, got %08x\n", GetLastError());
737 SetLastError(0xdeadbeef);
738 key = pSetupDiCreateDevRegKeyW(set, &devInfo, DICS_FLAG_GLOBAL, 0,
739 DIREG_DRV, NULL, NULL);
740 ok(key != INVALID_HANDLE_VALUE, "SetupDiCreateDevRegKey failed: %08x\n",
741 GetLastError());
742 RegCloseKey(key);
743 SetLastError(0xdeadbeef);
744 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
745 DIREG_DRV, 0);
746 todo_wine
747 ok(key == INVALID_HANDLE_VALUE &&
748 GetLastError() == ERROR_INVALID_DATA,
749 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
750 key = pSetupDiOpenDevRegKey(set, &devInfo, DICS_FLAG_GLOBAL, 0,
751 DIREG_DRV, KEY_READ);
752 ok(key != INVALID_HANDLE_VALUE, "SetupDiOpenDevRegKey failed: %08x\n",
753 GetLastError());
754 ret = pSetupDiCallClassInstaller(DIF_REMOVE, set, &devInfo);
755 pSetupDiDestroyDeviceInfoList(set);
757 devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
760 START_TEST(devinst)
762 init_function_pointers();
764 if (pSetupDiCreateDeviceInfoListExW && pSetupDiDestroyDeviceInfoList)
765 test_SetupDiCreateDeviceInfoListEx();
766 else
767 skip("SetupDiCreateDeviceInfoListExW and/or SetupDiDestroyDeviceInfoList not available\n");
769 if (pSetupDiOpenClassRegKeyExA)
770 test_SetupDiOpenClassRegKeyExA();
771 else
772 skip("SetupDiOpenClassRegKeyExA is not available\n");
773 testInstallClass();
774 testCreateDeviceInfo();
775 testGetDeviceInstanceId();
776 testRegisterDeviceInfo();
777 testCreateDeviceInterface();
778 testGetDeviceInterfaceDetail();
779 testDevRegKey();