1 /*
2  * Devinst tests
3  *
4  * Copyright 2006 Christian Gmeiner
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include <stdarg.h>
22 #include <stdio.h>
23 
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"
31 #include "cfgmgr32.h"
32 
33 #include "wine/heap.h"
34 #include "wine/test.h"
35 
36 #ifdef __REACTOS__
37 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
38 #endif
39 
40 /* This is a unique guid for testing purposes */
41 static GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}};
42 static GUID guid2 = {0x6a55b5a5, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}};
43 
44 static LSTATUS devinst_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
45 {
46     LONG ret;
47     DWORD dwMaxSubkeyLen, dwMaxValueLen;
48     DWORD dwMaxLen, dwSize;
49     WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
50     HKEY hSubKey = hKey;
51 
52     if(lpszSubKey)
53     {
54         ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
55         if (ret) return ret;
56     }
57 
58     /* Get highest length for keys, values */
59     ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
60             &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
61     if (ret) goto cleanup;
62 
63     dwMaxSubkeyLen++;
64     dwMaxValueLen++;
65     dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
66     if (dwMaxLen > ARRAY_SIZE(szNameBuf))
67     {
68         /* Name too big: alloc a buffer for it */
69         if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
70         {
71             ret = ERROR_NOT_ENOUGH_MEMORY;
72             goto cleanup;
73         }
74     }
75 
76 
77     /* Recursively delete all the subkeys */
78     while (TRUE)
79     {
80         dwSize = dwMaxLen;
81         if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
82                           NULL, NULL, NULL)) break;
83 
84         ret = devinst_RegDeleteTreeW(hSubKey, lpszName);
85         if (ret) goto cleanup;
86     }
87 
88     if (lpszSubKey)
89         ret = RegDeleteKeyW(hKey, lpszSubKey);
90     else
91         while (TRUE)
92         {
93             dwSize = dwMaxLen;
94             if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
95                   NULL, NULL, NULL, NULL)) break;
96 
97             ret = RegDeleteValueW(hKey, lpszName);
98             if (ret) goto cleanup;
99         }
100 
101 cleanup:
102     /* Free buffer if allocated */
103     if (lpszName != szNameBuf)
104         HeapFree( GetProcessHeap(), 0, lpszName);
105     if(lpszSubKey)
106         RegCloseKey(hSubKey);
107     return ret;
108 }
109 
110 static void test_create_device_list_ex(void)
111 {
112     static const WCHAR machine[] = { 'd','u','m','m','y',0 };
113     static const WCHAR empty[] = { 0 };
114     static char notnull[] = "NotNull";
115     HDEVINFO set;
116     BOOL ret;
117 
118     SetLastError(0xdeadbeef);
119     set = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, notnull);
120     ok(set == INVALID_HANDLE_VALUE, "Expected failure.\n");
121     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
122 
123     SetLastError(0xdeadbeef);
124     set = SetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL);
125     ok(set == INVALID_HANDLE_VALUE, "Expected failure.\n");
126     ok(GetLastError() == ERROR_INVALID_MACHINENAME
127             || GetLastError() == ERROR_MACHINE_UNAVAILABLE
128             || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
129             "Got unexpected error %#x.\n", GetLastError());
130 
131     set = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
132     ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.", GetLastError());
133 
134     ret = SetupDiDestroyDeviceInfoList(set);
135     ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError());
136 
137     set = SetupDiCreateDeviceInfoListExW(NULL, NULL, empty, NULL);
138     ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.", GetLastError());
139 
140     ret = SetupDiDestroyDeviceInfoList(set);
141     ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError());
142 }
143 
144 static void test_open_class_key(void)
145 {
146     static const char guidstr[] = "{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
147     HKEY root_key, class_key;
148     LONG res;
149 
150     SetLastError(0xdeadbeef);
151     class_key = SetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS, DIOCR_INSTALLER, NULL, NULL);
152     ok(class_key == INVALID_HANDLE_VALUE, "Expected failure.\n");
153 todo_wine
154     ok(GetLastError() == ERROR_INVALID_CLASS, "Got unexpected error %#x.\n", GetLastError());
155 
156     root_key = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS);
157     ok(root_key != INVALID_HANDLE_VALUE, "Failed to open root key, error %#x.\n", GetLastError());
158 
159     res = RegCreateKeyA(root_key, guidstr, &class_key);
160     ok(!res, "Failed to create class key, error %#x.\n", GetLastError());
161     RegCloseKey(class_key);
162 
163     SetLastError(0xdeadbeef);
164     class_key = SetupDiOpenClassRegKeyExA(&guid, KEY_ALL_ACCESS, DIOCR_INSTALLER, NULL, NULL);
165     ok(class_key != INVALID_HANDLE_VALUE, "Failed to open class key, error %#x.\n", GetLastError());
166     RegCloseKey(class_key);
167 
168     RegDeleteKeyA(root_key, guidstr);
169     RegCloseKey(root_key);
170 }
171 
172 static void create_inf_file(LPCSTR filename)
173 {
174     DWORD dwNumberOfBytesWritten;
175     HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
176                             CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
177 
178     static const char data[] =
179         "[Version]\n"
180         "Signature=\"$Chicago$\"\n"
181         "Class=Bogus\n"
182         "ClassGUID={6a55b5a4-3f65-11db-b704-0011955c2bdb}\n"
183         "[ClassInstall32]\n"
184         "AddReg=BogusClass.NT.AddReg\n"
185         "[BogusClass.NT.AddReg]\n"
186         "HKR,,,,\"Wine test devices\"\n";
187 
188     WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
189     CloseHandle(hf);
190 }
191 
192 static void get_temp_filename(LPSTR path)
193 {
194     static char curr[MAX_PATH] = { 0 };
195     char temp[MAX_PATH];
196     LPSTR ptr;
197 
198     if (!*curr)
199         GetCurrentDirectoryA(MAX_PATH, curr);
200     GetTempFileNameA(curr, "set", 0, temp);
201     ptr = strrchr(temp, '\\');
202 
203     lstrcpyA(path, ptr + 1);
204 }
205 
206 static void test_install_class(void)
207 {
208     static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
209      'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
210      'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
211      '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
212      '1','1','d','b','-','b','7','0','4','-',
213      '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
214     char tmpfile[MAX_PATH];
215     BOOL ret;
216 
217     tmpfile[0] = '.';
218     tmpfile[1] = '\\';
219     get_temp_filename(tmpfile + 2);
220     create_inf_file(tmpfile + 2);
221 
222     ret = SetupDiInstallClassA(NULL, NULL, 0, NULL);
223     ok(!ret, "Expected failure.\n");
224     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
225 
226     ret = SetupDiInstallClassA(NULL, NULL, DI_NOVCP, NULL);
227     ok(!ret, "Expected failure.\n");
228     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
229 
230     ret = SetupDiInstallClassA(NULL, tmpfile + 2, DI_NOVCP, NULL);
231     ok(!ret, "Expected failure.\n");
232     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
233 
234     ret = SetupDiInstallClassA(NULL, tmpfile + 2, 0, NULL);
235     ok(!ret, "Expected failure.\n");
236     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Got unexpected error %#x.\n", GetLastError());
237 
238     /* The next call will succeed. Information is put into the registry but the
239      * location(s) is/are depending on the Windows version.
240      */
241     ret = SetupDiInstallClassA(NULL, tmpfile, 0, NULL);
242     ok(ret, "Failed to install class, error %#x.\n", GetLastError());
243 
244     ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey), "Failed to delete class key, error %u.\n", GetLastError());
245     DeleteFileA(tmpfile);
246 }
247 
248 static void check_device_info_(int line, HDEVINFO set, int index, const GUID *class, const char *expect_id)
249 {
250     SP_DEVINFO_DATA device = {sizeof(device)};
251     char id[50];
252     BOOL ret;
253 
254     SetLastError(0xdeadbeef);
255     ret = SetupDiEnumDeviceInfo(set, index, &device);
256     if (expect_id)
257     {
258         ok_(__FILE__, line)(ret, "Got unexpected error %#x.\n", GetLastError());
259         ok_(__FILE__, line)(IsEqualGUID(&device.ClassGuid, class),
260                 "Got unexpected class %s.\n", wine_dbgstr_guid(&device.ClassGuid));
261         ret = SetupDiGetDeviceInstanceIdA(set, &device, id, sizeof(id), NULL);
262         ok_(__FILE__, line)(ret, "Got unexpected error %#x.\n", GetLastError());
263         ok_(__FILE__, line)(!strcasecmp(id, expect_id), "Got unexpected id %s.\n", id);
264     }
265     else
266     {
267         ok_(__FILE__, line)(!ret, "Expected failure.\n");
268         ok_(__FILE__, line)(GetLastError() == ERROR_NO_MORE_ITEMS,
269                 "Got unexpected error %#x.\n", GetLastError());
270     }
271 }
272 #define check_device_info(a,b,c,d) check_device_info_(__LINE__,a,b,c,d)
273 
274 static void test_device_info(void)
275 {
276     static const GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
277     SP_DEVINFO_DATA device = {0}, ret_device = {sizeof(ret_device)};
278     char id[MAX_DEVICE_ID_LEN + 2];
279     HDEVINFO set;
280     BOOL ret;
281 
282     SetLastError(0xdeadbeef);
283     ret = SetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL);
284     ok(!ret, "Expected failure.\n");
285     ok(GetLastError() == ERROR_INVALID_DEVINST_NAME, "Got unexpected error %#x.\n", GetLastError());
286 
287     SetLastError(0xdeadbeef);
288     ret = SetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL, NULL, NULL, 0, NULL);
289     ok(!ret, "Expected failure.\n");
290     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
291 
292     set = SetupDiCreateDeviceInfoList(&guid, NULL);
293     ok(set != INVALID_HANDLE_VALUE, "Failed to create device info, error %#x.\n", GetLastError());
294 
295     SetLastError(0xdeadbeef);
296     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL, NULL, NULL, 0, NULL);
297     ok(!ret, "Expected failure.\n");
298     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
299 
300     SetLastError(0xdeadbeef);
301     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &deadbeef, NULL, NULL, 0, NULL);
302     ok(!ret, "Expected failure.\n");
303     ok(GetLastError() == ERROR_CLASS_MISMATCH, "Got unexpected error %#x.\n", GetLastError());
304 
305     SetLastError(0xdeadbeef);
306     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &GUID_NULL, NULL, NULL, 0, NULL);
307     ok(!ret, "Expected failure.\n");
308     ok(GetLastError() == ERROR_CLASS_MISMATCH, "Got unexpected error %#x.\n", GetLastError());
309 
310     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, NULL);
311     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
312 
313     check_device_info(set, 0, &guid, "ROOT\\LEGACY_BOGUS\\0000");
314     check_device_info(set, 1, &guid, NULL);
315 
316     SetLastError(0xdeadbeef);
317     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device);
318     ok(!ret, "Expected failure.\n");
319     ok(GetLastError() == ERROR_DEVINST_ALREADY_EXISTS, "Got unexpected error %#x.\n", GetLastError());
320 
321     SetLastError(0xdeadbeef);
322     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0001", &guid, NULL, NULL, 0, &device);
323     ok(!ret, "Expected failure.\n");
324     ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError());
325 
326     check_device_info(set, 0, &guid, "ROOT\\LEGACY_BOGUS\\0000");
327     check_device_info(set, 1, &guid, "ROOT\\LEGACY_BOGUS\\0001");
328     check_device_info(set, 2, &guid, NULL);
329 
330     device.cbSize = sizeof(device);
331     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0002", &guid, NULL, NULL, 0, &device);
332     ok(ret, "Got unexpected error %#x.\n", GetLastError());
333     ok(IsEqualGUID(&device.ClassGuid, &guid), "Got unexpected class %s.\n",
334             wine_dbgstr_guid(&device.ClassGuid));
335     ret = SetupDiGetDeviceInstanceIdA(set, &device, id, sizeof(id), NULL);
336     ok(ret, "Got unexpected error %#x.\n", GetLastError());
337     ok(!strcmp(id, "ROOT\\LEGACY_BOGUS\\0002"), "Got unexpected id %s.\n", id);
338 
339     check_device_info(set, 0, &guid, "ROOT\\LEGACY_BOGUS\\0000");
340     check_device_info(set, 1, &guid, "ROOT\\LEGACY_BOGUS\\0001");
341     check_device_info(set, 2, &guid, "ROOT\\LEGACY_BOGUS\\0002");
342     check_device_info(set, 3, &guid, NULL);
343 
344     ret = SetupDiEnumDeviceInfo(set, 0, &ret_device);
345     ok(ret, "Failed to enumerate devices, error %#x.\n", GetLastError());
346     ret = SetupDiDeleteDeviceInfo(set, &ret_device);
347     ok(ret, "Failed to delete device, error %#x.\n", GetLastError());
348 
349     check_device_info(set, 0, &guid, "ROOT\\LEGACY_BOGUS\\0001");
350     check_device_info(set, 1, &guid, "ROOT\\LEGACY_BOGUS\\0002");
351     check_device_info(set, 2, &guid, NULL);
352 
353     ret = SetupDiRemoveDevice(set, &device);
354     ok(ret, "Got unexpected error %#x.\n", GetLastError());
355 
356     check_device_info(set, 0, &guid, "ROOT\\LEGACY_BOGUS\\0001");
357 
358     ret = SetupDiEnumDeviceInfo(set, 1, &ret_device);
359     ok(ret, "Got unexpected error %#x.\n", GetLastError());
360     ok(IsEqualGUID(&ret_device.ClassGuid, &guid), "Got unexpected class %s.\n",
361             wine_dbgstr_guid(&ret_device.ClassGuid));
362     ret = SetupDiGetDeviceInstanceIdA(set, &ret_device, id, sizeof(id), NULL);
363     ok(!ret, "Expected failure.\n");
364     ok(GetLastError() == ERROR_NO_SUCH_DEVINST, "Got unexpected error %#x.\n", GetLastError());
365     ok(ret_device.DevInst == device.DevInst, "Expected device node %#x, got %#x.\n",
366             device.DevInst, ret_device.DevInst);
367 
368     check_device_info(set, 2, &guid, NULL);
369 
370     SetupDiDestroyDeviceInfoList(set);
371 
372     set = SetupDiCreateDeviceInfoList(NULL, NULL);
373     ok(set != INVALID_HANDLE_VALUE, "Failed to create device info, error %#x.\n", GetLastError());
374 
375     SetLastError(0xdeadbeef);
376     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL, NULL, NULL, 0, NULL);
377     ok(!ret, "Expected failure.\n");
378     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
379 
380     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\deadbeef", &deadbeef, NULL, NULL, 0, NULL);
381     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
382 
383     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\null", &GUID_NULL, NULL, NULL, 0, NULL);
384     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
385 
386     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\testguid", &guid, NULL, NULL, 0, NULL);
387     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
388 
389     check_device_info(set, 0, &deadbeef, "ROOT\\LEGACY_BOGUS\\deadbeef");
390     check_device_info(set, 1, &GUID_NULL, "ROOT\\LEGACY_BOGUS\\null");
391     check_device_info(set, 2, &guid, "ROOT\\LEGACY_BOGUS\\testguid");
392     check_device_info(set, 3, NULL, NULL);
393 
394     memset(id, 'x', sizeof(id));
395     memcpy(id, "Root\\LEGACY_BOGUS\\", strlen("Root\\LEGACY_BOGUS\\"));
396     id[MAX_DEVICE_ID_LEN + 1] = 0;
397     SetLastError(0xdeadbeef);
398     ret = SetupDiCreateDeviceInfoA(set, id, &guid, NULL, NULL, 0, NULL);
399     ok(!ret, "Expected failure.\n");
400     ok(GetLastError() == ERROR_INVALID_DEVINST_NAME, "Got unexpected error %#x.\n", GetLastError());
401 
402     id[MAX_DEVICE_ID_LEN] = 0;
403     SetLastError(0xdeadbeef);
404     ret = SetupDiCreateDeviceInfoA(set, id, &guid, NULL, NULL, 0, NULL);
405     ok(!ret, "Expected failure.\n");
406     ok(GetLastError() == ERROR_INVALID_DEVINST_NAME, "Got unexpected error %#x.\n", GetLastError());
407 
408     id[MAX_DEVICE_ID_LEN - 1] = 0;
409     ret = SetupDiCreateDeviceInfoA(set, id, &guid, NULL, NULL, 0, NULL);
410     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
411 
412     SetupDiDestroyDeviceInfoList(set);
413 }
414 
415 static void test_get_device_instance_id(void)
416 {
417     BOOL ret;
418     HDEVINFO set;
419     SP_DEVINFO_DATA device = {0};
420     char id[200];
421     DWORD size;
422 
423     SetLastError(0xdeadbeef);
424     ret = SetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL);
425     ok(!ret, "Expected failure.\n");
426     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
427 
428     SetLastError(0xdeadbeef);
429     ret = SetupDiGetDeviceInstanceIdA(NULL, &device, NULL, 0, NULL);
430     ok(!ret, "Expected failure.\n");
431     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
432 
433     set = SetupDiCreateDeviceInfoList(&guid, NULL);
434     ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
435 
436     SetLastError(0xdeadbeef);
437     ret = SetupDiGetDeviceInstanceIdA(set, NULL, NULL, 0, NULL);
438     ok(!ret, "Expected failure.\n");
439     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
440 
441     SetLastError(0xdeadbeef);
442     ret = SetupDiGetDeviceInstanceIdA(set, &device, NULL, 0, NULL);
443     ok(!ret, "Expected failure.\n");
444     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
445 
446     SetLastError(0xdeadbeef);
447     ret = SetupDiGetDeviceInstanceIdA(set, &device, NULL, 0, &size);
448     ok(!ret, "Expected failure.\n");
449     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
450 
451     device.cbSize = sizeof(device);
452     SetLastError(0xdeadbeef);
453     ret = SetupDiGetDeviceInstanceIdA(set, &device, NULL, 0, &size);
454     ok(!ret, "Expected failure.\n");
455     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
456 
457     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device);
458     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
459 
460     SetLastError(0xdeadbeef);
461     ret = SetupDiGetDeviceInstanceIdA(set, &device, NULL, 0, &size);
462     ok(!ret, "Expected failure.\n");
463     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected error %#x.\n", GetLastError());
464 
465     ret = SetupDiGetDeviceInstanceIdA(set, &device, id, sizeof(id), NULL);
466     ok(ret, "Failed to get device id, error %#x.\n", GetLastError());
467     ok(!strcmp(id, "ROOT\\LEGACY_BOGUS\\0000"), "Got unexpected id %s.\n", id);
468 
469     ret = SetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL, DICD_GENERATE_ID, &device);
470     ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError());
471 
472     ret = SetupDiGetDeviceInstanceIdA(set, &device, id, sizeof(id), NULL);
473     ok(ret, "Failed to get device id, error %#x.\n", GetLastError());
474     ok(!strcmp(id, "ROOT\\LEGACY_BOGUS\\0001"), "Got unexpected id %s.\n", id);
475 
476     SetupDiDestroyDeviceInfoList(set);
477 }
478 
479 static void test_register_device_info(void)
480 {
481     SP_DEVINFO_DATA device = {0};
482     BOOL ret;
483     HDEVINFO set;
484     int i = 0;
485 
486     SetLastError(0xdeadbeef);
487     ret = SetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL);
488     ok(!ret, "Expected failure.\n");
489     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
490 
491     set = SetupDiCreateDeviceInfoList(&guid, NULL);
492     ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
493 
494     SetLastError(0xdeadbeef);
495     ret = SetupDiRegisterDeviceInfo(set, NULL, 0, NULL, NULL, NULL);
496     ok(!ret, "Expected failure.\n");
497     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
498 
499     SetLastError(0xdeadbeef);
500     ret = SetupDiRegisterDeviceInfo(set, &device, 0, NULL, NULL, NULL);
501     ok(!ret, "Expected failure.\n");
502     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
503 
504     device.cbSize = sizeof(device);
505     SetLastError(0xdeadbeef);
506     ret = SetupDiRegisterDeviceInfo(set, &device, 0, NULL, NULL, NULL);
507     ok(!ret, "Expected failure.\n");
508     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
509 
510     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device);
511     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
512     ret = SetupDiRegisterDeviceInfo(set, &device, 0, NULL, NULL, NULL);
513     ok(ret, "Failed to register device, error %#x.\n", GetLastError());
514 
515     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0001", &guid, NULL, NULL, 0, &device);
516     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
517     ret = SetupDiRegisterDeviceInfo(set, &device, 0, NULL, NULL, NULL);
518     ok(ret, "Failed to register device, error %#x.\n", GetLastError());
519     ret = SetupDiRemoveDevice(set, &device);
520     ok(ret, "Failed to remove device, error %#x.\n", GetLastError());
521 
522     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0002", &guid, NULL, NULL, 0, &device);
523     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
524     ret = SetupDiRegisterDeviceInfo(set, &device, 0, NULL, NULL, NULL);
525     ok(ret, "Failed to register device, error %#x.\n", GetLastError());
526     ret = SetupDiDeleteDeviceInfo(set, &device);
527     ok(ret, "Failed to remove device, error %#x.\n", GetLastError());
528 
529     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0003", &guid, NULL, NULL, 0, &device);
530     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
531 
532     SetupDiDestroyDeviceInfoList(set);
533 
534     set = SetupDiGetClassDevsA(&guid, NULL, NULL, 0);
535     ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
536 
537     check_device_info(set, 0, &guid, "Root\\LEGACY_BOGUS\\0000");
538     check_device_info(set, 1, &guid, "Root\\LEGACY_BOGUS\\0002");
539     check_device_info(set, 2, &guid, NULL);
540 
541     while (SetupDiEnumDeviceInfo(set, i++, &device))
542     {
543         ret = SetupDiRemoveDevice(set, &device);
544         ok(ret, "Failed to remove device, error %#x.\n", GetLastError());
545     }
546 
547     SetupDiDestroyDeviceInfoList(set);
548 }
549 
550 static void check_device_iface_(int line, HDEVINFO set, SP_DEVINFO_DATA *device,
551         const GUID *class, int index, DWORD flags, const char *path)
552 {
553     char buffer[200];
554     SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buffer;
555     SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
556     BOOL ret;
557 
558     detail->cbSize = sizeof(*detail);
559 
560     SetLastError(0xdeadbeef);
561     ret = SetupDiEnumDeviceInterfaces(set, device, class, index, &iface);
562     if (path)
563     {
564         ok_(__FILE__, line)(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError());
565         ok_(__FILE__, line)(IsEqualGUID(&iface.InterfaceClassGuid, class),
566                 "Got unexpected class %s.\n", wine_dbgstr_guid(&iface.InterfaceClassGuid));
567         ok_(__FILE__, line)(iface.Flags == flags, "Got unexpected flags %#x.\n", iface.Flags);
568         ret = SetupDiGetDeviceInterfaceDetailA(set, &iface, detail, sizeof(buffer), NULL, NULL);
569         ok_(__FILE__, line)(ret, "Failed to get interface detail, error %#x.\n", GetLastError());
570         ok_(__FILE__, line)(!strcasecmp(detail->DevicePath, path), "Got unexpected path %s.\n", detail->DevicePath);
571     }
572     else
573     {
574         ok_(__FILE__, line)(!ret, "Expected failure.\n");
575         ok_(__FILE__, line)(GetLastError() == ERROR_NO_MORE_ITEMS,
576                 "Got unexpected error %#x.\n", GetLastError());
577     }
578 }
579 #define check_device_iface(a,b,c,d,e,f) check_device_iface_(__LINE__,a,b,c,d,e,f)
580 
581 static void test_device_iface(void)
582 {
583     char buffer[200];
584     SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buffer;
585     SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
586     SP_DEVINFO_DATA device = {0};
587     BOOL ret;
588     HDEVINFO set;
589 
590     detail->cbSize = sizeof(*detail);
591 
592     SetLastError(0xdeadbeef);
593     ret = SetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL);
594     ok(!ret, "Expected failure.\n");
595     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
596 
597     SetLastError(0xdeadbeef);
598     ret = SetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL);
599     ok(!ret, "Expected failure.\n");
600     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
601 
602     set = SetupDiCreateDeviceInfoList(&guid, NULL);
603     ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
604 
605     SetLastError(0xdeadbeef);
606     ret = SetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL);
607     ok(!ret, "Expected failure.\n");
608     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
609 
610     SetLastError(0xdeadbeef);
611     ret = SetupDiCreateDeviceInterfaceA(set, &device, NULL, NULL, 0, NULL);
612     ok(!ret, "Expected failure.\n");
613     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
614 
615     device.cbSize = sizeof(device);
616     ret = SetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device);
617     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
618 
619     check_device_iface(set, &device, &guid, 0, 0, NULL);
620 
621     SetLastError(0xdeadbeef);
622     ret = SetupDiCreateDeviceInterfaceA(set, &device, NULL, NULL, 0, NULL);
623     ok(!ret, "Expected failure.\n");
624     ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError());
625 
626     ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, NULL, 0, NULL);
627     ok(ret, "Failed to create interface, error %#x.\n", GetLastError());
628 
629     check_device_iface(set, &device, &guid, 0, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}");
630     check_device_iface(set, &device, &guid, 1, 0, NULL);
631 
632     /* Creating the same interface a second time succeeds */
633     ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, NULL, 0, NULL);
634     ok(ret, "Failed to create interface, error %#x.\n", GetLastError());
635 
636     check_device_iface(set, &device, &guid, 0, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}");
637     check_device_iface(set, &device, &guid, 1, 0, NULL);
638 
639     ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, "Oogah", 0, NULL);
640     ok(ret, "Failed to create interface, error %#x.\n", GetLastError());
641 
642     check_device_iface(set, &device, &guid, 0, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}");
643     check_device_iface(set, &device, &guid, 1, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\Oogah");
644     check_device_iface(set, &device, &guid, 2, 0, NULL);
645 
646     ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, "test", 0, &iface);
647     ok(ret, "Failed to create interface, error %#x.\n", GetLastError());
648     ok(IsEqualGUID(&iface.InterfaceClassGuid, &guid), "Got unexpected class %s.\n",
649             wine_dbgstr_guid(&iface.InterfaceClassGuid));
650     ok(iface.Flags == 0, "Got unexpected flags %#x.\n", iface.Flags);
651     ret = SetupDiGetDeviceInterfaceDetailA(set, &iface, detail, sizeof(buffer), NULL, NULL);
652     ok(ret, "Failed to get interface detail, error %#x.\n", GetLastError());
653     ok(!strcasecmp(detail->DevicePath, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\test"),
654             "Got unexpected path %s.\n", detail->DevicePath);
655 
656     check_device_iface(set, &device, &guid, 0, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}");
657     check_device_iface(set, &device, &guid, 1, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\Oogah");
658     check_device_iface(set, &device, &guid, 2, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\test");
659     check_device_iface(set, &device, &guid, 3, 0, NULL);
660 
661     ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid2, NULL, 0, NULL);
662     ok(ret, "Failed to create interface, error %#x.\n", GetLastError());
663 
664     check_device_iface(set, &device, &guid2, 0, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A5-3F65-11DB-B704-0011955C2BDB}");
665     check_device_iface(set, &device, &guid2, 1, 0, NULL);
666 
667     ret = SetupDiEnumDeviceInterfaces(set, &device, &guid2, 0, &iface);
668     ok(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError());
669     ret = SetupDiRemoveDeviceInterface(set, &iface);
670     ok(ret, "Failed to remove interface, error %#x.\n", GetLastError());
671 
672     check_device_iface(set, &device, &guid2, 0, SPINT_REMOVED, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A5-3F65-11DB-B704-0011955C2BDB}");
673     check_device_iface(set, &device, &guid2, 1, 0, NULL);
674 
675     ret = SetupDiEnumDeviceInterfaces(set, &device, &guid, 0, &iface);
676     ok(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError());
677     ret = SetupDiDeleteDeviceInterfaceData(set, &iface);
678     ok(ret, "Failed to delete interface, error %#x.\n", GetLastError());
679 
680     check_device_iface(set, &device, &guid, 0, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\Oogah");
681     check_device_iface(set, &device, &guid, 1, 0, "\\\\?\\ROOT#LEGACY_BOGUS#0000#{6A55B5A4-3F65-11DB-B704-0011955C2BDB}\\test");
682     check_device_iface(set, &device, &guid, 2, 0, NULL);
683 
684     ret = SetupDiDestroyDeviceInfoList(set);
685     ok(ret, "Failed to destroy device list, error %#x.\n", GetLastError());
686 }
687 
688 static void test_device_iface_detail(void)
689 {
690     static const char path[] = "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
691     SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail;
692     SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
693     SP_DEVINFO_DATA device = {sizeof(device)};
694     DWORD size = 0, expectedsize;
695     HDEVINFO set;
696     BOOL ret;
697 
698     SetLastError(0xdeadbeef);
699     ret = SetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL);
700     ok(!ret, "Expected failure.\n");
701     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
702 
703     set = SetupDiCreateDeviceInfoList(&guid, NULL);
704     ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
705 
706     SetLastError(0xdeadbeef);
707     ret = SetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL, NULL);
708     ok(!ret, "Expected failure.\n");
709     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
710 
711     ret = SetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device);
712     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
713 
714     SetLastError(0xdeadbeef);
715     ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, NULL, 0, &iface);
716     ok(ret, "Failed to create interface, error %#x.\n", GetLastError());
717 
718     SetLastError(0xdeadbeef);
719     ret = SetupDiGetDeviceInterfaceDetailA(set, &iface, NULL, 0, NULL, NULL);
720     ok(!ret, "Expected failure.\n");
721     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected error %#x.\n", GetLastError());
722 
723     SetLastError(0xdeadbeef);
724     ret = SetupDiGetDeviceInterfaceDetailA(set, &iface, NULL, 100, NULL, NULL);
725     ok(!ret, "Expected failure.\n");
726     ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError());
727 
728     SetLastError(0xdeadbeef);
729     ret = SetupDiGetDeviceInterfaceDetailA(set, &iface, NULL, 0, &size, NULL);
730     ok(!ret, "Expected failure.\n");
731     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected error %#x.\n", GetLastError());
732 
733     detail = heap_alloc(size);
734     expectedsize = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath[strlen(path) + 1]);
735 
736     detail->cbSize = 0;
737     SetLastError(0xdeadbeef);
738     ret = SetupDiGetDeviceInterfaceDetailA(set, &iface, detail, size, &size, NULL);
739     ok(!ret, "Expected failure.\n");
740     ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError());
741 
742     detail->cbSize = size;
743     SetLastError(0xdeadbeef);
744     ret = SetupDiGetDeviceInterfaceDetailA(set, &iface, detail, size, &size, NULL);
745     ok(!ret, "Expected failure.\n");
746     ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "Got unexpected error %#x.\n", GetLastError());
747 
748     detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
749     SetLastError(0xdeadbeef);
750     ret = SetupDiGetDeviceInterfaceDetailA(set, &iface, detail, size, &size, NULL);
751     ok(ret, "Failed to get interface detail, error %#x.\n", GetLastError());
752     ok(!strcasecmp(path, detail->DevicePath), "Got unexpected path %s.\n", detail->DevicePath);
753 
754     ret = SetupDiGetDeviceInterfaceDetailW(set, &iface, NULL, 0, &size, NULL);
755     ok(!ret, "Expected failure.\n");
756     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected error %#x.\n", GetLastError());
757     ok(size == expectedsize, "Got unexpected size %d.\n", size);
758 
759     memset(&device, 0, sizeof(device));
760     device.cbSize = sizeof(device);
761     ret = SetupDiGetDeviceInterfaceDetailW(set, &iface, NULL, 0, &size, &device);
762     ok(!ret, "Expected failure.\n");
763     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected error %#x.\n", GetLastError());
764     ok(IsEqualGUID(&device.ClassGuid, &guid), "Got unexpected class %s.\n", wine_dbgstr_guid(&device.ClassGuid));
765 
766     heap_free(detail);
767     SetupDiDestroyDeviceInfoList(set);
768 }
769 
770 static void test_device_key(void)
771 {
772     static const WCHAR classKey[] = {'S','y','s','t','e','m','\\',
773      'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
774      'C','o','n','t','r','o','l','\\','C','l','a','s','s','\\',
775      '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-',
776      '1','1','d','b','-','b','7','0','4','-',
777      '0','0','1','1','9','5','5','c','2','b','d','b','}',0};
778     static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
779      'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
780      'E','n','u','m','\\','R','o','o','t','\\',
781      'L','E','G','A','C','Y','_','B','O','G','U','S',0};
782     SP_DEVINFO_DATA device = {sizeof(device)};
783     BOOL ret;
784     HDEVINFO set;
785     HKEY key = NULL;
786     LONG res;
787 
788     SetLastError(0xdeadbeef);
789     key = SetupDiCreateDevRegKeyW(NULL, NULL, 0, 0, 0, NULL, NULL);
790     ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n");
791     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
792 
793     set = SetupDiCreateDeviceInfoList(&guid, NULL);
794     ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
795 
796     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
797     ok(res != ERROR_SUCCESS, "Key should not exist.\n");
798     RegCloseKey(key);
799 
800     ret = SetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device);
801     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
802     ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key), "Key should exist.\n");
803     RegCloseKey(key);
804 
805     SetLastError(0xdeadbeef);
806     key = SetupDiOpenDevRegKey(NULL, NULL, 0, 0, 0, 0);
807     ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n");
808     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
809 
810     SetLastError(0xdeadbeef);
811     key = SetupDiOpenDevRegKey(set, NULL, 0, 0, 0, 0);
812     ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n");
813     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
814 
815     SetLastError(0xdeadbeef);
816     key = SetupDiOpenDevRegKey(set, &device, 0, 0, 0, 0);
817     ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n");
818     ok(GetLastError() == ERROR_INVALID_FLAGS, "Got unexpected error %#x.\n", GetLastError());
819 
820     SetLastError(0xdeadbeef);
821     key = SetupDiOpenDevRegKey(set, &device, DICS_FLAG_GLOBAL, 0, 0, 0);
822     ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n");
823     ok(GetLastError() == ERROR_INVALID_FLAGS, "Got unexpected error %#x.\n", GetLastError());
824 
825     SetLastError(0xdeadbeef);
826     key = SetupDiOpenDevRegKey(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_BOTH, 0);
827     ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n");
828     ok(GetLastError() == ERROR_INVALID_FLAGS, "Got unexpected error %#x.\n", GetLastError());
829 
830     SetLastError(0xdeadbeef);
831     key = SetupDiOpenDevRegKey(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DRV, 0);
832     ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n");
833     ok(GetLastError() == ERROR_DEVINFO_NOT_REGISTERED, "Got unexpected error %#x.\n", GetLastError());
834 
835     ret = SetupDiRegisterDeviceInfo(set, &device, 0, NULL, NULL, NULL);
836     ok(ret, "Failed to register device, error %#x.\n", GetLastError());
837 
838     SetLastError(0xdeadbeef);
839     key = SetupDiOpenDevRegKey(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DRV, 0);
840     ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n");
841     ok(GetLastError() == ERROR_KEY_DOES_NOT_EXIST, "Got unexpected error %#x.\n", GetLastError());
842 
843     SetLastError(0xdeadbeef);
844     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key);
845 todo_wine
846     ok(res == ERROR_FILE_NOT_FOUND, "Key should not exist.\n");
847     RegCloseKey(key);
848 
849     key = SetupDiCreateDevRegKeyW(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
850     ok(key != INVALID_HANDLE_VALUE || GetLastError() == ERROR_KEY_DOES_NOT_EXIST, /* Vista+ */
851             "Failed to create device key, error %#x.\n", GetLastError());
852     if (key != INVALID_HANDLE_VALUE)
853     {
854         RegCloseKey(key);
855 
856         ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key), "Key should exist.\n");
857         RegCloseKey(key);
858 
859         SetLastError(0xdeadbeef);
860         key = SetupDiOpenDevRegKey(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DRV, 0);
861 todo_wine {
862         ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n");
863         ok(GetLastError() == ERROR_INVALID_DATA || GetLastError() == ERROR_ACCESS_DENIED, /* win2k3 */
864                 "Got unexpected error %#x.\n", GetLastError());
865 }
866 
867         key = SetupDiOpenDevRegKey(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ);
868         ok(key != INVALID_HANDLE_VALUE, "Failed to open device key, error %#x.\n", GetLastError());
869         RegCloseKey(key);
870     }
871 
872     ret = SetupDiRemoveDevice(set, &device);
873     ok(ret, "Failed to remove device, error %#x.\n", GetLastError());
874     SetupDiDestroyDeviceInfoList(set);
875 
876     /* remove once Wine is fixed */
877     devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
878 }
879 
880 static void test_register_device_iface(void)
881 {
882     static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
883      'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
884      'E','n','u','m','\\','R','o','o','t','\\',
885      'L','E','G','A','C','Y','_','B','O','G','U','S',0};
886     SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}, ret_iface = {sizeof(ret_iface)};
887     SP_DEVINFO_DATA device = {sizeof(device)};
888     HDEVINFO set, set2;
889     BOOL ret;
890     HKEY key;
891     LONG res;
892 
893     set = SetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_ALLCLASSES);
894     ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
895 
896     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
897     ok(res == ERROR_FILE_NOT_FOUND, "Key should not exist.\n");
898 
899     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device);
900     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
901     ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, NULL, 0, &iface);
902     ok(ret, "Failed to create interface, error %#x.\n", GetLastError());
903     ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, "removed", 0, &iface);
904     ok(ret, "Failed to create interface, error %#x.\n", GetLastError());
905     ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, "deleted", 0, &iface);
906     ok(ret, "Failed to create interface, error %#x.\n", GetLastError());
907     ret = SetupDiRegisterDeviceInfo(set, &device, 0, NULL, NULL, NULL);
908     ok(ret, "Failed to register device, error %#x.\n", GetLastError());
909 
910     ret = SetupDiEnumDeviceInterfaces(set, &device, &guid, 1, &iface);
911     ok(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError());
912     ret = SetupDiRemoveDeviceInterface(set, &iface);
913     ok(ret, "Failed to delete interface, error %#x.\n", GetLastError());
914     ret = SetupDiEnumDeviceInterfaces(set, &device, &guid, 2, &iface);
915     ok(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError());
916     ret = SetupDiDeleteDeviceInterfaceData(set, &iface);
917     ok(ret, "Failed to delete interface, error %#x.\n", GetLastError());
918 
919     set2 = SetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
920     ok(set2 != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
921 
922     check_device_iface(set2, NULL, &guid, 0, 0, "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}");
923     check_device_iface(set2, NULL, &guid, 1, 0, "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\deleted");
924     check_device_iface(set2, NULL, &guid, 2, 0, NULL);
925 
926     ret = SetupDiRemoveDevice(set, &device);
927     ok(ret, "Failed to remove device, error %#x.\n", GetLastError());
928 
929     SetupDiDestroyDeviceInfoList(set);
930     SetupDiDestroyDeviceInfoList(set2);
931 }
932 
933 static void test_registry_property_a(void)
934 {
935     static const CHAR bogus[] = "System\\CurrentControlSet\\Enum\\Root\\LEGACY_BOGUS";
936     SP_DEVINFO_DATA device = {sizeof(device)};
937     CHAR buf[6] = "";
938     DWORD size, type;
939     HDEVINFO set;
940     BOOL ret;
941     LONG res;
942     HKEY key;
943 
944     set = SetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
945     ok(set != INVALID_HANDLE_VALUE, "Failed to get device list, error %#x.\n", GetLastError());
946 
947     ret = SetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL, DICD_GENERATE_ID, &device);
948     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
949 
950     SetLastError(0xdeadbeef);
951     ret = SetupDiSetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, 0);
952     ok(!ret, "Expected failure.\n");
953     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
954 
955     SetLastError(0xdeadbeef);
956     ret = SetupDiSetDeviceRegistryPropertyA(set, NULL, -1, NULL, 0);
957     ok(!ret, "Expected failure.\n");
958     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
959 
960     SetLastError(0xdeadbeef);
961     ret = SetupDiSetDeviceRegistryPropertyA(set, &device, -1, NULL, 0);
962     ok(!ret, "Expected failure.\n");
963 todo_wine
964     ok(GetLastError() == ERROR_INVALID_REG_PROPERTY, "Got unexpected error %#x.\n", GetLastError());
965 
966     ret = SetupDiSetDeviceRegistryPropertyA(set, &device, SPDRP_FRIENDLYNAME, NULL, 0);
967     todo_wine
968     ok(!ret, "Expected failure.\n");
969     /* GetLastError() returns nonsense in win2k3 */
970 
971     SetLastError(0xdeadbeef);
972     ret = SetupDiSetDeviceRegistryPropertyA(set, &device, SPDRP_FRIENDLYNAME, (BYTE *)"Bogus", sizeof("Bogus"));
973     ok(ret, "Failed to set property, error %#x.\n", GetLastError());
974 
975     SetLastError(0xdeadbeef);
976     ret = SetupDiGetDeviceRegistryPropertyA(NULL, NULL, -1, NULL, NULL, 0, NULL);
977     ok(!ret, "Expected failure.\n");
978     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
979 
980     SetLastError(0xdeadbeef);
981     ret = SetupDiGetDeviceRegistryPropertyA(set, NULL, -1, NULL, NULL, 0, NULL);
982     ok(!ret, "Expected failure.\n");
983     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
984 
985     SetLastError(0xdeadbeef);
986     ret = SetupDiGetDeviceRegistryPropertyA(set, &device, -1, NULL, NULL, 0, NULL);
987     ok(!ret, "Expected failure.\n");
988 todo_wine
989     ok(GetLastError() == ERROR_INVALID_REG_PROPERTY, "Got unexpected error %#x.\n", GetLastError());
990 
991     ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_FRIENDLYNAME, NULL, NULL, sizeof("Bogus"), NULL);
992     ok(!ret, "Expected failure, got %d\n", ret);
993     /* GetLastError() returns nonsense in win2k3 */
994 
995     SetLastError(0xdeadbeef);
996     ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_FRIENDLYNAME, NULL, NULL, 0, &size);
997     ok(!ret, "Expected failure.\n");
998     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected error %#x.\n", GetLastError());
999     ok(size == sizeof("Bogus"), "Got unexpected size %d.\n", size);
1000 
1001     SetLastError(0xdeadbeef);
1002     ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_FRIENDLYNAME, NULL, (BYTE *)buf, sizeof(buf), NULL);
1003     ok(ret, "Failed to get property, error %#x.\n", GetLastError());
1004     ok(!strcmp(buf, "Bogus"), "Got unexpected property %s.\n", buf);
1005 
1006     SetLastError(0xdeadbeef);
1007     ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_FRIENDLYNAME, &type, (BYTE *)buf, sizeof(buf), NULL);
1008     ok(ret, "Failed to get property, error %#x.\n", GetLastError());
1009     ok(!strcmp(buf, "Bogus"), "Got unexpected property %s.\n", buf);
1010     ok(type == REG_SZ, "Got unexpected type %d.\n", type);
1011 
1012     SetLastError(0xdeadbeef);
1013     ret = SetupDiSetDeviceRegistryPropertyA(set, &device, SPDRP_FRIENDLYNAME, NULL, 0);
1014     ok(ret, "Failed to set property, error %#x.\n", GetLastError());
1015 
1016     SetLastError(0xdeadbeef);
1017     ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_FRIENDLYNAME, NULL, (BYTE *)buf, sizeof(buf), &size);
1018 todo_wine {
1019     ok(!ret, "Expected failure.\n");
1020     ok(GetLastError() == ERROR_INVALID_DATA, "Got unexpected error %#x.\n", GetLastError());
1021 }
1022 
1023     ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_HARDWAREID, NULL, NULL, 0, &size);
1024     ok(!ret, "Expected failure.\n");
1025     ok(GetLastError() == ERROR_INVALID_DATA, "Got unexpected error %#x.\n", GetLastError());
1026 
1027     SetupDiDestroyDeviceInfoList(set);
1028 
1029     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, bogus, &key);
1030     ok(res == ERROR_FILE_NOT_FOUND, "Key should not exist.\n");
1031 }
1032 
1033 static void test_registry_property_w(void)
1034 {
1035     WCHAR friendly_name[] = {'B','o','g','u','s',0};
1036     SP_DEVINFO_DATA device = {sizeof(device)};
1037     WCHAR buf[6] = {0};
1038     DWORD size, type;
1039     HDEVINFO set;
1040     BOOL ret;
1041     LONG res;
1042     HKEY key;
1043     static const WCHAR bogus[] = {'S','y','s','t','e','m','\\',
1044      'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1045      'E','n','u','m','\\','R','o','o','t','\\',
1046      'L','E','G','A','C','Y','_','B','O','G','U','S',0};
1047 
1048     set = SetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
1049     ok(set != INVALID_HANDLE_VALUE, "Failed to get device list, error %#x.\n", GetLastError());
1050 
1051     ret = SetupDiCreateDeviceInfoA(set, "LEGACY_BOGUS", &guid, NULL, NULL, DICD_GENERATE_ID, &device);
1052     ok(ret, "Failed to create device, error %#x.\n", GetLastError());
1053 
1054     SetLastError(0xdeadbeef);
1055     ret = SetupDiSetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, 0);
1056     ok(!ret, "Expected failure.\n");
1057     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
1058 
1059     SetLastError(0xdeadbeef);
1060     ret = SetupDiSetDeviceRegistryPropertyW(set, NULL, -1, NULL, 0);
1061     ok(!ret, "Expected failure.\n");
1062     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
1063 
1064     SetLastError(0xdeadbeef);
1065     ret = SetupDiSetDeviceRegistryPropertyW(set, &device, -1, NULL, 0);
1066     ok(!ret, "Expected failure.\n");
1067 todo_wine
1068     ok(GetLastError() == ERROR_INVALID_REG_PROPERTY, "Got unexpected error %#x.\n", GetLastError());
1069 
1070     ret = SetupDiSetDeviceRegistryPropertyW(set, &device, SPDRP_FRIENDLYNAME, NULL, 0);
1071     todo_wine
1072     ok(!ret, "Expected failure.\n");
1073     /* GetLastError() returns nonsense in win2k3 */
1074 
1075     SetLastError(0xdeadbeef);
1076     ret = SetupDiSetDeviceRegistryPropertyW(set, &device, SPDRP_FRIENDLYNAME, (BYTE *)friendly_name, sizeof(friendly_name));
1077     ok(ret, "Failed to set property, error %#x.\n", GetLastError());
1078 
1079     SetLastError(0xdeadbeef);
1080     ret = SetupDiGetDeviceRegistryPropertyW(NULL, NULL, -1, NULL, NULL, 0, NULL);
1081     ok(!ret, "Expected failure.\n");
1082     ok(GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected error %#x.\n", GetLastError());
1083 
1084     SetLastError(0xdeadbeef);
1085     ret = SetupDiGetDeviceRegistryPropertyW(set, NULL, -1, NULL, NULL, 0, NULL);
1086     ok(!ret, "Expected failure.\n");
1087     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %#x.\n", GetLastError());
1088 
1089     SetLastError(0xdeadbeef);
1090     ret = SetupDiGetDeviceRegistryPropertyW(set, &device, -1, NULL, NULL, 0, NULL);
1091     ok(!ret, "Expected failure.\n");
1092 todo_wine
1093     ok(GetLastError() == ERROR_INVALID_REG_PROPERTY, "Got unexpected error %#x.\n", GetLastError());
1094 
1095     ret = SetupDiGetDeviceRegistryPropertyW(set, &device, SPDRP_FRIENDLYNAME, NULL, NULL, sizeof(buf), NULL);
1096     ok(!ret, "Expected failure.\n");
1097     /* GetLastError() returns nonsense in win2k3 */
1098 
1099     SetLastError(0xdeadbeef);
1100     ret = SetupDiGetDeviceRegistryPropertyW(set, &device, SPDRP_FRIENDLYNAME, NULL, NULL, 0, &size);
1101     ok(!ret, "Expected failure.\n");
1102     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got unexpected error %#x.\n", GetLastError());
1103     ok(size == sizeof(friendly_name), "Got unexpected size %d.\n", size);
1104 
1105     SetLastError(0xdeadbeef);
1106     ret = SetupDiGetDeviceRegistryPropertyW(set, &device, SPDRP_FRIENDLYNAME, NULL, (BYTE *)buf, sizeof(buf), NULL);
1107     ok(ret, "Failed to get property, error %#x.\n", GetLastError());
1108     ok(!lstrcmpW(buf, friendly_name), "Got unexpected property %s.\n", wine_dbgstr_w(buf));
1109 
1110     SetLastError(0xdeadbeef);
1111     ret = SetupDiGetDeviceRegistryPropertyW(set, &device, SPDRP_FRIENDLYNAME, &type, (BYTE *)buf, sizeof(buf), NULL);
1112     ok(ret, "Failed to get property, error %#x.\n", GetLastError());
1113     ok(!lstrcmpW(buf, friendly_name), "Got unexpected property %s.\n", wine_dbgstr_w(buf));
1114     ok(type == REG_SZ, "Got unexpected type %d.\n", type);
1115 
1116     SetLastError(0xdeadbeef);
1117     ret = SetupDiSetDeviceRegistryPropertyW(set, &device, SPDRP_FRIENDLYNAME, NULL, 0);
1118     ok(ret, "Failed to set property, error %#x.\n", GetLastError());
1119 
1120     SetLastError(0xdeadbeef);
1121     ret = SetupDiGetDeviceRegistryPropertyW(set, &device, SPDRP_FRIENDLYNAME, NULL, (BYTE *)buf, sizeof(buf), &size);
1122 todo_wine {
1123     ok(!ret, "Expected failure.\n");
1124     ok(GetLastError() == ERROR_INVALID_DATA, "Got unexpected error %#x.\n", GetLastError());
1125 }
1126 
1127     ret = SetupDiGetDeviceRegistryPropertyW(set, &device, SPDRP_HARDWAREID, NULL, NULL, 0, &size);
1128     ok(!ret, "Expected failure.\n");
1129     ok(GetLastError() == ERROR_INVALID_DATA, "Got unexpected error %#x.\n", GetLastError());
1130 
1131     SetupDiDestroyDeviceInfoList(set);
1132 
1133     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key);
1134     ok(res == ERROR_FILE_NOT_FOUND, "Key should not exist.\n");
1135 }
1136 
1137 static void test_get_inf_class(void)
1138 {
1139     static const char inffile[] = "winetest.inf";
1140     static const char content[] = "[Version]\r\n\r\n";
1141     static const char* signatures[] = {"\"$CHICAGO$\"", "\"$Windows NT$\""};
1142 
1143     char cn[MAX_PATH];
1144     char filename[MAX_PATH];
1145     DWORD count;
1146     BOOL retval;
1147     GUID guid;
1148     HANDLE h;
1149     int i;
1150 
1151     GetTempPathA(MAX_PATH, filename);
1152     strcat(filename, inffile);
1153     DeleteFileA(filename);
1154 
1155     /* not existing file */
1156     SetLastError(0xdeadbeef);
1157     retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count);
1158     ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1159     ok(ERROR_FILE_NOT_FOUND == GetLastError(),
1160         "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError());
1161 
1162     /* missing file wins against other invalid parameter */
1163     SetLastError(0xdeadbeef);
1164     retval = SetupDiGetINFClassA(filename, NULL, cn, MAX_PATH, &count);
1165     ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1166     ok(ERROR_FILE_NOT_FOUND == GetLastError(),
1167         "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError());
1168 
1169     SetLastError(0xdeadbeef);
1170     retval = SetupDiGetINFClassA(filename, &guid, NULL, MAX_PATH, &count);
1171     ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1172     ok(ERROR_FILE_NOT_FOUND == GetLastError(),
1173         "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError());
1174 
1175     SetLastError(0xdeadbeef);
1176     retval = SetupDiGetINFClassA(filename, &guid, cn, 0, &count);
1177     ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1178     ok(ERROR_FILE_NOT_FOUND == GetLastError(),
1179         "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError());
1180 
1181     SetLastError(0xdeadbeef);
1182     retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, NULL);
1183     ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1184     ok(ERROR_FILE_NOT_FOUND == GetLastError(),
1185         "expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError());
1186 
1187     /* test file content */
1188     h = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1189                     FILE_ATTRIBUTE_NORMAL, NULL);
1190     ok(h != INVALID_HANDLE_VALUE, "Failed to create file, error %#x.\n", GetLastError());
1191     CloseHandle(h);
1192 
1193     retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count);
1194     ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1195 
1196     for(i=0; i < ARRAY_SIZE(signatures); i++)
1197     {
1198         trace("testing signature %s\n", signatures[i]);
1199         h = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1200                         FILE_ATTRIBUTE_NORMAL, NULL);
1201         ok(h != INVALID_HANDLE_VALUE, "Failed to create file, error %#x.\n", GetLastError());
1202         WriteFile(h, content, sizeof(content), &count, NULL);
1203         CloseHandle(h);
1204 
1205         retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count);
1206         ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1207 
1208         WritePrivateProfileStringA("Version", "Signature", signatures[i], filename);
1209 
1210         retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count);
1211         ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1212 
1213         WritePrivateProfileStringA("Version", "Class", "WINE", filename);
1214 
1215         count = 0xdeadbeef;
1216         retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count);
1217         ok(retval, "expected SetupDiGetINFClassA to succeed! error %u\n", GetLastError());
1218         ok(count == 5, "expected count==5, got %u\n", count);
1219 
1220         count = 0xdeadbeef;
1221         retval = SetupDiGetINFClassA(filename, &guid, cn, 5, &count);
1222         ok(retval, "expected SetupDiGetINFClassA to succeed! error %u\n", GetLastError());
1223         ok(count == 5, "expected count==5, got %u\n", count);
1224 
1225         count = 0xdeadbeef;
1226         SetLastError(0xdeadbeef);
1227         retval = SetupDiGetINFClassA(filename, &guid, cn, 4, &count);
1228         ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1229         ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1230             "expected error ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
1231         ok(count == 5, "expected count==5, got %u\n", count);
1232 
1233         /* invalid parameter */
1234         SetLastError(0xdeadbeef);
1235         retval = SetupDiGetINFClassA(NULL, &guid, cn, MAX_PATH, &count);
1236         ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1237         ok(ERROR_INVALID_PARAMETER == GetLastError(),
1238             "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1239 
1240         SetLastError(0xdeadbeef);
1241         retval = SetupDiGetINFClassA(filename, NULL, cn, MAX_PATH, &count);
1242         ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1243         ok(ERROR_INVALID_PARAMETER == GetLastError(),
1244             "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1245 
1246         SetLastError(0xdeadbeef);
1247         retval = SetupDiGetINFClassA(filename, &guid, NULL, MAX_PATH, &count);
1248         ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1249         ok(ERROR_INVALID_PARAMETER == GetLastError(),
1250             "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1251 
1252         SetLastError(0xdeadbeef);
1253         retval = SetupDiGetINFClassA(filename, &guid, cn, 0, &count);
1254         ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1255         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER || GetLastError() == ERROR_INVALID_PARAMETER /* 2k3+ */,
1256                 "Got unexpected error %#x.\n", GetLastError());
1257 
1258         DeleteFileA(filename);
1259 
1260         WritePrivateProfileStringA("Version", "Signature", signatures[i], filename);
1261         WritePrivateProfileStringA("Version", "ClassGUID", "WINE", filename);
1262 
1263         SetLastError(0xdeadbeef);
1264         retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count);
1265         ok(!retval, "expected SetupDiGetINFClassA to fail!\n");
1266         ok(GetLastError() == RPC_S_INVALID_STRING_UUID || GetLastError() == ERROR_INVALID_PARAMETER /* 7+ */,
1267                 "Got unexpected error %#x.\n", GetLastError());
1268 
1269         /* network adapter guid */
1270         WritePrivateProfileStringA("Version", "ClassGUID",
1271                                    "{4d36e972-e325-11ce-bfc1-08002be10318}", filename);
1272 
1273         /* this test succeeds only if the guid is known to the system */
1274         count = 0xdeadbeef;
1275         retval = SetupDiGetINFClassA(filename, &guid, cn, MAX_PATH, &count);
1276         ok(retval, "expected SetupDiGetINFClassA to succeed! error %u\n", GetLastError());
1277         todo_wine
1278         ok(count == 4, "expected count==4, got %u(%s)\n", count, cn);
1279 
1280         DeleteFileA(filename);
1281     }
1282 }
1283 
1284 static void test_devnode(void)
1285 {
1286     HDEVINFO set;
1287     SP_DEVINFO_DATA device = { sizeof(SP_DEVINFO_DATA) };
1288     char buffer[50];
1289     DWORD ret;
1290 
1291     set = SetupDiGetClassDevsA(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE);
1292     ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevs failed: %#x\n", GetLastError());
1293     ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL,
1294         NULL, 0, &device);
1295     ok(ret, "SetupDiCreateDeviceInfo failed: %#x\n", GetLastError());
1296 
1297     ret = CM_Get_Device_IDA(device.DevInst, buffer, sizeof(buffer), 0);
1298     ok(!ret, "got %#x\n", ret);
1299     ok(!strcmp(buffer, "ROOT\\LEGACY_BOGUS\\0000"), "got %s\n", buffer);
1300 
1301     SetupDiDestroyDeviceInfoList(set);
1302 }
1303 
1304 static void test_device_interface_key(void)
1305 {
1306     const char keypath[] = "System\\CurrentControlSet\\Control\\DeviceClasses\\"
1307         "{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\"
1308         "##?#ROOT#LEGACY_BOGUS#0001#{6a55b5a4-3f65-11db-b704-0011955c2bdb}";
1309     SP_DEVICE_INTERFACE_DATA iface = { sizeof(iface) };
1310     SP_DEVINFO_DATA devinfo = { sizeof(devinfo) };
1311     HKEY parent, key, dikey;
1312     char buffer[5];
1313     HDEVINFO set;
1314     LONG sz, ret;
1315 
1316     set = SetupDiGetClassDevsA(NULL, NULL, 0, DIGCF_ALLCLASSES);
1317     ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevs failed: %#x\n", GetLastError());
1318 
1319     ret = SetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0001", &guid, NULL, NULL, 0, &devinfo);
1320     ok(ret, "SetupDiCreateDeviceInfo failed: %#x\n", GetLastError());
1321 
1322     ret = SetupDiCreateDeviceInterfaceA(set, &devinfo, &guid, NULL, 0, &iface);
1323     ok(ret, "SetupDiCreateDeviceInterface failed: %#x\n", GetLastError());
1324 
1325     ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &parent);
1326     ok(!ret, "failed to open device parent key: %u\n", ret);
1327 
1328     ret = RegOpenKeyA(parent, "#\\Device Parameters", &key);
1329     ok(ret == ERROR_FILE_NOT_FOUND, "key shouldn't exist\n");
1330 
1331     dikey = SetupDiCreateDeviceInterfaceRegKeyA(set, &iface, 0, KEY_ALL_ACCESS, NULL, NULL);
1332     ok(dikey != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
1333 
1334     ret = RegOpenKeyA(parent, "#\\Device Parameters", &key);
1335     ok(!ret, "key should exist: %u\n", ret);
1336 
1337     ret = RegSetValueA(key, NULL, REG_SZ, "test", 5);
1338     sz = sizeof(buffer);
1339     ret = RegQueryValueA(dikey, NULL, buffer, &sz);
1340     ok(!ret, "RegQueryValue failed: %u\n", ret);
1341     ok(!strcmp(buffer, "test"), "got wrong data %s\n", buffer);
1342 
1343     RegCloseKey(dikey);
1344     RegCloseKey(key);
1345 
1346     ret = SetupDiDeleteDeviceInterfaceRegKey(set, &iface, 0);
1347     ok(ret, "got error %u\n", GetLastError());
1348 
1349     ret = RegOpenKeyA(parent, "#\\Device Parameters", &key);
1350     ok(ret == ERROR_FILE_NOT_FOUND, "key shouldn't exist\n");
1351 
1352     RegCloseKey(parent);
1353     SetupDiRemoveDeviceInterface(set, &iface);
1354     SetupDiRemoveDevice(set, &devinfo);
1355     SetupDiDestroyDeviceInfoList(set);
1356 }
1357 
1358 static void testSetupDiGetClassDevsA(void)
1359 {
1360     static GUID displayguid = {0x4d36e968, 0xe325, 0x11ce, {0xbf,0xc1,0x08,0x00,0x2b,0xe1,0x03,0x18}};
1361     SP_DEVINFO_DATA devinfo;
1362     DISPLAY_DEVICEA disp;
1363     HDEVINFO set;
1364     BOOL ret;
1365 
1366     disp.cb = sizeof(disp);
1367     ok(EnumDisplayDevicesA(NULL, 0, &disp, 0), "EnumDisplayDevices failed: %08x\n", GetLastError());
1368 
1369     SetLastError(0xdeadbeef);
1370     set = SetupDiGetClassDevsA(&displayguid, disp.DeviceID, 0, 0);
1371     ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n", GetLastError());
1372 
1373     devinfo.cbSize = sizeof(devinfo);
1374     ret = SetupDiEnumDeviceInfo(set, 0, &devinfo);
1375     ok(ret, "SetupDiEnumDeviceInfo failed: %08x\n", GetLastError());
1376 
1377     SetupDiDestroyDeviceInfoList(set);
1378 }
1379 
1380 START_TEST(devinst)
1381 {
1382     HKEY hkey;
1383 
1384     if ((hkey = SetupDiOpenClassRegKey(NULL, KEY_ALL_ACCESS)) == INVALID_HANDLE_VALUE)
1385     {
1386         skip("needs admin rights\n");
1387         return;
1388     }
1389     RegCloseKey(hkey);
1390 
1391     test_create_device_list_ex();
1392     test_open_class_key();
1393     test_install_class();
1394     test_device_info();
1395     test_get_device_instance_id();
1396     test_register_device_info();
1397     test_device_iface();
1398     test_device_iface_detail();
1399     test_device_key();
1400     test_register_device_iface();
1401     test_registry_property_a();
1402     test_registry_property_w();
1403     test_get_inf_class();
1404     testSetupDiGetClassDevsA();
1405     test_devnode();
1406     test_device_interface_key();
1407 }
1408