Reverse the order for deleting the items in resetcontent to correctly
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
38 #include "rpc.h"
39 #include "rpcdce.h"
40
41 #include "setupapi_private.h"
42
43
44 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
45
46 /* Unicode constants */
47 static const WCHAR ClassGUID[]  = {'C','l','a','s','s','G','U','I','D',0};
48 static const WCHAR Class[]  = {'C','l','a','s','s',0};
49 static const WCHAR ClassInstall32[]  = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
50 static const WCHAR NoDisplayClass[]  = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
51 static const WCHAR NoInstallClass[]  = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0};
52 static const WCHAR NoUseClass[]  = {'N','o','U','s','e','C','l','a','s','s',0};
53 static const WCHAR NtExtension[]  = {'.','N','T',0};
54 static const WCHAR NtPlatformExtension[]  = {'.','N','T','x','8','6',0};
55 static const WCHAR Version[]  = {'V','e','r','s','i','o','n',0};
56 static const WCHAR WinExtension[]  = {'.','W','i','n',0};
57
58 /* Registry key and value names */
59 static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\',
60                                   'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
61                                   'C','o','n','t','r','o','l','\\',
62                                   'C','l','a','s','s',0};
63
64 static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
65                                   'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
66                                   'C','o','n','t','r','o','l','\\',
67                                   'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
68
69 /***********************************************************************
70  *              SetupDiBuildClassInfoList  (SETUPAPI.@)
71  */
72 BOOL WINAPI SetupDiBuildClassInfoList(
73         DWORD Flags,
74         LPGUID ClassGuidList,
75         DWORD ClassGuidListSize,
76         PDWORD RequiredSize)
77 {
78     TRACE("\n");
79     return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
80                                         ClassGuidListSize, RequiredSize,
81                                         NULL, NULL);
82 }
83
84 /***********************************************************************
85  *              SetupDiBuildClassInfoListExA  (SETUPAPI.@)
86  */
87 BOOL WINAPI SetupDiBuildClassInfoListExA(
88         DWORD Flags,
89         LPGUID ClassGuidList,
90         DWORD ClassGuidListSize,
91         PDWORD RequiredSize,
92         LPCSTR MachineName,
93         PVOID Reserved)
94 {
95     LPWSTR MachineNameW = NULL;
96     BOOL bResult;
97
98     TRACE("\n");
99
100     if (MachineName)
101     {
102         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
103         if (MachineNameW == NULL) return FALSE;
104     }
105
106     bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
107                                            ClassGuidListSize, RequiredSize,
108                                            MachineNameW, Reserved);
109
110     if (MachineNameW)
111         MyFree(MachineNameW);
112
113     return bResult;
114 }
115
116 /***********************************************************************
117  *              SetupDiBuildClassInfoListExW  (SETUPAPI.@)
118  */
119 BOOL WINAPI SetupDiBuildClassInfoListExW(
120         DWORD Flags,
121         LPGUID ClassGuidList,
122         DWORD ClassGuidListSize,
123         PDWORD RequiredSize,
124         LPCWSTR MachineName,
125         PVOID Reserved)
126 {
127     WCHAR szKeyName[40];
128     HKEY hClassesKey;
129     HKEY hClassKey;
130     DWORD dwLength;
131     DWORD dwIndex;
132     LONG lError;
133     DWORD dwGuidListIndex = 0;
134
135     TRACE("\n");
136
137     if (RequiredSize != NULL)
138         *RequiredSize = 0;
139
140     hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
141                                             KEY_ALL_ACCESS,
142                                             DIOCR_INSTALLER,
143                                             MachineName,
144                                             Reserved);
145     if (hClassesKey == INVALID_HANDLE_VALUE)
146     {
147         return FALSE;
148     }
149
150     for (dwIndex = 0; ; dwIndex++)
151     {
152         dwLength = 40;
153         lError = RegEnumKeyExW(hClassesKey,
154                                dwIndex,
155                                szKeyName,
156                                &dwLength,
157                                NULL,
158                                NULL,
159                                NULL,
160                                NULL);
161         TRACE("RegEnumKeyExW() returns %ld\n", lError);
162         if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
163         {
164             TRACE("Key name: %p\n", szKeyName);
165
166             if (RegOpenKeyExW(hClassesKey,
167                               szKeyName,
168                               0,
169                               KEY_ALL_ACCESS,
170                               &hClassKey))
171             {
172                 RegCloseKey(hClassesKey);
173                 return FALSE;
174             }
175
176             if (!RegQueryValueExW(hClassKey,
177                                   NoUseClass,
178                                   NULL,
179                                   NULL,
180                                   NULL,
181                                   NULL))
182             {
183                 TRACE("'NoUseClass' value found!\n");
184                 RegCloseKey(hClassKey);
185                 continue;
186             }
187
188             if ((Flags & DIBCI_NOINSTALLCLASS) &&
189                 (!RegQueryValueExW(hClassKey,
190                                    NoInstallClass,
191                                    NULL,
192                                    NULL,
193                                    NULL,
194                                    NULL)))
195             {
196                 TRACE("'NoInstallClass' value found!\n");
197                 RegCloseKey(hClassKey);
198                 continue;
199             }
200
201             if ((Flags & DIBCI_NODISPLAYCLASS) &&
202                 (!RegQueryValueExW(hClassKey,
203                                    NoDisplayClass,
204                                    NULL,
205                                    NULL,
206                                    NULL,
207                                    NULL)))
208             {
209                 TRACE("'NoDisplayClass' value found!\n");
210                 RegCloseKey(hClassKey);
211                 continue;
212             }
213
214             RegCloseKey(hClassKey);
215
216             TRACE("Guid: %p\n", szKeyName);
217             if (dwGuidListIndex < ClassGuidListSize)
218             {
219                 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
220                 {
221                     szKeyName[37] = 0;
222                 }
223                 TRACE("Guid: %p\n", &szKeyName[1]);
224
225                 UuidFromStringW(&szKeyName[1],
226                                 &ClassGuidList[dwGuidListIndex]);
227             }
228
229             dwGuidListIndex++;
230         }
231
232         if (lError != ERROR_SUCCESS)
233             break;
234     }
235
236     RegCloseKey(hClassesKey);
237
238     if (RequiredSize != NULL)
239         *RequiredSize = dwGuidListIndex;
240
241     if (ClassGuidListSize < dwGuidListIndex)
242     {
243         SetLastError(ERROR_INSUFFICIENT_BUFFER);
244         return FALSE;
245     }
246
247     return TRUE;
248 }
249
250 /***********************************************************************
251  *              SetupDiClassGuidsFromNameA  (SETUPAPI.@)
252  */
253 BOOL WINAPI SetupDiClassGuidsFromNameA(
254         LPCSTR ClassName,
255         LPGUID ClassGuidList,
256         DWORD ClassGuidListSize,
257         PDWORD RequiredSize)
258 {
259   return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
260                                       ClassGuidListSize, RequiredSize,
261                                       NULL, NULL);
262 }
263
264 /***********************************************************************
265  *              SetupDiClassGuidsFromNameW  (SETUPAPI.@)
266  */
267 BOOL WINAPI SetupDiClassGuidsFromNameW(
268         LPCWSTR ClassName,
269         LPGUID ClassGuidList,
270         DWORD ClassGuidListSize,
271         PDWORD RequiredSize)
272 {
273   return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
274                                       ClassGuidListSize, RequiredSize,
275                                       NULL, NULL);
276 }
277
278 /***********************************************************************
279  *              SetupDiClassGuidsFromNameExA  (SETUPAPI.@)
280  */
281 BOOL WINAPI SetupDiClassGuidsFromNameExA(
282         LPCSTR ClassName,
283         LPGUID ClassGuidList,
284         DWORD ClassGuidListSize,
285         PDWORD RequiredSize,
286         LPCSTR MachineName,
287         PVOID Reserved)
288 {
289     LPWSTR ClassNameW = NULL;
290     LPWSTR MachineNameW = NULL;
291     BOOL bResult;
292
293     FIXME("\n");
294
295     ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
296     if (ClassNameW == NULL)
297         return FALSE;
298
299     if (MachineNameW)
300     {
301         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
302         if (MachineNameW == NULL)
303         {
304             MyFree(ClassNameW);
305             return FALSE;
306         }
307     }
308
309     bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
310                                            ClassGuidListSize, RequiredSize,
311                                            MachineNameW, Reserved);
312
313     if (MachineNameW)
314         MyFree(MachineNameW);
315
316     MyFree(ClassNameW);
317
318     return bResult;
319 }
320
321 /***********************************************************************
322  *              SetupDiClassGuidsFromNameExW  (SETUPAPI.@)
323  */
324 BOOL WINAPI SetupDiClassGuidsFromNameExW(
325         LPCWSTR ClassName,
326         LPGUID ClassGuidList,
327         DWORD ClassGuidListSize,
328         PDWORD RequiredSize,
329         LPCWSTR MachineName,
330         PVOID Reserved)
331 {
332     WCHAR szKeyName[40];
333     WCHAR szClassName[256];
334     HKEY hClassesKey;
335     HKEY hClassKey;
336     DWORD dwLength;
337     DWORD dwIndex;
338     LONG lError;
339     DWORD dwGuidListIndex = 0;
340
341     if (RequiredSize != NULL)
342         *RequiredSize = 0;
343
344     hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
345                                             KEY_ALL_ACCESS,
346                                             DIOCR_INSTALLER,
347                                             MachineName,
348                                             Reserved);
349     if (hClassesKey == INVALID_HANDLE_VALUE)
350     {
351         return FALSE;
352     }
353
354     for (dwIndex = 0; ; dwIndex++)
355     {
356         dwLength = 40;
357         lError = RegEnumKeyExW(hClassesKey,
358                                dwIndex,
359                                szKeyName,
360                                &dwLength,
361                                NULL,
362                                NULL,
363                                NULL,
364                                NULL);
365         TRACE("RegEnumKeyExW() returns %ld\n", lError);
366         if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
367         {
368             TRACE("Key name: %p\n", szKeyName);
369
370             if (RegOpenKeyExW(hClassesKey,
371                               szKeyName,
372                               0,
373                               KEY_ALL_ACCESS,
374                               &hClassKey))
375             {
376                 RegCloseKey(hClassesKey);
377                 return FALSE;
378             }
379
380             dwLength = 256 * sizeof(WCHAR);
381             if (!RegQueryValueExW(hClassKey,
382                                   Class,
383                                   NULL,
384                                   NULL,
385                                   (LPBYTE)szClassName,
386                                   &dwLength))
387             {
388                 TRACE("Class name: %p\n", szClassName);
389
390                 if (strcmpiW(szClassName, ClassName) == 0)
391                 {
392                     TRACE("Found matching class name\n");
393
394                     TRACE("Guid: %p\n", szKeyName);
395                     if (dwGuidListIndex < ClassGuidListSize)
396                     {
397                         if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
398                         {
399                             szKeyName[37] = 0;
400                         }
401                         TRACE("Guid: %p\n", &szKeyName[1]);
402
403                         UuidFromStringW(&szKeyName[1],
404                                         &ClassGuidList[dwGuidListIndex]);
405                     }
406
407                     dwGuidListIndex++;
408                 }
409             }
410
411             RegCloseKey(hClassKey);
412         }
413
414         if (lError != ERROR_SUCCESS)
415             break;
416     }
417
418     RegCloseKey(hClassesKey);
419
420     if (RequiredSize != NULL)
421         *RequiredSize = dwGuidListIndex;
422
423     if (ClassGuidListSize < dwGuidListIndex)
424     {
425         SetLastError(ERROR_INSUFFICIENT_BUFFER);
426         return FALSE;
427     }
428
429     return TRUE;
430 }
431
432 /***********************************************************************
433  *              SetupDiClassNameFromGuidA  (SETUPAPI.@)
434  */
435 BOOL WINAPI SetupDiClassNameFromGuidA(
436         const GUID* ClassGuid,
437         PSTR ClassName,
438         DWORD ClassNameSize,
439         PDWORD RequiredSize)
440 {
441   return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
442                                      ClassNameSize, RequiredSize,
443                                      NULL, NULL);
444 }
445
446 /***********************************************************************
447  *              SetupDiClassNameFromGuidW  (SETUPAPI.@)
448  */
449 BOOL WINAPI SetupDiClassNameFromGuidW(
450         const GUID* ClassGuid,
451         PWSTR ClassName,
452         DWORD ClassNameSize,
453         PDWORD RequiredSize)
454 {
455   return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
456                                      ClassNameSize, RequiredSize,
457                                      NULL, NULL);
458 }
459
460 /***********************************************************************
461  *              SetupDiClassNameFromGuidExA  (SETUPAPI.@)
462  */
463 BOOL WINAPI SetupDiClassNameFromGuidExA(
464         const GUID* ClassGuid,
465         PSTR ClassName,
466         DWORD ClassNameSize,
467         PDWORD RequiredSize,
468         PCSTR MachineName,
469         PVOID Reserved)
470 {
471   FIXME("\n");
472   return FALSE;
473 }
474
475 /***********************************************************************
476  *              SetupDiClassNameFromGuidExW  (SETUPAPI.@)
477  */
478 BOOL WINAPI SetupDiClassNameFromGuidExW(
479         const GUID* ClassGuid,
480         PWSTR ClassName,
481         DWORD ClassNameSize,
482         PDWORD RequiredSize,
483         PCWSTR MachineName,
484         PVOID Reserved)
485 {
486     HKEY hKey;
487     DWORD dwLength;
488
489     hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
490                                      KEY_ALL_ACCESS,
491                                      DIOCR_INSTALLER,
492                                      MachineName,
493                                      Reserved);
494     if (hKey == INVALID_HANDLE_VALUE)
495     {
496         return FALSE;
497     }
498
499     if (RequiredSize != NULL)
500     {
501         dwLength = 0;
502         if (RegQueryValueExW(hKey,
503                              Class,
504                              NULL,
505                              NULL,
506                              NULL,
507                              &dwLength))
508         {
509             RegCloseKey(hKey);
510             return FALSE;
511         }
512
513         *RequiredSize = dwLength / sizeof(WCHAR);
514     }
515
516     dwLength = ClassNameSize * sizeof(WCHAR);
517     if (RegQueryValueExW(hKey,
518                          Class,
519                          NULL,
520                          NULL,
521                          (LPBYTE)ClassName,
522                          &dwLength))
523     {
524         RegCloseKey(hKey);
525         return FALSE;
526     }
527
528     RegCloseKey(hKey);
529
530     return TRUE;
531 }
532
533 /***********************************************************************
534  *              SetupDiCreateDeviceInfoList (SETUPAPI.@)
535  */
536 HDEVINFO WINAPI
537 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
538                             HWND hwndParent)
539 {
540   return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
541 }
542
543 /***********************************************************************
544  *              SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
545  */
546 HDEVINFO WINAPI
547 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
548                                HWND hwndParent,
549                                PCSTR MachineName,
550                                PVOID Reserved)
551 {
552     LPWSTR MachineNameW = NULL;
553     HDEVINFO hDevInfo;
554
555     TRACE("\n");
556
557     if (MachineName)
558     {
559         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
560         if (MachineNameW == NULL)
561             return (HDEVINFO)INVALID_HANDLE_VALUE;
562     }
563
564     hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
565                                               MachineNameW, Reserved);
566
567     if (MachineNameW)
568         MyFree(MachineNameW);
569
570     return hDevInfo;
571 }
572
573 /***********************************************************************
574  *              SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
575  */
576 HDEVINFO WINAPI
577 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
578                                HWND hwndParent,
579                                PCWSTR MachineName,
580                                PVOID Reserved)
581 {
582   FIXME("\n");
583   return (HDEVINFO)INVALID_HANDLE_VALUE;
584 }
585
586 /***********************************************************************
587  *              SetupDiDestroyDeviceInfoList (SETUPAPI.@)
588  */
589 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
590 {
591   FIXME("%p\n", devinfo);
592   return FALSE;
593 }
594
595 /***********************************************************************
596  *              SetupDiEnumDeviceInfo (SETUPAPI.@)
597  */
598 BOOL WINAPI SetupDiEnumDeviceInfo(
599         HDEVINFO  devinfo,
600         DWORD  index,
601         PSP_DEVINFO_DATA info)
602 {
603     FIXME("%p %ld %p\n", devinfo, index, info);
604
605     if(info==NULL)
606         return FALSE;
607     if(info->cbSize < sizeof(*info))
608         return FALSE;
609
610     return FALSE;
611 }
612
613 /***********************************************************************
614  *              SetupDiEnumDeviceInterfaces (SETUPAPI.@)
615  */
616 BOOL WINAPI SetupDiEnumDeviceInterfaces(
617        HDEVINFO DeviceInfoSet,
618        PSP_DEVINFO_DATA DeviceInfoData,
619        CONST GUID * InterfaceClassGuid,
620        DWORD MemberIndex,
621        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
622 {
623     FIXME("\n");
624     return FALSE;
625 }
626
627 /***********************************************************************
628  *              SetupDiGetActualSectionToInstallA (SETUPAPI.@)
629  */
630 BOOL WINAPI SetupDiGetActualSectionToInstallA(
631         HINF InfHandle,
632         PCSTR InfSectionName,
633         PSTR InfSectionWithExt,
634         DWORD InfSectionWithExtSize,
635         PDWORD RequiredSize,
636         PSTR *Extension)
637 {
638     FIXME("\n");
639     return FALSE;
640 }
641
642 /***********************************************************************
643  *              SetupDiGetActualSectionToInstallW (SETUPAPI.@)
644  */
645 BOOL WINAPI SetupDiGetActualSectionToInstallW(
646         HINF InfHandle,
647         PCWSTR InfSectionName,
648         PWSTR InfSectionWithExt,
649         DWORD InfSectionWithExtSize,
650         PDWORD RequiredSize,
651         PWSTR *Extension)
652 {
653     WCHAR szBuffer[MAX_PATH];
654     DWORD dwLength;
655     DWORD dwFullLength;
656     LONG lLineCount = -1;
657
658     lstrcpyW(szBuffer, InfSectionName);
659     dwLength = lstrlenW(szBuffer);
660
661     if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
662     {
663         /* Test section name with '.NTx86' extension */
664         lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
665         lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
666
667         if (lLineCount == -1)
668         {
669             /* Test section name with '.NT' extension */
670             lstrcpyW(&szBuffer[dwLength], NtExtension);
671             lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
672         }
673     }
674     else
675     {
676         /* Test section name with '.Win' extension */
677         lstrcpyW(&szBuffer[dwLength], WinExtension);
678         lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
679     }
680
681     if (lLineCount == -1)
682     {
683         /* Test section name without extension */
684         szBuffer[dwLength] = 0;
685         lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
686     }
687
688     if (lLineCount == -1)
689     {
690         SetLastError(ERROR_INVALID_PARAMETER);
691         return FALSE;
692     }
693
694     dwFullLength = lstrlenW(szBuffer);
695
696     if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
697     {
698         if (InfSectionWithExtSize < (dwFullLength + 1))
699         {
700             SetLastError(ERROR_INSUFFICIENT_BUFFER);
701             return FALSE;
702         }
703
704         lstrcpyW(InfSectionWithExt, szBuffer);
705         if (Extension != NULL)
706         {
707             *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
708         }
709     }
710
711     if (RequiredSize != NULL)
712     {
713         *RequiredSize = dwFullLength + 1;
714     }
715
716     return TRUE;
717 }
718
719 /***********************************************************************
720  *              SetupDiGetClassDescriptionA  (SETUPAPI.@)
721  */
722 BOOL WINAPI SetupDiGetClassDescriptionA(
723         const GUID* ClassGuid,
724         PSTR ClassDescription,
725         DWORD ClassDescriptionSize,
726         PDWORD RequiredSize)
727 {
728   return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
729                                        ClassDescriptionSize,
730                                        RequiredSize, NULL, NULL);
731 }
732
733 /***********************************************************************
734  *              SetupDiGetClassDescriptionW  (SETUPAPI.@)
735  */
736 BOOL WINAPI SetupDiGetClassDescriptionW(
737         const GUID* ClassGuid,
738         PWSTR ClassDescription,
739         DWORD ClassDescriptionSize,
740         PDWORD RequiredSize)
741 {
742   return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
743                                        ClassDescriptionSize,
744                                        RequiredSize, NULL, NULL);
745 }
746
747 /***********************************************************************
748  *              SetupDiGetClassDescriptionExA  (SETUPAPI.@)
749  */
750 BOOL WINAPI SetupDiGetClassDescriptionExA(
751         const GUID* ClassGuid,
752         PSTR ClassDescription,
753         DWORD ClassDescriptionSize,
754         PDWORD RequiredSize,
755         PCSTR MachineName,
756         PVOID Reserved)
757 {
758   FIXME("\n");
759   return FALSE;
760 }
761
762 /***********************************************************************
763  *              SetupDiGetClassDescriptionExW  (SETUPAPI.@)
764  */
765 BOOL WINAPI SetupDiGetClassDescriptionExW(
766         const GUID* ClassGuid,
767         PWSTR ClassDescription,
768         DWORD ClassDescriptionSize,
769         PDWORD RequiredSize,
770         PCWSTR MachineName,
771         PVOID Reserved)
772 {
773     HKEY hKey;
774     DWORD dwLength;
775
776     hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
777                                      KEY_ALL_ACCESS,
778                                      DIOCR_INSTALLER,
779                                      MachineName,
780                                      Reserved);
781     if (hKey == INVALID_HANDLE_VALUE)
782     {
783         WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
784         return FALSE;
785     }
786
787     if (RequiredSize != NULL)
788     {
789         dwLength = 0;
790         if (RegQueryValueExW(hKey,
791                              NULL,
792                              NULL,
793                              NULL,
794                              NULL,
795                              &dwLength))
796         {
797             RegCloseKey(hKey);
798             return FALSE;
799         }
800
801         *RequiredSize = dwLength / sizeof(WCHAR);
802     }
803
804     dwLength = ClassDescriptionSize * sizeof(WCHAR);
805     if (RegQueryValueExW(hKey,
806                          NULL,
807                          NULL,
808                          NULL,
809                          (LPBYTE)ClassDescription,
810                          &dwLength))
811     {
812         RegCloseKey(hKey);
813         return FALSE;
814     }
815
816     RegCloseKey(hKey);
817
818     return TRUE;
819 }
820
821 /***********************************************************************
822  *              SetupDiGetClassDevsA (SETUPAPI.@)
823  */
824 HDEVINFO WINAPI SetupDiGetClassDevsA(
825        CONST GUID *class,
826        LPCSTR enumstr,
827        HWND parent,
828        DWORD flags)
829 {
830     FIXME("%s %s %p %08lx\n",debugstr_guid(class),enumstr,parent,flags);
831
832     return (HDEVINFO) INVALID_HANDLE_VALUE;
833 }
834
835 /***********************************************************************
836  *              SetupDiGetClassDevsW (SETUPAPI.@)
837  */
838 HDEVINFO WINAPI SetupDiGetClassDevsW(
839        CONST GUID *class,
840        LPCWSTR enumstr,
841        HWND parent,
842        DWORD flags)
843 {
844     FIXME("%s %s %p %08lx\n",debugstr_guid(class),debugstr_w(enumstr),parent,flags);
845
846     return (HDEVINFO) INVALID_HANDLE_VALUE;
847 }
848
849 /***********************************************************************
850  *              SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
851  */
852 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
853       HDEVINFO DeviceInfoSet,
854       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
855       PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
856       DWORD DeviceInterfaceDetailDataSize,
857       PDWORD RequiredSize,
858       PSP_DEVINFO_DATA DeviceInfoData)
859 {
860     FIXME("\n");
861     return FALSE;
862 }
863
864 /***********************************************************************
865  *              SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
866  */
867 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
868       HDEVINFO DeviceInfoSet,
869       PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
870       PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
871       DWORD DeviceInterfaceDetailDataSize,
872       PDWORD RequiredSize,
873       PSP_DEVINFO_DATA DeviceInfoData)
874 {
875     FIXME("\n");
876     return FALSE;
877 }
878
879 /***********************************************************************
880  *              SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
881  */
882 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
883         HDEVINFO  devinfo,
884         PSP_DEVINFO_DATA  DeviceInfoData,
885         DWORD   Property,
886         PDWORD  PropertyRegDataType,
887         PBYTE   PropertyBuffer,
888         DWORD   PropertyBufferSize,
889         PDWORD  RequiredSize)
890 {
891     FIXME("%04lx %p %ld %p %p %ld %p\n", (DWORD)devinfo, DeviceInfoData,
892         Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
893         RequiredSize);
894     return FALSE;
895 }
896
897 /***********************************************************************
898  *              SetupDiInstallClassA (SETUPAPI.@)
899  */
900 BOOL WINAPI SetupDiInstallClassA(
901         HWND hwndParent,
902         PCSTR InfFileName,
903         DWORD Flags,
904         HSPFILEQ FileQueue)
905 {
906     UNICODE_STRING FileNameW;
907     BOOL Result;
908
909     if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
910     {
911         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
912         return FALSE;
913     }
914
915     Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
916
917     RtlFreeUnicodeString(&FileNameW);
918
919     return Result;
920 }
921
922 static HKEY CreateClassKey(HINF hInf)
923 {
924     WCHAR FullBuffer[MAX_PATH];
925     WCHAR Buffer[MAX_PATH];
926     DWORD RequiredSize;
927     HKEY hClassKey;
928
929     if (!SetupGetLineTextW(NULL,
930                            hInf,
931                            Version,
932                            ClassGUID,
933                            Buffer,
934                            MAX_PATH,
935                            &RequiredSize))
936     {
937         return INVALID_HANDLE_VALUE;
938     }
939
940     lstrcpyW(FullBuffer, ControlClass);
941     lstrcatW(FullBuffer, Buffer);
942
943     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
944                       FullBuffer,
945                       0,
946                       KEY_ALL_ACCESS,
947                       &hClassKey))
948     {
949         if (!SetupGetLineTextW(NULL,
950                                hInf,
951                                Version,
952                                Class,
953                                Buffer,
954                                MAX_PATH,
955                                &RequiredSize))
956         {
957             return INVALID_HANDLE_VALUE;
958         }
959
960         if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
961                             FullBuffer,
962                             0,
963                             NULL,
964                             REG_OPTION_NON_VOLATILE,
965                             KEY_ALL_ACCESS,
966                             NULL,
967                             &hClassKey,
968                             NULL))
969         {
970             return INVALID_HANDLE_VALUE;
971         }
972
973     }
974
975     if (RegSetValueExW(hClassKey,
976                        Class,
977                        0,
978                        REG_SZ,
979                        (LPBYTE)Buffer,
980                        RequiredSize * sizeof(WCHAR)))
981     {
982         RegCloseKey(hClassKey);
983         RegDeleteKeyW(HKEY_LOCAL_MACHINE,
984                       FullBuffer);
985         return INVALID_HANDLE_VALUE;
986     }
987
988     return hClassKey;
989 }
990
991 /***********************************************************************
992  *              SetupDiInstallClassW (SETUPAPI.@)
993  */
994 BOOL WINAPI SetupDiInstallClassW(
995         HWND hwndParent,
996         PCWSTR InfFileName,
997         DWORD Flags,
998         HSPFILEQ FileQueue)
999 {
1000     WCHAR SectionName[MAX_PATH];
1001     DWORD SectionNameLength = 0;
1002     HINF hInf;
1003     BOOL bFileQueueCreated = FALSE;
1004     HKEY hClassKey;
1005
1006
1007     FIXME("\n");
1008
1009     if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
1010     {
1011         SetLastError(ERROR_INVALID_PARAMETER);
1012         return FALSE;
1013     }
1014
1015     /* Open the .inf file */
1016     hInf = SetupOpenInfFileW(InfFileName,
1017                              NULL,
1018                              INF_STYLE_WIN4,
1019                              NULL);
1020     if (hInf == INVALID_HANDLE_VALUE)
1021     {
1022
1023         return FALSE;
1024     }
1025
1026     /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
1027     hClassKey = CreateClassKey(hInf);
1028     if (hClassKey == INVALID_HANDLE_VALUE)
1029     {
1030         SetupCloseInfFile(hInf);
1031         return FALSE;
1032     }
1033
1034
1035     /* Try to append a layout file */
1036 #if 0
1037     SetupOpenAppendInfFileW(NULL, hInf, NULL);
1038 #endif
1039
1040     /* Retrieve the actual section name */
1041     SetupDiGetActualSectionToInstallW(hInf,
1042                                       ClassInstall32,
1043                                       SectionName,
1044                                       MAX_PATH,
1045                                       &SectionNameLength,
1046                                       NULL);
1047
1048 #if 0
1049     if (!(Flags & DI_NOVCP))
1050     {
1051         FileQueue = SetupOpenFileQueue();
1052         if (FileQueue == INVALID_HANDLE_VALUE)
1053         {
1054             SetupCloseInfFile(hInf);
1055             return FALSE;
1056         }
1057
1058         bFileQueueCreated = TRUE;
1059
1060     }
1061 #endif
1062
1063     SetupInstallFromInfSectionW(NULL,
1064                                 hInf,
1065                                 SectionName,
1066                                 SPINST_REGISTRY,
1067                                 hClassKey,
1068                                 NULL,
1069                                 0,
1070                                 NULL,
1071                                 NULL,
1072                                 INVALID_HANDLE_VALUE,
1073                                 NULL);
1074
1075     /* FIXME: More code! */
1076
1077     if (bFileQueueCreated)
1078         SetupCloseFileQueue(FileQueue);
1079
1080     SetupCloseInfFile(hInf);
1081
1082     return TRUE;
1083 }
1084
1085
1086 /***********************************************************************
1087  *              SetupDiOpenClassRegKey  (SETUPAPI.@)
1088  */
1089 HKEY WINAPI SetupDiOpenClassRegKey(
1090         const GUID* ClassGuid,
1091         REGSAM samDesired)
1092 {
1093     return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1094                                      DIOCR_INSTALLER, NULL, NULL);
1095 }
1096
1097
1098 /***********************************************************************
1099  *              SetupDiOpenClassRegKeyExA  (SETUPAPI.@)
1100  */
1101 HKEY WINAPI SetupDiOpenClassRegKeyExA(
1102         const GUID* ClassGuid,
1103         REGSAM samDesired,
1104         DWORD Flags,
1105         PCSTR MachineName,
1106         PVOID Reserved)
1107 {
1108     PWSTR MachineNameW = NULL;
1109     HKEY hKey;
1110
1111     TRACE("\n");
1112
1113     if (MachineName)
1114     {
1115         MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1116         if (MachineNameW == NULL)
1117             return INVALID_HANDLE_VALUE;
1118     }
1119
1120     hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1121                                      Flags, MachineNameW, Reserved);
1122
1123     if (MachineNameW)
1124         MyFree(MachineNameW);
1125
1126     return hKey;
1127 }
1128
1129
1130 /***********************************************************************
1131  *              SetupDiOpenClassRegKeyExW  (SETUPAPI.@)
1132  */
1133 HKEY WINAPI SetupDiOpenClassRegKeyExW(
1134         const GUID* ClassGuid,
1135         REGSAM samDesired,
1136         DWORD Flags,
1137         PCWSTR MachineName,
1138         PVOID Reserved)
1139 {
1140     LPWSTR lpGuidString;
1141     HKEY hClassesKey;
1142     HKEY hClassKey;
1143     LPCWSTR lpKeyName;
1144
1145     if (MachineName != NULL)
1146     {
1147         FIXME("Remote access not supported yet!\n");
1148         return INVALID_HANDLE_VALUE;
1149     }
1150
1151     if (Flags == DIOCR_INSTALLER)
1152     {
1153         lpKeyName = ControlClass;
1154     }
1155     else if (Flags == DIOCR_INTERFACE)
1156     {
1157         lpKeyName = DeviceClasses;
1158     }
1159     else
1160     {
1161         ERR("Invalid Flags parameter!\n");
1162         SetLastError(ERROR_INVALID_PARAMETER);
1163         return INVALID_HANDLE_VALUE;
1164     }
1165
1166     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1167                       lpKeyName,
1168                       0,
1169                       KEY_ALL_ACCESS,
1170                       &hClassesKey))
1171     {
1172         return INVALID_HANDLE_VALUE;
1173     }
1174
1175     if (ClassGuid == NULL)
1176         return hClassesKey;
1177
1178     if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK)
1179     {
1180         RegCloseKey(hClassesKey);
1181         return FALSE;
1182     }
1183
1184     if (RegOpenKeyExW(hClassesKey,
1185                       lpGuidString,
1186                       0,
1187                       KEY_ALL_ACCESS,
1188                       &hClassKey))
1189     {
1190         RpcStringFreeW(&lpGuidString);
1191         RegCloseKey(hClassesKey);
1192         return FALSE;
1193     }
1194
1195     RpcStringFreeW(&lpGuidString);
1196     RegCloseKey(hClassesKey);
1197
1198     return hClassKey;
1199 }
1200
1201 /***********************************************************************
1202  *              SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
1203  */
1204 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
1205        HDEVINFO DeviceInfoSet,
1206        PCWSTR DevicePath,
1207        DWORD OpenFlags,
1208        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1209 {
1210     FIXME("%p %s %08lx %p\n",
1211         DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
1212     return FALSE;
1213 }
1214
1215 /***********************************************************************
1216  *              SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
1217  */
1218 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
1219        HDEVINFO DeviceInfoSet,
1220        PCSTR DevicePath,
1221        DWORD OpenFlags,
1222        PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1223 {
1224     FIXME("%p %s %08lx %p\n", DeviceInfoSet,
1225         debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
1226     return FALSE;
1227 }
1228
1229 /***********************************************************************
1230  *              SetupDiSetClassInstallParamsA (SETUPAPI.@)
1231  */
1232 BOOL WINAPI SetupDiSetClassInstallParamsA(
1233        HDEVINFO  DeviceInfoSet,
1234        PSP_DEVINFO_DATA DeviceInfoData,
1235        PSP_CLASSINSTALL_HEADER ClassInstallParams,
1236        DWORD ClassInstallParamsSize)
1237 {
1238     FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData,
1239           ClassInstallParams->InstallFunction, ClassInstallParamsSize);
1240     return FALSE;
1241 }
1242
1243 /***********************************************************************
1244  *              SetupDiCallClassInstaller (SETUPAPI.@)
1245  */
1246 BOOL WINAPI SetupDiCallClassInstaller(
1247        DWORD InstallFunction,
1248        HDEVINFO DeviceInfoSet,
1249        PSP_DEVINFO_DATA DeviceInfoData)
1250 {
1251     FIXME("%ld %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
1252     return FALSE;
1253 }
1254
1255 /***********************************************************************
1256  *              SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
1257  */
1258 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
1259        HDEVINFO DeviceInfoSet,
1260        PSP_DEVINFO_DATA DeviceInfoData,
1261        PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
1262 {
1263     FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
1264     return FALSE;
1265 }
1266
1267 /***********************************************************************
1268  *              SetupDiOpenDevRegKey (SETUPAPI.@)
1269  */
1270 HKEY WINAPI SetupDiOpenDevRegKey(
1271        HDEVINFO DeviceInfoSet,
1272        PSP_DEVINFO_DATA DeviceInfoData,
1273        DWORD Scope,
1274        DWORD HwProfile,
1275        DWORD KeyType,
1276        REGSAM samDesired)
1277 {
1278     FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet, DeviceInfoData,
1279           Scope, HwProfile, KeyType, samDesired);
1280     return INVALID_HANDLE_VALUE;
1281 }