wined3d: Unify pixel format correction.
[wine] / dlls / setupapi / devinst.c
1 /*
2  * SetupAPI device installer
3  *
4  * Copyright 2000 Andreas Mohr for CodeWeavers
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 "config.h"
22 #include "wine/port.h"
23  
24 #include <stdarg.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnt.h"
29 #include "winreg.h"
30 #include "winternl.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "winnls.h"
34 #include "setupapi.h"
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
37 #include "cfgmgr32.h"
38 #include "initguid.h"
39 #include "winioctl.h"
40 #include "rpc.h"
41 #include "rpcdce.h"
42
43 #include "setupapi_private.h"
44
45
46 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
47
48 /* Unicode constants */
49 static const WCHAR ClassGUID[]  = {'C','l','a','s','s','G','U','I','D',0};
50 static const WCHAR Class[]  = {'C','l','a','s','s',0};
51 static const WCHAR ClassInstall32[]  = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
52 static const WCHAR NoDisplayClass[]  = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
53 static const WCHAR NoInstallClass[]  = {'N','o','I','n','s','t','a','l','l','C','l','a','s','s',0};
54 static const WCHAR NoUseClass[]  = {'N','o','U','s','e','C','l','a','s','s',0};
55 static const WCHAR NtExtension[]  = {'.','N','T',0};
56 static const WCHAR NtPlatformExtension[]  = {'.','N','T','x','8','6',0};
57 static const WCHAR Version[]  = {'V','e','r','s','i','o','n',0};
58 static const WCHAR WinExtension[]  = {'.','W','i','n',0};
59
60 /* Registry key and value names */
61 static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
62                                   'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
63                                   'C','o','n','t','r','o','l','\\',
64                                   'C','l','a','s','s',0};
65
66 static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
67                                   'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
68                                   'C','o','n','t','r','o','l','\\',
69                                   'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
70 static const WCHAR Enum[] = {'S','y','s','t','e','m','\\',
71                                   'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
72                                   'E','n','u','m',0};
73 static const WCHAR DeviceDesc[] = {'D','e','v','i','c','e','D','e','s','c',0};
74 static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
75 static const WCHAR HardwareId[] = {'H','a','r','d','w','a','r','e','I','D',0};
76 static const WCHAR CompatibleIDs[] = {'C','o','m','p','a','t','i','b','l','e','I','d','s',0};
77 static const WCHAR Service[] = {'S','e','r','v','i','c','e',0};
78 static const WCHAR Driver[] = {'D','r','i','v','e','r',0};
79 static const WCHAR ConfigFlags[] = {'C','o','n','f','i','g','F','l','a','g','s',0};
80 static const WCHAR Mfg[] = {'M','f','g',0};
81 static const WCHAR FriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
82 static const WCHAR LocationInformation[] = {'L','o','c','a','t','i','o','n','I','n','f','o','r','m','a','t','i','o','n',0};
83 static const WCHAR Capabilities[] = {'C','a','p','a','b','i','l','i','t','i','e','s',0};
84 static const WCHAR UINumber[] = {'U','I','N','u','m','b','e','r',0};
85 static const WCHAR UpperFilters[] = {'U','p','p','e','r','F','i','l','t','e','r','s',0};
86 static const WCHAR LowerFilters[] = {'L','o','w','e','r','F','i','l','t','e','r','s',0};
87 static const WCHAR Phantom[] = {'P','h','a','n','t','o','m',0};
88
89 /* is used to identify if a DeviceInfoSet pointer is
90 valid or not */
91 #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056
92
93 struct DeviceInfoSet
94 {
95     DWORD magic;        /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */
96     GUID ClassGuid;
97     HWND hwndParent;
98     DWORD cDevices;
99     SP_DEVINFO_DATA *devices;
100 };
101
102 /* Pointed to by SP_DEVINFO_DATA's Reserved member */
103 struct DeviceInfo
104 {
105     HKEY   key;
106     BOOL   phantom;
107     LPWSTR instanceId;
108 };
109
110 static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(LPCWSTR instanceId,
111         BOOL phantom)
112 {
113     struct DeviceInfo *devInfo = HeapAlloc(GetProcessHeap(), 0,
114             sizeof(struct DeviceInfo));
115
116     if (devInfo)
117     {
118         devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
119                 (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
120         if (devInfo->instanceId)
121         {
122             HKEY enumKey;
123             LONG l;
124
125             devInfo->key = INVALID_HANDLE_VALUE;
126             devInfo->phantom = phantom;
127             lstrcpyW(devInfo->instanceId, instanceId);
128             struprW(devInfo->instanceId);
129             l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
130                     KEY_ALL_ACCESS, NULL, &enumKey, NULL);
131             if (!l)
132             {
133                 RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
134                         KEY_ALL_ACCESS, NULL, &devInfo->key, NULL);
135                 if (phantom)
136                     RegSetValueExW(devInfo->key, Phantom, 0, REG_DWORD,
137                             (LPBYTE)&phantom, sizeof(phantom));
138                 RegCloseKey(enumKey);
139             }
140         }
141         else
142         {
143             HeapFree(GetProcessHeap(), 0, devInfo);
144             devInfo = NULL;
145         }
146     }
147     return devInfo;
148 }
149
150 static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
151 {
152     if (devInfo->key != INVALID_HANDLE_VALUE)
153         RegCloseKey(devInfo->key);
154     if (devInfo->phantom)
155     {
156         HKEY enumKey;
157         LONG l;
158
159         l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
160                 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
161         if (!l)
162         {
163             RegDeleteTreeW(enumKey, devInfo->instanceId);
164             RegCloseKey(enumKey);
165         }
166     }
167     HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
168     HeapFree(GetProcessHeap(), 0, devInfo);
169 }
170
171 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
172 {
173     static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
174         '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
175         'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
176         '0','2','X','}',0};
177
178     sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
179         guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
180         guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
181 }
182
183 /* Adds a device with GUID guid and identifer devInst to set.  Allocates a
184  * struct DeviceInfo, and points the returned device info's Reserved member
185  * to it.  "Phantom" devices are deleted from the registry when closed.
186  * Returns a pointer to the newly allocated device info.
187  */
188 static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set,
189         const GUID *guid,
190         DWORD devInst,
191         LPCWSTR instanceId,
192         BOOL phantom,
193         SP_DEVINFO_DATA **dev)
194 {
195     BOOL ret = FALSE;
196     struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(instanceId,
197             phantom);
198
199     TRACE("%p, %s, %d, %s, %d\n", set, debugstr_guid(guid), devInst,
200             debugstr_w(instanceId), phantom);
201
202     if (devInfo)
203     {
204         if (set->devices)
205             set->devices = HeapReAlloc(GetProcessHeap(), 0, set->devices,
206                     (set->cDevices + 1) * sizeof(SP_DEVINFO_DATA));
207         else
208             set->devices = HeapAlloc(GetProcessHeap(), 0,
209                     sizeof(SP_DEVINFO_DATA));
210         if (set->devices)
211         {
212             WCHAR classGuidStr[39];
213
214             *dev = &set->devices[set->cDevices++];
215             (*dev)->cbSize = sizeof(SP_DEVINFO_DATA);
216             memcpy(&(*dev)->ClassGuid, guid, sizeof(GUID));
217             (*dev)->DevInst = devInst;
218             (*dev)->Reserved = (ULONG_PTR)devInfo;
219             SETUPDI_GuidToString(guid, classGuidStr);
220             SetupDiSetDeviceRegistryPropertyW((HDEVINFO)set,
221                 *dev, SPDRP_CLASSGUID, (const BYTE *)classGuidStr,
222                 lstrlenW(classGuidStr) * sizeof(WCHAR));
223             ret = TRUE;
224         }
225         else
226         {
227             HeapFree(GetProcessHeap(), 0, devInfo);
228             SetLastError(ERROR_OUTOFMEMORY);
229         }
230     }
231     return ret;
232 }
233
234 /***********************************************************************
235  *              SetupDiBuildClassInfoList  (SETUPAPI.@)
236  *
237  * Returns a list of setup class GUIDs that identify the classes
238  * that are installed on a local machine.
239  *
240  * PARAMS
241  *   Flags [I] control exclusion of classes from the list.
242  *   ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
243  *   ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
244  *   RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
245  *
246  * RETURNS
247  *   Success: TRUE.
248  *   Failure: FALSE.
249  */
250 BOOL WINAPI SetupDiBuildClassInfoList(
251         DWORD Flags,
252         LPGUID ClassGuidList,
253         DWORD ClassGuidListSize,
254         PDWORD RequiredSize)
255 {
256     TRACE("\n");
257     return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
258                                         ClassGuidListSize, RequiredSize,
259                                         NULL, NULL);
260 }
261
262 /***********************************************************************
263  *              SetupDiBuildClassInfoListExA  (SETUPAPI.@)
264  *
265  * Returns a list of setup class GUIDs that identify the classes
266  * that are installed on a local or remote macine.
267  *
268  * PARAMS
269  *   Flags [I] control exclusion of classes from the list.
270  *   ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
271  *   ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
272  *   RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
273  *   MachineName [I] name of a remote machine.
274  *   Reserved [I] must be NULL.
275  *
276  * RETURNS
277  *   Success: TRUE.
278  *   Failure: FALSE.
279  */
280 BOOL WINAPI SetupDiBuildClassInfoListExA(
281         DWORD Flags,
282         LPGUID ClassGuidList,
283         DWORD ClassGuidListSize,
284         PDWORD RequiredSize,
285         LPCSTR MachineName,
286         PVOID Reserved)
287 {
288     LPWSTR MachineNameW = NULL;
289     BOOL bResult;
290
291     TRACE("\n");
292
293     if (MachineName)
294     {
295         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
296         if (MachineNameW == NULL) return FALSE;
297     }
298
299     bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
300                                            ClassGuidListSize, RequiredSize,
301                                            MachineNameW, Reserved);
302
303     MyFree(MachineNameW);
304
305     return bResult;
306 }
307
308 /***********************************************************************
309  *              SetupDiBuildClassInfoListExW  (SETUPAPI.@)
310  *
311  * Returns a list of setup class GUIDs that identify the classes
312  * that are installed on a local or remote macine.
313  *
314  * PARAMS
315  *   Flags [I] control exclusion of classes from the list.
316  *   ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
317  *   ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
318  *   RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
319  *   MachineName [I] name of a remote machine.
320  *   Reserved [I] must be NULL.
321  *
322  * RETURNS
323  *   Success: TRUE.
324  *   Failure: FALSE.
325  */
326 BOOL WINAPI SetupDiBuildClassInfoListExW(
327         DWORD Flags,
328         LPGUID ClassGuidList,
329         DWORD ClassGuidListSize,
330         PDWORD RequiredSize,
331         LPCWSTR MachineName,
332         PVOID Reserved)
333 {
334     WCHAR szKeyName[40];
335     HKEY hClassesKey;
336     HKEY hClassKey;
337     DWORD dwLength;
338     DWORD dwIndex;
339     LONG lError;
340     DWORD dwGuidListIndex = 0;
341
342     TRACE("\n");
343
344     if (RequiredSize != NULL)
345         *RequiredSize = 0;
346
347     hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
348                                             KEY_ALL_ACCESS,
349                                             DIOCR_INSTALLER,
350                                             MachineName,
351                                             Reserved);
352     if (hClassesKey == INVALID_HANDLE_VALUE)
353     {
354         return FALSE;
355     }
356
357     for (dwIndex = 0; ; dwIndex++)
358     {
359         dwLength = 40;
360         lError = RegEnumKeyExW(hClassesKey,
361                                dwIndex,
362                                szKeyName,
363                                &dwLength,
364                                NULL,
365                                NULL,
366                                NULL,
367                                NULL);
368         TRACE("RegEnumKeyExW() returns %d\n", lError);
369         if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
370         {
371             TRACE("Key name: %p\n", szKeyName);
372
373             if (RegOpenKeyExW(hClassesKey,
374                               szKeyName,
375                               0,
376                               KEY_ALL_ACCESS,
377                               &hClassKey))
378             {
379                 RegCloseKey(hClassesKey);
380                 return FALSE;
381             }
382
383             if (!RegQueryValueExW(hClassKey,
384                                   NoUseClass,
385                                   NULL,
386                                   NULL,
387                                   NULL,
388                                   NULL))
389             {
390                 TRACE("'NoUseClass' value found!\n");
391                 RegCloseKey(hClassKey);
392                 continue;
393             }
394
395             if ((Flags & DIBCI_NOINSTALLCLASS) &&
396                 (!RegQueryValueExW(hClassKey,
397                                    NoInstallClass,
398                                    NULL,
399                                    NULL,
400                                    NULL,
401                                    NULL)))
402             {
403                 TRACE("'NoInstallClass' value found!\n");
404                 RegCloseKey(hClassKey);
405                 continue;
406             }
407
408             if ((Flags & DIBCI_NODISPLAYCLASS) &&
409                 (!RegQueryValueExW(hClassKey,
410                                    NoDisplayClass,
411                                    NULL,
412                                    NULL,
413                                    NULL,
414                                    NULL)))
415             {
416                 TRACE("'NoDisplayClass' value found!\n");
417                 RegCloseKey(hClassKey);
418                 continue;
419             }
420
421             RegCloseKey(hClassKey);
422
423             TRACE("Guid: %p\n", szKeyName);
424             if (dwGuidListIndex < ClassGuidListSize)
425             {
426                 if (szKeyName[0] == '{' && szKeyName[37] == '}')
427                 {
428                     szKeyName[37] = 0;
429                 }
430                 TRACE("Guid: %p\n", &szKeyName[1]);
431
432                 UuidFromStringW(&szKeyName[1],
433                                 &ClassGuidList[dwGuidListIndex]);
434             }
435
436             dwGuidListIndex++;
437         }
438
439         if (lError != ERROR_SUCCESS)
440             break;
441     }
442
443     RegCloseKey(hClassesKey);
444
445     if (RequiredSize != NULL)
446         *RequiredSize = dwGuidListIndex;
447
448     if (ClassGuidListSize < dwGuidListIndex)
449     {
450         SetLastError(ERROR_INSUFFICIENT_BUFFER);
451         return FALSE;
452     }
453
454     return TRUE;
455 }
456
457 /***********************************************************************
458  *              SetupDiClassGuidsFromNameA  (SETUPAPI.@)
459  */
460 BOOL WINAPI SetupDiClassGuidsFromNameA(
461         LPCSTR ClassName,
462         LPGUID ClassGuidList,
463         DWORD ClassGuidListSize,
464         PDWORD RequiredSize)
465 {
466   return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
467                                       ClassGuidListSize, RequiredSize,
468                                       NULL, NULL);
469 }
470
471 /***********************************************************************
472  *              SetupDiClassGuidsFromNameW  (SETUPAPI.@)
473  */
474 BOOL WINAPI SetupDiClassGuidsFromNameW(
475         LPCWSTR ClassName,
476         LPGUID ClassGuidList,
477         DWORD ClassGuidListSize,
478         PDWORD RequiredSize)
479 {
480   return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
481                                       ClassGuidListSize, RequiredSize,
482                                       NULL, NULL);
483 }
484
485 /***********************************************************************
486  *              SetupDiClassGuidsFromNameExA  (SETUPAPI.@)
487  */
488 BOOL WINAPI SetupDiClassGuidsFromNameExA(
489         LPCSTR ClassName,
490         LPGUID ClassGuidList,
491         DWORD ClassGuidListSize,
492         PDWORD RequiredSize,
493         LPCSTR MachineName,
494         PVOID Reserved)
495 {
496     LPWSTR ClassNameW = NULL;
497     LPWSTR MachineNameW = NULL;
498     BOOL bResult;
499
500     FIXME("\n");
501
502     ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
503     if (ClassNameW == NULL)
504         return FALSE;
505
506     if (MachineName)
507     {
508         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
509         if (MachineNameW == NULL)
510         {
511             MyFree(ClassNameW);
512             return FALSE;
513         }
514     }
515
516     bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
517                                            ClassGuidListSize, RequiredSize,
518                                            MachineNameW, Reserved);
519
520     MyFree(MachineNameW);
521     MyFree(ClassNameW);
522
523     return bResult;
524 }
525
526 /***********************************************************************
527  *              SetupDiClassGuidsFromNameExW  (SETUPAPI.@)
528  */
529 BOOL WINAPI SetupDiClassGuidsFromNameExW(
530         LPCWSTR ClassName,
531         LPGUID ClassGuidList,
532         DWORD ClassGuidListSize,
533         PDWORD RequiredSize,
534         LPCWSTR MachineName,
535         PVOID Reserved)
536 {
537     WCHAR szKeyName[40];
538     WCHAR szClassName[256];
539     HKEY hClassesKey;
540     HKEY hClassKey;
541     DWORD dwLength;
542     DWORD dwIndex;
543     LONG lError;
544     DWORD dwGuidListIndex = 0;
545
546     if (RequiredSize != NULL)
547         *RequiredSize = 0;
548
549     hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
550                                             KEY_ALL_ACCESS,
551                                             DIOCR_INSTALLER,
552                                             MachineName,
553                                             Reserved);
554     if (hClassesKey == INVALID_HANDLE_VALUE)
555     {
556         return FALSE;
557     }
558
559     for (dwIndex = 0; ; dwIndex++)
560     {
561         dwLength = 40;
562         lError = RegEnumKeyExW(hClassesKey,
563                                dwIndex,
564                                szKeyName,
565                                &dwLength,
566                                NULL,
567                                NULL,
568                                NULL,
569                                NULL);
570         TRACE("RegEnumKeyExW() returns %d\n", lError);
571         if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
572         {
573             TRACE("Key name: %p\n", szKeyName);
574
575             if (RegOpenKeyExW(hClassesKey,
576                               szKeyName,
577                               0,
578                               KEY_ALL_ACCESS,
579                               &hClassKey))
580             {
581                 RegCloseKey(hClassesKey);
582                 return FALSE;
583             }
584
585             dwLength = 256 * sizeof(WCHAR);
586             if (!RegQueryValueExW(hClassKey,
587                                   Class,
588                                   NULL,
589                                   NULL,
590                                   (LPBYTE)szClassName,
591                                   &dwLength))
592             {
593                 TRACE("Class name: %p\n", szClassName);
594
595                 if (strcmpiW(szClassName, ClassName) == 0)
596                 {
597                     TRACE("Found matching class name\n");
598
599                     TRACE("Guid: %p\n", szKeyName);
600                     if (dwGuidListIndex < ClassGuidListSize)
601                     {
602                         if (szKeyName[0] == '{' && szKeyName[37] == '}')
603                         {
604                             szKeyName[37] = 0;
605                         }
606                         TRACE("Guid: %p\n", &szKeyName[1]);
607
608                         UuidFromStringW(&szKeyName[1],
609                                         &ClassGuidList[dwGuidListIndex]);
610                     }
611
612                     dwGuidListIndex++;
613                 }
614             }
615
616             RegCloseKey(hClassKey);
617         }
618
619         if (lError != ERROR_SUCCESS)
620             break;
621     }
622
623     RegCloseKey(hClassesKey);
624
625     if (RequiredSize != NULL)
626         *RequiredSize = dwGuidListIndex;
627
628     if (ClassGuidListSize < dwGuidListIndex)
629     {
630         SetLastError(ERROR_INSUFFICIENT_BUFFER);
631         return FALSE;
632     }
633
634     return TRUE;
635 }
636
637 /***********************************************************************
638  *              SetupDiClassNameFromGuidA  (SETUPAPI.@)
639  */
640 BOOL WINAPI SetupDiClassNameFromGuidA(
641         const GUID* ClassGuid,
642         PSTR ClassName,
643         DWORD ClassNameSize,
644         PDWORD RequiredSize)
645 {
646   return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
647                                      ClassNameSize, RequiredSize,
648                                      NULL, NULL);
649 }
650
651 /***********************************************************************
652  *              SetupDiClassNameFromGuidW  (SETUPAPI.@)
653  */
654 BOOL WINAPI SetupDiClassNameFromGuidW(
655         const GUID* ClassGuid,
656         PWSTR ClassName,
657         DWORD ClassNameSize,
658         PDWORD RequiredSize)
659 {
660   return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
661                                      ClassNameSize, RequiredSize,
662                                      NULL, NULL);
663 }
664
665 /***********************************************************************
666  *              SetupDiClassNameFromGuidExA  (SETUPAPI.@)
667  */
668 BOOL WINAPI SetupDiClassNameFromGuidExA(
669         const GUID* ClassGuid,
670         PSTR ClassName,
671         DWORD ClassNameSize,
672         PDWORD RequiredSize,
673         PCSTR MachineName,
674         PVOID Reserved)
675 {
676     WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
677     LPWSTR MachineNameW = NULL;
678     BOOL ret;
679
680     if (MachineName)
681         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
682     ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
683      NULL, MachineNameW, Reserved);
684     if (ret)
685     {
686         int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
687          ClassNameSize, NULL, NULL);
688
689         if (!ClassNameSize && RequiredSize)
690             *RequiredSize = len;
691     }
692     MyFree(MachineNameW);
693     return ret;
694 }
695
696 /***********************************************************************
697  *              SetupDiClassNameFromGuidExW  (SETUPAPI.@)
698  */
699 BOOL WINAPI SetupDiClassNameFromGuidExW(
700         const GUID* ClassGuid,
701         PWSTR ClassName,
702         DWORD ClassNameSize,
703         PDWORD RequiredSize,
704         PCWSTR MachineName,
705         PVOID Reserved)
706 {
707     HKEY hKey;
708     DWORD dwLength;
709
710     hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
711                                      KEY_ALL_ACCESS,
712                                      DIOCR_INSTALLER,
713                                      MachineName,
714                                      Reserved);
715     if (hKey == INVALID_HANDLE_VALUE)
716     {
717         return FALSE;
718     }
719
720     if (RequiredSize != NULL)
721     {
722         dwLength = 0;
723         if (RegQueryValueExW(hKey,
724                              Class,
725                              NULL,
726                              NULL,
727                              NULL,
728                              &dwLength))
729         {
730             RegCloseKey(hKey);
731             return FALSE;
732         }
733
734         *RequiredSize = dwLength / sizeof(WCHAR);
735     }
736
737     dwLength = ClassNameSize * sizeof(WCHAR);
738     if (RegQueryValueExW(hKey,
739                          Class,
740                          NULL,
741                          NULL,
742                          (LPBYTE)ClassName,
743                          &dwLength))
744     {
745         RegCloseKey(hKey);
746         return FALSE;
747     }
748
749     RegCloseKey(hKey);
750
751     return TRUE;
752 }
753
754 /***********************************************************************
755  *              SetupDiCreateDeviceInfoList (SETUPAPI.@)
756  */
757 HDEVINFO WINAPI
758 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
759                             HWND hwndParent)
760 {
761   return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
762 }
763
764 /***********************************************************************
765  *              SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
766  */
767 HDEVINFO WINAPI
768 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
769                                HWND hwndParent,
770                                PCSTR MachineName,
771                                PVOID Reserved)
772 {
773     LPWSTR MachineNameW = NULL;
774     HDEVINFO hDevInfo;
775
776     TRACE("\n");
777
778     if (MachineName)
779     {
780         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
781         if (MachineNameW == NULL)
782             return (HDEVINFO)INVALID_HANDLE_VALUE;
783     }
784
785     hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
786                                               MachineNameW, Reserved);
787
788     MyFree(MachineNameW);
789
790     return hDevInfo;
791 }
792
793 /***********************************************************************
794  *              SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
795  *
796  * Create an empty DeviceInfoSet list.
797  *
798  * PARAMS
799  *   ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
800  *                 with this list.
801  *   hwndParent [I] hwnd needed for interface related actions.
802  *   MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
803  *                   local registry will be used.
804  *   Reserved [I] must be NULL
805  *
806  * RETURNS
807  *   Success: empty list.
808  *   Failure: INVALID_HANDLE_VALUE.
809  */
810 HDEVINFO WINAPI
811 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
812                                HWND hwndParent,
813                                PCWSTR MachineName,
814                                PVOID Reserved)
815 {
816     struct DeviceInfoSet *list = NULL;
817     DWORD size = sizeof(struct DeviceInfoSet);
818
819     TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
820       debugstr_w(MachineName), Reserved);
821
822     if (MachineName != NULL)
823     {
824         FIXME("remote support is not implemented\n");
825         SetLastError(ERROR_INVALID_MACHINENAME);
826         return (HDEVINFO)INVALID_HANDLE_VALUE;
827     }
828
829     if (Reserved != NULL)
830     {
831         SetLastError(ERROR_INVALID_PARAMETER);
832         return (HDEVINFO)INVALID_HANDLE_VALUE;
833     }
834
835     list = HeapAlloc(GetProcessHeap(), 0, size);
836     if (!list)
837     {
838         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
839         return (HDEVINFO)INVALID_HANDLE_VALUE;
840     }
841
842     list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
843     list->hwndParent = hwndParent;
844     memcpy(&list->ClassGuid,
845             ClassGuid ? ClassGuid : &GUID_NULL,
846             sizeof(list->ClassGuid));
847     list->cDevices = 0;
848     list->devices = NULL;
849
850     return (HDEVINFO)list;
851 }
852
853 /***********************************************************************
854  *              SetupDiCreateDeviceInfoA (SETUPAPI.@)
855  */
856 BOOL WINAPI SetupDiCreateDeviceInfoA(
857        HDEVINFO DeviceInfoSet,
858        PCSTR DeviceName,
859        CONST GUID *ClassGuid,
860        PCSTR DeviceDescription,
861        HWND hwndParent,
862        DWORD CreationFlags,
863        PSP_DEVINFO_DATA DeviceInfoData)
864 {
865     BOOL ret = FALSE;
866     LPWSTR DeviceNameW = NULL;
867     LPWSTR DeviceDescriptionW = NULL;
868
869     if (DeviceName)
870     {
871         DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
872         if (DeviceNameW == NULL) return FALSE;
873     }
874     if (DeviceDescription)
875     {
876         DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
877         if (DeviceDescriptionW == NULL)
878         {
879             MyFree(DeviceNameW);
880             return FALSE;
881         }
882     }
883
884     ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
885             hwndParent, CreationFlags, DeviceInfoData);
886
887     MyFree(DeviceNameW);
888     MyFree(DeviceDescriptionW);
889
890     return ret;
891 }
892
893 static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
894 {
895     LPCWSTR ptr;
896     DWORD devNameLen = lstrlenW(devName), devInst = 0;
897     BOOL valid = TRUE;
898
899     TRACE("%s\n", debugstr_w(devName));
900     for (ptr = devName; valid && *ptr && ptr - devName < devNameLen; )
901     {
902         if (isdigitW(*ptr))
903         {
904             devInst *= 10;
905             devInst |= *ptr - '0';
906             ptr++;
907         }
908         else
909             valid = FALSE;
910     }
911     TRACE("%d\n", valid ? devInst : 0xffffffff);
912     return valid ? devInst : 0xffffffff;
913 }
914
915 /***********************************************************************
916  *              SetupDiCreateDeviceInfoW (SETUPAPI.@)
917  */
918 BOOL WINAPI SetupDiCreateDeviceInfoW(
919        HDEVINFO DeviceInfoSet,
920        PCWSTR DeviceName,
921        CONST GUID *ClassGuid,
922        PCWSTR DeviceDescription,
923        HWND hwndParent,
924        DWORD CreationFlags,
925        PSP_DEVINFO_DATA DeviceInfoData)
926 {
927     struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
928     BOOL ret = FALSE, allocatedInstanceId = FALSE;
929     LPCWSTR instanceId = NULL;
930
931     TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
932         debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
933         hwndParent, CreationFlags, DeviceInfoData);
934
935     if (!DeviceName)
936     {
937         SetLastError(ERROR_INVALID_DEVINST_NAME);
938         return FALSE;
939     }
940     if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
941     {
942         SetLastError(ERROR_INVALID_HANDLE);
943         return FALSE;
944     }
945     if (!ClassGuid)
946     {
947         SetLastError(ERROR_INVALID_PARAMETER);
948         return FALSE;
949     }
950     if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
951     {
952         SetLastError(ERROR_INVALID_HANDLE);
953         return FALSE;
954     }
955     if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
956         !IsEqualGUID(ClassGuid, &set->ClassGuid))
957     {
958         SetLastError(ERROR_CLASS_MISMATCH);
959         return FALSE;
960     }
961     if ((CreationFlags & DICD_GENERATE_ID))
962     {
963         if (strchrW(DeviceName, '\\'))
964             SetLastError(ERROR_INVALID_DEVINST_NAME);
965         else
966         {
967             static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
968                 '\\','%','0','4','d',0};
969             DWORD devId;
970
971             if (set->cDevices)
972             {
973                 DWORD i, highestDevID = 0;
974
975                 for (i = 0; i < set->cDevices; i++)
976                 {
977                     struct DeviceInfo *devInfo =
978                         (struct DeviceInfo *)set->devices[i].Reserved;
979                     LPCWSTR devName = strrchrW(devInfo->instanceId, '\\');
980                     DWORD id;
981
982                     if (devName)
983                         devName++;
984                     else
985                         devName = devInfo->instanceId;
986                     id = SETUPDI_DevNameToDevID(devName);
987                     if (id != 0xffffffff && id > highestDevID)
988                         highestDevID = id;
989                 }
990                 devId = highestDevID + 1;
991             }
992             else
993                 devId = 0;
994             /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
995             instanceId = HeapAlloc(GetProcessHeap(), 0,
996                     (17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
997             if (instanceId)
998             {
999                 sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
1000                         devId);
1001                 allocatedInstanceId = TRUE;
1002                 ret = TRUE;
1003             }
1004             else
1005                 ret = FALSE;
1006         }
1007     }
1008     else
1009     {
1010         DWORD i;
1011
1012         ret = TRUE;
1013         instanceId = DeviceName;
1014         for (i = 0; ret && i < set->cDevices; i++)
1015         {
1016             struct DeviceInfo *devInfo =
1017                 (struct DeviceInfo *)set->devices[i].Reserved;
1018
1019             if (!lstrcmpiW(DeviceName, devInfo->instanceId))
1020             {
1021                 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1022                 ret = FALSE;
1023             }
1024         }
1025     }
1026     if (ret)
1027     {
1028         SP_DEVINFO_DATA *dev = NULL;
1029
1030         ret = SETUPDI_AddDeviceToSet(set, ClassGuid, 0 /* FIXME: DevInst */,
1031                 instanceId, TRUE, &dev);
1032         if (ret)
1033         {
1034             if (DeviceDescription)
1035                 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
1036                     dev, SPDRP_DEVICEDESC, (const BYTE *)DeviceDescription,
1037                     lstrlenW(DeviceDescription) * sizeof(WCHAR));
1038             if (DeviceInfoData)
1039             {
1040                 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1041                 {
1042                     SetLastError(ERROR_INVALID_USER_BUFFER);
1043                     ret = FALSE;
1044                 }
1045                 else
1046                     memcpy(DeviceInfoData, dev, sizeof(SP_DEVINFO_DATA));
1047             }
1048         }
1049     }
1050     if (allocatedInstanceId)
1051         HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
1052
1053     return ret;
1054 }
1055
1056 /***********************************************************************
1057  *              SetupDiRegisterDeviceInfo (SETUPAPI.@)
1058  */
1059 BOOL WINAPI SetupDiRegisterDeviceInfo(
1060         HDEVINFO DeviceInfoSet,
1061         PSP_DEVINFO_DATA DeviceInfoData,
1062         DWORD Flags,
1063         PSP_DETSIG_CMPPROC CompareProc,
1064         PVOID CompareContext,
1065         PSP_DEVINFO_DATA DupDeviceInfoData)
1066 {
1067     struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1068     struct DeviceInfo *devInfo;
1069
1070     TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1071             CompareProc, CompareContext, DupDeviceInfoData);
1072
1073     if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
1074     {
1075         SetLastError(ERROR_INVALID_HANDLE);
1076         return FALSE;
1077     }
1078     if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1079     {
1080         SetLastError(ERROR_INVALID_HANDLE);
1081         return FALSE;
1082     }
1083     if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1084             || !DeviceInfoData->Reserved)
1085     {
1086         SetLastError(ERROR_INVALID_PARAMETER);
1087         return FALSE;
1088     }
1089     devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1090     if (devInfo->phantom)
1091     {
1092         devInfo->phantom = FALSE;
1093         RegDeleteValueW(devInfo->key, Phantom);
1094     }
1095     return TRUE;
1096 }
1097
1098 /***********************************************************************
1099  *              SetupDiEnumDeviceInfo (SETUPAPI.@)
1100  */
1101 BOOL WINAPI SetupDiEnumDeviceInfo(
1102         HDEVINFO  devinfo,
1103         DWORD  index,
1104         PSP_DEVINFO_DATA info)
1105 {
1106     BOOL ret = FALSE;
1107
1108     TRACE("%p %d %p\n", devinfo, index, info);
1109
1110     if(info==NULL)
1111         return FALSE;
1112     if(info->cbSize < sizeof(*info))
1113         return FALSE;
1114     if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1115     {
1116         struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1117         if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1118         {
1119             if (index < list->cDevices)
1120             {
1121                 if (info->cbSize == sizeof(SP_DEVINFO_DATA))
1122                 {
1123                     memcpy(info, &list->devices[index], info->cbSize);
1124                     ret = TRUE;
1125                 }
1126                 else
1127                     SetLastError(ERROR_INVALID_USER_BUFFER);
1128             }
1129             else
1130                 SetLastError(ERROR_NO_MORE_ITEMS);
1131         }
1132         else
1133             SetLastError(ERROR_INVALID_HANDLE);
1134     }
1135     else
1136         SetLastError(ERROR_INVALID_HANDLE);
1137     return ret;
1138 }
1139
1140 /***********************************************************************
1141  *              SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1142  */
1143 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1144         HDEVINFO DeviceInfoSet,
1145         PSP_DEVINFO_DATA DeviceInfoData,
1146         PSTR DeviceInstanceId,
1147         DWORD DeviceInstanceIdSize,
1148         PDWORD RequiredSize)
1149 {
1150     BOOL ret = FALSE;
1151     DWORD size;
1152     PWSTR instanceId;
1153
1154     TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1155             DeviceInstanceIdSize, RequiredSize);
1156
1157     SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1158                                 DeviceInfoData,
1159                                 NULL,
1160                                 0,
1161                                 &size);
1162     if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1163         return FALSE;
1164     instanceId = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1165     if (instanceId)
1166     {
1167         ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1168                                           DeviceInfoData,
1169                                           instanceId,
1170                                           size,
1171                                           &size);
1172         if (ret)
1173         {
1174             int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1175                                           DeviceInstanceId,
1176                                           DeviceInstanceIdSize, NULL, NULL);
1177
1178             if (!len)
1179                 ret = FALSE;
1180             else
1181             {
1182                 if (len > DeviceInstanceIdSize)
1183                 {
1184                     SetLastError(ERROR_INSUFFICIENT_BUFFER);
1185                     ret = FALSE;
1186                 }
1187                 if (RequiredSize)
1188                     *RequiredSize = len;
1189             }
1190         }
1191         HeapFree(GetProcessHeap(), 0, instanceId);
1192     }
1193     return ret;
1194 }
1195
1196 /***********************************************************************
1197  *              SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1198  */
1199 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1200         HDEVINFO DeviceInfoSet,
1201         PSP_DEVINFO_DATA DeviceInfoData,
1202         PWSTR DeviceInstanceId,
1203         DWORD DeviceInstanceIdSize,
1204         PDWORD RequiredSize)
1205 {
1206     struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1207     struct DeviceInfo *devInfo;
1208
1209     TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1210             DeviceInstanceIdSize, RequiredSize);
1211
1212     if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1213     {
1214         SetLastError(ERROR_INVALID_HANDLE);
1215         return FALSE;
1216     }
1217     if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1218     {
1219         SetLastError(ERROR_INVALID_HANDLE);
1220         return FALSE;
1221     }
1222     if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1223             || !DeviceInfoData->Reserved)
1224     {
1225         SetLastError(ERROR_INVALID_PARAMETER);
1226         return FALSE;
1227     }
1228     devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1229     TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1230     if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1231     {
1232         SetLastError(ERROR_INSUFFICIENT_BUFFER);
1233         if (RequiredSize)
1234             *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1235         return FALSE;
1236     }
1237     lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1238     if (RequiredSize)
1239         *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1240     return TRUE;
1241 }
1242
1243 /***********************************************************************
1244  *              SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1245  */
1246 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1247         HINF InfHandle,
1248         PCSTR InfSectionName,
1249         PSTR InfSectionWithExt,
1250         DWORD InfSectionWithExtSize,
1251         PDWORD RequiredSize,
1252         PSTR *Extension)
1253 {
1254     FIXME("\n");
1255     return FALSE;
1256 }
1257
1258 /***********************************************************************
1259  *              SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1260  */
1261 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1262         HINF InfHandle,
1263         PCWSTR InfSectionName,
1264         PWSTR InfSectionWithExt,
1265         DWORD InfSectionWithExtSize,
1266         PDWORD RequiredSize,
1267         PWSTR *Extension)
1268 {
1269     WCHAR szBuffer[MAX_PATH];
1270     DWORD dwLength;
1271     DWORD dwFullLength;
1272     LONG lLineCount = -1;
1273
1274     lstrcpyW(szBuffer, InfSectionName);
1275     dwLength = lstrlenW(szBuffer);
1276
1277     if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1278     {
1279         /* Test section name with '.NTx86' extension */
1280         lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
1281         lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1282
1283         if (lLineCount == -1)
1284         {
1285             /* Test section name with '.NT' extension */
1286             lstrcpyW(&szBuffer[dwLength], NtExtension);
1287             lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1288         }
1289     }
1290     else
1291     {
1292         /* Test section name with '.Win' extension */
1293         lstrcpyW(&szBuffer[dwLength], WinExtension);
1294         lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1295     }
1296
1297     if (lLineCount == -1)
1298     {
1299         /* Test section name without extension */
1300         szBuffer[dwLength] = 0;
1301         lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1302     }
1303
1304     if (lLineCount == -1)
1305     {
1306         SetLastError(ERROR_INVALID_PARAMETER);
1307         return FALSE;
1308     }
1309
1310     dwFullLength = lstrlenW(szBuffer);
1311
1312     if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1313     {
1314         if (InfSectionWithExtSize < (dwFullLength + 1))
1315         {
1316             SetLastError(ERROR_INSUFFICIENT_BUFFER);
1317             return FALSE;
1318         }
1319
1320         lstrcpyW(InfSectionWithExt, szBuffer);
1321         if (Extension != NULL)
1322         {
1323             *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1324         }
1325     }
1326
1327     if (RequiredSize != NULL)
1328     {
1329         *RequiredSize = dwFullLength + 1;
1330     }
1331
1332     return TRUE;
1333 }
1334
1335 /***********************************************************************
1336  *              SetupDiGetClassDescriptionA  (SETUPAPI.@)
1337  */
1338 BOOL WINAPI SetupDiGetClassDescriptionA(
1339         const GUID* ClassGuid,
1340         PSTR ClassDescription,
1341         DWORD ClassDescriptionSize,
1342         PDWORD RequiredSize)
1343 {
1344   return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1345                                        ClassDescriptionSize,
1346                                        RequiredSize, NULL, NULL);
1347 }
1348
1349 /***********************************************************************
1350  *              SetupDiGetClassDescriptionW  (SETUPAPI.@)
1351  */
1352 BOOL WINAPI SetupDiGetClassDescriptionW(
1353         const GUID* ClassGuid,
1354         PWSTR ClassDescription,
1355         DWORD ClassDescriptionSize,
1356         PDWORD RequiredSize)
1357 {
1358   return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1359                                        ClassDescriptionSize,
1360                                        RequiredSize, NULL, NULL);
1361 }
1362
1363 /***********************************************************************
1364  *              SetupDiGetClassDescriptionExA  (SETUPAPI.@)
1365  */
1366 BOOL WINAPI SetupDiGetClassDescriptionExA(
1367         const GUID* ClassGuid,
1368         PSTR ClassDescription,
1369         DWORD ClassDescriptionSize,
1370         PDWORD RequiredSize,
1371         PCSTR MachineName,
1372         PVOID Reserved)
1373 {
1374     HKEY hKey;
1375     DWORD dwLength;
1376     BOOL ret;
1377
1378     hKey = SetupDiOpenClassRegKeyExA(ClassGuid,
1379                                      KEY_ALL_ACCESS,
1380                                      DIOCR_INSTALLER,
1381                                      MachineName,
1382                                      Reserved);
1383     if (hKey == INVALID_HANDLE_VALUE)
1384     {
1385         WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
1386         return FALSE;
1387     }
1388
1389     dwLength = ClassDescriptionSize;
1390     ret = !RegQueryValueExA( hKey, NULL, NULL, NULL,
1391                              (LPBYTE)ClassDescription, &dwLength );
1392     if (RequiredSize) *RequiredSize = dwLength;
1393     RegCloseKey(hKey);
1394     return ret;
1395 }
1396
1397 /***********************************************************************
1398  *              SetupDiGetClassDescriptionExW  (SETUPAPI.@)
1399  */
1400 BOOL WINAPI SetupDiGetClassDescriptionExW(
1401         const GUID* ClassGuid,
1402         PWSTR ClassDescription,
1403         DWORD ClassDescriptionSize,
1404         PDWORD RequiredSize,
1405         PCWSTR MachineName,
1406         PVOID Reserved)
1407 {
1408     HKEY hKey;
1409     DWORD dwLength;
1410     BOOL ret;
1411
1412     hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1413                                      KEY_ALL_ACCESS,
1414                                      DIOCR_INSTALLER,
1415                                      MachineName,
1416                                      Reserved);
1417     if (hKey == INVALID_HANDLE_VALUE)
1418     {
1419         WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1420         return FALSE;
1421     }
1422
1423     dwLength = ClassDescriptionSize * sizeof(WCHAR);
1424     ret = !RegQueryValueExW( hKey, NULL, NULL, NULL,
1425                              (LPBYTE)ClassDescription, &dwLength );
1426     if (RequiredSize) *RequiredSize = dwLength / sizeof(WCHAR);
1427     RegCloseKey(hKey);
1428     return ret;
1429 }
1430
1431 /***********************************************************************
1432  *              SetupDiGetClassDevsA (SETUPAPI.@)
1433  */
1434 HDEVINFO WINAPI SetupDiGetClassDevsA(
1435        CONST GUID *class,
1436        LPCSTR enumstr,
1437        HWND parent,
1438        DWORD flags)
1439 {
1440     HDEVINFO ret;
1441     LPWSTR enumstrW = NULL;
1442
1443     if (enumstr)
1444     {
1445         int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1446         enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1447         if (!enumstrW)
1448         {
1449             ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1450             goto end;
1451         }
1452         MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1453     }
1454     ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
1455     HeapFree(GetProcessHeap(), 0, enumstrW);
1456
1457 end:
1458     return ret;
1459 }
1460
1461 static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet,
1462         HKEY key, const GUID *interface, LPCWSTR enumstr)
1463 {
1464     struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1465     DWORD i, len;
1466     WCHAR subKeyName[MAX_PATH];
1467     LONG l;
1468     HKEY enumKey = INVALID_HANDLE_VALUE;
1469
1470     TRACE("%s\n", debugstr_w(enumstr));
1471
1472     l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
1473             &enumKey, NULL);
1474     for (i = 0; !l; i++)
1475     {
1476         len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1477         l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1478         if (!l)
1479         {
1480             HKEY subKey;
1481
1482             l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1483             if (!l)
1484             {
1485                 WCHAR deviceInst[MAX_PATH * 3];
1486                 DWORD dataType;
1487
1488                 len = sizeof(deviceInst);
1489                 l = RegQueryValueExW(subKey, DeviceInstance, NULL, &dataType,
1490                         (BYTE *)deviceInst, &len);
1491                 if (!l && dataType == REG_SZ)
1492                 {
1493                     TRACE("found instance ID %s\n", debugstr_w(deviceInst));
1494                     if (!enumstr || !lstrcmpiW(enumstr, deviceInst))
1495                     {
1496                         HKEY deviceKey;
1497
1498                         l = RegOpenKeyExW(enumKey, deviceInst, 0, KEY_READ,
1499                                 &deviceKey);
1500                         if (!l)
1501                         {
1502                             WCHAR deviceClassStr[40];
1503
1504                             len = sizeof(deviceClassStr);
1505                             l = RegQueryValueExW(deviceKey, ClassGUID, NULL,
1506                                     &dataType, (BYTE *)deviceClassStr, &len);
1507                             if (!l && dataType == REG_SZ &&
1508                                     deviceClassStr[0] == '{' &&
1509                                     deviceClassStr[37] == '}')
1510                             {
1511                                 GUID deviceClass;
1512                                 SP_DEVINFO_DATA *dev;
1513
1514                                 deviceClassStr[37] = 0;
1515                                 UuidFromStringW(&deviceClassStr[1],
1516                                         &deviceClass);
1517                                 SETUPDI_AddDeviceToSet(set, &deviceClass,
1518                                         0 /* FIXME: DevInst */, deviceInst,
1519                                         FALSE, &dev);
1520                                 /* FIXME: add this interface, and all the
1521                                  * device's interfaces, to the device
1522                                  */
1523                             }
1524                             RegCloseKey(deviceKey);
1525                         }
1526                     }
1527                 }
1528                 RegCloseKey(subKey);
1529             }
1530         }
1531     }
1532     if (enumKey != INVALID_HANDLE_VALUE)
1533         RegCloseKey(enumKey);
1534 }
1535
1536 static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet,
1537         const GUID *interface, LPCWSTR enumstr, DWORD flags)
1538 {
1539     HKEY interfacesKey = SetupDiOpenClassRegKeyExW(interface, KEY_READ,
1540             DIOCR_INTERFACE, NULL, NULL);
1541
1542     TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(interface),
1543             debugstr_w(enumstr), flags);
1544
1545     if (interfacesKey != INVALID_HANDLE_VALUE)
1546     {
1547         if (flags & DIGCF_ALLCLASSES)
1548         {
1549             DWORD i, len;
1550             WCHAR interfaceGuidStr[40];
1551             LONG l = ERROR_SUCCESS;
1552
1553             for (i = 0; !l; i++)
1554             {
1555                 len = sizeof(interfaceGuidStr) / sizeof(interfaceGuidStr[0]);
1556                 l = RegEnumKeyExW(interfacesKey, i, interfaceGuidStr, &len,
1557                         NULL, NULL, NULL, NULL);
1558                 if (!l)
1559                 {
1560                     if (interfaceGuidStr[0] == '{' &&
1561                             interfaceGuidStr[37] == '}')
1562                     {
1563                         HKEY interfaceKey;
1564                         GUID interfaceGuid;
1565
1566                         interfaceGuidStr[37] = 0;
1567                         UuidFromStringW(&interfaceGuidStr[1], &interfaceGuid);
1568                         l = RegOpenKeyExW(interfacesKey, interfaceGuidStr, 0,
1569                                 KEY_READ, &interfaceKey);
1570                         if (!l)
1571                         {
1572                             SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
1573                                     interfaceKey, &interfaceGuid, enumstr);
1574                             RegCloseKey(interfaceKey);
1575                         }
1576                     }
1577                 }
1578             }
1579         }
1580         else
1581         {
1582             /* In this case, SetupDiOpenClassRegKeyExW opened the specific
1583              * interface's key, so just pass that long
1584              */
1585             SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
1586                     interfacesKey, interface, enumstr);
1587         }
1588         RegCloseKey(interfacesKey);
1589     }
1590 }
1591
1592 static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet,
1593         LPCWSTR parent, HKEY key, const GUID *class, DWORD flags)
1594 {
1595     struct DeviceInfoSet *set = (struct DeviceInfoSet *)set;
1596     DWORD i, len;
1597     WCHAR subKeyName[MAX_PATH];
1598     LONG l = ERROR_SUCCESS;
1599
1600     TRACE("%s\n", debugstr_w(parent));
1601
1602     for (i = 0; !l; i++)
1603     {
1604         len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1605         l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
1606         if (!l)
1607         {
1608             HKEY subKey;
1609
1610             l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
1611             if (!l)
1612             {
1613                 WCHAR classGuid[40];
1614                 DWORD dataType;
1615
1616                 len = sizeof(classGuid);
1617                 l = RegQueryValueExW(subKey, ClassGUID, NULL, &dataType,
1618                         (BYTE *)classGuid, &len);
1619                 if (!l && dataType == REG_SZ)
1620                 {
1621                     if (classGuid[0] == '{' && classGuid[37] == '}')
1622                     {
1623                         GUID deviceClass;
1624
1625                         classGuid[37] = 0;
1626                         UuidFromStringW(&classGuid[1], &deviceClass);
1627                         if ((flags & DIGCF_ALLCLASSES) ||
1628                                 IsEqualGUID(class, &deviceClass))
1629                         {
1630                             static const WCHAR fmt[] = {'%','s','\\','%','s',0};
1631                             LPWSTR instanceId;
1632
1633                             instanceId = HeapAlloc(GetProcessHeap(), 0,
1634                                 (lstrlenW(parent) + lstrlenW(subKeyName) + 2)
1635                                 * sizeof(WCHAR));
1636                             if (instanceId)
1637                             {
1638                                 SP_DEVINFO_DATA *dev;
1639
1640                                 sprintfW(instanceId, fmt, parent, subKeyName);
1641                                 SETUPDI_AddDeviceToSet(set, &deviceClass,
1642                                         0 /* FIXME: DevInst */, instanceId,
1643                                         FALSE, &dev);
1644                                 HeapFree(GetProcessHeap(), 0, instanceId);
1645                             }
1646                         }
1647                     }
1648                 }
1649                 RegCloseKey(subKey);
1650             }
1651         }
1652     }
1653 }
1654
1655 static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class,
1656         LPCWSTR enumstr, DWORD flags)
1657 {
1658     HKEY classesKey = SetupDiOpenClassRegKeyExW(class, KEY_READ,
1659             DIOCR_INSTALLER, NULL, NULL);
1660
1661     TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class),
1662             debugstr_w(enumstr), flags);
1663
1664     if (classesKey != INVALID_HANDLE_VALUE)
1665     {
1666         if (enumstr)
1667         {
1668             HKEY enumKey;
1669             LONG l = RegOpenKeyExW(classesKey, enumstr, 0, KEY_READ,
1670                     &enumKey);
1671
1672             if (!l)
1673             {
1674                 SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr,
1675                         enumKey, class, flags);
1676                 RegCloseKey(enumKey);
1677             }
1678         }
1679         else
1680         {
1681             DWORD i, len;
1682             WCHAR subKeyName[MAX_PATH];
1683             LONG l = ERROR_SUCCESS;
1684
1685             for (i = 0; !l; i++)
1686             {
1687                 len = sizeof(subKeyName) / sizeof(subKeyName[0]);
1688                 l = RegEnumKeyExW(classesKey, i, subKeyName, &len, NULL,
1689                         NULL, NULL, NULL);
1690                 if (!l)
1691                 {
1692                     HKEY subKey;
1693
1694                     l = RegOpenKeyExW(classesKey, subKeyName, 0, KEY_READ,
1695                             &subKey);
1696                     if (!l)
1697                     {
1698                         SETUPDI_EnumerateMatchingDevices(DeviceInfoSet,
1699                                 subKeyName, subKey, class, flags);
1700                         RegCloseKey(subKey);
1701                     }
1702                 }
1703             }
1704         }
1705         RegCloseKey(classesKey);
1706     }
1707 }
1708
1709 /***********************************************************************
1710  *              SetupDiGetClassDevsW (SETUPAPI.@)
1711  */
1712 HDEVINFO WINAPI SetupDiGetClassDevsW(
1713        CONST GUID *class,
1714        LPCWSTR enumstr,
1715        HWND parent,
1716        DWORD flags)
1717 {
1718     static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PRESENT |
1719         DIGCF_PROFILE;
1720     HDEVINFO set;
1721
1722     TRACE("%s %s %p 0x%08x\n", debugstr_guid(class), debugstr_w(enumstr), parent, flags);
1723
1724     if (!(flags & DIGCF_ALLCLASSES) && !class)
1725     {
1726         SetLastError(ERROR_INVALID_PARAMETER);
1727         return NULL;
1728     }
1729     if (flags & unsupportedFlags)
1730         WARN("unsupported flags %08x\n", flags & unsupportedFlags);
1731     /* WinXP always succeeds, returns empty list for unknown classes */
1732     set = SetupDiCreateDeviceInfoList(class, parent);
1733     if (set)
1734     {
1735         if (flags & DIGCF_DEVICEINTERFACE)
1736             SETUPDI_EnumerateInterfaces(set, class, enumstr, flags);
1737         else
1738             SETUPDI_EnumerateDevices(set, class, enumstr, flags);
1739     }
1740     return set;
1741 }
1742
1743 /***********************************************************************
1744  *              SetupDiGetClassDevsExW (SETUPAPI.@)
1745  */
1746 HDEVINFO WINAPI SetupDiGetClassDevsExW(
1747         CONST GUID *class,
1748         PCWSTR enumstr,
1749         HWND parent,
1750         DWORD flags,
1751         HDEVINFO deviceset,
1752         PCWSTR machine,
1753         PVOID reserved)
1754 {
1755     FIXME("stub\n");
1756     return NULL;
1757 }
1758
1759 /***********************************************************************
1760  *              SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1761  */
1762 BOOL WINAPI SetupDiEnumDeviceInterfaces(
1763        HDEVINFO devinfo,
1764        PSP_DEVINFO_DATA DeviceInfoData,
1765        CONST GUID * InterfaceClassGuid,
1766        DWORD MemberIndex,
1767        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1768 {
1769     BOOL ret = FALSE;
1770
1771     FIXME("%p, %p, %s, 0x%08x, %p\n", devinfo, DeviceInfoData,
1772      debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
1773
1774     if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1775     {
1776         struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1777         if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1778             SetLastError(ERROR_NO_MORE_ITEMS);
1779         else
1780             SetLastError(ERROR_INVALID_HANDLE);
1781     }
1782     else
1783         SetLastError(ERROR_INVALID_HANDLE);
1784     return ret;
1785 }
1786
1787 /***********************************************************************
1788  *              SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1789   *
1790  * Destroy a DeviceInfoList and free all used memory of the list.
1791  *
1792  * PARAMS
1793  *   devinfo [I] DeviceInfoList pointer to list to destroy
1794  *
1795  * RETURNS
1796  *   Success: non zero value.
1797  *   Failure: zero value.
1798  */
1799 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
1800 {
1801     BOOL ret = FALSE;
1802
1803     TRACE("%p\n", devinfo);
1804     if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1805     {
1806         struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1807
1808         if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1809         {
1810             DWORD i;
1811
1812             for (i = 0; i < list->cDevices; i++)
1813                 SETUPDI_FreeDeviceInfo(
1814                         (struct DeviceInfo *)list->devices[i].Reserved);
1815             HeapFree(GetProcessHeap(), 0, list->devices);
1816             HeapFree(GetProcessHeap(), 0, list);
1817             ret = TRUE;
1818         }
1819     }
1820
1821     if (ret == FALSE)
1822         SetLastError(ERROR_INVALID_HANDLE);
1823
1824     return ret;
1825 }
1826
1827 /***********************************************************************
1828  *              SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1829  */
1830 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
1831       HDEVINFO DeviceInfoSet,
1832       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1833       PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
1834       DWORD DeviceInterfaceDetailDataSize,
1835       PDWORD RequiredSize,
1836       PSP_DEVINFO_DATA DeviceInfoData)
1837 {
1838     BOOL ret = FALSE;
1839
1840     FIXME("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
1841      DeviceInterfaceData, DeviceInterfaceDetailData,
1842      DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1843
1844     SetLastError(ERROR_INVALID_HANDLE);
1845     return ret;
1846 }
1847
1848 /***********************************************************************
1849  *              SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
1850  */
1851 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
1852       HDEVINFO DeviceInfoSet,
1853       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1854       PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
1855       DWORD DeviceInterfaceDetailDataSize,
1856       PDWORD RequiredSize,
1857       PSP_DEVINFO_DATA DeviceInfoData)
1858 {
1859     FIXME("(%p, %p, %p, %d, %p, %p): stub\n", DeviceInfoSet,
1860      DeviceInterfaceData, DeviceInterfaceDetailData,
1861      DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1862     return FALSE;
1863 }
1864
1865 struct PropertyMapEntry
1866 {
1867     DWORD   regType;
1868     LPCSTR  nameA;
1869     LPCWSTR nameW;
1870 };
1871
1872 static struct PropertyMapEntry PropertyMap[] = {
1873     { REG_SZ, "DeviceDesc", DeviceDesc },
1874     { REG_MULTI_SZ, "HardwareId", HardwareId },
1875     { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
1876     { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
1877     { REG_SZ, "Service", Service },
1878     { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
1879     { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
1880     { REG_SZ, "Class", Class },
1881     { REG_SZ, "ClassGUID", ClassGUID },
1882     { REG_SZ, "Driver", Driver },
1883     { REG_DWORD, "ConfigFlags", ConfigFlags },
1884     { REG_SZ, "Mfg", Mfg },
1885     { REG_SZ, "FriendlyName", FriendlyName },
1886     { REG_SZ, "LocationInformation", LocationInformation },
1887     { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
1888     { REG_DWORD, "Capabilities", Capabilities },
1889     { REG_DWORD, "UINumber", UINumber },
1890     { REG_MULTI_SZ, "UpperFilters", UpperFilters },
1891     { REG_MULTI_SZ, "LowerFilters", LowerFilters },
1892 };
1893
1894 /***********************************************************************
1895  *              SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
1896  */
1897 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
1898         HDEVINFO  DeviceInfoSet,
1899         PSP_DEVINFO_DATA  DeviceInfoData,
1900         DWORD   Property,
1901         PDWORD  PropertyRegDataType,
1902         PBYTE   PropertyBuffer,
1903         DWORD   PropertyBufferSize,
1904         PDWORD  RequiredSize)
1905 {
1906     BOOL ret = FALSE;
1907     struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1908     struct DeviceInfo *devInfo;
1909
1910     TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
1911         Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1912         RequiredSize);
1913
1914     if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1915     {
1916         SetLastError(ERROR_INVALID_HANDLE);
1917         return FALSE;
1918     }
1919     if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1920     {
1921         SetLastError(ERROR_INVALID_HANDLE);
1922         return FALSE;
1923     }
1924     if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1925             || !DeviceInfoData->Reserved)
1926     {
1927         SetLastError(ERROR_INVALID_PARAMETER);
1928         return FALSE;
1929     }
1930     devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1931     if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
1932         && PropertyMap[Property].nameA)
1933     {
1934         DWORD size = PropertyBufferSize;
1935         LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
1936                 NULL, PropertyRegDataType, PropertyBuffer, &size);
1937
1938         if (RequiredSize)
1939             *RequiredSize = size;
1940         if (!l)
1941             ret = TRUE;
1942         else
1943             SetLastError(l);
1944     }
1945     return ret;
1946 }
1947
1948 /***********************************************************************
1949  *              SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
1950  */
1951 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
1952         HDEVINFO  DeviceInfoSet,
1953         PSP_DEVINFO_DATA  DeviceInfoData,
1954         DWORD   Property,
1955         PDWORD  PropertyRegDataType,
1956         PBYTE   PropertyBuffer,
1957         DWORD   PropertyBufferSize,
1958         PDWORD  RequiredSize)
1959 {
1960     BOOL ret = FALSE;
1961     struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1962     struct DeviceInfo *devInfo;
1963
1964     TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
1965         Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1966         RequiredSize);
1967
1968     if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1969     {
1970         SetLastError(ERROR_INVALID_HANDLE);
1971         return FALSE;
1972     }
1973     if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1974     {
1975         SetLastError(ERROR_INVALID_HANDLE);
1976         return FALSE;
1977     }
1978     if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1979             || !DeviceInfoData->Reserved)
1980     {
1981         SetLastError(ERROR_INVALID_PARAMETER);
1982         return FALSE;
1983     }
1984     devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1985     if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
1986         && PropertyMap[Property].nameW)
1987     {
1988         DWORD size = PropertyBufferSize;
1989         LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
1990                 NULL, PropertyRegDataType, PropertyBuffer, &size);
1991
1992         if (RequiredSize)
1993             *RequiredSize = size;
1994         if (!l)
1995             ret = TRUE;
1996         else
1997             SetLastError(l);
1998     }
1999     return ret;
2000 }
2001
2002 /***********************************************************************
2003  *              SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2004  */
2005 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
2006         HDEVINFO DeviceInfoSet,
2007         PSP_DEVINFO_DATA DeviceInfoData,
2008         DWORD Property,
2009         const BYTE *PropertyBuffer,
2010         DWORD PropertyBufferSize)
2011 {
2012     BOOL ret = FALSE;
2013     struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2014     struct DeviceInfo *devInfo;
2015
2016     TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2017         PropertyBuffer, PropertyBufferSize);
2018
2019     if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2020     {
2021         SetLastError(ERROR_INVALID_HANDLE);
2022         return FALSE;
2023     }
2024     if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2025     {
2026         SetLastError(ERROR_INVALID_HANDLE);
2027         return FALSE;
2028     }
2029     if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2030             || !DeviceInfoData->Reserved)
2031     {
2032         SetLastError(ERROR_INVALID_PARAMETER);
2033         return FALSE;
2034     }
2035     devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2036     if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2037         && PropertyMap[Property].nameA)
2038     {
2039         LONG l = RegSetValueExA(devInfo->key, PropertyMap[Property].nameA, 0,
2040                 PropertyMap[Property].regType, PropertyBuffer,
2041                 PropertyBufferSize);
2042         if (!l)
2043             ret = TRUE;
2044         else
2045             SetLastError(l);
2046     }
2047     return ret;
2048 }
2049
2050 /***********************************************************************
2051  *              SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2052  */
2053 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
2054         HDEVINFO DeviceInfoSet,
2055         PSP_DEVINFO_DATA DeviceInfoData,
2056         DWORD Property,
2057         const BYTE *PropertyBuffer,
2058         DWORD PropertyBufferSize)
2059 {
2060     BOOL ret = FALSE;
2061     struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2062     struct DeviceInfo *devInfo;
2063
2064     TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
2065         PropertyBuffer, PropertyBufferSize);
2066
2067     if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2068     {
2069         SetLastError(ERROR_INVALID_HANDLE);
2070         return FALSE;
2071     }
2072     if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2073     {
2074         SetLastError(ERROR_INVALID_HANDLE);
2075         return FALSE;
2076     }
2077     if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2078             || !DeviceInfoData->Reserved)
2079     {
2080         SetLastError(ERROR_INVALID_PARAMETER);
2081         return FALSE;
2082     }
2083     devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2084     if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
2085         && PropertyMap[Property].nameW)
2086     {
2087         LONG l = RegSetValueExW(devInfo->key, PropertyMap[Property].nameW, 0,
2088                 PropertyMap[Property].regType, PropertyBuffer,
2089                 PropertyBufferSize);
2090         if (!l)
2091             ret = TRUE;
2092         else
2093             SetLastError(l);
2094     }
2095     return ret;
2096 }
2097
2098 /***********************************************************************
2099  *              SetupDiInstallClassA (SETUPAPI.@)
2100  */
2101 BOOL WINAPI SetupDiInstallClassA(
2102         HWND hwndParent,
2103         PCSTR InfFileName,
2104         DWORD Flags,
2105         HSPFILEQ FileQueue)
2106 {
2107     UNICODE_STRING FileNameW;
2108     BOOL Result;
2109
2110     if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
2111     {
2112         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2113         return FALSE;
2114     }
2115
2116     Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
2117
2118     RtlFreeUnicodeString(&FileNameW);
2119
2120     return Result;
2121 }
2122
2123 static HKEY CreateClassKey(HINF hInf)
2124 {
2125     WCHAR FullBuffer[MAX_PATH];
2126     WCHAR Buffer[MAX_PATH];
2127     DWORD RequiredSize;
2128     HKEY hClassKey;
2129
2130     if (!SetupGetLineTextW(NULL,
2131                            hInf,
2132                            Version,
2133                            ClassGUID,
2134                            Buffer,
2135                            MAX_PATH,
2136                            &RequiredSize))
2137     {
2138         return INVALID_HANDLE_VALUE;
2139     }
2140
2141     lstrcpyW(FullBuffer, ControlClass);
2142     lstrcatW(FullBuffer, Buffer);
2143
2144     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2145                       FullBuffer,
2146                       0,
2147                       KEY_ALL_ACCESS,
2148                       &hClassKey))
2149     {
2150         if (!SetupGetLineTextW(NULL,
2151                                hInf,
2152                                Version,
2153                                Class,
2154                                Buffer,
2155                                MAX_PATH,
2156                                &RequiredSize))
2157         {
2158             return INVALID_HANDLE_VALUE;
2159         }
2160
2161         if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
2162                             FullBuffer,
2163                             0,
2164                             NULL,
2165                             REG_OPTION_NON_VOLATILE,
2166                             KEY_ALL_ACCESS,
2167                             NULL,
2168                             &hClassKey,
2169                             NULL))
2170         {
2171             return INVALID_HANDLE_VALUE;
2172         }
2173
2174     }
2175
2176     if (RegSetValueExW(hClassKey,
2177                        Class,
2178                        0,
2179                        REG_SZ,
2180                        (LPBYTE)Buffer,
2181                        RequiredSize * sizeof(WCHAR)))
2182     {
2183         RegCloseKey(hClassKey);
2184         RegDeleteKeyW(HKEY_LOCAL_MACHINE,
2185                       FullBuffer);
2186         return INVALID_HANDLE_VALUE;
2187     }
2188
2189     return hClassKey;
2190 }
2191
2192 /***********************************************************************
2193  *              SetupDiInstallClassW (SETUPAPI.@)
2194  */
2195 BOOL WINAPI SetupDiInstallClassW(
2196         HWND hwndParent,
2197         PCWSTR InfFileName,
2198         DWORD Flags,
2199         HSPFILEQ FileQueue)
2200 {
2201     WCHAR SectionName[MAX_PATH];
2202     DWORD SectionNameLength = 0;
2203     HINF hInf;
2204     BOOL bFileQueueCreated = FALSE;
2205     HKEY hClassKey;
2206
2207
2208     FIXME("\n");
2209
2210     if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
2211     {
2212         SetLastError(ERROR_INVALID_PARAMETER);
2213         return FALSE;
2214     }
2215
2216     /* Open the .inf file */
2217     hInf = SetupOpenInfFileW(InfFileName,
2218                              NULL,
2219                              INF_STYLE_WIN4,
2220                              NULL);
2221     if (hInf == INVALID_HANDLE_VALUE)
2222     {
2223
2224         return FALSE;
2225     }
2226
2227     /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
2228     hClassKey = CreateClassKey(hInf);
2229     if (hClassKey == INVALID_HANDLE_VALUE)
2230     {
2231         SetupCloseInfFile(hInf);
2232         return FALSE;
2233     }
2234
2235
2236     /* Try to append a layout file */
2237 #if 0
2238     SetupOpenAppendInfFileW(NULL, hInf, NULL);
2239 #endif
2240
2241     /* Retrieve the actual section name */
2242     SetupDiGetActualSectionToInstallW(hInf,
2243                                       ClassInstall32,
2244                                       SectionName,
2245                                       MAX_PATH,
2246                                       &SectionNameLength,
2247                                       NULL);
2248
2249 #if 0
2250     if (!(Flags & DI_NOVCP))
2251     {
2252         FileQueue = SetupOpenFileQueue();
2253         if (FileQueue == INVALID_HANDLE_VALUE)
2254         {
2255             SetupCloseInfFile(hInf);
2256             return FALSE;
2257         }
2258
2259         bFileQueueCreated = TRUE;
2260
2261     }
2262 #endif
2263
2264     SetupInstallFromInfSectionW(NULL,
2265                                 hInf,
2266                                 SectionName,
2267                                 SPINST_REGISTRY,
2268                                 hClassKey,
2269                                 NULL,
2270                                 0,
2271                                 NULL,
2272                                 NULL,
2273                                 INVALID_HANDLE_VALUE,
2274                                 NULL);
2275
2276     /* FIXME: More code! */
2277
2278     if (bFileQueueCreated)
2279         SetupCloseFileQueue(FileQueue);
2280
2281     SetupCloseInfFile(hInf);
2282
2283     return TRUE;
2284 }
2285
2286
2287 /***********************************************************************
2288  *              SetupDiOpenClassRegKey  (SETUPAPI.@)
2289  */
2290 HKEY WINAPI SetupDiOpenClassRegKey(
2291         const GUID* ClassGuid,
2292         REGSAM samDesired)
2293 {
2294     return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2295                                      DIOCR_INSTALLER, NULL, NULL);
2296 }
2297
2298
2299 /***********************************************************************
2300  *              SetupDiOpenClassRegKeyExA  (SETUPAPI.@)
2301  */
2302 HKEY WINAPI SetupDiOpenClassRegKeyExA(
2303         const GUID* ClassGuid,
2304         REGSAM samDesired,
2305         DWORD Flags,
2306         PCSTR MachineName,
2307         PVOID Reserved)
2308 {
2309     PWSTR MachineNameW = NULL;
2310     HKEY hKey;
2311
2312     TRACE("\n");
2313
2314     if (MachineName)
2315     {
2316         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
2317         if (MachineNameW == NULL)
2318             return INVALID_HANDLE_VALUE;
2319     }
2320
2321     hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2322                                      Flags, MachineNameW, Reserved);
2323
2324     MyFree(MachineNameW);
2325
2326     return hKey;
2327 }
2328
2329
2330 /***********************************************************************
2331  *              SetupDiOpenClassRegKeyExW  (SETUPAPI.@)
2332  */
2333 HKEY WINAPI SetupDiOpenClassRegKeyExW(
2334         const GUID* ClassGuid,
2335         REGSAM samDesired,
2336         DWORD Flags,
2337         PCWSTR MachineName,
2338         PVOID Reserved)
2339 {
2340     WCHAR bracedGuidString[39];
2341     HKEY hClassesKey;
2342     HKEY hClassKey;
2343     LPCWSTR lpKeyName;
2344
2345     if (MachineName != NULL)
2346     {
2347         FIXME("Remote access not supported yet!\n");
2348         return INVALID_HANDLE_VALUE;
2349     }
2350
2351     if (Flags == DIOCR_INSTALLER)
2352     {
2353         lpKeyName = ControlClass;
2354     }
2355     else if (Flags == DIOCR_INTERFACE)
2356     {
2357         lpKeyName = DeviceClasses;
2358     }
2359     else
2360     {
2361         ERR("Invalid Flags parameter!\n");
2362         SetLastError(ERROR_INVALID_PARAMETER);
2363         return INVALID_HANDLE_VALUE;
2364     }
2365
2366     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2367                       lpKeyName,
2368                       0,
2369                       KEY_ALL_ACCESS,
2370                       &hClassesKey))
2371     {
2372         return INVALID_HANDLE_VALUE;
2373     }
2374
2375     if (ClassGuid == NULL)
2376         return hClassesKey;
2377
2378     SETUPDI_GuidToString(ClassGuid, bracedGuidString);
2379
2380     if (RegOpenKeyExW(hClassesKey,
2381                       bracedGuidString,
2382                       0,
2383                       KEY_ALL_ACCESS,
2384                       &hClassKey))
2385     {
2386         RegCloseKey(hClassesKey);
2387         return INVALID_HANDLE_VALUE;
2388     }
2389
2390     RegCloseKey(hClassesKey);
2391
2392     return hClassKey;
2393 }
2394
2395 /***********************************************************************
2396  *              SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2397  */
2398 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
2399        HDEVINFO DeviceInfoSet,
2400        PCWSTR DevicePath,
2401        DWORD OpenFlags,
2402        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2403 {
2404     FIXME("%p %s %08x %p\n",
2405         DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
2406     return FALSE;
2407 }
2408
2409 /***********************************************************************
2410  *              SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2411  */
2412 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
2413        HDEVINFO DeviceInfoSet,
2414        PCSTR DevicePath,
2415        DWORD OpenFlags,
2416        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2417 {
2418     FIXME("%p %s %08x %p\n", DeviceInfoSet,
2419         debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
2420     return FALSE;
2421 }
2422
2423 /***********************************************************************
2424  *              SetupDiSetClassInstallParamsA (SETUPAPI.@)
2425  */
2426 BOOL WINAPI SetupDiSetClassInstallParamsA(
2427        HDEVINFO  DeviceInfoSet,
2428        PSP_DEVINFO_DATA DeviceInfoData,
2429        PSP_CLASSINSTALL_HEADER ClassInstallParams,
2430        DWORD ClassInstallParamsSize)
2431 {
2432     FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
2433           ClassInstallParams->InstallFunction, ClassInstallParamsSize);
2434     return FALSE;
2435 }
2436
2437 /***********************************************************************
2438  *              SetupDiCallClassInstaller (SETUPAPI.@)
2439  */
2440 BOOL WINAPI SetupDiCallClassInstaller(
2441        DI_FUNCTION InstallFunction,
2442        HDEVINFO DeviceInfoSet,
2443        PSP_DEVINFO_DATA DeviceInfoData)
2444 {
2445     FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
2446     return FALSE;
2447 }
2448
2449 /***********************************************************************
2450  *              SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
2451  */
2452 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
2453        HDEVINFO DeviceInfoSet,
2454        PSP_DEVINFO_DATA DeviceInfoData,
2455        PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
2456 {
2457     FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
2458     return FALSE;
2459 }
2460
2461 /***********************************************************************
2462  *              SetupDiOpenDevRegKey (SETUPAPI.@)
2463  */
2464 HKEY WINAPI SetupDiOpenDevRegKey(
2465        HDEVINFO DeviceInfoSet,
2466        PSP_DEVINFO_DATA DeviceInfoData,
2467        DWORD Scope,
2468        DWORD HwProfile,
2469        DWORD KeyType,
2470        REGSAM samDesired)
2471 {
2472     FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
2473           Scope, HwProfile, KeyType, samDesired);
2474     return INVALID_HANDLE_VALUE;
2475 }