2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005 Hervé Poussineau (hpoussin@reactos.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "setupapi_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
27 /* Unicode constants */
28 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class
[] = {'C','l','a','s','s',0};
30 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
31 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
32 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
33 static const WCHAR InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
34 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
35 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
37 /* FIXME: header mess */
38 DEFINE_GUID(GUID_NULL
,
39 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
41 (CALLBACK
* CLASS_INSTALL_PROC
) (
42 IN DI_FUNCTION InstallFunction
,
43 IN HDEVINFO DeviceInfoSet
,
44 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
46 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
47 IN HDEVINFO DeviceInfoSet
,
48 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
50 (CALLBACK
* COINSTALLER_PROC
) (
51 IN DI_FUNCTION InstallFunction
,
52 IN HDEVINFO DeviceInfoSet
,
53 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
54 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
56 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
57 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
58 IN LPFNADDPROPSHEETPAGE fAddFunc
,
61 (*UPDATE_CLASS_PARAM_HANDLER
) (
62 IN HDEVINFO DeviceInfoSet
,
63 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
64 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
65 IN DWORD ClassInstallParamsSize
);
67 struct CoInstallerElement
72 COINSTALLER_PROC Function
;
73 BOOL DoPostProcessing
;
78 PropertyChangeHandler(
79 IN HDEVINFO DeviceInfoSet
,
80 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
81 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
82 IN DWORD ClassInstallParamsSize
);
84 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
85 NULL
, /* DIF_SELECTDEVICE */
86 NULL
, /* DIF_INSTALLDEVICE */
87 NULL
, /* DIF_ASSIGNRESOURCES */
88 NULL
, /* DIF_PROPERTIES */
89 NULL
, /* DIF_REMOVE */
90 NULL
, /* DIF_FIRSTTIMESETUP */
91 NULL
, /* DIF_FOUNDDEVICE */
92 NULL
, /* DIF_SELECTCLASSDRIVERS */
93 NULL
, /* DIF_VALIDATECLASSDRIVERS */
94 NULL
, /* DIF_INSTALLCLASSDRIVERS */
95 NULL
, /* DIF_CALCDISKSPACE */
96 NULL
, /* DIF_DESTROYPRIVATEDATA */
97 NULL
, /* DIF_VALIDATEDRIVER */
98 NULL
, /* DIF_MOVEDEVICE */
99 NULL
, /* DIF_DETECT */
100 NULL
, /* DIF_INSTALLWIZARD */
101 NULL
, /* DIF_DESTROYWIZARDDATA */
102 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
103 NULL
, /* DIF_ENABLECLASS */
104 NULL
, /* DIF_DETECTVERIFY */
105 NULL
, /* DIF_INSTALLDEVICEFILES */
106 NULL
, /* DIF_UNREMOVE */
107 NULL
, /* DIF_SELECTBESTCOMPATDRV */
108 NULL
, /* DIF_ALLOW_INSTALL */
109 NULL
, /* DIF_REGISTERDEVICE */
110 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
111 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
112 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
113 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
114 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
115 NULL
, /* DIF_UNUSED1 */
116 NULL
, /* DIF_INSTALLINTERFACES */
117 NULL
, /* DIF_DETECTCANCEL */
118 NULL
, /* DIF_REGISTER_COINSTALLERS */
119 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
120 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
121 NULL
, /* DIF_RESERVED1 */
122 NULL
, /* DIF_TROUBLESHOOTER */
123 NULL
, /* DIF_POWERMESSAGEWAKE */
124 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
125 NULL
, /* DIF_UPDATEDRIVER_UI */
126 NULL
/* DIF_RESERVED2 */
129 /***********************************************************************
130 * SetupDiBuildClassInfoList (SETUPAPI.@)
132 BOOL WINAPI
SetupDiBuildClassInfoList(
134 LPGUID ClassGuidList
,
135 DWORD ClassGuidListSize
,
139 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
140 ClassGuidListSize
, RequiredSize
,
144 /***********************************************************************
145 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
147 BOOL WINAPI
SetupDiBuildClassInfoListExA(
149 LPGUID ClassGuidList
,
150 DWORD ClassGuidListSize
,
155 LPWSTR MachineNameW
= NULL
;
162 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
163 if (MachineNameW
== NULL
) return FALSE
;
166 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
167 ClassGuidListSize
, RequiredSize
,
168 MachineNameW
, Reserved
);
171 MyFree(MachineNameW
);
176 /***********************************************************************
177 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
179 BOOL WINAPI
SetupDiBuildClassInfoListExW(
181 LPGUID ClassGuidList
,
182 DWORD ClassGuidListSize
,
187 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
193 DWORD dwGuidListIndex
= 0;
195 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
196 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
198 if (RequiredSize
!= NULL
)
201 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
202 KEY_ENUMERATE_SUB_KEYS
,
206 if (hClassesKey
== INVALID_HANDLE_VALUE
)
211 for (dwIndex
= 0; ; dwIndex
++)
213 dwLength
= MAX_GUID_STRING_LEN
+ 1;
214 lError
= RegEnumKeyExW(hClassesKey
,
222 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
223 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
225 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
227 if (RegOpenKeyExW(hClassesKey
,
233 RegCloseKey(hClassesKey
);
237 if (!RegQueryValueExW(hClassKey
,
238 REGSTR_VAL_NOUSECLASS
,
244 TRACE("'NoUseClass' value found!\n");
245 RegCloseKey(hClassKey
);
249 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
250 (!RegQueryValueExW(hClassKey
,
251 REGSTR_VAL_NOINSTALLCLASS
,
257 TRACE("'NoInstallClass' value found!\n");
258 RegCloseKey(hClassKey
);
262 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
263 (!RegQueryValueExW(hClassKey
,
264 REGSTR_VAL_NODISPLAYCLASS
,
270 TRACE("'NoDisplayClass' value found!\n");
271 RegCloseKey(hClassKey
);
275 RegCloseKey(hClassKey
);
277 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
278 if (dwGuidListIndex
< ClassGuidListSize
)
280 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
284 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
286 UuidFromStringW(&szKeyName
[1],
287 &ClassGuidList
[dwGuidListIndex
]);
293 if (lError
!= ERROR_SUCCESS
)
297 RegCloseKey(hClassesKey
);
299 if (RequiredSize
!= NULL
)
300 *RequiredSize
= dwGuidListIndex
;
302 if (ClassGuidListSize
< dwGuidListIndex
)
304 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
311 /***********************************************************************
312 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
314 BOOL WINAPI
SetupDiClassGuidsFromNameA(
316 LPGUID ClassGuidList
,
317 DWORD ClassGuidListSize
,
320 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
321 ClassGuidListSize
, RequiredSize
,
325 /***********************************************************************
326 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
328 BOOL WINAPI
SetupDiClassGuidsFromNameW(
330 LPGUID ClassGuidList
,
331 DWORD ClassGuidListSize
,
334 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
335 ClassGuidListSize
, RequiredSize
,
339 /***********************************************************************
340 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
342 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
344 LPGUID ClassGuidList
,
345 DWORD ClassGuidListSize
,
350 LPWSTR ClassNameW
= NULL
;
351 LPWSTR MachineNameW
= NULL
;
356 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
357 if (ClassNameW
== NULL
)
362 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
363 if (MachineNameW
== NULL
)
370 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
371 ClassGuidListSize
, RequiredSize
,
372 MachineNameW
, Reserved
);
375 MyFree(MachineNameW
);
382 /***********************************************************************
383 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
385 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
387 LPGUID ClassGuidList
,
388 DWORD ClassGuidListSize
,
393 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
394 WCHAR szClassName
[256];
400 DWORD dwGuidListIndex
= 0;
402 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
403 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
405 if (RequiredSize
!= NULL
)
408 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
409 KEY_ENUMERATE_SUB_KEYS
,
413 if (hClassesKey
== INVALID_HANDLE_VALUE
)
418 for (dwIndex
= 0; ; dwIndex
++)
420 dwLength
= MAX_GUID_STRING_LEN
+ 1;
421 lError
= RegEnumKeyExW(hClassesKey
,
429 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
430 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
432 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
434 if (RegOpenKeyExW(hClassesKey
,
440 RegCloseKey(hClassesKey
);
444 dwLength
= 256 * sizeof(WCHAR
);
445 if (!RegQueryValueExW(hClassKey
,
452 TRACE("Class name: %s\n", debugstr_w(szClassName
));
454 if (strcmpiW(szClassName
, ClassName
) == 0)
456 TRACE("Found matching class name\n");
458 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
459 if (dwGuidListIndex
< ClassGuidListSize
)
461 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
465 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
467 UuidFromStringW(&szKeyName
[1],
468 &ClassGuidList
[dwGuidListIndex
]);
475 RegCloseKey(hClassKey
);
478 if (lError
!= ERROR_SUCCESS
)
482 RegCloseKey(hClassesKey
);
484 if (RequiredSize
!= NULL
)
485 *RequiredSize
= dwGuidListIndex
;
487 if (ClassGuidListSize
< dwGuidListIndex
)
489 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
496 /***********************************************************************
497 * SetupDiClassNameFromGuidA (SETUPAPI.@)
499 BOOL WINAPI
SetupDiClassNameFromGuidA(
500 const GUID
* ClassGuid
,
505 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
506 ClassNameSize
, RequiredSize
,
510 /***********************************************************************
511 * SetupDiClassNameFromGuidW (SETUPAPI.@)
513 BOOL WINAPI
SetupDiClassNameFromGuidW(
514 const GUID
* ClassGuid
,
519 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
520 ClassNameSize
, RequiredSize
,
524 /***********************************************************************
525 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
527 BOOL WINAPI
SetupDiClassNameFromGuidExA(
528 const GUID
* ClassGuid
,
535 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
536 LPWSTR MachineNameW
= NULL
;
540 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
541 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
542 NULL
, MachineNameW
, Reserved
);
545 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
546 ClassNameSize
, NULL
, NULL
);
548 if (!ClassNameSize
&& RequiredSize
)
551 MyFree(MachineNameW
);
555 /***********************************************************************
556 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
558 BOOL WINAPI
SetupDiClassNameFromGuidExW(
559 const GUID
* ClassGuid
,
570 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
571 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
573 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
578 if (hKey
== INVALID_HANDLE_VALUE
)
583 if (RequiredSize
!= NULL
)
586 rc
= RegQueryValueExW(hKey
,
592 if (rc
!= ERROR_SUCCESS
)
599 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
602 dwLength
= ClassNameSize
* sizeof(WCHAR
);
603 rc
= RegQueryValueExW(hKey
,
609 if (rc
!= ERROR_SUCCESS
)
621 /***********************************************************************
622 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
625 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
628 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
631 /***********************************************************************
632 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
635 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
640 LPWSTR MachineNameW
= NULL
;
643 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
644 debugstr_a(MachineName
), Reserved
);
648 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
649 if (MachineNameW
== NULL
)
650 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
653 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
654 MachineNameW
, Reserved
);
657 MyFree(MachineNameW
);
663 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
667 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
668 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
669 case CR_SUCCESS
: return ERROR_SUCCESS
;
672 return ERROR_GEN_FAILURE
;
675 /* Does not happen */
678 /***********************************************************************
679 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
682 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
687 struct DeviceInfoSet
*list
;
688 LPWSTR UNCServerName
= NULL
;
692 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
694 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
695 debugstr_w(MachineName
), Reserved
);
697 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
699 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
700 list
= HeapAlloc(GetProcessHeap(), 0, size
);
703 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
706 memset(list
, 0, sizeof(struct DeviceInfoSet
));
708 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
711 ClassGuid
? ClassGuid
: &GUID_NULL
,
712 sizeof(list
->ClassGuid
));
713 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
714 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
715 list
->InstallParams
.hwndParent
= hwndParent
;
718 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
719 if (rc
!= ERROR_SUCCESS
)
724 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
727 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
731 strcpyW(UNCServerName
+ 2, MachineName
);
732 list
->szData
[0] = list
->szData
[1] = '\\';
733 strcpyW(list
->szData
+ 2, MachineName
);
734 list
->MachineName
= list
->szData
;
738 DWORD Size
= MAX_PATH
;
739 list
->HKLM
= HKEY_LOCAL_MACHINE
;
740 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
743 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
746 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
748 list
->MachineName
= NULL
;
751 UNCServerName
[0] = UNCServerName
[1] = '\\';
752 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
753 if (cr
!= CR_SUCCESS
)
755 SetLastError(GetErrorCodeFromCrCode(cr
));
759 InitializeListHead(&list
->DriverListHead
);
760 InitializeListHead(&list
->ListHead
);
762 ret
= (HDEVINFO
)list
;
765 if (ret
== INVALID_HANDLE_VALUE
)
767 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
768 RegCloseKey(list
->HKLM
);
769 HeapFree(GetProcessHeap(), 0, list
);
771 HeapFree(GetProcessHeap(), 0, UNCServerName
);
775 /***********************************************************************
776 * SetupDiEnumDeviceInfo (SETUPAPI.@)
778 BOOL WINAPI
SetupDiEnumDeviceInfo(
779 HDEVINFO DeviceInfoSet
,
781 PSP_DEVINFO_DATA DeviceInfoData
)
785 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
787 SetLastError(ERROR_INVALID_PARAMETER
);
788 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
790 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
792 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
793 SetLastError(ERROR_INVALID_HANDLE
);
794 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
795 SetLastError(ERROR_INVALID_USER_BUFFER
);
798 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
799 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
800 ItemList
= ItemList
->Flink
;
801 if (ItemList
== &list
->ListHead
)
802 SetLastError(ERROR_NO_MORE_ITEMS
);
805 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
806 memcpy(&DeviceInfoData
->ClassGuid
,
809 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
810 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
816 SetLastError(ERROR_INVALID_HANDLE
);
820 /***********************************************************************
821 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
824 SetupDiGetActualSectionToInstallA(
826 IN PCSTR InfSectionName
,
827 OUT PSTR InfSectionWithExt OPTIONAL
,
828 IN DWORD InfSectionWithExtSize
,
829 OUT PDWORD RequiredSize OPTIONAL
,
830 OUT PSTR
*Extension OPTIONAL
)
832 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
833 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
837 /***********************************************************************
838 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
841 SetupDiGetActualSectionToInstallW(
843 IN PCWSTR InfSectionName
,
844 OUT PWSTR InfSectionWithExt OPTIONAL
,
845 IN DWORD InfSectionWithExtSize
,
846 OUT PDWORD RequiredSize OPTIONAL
,
847 OUT PWSTR
*Extension OPTIONAL
)
849 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
850 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
854 /***********************************************************************
855 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
858 SetupDiGetActualSectionToInstallExA(
860 IN PCSTR InfSectionName
,
861 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
862 OUT PSTR InfSectionWithExt OPTIONAL
,
863 IN DWORD InfSectionWithExtSize
,
864 OUT PDWORD RequiredSize OPTIONAL
,
865 OUT PSTR
* Extension OPTIONAL
,
868 LPWSTR InfSectionNameW
= NULL
;
869 LPWSTR InfSectionWithExtW
= NULL
;
871 BOOL bResult
= FALSE
;
877 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
878 if (InfSectionNameW
== NULL
)
881 if (InfSectionWithExt
)
883 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
884 if (InfSectionWithExtW
== NULL
)
888 bResult
= SetupDiGetActualSectionToInstallExW(
889 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
890 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
891 InfSectionWithExtSize
,
893 Extension
? &ExtensionW
: NULL
,
896 if (bResult
&& InfSectionWithExt
)
898 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
899 InfSectionWithExtSize
, NULL
, NULL
) != 0;
901 if (bResult
&& Extension
)
903 if (ExtensionW
== NULL
)
906 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
910 MyFree(InfSectionNameW
);
911 MyFree(InfSectionWithExtW
);
916 /***********************************************************************
917 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
920 SetupDiGetActualSectionToInstallExW(
922 IN PCWSTR InfSectionName
,
923 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
924 OUT PWSTR InfSectionWithExt OPTIONAL
,
925 IN DWORD InfSectionWithExtSize
,
926 OUT PDWORD RequiredSize OPTIONAL
,
927 OUT PWSTR
* Extension OPTIONAL
,
932 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
933 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
934 RequiredSize
, Extension
, Reserved
);
936 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
937 SetLastError(ERROR_INVALID_HANDLE
);
938 else if (!InfSectionName
)
939 SetLastError(ERROR_INVALID_PARAMETER
);
940 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
941 SetLastError(ERROR_INVALID_USER_BUFFER
);
942 else if (Reserved
!= NULL
)
943 SetLastError(ERROR_INVALID_PARAMETER
);
946 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
947 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
948 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
949 WCHAR SectionName
[LINE_LEN
+ 1];
950 LONG lLineCount
= -1;
953 /* Fill platform info if needed */
954 if (AlternatePlatformInfo
)
955 pPlatformInfo
= AlternatePlatformInfo
;
956 else if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
958 /* That's the first time we go here. We need to fill in the structure */
959 OSVERSIONINFO VersionInfo
;
960 SYSTEM_INFO SystemInfo
;
961 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
962 ret
= GetVersionEx(&VersionInfo
);
965 GetSystemInfo(&SystemInfo
);
966 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
967 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
968 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
969 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
970 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
971 CurrentPlatform
.Reserved
= 0;
974 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
975 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
976 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
978 static const WCHAR ExtensionArchitectureNone
[] = {0};
979 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
980 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
981 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
983 /* Set various extensions values */
984 switch (pPlatformInfo
->Platform
)
986 case VER_PLATFORM_WIN32_WINDOWS
:
987 pExtensionPlatform
= ExtensionPlatformWindows
;
989 case VER_PLATFORM_WIN32_NT
:
990 pExtensionPlatform
= ExtensionPlatformNT
;
993 pExtensionPlatform
= ExtensionPlatformNone
;
996 switch (pPlatformInfo
->ProcessorArchitecture
)
998 case PROCESSOR_ARCHITECTURE_AMD64
:
999 pExtensionArchitecture
= ExtensionArchitectureamd64
;
1001 case PROCESSOR_ARCHITECTURE_INTEL
:
1002 pExtensionArchitecture
= ExtensionArchitecturex86
;
1004 case PROCESSOR_ARCHITECTURE_PPC
:
1005 pExtensionArchitecture
= ExtensionArchitectureppc
;
1008 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo
->ProcessorArchitecture
);
1009 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
1010 pExtensionArchitecture
= ExtensionArchitectureNone
;
1014 SectionName
[LINE_LEN
] = UNICODE_NULL
;
1016 /* Test with platform.architecture.major.minor extension */
1017 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s.%lu.%lu", InfSectionName
,
1018 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1019 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1020 if (lLineCount
!= -1) goto sectionfound
;
1022 /* Test with platform.major.minor extension */
1023 snprintfW(SectionName
, LINE_LEN
, L
"%s%s.%lu.%lu", InfSectionName
,
1024 pExtensionPlatform
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1025 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1026 if (lLineCount
!= -1) goto sectionfound
;
1028 /* Test with platform.architecture.major extension */
1029 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s.%lu", InfSectionName
,
1030 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
);
1031 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1032 if (lLineCount
!= -1) goto sectionfound
;
1034 /* Test with platform.major extension */
1035 snprintfW(SectionName
, LINE_LEN
, L
"%s%s.%lu", InfSectionName
,
1036 pExtensionPlatform
, pPlatformInfo
->MajorVersion
);
1037 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1038 if (lLineCount
!= -1) goto sectionfound
;
1040 /* Test with platform.architecture extension */
1041 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s", InfSectionName
,
1042 pExtensionPlatform
, pExtensionArchitecture
);
1043 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1044 if (lLineCount
!= -1) goto sectionfound
;
1046 /* Test with platform extension */
1047 snprintfW(SectionName
, LINE_LEN
, L
"%s%s", InfSectionName
,
1048 pExtensionPlatform
);
1049 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1050 if (lLineCount
!= -1) goto sectionfound
;
1052 /* Test without extension */
1053 snprintfW(SectionName
, LINE_LEN
, L
"%s", InfSectionName
);
1054 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1055 if (lLineCount
!= -1) goto sectionfound
;
1057 /* No appropriate section found */
1058 SetLastError(ERROR_INVALID_PARAMETER
);
1062 dwFullLength
= lstrlenW(SectionName
);
1063 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
1065 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
1067 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1071 lstrcpyW(InfSectionWithExt
, SectionName
);
1072 if (Extension
!= NULL
)
1074 DWORD dwLength
= lstrlenW(SectionName
);
1075 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1079 if (RequiredSize
!= NULL
)
1080 *RequiredSize
= dwFullLength
+ 1;
1086 TRACE("Returning %d\n", ret
);
1091 /***********************************************************************
1092 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1094 BOOL WINAPI
SetupDiGetClassDescriptionA(
1095 const GUID
* ClassGuid
,
1096 PSTR ClassDescription
,
1097 DWORD ClassDescriptionSize
,
1098 PDWORD RequiredSize
)
1100 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1101 ClassDescriptionSize
,
1102 RequiredSize
, NULL
, NULL
);
1105 /***********************************************************************
1106 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1108 BOOL WINAPI
SetupDiGetClassDescriptionW(
1109 const GUID
* ClassGuid
,
1110 PWSTR ClassDescription
,
1111 DWORD ClassDescriptionSize
,
1112 PDWORD RequiredSize
)
1114 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1115 ClassDescriptionSize
,
1116 RequiredSize
, NULL
, NULL
);
1119 /***********************************************************************
1120 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1122 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1123 const GUID
* ClassGuid
,
1124 PSTR ClassDescription
,
1125 DWORD ClassDescriptionSize
,
1126 PDWORD RequiredSize
,
1130 PWCHAR ClassDescriptionW
;
1131 LPWSTR MachineNameW
= NULL
;
1135 if (ClassDescriptionSize
> 0)
1137 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1138 if (!ClassDescriptionW
)
1140 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1146 ClassDescriptionW
= NULL
;
1150 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1153 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1159 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1160 NULL
, MachineNameW
, Reserved
);
1163 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1164 ClassDescriptionSize
, NULL
, NULL
);
1166 if (!ClassDescriptionSize
&& RequiredSize
)
1167 *RequiredSize
= len
;
1171 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1172 MyFree(MachineNameW
);
1176 /***********************************************************************
1177 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1179 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1180 const GUID
* ClassGuid
,
1181 PWSTR ClassDescription
,
1182 DWORD ClassDescriptionSize
,
1183 PDWORD RequiredSize
,
1190 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1191 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1193 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1198 if (hKey
== INVALID_HANDLE_VALUE
)
1200 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1204 if (RequiredSize
!= NULL
)
1207 if (RegQueryValueExW(hKey
,
1218 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1221 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1222 if (RegQueryValueExW(hKey
,
1226 (LPBYTE
)ClassDescription
,
1238 /***********************************************************************
1239 * SetupDiGetClassDevsA (SETUPAPI.@)
1241 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1247 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1248 flags
, NULL
, NULL
, NULL
);
1251 /***********************************************************************
1252 * SetupDiGetClassDevsW (SETUPAPI.@)
1254 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1260 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1261 flags
, NULL
, NULL
, NULL
);
1264 /***********************************************************************
1265 * SetupDiGetClassDevsExA (SETUPAPI.@)
1267 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1277 LPWSTR enumstrW
= NULL
;
1278 LPWSTR machineW
= NULL
;
1282 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1283 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1286 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1289 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1293 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1294 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1297 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1300 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1302 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1305 HeapFree(GetProcessHeap(), 0, enumstrW
);
1306 HeapFree(GetProcessHeap(), 0, machineW
);
1311 CreateDeviceInfoElement(
1312 IN
struct DeviceInfoSet
*list
,
1313 IN LPCWSTR InstancePath
,
1314 IN LPCGUID pClassGuid
,
1315 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1319 struct DeviceInfoElement
*deviceInfo
;
1321 *pDeviceInfo
= NULL
;
1323 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1324 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1327 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1330 memset(deviceInfo
, 0, size
);
1332 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1333 if (cr
!= CR_SUCCESS
)
1335 SetLastError(GetErrorCodeFromCrCode(cr
));
1339 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1340 wcscpy(deviceInfo
->Data
, InstancePath
);
1341 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1342 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1343 deviceInfo
->DeviceDescription
= NULL
;
1344 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1345 deviceInfo
->CreationFlags
= 0;
1346 InitializeListHead(&deviceInfo
->DriverListHead
);
1347 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1349 *pDeviceInfo
= deviceInfo
;
1354 CreateDeviceInterface(
1355 IN
struct DeviceInfoElement
* deviceInfo
,
1356 IN LPCWSTR SymbolicLink
,
1357 IN LPCGUID pInterfaceGuid
,
1358 OUT
struct DeviceInterface
**pDeviceInterface
)
1360 struct DeviceInterface
*deviceInterface
;
1362 *pDeviceInterface
= NULL
;
1364 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1365 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1366 if (!deviceInterface
)
1368 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1371 deviceInterface
->DeviceInfo
= deviceInfo
;
1372 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1373 deviceInterface
->Flags
= 0; /* FIXME */
1374 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1376 *pDeviceInterface
= deviceInterface
;
1380 static LONG
SETUP_CreateDevListFromEnumerator(
1381 struct DeviceInfoSet
*list
,
1382 LPCGUID pClassGuid OPTIONAL
,
1384 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1386 HKEY hDeviceIdKey
, hInstanceIdKey
;
1387 WCHAR KeyBuffer
[MAX_PATH
];
1388 WCHAR InstancePath
[MAX_PATH
];
1389 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1390 struct DeviceInfoElement
*deviceInfo
;
1392 DWORD dwLength
, dwRegType
;
1395 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1398 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1399 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1400 if (rc
== ERROR_NO_MORE_ITEMS
)
1402 if (rc
!= ERROR_SUCCESS
)
1406 /* Open device id sub key */
1407 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1408 if (rc
!= ERROR_SUCCESS
)
1410 wcscpy(InstancePath
, Enumerator
);
1411 wcscat(InstancePath
, L
"\\");
1412 wcscat(InstancePath
, KeyBuffer
);
1413 wcscat(InstancePath
, L
"\\");
1414 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1416 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1422 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1423 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1424 if (rc
== ERROR_NO_MORE_ITEMS
)
1426 if (rc
!= ERROR_SUCCESS
)
1428 RegCloseKey(hDeviceIdKey
);
1433 /* Open instance id sub key */
1434 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1435 if (rc
!= ERROR_SUCCESS
)
1437 RegCloseKey(hDeviceIdKey
);
1440 *pEndOfInstancePath
= '\0';
1441 wcscat(InstancePath
, KeyBuffer
);
1443 /* Read ClassGUID value */
1444 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1445 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1446 RegCloseKey(hInstanceIdKey
);
1447 if (rc
== ERROR_FILE_NOT_FOUND
)
1450 /* Skip this bad entry as we can't verify it */
1452 /* Set a default GUID for this device */
1453 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1455 else if (rc
!= ERROR_SUCCESS
)
1457 RegCloseKey(hDeviceIdKey
);
1460 else if (dwRegType
!= REG_SZ
)
1462 RegCloseKey(hDeviceIdKey
);
1463 return ERROR_GEN_FAILURE
;
1467 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1468 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1469 /* Bad GUID, skip the entry */
1473 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1475 /* Skip this entry as it is not the right device class */
1479 /* Add the entry to the list */
1480 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1482 RegCloseKey(hDeviceIdKey
);
1483 return GetLastError();
1485 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1486 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1488 RegCloseKey(hDeviceIdKey
);
1491 return ERROR_SUCCESS
;
1494 static LONG
SETUP_CreateDevList(
1495 struct DeviceInfoSet
*list
,
1496 PCWSTR MachineName OPTIONAL
,
1497 LPGUID
class OPTIONAL
,
1498 PCWSTR Enumerator OPTIONAL
)
1500 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1501 WCHAR KeyBuffer
[MAX_PATH
];
1506 if (class && IsEqualIID(class, &GUID_NULL
))
1510 if (MachineName
!= NULL
)
1512 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1513 if (rc
!= ERROR_SUCCESS
)
1517 HKLM
= HKEY_LOCAL_MACHINE
;
1519 rc
= RegOpenKeyExW(HKLM
,
1520 REGSTR_PATH_SYSTEMENUM
,
1522 KEY_ENUMERATE_SUB_KEYS
,
1524 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1525 if (rc
!= ERROR_SUCCESS
)
1528 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1529 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1538 KEY_ENUMERATE_SUB_KEYS
,
1540 RegCloseKey(hEnumKey
);
1541 if (rc
!= ERROR_SUCCESS
)
1543 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1544 RegCloseKey(hEnumeratorKey
);
1549 /* Enumerate enumerators */
1553 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1554 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1555 if (rc
== ERROR_NO_MORE_ITEMS
)
1557 if (rc
!= ERROR_SUCCESS
)
1559 RegCloseKey(hEnumKey
);
1565 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1566 if (rc
!= ERROR_SUCCESS
)
1568 RegCloseKey(hEnumKey
);
1572 /* Call SETUP_CreateDevListFromEnumerator */
1573 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1574 RegCloseKey(hEnumeratorKey
);
1575 if (rc
!= ERROR_SUCCESS
)
1577 RegCloseKey(hEnumKey
);
1581 RegCloseKey(hEnumKey
);
1582 return ERROR_SUCCESS
;
1587 static LONG
SETUP_CreateSerialDeviceList(
1588 struct DeviceInfoSet
*list
,
1590 LPGUID InterfaceGuid
,
1591 PCWSTR DeviceInstanceW
)
1593 static const size_t initialSize
= 100;
1595 WCHAR buf
[initialSize
];
1597 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1599 struct DeviceInfoElement
*deviceInfo
;
1602 WARN("'MachineName' is ignored on Wine!\n");
1603 if (DeviceInstanceW
)
1604 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1610 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1612 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1616 HeapFree(GetProcessHeap(), 0, devices
);
1617 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1619 return ERROR_NOT_ENOUGH_MEMORY
;
1625 HeapFree(GetProcessHeap(), 0, devices
);
1626 return GetLastError();
1630 /* 'devices' is a MULTI_SZ string */
1631 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1633 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1635 /* We have found a device */
1636 struct DeviceInterface
*interfaceInfo
;
1637 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1638 /* Step 1. Create a device info element */
1639 if (!CreateDeviceInfoElement(list
, ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1642 HeapFree(GetProcessHeap(), 0, devices
);
1643 return GetLastError();
1645 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1647 /* Step 2. Create an interface list for this element */
1648 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1651 HeapFree(GetProcessHeap(), 0, devices
);
1652 return GetLastError();
1654 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1658 HeapFree(GetProcessHeap(), 0, devices
);
1659 return ERROR_SUCCESS
;
1662 #else /* __REACTOS__ */
1664 static LONG
SETUP_CreateInterfaceList(
1665 struct DeviceInfoSet
*list
,
1667 LPGUID InterfaceGuid
,
1668 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1670 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1671 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1672 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1673 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1674 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1676 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1679 DWORD dwLength
, dwInstancePathLength
;
1682 struct DeviceInfoElement
*deviceInfo
;
1684 /* Open registry key related to this interface */
1685 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1686 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1687 return GetLastError();
1689 /* Enumerate sub keys of hInterfaceKey */
1693 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1694 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1695 if (rc
== ERROR_NO_MORE_ITEMS
)
1697 if (rc
!= ERROR_SUCCESS
)
1699 RegCloseKey(hInterfaceKey
);
1705 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1706 if (rc
!= ERROR_SUCCESS
)
1708 RegCloseKey(hInterfaceKey
);
1712 /* Read DeviceInstance */
1713 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1714 if (rc
!= ERROR_SUCCESS
)
1716 RegCloseKey(hDeviceInstanceKey
);
1717 RegCloseKey(hInterfaceKey
);
1720 if (dwRegType
!= REG_SZ
)
1722 RegCloseKey(hDeviceInstanceKey
);
1723 RegCloseKey(hInterfaceKey
);
1724 return ERROR_GEN_FAILURE
;
1726 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1729 RegCloseKey(hDeviceInstanceKey
);
1730 RegCloseKey(hInterfaceKey
);
1731 return ERROR_NOT_ENOUGH_MEMORY
;
1733 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1734 if (rc
!= ERROR_SUCCESS
)
1736 HeapFree(GetProcessHeap(), 0, InstancePath
);
1737 RegCloseKey(hDeviceInstanceKey
);
1738 RegCloseKey(hInterfaceKey
);
1741 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1742 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1744 if (DeviceInstanceW
)
1746 /* Check if device enumerator is not the right one */
1747 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1749 HeapFree(GetProcessHeap(), 0, InstancePath
);
1750 RegCloseKey(hDeviceInstanceKey
);
1755 /* Find class GUID associated to the device instance */
1758 REGSTR_PATH_SYSTEMENUM
,
1762 if (rc
!= ERROR_SUCCESS
)
1764 HeapFree(GetProcessHeap(), 0, InstancePath
);
1765 RegCloseKey(hDeviceInstanceKey
);
1766 RegCloseKey(hInterfaceKey
);
1775 RegCloseKey(hEnumKey
);
1776 if (rc
!= ERROR_SUCCESS
)
1778 HeapFree(GetProcessHeap(), 0, InstancePath
);
1779 RegCloseKey(hDeviceInstanceKey
);
1780 RegCloseKey(hInterfaceKey
);
1783 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1784 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1786 if (rc
!= ERROR_SUCCESS
)
1788 HeapFree(GetProcessHeap(), 0, InstancePath
);
1789 RegCloseKey(hDeviceInstanceKey
);
1790 RegCloseKey(hInterfaceKey
);
1793 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1794 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1795 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1797 HeapFree(GetProcessHeap(), 0, InstancePath
);
1798 RegCloseKey(hDeviceInstanceKey
);
1799 RegCloseKey(hInterfaceKey
);
1800 return ERROR_GEN_FAILURE
;
1802 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1804 /* If current device doesn't match the list GUID (if any), skip this entry */
1805 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1807 HeapFree(GetProcessHeap(), 0, InstancePath
);
1808 RegCloseKey(hDeviceInstanceKey
);
1812 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1816 LPWSTR pSymbolicLink
;
1817 struct DeviceInterface
*interfaceInfo
;
1819 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1820 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1821 if (rc
== ERROR_NO_MORE_ITEMS
)
1823 if (rc
!= ERROR_SUCCESS
)
1825 HeapFree(GetProcessHeap(), 0, InstancePath
);
1826 RegCloseKey(hDeviceInstanceKey
);
1827 RegCloseKey(hInterfaceKey
);
1831 if (KeyBuffer
[0] != '#')
1832 /* This entry doesn't represent an interesting entry */
1836 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1837 if (rc
!= ERROR_SUCCESS
)
1839 RegCloseKey(hDeviceInstanceKey
);
1840 RegCloseKey(hInterfaceKey
);
1844 /* Read SymbolicLink value */
1845 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1846 if (rc
!= ERROR_SUCCESS
)
1848 RegCloseKey(hReferenceKey
);
1849 RegCloseKey(hDeviceInstanceKey
);
1850 RegCloseKey(hInterfaceKey
);
1853 if (dwRegType
!= REG_SZ
)
1855 RegCloseKey(hReferenceKey
);
1856 RegCloseKey(hDeviceInstanceKey
);
1857 RegCloseKey(hInterfaceKey
);
1858 return ERROR_GEN_FAILURE
;
1861 /* We have found a device */
1862 /* Step 1. Create a device info element */
1863 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1865 RegCloseKey(hReferenceKey
);
1866 RegCloseKey(hDeviceInstanceKey
);
1867 RegCloseKey(hInterfaceKey
);
1868 return GetLastError();
1870 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1871 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1873 /* Step 2. Create an interface list for this element */
1874 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1877 RegCloseKey(hReferenceKey
);
1878 RegCloseKey(hDeviceInstanceKey
);
1879 RegCloseKey(hInterfaceKey
);
1880 return ERROR_NOT_ENOUGH_MEMORY
;
1882 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1883 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1884 RegCloseKey(hReferenceKey
);
1885 if (rc
!= ERROR_SUCCESS
)
1887 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1888 RegCloseKey(hDeviceInstanceKey
);
1889 RegCloseKey(hInterfaceKey
);
1892 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1894 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1895 RegCloseKey(hDeviceInstanceKey
);
1896 RegCloseKey(hInterfaceKey
);
1897 return GetLastError();
1899 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1900 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1901 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1903 RegCloseKey(hDeviceInstanceKey
);
1905 RegCloseKey(hInterfaceKey
);
1906 return ERROR_SUCCESS
;
1908 #endif /* __REACTOS__ */
1910 /***********************************************************************
1911 * SetupDiGetClassDevsExW (SETUPAPI.@)
1913 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1922 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1923 struct DeviceInfoSet
*list
;
1927 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1928 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1930 /* Create the deviceset if not set */
1933 list
= (struct DeviceInfoSet
*)deviceset
;
1934 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1936 SetLastError(ERROR_INVALID_HANDLE
);
1937 return INVALID_HANDLE_VALUE
;
1939 hDeviceInfo
= deviceset
;
1943 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1944 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1945 NULL
, machine
, NULL
);
1946 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1947 return INVALID_HANDLE_VALUE
;
1948 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1951 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1954 pClassGuid
= &list
->ClassGuid
;
1956 if (flags
& DIGCF_PRESENT
)
1957 FIXME(": flag DIGCF_PRESENT ignored\n");
1958 if (flags
& DIGCF_PROFILE
)
1959 FIXME(": flag DIGCF_PROFILE ignored\n");
1961 if (flags
& DIGCF_ALLCLASSES
)
1963 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1964 if (rc
!= ERROR_SUCCESS
)
1968 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1969 return INVALID_HANDLE_VALUE
;
1973 else if (flags
& DIGCF_DEVICEINTERFACE
)
1977 SetLastError(ERROR_INVALID_PARAMETER
);
1979 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1980 return INVALID_HANDLE_VALUE
;
1984 /* Special case: find serial ports by calling QueryDosDevice */
1985 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1986 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1987 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1988 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1991 ERR("Wine can only enumerate serial devices at the moment!\n");
1992 rc
= ERROR_INVALID_PARAMETER
;
1994 #else /* __REACTOS__ */
1995 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1996 #endif /* __REACTOS__ */
1997 if (rc
!= ERROR_SUCCESS
)
2001 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2002 return INVALID_HANDLE_VALUE
;
2008 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
2009 if (rc
!= ERROR_SUCCESS
)
2013 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2014 return INVALID_HANDLE_VALUE
;
2020 /***********************************************************************
2021 * SetupDiGetClassImageIndex (SETUPAPI.@)
2024 static BOOL
GetIconIndex(
2026 OUT PINT ImageIndex
)
2028 LPWSTR Buffer
= NULL
;
2029 DWORD dwRegType
, dwLength
;
2033 /* Read icon registry key */
2034 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
2035 if (rc
!= ERROR_SUCCESS
)
2039 } else if (dwRegType
!= REG_SZ
)
2041 SetLastError(ERROR_INVALID_INDEX
);
2044 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2047 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2050 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2051 if (rc
!= ERROR_SUCCESS
)
2056 /* make sure the returned buffer is NULL-terminated */
2057 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2059 /* Transform icon value to a INT */
2060 *ImageIndex
= atoiW(Buffer
);
2068 BOOL WINAPI
SetupDiGetClassImageIndex(
2069 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2070 IN CONST GUID
*ClassGuid
,
2071 OUT PINT ImageIndex
)
2073 struct ClassImageList
*list
;
2076 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2078 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2079 SetLastError(ERROR_INVALID_PARAMETER
);
2080 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2081 SetLastError(ERROR_INVALID_USER_BUFFER
);
2082 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2083 SetLastError(ERROR_INVALID_USER_BUFFER
);
2084 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2085 SetLastError(ERROR_INVALID_USER_BUFFER
);
2086 else if (!ImageIndex
)
2087 SetLastError(ERROR_INVALID_PARAMETER
);
2090 HKEY hKey
= INVALID_HANDLE_VALUE
;
2093 /* Read Icon registry entry into Buffer */
2094 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2095 if (hKey
== INVALID_HANDLE_VALUE
)
2097 if (!GetIconIndex(hKey
, &iconIndex
))
2102 SetLastError(ERROR_INVALID_INDEX
);
2106 *ImageIndex
= -iconIndex
;
2110 if (hKey
!= INVALID_HANDLE_VALUE
)
2114 TRACE("Returning %d\n", ret
);
2118 /***********************************************************************
2119 * SetupDiGetClassImageList(SETUPAPI.@)
2121 BOOL WINAPI
SetupDiGetClassImageList(
2122 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2124 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2127 /***********************************************************************
2128 * SetupDiGetClassImageListExA(SETUPAPI.@)
2130 BOOL WINAPI
SetupDiGetClassImageListExA(
2131 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2132 IN PCSTR MachineName OPTIONAL
,
2135 PWSTR MachineNameW
= NULL
;
2140 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2141 if (MachineNameW
== NULL
)
2145 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2148 MyFree(MachineNameW
);
2153 /***********************************************************************
2154 * SetupDiGetClassImageListExW(SETUPAPI.@)
2156 BOOL WINAPI
SetupDiGetClassImageListExW(
2157 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2158 IN PCWSTR MachineName OPTIONAL
,
2163 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2165 if (!ClassImageListData
)
2166 SetLastError(ERROR_INVALID_PARAMETER
);
2167 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2168 SetLastError(ERROR_INVALID_USER_BUFFER
);
2170 SetLastError(ERROR_INVALID_PARAMETER
);
2173 struct ClassImageList
*list
= NULL
;
2176 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2178 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
2179 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2182 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2185 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2188 list
->szData
[0] = list
->szData
[1] = '\\';
2189 strcpyW(list
->szData
+ 2, MachineName
);
2190 list
->MachineName
= list
->szData
;
2194 list
->MachineName
= NULL
;
2197 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2205 TRACE("Returning %d\n", ret
);
2209 /***********************************************************************
2210 * SetupDiLoadClassIcon(SETUPAPI.@)
2212 BOOL WINAPI
SetupDiLoadClassIcon(
2213 IN CONST GUID
*ClassGuid
,
2214 OUT HICON
*LargeIcon OPTIONAL
,
2215 OUT PINT MiniIconIndex OPTIONAL
)
2220 SetLastError(ERROR_INVALID_PARAMETER
);
2223 LPWSTR Buffer
= NULL
;
2226 HKEY hKey
= INVALID_HANDLE_VALUE
;
2228 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2229 if (hKey
== INVALID_HANDLE_VALUE
)
2232 if (!GetIconIndex(hKey
, &iconIndex
))
2237 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2240 DWORD dwRegType
, dwLength
;
2241 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2242 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2244 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2247 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2250 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2251 if (rc
!= ERROR_SUCCESS
)
2256 /* make sure the returned buffer is NULL-terminated */
2257 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2260 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2261 && dwRegType
== REG_SZ
)
2263 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2266 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2269 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2270 if (rc
!= ERROR_SUCCESS
)
2275 /* make sure the returned buffer is NULL-terminated */
2276 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2280 /* Unable to find where to load the icon */
2281 SetLastError(ERROR_FILE_NOT_FOUND
);
2284 Comma
= strchrW(Buffer
, ',');
2287 SetLastError(ERROR_GEN_FAILURE
);
2295 /* Look up icon in setupapi.dll */
2296 DllName
= L
"setupapi.dll";
2297 iconIndex
= -iconIndex
;
2300 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2303 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2305 SetLastError(ERROR_INVALID_INDEX
);
2310 *MiniIconIndex
= iconIndex
;
2314 if (hKey
!= INVALID_HANDLE_VALUE
)
2319 TRACE("Returning %d\n", ret
);
2323 /***********************************************************************
2324 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2326 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2327 HDEVINFO DeviceInfoSet
,
2328 PSP_DEVINFO_DATA DeviceInfoData
,
2329 CONST GUID
* InterfaceClassGuid
,
2331 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2335 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2336 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2338 if (!DeviceInterfaceData
)
2339 SetLastError(ERROR_INVALID_PARAMETER
);
2340 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2341 SetLastError(ERROR_INVALID_USER_BUFFER
);
2342 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2344 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2346 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2348 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2350 while (ItemList
!= &list
->ListHead
&& !Found
)
2352 PLIST_ENTRY InterfaceListEntry
;
2353 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2354 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2356 /* We are not searching for this element */
2357 ItemList
= ItemList
->Flink
;
2360 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2361 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2363 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2364 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2366 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2369 if (MemberIndex
-- == 0)
2371 /* return this item */
2372 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2373 &DevItf
->InterfaceClassGuid
,
2375 DeviceInterfaceData
->Flags
= 0; /* FIXME */
2376 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2379 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2381 ItemList
= ItemList
->Flink
;
2384 SetLastError(ERROR_NO_MORE_ITEMS
);
2389 SetLastError(ERROR_INVALID_HANDLE
);
2392 SetLastError(ERROR_INVALID_HANDLE
);
2396 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2398 InterlockedIncrement(&infFile
->References
);
2401 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2403 if (InterlockedDecrement(&infFile
->References
) == 0)
2405 SetupCloseInfFile(infFile
->hInf
);
2406 HeapFree(GetProcessHeap(), 0, infFile
);
2410 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2412 DereferenceInfFile(driverInfo
->InfFileDetails
);
2413 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2414 HeapFree(GetProcessHeap(), 0, driverInfo
);
2418 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2420 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2424 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2426 PLIST_ENTRY ListEntry
;
2427 struct DriverInfoElement
*driverInfo
;
2429 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2431 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2432 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2433 if (!DestroyDriverInfoElement(driverInfo
))
2436 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2438 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2439 HeapFree(GetProcessHeap(), 0, ListEntry
);
2441 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2442 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2446 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2448 PLIST_ENTRY ListEntry
;
2449 struct DeviceInfoElement
*deviceInfo
;
2451 while (!IsListEmpty(&list
->ListHead
))
2453 ListEntry
= RemoveHeadList(&list
->ListHead
);
2454 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2455 if (!DestroyDeviceInfoElement(deviceInfo
))
2458 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2459 RegCloseKey(list
->HKLM
);
2460 CM_Disconnect_Machine(list
->hMachine
);
2461 DestroyClassInstallParams(&list
->ClassInstallParams
);
2462 HeapFree(GetProcessHeap(), 0, list
);
2466 /***********************************************************************
2467 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2469 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2473 TRACE("%p\n", devinfo
);
2474 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2476 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2478 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2479 ret
= DestroyDeviceInfoSet(list
);
2481 SetLastError(ERROR_INVALID_HANDLE
);
2484 SetLastError(ERROR_INVALID_HANDLE
);
2486 TRACE("Returning %d\n", ret
);
2490 /***********************************************************************
2491 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2493 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2494 HDEVINFO DeviceInfoSet
,
2495 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2496 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2497 DWORD DeviceInterfaceDetailDataSize
,
2498 PDWORD RequiredSize
,
2499 PSP_DEVINFO_DATA DeviceInfoData
)
2501 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2502 DWORD sizeW
= 0, sizeA
;
2505 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2506 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2507 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2509 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2510 SetLastError(ERROR_INVALID_USER_BUFFER
);
2511 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2512 SetLastError(ERROR_INVALID_PARAMETER
);
2513 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2514 SetLastError(ERROR_INVALID_PARAMETER
);
2517 if (DeviceInterfaceDetailData
!= NULL
)
2519 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2520 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2521 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2522 if (!DeviceInterfaceDetailDataW
)
2524 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2527 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2529 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2530 ret
= SetupDiGetDeviceInterfaceDetailW(
2532 DeviceInterfaceData
,
2533 DeviceInterfaceDetailDataW
,
2537 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2538 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2540 *RequiredSize
= sizeA
;
2541 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2543 if (!WideCharToMultiByte(
2545 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2546 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2553 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2556 TRACE("Returning %d\n", ret
);
2560 /***********************************************************************
2561 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2563 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2564 HDEVINFO DeviceInfoSet
,
2565 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2566 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2567 DWORD DeviceInterfaceDetailDataSize
,
2568 PDWORD RequiredSize
,
2569 PSP_DEVINFO_DATA DeviceInfoData
)
2573 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2574 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2575 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2577 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2578 SetLastError(ERROR_INVALID_PARAMETER
);
2579 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2580 SetLastError(ERROR_INVALID_HANDLE
);
2581 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2582 SetLastError(ERROR_INVALID_HANDLE
);
2583 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2584 SetLastError(ERROR_INVALID_USER_BUFFER
);
2585 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2586 SetLastError(ERROR_INVALID_USER_BUFFER
);
2587 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2588 SetLastError(ERROR_INVALID_USER_BUFFER
);
2589 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2590 SetLastError(ERROR_INVALID_PARAMETER
);
2591 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2592 SetLastError(ERROR_INVALID_PARAMETER
);
2595 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2596 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2597 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2598 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2600 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2602 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2604 *RequiredSize
= sizeRequired
;
2608 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2609 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2612 memcpy(&DeviceInfoData
->ClassGuid
,
2613 &deviceInterface
->DeviceInfo
->ClassGuid
,
2615 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2616 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2622 TRACE("Returning %d\n", ret
);
2626 /***********************************************************************
2627 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2629 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2631 PSP_DEVINFO_DATA DeviceInfoData
,
2633 PDWORD PropertyRegDataType
,
2634 PBYTE PropertyBuffer
,
2635 DWORD PropertyBufferSize
,
2636 PDWORD RequiredSize
)
2639 BOOL bIsStringProperty
;
2641 DWORD RequiredSizeA
, RequiredSizeW
;
2642 DWORD PropertyBufferSizeW
;
2643 PBYTE PropertyBufferW
;
2645 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2646 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2649 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2650 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2652 bResult
= SetupDiGetDeviceRegistryPropertyW(
2658 PropertyBufferSizeW
,
2661 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2663 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2665 if (bIsStringProperty
)
2666 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2668 RequiredSizeA
= RequiredSizeW
;
2670 *RequiredSize
= RequiredSizeA
;
2671 if (PropertyRegDataType
)
2672 *PropertyRegDataType
= RegType
;
2677 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2681 if (RequiredSizeA
<= PropertyBufferSize
)
2683 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2685 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2687 /* Last error is already set by WideCharToMultiByte */
2692 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2696 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2700 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2704 /***********************************************************************
2705 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2707 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2708 HDEVINFO DeviceInfoSet
,
2709 PSP_DEVINFO_DATA DeviceInfoData
,
2711 PDWORD PropertyRegDataType
,
2712 PBYTE PropertyBuffer
,
2713 DWORD PropertyBufferSize
,
2714 PDWORD RequiredSize
)
2716 HKEY hEnumKey
, hKey
;
2720 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2721 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2724 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2725 SetLastError(ERROR_INVALID_HANDLE
);
2726 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2727 SetLastError(ERROR_INVALID_HANDLE
);
2728 else if (!DeviceInfoData
)
2729 SetLastError(ERROR_INVALID_PARAMETER
);
2730 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2731 SetLastError(ERROR_INVALID_USER_BUFFER
);
2732 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2733 SetLastError(ERROR_INVALID_PARAMETER
);
2736 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2737 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2741 case SPDRP_CAPABILITIES
:
2743 case SPDRP_CLASSGUID
:
2744 case SPDRP_COMPATIBLEIDS
:
2745 case SPDRP_CONFIGFLAGS
:
2746 case SPDRP_DEVICEDESC
:
2748 case SPDRP_FRIENDLYNAME
:
2749 case SPDRP_HARDWAREID
:
2750 case SPDRP_LOCATION_INFORMATION
:
2751 case SPDRP_LOWERFILTERS
:
2753 case SPDRP_SECURITY
:
2755 case SPDRP_UI_NUMBER
:
2756 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2757 case SPDRP_UPPERFILTERS
:
2759 LPCWSTR RegistryPropertyName
;
2764 case SPDRP_CAPABILITIES
:
2765 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2767 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2768 case SPDRP_CLASSGUID
:
2769 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2770 case SPDRP_COMPATIBLEIDS
:
2771 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2772 case SPDRP_CONFIGFLAGS
:
2773 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2774 case SPDRP_DEVICEDESC
:
2775 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2777 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2778 case SPDRP_FRIENDLYNAME
:
2779 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2780 case SPDRP_HARDWAREID
:
2781 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2782 case SPDRP_LOCATION_INFORMATION
:
2783 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2784 case SPDRP_LOWERFILTERS
:
2785 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2787 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2788 case SPDRP_SECURITY
:
2789 RegistryPropertyName
= L
"Security"; break;
2791 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2792 case SPDRP_UI_NUMBER
:
2793 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2794 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2795 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2796 case SPDRP_UPPERFILTERS
:
2797 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2799 /* Should not happen */
2800 RegistryPropertyName
= NULL
; break;
2803 /* Open registry key name */
2806 REGSTR_PATH_SYSTEMENUM
,
2810 if (rc
!= ERROR_SUCCESS
)
2821 RegCloseKey(hEnumKey
);
2822 if (rc
!= ERROR_SUCCESS
)
2827 /* Read registry entry */
2828 BufferSize
= PropertyBufferSize
;
2829 rc
= RegQueryValueExW(
2831 RegistryPropertyName
,
2832 NULL
, /* Reserved */
2833 PropertyRegDataType
,
2837 *RequiredSize
= BufferSize
;
2840 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2843 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2845 case ERROR_MORE_DATA
:
2846 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2855 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2857 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2859 if (PropertyRegDataType
)
2860 *PropertyRegDataType
= REG_SZ
;
2862 *RequiredSize
= required
;
2863 if (PropertyBufferSize
>= required
)
2865 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2869 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2873 /*case SPDRP_BUSTYPEGUID:
2874 case SPDRP_LEGACYBUSTYPE:
2875 case SPDRP_BUSNUMBER:
2876 case SPDRP_ENUMERATOR_NAME:
2877 case SPDRP_SECURITY_SDS:
2879 case SPDRP_EXCLUSIVE:
2880 case SPDRP_CHARACTERISTICS:
2882 case SPDRP_DEVICE_POWER_DATA:*/
2883 #if (WINVER >= 0x501)
2884 /*case SPDRP_REMOVAL_POLICY:
2885 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2886 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2887 case SPDRP_INSTALL_STATE:*/
2892 ERR("Property 0x%lx not implemented\n", Property
);
2893 SetLastError(ERROR_NOT_SUPPORTED
);
2898 TRACE("Returning %d\n", ret
);
2902 /***********************************************************************
2903 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2905 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2906 IN HDEVINFO DeviceInfoSet
,
2907 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2909 IN CONST BYTE
*PropertyBuffer
,
2910 IN DWORD PropertyBufferSize
)
2912 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2913 Property
, PropertyBuffer
, PropertyBufferSize
);
2914 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2918 /***********************************************************************
2919 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2921 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2922 IN HDEVINFO DeviceInfoSet
,
2923 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2925 IN
const BYTE
*PropertyBuffer
,
2926 IN DWORD PropertyBufferSize
)
2928 struct DeviceInfoSet
*list
;
2931 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2932 Property
, PropertyBuffer
, PropertyBufferSize
);
2935 SetLastError(ERROR_INVALID_HANDLE
);
2936 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2937 SetLastError(ERROR_INVALID_HANDLE
);
2938 else if (!DeviceInfoData
)
2939 SetLastError(ERROR_INVALID_HANDLE
);
2940 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2941 SetLastError(ERROR_INVALID_USER_BUFFER
);
2946 case SPDRP_COMPATIBLEIDS
:
2947 case SPDRP_CONFIGFLAGS
:
2948 case SPDRP_FRIENDLYNAME
:
2949 case SPDRP_HARDWAREID
:
2950 case SPDRP_LOCATION_INFORMATION
:
2951 case SPDRP_LOWERFILTERS
:
2952 case SPDRP_SECURITY
:
2954 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2955 case SPDRP_UPPERFILTERS
:
2957 LPCWSTR RegistryPropertyName
;
2958 DWORD RegistryDataType
;
2964 case SPDRP_COMPATIBLEIDS
:
2965 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2966 RegistryDataType
= REG_MULTI_SZ
;
2968 case SPDRP_CONFIGFLAGS
:
2969 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2970 RegistryDataType
= REG_DWORD
;
2972 case SPDRP_FRIENDLYNAME
:
2973 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2974 RegistryDataType
= REG_SZ
;
2976 case SPDRP_HARDWAREID
:
2977 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2978 RegistryDataType
= REG_MULTI_SZ
;
2980 case SPDRP_LOCATION_INFORMATION
:
2981 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2982 RegistryDataType
= REG_SZ
;
2984 case SPDRP_LOWERFILTERS
:
2985 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2986 RegistryDataType
= REG_MULTI_SZ
;
2988 case SPDRP_SECURITY
:
2989 RegistryPropertyName
= L
"Security";
2990 RegistryDataType
= REG_BINARY
;
2993 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2994 RegistryDataType
= REG_SZ
;
2996 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2997 RegistryPropertyName
= L
"UINumberDescFormat";
2998 RegistryDataType
= REG_SZ
;
3000 case SPDRP_UPPERFILTERS
:
3001 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
3002 RegistryDataType
= REG_MULTI_SZ
;
3005 /* Should not happen */
3006 RegistryPropertyName
= NULL
;
3007 RegistryDataType
= REG_BINARY
;
3010 /* Open device registry key */
3011 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3012 if (hKey
!= INVALID_HANDLE_VALUE
)
3014 /* Write new data */
3015 rc
= RegSetValueExW(
3017 RegistryPropertyName
,
3021 PropertyBufferSize
);
3022 if (rc
== ERROR_SUCCESS
)
3031 /*case SPDRP_CHARACTERISTICS:
3033 case SPDRP_EXCLUSIVE:*/
3034 #if (WINVER >= 0x501)
3035 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
3037 //case SPDRP_SECURITY_SDS:
3041 ERR("Property 0x%lx not implemented\n", Property
);
3042 SetLastError(ERROR_NOT_SUPPORTED
);
3047 TRACE("Returning %d\n", ret
);
3052 /***********************************************************************
3053 * SetupDiInstallClassA (SETUPAPI.@)
3055 BOOL WINAPI
SetupDiInstallClassA(
3056 IN HWND hwndParent OPTIONAL
,
3057 IN PCSTR InfFileName
,
3059 IN HSPFILEQ FileQueue OPTIONAL
)
3061 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3065 /***********************************************************************
3066 * SetupDiInstallClassW (SETUPAPI.@)
3068 BOOL WINAPI
SetupDiInstallClassW(
3069 IN HWND hwndParent OPTIONAL
,
3070 IN PCWSTR InfFileName
,
3072 IN HSPFILEQ FileQueue OPTIONAL
)
3074 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3078 /***********************************************************************
3079 * SetupDiInstallClassExA (SETUPAPI.@)
3081 BOOL WINAPI
SetupDiInstallClassExA(
3082 IN HWND hwndParent OPTIONAL
,
3083 IN PCSTR InfFileName OPTIONAL
,
3085 IN HSPFILEQ FileQueue OPTIONAL
,
3086 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3090 PWSTR InfFileNameW
= NULL
;
3095 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3096 if (InfFileNameW
== NULL
)
3098 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3103 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3104 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3106 MyFree(InfFileNameW
);
3112 static HKEY
CreateClassKey(HINF hInf
)
3114 WCHAR FullBuffer
[MAX_PATH
];
3115 WCHAR Buffer
[MAX_PATH
];
3120 if (!SetupGetLineTextW(NULL
,
3128 return INVALID_HANDLE_VALUE
;
3131 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3132 lstrcatW(FullBuffer
, Buffer
);
3135 if (!SetupGetLineTextW(NULL
,
3143 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3144 return INVALID_HANDLE_VALUE
;
3147 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3151 REG_OPTION_NON_VOLATILE
,
3157 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3158 return INVALID_HANDLE_VALUE
;
3161 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3166 RequiredSize
* sizeof(WCHAR
)))
3168 RegCloseKey(hClassKey
);
3169 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3170 return INVALID_HANDLE_VALUE
;
3178 InstallServicesSection(
3180 IN PCWSTR SectionName
,
3181 IN HDEVINFO DeviceInfoSet OPTIONAL
,
3182 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3183 OUT PCWSTR
* pAssociatedService OPTIONAL
,
3184 OUT PBOOL pRebootRequired OPTIONAL
)
3186 INFCONTEXT ContextService
;
3191 ret
= SetupFindFirstLineW(hInf
, SectionName
, NULL
, &ContextService
);
3194 LPWSTR ServiceName
= NULL
;
3195 LPWSTR ServiceSection
= NULL
;
3197 ret
= SetupGetStringFieldW(
3199 1, /* Field index */
3204 if (RequiredSize
> 0)
3206 /* We got the needed size for the buffer */
3207 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3210 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3213 ret
= SetupGetStringFieldW(
3215 1, /* Field index */
3216 ServiceName
, RequiredSize
,
3221 ret
= SetupGetIntField(
3223 2, /* Field index */
3227 /* The field may be empty. Ignore the error */
3230 ret
= SetupGetStringFieldW(
3232 3, /* Field index */
3237 if (GetLastError() == ERROR_INVALID_PARAMETER
)
3239 /* This first is probably missing. It is not
3240 * required, so ignore the error */
3247 if (RequiredSize
> 0)
3249 /* We got the needed size for the buffer */
3250 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3251 if (!ServiceSection
)
3253 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3256 ret
= SetupGetStringFieldW(
3258 3, /* Field index */
3259 ServiceSection
, RequiredSize
,
3264 SetLastError(ERROR_SUCCESS
);
3265 ret
= SetupInstallServicesFromInfSectionExW(
3267 ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
3269 if (ret
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
3271 if (pAssociatedService
)
3273 *pAssociatedService
= ServiceName
;
3276 if (pRebootRequired
&& GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
3277 *pRebootRequired
= TRUE
;
3280 HeapFree(GetProcessHeap(), 0, ServiceName
);
3281 HeapFree(GetProcessHeap(), 0, ServiceSection
);
3284 ret
= SetupFindNextLine(&ContextService
, &ContextService
);
3293 /***********************************************************************
3294 * SetupDiInstallClassExW (SETUPAPI.@)
3296 BOOL WINAPI
SetupDiInstallClassExW(
3297 IN HWND hwndParent OPTIONAL
,
3298 IN PCWSTR InfFileName OPTIONAL
,
3300 IN HSPFILEQ FileQueue OPTIONAL
,
3301 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3307 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3308 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3310 if (!InfFileName
&& !InterfaceClassGuid
)
3311 SetLastError(ERROR_INVALID_PARAMETER
);
3312 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3314 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3315 SetLastError(ERROR_INVALID_FLAGS
);
3317 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3318 SetLastError(ERROR_INVALID_PARAMETER
);
3319 else if (Reserved1
!= NULL
)
3320 SetLastError(ERROR_INVALID_PARAMETER
);
3321 else if (Reserved2
!= NULL
)
3322 SetLastError(ERROR_INVALID_PARAMETER
);
3325 WCHAR SectionName
[MAX_PATH
];
3326 HINF hInf
= INVALID_HANDLE_VALUE
;
3327 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3328 PVOID callback_context
= NULL
;
3330 if (InterfaceClassGuid
)
3332 /* SetupDiCreateDeviceInterface??? */
3333 FIXME("Installing an interface is not implemented\n");
3334 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3338 if (Flags
& DI_NOVCP
)
3339 FIXME("FileQueue argument ignored\n");
3340 if (Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3341 FIXME("Flags 0x%lx ignored\n", Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3343 /* Open the .inf file */
3344 hInf
= SetupOpenInfFileW(
3349 if (hInf
== INVALID_HANDLE_VALUE
)
3352 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3353 hClassKey
= CreateClassKey(hInf
);
3354 if (hClassKey
== INVALID_HANDLE_VALUE
)
3357 /* Try to append a layout file */
3358 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3362 /* Retrieve the actual section name */
3363 ret
= SetupDiGetActualSectionToInstallW(
3367 MAX_PATH
- wcslen(DotServices
),
3373 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3374 if (!callback_context
)
3377 ret
= SetupInstallFromInfSectionW(
3381 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3383 NULL
, /* SourceRootPath */
3385 SetupDefaultQueueCallbackW
,
3392 /* Install .Services section */
3393 lstrcatW(SectionName
, DotServices
);
3394 ret
= InstallServicesSection(hInf
, SectionName
, NULL
, NULL
, NULL
, NULL
);
3402 if (hInf
!= INVALID_HANDLE_VALUE
)
3403 SetupCloseInfFile(hInf
);
3404 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3405 RegCloseKey(hClassKey
);
3406 SetupTermDefaultQueueCallback(callback_context
);
3409 TRACE("Returning %d\n", ret
);
3414 /***********************************************************************
3415 * SetupDiOpenClassRegKey (SETUPAPI.@)
3417 HKEY WINAPI
SetupDiOpenClassRegKey(
3418 const GUID
* ClassGuid
,
3421 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3422 DIOCR_INSTALLER
, NULL
, NULL
);
3426 /***********************************************************************
3427 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3429 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3430 const GUID
* ClassGuid OPTIONAL
,
3433 PCSTR MachineName OPTIONAL
,
3436 PWSTR MachineNameW
= NULL
;
3443 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3444 if (MachineNameW
== NULL
)
3445 return INVALID_HANDLE_VALUE
;
3448 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3449 Flags
, MachineNameW
, Reserved
);
3452 MyFree(MachineNameW
);
3458 /***********************************************************************
3459 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3461 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3462 const GUID
* ClassGuid OPTIONAL
,
3465 PCWSTR MachineName OPTIONAL
,
3468 LPWSTR lpGuidString
;
3469 LPWSTR lpFullGuidString
;
3477 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3478 Flags
, debugstr_w(MachineName
), Reserved
);
3480 if (Flags
== DIOCR_INSTALLER
)
3482 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3484 else if (Flags
== DIOCR_INTERFACE
)
3486 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3490 ERR("Invalid Flags parameter!\n");
3491 SetLastError(ERROR_INVALID_FLAGS
);
3492 return INVALID_HANDLE_VALUE
;
3495 if (MachineName
!= NULL
)
3497 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3498 if (rc
!= ERROR_SUCCESS
)
3501 return INVALID_HANDLE_VALUE
;
3505 HKLM
= HKEY_LOCAL_MACHINE
;
3507 rc
= RegOpenKeyExW(HKLM
,
3510 ClassGuid
? 0 : samDesired
,
3512 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3513 if (rc
!= ERROR_SUCCESS
)
3516 return INVALID_HANDLE_VALUE
;
3519 if (ClassGuid
== NULL
)
3522 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3524 SetLastError(ERROR_GEN_FAILURE
);
3525 RegCloseKey(hClassesKey
);
3526 return INVALID_HANDLE_VALUE
;
3529 dwLength
= lstrlenW(lpGuidString
);
3530 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3531 if (!lpFullGuidString
)
3533 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3534 RpcStringFreeW(&lpGuidString
);
3535 return INVALID_HANDLE_VALUE
;
3537 lpFullGuidString
[0] = '{';
3538 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3539 lpFullGuidString
[dwLength
+ 1] = '}';
3540 lpFullGuidString
[dwLength
+ 2] = '\0';
3541 RpcStringFreeW(&lpGuidString
);
3543 rc
= RegOpenKeyExW(hClassesKey
,
3548 if (rc
!= ERROR_SUCCESS
)
3551 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3552 RegCloseKey(hClassesKey
);
3553 return INVALID_HANDLE_VALUE
;
3556 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3557 RegCloseKey(hClassesKey
);
3562 /***********************************************************************
3563 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3565 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3566 HDEVINFO DeviceInfoSet
,
3569 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3571 FIXME("%p %s %08lx %p\n",
3572 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3576 /***********************************************************************
3577 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3579 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3580 HDEVINFO DeviceInfoSet
,
3583 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3585 LPWSTR DevicePathW
= NULL
;
3588 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3590 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3591 if (DevicePathW
== NULL
)
3594 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3595 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3597 MyFree(DevicePathW
);
3602 /***********************************************************************
3603 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3605 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3606 HDEVINFO DeviceInfoSet
,
3607 PSP_DEVINFO_DATA DeviceInfoData
,
3608 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3609 DWORD ClassInstallParamsSize
)
3611 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3612 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3616 /***********************************************************************
3617 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3619 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3620 IN HDEVINFO DeviceInfoSet
,
3621 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3622 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3623 IN DWORD ClassInstallParamsSize
)
3625 struct DeviceInfoSet
*list
;
3628 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3629 ClassInstallParams
, ClassInstallParamsSize
);
3632 SetLastError(ERROR_INVALID_PARAMETER
);
3633 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3634 SetLastError(ERROR_INVALID_HANDLE
);
3635 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3636 SetLastError(ERROR_INVALID_HANDLE
);
3637 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3638 SetLastError(ERROR_INVALID_USER_BUFFER
);
3639 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3640 SetLastError(ERROR_INVALID_USER_BUFFER
);
3641 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3642 SetLastError(ERROR_INVALID_PARAMETER
);
3643 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3644 SetLastError(ERROR_INVALID_PARAMETER
);
3647 SP_DEVINSTALL_PARAMS_W InstallParams
;
3650 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3651 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3655 if (ClassInstallParams
)
3657 /* Check parameters in ClassInstallParams */
3658 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3659 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3661 SetLastError(ERROR_INVALID_USER_BUFFER
);
3664 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3666 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3667 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3670 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3673 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3677 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3680 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3684 TRACE("Returning %d\n", ret
);
3688 static BOOL
PropertyChangeHandler(
3689 IN HDEVINFO DeviceInfoSet
,
3690 IN PSP_DEVINFO_DATA DeviceInfoData
,
3691 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3692 IN DWORD ClassInstallParamsSize
)
3694 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3697 if (!DeviceInfoData
)
3698 SetLastError(ERROR_INVALID_PARAMETER
);
3699 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3700 SetLastError(ERROR_INVALID_PARAMETER
);
3701 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3702 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3703 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3704 SetLastError(ERROR_INVALID_FLAGS
);
3705 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3706 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3707 SetLastError(ERROR_INVALID_FLAGS
);
3708 else if (PropChangeParams
3709 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3710 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3711 SetLastError(ERROR_INVALID_USER_BUFFER
);
3714 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3715 if (!DeviceInfoData
)
3717 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3718 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3722 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3723 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3725 if (*CurrentPropChangeParams
)
3727 MyFree(*CurrentPropChangeParams
);
3728 *CurrentPropChangeParams
= NULL
;
3730 if (PropChangeParams
)
3732 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3733 if (!*CurrentPropChangeParams
)
3735 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3738 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3749 IN PWSTR InstallerName
,
3750 OUT HMODULE
* ModulePointer
,
3751 OUT PVOID
* FunctionPointer
)
3753 HMODULE hModule
= NULL
;
3754 LPSTR FunctionNameA
= NULL
;
3758 *ModulePointer
= NULL
;
3759 *FunctionPointer
= NULL
;
3761 Comma
= strchrW(InstallerName
, ',');
3764 rc
= ERROR_INVALID_PARAMETER
;
3770 hModule
= LoadLibraryW(InstallerName
);
3774 rc
= GetLastError();
3778 /* Skip comma spaces */
3779 while (*Comma
== ',' || isspaceW(*Comma
))
3782 /* W->A conversion for function name */
3783 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3786 rc
= GetLastError();
3790 /* Search function */
3791 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3792 if (!*FunctionPointer
)
3794 rc
= GetLastError();
3798 *ModulePointer
= hModule
;
3802 if (rc
!= ERROR_SUCCESS
&& hModule
)
3803 FreeLibrary(hModule
);
3804 MyFree(FunctionNameA
);
3809 FreeFunctionPointer(
3810 IN HMODULE ModulePointer
,
3811 IN PVOID FunctionPointer
)
3813 if (ModulePointer
== NULL
)
3814 return ERROR_SUCCESS
;
3815 if (FreeLibrary(ModulePointer
))
3816 return ERROR_SUCCESS
;
3818 return GetLastError();
3821 /***********************************************************************
3822 * SetupDiCallClassInstaller (SETUPAPI.@)
3824 BOOL WINAPI
SetupDiCallClassInstaller(
3825 IN DI_FUNCTION InstallFunction
,
3826 IN HDEVINFO DeviceInfoSet
,
3827 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3831 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3834 SetLastError(ERROR_INVALID_PARAMETER
);
3835 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3836 SetLastError(ERROR_INVALID_HANDLE
);
3837 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3838 SetLastError(ERROR_INVALID_HANDLE
);
3839 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3840 SetLastError(ERROR_INVALID_HANDLE
);
3841 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3842 SetLastError(ERROR_INVALID_USER_BUFFER
);
3845 SP_DEVINSTALL_PARAMS_W InstallParams
;
3846 #define CLASS_COINSTALLER 0x1
3847 #define DEVICE_COINSTALLER 0x2
3848 #define CLASS_INSTALLER 0x4
3849 UCHAR CanHandle
= 0;
3850 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3852 switch (InstallFunction
)
3854 case DIF_ALLOW_INSTALL
:
3855 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3857 case DIF_DESTROYPRIVATEDATA
:
3858 CanHandle
= CLASS_INSTALLER
;
3860 case DIF_INSTALLDEVICE
:
3861 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3862 DefaultHandler
= SetupDiInstallDevice
;
3864 case DIF_INSTALLDEVICEFILES
:
3865 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3866 DefaultHandler
= SetupDiInstallDriverFiles
;
3868 case DIF_INSTALLINTERFACES
:
3869 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3870 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3872 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3873 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3875 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3876 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3878 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3879 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3881 case DIF_PROPERTYCHANGE
:
3882 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3883 DefaultHandler
= SetupDiChangeState
;
3885 case DIF_REGISTER_COINSTALLERS
:
3886 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3887 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3889 case DIF_SELECTBESTCOMPATDRV
:
3890 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3891 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3894 ERR("Install function %u not supported\n", InstallFunction
);
3895 SetLastError(ERROR_NOT_SUPPORTED
);
3898 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3899 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3900 /* Don't process this call, as a parameter is invalid */
3905 LIST_ENTRY ClassCoInstallersListHead
;
3906 LIST_ENTRY DeviceCoInstallersListHead
;
3907 HMODULE ClassInstallerLibrary
= NULL
;
3908 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3909 COINSTALLER_CONTEXT_DATA Context
;
3910 PLIST_ENTRY ListEntry
;
3912 DWORD dwRegType
, dwLength
;
3913 DWORD rc
= NO_ERROR
;
3915 InitializeListHead(&ClassCoInstallersListHead
);
3916 InitializeListHead(&DeviceCoInstallersListHead
);
3918 if (CanHandle
& DEVICE_COINSTALLER
)
3920 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3921 if (hKey
!= INVALID_HANDLE_VALUE
)
3923 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3924 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3926 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3927 if (KeyBuffer
!= NULL
)
3929 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3930 if (rc
== ERROR_SUCCESS
)
3933 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3935 /* Add coinstaller to DeviceCoInstallersListHead list */
3936 struct CoInstallerElement
*coinstaller
;
3937 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3938 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3941 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3942 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3943 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3945 HeapFree(GetProcessHeap(), 0, coinstaller
);
3948 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3954 if (CanHandle
& CLASS_COINSTALLER
)
3958 REGSTR_PATH_CODEVICEINSTALLERS
,
3962 if (rc
== ERROR_SUCCESS
)
3964 LPWSTR lpGuidString
;
3965 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3967 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3968 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3970 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3971 if (KeyBuffer
!= NULL
)
3973 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3974 if (rc
== ERROR_SUCCESS
)
3977 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3979 /* Add coinstaller to ClassCoInstallersListHead list */
3980 struct CoInstallerElement
*coinstaller
;
3981 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3982 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3985 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3986 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3987 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3989 HeapFree(GetProcessHeap(), 0, coinstaller
);
3992 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3995 RpcStringFreeW(&lpGuidString
);
4000 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
4002 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
4003 if (hKey
!= INVALID_HANDLE_VALUE
)
4005 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4006 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
4008 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4009 if (KeyBuffer
!= NULL
)
4011 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4012 if (rc
== ERROR_SUCCESS
)
4014 /* Get ClassInstaller function pointer */
4015 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
4016 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
4018 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
4019 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4022 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4029 /* Call Class co-installers */
4030 Context
.PostProcessing
= FALSE
;
4032 ListEntry
= ClassCoInstallersListHead
.Flink
;
4033 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
4035 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
4036 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4037 coinstaller
->PrivateData
= Context
.PrivateData
;
4038 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4040 coinstaller
->DoPostProcessing
= TRUE
;
4043 ListEntry
= ListEntry
->Flink
;
4046 /* Call Device co-installers */
4047 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4048 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
4050 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
4051 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4052 coinstaller
->PrivateData
= Context
.PrivateData
;
4053 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4055 coinstaller
->DoPostProcessing
= TRUE
;
4058 ListEntry
= ListEntry
->Flink
;
4061 /* Call Class installer */
4064 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4065 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
4068 rc
= ERROR_DI_DO_DEFAULT
;
4070 /* Call default handler */
4071 if (rc
== ERROR_DI_DO_DEFAULT
)
4073 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
4075 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
4078 rc
= GetLastError();
4084 /* Call Class co-installers that required postprocessing */
4085 Context
.PostProcessing
= TRUE
;
4086 ListEntry
= ClassCoInstallersListHead
.Flink
;
4087 while (ListEntry
!= &ClassCoInstallersListHead
)
4089 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
4090 if (coinstaller
->DoPostProcessing
)
4092 Context
.InstallResult
= rc
;
4093 Context
.PrivateData
= coinstaller
->PrivateData
;
4094 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4096 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4097 ListEntry
= ListEntry
->Flink
;
4100 /* Call Device co-installers that required postprocessing */
4101 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4102 while (ListEntry
!= &DeviceCoInstallersListHead
)
4104 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
4105 if (coinstaller
->DoPostProcessing
)
4107 Context
.InstallResult
= rc
;
4108 Context
.PrivateData
= coinstaller
->PrivateData
;
4109 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4111 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4112 ListEntry
= ListEntry
->Flink
;
4115 /* Free allocated memory */
4116 while (!IsListEmpty(&ClassCoInstallersListHead
))
4118 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4119 HeapFree(GetProcessHeap(), 0, ListEntry
);
4121 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4123 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4124 HeapFree(GetProcessHeap(), 0, ListEntry
);
4127 ret
= (rc
== NO_ERROR
);
4131 TRACE("Returning %d\n", ret
);
4135 /***********************************************************************
4136 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4138 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
4139 IN HDEVINFO DeviceInfoSet
,
4140 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
4142 struct DeviceInfoSet
*list
;
4145 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
4148 SetLastError(ERROR_INVALID_HANDLE
);
4149 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4150 SetLastError(ERROR_INVALID_HANDLE
);
4151 else if (!DeviceInfoListDetailData
)
4152 SetLastError(ERROR_INVALID_PARAMETER
);
4153 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
4154 SetLastError(ERROR_INVALID_USER_BUFFER
);
4158 &DeviceInfoListDetailData
->ClassGuid
,
4161 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
4162 if (list
->MachineName
)
4163 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
4165 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
4170 TRACE("Returning %d\n", ret
);
4174 /***********************************************************************
4175 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4177 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4178 IN HDEVINFO DeviceInfoSet
,
4179 IN PSP_DEVINFO_DATA DeviceInfoData
,
4180 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4182 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4185 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4187 if (DeviceInstallParams
== NULL
)
4188 SetLastError(ERROR_INVALID_PARAMETER
);
4189 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4190 SetLastError(ERROR_INVALID_USER_BUFFER
);
4193 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4194 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4198 /* Do W->A conversion */
4200 DeviceInstallParams
,
4201 &deviceInstallParamsW
,
4202 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4203 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4204 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4206 DeviceInstallParams
->DriverPath
[0] = '\0';
4212 TRACE("Returning %d\n", ret
);
4216 /***********************************************************************
4217 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4219 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
4220 IN HDEVINFO DeviceInfoSet
,
4221 IN PSP_DEVINFO_DATA DeviceInfoData
,
4222 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4224 struct DeviceInfoSet
*list
;
4227 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4230 SetLastError(ERROR_INVALID_HANDLE
);
4231 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4232 SetLastError(ERROR_INVALID_HANDLE
);
4233 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4234 SetLastError(ERROR_INVALID_USER_BUFFER
);
4235 else if (!DeviceInstallParams
)
4236 SetLastError(ERROR_INVALID_PARAMETER
);
4237 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4238 SetLastError(ERROR_INVALID_USER_BUFFER
);
4241 PSP_DEVINSTALL_PARAMS_W Source
;
4244 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4246 Source
= &list
->InstallParams
;
4247 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4251 TRACE("Returning %d\n", ret
);
4255 /***********************************************************************
4256 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4258 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
4259 IN HDEVINFO DeviceInfoSet
,
4260 IN PSP_DEVINFO_DATA DeviceInfoData
,
4261 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4263 struct DeviceInfoSet
*list
;
4266 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4269 SetLastError(ERROR_INVALID_HANDLE
);
4270 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4271 SetLastError(ERROR_INVALID_HANDLE
);
4272 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4273 SetLastError(ERROR_INVALID_USER_BUFFER
);
4274 else if (!DeviceInstallParams
)
4275 SetLastError(ERROR_INVALID_PARAMETER
);
4276 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4277 SetLastError(ERROR_INVALID_USER_BUFFER
);
4280 PSP_DEVINSTALL_PARAMS_W Destination
;
4282 /* FIXME: Validate parameters */
4285 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4287 Destination
= &list
->InstallParams
;
4288 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4292 TRACE("Returning %d\n", ret
);
4296 /***********************************************************************
4297 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4299 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
4300 IN HDEVINFO DeviceInfoSet
,
4301 IN PSP_DEVINFO_DATA DeviceInfoData
,
4302 OUT PSTR DeviceInstanceId OPTIONAL
,
4303 IN DWORD DeviceInstanceIdSize
,
4304 OUT PDWORD RequiredSize OPTIONAL
)
4306 PWSTR DeviceInstanceIdW
= NULL
;
4309 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4310 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4312 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4313 SetLastError(ERROR_INVALID_PARAMETER
);
4316 if (DeviceInstanceIdSize
!= 0)
4318 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4319 if (DeviceInstanceIdW
== NULL
)
4323 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4324 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4327 if (ret
&& DeviceInstanceIdW
!= NULL
)
4329 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4330 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4332 DeviceInstanceId
[0] = '\0';
4338 TRACE("Returning %d\n", ret
);
4342 /***********************************************************************
4343 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4345 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
4346 IN HDEVINFO DeviceInfoSet
,
4347 IN PSP_DEVINFO_DATA DeviceInfoData
,
4348 OUT PWSTR DeviceInstanceId OPTIONAL
,
4349 IN DWORD DeviceInstanceIdSize
,
4350 OUT PDWORD RequiredSize OPTIONAL
)
4354 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4355 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4358 SetLastError(ERROR_INVALID_HANDLE
);
4359 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4360 SetLastError(ERROR_INVALID_HANDLE
);
4361 else if (!DeviceInfoData
)
4362 SetLastError(ERROR_INVALID_PARAMETER
);
4363 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4364 SetLastError(ERROR_INVALID_USER_BUFFER
);
4365 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4366 SetLastError(ERROR_INVALID_PARAMETER
);
4367 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4368 SetLastError(ERROR_INVALID_PARAMETER
);
4371 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4374 required
= (wcslen(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4376 *RequiredSize
= required
;
4378 if (required
<= DeviceInstanceIdSize
)
4380 wcscpy(DeviceInstanceId
, DevInfo
->DeviceName
);
4384 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4387 TRACE("Returning %d\n", ret
);
4391 /***********************************************************************
4392 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4394 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
4395 IN HDEVINFO DeviceInfoSet
,
4396 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4397 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4398 IN DWORD PropertySheetHeaderPageListSize
,
4399 OUT PDWORD RequiredSize OPTIONAL
,
4400 IN DWORD PropertySheetType
)
4402 PROPSHEETHEADERW psh
;
4405 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4406 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4407 RequiredSize
, PropertySheetType
);
4409 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4410 psh
.phpage
= PropertySheetHeader
->phpage
;
4411 psh
.nPages
= PropertySheetHeader
->nPages
;
4413 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4414 PropertySheetHeaderPageListSize
, RequiredSize
,
4418 PropertySheetHeader
->nPages
= psh
.nPages
;
4421 TRACE("Returning %d\n", ret
);
4425 struct ClassDevPropertySheetsData
4427 HPROPSHEETPAGE
*PropertySheetPages
;
4428 DWORD MaximumNumberOfPages
;
4429 DWORD NumberOfPages
;
4432 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
4433 IN HPROPSHEETPAGE hPropSheetPage
,
4434 IN OUT LPARAM lParam
)
4436 struct ClassDevPropertySheetsData
*PropPageData
;
4438 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4440 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4442 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4443 PropPageData
->PropertySheetPages
++;
4446 PropPageData
->NumberOfPages
++;
4450 /***********************************************************************
4451 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4453 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
4454 IN HDEVINFO DeviceInfoSet
,
4455 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4456 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4457 IN DWORD PropertySheetHeaderPageListSize
,
4458 OUT PDWORD RequiredSize OPTIONAL
,
4459 IN DWORD PropertySheetType
)
4461 struct DeviceInfoSet
*list
;
4464 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4465 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4466 RequiredSize
, PropertySheetType
);
4469 SetLastError(ERROR_INVALID_HANDLE
);
4470 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4471 SetLastError(ERROR_INVALID_HANDLE
);
4472 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4473 SetLastError(ERROR_INVALID_HANDLE
);
4474 else if (!PropertySheetHeader
)
4475 SetLastError(ERROR_INVALID_PARAMETER
);
4476 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4477 SetLastError(ERROR_INVALID_FLAGS
);
4478 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4479 SetLastError(ERROR_INVALID_USER_BUFFER
);
4480 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4481 SetLastError(ERROR_INVALID_PARAMETER
);
4482 else if (!PropertySheetHeader
)
4483 SetLastError(ERROR_INVALID_PARAMETER
);
4484 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4485 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4486 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4487 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4488 SetLastError(ERROR_INVALID_PARAMETER
);
4491 HKEY hKey
= INVALID_HANDLE_VALUE
;
4492 SP_PROPSHEETPAGE_REQUEST Request
;
4493 LPWSTR PropPageProvider
= NULL
;
4494 HMODULE hModule
= NULL
;
4495 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4496 struct ClassDevPropertySheetsData PropPageData
;
4497 DWORD dwLength
, dwRegType
;
4501 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4504 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4505 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4507 if (hKey
== INVALID_HANDLE_VALUE
)
4510 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4511 if (rc
== ERROR_FILE_NOT_FOUND
)
4513 /* No registry key. As it is optional, don't say it's a bad error */
4519 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4525 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4526 if (!PropPageProvider
)
4528 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4531 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4532 if (rc
!= ERROR_SUCCESS
)
4537 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4539 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4540 if (rc
!= ERROR_SUCCESS
)
4542 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4546 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4547 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4548 Request
.DeviceInfoSet
= DeviceInfoSet
;
4549 Request
.DeviceInfoData
= DeviceInfoData
;
4550 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4551 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4552 PropPageData
.NumberOfPages
= 0;
4553 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4558 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4559 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4561 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4566 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4567 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4571 if (hKey
!= INVALID_HANDLE_VALUE
)
4573 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4574 FreeFunctionPointer(hModule
, pPropPageProvider
);
4577 TRACE("Returning %d\n", ret
);
4581 /***********************************************************************
4582 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4584 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4585 IN HDEVINFO DeviceInfoSet
,
4586 IN PSP_DEVINFO_DATA DeviceInfoData
,
4590 IN HINF InfHandle OPTIONAL
,
4591 IN PCSTR InfSectionName OPTIONAL
)
4593 PCWSTR InfSectionNameW
= NULL
;
4594 HKEY ret
= INVALID_HANDLE_VALUE
;
4598 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4599 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4602 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4610 if (InfSectionNameW
!= NULL
)
4611 MyFree((PVOID
)InfSectionNameW
);
4617 OpenHardwareProfileKey(
4620 IN DWORD samDesired
)
4622 HKEY hHWProfilesKey
= INVALID_HANDLE_VALUE
;
4623 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4624 HKEY ret
= INVALID_HANDLE_VALUE
;
4627 rc
= RegOpenKeyExW(HKLM
,
4628 REGSTR_PATH_HWPROFILES
,
4632 if (rc
!= ERROR_SUCCESS
)
4649 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4658 if (rc
!= ERROR_SUCCESS
)
4663 ret
= hHWProfileKey
;
4666 if (hHWProfilesKey
!= INVALID_HANDLE_VALUE
)
4667 RegCloseKey(hHWProfilesKey
);
4668 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
&& hHWProfileKey
!= ret
)
4669 RegCloseKey(hHWProfileKey
);
4673 /***********************************************************************
4674 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4676 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4677 IN HDEVINFO DeviceInfoSet
,
4678 IN PSP_DEVINFO_DATA DeviceInfoData
,
4682 IN HINF InfHandle OPTIONAL
,
4683 IN PCWSTR InfSectionName OPTIONAL
)
4685 struct DeviceInfoSet
*list
;
4686 HKEY ret
= INVALID_HANDLE_VALUE
;
4688 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4689 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4692 SetLastError(ERROR_INVALID_HANDLE
);
4693 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4694 SetLastError(ERROR_INVALID_HANDLE
);
4695 else if (!DeviceInfoData
)
4696 SetLastError(ERROR_INVALID_PARAMETER
);
4697 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4698 SetLastError(ERROR_INVALID_USER_BUFFER
);
4699 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4700 SetLastError(ERROR_INVALID_PARAMETER
);
4701 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4702 SetLastError(ERROR_INVALID_PARAMETER
);
4703 else if (InfHandle
&& !InfSectionName
)
4704 SetLastError(ERROR_INVALID_PARAMETER
);
4705 else if (!InfHandle
&& InfSectionName
)
4706 SetLastError(ERROR_INVALID_PARAMETER
);
4709 LPWSTR lpGuidString
= NULL
;
4710 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4711 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4712 DWORD Index
; /* Index used in the DriverKey name */
4714 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4715 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4716 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4717 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4718 HKEY hKey
= INVALID_HANDLE_VALUE
;
4721 if (Scope
== DICS_FLAG_GLOBAL
)
4722 RootKey
= list
->HKLM
;
4723 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4725 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
4726 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4728 RootKey
= hHWProfileKey
;
4731 if (KeyType
== DIREG_DEV
)
4733 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4735 rc
= RegCreateKeyExW(
4737 REGSTR_PATH_SYSTEMENUM
,
4740 REG_OPTION_NON_VOLATILE
,
4745 if (rc
!= ERROR_SUCCESS
)
4750 rc
= RegCreateKeyExW(
4752 deviceInfo
->DeviceName
,
4755 REG_OPTION_NON_VOLATILE
,
4756 #if _WIN32_WINNT >= 0x502
4757 KEY_READ
| KEY_WRITE
,
4764 if (rc
!= ERROR_SUCCESS
)
4770 else /* KeyType == DIREG_DRV */
4772 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4774 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4775 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4778 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4781 wcscpy(DriverKey
, L
"{");
4782 wcscat(DriverKey
, lpGuidString
);
4783 wcscat(DriverKey
, L
"}\\");
4784 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4785 rc
= RegOpenKeyExW(RootKey
,
4786 REGSTR_PATH_CLASS_NT
,
4790 if (rc
!= ERROR_SUCCESS
)
4796 /* Try all values for Index between 0 and 9999 */
4798 while (Index
<= 9999)
4801 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4802 rc
= RegCreateKeyEx(hClassKey
,
4806 REG_OPTION_NON_VOLATILE
,
4807 #if _WIN32_WINNT >= 0x502
4808 KEY_READ
| KEY_WRITE
,
4815 if (rc
!= ERROR_SUCCESS
)
4820 if (Disposition
== REG_CREATED_NEW_KEY
)
4823 hKey
= INVALID_HANDLE_VALUE
;
4828 /* Unable to create more than 9999 devices within the same class */
4829 SetLastError(ERROR_GEN_FAILURE
);
4833 /* Open device key, to write Driver value */
4834 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4835 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4837 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4838 if (rc
!= ERROR_SUCCESS
)
4845 /* Do installation of the specified section */
4848 FIXME("Need to install section %s in file %p\n",
4849 debugstr_w(InfSectionName
), InfHandle
);
4855 RpcStringFreeW(&lpGuidString
);
4856 HeapFree(GetProcessHeap(), 0, DriverKey
);
4857 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4858 RegCloseKey(hHWProfileKey
);
4859 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4860 RegCloseKey(hEnumKey
);
4861 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4862 RegCloseKey(hClassKey
);
4863 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4864 RegCloseKey(hDeviceKey
);
4865 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4869 TRACE("Returning 0x%p\n", ret
);
4873 /***********************************************************************
4874 * SetupDiOpenDevRegKey (SETUPAPI.@)
4876 HKEY WINAPI
SetupDiOpenDevRegKey(
4877 HDEVINFO DeviceInfoSet
,
4878 PSP_DEVINFO_DATA DeviceInfoData
,
4884 struct DeviceInfoSet
*list
;
4885 HKEY ret
= INVALID_HANDLE_VALUE
;
4887 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4888 Scope
, HwProfile
, KeyType
, samDesired
);
4891 SetLastError(ERROR_INVALID_HANDLE
);
4892 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4893 SetLastError(ERROR_INVALID_HANDLE
);
4894 else if (!DeviceInfoData
)
4895 SetLastError(ERROR_INVALID_PARAMETER
);
4896 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4897 SetLastError(ERROR_INVALID_USER_BUFFER
);
4898 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4899 SetLastError(ERROR_INVALID_PARAMETER
);
4900 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4901 SetLastError(ERROR_INVALID_PARAMETER
);
4904 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4905 LPWSTR DriverKey
= NULL
;
4909 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4910 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4911 HKEY hKey
= INVALID_HANDLE_VALUE
;
4914 if (Scope
== DICS_FLAG_GLOBAL
)
4915 RootKey
= list
->HKLM
;
4916 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4918 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
4919 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4921 RootKey
= hHWProfileKey
;
4926 REGSTR_PATH_SYSTEMENUM
,
4930 if (rc
!= ERROR_SUCCESS
)
4937 deviceInfo
->DeviceName
,
4939 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4941 RegCloseKey(hEnumKey
);
4942 hEnumKey
= INVALID_HANDLE_VALUE
;
4943 if (rc
!= ERROR_SUCCESS
)
4948 if (KeyType
== DIREG_DEV
)
4950 /* We're done. Just return the hKey handle */
4954 /* Read the 'Driver' key */
4955 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
4956 if (rc
!= ERROR_SUCCESS
)
4961 else if (dwRegType
!= REG_SZ
)
4963 SetLastError(ERROR_GEN_FAILURE
);
4966 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4969 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4972 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4973 if (rc
!= ERROR_SUCCESS
)
4979 hKey
= INVALID_HANDLE_VALUE
;
4980 /* Need to open the driver key */
4983 REGSTR_PATH_CLASS_NT
,
4987 if (rc
!= ERROR_SUCCESS
)
4998 if (rc
!= ERROR_SUCCESS
)
5006 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
5007 RegCloseKey(hHWProfileKey
);
5008 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
5009 RegCloseKey(hEnumKey
);
5010 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
5014 TRACE("Returning 0x%p\n", ret
);
5018 /***********************************************************************
5019 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
5021 BOOL WINAPI
SetupDiCreateDeviceInfoA(
5022 HDEVINFO DeviceInfoSet
,
5024 CONST GUID
*ClassGuid
,
5025 PCSTR DeviceDescription
,
5027 DWORD CreationFlags
,
5028 PSP_DEVINFO_DATA DeviceInfoData
)
5030 LPWSTR DeviceNameW
= NULL
;
5031 LPWSTR DeviceDescriptionW
= NULL
;
5038 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
5039 if (DeviceNameW
== NULL
) return FALSE
;
5041 if (DeviceDescription
)
5043 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
5044 if (DeviceDescriptionW
== NULL
)
5046 if (DeviceNameW
) MyFree(DeviceNameW
);
5051 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
5052 ClassGuid
, DeviceDescriptionW
,
5053 hwndParent
, CreationFlags
,
5056 if (DeviceNameW
) MyFree(DeviceNameW
);
5057 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
5062 /***********************************************************************
5063 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
5065 BOOL WINAPI
SetupDiCreateDeviceInfoW(
5066 HDEVINFO DeviceInfoSet
,
5068 CONST GUID
*ClassGuid
,
5069 PCWSTR DeviceDescription
,
5071 DWORD CreationFlags
,
5072 PSP_DEVINFO_DATA DeviceInfoData
)
5074 struct DeviceInfoSet
*list
;
5077 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
5078 debugstr_guid(ClassGuid
), DeviceDescription
,
5079 hwndParent
, CreationFlags
, DeviceInfoData
);
5082 SetLastError(ERROR_INVALID_HANDLE
);
5083 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5084 SetLastError(ERROR_INVALID_HANDLE
);
5085 else if (!ClassGuid
)
5086 SetLastError(ERROR_INVALID_PARAMETER
);
5087 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
5088 SetLastError(ERROR_CLASS_MISMATCH
);
5089 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
5091 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
5092 SetLastError(ERROR_INVALID_FLAGS
);
5096 SP_DEVINFO_DATA DevInfo
;
5098 if (CreationFlags
& DICD_GENERATE_ID
)
5100 /* Generate a new unique ID for this device */
5101 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5102 FIXME("not implemented\n");
5106 /* Device name is fully qualified. Try to open it */
5109 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
5110 rc
= SetupDiOpenDeviceInfoW(
5113 NULL
, /* hwndParent */
5114 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
5119 /* SetupDiOpenDeviceInfoW has already added
5120 * the device info to the device info set
5122 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
5124 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5126 struct DeviceInfoElement
*deviceInfo
;
5128 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
5130 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5132 if (!DeviceInfoData
)
5136 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
5138 SetLastError(ERROR_INVALID_USER_BUFFER
);
5142 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5143 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5144 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5153 TRACE("Returning %d\n", ret
);
5157 /***********************************************************************
5158 * Helper functions for SetupDiBuildDriverInfoList
5162 IN PLIST_ENTRY DriverListHead
,
5163 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5164 IN LPGUID ClassGuid
,
5165 IN INFCONTEXT ContextDevice
,
5166 IN
struct InfFileDetails
*InfFileDetails
,
5168 IN LPCWSTR ProviderName
,
5169 IN LPCWSTR ManufacturerName
,
5170 IN LPCWSTR MatchingId
,
5171 FILETIME DriverDate
,
5172 DWORDLONG DriverVersion
,
5175 struct DriverInfoElement
*driverInfo
= NULL
;
5176 HANDLE hFile
= INVALID_HANDLE_VALUE
;
5177 DWORD RequiredSize
= 128; /* Initial buffer size */
5178 BOOL Result
= FALSE
;
5179 PLIST_ENTRY PreviousEntry
;
5180 LPWSTR InfInstallSection
= NULL
;
5183 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
5186 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5189 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
5191 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
5192 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
5194 /* Copy InfFileName field */
5195 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
5196 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
5198 /* Fill InfDate field */
5199 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5200 GENERIC_READ, FILE_SHARE_READ,
5201 NULL, OPEN_EXISTING, 0, NULL);
5202 if (hFile == INVALID_HANDLE_VALUE)
5204 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5208 /* Fill SectionName field */
5209 Result
= SetupGetStringFieldW(
5212 driverInfo
->Details
.SectionName
, LINE_LEN
,
5217 /* Fill DrvDescription field */
5218 Result
= SetupGetStringFieldW(
5220 0, /* Field index */
5221 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
5224 /* Copy MatchingId information */
5225 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5226 if (!driverInfo
->MatchingId
)
5228 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5231 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5233 /* Get inf install section */
5235 RequiredSize
= 128; /* Initial buffer size */
5236 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5237 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5239 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5240 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5241 if (!InfInstallSection
)
5243 Result
= SetupGetStringFieldW(
5245 1, /* Field index */
5246 InfInstallSection
, RequiredSize
,
5252 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
5253 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
5255 driverInfo
->DriverRank
= Rank
;
5256 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
5257 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5258 driverInfo
->Info
.DriverType
= DriverType
;
5259 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
5260 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
5261 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
5262 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
5263 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
5266 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
5267 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
5270 driverInfo
->Info
.ProviderName
[0] = '\0';
5271 driverInfo
->Info
.DriverDate
= DriverDate
;
5272 driverInfo
->Info
.DriverVersion
= DriverVersion
;
5273 ReferenceInfFile(InfFileDetails
);
5274 driverInfo
->InfFileDetails
= InfFileDetails
;
5276 /* Insert current driver in driver list, according to its rank */
5277 PreviousEntry
= DriverListHead
->Flink
;
5278 while (PreviousEntry
!= DriverListHead
)
5280 struct DriverInfoElement
*CurrentDriver
;
5281 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
5282 if (CurrentDriver
->DriverRank
> Rank
||
5283 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
5285 /* Insert before the current item */
5286 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
5289 PreviousEntry
= PreviousEntry
->Flink
;
5291 if (PreviousEntry
== DriverListHead
)
5293 /* Insert at the end of the list */
5294 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
5303 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
5304 HeapFree(GetProcessHeap(), 0, driverInfo
);
5306 if (hFile
!= INVALID_HANDLE_VALUE
)
5308 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5314 GetVersionInformationFromInfFile(
5316 OUT LPGUID ClassGuid
,
5317 OUT LPWSTR
* pProviderName
,
5318 OUT FILETIME
* DriverDate
,
5319 OUT DWORDLONG
* DriverVersion
)
5322 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5323 LPWSTR DriverVer
= NULL
;
5324 LPWSTR ProviderName
= NULL
;
5325 LPWSTR pComma
; /* Points into DriverVer */
5326 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5327 SYSTEMTIME SystemTime
;
5329 BOOL ret
= FALSE
; /* Final result */
5331 /* Get class Guid */
5332 if (!SetupGetLineTextW(
5335 L
"Version", L
"ClassGUID",
5336 guidW
, sizeof(guidW
),
5337 NULL
/* Required size */))
5341 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5342 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5344 SetLastError(ERROR_GEN_FAILURE
);
5348 /* Get provider name */
5349 Result
= SetupGetLineTextW(
5351 hInf
, L
"Version", L
"Provider",
5356 /* We know know the needed buffer size */
5357 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5360 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5363 Result
= SetupGetLineTextW(
5365 hInf
, L
"Version", L
"Provider",
5366 ProviderName
, RequiredSize
,
5371 *pProviderName
= ProviderName
;
5373 /* Read the "DriverVer" value */
5374 Result
= SetupGetLineTextW(
5376 hInf
, L
"Version", L
"DriverVer",
5381 /* We know know the needed buffer size */
5382 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5385 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5388 Result
= SetupGetLineTextW(
5390 hInf
, L
"Version", L
"DriverVer",
5391 DriverVer
, RequiredSize
,
5397 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5398 pComma
= wcschr(DriverVer
, ',');
5401 *pComma
= UNICODE_NULL
;
5402 pVersion
= pComma
+ 1;
5404 /* Get driver date version. Invalid date = 00/00/00 */
5405 memset(DriverDate
, 0, sizeof(FILETIME
));
5406 if (wcslen(DriverVer
) == 10
5407 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5408 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5410 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5411 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5412 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5413 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5414 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5415 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5417 /* Get driver version. Invalid version = 0.0.0.0 */
5421 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5422 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5423 LARGE_INTEGER fullVersion
;
5425 pMinor
= strchrW(pVersion
, '.');
5429 pRevision
= strchrW(++pMinor
, '.');
5430 Minor
= atoiW(pMinor
);
5435 pBuild
= strchrW(++pRevision
, '.');
5436 Revision
= atoiW(pRevision
);
5442 Build
= atoiW(pBuild
);
5444 Major
= atoiW(pVersion
);
5445 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5446 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5447 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5454 HeapFree(GetProcessHeap(), 0, ProviderName
);
5455 HeapFree(GetProcessHeap(), 0, DriverVer
);
5460 /***********************************************************************
5461 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5464 SetupDiBuildDriverInfoList(
5465 IN HDEVINFO DeviceInfoSet
,
5466 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5467 IN DWORD DriverType
)
5469 struct DeviceInfoSet
*list
;
5470 SP_DEVINSTALL_PARAMS_W InstallParams
;
5471 PVOID Buffer
= NULL
;
5472 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5473 LPWSTR ProviderName
= NULL
;
5474 LPWSTR ManufacturerName
= NULL
;
5475 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5476 LPWSTR HardwareIDs
= NULL
;
5477 LPWSTR CompatibleIDs
= NULL
;
5478 LPWSTR FullInfFileName
= NULL
;
5479 FILETIME DriverDate
;
5480 DWORDLONG DriverVersion
= 0;
5484 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5487 SetLastError(ERROR_INVALID_HANDLE
);
5488 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5489 SetLastError(ERROR_INVALID_HANDLE
);
5490 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5491 SetLastError(ERROR_INVALID_HANDLE
);
5492 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5493 SetLastError(ERROR_INVALID_PARAMETER
);
5494 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
5495 SetLastError(ERROR_INVALID_PARAMETER
);
5496 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5497 SetLastError(ERROR_INVALID_PARAMETER
);
5498 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5499 SetLastError(ERROR_INVALID_USER_BUFFER
);
5504 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
5505 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5509 if (DriverType
== SPDIT_COMPATDRIVER
)
5511 /* Get hardware IDs list */
5513 RequiredSize
= 512; /* Initial buffer size */
5514 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5515 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5517 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5518 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5521 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5524 Result
= SetupDiGetDeviceRegistryPropertyW(
5536 /* Get compatible IDs list */
5538 RequiredSize
= 512; /* Initial buffer size */
5539 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5540 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5542 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5543 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5546 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5549 Result
= SetupDiGetDeviceRegistryPropertyW(
5552 SPDRP_COMPATIBLEIDS
,
5554 (PBYTE
)CompatibleIDs
,
5557 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5559 /* No compatible ID for this device */
5560 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5561 CompatibleIDs
= NULL
;
5569 /* Enumerate .inf files */
5571 RequiredSize
= 32768; /* Initial buffer size */
5572 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5573 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5575 HeapFree(GetProcessHeap(), 0, Buffer
);
5576 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5580 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5583 Result
= SetupGetInfFileListW(
5584 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5586 Buffer
, RequiredSize
,
5589 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5591 /* No .inf file in specified directory. So, we should
5592 * success as we created an empty driver info list.
5600 LPWSTR pFullFilename
;
5602 if (*InstallParams
.DriverPath
)
5605 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5608 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5609 if (!FullInfFileName
)
5611 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5614 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
5615 wcscat(FullInfFileName
, L
"\\");
5616 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
5620 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5621 if (!FullInfFileName
)
5623 pFullFilename
= &FullInfFileName
[0];
5626 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
5628 INFCONTEXT ContextManufacturer
, ContextDevice
;
5631 wcscpy(pFullFilename
, filename
);
5632 TRACE("Opening file %S\n", FullInfFileName
);
5634 currentInfFileDetails
= HeapAlloc(
5637 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
5638 if (!currentInfFileDetails
)
5640 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5641 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5643 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5644 ReferenceInfFile(currentInfFileDetails
);
5645 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5647 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5648 currentInfFileDetails
= NULL
;
5652 if (!GetVersionInformationFromInfFile(
5653 currentInfFileDetails
->hInf
,
5659 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5660 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5661 currentInfFileDetails
= NULL
;
5665 if (DriverType
== SPDIT_CLASSDRIVER
)
5667 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5668 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5674 /* Get the manufacturers list */
5675 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
5678 Result
= SetupGetStringFieldW(
5679 &ContextManufacturer
,
5680 0, /* Field index */
5685 /* We got the needed size for the buffer */
5686 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5687 if (!ManufacturerName
)
5689 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5692 Result
= SetupGetStringFieldW(
5693 &ContextManufacturer
,
5694 0, /* Field index */
5695 ManufacturerName
, RequiredSize
,
5698 /* Get manufacturer section name */
5699 Result
= SetupGetStringFieldW(
5700 &ContextManufacturer
,
5701 1, /* Field index */
5702 ManufacturerSection
, LINE_LEN
,
5706 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5707 /* Add (possible) extension to manufacturer section name */
5708 Result
= SetupDiGetActualSectionToInstallW(
5709 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5712 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
5713 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5718 if (DriverType
== SPDIT_CLASSDRIVER
)
5720 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5721 if (!AddDriverToList(
5722 &list
->DriverListHead
,
5726 currentInfFileDetails
,
5731 DriverDate
, DriverVersion
,
5737 else /* DriverType = SPDIT_COMPATDRIVER */
5739 /* 1. Get all fields */
5740 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5744 BOOL DriverAlreadyAdded
;
5746 for (i
= 2; i
<= FieldCount
; i
++)
5748 LPWSTR DeviceId
= NULL
;
5750 RequiredSize
= 128; /* Initial buffer size */
5751 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5752 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5754 HeapFree(GetProcessHeap(), 0, DeviceId
);
5755 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5758 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5761 Result
= SetupGetStringFieldW(
5764 DeviceId
, RequiredSize
,
5769 HeapFree(GetProcessHeap(), 0, DeviceId
);
5772 DriverAlreadyAdded
= FALSE
;
5773 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5775 if (wcsicmp(DeviceId
, currentId
) == 0)
5778 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5782 currentInfFileDetails
,
5787 DriverDate
, DriverVersion
,
5788 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5789 DriverAlreadyAdded
= TRUE
;
5794 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5796 if (wcsicmp(DeviceId
, currentId
) == 0)
5799 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5803 currentInfFileDetails
,
5808 DriverDate
, DriverVersion
,
5809 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5810 DriverAlreadyAdded
= TRUE
;
5814 HeapFree(GetProcessHeap(), 0, DeviceId
);
5817 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5820 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5821 ManufacturerName
= NULL
;
5822 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5827 HeapFree(GetProcessHeap(), 0, ProviderName
);
5828 ProviderName
= NULL
;
5830 DereferenceInfFile(currentInfFileDetails
);
5831 currentInfFileDetails
= NULL
;
5842 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5843 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5847 InstallParams
.Flags
|= DI_DIDCLASS
;
5848 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5850 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5853 HeapFree(GetProcessHeap(), 0, ProviderName
);
5854 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5855 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5856 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5857 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5858 if (currentInfFileDetails
)
5859 DereferenceInfFile(currentInfFileDetails
);
5860 HeapFree(GetProcessHeap(), 0, Buffer
);
5862 TRACE("Returning %d\n", ret
);
5866 /***********************************************************************
5867 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5870 SetupDiDeleteDeviceInfo(
5871 IN HDEVINFO DeviceInfoSet
,
5872 IN PSP_DEVINFO_DATA DeviceInfoData
)
5874 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5876 FIXME("not implemented\n");
5877 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5882 /***********************************************************************
5883 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5886 SetupDiDestroyDriverInfoList(
5887 IN HDEVINFO DeviceInfoSet
,
5888 IN PSP_DEVINFO_DATA DeviceInfoData
,
5889 IN DWORD DriverType
)
5891 struct DeviceInfoSet
*list
;
5894 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5897 SetLastError(ERROR_INVALID_HANDLE
);
5898 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5899 SetLastError(ERROR_INVALID_HANDLE
);
5900 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5901 SetLastError(ERROR_INVALID_PARAMETER
);
5902 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5903 SetLastError(ERROR_INVALID_PARAMETER
);
5904 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5905 SetLastError(ERROR_INVALID_USER_BUFFER
);
5908 PLIST_ENTRY ListEntry
;
5909 struct DriverInfoElement
*driverInfo
;
5910 SP_DEVINSTALL_PARAMS_W InstallParams
;
5912 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5913 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5916 if (!DeviceInfoData
)
5917 /* Fall back to destroying class driver list */
5918 DriverType
= SPDIT_CLASSDRIVER
;
5920 if (DriverType
== SPDIT_CLASSDRIVER
)
5922 while (!IsListEmpty(&list
->DriverListHead
))
5924 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
5925 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5926 DestroyDriverInfoElement(driverInfo
);
5928 InstallParams
.Reserved
= 0;
5929 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
5930 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
5931 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
5935 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
5936 struct DeviceInfoElement
*deviceInfo
;
5938 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5939 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
5941 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5942 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
5944 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
5945 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5946 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
5948 InstallParamsSet
.Reserved
= 0;
5949 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
5951 DestroyDriverInfoElement(driverInfo
);
5953 InstallParams
.Reserved
= 0;
5954 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
5955 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
5956 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5961 TRACE("Returning %d\n", ret
);
5966 /***********************************************************************
5967 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
5970 SetupDiOpenDeviceInfoA(
5971 IN HDEVINFO DeviceInfoSet
,
5972 IN PCSTR DeviceInstanceId
,
5973 IN HWND hwndParent OPTIONAL
,
5975 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5977 LPWSTR DeviceInstanceIdW
= NULL
;
5980 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5982 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
5983 if (DeviceInstanceIdW
== NULL
)
5986 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
5987 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
5989 MyFree(DeviceInstanceIdW
);
5995 /***********************************************************************
5996 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
5999 SetupDiOpenDeviceInfoW(
6000 IN HDEVINFO DeviceInfoSet
,
6001 IN PCWSTR DeviceInstanceId
,
6002 IN HWND hwndParent OPTIONAL
,
6004 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6006 struct DeviceInfoSet
*list
;
6007 HKEY hEnumKey
, hKey
;
6011 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
6013 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
6014 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
6017 SetLastError(ERROR_INVALID_HANDLE
);
6018 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6019 SetLastError(ERROR_INVALID_HANDLE
);
6020 else if (!DeviceInstanceId
)
6021 SetLastError(ERROR_INVALID_PARAMETER
);
6022 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
6024 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
6025 SetLastError(ERROR_INVALID_FLAGS
);
6027 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6028 SetLastError(ERROR_INVALID_USER_BUFFER
);
6031 struct DeviceInfoElement
*deviceInfo
= NULL
;
6032 /* Search if device already exists in DeviceInfoSet.
6033 * If yes, return the existing element
6034 * If no, create a new element using informations in registry
6036 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
6037 while (ItemList
!= &list
->ListHead
)
6042 FIXME("not implemented\n");
6043 ItemList
= ItemList
->Flink
;
6048 /* good one found */
6053 /* Open supposed registry key */
6056 REGSTR_PATH_SYSTEMENUM
,
6060 if (rc
!= ERROR_SUCCESS
)
6071 RegCloseKey(hEnumKey
);
6072 if (rc
!= ERROR_SUCCESS
)
6074 if (rc
== ERROR_FILE_NOT_FOUND
)
6075 rc
= ERROR_NO_SUCH_DEVINST
;
6080 /* FIXME: try to get ClassGUID from registry, instead of
6081 * sending GUID_NULL to CreateDeviceInfoElement
6083 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
6088 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
6094 if (ret
&& deviceInfo
&& DeviceInfoData
)
6096 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
6097 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
6098 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
6106 /***********************************************************************
6107 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6110 SetupDiEnumDriverInfoA(
6111 IN HDEVINFO DeviceInfoSet
,
6112 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6113 IN DWORD DriverType
,
6114 IN DWORD MemberIndex
,
6115 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6117 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6120 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6121 DriverType
, MemberIndex
, DriverInfoData
);
6123 if (DriverInfoData
== NULL
)
6124 SetLastError(ERROR_INVALID_PARAMETER
);
6125 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6126 SetLastError(ERROR_INVALID_USER_BUFFER
);
6129 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6130 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
6131 DriverType
, MemberIndex
, &driverInfoData2W
);
6135 /* Do W->A conversion */
6136 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6137 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6138 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6139 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6141 DriverInfoData
->Description
[0] = '\0';
6144 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6145 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6147 DriverInfoData
->MfgName
[0] = '\0';
6150 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6151 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6153 DriverInfoData
->ProviderName
[0] = '\0';
6156 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6158 /* Copy more fields */
6159 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6160 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6165 TRACE("Returning %d\n", ret
);
6170 /***********************************************************************
6171 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6174 SetupDiEnumDriverInfoW(
6175 IN HDEVINFO DeviceInfoSet
,
6176 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6177 IN DWORD DriverType
,
6178 IN DWORD MemberIndex
,
6179 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6181 PLIST_ENTRY ListHead
;
6184 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6185 DriverType
, MemberIndex
, DriverInfoData
);
6187 if (!DeviceInfoSet
|| !DriverInfoData
)
6188 SetLastError(ERROR_INVALID_PARAMETER
);
6189 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6190 SetLastError(ERROR_INVALID_HANDLE
);
6191 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6192 SetLastError(ERROR_INVALID_HANDLE
);
6193 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6194 SetLastError(ERROR_INVALID_PARAMETER
);
6195 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
6196 SetLastError(ERROR_INVALID_PARAMETER
);
6197 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6198 SetLastError(ERROR_INVALID_PARAMETER
);
6199 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6200 SetLastError(ERROR_INVALID_USER_BUFFER
);
6203 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6204 PLIST_ENTRY ItemList
;
6205 if (DriverType
== SPDIT_CLASSDRIVER
||
6206 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
6208 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6212 ListHead
= &devInfo
->DriverListHead
;
6215 ItemList
= ListHead
->Flink
;
6216 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
6217 ItemList
= ItemList
->Flink
;
6218 if (ItemList
== ListHead
)
6219 SetLastError(ERROR_NO_MORE_ITEMS
);
6222 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
6225 &DriverInfoData
->DriverType
,
6226 &DrvInfo
->Info
.DriverType
,
6227 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6232 TRACE("Returning %d\n", ret
);
6237 /***********************************************************************
6238 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6241 SetupDiGetSelectedDriverA(
6242 IN HDEVINFO DeviceInfoSet
,
6243 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6244 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6246 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6249 if (DriverInfoData
== NULL
)
6250 SetLastError(ERROR_INVALID_PARAMETER
);
6251 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6252 SetLastError(ERROR_INVALID_USER_BUFFER
);
6255 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6257 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
6263 /* Do W->A conversion */
6264 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6265 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6266 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6267 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6269 DriverInfoData
->Description
[0] = '\0';
6272 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6273 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6275 DriverInfoData
->MfgName
[0] = '\0';
6278 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6279 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6281 DriverInfoData
->ProviderName
[0] = '\0';
6284 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6286 /* Copy more fields */
6287 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6288 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6297 /***********************************************************************
6298 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6301 SetupDiGetSelectedDriverW(
6302 IN HDEVINFO DeviceInfoSet
,
6303 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6304 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6308 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6310 if (!DeviceInfoSet
|| !DriverInfoData
)
6311 SetLastError(ERROR_INVALID_PARAMETER
);
6312 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6313 SetLastError(ERROR_INVALID_HANDLE
);
6314 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6315 SetLastError(ERROR_INVALID_HANDLE
);
6316 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6317 SetLastError(ERROR_INVALID_USER_BUFFER
);
6318 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6319 SetLastError(ERROR_INVALID_USER_BUFFER
);
6322 SP_DEVINSTALL_PARAMS InstallParams
;
6324 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
6325 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6327 struct DriverInfoElement
*driverInfo
;
6328 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6329 if (driverInfo
== NULL
)
6330 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6334 &DriverInfoData
->DriverType
,
6335 &driverInfo
->Info
.DriverType
,
6336 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6342 TRACE("Returning %d\n", ret
);
6347 /***********************************************************************
6348 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6351 SetupDiSetSelectedDriverA(
6352 IN HDEVINFO DeviceInfoSet
,
6353 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6354 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6356 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6357 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6360 if (DriverInfoData
!= NULL
)
6362 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6363 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6365 SetLastError(ERROR_INVALID_PARAMETER
);
6369 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6370 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6372 if (DriverInfoDataW
.Reserved
== 0)
6374 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6376 /* convert the strings to unicode */
6377 if (!MultiByteToWideChar(CP_ACP
,
6379 DriverInfoData
->Description
,
6381 DriverInfoDataW
.Description
,
6383 !MultiByteToWideChar(CP_ACP
,
6385 DriverInfoData
->ProviderName
,
6387 DriverInfoDataW
.ProviderName
,
6394 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6397 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6401 if (ret
&& pDriverInfoDataW
!= NULL
)
6403 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6410 /***********************************************************************
6411 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6414 SetupDiSetSelectedDriverW(
6415 IN HDEVINFO DeviceInfoSet
,
6416 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6417 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6421 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6424 SetLastError(ERROR_INVALID_PARAMETER
);
6425 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6426 SetLastError(ERROR_INVALID_HANDLE
);
6427 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6428 SetLastError(ERROR_INVALID_HANDLE
);
6429 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6430 SetLastError(ERROR_INVALID_USER_BUFFER
);
6431 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6432 SetLastError(ERROR_INVALID_USER_BUFFER
);
6435 struct DriverInfoElement
**pDriverInfo
;
6436 PLIST_ENTRY ListHead
, ItemList
;
6440 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6441 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6445 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6446 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6449 if (!DriverInfoData
)
6451 *pDriverInfo
= NULL
;
6456 /* Search selected driver in list */
6457 ItemList
= ListHead
->Flink
;
6458 while (ItemList
!= ListHead
)
6460 if (DriverInfoData
->Reserved
!= 0)
6462 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6467 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6468 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
6469 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6470 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6471 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6477 if (ItemList
== ListHead
)
6478 SetLastError(ERROR_INVALID_PARAMETER
);
6481 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
6482 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6484 TRACE("Choosing driver whose rank is 0x%lx\n",
6485 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
6487 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6492 TRACE("Returning %d\n", ret
);
6496 /***********************************************************************
6497 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6500 SetupDiGetDriverInfoDetailA(
6501 IN HDEVINFO DeviceInfoSet
,
6502 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6503 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6504 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6505 IN DWORD DriverInfoDetailDataSize
,
6506 OUT PDWORD RequiredSize OPTIONAL
)
6508 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6509 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6511 DWORD HardwareIDLen
= 0;
6514 /* do some sanity checks, the unicode version might do more thorough checks */
6515 if (DriverInfoData
== NULL
||
6516 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6517 (DriverInfoDetailData
!= NULL
&&
6518 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6519 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6521 SetLastError(ERROR_INVALID_PARAMETER
);
6525 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6526 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6528 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6530 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6532 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6536 SetLastError(ERROR_INVALID_PARAMETER
);
6539 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6540 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6542 /* convert the strings to unicode */
6543 if (MultiByteToWideChar(CP_ACP
,
6545 DriverInfoData
->Description
,
6547 DriverInfoDataW
.Description
,
6549 MultiByteToWideChar(CP_ACP
,
6551 DriverInfoData
->MfgName
,
6553 DriverInfoDataW
.MfgName
,
6555 MultiByteToWideChar(CP_ACP
,
6557 DriverInfoData
->ProviderName
,
6559 DriverInfoDataW
.ProviderName
,
6562 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6564 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6565 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6568 if (DriverInfoDetailData
!= NULL
)
6570 /* calculate the unicode buffer size from the ansi buffer size */
6571 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6572 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6573 (HardwareIDLen
* sizeof(WCHAR
));
6575 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6576 if (DriverInfoDetailDataW
== NULL
)
6578 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6582 /* initialize the buffer */
6583 ZeroMemory(DriverInfoDetailDataW
,
6585 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6588 /* call the unicode version */
6589 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6592 DriverInfoDetailDataW
,
6598 if (DriverInfoDetailDataW
!= NULL
)
6600 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6601 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6602 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6603 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6604 if (WideCharToMultiByte(CP_ACP
,
6606 DriverInfoDetailDataW
->SectionName
,
6608 DriverInfoDetailData
->SectionName
,
6612 WideCharToMultiByte(CP_ACP
,
6614 DriverInfoDetailDataW
->InfFileName
,
6616 DriverInfoDetailData
->InfFileName
,
6620 WideCharToMultiByte(CP_ACP
,
6622 DriverInfoDetailDataW
->DrvDescription
,
6624 DriverInfoDetailData
->DrvDescription
,
6628 WideCharToMultiByte(CP_ACP
,
6630 DriverInfoDetailDataW
->HardwareID
,
6632 DriverInfoDetailData
->HardwareID
,
6638 DWORD hwidlen
= HardwareIDLen
;
6639 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6641 /* count the strings in the list */
6644 len
= lstrlenA(s
) + 1;
6653 /* looks like the string list wasn't terminated... */
6654 SetLastError(ERROR_INVALID_USER_BUFFER
);
6660 /* make sure CompatIDsOffset points to the second string in the
6664 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6665 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6666 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6670 DriverInfoDetailData
->CompatIDsOffset
= 0;
6671 DriverInfoDetailData
->CompatIDsLength
= 0;
6680 if (RequiredSize
!= NULL
)
6682 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6683 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6689 if (DriverInfoDetailDataW
!= NULL
)
6691 MyFree(DriverInfoDetailDataW
);
6697 /***********************************************************************
6698 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6701 SetupDiGetDriverInfoDetailW(
6702 IN HDEVINFO DeviceInfoSet
,
6703 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6704 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6705 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6706 IN DWORD DriverInfoDetailDataSize
,
6707 OUT PDWORD RequiredSize OPTIONAL
)
6711 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6712 DriverInfoData
, DriverInfoDetailData
,
6713 DriverInfoDetailDataSize
, RequiredSize
);
6716 SetLastError(ERROR_INVALID_PARAMETER
);
6717 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6718 SetLastError(ERROR_INVALID_HANDLE
);
6719 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6720 SetLastError(ERROR_INVALID_HANDLE
);
6721 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6722 SetLastError(ERROR_INVALID_USER_BUFFER
);
6723 else if (!DriverInfoData
)
6724 SetLastError(ERROR_INVALID_PARAMETER
);
6725 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6726 SetLastError(ERROR_INVALID_PARAMETER
);
6727 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6728 SetLastError(ERROR_INVALID_PARAMETER
);
6729 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6730 SetLastError(ERROR_INVALID_USER_BUFFER
);
6731 else if (DriverInfoData
->Reserved
== 0)
6732 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6735 struct DriverInfoElement
*driverInfoElement
;
6736 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6739 DriverInfoDetailData
,
6740 &driverInfoElement
->Details
,
6741 driverInfoElement
->Details
.cbSize
);
6742 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6743 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6748 TRACE("Returning %d\n", ret
);
6752 /* Return the current hardware profile id, or -1 if error */
6754 GetCurrentHwProfile(
6755 IN HDEVINFO DeviceInfoSet
)
6757 HKEY hKey
= INVALID_HANDLE_VALUE
;
6758 DWORD dwRegType
, dwLength
;
6761 DWORD ret
= (DWORD
)-1;
6764 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
6765 REGSTR_PATH_IDCONFIGDB
,
6769 if (rc
!= ERROR_SUCCESS
)
6775 dwLength
= sizeof(DWORD
);
6776 rc
= RegQueryValueExW(
6778 REGSTR_VAL_CURRENTCONFIG
,
6781 (LPBYTE
)&hwProfile
, &dwLength
);
6782 if (rc
!= ERROR_SUCCESS
)
6787 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6789 SetLastError(ERROR_GEN_FAILURE
);
6796 if (hKey
!= INVALID_HANDLE_VALUE
)
6804 IN HDEVINFO DeviceInfoSet
,
6805 IN PSP_DEVINFO_DATA DeviceInfoData
)
6807 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6808 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6811 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
6813 /* At the moment, I only know how to start local devices */
6814 SetLastError(ERROR_INVALID_COMPUTERNAME
);
6818 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
6819 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6820 SetLastError(RtlNtStatusToDosError(Status
));
6821 return NT_SUCCESS(Status
);
6824 static BOOL
StopDevice(
6825 IN HDEVINFO DeviceInfoSet
,
6826 IN PSP_DEVINFO_DATA DeviceInfoData
)
6828 FIXME("Stub %p %p\n", DeviceInfoSet
, DeviceInfoData
);
6832 /***********************************************************************
6833 * SetupDiChangeState (SETUPAPI.@)
6837 IN HDEVINFO DeviceInfoSet
,
6838 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6840 PSP_PROPCHANGE_PARAMS PropChange
;
6841 HKEY hKey
= INVALID_HANDLE_VALUE
;
6842 LPCWSTR RegistryValueName
;
6843 DWORD dwConfigFlags
, dwLength
, dwRegType
;
6847 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6849 if (!DeviceInfoData
)
6850 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
6852 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
6855 SetLastError(ERROR_INVALID_PARAMETER
);
6859 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
6860 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
6862 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
6864 switch (PropChange
->StateChange
)
6869 /* Enable/disable device in registry */
6870 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
6871 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6872 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
6873 if (hKey
== INVALID_HANDLE_VALUE
)
6875 dwLength
= sizeof(DWORD
);
6876 rc
= RegQueryValueExW(
6881 (LPBYTE
)&dwConfigFlags
, &dwLength
);
6882 if (rc
== ERROR_FILE_NOT_FOUND
)
6884 else if (rc
!= ERROR_SUCCESS
)
6889 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6891 SetLastError(ERROR_GEN_FAILURE
);
6894 if (PropChange
->StateChange
== DICS_ENABLE
)
6895 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6897 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6903 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
6904 if (rc
!= ERROR_SUCCESS
)
6910 /* Enable/disable device if needed */
6911 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
6912 || PropChange
->HwProfile
== 0
6913 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
6915 if (PropChange
->StateChange
== DICS_ENABLE
)
6916 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6918 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
6924 case DICS_PROPCHANGE
:
6926 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6931 FIXME("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
6932 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
6937 if (hKey
!= INVALID_HANDLE_VALUE
)
6940 TRACE("Returning %d\n", ret
);
6944 /***********************************************************************
6945 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
6948 SetupDiSelectBestCompatDrv(
6949 IN HDEVINFO DeviceInfoSet
,
6950 IN PSP_DEVINFO_DATA DeviceInfoData
)
6952 SP_DRVINFO_DATA_W drvInfoData
;
6955 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6957 /* Drivers are sorted by rank in the driver list, so
6958 * the first driver in the list is the best one.
6960 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
6961 ret
= SetupDiEnumDriverInfoW(
6965 0, /* Member index */
6970 ret
= SetupDiSetSelectedDriverW(
6976 TRACE("Returning %d\n", ret
);
6980 /***********************************************************************
6981 * SetupDiInstallDriverFiles (SETUPAPI.@)
6984 SetupDiInstallDriverFiles(
6985 IN HDEVINFO DeviceInfoSet
,
6986 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6990 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6993 SetLastError(ERROR_INVALID_PARAMETER
);
6994 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6995 SetLastError(ERROR_INVALID_HANDLE
);
6996 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6997 SetLastError(ERROR_INVALID_HANDLE
);
6998 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6999 SetLastError(ERROR_INVALID_USER_BUFFER
);
7000 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
7001 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7002 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
7003 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7006 SP_DEVINSTALL_PARAMS_W InstallParams
;
7007 struct DriverInfoElement
*SelectedDriver
;
7008 WCHAR SectionName
[MAX_PATH
];
7009 DWORD SectionNameLength
= 0;
7011 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7012 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7016 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7017 if (!SelectedDriver
)
7019 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7023 ret
= SetupDiGetActualSectionToInstallW(
7024 SelectedDriver
->InfFileDetails
->hInf
,
7025 SelectedDriver
->Details
.SectionName
,
7026 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7030 if (!InstallParams
.InstallMsgHandler
)
7032 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
7033 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7034 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7036 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7037 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7038 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7039 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7040 DeviceInfoSet
, DeviceInfoData
);
7044 TRACE("Returning %d\n", ret
);
7048 /***********************************************************************
7049 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7052 SetupDiRegisterCoDeviceInstallers(
7053 IN HDEVINFO DeviceInfoSet
,
7054 IN PSP_DEVINFO_DATA DeviceInfoData
)
7056 BOOL ret
= FALSE
; /* Return value */
7058 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7061 SetLastError(ERROR_INVALID_PARAMETER
);
7062 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7063 SetLastError(ERROR_INVALID_HANDLE
);
7064 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7065 SetLastError(ERROR_INVALID_HANDLE
);
7066 else if (!DeviceInfoData
)
7067 SetLastError(ERROR_INVALID_PARAMETER
);
7068 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7069 SetLastError(ERROR_INVALID_USER_BUFFER
);
7072 SP_DEVINSTALL_PARAMS_W InstallParams
;
7073 struct DriverInfoElement
*SelectedDriver
;
7076 WCHAR SectionName
[MAX_PATH
];
7077 DWORD SectionNameLength
= 0;
7078 HKEY hKey
= INVALID_HANDLE_VALUE
;
7080 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7081 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7085 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7086 if (SelectedDriver
== NULL
)
7088 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7092 /* Get .CoInstallers section name */
7093 Result
= SetupDiGetActualSectionToInstallW(
7094 SelectedDriver
->InfFileDetails
->hInf
,
7095 SelectedDriver
->Details
.SectionName
,
7096 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7097 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".CoInstallers") - 1)
7099 wcscat(SectionName
, L
".CoInstallers");
7101 /* Open/Create driver key information */
7102 #if _WIN32_WINNT >= 0x502
7103 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7105 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7107 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7108 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7109 if (hKey
== INVALID_HANDLE_VALUE
)
7112 /* Install .CoInstallers section */
7113 DoAction
= SPINST_REGISTRY
;
7114 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7116 DoAction
|= SPINST_FILES
;
7117 if (!InstallParams
.InstallMsgHandler
)
7119 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
7120 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7121 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7124 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7125 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7126 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7127 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7128 DeviceInfoSet
, DeviceInfoData
);
7135 if (hKey
!= INVALID_HANDLE_VALUE
)
7139 TRACE("Returning %d\n", ret
);
7143 /***********************************************************************
7144 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7147 SetupDiInstallDeviceInterfaces(
7148 IN HDEVINFO DeviceInfoSet
,
7149 IN PSP_DEVINFO_DATA DeviceInfoData
)
7151 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7153 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
7154 //SetLastError(ERROR_GEN_FAILURE);
7160 InfIsFromOEMLocation(
7162 OUT LPBOOL IsOEMLocation
)
7166 last
= strrchrW(FullName
, '\\');
7169 /* No directory specified */
7170 *IsOEMLocation
= FALSE
;
7174 WCHAR Windir
[MAX_PATH
];
7177 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
7178 if (ret
== 0 || ret
>= MAX_PATH
)
7180 SetLastError(ERROR_GEN_FAILURE
);
7184 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
7186 /* The path is %SYSTEMROOT%\Inf */
7187 *IsOEMLocation
= FALSE
;
7191 /* The file is in another place */
7192 *IsOEMLocation
= TRUE
;
7198 /***********************************************************************
7199 * SetupDiInstallDevice (SETUPAPI.@)
7202 SetupDiInstallDevice(
7203 IN HDEVINFO DeviceInfoSet
,
7204 IN PSP_DEVINFO_DATA DeviceInfoData
)
7206 SP_DEVINSTALL_PARAMS_W InstallParams
;
7207 struct DriverInfoElement
*SelectedDriver
;
7208 SYSTEMTIME DriverDate
;
7209 WCHAR SectionName
[MAX_PATH
];
7211 DWORD SectionNameLength
= 0;
7212 BOOL Result
= FALSE
;
7215 LPCWSTR AssociatedService
= NULL
;
7216 LPWSTR pSectionName
= NULL
;
7217 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
7219 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
7220 BOOL RebootRequired
= FALSE
;
7221 HKEY hKey
= INVALID_HANDLE_VALUE
;
7222 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
7223 BOOL NeedtoCopyFile
;
7224 LARGE_INTEGER fullVersion
;
7226 BOOL ret
= FALSE
; /* Return value */
7228 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7231 SetLastError(ERROR_INVALID_PARAMETER
);
7232 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7233 SetLastError(ERROR_INVALID_HANDLE
);
7234 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7235 SetLastError(ERROR_INVALID_HANDLE
);
7236 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7237 SetLastError(ERROR_INVALID_USER_BUFFER
);
7243 /* One parameter is bad */
7247 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7248 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7252 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
7254 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
7258 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7259 if (SelectedDriver
== NULL
)
7261 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7265 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
7267 Result
= SetupDiGetActualSectionToInstallW(
7268 SelectedDriver
->InfFileDetails
->hInf
,
7269 SelectedDriver
->Details
.SectionName
,
7270 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7271 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(DotServices
))
7273 pSectionName
= &SectionName
[wcslen(SectionName
)];
7275 /* Get information from [Version] section */
7276 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
7278 /* Format ClassGuid to a string */
7279 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
7281 RequiredSize
= lstrlenW(lpGuidString
);
7282 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
7283 if (!lpFullGuidString
)
7285 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7288 lpFullGuidString
[0] = '{';
7289 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
7290 lpFullGuidString
[RequiredSize
+ 1] = '}';
7291 lpFullGuidString
[RequiredSize
+ 2] = '\0';
7293 /* Open/Create driver key information */
7294 #if _WIN32_WINNT >= 0x502
7295 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7297 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7299 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7300 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7301 if (hKey
== INVALID_HANDLE_VALUE
)
7304 /* Install main section */
7305 DoAction
= SPINST_REGISTRY
;
7306 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7308 DoAction
|= SPINST_FILES
;
7309 if (!InstallParams
.InstallMsgHandler
)
7311 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
7312 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7313 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7316 *pSectionName
= '\0';
7317 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7318 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7319 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7320 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7321 DeviceInfoSet
, DeviceInfoData
);
7324 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
7326 if (Result
&& InstallParams
.InstallMsgHandler
== SetupDefaultQueueCallbackW
)
7328 /* Delete resources allocated by SetupInitDefaultQueueCallback */
7329 SetupTermDefaultQueueCallback(InstallParams
.InstallMsgHandlerContext
);
7332 InstallParams
.Flags
|= DI_NOFILECOPY
;
7333 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7335 /* Write information to driver key */
7336 *pSectionName
= UNICODE_NULL
;
7337 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
7338 TRACE("Write information to driver key\n");
7339 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7340 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7341 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7342 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
7343 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
7344 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
7345 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
7346 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
7347 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7348 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7349 if (rc
== ERROR_SUCCESS
)
7350 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7351 if (rc
== ERROR_SUCCESS
)
7352 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7353 if (rc
== ERROR_SUCCESS
)
7355 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7356 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7358 if (rc
== ERROR_SUCCESS
)
7359 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7360 if (rc
== ERROR_SUCCESS
)
7361 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7362 if (rc
== ERROR_SUCCESS
)
7363 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7364 if (rc
== ERROR_SUCCESS
)
7365 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7366 if (rc
== ERROR_SUCCESS
)
7367 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7368 if (rc
!= ERROR_SUCCESS
)
7374 hKey
= INVALID_HANDLE_VALUE
;
7376 /* FIXME: Process .LogConfigOverride section */
7378 /* Install .Services section */
7379 wcscpy(pSectionName
, DotServices
);
7380 Result
= InstallServicesSection(
7381 SelectedDriver
->InfFileDetails
->hInf
,
7390 /* Copy .inf file to Inf\ directory (if needed) */
7391 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7396 Result
= SetupCopyOEMInfW(
7397 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7400 SP_COPY_NOOVERWRITE
,
7406 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7407 * to release use of current InfFile */
7410 /* Open device registry key */
7411 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7412 if (hKey
== INVALID_HANDLE_VALUE
)
7415 /* Install .HW section */
7416 wcscpy(pSectionName
, L
".HW");
7417 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7418 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7419 SPINST_REGISTRY
, hKey
, NULL
, 0,
7420 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7421 DeviceInfoSet
, DeviceInfoData
);
7425 /* Write information to enum key */
7426 TRACE("Write information to enum key\n");
7427 TRACE("Class : '%S'\n", ClassName
);
7428 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
7429 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7430 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
7431 TRACE("Service : '%S'\n", AssociatedService
);
7432 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
7433 if (rc
== ERROR_SUCCESS
)
7434 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7435 if (rc
== ERROR_SUCCESS
)
7436 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7437 if (rc
== ERROR_SUCCESS
)
7438 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7439 if (rc
== ERROR_SUCCESS
&& AssociatedService
&& *AssociatedService
)
7440 rc
= RegSetValueEx(hKey
, REGSTR_VAL_SERVICE
, 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
7441 if (rc
!= ERROR_SUCCESS
)
7447 /* Start the device */
7448 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7449 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7454 /* End of installation */
7455 if (hClassKey
!= INVALID_HANDLE_VALUE
)
7456 RegCloseKey(hClassKey
);
7457 if (hKey
!= INVALID_HANDLE_VALUE
)
7460 RpcStringFreeW(&lpGuidString
);
7461 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
7462 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7464 TRACE("Returning %d\n", ret
);