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