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 Control
[] = {'C','o','n','t','r','o','l',0};
32 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
33 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
34 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
35 static const WCHAR InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
36 static const WCHAR Linked
[] = {'L','i','n','k','e','d',0};
37 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
38 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
40 /* FIXME: header mess */
41 DEFINE_GUID(GUID_NULL
,
42 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
44 (CALLBACK
* CLASS_INSTALL_PROC
) (
45 IN DI_FUNCTION InstallFunction
,
46 IN HDEVINFO DeviceInfoSet
,
47 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
49 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
50 IN HDEVINFO DeviceInfoSet
,
51 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
53 (CALLBACK
* COINSTALLER_PROC
) (
54 IN DI_FUNCTION InstallFunction
,
55 IN HDEVINFO DeviceInfoSet
,
56 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
57 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
59 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
60 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
61 IN LPFNADDPROPSHEETPAGE fAddFunc
,
64 (*UPDATE_CLASS_PARAM_HANDLER
) (
65 IN HDEVINFO DeviceInfoSet
,
66 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
67 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
68 IN DWORD ClassInstallParamsSize
);
70 struct CoInstallerElement
75 COINSTALLER_PROC Function
;
76 BOOL DoPostProcessing
;
81 PropertyChangeHandler(
82 IN HDEVINFO DeviceInfoSet
,
83 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
84 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
85 IN DWORD ClassInstallParamsSize
);
87 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
88 NULL
, /* DIF_SELECTDEVICE */
89 NULL
, /* DIF_INSTALLDEVICE */
90 NULL
, /* DIF_ASSIGNRESOURCES */
91 NULL
, /* DIF_PROPERTIES */
92 NULL
, /* DIF_REMOVE */
93 NULL
, /* DIF_FIRSTTIMESETUP */
94 NULL
, /* DIF_FOUNDDEVICE */
95 NULL
, /* DIF_SELECTCLASSDRIVERS */
96 NULL
, /* DIF_VALIDATECLASSDRIVERS */
97 NULL
, /* DIF_INSTALLCLASSDRIVERS */
98 NULL
, /* DIF_CALCDISKSPACE */
99 NULL
, /* DIF_DESTROYPRIVATEDATA */
100 NULL
, /* DIF_VALIDATEDRIVER */
101 NULL
, /* DIF_MOVEDEVICE */
102 NULL
, /* DIF_DETECT */
103 NULL
, /* DIF_INSTALLWIZARD */
104 NULL
, /* DIF_DESTROYWIZARDDATA */
105 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
106 NULL
, /* DIF_ENABLECLASS */
107 NULL
, /* DIF_DETECTVERIFY */
108 NULL
, /* DIF_INSTALLDEVICEFILES */
109 NULL
, /* DIF_UNREMOVE */
110 NULL
, /* DIF_SELECTBESTCOMPATDRV */
111 NULL
, /* DIF_ALLOW_INSTALL */
112 NULL
, /* DIF_REGISTERDEVICE */
113 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
114 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
115 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
116 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
117 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
118 NULL
, /* DIF_UNUSED1 */
119 NULL
, /* DIF_INSTALLINTERFACES */
120 NULL
, /* DIF_DETECTCANCEL */
121 NULL
, /* DIF_REGISTER_COINSTALLERS */
122 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
123 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
124 NULL
, /* DIF_RESERVED1 */
125 NULL
, /* DIF_TROUBLESHOOTER */
126 NULL
, /* DIF_POWERMESSAGEWAKE */
127 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
128 NULL
, /* DIF_UPDATEDRIVER_UI */
129 NULL
/* DIF_RESERVED2 */
132 /***********************************************************************
133 * SetupDiBuildClassInfoList (SETUPAPI.@)
135 BOOL WINAPI
SetupDiBuildClassInfoList(
137 LPGUID ClassGuidList
,
138 DWORD ClassGuidListSize
,
142 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
143 ClassGuidListSize
, RequiredSize
,
147 /***********************************************************************
148 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
150 BOOL WINAPI
SetupDiBuildClassInfoListExA(
152 LPGUID ClassGuidList
,
153 DWORD ClassGuidListSize
,
158 LPWSTR MachineNameW
= NULL
;
165 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
166 if (MachineNameW
== NULL
) return FALSE
;
169 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
170 ClassGuidListSize
, RequiredSize
,
171 MachineNameW
, Reserved
);
174 MyFree(MachineNameW
);
179 /***********************************************************************
180 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
182 BOOL WINAPI
SetupDiBuildClassInfoListExW(
184 LPGUID ClassGuidList
,
185 DWORD ClassGuidListSize
,
190 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
196 DWORD dwGuidListIndex
= 0;
198 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
199 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
201 if (RequiredSize
!= NULL
)
204 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
205 KEY_ENUMERATE_SUB_KEYS
,
209 if (hClassesKey
== INVALID_HANDLE_VALUE
)
214 for (dwIndex
= 0; ; dwIndex
++)
216 dwLength
= MAX_GUID_STRING_LEN
+ 1;
217 lError
= RegEnumKeyExW(hClassesKey
,
225 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
226 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
228 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
230 if (RegOpenKeyExW(hClassesKey
,
236 RegCloseKey(hClassesKey
);
240 if (!RegQueryValueExW(hClassKey
,
241 REGSTR_VAL_NOUSECLASS
,
247 TRACE("'NoUseClass' value found!\n");
248 RegCloseKey(hClassKey
);
252 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
253 (!RegQueryValueExW(hClassKey
,
254 REGSTR_VAL_NOINSTALLCLASS
,
260 TRACE("'NoInstallClass' value found!\n");
261 RegCloseKey(hClassKey
);
265 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
266 (!RegQueryValueExW(hClassKey
,
267 REGSTR_VAL_NODISPLAYCLASS
,
273 TRACE("'NoDisplayClass' value found!\n");
274 RegCloseKey(hClassKey
);
278 RegCloseKey(hClassKey
);
280 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
281 if (dwGuidListIndex
< ClassGuidListSize
)
283 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
287 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
289 UuidFromStringW(&szKeyName
[1],
290 &ClassGuidList
[dwGuidListIndex
]);
296 if (lError
!= ERROR_SUCCESS
)
300 RegCloseKey(hClassesKey
);
302 if (RequiredSize
!= NULL
)
303 *RequiredSize
= dwGuidListIndex
;
305 if (ClassGuidListSize
< dwGuidListIndex
)
307 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
314 /***********************************************************************
315 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
317 BOOL WINAPI
SetupDiClassGuidsFromNameA(
319 LPGUID ClassGuidList
,
320 DWORD ClassGuidListSize
,
323 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
324 ClassGuidListSize
, RequiredSize
,
328 /***********************************************************************
329 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
331 BOOL WINAPI
SetupDiClassGuidsFromNameW(
333 LPGUID ClassGuidList
,
334 DWORD ClassGuidListSize
,
337 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
338 ClassGuidListSize
, RequiredSize
,
342 /***********************************************************************
343 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
345 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
347 LPGUID ClassGuidList
,
348 DWORD ClassGuidListSize
,
353 LPWSTR ClassNameW
= NULL
;
354 LPWSTR MachineNameW
= NULL
;
359 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
360 if (ClassNameW
== NULL
)
365 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
366 if (MachineNameW
== NULL
)
373 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
374 ClassGuidListSize
, RequiredSize
,
375 MachineNameW
, Reserved
);
378 MyFree(MachineNameW
);
385 /***********************************************************************
386 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
388 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
390 LPGUID ClassGuidList
,
391 DWORD ClassGuidListSize
,
396 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
397 WCHAR szClassName
[256];
403 DWORD dwGuidListIndex
= 0;
405 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
406 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
408 if (RequiredSize
!= NULL
)
411 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
412 KEY_ENUMERATE_SUB_KEYS
,
416 if (hClassesKey
== INVALID_HANDLE_VALUE
)
421 for (dwIndex
= 0; ; dwIndex
++)
423 dwLength
= MAX_GUID_STRING_LEN
+ 1;
424 lError
= RegEnumKeyExW(hClassesKey
,
432 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
433 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
435 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
437 if (RegOpenKeyExW(hClassesKey
,
443 RegCloseKey(hClassesKey
);
447 dwLength
= 256 * sizeof(WCHAR
);
448 if (!RegQueryValueExW(hClassKey
,
455 TRACE("Class name: %s\n", debugstr_w(szClassName
));
457 if (strcmpiW(szClassName
, ClassName
) == 0)
459 TRACE("Found matching class name\n");
461 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
462 if (dwGuidListIndex
< ClassGuidListSize
)
464 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
468 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
470 UuidFromStringW(&szKeyName
[1],
471 &ClassGuidList
[dwGuidListIndex
]);
478 RegCloseKey(hClassKey
);
481 if (lError
!= ERROR_SUCCESS
)
485 RegCloseKey(hClassesKey
);
487 if (RequiredSize
!= NULL
)
488 *RequiredSize
= dwGuidListIndex
;
490 if (ClassGuidListSize
< dwGuidListIndex
)
492 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
499 /***********************************************************************
500 * SetupDiClassNameFromGuidA (SETUPAPI.@)
502 BOOL WINAPI
SetupDiClassNameFromGuidA(
503 const GUID
* ClassGuid
,
508 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
509 ClassNameSize
, RequiredSize
,
513 /***********************************************************************
514 * SetupDiClassNameFromGuidW (SETUPAPI.@)
516 BOOL WINAPI
SetupDiClassNameFromGuidW(
517 const GUID
* ClassGuid
,
522 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
523 ClassNameSize
, RequiredSize
,
527 /***********************************************************************
528 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
530 BOOL WINAPI
SetupDiClassNameFromGuidExA(
531 const GUID
* ClassGuid
,
538 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
539 LPWSTR MachineNameW
= NULL
;
543 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
544 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
545 NULL
, MachineNameW
, Reserved
);
548 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
549 ClassNameSize
, NULL
, NULL
);
551 if (!ClassNameSize
&& RequiredSize
)
554 MyFree(MachineNameW
);
558 /***********************************************************************
559 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
561 BOOL WINAPI
SetupDiClassNameFromGuidExW(
562 const GUID
* ClassGuid
,
573 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
574 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
576 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
581 if (hKey
== INVALID_HANDLE_VALUE
)
586 if (RequiredSize
!= NULL
)
589 rc
= RegQueryValueExW(hKey
,
595 if (rc
!= ERROR_SUCCESS
)
602 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
605 dwLength
= ClassNameSize
* sizeof(WCHAR
);
606 rc
= RegQueryValueExW(hKey
,
612 if (rc
!= ERROR_SUCCESS
)
624 /***********************************************************************
625 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
628 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
631 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
634 /***********************************************************************
635 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
638 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
643 LPWSTR MachineNameW
= NULL
;
646 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
647 debugstr_a(MachineName
), Reserved
);
651 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
652 if (MachineNameW
== NULL
)
653 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
656 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
657 MachineNameW
, Reserved
);
660 MyFree(MachineNameW
);
666 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
670 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
671 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
672 case CR_SUCCESS
: return ERROR_SUCCESS
;
675 return ERROR_GEN_FAILURE
;
678 /* Does not happen */
681 /***********************************************************************
682 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
685 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
690 struct DeviceInfoSet
*list
;
691 LPWSTR UNCServerName
= NULL
;
695 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
697 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
698 debugstr_w(MachineName
), Reserved
);
700 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
702 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
703 list
= HeapAlloc(GetProcessHeap(), 0, size
);
706 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
709 memset(list
, 0, sizeof(struct DeviceInfoSet
));
711 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
714 ClassGuid
? ClassGuid
: &GUID_NULL
,
715 sizeof(list
->ClassGuid
));
716 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
717 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
718 list
->InstallParams
.hwndParent
= hwndParent
;
721 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
722 if (rc
!= ERROR_SUCCESS
)
727 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
730 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
734 strcpyW(UNCServerName
+ 2, MachineName
);
735 list
->szData
[0] = list
->szData
[1] = '\\';
736 strcpyW(list
->szData
+ 2, MachineName
);
737 list
->MachineName
= list
->szData
;
741 DWORD Size
= MAX_PATH
;
742 list
->HKLM
= HKEY_LOCAL_MACHINE
;
743 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
746 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
749 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
751 list
->MachineName
= NULL
;
754 UNCServerName
[0] = UNCServerName
[1] = '\\';
755 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
756 if (cr
!= CR_SUCCESS
)
758 SetLastError(GetErrorCodeFromCrCode(cr
));
762 InitializeListHead(&list
->DriverListHead
);
763 InitializeListHead(&list
->ListHead
);
765 ret
= (HDEVINFO
)list
;
768 if (ret
== INVALID_HANDLE_VALUE
)
770 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
771 RegCloseKey(list
->HKLM
);
772 HeapFree(GetProcessHeap(), 0, list
);
774 HeapFree(GetProcessHeap(), 0, UNCServerName
);
778 /***********************************************************************
779 * SetupDiEnumDeviceInfo (SETUPAPI.@)
781 BOOL WINAPI
SetupDiEnumDeviceInfo(
782 HDEVINFO DeviceInfoSet
,
784 PSP_DEVINFO_DATA DeviceInfoData
)
788 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
790 SetLastError(ERROR_INVALID_PARAMETER
);
791 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
793 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
795 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
796 SetLastError(ERROR_INVALID_HANDLE
);
797 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
798 SetLastError(ERROR_INVALID_USER_BUFFER
);
801 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
802 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
803 ItemList
= ItemList
->Flink
;
804 if (ItemList
== &list
->ListHead
)
805 SetLastError(ERROR_NO_MORE_ITEMS
);
808 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
809 memcpy(&DeviceInfoData
->ClassGuid
,
812 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
813 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
819 SetLastError(ERROR_INVALID_HANDLE
);
823 /***********************************************************************
824 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
827 SetupDiGetActualSectionToInstallA(
829 IN PCSTR InfSectionName
,
830 OUT PSTR InfSectionWithExt OPTIONAL
,
831 IN DWORD InfSectionWithExtSize
,
832 OUT PDWORD RequiredSize OPTIONAL
,
833 OUT PSTR
*Extension OPTIONAL
)
835 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
836 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
840 /***********************************************************************
841 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
844 SetupDiGetActualSectionToInstallW(
846 IN PCWSTR InfSectionName
,
847 OUT PWSTR InfSectionWithExt OPTIONAL
,
848 IN DWORD InfSectionWithExtSize
,
849 OUT PDWORD RequiredSize OPTIONAL
,
850 OUT PWSTR
*Extension OPTIONAL
)
852 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
853 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
857 /***********************************************************************
858 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
861 SetupDiGetActualSectionToInstallExA(
863 IN PCSTR InfSectionName
,
864 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
865 OUT PSTR InfSectionWithExt OPTIONAL
,
866 IN DWORD InfSectionWithExtSize
,
867 OUT PDWORD RequiredSize OPTIONAL
,
868 OUT PSTR
* Extension OPTIONAL
,
871 LPWSTR InfSectionNameW
= NULL
;
872 LPWSTR InfSectionWithExtW
= NULL
;
874 BOOL bResult
= FALSE
;
880 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
881 if (InfSectionNameW
== NULL
)
884 if (InfSectionWithExt
)
886 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
887 if (InfSectionWithExtW
== NULL
)
891 bResult
= SetupDiGetActualSectionToInstallExW(
892 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
893 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
894 InfSectionWithExtSize
,
896 Extension
? &ExtensionW
: NULL
,
899 if (bResult
&& InfSectionWithExt
)
901 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
902 InfSectionWithExtSize
, NULL
, NULL
) != 0;
904 if (bResult
&& Extension
)
906 if (ExtensionW
== NULL
)
909 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
913 MyFree(InfSectionNameW
);
914 MyFree(InfSectionWithExtW
);
919 /***********************************************************************
920 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
923 SetupDiGetActualSectionToInstallExW(
925 IN PCWSTR InfSectionName
,
926 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
927 OUT PWSTR InfSectionWithExt OPTIONAL
,
928 IN DWORD InfSectionWithExtSize
,
929 OUT PDWORD RequiredSize OPTIONAL
,
930 OUT PWSTR
* Extension OPTIONAL
,
935 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
936 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
937 RequiredSize
, Extension
, Reserved
);
939 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
940 SetLastError(ERROR_INVALID_HANDLE
);
941 else if (!InfSectionName
)
942 SetLastError(ERROR_INVALID_PARAMETER
);
943 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
944 SetLastError(ERROR_INVALID_USER_BUFFER
);
945 else if (Reserved
!= NULL
)
946 SetLastError(ERROR_INVALID_PARAMETER
);
949 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
950 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
951 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
952 WCHAR SectionName
[LINE_LEN
+ 1];
953 LONG lLineCount
= -1;
956 /* Fill platform info if needed */
957 if (AlternatePlatformInfo
)
958 pPlatformInfo
= AlternatePlatformInfo
;
959 else if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
961 /* That's the first time we go here. We need to fill in the structure */
962 OSVERSIONINFO VersionInfo
;
963 SYSTEM_INFO SystemInfo
;
964 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
965 ret
= GetVersionEx(&VersionInfo
);
968 GetSystemInfo(&SystemInfo
);
969 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
970 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
971 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
972 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
973 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
974 CurrentPlatform
.Reserved
= 0;
977 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
978 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
979 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
981 static const WCHAR ExtensionArchitectureNone
[] = {0};
982 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
983 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
984 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
986 /* Set various extensions values */
987 switch (pPlatformInfo
->Platform
)
989 case VER_PLATFORM_WIN32_WINDOWS
:
990 pExtensionPlatform
= ExtensionPlatformWindows
;
992 case VER_PLATFORM_WIN32_NT
:
993 pExtensionPlatform
= ExtensionPlatformNT
;
996 pExtensionPlatform
= ExtensionPlatformNone
;
999 switch (pPlatformInfo
->ProcessorArchitecture
)
1001 case PROCESSOR_ARCHITECTURE_AMD64
:
1002 pExtensionArchitecture
= ExtensionArchitectureamd64
;
1004 case PROCESSOR_ARCHITECTURE_INTEL
:
1005 pExtensionArchitecture
= ExtensionArchitecturex86
;
1007 case PROCESSOR_ARCHITECTURE_PPC
:
1008 pExtensionArchitecture
= ExtensionArchitectureppc
;
1011 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo
->ProcessorArchitecture
);
1012 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
1013 pExtensionArchitecture
= ExtensionArchitectureNone
;
1017 SectionName
[LINE_LEN
] = UNICODE_NULL
;
1019 /* Test with platform.architecture.major.minor extension */
1020 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s.%lu.%lu", InfSectionName
,
1021 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1022 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1023 if (lLineCount
!= -1) goto sectionfound
;
1025 /* Test with platform.major.minor extension */
1026 snprintfW(SectionName
, LINE_LEN
, L
"%s%s.%lu.%lu", InfSectionName
,
1027 pExtensionPlatform
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1028 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1029 if (lLineCount
!= -1) goto sectionfound
;
1031 /* Test with platform.architecture.major extension */
1032 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s.%lu", InfSectionName
,
1033 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
);
1034 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1035 if (lLineCount
!= -1) goto sectionfound
;
1037 /* Test with platform.major extension */
1038 snprintfW(SectionName
, LINE_LEN
, L
"%s%s.%lu", InfSectionName
,
1039 pExtensionPlatform
, pPlatformInfo
->MajorVersion
);
1040 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1041 if (lLineCount
!= -1) goto sectionfound
;
1043 /* Test with platform.architecture extension */
1044 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s", InfSectionName
,
1045 pExtensionPlatform
, pExtensionArchitecture
);
1046 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1047 if (lLineCount
!= -1) goto sectionfound
;
1049 /* Test with platform extension */
1050 snprintfW(SectionName
, LINE_LEN
, L
"%s%s", InfSectionName
,
1051 pExtensionPlatform
);
1052 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1053 if (lLineCount
!= -1) goto sectionfound
;
1055 /* Test without extension */
1056 snprintfW(SectionName
, LINE_LEN
, L
"%s", InfSectionName
);
1057 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1058 if (lLineCount
!= -1) goto sectionfound
;
1060 /* No appropriate section found */
1061 SetLastError(ERROR_INVALID_PARAMETER
);
1065 dwFullLength
= lstrlenW(SectionName
);
1066 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
1068 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
1070 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1074 lstrcpyW(InfSectionWithExt
, SectionName
);
1075 if (Extension
!= NULL
)
1077 DWORD dwLength
= lstrlenW(SectionName
);
1078 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1082 if (RequiredSize
!= NULL
)
1083 *RequiredSize
= dwFullLength
+ 1;
1089 TRACE("Returning %d\n", ret
);
1094 /***********************************************************************
1095 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1097 BOOL WINAPI
SetupDiGetClassDescriptionA(
1098 const GUID
* ClassGuid
,
1099 PSTR ClassDescription
,
1100 DWORD ClassDescriptionSize
,
1101 PDWORD RequiredSize
)
1103 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1104 ClassDescriptionSize
,
1105 RequiredSize
, NULL
, NULL
);
1108 /***********************************************************************
1109 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1111 BOOL WINAPI
SetupDiGetClassDescriptionW(
1112 const GUID
* ClassGuid
,
1113 PWSTR ClassDescription
,
1114 DWORD ClassDescriptionSize
,
1115 PDWORD RequiredSize
)
1117 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1118 ClassDescriptionSize
,
1119 RequiredSize
, NULL
, NULL
);
1122 /***********************************************************************
1123 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1125 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1126 const GUID
* ClassGuid
,
1127 PSTR ClassDescription
,
1128 DWORD ClassDescriptionSize
,
1129 PDWORD RequiredSize
,
1133 PWCHAR ClassDescriptionW
;
1134 LPWSTR MachineNameW
= NULL
;
1138 if (ClassDescriptionSize
> 0)
1140 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1141 if (!ClassDescriptionW
)
1143 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1149 ClassDescriptionW
= NULL
;
1153 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1156 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1162 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1163 NULL
, MachineNameW
, Reserved
);
1166 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1167 ClassDescriptionSize
, NULL
, NULL
);
1169 if (!ClassDescriptionSize
&& RequiredSize
)
1170 *RequiredSize
= len
;
1174 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1175 MyFree(MachineNameW
);
1179 /***********************************************************************
1180 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1182 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1183 const GUID
* ClassGuid
,
1184 PWSTR ClassDescription
,
1185 DWORD ClassDescriptionSize
,
1186 PDWORD RequiredSize
,
1193 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1194 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1196 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1201 if (hKey
== INVALID_HANDLE_VALUE
)
1203 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1207 if (RequiredSize
!= NULL
)
1210 if (RegQueryValueExW(hKey
,
1221 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1224 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1225 if (RegQueryValueExW(hKey
,
1229 (LPBYTE
)ClassDescription
,
1241 /***********************************************************************
1242 * SetupDiGetClassDevsA (SETUPAPI.@)
1244 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1250 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1251 flags
, NULL
, NULL
, NULL
);
1254 /***********************************************************************
1255 * SetupDiGetClassDevsW (SETUPAPI.@)
1257 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1263 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1264 flags
, NULL
, NULL
, NULL
);
1267 /***********************************************************************
1268 * SetupDiGetClassDevsExA (SETUPAPI.@)
1270 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1280 LPWSTR enumstrW
= NULL
;
1281 LPWSTR machineW
= NULL
;
1285 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1286 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1289 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1292 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1296 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1297 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1300 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1303 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1305 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1308 HeapFree(GetProcessHeap(), 0, enumstrW
);
1309 HeapFree(GetProcessHeap(), 0, machineW
);
1314 CreateDeviceInfoElement(
1315 IN
struct DeviceInfoSet
*list
,
1316 IN LPCWSTR InstancePath
,
1317 IN LPCGUID pClassGuid
,
1318 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1322 struct DeviceInfoElement
*deviceInfo
;
1324 *pDeviceInfo
= NULL
;
1326 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1327 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1330 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1333 memset(deviceInfo
, 0, size
);
1335 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1336 if (cr
!= CR_SUCCESS
)
1338 SetLastError(GetErrorCodeFromCrCode(cr
));
1342 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1343 wcscpy(deviceInfo
->Data
, InstancePath
);
1344 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1345 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1346 deviceInfo
->DeviceDescription
= NULL
;
1347 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1348 deviceInfo
->CreationFlags
= 0;
1349 InitializeListHead(&deviceInfo
->DriverListHead
);
1350 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1352 *pDeviceInfo
= deviceInfo
;
1357 CreateDeviceInterface(
1358 IN
struct DeviceInfoElement
* deviceInfo
,
1359 IN LPCWSTR SymbolicLink
,
1360 IN LPCGUID pInterfaceGuid
,
1361 OUT
struct DeviceInterface
**pDeviceInterface
)
1363 struct DeviceInterface
*deviceInterface
;
1365 *pDeviceInterface
= NULL
;
1367 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1368 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1369 if (!deviceInterface
)
1371 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1374 deviceInterface
->DeviceInfo
= deviceInfo
;
1375 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1376 deviceInterface
->Flags
= 0; /* FIXME */
1377 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1379 *pDeviceInterface
= deviceInterface
;
1383 static LONG
SETUP_CreateDevListFromEnumerator(
1384 struct DeviceInfoSet
*list
,
1385 LPCGUID pClassGuid OPTIONAL
,
1387 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1389 HKEY hDeviceIdKey
, hInstanceIdKey
;
1390 WCHAR KeyBuffer
[MAX_PATH
];
1391 WCHAR InstancePath
[MAX_PATH
];
1392 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1393 struct DeviceInfoElement
*deviceInfo
;
1395 DWORD dwLength
, dwRegType
;
1398 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1401 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1402 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1403 if (rc
== ERROR_NO_MORE_ITEMS
)
1405 if (rc
!= ERROR_SUCCESS
)
1409 /* Open device id sub key */
1410 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1411 if (rc
!= ERROR_SUCCESS
)
1413 wcscpy(InstancePath
, Enumerator
);
1414 wcscat(InstancePath
, L
"\\");
1415 wcscat(InstancePath
, KeyBuffer
);
1416 wcscat(InstancePath
, L
"\\");
1417 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1419 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1425 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1426 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1427 if (rc
== ERROR_NO_MORE_ITEMS
)
1429 if (rc
!= ERROR_SUCCESS
)
1431 RegCloseKey(hDeviceIdKey
);
1436 /* Open instance id sub key */
1437 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1438 if (rc
!= ERROR_SUCCESS
)
1440 RegCloseKey(hDeviceIdKey
);
1443 *pEndOfInstancePath
= '\0';
1444 wcscat(InstancePath
, KeyBuffer
);
1446 /* Read ClassGUID value */
1447 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1448 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1449 RegCloseKey(hInstanceIdKey
);
1450 if (rc
== ERROR_FILE_NOT_FOUND
)
1453 /* Skip this bad entry as we can't verify it */
1455 /* Set a default GUID for this device */
1456 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1458 else if (rc
!= ERROR_SUCCESS
)
1460 RegCloseKey(hDeviceIdKey
);
1463 else if (dwRegType
!= REG_SZ
)
1465 RegCloseKey(hDeviceIdKey
);
1466 return ERROR_GEN_FAILURE
;
1470 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1471 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1472 /* Bad GUID, skip the entry */
1476 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1478 /* Skip this entry as it is not the right device class */
1482 /* Add the entry to the list */
1483 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1485 RegCloseKey(hDeviceIdKey
);
1486 return GetLastError();
1488 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1489 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1491 RegCloseKey(hDeviceIdKey
);
1494 return ERROR_SUCCESS
;
1497 static LONG
SETUP_CreateDevList(
1498 struct DeviceInfoSet
*list
,
1499 PCWSTR MachineName OPTIONAL
,
1500 LPGUID
class OPTIONAL
,
1501 PCWSTR Enumerator OPTIONAL
)
1503 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1504 WCHAR KeyBuffer
[MAX_PATH
];
1509 if (class && IsEqualIID(class, &GUID_NULL
))
1513 if (MachineName
!= NULL
)
1515 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1516 if (rc
!= ERROR_SUCCESS
)
1520 HKLM
= HKEY_LOCAL_MACHINE
;
1522 rc
= RegOpenKeyExW(HKLM
,
1523 REGSTR_PATH_SYSTEMENUM
,
1525 KEY_ENUMERATE_SUB_KEYS
,
1527 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1528 if (rc
!= ERROR_SUCCESS
)
1531 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1532 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1541 KEY_ENUMERATE_SUB_KEYS
,
1543 RegCloseKey(hEnumKey
);
1544 if (rc
!= ERROR_SUCCESS
)
1546 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1547 RegCloseKey(hEnumeratorKey
);
1552 /* Enumerate enumerators */
1556 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1557 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1558 if (rc
== ERROR_NO_MORE_ITEMS
)
1560 if (rc
!= ERROR_SUCCESS
)
1562 RegCloseKey(hEnumKey
);
1568 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1569 if (rc
!= ERROR_SUCCESS
)
1571 RegCloseKey(hEnumKey
);
1575 /* Call SETUP_CreateDevListFromEnumerator */
1576 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1577 RegCloseKey(hEnumeratorKey
);
1578 if (rc
!= ERROR_SUCCESS
)
1580 RegCloseKey(hEnumKey
);
1584 RegCloseKey(hEnumKey
);
1585 return ERROR_SUCCESS
;
1589 static LONG
SETUP_CreateInterfaceList(
1590 struct DeviceInfoSet
*list
,
1592 LPGUID InterfaceGuid
,
1593 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1595 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1596 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1597 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1598 HKEY hControlKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */
1599 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1600 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1602 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1605 DWORD dwLength
, dwInstancePathLength
;
1609 struct DeviceInfoElement
*deviceInfo
;
1611 /* Open registry key related to this interface */
1612 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1613 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1614 return GetLastError();
1616 /* Enumerate sub keys of hInterfaceKey */
1620 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1621 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1622 if (rc
== ERROR_NO_MORE_ITEMS
)
1624 if (rc
!= ERROR_SUCCESS
)
1626 RegCloseKey(hInterfaceKey
);
1632 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1633 if (rc
!= ERROR_SUCCESS
)
1635 RegCloseKey(hInterfaceKey
);
1639 /* Read DeviceInstance */
1640 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1641 if (rc
!= ERROR_SUCCESS
)
1643 RegCloseKey(hDeviceInstanceKey
);
1644 RegCloseKey(hInterfaceKey
);
1647 if (dwRegType
!= REG_SZ
)
1649 RegCloseKey(hDeviceInstanceKey
);
1650 RegCloseKey(hInterfaceKey
);
1651 return ERROR_GEN_FAILURE
;
1653 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1656 RegCloseKey(hDeviceInstanceKey
);
1657 RegCloseKey(hInterfaceKey
);
1658 return ERROR_NOT_ENOUGH_MEMORY
;
1660 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1661 if (rc
!= ERROR_SUCCESS
)
1663 HeapFree(GetProcessHeap(), 0, InstancePath
);
1664 RegCloseKey(hDeviceInstanceKey
);
1665 RegCloseKey(hInterfaceKey
);
1668 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1669 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1671 if (DeviceInstanceW
)
1673 /* Check if device enumerator is not the right one */
1674 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1676 HeapFree(GetProcessHeap(), 0, InstancePath
);
1677 RegCloseKey(hDeviceInstanceKey
);
1682 /* Find class GUID associated to the device instance */
1685 REGSTR_PATH_SYSTEMENUM
,
1689 if (rc
!= ERROR_SUCCESS
)
1691 HeapFree(GetProcessHeap(), 0, InstancePath
);
1692 RegCloseKey(hDeviceInstanceKey
);
1693 RegCloseKey(hInterfaceKey
);
1702 RegCloseKey(hEnumKey
);
1703 if (rc
!= ERROR_SUCCESS
)
1705 HeapFree(GetProcessHeap(), 0, InstancePath
);
1706 RegCloseKey(hDeviceInstanceKey
);
1707 RegCloseKey(hInterfaceKey
);
1710 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1711 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1713 if (rc
!= ERROR_SUCCESS
)
1715 HeapFree(GetProcessHeap(), 0, InstancePath
);
1716 RegCloseKey(hDeviceInstanceKey
);
1717 RegCloseKey(hInterfaceKey
);
1720 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1721 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1722 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1724 HeapFree(GetProcessHeap(), 0, InstancePath
);
1725 RegCloseKey(hDeviceInstanceKey
);
1726 RegCloseKey(hInterfaceKey
);
1727 return ERROR_GEN_FAILURE
;
1729 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1731 /* If current device doesn't match the list GUID (if any), skip this entry */
1732 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1734 HeapFree(GetProcessHeap(), 0, InstancePath
);
1735 RegCloseKey(hDeviceInstanceKey
);
1739 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1743 LPWSTR pSymbolicLink
;
1744 struct DeviceInterface
*interfaceInfo
;
1746 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1747 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1748 if (rc
== ERROR_NO_MORE_ITEMS
)
1750 if (rc
!= ERROR_SUCCESS
)
1752 HeapFree(GetProcessHeap(), 0, InstancePath
);
1753 RegCloseKey(hDeviceInstanceKey
);
1754 RegCloseKey(hInterfaceKey
);
1758 if (KeyBuffer
[0] != '#')
1759 /* This entry doesn't represent an interesting entry */
1763 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1764 if (rc
!= ERROR_SUCCESS
)
1766 RegCloseKey(hDeviceInstanceKey
);
1767 RegCloseKey(hInterfaceKey
);
1771 /* Read SymbolicLink value */
1772 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1773 if (rc
!= ERROR_SUCCESS
)
1775 RegCloseKey(hReferenceKey
);
1776 RegCloseKey(hDeviceInstanceKey
);
1777 RegCloseKey(hInterfaceKey
);
1780 if (dwRegType
!= REG_SZ
)
1782 RegCloseKey(hReferenceKey
);
1783 RegCloseKey(hDeviceInstanceKey
);
1784 RegCloseKey(hInterfaceKey
);
1785 return ERROR_GEN_FAILURE
;
1788 /* We have found a device */
1789 /* Step 1. Create a device info element */
1790 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1792 RegCloseKey(hReferenceKey
);
1793 RegCloseKey(hDeviceInstanceKey
);
1794 RegCloseKey(hInterfaceKey
);
1795 return GetLastError();
1797 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1798 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1800 /* Step 2. Create an interface list for this element */
1801 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1804 RegCloseKey(hReferenceKey
);
1805 RegCloseKey(hDeviceInstanceKey
);
1806 RegCloseKey(hInterfaceKey
);
1807 return ERROR_NOT_ENOUGH_MEMORY
;
1809 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1810 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1811 RegCloseKey(hReferenceKey
);
1812 if (rc
!= ERROR_SUCCESS
)
1814 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1815 RegCloseKey(hDeviceInstanceKey
);
1816 RegCloseKey(hInterfaceKey
);
1819 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1821 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1822 RegCloseKey(hDeviceInstanceKey
);
1823 RegCloseKey(hInterfaceKey
);
1824 return GetLastError();
1827 /* Step 3. Update flags */
1828 if (KeyBuffer
[1] == '\0')
1829 interfaceInfo
->Flags
|= SPINT_DEFAULT
;
1830 rc
= RegOpenKeyExW(hReferenceKey
, Control
, 0, KEY_QUERY_VALUE
, &hControlKey
);
1832 interfaceInfo
->Flags
|= SPINT_REMOVED
;
1835 dwLength
= sizeof(DWORD
);
1836 if (RegQueryValueExW(hControlKey
, Linked
, NULL
, &dwRegType
, (LPBYTE
)&LinkedValue
, &dwLength
)
1837 && dwRegType
== REG_DWORD
&& LinkedValue
)
1838 interfaceInfo
->Flags
|= SPINT_ACTIVE
;
1839 RegCloseKey(hControlKey
);
1842 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1843 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1844 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1846 RegCloseKey(hDeviceInstanceKey
);
1848 RegCloseKey(hInterfaceKey
);
1849 return ERROR_SUCCESS
;
1852 /***********************************************************************
1853 * SetupDiGetClassDevsExW (SETUPAPI.@)
1855 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1864 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1865 struct DeviceInfoSet
*list
;
1869 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1870 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1872 /* Create the deviceset if not set */
1875 list
= (struct DeviceInfoSet
*)deviceset
;
1876 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1878 SetLastError(ERROR_INVALID_HANDLE
);
1879 return INVALID_HANDLE_VALUE
;
1881 hDeviceInfo
= deviceset
;
1885 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1886 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1887 NULL
, machine
, NULL
);
1888 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1889 return INVALID_HANDLE_VALUE
;
1890 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1893 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1896 pClassGuid
= &list
->ClassGuid
;
1898 if (flags
& DIGCF_PRESENT
)
1899 FIXME(": flag DIGCF_PRESENT ignored\n");
1900 if (flags
& DIGCF_PROFILE
)
1901 FIXME(": flag DIGCF_PROFILE ignored\n");
1903 if (flags
& DIGCF_ALLCLASSES
)
1905 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1906 if (rc
!= ERROR_SUCCESS
)
1910 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1911 return INVALID_HANDLE_VALUE
;
1915 else if (flags
& DIGCF_DEVICEINTERFACE
)
1919 SetLastError(ERROR_INVALID_PARAMETER
);
1921 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1922 return INVALID_HANDLE_VALUE
;
1925 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1926 if (rc
!= ERROR_SUCCESS
)
1930 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1931 return INVALID_HANDLE_VALUE
;
1937 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1938 if (rc
!= ERROR_SUCCESS
)
1942 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1943 return INVALID_HANDLE_VALUE
;
1949 /***********************************************************************
1950 * SetupDiGetClassImageIndex (SETUPAPI.@)
1953 static BOOL
GetIconIndex(
1955 OUT PINT ImageIndex
)
1957 LPWSTR Buffer
= NULL
;
1958 DWORD dwRegType
, dwLength
;
1962 /* Read icon registry key */
1963 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
1964 if (rc
!= ERROR_SUCCESS
)
1968 } else if (dwRegType
!= REG_SZ
)
1970 SetLastError(ERROR_INVALID_INDEX
);
1973 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
1976 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1979 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
1980 if (rc
!= ERROR_SUCCESS
)
1985 /* make sure the returned buffer is NULL-terminated */
1986 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
1988 /* Transform icon value to a INT */
1989 *ImageIndex
= atoiW(Buffer
);
1997 BOOL WINAPI
SetupDiGetClassImageIndex(
1998 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1999 IN CONST GUID
*ClassGuid
,
2000 OUT PINT ImageIndex
)
2002 struct ClassImageList
*list
;
2005 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2007 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2008 SetLastError(ERROR_INVALID_PARAMETER
);
2009 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2010 SetLastError(ERROR_INVALID_USER_BUFFER
);
2011 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2012 SetLastError(ERROR_INVALID_USER_BUFFER
);
2013 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2014 SetLastError(ERROR_INVALID_USER_BUFFER
);
2015 else if (!ImageIndex
)
2016 SetLastError(ERROR_INVALID_PARAMETER
);
2019 HKEY hKey
= INVALID_HANDLE_VALUE
;
2022 /* Read Icon registry entry into Buffer */
2023 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2024 if (hKey
== INVALID_HANDLE_VALUE
)
2026 if (!GetIconIndex(hKey
, &iconIndex
))
2031 SetLastError(ERROR_INVALID_INDEX
);
2035 *ImageIndex
= -iconIndex
;
2039 if (hKey
!= INVALID_HANDLE_VALUE
)
2043 TRACE("Returning %d\n", ret
);
2047 /***********************************************************************
2048 * SetupDiGetClassImageList(SETUPAPI.@)
2050 BOOL WINAPI
SetupDiGetClassImageList(
2051 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2053 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2056 /***********************************************************************
2057 * SetupDiGetClassImageListExA(SETUPAPI.@)
2059 BOOL WINAPI
SetupDiGetClassImageListExA(
2060 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2061 IN PCSTR MachineName OPTIONAL
,
2064 PWSTR MachineNameW
= NULL
;
2069 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2070 if (MachineNameW
== NULL
)
2074 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2077 MyFree(MachineNameW
);
2082 /***********************************************************************
2083 * SetupDiGetClassImageListExW(SETUPAPI.@)
2085 BOOL WINAPI
SetupDiGetClassImageListExW(
2086 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2087 IN PCWSTR MachineName OPTIONAL
,
2092 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2094 if (!ClassImageListData
)
2095 SetLastError(ERROR_INVALID_PARAMETER
);
2096 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2097 SetLastError(ERROR_INVALID_USER_BUFFER
);
2099 SetLastError(ERROR_INVALID_PARAMETER
);
2102 struct ClassImageList
*list
= NULL
;
2105 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2107 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
2108 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2111 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2114 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2117 list
->szData
[0] = list
->szData
[1] = '\\';
2118 strcpyW(list
->szData
+ 2, MachineName
);
2119 list
->MachineName
= list
->szData
;
2123 list
->MachineName
= NULL
;
2126 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2134 TRACE("Returning %d\n", ret
);
2138 /***********************************************************************
2139 * SetupDiLoadClassIcon(SETUPAPI.@)
2141 BOOL WINAPI
SetupDiLoadClassIcon(
2142 IN CONST GUID
*ClassGuid
,
2143 OUT HICON
*LargeIcon OPTIONAL
,
2144 OUT PINT MiniIconIndex OPTIONAL
)
2149 SetLastError(ERROR_INVALID_PARAMETER
);
2152 LPWSTR Buffer
= NULL
;
2155 HKEY hKey
= INVALID_HANDLE_VALUE
;
2157 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2158 if (hKey
== INVALID_HANDLE_VALUE
)
2161 if (!GetIconIndex(hKey
, &iconIndex
))
2166 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2169 DWORD dwRegType
, dwLength
;
2170 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2171 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2173 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2176 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2179 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2180 if (rc
!= ERROR_SUCCESS
)
2185 /* make sure the returned buffer is NULL-terminated */
2186 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2189 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2190 && dwRegType
== REG_SZ
)
2192 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2195 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2198 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2199 if (rc
!= ERROR_SUCCESS
)
2204 /* make sure the returned buffer is NULL-terminated */
2205 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2209 /* Unable to find where to load the icon */
2210 SetLastError(ERROR_FILE_NOT_FOUND
);
2213 Comma
= strchrW(Buffer
, ',');
2216 SetLastError(ERROR_GEN_FAILURE
);
2224 /* Look up icon in setupapi.dll */
2225 DllName
= L
"setupapi.dll";
2226 iconIndex
= -iconIndex
;
2229 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2232 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2234 SetLastError(ERROR_INVALID_INDEX
);
2239 *MiniIconIndex
= iconIndex
;
2243 if (hKey
!= INVALID_HANDLE_VALUE
)
2248 TRACE("Returning %d\n", ret
);
2252 /***********************************************************************
2253 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2255 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2256 HDEVINFO DeviceInfoSet
,
2257 PSP_DEVINFO_DATA DeviceInfoData
,
2258 CONST GUID
* InterfaceClassGuid
,
2260 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2264 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2265 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2267 if (!DeviceInterfaceData
)
2268 SetLastError(ERROR_INVALID_PARAMETER
);
2269 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2270 SetLastError(ERROR_INVALID_USER_BUFFER
);
2271 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2273 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2275 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2277 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2279 while (ItemList
!= &list
->ListHead
&& !Found
)
2281 PLIST_ENTRY InterfaceListEntry
;
2282 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2283 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2285 /* We are not searching for this element */
2286 ItemList
= ItemList
->Flink
;
2289 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2290 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2292 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2293 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2295 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2298 if (MemberIndex
-- == 0)
2300 /* return this item */
2301 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2302 &DevItf
->InterfaceClassGuid
,
2304 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2305 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2308 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2310 ItemList
= ItemList
->Flink
;
2313 SetLastError(ERROR_NO_MORE_ITEMS
);
2318 SetLastError(ERROR_INVALID_HANDLE
);
2321 SetLastError(ERROR_INVALID_HANDLE
);
2325 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2327 InterlockedIncrement(&infFile
->References
);
2330 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2332 if (InterlockedDecrement(&infFile
->References
) == 0)
2334 SetupCloseInfFile(infFile
->hInf
);
2335 HeapFree(GetProcessHeap(), 0, infFile
);
2339 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2341 DereferenceInfFile(driverInfo
->InfFileDetails
);
2342 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2343 HeapFree(GetProcessHeap(), 0, driverInfo
);
2347 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2349 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2353 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2355 PLIST_ENTRY ListEntry
;
2356 struct DriverInfoElement
*driverInfo
;
2358 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2360 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2361 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2362 if (!DestroyDriverInfoElement(driverInfo
))
2365 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2367 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2368 HeapFree(GetProcessHeap(), 0, ListEntry
);
2370 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2371 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2375 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2377 PLIST_ENTRY ListEntry
;
2378 struct DeviceInfoElement
*deviceInfo
;
2380 while (!IsListEmpty(&list
->ListHead
))
2382 ListEntry
= RemoveHeadList(&list
->ListHead
);
2383 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2384 if (!DestroyDeviceInfoElement(deviceInfo
))
2387 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2388 RegCloseKey(list
->HKLM
);
2389 CM_Disconnect_Machine(list
->hMachine
);
2390 DestroyClassInstallParams(&list
->ClassInstallParams
);
2391 HeapFree(GetProcessHeap(), 0, list
);
2395 /***********************************************************************
2396 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2398 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2402 TRACE("%p\n", devinfo
);
2403 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2405 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2407 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2408 ret
= DestroyDeviceInfoSet(list
);
2410 SetLastError(ERROR_INVALID_HANDLE
);
2413 SetLastError(ERROR_INVALID_HANDLE
);
2415 TRACE("Returning %d\n", ret
);
2419 /***********************************************************************
2420 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2422 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2423 HDEVINFO DeviceInfoSet
,
2424 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2425 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2426 DWORD DeviceInterfaceDetailDataSize
,
2427 PDWORD RequiredSize
,
2428 PSP_DEVINFO_DATA DeviceInfoData
)
2430 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2431 DWORD sizeW
= 0, sizeA
;
2434 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2435 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2436 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2438 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2439 SetLastError(ERROR_INVALID_USER_BUFFER
);
2440 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2441 SetLastError(ERROR_INVALID_PARAMETER
);
2442 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2443 SetLastError(ERROR_INVALID_PARAMETER
);
2446 if (DeviceInterfaceDetailData
!= NULL
)
2448 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2449 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2450 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2451 if (!DeviceInterfaceDetailDataW
)
2453 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2456 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2458 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2459 ret
= SetupDiGetDeviceInterfaceDetailW(
2461 DeviceInterfaceData
,
2462 DeviceInterfaceDetailDataW
,
2466 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2467 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2469 *RequiredSize
= sizeA
;
2470 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2472 if (!WideCharToMultiByte(
2474 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2475 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2482 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2485 TRACE("Returning %d\n", ret
);
2489 /***********************************************************************
2490 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2492 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2493 HDEVINFO DeviceInfoSet
,
2494 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2495 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2496 DWORD DeviceInterfaceDetailDataSize
,
2497 PDWORD RequiredSize
,
2498 PSP_DEVINFO_DATA DeviceInfoData
)
2502 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2503 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2504 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2506 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2507 SetLastError(ERROR_INVALID_PARAMETER
);
2508 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2509 SetLastError(ERROR_INVALID_HANDLE
);
2510 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2511 SetLastError(ERROR_INVALID_HANDLE
);
2512 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2513 SetLastError(ERROR_INVALID_USER_BUFFER
);
2514 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2515 SetLastError(ERROR_INVALID_USER_BUFFER
);
2516 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2517 SetLastError(ERROR_INVALID_USER_BUFFER
);
2518 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2519 SetLastError(ERROR_INVALID_PARAMETER
);
2520 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2521 SetLastError(ERROR_INVALID_PARAMETER
);
2524 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2525 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2526 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2527 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2529 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2531 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2533 *RequiredSize
= sizeRequired
;
2537 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2538 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2541 memcpy(&DeviceInfoData
->ClassGuid
,
2542 &deviceInterface
->DeviceInfo
->ClassGuid
,
2544 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2545 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2551 TRACE("Returning %d\n", ret
);
2555 /***********************************************************************
2556 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2558 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2560 PSP_DEVINFO_DATA DeviceInfoData
,
2562 PDWORD PropertyRegDataType
,
2563 PBYTE PropertyBuffer
,
2564 DWORD PropertyBufferSize
,
2565 PDWORD RequiredSize
)
2568 BOOL bIsStringProperty
;
2570 DWORD RequiredSizeA
, RequiredSizeW
;
2571 DWORD PropertyBufferSizeW
;
2572 PBYTE PropertyBufferW
;
2574 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2575 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2578 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2579 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2581 bResult
= SetupDiGetDeviceRegistryPropertyW(
2587 PropertyBufferSizeW
,
2590 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2592 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2594 if (bIsStringProperty
)
2595 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2597 RequiredSizeA
= RequiredSizeW
;
2599 *RequiredSize
= RequiredSizeA
;
2600 if (PropertyRegDataType
)
2601 *PropertyRegDataType
= RegType
;
2606 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2610 if (RequiredSizeA
<= PropertyBufferSize
)
2612 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2614 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2616 /* Last error is already set by WideCharToMultiByte */
2621 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2625 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2629 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2633 /***********************************************************************
2634 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2636 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2637 HDEVINFO DeviceInfoSet
,
2638 PSP_DEVINFO_DATA DeviceInfoData
,
2640 PDWORD PropertyRegDataType
,
2641 PBYTE PropertyBuffer
,
2642 DWORD PropertyBufferSize
,
2643 PDWORD RequiredSize
)
2645 HKEY hEnumKey
, hKey
;
2649 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2650 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2653 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2654 SetLastError(ERROR_INVALID_HANDLE
);
2655 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2656 SetLastError(ERROR_INVALID_HANDLE
);
2657 else if (!DeviceInfoData
)
2658 SetLastError(ERROR_INVALID_PARAMETER
);
2659 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2660 SetLastError(ERROR_INVALID_USER_BUFFER
);
2661 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2662 SetLastError(ERROR_INVALID_PARAMETER
);
2665 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2666 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2670 case SPDRP_CAPABILITIES
:
2672 case SPDRP_CLASSGUID
:
2673 case SPDRP_COMPATIBLEIDS
:
2674 case SPDRP_CONFIGFLAGS
:
2675 case SPDRP_DEVICEDESC
:
2677 case SPDRP_FRIENDLYNAME
:
2678 case SPDRP_HARDWAREID
:
2679 case SPDRP_LOCATION_INFORMATION
:
2680 case SPDRP_LOWERFILTERS
:
2682 case SPDRP_SECURITY
:
2684 case SPDRP_UI_NUMBER
:
2685 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2686 case SPDRP_UPPERFILTERS
:
2688 LPCWSTR RegistryPropertyName
;
2693 case SPDRP_CAPABILITIES
:
2694 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2696 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2697 case SPDRP_CLASSGUID
:
2698 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2699 case SPDRP_COMPATIBLEIDS
:
2700 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2701 case SPDRP_CONFIGFLAGS
:
2702 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2703 case SPDRP_DEVICEDESC
:
2704 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2706 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2707 case SPDRP_FRIENDLYNAME
:
2708 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2709 case SPDRP_HARDWAREID
:
2710 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2711 case SPDRP_LOCATION_INFORMATION
:
2712 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2713 case SPDRP_LOWERFILTERS
:
2714 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2716 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2717 case SPDRP_SECURITY
:
2718 RegistryPropertyName
= L
"Security"; break;
2720 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2721 case SPDRP_UI_NUMBER
:
2722 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2723 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2724 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2725 case SPDRP_UPPERFILTERS
:
2726 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2728 /* Should not happen */
2729 RegistryPropertyName
= NULL
; break;
2732 /* Open registry key name */
2735 REGSTR_PATH_SYSTEMENUM
,
2739 if (rc
!= ERROR_SUCCESS
)
2750 RegCloseKey(hEnumKey
);
2751 if (rc
!= ERROR_SUCCESS
)
2756 /* Read registry entry */
2757 BufferSize
= PropertyBufferSize
;
2758 rc
= RegQueryValueExW(
2760 RegistryPropertyName
,
2761 NULL
, /* Reserved */
2762 PropertyRegDataType
,
2766 *RequiredSize
= BufferSize
;
2769 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2772 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2774 case ERROR_MORE_DATA
:
2775 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2784 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2786 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2788 if (PropertyRegDataType
)
2789 *PropertyRegDataType
= REG_SZ
;
2791 *RequiredSize
= required
;
2792 if (PropertyBufferSize
>= required
)
2794 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2798 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2802 /*case SPDRP_BUSTYPEGUID:
2803 case SPDRP_LEGACYBUSTYPE:
2804 case SPDRP_BUSNUMBER:
2805 case SPDRP_ENUMERATOR_NAME:
2806 case SPDRP_SECURITY_SDS:
2808 case SPDRP_EXCLUSIVE:
2809 case SPDRP_CHARACTERISTICS:
2811 case SPDRP_DEVICE_POWER_DATA:*/
2812 #if (WINVER >= 0x501)
2813 /*case SPDRP_REMOVAL_POLICY:
2814 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2815 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2816 case SPDRP_INSTALL_STATE:*/
2821 ERR("Property 0x%lx not implemented\n", Property
);
2822 SetLastError(ERROR_NOT_SUPPORTED
);
2827 TRACE("Returning %d\n", ret
);
2831 /***********************************************************************
2832 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2834 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2835 IN HDEVINFO DeviceInfoSet
,
2836 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2838 IN CONST BYTE
*PropertyBuffer
,
2839 IN DWORD PropertyBufferSize
)
2841 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2842 Property
, PropertyBuffer
, PropertyBufferSize
);
2843 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2847 /***********************************************************************
2848 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2850 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2851 IN HDEVINFO DeviceInfoSet
,
2852 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2854 IN
const BYTE
*PropertyBuffer
,
2855 IN DWORD PropertyBufferSize
)
2857 struct DeviceInfoSet
*list
;
2860 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2861 Property
, PropertyBuffer
, PropertyBufferSize
);
2864 SetLastError(ERROR_INVALID_HANDLE
);
2865 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2866 SetLastError(ERROR_INVALID_HANDLE
);
2867 else if (!DeviceInfoData
)
2868 SetLastError(ERROR_INVALID_HANDLE
);
2869 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2870 SetLastError(ERROR_INVALID_USER_BUFFER
);
2875 case SPDRP_COMPATIBLEIDS
:
2876 case SPDRP_CONFIGFLAGS
:
2877 case SPDRP_FRIENDLYNAME
:
2878 case SPDRP_HARDWAREID
:
2879 case SPDRP_LOCATION_INFORMATION
:
2880 case SPDRP_LOWERFILTERS
:
2881 case SPDRP_SECURITY
:
2883 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2884 case SPDRP_UPPERFILTERS
:
2886 LPCWSTR RegistryPropertyName
;
2887 DWORD RegistryDataType
;
2893 case SPDRP_COMPATIBLEIDS
:
2894 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2895 RegistryDataType
= REG_MULTI_SZ
;
2897 case SPDRP_CONFIGFLAGS
:
2898 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2899 RegistryDataType
= REG_DWORD
;
2901 case SPDRP_FRIENDLYNAME
:
2902 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2903 RegistryDataType
= REG_SZ
;
2905 case SPDRP_HARDWAREID
:
2906 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2907 RegistryDataType
= REG_MULTI_SZ
;
2909 case SPDRP_LOCATION_INFORMATION
:
2910 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2911 RegistryDataType
= REG_SZ
;
2913 case SPDRP_LOWERFILTERS
:
2914 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2915 RegistryDataType
= REG_MULTI_SZ
;
2917 case SPDRP_SECURITY
:
2918 RegistryPropertyName
= L
"Security";
2919 RegistryDataType
= REG_BINARY
;
2922 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2923 RegistryDataType
= REG_SZ
;
2925 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2926 RegistryPropertyName
= L
"UINumberDescFormat";
2927 RegistryDataType
= REG_SZ
;
2929 case SPDRP_UPPERFILTERS
:
2930 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
2931 RegistryDataType
= REG_MULTI_SZ
;
2934 /* Should not happen */
2935 RegistryPropertyName
= NULL
;
2936 RegistryDataType
= REG_BINARY
;
2939 /* Open device registry key */
2940 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2941 if (hKey
!= INVALID_HANDLE_VALUE
)
2943 /* Write new data */
2944 rc
= RegSetValueExW(
2946 RegistryPropertyName
,
2950 PropertyBufferSize
);
2951 if (rc
== ERROR_SUCCESS
)
2960 /*case SPDRP_CHARACTERISTICS:
2962 case SPDRP_EXCLUSIVE:*/
2963 #if (WINVER >= 0x501)
2964 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2966 //case SPDRP_SECURITY_SDS:
2970 ERR("Property 0x%lx not implemented\n", Property
);
2971 SetLastError(ERROR_NOT_SUPPORTED
);
2976 TRACE("Returning %d\n", ret
);
2981 /***********************************************************************
2982 * SetupDiInstallClassA (SETUPAPI.@)
2984 BOOL WINAPI
SetupDiInstallClassA(
2985 IN HWND hwndParent OPTIONAL
,
2986 IN PCSTR InfFileName
,
2988 IN HSPFILEQ FileQueue OPTIONAL
)
2990 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
2994 /***********************************************************************
2995 * SetupDiInstallClassW (SETUPAPI.@)
2997 BOOL WINAPI
SetupDiInstallClassW(
2998 IN HWND hwndParent OPTIONAL
,
2999 IN PCWSTR InfFileName
,
3001 IN HSPFILEQ FileQueue OPTIONAL
)
3003 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3007 /***********************************************************************
3008 * SetupDiInstallClassExA (SETUPAPI.@)
3010 BOOL WINAPI
SetupDiInstallClassExA(
3011 IN HWND hwndParent OPTIONAL
,
3012 IN PCSTR InfFileName OPTIONAL
,
3014 IN HSPFILEQ FileQueue OPTIONAL
,
3015 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3019 PWSTR InfFileNameW
= NULL
;
3024 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3025 if (InfFileNameW
== NULL
)
3027 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3032 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3033 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3035 MyFree(InfFileNameW
);
3041 static HKEY
CreateClassKey(HINF hInf
)
3043 WCHAR FullBuffer
[MAX_PATH
];
3044 WCHAR Buffer
[MAX_PATH
];
3049 if (!SetupGetLineTextW(NULL
,
3057 return INVALID_HANDLE_VALUE
;
3060 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3061 lstrcatW(FullBuffer
, Buffer
);
3064 if (!SetupGetLineTextW(NULL
,
3072 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3073 return INVALID_HANDLE_VALUE
;
3076 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3080 REG_OPTION_NON_VOLATILE
,
3086 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3087 return INVALID_HANDLE_VALUE
;
3090 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3095 RequiredSize
* sizeof(WCHAR
)))
3097 RegCloseKey(hClassKey
);
3098 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3099 return INVALID_HANDLE_VALUE
;
3106 /***********************************************************************
3107 * SetupDiInstallClassExW (SETUPAPI.@)
3109 BOOL WINAPI
SetupDiInstallClassExW(
3110 IN HWND hwndParent OPTIONAL
,
3111 IN PCWSTR InfFileName OPTIONAL
,
3113 IN HSPFILEQ FileQueue OPTIONAL
,
3114 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3120 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3121 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3123 if (!InfFileName
&& !InterfaceClassGuid
)
3124 SetLastError(ERROR_INVALID_PARAMETER
);
3125 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3127 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3128 SetLastError(ERROR_INVALID_FLAGS
);
3130 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3131 SetLastError(ERROR_INVALID_PARAMETER
);
3132 else if (Reserved1
!= NULL
)
3133 SetLastError(ERROR_INVALID_PARAMETER
);
3134 else if (Reserved2
!= NULL
)
3135 SetLastError(ERROR_INVALID_PARAMETER
);
3138 WCHAR SectionName
[MAX_PATH
];
3139 HINF hInf
= INVALID_HANDLE_VALUE
;
3140 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3141 PVOID callback_context
= NULL
;
3143 if (InterfaceClassGuid
)
3145 /* SetupDiCreateDeviceInterface??? */
3146 FIXME("Installing an interface is not implemented\n");
3147 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3151 if (Flags
& DI_NOVCP
)
3152 FIXME("FileQueue argument ignored\n");
3153 if (Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3154 FIXME("Flags 0x%lx ignored\n", Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3156 /* Open the .inf file */
3157 hInf
= SetupOpenInfFileW(
3162 if (hInf
== INVALID_HANDLE_VALUE
)
3165 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3166 hClassKey
= CreateClassKey(hInf
);
3167 if (hClassKey
== INVALID_HANDLE_VALUE
)
3170 /* Try to append a layout file */
3171 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3175 /* Retrieve the actual section name */
3176 ret
= SetupDiGetActualSectionToInstallW(
3180 MAX_PATH
- wcslen(DotServices
),
3186 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3187 if (!callback_context
)
3190 ret
= SetupInstallFromInfSectionW(
3194 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3196 NULL
, /* SourceRootPath */
3198 SetupDefaultQueueCallbackW
,
3205 /* Install .Services section */
3206 lstrcatW(SectionName
, DotServices
);
3207 ret
= SetupInstallServicesFromInfSectionW(hInf
, SectionName
, 0);
3215 if (hInf
!= INVALID_HANDLE_VALUE
)
3216 SetupCloseInfFile(hInf
);
3217 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3218 RegCloseKey(hClassKey
);
3219 SetupTermDefaultQueueCallback(callback_context
);
3222 TRACE("Returning %d\n", ret
);
3227 /***********************************************************************
3228 * SetupDiOpenClassRegKey (SETUPAPI.@)
3230 HKEY WINAPI
SetupDiOpenClassRegKey(
3231 const GUID
* ClassGuid
,
3234 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3235 DIOCR_INSTALLER
, NULL
, NULL
);
3239 /***********************************************************************
3240 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3242 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3243 const GUID
* ClassGuid OPTIONAL
,
3246 PCSTR MachineName OPTIONAL
,
3249 PWSTR MachineNameW
= NULL
;
3256 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3257 if (MachineNameW
== NULL
)
3258 return INVALID_HANDLE_VALUE
;
3261 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3262 Flags
, MachineNameW
, Reserved
);
3265 MyFree(MachineNameW
);
3271 /***********************************************************************
3272 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3274 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3275 const GUID
* ClassGuid OPTIONAL
,
3278 PCWSTR MachineName OPTIONAL
,
3281 LPWSTR lpGuidString
;
3282 LPWSTR lpFullGuidString
;
3290 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3291 Flags
, debugstr_w(MachineName
), Reserved
);
3293 if (Flags
== DIOCR_INSTALLER
)
3295 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3297 else if (Flags
== DIOCR_INTERFACE
)
3299 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3303 ERR("Invalid Flags parameter!\n");
3304 SetLastError(ERROR_INVALID_FLAGS
);
3305 return INVALID_HANDLE_VALUE
;
3308 if (MachineName
!= NULL
)
3310 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3311 if (rc
!= ERROR_SUCCESS
)
3314 return INVALID_HANDLE_VALUE
;
3318 HKLM
= HKEY_LOCAL_MACHINE
;
3320 rc
= RegOpenKeyExW(HKLM
,
3323 ClassGuid
? 0 : samDesired
,
3325 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3326 if (rc
!= ERROR_SUCCESS
)
3329 return INVALID_HANDLE_VALUE
;
3332 if (ClassGuid
== NULL
)
3335 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3337 SetLastError(ERROR_GEN_FAILURE
);
3338 RegCloseKey(hClassesKey
);
3339 return INVALID_HANDLE_VALUE
;
3342 dwLength
= lstrlenW(lpGuidString
);
3343 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3344 if (!lpFullGuidString
)
3346 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3347 RpcStringFreeW(&lpGuidString
);
3348 return INVALID_HANDLE_VALUE
;
3350 lpFullGuidString
[0] = '{';
3351 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3352 lpFullGuidString
[dwLength
+ 1] = '}';
3353 lpFullGuidString
[dwLength
+ 2] = '\0';
3354 RpcStringFreeW(&lpGuidString
);
3356 rc
= RegOpenKeyExW(hClassesKey
,
3361 if (rc
!= ERROR_SUCCESS
)
3364 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3365 RegCloseKey(hClassesKey
);
3366 return INVALID_HANDLE_VALUE
;
3369 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3370 RegCloseKey(hClassesKey
);
3375 /***********************************************************************
3376 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3378 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3379 HDEVINFO DeviceInfoSet
,
3382 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3384 FIXME("%p %s %08lx %p\n",
3385 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3389 /***********************************************************************
3390 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3392 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3393 HDEVINFO DeviceInfoSet
,
3396 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3398 LPWSTR DevicePathW
= NULL
;
3401 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3403 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3404 if (DevicePathW
== NULL
)
3407 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3408 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3410 MyFree(DevicePathW
);
3415 /***********************************************************************
3416 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3418 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3419 HDEVINFO DeviceInfoSet
,
3420 PSP_DEVINFO_DATA DeviceInfoData
,
3421 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3422 DWORD ClassInstallParamsSize
)
3424 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3425 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3429 /***********************************************************************
3430 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3432 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3433 IN HDEVINFO DeviceInfoSet
,
3434 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3435 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3436 IN DWORD ClassInstallParamsSize
)
3438 struct DeviceInfoSet
*list
;
3441 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3442 ClassInstallParams
, ClassInstallParamsSize
);
3445 SetLastError(ERROR_INVALID_PARAMETER
);
3446 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3447 SetLastError(ERROR_INVALID_HANDLE
);
3448 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3449 SetLastError(ERROR_INVALID_HANDLE
);
3450 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3451 SetLastError(ERROR_INVALID_USER_BUFFER
);
3452 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3453 SetLastError(ERROR_INVALID_USER_BUFFER
);
3454 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3455 SetLastError(ERROR_INVALID_PARAMETER
);
3456 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3457 SetLastError(ERROR_INVALID_PARAMETER
);
3460 SP_DEVINSTALL_PARAMS_W InstallParams
;
3463 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3464 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3468 if (ClassInstallParams
)
3470 /* Check parameters in ClassInstallParams */
3471 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3472 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3474 SetLastError(ERROR_INVALID_USER_BUFFER
);
3477 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3479 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3480 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3483 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3486 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3490 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3493 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3497 TRACE("Returning %d\n", ret
);
3501 static BOOL
PropertyChangeHandler(
3502 IN HDEVINFO DeviceInfoSet
,
3503 IN PSP_DEVINFO_DATA DeviceInfoData
,
3504 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3505 IN DWORD ClassInstallParamsSize
)
3507 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3510 if (!DeviceInfoData
)
3511 SetLastError(ERROR_INVALID_PARAMETER
);
3512 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3513 SetLastError(ERROR_INVALID_PARAMETER
);
3514 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3515 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3516 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3517 SetLastError(ERROR_INVALID_FLAGS
);
3518 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3519 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3520 SetLastError(ERROR_INVALID_FLAGS
);
3521 else if (PropChangeParams
3522 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3523 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3524 SetLastError(ERROR_INVALID_USER_BUFFER
);
3527 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3528 if (!DeviceInfoData
)
3530 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3531 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3535 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3536 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3538 if (*CurrentPropChangeParams
)
3540 MyFree(*CurrentPropChangeParams
);
3541 *CurrentPropChangeParams
= NULL
;
3543 if (PropChangeParams
)
3545 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3546 if (!*CurrentPropChangeParams
)
3548 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3551 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3562 IN PWSTR InstallerName
,
3563 OUT HMODULE
* ModulePointer
,
3564 OUT PVOID
* FunctionPointer
)
3566 HMODULE hModule
= NULL
;
3567 LPSTR FunctionNameA
= NULL
;
3571 *ModulePointer
= NULL
;
3572 *FunctionPointer
= NULL
;
3574 Comma
= strchrW(InstallerName
, ',');
3577 rc
= ERROR_INVALID_PARAMETER
;
3583 hModule
= LoadLibraryW(InstallerName
);
3587 rc
= GetLastError();
3591 /* Skip comma spaces */
3592 while (*Comma
== ',' || isspaceW(*Comma
))
3595 /* W->A conversion for function name */
3596 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3599 rc
= GetLastError();
3603 /* Search function */
3604 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3605 if (!*FunctionPointer
)
3607 rc
= GetLastError();
3611 *ModulePointer
= hModule
;
3615 if (rc
!= ERROR_SUCCESS
&& hModule
)
3616 FreeLibrary(hModule
);
3617 MyFree(FunctionNameA
);
3622 FreeFunctionPointer(
3623 IN HMODULE ModulePointer
,
3624 IN PVOID FunctionPointer
)
3626 if (ModulePointer
== NULL
)
3627 return ERROR_SUCCESS
;
3628 if (FreeLibrary(ModulePointer
))
3629 return ERROR_SUCCESS
;
3631 return GetLastError();
3635 IntSetupDiRegisterDeviceInfo(
3636 IN HDEVINFO DeviceInfoSet
,
3637 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
3639 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
3642 /***********************************************************************
3643 * SetupDiCallClassInstaller (SETUPAPI.@)
3645 BOOL WINAPI
SetupDiCallClassInstaller(
3646 IN DI_FUNCTION InstallFunction
,
3647 IN HDEVINFO DeviceInfoSet
,
3648 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3652 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3655 SetLastError(ERROR_INVALID_PARAMETER
);
3656 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3657 SetLastError(ERROR_INVALID_HANDLE
);
3658 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3659 SetLastError(ERROR_INVALID_HANDLE
);
3660 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3661 SetLastError(ERROR_INVALID_HANDLE
);
3662 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3663 SetLastError(ERROR_INVALID_USER_BUFFER
);
3666 SP_DEVINSTALL_PARAMS_W InstallParams
;
3667 #define CLASS_COINSTALLER 0x1
3668 #define DEVICE_COINSTALLER 0x2
3669 #define CLASS_INSTALLER 0x4
3670 UCHAR CanHandle
= 0;
3671 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3673 switch (InstallFunction
)
3675 case DIF_ADDPROPERTYPAGE_ADVANCED
:
3676 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3678 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
3679 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3681 case DIF_ALLOW_INSTALL
:
3682 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3685 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3687 case DIF_DESTROYPRIVATEDATA
:
3688 CanHandle
= CLASS_INSTALLER
;
3690 case DIF_INSTALLDEVICE
:
3691 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3692 DefaultHandler
= SetupDiInstallDevice
;
3694 case DIF_INSTALLDEVICEFILES
:
3695 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3696 DefaultHandler
= SetupDiInstallDriverFiles
;
3698 case DIF_INSTALLINTERFACES
:
3699 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3700 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3702 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3703 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3705 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3706 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3708 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3709 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3711 case DIF_NEWDEVICEWIZARD_PRESELECT
:
3712 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3714 case DIF_NEWDEVICEWIZARD_SELECT
:
3715 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3717 case DIF_POWERMESSAGEWAKE
:
3718 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3720 case DIF_PROPERTYCHANGE
:
3721 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3722 DefaultHandler
= SetupDiChangeState
;
3724 case DIF_REGISTER_COINSTALLERS
:
3725 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3726 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3728 case DIF_REGISTERDEVICE
:
3729 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3730 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
3733 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3734 DefaultHandler
= SetupDiRemoveDevice
;
3736 case DIF_SELECTBESTCOMPATDRV
:
3737 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3738 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3740 case DIF_SELECTDEVICE
:
3741 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3742 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3744 case DIF_TROUBLESHOOTER
:
3745 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3748 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3749 DefaultHandler
= SetupDiUnremoveDevice
;
3752 ERR("Install function %u not supported\n", InstallFunction
);
3753 SetLastError(ERROR_NOT_SUPPORTED
);
3756 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3757 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3758 /* Don't process this call, as a parameter is invalid */
3763 LIST_ENTRY ClassCoInstallersListHead
;
3764 LIST_ENTRY DeviceCoInstallersListHead
;
3765 HMODULE ClassInstallerLibrary
= NULL
;
3766 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3767 COINSTALLER_CONTEXT_DATA Context
;
3768 PLIST_ENTRY ListEntry
;
3770 DWORD dwRegType
, dwLength
;
3771 DWORD rc
= NO_ERROR
;
3773 InitializeListHead(&ClassCoInstallersListHead
);
3774 InitializeListHead(&DeviceCoInstallersListHead
);
3776 if (CanHandle
& DEVICE_COINSTALLER
)
3778 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3779 if (hKey
!= INVALID_HANDLE_VALUE
)
3781 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3782 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3784 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3785 if (KeyBuffer
!= NULL
)
3787 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3788 if (rc
== ERROR_SUCCESS
)
3791 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3793 /* Add coinstaller to DeviceCoInstallersListHead list */
3794 struct CoInstallerElement
*coinstaller
;
3795 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3796 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3799 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3800 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3801 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3803 HeapFree(GetProcessHeap(), 0, coinstaller
);
3806 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3812 if (CanHandle
& CLASS_COINSTALLER
)
3816 REGSTR_PATH_CODEVICEINSTALLERS
,
3820 if (rc
== ERROR_SUCCESS
)
3822 LPWSTR lpGuidString
;
3823 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3825 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3826 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3828 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3829 if (KeyBuffer
!= NULL
)
3831 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3832 if (rc
== ERROR_SUCCESS
)
3835 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3837 /* Add coinstaller to ClassCoInstallersListHead list */
3838 struct CoInstallerElement
*coinstaller
;
3839 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3840 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3843 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3844 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3845 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3847 HeapFree(GetProcessHeap(), 0, coinstaller
);
3850 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3853 RpcStringFreeW(&lpGuidString
);
3858 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3860 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3861 if (hKey
!= INVALID_HANDLE_VALUE
)
3863 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3864 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3866 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3867 if (KeyBuffer
!= NULL
)
3869 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3870 if (rc
== ERROR_SUCCESS
)
3872 /* Get ClassInstaller function pointer */
3873 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3874 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3876 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3877 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3880 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3887 /* Call Class co-installers */
3888 Context
.PostProcessing
= FALSE
;
3890 ListEntry
= ClassCoInstallersListHead
.Flink
;
3891 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3893 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3894 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3895 coinstaller
->PrivateData
= Context
.PrivateData
;
3896 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3898 coinstaller
->DoPostProcessing
= TRUE
;
3901 ListEntry
= ListEntry
->Flink
;
3904 /* Call Device co-installers */
3905 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3906 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3908 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3909 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3910 coinstaller
->PrivateData
= Context
.PrivateData
;
3911 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3913 coinstaller
->DoPostProcessing
= TRUE
;
3916 ListEntry
= ListEntry
->Flink
;
3919 /* Call Class installer */
3922 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3923 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3926 rc
= ERROR_DI_DO_DEFAULT
;
3928 /* Call default handler */
3929 if (rc
== ERROR_DI_DO_DEFAULT
)
3931 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3933 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3936 rc
= GetLastError();
3942 /* Call Class co-installers that required postprocessing */
3943 Context
.PostProcessing
= TRUE
;
3944 ListEntry
= ClassCoInstallersListHead
.Flink
;
3945 while (ListEntry
!= &ClassCoInstallersListHead
)
3947 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3948 if (coinstaller
->DoPostProcessing
)
3950 Context
.InstallResult
= rc
;
3951 Context
.PrivateData
= coinstaller
->PrivateData
;
3952 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3954 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3955 ListEntry
= ListEntry
->Flink
;
3958 /* Call Device co-installers that required postprocessing */
3959 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3960 while (ListEntry
!= &DeviceCoInstallersListHead
)
3962 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3963 if (coinstaller
->DoPostProcessing
)
3965 Context
.InstallResult
= rc
;
3966 Context
.PrivateData
= coinstaller
->PrivateData
;
3967 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3969 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3970 ListEntry
= ListEntry
->Flink
;
3973 /* Free allocated memory */
3974 while (!IsListEmpty(&ClassCoInstallersListHead
))
3976 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3977 HeapFree(GetProcessHeap(), 0, ListEntry
);
3979 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3981 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3982 HeapFree(GetProcessHeap(), 0, ListEntry
);
3985 ret
= (rc
== NO_ERROR
);
3989 TRACE("Returning %d\n", ret
);
3993 /***********************************************************************
3994 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
3996 BOOL WINAPI
SetupDiGetDeviceInfoListClass(
3997 IN HDEVINFO DeviceInfoSet
,
3998 OUT LPGUID ClassGuid
)
4000 struct DeviceInfoSet
*list
;
4003 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4006 SetLastError(ERROR_INVALID_HANDLE
);
4007 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4008 SetLastError(ERROR_INVALID_HANDLE
);
4009 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4010 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4013 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4018 TRACE("Returning %d\n", ret
);
4022 /***********************************************************************
4023 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4025 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
4026 IN HDEVINFO DeviceInfoSet
,
4027 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
4029 struct DeviceInfoSet
*list
;
4032 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
4035 SetLastError(ERROR_INVALID_HANDLE
);
4036 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4037 SetLastError(ERROR_INVALID_HANDLE
);
4038 else if (!DeviceInfoListDetailData
)
4039 SetLastError(ERROR_INVALID_PARAMETER
);
4040 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
4041 SetLastError(ERROR_INVALID_USER_BUFFER
);
4045 &DeviceInfoListDetailData
->ClassGuid
,
4048 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
4049 if (list
->MachineName
)
4050 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
4052 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
4057 TRACE("Returning %d\n", ret
);
4061 /***********************************************************************
4062 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4064 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4065 IN HDEVINFO DeviceInfoSet
,
4066 IN PSP_DEVINFO_DATA DeviceInfoData
,
4067 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4069 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4072 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4074 if (DeviceInstallParams
== NULL
)
4075 SetLastError(ERROR_INVALID_PARAMETER
);
4076 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4077 SetLastError(ERROR_INVALID_USER_BUFFER
);
4080 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4081 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4085 /* Do W->A conversion */
4087 DeviceInstallParams
,
4088 &deviceInstallParamsW
,
4089 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4090 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4091 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4093 DeviceInstallParams
->DriverPath
[0] = '\0';
4099 TRACE("Returning %d\n", ret
);
4103 /***********************************************************************
4104 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4106 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
4107 IN HDEVINFO DeviceInfoSet
,
4108 IN PSP_DEVINFO_DATA DeviceInfoData
,
4109 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4111 struct DeviceInfoSet
*list
;
4114 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4117 SetLastError(ERROR_INVALID_HANDLE
);
4118 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4119 SetLastError(ERROR_INVALID_HANDLE
);
4120 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4121 SetLastError(ERROR_INVALID_USER_BUFFER
);
4122 else if (!DeviceInstallParams
)
4123 SetLastError(ERROR_INVALID_PARAMETER
);
4124 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4125 SetLastError(ERROR_INVALID_USER_BUFFER
);
4128 PSP_DEVINSTALL_PARAMS_W Source
;
4131 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4133 Source
= &list
->InstallParams
;
4134 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4138 TRACE("Returning %d\n", ret
);
4142 /***********************************************************************
4143 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4145 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
4146 IN HDEVINFO DeviceInfoSet
,
4147 IN PSP_DEVINFO_DATA DeviceInfoData
,
4148 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4150 struct DeviceInfoSet
*list
;
4153 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4156 SetLastError(ERROR_INVALID_HANDLE
);
4157 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4158 SetLastError(ERROR_INVALID_HANDLE
);
4159 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4160 SetLastError(ERROR_INVALID_USER_BUFFER
);
4161 else if (!DeviceInstallParams
)
4162 SetLastError(ERROR_INVALID_PARAMETER
);
4163 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4164 SetLastError(ERROR_INVALID_USER_BUFFER
);
4167 PSP_DEVINSTALL_PARAMS_W Destination
;
4169 /* FIXME: Validate parameters */
4172 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4174 Destination
= &list
->InstallParams
;
4175 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4179 TRACE("Returning %d\n", ret
);
4183 /***********************************************************************
4184 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4186 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
4187 IN HDEVINFO DeviceInfoSet
,
4188 IN PSP_DEVINFO_DATA DeviceInfoData
,
4189 OUT PSTR DeviceInstanceId OPTIONAL
,
4190 IN DWORD DeviceInstanceIdSize
,
4191 OUT PDWORD RequiredSize OPTIONAL
)
4193 PWSTR DeviceInstanceIdW
= NULL
;
4196 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4197 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4199 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4200 SetLastError(ERROR_INVALID_PARAMETER
);
4203 if (DeviceInstanceIdSize
!= 0)
4205 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4206 if (DeviceInstanceIdW
== NULL
)
4210 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4211 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4214 if (ret
&& DeviceInstanceIdW
!= NULL
)
4216 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4217 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4219 DeviceInstanceId
[0] = '\0';
4225 TRACE("Returning %d\n", ret
);
4229 /***********************************************************************
4230 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4232 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
4233 IN HDEVINFO DeviceInfoSet
,
4234 IN PSP_DEVINFO_DATA DeviceInfoData
,
4235 OUT PWSTR DeviceInstanceId OPTIONAL
,
4236 IN DWORD DeviceInstanceIdSize
,
4237 OUT PDWORD RequiredSize OPTIONAL
)
4241 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4242 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4245 SetLastError(ERROR_INVALID_HANDLE
);
4246 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4247 SetLastError(ERROR_INVALID_HANDLE
);
4248 else if (!DeviceInfoData
)
4249 SetLastError(ERROR_INVALID_PARAMETER
);
4250 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4251 SetLastError(ERROR_INVALID_USER_BUFFER
);
4252 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4253 SetLastError(ERROR_INVALID_PARAMETER
);
4254 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4255 SetLastError(ERROR_INVALID_PARAMETER
);
4258 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4261 required
= (wcslen(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4263 *RequiredSize
= required
;
4265 if (required
<= DeviceInstanceIdSize
)
4267 wcscpy(DeviceInstanceId
, DevInfo
->DeviceName
);
4271 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4274 TRACE("Returning %d\n", ret
);
4278 /***********************************************************************
4279 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4281 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
4282 IN HDEVINFO DeviceInfoSet
,
4283 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4284 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4285 IN DWORD PropertySheetHeaderPageListSize
,
4286 OUT PDWORD RequiredSize OPTIONAL
,
4287 IN DWORD PropertySheetType
)
4289 PROPSHEETHEADERW psh
;
4292 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4293 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4294 RequiredSize
, PropertySheetType
);
4296 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4297 psh
.phpage
= PropertySheetHeader
->phpage
;
4298 psh
.nPages
= PropertySheetHeader
->nPages
;
4300 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4301 PropertySheetHeaderPageListSize
, RequiredSize
,
4305 PropertySheetHeader
->nPages
= psh
.nPages
;
4308 TRACE("Returning %d\n", ret
);
4312 struct ClassDevPropertySheetsData
4314 HPROPSHEETPAGE
*PropertySheetPages
;
4315 DWORD MaximumNumberOfPages
;
4316 DWORD NumberOfPages
;
4319 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
4320 IN HPROPSHEETPAGE hPropSheetPage
,
4321 IN OUT LPARAM lParam
)
4323 struct ClassDevPropertySheetsData
*PropPageData
;
4325 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4327 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4329 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4330 PropPageData
->PropertySheetPages
++;
4333 PropPageData
->NumberOfPages
++;
4337 /***********************************************************************
4338 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4340 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
4341 IN HDEVINFO DeviceInfoSet
,
4342 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4343 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4344 IN DWORD PropertySheetHeaderPageListSize
,
4345 OUT PDWORD RequiredSize OPTIONAL
,
4346 IN DWORD PropertySheetType
)
4348 struct DeviceInfoSet
*list
;
4351 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4352 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4353 RequiredSize
, PropertySheetType
);
4356 SetLastError(ERROR_INVALID_HANDLE
);
4357 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4358 SetLastError(ERROR_INVALID_HANDLE
);
4359 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4360 SetLastError(ERROR_INVALID_HANDLE
);
4361 else if (!PropertySheetHeader
)
4362 SetLastError(ERROR_INVALID_PARAMETER
);
4363 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4364 SetLastError(ERROR_INVALID_FLAGS
);
4365 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4366 SetLastError(ERROR_INVALID_USER_BUFFER
);
4367 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4368 SetLastError(ERROR_INVALID_PARAMETER
);
4369 else if (!PropertySheetHeader
)
4370 SetLastError(ERROR_INVALID_PARAMETER
);
4371 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4372 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4373 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4374 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4375 SetLastError(ERROR_INVALID_PARAMETER
);
4378 HKEY hKey
= INVALID_HANDLE_VALUE
;
4379 SP_PROPSHEETPAGE_REQUEST Request
;
4380 LPWSTR PropPageProvider
= NULL
;
4381 HMODULE hModule
= NULL
;
4382 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4383 struct ClassDevPropertySheetsData PropPageData
;
4384 DWORD dwLength
, dwRegType
;
4388 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4391 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4392 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4394 if (hKey
== INVALID_HANDLE_VALUE
)
4397 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4398 if (rc
== ERROR_FILE_NOT_FOUND
)
4400 /* No registry key. As it is optional, don't say it's a bad error */
4406 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4412 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4413 if (!PropPageProvider
)
4415 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4418 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4419 if (rc
!= ERROR_SUCCESS
)
4424 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4426 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4427 if (rc
!= ERROR_SUCCESS
)
4429 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4433 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4434 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4435 Request
.DeviceInfoSet
= DeviceInfoSet
;
4436 Request
.DeviceInfoData
= DeviceInfoData
;
4437 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4438 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4439 PropPageData
.NumberOfPages
= 0;
4440 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4445 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4446 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4448 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4453 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4454 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4458 if (hKey
!= INVALID_HANDLE_VALUE
)
4460 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4461 FreeFunctionPointer(hModule
, pPropPageProvider
);
4464 TRACE("Returning %d\n", ret
);
4468 /***********************************************************************
4469 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4471 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4472 IN HDEVINFO DeviceInfoSet
,
4473 IN PSP_DEVINFO_DATA DeviceInfoData
,
4477 IN HINF InfHandle OPTIONAL
,
4478 IN PCSTR InfSectionName OPTIONAL
)
4480 PCWSTR InfSectionNameW
= NULL
;
4481 HKEY ret
= INVALID_HANDLE_VALUE
;
4485 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4486 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4489 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4497 if (InfSectionNameW
!= NULL
)
4498 MyFree((PVOID
)InfSectionNameW
);
4504 OpenHardwareProfileKey(
4507 IN DWORD samDesired
)
4509 HKEY hHWProfilesKey
= INVALID_HANDLE_VALUE
;
4510 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4511 HKEY ret
= INVALID_HANDLE_VALUE
;
4514 rc
= RegOpenKeyExW(HKLM
,
4515 REGSTR_PATH_HWPROFILES
,
4519 if (rc
!= ERROR_SUCCESS
)
4536 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4545 if (rc
!= ERROR_SUCCESS
)
4550 ret
= hHWProfileKey
;
4553 if (hHWProfilesKey
!= INVALID_HANDLE_VALUE
)
4554 RegCloseKey(hHWProfilesKey
);
4555 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
&& hHWProfileKey
!= ret
)
4556 RegCloseKey(hHWProfileKey
);
4560 /***********************************************************************
4561 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4563 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4564 IN HDEVINFO DeviceInfoSet
,
4565 IN PSP_DEVINFO_DATA DeviceInfoData
,
4569 IN HINF InfHandle OPTIONAL
,
4570 IN PCWSTR InfSectionName OPTIONAL
)
4572 struct DeviceInfoSet
*list
;
4573 HKEY ret
= INVALID_HANDLE_VALUE
;
4575 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4576 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4579 SetLastError(ERROR_INVALID_HANDLE
);
4580 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4581 SetLastError(ERROR_INVALID_HANDLE
);
4582 else if (!DeviceInfoData
)
4583 SetLastError(ERROR_INVALID_PARAMETER
);
4584 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4585 SetLastError(ERROR_INVALID_USER_BUFFER
);
4586 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4587 SetLastError(ERROR_INVALID_PARAMETER
);
4588 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4589 SetLastError(ERROR_INVALID_PARAMETER
);
4590 else if (InfHandle
&& !InfSectionName
)
4591 SetLastError(ERROR_INVALID_PARAMETER
);
4592 else if (!InfHandle
&& InfSectionName
)
4593 SetLastError(ERROR_INVALID_PARAMETER
);
4596 LPWSTR lpGuidString
= NULL
;
4597 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4598 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4599 DWORD Index
; /* Index used in the DriverKey name */
4601 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4602 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4603 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4604 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4605 HKEY hKey
= INVALID_HANDLE_VALUE
;
4608 if (Scope
== DICS_FLAG_GLOBAL
)
4609 RootKey
= list
->HKLM
;
4610 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4612 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
4613 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4615 RootKey
= hHWProfileKey
;
4618 if (KeyType
== DIREG_DEV
)
4620 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4622 rc
= RegCreateKeyExW(
4624 REGSTR_PATH_SYSTEMENUM
,
4627 REG_OPTION_NON_VOLATILE
,
4632 if (rc
!= ERROR_SUCCESS
)
4637 rc
= RegCreateKeyExW(
4639 deviceInfo
->DeviceName
,
4642 REG_OPTION_NON_VOLATILE
,
4643 #if _WIN32_WINNT >= 0x502
4644 KEY_READ
| KEY_WRITE
,
4651 if (rc
!= ERROR_SUCCESS
)
4657 else /* KeyType == DIREG_DRV */
4659 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4661 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4662 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4665 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4668 wcscpy(DriverKey
, L
"{");
4669 wcscat(DriverKey
, lpGuidString
);
4670 wcscat(DriverKey
, L
"}\\");
4671 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4672 rc
= RegOpenKeyExW(RootKey
,
4673 REGSTR_PATH_CLASS_NT
,
4677 if (rc
!= ERROR_SUCCESS
)
4683 /* Try all values for Index between 0 and 9999 */
4685 while (Index
<= 9999)
4688 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4689 rc
= RegCreateKeyEx(hClassKey
,
4693 REG_OPTION_NON_VOLATILE
,
4694 #if _WIN32_WINNT >= 0x502
4695 KEY_READ
| KEY_WRITE
,
4702 if (rc
!= ERROR_SUCCESS
)
4707 if (Disposition
== REG_CREATED_NEW_KEY
)
4710 hKey
= INVALID_HANDLE_VALUE
;
4715 /* Unable to create more than 9999 devices within the same class */
4716 SetLastError(ERROR_GEN_FAILURE
);
4720 /* Open device key, to write Driver value */
4721 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4722 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4724 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4725 if (rc
!= ERROR_SUCCESS
)
4732 /* Do installation of the specified section */
4735 FIXME("Need to install section %s in file %p\n",
4736 debugstr_w(InfSectionName
), InfHandle
);
4742 RpcStringFreeW(&lpGuidString
);
4743 HeapFree(GetProcessHeap(), 0, DriverKey
);
4744 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4745 RegCloseKey(hHWProfileKey
);
4746 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4747 RegCloseKey(hEnumKey
);
4748 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4749 RegCloseKey(hClassKey
);
4750 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4751 RegCloseKey(hDeviceKey
);
4752 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4756 TRACE("Returning 0x%p\n", ret
);
4760 /***********************************************************************
4761 * SetupDiOpenDevRegKey (SETUPAPI.@)
4763 HKEY WINAPI
SetupDiOpenDevRegKey(
4764 HDEVINFO DeviceInfoSet
,
4765 PSP_DEVINFO_DATA DeviceInfoData
,
4771 struct DeviceInfoSet
*list
;
4772 HKEY ret
= INVALID_HANDLE_VALUE
;
4774 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4775 Scope
, HwProfile
, KeyType
, samDesired
);
4778 SetLastError(ERROR_INVALID_HANDLE
);
4779 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4780 SetLastError(ERROR_INVALID_HANDLE
);
4781 else if (!DeviceInfoData
)
4782 SetLastError(ERROR_INVALID_PARAMETER
);
4783 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4784 SetLastError(ERROR_INVALID_USER_BUFFER
);
4785 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4786 SetLastError(ERROR_INVALID_PARAMETER
);
4787 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4788 SetLastError(ERROR_INVALID_PARAMETER
);
4791 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4792 LPWSTR DriverKey
= NULL
;
4796 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4797 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4798 HKEY hKey
= INVALID_HANDLE_VALUE
;
4801 if (Scope
== DICS_FLAG_GLOBAL
)
4802 RootKey
= list
->HKLM
;
4803 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4805 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
4806 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4808 RootKey
= hHWProfileKey
;
4813 REGSTR_PATH_SYSTEMENUM
,
4817 if (rc
!= ERROR_SUCCESS
)
4824 deviceInfo
->DeviceName
,
4826 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4828 RegCloseKey(hEnumKey
);
4829 hEnumKey
= INVALID_HANDLE_VALUE
;
4830 if (rc
!= ERROR_SUCCESS
)
4835 if (KeyType
== DIREG_DEV
)
4837 /* We're done. Just return the hKey handle */
4841 /* Read the 'Driver' key */
4842 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
4843 if (rc
!= ERROR_SUCCESS
)
4848 else if (dwRegType
!= REG_SZ
)
4850 SetLastError(ERROR_GEN_FAILURE
);
4853 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4856 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4859 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4860 if (rc
!= ERROR_SUCCESS
)
4866 hKey
= INVALID_HANDLE_VALUE
;
4867 /* Need to open the driver key */
4870 REGSTR_PATH_CLASS_NT
,
4874 if (rc
!= ERROR_SUCCESS
)
4885 if (rc
!= ERROR_SUCCESS
)
4893 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4894 RegCloseKey(hHWProfileKey
);
4895 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4896 RegCloseKey(hEnumKey
);
4897 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4901 TRACE("Returning 0x%p\n", ret
);
4905 /***********************************************************************
4906 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
4908 BOOL WINAPI
SetupDiCreateDeviceInfoA(
4909 HDEVINFO DeviceInfoSet
,
4911 CONST GUID
*ClassGuid
,
4912 PCSTR DeviceDescription
,
4914 DWORD CreationFlags
,
4915 PSP_DEVINFO_DATA DeviceInfoData
)
4917 LPWSTR DeviceNameW
= NULL
;
4918 LPWSTR DeviceDescriptionW
= NULL
;
4925 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
4926 if (DeviceNameW
== NULL
) return FALSE
;
4928 if (DeviceDescription
)
4930 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
4931 if (DeviceDescriptionW
== NULL
)
4933 if (DeviceNameW
) MyFree(DeviceNameW
);
4938 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
4939 ClassGuid
, DeviceDescriptionW
,
4940 hwndParent
, CreationFlags
,
4943 if (DeviceNameW
) MyFree(DeviceNameW
);
4944 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
4949 /***********************************************************************
4950 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
4952 BOOL WINAPI
SetupDiCreateDeviceInfoW(
4953 HDEVINFO DeviceInfoSet
,
4955 CONST GUID
*ClassGuid
,
4956 PCWSTR DeviceDescription
,
4958 DWORD CreationFlags
,
4959 PSP_DEVINFO_DATA DeviceInfoData
)
4961 struct DeviceInfoSet
*list
;
4964 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
4965 debugstr_guid(ClassGuid
), DeviceDescription
,
4966 hwndParent
, CreationFlags
, DeviceInfoData
);
4969 SetLastError(ERROR_INVALID_HANDLE
);
4970 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4971 SetLastError(ERROR_INVALID_HANDLE
);
4972 else if (!ClassGuid
)
4973 SetLastError(ERROR_INVALID_PARAMETER
);
4974 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
4975 SetLastError(ERROR_CLASS_MISMATCH
);
4976 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
4978 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
4979 SetLastError(ERROR_INVALID_FLAGS
);
4983 SP_DEVINFO_DATA DevInfo
;
4985 if (CreationFlags
& DICD_GENERATE_ID
)
4987 /* Generate a new unique ID for this device */
4988 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
4989 FIXME("not implemented\n");
4993 /* Device name is fully qualified. Try to open it */
4996 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
4997 rc
= SetupDiOpenDeviceInfoW(
5000 NULL
, /* hwndParent */
5001 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
5006 /* SetupDiOpenDeviceInfoW has already added
5007 * the device info to the device info set
5009 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
5011 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5013 struct DeviceInfoElement
*deviceInfo
;
5015 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
5017 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5019 if (!DeviceInfoData
)
5023 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
5025 SetLastError(ERROR_INVALID_USER_BUFFER
);
5029 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5030 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5031 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5040 TRACE("Returning %d\n", ret
);
5044 /***********************************************************************
5045 * Helper functions for SetupDiBuildDriverInfoList
5049 IN PLIST_ENTRY DriverListHead
,
5050 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5051 IN LPGUID ClassGuid
,
5052 IN INFCONTEXT ContextDevice
,
5053 IN
struct InfFileDetails
*InfFileDetails
,
5055 IN LPCWSTR ProviderName
,
5056 IN LPCWSTR ManufacturerName
,
5057 IN LPCWSTR MatchingId
,
5058 FILETIME DriverDate
,
5059 DWORDLONG DriverVersion
,
5062 struct DriverInfoElement
*driverInfo
= NULL
;
5063 HANDLE hFile
= INVALID_HANDLE_VALUE
;
5064 DWORD RequiredSize
= 128; /* Initial buffer size */
5065 BOOL Result
= FALSE
;
5066 PLIST_ENTRY PreviousEntry
;
5067 LPWSTR InfInstallSection
= NULL
;
5070 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
5073 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5076 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
5078 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
5079 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
5081 /* Copy InfFileName field */
5082 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
5083 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
5085 /* Fill InfDate field */
5086 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5087 GENERIC_READ, FILE_SHARE_READ,
5088 NULL, OPEN_EXISTING, 0, NULL);
5089 if (hFile == INVALID_HANDLE_VALUE)
5091 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5095 /* Fill SectionName field */
5096 Result
= SetupGetStringFieldW(
5099 driverInfo
->Details
.SectionName
, LINE_LEN
,
5104 /* Fill DrvDescription field */
5105 Result
= SetupGetStringFieldW(
5107 0, /* Field index */
5108 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
5111 /* Copy MatchingId information */
5114 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5115 if (!driverInfo
->MatchingId
)
5117 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5120 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5123 driverInfo
->MatchingId
= NULL
;
5125 /* Get inf install section */
5127 RequiredSize
= 128; /* Initial buffer size */
5128 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5129 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5131 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5132 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5133 if (!InfInstallSection
)
5135 Result
= SetupGetStringFieldW(
5137 1, /* Field index */
5138 InfInstallSection
, RequiredSize
,
5144 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
5145 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
5147 driverInfo
->DriverRank
= Rank
;
5148 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
5149 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5150 driverInfo
->Info
.DriverType
= DriverType
;
5151 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
5152 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
5153 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
5154 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
5155 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
5158 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
5159 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
5162 driverInfo
->Info
.ProviderName
[0] = '\0';
5163 driverInfo
->Info
.DriverDate
= DriverDate
;
5164 driverInfo
->Info
.DriverVersion
= DriverVersion
;
5165 ReferenceInfFile(InfFileDetails
);
5166 driverInfo
->InfFileDetails
= InfFileDetails
;
5168 /* Insert current driver in driver list, according to its rank */
5169 PreviousEntry
= DriverListHead
->Flink
;
5170 while (PreviousEntry
!= DriverListHead
)
5172 struct DriverInfoElement
*CurrentDriver
;
5173 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
5174 if (CurrentDriver
->DriverRank
> Rank
||
5175 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
5177 /* Insert before the current item */
5178 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
5181 PreviousEntry
= PreviousEntry
->Flink
;
5183 if (PreviousEntry
== DriverListHead
)
5185 /* Insert at the end of the list */
5186 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
5195 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
5196 HeapFree(GetProcessHeap(), 0, driverInfo
);
5198 if (hFile
!= INVALID_HANDLE_VALUE
)
5200 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5206 GetVersionInformationFromInfFile(
5208 OUT LPGUID ClassGuid
,
5209 OUT LPWSTR
* pProviderName
,
5210 OUT FILETIME
* DriverDate
,
5211 OUT DWORDLONG
* DriverVersion
)
5214 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5215 LPWSTR DriverVer
= NULL
;
5216 LPWSTR ProviderName
= NULL
;
5217 LPWSTR pComma
; /* Points into DriverVer */
5218 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5219 SYSTEMTIME SystemTime
;
5221 BOOL ret
= FALSE
; /* Final result */
5223 /* Get class Guid */
5224 if (!SetupGetLineTextW(
5227 L
"Version", L
"ClassGUID",
5228 guidW
, sizeof(guidW
),
5229 NULL
/* Required size */))
5233 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5234 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5236 SetLastError(ERROR_GEN_FAILURE
);
5240 /* Get provider name */
5241 Result
= SetupGetLineTextW(
5243 hInf
, L
"Version", L
"Provider",
5248 /* We know know the needed buffer size */
5249 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5252 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5255 Result
= SetupGetLineTextW(
5257 hInf
, L
"Version", L
"Provider",
5258 ProviderName
, RequiredSize
,
5263 *pProviderName
= ProviderName
;
5265 /* Read the "DriverVer" value */
5266 Result
= SetupGetLineTextW(
5268 hInf
, L
"Version", L
"DriverVer",
5273 /* We know know the needed buffer size */
5274 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5277 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5280 Result
= SetupGetLineTextW(
5282 hInf
, L
"Version", L
"DriverVer",
5283 DriverVer
, RequiredSize
,
5289 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5290 pComma
= wcschr(DriverVer
, ',');
5293 *pComma
= UNICODE_NULL
;
5294 pVersion
= pComma
+ 1;
5296 /* Get driver date version. Invalid date = 00/00/00 */
5297 memset(DriverDate
, 0, sizeof(FILETIME
));
5298 if (wcslen(DriverVer
) == 10
5299 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5300 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5302 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5303 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5304 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5305 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5306 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5307 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5309 /* Get driver version. Invalid version = 0.0.0.0 */
5313 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5314 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5315 LARGE_INTEGER fullVersion
;
5317 pMinor
= strchrW(pVersion
, '.');
5321 pRevision
= strchrW(++pMinor
, '.');
5322 Minor
= atoiW(pMinor
);
5327 pBuild
= strchrW(++pRevision
, '.');
5328 Revision
= atoiW(pRevision
);
5334 Build
= atoiW(pBuild
);
5336 Major
= atoiW(pVersion
);
5337 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5338 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5339 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5346 HeapFree(GetProcessHeap(), 0, ProviderName
);
5347 HeapFree(GetProcessHeap(), 0, DriverVer
);
5352 /***********************************************************************
5353 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5356 SetupDiBuildDriverInfoList(
5357 IN HDEVINFO DeviceInfoSet
,
5358 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5359 IN DWORD DriverType
)
5361 struct DeviceInfoSet
*list
;
5362 SP_DEVINSTALL_PARAMS_W InstallParams
;
5363 PVOID Buffer
= NULL
;
5364 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5365 LPWSTR ProviderName
= NULL
;
5366 LPWSTR ManufacturerName
= NULL
;
5367 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5368 LPWSTR HardwareIDs
= NULL
;
5369 LPWSTR CompatibleIDs
= NULL
;
5370 LPWSTR FullInfFileName
= NULL
;
5371 FILETIME DriverDate
;
5372 DWORDLONG DriverVersion
= 0;
5376 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5379 SetLastError(ERROR_INVALID_HANDLE
);
5380 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5381 SetLastError(ERROR_INVALID_HANDLE
);
5382 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5383 SetLastError(ERROR_INVALID_HANDLE
);
5384 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5385 SetLastError(ERROR_INVALID_PARAMETER
);
5386 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5387 SetLastError(ERROR_INVALID_PARAMETER
);
5388 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5389 SetLastError(ERROR_INVALID_USER_BUFFER
);
5394 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5395 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5399 if (DriverType
== SPDIT_COMPATDRIVER
)
5401 /* Get hardware IDs list */
5403 RequiredSize
= 512; /* Initial buffer size */
5404 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5405 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5407 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5408 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5411 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5414 Result
= SetupDiGetDeviceRegistryPropertyW(
5426 /* Get compatible IDs list */
5428 RequiredSize
= 512; /* Initial buffer size */
5429 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5430 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5432 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5433 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5436 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5439 Result
= SetupDiGetDeviceRegistryPropertyW(
5442 SPDRP_COMPATIBLEIDS
,
5444 (PBYTE
)CompatibleIDs
,
5447 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5449 /* No compatible ID for this device */
5450 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5451 CompatibleIDs
= NULL
;
5459 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5461 /* InstallParams.DriverPath contains the name of a .inf file */
5462 RequiredSize
= wcslen(InstallParams
.DriverPath
) + 2;
5463 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5466 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5469 wcscpy(Buffer
, InstallParams
.DriverPath
);
5470 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
5475 /* Enumerate .inf files */
5477 RequiredSize
= 32768; /* Initial buffer size */
5478 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5479 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5481 HeapFree(GetProcessHeap(), 0, Buffer
);
5482 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5486 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5489 Result
= SetupGetInfFileListW(
5490 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5492 Buffer
, RequiredSize
,
5495 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5497 /* No .inf file in specified directory. So, we should
5498 * success as we created an empty driver info list.
5507 LPWSTR pFullFilename
;
5509 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5511 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5512 if (!FullInfFileName
)
5514 pFullFilename
= &FullInfFileName
[0];
5516 else if (*InstallParams
.DriverPath
)
5519 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5522 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5523 if (!FullInfFileName
)
5525 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5528 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
5529 wcscat(FullInfFileName
, L
"\\");
5530 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
5534 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5535 if (!FullInfFileName
)
5537 pFullFilename
= &FullInfFileName
[0];
5540 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
5542 INFCONTEXT ContextManufacturer
, ContextDevice
;
5545 wcscpy(pFullFilename
, filename
);
5546 TRACE("Opening file %S\n", FullInfFileName
);
5548 currentInfFileDetails
= HeapAlloc(
5551 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
5552 if (!currentInfFileDetails
)
5554 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5555 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5557 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5558 ReferenceInfFile(currentInfFileDetails
);
5559 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5561 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5562 currentInfFileDetails
= NULL
;
5566 if (!GetVersionInformationFromInfFile(
5567 currentInfFileDetails
->hInf
,
5573 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5574 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5575 currentInfFileDetails
= NULL
;
5579 if (DriverType
== SPDIT_CLASSDRIVER
)
5581 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5582 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5588 /* Get the manufacturers list */
5589 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
5592 Result
= SetupGetStringFieldW(
5593 &ContextManufacturer
,
5594 0, /* Field index */
5599 /* We got the needed size for the buffer */
5600 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5601 if (!ManufacturerName
)
5603 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5606 Result
= SetupGetStringFieldW(
5607 &ContextManufacturer
,
5608 0, /* Field index */
5609 ManufacturerName
, RequiredSize
,
5612 /* Get manufacturer section name */
5613 Result
= SetupGetStringFieldW(
5614 &ContextManufacturer
,
5615 1, /* Field index */
5616 ManufacturerSection
, LINE_LEN
,
5620 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5621 /* Add (possible) extension to manufacturer section name */
5622 Result
= SetupDiGetActualSectionToInstallW(
5623 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5626 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
5627 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5632 if (DriverType
== SPDIT_CLASSDRIVER
)
5634 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5635 if (!AddDriverToList(
5636 &list
->DriverListHead
,
5640 currentInfFileDetails
,
5645 DriverDate
, DriverVersion
,
5651 else /* DriverType = SPDIT_COMPATDRIVER */
5653 /* 1. Get all fields */
5654 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5658 BOOL DriverAlreadyAdded
;
5660 for (i
= 2; i
<= FieldCount
; i
++)
5662 LPWSTR DeviceId
= NULL
;
5664 RequiredSize
= 128; /* Initial buffer size */
5665 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5666 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5668 HeapFree(GetProcessHeap(), 0, DeviceId
);
5669 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5672 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5675 Result
= SetupGetStringFieldW(
5678 DeviceId
, RequiredSize
,
5683 HeapFree(GetProcessHeap(), 0, DeviceId
);
5686 DriverAlreadyAdded
= FALSE
;
5687 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5689 if (wcsicmp(DeviceId
, currentId
) == 0)
5692 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5696 currentInfFileDetails
,
5701 DriverDate
, DriverVersion
,
5702 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5703 DriverAlreadyAdded
= TRUE
;
5708 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5710 if (wcsicmp(DeviceId
, currentId
) == 0)
5713 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5717 currentInfFileDetails
,
5722 DriverDate
, DriverVersion
,
5723 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5724 DriverAlreadyAdded
= TRUE
;
5728 HeapFree(GetProcessHeap(), 0, DeviceId
);
5731 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5734 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5735 ManufacturerName
= NULL
;
5736 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5741 HeapFree(GetProcessHeap(), 0, ProviderName
);
5742 ProviderName
= NULL
;
5744 DereferenceInfFile(currentInfFileDetails
);
5745 currentInfFileDetails
= NULL
;
5756 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5757 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5761 InstallParams
.Flags
|= DI_DIDCLASS
;
5762 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5764 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5767 HeapFree(GetProcessHeap(), 0, ProviderName
);
5768 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5769 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5770 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5771 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5772 if (currentInfFileDetails
)
5773 DereferenceInfFile(currentInfFileDetails
);
5774 HeapFree(GetProcessHeap(), 0, Buffer
);
5776 TRACE("Returning %d\n", ret
);
5780 /***********************************************************************
5781 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5784 SetupDiDeleteDeviceInfo(
5785 IN HDEVINFO DeviceInfoSet
,
5786 IN PSP_DEVINFO_DATA DeviceInfoData
)
5788 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5790 FIXME("not implemented\n");
5791 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5796 /***********************************************************************
5797 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5800 SetupDiDestroyDriverInfoList(
5801 IN HDEVINFO DeviceInfoSet
,
5802 IN PSP_DEVINFO_DATA DeviceInfoData
,
5803 IN DWORD DriverType
)
5805 struct DeviceInfoSet
*list
;
5808 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5811 SetLastError(ERROR_INVALID_HANDLE
);
5812 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5813 SetLastError(ERROR_INVALID_HANDLE
);
5814 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5815 SetLastError(ERROR_INVALID_PARAMETER
);
5816 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5817 SetLastError(ERROR_INVALID_PARAMETER
);
5818 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5819 SetLastError(ERROR_INVALID_USER_BUFFER
);
5822 PLIST_ENTRY ListEntry
;
5823 struct DriverInfoElement
*driverInfo
;
5824 SP_DEVINSTALL_PARAMS_W InstallParams
;
5826 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5827 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5830 if (!DeviceInfoData
)
5831 /* Fall back to destroying class driver list */
5832 DriverType
= SPDIT_CLASSDRIVER
;
5834 if (DriverType
== SPDIT_CLASSDRIVER
)
5836 while (!IsListEmpty(&list
->DriverListHead
))
5838 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
5839 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5840 DestroyDriverInfoElement(driverInfo
);
5842 InstallParams
.Reserved
= 0;
5843 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
5844 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
5845 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
5849 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
5850 struct DeviceInfoElement
*deviceInfo
;
5852 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5853 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
5855 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5856 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
5858 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
5859 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5860 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
5862 InstallParamsSet
.Reserved
= 0;
5863 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
5865 DestroyDriverInfoElement(driverInfo
);
5867 InstallParams
.Reserved
= 0;
5868 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
5869 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
5870 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5875 TRACE("Returning %d\n", ret
);
5880 /***********************************************************************
5881 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
5884 SetupDiOpenDeviceInfoA(
5885 IN HDEVINFO DeviceInfoSet
,
5886 IN PCSTR DeviceInstanceId
,
5887 IN HWND hwndParent OPTIONAL
,
5889 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5891 LPWSTR DeviceInstanceIdW
= NULL
;
5894 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5896 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
5897 if (DeviceInstanceIdW
== NULL
)
5900 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
5901 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
5903 MyFree(DeviceInstanceIdW
);
5909 /***********************************************************************
5910 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
5913 SetupDiOpenDeviceInfoW(
5914 IN HDEVINFO DeviceInfoSet
,
5915 IN PCWSTR DeviceInstanceId
,
5916 IN HWND hwndParent OPTIONAL
,
5918 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5920 struct DeviceInfoSet
*list
;
5921 HKEY hEnumKey
, hKey
;
5925 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5927 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
5928 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
5931 SetLastError(ERROR_INVALID_HANDLE
);
5932 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5933 SetLastError(ERROR_INVALID_HANDLE
);
5934 else if (!DeviceInstanceId
)
5935 SetLastError(ERROR_INVALID_PARAMETER
);
5936 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
5938 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
5939 SetLastError(ERROR_INVALID_FLAGS
);
5941 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5942 SetLastError(ERROR_INVALID_USER_BUFFER
);
5945 struct DeviceInfoElement
*deviceInfo
= NULL
;
5946 /* Search if device already exists in DeviceInfoSet.
5947 * If yes, return the existing element
5948 * If no, create a new element using informations in registry
5950 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
5951 while (ItemList
!= &list
->ListHead
)
5956 FIXME("not implemented\n");
5957 ItemList
= ItemList
->Flink
;
5962 /* good one found */
5967 /* Open supposed registry key */
5970 REGSTR_PATH_SYSTEMENUM
,
5974 if (rc
!= ERROR_SUCCESS
)
5985 RegCloseKey(hEnumKey
);
5986 if (rc
!= ERROR_SUCCESS
)
5988 if (rc
== ERROR_FILE_NOT_FOUND
)
5989 rc
= ERROR_NO_SUCH_DEVINST
;
5994 /* FIXME: try to get ClassGUID from registry, instead of
5995 * sending GUID_NULL to CreateDeviceInfoElement
5997 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
6002 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
6008 if (ret
&& deviceInfo
&& DeviceInfoData
)
6010 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
6011 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
6012 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
6020 /***********************************************************************
6021 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6024 SetupDiEnumDriverInfoA(
6025 IN HDEVINFO DeviceInfoSet
,
6026 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6027 IN DWORD DriverType
,
6028 IN DWORD MemberIndex
,
6029 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6031 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6034 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6035 DriverType
, MemberIndex
, DriverInfoData
);
6037 if (DriverInfoData
== NULL
)
6038 SetLastError(ERROR_INVALID_PARAMETER
);
6039 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6040 SetLastError(ERROR_INVALID_USER_BUFFER
);
6043 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6044 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
6045 DriverType
, MemberIndex
, &driverInfoData2W
);
6049 /* Do W->A conversion */
6050 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6051 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6052 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6053 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6055 DriverInfoData
->Description
[0] = '\0';
6058 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6059 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6061 DriverInfoData
->MfgName
[0] = '\0';
6064 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6065 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6067 DriverInfoData
->ProviderName
[0] = '\0';
6070 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6072 /* Copy more fields */
6073 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6074 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6079 TRACE("Returning %d\n", ret
);
6084 /***********************************************************************
6085 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6088 SetupDiEnumDriverInfoW(
6089 IN HDEVINFO DeviceInfoSet
,
6090 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6091 IN DWORD DriverType
,
6092 IN DWORD MemberIndex
,
6093 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6095 PLIST_ENTRY ListHead
;
6098 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6099 DriverType
, MemberIndex
, DriverInfoData
);
6101 if (!DeviceInfoSet
|| !DriverInfoData
)
6102 SetLastError(ERROR_INVALID_PARAMETER
);
6103 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6104 SetLastError(ERROR_INVALID_HANDLE
);
6105 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6106 SetLastError(ERROR_INVALID_HANDLE
);
6107 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6108 SetLastError(ERROR_INVALID_PARAMETER
);
6109 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
6110 SetLastError(ERROR_INVALID_PARAMETER
);
6111 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6112 SetLastError(ERROR_INVALID_PARAMETER
);
6113 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6114 SetLastError(ERROR_INVALID_USER_BUFFER
);
6117 struct DeviceInfoElement
*devInfo
= NULL
;
6118 PLIST_ENTRY ItemList
;
6120 devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6121 if (DriverType
== SPDIT_CLASSDRIVER
||
6122 (devInfo
&& devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
6124 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6128 ListHead
= &devInfo
->DriverListHead
;
6131 ItemList
= ListHead
->Flink
;
6132 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
6133 ItemList
= ItemList
->Flink
;
6134 if (ItemList
== ListHead
)
6135 SetLastError(ERROR_NO_MORE_ITEMS
);
6138 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
6141 &DriverInfoData
->DriverType
,
6142 &DrvInfo
->Info
.DriverType
,
6143 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6148 TRACE("Returning %d\n", ret
);
6153 /***********************************************************************
6154 * SetupDiGetSelectedDevice (SETUPAPI.@)
6157 SetupDiGetSelectedDevice(
6158 IN HDEVINFO DeviceInfoSet
,
6159 OUT PSP_DEVINFO_DATA DeviceInfoData
)
6161 struct DeviceInfoSet
*list
;
6164 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6167 SetLastError(ERROR_INVALID_HANDLE
);
6168 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6169 SetLastError(ERROR_INVALID_HANDLE
);
6170 else if (list
->SelectedDevice
== NULL
)
6171 SetLastError(ERROR_NO_DEVICE_SELECTED
);
6172 else if (!DeviceInfoData
)
6173 SetLastError(ERROR_INVALID_PARAMETER
);
6174 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6175 SetLastError(ERROR_INVALID_USER_BUFFER
);
6178 memcpy(&DeviceInfoData
->ClassGuid
,
6179 &list
->SelectedDevice
->ClassGuid
,
6181 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
6182 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
6186 TRACE("Returning %d\n", ret
);
6191 /***********************************************************************
6192 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6195 SetupDiGetSelectedDriverA(
6196 IN HDEVINFO DeviceInfoSet
,
6197 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6198 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6200 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6203 if (DriverInfoData
== NULL
)
6204 SetLastError(ERROR_INVALID_PARAMETER
);
6205 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6206 SetLastError(ERROR_INVALID_USER_BUFFER
);
6209 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6211 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
6217 /* Do W->A conversion */
6218 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6219 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6220 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6221 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6223 DriverInfoData
->Description
[0] = '\0';
6226 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6227 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6229 DriverInfoData
->MfgName
[0] = '\0';
6232 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6233 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6235 DriverInfoData
->ProviderName
[0] = '\0';
6238 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6240 /* Copy more fields */
6241 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6242 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6251 /***********************************************************************
6252 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6255 SetupDiGetSelectedDriverW(
6256 IN HDEVINFO DeviceInfoSet
,
6257 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6258 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6262 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6264 if (!DeviceInfoSet
|| !DriverInfoData
)
6265 SetLastError(ERROR_INVALID_PARAMETER
);
6266 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6267 SetLastError(ERROR_INVALID_HANDLE
);
6268 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6269 SetLastError(ERROR_INVALID_HANDLE
);
6270 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6271 SetLastError(ERROR_INVALID_USER_BUFFER
);
6272 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6273 SetLastError(ERROR_INVALID_USER_BUFFER
);
6276 SP_DEVINSTALL_PARAMS InstallParams
;
6278 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6279 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6281 struct DriverInfoElement
*driverInfo
;
6282 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6283 if (driverInfo
== NULL
)
6284 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6288 &DriverInfoData
->DriverType
,
6289 &driverInfo
->Info
.DriverType
,
6290 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6296 TRACE("Returning %d\n", ret
);
6301 /***********************************************************************
6302 * SetupDiSetSelectedDevice (SETUPAPI.@)
6305 SetupDiSetSelectedDevice(
6306 IN HDEVINFO DeviceInfoSet
,
6307 IN PSP_DEVINFO_DATA DeviceInfoData
)
6309 struct DeviceInfoSet
*list
;
6312 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6315 SetLastError(ERROR_INVALID_HANDLE
);
6316 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6317 SetLastError(ERROR_INVALID_HANDLE
);
6318 else if (!DeviceInfoData
)
6319 SetLastError(ERROR_INVALID_PARAMETER
);
6320 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6321 SetLastError(ERROR_INVALID_USER_BUFFER
);
6322 else if (DeviceInfoData
->Reserved
== 0)
6323 SetLastError(ERROR_INVALID_USER_BUFFER
);
6326 list
->SelectedDevice
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6330 TRACE("Returning %d\n", ret
);
6335 /***********************************************************************
6336 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6339 SetupDiSetSelectedDriverA(
6340 IN HDEVINFO DeviceInfoSet
,
6341 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6342 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6344 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6345 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6348 if (DriverInfoData
!= NULL
)
6350 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6351 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6353 SetLastError(ERROR_INVALID_PARAMETER
);
6357 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6358 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6360 if (DriverInfoDataW
.Reserved
== 0)
6362 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6364 /* convert the strings to unicode */
6365 if (!MultiByteToWideChar(CP_ACP
,
6367 DriverInfoData
->Description
,
6369 DriverInfoDataW
.Description
,
6371 !MultiByteToWideChar(CP_ACP
,
6373 DriverInfoData
->ProviderName
,
6375 DriverInfoDataW
.ProviderName
,
6382 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6385 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6389 if (ret
&& pDriverInfoDataW
!= NULL
)
6391 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6398 /***********************************************************************
6399 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6402 SetupDiSetSelectedDriverW(
6403 IN HDEVINFO DeviceInfoSet
,
6404 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6405 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6409 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6412 SetLastError(ERROR_INVALID_PARAMETER
);
6413 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6414 SetLastError(ERROR_INVALID_HANDLE
);
6415 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6416 SetLastError(ERROR_INVALID_HANDLE
);
6417 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6418 SetLastError(ERROR_INVALID_USER_BUFFER
);
6419 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6420 SetLastError(ERROR_INVALID_USER_BUFFER
);
6423 struct DriverInfoElement
**pDriverInfo
;
6424 PLIST_ENTRY ListHead
, ItemList
;
6428 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6429 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6433 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6434 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6437 if (!DriverInfoData
)
6439 *pDriverInfo
= NULL
;
6444 /* Search selected driver in list */
6445 ItemList
= ListHead
->Flink
;
6446 while (ItemList
!= ListHead
)
6448 if (DriverInfoData
->Reserved
!= 0)
6450 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6455 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6456 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
6457 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6458 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6459 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6465 if (ItemList
== ListHead
)
6466 SetLastError(ERROR_INVALID_PARAMETER
);
6469 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
6470 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6472 TRACE("Choosing driver whose rank is 0x%lx\n",
6473 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
6475 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6480 TRACE("Returning %d\n", ret
);
6484 /***********************************************************************
6485 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6488 SetupDiGetDriverInfoDetailA(
6489 IN HDEVINFO DeviceInfoSet
,
6490 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6491 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6492 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6493 IN DWORD DriverInfoDetailDataSize
,
6494 OUT PDWORD RequiredSize OPTIONAL
)
6496 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6497 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6499 DWORD HardwareIDLen
= 0;
6502 /* do some sanity checks, the unicode version might do more thorough checks */
6503 if (DriverInfoData
== NULL
||
6504 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6505 (DriverInfoDetailData
!= NULL
&&
6506 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6507 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6509 SetLastError(ERROR_INVALID_PARAMETER
);
6513 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6514 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6516 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6518 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6520 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6524 SetLastError(ERROR_INVALID_PARAMETER
);
6527 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6528 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6530 /* convert the strings to unicode */
6531 if (MultiByteToWideChar(CP_ACP
,
6533 DriverInfoData
->Description
,
6535 DriverInfoDataW
.Description
,
6537 MultiByteToWideChar(CP_ACP
,
6539 DriverInfoData
->MfgName
,
6541 DriverInfoDataW
.MfgName
,
6543 MultiByteToWideChar(CP_ACP
,
6545 DriverInfoData
->ProviderName
,
6547 DriverInfoDataW
.ProviderName
,
6550 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6552 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6553 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6556 if (DriverInfoDetailData
!= NULL
)
6558 /* calculate the unicode buffer size from the ansi buffer size */
6559 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6560 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6561 (HardwareIDLen
* sizeof(WCHAR
));
6563 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6564 if (DriverInfoDetailDataW
== NULL
)
6566 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6570 /* initialize the buffer */
6571 ZeroMemory(DriverInfoDetailDataW
,
6573 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6576 /* call the unicode version */
6577 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6580 DriverInfoDetailDataW
,
6586 if (DriverInfoDetailDataW
!= NULL
)
6588 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6589 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6590 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6591 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6592 if (WideCharToMultiByte(CP_ACP
,
6594 DriverInfoDetailDataW
->SectionName
,
6596 DriverInfoDetailData
->SectionName
,
6600 WideCharToMultiByte(CP_ACP
,
6602 DriverInfoDetailDataW
->InfFileName
,
6604 DriverInfoDetailData
->InfFileName
,
6608 WideCharToMultiByte(CP_ACP
,
6610 DriverInfoDetailDataW
->DrvDescription
,
6612 DriverInfoDetailData
->DrvDescription
,
6616 WideCharToMultiByte(CP_ACP
,
6618 DriverInfoDetailDataW
->HardwareID
,
6620 DriverInfoDetailData
->HardwareID
,
6626 DWORD hwidlen
= HardwareIDLen
;
6627 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6629 /* count the strings in the list */
6632 len
= lstrlenA(s
) + 1;
6641 /* looks like the string list wasn't terminated... */
6642 SetLastError(ERROR_INVALID_USER_BUFFER
);
6648 /* make sure CompatIDsOffset points to the second string in the
6652 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6653 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6654 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6658 DriverInfoDetailData
->CompatIDsOffset
= 0;
6659 DriverInfoDetailData
->CompatIDsLength
= 0;
6668 if (RequiredSize
!= NULL
)
6670 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6671 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6677 if (DriverInfoDetailDataW
!= NULL
)
6679 MyFree(DriverInfoDetailDataW
);
6685 /***********************************************************************
6686 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6689 SetupDiGetDriverInfoDetailW(
6690 IN HDEVINFO DeviceInfoSet
,
6691 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6692 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6693 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6694 IN DWORD DriverInfoDetailDataSize
,
6695 OUT PDWORD RequiredSize OPTIONAL
)
6699 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6700 DriverInfoData
, DriverInfoDetailData
,
6701 DriverInfoDetailDataSize
, RequiredSize
);
6704 SetLastError(ERROR_INVALID_PARAMETER
);
6705 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6706 SetLastError(ERROR_INVALID_HANDLE
);
6707 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6708 SetLastError(ERROR_INVALID_HANDLE
);
6709 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6710 SetLastError(ERROR_INVALID_USER_BUFFER
);
6711 else if (!DriverInfoData
)
6712 SetLastError(ERROR_INVALID_PARAMETER
);
6713 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6714 SetLastError(ERROR_INVALID_PARAMETER
);
6715 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6716 SetLastError(ERROR_INVALID_PARAMETER
);
6717 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6718 SetLastError(ERROR_INVALID_USER_BUFFER
);
6719 else if (DriverInfoData
->Reserved
== 0)
6720 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6723 struct DriverInfoElement
*driverInfoElement
;
6724 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6727 DriverInfoDetailData
,
6728 &driverInfoElement
->Details
,
6729 driverInfoElement
->Details
.cbSize
);
6730 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6731 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6736 TRACE("Returning %d\n", ret
);
6740 /* Return the current hardware profile id, or -1 if error */
6742 GetCurrentHwProfile(
6743 IN HDEVINFO DeviceInfoSet
)
6745 HKEY hKey
= INVALID_HANDLE_VALUE
;
6746 DWORD dwRegType
, dwLength
;
6749 DWORD ret
= (DWORD
)-1;
6752 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
6753 REGSTR_PATH_IDCONFIGDB
,
6757 if (rc
!= ERROR_SUCCESS
)
6763 dwLength
= sizeof(DWORD
);
6764 rc
= RegQueryValueExW(
6766 REGSTR_VAL_CURRENTCONFIG
,
6769 (LPBYTE
)&hwProfile
, &dwLength
);
6770 if (rc
!= ERROR_SUCCESS
)
6775 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6777 SetLastError(ERROR_GEN_FAILURE
);
6784 if (hKey
!= INVALID_HANDLE_VALUE
)
6792 IN HDEVINFO DeviceInfoSet
,
6793 IN PSP_DEVINFO_DATA DeviceInfoData
)
6795 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6796 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6799 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
6801 /* At the moment, I only know how to start local devices */
6802 SetLastError(ERROR_INVALID_COMPUTERNAME
);
6806 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
6807 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6808 SetLastError(RtlNtStatusToDosError(Status
));
6809 return NT_SUCCESS(Status
);
6812 static BOOL
StopDevice(
6813 IN HDEVINFO DeviceInfoSet
,
6814 IN PSP_DEVINFO_DATA DeviceInfoData
)
6816 FIXME("Stub %p %p\n", DeviceInfoSet
, DeviceInfoData
);
6820 /***********************************************************************
6821 * SetupDiChangeState (SETUPAPI.@)
6825 IN HDEVINFO DeviceInfoSet
,
6826 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6828 PSP_PROPCHANGE_PARAMS PropChange
;
6829 HKEY hKey
= INVALID_HANDLE_VALUE
;
6830 LPCWSTR RegistryValueName
;
6831 DWORD dwConfigFlags
, dwLength
, dwRegType
;
6835 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6837 if (!DeviceInfoData
)
6838 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
6840 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
6843 SetLastError(ERROR_INVALID_PARAMETER
);
6847 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
6848 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
6850 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
6852 switch (PropChange
->StateChange
)
6857 /* Enable/disable device in registry */
6858 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
6859 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6860 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
6861 if (hKey
== INVALID_HANDLE_VALUE
)
6863 dwLength
= sizeof(DWORD
);
6864 rc
= RegQueryValueExW(
6869 (LPBYTE
)&dwConfigFlags
, &dwLength
);
6870 if (rc
== ERROR_FILE_NOT_FOUND
)
6872 else if (rc
!= ERROR_SUCCESS
)
6877 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6879 SetLastError(ERROR_GEN_FAILURE
);
6882 if (PropChange
->StateChange
== DICS_ENABLE
)
6883 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6885 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6891 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
6892 if (rc
!= ERROR_SUCCESS
)
6898 /* Enable/disable device if needed */
6899 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
6900 || PropChange
->HwProfile
== 0
6901 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
6903 if (PropChange
->StateChange
== DICS_ENABLE
)
6904 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6906 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
6912 case DICS_PROPCHANGE
:
6914 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6919 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
6920 SetLastError(ERROR_NOT_SUPPORTED
);
6925 if (hKey
!= INVALID_HANDLE_VALUE
)
6928 TRACE("Returning %d\n", ret
);
6932 /***********************************************************************
6933 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
6936 SetupDiSelectBestCompatDrv(
6937 IN HDEVINFO DeviceInfoSet
,
6938 IN PSP_DEVINFO_DATA DeviceInfoData
)
6940 SP_DRVINFO_DATA_W drvInfoData
;
6943 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6945 /* Drivers are sorted by rank in the driver list, so
6946 * the first driver in the list is the best one.
6948 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
6949 ret
= SetupDiEnumDriverInfoW(
6953 0, /* Member index */
6958 ret
= SetupDiSetSelectedDriverW(
6964 TRACE("Returning %d\n", ret
);
6968 /***********************************************************************
6969 * SetupDiInstallDriverFiles (SETUPAPI.@)
6972 SetupDiInstallDriverFiles(
6973 IN HDEVINFO DeviceInfoSet
,
6974 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6978 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6981 SetLastError(ERROR_INVALID_PARAMETER
);
6982 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6983 SetLastError(ERROR_INVALID_HANDLE
);
6984 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6985 SetLastError(ERROR_INVALID_HANDLE
);
6986 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6987 SetLastError(ERROR_INVALID_USER_BUFFER
);
6988 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
6989 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6990 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
6991 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6994 SP_DEVINSTALL_PARAMS_W InstallParams
;
6995 struct DriverInfoElement
*SelectedDriver
;
6996 WCHAR SectionName
[MAX_PATH
];
6997 DWORD SectionNameLength
= 0;
6998 PVOID InstallMsgHandler
;
6999 PVOID InstallMsgHandlerContext
;
7000 PVOID Context
= NULL
;
7002 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7003 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7007 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7008 if (!SelectedDriver
)
7010 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7014 ret
= SetupDiGetActualSectionToInstallW(
7015 SelectedDriver
->InfFileDetails
->hInf
,
7016 SelectedDriver
->Details
.SectionName
,
7017 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
7021 if (InstallParams
.InstallMsgHandler
)
7023 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
7024 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
7028 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7031 InstallMsgHandler
= SetupDefaultQueueCallback
;
7032 InstallMsgHandlerContext
= Context
;
7034 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7035 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7036 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7037 InstallMsgHandler
, InstallMsgHandlerContext
,
7038 DeviceInfoSet
, DeviceInfoData
);
7042 /* Install files from .CoInstallers section */
7043 lstrcatW(SectionName
, DotCoInstallers
);
7044 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7045 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7046 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7047 InstallMsgHandler
, InstallMsgHandlerContext
,
7048 DeviceInfoSet
, DeviceInfoData
);
7052 /* Set the DI_NOFILECOPY flag to prevent another
7053 * installation during SetupDiInstallDevice */
7054 InstallParams
.Flags
|= DI_NOFILECOPY
;
7055 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7059 SetupTermDefaultQueueCallback(Context
);
7063 TRACE("Returning %d\n", ret
);
7067 /***********************************************************************
7068 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7071 SetupDiRegisterCoDeviceInstallers(
7072 IN HDEVINFO DeviceInfoSet
,
7073 IN PSP_DEVINFO_DATA DeviceInfoData
)
7075 BOOL ret
= FALSE
; /* Return value */
7077 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7080 SetLastError(ERROR_INVALID_PARAMETER
);
7081 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7082 SetLastError(ERROR_INVALID_HANDLE
);
7083 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7084 SetLastError(ERROR_INVALID_HANDLE
);
7085 else if (!DeviceInfoData
)
7086 SetLastError(ERROR_INVALID_PARAMETER
);
7087 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7088 SetLastError(ERROR_INVALID_USER_BUFFER
);
7091 SP_DEVINSTALL_PARAMS_W InstallParams
;
7092 struct DriverInfoElement
*SelectedDriver
;
7095 WCHAR SectionName
[MAX_PATH
];
7096 DWORD SectionNameLength
= 0;
7097 HKEY hKey
= INVALID_HANDLE_VALUE
;
7098 PVOID Context
= NULL
;
7100 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7101 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7105 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7106 if (SelectedDriver
== NULL
)
7108 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7112 /* Get .CoInstallers section name */
7113 Result
= SetupDiGetActualSectionToInstallW(
7114 SelectedDriver
->InfFileDetails
->hInf
,
7115 SelectedDriver
->Details
.SectionName
,
7116 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7117 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
7119 lstrcatW(SectionName
, DotCoInstallers
);
7121 /* Open/Create driver key information */
7122 #if _WIN32_WINNT >= 0x502
7123 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7125 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7127 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7128 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7129 if (hKey
== INVALID_HANDLE_VALUE
)
7132 /* Install .CoInstallers section */
7133 DoAction
= SPINST_REGISTRY
;
7134 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7136 DoAction
|= SPINST_FILES
;
7137 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7141 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7142 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7143 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7144 SetupDefaultQueueCallback
, Context
,
7145 DeviceInfoSet
, DeviceInfoData
);
7153 SetupTermDefaultQueueCallback(Context
);
7154 if (hKey
!= INVALID_HANDLE_VALUE
)
7158 TRACE("Returning %d\n", ret
);
7163 InstallOneInterface(
7164 IN LPGUID InterfaceGuid
,
7165 IN LPCWSTR ReferenceString
,
7166 IN LPCWSTR InterfaceSection
,
7167 IN UINT InterfaceFlags
)
7169 if (InterfaceFlags
!= 0)
7171 SetLastError(ERROR_INVALID_PARAMETER
);
7175 FIXME("Need to AddInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid
),
7176 debugstr_w(ReferenceString
), debugstr_w(InterfaceSection
), InterfaceFlags
);
7180 /***********************************************************************
7181 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7184 SetupDiInstallDeviceInterfaces(
7185 IN HDEVINFO DeviceInfoSet
,
7186 IN PSP_DEVINFO_DATA DeviceInfoData
)
7188 struct DeviceInfoSet
*list
= NULL
;
7191 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7194 SetLastError(ERROR_INVALID_PARAMETER
);
7195 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7196 SetLastError(ERROR_INVALID_HANDLE
);
7197 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7198 SetLastError(ERROR_INVALID_HANDLE
);
7199 else if (!DeviceInfoData
)
7200 SetLastError(ERROR_INVALID_PARAMETER
);
7201 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7202 SetLastError(ERROR_INVALID_USER_BUFFER
);
7205 struct DriverInfoElement
*SelectedDriver
;
7206 SP_DEVINSTALL_PARAMS_W InstallParams
;
7207 WCHAR SectionName
[MAX_PATH
];
7208 DWORD SectionNameLength
= 0;
7209 INFCONTEXT ContextInterface
;
7210 LPWSTR InterfaceGuidString
= NULL
;
7211 LPWSTR ReferenceString
= NULL
;
7212 LPWSTR InterfaceSection
= NULL
;
7213 UINT InterfaceFlags
;
7217 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7218 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7222 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7223 if (SelectedDriver
== NULL
)
7225 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7230 /* Get .Interfaces section name */
7231 Result
= SetupDiGetActualSectionToInstallW(
7232 SelectedDriver
->InfFileDetails
->hInf
,
7233 SelectedDriver
->Details
.SectionName
,
7234 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7235 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".Interfaces") - 1)
7237 wcscat(SectionName
, L
".Interfaces");
7240 Result
= SetupFindFirstLineW(
7241 SelectedDriver
->InfFileDetails
->hInf
,
7245 while (ret
&& Result
)
7247 ret
= GetStringField(&ContextInterface
, 1, &InterfaceGuidString
);
7250 else if (strlenW(InterfaceGuidString
) != MAX_GUID_STRING_LEN
- 1)
7252 SetLastError(ERROR_INVALID_PARAMETER
);
7257 InterfaceGuidString
[MAX_GUID_STRING_LEN
- 2] = '\0'; /* Replace the } by a NULL character */
7258 if (UuidFromStringW(&InterfaceGuidString
[1], &InterfaceGuid
) != RPC_S_OK
)
7260 /* Bad GUID, skip the entry */
7261 SetLastError(ERROR_INVALID_PARAMETER
);
7266 ret
= GetStringField(&ContextInterface
, 2, &ReferenceString
);
7270 ret
= GetStringField(&ContextInterface
, 3, &InterfaceSection
);
7274 ret
= SetupGetIntField(
7276 4, /* Field index */
7280 if (GetLastError() == ERROR_INVALID_PARAMETER
)
7282 /* The field may be empty. Ignore the error */
7290 /* Install Interface */
7291 ret
= InstallOneInterface(&InterfaceGuid
, ReferenceString
, InterfaceSection
, InterfaceFlags
);
7294 MyFree(InterfaceGuidString
);
7295 MyFree(ReferenceString
);
7296 MyFree(InterfaceSection
);
7297 InterfaceGuidString
= ReferenceString
= InterfaceSection
= NULL
;
7298 Result
= SetupFindNextMatchLineW(&ContextInterface
, L
"AddInterface", &ContextInterface
);
7302 TRACE("Returning %d\n", ret
);
7307 InfIsFromOEMLocation(
7309 OUT LPBOOL IsOEMLocation
)
7313 last
= strrchrW(FullName
, '\\');
7316 /* No directory specified */
7317 *IsOEMLocation
= FALSE
;
7321 WCHAR Windir
[MAX_PATH
];
7324 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
7325 if (ret
== 0 || ret
>= MAX_PATH
)
7327 SetLastError(ERROR_GEN_FAILURE
);
7331 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
7333 /* The path is %SYSTEMROOT%\Inf */
7334 *IsOEMLocation
= FALSE
;
7338 /* The file is in another place */
7339 *IsOEMLocation
= TRUE
;
7345 /***********************************************************************
7346 * SetupDiInstallDevice (SETUPAPI.@)
7349 SetupDiInstallDevice(
7350 IN HDEVINFO DeviceInfoSet
,
7351 IN PSP_DEVINFO_DATA DeviceInfoData
)
7353 SP_DEVINSTALL_PARAMS_W InstallParams
;
7354 struct DriverInfoElement
*SelectedDriver
;
7355 SYSTEMTIME DriverDate
;
7356 WCHAR SectionName
[MAX_PATH
];
7358 DWORD SectionNameLength
= 0;
7359 BOOL Result
= FALSE
;
7362 LPWSTR pSectionName
= NULL
;
7363 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
7365 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
7366 BOOL RebootRequired
= FALSE
;
7367 HKEY hKey
= INVALID_HANDLE_VALUE
;
7368 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
7369 BOOL NeedtoCopyFile
;
7370 LARGE_INTEGER fullVersion
;
7372 PVOID Context
= NULL
;
7373 BOOL ret
= FALSE
; /* Return value */
7375 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7378 SetLastError(ERROR_INVALID_PARAMETER
);
7379 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7380 SetLastError(ERROR_INVALID_HANDLE
);
7381 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7382 SetLastError(ERROR_INVALID_HANDLE
);
7383 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7384 SetLastError(ERROR_INVALID_USER_BUFFER
);
7390 /* One parameter is bad */
7394 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7395 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7399 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
7401 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
7405 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7406 if (SelectedDriver
== NULL
)
7408 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7412 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
7414 Result
= SetupDiGetActualSectionToInstallW(
7415 SelectedDriver
->InfFileDetails
->hInf
,
7416 SelectedDriver
->Details
.SectionName
,
7417 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7418 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(DotServices
))
7420 pSectionName
= &SectionName
[wcslen(SectionName
)];
7422 /* Get information from [Version] section */
7423 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
7425 /* Format ClassGuid to a string */
7426 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
7428 RequiredSize
= lstrlenW(lpGuidString
);
7429 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
7430 if (!lpFullGuidString
)
7432 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7435 lpFullGuidString
[0] = '{';
7436 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
7437 lpFullGuidString
[RequiredSize
+ 1] = '}';
7438 lpFullGuidString
[RequiredSize
+ 2] = '\0';
7440 /* Open/Create driver key information */
7441 #if _WIN32_WINNT >= 0x502
7442 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7444 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7446 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7447 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7448 if (hKey
== INVALID_HANDLE_VALUE
)
7451 /* Install main section */
7453 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7454 DoAction
|= SPINST_REGISTRY
;
7455 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7457 DoAction
|= SPINST_FILES
;
7458 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7462 *pSectionName
= '\0';
7463 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7464 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7465 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7466 SetupDefaultQueueCallback
, Context
,
7467 DeviceInfoSet
, DeviceInfoData
);
7470 InstallParams
.Flags
|= DI_NOFILECOPY
;
7471 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7473 /* Write information to driver key */
7474 *pSectionName
= UNICODE_NULL
;
7475 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
7476 TRACE("Write information to driver key\n");
7477 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7478 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7479 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7480 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
7481 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
7482 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
7483 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
7484 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
7485 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7486 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7487 if (rc
== ERROR_SUCCESS
)
7488 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7489 if (rc
== ERROR_SUCCESS
)
7490 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7491 if (rc
== ERROR_SUCCESS
)
7493 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7494 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7496 if (rc
== ERROR_SUCCESS
)
7497 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7498 if (rc
== ERROR_SUCCESS
)
7499 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7500 if (rc
== ERROR_SUCCESS
)
7501 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTIONEXT
, 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7502 if (rc
== ERROR_SUCCESS
)
7503 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7504 if (rc
== ERROR_SUCCESS
)
7505 rc
= RegSetValueEx(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7506 if (rc
!= ERROR_SUCCESS
)
7512 hKey
= INVALID_HANDLE_VALUE
;
7514 /* FIXME: Process .LogConfigOverride section */
7516 /* Install .Services section */
7517 wcscpy(pSectionName
, DotServices
);
7518 Result
= SetupInstallServicesFromInfSectionExW(
7519 SelectedDriver
->InfFileDetails
->hInf
,
7528 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
7529 RebootRequired
= TRUE
;
7531 /* Copy .inf file to Inf\ directory (if needed) */
7532 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7537 Result
= SetupCopyOEMInfW(
7538 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7541 SP_COPY_NOOVERWRITE
,
7547 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7548 * to release use of current InfFile */
7551 /* Open device registry key */
7552 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7553 if (hKey
== INVALID_HANDLE_VALUE
)
7556 /* Install .HW section */
7558 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7559 DoAction
|= SPINST_REGISTRY
;
7560 wcscpy(pSectionName
, L
".HW");
7561 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7562 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7563 DoAction
, hKey
, NULL
, 0,
7565 DeviceInfoSet
, DeviceInfoData
);
7569 /* Write information to enum key */
7570 TRACE("Write information to enum key\n");
7571 TRACE("Class : '%S'\n", ClassName
);
7572 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
7573 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7574 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
7575 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
7576 if (rc
== ERROR_SUCCESS
)
7577 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7578 if (rc
== ERROR_SUCCESS
)
7579 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7580 if (rc
== ERROR_SUCCESS
)
7581 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7582 if (rc
!= ERROR_SUCCESS
)
7588 /* Start the device */
7589 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7590 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7595 /* End of installation */
7596 if (hClassKey
!= INVALID_HANDLE_VALUE
)
7597 RegCloseKey(hClassKey
);
7598 if (hKey
!= INVALID_HANDLE_VALUE
)
7601 RpcStringFreeW(&lpGuidString
);
7602 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7604 SetupTermDefaultQueueCallback(Context
);
7605 TRACE("Returning %d\n", ret
);