hal: Added an initial stub.
[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 registry 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     SetLastError(ERROR_NO_MORE_ITEMS);
776     return FALSE;
777 }
778
779 /***********************************************************************
780  *              SetupDiGetActualSectionToInstallA (SETUPAPI.@)
781  */
782 BOOL WINAPI SetupDiGetActualSectionToInstallA(
783         HINF InfHandle,
784         PCSTR InfSectionName,
785         PSTR InfSectionWithExt,
786         DWORD InfSectionWithExtSize,
787         PDWORD RequiredSize,
788         PSTR *Extension)
789 {
790     FIXME("\n");
791     return FALSE;
792 }
793
794 /***********************************************************************
795  *              SetupDiGetActualSectionToInstallW (SETUPAPI.@)
796  */
797 BOOL WINAPI SetupDiGetActualSectionToInstallW(
798         HINF InfHandle,
799         PCWSTR InfSectionName,
800         PWSTR InfSectionWithExt,
801         DWORD InfSectionWithExtSize,
802         PDWORD RequiredSize,
803         PWSTR *Extension)
804 {
805     WCHAR szBuffer[MAX_PATH];
806     DWORD dwLength;
807     DWORD dwFullLength;
808     LONG lLineCount = -1;
809
810     lstrcpyW(szBuffer, InfSectionName);
811     dwLength = lstrlenW(szBuffer);
812
813     if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
814     {
815         /* Test section name with '.NTx86' extension */
816         lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
817         lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
818
819         if (lLineCount == -1)
820         {
821             /* Test section name with '.NT' extension */
822             lstrcpyW(&szBuffer[dwLength], NtExtension);
823             lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
824         }
825     }
826     else
827     {
828         /* Test section name with '.Win' extension */
829         lstrcpyW(&szBuffer[dwLength], WinExtension);
830         lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
831     }
832
833     if (lLineCount == -1)
834     {
835         /* Test section name without extension */
836         szBuffer[dwLength] = 0;
837         lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
838     }
839
840     if (lLineCount == -1)
841     {
842         SetLastError(ERROR_INVALID_PARAMETER);
843         return FALSE;
844     }
845
846     dwFullLength = lstrlenW(szBuffer);
847
848     if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
849     {
850         if (InfSectionWithExtSize < (dwFullLength + 1))
851         {
852             SetLastError(ERROR_INSUFFICIENT_BUFFER);
853             return FALSE;
854         }
855
856         lstrcpyW(InfSectionWithExt, szBuffer);
857         if (Extension != NULL)
858         {
859             *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
860         }
861     }
862
863     if (RequiredSize != NULL)
864     {
865         *RequiredSize = dwFullLength + 1;
866     }
867
868     return TRUE;
869 }
870
871 /***********************************************************************
872  *              SetupDiGetClassDescriptionA  (SETUPAPI.@)
873  */
874 BOOL WINAPI SetupDiGetClassDescriptionA(
875         const GUID* ClassGuid,
876         PSTR ClassDescription,
877         DWORD ClassDescriptionSize,
878         PDWORD RequiredSize)
879 {
880   return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
881                                        ClassDescriptionSize,
882                                        RequiredSize, NULL, NULL);
883 }
884
885 /***********************************************************************
886  *              SetupDiGetClassDescriptionW  (SETUPAPI.@)
887  */
888 BOOL WINAPI SetupDiGetClassDescriptionW(
889         const GUID* ClassGuid,
890         PWSTR ClassDescription,
891         DWORD ClassDescriptionSize,
892         PDWORD RequiredSize)
893 {
894   return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
895                                        ClassDescriptionSize,
896                                        RequiredSize, NULL, NULL);
897 }
898
899 /***********************************************************************
900  *              SetupDiGetClassDescriptionExA  (SETUPAPI.@)
901  */
902 BOOL WINAPI SetupDiGetClassDescriptionExA(
903         const GUID* ClassGuid,
904         PSTR ClassDescription,
905         DWORD ClassDescriptionSize,
906         PDWORD RequiredSize,
907         PCSTR MachineName,
908         PVOID Reserved)
909 {
910   FIXME("\n");
911   return FALSE;
912 }
913
914 /***********************************************************************
915  *              SetupDiGetClassDescriptionExW  (SETUPAPI.@)
916  */
917 BOOL WINAPI SetupDiGetClassDescriptionExW(
918         const GUID* ClassGuid,
919         PWSTR ClassDescription,
920         DWORD ClassDescriptionSize,
921         PDWORD RequiredSize,
922         PCWSTR MachineName,
923         PVOID Reserved)
924 {
925     HKEY hKey;
926     DWORD dwLength;
927
928     hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
929                                      KEY_ALL_ACCESS,
930                                      DIOCR_INSTALLER,
931                                      MachineName,
932                                      Reserved);
933     if (hKey == INVALID_HANDLE_VALUE)
934     {
935         WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
936         return FALSE;
937     }
938
939     if (RequiredSize != NULL)
940     {
941         dwLength = 0;
942         if (RegQueryValueExW(hKey,
943                              NULL,
944                              NULL,
945                              NULL,
946                              NULL,
947                              &dwLength))
948         {
949             RegCloseKey(hKey);
950             return FALSE;
951         }
952
953         *RequiredSize = dwLength / sizeof(WCHAR);
954     }
955
956     dwLength = ClassDescriptionSize * sizeof(WCHAR);
957     if (RegQueryValueExW(hKey,
958                          NULL,
959                          NULL,
960                          NULL,
961                          (LPBYTE)ClassDescription,
962                          &dwLength))
963     {
964         RegCloseKey(hKey);
965         return FALSE;
966     }
967
968     RegCloseKey(hKey);
969
970     return TRUE;
971 }
972
973 /***********************************************************************
974  *              SetupDiGetClassDevsA (SETUPAPI.@)
975  */
976 HDEVINFO WINAPI SetupDiGetClassDevsA(
977        CONST GUID *class,
978        LPCSTR enumstr,
979        HWND parent,
980        DWORD flags)
981 {
982     HDEVINFO ret;
983     LPWSTR enumstrW = NULL;
984
985     if (enumstr)
986     {
987         int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
988         enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
989         if (!enumstrW)
990         {
991             ret = (HDEVINFO)INVALID_HANDLE_VALUE;
992             goto end;
993         }
994         MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
995     }
996     ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
997     HeapFree(GetProcessHeap(), 0, enumstrW);
998
999 end:
1000     return ret;
1001 }
1002
1003 /***********************************************************************
1004  *              SetupDiGetClassDevsW (SETUPAPI.@)
1005  */
1006 HDEVINFO WINAPI SetupDiGetClassDevsW(
1007        CONST GUID *class,
1008        LPCWSTR enumstr,
1009        HWND parent,
1010        DWORD flags)
1011 {
1012     TRACE("%s %s %p 0x%08x\n", debugstr_guid(class), debugstr_w(enumstr), parent, flags);
1013
1014     /* WinXP always succeeds, returns empty list for unknown classes */
1015     FIXME("returning empty list\n");
1016     return SetupDiCreateDeviceInfoList(class, parent);
1017 }
1018
1019 /***********************************************************************
1020  *              SetupDiGetClassDevsExW (SETUPAPI.@)
1021  */
1022 HDEVINFO WINAPI SetupDiGetClassDevsExW(
1023         CONST GUID *class,
1024         PCWSTR enumstr,
1025         HWND parent,
1026         DWORD flags,
1027         HDEVINFO deviceset,
1028         PCWSTR machine,
1029         PVOID reserved)
1030 {
1031     FIXME("stub\n");
1032     return FALSE;
1033 }
1034
1035 /***********************************************************************
1036  *              SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1037  */
1038 BOOL WINAPI SetupDiEnumDeviceInterfaces(
1039        HDEVINFO devinfo,
1040        PSP_DEVINFO_DATA DeviceInfoData,
1041        CONST GUID * InterfaceClassGuid,
1042        DWORD MemberIndex,
1043        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1044 {
1045     BOOL ret = FALSE;
1046
1047     FIXME("%p, %p, %s, 0x%08x, %p\n", devinfo, DeviceInfoData,
1048      debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
1049
1050     if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1051     {
1052         struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1053         if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1054             SetLastError(ERROR_NO_MORE_ITEMS);
1055         else
1056             SetLastError(ERROR_INVALID_HANDLE);
1057     }
1058     else
1059         SetLastError(ERROR_INVALID_HANDLE);
1060     return ret;
1061 }
1062
1063 /***********************************************************************
1064  *              SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1065   *
1066  * Destroy a DeviceInfoList and free all used memory of the list.
1067  *
1068  * PARAMS
1069  *   devinfo [I] DeviceInfoList pointer to list to destroy
1070  *
1071  * RETURNS
1072  *   Success: non zero value.
1073  *   Failure: zero value.
1074  */
1075 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
1076 {
1077     BOOL ret = FALSE;
1078
1079     TRACE("%p\n", devinfo);
1080     if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1081     {
1082         struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1083
1084         if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1085         {
1086             HeapFree(GetProcessHeap(), 0, list);
1087             ret = TRUE;
1088         }
1089     }
1090
1091     if (ret == FALSE)
1092         SetLastError(ERROR_INVALID_HANDLE);
1093
1094     return ret;
1095 }
1096
1097 /***********************************************************************
1098  *              SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1099  */
1100 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
1101       HDEVINFO DeviceInfoSet,
1102       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1103       PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
1104       DWORD DeviceInterfaceDetailDataSize,
1105       PDWORD RequiredSize,
1106       PSP_DEVINFO_DATA DeviceInfoData)
1107 {
1108     BOOL ret = FALSE;
1109
1110     FIXME("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
1111      DeviceInterfaceData, DeviceInterfaceDetailData,
1112      DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1113
1114     SetLastError(ERROR_INVALID_HANDLE);
1115     return ret;
1116 }
1117
1118 /***********************************************************************
1119  *              SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
1120  */
1121 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
1122       HDEVINFO DeviceInfoSet,
1123       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1124       PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
1125       DWORD DeviceInterfaceDetailDataSize,
1126       PDWORD RequiredSize,
1127       PSP_DEVINFO_DATA DeviceInfoData)
1128 {
1129     FIXME("(%p, %p, %p, %d, %p, %p): stub\n", DeviceInfoSet,
1130      DeviceInterfaceData, DeviceInterfaceDetailData,
1131      DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1132     return FALSE;
1133 }
1134
1135 /***********************************************************************
1136  *              SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
1137  */
1138 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
1139         HDEVINFO  devinfo,
1140         PSP_DEVINFO_DATA  DeviceInfoData,
1141         DWORD   Property,
1142         PDWORD  PropertyRegDataType,
1143         PBYTE   PropertyBuffer,
1144         DWORD   PropertyBufferSize,
1145         PDWORD  RequiredSize)
1146 {
1147     FIXME("%04x %p %d %p %p %d %p\n", (DWORD)devinfo, DeviceInfoData,
1148         Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1149         RequiredSize);
1150     return FALSE;
1151 }
1152
1153 /***********************************************************************
1154  *              SetupDiInstallClassA (SETUPAPI.@)
1155  */
1156 BOOL WINAPI SetupDiInstallClassA(
1157         HWND hwndParent,
1158         PCSTR InfFileName,
1159         DWORD Flags,
1160         HSPFILEQ FileQueue)
1161 {
1162     UNICODE_STRING FileNameW;
1163     BOOL Result;
1164
1165     if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
1166     {
1167         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1168         return FALSE;
1169     }
1170
1171     Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
1172
1173     RtlFreeUnicodeString(&FileNameW);
1174
1175     return Result;
1176 }
1177
1178 static HKEY CreateClassKey(HINF hInf)
1179 {
1180     WCHAR FullBuffer[MAX_PATH];
1181     WCHAR Buffer[MAX_PATH];
1182     DWORD RequiredSize;
1183     HKEY hClassKey;
1184
1185     if (!SetupGetLineTextW(NULL,
1186                            hInf,
1187                            Version,
1188                            ClassGUID,
1189                            Buffer,
1190                            MAX_PATH,
1191                            &RequiredSize))
1192     {
1193         return INVALID_HANDLE_VALUE;
1194     }
1195
1196     lstrcpyW(FullBuffer, ControlClass);
1197     lstrcatW(FullBuffer, Buffer);
1198
1199     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1200                       FullBuffer,
1201                       0,
1202                       KEY_ALL_ACCESS,
1203                       &hClassKey))
1204     {
1205         if (!SetupGetLineTextW(NULL,
1206                                hInf,
1207                                Version,
1208                                Class,
1209                                Buffer,
1210                                MAX_PATH,
1211                                &RequiredSize))
1212         {
1213             return INVALID_HANDLE_VALUE;
1214         }
1215
1216         if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
1217                             FullBuffer,
1218                             0,
1219                             NULL,
1220                             REG_OPTION_NON_VOLATILE,
1221                             KEY_ALL_ACCESS,
1222                             NULL,
1223                             &hClassKey,
1224                             NULL))
1225         {
1226             return INVALID_HANDLE_VALUE;
1227         }
1228
1229     }
1230
1231     if (RegSetValueExW(hClassKey,
1232                        Class,
1233                        0,
1234                        REG_SZ,
1235                        (LPBYTE)Buffer,
1236                        RequiredSize * sizeof(WCHAR)))
1237     {
1238         RegCloseKey(hClassKey);
1239         RegDeleteKeyW(HKEY_LOCAL_MACHINE,
1240                       FullBuffer);
1241         return INVALID_HANDLE_VALUE;
1242     }
1243
1244     return hClassKey;
1245 }
1246
1247 /***********************************************************************
1248  *              SetupDiInstallClassW (SETUPAPI.@)
1249  */
1250 BOOL WINAPI SetupDiInstallClassW(
1251         HWND hwndParent,
1252         PCWSTR InfFileName,
1253         DWORD Flags,
1254         HSPFILEQ FileQueue)
1255 {
1256     WCHAR SectionName[MAX_PATH];
1257     DWORD SectionNameLength = 0;
1258     HINF hInf;
1259     BOOL bFileQueueCreated = FALSE;
1260     HKEY hClassKey;
1261
1262
1263     FIXME("\n");
1264
1265     if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
1266     {
1267         SetLastError(ERROR_INVALID_PARAMETER);
1268         return FALSE;
1269     }
1270
1271     /* Open the .inf file */
1272     hInf = SetupOpenInfFileW(InfFileName,
1273                              NULL,
1274                              INF_STYLE_WIN4,
1275                              NULL);
1276     if (hInf == INVALID_HANDLE_VALUE)
1277     {
1278
1279         return FALSE;
1280     }
1281
1282     /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
1283     hClassKey = CreateClassKey(hInf);
1284     if (hClassKey == INVALID_HANDLE_VALUE)
1285     {
1286         SetupCloseInfFile(hInf);
1287         return FALSE;
1288     }
1289
1290
1291     /* Try to append a layout file */
1292 #if 0
1293     SetupOpenAppendInfFileW(NULL, hInf, NULL);
1294 #endif
1295
1296     /* Retrieve the actual section name */
1297     SetupDiGetActualSectionToInstallW(hInf,
1298                                       ClassInstall32,
1299                                       SectionName,
1300                                       MAX_PATH,
1301                                       &SectionNameLength,
1302                                       NULL);
1303
1304 #if 0
1305     if (!(Flags & DI_NOVCP))
1306     {
1307         FileQueue = SetupOpenFileQueue();
1308         if (FileQueue == INVALID_HANDLE_VALUE)
1309         {
1310             SetupCloseInfFile(hInf);
1311             return FALSE;
1312         }
1313
1314         bFileQueueCreated = TRUE;
1315
1316     }
1317 #endif
1318
1319     SetupInstallFromInfSectionW(NULL,
1320                                 hInf,
1321                                 SectionName,
1322                                 SPINST_REGISTRY,
1323                                 hClassKey,
1324                                 NULL,
1325                                 0,
1326                                 NULL,
1327                                 NULL,
1328                                 INVALID_HANDLE_VALUE,
1329                                 NULL);
1330
1331     /* FIXME: More code! */
1332
1333     if (bFileQueueCreated)
1334         SetupCloseFileQueue(FileQueue);
1335
1336     SetupCloseInfFile(hInf);
1337
1338     return TRUE;
1339 }
1340
1341
1342 /***********************************************************************
1343  *              SetupDiOpenClassRegKey  (SETUPAPI.@)
1344  */
1345 HKEY WINAPI SetupDiOpenClassRegKey(
1346         const GUID* ClassGuid,
1347         REGSAM samDesired)
1348 {
1349     return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1350                                      DIOCR_INSTALLER, NULL, NULL);
1351 }
1352
1353
1354 /***********************************************************************
1355  *              SetupDiOpenClassRegKeyExA  (SETUPAPI.@)
1356  */
1357 HKEY WINAPI SetupDiOpenClassRegKeyExA(
1358         const GUID* ClassGuid,
1359         REGSAM samDesired,
1360         DWORD Flags,
1361         PCSTR MachineName,
1362         PVOID Reserved)
1363 {
1364     PWSTR MachineNameW = NULL;
1365     HKEY hKey;
1366
1367     TRACE("\n");
1368
1369     if (MachineName)
1370     {
1371         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1372         if (MachineNameW == NULL)
1373             return INVALID_HANDLE_VALUE;
1374     }
1375
1376     hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1377                                      Flags, MachineNameW, Reserved);
1378
1379     MyFree(MachineNameW);
1380
1381     return hKey;
1382 }
1383
1384
1385 /***********************************************************************
1386  *              SetupDiOpenClassRegKeyExW  (SETUPAPI.@)
1387  */
1388 HKEY WINAPI SetupDiOpenClassRegKeyExW(
1389         const GUID* ClassGuid,
1390         REGSAM samDesired,
1391         DWORD Flags,
1392         PCWSTR MachineName,
1393         PVOID Reserved)
1394 {
1395     LPWSTR lpGuidString;
1396     WCHAR bracedGuidString[39];
1397     HKEY hClassesKey;
1398     HKEY hClassKey;
1399     LPCWSTR lpKeyName;
1400
1401     if (MachineName != NULL)
1402     {
1403         FIXME("Remote access not supported yet!\n");
1404         return INVALID_HANDLE_VALUE;
1405     }
1406
1407     if (Flags == DIOCR_INSTALLER)
1408     {
1409         lpKeyName = ControlClass;
1410     }
1411     else if (Flags == DIOCR_INTERFACE)
1412     {
1413         lpKeyName = DeviceClasses;
1414     }
1415     else
1416     {
1417         ERR("Invalid Flags parameter!\n");
1418         SetLastError(ERROR_INVALID_PARAMETER);
1419         return INVALID_HANDLE_VALUE;
1420     }
1421
1422     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1423                       lpKeyName,
1424                       0,
1425                       KEY_ALL_ACCESS,
1426                       &hClassesKey))
1427     {
1428         return INVALID_HANDLE_VALUE;
1429     }
1430
1431     if (ClassGuid == NULL)
1432         return hClassesKey;
1433
1434     if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK)
1435     {
1436         RegCloseKey(hClassesKey);
1437         return INVALID_HANDLE_VALUE;
1438     }
1439     bracedGuidString[0] = '{';
1440     memcpy(&bracedGuidString[1], lpGuidString, 36*sizeof(WCHAR));
1441     bracedGuidString[37] = '}';
1442     bracedGuidString[38] = 0;
1443     RpcStringFreeW(&lpGuidString);
1444
1445     if (RegOpenKeyExW(hClassesKey,
1446                       bracedGuidString,
1447                       0,
1448                       KEY_ALL_ACCESS,
1449                       &hClassKey))
1450     {
1451         RegCloseKey(hClassesKey);
1452         return INVALID_HANDLE_VALUE;
1453     }
1454
1455     RegCloseKey(hClassesKey);
1456
1457     return hClassKey;
1458 }
1459
1460 /***********************************************************************
1461  *              SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
1462  */
1463 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
1464        HDEVINFO DeviceInfoSet,
1465        PCWSTR DevicePath,
1466        DWORD OpenFlags,
1467        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1468 {
1469     FIXME("%p %s %08x %p\n",
1470         DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
1471     return FALSE;
1472 }
1473
1474 /***********************************************************************
1475  *              SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
1476  */
1477 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
1478        HDEVINFO DeviceInfoSet,
1479        PCSTR DevicePath,
1480        DWORD OpenFlags,
1481        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1482 {
1483     FIXME("%p %s %08x %p\n", DeviceInfoSet,
1484         debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
1485     return FALSE;
1486 }
1487
1488 /***********************************************************************
1489  *              SetupDiSetClassInstallParamsA (SETUPAPI.@)
1490  */
1491 BOOL WINAPI SetupDiSetClassInstallParamsA(
1492        HDEVINFO  DeviceInfoSet,
1493        PSP_DEVINFO_DATA DeviceInfoData,
1494        PSP_CLASSINSTALL_HEADER ClassInstallParams,
1495        DWORD ClassInstallParamsSize)
1496 {
1497     FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
1498           ClassInstallParams->InstallFunction, ClassInstallParamsSize);
1499     return FALSE;
1500 }
1501
1502 /***********************************************************************
1503  *              SetupDiCallClassInstaller (SETUPAPI.@)
1504  */
1505 BOOL WINAPI SetupDiCallClassInstaller(
1506        DI_FUNCTION InstallFunction,
1507        HDEVINFO DeviceInfoSet,
1508        PSP_DEVINFO_DATA DeviceInfoData)
1509 {
1510     FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
1511     return FALSE;
1512 }
1513
1514 /***********************************************************************
1515  *              SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
1516  */
1517 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
1518        HDEVINFO DeviceInfoSet,
1519        PSP_DEVINFO_DATA DeviceInfoData,
1520        PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
1521 {
1522     FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
1523     return FALSE;
1524 }
1525
1526 /***********************************************************************
1527  *              SetupDiOpenDevRegKey (SETUPAPI.@)
1528  */
1529 HKEY WINAPI SetupDiOpenDevRegKey(
1530        HDEVINFO DeviceInfoSet,
1531        PSP_DEVINFO_DATA DeviceInfoData,
1532        DWORD Scope,
1533        DWORD HwProfile,
1534        DWORD KeyType,
1535        REGSAM samDesired)
1536 {
1537     FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
1538           Scope, HwProfile, KeyType, samDesired);
1539     return INVALID_HANDLE_VALUE;
1540 }