include: Move cfgmgr32.h to include/ to match the SDK.
[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','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
71 /* is used to identify if a DeviceInfoSet pointer is
72 valid or not */
73 #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056
74
75 struct DeviceInfoSet
76 {
77     DWORD magic;        /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */
78     GUID ClassGuid;
79     HWND hwndParent;
80 };
81
82 /***********************************************************************
83  *              SetupDiBuildClassInfoList  (SETUPAPI.@)
84  *
85  * Returns a list of setup class GUIDs that identify the classes
86  * that are installed on a local machine.
87  *
88  * PARAMS
89  *   Flags [I] control exclusion of classes from the list.
90  *   ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
91  *   ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
92  *   RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
93  *
94  * RETURNS
95  *   Success: TRUE.
96  *   Failure: FALSE.
97  */
98 BOOL WINAPI SetupDiBuildClassInfoList(
99         DWORD Flags,
100         LPGUID ClassGuidList,
101         DWORD ClassGuidListSize,
102         PDWORD RequiredSize)
103 {
104     TRACE("\n");
105     return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
106                                         ClassGuidListSize, RequiredSize,
107                                         NULL, NULL);
108 }
109
110 /***********************************************************************
111  *              SetupDiBuildClassInfoListExA  (SETUPAPI.@)
112  *
113  * Returns a list of setup class GUIDs that identify the classes
114  * that are installed on a local or remote macine.
115  *
116  * PARAMS
117  *   Flags [I] control exclusion of classes from the list.
118  *   ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
119  *   ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
120  *   RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
121  *   MachineName [I] name of a remote machine.
122  *   Reserved [I] must be NULL.
123  *
124  * RETURNS
125  *   Success: TRUE.
126  *   Failure: FALSE.
127  */
128 BOOL WINAPI SetupDiBuildClassInfoListExA(
129         DWORD Flags,
130         LPGUID ClassGuidList,
131         DWORD ClassGuidListSize,
132         PDWORD RequiredSize,
133         LPCSTR MachineName,
134         PVOID Reserved)
135 {
136     LPWSTR MachineNameW = NULL;
137     BOOL bResult;
138
139     TRACE("\n");
140
141     if (MachineName)
142     {
143         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
144         if (MachineNameW == NULL) return FALSE;
145     }
146
147     bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
148                                            ClassGuidListSize, RequiredSize,
149                                            MachineNameW, Reserved);
150
151     MyFree(MachineNameW);
152
153     return bResult;
154 }
155
156 /***********************************************************************
157  *              SetupDiBuildClassInfoListExW  (SETUPAPI.@)
158  *
159  * Returns a list of setup class GUIDs that identify the classes
160  * that are installed on a local or remote macine.
161  *
162  * PARAMS
163  *   Flags [I] control exclusion of classes from the list.
164  *   ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
165  *   ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
166  *   RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
167  *   MachineName [I] name of a remote machine.
168  *   Reserved [I] must be NULL.
169  *
170  * RETURNS
171  *   Success: TRUE.
172  *   Failure: FALSE.
173  */
174 BOOL WINAPI SetupDiBuildClassInfoListExW(
175         DWORD Flags,
176         LPGUID ClassGuidList,
177         DWORD ClassGuidListSize,
178         PDWORD RequiredSize,
179         LPCWSTR MachineName,
180         PVOID Reserved)
181 {
182     WCHAR szKeyName[40];
183     HKEY hClassesKey;
184     HKEY hClassKey;
185     DWORD dwLength;
186     DWORD dwIndex;
187     LONG lError;
188     DWORD dwGuidListIndex = 0;
189
190     TRACE("\n");
191
192     if (RequiredSize != NULL)
193         *RequiredSize = 0;
194
195     hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
196                                             KEY_ALL_ACCESS,
197                                             DIOCR_INSTALLER,
198                                             MachineName,
199                                             Reserved);
200     if (hClassesKey == INVALID_HANDLE_VALUE)
201     {
202         return FALSE;
203     }
204
205     for (dwIndex = 0; ; dwIndex++)
206     {
207         dwLength = 40;
208         lError = RegEnumKeyExW(hClassesKey,
209                                dwIndex,
210                                szKeyName,
211                                &dwLength,
212                                NULL,
213                                NULL,
214                                NULL,
215                                NULL);
216         TRACE("RegEnumKeyExW() returns %d\n", lError);
217         if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
218         {
219             TRACE("Key name: %p\n", szKeyName);
220
221             if (RegOpenKeyExW(hClassesKey,
222                               szKeyName,
223                               0,
224                               KEY_ALL_ACCESS,
225                               &hClassKey))
226             {
227                 RegCloseKey(hClassesKey);
228                 return FALSE;
229             }
230
231             if (!RegQueryValueExW(hClassKey,
232                                   NoUseClass,
233                                   NULL,
234                                   NULL,
235                                   NULL,
236                                   NULL))
237             {
238                 TRACE("'NoUseClass' value found!\n");
239                 RegCloseKey(hClassKey);
240                 continue;
241             }
242
243             if ((Flags & DIBCI_NOINSTALLCLASS) &&
244                 (!RegQueryValueExW(hClassKey,
245                                    NoInstallClass,
246                                    NULL,
247                                    NULL,
248                                    NULL,
249                                    NULL)))
250             {
251                 TRACE("'NoInstallClass' value found!\n");
252                 RegCloseKey(hClassKey);
253                 continue;
254             }
255
256             if ((Flags & DIBCI_NODISPLAYCLASS) &&
257                 (!RegQueryValueExW(hClassKey,
258                                    NoDisplayClass,
259                                    NULL,
260                                    NULL,
261                                    NULL,
262                                    NULL)))
263             {
264                 TRACE("'NoDisplayClass' value found!\n");
265                 RegCloseKey(hClassKey);
266                 continue;
267             }
268
269             RegCloseKey(hClassKey);
270
271             TRACE("Guid: %p\n", szKeyName);
272             if (dwGuidListIndex < ClassGuidListSize)
273             {
274                 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
275                 {
276                     szKeyName[37] = 0;
277                 }
278                 TRACE("Guid: %p\n", &szKeyName[1]);
279
280                 UuidFromStringW(&szKeyName[1],
281                                 &ClassGuidList[dwGuidListIndex]);
282             }
283
284             dwGuidListIndex++;
285         }
286
287         if (lError != ERROR_SUCCESS)
288             break;
289     }
290
291     RegCloseKey(hClassesKey);
292
293     if (RequiredSize != NULL)
294         *RequiredSize = dwGuidListIndex;
295
296     if (ClassGuidListSize < dwGuidListIndex)
297     {
298         SetLastError(ERROR_INSUFFICIENT_BUFFER);
299         return FALSE;
300     }
301
302     return TRUE;
303 }
304
305 /***********************************************************************
306  *              SetupDiClassGuidsFromNameA  (SETUPAPI.@)
307  */
308 BOOL WINAPI SetupDiClassGuidsFromNameA(
309         LPCSTR ClassName,
310         LPGUID ClassGuidList,
311         DWORD ClassGuidListSize,
312         PDWORD RequiredSize)
313 {
314   return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
315                                       ClassGuidListSize, RequiredSize,
316                                       NULL, NULL);
317 }
318
319 /***********************************************************************
320  *              SetupDiClassGuidsFromNameW  (SETUPAPI.@)
321  */
322 BOOL WINAPI SetupDiClassGuidsFromNameW(
323         LPCWSTR ClassName,
324         LPGUID ClassGuidList,
325         DWORD ClassGuidListSize,
326         PDWORD RequiredSize)
327 {
328   return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
329                                       ClassGuidListSize, RequiredSize,
330                                       NULL, NULL);
331 }
332
333 /***********************************************************************
334  *              SetupDiClassGuidsFromNameExA  (SETUPAPI.@)
335  */
336 BOOL WINAPI SetupDiClassGuidsFromNameExA(
337         LPCSTR ClassName,
338         LPGUID ClassGuidList,
339         DWORD ClassGuidListSize,
340         PDWORD RequiredSize,
341         LPCSTR MachineName,
342         PVOID Reserved)
343 {
344     LPWSTR ClassNameW = NULL;
345     LPWSTR MachineNameW = NULL;
346     BOOL bResult;
347
348     FIXME("\n");
349
350     ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
351     if (ClassNameW == NULL)
352         return FALSE;
353
354     if (MachineName)
355     {
356         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
357         if (MachineNameW == NULL)
358         {
359             MyFree(ClassNameW);
360             return FALSE;
361         }
362     }
363
364     bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
365                                            ClassGuidListSize, RequiredSize,
366                                            MachineNameW, Reserved);
367
368     MyFree(MachineNameW);
369     MyFree(ClassNameW);
370
371     return bResult;
372 }
373
374 /***********************************************************************
375  *              SetupDiClassGuidsFromNameExW  (SETUPAPI.@)
376  */
377 BOOL WINAPI SetupDiClassGuidsFromNameExW(
378         LPCWSTR ClassName,
379         LPGUID ClassGuidList,
380         DWORD ClassGuidListSize,
381         PDWORD RequiredSize,
382         LPCWSTR MachineName,
383         PVOID Reserved)
384 {
385     WCHAR szKeyName[40];
386     WCHAR szClassName[256];
387     HKEY hClassesKey;
388     HKEY hClassKey;
389     DWORD dwLength;
390     DWORD dwIndex;
391     LONG lError;
392     DWORD dwGuidListIndex = 0;
393
394     if (RequiredSize != NULL)
395         *RequiredSize = 0;
396
397     hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
398                                             KEY_ALL_ACCESS,
399                                             DIOCR_INSTALLER,
400                                             MachineName,
401                                             Reserved);
402     if (hClassesKey == INVALID_HANDLE_VALUE)
403     {
404         return FALSE;
405     }
406
407     for (dwIndex = 0; ; dwIndex++)
408     {
409         dwLength = 40;
410         lError = RegEnumKeyExW(hClassesKey,
411                                dwIndex,
412                                szKeyName,
413                                &dwLength,
414                                NULL,
415                                NULL,
416                                NULL,
417                                NULL);
418         TRACE("RegEnumKeyExW() returns %d\n", lError);
419         if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
420         {
421             TRACE("Key name: %p\n", szKeyName);
422
423             if (RegOpenKeyExW(hClassesKey,
424                               szKeyName,
425                               0,
426                               KEY_ALL_ACCESS,
427                               &hClassKey))
428             {
429                 RegCloseKey(hClassesKey);
430                 return FALSE;
431             }
432
433             dwLength = 256 * sizeof(WCHAR);
434             if (!RegQueryValueExW(hClassKey,
435                                   Class,
436                                   NULL,
437                                   NULL,
438                                   (LPBYTE)szClassName,
439                                   &dwLength))
440             {
441                 TRACE("Class name: %p\n", szClassName);
442
443                 if (strcmpiW(szClassName, ClassName) == 0)
444                 {
445                     TRACE("Found matching class name\n");
446
447                     TRACE("Guid: %p\n", szKeyName);
448                     if (dwGuidListIndex < ClassGuidListSize)
449                     {
450                         if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
451                         {
452                             szKeyName[37] = 0;
453                         }
454                         TRACE("Guid: %p\n", &szKeyName[1]);
455
456                         UuidFromStringW(&szKeyName[1],
457                                         &ClassGuidList[dwGuidListIndex]);
458                     }
459
460                     dwGuidListIndex++;
461                 }
462             }
463
464             RegCloseKey(hClassKey);
465         }
466
467         if (lError != ERROR_SUCCESS)
468             break;
469     }
470
471     RegCloseKey(hClassesKey);
472
473     if (RequiredSize != NULL)
474         *RequiredSize = dwGuidListIndex;
475
476     if (ClassGuidListSize < dwGuidListIndex)
477     {
478         SetLastError(ERROR_INSUFFICIENT_BUFFER);
479         return FALSE;
480     }
481
482     return TRUE;
483 }
484
485 /***********************************************************************
486  *              SetupDiClassNameFromGuidA  (SETUPAPI.@)
487  */
488 BOOL WINAPI SetupDiClassNameFromGuidA(
489         const GUID* ClassGuid,
490         PSTR ClassName,
491         DWORD ClassNameSize,
492         PDWORD RequiredSize)
493 {
494   return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
495                                      ClassNameSize, RequiredSize,
496                                      NULL, NULL);
497 }
498
499 /***********************************************************************
500  *              SetupDiClassNameFromGuidW  (SETUPAPI.@)
501  */
502 BOOL WINAPI SetupDiClassNameFromGuidW(
503         const GUID* ClassGuid,
504         PWSTR ClassName,
505         DWORD ClassNameSize,
506         PDWORD RequiredSize)
507 {
508   return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
509                                      ClassNameSize, RequiredSize,
510                                      NULL, NULL);
511 }
512
513 /***********************************************************************
514  *              SetupDiClassNameFromGuidExA  (SETUPAPI.@)
515  */
516 BOOL WINAPI SetupDiClassNameFromGuidExA(
517         const GUID* ClassGuid,
518         PSTR ClassName,
519         DWORD ClassNameSize,
520         PDWORD RequiredSize,
521         PCSTR MachineName,
522         PVOID Reserved)
523 {
524     WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
525     LPWSTR MachineNameW = NULL;
526     BOOL ret;
527
528     if (MachineName)
529         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
530     ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
531      NULL, MachineNameW, Reserved);
532     if (ret)
533     {
534         int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
535          ClassNameSize, NULL, NULL);
536
537         if (!ClassNameSize && RequiredSize)
538             *RequiredSize = len;
539     }
540     MyFree(MachineNameW);
541     return ret;
542 }
543
544 /***********************************************************************
545  *              SetupDiClassNameFromGuidExW  (SETUPAPI.@)
546  */
547 BOOL WINAPI SetupDiClassNameFromGuidExW(
548         const GUID* ClassGuid,
549         PWSTR ClassName,
550         DWORD ClassNameSize,
551         PDWORD RequiredSize,
552         PCWSTR MachineName,
553         PVOID Reserved)
554 {
555     HKEY hKey;
556     DWORD dwLength;
557
558     hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
559                                      KEY_ALL_ACCESS,
560                                      DIOCR_INSTALLER,
561                                      MachineName,
562                                      Reserved);
563     if (hKey == INVALID_HANDLE_VALUE)
564     {
565         return FALSE;
566     }
567
568     if (RequiredSize != NULL)
569     {
570         dwLength = 0;
571         if (RegQueryValueExW(hKey,
572                              Class,
573                              NULL,
574                              NULL,
575                              NULL,
576                              &dwLength))
577         {
578             RegCloseKey(hKey);
579             return FALSE;
580         }
581
582         *RequiredSize = dwLength / sizeof(WCHAR);
583     }
584
585     dwLength = ClassNameSize * sizeof(WCHAR);
586     if (RegQueryValueExW(hKey,
587                          Class,
588                          NULL,
589                          NULL,
590                          (LPBYTE)ClassName,
591                          &dwLength))
592     {
593         RegCloseKey(hKey);
594         return FALSE;
595     }
596
597     RegCloseKey(hKey);
598
599     return TRUE;
600 }
601
602 /***********************************************************************
603  *              SetupDiCreateDeviceInfoList (SETUPAPI.@)
604  */
605 HDEVINFO WINAPI
606 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
607                             HWND hwndParent)
608 {
609   return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
610 }
611
612 /***********************************************************************
613  *              SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
614  */
615 HDEVINFO WINAPI
616 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
617                                HWND hwndParent,
618                                PCSTR MachineName,
619                                PVOID Reserved)
620 {
621     LPWSTR MachineNameW = NULL;
622     HDEVINFO hDevInfo;
623
624     TRACE("\n");
625
626     if (MachineName)
627     {
628         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
629         if (MachineNameW == NULL)
630             return (HDEVINFO)INVALID_HANDLE_VALUE;
631     }
632
633     hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
634                                               MachineNameW, Reserved);
635
636     MyFree(MachineNameW);
637
638     return hDevInfo;
639 }
640
641 /***********************************************************************
642  *              SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
643  *
644  * Create an empty DeviceInfoSet list.
645  *
646  * PARAMS
647  *   ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
648  *                 with this list.
649  *   hwndParent [I] hwnd needed for interface related actions.
650  *   MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
651  *                   local regestry will be used.
652  *   Reserved [I] must be NULL
653  *
654  * RETURNS
655  *   Success: empty list.
656  *   Failure: INVALID_HANDLE_VALUE.
657  */
658 HDEVINFO WINAPI
659 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
660                                HWND hwndParent,
661                                PCWSTR MachineName,
662                                PVOID Reserved)
663 {
664     struct DeviceInfoSet *list = NULL;
665     DWORD size = sizeof(struct DeviceInfoSet);
666
667     TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
668       debugstr_w(MachineName), Reserved);
669
670     if (MachineName != NULL)
671     {
672         FIXME("remote support is not implemented\n");
673         SetLastError(ERROR_INVALID_MACHINENAME);
674         return (HDEVINFO)INVALID_HANDLE_VALUE;
675     }
676
677     if (Reserved != NULL)
678     {
679         SetLastError(ERROR_INVALID_PARAMETER);
680         return (HDEVINFO)INVALID_HANDLE_VALUE;
681     }
682
683     list = HeapAlloc(GetProcessHeap(), 0, size);
684     if (!list)
685     {
686         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
687         return (HDEVINFO)INVALID_HANDLE_VALUE;
688     }
689
690     list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
691     list->hwndParent = hwndParent;
692     memcpy(&list->ClassGuid,
693             ClassGuid ? ClassGuid : &GUID_NULL,
694             sizeof(list->ClassGuid));
695
696     return (HDEVINFO)list;
697 }
698
699 /***********************************************************************
700  *              SetupDiCreateDeviceInfoA (SETUPAPI.@)
701  */
702 BOOL WINAPI SetupDiCreateDeviceInfoA(
703        HDEVINFO DeviceInfoSet,
704        PCSTR DeviceName,
705        CONST GUID *ClassGuid,
706        PCSTR DeviceDescription,
707        HWND hwndParent,
708        DWORD CreationFlags,
709        PSP_DEVINFO_DATA DeviceInfoData)
710 {
711     BOOL ret = FALSE;
712     LPWSTR DeviceNameW = NULL;
713     LPWSTR DeviceDescriptionW = NULL;
714
715     if (DeviceName)
716     {
717         DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
718         if (DeviceNameW == NULL) return FALSE;
719     }
720     if (DeviceDescription)
721     {
722         DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
723         if (DeviceDescriptionW == NULL)
724         {
725             MyFree(DeviceNameW);
726             return FALSE;
727         }
728     }
729
730     ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
731             hwndParent, CreationFlags, DeviceInfoData);
732
733     MyFree(DeviceNameW);
734     MyFree(DeviceDescriptionW);
735
736     return ret;
737 }
738
739 /***********************************************************************
740  *              SetupDiCreateDeviceInfoW (SETUPAPI.@)
741  */
742 BOOL WINAPI SetupDiCreateDeviceInfoW(
743        HDEVINFO DeviceInfoSet,
744        PCWSTR DeviceName,
745        CONST GUID *ClassGuid,
746        PCWSTR DeviceDescription,
747        HWND hwndParent,
748        DWORD CreationFlags,
749        PSP_DEVINFO_DATA DeviceInfoData)
750 {
751     TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
752         debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
753         hwndParent, CreationFlags, DeviceInfoData);
754
755     FIXME("stub\n");
756
757     return FALSE;
758 }
759
760 /***********************************************************************
761  *              SetupDiEnumDeviceInfo (SETUPAPI.@)
762  */
763 BOOL WINAPI SetupDiEnumDeviceInfo(
764         HDEVINFO  devinfo,
765         DWORD  index,
766         PSP_DEVINFO_DATA info)
767 {
768     FIXME("%p %d %p\n", devinfo, index, info);
769
770     if(info==NULL)
771         return FALSE;
772     if(info->cbSize < sizeof(*info))
773         return FALSE;
774
775     return FALSE;
776 }
777
778 /***********************************************************************
779  *              SetupDiGetActualSectionToInstallA (SETUPAPI.@)
780  */
781 BOOL WINAPI SetupDiGetActualSectionToInstallA(
782         HINF InfHandle,
783         PCSTR InfSectionName,
784         PSTR InfSectionWithExt,
785         DWORD InfSectionWithExtSize,
786         PDWORD RequiredSize,
787         PSTR *Extension)
788 {
789     FIXME("\n");
790     return FALSE;
791 }
792
793 /***********************************************************************
794  *              SetupDiGetActualSectionToInstallW (SETUPAPI.@)
795  */
796 BOOL WINAPI SetupDiGetActualSectionToInstallW(
797         HINF InfHandle,
798         PCWSTR InfSectionName,
799         PWSTR InfSectionWithExt,
800         DWORD InfSectionWithExtSize,
801         PDWORD RequiredSize,
802         PWSTR *Extension)
803 {
804     WCHAR szBuffer[MAX_PATH];
805     DWORD dwLength;
806     DWORD dwFullLength;
807     LONG lLineCount = -1;
808
809     lstrcpyW(szBuffer, InfSectionName);
810     dwLength = lstrlenW(szBuffer);
811
812     if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
813     {
814         /* Test section name with '.NTx86' extension */
815         lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
816         lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
817
818         if (lLineCount == -1)
819         {
820             /* Test section name with '.NT' extension */
821             lstrcpyW(&szBuffer[dwLength], NtExtension);
822             lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
823         }
824     }
825     else
826     {
827         /* Test section name with '.Win' extension */
828         lstrcpyW(&szBuffer[dwLength], WinExtension);
829         lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
830     }
831
832     if (lLineCount == -1)
833     {
834         /* Test section name without extension */
835         szBuffer[dwLength] = 0;
836         lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
837     }
838
839     if (lLineCount == -1)
840     {
841         SetLastError(ERROR_INVALID_PARAMETER);
842         return FALSE;
843     }
844
845     dwFullLength = lstrlenW(szBuffer);
846
847     if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
848     {
849         if (InfSectionWithExtSize < (dwFullLength + 1))
850         {
851             SetLastError(ERROR_INSUFFICIENT_BUFFER);
852             return FALSE;
853         }
854
855         lstrcpyW(InfSectionWithExt, szBuffer);
856         if (Extension != NULL)
857         {
858             *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
859         }
860     }
861
862     if (RequiredSize != NULL)
863     {
864         *RequiredSize = dwFullLength + 1;
865     }
866
867     return TRUE;
868 }
869
870 /***********************************************************************
871  *              SetupDiGetClassDescriptionA  (SETUPAPI.@)
872  */
873 BOOL WINAPI SetupDiGetClassDescriptionA(
874         const GUID* ClassGuid,
875         PSTR ClassDescription,
876         DWORD ClassDescriptionSize,
877         PDWORD RequiredSize)
878 {
879   return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
880                                        ClassDescriptionSize,
881                                        RequiredSize, NULL, NULL);
882 }
883
884 /***********************************************************************
885  *              SetupDiGetClassDescriptionW  (SETUPAPI.@)
886  */
887 BOOL WINAPI SetupDiGetClassDescriptionW(
888         const GUID* ClassGuid,
889         PWSTR ClassDescription,
890         DWORD ClassDescriptionSize,
891         PDWORD RequiredSize)
892 {
893   return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
894                                        ClassDescriptionSize,
895                                        RequiredSize, NULL, NULL);
896 }
897
898 /***********************************************************************
899  *              SetupDiGetClassDescriptionExA  (SETUPAPI.@)
900  */
901 BOOL WINAPI SetupDiGetClassDescriptionExA(
902         const GUID* ClassGuid,
903         PSTR ClassDescription,
904         DWORD ClassDescriptionSize,
905         PDWORD RequiredSize,
906         PCSTR MachineName,
907         PVOID Reserved)
908 {
909   FIXME("\n");
910   return FALSE;
911 }
912
913 /***********************************************************************
914  *              SetupDiGetClassDescriptionExW  (SETUPAPI.@)
915  */
916 BOOL WINAPI SetupDiGetClassDescriptionExW(
917         const GUID* ClassGuid,
918         PWSTR ClassDescription,
919         DWORD ClassDescriptionSize,
920         PDWORD RequiredSize,
921         PCWSTR MachineName,
922         PVOID Reserved)
923 {
924     HKEY hKey;
925     DWORD dwLength;
926
927     hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
928                                      KEY_ALL_ACCESS,
929                                      DIOCR_INSTALLER,
930                                      MachineName,
931                                      Reserved);
932     if (hKey == INVALID_HANDLE_VALUE)
933     {
934         WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
935         return FALSE;
936     }
937
938     if (RequiredSize != NULL)
939     {
940         dwLength = 0;
941         if (RegQueryValueExW(hKey,
942                              NULL,
943                              NULL,
944                              NULL,
945                              NULL,
946                              &dwLength))
947         {
948             RegCloseKey(hKey);
949             return FALSE;
950         }
951
952         *RequiredSize = dwLength / sizeof(WCHAR);
953     }
954
955     dwLength = ClassDescriptionSize * sizeof(WCHAR);
956     if (RegQueryValueExW(hKey,
957                          NULL,
958                          NULL,
959                          NULL,
960                          (LPBYTE)ClassDescription,
961                          &dwLength))
962     {
963         RegCloseKey(hKey);
964         return FALSE;
965     }
966
967     RegCloseKey(hKey);
968
969     return TRUE;
970 }
971
972 /***********************************************************************
973  *              SetupDiGetClassDevsA (SETUPAPI.@)
974  */
975 HDEVINFO WINAPI SetupDiGetClassDevsA(
976        CONST GUID *class,
977        LPCSTR enumstr,
978        HWND parent,
979        DWORD flags)
980 {
981     HDEVINFO ret;
982     LPWSTR enumstrW = NULL;
983
984     if (enumstr)
985     {
986         int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
987         enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
988         if (!enumstrW)
989         {
990             ret = (HDEVINFO)INVALID_HANDLE_VALUE;
991             goto end;
992         }
993         MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
994     }
995     ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
996     HeapFree(GetProcessHeap(), 0, enumstrW);
997
998 end:
999     return ret;
1000 }
1001
1002 /***********************************************************************
1003  *              SetupDiGetClassDevsW (SETUPAPI.@)
1004  */
1005 HDEVINFO WINAPI SetupDiGetClassDevsW(
1006        CONST GUID *class,
1007        LPCWSTR enumstr,
1008        HWND parent,
1009        DWORD flags)
1010 {
1011     HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1012
1013     TRACE("%s %s %p 0x%08x\n", debugstr_guid(class), debugstr_w(enumstr),
1014      parent, flags);
1015
1016     if(flags & DIGCF_DEVICEINTERFACE)
1017     {
1018         if(!class)
1019             SetLastError(ERROR_INVALID_PARAMETER);
1020         else
1021         {
1022             /* WinXP always succeeds, returns empty list for unknown classes */
1023             FIXME(": returning empty list\n");
1024             ret = SetupDiCreateDeviceInfoList(class, parent);
1025         }
1026     }
1027     else if (enumstr)
1028         FIXME(": unimplemented for enumerator strings (%s)\n",
1029          debugstr_w(enumstr));
1030     else if (flags & DIGCF_ALLCLASSES)
1031         FIXME(": unimplemented for DIGCF_ALLCLASSES\n");
1032     else
1033     {
1034         FIXME("(%s): stub\n", debugstr_guid(class));
1035     }
1036     return ret;
1037 }
1038
1039 /***********************************************************************
1040  *              SetupDiGetClassDevsExW (SETUPAPI.@)
1041  */
1042 HDEVINFO WINAPI SetupDiGetClassDevsExW(
1043         CONST GUID *class,
1044         PCWSTR enumstr,
1045         HWND parent,
1046         DWORD flags,
1047         HDEVINFO deviceset,
1048         PCWSTR machine,
1049         PVOID reserved)
1050 {
1051     FIXME("stub\n");
1052     return FALSE;
1053 }
1054
1055 /***********************************************************************
1056  *              SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1057  */
1058 BOOL WINAPI SetupDiEnumDeviceInterfaces(
1059        HDEVINFO devinfo,
1060        PSP_DEVINFO_DATA DeviceInfoData,
1061        CONST GUID * InterfaceClassGuid,
1062        DWORD MemberIndex,
1063        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1064 {
1065     BOOL ret = FALSE;
1066
1067     FIXME("%p, %p, %s, 0x%08x, %p\n", devinfo, DeviceInfoData,
1068      debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
1069
1070     if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1071     {
1072         struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1073         if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1074             SetLastError(ERROR_NO_MORE_ITEMS);
1075         else
1076             SetLastError(ERROR_INVALID_HANDLE);
1077     }
1078     else
1079         SetLastError(ERROR_INVALID_HANDLE);
1080     return ret;
1081 }
1082
1083 /***********************************************************************
1084  *              SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1085   *
1086  * Destroy a DeviceInfoList and free all used memory of the list.
1087  *
1088  * PARAMS
1089  *   devinfo [I] DeviceInfoList pointer to list to destroy
1090  *
1091  * RETURNS
1092  *   Success: non zero value.
1093  *   Failure: zero value.
1094  */
1095 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
1096 {
1097     BOOL ret = FALSE;
1098
1099     TRACE("%p\n", devinfo);
1100     if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1101     {
1102         struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1103
1104         if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1105         {
1106             HeapFree(GetProcessHeap(), 0, list);
1107             ret = TRUE;
1108         }
1109     }
1110
1111     if (ret == FALSE)
1112         SetLastError(ERROR_INVALID_HANDLE);
1113
1114     return ret;
1115 }
1116
1117 /***********************************************************************
1118  *              SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1119  */
1120 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
1121       HDEVINFO DeviceInfoSet,
1122       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1123       PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
1124       DWORD DeviceInterfaceDetailDataSize,
1125       PDWORD RequiredSize,
1126       PSP_DEVINFO_DATA DeviceInfoData)
1127 {
1128     BOOL ret = FALSE;
1129
1130     FIXME("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
1131      DeviceInterfaceData, DeviceInterfaceDetailData,
1132      DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1133
1134     SetLastError(ERROR_INVALID_HANDLE);
1135     return ret;
1136 }
1137
1138 /***********************************************************************
1139  *              SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
1140  */
1141 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
1142       HDEVINFO DeviceInfoSet,
1143       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1144       PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
1145       DWORD DeviceInterfaceDetailDataSize,
1146       PDWORD RequiredSize,
1147       PSP_DEVINFO_DATA DeviceInfoData)
1148 {
1149     FIXME("(%p, %p, %p, %d, %p, %p): stub\n", DeviceInfoSet,
1150      DeviceInterfaceData, DeviceInterfaceDetailData,
1151      DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1152     return FALSE;
1153 }
1154
1155 /***********************************************************************
1156  *              SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
1157  */
1158 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
1159         HDEVINFO  devinfo,
1160         PSP_DEVINFO_DATA  DeviceInfoData,
1161         DWORD   Property,
1162         PDWORD  PropertyRegDataType,
1163         PBYTE   PropertyBuffer,
1164         DWORD   PropertyBufferSize,
1165         PDWORD  RequiredSize)
1166 {
1167     FIXME("%04x %p %d %p %p %d %p\n", (DWORD)devinfo, DeviceInfoData,
1168         Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1169         RequiredSize);
1170     return FALSE;
1171 }
1172
1173 /***********************************************************************
1174  *              SetupDiInstallClassA (SETUPAPI.@)
1175  */
1176 BOOL WINAPI SetupDiInstallClassA(
1177         HWND hwndParent,
1178         PCSTR InfFileName,
1179         DWORD Flags,
1180         HSPFILEQ FileQueue)
1181 {
1182     UNICODE_STRING FileNameW;
1183     BOOL Result;
1184
1185     if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
1186     {
1187         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1188         return FALSE;
1189     }
1190
1191     Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
1192
1193     RtlFreeUnicodeString(&FileNameW);
1194
1195     return Result;
1196 }
1197
1198 static HKEY CreateClassKey(HINF hInf)
1199 {
1200     WCHAR FullBuffer[MAX_PATH];
1201     WCHAR Buffer[MAX_PATH];
1202     DWORD RequiredSize;
1203     HKEY hClassKey;
1204
1205     if (!SetupGetLineTextW(NULL,
1206                            hInf,
1207                            Version,
1208                            ClassGUID,
1209                            Buffer,
1210                            MAX_PATH,
1211                            &RequiredSize))
1212     {
1213         return INVALID_HANDLE_VALUE;
1214     }
1215
1216     lstrcpyW(FullBuffer, ControlClass);
1217     lstrcatW(FullBuffer, Buffer);
1218
1219     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1220                       FullBuffer,
1221                       0,
1222                       KEY_ALL_ACCESS,
1223                       &hClassKey))
1224     {
1225         if (!SetupGetLineTextW(NULL,
1226                                hInf,
1227                                Version,
1228                                Class,
1229                                Buffer,
1230                                MAX_PATH,
1231                                &RequiredSize))
1232         {
1233             return INVALID_HANDLE_VALUE;
1234         }
1235
1236         if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
1237                             FullBuffer,
1238                             0,
1239                             NULL,
1240                             REG_OPTION_NON_VOLATILE,
1241                             KEY_ALL_ACCESS,
1242                             NULL,
1243                             &hClassKey,
1244                             NULL))
1245         {
1246             return INVALID_HANDLE_VALUE;
1247         }
1248
1249     }
1250
1251     if (RegSetValueExW(hClassKey,
1252                        Class,
1253                        0,
1254                        REG_SZ,
1255                        (LPBYTE)Buffer,
1256                        RequiredSize * sizeof(WCHAR)))
1257     {
1258         RegCloseKey(hClassKey);
1259         RegDeleteKeyW(HKEY_LOCAL_MACHINE,
1260                       FullBuffer);
1261         return INVALID_HANDLE_VALUE;
1262     }
1263
1264     return hClassKey;
1265 }
1266
1267 /***********************************************************************
1268  *              SetupDiInstallClassW (SETUPAPI.@)
1269  */
1270 BOOL WINAPI SetupDiInstallClassW(
1271         HWND hwndParent,
1272         PCWSTR InfFileName,
1273         DWORD Flags,
1274         HSPFILEQ FileQueue)
1275 {
1276     WCHAR SectionName[MAX_PATH];
1277     DWORD SectionNameLength = 0;
1278     HINF hInf;
1279     BOOL bFileQueueCreated = FALSE;
1280     HKEY hClassKey;
1281
1282
1283     FIXME("\n");
1284
1285     if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
1286     {
1287         SetLastError(ERROR_INVALID_PARAMETER);
1288         return FALSE;
1289     }
1290
1291     /* Open the .inf file */
1292     hInf = SetupOpenInfFileW(InfFileName,
1293                              NULL,
1294                              INF_STYLE_WIN4,
1295                              NULL);
1296     if (hInf == INVALID_HANDLE_VALUE)
1297     {
1298
1299         return FALSE;
1300     }
1301
1302     /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
1303     hClassKey = CreateClassKey(hInf);
1304     if (hClassKey == INVALID_HANDLE_VALUE)
1305     {
1306         SetupCloseInfFile(hInf);
1307         return FALSE;
1308     }
1309
1310
1311     /* Try to append a layout file */
1312 #if 0
1313     SetupOpenAppendInfFileW(NULL, hInf, NULL);
1314 #endif
1315
1316     /* Retrieve the actual section name */
1317     SetupDiGetActualSectionToInstallW(hInf,
1318                                       ClassInstall32,
1319                                       SectionName,
1320                                       MAX_PATH,
1321                                       &SectionNameLength,
1322                                       NULL);
1323
1324 #if 0
1325     if (!(Flags & DI_NOVCP))
1326     {
1327         FileQueue = SetupOpenFileQueue();
1328         if (FileQueue == INVALID_HANDLE_VALUE)
1329         {
1330             SetupCloseInfFile(hInf);
1331             return FALSE;
1332         }
1333
1334         bFileQueueCreated = TRUE;
1335
1336     }
1337 #endif
1338
1339     SetupInstallFromInfSectionW(NULL,
1340                                 hInf,
1341                                 SectionName,
1342                                 SPINST_REGISTRY,
1343                                 hClassKey,
1344                                 NULL,
1345                                 0,
1346                                 NULL,
1347                                 NULL,
1348                                 INVALID_HANDLE_VALUE,
1349                                 NULL);
1350
1351     /* FIXME: More code! */
1352
1353     if (bFileQueueCreated)
1354         SetupCloseFileQueue(FileQueue);
1355
1356     SetupCloseInfFile(hInf);
1357
1358     return TRUE;
1359 }
1360
1361
1362 /***********************************************************************
1363  *              SetupDiOpenClassRegKey  (SETUPAPI.@)
1364  */
1365 HKEY WINAPI SetupDiOpenClassRegKey(
1366         const GUID* ClassGuid,
1367         REGSAM samDesired)
1368 {
1369     return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1370                                      DIOCR_INSTALLER, NULL, NULL);
1371 }
1372
1373
1374 /***********************************************************************
1375  *              SetupDiOpenClassRegKeyExA  (SETUPAPI.@)
1376  */
1377 HKEY WINAPI SetupDiOpenClassRegKeyExA(
1378         const GUID* ClassGuid,
1379         REGSAM samDesired,
1380         DWORD Flags,
1381         PCSTR MachineName,
1382         PVOID Reserved)
1383 {
1384     PWSTR MachineNameW = NULL;
1385     HKEY hKey;
1386
1387     TRACE("\n");
1388
1389     if (MachineName)
1390     {
1391         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1392         if (MachineNameW == NULL)
1393             return INVALID_HANDLE_VALUE;
1394     }
1395
1396     hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1397                                      Flags, MachineNameW, Reserved);
1398
1399     MyFree(MachineNameW);
1400
1401     return hKey;
1402 }
1403
1404
1405 /***********************************************************************
1406  *              SetupDiOpenClassRegKeyExW  (SETUPAPI.@)
1407  */
1408 HKEY WINAPI SetupDiOpenClassRegKeyExW(
1409         const GUID* ClassGuid,
1410         REGSAM samDesired,
1411         DWORD Flags,
1412         PCWSTR MachineName,
1413         PVOID Reserved)
1414 {
1415     LPWSTR lpGuidString;
1416     WCHAR bracedGuidString[39];
1417     HKEY hClassesKey;
1418     HKEY hClassKey;
1419     LPCWSTR lpKeyName;
1420
1421     if (MachineName != NULL)
1422     {
1423         FIXME("Remote access not supported yet!\n");
1424         return INVALID_HANDLE_VALUE;
1425     }
1426
1427     if (Flags == DIOCR_INSTALLER)
1428     {
1429         lpKeyName = ControlClass;
1430     }
1431     else if (Flags == DIOCR_INTERFACE)
1432     {
1433         lpKeyName = DeviceClasses;
1434     }
1435     else
1436     {
1437         ERR("Invalid Flags parameter!\n");
1438         SetLastError(ERROR_INVALID_PARAMETER);
1439         return INVALID_HANDLE_VALUE;
1440     }
1441
1442     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1443                       lpKeyName,
1444                       0,
1445                       KEY_ALL_ACCESS,
1446                       &hClassesKey))
1447     {
1448         return INVALID_HANDLE_VALUE;
1449     }
1450
1451     if (ClassGuid == NULL)
1452         return hClassesKey;
1453
1454     if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK)
1455     {
1456         RegCloseKey(hClassesKey);
1457         return INVALID_HANDLE_VALUE;
1458     }
1459     bracedGuidString[0] = '{';
1460     memcpy(&bracedGuidString[1], lpGuidString, 36*sizeof(WCHAR));
1461     bracedGuidString[37] = '}';
1462     bracedGuidString[38] = 0;
1463     RpcStringFreeW(&lpGuidString);
1464
1465     if (RegOpenKeyExW(hClassesKey,
1466                       bracedGuidString,
1467                       0,
1468                       KEY_ALL_ACCESS,
1469                       &hClassKey))
1470     {
1471         RegCloseKey(hClassesKey);
1472         return INVALID_HANDLE_VALUE;
1473     }
1474
1475     RegCloseKey(hClassesKey);
1476
1477     return hClassKey;
1478 }
1479
1480 /***********************************************************************
1481  *              SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
1482  */
1483 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
1484        HDEVINFO DeviceInfoSet,
1485        PCWSTR DevicePath,
1486        DWORD OpenFlags,
1487        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1488 {
1489     FIXME("%p %s %08x %p\n",
1490         DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
1491     return FALSE;
1492 }
1493
1494 /***********************************************************************
1495  *              SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
1496  */
1497 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
1498        HDEVINFO DeviceInfoSet,
1499        PCSTR DevicePath,
1500        DWORD OpenFlags,
1501        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1502 {
1503     FIXME("%p %s %08x %p\n", DeviceInfoSet,
1504         debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
1505     return FALSE;
1506 }
1507
1508 /***********************************************************************
1509  *              SetupDiSetClassInstallParamsA (SETUPAPI.@)
1510  */
1511 BOOL WINAPI SetupDiSetClassInstallParamsA(
1512        HDEVINFO  DeviceInfoSet,
1513        PSP_DEVINFO_DATA DeviceInfoData,
1514        PSP_CLASSINSTALL_HEADER ClassInstallParams,
1515        DWORD ClassInstallParamsSize)
1516 {
1517     FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
1518           ClassInstallParams->InstallFunction, ClassInstallParamsSize);
1519     return FALSE;
1520 }
1521
1522 /***********************************************************************
1523  *              SetupDiCallClassInstaller (SETUPAPI.@)
1524  */
1525 BOOL WINAPI SetupDiCallClassInstaller(
1526        DI_FUNCTION InstallFunction,
1527        HDEVINFO DeviceInfoSet,
1528        PSP_DEVINFO_DATA DeviceInfoData)
1529 {
1530     FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
1531     return FALSE;
1532 }
1533
1534 /***********************************************************************
1535  *              SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
1536  */
1537 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
1538        HDEVINFO DeviceInfoSet,
1539        PSP_DEVINFO_DATA DeviceInfoData,
1540        PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
1541 {
1542     FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
1543     return FALSE;
1544 }
1545
1546 /***********************************************************************
1547  *              SetupDiOpenDevRegKey (SETUPAPI.@)
1548  */
1549 HKEY WINAPI SetupDiOpenDevRegKey(
1550        HDEVINFO DeviceInfoSet,
1551        PSP_DEVINFO_DATA DeviceInfoData,
1552        DWORD Scope,
1553        DWORD HwProfile,
1554        DWORD KeyType,
1555        REGSAM samDesired)
1556 {
1557     FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
1558           Scope, HwProfile, KeyType, samDesired);
1559     return INVALID_HANDLE_VALUE;
1560 }