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