2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 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 ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
983 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
984 static const WCHAR ExtensionArchitectureia64
[] = {'i','a','6','4',0};
985 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
986 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
987 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
989 /* Set various extensions values */
990 switch (pPlatformInfo
->Platform
)
992 case VER_PLATFORM_WIN32_WINDOWS
:
993 pExtensionPlatform
= ExtensionPlatformWindows
;
995 case VER_PLATFORM_WIN32_NT
:
996 pExtensionPlatform
= ExtensionPlatformNT
;
999 ERR("Unkown platform 0x%lx\n", pPlatformInfo
->Platform
);
1000 pExtensionPlatform
= ExtensionPlatformNone
;
1003 switch (pPlatformInfo
->ProcessorArchitecture
)
1005 case PROCESSOR_ARCHITECTURE_ALPHA
:
1006 pExtensionArchitecture
= ExtensionArchitecturealpha
;
1008 case PROCESSOR_ARCHITECTURE_AMD64
:
1009 pExtensionArchitecture
= ExtensionArchitectureamd64
;
1011 case PROCESSOR_ARCHITECTURE_IA64
:
1012 pExtensionArchitecture
= ExtensionArchitectureia64
;
1014 case PROCESSOR_ARCHITECTURE_INTEL
:
1015 pExtensionArchitecture
= ExtensionArchitecturex86
;
1017 case PROCESSOR_ARCHITECTURE_MIPS
:
1018 pExtensionArchitecture
= ExtensionArchitecturemips
;
1020 case PROCESSOR_ARCHITECTURE_PPC
:
1021 pExtensionArchitecture
= ExtensionArchitectureppc
;
1024 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo
->ProcessorArchitecture
);
1025 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
1026 pExtensionArchitecture
= ExtensionArchitectureNone
;
1030 SectionName
[LINE_LEN
] = UNICODE_NULL
;
1032 /* Test with platform.architecture.major.minor extension */
1033 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s.%lu.%lu", InfSectionName
,
1034 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1035 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1036 if (lLineCount
!= -1) goto sectionfound
;
1038 /* Test with platform.major.minor extension */
1039 snprintfW(SectionName
, LINE_LEN
, L
"%s%s.%lu.%lu", InfSectionName
,
1040 pExtensionPlatform
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1041 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1042 if (lLineCount
!= -1) goto sectionfound
;
1044 /* Test with platform.architecture.major extension */
1045 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s.%lu", InfSectionName
,
1046 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
);
1047 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1048 if (lLineCount
!= -1) goto sectionfound
;
1050 /* Test with platform.major extension */
1051 snprintfW(SectionName
, LINE_LEN
, L
"%s%s.%lu", InfSectionName
,
1052 pExtensionPlatform
, pPlatformInfo
->MajorVersion
);
1053 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1054 if (lLineCount
!= -1) goto sectionfound
;
1056 /* Test with platform.architecture extension */
1057 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s", InfSectionName
,
1058 pExtensionPlatform
, pExtensionArchitecture
);
1059 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1060 if (lLineCount
!= -1) goto sectionfound
;
1062 /* Test with platform extension */
1063 snprintfW(SectionName
, LINE_LEN
, L
"%s%s", InfSectionName
,
1064 pExtensionPlatform
);
1065 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1066 if (lLineCount
!= -1) goto sectionfound
;
1068 /* Test without extension */
1069 snprintfW(SectionName
, LINE_LEN
, L
"%s", InfSectionName
);
1070 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1071 if (lLineCount
!= -1) goto sectionfound
;
1073 /* No appropriate section found */
1074 SetLastError(ERROR_INVALID_PARAMETER
);
1078 dwFullLength
= lstrlenW(SectionName
);
1079 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
1081 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
1083 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1087 lstrcpyW(InfSectionWithExt
, SectionName
);
1088 if (Extension
!= NULL
)
1090 DWORD dwLength
= lstrlenW(SectionName
);
1091 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1095 if (RequiredSize
!= NULL
)
1096 *RequiredSize
= dwFullLength
+ 1;
1102 TRACE("Returning %d\n", ret
);
1107 /***********************************************************************
1108 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1110 BOOL WINAPI
SetupDiGetClassDescriptionA(
1111 const GUID
* ClassGuid
,
1112 PSTR ClassDescription
,
1113 DWORD ClassDescriptionSize
,
1114 PDWORD RequiredSize
)
1116 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1117 ClassDescriptionSize
,
1118 RequiredSize
, NULL
, NULL
);
1121 /***********************************************************************
1122 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1124 BOOL WINAPI
SetupDiGetClassDescriptionW(
1125 const GUID
* ClassGuid
,
1126 PWSTR ClassDescription
,
1127 DWORD ClassDescriptionSize
,
1128 PDWORD RequiredSize
)
1130 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1131 ClassDescriptionSize
,
1132 RequiredSize
, NULL
, NULL
);
1135 /***********************************************************************
1136 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1138 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1139 const GUID
* ClassGuid
,
1140 PSTR ClassDescription
,
1141 DWORD ClassDescriptionSize
,
1142 PDWORD RequiredSize
,
1146 PWCHAR ClassDescriptionW
;
1147 LPWSTR MachineNameW
= NULL
;
1151 if (ClassDescriptionSize
> 0)
1153 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1154 if (!ClassDescriptionW
)
1156 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1162 ClassDescriptionW
= NULL
;
1166 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1169 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1175 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1176 NULL
, MachineNameW
, Reserved
);
1179 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1180 ClassDescriptionSize
, NULL
, NULL
);
1182 if (!ClassDescriptionSize
&& RequiredSize
)
1183 *RequiredSize
= len
;
1187 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1188 MyFree(MachineNameW
);
1192 /***********************************************************************
1193 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1195 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1196 const GUID
* ClassGuid
,
1197 PWSTR ClassDescription
,
1198 DWORD ClassDescriptionSize
,
1199 PDWORD RequiredSize
,
1206 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1207 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1209 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1214 if (hKey
== INVALID_HANDLE_VALUE
)
1216 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1220 if (RequiredSize
!= NULL
)
1223 if (RegQueryValueExW(hKey
,
1234 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1237 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1238 if (RegQueryValueExW(hKey
,
1242 (LPBYTE
)ClassDescription
,
1254 /***********************************************************************
1255 * SetupDiGetClassDevsA (SETUPAPI.@)
1257 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1263 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1264 flags
, NULL
, NULL
, NULL
);
1267 /***********************************************************************
1268 * SetupDiGetClassDevsW (SETUPAPI.@)
1270 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1276 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1277 flags
, NULL
, NULL
, NULL
);
1280 /***********************************************************************
1281 * SetupDiGetClassDevsExA (SETUPAPI.@)
1283 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1293 LPWSTR enumstrW
= NULL
;
1294 LPWSTR machineW
= NULL
;
1298 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1299 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1302 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1305 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1309 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1310 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1313 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1316 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1318 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1321 HeapFree(GetProcessHeap(), 0, enumstrW
);
1322 HeapFree(GetProcessHeap(), 0, machineW
);
1327 CreateDeviceInfoElement(
1328 IN
struct DeviceInfoSet
*list
,
1329 IN LPCWSTR InstancePath
,
1330 IN LPCGUID pClassGuid
,
1331 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1335 struct DeviceInfoElement
*deviceInfo
;
1337 *pDeviceInfo
= NULL
;
1339 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1340 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1343 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1346 memset(deviceInfo
, 0, size
);
1348 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1349 if (cr
!= CR_SUCCESS
)
1351 SetLastError(GetErrorCodeFromCrCode(cr
));
1355 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1356 wcscpy(deviceInfo
->Data
, InstancePath
);
1357 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1358 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1359 deviceInfo
->DeviceDescription
= NULL
;
1360 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1361 deviceInfo
->CreationFlags
= 0;
1362 InitializeListHead(&deviceInfo
->DriverListHead
);
1363 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1365 *pDeviceInfo
= deviceInfo
;
1370 CreateDeviceInterface(
1371 IN
struct DeviceInfoElement
* deviceInfo
,
1372 IN LPCWSTR SymbolicLink
,
1373 IN LPCGUID pInterfaceGuid
,
1374 OUT
struct DeviceInterface
**pDeviceInterface
)
1376 struct DeviceInterface
*deviceInterface
;
1378 *pDeviceInterface
= NULL
;
1380 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1381 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1382 if (!deviceInterface
)
1384 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1387 deviceInterface
->DeviceInfo
= deviceInfo
;
1388 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1389 deviceInterface
->Flags
= 0; /* FIXME */
1390 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1392 *pDeviceInterface
= deviceInterface
;
1396 static LONG
SETUP_CreateDevListFromEnumerator(
1397 struct DeviceInfoSet
*list
,
1398 LPCGUID pClassGuid OPTIONAL
,
1400 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1402 HKEY hDeviceIdKey
, hInstanceIdKey
;
1403 WCHAR KeyBuffer
[MAX_PATH
];
1404 WCHAR InstancePath
[MAX_PATH
];
1405 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1406 struct DeviceInfoElement
*deviceInfo
;
1408 DWORD dwLength
, dwRegType
;
1411 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1414 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1415 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1416 if (rc
== ERROR_NO_MORE_ITEMS
)
1418 if (rc
!= ERROR_SUCCESS
)
1422 /* Open device id sub key */
1423 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1424 if (rc
!= ERROR_SUCCESS
)
1426 wcscpy(InstancePath
, Enumerator
);
1427 wcscat(InstancePath
, L
"\\");
1428 wcscat(InstancePath
, KeyBuffer
);
1429 wcscat(InstancePath
, L
"\\");
1430 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1432 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1438 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1439 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1440 if (rc
== ERROR_NO_MORE_ITEMS
)
1442 if (rc
!= ERROR_SUCCESS
)
1444 RegCloseKey(hDeviceIdKey
);
1449 /* Open instance id sub key */
1450 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1451 if (rc
!= ERROR_SUCCESS
)
1453 RegCloseKey(hDeviceIdKey
);
1456 *pEndOfInstancePath
= '\0';
1457 wcscat(InstancePath
, KeyBuffer
);
1459 /* Read ClassGUID value */
1460 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1461 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1462 RegCloseKey(hInstanceIdKey
);
1463 if (rc
== ERROR_FILE_NOT_FOUND
)
1466 /* Skip this bad entry as we can't verify it */
1468 /* Set a default GUID for this device */
1469 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1471 else if (rc
!= ERROR_SUCCESS
)
1473 RegCloseKey(hDeviceIdKey
);
1476 else if (dwRegType
!= REG_SZ
)
1478 RegCloseKey(hDeviceIdKey
);
1479 return ERROR_GEN_FAILURE
;
1483 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1484 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1485 /* Bad GUID, skip the entry */
1489 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1491 /* Skip this entry as it is not the right device class */
1495 /* Add the entry to the list */
1496 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1498 RegCloseKey(hDeviceIdKey
);
1499 return GetLastError();
1501 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1502 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1504 RegCloseKey(hDeviceIdKey
);
1507 return ERROR_SUCCESS
;
1510 static LONG
SETUP_CreateDevList(
1511 struct DeviceInfoSet
*list
,
1512 PCWSTR MachineName OPTIONAL
,
1513 LPGUID
class OPTIONAL
,
1514 PCWSTR Enumerator OPTIONAL
)
1516 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1517 WCHAR KeyBuffer
[MAX_PATH
];
1522 if (class && IsEqualIID(class, &GUID_NULL
))
1526 if (MachineName
!= NULL
)
1528 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1529 if (rc
!= ERROR_SUCCESS
)
1533 HKLM
= HKEY_LOCAL_MACHINE
;
1535 rc
= RegOpenKeyExW(HKLM
,
1536 REGSTR_PATH_SYSTEMENUM
,
1538 KEY_ENUMERATE_SUB_KEYS
,
1540 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1541 if (rc
!= ERROR_SUCCESS
)
1544 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1545 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1554 KEY_ENUMERATE_SUB_KEYS
,
1556 RegCloseKey(hEnumKey
);
1557 if (rc
!= ERROR_SUCCESS
)
1559 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1560 RegCloseKey(hEnumeratorKey
);
1565 /* Enumerate enumerators */
1569 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1570 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1571 if (rc
== ERROR_NO_MORE_ITEMS
)
1573 if (rc
!= ERROR_SUCCESS
)
1575 RegCloseKey(hEnumKey
);
1581 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1582 if (rc
!= ERROR_SUCCESS
)
1584 RegCloseKey(hEnumKey
);
1588 /* Call SETUP_CreateDevListFromEnumerator */
1589 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1590 RegCloseKey(hEnumeratorKey
);
1591 if (rc
!= ERROR_SUCCESS
)
1593 RegCloseKey(hEnumKey
);
1597 RegCloseKey(hEnumKey
);
1598 return ERROR_SUCCESS
;
1602 static LONG
SETUP_CreateInterfaceList(
1603 struct DeviceInfoSet
*list
,
1605 LPGUID InterfaceGuid
,
1606 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1608 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1609 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1610 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1611 HKEY hControlKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */
1612 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1613 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1615 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1618 DWORD dwLength
, dwInstancePathLength
;
1622 struct DeviceInfoElement
*deviceInfo
;
1624 /* Open registry key related to this interface */
1625 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1626 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1627 return GetLastError();
1629 /* Enumerate sub keys of hInterfaceKey */
1633 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1634 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1635 if (rc
== ERROR_NO_MORE_ITEMS
)
1637 if (rc
!= ERROR_SUCCESS
)
1639 RegCloseKey(hInterfaceKey
);
1645 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1646 if (rc
!= ERROR_SUCCESS
)
1648 RegCloseKey(hInterfaceKey
);
1652 /* Read DeviceInstance */
1653 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1654 if (rc
!= ERROR_SUCCESS
)
1656 RegCloseKey(hDeviceInstanceKey
);
1657 RegCloseKey(hInterfaceKey
);
1660 if (dwRegType
!= REG_SZ
)
1662 RegCloseKey(hDeviceInstanceKey
);
1663 RegCloseKey(hInterfaceKey
);
1664 return ERROR_GEN_FAILURE
;
1666 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1669 RegCloseKey(hDeviceInstanceKey
);
1670 RegCloseKey(hInterfaceKey
);
1671 return ERROR_NOT_ENOUGH_MEMORY
;
1673 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1674 if (rc
!= ERROR_SUCCESS
)
1676 HeapFree(GetProcessHeap(), 0, InstancePath
);
1677 RegCloseKey(hDeviceInstanceKey
);
1678 RegCloseKey(hInterfaceKey
);
1681 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1682 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1684 if (DeviceInstanceW
)
1686 /* Check if device enumerator is not the right one */
1687 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1689 HeapFree(GetProcessHeap(), 0, InstancePath
);
1690 RegCloseKey(hDeviceInstanceKey
);
1695 /* Find class GUID associated to the device instance */
1698 REGSTR_PATH_SYSTEMENUM
,
1702 if (rc
!= ERROR_SUCCESS
)
1704 HeapFree(GetProcessHeap(), 0, InstancePath
);
1705 RegCloseKey(hDeviceInstanceKey
);
1706 RegCloseKey(hInterfaceKey
);
1715 RegCloseKey(hEnumKey
);
1716 if (rc
!= ERROR_SUCCESS
)
1718 HeapFree(GetProcessHeap(), 0, InstancePath
);
1719 RegCloseKey(hDeviceInstanceKey
);
1720 RegCloseKey(hInterfaceKey
);
1723 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1724 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1726 if (rc
!= ERROR_SUCCESS
)
1728 HeapFree(GetProcessHeap(), 0, InstancePath
);
1729 RegCloseKey(hDeviceInstanceKey
);
1730 RegCloseKey(hInterfaceKey
);
1733 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1734 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1735 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1737 HeapFree(GetProcessHeap(), 0, InstancePath
);
1738 RegCloseKey(hDeviceInstanceKey
);
1739 RegCloseKey(hInterfaceKey
);
1740 return ERROR_GEN_FAILURE
;
1742 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1744 /* If current device doesn't match the list GUID (if any), skip this entry */
1745 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1747 HeapFree(GetProcessHeap(), 0, InstancePath
);
1748 RegCloseKey(hDeviceInstanceKey
);
1752 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1756 LPWSTR pSymbolicLink
;
1757 struct DeviceInterface
*interfaceInfo
;
1759 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1760 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1761 if (rc
== ERROR_NO_MORE_ITEMS
)
1763 if (rc
!= ERROR_SUCCESS
)
1765 HeapFree(GetProcessHeap(), 0, InstancePath
);
1766 RegCloseKey(hDeviceInstanceKey
);
1767 RegCloseKey(hInterfaceKey
);
1771 if (KeyBuffer
[0] != '#')
1772 /* This entry doesn't represent an interesting entry */
1776 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1777 if (rc
!= ERROR_SUCCESS
)
1779 RegCloseKey(hDeviceInstanceKey
);
1780 RegCloseKey(hInterfaceKey
);
1784 /* Read SymbolicLink value */
1785 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1786 if (rc
!= ERROR_SUCCESS
)
1788 RegCloseKey(hReferenceKey
);
1789 RegCloseKey(hDeviceInstanceKey
);
1790 RegCloseKey(hInterfaceKey
);
1793 if (dwRegType
!= REG_SZ
)
1795 RegCloseKey(hReferenceKey
);
1796 RegCloseKey(hDeviceInstanceKey
);
1797 RegCloseKey(hInterfaceKey
);
1798 return ERROR_GEN_FAILURE
;
1801 /* We have found a device */
1802 /* Step 1. Create a device info element */
1803 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1805 RegCloseKey(hReferenceKey
);
1806 RegCloseKey(hDeviceInstanceKey
);
1807 RegCloseKey(hInterfaceKey
);
1808 return GetLastError();
1810 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1811 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1813 /* Step 2. Create an interface list for this element */
1814 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1817 RegCloseKey(hReferenceKey
);
1818 RegCloseKey(hDeviceInstanceKey
);
1819 RegCloseKey(hInterfaceKey
);
1820 return ERROR_NOT_ENOUGH_MEMORY
;
1822 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1823 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1824 RegCloseKey(hReferenceKey
);
1825 if (rc
!= ERROR_SUCCESS
)
1827 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1828 RegCloseKey(hDeviceInstanceKey
);
1829 RegCloseKey(hInterfaceKey
);
1832 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1834 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1835 RegCloseKey(hDeviceInstanceKey
);
1836 RegCloseKey(hInterfaceKey
);
1837 return GetLastError();
1840 /* Step 3. Update flags */
1841 if (KeyBuffer
[1] == '\0')
1842 interfaceInfo
->Flags
|= SPINT_DEFAULT
;
1843 rc
= RegOpenKeyExW(hReferenceKey
, Control
, 0, KEY_QUERY_VALUE
, &hControlKey
);
1845 interfaceInfo
->Flags
|= SPINT_REMOVED
;
1848 dwLength
= sizeof(DWORD
);
1849 if (RegQueryValueExW(hControlKey
, Linked
, NULL
, &dwRegType
, (LPBYTE
)&LinkedValue
, &dwLength
)
1850 && dwRegType
== REG_DWORD
&& LinkedValue
)
1851 interfaceInfo
->Flags
|= SPINT_ACTIVE
;
1852 RegCloseKey(hControlKey
);
1855 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1856 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1857 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1859 RegCloseKey(hDeviceInstanceKey
);
1861 RegCloseKey(hInterfaceKey
);
1862 return ERROR_SUCCESS
;
1865 /***********************************************************************
1866 * SetupDiGetClassDevsExW (SETUPAPI.@)
1868 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1877 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1878 struct DeviceInfoSet
*list
;
1882 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1883 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1885 /* Create the deviceset if not set */
1888 list
= (struct DeviceInfoSet
*)deviceset
;
1889 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1891 SetLastError(ERROR_INVALID_HANDLE
);
1892 return INVALID_HANDLE_VALUE
;
1894 hDeviceInfo
= deviceset
;
1898 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1899 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1900 NULL
, machine
, NULL
);
1901 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1902 return INVALID_HANDLE_VALUE
;
1903 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1906 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1909 pClassGuid
= &list
->ClassGuid
;
1911 if (flags
& DIGCF_PRESENT
)
1912 FIXME(": flag DIGCF_PRESENT ignored\n");
1913 if (flags
& DIGCF_PROFILE
)
1914 FIXME(": flag DIGCF_PROFILE ignored\n");
1916 if (flags
& DIGCF_ALLCLASSES
)
1918 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1919 if (rc
!= ERROR_SUCCESS
)
1923 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1924 return INVALID_HANDLE_VALUE
;
1928 else if (flags
& DIGCF_DEVICEINTERFACE
)
1932 SetLastError(ERROR_INVALID_PARAMETER
);
1934 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1935 return INVALID_HANDLE_VALUE
;
1938 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1939 if (rc
!= ERROR_SUCCESS
)
1943 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1944 return INVALID_HANDLE_VALUE
;
1950 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1951 if (rc
!= ERROR_SUCCESS
)
1955 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1956 return INVALID_HANDLE_VALUE
;
1962 /***********************************************************************
1963 * SetupDiGetClassImageIndex (SETUPAPI.@)
1966 static BOOL
GetIconIndex(
1968 OUT PINT ImageIndex
)
1970 LPWSTR Buffer
= NULL
;
1971 DWORD dwRegType
, dwLength
;
1975 /* Read icon registry key */
1976 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
1977 if (rc
!= ERROR_SUCCESS
)
1981 } else if (dwRegType
!= REG_SZ
)
1983 SetLastError(ERROR_INVALID_INDEX
);
1986 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
1989 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1992 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
1993 if (rc
!= ERROR_SUCCESS
)
1998 /* make sure the returned buffer is NULL-terminated */
1999 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2001 /* Transform icon value to a INT */
2002 *ImageIndex
= atoiW(Buffer
);
2010 BOOL WINAPI
SetupDiGetClassImageIndex(
2011 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2012 IN CONST GUID
*ClassGuid
,
2013 OUT PINT ImageIndex
)
2015 struct ClassImageList
*list
;
2018 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2020 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2021 SetLastError(ERROR_INVALID_PARAMETER
);
2022 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2023 SetLastError(ERROR_INVALID_USER_BUFFER
);
2024 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2025 SetLastError(ERROR_INVALID_USER_BUFFER
);
2026 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2027 SetLastError(ERROR_INVALID_USER_BUFFER
);
2028 else if (!ImageIndex
)
2029 SetLastError(ERROR_INVALID_PARAMETER
);
2032 HKEY hKey
= INVALID_HANDLE_VALUE
;
2035 /* Read Icon registry entry into Buffer */
2036 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2037 if (hKey
== INVALID_HANDLE_VALUE
)
2039 if (!GetIconIndex(hKey
, &iconIndex
))
2044 SetLastError(ERROR_INVALID_INDEX
);
2048 *ImageIndex
= -iconIndex
;
2052 if (hKey
!= INVALID_HANDLE_VALUE
)
2056 TRACE("Returning %d\n", ret
);
2060 /***********************************************************************
2061 * SetupDiGetClassImageList(SETUPAPI.@)
2063 BOOL WINAPI
SetupDiGetClassImageList(
2064 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2066 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2069 /***********************************************************************
2070 * SetupDiGetClassImageListExA(SETUPAPI.@)
2072 BOOL WINAPI
SetupDiGetClassImageListExA(
2073 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2074 IN PCSTR MachineName OPTIONAL
,
2077 PWSTR MachineNameW
= NULL
;
2082 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2083 if (MachineNameW
== NULL
)
2087 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2090 MyFree(MachineNameW
);
2095 /***********************************************************************
2096 * SetupDiGetClassImageListExW(SETUPAPI.@)
2098 BOOL WINAPI
SetupDiGetClassImageListExW(
2099 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2100 IN PCWSTR MachineName OPTIONAL
,
2105 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2107 if (!ClassImageListData
)
2108 SetLastError(ERROR_INVALID_PARAMETER
);
2109 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2110 SetLastError(ERROR_INVALID_USER_BUFFER
);
2112 SetLastError(ERROR_INVALID_PARAMETER
);
2115 struct ClassImageList
*list
= NULL
;
2118 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2120 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
2121 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2124 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2127 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2130 list
->szData
[0] = list
->szData
[1] = '\\';
2131 strcpyW(list
->szData
+ 2, MachineName
);
2132 list
->MachineName
= list
->szData
;
2136 list
->MachineName
= NULL
;
2139 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2147 TRACE("Returning %d\n", ret
);
2151 /***********************************************************************
2152 * SetupDiLoadClassIcon(SETUPAPI.@)
2154 BOOL WINAPI
SetupDiLoadClassIcon(
2155 IN CONST GUID
*ClassGuid
,
2156 OUT HICON
*LargeIcon OPTIONAL
,
2157 OUT PINT MiniIconIndex OPTIONAL
)
2162 SetLastError(ERROR_INVALID_PARAMETER
);
2165 LPWSTR Buffer
= NULL
;
2168 HKEY hKey
= INVALID_HANDLE_VALUE
;
2170 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2171 if (hKey
== INVALID_HANDLE_VALUE
)
2174 if (!GetIconIndex(hKey
, &iconIndex
))
2179 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2182 DWORD dwRegType
, dwLength
;
2183 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2184 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2186 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2189 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2192 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2193 if (rc
!= ERROR_SUCCESS
)
2198 /* make sure the returned buffer is NULL-terminated */
2199 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2202 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2203 && dwRegType
== REG_SZ
)
2205 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2208 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2211 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2212 if (rc
!= ERROR_SUCCESS
)
2217 /* make sure the returned buffer is NULL-terminated */
2218 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2222 /* Unable to find where to load the icon */
2223 SetLastError(ERROR_FILE_NOT_FOUND
);
2226 Comma
= strchrW(Buffer
, ',');
2229 SetLastError(ERROR_GEN_FAILURE
);
2237 /* Look up icon in setupapi.dll */
2238 DllName
= L
"setupapi.dll";
2239 iconIndex
= -iconIndex
;
2242 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2245 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2247 SetLastError(ERROR_INVALID_INDEX
);
2252 *MiniIconIndex
= iconIndex
;
2256 if (hKey
!= INVALID_HANDLE_VALUE
)
2261 TRACE("Returning %d\n", ret
);
2265 /***********************************************************************
2266 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2268 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2269 HDEVINFO DeviceInfoSet
,
2270 PSP_DEVINFO_DATA DeviceInfoData
,
2271 CONST GUID
* InterfaceClassGuid
,
2273 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2277 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2278 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2280 if (!DeviceInterfaceData
)
2281 SetLastError(ERROR_INVALID_PARAMETER
);
2282 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2283 SetLastError(ERROR_INVALID_USER_BUFFER
);
2284 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2286 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2288 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2290 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2292 while (ItemList
!= &list
->ListHead
&& !Found
)
2294 PLIST_ENTRY InterfaceListEntry
;
2295 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2296 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2298 /* We are not searching for this element */
2299 ItemList
= ItemList
->Flink
;
2302 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2303 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2305 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2306 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2308 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2311 if (MemberIndex
-- == 0)
2313 /* return this item */
2314 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2315 &DevItf
->InterfaceClassGuid
,
2317 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2318 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2321 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2323 ItemList
= ItemList
->Flink
;
2326 SetLastError(ERROR_NO_MORE_ITEMS
);
2331 SetLastError(ERROR_INVALID_HANDLE
);
2334 SetLastError(ERROR_INVALID_HANDLE
);
2338 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2340 InterlockedIncrement(&infFile
->References
);
2343 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2345 if (InterlockedDecrement(&infFile
->References
) == 0)
2347 SetupCloseInfFile(infFile
->hInf
);
2348 HeapFree(GetProcessHeap(), 0, infFile
);
2352 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2354 DereferenceInfFile(driverInfo
->InfFileDetails
);
2355 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2356 HeapFree(GetProcessHeap(), 0, driverInfo
);
2360 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2362 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2366 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2368 PLIST_ENTRY ListEntry
;
2369 struct DriverInfoElement
*driverInfo
;
2371 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2373 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2374 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2375 if (!DestroyDriverInfoElement(driverInfo
))
2378 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2380 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2381 HeapFree(GetProcessHeap(), 0, ListEntry
);
2383 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2384 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2388 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2390 PLIST_ENTRY ListEntry
;
2391 struct DeviceInfoElement
*deviceInfo
;
2393 while (!IsListEmpty(&list
->ListHead
))
2395 ListEntry
= RemoveHeadList(&list
->ListHead
);
2396 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2397 if (!DestroyDeviceInfoElement(deviceInfo
))
2400 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2401 RegCloseKey(list
->HKLM
);
2402 CM_Disconnect_Machine(list
->hMachine
);
2403 DestroyClassInstallParams(&list
->ClassInstallParams
);
2404 HeapFree(GetProcessHeap(), 0, list
);
2408 /***********************************************************************
2409 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2411 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2415 TRACE("%p\n", devinfo
);
2416 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2418 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2420 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2421 ret
= DestroyDeviceInfoSet(list
);
2423 SetLastError(ERROR_INVALID_HANDLE
);
2426 SetLastError(ERROR_INVALID_HANDLE
);
2428 TRACE("Returning %d\n", ret
);
2432 /***********************************************************************
2433 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2435 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2436 HDEVINFO DeviceInfoSet
,
2437 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2438 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2439 DWORD DeviceInterfaceDetailDataSize
,
2440 PDWORD RequiredSize
,
2441 PSP_DEVINFO_DATA DeviceInfoData
)
2443 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2444 DWORD sizeW
= 0, sizeA
;
2447 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2448 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2449 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2451 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2452 SetLastError(ERROR_INVALID_USER_BUFFER
);
2453 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2454 SetLastError(ERROR_INVALID_PARAMETER
);
2455 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2456 SetLastError(ERROR_INVALID_PARAMETER
);
2459 if (DeviceInterfaceDetailData
!= NULL
)
2461 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2462 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2463 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2464 if (!DeviceInterfaceDetailDataW
)
2466 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2469 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2471 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2472 ret
= SetupDiGetDeviceInterfaceDetailW(
2474 DeviceInterfaceData
,
2475 DeviceInterfaceDetailDataW
,
2479 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2480 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2482 *RequiredSize
= sizeA
;
2483 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2485 if (!WideCharToMultiByte(
2487 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2488 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2495 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2498 TRACE("Returning %d\n", ret
);
2502 /***********************************************************************
2503 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2505 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2506 HDEVINFO DeviceInfoSet
,
2507 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2508 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2509 DWORD DeviceInterfaceDetailDataSize
,
2510 PDWORD RequiredSize
,
2511 PSP_DEVINFO_DATA DeviceInfoData
)
2515 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2516 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2517 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2519 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2520 SetLastError(ERROR_INVALID_PARAMETER
);
2521 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2522 SetLastError(ERROR_INVALID_HANDLE
);
2523 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2524 SetLastError(ERROR_INVALID_HANDLE
);
2525 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2526 SetLastError(ERROR_INVALID_USER_BUFFER
);
2527 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2528 SetLastError(ERROR_INVALID_USER_BUFFER
);
2529 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2530 SetLastError(ERROR_INVALID_USER_BUFFER
);
2531 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2532 SetLastError(ERROR_INVALID_PARAMETER
);
2533 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2534 SetLastError(ERROR_INVALID_PARAMETER
);
2537 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2538 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2539 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2540 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2542 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2544 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2546 *RequiredSize
= sizeRequired
;
2550 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2551 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2554 memcpy(&DeviceInfoData
->ClassGuid
,
2555 &deviceInterface
->DeviceInfo
->ClassGuid
,
2557 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2558 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2564 TRACE("Returning %d\n", ret
);
2568 /***********************************************************************
2569 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2571 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2573 PSP_DEVINFO_DATA DeviceInfoData
,
2575 PDWORD PropertyRegDataType
,
2576 PBYTE PropertyBuffer
,
2577 DWORD PropertyBufferSize
,
2578 PDWORD RequiredSize
)
2581 BOOL bIsStringProperty
;
2583 DWORD RequiredSizeA
, RequiredSizeW
;
2584 DWORD PropertyBufferSizeW
;
2585 PBYTE PropertyBufferW
;
2587 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2588 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2591 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2592 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2594 bResult
= SetupDiGetDeviceRegistryPropertyW(
2600 PropertyBufferSizeW
,
2603 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2605 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2607 if (bIsStringProperty
)
2608 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2610 RequiredSizeA
= RequiredSizeW
;
2612 *RequiredSize
= RequiredSizeA
;
2613 if (PropertyRegDataType
)
2614 *PropertyRegDataType
= RegType
;
2619 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2623 if (RequiredSizeA
<= PropertyBufferSize
)
2625 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2627 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2629 /* Last error is already set by WideCharToMultiByte */
2634 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2638 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2642 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2646 /***********************************************************************
2647 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2649 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2650 HDEVINFO DeviceInfoSet
,
2651 PSP_DEVINFO_DATA DeviceInfoData
,
2653 PDWORD PropertyRegDataType
,
2654 PBYTE PropertyBuffer
,
2655 DWORD PropertyBufferSize
,
2656 PDWORD RequiredSize
)
2658 HKEY hEnumKey
, hKey
;
2662 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2663 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2666 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2667 SetLastError(ERROR_INVALID_HANDLE
);
2668 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2669 SetLastError(ERROR_INVALID_HANDLE
);
2670 else if (!DeviceInfoData
)
2671 SetLastError(ERROR_INVALID_PARAMETER
);
2672 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2673 SetLastError(ERROR_INVALID_USER_BUFFER
);
2674 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2675 SetLastError(ERROR_INVALID_PARAMETER
);
2678 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2679 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2683 case SPDRP_CAPABILITIES
:
2685 case SPDRP_CLASSGUID
:
2686 case SPDRP_COMPATIBLEIDS
:
2687 case SPDRP_CONFIGFLAGS
:
2688 case SPDRP_DEVICEDESC
:
2690 case SPDRP_FRIENDLYNAME
:
2691 case SPDRP_HARDWAREID
:
2692 case SPDRP_LOCATION_INFORMATION
:
2693 case SPDRP_LOWERFILTERS
:
2695 case SPDRP_SECURITY
:
2697 case SPDRP_UI_NUMBER
:
2698 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2699 case SPDRP_UPPERFILTERS
:
2701 LPCWSTR RegistryPropertyName
;
2706 case SPDRP_CAPABILITIES
:
2707 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2709 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2710 case SPDRP_CLASSGUID
:
2711 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2712 case SPDRP_COMPATIBLEIDS
:
2713 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2714 case SPDRP_CONFIGFLAGS
:
2715 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2716 case SPDRP_DEVICEDESC
:
2717 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2719 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2720 case SPDRP_FRIENDLYNAME
:
2721 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2722 case SPDRP_HARDWAREID
:
2723 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2724 case SPDRP_LOCATION_INFORMATION
:
2725 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2726 case SPDRP_LOWERFILTERS
:
2727 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2729 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2730 case SPDRP_SECURITY
:
2731 RegistryPropertyName
= L
"Security"; break;
2733 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2734 case SPDRP_UI_NUMBER
:
2735 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2736 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2737 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2738 case SPDRP_UPPERFILTERS
:
2739 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2741 /* Should not happen */
2742 RegistryPropertyName
= NULL
; break;
2745 /* Open registry key name */
2748 REGSTR_PATH_SYSTEMENUM
,
2752 if (rc
!= ERROR_SUCCESS
)
2763 RegCloseKey(hEnumKey
);
2764 if (rc
!= ERROR_SUCCESS
)
2769 /* Read registry entry */
2770 BufferSize
= PropertyBufferSize
;
2771 rc
= RegQueryValueExW(
2773 RegistryPropertyName
,
2774 NULL
, /* Reserved */
2775 PropertyRegDataType
,
2779 *RequiredSize
= BufferSize
;
2782 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2785 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2787 case ERROR_MORE_DATA
:
2788 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2797 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2799 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2801 if (PropertyRegDataType
)
2802 *PropertyRegDataType
= REG_SZ
;
2804 *RequiredSize
= required
;
2805 if (PropertyBufferSize
>= required
)
2807 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2811 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2815 /*case SPDRP_BUSTYPEGUID:
2816 case SPDRP_LEGACYBUSTYPE:
2817 case SPDRP_BUSNUMBER:
2818 case SPDRP_ENUMERATOR_NAME:
2819 case SPDRP_SECURITY_SDS:
2821 case SPDRP_EXCLUSIVE:
2822 case SPDRP_CHARACTERISTICS:
2824 case SPDRP_DEVICE_POWER_DATA:*/
2825 #if (WINVER >= 0x501)
2826 /*case SPDRP_REMOVAL_POLICY:
2827 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2828 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2829 case SPDRP_INSTALL_STATE:*/
2834 ERR("Property 0x%lx not implemented\n", Property
);
2835 SetLastError(ERROR_NOT_SUPPORTED
);
2840 TRACE("Returning %d\n", ret
);
2844 /***********************************************************************
2845 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2847 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2848 IN HDEVINFO DeviceInfoSet
,
2849 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2851 IN CONST BYTE
*PropertyBuffer
,
2852 IN DWORD PropertyBufferSize
)
2854 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2855 Property
, PropertyBuffer
, PropertyBufferSize
);
2856 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2860 /***********************************************************************
2861 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2863 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2864 IN HDEVINFO DeviceInfoSet
,
2865 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2867 IN
const BYTE
*PropertyBuffer
,
2868 IN DWORD PropertyBufferSize
)
2870 struct DeviceInfoSet
*list
;
2873 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2874 Property
, PropertyBuffer
, PropertyBufferSize
);
2877 SetLastError(ERROR_INVALID_HANDLE
);
2878 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2879 SetLastError(ERROR_INVALID_HANDLE
);
2880 else if (!DeviceInfoData
)
2881 SetLastError(ERROR_INVALID_HANDLE
);
2882 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2883 SetLastError(ERROR_INVALID_USER_BUFFER
);
2888 case SPDRP_COMPATIBLEIDS
:
2889 case SPDRP_CONFIGFLAGS
:
2890 case SPDRP_FRIENDLYNAME
:
2891 case SPDRP_HARDWAREID
:
2892 case SPDRP_LOCATION_INFORMATION
:
2893 case SPDRP_LOWERFILTERS
:
2894 case SPDRP_SECURITY
:
2896 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2897 case SPDRP_UPPERFILTERS
:
2899 LPCWSTR RegistryPropertyName
;
2900 DWORD RegistryDataType
;
2906 case SPDRP_COMPATIBLEIDS
:
2907 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2908 RegistryDataType
= REG_MULTI_SZ
;
2910 case SPDRP_CONFIGFLAGS
:
2911 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2912 RegistryDataType
= REG_DWORD
;
2914 case SPDRP_FRIENDLYNAME
:
2915 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2916 RegistryDataType
= REG_SZ
;
2918 case SPDRP_HARDWAREID
:
2919 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2920 RegistryDataType
= REG_MULTI_SZ
;
2922 case SPDRP_LOCATION_INFORMATION
:
2923 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2924 RegistryDataType
= REG_SZ
;
2926 case SPDRP_LOWERFILTERS
:
2927 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2928 RegistryDataType
= REG_MULTI_SZ
;
2930 case SPDRP_SECURITY
:
2931 RegistryPropertyName
= L
"Security";
2932 RegistryDataType
= REG_BINARY
;
2935 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2936 RegistryDataType
= REG_SZ
;
2938 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2939 RegistryPropertyName
= L
"UINumberDescFormat";
2940 RegistryDataType
= REG_SZ
;
2942 case SPDRP_UPPERFILTERS
:
2943 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
2944 RegistryDataType
= REG_MULTI_SZ
;
2947 /* Should not happen */
2948 RegistryPropertyName
= NULL
;
2949 RegistryDataType
= REG_BINARY
;
2952 /* Open device registry key */
2953 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2954 if (hKey
!= INVALID_HANDLE_VALUE
)
2956 /* Write new data */
2957 rc
= RegSetValueExW(
2959 RegistryPropertyName
,
2963 PropertyBufferSize
);
2964 if (rc
== ERROR_SUCCESS
)
2973 /*case SPDRP_CHARACTERISTICS:
2975 case SPDRP_EXCLUSIVE:*/
2976 #if (WINVER >= 0x501)
2977 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2979 //case SPDRP_SECURITY_SDS:
2983 ERR("Property 0x%lx not implemented\n", Property
);
2984 SetLastError(ERROR_NOT_SUPPORTED
);
2989 TRACE("Returning %d\n", ret
);
2994 /***********************************************************************
2995 * SetupDiInstallClassA (SETUPAPI.@)
2997 BOOL WINAPI
SetupDiInstallClassA(
2998 IN HWND hwndParent OPTIONAL
,
2999 IN PCSTR InfFileName
,
3001 IN HSPFILEQ FileQueue OPTIONAL
)
3003 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3007 /***********************************************************************
3008 * SetupDiInstallClassW (SETUPAPI.@)
3010 BOOL WINAPI
SetupDiInstallClassW(
3011 IN HWND hwndParent OPTIONAL
,
3012 IN PCWSTR InfFileName
,
3014 IN HSPFILEQ FileQueue OPTIONAL
)
3016 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3020 /***********************************************************************
3021 * SetupDiInstallClassExA (SETUPAPI.@)
3023 BOOL WINAPI
SetupDiInstallClassExA(
3024 IN HWND hwndParent OPTIONAL
,
3025 IN PCSTR InfFileName OPTIONAL
,
3027 IN HSPFILEQ FileQueue OPTIONAL
,
3028 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3032 PWSTR InfFileNameW
= NULL
;
3037 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3038 if (InfFileNameW
== NULL
)
3040 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3045 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3046 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3048 MyFree(InfFileNameW
);
3054 static HKEY
CreateClassKey(HINF hInf
)
3056 WCHAR FullBuffer
[MAX_PATH
];
3057 WCHAR Buffer
[MAX_PATH
];
3062 if (!SetupGetLineTextW(NULL
,
3070 return INVALID_HANDLE_VALUE
;
3073 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3074 lstrcatW(FullBuffer
, Buffer
);
3077 if (!SetupGetLineTextW(NULL
,
3085 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3086 return INVALID_HANDLE_VALUE
;
3089 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3093 REG_OPTION_NON_VOLATILE
,
3099 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3100 return INVALID_HANDLE_VALUE
;
3103 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3108 RequiredSize
* sizeof(WCHAR
)))
3110 RegCloseKey(hClassKey
);
3111 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3112 return INVALID_HANDLE_VALUE
;
3119 /***********************************************************************
3120 * SetupDiInstallClassExW (SETUPAPI.@)
3122 BOOL WINAPI
SetupDiInstallClassExW(
3123 IN HWND hwndParent OPTIONAL
,
3124 IN PCWSTR InfFileName OPTIONAL
,
3126 IN HSPFILEQ FileQueue OPTIONAL
,
3127 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3133 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3134 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3136 if (!InfFileName
&& !InterfaceClassGuid
)
3137 SetLastError(ERROR_INVALID_PARAMETER
);
3138 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3140 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3141 SetLastError(ERROR_INVALID_FLAGS
);
3143 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3144 SetLastError(ERROR_INVALID_PARAMETER
);
3145 else if (Reserved1
!= NULL
)
3146 SetLastError(ERROR_INVALID_PARAMETER
);
3147 else if (Reserved2
!= NULL
)
3148 SetLastError(ERROR_INVALID_PARAMETER
);
3151 WCHAR SectionName
[MAX_PATH
];
3152 HINF hInf
= INVALID_HANDLE_VALUE
;
3153 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3154 PVOID callback_context
= NULL
;
3156 if (InterfaceClassGuid
)
3158 /* SetupDiCreateDeviceInterface??? */
3159 FIXME("Installing an interface is not implemented\n");
3160 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3164 if (Flags
& DI_NOVCP
)
3165 FIXME("FileQueue argument ignored\n");
3166 if (Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3167 FIXME("Flags 0x%lx ignored\n", Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3169 /* Open the .inf file */
3170 hInf
= SetupOpenInfFileW(
3175 if (hInf
== INVALID_HANDLE_VALUE
)
3178 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3179 hClassKey
= CreateClassKey(hInf
);
3180 if (hClassKey
== INVALID_HANDLE_VALUE
)
3183 /* Try to append a layout file */
3184 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3188 /* Retrieve the actual section name */
3189 ret
= SetupDiGetActualSectionToInstallW(
3193 MAX_PATH
- wcslen(DotServices
),
3199 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3200 if (!callback_context
)
3203 ret
= SetupInstallFromInfSectionW(
3207 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3209 NULL
, /* SourceRootPath */
3211 SetupDefaultQueueCallbackW
,
3218 /* Install .Services section */
3219 lstrcatW(SectionName
, DotServices
);
3220 ret
= SetupInstallServicesFromInfSectionW(hInf
, SectionName
, 0);
3228 if (hInf
!= INVALID_HANDLE_VALUE
)
3229 SetupCloseInfFile(hInf
);
3230 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3231 RegCloseKey(hClassKey
);
3232 SetupTermDefaultQueueCallback(callback_context
);
3235 TRACE("Returning %d\n", ret
);
3240 /***********************************************************************
3241 * SetupDiOpenClassRegKey (SETUPAPI.@)
3243 HKEY WINAPI
SetupDiOpenClassRegKey(
3244 const GUID
* ClassGuid
,
3247 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3248 DIOCR_INSTALLER
, NULL
, NULL
);
3252 /***********************************************************************
3253 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3255 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3256 const GUID
* ClassGuid OPTIONAL
,
3259 PCSTR MachineName OPTIONAL
,
3262 PWSTR MachineNameW
= NULL
;
3269 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3270 if (MachineNameW
== NULL
)
3271 return INVALID_HANDLE_VALUE
;
3274 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3275 Flags
, MachineNameW
, Reserved
);
3278 MyFree(MachineNameW
);
3284 /***********************************************************************
3285 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3287 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3288 const GUID
* ClassGuid OPTIONAL
,
3291 PCWSTR MachineName OPTIONAL
,
3294 LPWSTR lpGuidString
;
3295 LPWSTR lpFullGuidString
;
3303 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3304 Flags
, debugstr_w(MachineName
), Reserved
);
3306 if (Flags
== DIOCR_INSTALLER
)
3308 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3310 else if (Flags
== DIOCR_INTERFACE
)
3312 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3316 ERR("Invalid Flags parameter!\n");
3317 SetLastError(ERROR_INVALID_FLAGS
);
3318 return INVALID_HANDLE_VALUE
;
3321 if (MachineName
!= NULL
)
3323 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3324 if (rc
!= ERROR_SUCCESS
)
3327 return INVALID_HANDLE_VALUE
;
3331 HKLM
= HKEY_LOCAL_MACHINE
;
3333 rc
= RegOpenKeyExW(HKLM
,
3336 ClassGuid
? 0 : samDesired
,
3338 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3339 if (rc
!= ERROR_SUCCESS
)
3342 return INVALID_HANDLE_VALUE
;
3345 if (ClassGuid
== NULL
)
3348 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3350 SetLastError(ERROR_GEN_FAILURE
);
3351 RegCloseKey(hClassesKey
);
3352 return INVALID_HANDLE_VALUE
;
3355 dwLength
= lstrlenW(lpGuidString
);
3356 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3357 if (!lpFullGuidString
)
3359 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3360 RpcStringFreeW(&lpGuidString
);
3361 return INVALID_HANDLE_VALUE
;
3363 lpFullGuidString
[0] = '{';
3364 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3365 lpFullGuidString
[dwLength
+ 1] = '}';
3366 lpFullGuidString
[dwLength
+ 2] = '\0';
3367 RpcStringFreeW(&lpGuidString
);
3369 rc
= RegOpenKeyExW(hClassesKey
,
3374 if (rc
!= ERROR_SUCCESS
)
3377 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3378 RegCloseKey(hClassesKey
);
3379 return INVALID_HANDLE_VALUE
;
3382 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3383 RegCloseKey(hClassesKey
);
3388 /***********************************************************************
3389 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3391 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3392 HDEVINFO DeviceInfoSet
,
3395 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3397 FIXME("%p %s %08lx %p\n",
3398 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3402 /***********************************************************************
3403 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3405 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3406 HDEVINFO DeviceInfoSet
,
3409 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3411 LPWSTR DevicePathW
= NULL
;
3414 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3416 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3417 if (DevicePathW
== NULL
)
3420 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3421 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3423 MyFree(DevicePathW
);
3428 /***********************************************************************
3429 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3431 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3432 HDEVINFO DeviceInfoSet
,
3433 PSP_DEVINFO_DATA DeviceInfoData
,
3434 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3435 DWORD ClassInstallParamsSize
)
3437 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3438 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3442 /***********************************************************************
3443 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3445 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3446 IN HDEVINFO DeviceInfoSet
,
3447 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3448 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3449 IN DWORD ClassInstallParamsSize
)
3451 struct DeviceInfoSet
*list
;
3454 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3455 ClassInstallParams
, ClassInstallParamsSize
);
3458 SetLastError(ERROR_INVALID_PARAMETER
);
3459 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3460 SetLastError(ERROR_INVALID_HANDLE
);
3461 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3462 SetLastError(ERROR_INVALID_HANDLE
);
3463 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3464 SetLastError(ERROR_INVALID_USER_BUFFER
);
3465 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3466 SetLastError(ERROR_INVALID_USER_BUFFER
);
3467 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3468 SetLastError(ERROR_INVALID_PARAMETER
);
3469 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3470 SetLastError(ERROR_INVALID_PARAMETER
);
3473 SP_DEVINSTALL_PARAMS_W InstallParams
;
3476 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3477 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3481 if (ClassInstallParams
)
3483 /* Check parameters in ClassInstallParams */
3484 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3485 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3487 SetLastError(ERROR_INVALID_USER_BUFFER
);
3490 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3492 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3493 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3496 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3499 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3503 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3506 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3510 TRACE("Returning %d\n", ret
);
3514 static BOOL
PropertyChangeHandler(
3515 IN HDEVINFO DeviceInfoSet
,
3516 IN PSP_DEVINFO_DATA DeviceInfoData
,
3517 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3518 IN DWORD ClassInstallParamsSize
)
3520 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3523 if (!DeviceInfoData
)
3524 SetLastError(ERROR_INVALID_PARAMETER
);
3525 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3526 SetLastError(ERROR_INVALID_PARAMETER
);
3527 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3528 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3529 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3530 SetLastError(ERROR_INVALID_FLAGS
);
3531 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3532 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3533 SetLastError(ERROR_INVALID_FLAGS
);
3534 else if (PropChangeParams
3535 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3536 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3537 SetLastError(ERROR_INVALID_USER_BUFFER
);
3540 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3541 if (!DeviceInfoData
)
3543 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3544 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3548 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3549 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3551 if (*CurrentPropChangeParams
)
3553 MyFree(*CurrentPropChangeParams
);
3554 *CurrentPropChangeParams
= NULL
;
3556 if (PropChangeParams
)
3558 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3559 if (!*CurrentPropChangeParams
)
3561 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3564 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3575 IN PWSTR InstallerName
,
3576 OUT HMODULE
* ModulePointer
,
3577 OUT PVOID
* FunctionPointer
)
3579 HMODULE hModule
= NULL
;
3580 LPSTR FunctionNameA
= NULL
;
3584 *ModulePointer
= NULL
;
3585 *FunctionPointer
= NULL
;
3587 Comma
= strchrW(InstallerName
, ',');
3590 rc
= ERROR_INVALID_PARAMETER
;
3596 hModule
= LoadLibraryW(InstallerName
);
3600 rc
= GetLastError();
3604 /* Skip comma spaces */
3605 while (*Comma
== ',' || isspaceW(*Comma
))
3608 /* W->A conversion for function name */
3609 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3612 rc
= GetLastError();
3616 /* Search function */
3617 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3618 if (!*FunctionPointer
)
3620 rc
= GetLastError();
3624 *ModulePointer
= hModule
;
3628 if (rc
!= ERROR_SUCCESS
&& hModule
)
3629 FreeLibrary(hModule
);
3630 MyFree(FunctionNameA
);
3635 FreeFunctionPointer(
3636 IN HMODULE ModulePointer
,
3637 IN PVOID FunctionPointer
)
3639 if (ModulePointer
== NULL
)
3640 return ERROR_SUCCESS
;
3641 if (FreeLibrary(ModulePointer
))
3642 return ERROR_SUCCESS
;
3644 return GetLastError();
3648 IntSetupDiRegisterDeviceInfo(
3649 IN HDEVINFO DeviceInfoSet
,
3650 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
3652 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
3655 /***********************************************************************
3656 * SetupDiCallClassInstaller (SETUPAPI.@)
3658 BOOL WINAPI
SetupDiCallClassInstaller(
3659 IN DI_FUNCTION InstallFunction
,
3660 IN HDEVINFO DeviceInfoSet
,
3661 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3665 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3668 SetLastError(ERROR_INVALID_PARAMETER
);
3669 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3670 SetLastError(ERROR_INVALID_HANDLE
);
3671 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3672 SetLastError(ERROR_INVALID_HANDLE
);
3673 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3674 SetLastError(ERROR_INVALID_HANDLE
);
3675 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3676 SetLastError(ERROR_INVALID_USER_BUFFER
);
3679 SP_DEVINSTALL_PARAMS_W InstallParams
;
3680 #define CLASS_COINSTALLER 0x1
3681 #define DEVICE_COINSTALLER 0x2
3682 #define CLASS_INSTALLER 0x4
3683 UCHAR CanHandle
= 0;
3684 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3686 switch (InstallFunction
)
3688 case DIF_ADDPROPERTYPAGE_ADVANCED
:
3689 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3691 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
3692 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3694 case DIF_ALLOW_INSTALL
:
3695 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3698 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3700 case DIF_DESTROYPRIVATEDATA
:
3701 CanHandle
= CLASS_INSTALLER
;
3703 case DIF_INSTALLDEVICE
:
3704 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3705 DefaultHandler
= SetupDiInstallDevice
;
3707 case DIF_INSTALLDEVICEFILES
:
3708 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3709 DefaultHandler
= SetupDiInstallDriverFiles
;
3711 case DIF_INSTALLINTERFACES
:
3712 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3713 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3715 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3716 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3718 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3719 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3721 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3722 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3724 case DIF_NEWDEVICEWIZARD_PRESELECT
:
3725 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3727 case DIF_NEWDEVICEWIZARD_SELECT
:
3728 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3730 case DIF_POWERMESSAGEWAKE
:
3731 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3733 case DIF_PROPERTYCHANGE
:
3734 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3735 DefaultHandler
= SetupDiChangeState
;
3737 case DIF_REGISTER_COINSTALLERS
:
3738 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3739 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3741 case DIF_REGISTERDEVICE
:
3742 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3743 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
3746 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3747 DefaultHandler
= SetupDiRemoveDevice
;
3749 case DIF_SELECTBESTCOMPATDRV
:
3750 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3751 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3753 case DIF_SELECTDEVICE
:
3754 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3755 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3757 case DIF_TROUBLESHOOTER
:
3758 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3761 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3762 DefaultHandler
= SetupDiUnremoveDevice
;
3765 ERR("Install function %u not supported\n", InstallFunction
);
3766 SetLastError(ERROR_NOT_SUPPORTED
);
3769 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3770 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3771 /* Don't process this call, as a parameter is invalid */
3776 LIST_ENTRY ClassCoInstallersListHead
;
3777 LIST_ENTRY DeviceCoInstallersListHead
;
3778 HMODULE ClassInstallerLibrary
= NULL
;
3779 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3780 COINSTALLER_CONTEXT_DATA Context
;
3781 PLIST_ENTRY ListEntry
;
3783 DWORD dwRegType
, dwLength
;
3784 DWORD rc
= NO_ERROR
;
3786 InitializeListHead(&ClassCoInstallersListHead
);
3787 InitializeListHead(&DeviceCoInstallersListHead
);
3789 if (CanHandle
& DEVICE_COINSTALLER
)
3791 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3792 if (hKey
!= INVALID_HANDLE_VALUE
)
3794 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3795 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3797 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3798 if (KeyBuffer
!= NULL
)
3800 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3801 if (rc
== ERROR_SUCCESS
)
3804 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3806 /* Add coinstaller to DeviceCoInstallersListHead list */
3807 struct CoInstallerElement
*coinstaller
;
3808 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3809 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3812 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3813 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3814 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3816 HeapFree(GetProcessHeap(), 0, coinstaller
);
3819 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3825 if (CanHandle
& CLASS_COINSTALLER
)
3829 REGSTR_PATH_CODEVICEINSTALLERS
,
3833 if (rc
== ERROR_SUCCESS
)
3835 LPWSTR lpGuidString
;
3836 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3838 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3839 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3841 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3842 if (KeyBuffer
!= NULL
)
3844 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3845 if (rc
== ERROR_SUCCESS
)
3848 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3850 /* Add coinstaller to ClassCoInstallersListHead list */
3851 struct CoInstallerElement
*coinstaller
;
3852 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3853 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3856 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3857 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3858 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3860 HeapFree(GetProcessHeap(), 0, coinstaller
);
3863 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3866 RpcStringFreeW(&lpGuidString
);
3871 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3873 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3874 if (hKey
!= INVALID_HANDLE_VALUE
)
3876 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3877 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3879 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3880 if (KeyBuffer
!= NULL
)
3882 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3883 if (rc
== ERROR_SUCCESS
)
3885 /* Get ClassInstaller function pointer */
3886 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3887 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3889 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3890 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3893 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3900 /* Call Class co-installers */
3901 Context
.PostProcessing
= FALSE
;
3903 ListEntry
= ClassCoInstallersListHead
.Flink
;
3904 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3906 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3907 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3908 coinstaller
->PrivateData
= Context
.PrivateData
;
3909 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3911 coinstaller
->DoPostProcessing
= TRUE
;
3914 ListEntry
= ListEntry
->Flink
;
3917 /* Call Device co-installers */
3918 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3919 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3921 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3922 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3923 coinstaller
->PrivateData
= Context
.PrivateData
;
3924 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3926 coinstaller
->DoPostProcessing
= TRUE
;
3929 ListEntry
= ListEntry
->Flink
;
3932 /* Call Class installer */
3935 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3936 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3939 rc
= ERROR_DI_DO_DEFAULT
;
3941 /* Call default handler */
3942 if (rc
== ERROR_DI_DO_DEFAULT
)
3944 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3946 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3949 rc
= GetLastError();
3955 /* Call Class co-installers that required postprocessing */
3956 Context
.PostProcessing
= TRUE
;
3957 ListEntry
= ClassCoInstallersListHead
.Flink
;
3958 while (ListEntry
!= &ClassCoInstallersListHead
)
3960 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3961 if (coinstaller
->DoPostProcessing
)
3963 Context
.InstallResult
= rc
;
3964 Context
.PrivateData
= coinstaller
->PrivateData
;
3965 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3967 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3968 ListEntry
= ListEntry
->Flink
;
3971 /* Call Device co-installers that required postprocessing */
3972 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3973 while (ListEntry
!= &DeviceCoInstallersListHead
)
3975 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3976 if (coinstaller
->DoPostProcessing
)
3978 Context
.InstallResult
= rc
;
3979 Context
.PrivateData
= coinstaller
->PrivateData
;
3980 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3982 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3983 ListEntry
= ListEntry
->Flink
;
3986 /* Free allocated memory */
3987 while (!IsListEmpty(&ClassCoInstallersListHead
))
3989 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3990 HeapFree(GetProcessHeap(), 0, ListEntry
);
3992 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3994 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3995 HeapFree(GetProcessHeap(), 0, ListEntry
);
3998 ret
= (rc
== NO_ERROR
);
4002 TRACE("Returning %d\n", ret
);
4006 /***********************************************************************
4007 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4009 BOOL WINAPI
SetupDiGetDeviceInfoListClass(
4010 IN HDEVINFO DeviceInfoSet
,
4011 OUT LPGUID ClassGuid
)
4013 struct DeviceInfoSet
*list
;
4016 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4019 SetLastError(ERROR_INVALID_HANDLE
);
4020 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4021 SetLastError(ERROR_INVALID_HANDLE
);
4022 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4023 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4026 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4031 TRACE("Returning %d\n", ret
);
4035 /***********************************************************************
4036 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4038 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
4039 IN HDEVINFO DeviceInfoSet
,
4040 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
4042 struct DeviceInfoSet
*list
;
4045 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
4048 SetLastError(ERROR_INVALID_HANDLE
);
4049 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4050 SetLastError(ERROR_INVALID_HANDLE
);
4051 else if (!DeviceInfoListDetailData
)
4052 SetLastError(ERROR_INVALID_PARAMETER
);
4053 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
4054 SetLastError(ERROR_INVALID_USER_BUFFER
);
4058 &DeviceInfoListDetailData
->ClassGuid
,
4061 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
4062 if (list
->MachineName
)
4063 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
4065 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
4070 TRACE("Returning %d\n", ret
);
4074 /***********************************************************************
4075 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4077 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4078 IN HDEVINFO DeviceInfoSet
,
4079 IN PSP_DEVINFO_DATA DeviceInfoData
,
4080 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4082 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4085 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4087 if (DeviceInstallParams
== NULL
)
4088 SetLastError(ERROR_INVALID_PARAMETER
);
4089 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4090 SetLastError(ERROR_INVALID_USER_BUFFER
);
4093 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4094 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4098 /* Do W->A conversion */
4100 DeviceInstallParams
,
4101 &deviceInstallParamsW
,
4102 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4103 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4104 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4106 DeviceInstallParams
->DriverPath
[0] = '\0';
4112 TRACE("Returning %d\n", ret
);
4116 /***********************************************************************
4117 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4119 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
4120 IN HDEVINFO DeviceInfoSet
,
4121 IN PSP_DEVINFO_DATA DeviceInfoData
,
4122 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4124 struct DeviceInfoSet
*list
;
4127 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4130 SetLastError(ERROR_INVALID_HANDLE
);
4131 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4132 SetLastError(ERROR_INVALID_HANDLE
);
4133 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4134 SetLastError(ERROR_INVALID_USER_BUFFER
);
4135 else if (!DeviceInstallParams
)
4136 SetLastError(ERROR_INVALID_PARAMETER
);
4137 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4138 SetLastError(ERROR_INVALID_USER_BUFFER
);
4141 PSP_DEVINSTALL_PARAMS_W Source
;
4144 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4146 Source
= &list
->InstallParams
;
4147 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4151 TRACE("Returning %d\n", ret
);
4156 CheckDeviceInstallParameters(
4157 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4159 DWORD SupportedFlags
=
4160 DI_NOVCP
| /* 0x00000008 */
4161 DI_DIDCOMPAT
| /* 0x00000010 */
4162 DI_DIDCLASS
| /* 0x00000020 */
4163 DI_NEEDRESTART
| /* 0x00000080 */
4164 DI_NEEDREBOOT
| /* 0x00000100 */
4165 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4166 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4167 DI_ENUMSINGLEINF
| /* 0x00010000 */
4168 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4169 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4170 DI_NOFILECOPY
| /* 0x01000000 */
4171 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4172 DWORD SupportedFlagsEx
=
4173 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4174 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4175 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4176 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4177 DI_FLAGSEX_NO_DRVREG_MODIFY
; /* 0x00008000 */
4180 /* FIXME: add support for more flags */
4182 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4183 * It should be checked before accessing to other values
4184 * of the SP_DEVINSTALL_PARAMS structure */
4186 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4188 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4189 SetLastError(ERROR_INVALID_FLAGS
);
4191 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4193 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4194 SetLastError(ERROR_INVALID_FLAGS
);
4196 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4197 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4198 SetLastError(ERROR_INVALID_USER_BUFFER
);
4201 /* FIXME: check Reserved field */
4208 /***********************************************************************
4209 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4211 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
4212 IN HDEVINFO DeviceInfoSet
,
4213 IN PSP_DEVINFO_DATA DeviceInfoData
,
4214 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4216 struct DeviceInfoSet
*list
;
4219 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4222 SetLastError(ERROR_INVALID_HANDLE
);
4223 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4224 SetLastError(ERROR_INVALID_HANDLE
);
4225 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4226 SetLastError(ERROR_INVALID_USER_BUFFER
);
4227 else if (!DeviceInstallParams
)
4228 SetLastError(ERROR_INVALID_PARAMETER
);
4229 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4230 SetLastError(ERROR_INVALID_USER_BUFFER
);
4231 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4233 PSP_DEVINSTALL_PARAMS_W Destination
;
4236 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4238 Destination
= &list
->InstallParams
;
4239 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4243 TRACE("Returning %d\n", ret
);
4247 /***********************************************************************
4248 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4250 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
4251 IN HDEVINFO DeviceInfoSet
,
4252 IN PSP_DEVINFO_DATA DeviceInfoData
,
4253 OUT PSTR DeviceInstanceId OPTIONAL
,
4254 IN DWORD DeviceInstanceIdSize
,
4255 OUT PDWORD RequiredSize OPTIONAL
)
4257 PWSTR DeviceInstanceIdW
= NULL
;
4260 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4261 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4263 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4264 SetLastError(ERROR_INVALID_PARAMETER
);
4267 if (DeviceInstanceIdSize
!= 0)
4269 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4270 if (DeviceInstanceIdW
== NULL
)
4274 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4275 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4278 if (ret
&& DeviceInstanceIdW
!= NULL
)
4280 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4281 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4283 DeviceInstanceId
[0] = '\0';
4289 TRACE("Returning %d\n", ret
);
4293 /***********************************************************************
4294 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4296 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
4297 IN HDEVINFO DeviceInfoSet
,
4298 IN PSP_DEVINFO_DATA DeviceInfoData
,
4299 OUT PWSTR DeviceInstanceId OPTIONAL
,
4300 IN DWORD DeviceInstanceIdSize
,
4301 OUT PDWORD RequiredSize OPTIONAL
)
4305 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4306 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4309 SetLastError(ERROR_INVALID_HANDLE
);
4310 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4311 SetLastError(ERROR_INVALID_HANDLE
);
4312 else if (!DeviceInfoData
)
4313 SetLastError(ERROR_INVALID_PARAMETER
);
4314 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4315 SetLastError(ERROR_INVALID_USER_BUFFER
);
4316 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4317 SetLastError(ERROR_INVALID_PARAMETER
);
4318 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4319 SetLastError(ERROR_INVALID_PARAMETER
);
4322 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4325 required
= (wcslen(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4327 *RequiredSize
= required
;
4329 if (required
<= DeviceInstanceIdSize
)
4331 wcscpy(DeviceInstanceId
, DevInfo
->DeviceName
);
4335 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4338 TRACE("Returning %d\n", ret
);
4342 /***********************************************************************
4343 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4345 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
4346 IN HDEVINFO DeviceInfoSet
,
4347 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4348 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4349 IN DWORD PropertySheetHeaderPageListSize
,
4350 OUT PDWORD RequiredSize OPTIONAL
,
4351 IN DWORD PropertySheetType
)
4353 PROPSHEETHEADERW psh
;
4356 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4357 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4358 RequiredSize
, PropertySheetType
);
4360 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4361 psh
.phpage
= PropertySheetHeader
->phpage
;
4362 psh
.nPages
= PropertySheetHeader
->nPages
;
4364 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4365 PropertySheetHeaderPageListSize
, RequiredSize
,
4369 PropertySheetHeader
->nPages
= psh
.nPages
;
4372 TRACE("Returning %d\n", ret
);
4376 struct ClassDevPropertySheetsData
4378 HPROPSHEETPAGE
*PropertySheetPages
;
4379 DWORD MaximumNumberOfPages
;
4380 DWORD NumberOfPages
;
4383 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
4384 IN HPROPSHEETPAGE hPropSheetPage
,
4385 IN OUT LPARAM lParam
)
4387 struct ClassDevPropertySheetsData
*PropPageData
;
4389 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4391 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4393 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4394 PropPageData
->PropertySheetPages
++;
4397 PropPageData
->NumberOfPages
++;
4401 /***********************************************************************
4402 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4404 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
4405 IN HDEVINFO DeviceInfoSet
,
4406 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4407 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4408 IN DWORD PropertySheetHeaderPageListSize
,
4409 OUT PDWORD RequiredSize OPTIONAL
,
4410 IN DWORD PropertySheetType
)
4412 struct DeviceInfoSet
*list
;
4415 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4416 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4417 RequiredSize
, PropertySheetType
);
4420 SetLastError(ERROR_INVALID_HANDLE
);
4421 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4422 SetLastError(ERROR_INVALID_HANDLE
);
4423 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4424 SetLastError(ERROR_INVALID_HANDLE
);
4425 else if (!PropertySheetHeader
)
4426 SetLastError(ERROR_INVALID_PARAMETER
);
4427 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4428 SetLastError(ERROR_INVALID_FLAGS
);
4429 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4430 SetLastError(ERROR_INVALID_USER_BUFFER
);
4431 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4432 SetLastError(ERROR_INVALID_PARAMETER
);
4433 else if (!PropertySheetHeader
)
4434 SetLastError(ERROR_INVALID_PARAMETER
);
4435 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4436 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4437 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4438 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4439 SetLastError(ERROR_INVALID_PARAMETER
);
4442 HKEY hKey
= INVALID_HANDLE_VALUE
;
4443 SP_PROPSHEETPAGE_REQUEST Request
;
4444 LPWSTR PropPageProvider
= NULL
;
4445 HMODULE hModule
= NULL
;
4446 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4447 struct ClassDevPropertySheetsData PropPageData
;
4448 DWORD dwLength
, dwRegType
;
4452 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4455 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4456 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4458 if (hKey
== INVALID_HANDLE_VALUE
)
4461 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4462 if (rc
== ERROR_FILE_NOT_FOUND
)
4464 /* No registry key. As it is optional, don't say it's a bad error */
4470 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4476 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4477 if (!PropPageProvider
)
4479 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4482 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4483 if (rc
!= ERROR_SUCCESS
)
4488 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4490 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4491 if (rc
!= ERROR_SUCCESS
)
4493 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4497 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4498 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4499 Request
.DeviceInfoSet
= DeviceInfoSet
;
4500 Request
.DeviceInfoData
= DeviceInfoData
;
4501 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4502 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4503 PropPageData
.NumberOfPages
= 0;
4504 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4509 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4510 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4512 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4517 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4518 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4522 if (hKey
!= INVALID_HANDLE_VALUE
)
4524 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4525 FreeFunctionPointer(hModule
, pPropPageProvider
);
4528 TRACE("Returning %d\n", ret
);
4532 /***********************************************************************
4533 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4535 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4536 IN HDEVINFO DeviceInfoSet
,
4537 IN PSP_DEVINFO_DATA DeviceInfoData
,
4541 IN HINF InfHandle OPTIONAL
,
4542 IN PCSTR InfSectionName OPTIONAL
)
4544 PCWSTR InfSectionNameW
= NULL
;
4545 HKEY ret
= INVALID_HANDLE_VALUE
;
4549 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4550 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4553 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4561 if (InfSectionNameW
!= NULL
)
4562 MyFree((PVOID
)InfSectionNameW
);
4568 OpenHardwareProfileKey(
4571 IN DWORD samDesired
)
4573 HKEY hHWProfilesKey
= INVALID_HANDLE_VALUE
;
4574 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4575 HKEY ret
= INVALID_HANDLE_VALUE
;
4578 rc
= RegOpenKeyExW(HKLM
,
4579 REGSTR_PATH_HWPROFILES
,
4583 if (rc
!= ERROR_SUCCESS
)
4600 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4609 if (rc
!= ERROR_SUCCESS
)
4614 ret
= hHWProfileKey
;
4617 if (hHWProfilesKey
!= INVALID_HANDLE_VALUE
)
4618 RegCloseKey(hHWProfilesKey
);
4619 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
&& hHWProfileKey
!= ret
)
4620 RegCloseKey(hHWProfileKey
);
4624 /***********************************************************************
4625 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4627 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4628 IN HDEVINFO DeviceInfoSet
,
4629 IN PSP_DEVINFO_DATA DeviceInfoData
,
4633 IN HINF InfHandle OPTIONAL
,
4634 IN PCWSTR InfSectionName OPTIONAL
)
4636 struct DeviceInfoSet
*list
;
4637 HKEY ret
= INVALID_HANDLE_VALUE
;
4639 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4640 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4643 SetLastError(ERROR_INVALID_HANDLE
);
4644 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4645 SetLastError(ERROR_INVALID_HANDLE
);
4646 else if (!DeviceInfoData
)
4647 SetLastError(ERROR_INVALID_PARAMETER
);
4648 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4649 SetLastError(ERROR_INVALID_USER_BUFFER
);
4650 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4651 SetLastError(ERROR_INVALID_PARAMETER
);
4652 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4653 SetLastError(ERROR_INVALID_PARAMETER
);
4654 else if (InfHandle
&& !InfSectionName
)
4655 SetLastError(ERROR_INVALID_PARAMETER
);
4656 else if (!InfHandle
&& InfSectionName
)
4657 SetLastError(ERROR_INVALID_PARAMETER
);
4660 LPWSTR lpGuidString
= NULL
;
4661 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4662 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4663 DWORD Index
; /* Index used in the DriverKey name */
4665 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4666 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4667 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4668 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4669 HKEY hKey
= INVALID_HANDLE_VALUE
;
4672 if (Scope
== DICS_FLAG_GLOBAL
)
4673 RootKey
= list
->HKLM
;
4674 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4676 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
4677 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4679 RootKey
= hHWProfileKey
;
4682 if (KeyType
== DIREG_DEV
)
4684 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4686 rc
= RegCreateKeyExW(
4688 REGSTR_PATH_SYSTEMENUM
,
4691 REG_OPTION_NON_VOLATILE
,
4696 if (rc
!= ERROR_SUCCESS
)
4701 rc
= RegCreateKeyExW(
4703 deviceInfo
->DeviceName
,
4706 REG_OPTION_NON_VOLATILE
,
4707 #if _WIN32_WINNT >= 0x502
4708 KEY_READ
| KEY_WRITE
,
4715 if (rc
!= ERROR_SUCCESS
)
4721 else /* KeyType == DIREG_DRV */
4723 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4725 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4726 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4729 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4732 wcscpy(DriverKey
, L
"{");
4733 wcscat(DriverKey
, lpGuidString
);
4734 wcscat(DriverKey
, L
"}\\");
4735 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4736 rc
= RegOpenKeyExW(RootKey
,
4737 REGSTR_PATH_CLASS_NT
,
4741 if (rc
!= ERROR_SUCCESS
)
4747 /* Try all values for Index between 0 and 9999 */
4749 while (Index
<= 9999)
4752 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4753 rc
= RegCreateKeyEx(hClassKey
,
4757 REG_OPTION_NON_VOLATILE
,
4758 #if _WIN32_WINNT >= 0x502
4759 KEY_READ
| KEY_WRITE
,
4766 if (rc
!= ERROR_SUCCESS
)
4771 if (Disposition
== REG_CREATED_NEW_KEY
)
4774 hKey
= INVALID_HANDLE_VALUE
;
4779 /* Unable to create more than 9999 devices within the same class */
4780 SetLastError(ERROR_GEN_FAILURE
);
4784 /* Open device key, to write Driver value */
4785 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4786 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4788 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4789 if (rc
!= ERROR_SUCCESS
)
4796 /* Do installation of the specified section */
4799 FIXME("Need to install section %s in file %p\n",
4800 debugstr_w(InfSectionName
), InfHandle
);
4806 RpcStringFreeW(&lpGuidString
);
4807 HeapFree(GetProcessHeap(), 0, DriverKey
);
4808 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4809 RegCloseKey(hHWProfileKey
);
4810 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4811 RegCloseKey(hEnumKey
);
4812 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4813 RegCloseKey(hClassKey
);
4814 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4815 RegCloseKey(hDeviceKey
);
4816 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4820 TRACE("Returning 0x%p\n", ret
);
4824 /***********************************************************************
4825 * SetupDiOpenDevRegKey (SETUPAPI.@)
4827 HKEY WINAPI
SetupDiOpenDevRegKey(
4828 HDEVINFO DeviceInfoSet
,
4829 PSP_DEVINFO_DATA DeviceInfoData
,
4835 struct DeviceInfoSet
*list
;
4836 HKEY ret
= INVALID_HANDLE_VALUE
;
4838 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4839 Scope
, HwProfile
, KeyType
, samDesired
);
4842 SetLastError(ERROR_INVALID_HANDLE
);
4843 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4844 SetLastError(ERROR_INVALID_HANDLE
);
4845 else if (!DeviceInfoData
)
4846 SetLastError(ERROR_INVALID_PARAMETER
);
4847 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4848 SetLastError(ERROR_INVALID_USER_BUFFER
);
4849 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4850 SetLastError(ERROR_INVALID_PARAMETER
);
4851 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4852 SetLastError(ERROR_INVALID_PARAMETER
);
4855 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4856 LPWSTR DriverKey
= NULL
;
4860 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4861 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4862 HKEY hKey
= INVALID_HANDLE_VALUE
;
4865 if (Scope
== DICS_FLAG_GLOBAL
)
4866 RootKey
= list
->HKLM
;
4867 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4869 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
4870 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4872 RootKey
= hHWProfileKey
;
4877 REGSTR_PATH_SYSTEMENUM
,
4881 if (rc
!= ERROR_SUCCESS
)
4888 deviceInfo
->DeviceName
,
4890 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4892 RegCloseKey(hEnumKey
);
4893 hEnumKey
= INVALID_HANDLE_VALUE
;
4894 if (rc
!= ERROR_SUCCESS
)
4899 if (KeyType
== DIREG_DEV
)
4901 /* We're done. Just return the hKey handle */
4905 /* Read the 'Driver' key */
4906 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
4907 if (rc
!= ERROR_SUCCESS
)
4912 else if (dwRegType
!= REG_SZ
)
4914 SetLastError(ERROR_GEN_FAILURE
);
4917 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4920 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4923 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4924 if (rc
!= ERROR_SUCCESS
)
4930 hKey
= INVALID_HANDLE_VALUE
;
4931 /* Need to open the driver key */
4934 REGSTR_PATH_CLASS_NT
,
4938 if (rc
!= ERROR_SUCCESS
)
4949 if (rc
!= ERROR_SUCCESS
)
4957 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4958 RegCloseKey(hHWProfileKey
);
4959 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4960 RegCloseKey(hEnumKey
);
4961 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4965 TRACE("Returning 0x%p\n", ret
);
4969 /***********************************************************************
4970 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
4972 BOOL WINAPI
SetupDiCreateDeviceInfoA(
4973 HDEVINFO DeviceInfoSet
,
4975 CONST GUID
*ClassGuid
,
4976 PCSTR DeviceDescription
,
4978 DWORD CreationFlags
,
4979 PSP_DEVINFO_DATA DeviceInfoData
)
4981 LPWSTR DeviceNameW
= NULL
;
4982 LPWSTR DeviceDescriptionW
= NULL
;
4989 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
4990 if (DeviceNameW
== NULL
) return FALSE
;
4992 if (DeviceDescription
)
4994 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
4995 if (DeviceDescriptionW
== NULL
)
4997 if (DeviceNameW
) MyFree(DeviceNameW
);
5002 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
5003 ClassGuid
, DeviceDescriptionW
,
5004 hwndParent
, CreationFlags
,
5007 if (DeviceNameW
) MyFree(DeviceNameW
);
5008 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
5013 /***********************************************************************
5014 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
5016 BOOL WINAPI
SetupDiCreateDeviceInfoW(
5017 HDEVINFO DeviceInfoSet
,
5019 CONST GUID
*ClassGuid
,
5020 PCWSTR DeviceDescription
,
5022 DWORD CreationFlags
,
5023 PSP_DEVINFO_DATA DeviceInfoData
)
5025 struct DeviceInfoSet
*list
;
5028 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
5029 debugstr_guid(ClassGuid
), DeviceDescription
,
5030 hwndParent
, CreationFlags
, DeviceInfoData
);
5033 SetLastError(ERROR_INVALID_HANDLE
);
5034 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5035 SetLastError(ERROR_INVALID_HANDLE
);
5036 else if (!ClassGuid
)
5037 SetLastError(ERROR_INVALID_PARAMETER
);
5038 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
5039 SetLastError(ERROR_CLASS_MISMATCH
);
5040 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
5042 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
5043 SetLastError(ERROR_INVALID_FLAGS
);
5047 SP_DEVINFO_DATA DevInfo
;
5049 if (CreationFlags
& DICD_GENERATE_ID
)
5051 /* Generate a new unique ID for this device */
5052 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5053 FIXME("not implemented\n");
5057 /* Device name is fully qualified. Try to open it */
5060 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
5061 rc
= SetupDiOpenDeviceInfoW(
5064 NULL
, /* hwndParent */
5065 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
5070 /* SetupDiOpenDeviceInfoW has already added
5071 * the device info to the device info set
5073 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
5075 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5077 struct DeviceInfoElement
*deviceInfo
;
5079 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
5081 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5083 if (!DeviceInfoData
)
5087 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
5089 SetLastError(ERROR_INVALID_USER_BUFFER
);
5093 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5094 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5095 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5104 TRACE("Returning %d\n", ret
);
5108 /***********************************************************************
5109 * Helper functions for SetupDiBuildDriverInfoList
5113 IN PLIST_ENTRY DriverListHead
,
5114 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5115 IN LPGUID ClassGuid
,
5116 IN INFCONTEXT ContextDevice
,
5117 IN
struct InfFileDetails
*InfFileDetails
,
5119 IN LPCWSTR ProviderName
,
5120 IN LPCWSTR ManufacturerName
,
5121 IN LPCWSTR MatchingId
,
5122 FILETIME DriverDate
,
5123 DWORDLONG DriverVersion
,
5126 struct DriverInfoElement
*driverInfo
= NULL
;
5127 HANDLE hFile
= INVALID_HANDLE_VALUE
;
5128 DWORD RequiredSize
= 128; /* Initial buffer size */
5129 BOOL Result
= FALSE
;
5130 PLIST_ENTRY PreviousEntry
;
5131 LPWSTR InfInstallSection
= NULL
;
5134 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
5137 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5140 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
5142 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
5143 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
5145 /* Copy InfFileName field */
5146 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
5147 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
5149 /* Fill InfDate field */
5150 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5151 GENERIC_READ, FILE_SHARE_READ,
5152 NULL, OPEN_EXISTING, 0, NULL);
5153 if (hFile == INVALID_HANDLE_VALUE)
5155 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5159 /* Fill SectionName field */
5160 Result
= SetupGetStringFieldW(
5163 driverInfo
->Details
.SectionName
, LINE_LEN
,
5168 /* Fill DrvDescription field */
5169 Result
= SetupGetStringFieldW(
5171 0, /* Field index */
5172 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
5175 /* Copy MatchingId information */
5178 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5179 if (!driverInfo
->MatchingId
)
5181 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5184 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5187 driverInfo
->MatchingId
= NULL
;
5189 /* Get inf install section */
5191 RequiredSize
= 128; /* Initial buffer size */
5192 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5193 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5195 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5196 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5197 if (!InfInstallSection
)
5199 Result
= SetupGetStringFieldW(
5201 1, /* Field index */
5202 InfInstallSection
, RequiredSize
,
5208 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
5209 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
5211 driverInfo
->DriverRank
= Rank
;
5212 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
5213 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5214 driverInfo
->Info
.DriverType
= DriverType
;
5215 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
5216 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
5217 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
5218 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
5219 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
5222 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
5223 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
5226 driverInfo
->Info
.ProviderName
[0] = '\0';
5227 driverInfo
->Info
.DriverDate
= DriverDate
;
5228 driverInfo
->Info
.DriverVersion
= DriverVersion
;
5229 ReferenceInfFile(InfFileDetails
);
5230 driverInfo
->InfFileDetails
= InfFileDetails
;
5232 /* Insert current driver in driver list, according to its rank */
5233 PreviousEntry
= DriverListHead
->Flink
;
5234 while (PreviousEntry
!= DriverListHead
)
5236 struct DriverInfoElement
*CurrentDriver
;
5237 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
5238 if (CurrentDriver
->DriverRank
> Rank
||
5239 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
5241 /* Insert before the current item */
5242 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
5245 PreviousEntry
= PreviousEntry
->Flink
;
5247 if (PreviousEntry
== DriverListHead
)
5249 /* Insert at the end of the list */
5250 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
5259 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
5260 HeapFree(GetProcessHeap(), 0, driverInfo
);
5262 if (hFile
!= INVALID_HANDLE_VALUE
)
5264 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5270 GetVersionInformationFromInfFile(
5272 OUT LPGUID ClassGuid
,
5273 OUT LPWSTR
* pProviderName
,
5274 OUT FILETIME
* DriverDate
,
5275 OUT DWORDLONG
* DriverVersion
)
5278 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5279 LPWSTR DriverVer
= NULL
;
5280 LPWSTR ProviderName
= NULL
;
5281 LPWSTR pComma
; /* Points into DriverVer */
5282 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5283 SYSTEMTIME SystemTime
;
5285 BOOL ret
= FALSE
; /* Final result */
5287 /* Get class Guid */
5288 if (!SetupGetLineTextW(
5291 L
"Version", L
"ClassGUID",
5292 guidW
, sizeof(guidW
),
5293 NULL
/* Required size */))
5297 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5298 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5300 SetLastError(ERROR_GEN_FAILURE
);
5304 /* Get provider name */
5305 Result
= SetupGetLineTextW(
5307 hInf
, L
"Version", L
"Provider",
5312 /* We know know the needed buffer size */
5313 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5316 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5319 Result
= SetupGetLineTextW(
5321 hInf
, L
"Version", L
"Provider",
5322 ProviderName
, RequiredSize
,
5327 *pProviderName
= ProviderName
;
5329 /* Read the "DriverVer" value */
5330 Result
= SetupGetLineTextW(
5332 hInf
, L
"Version", L
"DriverVer",
5337 /* We know know the needed buffer size */
5338 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5341 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5344 Result
= SetupGetLineTextW(
5346 hInf
, L
"Version", L
"DriverVer",
5347 DriverVer
, RequiredSize
,
5353 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5354 pComma
= wcschr(DriverVer
, ',');
5357 *pComma
= UNICODE_NULL
;
5358 pVersion
= pComma
+ 1;
5360 /* Get driver date version. Invalid date = 00/00/00 */
5361 memset(DriverDate
, 0, sizeof(FILETIME
));
5362 if (wcslen(DriverVer
) == 10
5363 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5364 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5366 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5367 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5368 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5369 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5370 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5371 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5373 /* Get driver version. Invalid version = 0.0.0.0 */
5377 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5378 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5379 LARGE_INTEGER fullVersion
;
5381 pMinor
= strchrW(pVersion
, '.');
5385 pRevision
= strchrW(++pMinor
, '.');
5386 Minor
= atoiW(pMinor
);
5391 pBuild
= strchrW(++pRevision
, '.');
5392 Revision
= atoiW(pRevision
);
5398 Build
= atoiW(pBuild
);
5400 Major
= atoiW(pVersion
);
5401 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5402 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5403 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5410 HeapFree(GetProcessHeap(), 0, ProviderName
);
5411 HeapFree(GetProcessHeap(), 0, DriverVer
);
5416 /***********************************************************************
5417 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5420 SetupDiBuildDriverInfoList(
5421 IN HDEVINFO DeviceInfoSet
,
5422 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5423 IN DWORD DriverType
)
5425 struct DeviceInfoSet
*list
;
5426 SP_DEVINSTALL_PARAMS_W InstallParams
;
5427 PVOID Buffer
= NULL
;
5428 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5429 LPWSTR ProviderName
= NULL
;
5430 LPWSTR ManufacturerName
= NULL
;
5431 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5432 LPWSTR HardwareIDs
= NULL
;
5433 LPWSTR CompatibleIDs
= NULL
;
5434 LPWSTR FullInfFileName
= NULL
;
5435 LPWSTR ExcludeFromSelect
= NULL
;
5436 FILETIME DriverDate
;
5437 DWORDLONG DriverVersion
= 0;
5441 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5444 SetLastError(ERROR_INVALID_HANDLE
);
5445 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5446 SetLastError(ERROR_INVALID_HANDLE
);
5447 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5448 SetLastError(ERROR_INVALID_HANDLE
);
5449 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5450 SetLastError(ERROR_INVALID_PARAMETER
);
5451 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5452 SetLastError(ERROR_INVALID_PARAMETER
);
5453 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5454 SetLastError(ERROR_INVALID_USER_BUFFER
);
5457 PLIST_ENTRY pDriverListHead
= &list
->DriverListHead
;
5460 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5461 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5467 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5468 if (!(devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
5469 pDriverListHead
= &devInfo
->DriverListHead
;
5472 if (DriverType
== SPDIT_COMPATDRIVER
)
5474 /* Get hardware IDs list */
5476 RequiredSize
= 512; /* Initial buffer size */
5477 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5478 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5480 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5481 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5484 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5487 Result
= SetupDiGetDeviceRegistryPropertyW(
5499 /* Get compatible IDs list */
5501 RequiredSize
= 512; /* Initial buffer size */
5502 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5503 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5505 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5506 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5509 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5512 Result
= SetupDiGetDeviceRegistryPropertyW(
5515 SPDRP_COMPATIBLEIDS
,
5517 (PBYTE
)CompatibleIDs
,
5520 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5522 /* No compatible ID for this device */
5523 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5524 CompatibleIDs
= NULL
;
5532 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5534 /* InstallParams.DriverPath contains the name of a .inf file */
5535 RequiredSize
= wcslen(InstallParams
.DriverPath
) + 2;
5536 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5539 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5542 wcscpy(Buffer
, InstallParams
.DriverPath
);
5543 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
5548 /* Enumerate .inf files */
5550 RequiredSize
= 32768; /* Initial buffer size */
5551 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5552 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5554 HeapFree(GetProcessHeap(), 0, Buffer
);
5555 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5559 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5562 Result
= SetupGetInfFileListW(
5563 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5565 Buffer
, RequiredSize
,
5568 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5570 /* No .inf file in specified directory. So, we should
5571 * success as we created an empty driver info list.
5580 LPWSTR pFullFilename
;
5582 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5584 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5585 if (!FullInfFileName
)
5587 pFullFilename
= &FullInfFileName
[0];
5589 else if (*InstallParams
.DriverPath
)
5592 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5595 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5596 if (!FullInfFileName
)
5598 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5601 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
5602 wcscat(FullInfFileName
, L
"\\");
5603 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
5607 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5608 if (!FullInfFileName
)
5610 pFullFilename
= &FullInfFileName
[0];
5613 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
5615 INFCONTEXT ContextManufacturer
, ContextDevice
;
5618 wcscpy(pFullFilename
, filename
);
5619 TRACE("Opening file %S\n", FullInfFileName
);
5621 currentInfFileDetails
= HeapAlloc(
5624 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
5625 if (!currentInfFileDetails
)
5627 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5628 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5630 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5631 ReferenceInfFile(currentInfFileDetails
);
5632 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5634 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5635 currentInfFileDetails
= NULL
;
5639 if (!GetVersionInformationFromInfFile(
5640 currentInfFileDetails
->hInf
,
5646 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5647 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5648 currentInfFileDetails
= NULL
;
5652 if (DriverType
== SPDIT_CLASSDRIVER
)
5654 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5655 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5661 if (InstallParams
.FlagsEx
& DI_FLAGSEX_ALLOWEXCLUDEDDRVS
)
5663 /* Read ExcludeFromSelect control flags */
5667 FIXME("ExcludeFromSelect list ignored\n");
5669 /* Get the manufacturers list */
5670 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
5673 Result
= SetupGetStringFieldW(
5674 &ContextManufacturer
,
5675 0, /* Field index */
5680 /* We got the needed size for the buffer */
5681 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5682 if (!ManufacturerName
)
5684 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5687 Result
= SetupGetStringFieldW(
5688 &ContextManufacturer
,
5689 0, /* Field index */
5690 ManufacturerName
, RequiredSize
,
5693 /* Get manufacturer section name */
5694 Result
= SetupGetStringFieldW(
5695 &ContextManufacturer
,
5696 1, /* Field index */
5697 ManufacturerSection
, LINE_LEN
,
5701 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5702 /* Add (possible) extension to manufacturer section name */
5703 Result
= SetupDiGetActualSectionToInstallW(
5704 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5707 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
5708 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5713 if (DriverType
== SPDIT_CLASSDRIVER
)
5715 /* FIXME: Check ExcludeFromSelect list */
5716 if (!AddDriverToList(
5721 currentInfFileDetails
,
5726 DriverDate
, DriverVersion
,
5732 else /* DriverType = SPDIT_COMPATDRIVER */
5734 /* 1. Get all fields */
5735 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5739 BOOL DriverAlreadyAdded
;
5741 for (i
= 2; i
<= FieldCount
; i
++)
5743 LPWSTR DeviceId
= NULL
;
5745 RequiredSize
= 128; /* Initial buffer size */
5746 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5747 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5749 HeapFree(GetProcessHeap(), 0, DeviceId
);
5750 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5753 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5756 Result
= SetupGetStringFieldW(
5759 DeviceId
, RequiredSize
,
5764 HeapFree(GetProcessHeap(), 0, DeviceId
);
5767 /* FIXME: Check ExcludeFromSelect list */
5768 DriverAlreadyAdded
= FALSE
;
5769 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5771 if (wcsicmp(DeviceId
, currentId
) == 0)
5778 currentInfFileDetails
,
5783 DriverDate
, DriverVersion
,
5784 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5785 DriverAlreadyAdded
= TRUE
;
5790 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5792 if (wcsicmp(DeviceId
, currentId
) == 0)
5799 currentInfFileDetails
,
5804 DriverDate
, DriverVersion
,
5805 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5806 DriverAlreadyAdded
= TRUE
;
5810 HeapFree(GetProcessHeap(), 0, DeviceId
);
5813 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5816 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5817 ManufacturerName
= NULL
;
5818 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5823 HeapFree(GetProcessHeap(), 0, ProviderName
);
5824 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
5825 ProviderName
= ExcludeFromSelect
= NULL
;
5827 DereferenceInfFile(currentInfFileDetails
);
5828 currentInfFileDetails
= NULL
;
5839 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5840 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5844 InstallParams
.Flags
|= DI_DIDCLASS
;
5845 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5847 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5850 HeapFree(GetProcessHeap(), 0, ProviderName
);
5851 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5852 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5853 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5854 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5855 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
5856 if (currentInfFileDetails
)
5857 DereferenceInfFile(currentInfFileDetails
);
5858 HeapFree(GetProcessHeap(), 0, Buffer
);
5860 TRACE("Returning %d\n", ret
);
5864 /***********************************************************************
5865 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5868 SetupDiDeleteDeviceInfo(
5869 IN HDEVINFO DeviceInfoSet
,
5870 IN PSP_DEVINFO_DATA DeviceInfoData
)
5872 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5874 FIXME("not implemented\n");
5875 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5880 /***********************************************************************
5881 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5884 SetupDiDestroyDriverInfoList(
5885 IN HDEVINFO DeviceInfoSet
,
5886 IN PSP_DEVINFO_DATA DeviceInfoData
,
5887 IN DWORD DriverType
)
5889 struct DeviceInfoSet
*list
;
5892 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5895 SetLastError(ERROR_INVALID_HANDLE
);
5896 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5897 SetLastError(ERROR_INVALID_HANDLE
);
5898 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5899 SetLastError(ERROR_INVALID_PARAMETER
);
5900 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5901 SetLastError(ERROR_INVALID_PARAMETER
);
5902 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5903 SetLastError(ERROR_INVALID_USER_BUFFER
);
5906 PLIST_ENTRY ListEntry
;
5907 struct DriverInfoElement
*driverInfo
;
5908 SP_DEVINSTALL_PARAMS_W InstallParams
;
5910 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5911 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5914 if (!DeviceInfoData
)
5915 /* Fall back to destroying class driver list */
5916 DriverType
= SPDIT_CLASSDRIVER
;
5918 if (DriverType
== SPDIT_CLASSDRIVER
)
5920 while (!IsListEmpty(&list
->DriverListHead
))
5922 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
5923 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5924 DestroyDriverInfoElement(driverInfo
);
5926 InstallParams
.Reserved
= 0;
5927 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
5928 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
5929 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
5933 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
5934 struct DeviceInfoElement
*deviceInfo
;
5936 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5937 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
5939 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5940 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
5942 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
5943 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5944 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
5946 InstallParamsSet
.Reserved
= 0;
5947 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
5949 DestroyDriverInfoElement(driverInfo
);
5951 InstallParams
.Reserved
= 0;
5952 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
5953 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
5954 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5959 TRACE("Returning %d\n", ret
);
5964 /***********************************************************************
5965 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
5968 SetupDiOpenDeviceInfoA(
5969 IN HDEVINFO DeviceInfoSet
,
5970 IN PCSTR DeviceInstanceId
,
5971 IN HWND hwndParent OPTIONAL
,
5973 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5975 LPWSTR DeviceInstanceIdW
= NULL
;
5978 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5980 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
5981 if (DeviceInstanceIdW
== NULL
)
5984 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
5985 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
5987 MyFree(DeviceInstanceIdW
);
5993 /***********************************************************************
5994 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
5997 SetupDiOpenDeviceInfoW(
5998 IN HDEVINFO DeviceInfoSet
,
5999 IN PCWSTR DeviceInstanceId
,
6000 IN HWND hwndParent OPTIONAL
,
6002 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6004 struct DeviceInfoSet
*list
;
6005 HKEY hEnumKey
, hKey
;
6009 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
6011 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
6012 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
6015 SetLastError(ERROR_INVALID_HANDLE
);
6016 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6017 SetLastError(ERROR_INVALID_HANDLE
);
6018 else if (!DeviceInstanceId
)
6019 SetLastError(ERROR_INVALID_PARAMETER
);
6020 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
6022 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
6023 SetLastError(ERROR_INVALID_FLAGS
);
6025 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6026 SetLastError(ERROR_INVALID_USER_BUFFER
);
6029 struct DeviceInfoElement
*deviceInfo
= NULL
;
6030 /* Search if device already exists in DeviceInfoSet.
6031 * If yes, return the existing element
6032 * If no, create a new element using informations in registry
6034 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
6035 while (ItemList
!= &list
->ListHead
)
6040 FIXME("not implemented\n");
6041 ItemList
= ItemList
->Flink
;
6046 /* good one found */
6051 /* Open supposed registry key */
6054 REGSTR_PATH_SYSTEMENUM
,
6058 if (rc
!= ERROR_SUCCESS
)
6069 RegCloseKey(hEnumKey
);
6070 if (rc
!= ERROR_SUCCESS
)
6072 if (rc
== ERROR_FILE_NOT_FOUND
)
6073 rc
= ERROR_NO_SUCH_DEVINST
;
6078 /* FIXME: try to get ClassGUID from registry, instead of
6079 * sending GUID_NULL to CreateDeviceInfoElement
6081 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
6086 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
6092 if (ret
&& deviceInfo
&& DeviceInfoData
)
6094 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
6095 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
6096 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
6104 /***********************************************************************
6105 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6108 SetupDiEnumDriverInfoA(
6109 IN HDEVINFO DeviceInfoSet
,
6110 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6111 IN DWORD DriverType
,
6112 IN DWORD MemberIndex
,
6113 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6115 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6118 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6119 DriverType
, MemberIndex
, DriverInfoData
);
6121 if (DriverInfoData
== NULL
)
6122 SetLastError(ERROR_INVALID_PARAMETER
);
6123 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6124 SetLastError(ERROR_INVALID_USER_BUFFER
);
6127 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6128 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
6129 DriverType
, MemberIndex
, &driverInfoData2W
);
6133 /* Do W->A conversion */
6134 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6135 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6136 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6137 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6139 DriverInfoData
->Description
[0] = '\0';
6142 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6143 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6145 DriverInfoData
->MfgName
[0] = '\0';
6148 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6149 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6151 DriverInfoData
->ProviderName
[0] = '\0';
6154 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6156 /* Copy more fields */
6157 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6158 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6163 TRACE("Returning %d\n", ret
);
6168 /***********************************************************************
6169 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6172 SetupDiEnumDriverInfoW(
6173 IN HDEVINFO DeviceInfoSet
,
6174 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6175 IN DWORD DriverType
,
6176 IN DWORD MemberIndex
,
6177 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6179 PLIST_ENTRY ListHead
;
6182 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6183 DriverType
, MemberIndex
, DriverInfoData
);
6185 if (!DeviceInfoSet
|| !DriverInfoData
)
6186 SetLastError(ERROR_INVALID_PARAMETER
);
6187 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6188 SetLastError(ERROR_INVALID_HANDLE
);
6189 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6190 SetLastError(ERROR_INVALID_HANDLE
);
6191 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6192 SetLastError(ERROR_INVALID_PARAMETER
);
6193 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6194 SetLastError(ERROR_INVALID_PARAMETER
);
6195 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6196 SetLastError(ERROR_INVALID_USER_BUFFER
);
6199 struct DeviceInfoElement
*devInfo
= NULL
;
6200 PLIST_ENTRY ItemList
;
6202 devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6203 if (!devInfo
|| (devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
6205 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6209 ListHead
= &devInfo
->DriverListHead
;
6212 ItemList
= ListHead
->Flink
;
6213 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
6214 ItemList
= ItemList
->Flink
;
6215 if (ItemList
== ListHead
)
6216 SetLastError(ERROR_NO_MORE_ITEMS
);
6219 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
6222 &DriverInfoData
->DriverType
,
6223 &DrvInfo
->Info
.DriverType
,
6224 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6229 TRACE("Returning %d\n", ret
);
6234 /***********************************************************************
6235 * SetupDiGetSelectedDevice (SETUPAPI.@)
6238 SetupDiGetSelectedDevice(
6239 IN HDEVINFO DeviceInfoSet
,
6240 OUT PSP_DEVINFO_DATA DeviceInfoData
)
6242 struct DeviceInfoSet
*list
;
6245 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6248 SetLastError(ERROR_INVALID_HANDLE
);
6249 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6250 SetLastError(ERROR_INVALID_HANDLE
);
6251 else if (list
->SelectedDevice
== NULL
)
6252 SetLastError(ERROR_NO_DEVICE_SELECTED
);
6253 else if (!DeviceInfoData
)
6254 SetLastError(ERROR_INVALID_PARAMETER
);
6255 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6256 SetLastError(ERROR_INVALID_USER_BUFFER
);
6259 memcpy(&DeviceInfoData
->ClassGuid
,
6260 &list
->SelectedDevice
->ClassGuid
,
6262 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
6263 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
6267 TRACE("Returning %d\n", ret
);
6272 /***********************************************************************
6273 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6276 SetupDiGetSelectedDriverA(
6277 IN HDEVINFO DeviceInfoSet
,
6278 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6279 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6281 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6284 if (DriverInfoData
== NULL
)
6285 SetLastError(ERROR_INVALID_PARAMETER
);
6286 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6287 SetLastError(ERROR_INVALID_USER_BUFFER
);
6290 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6292 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
6298 /* Do W->A conversion */
6299 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6300 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6301 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6302 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6304 DriverInfoData
->Description
[0] = '\0';
6307 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6308 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6310 DriverInfoData
->MfgName
[0] = '\0';
6313 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6314 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6316 DriverInfoData
->ProviderName
[0] = '\0';
6319 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6321 /* Copy more fields */
6322 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6323 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6332 /***********************************************************************
6333 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6336 SetupDiGetSelectedDriverW(
6337 IN HDEVINFO DeviceInfoSet
,
6338 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6339 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6343 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6345 if (!DeviceInfoSet
|| !DriverInfoData
)
6346 SetLastError(ERROR_INVALID_PARAMETER
);
6347 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6348 SetLastError(ERROR_INVALID_HANDLE
);
6349 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6350 SetLastError(ERROR_INVALID_HANDLE
);
6351 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6352 SetLastError(ERROR_INVALID_USER_BUFFER
);
6353 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6354 SetLastError(ERROR_INVALID_USER_BUFFER
);
6357 SP_DEVINSTALL_PARAMS InstallParams
;
6359 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6360 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6362 struct DriverInfoElement
*driverInfo
;
6363 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6364 if (driverInfo
== NULL
)
6365 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6369 &DriverInfoData
->DriverType
,
6370 &driverInfo
->Info
.DriverType
,
6371 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6377 TRACE("Returning %d\n", ret
);
6382 /***********************************************************************
6383 * SetupDiSetSelectedDevice (SETUPAPI.@)
6386 SetupDiSetSelectedDevice(
6387 IN HDEVINFO DeviceInfoSet
,
6388 IN PSP_DEVINFO_DATA DeviceInfoData
)
6390 struct DeviceInfoSet
*list
;
6393 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6396 SetLastError(ERROR_INVALID_HANDLE
);
6397 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6398 SetLastError(ERROR_INVALID_HANDLE
);
6399 else if (!DeviceInfoData
)
6400 SetLastError(ERROR_INVALID_PARAMETER
);
6401 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6402 SetLastError(ERROR_INVALID_USER_BUFFER
);
6403 else if (DeviceInfoData
->Reserved
== 0)
6404 SetLastError(ERROR_INVALID_USER_BUFFER
);
6407 list
->SelectedDevice
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6411 TRACE("Returning %d\n", ret
);
6416 /***********************************************************************
6417 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6420 SetupDiSetSelectedDriverA(
6421 IN HDEVINFO DeviceInfoSet
,
6422 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6423 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6425 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6426 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6429 if (DriverInfoData
!= NULL
)
6431 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6432 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6434 SetLastError(ERROR_INVALID_PARAMETER
);
6438 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6439 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6441 if (DriverInfoDataW
.Reserved
== 0)
6443 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6445 /* convert the strings to unicode */
6446 if (!MultiByteToWideChar(CP_ACP
,
6448 DriverInfoData
->Description
,
6450 DriverInfoDataW
.Description
,
6452 !MultiByteToWideChar(CP_ACP
,
6454 DriverInfoData
->ProviderName
,
6456 DriverInfoDataW
.ProviderName
,
6463 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6466 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6470 if (ret
&& pDriverInfoDataW
!= NULL
)
6472 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6479 /***********************************************************************
6480 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6483 SetupDiSetSelectedDriverW(
6484 IN HDEVINFO DeviceInfoSet
,
6485 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6486 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6490 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6493 SetLastError(ERROR_INVALID_PARAMETER
);
6494 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6495 SetLastError(ERROR_INVALID_HANDLE
);
6496 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6497 SetLastError(ERROR_INVALID_HANDLE
);
6498 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6499 SetLastError(ERROR_INVALID_USER_BUFFER
);
6500 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6501 SetLastError(ERROR_INVALID_USER_BUFFER
);
6504 struct DriverInfoElement
**pDriverInfo
;
6505 PLIST_ENTRY ListHead
, ItemList
;
6509 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6510 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6514 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6515 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6518 if (!DriverInfoData
)
6520 *pDriverInfo
= NULL
;
6525 /* Search selected driver in list */
6526 ItemList
= ListHead
->Flink
;
6527 while (ItemList
!= ListHead
)
6529 if (DriverInfoData
->Reserved
!= 0)
6531 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6536 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6537 struct DriverInfoElement
*driverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6538 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6539 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6540 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6545 ItemList
= ItemList
->Flink
;
6547 if (ItemList
== ListHead
)
6548 SetLastError(ERROR_INVALID_PARAMETER
);
6551 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
6552 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6554 TRACE("Choosing driver whose rank is 0x%lx\n",
6555 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
6557 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6562 TRACE("Returning %d\n", ret
);
6566 /***********************************************************************
6567 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6570 SetupDiGetDriverInfoDetailA(
6571 IN HDEVINFO DeviceInfoSet
,
6572 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6573 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6574 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6575 IN DWORD DriverInfoDetailDataSize
,
6576 OUT PDWORD RequiredSize OPTIONAL
)
6578 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6579 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6581 DWORD HardwareIDLen
= 0;
6584 /* do some sanity checks, the unicode version might do more thorough checks */
6585 if (DriverInfoData
== NULL
||
6586 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6587 (DriverInfoDetailData
!= NULL
&&
6588 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6589 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6591 SetLastError(ERROR_INVALID_PARAMETER
);
6595 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6596 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6598 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6600 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6602 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6606 SetLastError(ERROR_INVALID_PARAMETER
);
6609 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6610 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6612 /* convert the strings to unicode */
6613 if (MultiByteToWideChar(CP_ACP
,
6615 DriverInfoData
->Description
,
6617 DriverInfoDataW
.Description
,
6619 MultiByteToWideChar(CP_ACP
,
6621 DriverInfoData
->MfgName
,
6623 DriverInfoDataW
.MfgName
,
6625 MultiByteToWideChar(CP_ACP
,
6627 DriverInfoData
->ProviderName
,
6629 DriverInfoDataW
.ProviderName
,
6632 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6634 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6635 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6638 if (DriverInfoDetailData
!= NULL
)
6640 /* calculate the unicode buffer size from the ansi buffer size */
6641 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6642 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6643 (HardwareIDLen
* sizeof(WCHAR
));
6645 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6646 if (DriverInfoDetailDataW
== NULL
)
6648 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6652 /* initialize the buffer */
6653 ZeroMemory(DriverInfoDetailDataW
,
6655 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6658 /* call the unicode version */
6659 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6662 DriverInfoDetailDataW
,
6668 if (DriverInfoDetailDataW
!= NULL
)
6670 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6671 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6672 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6673 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6674 if (WideCharToMultiByte(CP_ACP
,
6676 DriverInfoDetailDataW
->SectionName
,
6678 DriverInfoDetailData
->SectionName
,
6682 WideCharToMultiByte(CP_ACP
,
6684 DriverInfoDetailDataW
->InfFileName
,
6686 DriverInfoDetailData
->InfFileName
,
6690 WideCharToMultiByte(CP_ACP
,
6692 DriverInfoDetailDataW
->DrvDescription
,
6694 DriverInfoDetailData
->DrvDescription
,
6698 WideCharToMultiByte(CP_ACP
,
6700 DriverInfoDetailDataW
->HardwareID
,
6702 DriverInfoDetailData
->HardwareID
,
6708 DWORD hwidlen
= HardwareIDLen
;
6709 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6711 /* count the strings in the list */
6714 len
= lstrlenA(s
) + 1;
6723 /* looks like the string list wasn't terminated... */
6724 SetLastError(ERROR_INVALID_USER_BUFFER
);
6730 /* make sure CompatIDsOffset points to the second string in the
6734 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6735 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6736 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6740 DriverInfoDetailData
->CompatIDsOffset
= 0;
6741 DriverInfoDetailData
->CompatIDsLength
= 0;
6750 if (RequiredSize
!= NULL
)
6752 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6753 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6759 if (DriverInfoDetailDataW
!= NULL
)
6761 MyFree(DriverInfoDetailDataW
);
6767 /***********************************************************************
6768 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6771 SetupDiGetDriverInfoDetailW(
6772 IN HDEVINFO DeviceInfoSet
,
6773 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6774 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6775 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6776 IN DWORD DriverInfoDetailDataSize
,
6777 OUT PDWORD RequiredSize OPTIONAL
)
6781 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6782 DriverInfoData
, DriverInfoDetailData
,
6783 DriverInfoDetailDataSize
, RequiredSize
);
6786 SetLastError(ERROR_INVALID_PARAMETER
);
6787 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6788 SetLastError(ERROR_INVALID_HANDLE
);
6789 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6790 SetLastError(ERROR_INVALID_HANDLE
);
6791 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6792 SetLastError(ERROR_INVALID_USER_BUFFER
);
6793 else if (!DriverInfoData
)
6794 SetLastError(ERROR_INVALID_PARAMETER
);
6795 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6796 SetLastError(ERROR_INVALID_PARAMETER
);
6797 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6798 SetLastError(ERROR_INVALID_PARAMETER
);
6799 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6800 SetLastError(ERROR_INVALID_USER_BUFFER
);
6801 else if (DriverInfoData
->Reserved
== 0)
6802 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6805 struct DriverInfoElement
*driverInfoElement
;
6806 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6809 DriverInfoDetailData
,
6810 &driverInfoElement
->Details
,
6811 driverInfoElement
->Details
.cbSize
);
6812 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6813 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6818 TRACE("Returning %d\n", ret
);
6822 /* Return the current hardware profile id, or -1 if error */
6824 GetCurrentHwProfile(
6825 IN HDEVINFO DeviceInfoSet
)
6827 HKEY hKey
= INVALID_HANDLE_VALUE
;
6828 DWORD dwRegType
, dwLength
;
6831 DWORD ret
= (DWORD
)-1;
6834 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
6835 REGSTR_PATH_IDCONFIGDB
,
6839 if (rc
!= ERROR_SUCCESS
)
6845 dwLength
= sizeof(DWORD
);
6846 rc
= RegQueryValueExW(
6848 REGSTR_VAL_CURRENTCONFIG
,
6851 (LPBYTE
)&hwProfile
, &dwLength
);
6852 if (rc
!= ERROR_SUCCESS
)
6857 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6859 SetLastError(ERROR_GEN_FAILURE
);
6866 if (hKey
!= INVALID_HANDLE_VALUE
)
6874 IN HDEVINFO DeviceInfoSet
,
6875 IN PSP_DEVINFO_DATA DeviceInfoData
)
6877 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6878 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6881 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
6883 /* At the moment, I only know how to start local devices */
6884 SetLastError(ERROR_INVALID_COMPUTERNAME
);
6888 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
6889 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6890 SetLastError(RtlNtStatusToDosError(Status
));
6891 return NT_SUCCESS(Status
);
6894 static BOOL
StopDevice(
6895 IN HDEVINFO DeviceInfoSet
,
6896 IN PSP_DEVINFO_DATA DeviceInfoData
)
6898 FIXME("Stub %p %p\n", DeviceInfoSet
, DeviceInfoData
);
6902 /***********************************************************************
6903 * SetupDiChangeState (SETUPAPI.@)
6907 IN HDEVINFO DeviceInfoSet
,
6908 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6910 PSP_PROPCHANGE_PARAMS PropChange
;
6911 HKEY hKey
= INVALID_HANDLE_VALUE
;
6912 LPCWSTR RegistryValueName
;
6913 DWORD dwConfigFlags
, dwLength
, dwRegType
;
6917 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6919 if (!DeviceInfoData
)
6920 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
6922 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
6925 SetLastError(ERROR_INVALID_PARAMETER
);
6929 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
6930 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
6932 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
6934 switch (PropChange
->StateChange
)
6939 /* Enable/disable device in registry */
6940 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
6941 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6942 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
6943 if (hKey
== INVALID_HANDLE_VALUE
)
6945 dwLength
= sizeof(DWORD
);
6946 rc
= RegQueryValueExW(
6951 (LPBYTE
)&dwConfigFlags
, &dwLength
);
6952 if (rc
== ERROR_FILE_NOT_FOUND
)
6954 else if (rc
!= ERROR_SUCCESS
)
6959 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6961 SetLastError(ERROR_GEN_FAILURE
);
6964 if (PropChange
->StateChange
== DICS_ENABLE
)
6965 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6967 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6973 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
6974 if (rc
!= ERROR_SUCCESS
)
6980 /* Enable/disable device if needed */
6981 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
6982 || PropChange
->HwProfile
== 0
6983 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
6985 if (PropChange
->StateChange
== DICS_ENABLE
)
6986 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6988 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
6994 case DICS_PROPCHANGE
:
6996 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7001 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
7002 SetLastError(ERROR_NOT_SUPPORTED
);
7007 if (hKey
!= INVALID_HANDLE_VALUE
)
7010 TRACE("Returning %d\n", ret
);
7014 /***********************************************************************
7015 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
7018 SetupDiSelectBestCompatDrv(
7019 IN HDEVINFO DeviceInfoSet
,
7020 IN PSP_DEVINFO_DATA DeviceInfoData
)
7022 SP_DRVINFO_DATA_W drvInfoData
;
7025 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7027 /* Drivers are sorted by rank in the driver list, so
7028 * the first driver in the list is the best one.
7030 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
7031 ret
= SetupDiEnumDriverInfoW(
7035 0, /* Member index */
7040 ret
= SetupDiSetSelectedDriverW(
7046 TRACE("Returning %d\n", ret
);
7050 /***********************************************************************
7051 * SetupDiInstallDriverFiles (SETUPAPI.@)
7054 SetupDiInstallDriverFiles(
7055 IN HDEVINFO DeviceInfoSet
,
7056 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7060 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7063 SetLastError(ERROR_INVALID_PARAMETER
);
7064 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7065 SetLastError(ERROR_INVALID_HANDLE
);
7066 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7067 SetLastError(ERROR_INVALID_HANDLE
);
7068 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7069 SetLastError(ERROR_INVALID_USER_BUFFER
);
7070 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
7071 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7072 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
7073 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7076 SP_DEVINSTALL_PARAMS_W InstallParams
;
7077 struct DriverInfoElement
*SelectedDriver
;
7078 WCHAR SectionName
[MAX_PATH
];
7079 DWORD SectionNameLength
= 0;
7080 PVOID InstallMsgHandler
;
7081 PVOID InstallMsgHandlerContext
;
7082 PVOID Context
= NULL
;
7084 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7085 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7089 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7090 if (!SelectedDriver
)
7092 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7096 ret
= SetupDiGetActualSectionToInstallW(
7097 SelectedDriver
->InfFileDetails
->hInf
,
7098 SelectedDriver
->Details
.SectionName
,
7099 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
7103 if (InstallParams
.InstallMsgHandler
)
7105 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
7106 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
7110 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7113 InstallMsgHandler
= SetupDefaultQueueCallback
;
7114 InstallMsgHandlerContext
= Context
;
7116 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7117 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7118 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7119 InstallMsgHandler
, InstallMsgHandlerContext
,
7120 DeviceInfoSet
, DeviceInfoData
);
7124 /* Install files from .CoInstallers section */
7125 lstrcatW(SectionName
, DotCoInstallers
);
7126 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7127 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7128 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7129 InstallMsgHandler
, InstallMsgHandlerContext
,
7130 DeviceInfoSet
, DeviceInfoData
);
7134 /* Set the DI_NOFILECOPY flag to prevent another
7135 * installation during SetupDiInstallDevice */
7136 InstallParams
.Flags
|= DI_NOFILECOPY
;
7137 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7141 SetupTermDefaultQueueCallback(Context
);
7145 TRACE("Returning %d\n", ret
);
7149 /***********************************************************************
7150 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7153 SetupDiRegisterCoDeviceInstallers(
7154 IN HDEVINFO DeviceInfoSet
,
7155 IN PSP_DEVINFO_DATA DeviceInfoData
)
7157 BOOL ret
= FALSE
; /* Return value */
7159 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7162 SetLastError(ERROR_INVALID_PARAMETER
);
7163 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7164 SetLastError(ERROR_INVALID_HANDLE
);
7165 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7166 SetLastError(ERROR_INVALID_HANDLE
);
7167 else if (!DeviceInfoData
)
7168 SetLastError(ERROR_INVALID_PARAMETER
);
7169 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7170 SetLastError(ERROR_INVALID_USER_BUFFER
);
7173 SP_DEVINSTALL_PARAMS_W InstallParams
;
7174 struct DriverInfoElement
*SelectedDriver
;
7177 WCHAR SectionName
[MAX_PATH
];
7178 DWORD SectionNameLength
= 0;
7179 HKEY hKey
= INVALID_HANDLE_VALUE
;
7180 PVOID Context
= NULL
;
7182 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7183 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7187 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7188 if (SelectedDriver
== NULL
)
7190 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7194 /* Get .CoInstallers section name */
7195 Result
= SetupDiGetActualSectionToInstallW(
7196 SelectedDriver
->InfFileDetails
->hInf
,
7197 SelectedDriver
->Details
.SectionName
,
7198 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7199 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
7201 lstrcatW(SectionName
, DotCoInstallers
);
7203 /* Open/Create driver key information */
7204 #if _WIN32_WINNT >= 0x502
7205 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7207 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7209 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7210 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7211 if (hKey
== INVALID_HANDLE_VALUE
)
7214 /* Install .CoInstallers section */
7215 DoAction
= SPINST_REGISTRY
;
7216 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7218 DoAction
|= SPINST_FILES
;
7219 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7223 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7224 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7225 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7226 SetupDefaultQueueCallback
, Context
,
7227 DeviceInfoSet
, DeviceInfoData
);
7235 SetupTermDefaultQueueCallback(Context
);
7236 if (hKey
!= INVALID_HANDLE_VALUE
)
7240 TRACE("Returning %d\n", ret
);
7245 InstallOneInterface(
7246 IN LPGUID InterfaceGuid
,
7247 IN LPCWSTR ReferenceString
,
7248 IN LPCWSTR InterfaceSection
,
7249 IN UINT InterfaceFlags
)
7251 if (InterfaceFlags
!= 0)
7253 SetLastError(ERROR_INVALID_PARAMETER
);
7257 FIXME("Need to AddInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid
),
7258 debugstr_w(ReferenceString
), debugstr_w(InterfaceSection
), InterfaceFlags
);
7262 /***********************************************************************
7263 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7266 SetupDiInstallDeviceInterfaces(
7267 IN HDEVINFO DeviceInfoSet
,
7268 IN PSP_DEVINFO_DATA DeviceInfoData
)
7270 struct DeviceInfoSet
*list
= NULL
;
7273 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7276 SetLastError(ERROR_INVALID_PARAMETER
);
7277 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7278 SetLastError(ERROR_INVALID_HANDLE
);
7279 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7280 SetLastError(ERROR_INVALID_HANDLE
);
7281 else if (!DeviceInfoData
)
7282 SetLastError(ERROR_INVALID_PARAMETER
);
7283 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7284 SetLastError(ERROR_INVALID_USER_BUFFER
);
7287 struct DriverInfoElement
*SelectedDriver
;
7288 SP_DEVINSTALL_PARAMS_W InstallParams
;
7289 WCHAR SectionName
[MAX_PATH
];
7290 DWORD SectionNameLength
= 0;
7291 INFCONTEXT ContextInterface
;
7292 LPWSTR InterfaceGuidString
= NULL
;
7293 LPWSTR ReferenceString
= NULL
;
7294 LPWSTR InterfaceSection
= NULL
;
7299 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7300 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7304 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7305 if (SelectedDriver
== NULL
)
7307 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7312 /* Get .Interfaces section name */
7313 Result
= SetupDiGetActualSectionToInstallW(
7314 SelectedDriver
->InfFileDetails
->hInf
,
7315 SelectedDriver
->Details
.SectionName
,
7316 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7317 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".Interfaces") - 1)
7319 wcscat(SectionName
, L
".Interfaces");
7322 Result
= SetupFindFirstLineW(
7323 SelectedDriver
->InfFileDetails
->hInf
,
7327 while (ret
&& Result
)
7329 ret
= GetStringField(&ContextInterface
, 1, &InterfaceGuidString
);
7332 else if (strlenW(InterfaceGuidString
) != MAX_GUID_STRING_LEN
- 1)
7334 SetLastError(ERROR_INVALID_PARAMETER
);
7339 InterfaceGuidString
[MAX_GUID_STRING_LEN
- 2] = '\0'; /* Replace the } by a NULL character */
7340 if (UuidFromStringW(&InterfaceGuidString
[1], &InterfaceGuid
) != RPC_S_OK
)
7342 /* Bad GUID, skip the entry */
7343 SetLastError(ERROR_INVALID_PARAMETER
);
7348 ret
= GetStringField(&ContextInterface
, 2, &ReferenceString
);
7352 ret
= GetStringField(&ContextInterface
, 3, &InterfaceSection
);
7356 ret
= SetupGetIntField(
7358 4, /* Field index */
7362 if (GetLastError() == ERROR_INVALID_PARAMETER
)
7364 /* The field may be empty. Ignore the error */
7372 /* Install Interface */
7373 ret
= InstallOneInterface(&InterfaceGuid
, ReferenceString
, InterfaceSection
, InterfaceFlags
);
7376 MyFree(InterfaceGuidString
);
7377 MyFree(ReferenceString
);
7378 MyFree(InterfaceSection
);
7379 InterfaceGuidString
= ReferenceString
= InterfaceSection
= NULL
;
7380 Result
= SetupFindNextMatchLineW(&ContextInterface
, L
"AddInterface", &ContextInterface
);
7384 TRACE("Returning %d\n", ret
);
7389 InfIsFromOEMLocation(
7391 OUT LPBOOL IsOEMLocation
)
7395 last
= strrchrW(FullName
, '\\');
7398 /* No directory specified */
7399 *IsOEMLocation
= FALSE
;
7403 WCHAR Windir
[MAX_PATH
];
7406 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
7407 if (ret
== 0 || ret
>= MAX_PATH
)
7409 SetLastError(ERROR_GEN_FAILURE
);
7413 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
7415 /* The path is %SYSTEMROOT%\Inf */
7416 *IsOEMLocation
= FALSE
;
7420 /* The file is in another place */
7421 *IsOEMLocation
= TRUE
;
7427 /***********************************************************************
7428 * SetupDiInstallDevice (SETUPAPI.@)
7431 SetupDiInstallDevice(
7432 IN HDEVINFO DeviceInfoSet
,
7433 IN PSP_DEVINFO_DATA DeviceInfoData
)
7435 SP_DEVINSTALL_PARAMS_W InstallParams
;
7436 struct DriverInfoElement
*SelectedDriver
;
7437 SYSTEMTIME DriverDate
;
7438 WCHAR SectionName
[MAX_PATH
];
7440 DWORD SectionNameLength
= 0;
7441 BOOL Result
= FALSE
;
7444 LPWSTR pSectionName
= NULL
;
7445 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
7447 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
7448 BOOL RebootRequired
= FALSE
;
7449 HKEY hKey
= INVALID_HANDLE_VALUE
;
7450 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
7451 BOOL NeedtoCopyFile
;
7452 LARGE_INTEGER fullVersion
;
7454 PVOID Context
= NULL
;
7455 BOOL ret
= FALSE
; /* Return value */
7457 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7460 SetLastError(ERROR_INVALID_PARAMETER
);
7461 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7462 SetLastError(ERROR_INVALID_HANDLE
);
7463 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7464 SetLastError(ERROR_INVALID_HANDLE
);
7465 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7466 SetLastError(ERROR_INVALID_USER_BUFFER
);
7472 /* One parameter is bad */
7476 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7477 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7481 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
7483 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
7487 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7488 if (SelectedDriver
== NULL
)
7490 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7494 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
7496 Result
= SetupDiGetActualSectionToInstallW(
7497 SelectedDriver
->InfFileDetails
->hInf
,
7498 SelectedDriver
->Details
.SectionName
,
7499 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7500 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(DotServices
))
7502 pSectionName
= &SectionName
[wcslen(SectionName
)];
7504 /* Get information from [Version] section */
7505 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
7507 /* Format ClassGuid to a string */
7508 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
7510 RequiredSize
= lstrlenW(lpGuidString
);
7511 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
7512 if (!lpFullGuidString
)
7514 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7517 lpFullGuidString
[0] = '{';
7518 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
7519 lpFullGuidString
[RequiredSize
+ 1] = '}';
7520 lpFullGuidString
[RequiredSize
+ 2] = '\0';
7522 /* Open/Create driver key information */
7523 #if _WIN32_WINNT >= 0x502
7524 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7526 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7528 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7529 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7530 if (hKey
== INVALID_HANDLE_VALUE
)
7533 /* Install main section */
7535 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7536 DoAction
|= SPINST_REGISTRY
;
7537 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7539 DoAction
|= SPINST_FILES
;
7540 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7544 *pSectionName
= '\0';
7545 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7546 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7547 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7548 SetupDefaultQueueCallback
, Context
,
7549 DeviceInfoSet
, DeviceInfoData
);
7552 InstallParams
.Flags
|= DI_NOFILECOPY
;
7553 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7555 /* Write information to driver key */
7556 *pSectionName
= UNICODE_NULL
;
7557 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
7558 TRACE("Write information to driver key\n");
7559 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7560 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7561 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7562 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
7563 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
7564 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
7565 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
7566 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
7567 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7568 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7569 if (rc
== ERROR_SUCCESS
)
7570 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7571 if (rc
== ERROR_SUCCESS
)
7572 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7573 if (rc
== ERROR_SUCCESS
)
7575 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7576 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7578 if (rc
== ERROR_SUCCESS
)
7579 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7580 if (rc
== ERROR_SUCCESS
)
7581 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7582 if (rc
== ERROR_SUCCESS
)
7583 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
));
7584 if (rc
== ERROR_SUCCESS
)
7585 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7586 if (rc
== ERROR_SUCCESS
)
7587 rc
= RegSetValueEx(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7588 if (rc
!= ERROR_SUCCESS
)
7594 hKey
= INVALID_HANDLE_VALUE
;
7596 /* FIXME: Process .LogConfigOverride section */
7598 /* Install .Services section */
7599 wcscpy(pSectionName
, DotServices
);
7600 Result
= SetupInstallServicesFromInfSectionExW(
7601 SelectedDriver
->InfFileDetails
->hInf
,
7610 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
7611 RebootRequired
= TRUE
;
7613 /* Copy .inf file to Inf\ directory (if needed) */
7614 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7619 Result
= SetupCopyOEMInfW(
7620 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7623 SP_COPY_NOOVERWRITE
,
7629 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7630 * to release use of current InfFile */
7633 /* Open device registry key */
7634 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7635 if (hKey
== INVALID_HANDLE_VALUE
)
7638 /* Install .HW section */
7640 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7641 DoAction
|= SPINST_REGISTRY
;
7642 wcscpy(pSectionName
, L
".HW");
7643 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7644 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7645 DoAction
, hKey
, NULL
, 0,
7647 DeviceInfoSet
, DeviceInfoData
);
7651 /* Write information to enum key */
7652 TRACE("Write information to enum key\n");
7653 TRACE("Class : '%S'\n", ClassName
);
7654 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
7655 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7656 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
7657 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
7658 if (rc
== ERROR_SUCCESS
)
7659 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7660 if (rc
== ERROR_SUCCESS
)
7661 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7662 if (rc
== ERROR_SUCCESS
)
7663 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7664 if (rc
!= ERROR_SUCCESS
)
7670 /* Start the device */
7671 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7672 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7677 /* End of installation */
7678 if (hClassKey
!= INVALID_HANDLE_VALUE
)
7679 RegCloseKey(hClassKey
);
7680 if (hKey
!= INVALID_HANDLE_VALUE
)
7683 RpcStringFreeW(&lpGuidString
);
7684 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7686 SetupTermDefaultQueueCallback(Context
);
7687 TRACE("Returning %d\n", ret
);