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