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