2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005 Hervé Poussineau (hpoussin@reactos.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "setupapi_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
27 /* Unicode constants */
28 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class
[] = {'C','l','a','s','s',0};
30 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
31 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
32 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
33 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
34 static const WCHAR InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
35 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
36 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
38 /* FIXME: header mess */
39 DEFINE_GUID(GUID_NULL
,
40 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
42 (CALLBACK
* CLASS_INSTALL_PROC
) (
43 IN DI_FUNCTION InstallFunction
,
44 IN HDEVINFO DeviceInfoSet
,
45 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
47 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
48 IN HDEVINFO DeviceInfoSet
,
49 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
51 (CALLBACK
* COINSTALLER_PROC
) (
52 IN DI_FUNCTION InstallFunction
,
53 IN HDEVINFO DeviceInfoSet
,
54 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
55 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
57 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
58 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
59 IN LPFNADDPROPSHEETPAGE fAddFunc
,
62 (*UPDATE_CLASS_PARAM_HANDLER
) (
63 IN HDEVINFO DeviceInfoSet
,
64 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
65 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
66 IN DWORD ClassInstallParamsSize
);
68 struct CoInstallerElement
73 COINSTALLER_PROC Function
;
74 BOOL DoPostProcessing
;
79 PropertyChangeHandler(
80 IN HDEVINFO DeviceInfoSet
,
81 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
82 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
83 IN DWORD ClassInstallParamsSize
);
85 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
86 NULL
, /* DIF_SELECTDEVICE */
87 NULL
, /* DIF_INSTALLDEVICE */
88 NULL
, /* DIF_ASSIGNRESOURCES */
89 NULL
, /* DIF_PROPERTIES */
90 NULL
, /* DIF_REMOVE */
91 NULL
, /* DIF_FIRSTTIMESETUP */
92 NULL
, /* DIF_FOUNDDEVICE */
93 NULL
, /* DIF_SELECTCLASSDRIVERS */
94 NULL
, /* DIF_VALIDATECLASSDRIVERS */
95 NULL
, /* DIF_INSTALLCLASSDRIVERS */
96 NULL
, /* DIF_CALCDISKSPACE */
97 NULL
, /* DIF_DESTROYPRIVATEDATA */
98 NULL
, /* DIF_VALIDATEDRIVER */
99 NULL
, /* DIF_MOVEDEVICE */
100 NULL
, /* DIF_DETECT */
101 NULL
, /* DIF_INSTALLWIZARD */
102 NULL
, /* DIF_DESTROYWIZARDDATA */
103 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
104 NULL
, /* DIF_ENABLECLASS */
105 NULL
, /* DIF_DETECTVERIFY */
106 NULL
, /* DIF_INSTALLDEVICEFILES */
107 NULL
, /* DIF_UNREMOVE */
108 NULL
, /* DIF_SELECTBESTCOMPATDRV */
109 NULL
, /* DIF_ALLOW_INSTALL */
110 NULL
, /* DIF_REGISTERDEVICE */
111 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
112 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
113 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
114 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
115 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
116 NULL
, /* DIF_UNUSED1 */
117 NULL
, /* DIF_INSTALLINTERFACES */
118 NULL
, /* DIF_DETECTCANCEL */
119 NULL
, /* DIF_REGISTER_COINSTALLERS */
120 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
121 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
122 NULL
, /* DIF_RESERVED1 */
123 NULL
, /* DIF_TROUBLESHOOTER */
124 NULL
, /* DIF_POWERMESSAGEWAKE */
125 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
126 NULL
, /* DIF_UPDATEDRIVER_UI */
127 NULL
/* DIF_RESERVED2 */
130 /***********************************************************************
131 * SetupDiBuildClassInfoList (SETUPAPI.@)
133 BOOL WINAPI
SetupDiBuildClassInfoList(
135 LPGUID ClassGuidList
,
136 DWORD ClassGuidListSize
,
140 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
141 ClassGuidListSize
, RequiredSize
,
145 /***********************************************************************
146 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
148 BOOL WINAPI
SetupDiBuildClassInfoListExA(
150 LPGUID ClassGuidList
,
151 DWORD ClassGuidListSize
,
156 LPWSTR MachineNameW
= NULL
;
163 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
164 if (MachineNameW
== NULL
) return FALSE
;
167 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
168 ClassGuidListSize
, RequiredSize
,
169 MachineNameW
, Reserved
);
172 MyFree(MachineNameW
);
177 /***********************************************************************
178 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
180 BOOL WINAPI
SetupDiBuildClassInfoListExW(
182 LPGUID ClassGuidList
,
183 DWORD ClassGuidListSize
,
188 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
194 DWORD dwGuidListIndex
= 0;
196 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
197 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
199 if (RequiredSize
!= NULL
)
202 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
203 KEY_ENUMERATE_SUB_KEYS
,
207 if (hClassesKey
== INVALID_HANDLE_VALUE
)
212 for (dwIndex
= 0; ; dwIndex
++)
214 dwLength
= MAX_GUID_STRING_LEN
+ 1;
215 lError
= RegEnumKeyExW(hClassesKey
,
223 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
224 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
226 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
228 if (RegOpenKeyExW(hClassesKey
,
234 RegCloseKey(hClassesKey
);
238 if (!RegQueryValueExW(hClassKey
,
239 REGSTR_VAL_NOUSECLASS
,
245 TRACE("'NoUseClass' value found!\n");
246 RegCloseKey(hClassKey
);
250 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
251 (!RegQueryValueExW(hClassKey
,
252 REGSTR_VAL_NOINSTALLCLASS
,
258 TRACE("'NoInstallClass' value found!\n");
259 RegCloseKey(hClassKey
);
263 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
264 (!RegQueryValueExW(hClassKey
,
265 REGSTR_VAL_NODISPLAYCLASS
,
271 TRACE("'NoDisplayClass' value found!\n");
272 RegCloseKey(hClassKey
);
276 RegCloseKey(hClassKey
);
278 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
279 if (dwGuidListIndex
< ClassGuidListSize
)
281 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
285 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
287 UuidFromStringW(&szKeyName
[1],
288 &ClassGuidList
[dwGuidListIndex
]);
294 if (lError
!= ERROR_SUCCESS
)
298 RegCloseKey(hClassesKey
);
300 if (RequiredSize
!= NULL
)
301 *RequiredSize
= dwGuidListIndex
;
303 if (ClassGuidListSize
< dwGuidListIndex
)
305 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
312 /***********************************************************************
313 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
315 BOOL WINAPI
SetupDiClassGuidsFromNameA(
317 LPGUID ClassGuidList
,
318 DWORD ClassGuidListSize
,
321 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
322 ClassGuidListSize
, RequiredSize
,
326 /***********************************************************************
327 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
329 BOOL WINAPI
SetupDiClassGuidsFromNameW(
331 LPGUID ClassGuidList
,
332 DWORD ClassGuidListSize
,
335 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
336 ClassGuidListSize
, RequiredSize
,
340 /***********************************************************************
341 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
343 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
345 LPGUID ClassGuidList
,
346 DWORD ClassGuidListSize
,
351 LPWSTR ClassNameW
= NULL
;
352 LPWSTR MachineNameW
= NULL
;
357 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
358 if (ClassNameW
== NULL
)
363 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
364 if (MachineNameW
== NULL
)
371 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
372 ClassGuidListSize
, RequiredSize
,
373 MachineNameW
, Reserved
);
376 MyFree(MachineNameW
);
383 /***********************************************************************
384 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
386 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
388 LPGUID ClassGuidList
,
389 DWORD ClassGuidListSize
,
394 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
395 WCHAR szClassName
[256];
401 DWORD dwGuidListIndex
= 0;
403 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
404 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
406 if (RequiredSize
!= NULL
)
409 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
410 KEY_ENUMERATE_SUB_KEYS
,
414 if (hClassesKey
== INVALID_HANDLE_VALUE
)
419 for (dwIndex
= 0; ; dwIndex
++)
421 dwLength
= MAX_GUID_STRING_LEN
+ 1;
422 lError
= RegEnumKeyExW(hClassesKey
,
430 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
431 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
433 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
435 if (RegOpenKeyExW(hClassesKey
,
441 RegCloseKey(hClassesKey
);
445 dwLength
= 256 * sizeof(WCHAR
);
446 if (!RegQueryValueExW(hClassKey
,
453 TRACE("Class name: %s\n", debugstr_w(szClassName
));
455 if (strcmpiW(szClassName
, ClassName
) == 0)
457 TRACE("Found matching class name\n");
459 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
460 if (dwGuidListIndex
< ClassGuidListSize
)
462 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
466 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
468 UuidFromStringW(&szKeyName
[1],
469 &ClassGuidList
[dwGuidListIndex
]);
476 RegCloseKey(hClassKey
);
479 if (lError
!= ERROR_SUCCESS
)
483 RegCloseKey(hClassesKey
);
485 if (RequiredSize
!= NULL
)
486 *RequiredSize
= dwGuidListIndex
;
488 if (ClassGuidListSize
< dwGuidListIndex
)
490 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
497 /***********************************************************************
498 * SetupDiClassNameFromGuidA (SETUPAPI.@)
500 BOOL WINAPI
SetupDiClassNameFromGuidA(
501 const GUID
* ClassGuid
,
506 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
507 ClassNameSize
, RequiredSize
,
511 /***********************************************************************
512 * SetupDiClassNameFromGuidW (SETUPAPI.@)
514 BOOL WINAPI
SetupDiClassNameFromGuidW(
515 const GUID
* ClassGuid
,
520 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
521 ClassNameSize
, RequiredSize
,
525 /***********************************************************************
526 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
528 BOOL WINAPI
SetupDiClassNameFromGuidExA(
529 const GUID
* ClassGuid
,
536 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
537 LPWSTR MachineNameW
= NULL
;
541 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
542 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
543 NULL
, MachineNameW
, Reserved
);
546 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
547 ClassNameSize
, NULL
, NULL
);
549 if (!ClassNameSize
&& RequiredSize
)
552 MyFree(MachineNameW
);
556 /***********************************************************************
557 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
559 BOOL WINAPI
SetupDiClassNameFromGuidExW(
560 const GUID
* ClassGuid
,
571 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
572 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
574 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
579 if (hKey
== INVALID_HANDLE_VALUE
)
584 if (RequiredSize
!= NULL
)
587 rc
= RegQueryValueExW(hKey
,
593 if (rc
!= ERROR_SUCCESS
)
600 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
603 dwLength
= ClassNameSize
* sizeof(WCHAR
);
604 rc
= RegQueryValueExW(hKey
,
610 if (rc
!= ERROR_SUCCESS
)
622 /***********************************************************************
623 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
626 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
629 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
632 /***********************************************************************
633 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
636 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
641 LPWSTR MachineNameW
= NULL
;
644 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
645 debugstr_a(MachineName
), Reserved
);
649 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
650 if (MachineNameW
== NULL
)
651 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
654 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
655 MachineNameW
, Reserved
);
658 MyFree(MachineNameW
);
664 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
668 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
669 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
670 case CR_SUCCESS
: return ERROR_SUCCESS
;
673 return ERROR_GEN_FAILURE
;
676 /* Does not happen */
679 /***********************************************************************
680 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
683 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
688 struct DeviceInfoSet
*list
;
689 LPWSTR UNCServerName
= NULL
;
693 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
695 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
696 debugstr_w(MachineName
), Reserved
);
698 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
700 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
701 list
= HeapAlloc(GetProcessHeap(), 0, size
);
704 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
707 memset(list
, 0, sizeof(struct DeviceInfoSet
));
709 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
712 ClassGuid
? ClassGuid
: &GUID_NULL
,
713 sizeof(list
->ClassGuid
));
714 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
715 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
716 list
->InstallParams
.hwndParent
= hwndParent
;
719 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
720 if (rc
!= ERROR_SUCCESS
)
725 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
728 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
732 strcpyW(UNCServerName
+ 2, MachineName
);
733 list
->szData
[0] = list
->szData
[1] = '\\';
734 strcpyW(list
->szData
+ 2, MachineName
);
735 list
->MachineName
= list
->szData
;
739 DWORD Size
= MAX_PATH
;
740 list
->HKLM
= HKEY_LOCAL_MACHINE
;
741 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
744 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
747 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
749 list
->MachineName
= NULL
;
752 UNCServerName
[0] = UNCServerName
[1] = '\\';
753 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
754 if (cr
!= CR_SUCCESS
)
756 SetLastError(GetErrorCodeFromCrCode(cr
));
760 InitializeListHead(&list
->DriverListHead
);
761 InitializeListHead(&list
->ListHead
);
763 ret
= (HDEVINFO
)list
;
766 if (ret
== INVALID_HANDLE_VALUE
)
768 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
769 RegCloseKey(list
->HKLM
);
770 HeapFree(GetProcessHeap(), 0, list
);
772 HeapFree(GetProcessHeap(), 0, UNCServerName
);
776 /***********************************************************************
777 * SetupDiEnumDeviceInfo (SETUPAPI.@)
779 BOOL WINAPI
SetupDiEnumDeviceInfo(
780 HDEVINFO DeviceInfoSet
,
782 PSP_DEVINFO_DATA DeviceInfoData
)
786 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
788 SetLastError(ERROR_INVALID_PARAMETER
);
789 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
791 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
793 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
794 SetLastError(ERROR_INVALID_HANDLE
);
795 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
796 SetLastError(ERROR_INVALID_USER_BUFFER
);
799 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
800 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
801 ItemList
= ItemList
->Flink
;
802 if (ItemList
== &list
->ListHead
)
803 SetLastError(ERROR_NO_MORE_ITEMS
);
806 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
807 memcpy(&DeviceInfoData
->ClassGuid
,
810 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
811 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
817 SetLastError(ERROR_INVALID_HANDLE
);
821 /***********************************************************************
822 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
825 SetupDiGetActualSectionToInstallA(
827 IN PCSTR InfSectionName
,
828 OUT PSTR InfSectionWithExt OPTIONAL
,
829 IN DWORD InfSectionWithExtSize
,
830 OUT PDWORD RequiredSize OPTIONAL
,
831 OUT PSTR
*Extension OPTIONAL
)
833 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
834 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
838 /***********************************************************************
839 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
842 SetupDiGetActualSectionToInstallW(
844 IN PCWSTR InfSectionName
,
845 OUT PWSTR InfSectionWithExt OPTIONAL
,
846 IN DWORD InfSectionWithExtSize
,
847 OUT PDWORD RequiredSize OPTIONAL
,
848 OUT PWSTR
*Extension OPTIONAL
)
850 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
851 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
855 /***********************************************************************
856 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
859 SetupDiGetActualSectionToInstallExA(
861 IN PCSTR InfSectionName
,
862 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
863 OUT PSTR InfSectionWithExt OPTIONAL
,
864 IN DWORD InfSectionWithExtSize
,
865 OUT PDWORD RequiredSize OPTIONAL
,
866 OUT PSTR
* Extension OPTIONAL
,
869 LPWSTR InfSectionNameW
= NULL
;
870 LPWSTR InfSectionWithExtW
= NULL
;
872 BOOL bResult
= FALSE
;
878 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
879 if (InfSectionNameW
== NULL
)
882 if (InfSectionWithExt
)
884 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
885 if (InfSectionWithExtW
== NULL
)
889 bResult
= SetupDiGetActualSectionToInstallExW(
890 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
891 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
892 InfSectionWithExtSize
,
894 Extension
? &ExtensionW
: NULL
,
897 if (bResult
&& InfSectionWithExt
)
899 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
900 InfSectionWithExtSize
, NULL
, NULL
) != 0;
902 if (bResult
&& Extension
)
904 if (ExtensionW
== NULL
)
907 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
911 MyFree(InfSectionNameW
);
912 MyFree(InfSectionWithExtW
);
917 /***********************************************************************
918 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
921 SetupDiGetActualSectionToInstallExW(
923 IN PCWSTR InfSectionName
,
924 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
925 OUT PWSTR InfSectionWithExt OPTIONAL
,
926 IN DWORD InfSectionWithExtSize
,
927 OUT PDWORD RequiredSize OPTIONAL
,
928 OUT PWSTR
* Extension OPTIONAL
,
933 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
934 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
935 RequiredSize
, Extension
, Reserved
);
937 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
938 SetLastError(ERROR_INVALID_HANDLE
);
939 else if (!InfSectionName
)
940 SetLastError(ERROR_INVALID_PARAMETER
);
941 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
942 SetLastError(ERROR_INVALID_USER_BUFFER
);
943 else if (Reserved
!= NULL
)
944 SetLastError(ERROR_INVALID_PARAMETER
);
947 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
948 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
949 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
950 WCHAR SectionName
[LINE_LEN
+ 1];
951 LONG lLineCount
= -1;
954 /* Fill platform info if needed */
955 if (AlternatePlatformInfo
)
956 pPlatformInfo
= AlternatePlatformInfo
;
957 else if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
959 /* That's the first time we go here. We need to fill in the structure */
960 OSVERSIONINFO VersionInfo
;
961 SYSTEM_INFO SystemInfo
;
962 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
963 ret
= GetVersionEx(&VersionInfo
);
966 GetSystemInfo(&SystemInfo
);
967 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
968 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
969 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
970 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
971 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
972 CurrentPlatform
.Reserved
= 0;
975 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
976 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
977 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
979 static const WCHAR ExtensionArchitectureNone
[] = {0};
980 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
981 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
982 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
984 /* Set various extensions values */
985 switch (pPlatformInfo
->Platform
)
987 case VER_PLATFORM_WIN32_WINDOWS
:
988 pExtensionPlatform
= ExtensionPlatformWindows
;
990 case VER_PLATFORM_WIN32_NT
:
991 pExtensionPlatform
= ExtensionPlatformNT
;
994 pExtensionPlatform
= ExtensionPlatformNone
;
997 switch (pPlatformInfo
->ProcessorArchitecture
)
999 case PROCESSOR_ARCHITECTURE_AMD64
:
1000 pExtensionArchitecture
= ExtensionArchitectureamd64
;
1002 case PROCESSOR_ARCHITECTURE_INTEL
:
1003 pExtensionArchitecture
= ExtensionArchitecturex86
;
1005 case PROCESSOR_ARCHITECTURE_PPC
:
1006 pExtensionArchitecture
= ExtensionArchitectureppc
;
1009 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo
->ProcessorArchitecture
);
1010 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
1011 pExtensionArchitecture
= ExtensionArchitectureNone
;
1015 SectionName
[LINE_LEN
] = UNICODE_NULL
;
1017 /* Test with platform.architecture.major.minor extension */
1018 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s.%lu.%lu", InfSectionName
,
1019 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1020 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1021 if (lLineCount
!= -1) goto sectionfound
;
1023 /* Test with platform.major.minor extension */
1024 snprintfW(SectionName
, LINE_LEN
, L
"%s%s.%lu.%lu", InfSectionName
,
1025 pExtensionPlatform
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1026 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1027 if (lLineCount
!= -1) goto sectionfound
;
1029 /* Test with platform.architecture.major extension */
1030 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s.%lu", InfSectionName
,
1031 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
);
1032 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1033 if (lLineCount
!= -1) goto sectionfound
;
1035 /* Test with platform.major extension */
1036 snprintfW(SectionName
, LINE_LEN
, L
"%s%s.%lu", InfSectionName
,
1037 pExtensionPlatform
, pPlatformInfo
->MajorVersion
);
1038 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1039 if (lLineCount
!= -1) goto sectionfound
;
1041 /* Test with platform.architecture extension */
1042 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s", InfSectionName
,
1043 pExtensionPlatform
, pExtensionArchitecture
);
1044 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1045 if (lLineCount
!= -1) goto sectionfound
;
1047 /* Test with platform extension */
1048 snprintfW(SectionName
, LINE_LEN
, L
"%s%s", InfSectionName
,
1049 pExtensionPlatform
);
1050 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1051 if (lLineCount
!= -1) goto sectionfound
;
1053 /* Test without extension */
1054 snprintfW(SectionName
, LINE_LEN
, L
"%s", InfSectionName
);
1055 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1056 if (lLineCount
!= -1) goto sectionfound
;
1058 /* No appropriate section found */
1059 SetLastError(ERROR_INVALID_PARAMETER
);
1063 dwFullLength
= lstrlenW(SectionName
);
1064 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
1066 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
1068 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1072 lstrcpyW(InfSectionWithExt
, SectionName
);
1073 if (Extension
!= NULL
)
1075 DWORD dwLength
= lstrlenW(SectionName
);
1076 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1080 if (RequiredSize
!= NULL
)
1081 *RequiredSize
= dwFullLength
+ 1;
1087 TRACE("Returning %d\n", ret
);
1092 /***********************************************************************
1093 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1095 BOOL WINAPI
SetupDiGetClassDescriptionA(
1096 const GUID
* ClassGuid
,
1097 PSTR ClassDescription
,
1098 DWORD ClassDescriptionSize
,
1099 PDWORD RequiredSize
)
1101 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1102 ClassDescriptionSize
,
1103 RequiredSize
, NULL
, NULL
);
1106 /***********************************************************************
1107 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1109 BOOL WINAPI
SetupDiGetClassDescriptionW(
1110 const GUID
* ClassGuid
,
1111 PWSTR ClassDescription
,
1112 DWORD ClassDescriptionSize
,
1113 PDWORD RequiredSize
)
1115 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1116 ClassDescriptionSize
,
1117 RequiredSize
, NULL
, NULL
);
1120 /***********************************************************************
1121 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1123 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1124 const GUID
* ClassGuid
,
1125 PSTR ClassDescription
,
1126 DWORD ClassDescriptionSize
,
1127 PDWORD RequiredSize
,
1131 PWCHAR ClassDescriptionW
;
1132 LPWSTR MachineNameW
= NULL
;
1136 if (ClassDescriptionSize
> 0)
1138 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1139 if (!ClassDescriptionW
)
1141 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1147 ClassDescriptionW
= NULL
;
1151 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1154 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1160 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1161 NULL
, MachineNameW
, Reserved
);
1164 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1165 ClassDescriptionSize
, NULL
, NULL
);
1167 if (!ClassDescriptionSize
&& RequiredSize
)
1168 *RequiredSize
= len
;
1172 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1173 MyFree(MachineNameW
);
1177 /***********************************************************************
1178 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1180 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1181 const GUID
* ClassGuid
,
1182 PWSTR ClassDescription
,
1183 DWORD ClassDescriptionSize
,
1184 PDWORD RequiredSize
,
1191 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1192 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1194 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1199 if (hKey
== INVALID_HANDLE_VALUE
)
1201 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1205 if (RequiredSize
!= NULL
)
1208 if (RegQueryValueExW(hKey
,
1219 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1222 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1223 if (RegQueryValueExW(hKey
,
1227 (LPBYTE
)ClassDescription
,
1239 /***********************************************************************
1240 * SetupDiGetClassDevsA (SETUPAPI.@)
1242 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1248 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1249 flags
, NULL
, NULL
, NULL
);
1252 /***********************************************************************
1253 * SetupDiGetClassDevsW (SETUPAPI.@)
1255 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1261 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1262 flags
, NULL
, NULL
, NULL
);
1265 /***********************************************************************
1266 * SetupDiGetClassDevsExA (SETUPAPI.@)
1268 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1278 LPWSTR enumstrW
= NULL
;
1279 LPWSTR machineW
= NULL
;
1283 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1284 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1287 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1290 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1294 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1295 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1298 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1301 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1303 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1306 HeapFree(GetProcessHeap(), 0, enumstrW
);
1307 HeapFree(GetProcessHeap(), 0, machineW
);
1312 CreateDeviceInfoElement(
1313 IN
struct DeviceInfoSet
*list
,
1314 IN LPCWSTR InstancePath
,
1315 IN LPCGUID pClassGuid
,
1316 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1320 struct DeviceInfoElement
*deviceInfo
;
1322 *pDeviceInfo
= NULL
;
1324 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1325 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1328 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1331 memset(deviceInfo
, 0, size
);
1333 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1334 if (cr
!= CR_SUCCESS
)
1336 SetLastError(GetErrorCodeFromCrCode(cr
));
1340 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1341 wcscpy(deviceInfo
->Data
, InstancePath
);
1342 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1343 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1344 deviceInfo
->DeviceDescription
= NULL
;
1345 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1346 deviceInfo
->CreationFlags
= 0;
1347 InitializeListHead(&deviceInfo
->DriverListHead
);
1348 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1350 *pDeviceInfo
= deviceInfo
;
1355 CreateDeviceInterface(
1356 IN
struct DeviceInfoElement
* deviceInfo
,
1357 IN LPCWSTR SymbolicLink
,
1358 IN LPCGUID pInterfaceGuid
,
1359 OUT
struct DeviceInterface
**pDeviceInterface
)
1361 struct DeviceInterface
*deviceInterface
;
1363 *pDeviceInterface
= NULL
;
1365 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1366 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1367 if (!deviceInterface
)
1369 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1372 deviceInterface
->DeviceInfo
= deviceInfo
;
1373 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1374 deviceInterface
->Flags
= 0; /* FIXME */
1375 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1377 *pDeviceInterface
= deviceInterface
;
1381 static LONG
SETUP_CreateDevListFromEnumerator(
1382 struct DeviceInfoSet
*list
,
1383 LPCGUID pClassGuid OPTIONAL
,
1385 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1387 HKEY hDeviceIdKey
, hInstanceIdKey
;
1388 WCHAR KeyBuffer
[MAX_PATH
];
1389 WCHAR InstancePath
[MAX_PATH
];
1390 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1391 struct DeviceInfoElement
*deviceInfo
;
1393 DWORD dwLength
, dwRegType
;
1396 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1399 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1400 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1401 if (rc
== ERROR_NO_MORE_ITEMS
)
1403 if (rc
!= ERROR_SUCCESS
)
1407 /* Open device id sub key */
1408 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1409 if (rc
!= ERROR_SUCCESS
)
1411 wcscpy(InstancePath
, Enumerator
);
1412 wcscat(InstancePath
, L
"\\");
1413 wcscat(InstancePath
, KeyBuffer
);
1414 wcscat(InstancePath
, L
"\\");
1415 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1417 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1423 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1424 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1425 if (rc
== ERROR_NO_MORE_ITEMS
)
1427 if (rc
!= ERROR_SUCCESS
)
1429 RegCloseKey(hDeviceIdKey
);
1434 /* Open instance id sub key */
1435 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1436 if (rc
!= ERROR_SUCCESS
)
1438 RegCloseKey(hDeviceIdKey
);
1441 *pEndOfInstancePath
= '\0';
1442 wcscat(InstancePath
, KeyBuffer
);
1444 /* Read ClassGUID value */
1445 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1446 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1447 RegCloseKey(hInstanceIdKey
);
1448 if (rc
== ERROR_FILE_NOT_FOUND
)
1451 /* Skip this bad entry as we can't verify it */
1453 /* Set a default GUID for this device */
1454 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1456 else if (rc
!= ERROR_SUCCESS
)
1458 RegCloseKey(hDeviceIdKey
);
1461 else if (dwRegType
!= REG_SZ
)
1463 RegCloseKey(hDeviceIdKey
);
1464 return ERROR_GEN_FAILURE
;
1468 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1469 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1470 /* Bad GUID, skip the entry */
1474 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1476 /* Skip this entry as it is not the right device class */
1480 /* Add the entry to the list */
1481 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1483 RegCloseKey(hDeviceIdKey
);
1484 return GetLastError();
1486 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1487 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1489 RegCloseKey(hDeviceIdKey
);
1492 return ERROR_SUCCESS
;
1495 static LONG
SETUP_CreateDevList(
1496 struct DeviceInfoSet
*list
,
1497 PCWSTR MachineName OPTIONAL
,
1498 LPGUID
class OPTIONAL
,
1499 PCWSTR Enumerator OPTIONAL
)
1501 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1502 WCHAR KeyBuffer
[MAX_PATH
];
1507 if (class && IsEqualIID(class, &GUID_NULL
))
1511 if (MachineName
!= NULL
)
1513 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1514 if (rc
!= ERROR_SUCCESS
)
1518 HKLM
= HKEY_LOCAL_MACHINE
;
1520 rc
= RegOpenKeyExW(HKLM
,
1521 REGSTR_PATH_SYSTEMENUM
,
1523 KEY_ENUMERATE_SUB_KEYS
,
1525 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1526 if (rc
!= ERROR_SUCCESS
)
1529 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1530 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1539 KEY_ENUMERATE_SUB_KEYS
,
1541 RegCloseKey(hEnumKey
);
1542 if (rc
!= ERROR_SUCCESS
)
1544 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1545 RegCloseKey(hEnumeratorKey
);
1550 /* Enumerate enumerators */
1554 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1555 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1556 if (rc
== ERROR_NO_MORE_ITEMS
)
1558 if (rc
!= ERROR_SUCCESS
)
1560 RegCloseKey(hEnumKey
);
1566 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1567 if (rc
!= ERROR_SUCCESS
)
1569 RegCloseKey(hEnumKey
);
1573 /* Call SETUP_CreateDevListFromEnumerator */
1574 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1575 RegCloseKey(hEnumeratorKey
);
1576 if (rc
!= ERROR_SUCCESS
)
1578 RegCloseKey(hEnumKey
);
1582 RegCloseKey(hEnumKey
);
1583 return ERROR_SUCCESS
;
1588 static LONG
SETUP_CreateSerialDeviceList(
1589 struct DeviceInfoSet
*list
,
1591 LPGUID InterfaceGuid
,
1592 PCWSTR DeviceInstanceW
)
1594 static const size_t initialSize
= 100;
1596 WCHAR buf
[initialSize
];
1598 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1600 struct DeviceInfoElement
*deviceInfo
;
1603 WARN("'MachineName' is ignored on Wine!\n");
1604 if (DeviceInstanceW
)
1605 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1611 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1613 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1617 HeapFree(GetProcessHeap(), 0, devices
);
1618 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1620 return ERROR_NOT_ENOUGH_MEMORY
;
1626 HeapFree(GetProcessHeap(), 0, devices
);
1627 return GetLastError();
1631 /* 'devices' is a MULTI_SZ string */
1632 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1634 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1636 /* We have found a device */
1637 struct DeviceInterface
*interfaceInfo
;
1638 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1639 /* Step 1. Create a device info element */
1640 if (!CreateDeviceInfoElement(list
, ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1643 HeapFree(GetProcessHeap(), 0, devices
);
1644 return GetLastError();
1646 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1648 /* Step 2. Create an interface list for this element */
1649 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1652 HeapFree(GetProcessHeap(), 0, devices
);
1653 return GetLastError();
1655 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1659 HeapFree(GetProcessHeap(), 0, devices
);
1660 return ERROR_SUCCESS
;
1663 #else /* __REACTOS__ */
1665 static LONG
SETUP_CreateInterfaceList(
1666 struct DeviceInfoSet
*list
,
1668 LPGUID InterfaceGuid
,
1669 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1671 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1672 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1673 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1674 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1675 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1677 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1680 DWORD dwLength
, dwInstancePathLength
;
1683 struct DeviceInfoElement
*deviceInfo
;
1685 /* Open registry key related to this interface */
1686 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1687 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1688 return GetLastError();
1690 /* Enumerate sub keys of hInterfaceKey */
1694 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1695 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1696 if (rc
== ERROR_NO_MORE_ITEMS
)
1698 if (rc
!= ERROR_SUCCESS
)
1700 RegCloseKey(hInterfaceKey
);
1706 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1707 if (rc
!= ERROR_SUCCESS
)
1709 RegCloseKey(hInterfaceKey
);
1713 /* Read DeviceInstance */
1714 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1715 if (rc
!= ERROR_SUCCESS
)
1717 RegCloseKey(hDeviceInstanceKey
);
1718 RegCloseKey(hInterfaceKey
);
1721 if (dwRegType
!= REG_SZ
)
1723 RegCloseKey(hDeviceInstanceKey
);
1724 RegCloseKey(hInterfaceKey
);
1725 return ERROR_GEN_FAILURE
;
1727 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1730 RegCloseKey(hDeviceInstanceKey
);
1731 RegCloseKey(hInterfaceKey
);
1732 return ERROR_NOT_ENOUGH_MEMORY
;
1734 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1735 if (rc
!= ERROR_SUCCESS
)
1737 HeapFree(GetProcessHeap(), 0, InstancePath
);
1738 RegCloseKey(hDeviceInstanceKey
);
1739 RegCloseKey(hInterfaceKey
);
1742 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1743 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1745 if (DeviceInstanceW
)
1747 /* Check if device enumerator is not the right one */
1748 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1750 HeapFree(GetProcessHeap(), 0, InstancePath
);
1751 RegCloseKey(hDeviceInstanceKey
);
1756 /* Find class GUID associated to the device instance */
1759 REGSTR_PATH_SYSTEMENUM
,
1763 if (rc
!= ERROR_SUCCESS
)
1765 HeapFree(GetProcessHeap(), 0, InstancePath
);
1766 RegCloseKey(hDeviceInstanceKey
);
1767 RegCloseKey(hInterfaceKey
);
1776 RegCloseKey(hEnumKey
);
1777 if (rc
!= ERROR_SUCCESS
)
1779 HeapFree(GetProcessHeap(), 0, InstancePath
);
1780 RegCloseKey(hDeviceInstanceKey
);
1781 RegCloseKey(hInterfaceKey
);
1784 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1785 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1787 if (rc
!= ERROR_SUCCESS
)
1789 HeapFree(GetProcessHeap(), 0, InstancePath
);
1790 RegCloseKey(hDeviceInstanceKey
);
1791 RegCloseKey(hInterfaceKey
);
1794 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1795 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1796 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1798 HeapFree(GetProcessHeap(), 0, InstancePath
);
1799 RegCloseKey(hDeviceInstanceKey
);
1800 RegCloseKey(hInterfaceKey
);
1801 return ERROR_GEN_FAILURE
;
1803 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1805 /* If current device doesn't match the list GUID (if any), skip this entry */
1806 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1808 HeapFree(GetProcessHeap(), 0, InstancePath
);
1809 RegCloseKey(hDeviceInstanceKey
);
1813 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1817 LPWSTR pSymbolicLink
;
1818 struct DeviceInterface
*interfaceInfo
;
1820 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1821 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1822 if (rc
== ERROR_NO_MORE_ITEMS
)
1824 if (rc
!= ERROR_SUCCESS
)
1826 HeapFree(GetProcessHeap(), 0, InstancePath
);
1827 RegCloseKey(hDeviceInstanceKey
);
1828 RegCloseKey(hInterfaceKey
);
1832 if (KeyBuffer
[0] != '#')
1833 /* This entry doesn't represent an interesting entry */
1837 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1838 if (rc
!= ERROR_SUCCESS
)
1840 RegCloseKey(hDeviceInstanceKey
);
1841 RegCloseKey(hInterfaceKey
);
1845 /* Read SymbolicLink value */
1846 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1847 if (rc
!= ERROR_SUCCESS
)
1849 RegCloseKey(hReferenceKey
);
1850 RegCloseKey(hDeviceInstanceKey
);
1851 RegCloseKey(hInterfaceKey
);
1854 if (dwRegType
!= REG_SZ
)
1856 RegCloseKey(hReferenceKey
);
1857 RegCloseKey(hDeviceInstanceKey
);
1858 RegCloseKey(hInterfaceKey
);
1859 return ERROR_GEN_FAILURE
;
1862 /* We have found a device */
1863 /* Step 1. Create a device info element */
1864 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1866 RegCloseKey(hReferenceKey
);
1867 RegCloseKey(hDeviceInstanceKey
);
1868 RegCloseKey(hInterfaceKey
);
1869 return GetLastError();
1871 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1872 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1874 /* Step 2. Create an interface list for this element */
1875 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1878 RegCloseKey(hReferenceKey
);
1879 RegCloseKey(hDeviceInstanceKey
);
1880 RegCloseKey(hInterfaceKey
);
1881 return ERROR_NOT_ENOUGH_MEMORY
;
1883 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1884 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1885 RegCloseKey(hReferenceKey
);
1886 if (rc
!= ERROR_SUCCESS
)
1888 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1889 RegCloseKey(hDeviceInstanceKey
);
1890 RegCloseKey(hInterfaceKey
);
1893 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1895 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1896 RegCloseKey(hDeviceInstanceKey
);
1897 RegCloseKey(hInterfaceKey
);
1898 return GetLastError();
1900 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1901 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1902 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1904 RegCloseKey(hDeviceInstanceKey
);
1906 RegCloseKey(hInterfaceKey
);
1907 return ERROR_SUCCESS
;
1909 #endif /* __REACTOS__ */
1911 /***********************************************************************
1912 * SetupDiGetClassDevsExW (SETUPAPI.@)
1914 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1923 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1924 struct DeviceInfoSet
*list
;
1928 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1929 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1931 /* Create the deviceset if not set */
1934 list
= (struct DeviceInfoSet
*)deviceset
;
1935 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1937 SetLastError(ERROR_INVALID_HANDLE
);
1938 return INVALID_HANDLE_VALUE
;
1940 hDeviceInfo
= deviceset
;
1944 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1945 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1946 NULL
, machine
, NULL
);
1947 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1948 return INVALID_HANDLE_VALUE
;
1949 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1952 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1955 pClassGuid
= &list
->ClassGuid
;
1957 if (flags
& DIGCF_PRESENT
)
1958 FIXME(": flag DIGCF_PRESENT ignored\n");
1959 if (flags
& DIGCF_PROFILE
)
1960 FIXME(": flag DIGCF_PROFILE ignored\n");
1962 if (flags
& DIGCF_ALLCLASSES
)
1964 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1965 if (rc
!= ERROR_SUCCESS
)
1969 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1970 return INVALID_HANDLE_VALUE
;
1974 else if (flags
& DIGCF_DEVICEINTERFACE
)
1978 SetLastError(ERROR_INVALID_PARAMETER
);
1980 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1981 return INVALID_HANDLE_VALUE
;
1985 /* Special case: find serial ports by calling QueryDosDevice */
1986 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1987 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1988 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1989 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1992 ERR("Wine can only enumerate serial devices at the moment!\n");
1993 rc
= ERROR_INVALID_PARAMETER
;
1995 #else /* __REACTOS__ */
1996 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1997 #endif /* __REACTOS__ */
1998 if (rc
!= ERROR_SUCCESS
)
2002 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2003 return INVALID_HANDLE_VALUE
;
2009 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
2010 if (rc
!= ERROR_SUCCESS
)
2014 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2015 return INVALID_HANDLE_VALUE
;
2021 /***********************************************************************
2022 * SetupDiGetClassImageIndex (SETUPAPI.@)
2025 static BOOL
GetIconIndex(
2027 OUT PINT ImageIndex
)
2029 LPWSTR Buffer
= NULL
;
2030 DWORD dwRegType
, dwLength
;
2034 /* Read icon registry key */
2035 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
2036 if (rc
!= ERROR_SUCCESS
)
2040 } else if (dwRegType
!= REG_SZ
)
2042 SetLastError(ERROR_INVALID_INDEX
);
2045 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2048 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2051 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2052 if (rc
!= ERROR_SUCCESS
)
2057 /* make sure the returned buffer is NULL-terminated */
2058 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2060 /* Transform icon value to a INT */
2061 *ImageIndex
= atoiW(Buffer
);
2069 BOOL WINAPI
SetupDiGetClassImageIndex(
2070 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2071 IN CONST GUID
*ClassGuid
,
2072 OUT PINT ImageIndex
)
2074 struct ClassImageList
*list
;
2077 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2079 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2080 SetLastError(ERROR_INVALID_PARAMETER
);
2081 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2082 SetLastError(ERROR_INVALID_USER_BUFFER
);
2083 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2084 SetLastError(ERROR_INVALID_USER_BUFFER
);
2085 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2086 SetLastError(ERROR_INVALID_USER_BUFFER
);
2087 else if (!ImageIndex
)
2088 SetLastError(ERROR_INVALID_PARAMETER
);
2091 HKEY hKey
= INVALID_HANDLE_VALUE
;
2094 /* Read Icon registry entry into Buffer */
2095 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2096 if (hKey
== INVALID_HANDLE_VALUE
)
2098 if (!GetIconIndex(hKey
, &iconIndex
))
2103 SetLastError(ERROR_INVALID_INDEX
);
2107 *ImageIndex
= -iconIndex
;
2111 if (hKey
!= INVALID_HANDLE_VALUE
)
2115 TRACE("Returning %d\n", ret
);
2119 /***********************************************************************
2120 * SetupDiGetClassImageList(SETUPAPI.@)
2122 BOOL WINAPI
SetupDiGetClassImageList(
2123 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2125 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2128 /***********************************************************************
2129 * SetupDiGetClassImageListExA(SETUPAPI.@)
2131 BOOL WINAPI
SetupDiGetClassImageListExA(
2132 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2133 IN PCSTR MachineName OPTIONAL
,
2136 PWSTR MachineNameW
= NULL
;
2141 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2142 if (MachineNameW
== NULL
)
2146 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2149 MyFree(MachineNameW
);
2154 /***********************************************************************
2155 * SetupDiGetClassImageListExW(SETUPAPI.@)
2157 BOOL WINAPI
SetupDiGetClassImageListExW(
2158 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2159 IN PCWSTR MachineName OPTIONAL
,
2164 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2166 if (!ClassImageListData
)
2167 SetLastError(ERROR_INVALID_PARAMETER
);
2168 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2169 SetLastError(ERROR_INVALID_USER_BUFFER
);
2171 SetLastError(ERROR_INVALID_PARAMETER
);
2174 struct ClassImageList
*list
= NULL
;
2177 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2179 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
2180 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2183 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2186 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2189 list
->szData
[0] = list
->szData
[1] = '\\';
2190 strcpyW(list
->szData
+ 2, MachineName
);
2191 list
->MachineName
= list
->szData
;
2195 list
->MachineName
= NULL
;
2198 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2206 TRACE("Returning %d\n", ret
);
2210 /***********************************************************************
2211 * SetupDiLoadClassIcon(SETUPAPI.@)
2213 BOOL WINAPI
SetupDiLoadClassIcon(
2214 IN CONST GUID
*ClassGuid
,
2215 OUT HICON
*LargeIcon OPTIONAL
,
2216 OUT PINT MiniIconIndex OPTIONAL
)
2221 SetLastError(ERROR_INVALID_PARAMETER
);
2224 LPWSTR Buffer
= NULL
;
2227 HKEY hKey
= INVALID_HANDLE_VALUE
;
2229 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2230 if (hKey
== INVALID_HANDLE_VALUE
)
2233 if (!GetIconIndex(hKey
, &iconIndex
))
2238 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2241 DWORD dwRegType
, dwLength
;
2242 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2243 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2245 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2248 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2251 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2252 if (rc
!= ERROR_SUCCESS
)
2257 /* make sure the returned buffer is NULL-terminated */
2258 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2261 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2262 && dwRegType
== REG_SZ
)
2264 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2267 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2270 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2271 if (rc
!= ERROR_SUCCESS
)
2276 /* make sure the returned buffer is NULL-terminated */
2277 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2281 /* Unable to find where to load the icon */
2282 SetLastError(ERROR_FILE_NOT_FOUND
);
2285 Comma
= strchrW(Buffer
, ',');
2288 SetLastError(ERROR_GEN_FAILURE
);
2296 /* Look up icon in setupapi.dll */
2297 DllName
= L
"setupapi.dll";
2298 iconIndex
= -iconIndex
;
2301 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2304 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2306 SetLastError(ERROR_INVALID_INDEX
);
2311 *MiniIconIndex
= iconIndex
;
2315 if (hKey
!= INVALID_HANDLE_VALUE
)
2320 TRACE("Returning %d\n", ret
);
2324 /***********************************************************************
2325 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2327 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2328 HDEVINFO DeviceInfoSet
,
2329 PSP_DEVINFO_DATA DeviceInfoData
,
2330 CONST GUID
* InterfaceClassGuid
,
2332 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2336 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2337 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2339 if (!DeviceInterfaceData
)
2340 SetLastError(ERROR_INVALID_PARAMETER
);
2341 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2342 SetLastError(ERROR_INVALID_USER_BUFFER
);
2343 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2345 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2347 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2349 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2351 while (ItemList
!= &list
->ListHead
&& !Found
)
2353 PLIST_ENTRY InterfaceListEntry
;
2354 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2355 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2357 /* We are not searching for this element */
2358 ItemList
= ItemList
->Flink
;
2361 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2362 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2364 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2365 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2367 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2370 if (MemberIndex
-- == 0)
2372 /* return this item */
2373 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2374 &DevItf
->InterfaceClassGuid
,
2376 DeviceInterfaceData
->Flags
= 0; /* FIXME */
2377 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2380 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2382 ItemList
= ItemList
->Flink
;
2385 SetLastError(ERROR_NO_MORE_ITEMS
);
2390 SetLastError(ERROR_INVALID_HANDLE
);
2393 SetLastError(ERROR_INVALID_HANDLE
);
2397 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2399 InterlockedIncrement(&infFile
->References
);
2402 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2404 if (InterlockedDecrement(&infFile
->References
) == 0)
2406 SetupCloseInfFile(infFile
->hInf
);
2407 HeapFree(GetProcessHeap(), 0, infFile
);
2411 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2413 DereferenceInfFile(driverInfo
->InfFileDetails
);
2414 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2415 HeapFree(GetProcessHeap(), 0, driverInfo
);
2419 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2421 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2425 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2427 PLIST_ENTRY ListEntry
;
2428 struct DriverInfoElement
*driverInfo
;
2430 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2432 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2433 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2434 if (!DestroyDriverInfoElement(driverInfo
))
2437 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2439 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2440 HeapFree(GetProcessHeap(), 0, ListEntry
);
2442 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2443 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2447 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2449 PLIST_ENTRY ListEntry
;
2450 struct DeviceInfoElement
*deviceInfo
;
2452 while (!IsListEmpty(&list
->ListHead
))
2454 ListEntry
= RemoveHeadList(&list
->ListHead
);
2455 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2456 if (!DestroyDeviceInfoElement(deviceInfo
))
2459 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2460 RegCloseKey(list
->HKLM
);
2461 CM_Disconnect_Machine(list
->hMachine
);
2462 DestroyClassInstallParams(&list
->ClassInstallParams
);
2463 HeapFree(GetProcessHeap(), 0, list
);
2467 /***********************************************************************
2468 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2470 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2474 TRACE("%p\n", devinfo
);
2475 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2477 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2479 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2480 ret
= DestroyDeviceInfoSet(list
);
2482 SetLastError(ERROR_INVALID_HANDLE
);
2485 SetLastError(ERROR_INVALID_HANDLE
);
2487 TRACE("Returning %d\n", ret
);
2491 /***********************************************************************
2492 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2494 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2495 HDEVINFO DeviceInfoSet
,
2496 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2497 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2498 DWORD DeviceInterfaceDetailDataSize
,
2499 PDWORD RequiredSize
,
2500 PSP_DEVINFO_DATA DeviceInfoData
)
2502 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2503 DWORD sizeW
= 0, sizeA
;
2506 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2507 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2508 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2510 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2511 SetLastError(ERROR_INVALID_USER_BUFFER
);
2512 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2513 SetLastError(ERROR_INVALID_PARAMETER
);
2514 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2515 SetLastError(ERROR_INVALID_PARAMETER
);
2518 if (DeviceInterfaceDetailData
!= NULL
)
2520 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2521 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2522 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2523 if (!DeviceInterfaceDetailDataW
)
2525 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2528 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2530 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2531 ret
= SetupDiGetDeviceInterfaceDetailW(
2533 DeviceInterfaceData
,
2534 DeviceInterfaceDetailDataW
,
2538 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2539 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2541 *RequiredSize
= sizeA
;
2542 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2544 if (!WideCharToMultiByte(
2546 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2547 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2554 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2557 TRACE("Returning %d\n", ret
);
2561 /***********************************************************************
2562 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2564 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2565 HDEVINFO DeviceInfoSet
,
2566 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2567 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2568 DWORD DeviceInterfaceDetailDataSize
,
2569 PDWORD RequiredSize
,
2570 PSP_DEVINFO_DATA DeviceInfoData
)
2574 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2575 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2576 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2578 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2579 SetLastError(ERROR_INVALID_PARAMETER
);
2580 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2581 SetLastError(ERROR_INVALID_HANDLE
);
2582 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2583 SetLastError(ERROR_INVALID_HANDLE
);
2584 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2585 SetLastError(ERROR_INVALID_USER_BUFFER
);
2586 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2587 SetLastError(ERROR_INVALID_USER_BUFFER
);
2588 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2589 SetLastError(ERROR_INVALID_USER_BUFFER
);
2590 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2591 SetLastError(ERROR_INVALID_PARAMETER
);
2592 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2593 SetLastError(ERROR_INVALID_PARAMETER
);
2596 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2597 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2598 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2599 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2601 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2603 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2605 *RequiredSize
= sizeRequired
;
2609 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2610 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2613 memcpy(&DeviceInfoData
->ClassGuid
,
2614 &deviceInterface
->DeviceInfo
->ClassGuid
,
2616 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2617 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2623 TRACE("Returning %d\n", ret
);
2627 /***********************************************************************
2628 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2630 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2632 PSP_DEVINFO_DATA DeviceInfoData
,
2634 PDWORD PropertyRegDataType
,
2635 PBYTE PropertyBuffer
,
2636 DWORD PropertyBufferSize
,
2637 PDWORD RequiredSize
)
2640 BOOL bIsStringProperty
;
2642 DWORD RequiredSizeA
, RequiredSizeW
;
2643 DWORD PropertyBufferSizeW
;
2644 PBYTE PropertyBufferW
;
2646 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2647 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2650 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2651 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2653 bResult
= SetupDiGetDeviceRegistryPropertyW(
2659 PropertyBufferSizeW
,
2662 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2664 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2666 if (bIsStringProperty
)
2667 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2669 RequiredSizeA
= RequiredSizeW
;
2671 *RequiredSize
= RequiredSizeA
;
2672 if (PropertyRegDataType
)
2673 *PropertyRegDataType
= RegType
;
2678 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2682 if (RequiredSizeA
<= PropertyBufferSize
)
2684 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2686 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2688 /* Last error is already set by WideCharToMultiByte */
2693 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2697 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2701 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2705 /***********************************************************************
2706 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2708 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2709 HDEVINFO DeviceInfoSet
,
2710 PSP_DEVINFO_DATA DeviceInfoData
,
2712 PDWORD PropertyRegDataType
,
2713 PBYTE PropertyBuffer
,
2714 DWORD PropertyBufferSize
,
2715 PDWORD RequiredSize
)
2717 HKEY hEnumKey
, hKey
;
2721 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2722 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2725 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2726 SetLastError(ERROR_INVALID_HANDLE
);
2727 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2728 SetLastError(ERROR_INVALID_HANDLE
);
2729 else if (!DeviceInfoData
)
2730 SetLastError(ERROR_INVALID_PARAMETER
);
2731 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2732 SetLastError(ERROR_INVALID_USER_BUFFER
);
2733 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2734 SetLastError(ERROR_INVALID_PARAMETER
);
2737 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2738 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2742 case SPDRP_CAPABILITIES
:
2744 case SPDRP_CLASSGUID
:
2745 case SPDRP_COMPATIBLEIDS
:
2746 case SPDRP_CONFIGFLAGS
:
2747 case SPDRP_DEVICEDESC
:
2749 case SPDRP_FRIENDLYNAME
:
2750 case SPDRP_HARDWAREID
:
2751 case SPDRP_LOCATION_INFORMATION
:
2752 case SPDRP_LOWERFILTERS
:
2754 case SPDRP_SECURITY
:
2756 case SPDRP_UI_NUMBER
:
2757 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2758 case SPDRP_UPPERFILTERS
:
2760 LPCWSTR RegistryPropertyName
;
2765 case SPDRP_CAPABILITIES
:
2766 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2768 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2769 case SPDRP_CLASSGUID
:
2770 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2771 case SPDRP_COMPATIBLEIDS
:
2772 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2773 case SPDRP_CONFIGFLAGS
:
2774 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2775 case SPDRP_DEVICEDESC
:
2776 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2778 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2779 case SPDRP_FRIENDLYNAME
:
2780 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2781 case SPDRP_HARDWAREID
:
2782 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2783 case SPDRP_LOCATION_INFORMATION
:
2784 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2785 case SPDRP_LOWERFILTERS
:
2786 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2788 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2789 case SPDRP_SECURITY
:
2790 RegistryPropertyName
= L
"Security"; break;
2792 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2793 case SPDRP_UI_NUMBER
:
2794 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2795 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2796 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2797 case SPDRP_UPPERFILTERS
:
2798 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2800 /* Should not happen */
2801 RegistryPropertyName
= NULL
; break;
2804 /* Open registry key name */
2807 REGSTR_PATH_SYSTEMENUM
,
2811 if (rc
!= ERROR_SUCCESS
)
2822 RegCloseKey(hEnumKey
);
2823 if (rc
!= ERROR_SUCCESS
)
2828 /* Read registry entry */
2829 BufferSize
= PropertyBufferSize
;
2830 rc
= RegQueryValueExW(
2832 RegistryPropertyName
,
2833 NULL
, /* Reserved */
2834 PropertyRegDataType
,
2838 *RequiredSize
= BufferSize
;
2841 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2844 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2846 case ERROR_MORE_DATA
:
2847 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2856 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2858 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2860 if (PropertyRegDataType
)
2861 *PropertyRegDataType
= REG_SZ
;
2863 *RequiredSize
= required
;
2864 if (PropertyBufferSize
>= required
)
2866 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2870 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2874 /*case SPDRP_BUSTYPEGUID:
2875 case SPDRP_LEGACYBUSTYPE:
2876 case SPDRP_BUSNUMBER:
2877 case SPDRP_ENUMERATOR_NAME:
2878 case SPDRP_SECURITY_SDS:
2880 case SPDRP_EXCLUSIVE:
2881 case SPDRP_CHARACTERISTICS:
2883 case SPDRP_DEVICE_POWER_DATA:*/
2884 #if (WINVER >= 0x501)
2885 /*case SPDRP_REMOVAL_POLICY:
2886 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2887 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2888 case SPDRP_INSTALL_STATE:*/
2893 ERR("Property 0x%lx not implemented\n", Property
);
2894 SetLastError(ERROR_NOT_SUPPORTED
);
2899 TRACE("Returning %d\n", ret
);
2903 /***********************************************************************
2904 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2906 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2907 IN HDEVINFO DeviceInfoSet
,
2908 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2910 IN CONST BYTE
*PropertyBuffer
,
2911 IN DWORD PropertyBufferSize
)
2913 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2914 Property
, PropertyBuffer
, PropertyBufferSize
);
2915 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2919 /***********************************************************************
2920 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2922 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2923 IN HDEVINFO DeviceInfoSet
,
2924 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2926 IN
const BYTE
*PropertyBuffer
,
2927 IN DWORD PropertyBufferSize
)
2929 struct DeviceInfoSet
*list
;
2932 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2933 Property
, PropertyBuffer
, PropertyBufferSize
);
2936 SetLastError(ERROR_INVALID_HANDLE
);
2937 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2938 SetLastError(ERROR_INVALID_HANDLE
);
2939 else if (!DeviceInfoData
)
2940 SetLastError(ERROR_INVALID_HANDLE
);
2941 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2942 SetLastError(ERROR_INVALID_USER_BUFFER
);
2947 case SPDRP_COMPATIBLEIDS
:
2948 case SPDRP_CONFIGFLAGS
:
2949 case SPDRP_FRIENDLYNAME
:
2950 case SPDRP_HARDWAREID
:
2951 case SPDRP_LOCATION_INFORMATION
:
2952 case SPDRP_LOWERFILTERS
:
2953 case SPDRP_SECURITY
:
2955 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2956 case SPDRP_UPPERFILTERS
:
2958 LPCWSTR RegistryPropertyName
;
2959 DWORD RegistryDataType
;
2965 case SPDRP_COMPATIBLEIDS
:
2966 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2967 RegistryDataType
= REG_MULTI_SZ
;
2969 case SPDRP_CONFIGFLAGS
:
2970 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2971 RegistryDataType
= REG_DWORD
;
2973 case SPDRP_FRIENDLYNAME
:
2974 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2975 RegistryDataType
= REG_SZ
;
2977 case SPDRP_HARDWAREID
:
2978 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2979 RegistryDataType
= REG_MULTI_SZ
;
2981 case SPDRP_LOCATION_INFORMATION
:
2982 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2983 RegistryDataType
= REG_SZ
;
2985 case SPDRP_LOWERFILTERS
:
2986 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2987 RegistryDataType
= REG_MULTI_SZ
;
2989 case SPDRP_SECURITY
:
2990 RegistryPropertyName
= L
"Security";
2991 RegistryDataType
= REG_BINARY
;
2994 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2995 RegistryDataType
= REG_SZ
;
2997 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2998 RegistryPropertyName
= L
"UINumberDescFormat";
2999 RegistryDataType
= REG_SZ
;
3001 case SPDRP_UPPERFILTERS
:
3002 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
3003 RegistryDataType
= REG_MULTI_SZ
;
3006 /* Should not happen */
3007 RegistryPropertyName
= NULL
;
3008 RegistryDataType
= REG_BINARY
;
3011 /* Open device registry key */
3012 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3013 if (hKey
!= INVALID_HANDLE_VALUE
)
3015 /* Write new data */
3016 rc
= RegSetValueExW(
3018 RegistryPropertyName
,
3022 PropertyBufferSize
);
3023 if (rc
== ERROR_SUCCESS
)
3032 /*case SPDRP_CHARACTERISTICS:
3034 case SPDRP_EXCLUSIVE:*/
3035 #if (WINVER >= 0x501)
3036 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
3038 //case SPDRP_SECURITY_SDS:
3042 ERR("Property 0x%lx not implemented\n", Property
);
3043 SetLastError(ERROR_NOT_SUPPORTED
);
3048 TRACE("Returning %d\n", ret
);
3053 /***********************************************************************
3054 * SetupDiInstallClassA (SETUPAPI.@)
3056 BOOL WINAPI
SetupDiInstallClassA(
3057 IN HWND hwndParent OPTIONAL
,
3058 IN PCSTR InfFileName
,
3060 IN HSPFILEQ FileQueue OPTIONAL
)
3062 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3066 /***********************************************************************
3067 * SetupDiInstallClassW (SETUPAPI.@)
3069 BOOL WINAPI
SetupDiInstallClassW(
3070 IN HWND hwndParent OPTIONAL
,
3071 IN PCWSTR InfFileName
,
3073 IN HSPFILEQ FileQueue OPTIONAL
)
3075 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3079 /***********************************************************************
3080 * SetupDiInstallClassExA (SETUPAPI.@)
3082 BOOL WINAPI
SetupDiInstallClassExA(
3083 IN HWND hwndParent OPTIONAL
,
3084 IN PCSTR InfFileName OPTIONAL
,
3086 IN HSPFILEQ FileQueue OPTIONAL
,
3087 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3091 PWSTR InfFileNameW
= NULL
;
3096 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3097 if (InfFileNameW
== NULL
)
3099 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3104 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3105 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3107 MyFree(InfFileNameW
);
3113 static HKEY
CreateClassKey(HINF hInf
)
3115 WCHAR FullBuffer
[MAX_PATH
];
3116 WCHAR Buffer
[MAX_PATH
];
3121 if (!SetupGetLineTextW(NULL
,
3129 return INVALID_HANDLE_VALUE
;
3132 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3133 lstrcatW(FullBuffer
, Buffer
);
3136 if (!SetupGetLineTextW(NULL
,
3144 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3145 return INVALID_HANDLE_VALUE
;
3148 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3152 REG_OPTION_NON_VOLATILE
,
3158 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3159 return INVALID_HANDLE_VALUE
;
3162 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3167 RequiredSize
* sizeof(WCHAR
)))
3169 RegCloseKey(hClassKey
);
3170 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3171 return INVALID_HANDLE_VALUE
;
3178 /***********************************************************************
3179 * SetupDiInstallClassExW (SETUPAPI.@)
3181 BOOL WINAPI
SetupDiInstallClassExW(
3182 IN HWND hwndParent OPTIONAL
,
3183 IN PCWSTR InfFileName OPTIONAL
,
3185 IN HSPFILEQ FileQueue OPTIONAL
,
3186 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3192 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3193 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3195 if (!InfFileName
&& !InterfaceClassGuid
)
3196 SetLastError(ERROR_INVALID_PARAMETER
);
3197 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3199 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3200 SetLastError(ERROR_INVALID_FLAGS
);
3202 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3203 SetLastError(ERROR_INVALID_PARAMETER
);
3204 else if (Reserved1
!= NULL
)
3205 SetLastError(ERROR_INVALID_PARAMETER
);
3206 else if (Reserved2
!= NULL
)
3207 SetLastError(ERROR_INVALID_PARAMETER
);
3210 WCHAR SectionName
[MAX_PATH
];
3211 HINF hInf
= INVALID_HANDLE_VALUE
;
3212 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3213 PVOID callback_context
= NULL
;
3215 if (InterfaceClassGuid
)
3217 /* SetupDiCreateDeviceInterface??? */
3218 FIXME("Installing an interface is not implemented\n");
3219 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3223 if (Flags
& DI_NOVCP
)
3224 FIXME("FileQueue argument ignored\n");
3225 if (Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3226 FIXME("Flags 0x%lx ignored\n", Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3228 /* Open the .inf file */
3229 hInf
= SetupOpenInfFileW(
3234 if (hInf
== INVALID_HANDLE_VALUE
)
3237 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3238 hClassKey
= CreateClassKey(hInf
);
3239 if (hClassKey
== INVALID_HANDLE_VALUE
)
3242 /* Try to append a layout file */
3243 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3247 /* Retrieve the actual section name */
3248 ret
= SetupDiGetActualSectionToInstallW(
3252 MAX_PATH
- wcslen(DotServices
),
3258 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3259 if (!callback_context
)
3262 ret
= SetupInstallFromInfSectionW(
3266 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3268 NULL
, /* SourceRootPath */
3270 SetupDefaultQueueCallbackW
,
3277 /* Install .Services section */
3278 lstrcatW(SectionName
, DotServices
);
3279 ret
= SetupInstallServicesFromInfSectionW(hInf
, SectionName
, 0);
3287 if (hInf
!= INVALID_HANDLE_VALUE
)
3288 SetupCloseInfFile(hInf
);
3289 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3290 RegCloseKey(hClassKey
);
3291 SetupTermDefaultQueueCallback(callback_context
);
3294 TRACE("Returning %d\n", ret
);
3299 /***********************************************************************
3300 * SetupDiOpenClassRegKey (SETUPAPI.@)
3302 HKEY WINAPI
SetupDiOpenClassRegKey(
3303 const GUID
* ClassGuid
,
3306 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3307 DIOCR_INSTALLER
, NULL
, NULL
);
3311 /***********************************************************************
3312 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3314 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3315 const GUID
* ClassGuid OPTIONAL
,
3318 PCSTR MachineName OPTIONAL
,
3321 PWSTR MachineNameW
= NULL
;
3328 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3329 if (MachineNameW
== NULL
)
3330 return INVALID_HANDLE_VALUE
;
3333 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3334 Flags
, MachineNameW
, Reserved
);
3337 MyFree(MachineNameW
);
3343 /***********************************************************************
3344 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3346 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3347 const GUID
* ClassGuid OPTIONAL
,
3350 PCWSTR MachineName OPTIONAL
,
3353 LPWSTR lpGuidString
;
3354 LPWSTR lpFullGuidString
;
3362 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3363 Flags
, debugstr_w(MachineName
), Reserved
);
3365 if (Flags
== DIOCR_INSTALLER
)
3367 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3369 else if (Flags
== DIOCR_INTERFACE
)
3371 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3375 ERR("Invalid Flags parameter!\n");
3376 SetLastError(ERROR_INVALID_FLAGS
);
3377 return INVALID_HANDLE_VALUE
;
3380 if (MachineName
!= NULL
)
3382 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3383 if (rc
!= ERROR_SUCCESS
)
3386 return INVALID_HANDLE_VALUE
;
3390 HKLM
= HKEY_LOCAL_MACHINE
;
3392 rc
= RegOpenKeyExW(HKLM
,
3395 ClassGuid
? 0 : samDesired
,
3397 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3398 if (rc
!= ERROR_SUCCESS
)
3401 return INVALID_HANDLE_VALUE
;
3404 if (ClassGuid
== NULL
)
3407 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3409 SetLastError(ERROR_GEN_FAILURE
);
3410 RegCloseKey(hClassesKey
);
3411 return INVALID_HANDLE_VALUE
;
3414 dwLength
= lstrlenW(lpGuidString
);
3415 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3416 if (!lpFullGuidString
)
3418 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3419 RpcStringFreeW(&lpGuidString
);
3420 return INVALID_HANDLE_VALUE
;
3422 lpFullGuidString
[0] = '{';
3423 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3424 lpFullGuidString
[dwLength
+ 1] = '}';
3425 lpFullGuidString
[dwLength
+ 2] = '\0';
3426 RpcStringFreeW(&lpGuidString
);
3428 rc
= RegOpenKeyExW(hClassesKey
,
3433 if (rc
!= ERROR_SUCCESS
)
3436 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3437 RegCloseKey(hClassesKey
);
3438 return INVALID_HANDLE_VALUE
;
3441 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3442 RegCloseKey(hClassesKey
);
3447 /***********************************************************************
3448 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3450 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3451 HDEVINFO DeviceInfoSet
,
3454 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3456 FIXME("%p %s %08lx %p\n",
3457 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3461 /***********************************************************************
3462 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3464 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3465 HDEVINFO DeviceInfoSet
,
3468 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3470 LPWSTR DevicePathW
= NULL
;
3473 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3475 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3476 if (DevicePathW
== NULL
)
3479 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3480 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3482 MyFree(DevicePathW
);
3487 /***********************************************************************
3488 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3490 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3491 HDEVINFO DeviceInfoSet
,
3492 PSP_DEVINFO_DATA DeviceInfoData
,
3493 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3494 DWORD ClassInstallParamsSize
)
3496 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3497 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3501 /***********************************************************************
3502 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3504 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3505 IN HDEVINFO DeviceInfoSet
,
3506 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3507 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3508 IN DWORD ClassInstallParamsSize
)
3510 struct DeviceInfoSet
*list
;
3513 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3514 ClassInstallParams
, ClassInstallParamsSize
);
3517 SetLastError(ERROR_INVALID_PARAMETER
);
3518 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3519 SetLastError(ERROR_INVALID_HANDLE
);
3520 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3521 SetLastError(ERROR_INVALID_HANDLE
);
3522 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3523 SetLastError(ERROR_INVALID_USER_BUFFER
);
3524 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3525 SetLastError(ERROR_INVALID_USER_BUFFER
);
3526 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3527 SetLastError(ERROR_INVALID_PARAMETER
);
3528 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3529 SetLastError(ERROR_INVALID_PARAMETER
);
3532 SP_DEVINSTALL_PARAMS_W InstallParams
;
3535 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3536 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3540 if (ClassInstallParams
)
3542 /* Check parameters in ClassInstallParams */
3543 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3544 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3546 SetLastError(ERROR_INVALID_USER_BUFFER
);
3549 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3551 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3552 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3555 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3558 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3562 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3565 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3569 TRACE("Returning %d\n", ret
);
3573 static BOOL
PropertyChangeHandler(
3574 IN HDEVINFO DeviceInfoSet
,
3575 IN PSP_DEVINFO_DATA DeviceInfoData
,
3576 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3577 IN DWORD ClassInstallParamsSize
)
3579 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3582 if (!DeviceInfoData
)
3583 SetLastError(ERROR_INVALID_PARAMETER
);
3584 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3585 SetLastError(ERROR_INVALID_PARAMETER
);
3586 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3587 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3588 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3589 SetLastError(ERROR_INVALID_FLAGS
);
3590 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3591 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3592 SetLastError(ERROR_INVALID_FLAGS
);
3593 else if (PropChangeParams
3594 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3595 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3596 SetLastError(ERROR_INVALID_USER_BUFFER
);
3599 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3600 if (!DeviceInfoData
)
3602 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3603 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3607 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3608 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3610 if (*CurrentPropChangeParams
)
3612 MyFree(*CurrentPropChangeParams
);
3613 *CurrentPropChangeParams
= NULL
;
3615 if (PropChangeParams
)
3617 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3618 if (!*CurrentPropChangeParams
)
3620 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3623 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3634 IN PWSTR InstallerName
,
3635 OUT HMODULE
* ModulePointer
,
3636 OUT PVOID
* FunctionPointer
)
3638 HMODULE hModule
= NULL
;
3639 LPSTR FunctionNameA
= NULL
;
3643 *ModulePointer
= NULL
;
3644 *FunctionPointer
= NULL
;
3646 Comma
= strchrW(InstallerName
, ',');
3649 rc
= ERROR_INVALID_PARAMETER
;
3655 hModule
= LoadLibraryW(InstallerName
);
3659 rc
= GetLastError();
3663 /* Skip comma spaces */
3664 while (*Comma
== ',' || isspaceW(*Comma
))
3667 /* W->A conversion for function name */
3668 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3671 rc
= GetLastError();
3675 /* Search function */
3676 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3677 if (!*FunctionPointer
)
3679 rc
= GetLastError();
3683 *ModulePointer
= hModule
;
3687 if (rc
!= ERROR_SUCCESS
&& hModule
)
3688 FreeLibrary(hModule
);
3689 MyFree(FunctionNameA
);
3694 FreeFunctionPointer(
3695 IN HMODULE ModulePointer
,
3696 IN PVOID FunctionPointer
)
3698 if (ModulePointer
== NULL
)
3699 return ERROR_SUCCESS
;
3700 if (FreeLibrary(ModulePointer
))
3701 return ERROR_SUCCESS
;
3703 return GetLastError();
3706 /***********************************************************************
3707 * SetupDiCallClassInstaller (SETUPAPI.@)
3709 BOOL WINAPI
SetupDiCallClassInstaller(
3710 IN DI_FUNCTION InstallFunction
,
3711 IN HDEVINFO DeviceInfoSet
,
3712 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3716 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3719 SetLastError(ERROR_INVALID_PARAMETER
);
3720 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3721 SetLastError(ERROR_INVALID_HANDLE
);
3722 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3723 SetLastError(ERROR_INVALID_HANDLE
);
3724 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3725 SetLastError(ERROR_INVALID_HANDLE
);
3726 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3727 SetLastError(ERROR_INVALID_USER_BUFFER
);
3730 SP_DEVINSTALL_PARAMS_W InstallParams
;
3731 #define CLASS_COINSTALLER 0x1
3732 #define DEVICE_COINSTALLER 0x2
3733 #define CLASS_INSTALLER 0x4
3734 UCHAR CanHandle
= 0;
3735 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3737 switch (InstallFunction
)
3739 case DIF_ALLOW_INSTALL
:
3740 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3742 case DIF_DESTROYPRIVATEDATA
:
3743 CanHandle
= CLASS_INSTALLER
;
3745 case DIF_INSTALLDEVICE
:
3746 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3747 DefaultHandler
= SetupDiInstallDevice
;
3749 case DIF_INSTALLDEVICEFILES
:
3750 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3751 DefaultHandler
= SetupDiInstallDriverFiles
;
3753 case DIF_INSTALLINTERFACES
:
3754 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3755 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3757 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3758 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3760 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3761 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3763 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3764 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3766 case DIF_PROPERTYCHANGE
:
3767 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3768 DefaultHandler
= SetupDiChangeState
;
3770 case DIF_REGISTER_COINSTALLERS
:
3771 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3772 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3774 case DIF_SELECTBESTCOMPATDRV
:
3775 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3776 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3779 ERR("Install function %u not supported\n", InstallFunction
);
3780 SetLastError(ERROR_NOT_SUPPORTED
);
3783 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3784 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3785 /* Don't process this call, as a parameter is invalid */
3790 LIST_ENTRY ClassCoInstallersListHead
;
3791 LIST_ENTRY DeviceCoInstallersListHead
;
3792 HMODULE ClassInstallerLibrary
= NULL
;
3793 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3794 COINSTALLER_CONTEXT_DATA Context
;
3795 PLIST_ENTRY ListEntry
;
3797 DWORD dwRegType
, dwLength
;
3798 DWORD rc
= NO_ERROR
;
3800 InitializeListHead(&ClassCoInstallersListHead
);
3801 InitializeListHead(&DeviceCoInstallersListHead
);
3803 if (CanHandle
& DEVICE_COINSTALLER
)
3805 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3806 if (hKey
!= INVALID_HANDLE_VALUE
)
3808 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3809 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3811 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3812 if (KeyBuffer
!= NULL
)
3814 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3815 if (rc
== ERROR_SUCCESS
)
3818 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3820 /* Add coinstaller to DeviceCoInstallersListHead list */
3821 struct CoInstallerElement
*coinstaller
;
3822 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3823 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3826 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3827 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3828 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3830 HeapFree(GetProcessHeap(), 0, coinstaller
);
3833 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3839 if (CanHandle
& CLASS_COINSTALLER
)
3843 REGSTR_PATH_CODEVICEINSTALLERS
,
3847 if (rc
== ERROR_SUCCESS
)
3849 LPWSTR lpGuidString
;
3850 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3852 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3853 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3855 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3856 if (KeyBuffer
!= NULL
)
3858 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3859 if (rc
== ERROR_SUCCESS
)
3862 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3864 /* Add coinstaller to ClassCoInstallersListHead list */
3865 struct CoInstallerElement
*coinstaller
;
3866 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3867 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3870 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3871 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3872 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3874 HeapFree(GetProcessHeap(), 0, coinstaller
);
3877 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3880 RpcStringFreeW(&lpGuidString
);
3885 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3887 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3888 if (hKey
!= INVALID_HANDLE_VALUE
)
3890 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3891 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3893 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3894 if (KeyBuffer
!= NULL
)
3896 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3897 if (rc
== ERROR_SUCCESS
)
3899 /* Get ClassInstaller function pointer */
3900 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3901 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3903 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3904 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3907 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3914 /* Call Class co-installers */
3915 Context
.PostProcessing
= FALSE
;
3917 ListEntry
= ClassCoInstallersListHead
.Flink
;
3918 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3920 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3921 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3922 coinstaller
->PrivateData
= Context
.PrivateData
;
3923 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3925 coinstaller
->DoPostProcessing
= TRUE
;
3928 ListEntry
= ListEntry
->Flink
;
3931 /* Call Device co-installers */
3932 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3933 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3935 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3936 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3937 coinstaller
->PrivateData
= Context
.PrivateData
;
3938 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3940 coinstaller
->DoPostProcessing
= TRUE
;
3943 ListEntry
= ListEntry
->Flink
;
3946 /* Call Class installer */
3949 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3950 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3953 rc
= ERROR_DI_DO_DEFAULT
;
3955 /* Call default handler */
3956 if (rc
== ERROR_DI_DO_DEFAULT
)
3958 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3960 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3963 rc
= GetLastError();
3969 /* Call Class co-installers that required postprocessing */
3970 Context
.PostProcessing
= TRUE
;
3971 ListEntry
= ClassCoInstallersListHead
.Flink
;
3972 while (ListEntry
!= &ClassCoInstallersListHead
)
3974 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3975 if (coinstaller
->DoPostProcessing
)
3977 Context
.InstallResult
= rc
;
3978 Context
.PrivateData
= coinstaller
->PrivateData
;
3979 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3981 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3982 ListEntry
= ListEntry
->Flink
;
3985 /* Call Device co-installers that required postprocessing */
3986 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3987 while (ListEntry
!= &DeviceCoInstallersListHead
)
3989 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3990 if (coinstaller
->DoPostProcessing
)
3992 Context
.InstallResult
= rc
;
3993 Context
.PrivateData
= coinstaller
->PrivateData
;
3994 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3996 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3997 ListEntry
= ListEntry
->Flink
;
4000 /* Free allocated memory */
4001 while (!IsListEmpty(&ClassCoInstallersListHead
))
4003 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4004 HeapFree(GetProcessHeap(), 0, ListEntry
);
4006 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4008 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4009 HeapFree(GetProcessHeap(), 0, ListEntry
);
4012 ret
= (rc
== NO_ERROR
);
4016 TRACE("Returning %d\n", ret
);
4020 /***********************************************************************
4021 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4023 BOOL WINAPI
SetupDiGetDeviceInfoListClass(
4024 IN HDEVINFO DeviceInfoSet
,
4025 OUT LPGUID ClassGuid
)
4027 struct DeviceInfoSet
*list
;
4030 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4033 SetLastError(ERROR_INVALID_HANDLE
);
4034 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4035 SetLastError(ERROR_INVALID_HANDLE
);
4036 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4037 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4040 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4045 TRACE("Returning %d\n", ret
);
4049 /***********************************************************************
4050 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4052 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
4053 IN HDEVINFO DeviceInfoSet
,
4054 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
4056 struct DeviceInfoSet
*list
;
4059 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
4062 SetLastError(ERROR_INVALID_HANDLE
);
4063 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4064 SetLastError(ERROR_INVALID_HANDLE
);
4065 else if (!DeviceInfoListDetailData
)
4066 SetLastError(ERROR_INVALID_PARAMETER
);
4067 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
4068 SetLastError(ERROR_INVALID_USER_BUFFER
);
4072 &DeviceInfoListDetailData
->ClassGuid
,
4075 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
4076 if (list
->MachineName
)
4077 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
4079 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
4084 TRACE("Returning %d\n", ret
);
4088 /***********************************************************************
4089 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4091 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4092 IN HDEVINFO DeviceInfoSet
,
4093 IN PSP_DEVINFO_DATA DeviceInfoData
,
4094 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4096 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4099 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4101 if (DeviceInstallParams
== NULL
)
4102 SetLastError(ERROR_INVALID_PARAMETER
);
4103 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4104 SetLastError(ERROR_INVALID_USER_BUFFER
);
4107 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4108 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4112 /* Do W->A conversion */
4114 DeviceInstallParams
,
4115 &deviceInstallParamsW
,
4116 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4117 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4118 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4120 DeviceInstallParams
->DriverPath
[0] = '\0';
4126 TRACE("Returning %d\n", ret
);
4130 /***********************************************************************
4131 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4133 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
4134 IN HDEVINFO DeviceInfoSet
,
4135 IN PSP_DEVINFO_DATA DeviceInfoData
,
4136 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4138 struct DeviceInfoSet
*list
;
4141 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4144 SetLastError(ERROR_INVALID_HANDLE
);
4145 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4146 SetLastError(ERROR_INVALID_HANDLE
);
4147 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4148 SetLastError(ERROR_INVALID_USER_BUFFER
);
4149 else if (!DeviceInstallParams
)
4150 SetLastError(ERROR_INVALID_PARAMETER
);
4151 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4152 SetLastError(ERROR_INVALID_USER_BUFFER
);
4155 PSP_DEVINSTALL_PARAMS_W Source
;
4158 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4160 Source
= &list
->InstallParams
;
4161 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4165 TRACE("Returning %d\n", ret
);
4169 /***********************************************************************
4170 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4172 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
4173 IN HDEVINFO DeviceInfoSet
,
4174 IN PSP_DEVINFO_DATA DeviceInfoData
,
4175 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4177 struct DeviceInfoSet
*list
;
4180 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4183 SetLastError(ERROR_INVALID_HANDLE
);
4184 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4185 SetLastError(ERROR_INVALID_HANDLE
);
4186 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4187 SetLastError(ERROR_INVALID_USER_BUFFER
);
4188 else if (!DeviceInstallParams
)
4189 SetLastError(ERROR_INVALID_PARAMETER
);
4190 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4191 SetLastError(ERROR_INVALID_USER_BUFFER
);
4194 PSP_DEVINSTALL_PARAMS_W Destination
;
4196 /* FIXME: Validate parameters */
4199 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4201 Destination
= &list
->InstallParams
;
4202 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4206 TRACE("Returning %d\n", ret
);
4210 /***********************************************************************
4211 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4213 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
4214 IN HDEVINFO DeviceInfoSet
,
4215 IN PSP_DEVINFO_DATA DeviceInfoData
,
4216 OUT PSTR DeviceInstanceId OPTIONAL
,
4217 IN DWORD DeviceInstanceIdSize
,
4218 OUT PDWORD RequiredSize OPTIONAL
)
4220 PWSTR DeviceInstanceIdW
= NULL
;
4223 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4224 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4226 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4227 SetLastError(ERROR_INVALID_PARAMETER
);
4230 if (DeviceInstanceIdSize
!= 0)
4232 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4233 if (DeviceInstanceIdW
== NULL
)
4237 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4238 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4241 if (ret
&& DeviceInstanceIdW
!= NULL
)
4243 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4244 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4246 DeviceInstanceId
[0] = '\0';
4252 TRACE("Returning %d\n", ret
);
4256 /***********************************************************************
4257 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4259 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
4260 IN HDEVINFO DeviceInfoSet
,
4261 IN PSP_DEVINFO_DATA DeviceInfoData
,
4262 OUT PWSTR DeviceInstanceId OPTIONAL
,
4263 IN DWORD DeviceInstanceIdSize
,
4264 OUT PDWORD RequiredSize OPTIONAL
)
4268 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4269 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4272 SetLastError(ERROR_INVALID_HANDLE
);
4273 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4274 SetLastError(ERROR_INVALID_HANDLE
);
4275 else if (!DeviceInfoData
)
4276 SetLastError(ERROR_INVALID_PARAMETER
);
4277 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4278 SetLastError(ERROR_INVALID_USER_BUFFER
);
4279 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4280 SetLastError(ERROR_INVALID_PARAMETER
);
4281 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4282 SetLastError(ERROR_INVALID_PARAMETER
);
4285 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4288 required
= (wcslen(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4290 *RequiredSize
= required
;
4292 if (required
<= DeviceInstanceIdSize
)
4294 wcscpy(DeviceInstanceId
, DevInfo
->DeviceName
);
4298 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4301 TRACE("Returning %d\n", ret
);
4305 /***********************************************************************
4306 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4308 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
4309 IN HDEVINFO DeviceInfoSet
,
4310 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4311 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4312 IN DWORD PropertySheetHeaderPageListSize
,
4313 OUT PDWORD RequiredSize OPTIONAL
,
4314 IN DWORD PropertySheetType
)
4316 PROPSHEETHEADERW psh
;
4319 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4320 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4321 RequiredSize
, PropertySheetType
);
4323 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4324 psh
.phpage
= PropertySheetHeader
->phpage
;
4325 psh
.nPages
= PropertySheetHeader
->nPages
;
4327 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4328 PropertySheetHeaderPageListSize
, RequiredSize
,
4332 PropertySheetHeader
->nPages
= psh
.nPages
;
4335 TRACE("Returning %d\n", ret
);
4339 struct ClassDevPropertySheetsData
4341 HPROPSHEETPAGE
*PropertySheetPages
;
4342 DWORD MaximumNumberOfPages
;
4343 DWORD NumberOfPages
;
4346 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
4347 IN HPROPSHEETPAGE hPropSheetPage
,
4348 IN OUT LPARAM lParam
)
4350 struct ClassDevPropertySheetsData
*PropPageData
;
4352 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4354 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4356 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4357 PropPageData
->PropertySheetPages
++;
4360 PropPageData
->NumberOfPages
++;
4364 /***********************************************************************
4365 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4367 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
4368 IN HDEVINFO DeviceInfoSet
,
4369 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4370 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4371 IN DWORD PropertySheetHeaderPageListSize
,
4372 OUT PDWORD RequiredSize OPTIONAL
,
4373 IN DWORD PropertySheetType
)
4375 struct DeviceInfoSet
*list
;
4378 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4379 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4380 RequiredSize
, PropertySheetType
);
4383 SetLastError(ERROR_INVALID_HANDLE
);
4384 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4385 SetLastError(ERROR_INVALID_HANDLE
);
4386 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4387 SetLastError(ERROR_INVALID_HANDLE
);
4388 else if (!PropertySheetHeader
)
4389 SetLastError(ERROR_INVALID_PARAMETER
);
4390 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4391 SetLastError(ERROR_INVALID_FLAGS
);
4392 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4393 SetLastError(ERROR_INVALID_USER_BUFFER
);
4394 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4395 SetLastError(ERROR_INVALID_PARAMETER
);
4396 else if (!PropertySheetHeader
)
4397 SetLastError(ERROR_INVALID_PARAMETER
);
4398 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4399 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4400 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4401 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4402 SetLastError(ERROR_INVALID_PARAMETER
);
4405 HKEY hKey
= INVALID_HANDLE_VALUE
;
4406 SP_PROPSHEETPAGE_REQUEST Request
;
4407 LPWSTR PropPageProvider
= NULL
;
4408 HMODULE hModule
= NULL
;
4409 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4410 struct ClassDevPropertySheetsData PropPageData
;
4411 DWORD dwLength
, dwRegType
;
4415 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4418 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4419 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4421 if (hKey
== INVALID_HANDLE_VALUE
)
4424 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4425 if (rc
== ERROR_FILE_NOT_FOUND
)
4427 /* No registry key. As it is optional, don't say it's a bad error */
4433 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4439 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4440 if (!PropPageProvider
)
4442 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4445 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4446 if (rc
!= ERROR_SUCCESS
)
4451 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4453 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4454 if (rc
!= ERROR_SUCCESS
)
4456 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4460 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4461 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4462 Request
.DeviceInfoSet
= DeviceInfoSet
;
4463 Request
.DeviceInfoData
= DeviceInfoData
;
4464 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4465 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4466 PropPageData
.NumberOfPages
= 0;
4467 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4472 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4473 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4475 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4480 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4481 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4485 if (hKey
!= INVALID_HANDLE_VALUE
)
4487 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4488 FreeFunctionPointer(hModule
, pPropPageProvider
);
4491 TRACE("Returning %d\n", ret
);
4495 /***********************************************************************
4496 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4498 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4499 IN HDEVINFO DeviceInfoSet
,
4500 IN PSP_DEVINFO_DATA DeviceInfoData
,
4504 IN HINF InfHandle OPTIONAL
,
4505 IN PCSTR InfSectionName OPTIONAL
)
4507 PCWSTR InfSectionNameW
= NULL
;
4508 HKEY ret
= INVALID_HANDLE_VALUE
;
4512 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4513 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4516 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4524 if (InfSectionNameW
!= NULL
)
4525 MyFree((PVOID
)InfSectionNameW
);
4531 OpenHardwareProfileKey(
4534 IN DWORD samDesired
)
4536 HKEY hHWProfilesKey
= INVALID_HANDLE_VALUE
;
4537 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4538 HKEY ret
= INVALID_HANDLE_VALUE
;
4541 rc
= RegOpenKeyExW(HKLM
,
4542 REGSTR_PATH_HWPROFILES
,
4546 if (rc
!= ERROR_SUCCESS
)
4563 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4572 if (rc
!= ERROR_SUCCESS
)
4577 ret
= hHWProfileKey
;
4580 if (hHWProfilesKey
!= INVALID_HANDLE_VALUE
)
4581 RegCloseKey(hHWProfilesKey
);
4582 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
&& hHWProfileKey
!= ret
)
4583 RegCloseKey(hHWProfileKey
);
4587 /***********************************************************************
4588 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4590 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4591 IN HDEVINFO DeviceInfoSet
,
4592 IN PSP_DEVINFO_DATA DeviceInfoData
,
4596 IN HINF InfHandle OPTIONAL
,
4597 IN PCWSTR InfSectionName OPTIONAL
)
4599 struct DeviceInfoSet
*list
;
4600 HKEY ret
= INVALID_HANDLE_VALUE
;
4602 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4603 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4606 SetLastError(ERROR_INVALID_HANDLE
);
4607 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4608 SetLastError(ERROR_INVALID_HANDLE
);
4609 else if (!DeviceInfoData
)
4610 SetLastError(ERROR_INVALID_PARAMETER
);
4611 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4612 SetLastError(ERROR_INVALID_USER_BUFFER
);
4613 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4614 SetLastError(ERROR_INVALID_PARAMETER
);
4615 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4616 SetLastError(ERROR_INVALID_PARAMETER
);
4617 else if (InfHandle
&& !InfSectionName
)
4618 SetLastError(ERROR_INVALID_PARAMETER
);
4619 else if (!InfHandle
&& InfSectionName
)
4620 SetLastError(ERROR_INVALID_PARAMETER
);
4623 LPWSTR lpGuidString
= NULL
;
4624 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4625 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4626 DWORD Index
; /* Index used in the DriverKey name */
4628 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4629 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4630 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4631 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4632 HKEY hKey
= INVALID_HANDLE_VALUE
;
4635 if (Scope
== DICS_FLAG_GLOBAL
)
4636 RootKey
= list
->HKLM
;
4637 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4639 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
4640 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4642 RootKey
= hHWProfileKey
;
4645 if (KeyType
== DIREG_DEV
)
4647 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4649 rc
= RegCreateKeyExW(
4651 REGSTR_PATH_SYSTEMENUM
,
4654 REG_OPTION_NON_VOLATILE
,
4659 if (rc
!= ERROR_SUCCESS
)
4664 rc
= RegCreateKeyExW(
4666 deviceInfo
->DeviceName
,
4669 REG_OPTION_NON_VOLATILE
,
4670 #if _WIN32_WINNT >= 0x502
4671 KEY_READ
| KEY_WRITE
,
4678 if (rc
!= ERROR_SUCCESS
)
4684 else /* KeyType == DIREG_DRV */
4686 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4688 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4689 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4692 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4695 wcscpy(DriverKey
, L
"{");
4696 wcscat(DriverKey
, lpGuidString
);
4697 wcscat(DriverKey
, L
"}\\");
4698 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4699 rc
= RegOpenKeyExW(RootKey
,
4700 REGSTR_PATH_CLASS_NT
,
4704 if (rc
!= ERROR_SUCCESS
)
4710 /* Try all values for Index between 0 and 9999 */
4712 while (Index
<= 9999)
4715 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4716 rc
= RegCreateKeyEx(hClassKey
,
4720 REG_OPTION_NON_VOLATILE
,
4721 #if _WIN32_WINNT >= 0x502
4722 KEY_READ
| KEY_WRITE
,
4729 if (rc
!= ERROR_SUCCESS
)
4734 if (Disposition
== REG_CREATED_NEW_KEY
)
4737 hKey
= INVALID_HANDLE_VALUE
;
4742 /* Unable to create more than 9999 devices within the same class */
4743 SetLastError(ERROR_GEN_FAILURE
);
4747 /* Open device key, to write Driver value */
4748 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4749 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4751 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4752 if (rc
!= ERROR_SUCCESS
)
4759 /* Do installation of the specified section */
4762 FIXME("Need to install section %s in file %p\n",
4763 debugstr_w(InfSectionName
), InfHandle
);
4769 RpcStringFreeW(&lpGuidString
);
4770 HeapFree(GetProcessHeap(), 0, DriverKey
);
4771 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4772 RegCloseKey(hHWProfileKey
);
4773 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4774 RegCloseKey(hEnumKey
);
4775 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4776 RegCloseKey(hClassKey
);
4777 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4778 RegCloseKey(hDeviceKey
);
4779 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4783 TRACE("Returning 0x%p\n", ret
);
4787 /***********************************************************************
4788 * SetupDiOpenDevRegKey (SETUPAPI.@)
4790 HKEY WINAPI
SetupDiOpenDevRegKey(
4791 HDEVINFO DeviceInfoSet
,
4792 PSP_DEVINFO_DATA DeviceInfoData
,
4798 struct DeviceInfoSet
*list
;
4799 HKEY ret
= INVALID_HANDLE_VALUE
;
4801 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4802 Scope
, HwProfile
, KeyType
, samDesired
);
4805 SetLastError(ERROR_INVALID_HANDLE
);
4806 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4807 SetLastError(ERROR_INVALID_HANDLE
);
4808 else if (!DeviceInfoData
)
4809 SetLastError(ERROR_INVALID_PARAMETER
);
4810 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4811 SetLastError(ERROR_INVALID_USER_BUFFER
);
4812 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4813 SetLastError(ERROR_INVALID_PARAMETER
);
4814 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4815 SetLastError(ERROR_INVALID_PARAMETER
);
4818 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4819 LPWSTR DriverKey
= NULL
;
4823 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4824 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4825 HKEY hKey
= INVALID_HANDLE_VALUE
;
4828 if (Scope
== DICS_FLAG_GLOBAL
)
4829 RootKey
= list
->HKLM
;
4830 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4832 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
4833 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4835 RootKey
= hHWProfileKey
;
4840 REGSTR_PATH_SYSTEMENUM
,
4844 if (rc
!= ERROR_SUCCESS
)
4851 deviceInfo
->DeviceName
,
4853 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4855 RegCloseKey(hEnumKey
);
4856 hEnumKey
= INVALID_HANDLE_VALUE
;
4857 if (rc
!= ERROR_SUCCESS
)
4862 if (KeyType
== DIREG_DEV
)
4864 /* We're done. Just return the hKey handle */
4868 /* Read the 'Driver' key */
4869 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
4870 if (rc
!= ERROR_SUCCESS
)
4875 else if (dwRegType
!= REG_SZ
)
4877 SetLastError(ERROR_GEN_FAILURE
);
4880 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4883 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4886 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4887 if (rc
!= ERROR_SUCCESS
)
4893 hKey
= INVALID_HANDLE_VALUE
;
4894 /* Need to open the driver key */
4897 REGSTR_PATH_CLASS_NT
,
4901 if (rc
!= ERROR_SUCCESS
)
4912 if (rc
!= ERROR_SUCCESS
)
4920 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4921 RegCloseKey(hHWProfileKey
);
4922 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4923 RegCloseKey(hEnumKey
);
4924 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4928 TRACE("Returning 0x%p\n", ret
);
4932 /***********************************************************************
4933 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
4935 BOOL WINAPI
SetupDiCreateDeviceInfoA(
4936 HDEVINFO DeviceInfoSet
,
4938 CONST GUID
*ClassGuid
,
4939 PCSTR DeviceDescription
,
4941 DWORD CreationFlags
,
4942 PSP_DEVINFO_DATA DeviceInfoData
)
4944 LPWSTR DeviceNameW
= NULL
;
4945 LPWSTR DeviceDescriptionW
= NULL
;
4952 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
4953 if (DeviceNameW
== NULL
) return FALSE
;
4955 if (DeviceDescription
)
4957 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
4958 if (DeviceDescriptionW
== NULL
)
4960 if (DeviceNameW
) MyFree(DeviceNameW
);
4965 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
4966 ClassGuid
, DeviceDescriptionW
,
4967 hwndParent
, CreationFlags
,
4970 if (DeviceNameW
) MyFree(DeviceNameW
);
4971 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
4976 /***********************************************************************
4977 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
4979 BOOL WINAPI
SetupDiCreateDeviceInfoW(
4980 HDEVINFO DeviceInfoSet
,
4982 CONST GUID
*ClassGuid
,
4983 PCWSTR DeviceDescription
,
4985 DWORD CreationFlags
,
4986 PSP_DEVINFO_DATA DeviceInfoData
)
4988 struct DeviceInfoSet
*list
;
4991 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
4992 debugstr_guid(ClassGuid
), DeviceDescription
,
4993 hwndParent
, CreationFlags
, DeviceInfoData
);
4996 SetLastError(ERROR_INVALID_HANDLE
);
4997 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4998 SetLastError(ERROR_INVALID_HANDLE
);
4999 else if (!ClassGuid
)
5000 SetLastError(ERROR_INVALID_PARAMETER
);
5001 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
5002 SetLastError(ERROR_CLASS_MISMATCH
);
5003 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
5005 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
5006 SetLastError(ERROR_INVALID_FLAGS
);
5010 SP_DEVINFO_DATA DevInfo
;
5012 if (CreationFlags
& DICD_GENERATE_ID
)
5014 /* Generate a new unique ID for this device */
5015 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5016 FIXME("not implemented\n");
5020 /* Device name is fully qualified. Try to open it */
5023 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
5024 rc
= SetupDiOpenDeviceInfoW(
5027 NULL
, /* hwndParent */
5028 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
5033 /* SetupDiOpenDeviceInfoW has already added
5034 * the device info to the device info set
5036 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
5038 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5040 struct DeviceInfoElement
*deviceInfo
;
5042 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
5044 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5046 if (!DeviceInfoData
)
5050 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
5052 SetLastError(ERROR_INVALID_USER_BUFFER
);
5056 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5057 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5058 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5067 TRACE("Returning %d\n", ret
);
5071 /***********************************************************************
5072 * Helper functions for SetupDiBuildDriverInfoList
5076 IN PLIST_ENTRY DriverListHead
,
5077 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5078 IN LPGUID ClassGuid
,
5079 IN INFCONTEXT ContextDevice
,
5080 IN
struct InfFileDetails
*InfFileDetails
,
5082 IN LPCWSTR ProviderName
,
5083 IN LPCWSTR ManufacturerName
,
5084 IN LPCWSTR MatchingId
,
5085 FILETIME DriverDate
,
5086 DWORDLONG DriverVersion
,
5089 struct DriverInfoElement
*driverInfo
= NULL
;
5090 HANDLE hFile
= INVALID_HANDLE_VALUE
;
5091 DWORD RequiredSize
= 128; /* Initial buffer size */
5092 BOOL Result
= FALSE
;
5093 PLIST_ENTRY PreviousEntry
;
5094 LPWSTR InfInstallSection
= NULL
;
5097 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
5100 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5103 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
5105 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
5106 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
5108 /* Copy InfFileName field */
5109 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
5110 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
5112 /* Fill InfDate field */
5113 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5114 GENERIC_READ, FILE_SHARE_READ,
5115 NULL, OPEN_EXISTING, 0, NULL);
5116 if (hFile == INVALID_HANDLE_VALUE)
5118 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5122 /* Fill SectionName field */
5123 Result
= SetupGetStringFieldW(
5126 driverInfo
->Details
.SectionName
, LINE_LEN
,
5131 /* Fill DrvDescription field */
5132 Result
= SetupGetStringFieldW(
5134 0, /* Field index */
5135 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
5138 /* Copy MatchingId information */
5141 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5142 if (!driverInfo
->MatchingId
)
5144 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5147 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5150 driverInfo
->MatchingId
= NULL
;
5152 /* Get inf install section */
5154 RequiredSize
= 128; /* Initial buffer size */
5155 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5156 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5158 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5159 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5160 if (!InfInstallSection
)
5162 Result
= SetupGetStringFieldW(
5164 1, /* Field index */
5165 InfInstallSection
, RequiredSize
,
5171 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
5172 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
5174 driverInfo
->DriverRank
= Rank
;
5175 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
5176 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5177 driverInfo
->Info
.DriverType
= DriverType
;
5178 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
5179 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
5180 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
5181 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
5182 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
5185 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
5186 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
5189 driverInfo
->Info
.ProviderName
[0] = '\0';
5190 driverInfo
->Info
.DriverDate
= DriverDate
;
5191 driverInfo
->Info
.DriverVersion
= DriverVersion
;
5192 ReferenceInfFile(InfFileDetails
);
5193 driverInfo
->InfFileDetails
= InfFileDetails
;
5195 /* Insert current driver in driver list, according to its rank */
5196 PreviousEntry
= DriverListHead
->Flink
;
5197 while (PreviousEntry
!= DriverListHead
)
5199 struct DriverInfoElement
*CurrentDriver
;
5200 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
5201 if (CurrentDriver
->DriverRank
> Rank
||
5202 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
5204 /* Insert before the current item */
5205 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
5208 PreviousEntry
= PreviousEntry
->Flink
;
5210 if (PreviousEntry
== DriverListHead
)
5212 /* Insert at the end of the list */
5213 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
5222 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
5223 HeapFree(GetProcessHeap(), 0, driverInfo
);
5225 if (hFile
!= INVALID_HANDLE_VALUE
)
5227 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5233 GetVersionInformationFromInfFile(
5235 OUT LPGUID ClassGuid
,
5236 OUT LPWSTR
* pProviderName
,
5237 OUT FILETIME
* DriverDate
,
5238 OUT DWORDLONG
* DriverVersion
)
5241 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5242 LPWSTR DriverVer
= NULL
;
5243 LPWSTR ProviderName
= NULL
;
5244 LPWSTR pComma
; /* Points into DriverVer */
5245 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5246 SYSTEMTIME SystemTime
;
5248 BOOL ret
= FALSE
; /* Final result */
5250 /* Get class Guid */
5251 if (!SetupGetLineTextW(
5254 L
"Version", L
"ClassGUID",
5255 guidW
, sizeof(guidW
),
5256 NULL
/* Required size */))
5260 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5261 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5263 SetLastError(ERROR_GEN_FAILURE
);
5267 /* Get provider name */
5268 Result
= SetupGetLineTextW(
5270 hInf
, L
"Version", L
"Provider",
5275 /* We know know the needed buffer size */
5276 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5279 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5282 Result
= SetupGetLineTextW(
5284 hInf
, L
"Version", L
"Provider",
5285 ProviderName
, RequiredSize
,
5290 *pProviderName
= ProviderName
;
5292 /* Read the "DriverVer" value */
5293 Result
= SetupGetLineTextW(
5295 hInf
, L
"Version", L
"DriverVer",
5300 /* We know know the needed buffer size */
5301 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5304 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5307 Result
= SetupGetLineTextW(
5309 hInf
, L
"Version", L
"DriverVer",
5310 DriverVer
, RequiredSize
,
5316 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5317 pComma
= wcschr(DriverVer
, ',');
5320 *pComma
= UNICODE_NULL
;
5321 pVersion
= pComma
+ 1;
5323 /* Get driver date version. Invalid date = 00/00/00 */
5324 memset(DriverDate
, 0, sizeof(FILETIME
));
5325 if (wcslen(DriverVer
) == 10
5326 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5327 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5329 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5330 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5331 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5332 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5333 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5334 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5336 /* Get driver version. Invalid version = 0.0.0.0 */
5340 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5341 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5342 LARGE_INTEGER fullVersion
;
5344 pMinor
= strchrW(pVersion
, '.');
5348 pRevision
= strchrW(++pMinor
, '.');
5349 Minor
= atoiW(pMinor
);
5354 pBuild
= strchrW(++pRevision
, '.');
5355 Revision
= atoiW(pRevision
);
5361 Build
= atoiW(pBuild
);
5363 Major
= atoiW(pVersion
);
5364 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5365 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5366 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5373 HeapFree(GetProcessHeap(), 0, ProviderName
);
5374 HeapFree(GetProcessHeap(), 0, DriverVer
);
5379 /***********************************************************************
5380 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5383 SetupDiBuildDriverInfoList(
5384 IN HDEVINFO DeviceInfoSet
,
5385 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5386 IN DWORD DriverType
)
5388 struct DeviceInfoSet
*list
;
5389 SP_DEVINSTALL_PARAMS_W InstallParams
;
5390 PVOID Buffer
= NULL
;
5391 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5392 LPWSTR ProviderName
= NULL
;
5393 LPWSTR ManufacturerName
= NULL
;
5394 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5395 LPWSTR HardwareIDs
= NULL
;
5396 LPWSTR CompatibleIDs
= NULL
;
5397 LPWSTR FullInfFileName
= NULL
;
5398 FILETIME DriverDate
;
5399 DWORDLONG DriverVersion
= 0;
5403 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5406 SetLastError(ERROR_INVALID_HANDLE
);
5407 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5408 SetLastError(ERROR_INVALID_HANDLE
);
5409 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5410 SetLastError(ERROR_INVALID_HANDLE
);
5411 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5412 SetLastError(ERROR_INVALID_PARAMETER
);
5413 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5414 SetLastError(ERROR_INVALID_PARAMETER
);
5415 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5416 SetLastError(ERROR_INVALID_USER_BUFFER
);
5421 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
5422 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5426 if (DriverType
== SPDIT_COMPATDRIVER
)
5428 /* Get hardware IDs list */
5430 RequiredSize
= 512; /* Initial buffer size */
5431 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5432 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5434 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5435 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5438 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5441 Result
= SetupDiGetDeviceRegistryPropertyW(
5453 /* Get compatible IDs list */
5455 RequiredSize
= 512; /* Initial buffer size */
5456 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5457 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5459 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5460 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5463 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5466 Result
= SetupDiGetDeviceRegistryPropertyW(
5469 SPDRP_COMPATIBLEIDS
,
5471 (PBYTE
)CompatibleIDs
,
5474 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5476 /* No compatible ID for this device */
5477 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5478 CompatibleIDs
= NULL
;
5486 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5488 /* InstallParams.DriverPath contains the name of a .inf file */
5489 RequiredSize
= wcslen(InstallParams
.DriverPath
) + 2;
5490 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5493 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5496 wcscpy(Buffer
, InstallParams
.DriverPath
);
5497 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
5502 /* Enumerate .inf files */
5504 RequiredSize
= 32768; /* Initial buffer size */
5505 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5506 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5508 HeapFree(GetProcessHeap(), 0, Buffer
);
5509 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5513 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5516 Result
= SetupGetInfFileListW(
5517 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5519 Buffer
, RequiredSize
,
5522 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5524 /* No .inf file in specified directory. So, we should
5525 * success as we created an empty driver info list.
5534 LPWSTR pFullFilename
;
5536 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5538 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5539 if (!FullInfFileName
)
5541 pFullFilename
= &FullInfFileName
[0];
5543 else if (*InstallParams
.DriverPath
)
5546 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5549 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5550 if (!FullInfFileName
)
5552 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5555 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
5556 wcscat(FullInfFileName
, L
"\\");
5557 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
5561 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5562 if (!FullInfFileName
)
5564 pFullFilename
= &FullInfFileName
[0];
5567 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
5569 INFCONTEXT ContextManufacturer
, ContextDevice
;
5572 wcscpy(pFullFilename
, filename
);
5573 TRACE("Opening file %S\n", FullInfFileName
);
5575 currentInfFileDetails
= HeapAlloc(
5578 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
5579 if (!currentInfFileDetails
)
5581 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5582 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5584 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5585 ReferenceInfFile(currentInfFileDetails
);
5586 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5588 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5589 currentInfFileDetails
= NULL
;
5593 if (!GetVersionInformationFromInfFile(
5594 currentInfFileDetails
->hInf
,
5600 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5601 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5602 currentInfFileDetails
= NULL
;
5606 if (DriverType
== SPDIT_CLASSDRIVER
)
5608 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5609 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5615 /* Get the manufacturers list */
5616 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
5619 Result
= SetupGetStringFieldW(
5620 &ContextManufacturer
,
5621 0, /* Field index */
5626 /* We got the needed size for the buffer */
5627 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5628 if (!ManufacturerName
)
5630 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5633 Result
= SetupGetStringFieldW(
5634 &ContextManufacturer
,
5635 0, /* Field index */
5636 ManufacturerName
, RequiredSize
,
5639 /* Get manufacturer section name */
5640 Result
= SetupGetStringFieldW(
5641 &ContextManufacturer
,
5642 1, /* Field index */
5643 ManufacturerSection
, LINE_LEN
,
5647 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5648 /* Add (possible) extension to manufacturer section name */
5649 Result
= SetupDiGetActualSectionToInstallW(
5650 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5653 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
5654 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5659 if (DriverType
== SPDIT_CLASSDRIVER
)
5661 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5662 if (!AddDriverToList(
5663 &list
->DriverListHead
,
5667 currentInfFileDetails
,
5672 DriverDate
, DriverVersion
,
5678 else /* DriverType = SPDIT_COMPATDRIVER */
5680 /* 1. Get all fields */
5681 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5685 BOOL DriverAlreadyAdded
;
5687 for (i
= 2; i
<= FieldCount
; i
++)
5689 LPWSTR DeviceId
= NULL
;
5691 RequiredSize
= 128; /* Initial buffer size */
5692 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5693 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5695 HeapFree(GetProcessHeap(), 0, DeviceId
);
5696 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5699 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5702 Result
= SetupGetStringFieldW(
5705 DeviceId
, RequiredSize
,
5710 HeapFree(GetProcessHeap(), 0, DeviceId
);
5713 DriverAlreadyAdded
= FALSE
;
5714 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5716 if (wcsicmp(DeviceId
, currentId
) == 0)
5719 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5723 currentInfFileDetails
,
5728 DriverDate
, DriverVersion
,
5729 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5730 DriverAlreadyAdded
= TRUE
;
5735 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5737 if (wcsicmp(DeviceId
, currentId
) == 0)
5740 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5744 currentInfFileDetails
,
5749 DriverDate
, DriverVersion
,
5750 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5751 DriverAlreadyAdded
= TRUE
;
5755 HeapFree(GetProcessHeap(), 0, DeviceId
);
5758 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5761 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5762 ManufacturerName
= NULL
;
5763 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5768 HeapFree(GetProcessHeap(), 0, ProviderName
);
5769 ProviderName
= NULL
;
5771 DereferenceInfFile(currentInfFileDetails
);
5772 currentInfFileDetails
= NULL
;
5783 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5784 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5788 InstallParams
.Flags
|= DI_DIDCLASS
;
5789 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5791 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5794 HeapFree(GetProcessHeap(), 0, ProviderName
);
5795 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5796 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5797 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5798 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5799 if (currentInfFileDetails
)
5800 DereferenceInfFile(currentInfFileDetails
);
5801 HeapFree(GetProcessHeap(), 0, Buffer
);
5803 TRACE("Returning %d\n", ret
);
5807 /***********************************************************************
5808 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5811 SetupDiDeleteDeviceInfo(
5812 IN HDEVINFO DeviceInfoSet
,
5813 IN PSP_DEVINFO_DATA DeviceInfoData
)
5815 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5817 FIXME("not implemented\n");
5818 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5823 /***********************************************************************
5824 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5827 SetupDiDestroyDriverInfoList(
5828 IN HDEVINFO DeviceInfoSet
,
5829 IN PSP_DEVINFO_DATA DeviceInfoData
,
5830 IN DWORD DriverType
)
5832 struct DeviceInfoSet
*list
;
5835 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5838 SetLastError(ERROR_INVALID_HANDLE
);
5839 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5840 SetLastError(ERROR_INVALID_HANDLE
);
5841 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5842 SetLastError(ERROR_INVALID_PARAMETER
);
5843 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5844 SetLastError(ERROR_INVALID_PARAMETER
);
5845 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5846 SetLastError(ERROR_INVALID_USER_BUFFER
);
5849 PLIST_ENTRY ListEntry
;
5850 struct DriverInfoElement
*driverInfo
;
5851 SP_DEVINSTALL_PARAMS_W InstallParams
;
5853 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5854 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5857 if (!DeviceInfoData
)
5858 /* Fall back to destroying class driver list */
5859 DriverType
= SPDIT_CLASSDRIVER
;
5861 if (DriverType
== SPDIT_CLASSDRIVER
)
5863 while (!IsListEmpty(&list
->DriverListHead
))
5865 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
5866 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5867 DestroyDriverInfoElement(driverInfo
);
5869 InstallParams
.Reserved
= 0;
5870 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
5871 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
5872 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
5876 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
5877 struct DeviceInfoElement
*deviceInfo
;
5879 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5880 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
5882 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5883 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
5885 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
5886 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5887 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
5889 InstallParamsSet
.Reserved
= 0;
5890 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
5892 DestroyDriverInfoElement(driverInfo
);
5894 InstallParams
.Reserved
= 0;
5895 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
5896 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
5897 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5902 TRACE("Returning %d\n", ret
);
5907 /***********************************************************************
5908 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
5911 SetupDiOpenDeviceInfoA(
5912 IN HDEVINFO DeviceInfoSet
,
5913 IN PCSTR DeviceInstanceId
,
5914 IN HWND hwndParent OPTIONAL
,
5916 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5918 LPWSTR DeviceInstanceIdW
= NULL
;
5921 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5923 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
5924 if (DeviceInstanceIdW
== NULL
)
5927 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
5928 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
5930 MyFree(DeviceInstanceIdW
);
5936 /***********************************************************************
5937 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
5940 SetupDiOpenDeviceInfoW(
5941 IN HDEVINFO DeviceInfoSet
,
5942 IN PCWSTR DeviceInstanceId
,
5943 IN HWND hwndParent OPTIONAL
,
5945 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5947 struct DeviceInfoSet
*list
;
5948 HKEY hEnumKey
, hKey
;
5952 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5954 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
5955 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
5958 SetLastError(ERROR_INVALID_HANDLE
);
5959 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5960 SetLastError(ERROR_INVALID_HANDLE
);
5961 else if (!DeviceInstanceId
)
5962 SetLastError(ERROR_INVALID_PARAMETER
);
5963 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
5965 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
5966 SetLastError(ERROR_INVALID_FLAGS
);
5968 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5969 SetLastError(ERROR_INVALID_USER_BUFFER
);
5972 struct DeviceInfoElement
*deviceInfo
= NULL
;
5973 /* Search if device already exists in DeviceInfoSet.
5974 * If yes, return the existing element
5975 * If no, create a new element using informations in registry
5977 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
5978 while (ItemList
!= &list
->ListHead
)
5983 FIXME("not implemented\n");
5984 ItemList
= ItemList
->Flink
;
5989 /* good one found */
5994 /* Open supposed registry key */
5997 REGSTR_PATH_SYSTEMENUM
,
6001 if (rc
!= ERROR_SUCCESS
)
6012 RegCloseKey(hEnumKey
);
6013 if (rc
!= ERROR_SUCCESS
)
6015 if (rc
== ERROR_FILE_NOT_FOUND
)
6016 rc
= ERROR_NO_SUCH_DEVINST
;
6021 /* FIXME: try to get ClassGUID from registry, instead of
6022 * sending GUID_NULL to CreateDeviceInfoElement
6024 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
6029 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
6035 if (ret
&& deviceInfo
&& DeviceInfoData
)
6037 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
6038 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
6039 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
6047 /***********************************************************************
6048 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6051 SetupDiEnumDriverInfoA(
6052 IN HDEVINFO DeviceInfoSet
,
6053 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6054 IN DWORD DriverType
,
6055 IN DWORD MemberIndex
,
6056 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6058 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6061 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6062 DriverType
, MemberIndex
, DriverInfoData
);
6064 if (DriverInfoData
== NULL
)
6065 SetLastError(ERROR_INVALID_PARAMETER
);
6066 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6067 SetLastError(ERROR_INVALID_USER_BUFFER
);
6070 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6071 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
6072 DriverType
, MemberIndex
, &driverInfoData2W
);
6076 /* Do W->A conversion */
6077 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6078 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6079 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6080 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6082 DriverInfoData
->Description
[0] = '\0';
6085 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6086 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6088 DriverInfoData
->MfgName
[0] = '\0';
6091 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6092 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6094 DriverInfoData
->ProviderName
[0] = '\0';
6097 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6099 /* Copy more fields */
6100 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6101 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6106 TRACE("Returning %d\n", ret
);
6111 /***********************************************************************
6112 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6115 SetupDiEnumDriverInfoW(
6116 IN HDEVINFO DeviceInfoSet
,
6117 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6118 IN DWORD DriverType
,
6119 IN DWORD MemberIndex
,
6120 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6122 PLIST_ENTRY ListHead
;
6125 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6126 DriverType
, MemberIndex
, DriverInfoData
);
6128 if (!DeviceInfoSet
|| !DriverInfoData
)
6129 SetLastError(ERROR_INVALID_PARAMETER
);
6130 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6131 SetLastError(ERROR_INVALID_HANDLE
);
6132 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6133 SetLastError(ERROR_INVALID_HANDLE
);
6134 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6135 SetLastError(ERROR_INVALID_PARAMETER
);
6136 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
6137 SetLastError(ERROR_INVALID_PARAMETER
);
6138 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6139 SetLastError(ERROR_INVALID_PARAMETER
);
6140 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6141 SetLastError(ERROR_INVALID_USER_BUFFER
);
6144 struct DeviceInfoElement
*devInfo
= NULL
;
6145 PLIST_ENTRY ItemList
;
6147 devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6148 if (DriverType
== SPDIT_CLASSDRIVER
||
6149 (devInfo
&& devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
6151 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6155 ListHead
= &devInfo
->DriverListHead
;
6158 ItemList
= ListHead
->Flink
;
6159 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
6160 ItemList
= ItemList
->Flink
;
6161 if (ItemList
== ListHead
)
6162 SetLastError(ERROR_NO_MORE_ITEMS
);
6165 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
6168 &DriverInfoData
->DriverType
,
6169 &DrvInfo
->Info
.DriverType
,
6170 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6175 TRACE("Returning %d\n", ret
);
6180 /***********************************************************************
6181 * SetupDiGetSelectedDevice (SETUPAPI.@)
6184 SetupDiGetSelectedDevice(
6185 IN HDEVINFO DeviceInfoSet
,
6186 OUT PSP_DEVINFO_DATA DeviceInfoData
)
6188 struct DeviceInfoSet
*list
;
6191 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6194 SetLastError(ERROR_INVALID_HANDLE
);
6195 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6196 SetLastError(ERROR_INVALID_HANDLE
);
6197 else if (list
->SelectedDevice
== NULL
)
6198 SetLastError(ERROR_NO_DEVICE_SELECTED
);
6199 else if (!DeviceInfoData
)
6200 SetLastError(ERROR_INVALID_PARAMETER
);
6201 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6202 SetLastError(ERROR_INVALID_USER_BUFFER
);
6205 memcpy(&DeviceInfoData
->ClassGuid
,
6206 &list
->SelectedDevice
->ClassGuid
,
6208 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
6209 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
6213 TRACE("Returning %d\n", ret
);
6218 /***********************************************************************
6219 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6222 SetupDiGetSelectedDriverA(
6223 IN HDEVINFO DeviceInfoSet
,
6224 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6225 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6227 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6230 if (DriverInfoData
== NULL
)
6231 SetLastError(ERROR_INVALID_PARAMETER
);
6232 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6233 SetLastError(ERROR_INVALID_USER_BUFFER
);
6236 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6238 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
6244 /* Do W->A conversion */
6245 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6246 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6247 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6248 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6250 DriverInfoData
->Description
[0] = '\0';
6253 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6254 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6256 DriverInfoData
->MfgName
[0] = '\0';
6259 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6260 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6262 DriverInfoData
->ProviderName
[0] = '\0';
6265 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6267 /* Copy more fields */
6268 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6269 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6278 /***********************************************************************
6279 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6282 SetupDiGetSelectedDriverW(
6283 IN HDEVINFO DeviceInfoSet
,
6284 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6285 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6289 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6291 if (!DeviceInfoSet
|| !DriverInfoData
)
6292 SetLastError(ERROR_INVALID_PARAMETER
);
6293 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6294 SetLastError(ERROR_INVALID_HANDLE
);
6295 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6296 SetLastError(ERROR_INVALID_HANDLE
);
6297 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6298 SetLastError(ERROR_INVALID_USER_BUFFER
);
6299 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6300 SetLastError(ERROR_INVALID_USER_BUFFER
);
6303 SP_DEVINSTALL_PARAMS InstallParams
;
6305 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
6306 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6308 struct DriverInfoElement
*driverInfo
;
6309 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6310 if (driverInfo
== NULL
)
6311 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6315 &DriverInfoData
->DriverType
,
6316 &driverInfo
->Info
.DriverType
,
6317 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6323 TRACE("Returning %d\n", ret
);
6328 /***********************************************************************
6329 * SetupDiSetSelectedDevice (SETUPAPI.@)
6332 SetupDiSetSelectedDevice(
6333 IN HDEVINFO DeviceInfoSet
,
6334 IN PSP_DEVINFO_DATA DeviceInfoData
)
6336 struct DeviceInfoSet
*list
;
6339 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6342 SetLastError(ERROR_INVALID_HANDLE
);
6343 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6344 SetLastError(ERROR_INVALID_HANDLE
);
6345 else if (!DeviceInfoData
)
6346 SetLastError(ERROR_INVALID_PARAMETER
);
6347 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6348 SetLastError(ERROR_INVALID_USER_BUFFER
);
6349 else if (DeviceInfoData
->Reserved
== 0)
6350 SetLastError(ERROR_INVALID_USER_BUFFER
);
6353 list
->SelectedDevice
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6357 TRACE("Returning %d\n", ret
);
6362 /***********************************************************************
6363 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6366 SetupDiSetSelectedDriverA(
6367 IN HDEVINFO DeviceInfoSet
,
6368 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6369 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6371 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6372 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6375 if (DriverInfoData
!= NULL
)
6377 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6378 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6380 SetLastError(ERROR_INVALID_PARAMETER
);
6384 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6385 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6387 if (DriverInfoDataW
.Reserved
== 0)
6389 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6391 /* convert the strings to unicode */
6392 if (!MultiByteToWideChar(CP_ACP
,
6394 DriverInfoData
->Description
,
6396 DriverInfoDataW
.Description
,
6398 !MultiByteToWideChar(CP_ACP
,
6400 DriverInfoData
->ProviderName
,
6402 DriverInfoDataW
.ProviderName
,
6409 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6412 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6416 if (ret
&& pDriverInfoDataW
!= NULL
)
6418 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6425 /***********************************************************************
6426 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6429 SetupDiSetSelectedDriverW(
6430 IN HDEVINFO DeviceInfoSet
,
6431 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6432 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6436 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6439 SetLastError(ERROR_INVALID_PARAMETER
);
6440 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6441 SetLastError(ERROR_INVALID_HANDLE
);
6442 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6443 SetLastError(ERROR_INVALID_HANDLE
);
6444 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6445 SetLastError(ERROR_INVALID_USER_BUFFER
);
6446 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6447 SetLastError(ERROR_INVALID_USER_BUFFER
);
6450 struct DriverInfoElement
**pDriverInfo
;
6451 PLIST_ENTRY ListHead
, ItemList
;
6455 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6456 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6460 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6461 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6464 if (!DriverInfoData
)
6466 *pDriverInfo
= NULL
;
6471 /* Search selected driver in list */
6472 ItemList
= ListHead
->Flink
;
6473 while (ItemList
!= ListHead
)
6475 if (DriverInfoData
->Reserved
!= 0)
6477 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6482 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6483 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
6484 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6485 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6486 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6492 if (ItemList
== ListHead
)
6493 SetLastError(ERROR_INVALID_PARAMETER
);
6496 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
6497 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6499 TRACE("Choosing driver whose rank is 0x%lx\n",
6500 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
6502 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6507 TRACE("Returning %d\n", ret
);
6511 /***********************************************************************
6512 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6515 SetupDiGetDriverInfoDetailA(
6516 IN HDEVINFO DeviceInfoSet
,
6517 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6518 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6519 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6520 IN DWORD DriverInfoDetailDataSize
,
6521 OUT PDWORD RequiredSize OPTIONAL
)
6523 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6524 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6526 DWORD HardwareIDLen
= 0;
6529 /* do some sanity checks, the unicode version might do more thorough checks */
6530 if (DriverInfoData
== NULL
||
6531 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6532 (DriverInfoDetailData
!= NULL
&&
6533 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6534 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6536 SetLastError(ERROR_INVALID_PARAMETER
);
6540 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6541 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6543 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6545 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6547 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6551 SetLastError(ERROR_INVALID_PARAMETER
);
6554 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6555 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6557 /* convert the strings to unicode */
6558 if (MultiByteToWideChar(CP_ACP
,
6560 DriverInfoData
->Description
,
6562 DriverInfoDataW
.Description
,
6564 MultiByteToWideChar(CP_ACP
,
6566 DriverInfoData
->MfgName
,
6568 DriverInfoDataW
.MfgName
,
6570 MultiByteToWideChar(CP_ACP
,
6572 DriverInfoData
->ProviderName
,
6574 DriverInfoDataW
.ProviderName
,
6577 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6579 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6580 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6583 if (DriverInfoDetailData
!= NULL
)
6585 /* calculate the unicode buffer size from the ansi buffer size */
6586 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6587 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6588 (HardwareIDLen
* sizeof(WCHAR
));
6590 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6591 if (DriverInfoDetailDataW
== NULL
)
6593 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6597 /* initialize the buffer */
6598 ZeroMemory(DriverInfoDetailDataW
,
6600 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6603 /* call the unicode version */
6604 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6607 DriverInfoDetailDataW
,
6613 if (DriverInfoDetailDataW
!= NULL
)
6615 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6616 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6617 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6618 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6619 if (WideCharToMultiByte(CP_ACP
,
6621 DriverInfoDetailDataW
->SectionName
,
6623 DriverInfoDetailData
->SectionName
,
6627 WideCharToMultiByte(CP_ACP
,
6629 DriverInfoDetailDataW
->InfFileName
,
6631 DriverInfoDetailData
->InfFileName
,
6635 WideCharToMultiByte(CP_ACP
,
6637 DriverInfoDetailDataW
->DrvDescription
,
6639 DriverInfoDetailData
->DrvDescription
,
6643 WideCharToMultiByte(CP_ACP
,
6645 DriverInfoDetailDataW
->HardwareID
,
6647 DriverInfoDetailData
->HardwareID
,
6653 DWORD hwidlen
= HardwareIDLen
;
6654 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6656 /* count the strings in the list */
6659 len
= lstrlenA(s
) + 1;
6668 /* looks like the string list wasn't terminated... */
6669 SetLastError(ERROR_INVALID_USER_BUFFER
);
6675 /* make sure CompatIDsOffset points to the second string in the
6679 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6680 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6681 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6685 DriverInfoDetailData
->CompatIDsOffset
= 0;
6686 DriverInfoDetailData
->CompatIDsLength
= 0;
6695 if (RequiredSize
!= NULL
)
6697 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6698 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6704 if (DriverInfoDetailDataW
!= NULL
)
6706 MyFree(DriverInfoDetailDataW
);
6712 /***********************************************************************
6713 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6716 SetupDiGetDriverInfoDetailW(
6717 IN HDEVINFO DeviceInfoSet
,
6718 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6719 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6720 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6721 IN DWORD DriverInfoDetailDataSize
,
6722 OUT PDWORD RequiredSize OPTIONAL
)
6726 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6727 DriverInfoData
, DriverInfoDetailData
,
6728 DriverInfoDetailDataSize
, RequiredSize
);
6731 SetLastError(ERROR_INVALID_PARAMETER
);
6732 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6733 SetLastError(ERROR_INVALID_HANDLE
);
6734 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6735 SetLastError(ERROR_INVALID_HANDLE
);
6736 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6737 SetLastError(ERROR_INVALID_USER_BUFFER
);
6738 else if (!DriverInfoData
)
6739 SetLastError(ERROR_INVALID_PARAMETER
);
6740 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6741 SetLastError(ERROR_INVALID_PARAMETER
);
6742 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6743 SetLastError(ERROR_INVALID_PARAMETER
);
6744 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6745 SetLastError(ERROR_INVALID_USER_BUFFER
);
6746 else if (DriverInfoData
->Reserved
== 0)
6747 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6750 struct DriverInfoElement
*driverInfoElement
;
6751 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6754 DriverInfoDetailData
,
6755 &driverInfoElement
->Details
,
6756 driverInfoElement
->Details
.cbSize
);
6757 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6758 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6763 TRACE("Returning %d\n", ret
);
6767 /* Return the current hardware profile id, or -1 if error */
6769 GetCurrentHwProfile(
6770 IN HDEVINFO DeviceInfoSet
)
6772 HKEY hKey
= INVALID_HANDLE_VALUE
;
6773 DWORD dwRegType
, dwLength
;
6776 DWORD ret
= (DWORD
)-1;
6779 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
6780 REGSTR_PATH_IDCONFIGDB
,
6784 if (rc
!= ERROR_SUCCESS
)
6790 dwLength
= sizeof(DWORD
);
6791 rc
= RegQueryValueExW(
6793 REGSTR_VAL_CURRENTCONFIG
,
6796 (LPBYTE
)&hwProfile
, &dwLength
);
6797 if (rc
!= ERROR_SUCCESS
)
6802 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6804 SetLastError(ERROR_GEN_FAILURE
);
6811 if (hKey
!= INVALID_HANDLE_VALUE
)
6819 IN HDEVINFO DeviceInfoSet
,
6820 IN PSP_DEVINFO_DATA DeviceInfoData
)
6822 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6823 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6826 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
6828 /* At the moment, I only know how to start local devices */
6829 SetLastError(ERROR_INVALID_COMPUTERNAME
);
6833 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
6834 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6835 SetLastError(RtlNtStatusToDosError(Status
));
6836 return NT_SUCCESS(Status
);
6839 static BOOL
StopDevice(
6840 IN HDEVINFO DeviceInfoSet
,
6841 IN PSP_DEVINFO_DATA DeviceInfoData
)
6843 FIXME("Stub %p %p\n", DeviceInfoSet
, DeviceInfoData
);
6847 /***********************************************************************
6848 * SetupDiChangeState (SETUPAPI.@)
6852 IN HDEVINFO DeviceInfoSet
,
6853 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6855 PSP_PROPCHANGE_PARAMS PropChange
;
6856 HKEY hKey
= INVALID_HANDLE_VALUE
;
6857 LPCWSTR RegistryValueName
;
6858 DWORD dwConfigFlags
, dwLength
, dwRegType
;
6862 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6864 if (!DeviceInfoData
)
6865 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
6867 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
6870 SetLastError(ERROR_INVALID_PARAMETER
);
6874 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
6875 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
6877 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
6879 switch (PropChange
->StateChange
)
6884 /* Enable/disable device in registry */
6885 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
6886 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6887 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
6888 if (hKey
== INVALID_HANDLE_VALUE
)
6890 dwLength
= sizeof(DWORD
);
6891 rc
= RegQueryValueExW(
6896 (LPBYTE
)&dwConfigFlags
, &dwLength
);
6897 if (rc
== ERROR_FILE_NOT_FOUND
)
6899 else if (rc
!= ERROR_SUCCESS
)
6904 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6906 SetLastError(ERROR_GEN_FAILURE
);
6909 if (PropChange
->StateChange
== DICS_ENABLE
)
6910 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6912 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6918 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
6919 if (rc
!= ERROR_SUCCESS
)
6925 /* Enable/disable device if needed */
6926 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
6927 || PropChange
->HwProfile
== 0
6928 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
6930 if (PropChange
->StateChange
== DICS_ENABLE
)
6931 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6933 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
6939 case DICS_PROPCHANGE
:
6941 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6946 FIXME("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
6947 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
6952 if (hKey
!= INVALID_HANDLE_VALUE
)
6955 TRACE("Returning %d\n", ret
);
6959 /***********************************************************************
6960 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
6963 SetupDiSelectBestCompatDrv(
6964 IN HDEVINFO DeviceInfoSet
,
6965 IN PSP_DEVINFO_DATA DeviceInfoData
)
6967 SP_DRVINFO_DATA_W drvInfoData
;
6970 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6972 /* Drivers are sorted by rank in the driver list, so
6973 * the first driver in the list is the best one.
6975 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
6976 ret
= SetupDiEnumDriverInfoW(
6980 0, /* Member index */
6985 ret
= SetupDiSetSelectedDriverW(
6991 TRACE("Returning %d\n", ret
);
6995 /***********************************************************************
6996 * SetupDiInstallDriverFiles (SETUPAPI.@)
6999 SetupDiInstallDriverFiles(
7000 IN HDEVINFO DeviceInfoSet
,
7001 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7005 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7008 SetLastError(ERROR_INVALID_PARAMETER
);
7009 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7010 SetLastError(ERROR_INVALID_HANDLE
);
7011 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7012 SetLastError(ERROR_INVALID_HANDLE
);
7013 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7014 SetLastError(ERROR_INVALID_USER_BUFFER
);
7015 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
7016 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7017 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
7018 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7021 SP_DEVINSTALL_PARAMS_W InstallParams
;
7022 struct DriverInfoElement
*SelectedDriver
;
7023 WCHAR SectionName
[MAX_PATH
];
7024 DWORD SectionNameLength
= 0;
7025 PVOID InstallMsgHandler
;
7026 PVOID InstallMsgHandlerContext
;
7027 PVOID Context
= NULL
;
7029 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7030 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7034 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7035 if (!SelectedDriver
)
7037 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7041 ret
= SetupDiGetActualSectionToInstallW(
7042 SelectedDriver
->InfFileDetails
->hInf
,
7043 SelectedDriver
->Details
.SectionName
,
7044 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
7048 if (InstallParams
.InstallMsgHandler
)
7050 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
7051 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
7055 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7058 InstallMsgHandler
= SetupDefaultQueueCallback
;
7059 InstallMsgHandlerContext
= Context
;
7061 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7062 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7063 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7064 InstallMsgHandler
, InstallMsgHandlerContext
,
7065 DeviceInfoSet
, DeviceInfoData
);
7069 /* Install files from .CoInstallers section */
7070 lstrcatW(SectionName
, DotCoInstallers
);
7071 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7072 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7073 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7074 InstallMsgHandler
, InstallMsgHandlerContext
,
7075 DeviceInfoSet
, DeviceInfoData
);
7079 /* Set the DI_NOFILECOPY flag to prevent another
7080 * installation during SetupDiInstallDevice */
7081 InstallParams
.Flags
|= DI_NOFILECOPY
;
7082 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7086 SetupTermDefaultQueueCallback(Context
);
7090 TRACE("Returning %d\n", ret
);
7094 /***********************************************************************
7095 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7098 SetupDiRegisterCoDeviceInstallers(
7099 IN HDEVINFO DeviceInfoSet
,
7100 IN PSP_DEVINFO_DATA DeviceInfoData
)
7102 BOOL ret
= FALSE
; /* Return value */
7104 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7107 SetLastError(ERROR_INVALID_PARAMETER
);
7108 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7109 SetLastError(ERROR_INVALID_HANDLE
);
7110 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7111 SetLastError(ERROR_INVALID_HANDLE
);
7112 else if (!DeviceInfoData
)
7113 SetLastError(ERROR_INVALID_PARAMETER
);
7114 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7115 SetLastError(ERROR_INVALID_USER_BUFFER
);
7118 SP_DEVINSTALL_PARAMS_W InstallParams
;
7119 struct DriverInfoElement
*SelectedDriver
;
7122 WCHAR SectionName
[MAX_PATH
];
7123 DWORD SectionNameLength
= 0;
7124 HKEY hKey
= INVALID_HANDLE_VALUE
;
7125 PVOID Context
= NULL
;
7127 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7128 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7132 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7133 if (SelectedDriver
== NULL
)
7135 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7139 /* Get .CoInstallers section name */
7140 Result
= SetupDiGetActualSectionToInstallW(
7141 SelectedDriver
->InfFileDetails
->hInf
,
7142 SelectedDriver
->Details
.SectionName
,
7143 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7144 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
7146 lstrcatW(SectionName
, DotCoInstallers
);
7148 /* Open/Create driver key information */
7149 #if _WIN32_WINNT >= 0x502
7150 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7152 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7154 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7155 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7156 if (hKey
== INVALID_HANDLE_VALUE
)
7159 /* Install .CoInstallers section */
7160 DoAction
= SPINST_REGISTRY
;
7161 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7163 DoAction
|= SPINST_FILES
;
7164 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7168 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7169 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7170 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7171 SetupDefaultQueueCallback
, Context
,
7172 DeviceInfoSet
, DeviceInfoData
);
7180 SetupTermDefaultQueueCallback(Context
);
7181 if (hKey
!= INVALID_HANDLE_VALUE
)
7185 TRACE("Returning %d\n", ret
);
7190 InstallOneInterface(
7191 IN LPGUID InterfaceGuid
,
7192 IN LPCWSTR ReferenceString
,
7193 IN LPCWSTR InterfaceSection
,
7194 IN UINT InterfaceFlags
)
7196 if (InterfaceFlags
!= 0)
7198 SetLastError(ERROR_INVALID_PARAMETER
);
7202 FIXME("Need to AddInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid
),
7203 debugstr_w(ReferenceString
), debugstr_w(InterfaceSection
), InterfaceFlags
);
7207 /***********************************************************************
7208 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7211 SetupDiInstallDeviceInterfaces(
7212 IN HDEVINFO DeviceInfoSet
,
7213 IN PSP_DEVINFO_DATA DeviceInfoData
)
7215 struct DeviceInfoSet
*list
= NULL
;
7218 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7221 SetLastError(ERROR_INVALID_PARAMETER
);
7222 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7223 SetLastError(ERROR_INVALID_HANDLE
);
7224 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7225 SetLastError(ERROR_INVALID_HANDLE
);
7226 else if (!DeviceInfoData
)
7227 SetLastError(ERROR_INVALID_PARAMETER
);
7228 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7229 SetLastError(ERROR_INVALID_USER_BUFFER
);
7232 struct DriverInfoElement
*SelectedDriver
;
7233 SP_DEVINSTALL_PARAMS_W InstallParams
;
7234 WCHAR SectionName
[MAX_PATH
];
7235 DWORD SectionNameLength
= 0;
7236 INFCONTEXT ContextInterface
;
7237 LPWSTR InterfaceGuidString
= NULL
;
7238 LPWSTR ReferenceString
= NULL
;
7239 LPWSTR InterfaceSection
= NULL
;
7240 UINT InterfaceFlags
;
7244 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7245 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7249 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7250 if (SelectedDriver
== NULL
)
7252 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7257 /* Get .Interfaces section name */
7258 Result
= SetupDiGetActualSectionToInstallW(
7259 SelectedDriver
->InfFileDetails
->hInf
,
7260 SelectedDriver
->Details
.SectionName
,
7261 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7262 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".Interfaces") - 1)
7264 wcscat(SectionName
, L
".Interfaces");
7267 Result
= SetupFindFirstLineW(
7268 SelectedDriver
->InfFileDetails
->hInf
,
7272 while (ret
&& Result
)
7274 ret
= GetStringField(&ContextInterface
, 1, &InterfaceGuidString
);
7277 else if (strlenW(InterfaceGuidString
) != MAX_GUID_STRING_LEN
- 1)
7279 SetLastError(ERROR_INVALID_PARAMETER
);
7284 InterfaceGuidString
[MAX_GUID_STRING_LEN
- 2] = '\0'; /* Replace the } by a NULL character */
7285 if (UuidFromStringW(&InterfaceGuidString
[1], &InterfaceGuid
) != RPC_S_OK
)
7287 /* Bad GUID, skip the entry */
7288 SetLastError(ERROR_INVALID_PARAMETER
);
7293 ret
= GetStringField(&ContextInterface
, 2, &ReferenceString
);
7297 ret
= GetStringField(&ContextInterface
, 3, &InterfaceSection
);
7301 ret
= SetupGetIntField(
7303 4, /* Field index */
7307 if (GetLastError() == ERROR_INVALID_PARAMETER
)
7309 /* The field may be empty. Ignore the error */
7317 /* Install Interface */
7318 ret
= InstallOneInterface(&InterfaceGuid
, ReferenceString
, InterfaceSection
, InterfaceFlags
);
7321 MyFree(InterfaceGuidString
);
7322 MyFree(ReferenceString
);
7323 MyFree(InterfaceSection
);
7324 InterfaceGuidString
= ReferenceString
= InterfaceSection
= NULL
;
7325 Result
= SetupFindNextMatchLineW(&ContextInterface
, L
"AddInterface", &ContextInterface
);
7329 TRACE("Returning %d\n", ret
);
7334 InfIsFromOEMLocation(
7336 OUT LPBOOL IsOEMLocation
)
7340 last
= strrchrW(FullName
, '\\');
7343 /* No directory specified */
7344 *IsOEMLocation
= FALSE
;
7348 WCHAR Windir
[MAX_PATH
];
7351 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
7352 if (ret
== 0 || ret
>= MAX_PATH
)
7354 SetLastError(ERROR_GEN_FAILURE
);
7358 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
7360 /* The path is %SYSTEMROOT%\Inf */
7361 *IsOEMLocation
= FALSE
;
7365 /* The file is in another place */
7366 *IsOEMLocation
= TRUE
;
7372 /***********************************************************************
7373 * SetupDiInstallDevice (SETUPAPI.@)
7376 SetupDiInstallDevice(
7377 IN HDEVINFO DeviceInfoSet
,
7378 IN PSP_DEVINFO_DATA DeviceInfoData
)
7380 SP_DEVINSTALL_PARAMS_W InstallParams
;
7381 struct DriverInfoElement
*SelectedDriver
;
7382 SYSTEMTIME DriverDate
;
7383 WCHAR SectionName
[MAX_PATH
];
7385 DWORD SectionNameLength
= 0;
7386 BOOL Result
= FALSE
;
7389 LPWSTR pSectionName
= NULL
;
7390 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
7392 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
7393 BOOL RebootRequired
= FALSE
;
7394 HKEY hKey
= INVALID_HANDLE_VALUE
;
7395 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
7396 BOOL NeedtoCopyFile
;
7397 LARGE_INTEGER fullVersion
;
7399 PVOID Context
= NULL
;
7400 BOOL ret
= FALSE
; /* Return value */
7402 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7405 SetLastError(ERROR_INVALID_PARAMETER
);
7406 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7407 SetLastError(ERROR_INVALID_HANDLE
);
7408 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7409 SetLastError(ERROR_INVALID_HANDLE
);
7410 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7411 SetLastError(ERROR_INVALID_USER_BUFFER
);
7417 /* One parameter is bad */
7421 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7422 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7426 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
7428 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
7432 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7433 if (SelectedDriver
== NULL
)
7435 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7439 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
7441 Result
= SetupDiGetActualSectionToInstallW(
7442 SelectedDriver
->InfFileDetails
->hInf
,
7443 SelectedDriver
->Details
.SectionName
,
7444 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7445 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(DotServices
))
7447 pSectionName
= &SectionName
[wcslen(SectionName
)];
7449 /* Get information from [Version] section */
7450 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
7452 /* Format ClassGuid to a string */
7453 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
7455 RequiredSize
= lstrlenW(lpGuidString
);
7456 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
7457 if (!lpFullGuidString
)
7459 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7462 lpFullGuidString
[0] = '{';
7463 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
7464 lpFullGuidString
[RequiredSize
+ 1] = '}';
7465 lpFullGuidString
[RequiredSize
+ 2] = '\0';
7467 /* Open/Create driver key information */
7468 #if _WIN32_WINNT >= 0x502
7469 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7471 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7473 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7474 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7475 if (hKey
== INVALID_HANDLE_VALUE
)
7478 /* Install main section */
7480 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7481 DoAction
|= SPINST_REGISTRY
;
7482 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7484 DoAction
|= SPINST_FILES
;
7485 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7489 *pSectionName
= '\0';
7490 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7491 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7492 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7493 SetupDefaultQueueCallback
, Context
,
7494 DeviceInfoSet
, DeviceInfoData
);
7497 InstallParams
.Flags
|= DI_NOFILECOPY
;
7498 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7500 /* Write information to driver key */
7501 *pSectionName
= UNICODE_NULL
;
7502 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
7503 TRACE("Write information to driver key\n");
7504 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7505 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7506 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7507 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
7508 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
7509 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
7510 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
7511 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
7512 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7513 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7514 if (rc
== ERROR_SUCCESS
)
7515 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7516 if (rc
== ERROR_SUCCESS
)
7517 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7518 if (rc
== ERROR_SUCCESS
)
7520 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7521 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7523 if (rc
== ERROR_SUCCESS
)
7524 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7525 if (rc
== ERROR_SUCCESS
)
7526 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7527 if (rc
== ERROR_SUCCESS
)
7528 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7529 if (rc
== ERROR_SUCCESS
)
7530 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7531 if (rc
== ERROR_SUCCESS
)
7532 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7533 if (rc
!= ERROR_SUCCESS
)
7539 hKey
= INVALID_HANDLE_VALUE
;
7541 /* FIXME: Process .LogConfigOverride section */
7543 /* Install .Services section */
7544 wcscpy(pSectionName
, DotServices
);
7545 Result
= SetupInstallServicesFromInfSectionExW(
7546 SelectedDriver
->InfFileDetails
->hInf
,
7555 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
7556 RebootRequired
= TRUE
;
7558 /* Copy .inf file to Inf\ directory (if needed) */
7559 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7564 Result
= SetupCopyOEMInfW(
7565 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7568 SP_COPY_NOOVERWRITE
,
7574 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7575 * to release use of current InfFile */
7578 /* Open device registry key */
7579 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7580 if (hKey
== INVALID_HANDLE_VALUE
)
7583 /* Install .HW section */
7585 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7586 DoAction
|= SPINST_REGISTRY
;
7587 wcscpy(pSectionName
, L
".HW");
7588 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7589 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7590 DoAction
, hKey
, NULL
, 0,
7592 DeviceInfoSet
, DeviceInfoData
);
7596 /* Write information to enum key */
7597 TRACE("Write information to enum key\n");
7598 TRACE("Class : '%S'\n", ClassName
);
7599 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
7600 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7601 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
7602 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
7603 if (rc
== ERROR_SUCCESS
)
7604 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7605 if (rc
== ERROR_SUCCESS
)
7606 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7607 if (rc
== ERROR_SUCCESS
)
7608 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7609 if (rc
!= ERROR_SUCCESS
)
7615 /* Start the device */
7616 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7617 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7622 /* End of installation */
7623 if (hClassKey
!= INVALID_HANDLE_VALUE
)
7624 RegCloseKey(hClassKey
);
7625 if (hKey
!= INVALID_HANDLE_VALUE
)
7628 RpcStringFreeW(&lpGuidString
);
7629 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7631 SetupTermDefaultQueueCallback(Context
);
7632 TRACE("Returning %d\n", ret
);