2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "setupapi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
26 /* Unicode constants */
27 static const WCHAR AddInterface
[] = {'A','d','d','I','n','t','e','r','f','a','c','e',0};
28 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class
[] = {'C','l','a','s','s',0};
30 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
31 static const WCHAR Control
[] = {'C','o','n','t','r','o','l',0};
32 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
33 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
34 static const WCHAR DotHW
[] = {'.','H','W',0};
35 static const WCHAR DotInterfaces
[] = {'.','I','n','t','e','r','f','a','c','e','s',0};
36 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
37 static const WCHAR InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
38 static const WCHAR Linked
[] = {'L','i','n','k','e','d',0};
39 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
40 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
42 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
43 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
44 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
45 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
46 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT
[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
48 static const WCHAR INF_MANUFACTURER
[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
49 static const WCHAR INF_PROVIDER
[] = {'P','r','o','v','i','d','e','r',0};
50 static const WCHAR INF_DRIVER_VER
[] = {'D','r','i','v','e','r','V','e','r',0};
53 (CALLBACK
* CLASS_INSTALL_PROC
) (
54 IN DI_FUNCTION InstallFunction
,
55 IN HDEVINFO DeviceInfoSet
,
56 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
58 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
59 IN HDEVINFO DeviceInfoSet
,
60 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
62 (CALLBACK
* COINSTALLER_PROC
) (
63 IN DI_FUNCTION InstallFunction
,
64 IN HDEVINFO DeviceInfoSet
,
65 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
66 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
68 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
69 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
70 IN LPFNADDPROPSHEETPAGE fAddFunc
,
73 (*UPDATE_CLASS_PARAM_HANDLER
) (
74 IN HDEVINFO DeviceInfoSet
,
75 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
76 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
77 IN DWORD ClassInstallParamsSize
);
79 struct CoInstallerElement
84 COINSTALLER_PROC Function
;
85 BOOL DoPostProcessing
;
90 PropertyChangeHandler(
91 IN HDEVINFO DeviceInfoSet
,
92 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
93 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
94 IN DWORD ClassInstallParamsSize
);
96 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
97 NULL
, /* DIF_SELECTDEVICE */
98 NULL
, /* DIF_INSTALLDEVICE */
99 NULL
, /* DIF_ASSIGNRESOURCES */
100 NULL
, /* DIF_PROPERTIES */
101 NULL
, /* DIF_REMOVE */
102 NULL
, /* DIF_FIRSTTIMESETUP */
103 NULL
, /* DIF_FOUNDDEVICE */
104 NULL
, /* DIF_SELECTCLASSDRIVERS */
105 NULL
, /* DIF_VALIDATECLASSDRIVERS */
106 NULL
, /* DIF_INSTALLCLASSDRIVERS */
107 NULL
, /* DIF_CALCDISKSPACE */
108 NULL
, /* DIF_DESTROYPRIVATEDATA */
109 NULL
, /* DIF_VALIDATEDRIVER */
110 NULL
, /* DIF_MOVEDEVICE */
111 NULL
, /* DIF_DETECT */
112 NULL
, /* DIF_INSTALLWIZARD */
113 NULL
, /* DIF_DESTROYWIZARDDATA */
114 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
115 NULL
, /* DIF_ENABLECLASS */
116 NULL
, /* DIF_DETECTVERIFY */
117 NULL
, /* DIF_INSTALLDEVICEFILES */
118 NULL
, /* DIF_UNREMOVE */
119 NULL
, /* DIF_SELECTBESTCOMPATDRV */
120 NULL
, /* DIF_ALLOW_INSTALL */
121 NULL
, /* DIF_REGISTERDEVICE */
122 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
123 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
124 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
125 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
126 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
127 NULL
, /* DIF_UNUSED1 */
128 NULL
, /* DIF_INSTALLINTERFACES */
129 NULL
, /* DIF_DETECTCANCEL */
130 NULL
, /* DIF_REGISTER_COINSTALLERS */
131 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
132 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
133 NULL
, /* DIF_RESERVED1 */
134 NULL
, /* DIF_TROUBLESHOOTER */
135 NULL
, /* DIF_POWERMESSAGEWAKE */
136 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
137 NULL
, /* DIF_UPDATEDRIVER_UI */
138 NULL
/* DIF_RESERVED2 */
141 /***********************************************************************
142 * SetupDiBuildClassInfoList (SETUPAPI.@)
144 BOOL WINAPI
SetupDiBuildClassInfoList(
146 LPGUID ClassGuidList
,
147 DWORD ClassGuidListSize
,
151 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
152 ClassGuidListSize
, RequiredSize
,
156 /***********************************************************************
157 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
159 BOOL WINAPI
SetupDiBuildClassInfoListExA(
161 LPGUID ClassGuidList
,
162 DWORD ClassGuidListSize
,
167 LPWSTR MachineNameW
= NULL
;
174 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
175 if (MachineNameW
== NULL
) return FALSE
;
178 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
179 ClassGuidListSize
, RequiredSize
,
180 MachineNameW
, Reserved
);
183 MyFree(MachineNameW
);
188 /***********************************************************************
189 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
191 BOOL WINAPI
SetupDiBuildClassInfoListExW(
193 LPGUID ClassGuidList
,
194 DWORD ClassGuidListSize
,
199 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
205 DWORD dwGuidListIndex
= 0;
207 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
208 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
210 if (RequiredSize
!= NULL
)
213 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
214 KEY_ENUMERATE_SUB_KEYS
,
218 if (hClassesKey
== INVALID_HANDLE_VALUE
)
223 for (dwIndex
= 0; ; dwIndex
++)
225 dwLength
= MAX_GUID_STRING_LEN
+ 1;
226 lError
= RegEnumKeyExW(hClassesKey
,
234 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
235 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
237 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
239 if (RegOpenKeyExW(hClassesKey
,
245 RegCloseKey(hClassesKey
);
249 if (!RegQueryValueExW(hClassKey
,
250 REGSTR_VAL_NOUSECLASS
,
256 TRACE("'NoUseClass' value found!\n");
257 RegCloseKey(hClassKey
);
261 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
262 (!RegQueryValueExW(hClassKey
,
263 REGSTR_VAL_NOINSTALLCLASS
,
269 TRACE("'NoInstallClass' value found!\n");
270 RegCloseKey(hClassKey
);
274 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
275 (!RegQueryValueExW(hClassKey
,
276 REGSTR_VAL_NODISPLAYCLASS
,
282 TRACE("'NoDisplayClass' value found!\n");
283 RegCloseKey(hClassKey
);
287 RegCloseKey(hClassKey
);
289 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
290 if (dwGuidListIndex
< ClassGuidListSize
)
292 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
296 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
298 UuidFromStringW(&szKeyName
[1],
299 &ClassGuidList
[dwGuidListIndex
]);
305 if (lError
!= ERROR_SUCCESS
)
309 RegCloseKey(hClassesKey
);
311 if (RequiredSize
!= NULL
)
312 *RequiredSize
= dwGuidListIndex
;
314 if (ClassGuidListSize
< dwGuidListIndex
)
316 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
323 /***********************************************************************
324 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
326 BOOL WINAPI
SetupDiClassGuidsFromNameA(
328 LPGUID ClassGuidList
,
329 DWORD ClassGuidListSize
,
332 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
333 ClassGuidListSize
, RequiredSize
,
337 /***********************************************************************
338 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
340 BOOL WINAPI
SetupDiClassGuidsFromNameW(
342 LPGUID ClassGuidList
,
343 DWORD ClassGuidListSize
,
346 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
347 ClassGuidListSize
, RequiredSize
,
351 /***********************************************************************
352 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
354 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
356 LPGUID ClassGuidList
,
357 DWORD ClassGuidListSize
,
362 LPWSTR ClassNameW
= NULL
;
363 LPWSTR MachineNameW
= NULL
;
368 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
369 if (ClassNameW
== NULL
)
374 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
375 if (MachineNameW
== NULL
)
382 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
383 ClassGuidListSize
, RequiredSize
,
384 MachineNameW
, Reserved
);
387 MyFree(MachineNameW
);
394 /***********************************************************************
395 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
397 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
399 LPGUID ClassGuidList
,
400 DWORD ClassGuidListSize
,
405 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
406 WCHAR szClassName
[256];
412 DWORD dwGuidListIndex
= 0;
414 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
415 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
417 if (RequiredSize
!= NULL
)
420 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
421 KEY_ENUMERATE_SUB_KEYS
,
425 if (hClassesKey
== INVALID_HANDLE_VALUE
)
430 for (dwIndex
= 0; ; dwIndex
++)
432 dwLength
= MAX_GUID_STRING_LEN
+ 1;
433 lError
= RegEnumKeyExW(hClassesKey
,
441 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
442 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
444 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
446 if (RegOpenKeyExW(hClassesKey
,
452 RegCloseKey(hClassesKey
);
456 dwLength
= 256 * sizeof(WCHAR
);
457 if (!RegQueryValueExW(hClassKey
,
464 TRACE("Class name: %s\n", debugstr_w(szClassName
));
466 if (strcmpiW(szClassName
, ClassName
) == 0)
468 TRACE("Found matching class name\n");
470 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
471 if (dwGuidListIndex
< ClassGuidListSize
)
473 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
477 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
479 UuidFromStringW(&szKeyName
[1],
480 &ClassGuidList
[dwGuidListIndex
]);
487 RegCloseKey(hClassKey
);
490 if (lError
!= ERROR_SUCCESS
)
494 RegCloseKey(hClassesKey
);
496 if (RequiredSize
!= NULL
)
497 *RequiredSize
= dwGuidListIndex
;
499 if (ClassGuidListSize
< dwGuidListIndex
)
501 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
508 /***********************************************************************
509 * SetupDiClassNameFromGuidA (SETUPAPI.@)
511 BOOL WINAPI
SetupDiClassNameFromGuidA(
512 const GUID
* ClassGuid
,
517 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
518 ClassNameSize
, RequiredSize
,
522 /***********************************************************************
523 * SetupDiClassNameFromGuidW (SETUPAPI.@)
525 BOOL WINAPI
SetupDiClassNameFromGuidW(
526 const GUID
* ClassGuid
,
531 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
532 ClassNameSize
, RequiredSize
,
536 /***********************************************************************
537 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
539 BOOL WINAPI
SetupDiClassNameFromGuidExA(
540 const GUID
* ClassGuid
,
547 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
548 LPWSTR MachineNameW
= NULL
;
552 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
553 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
554 NULL
, MachineNameW
, Reserved
);
557 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
558 ClassNameSize
, NULL
, NULL
);
560 if (!ClassNameSize
&& RequiredSize
)
563 MyFree(MachineNameW
);
567 /***********************************************************************
568 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
570 BOOL WINAPI
SetupDiClassNameFromGuidExW(
571 const GUID
* ClassGuid
,
582 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
583 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
585 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
590 if (hKey
== INVALID_HANDLE_VALUE
)
595 if (RequiredSize
!= NULL
)
598 rc
= RegQueryValueExW(hKey
,
604 if (rc
!= ERROR_SUCCESS
)
611 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
614 dwLength
= ClassNameSize
* sizeof(WCHAR
);
615 rc
= RegQueryValueExW(hKey
,
621 if (rc
!= ERROR_SUCCESS
)
633 /***********************************************************************
634 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
637 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
640 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
643 /***********************************************************************
644 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
647 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
652 LPWSTR MachineNameW
= NULL
;
655 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
656 debugstr_a(MachineName
), Reserved
);
660 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
661 if (MachineNameW
== NULL
)
662 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
665 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
666 MachineNameW
, Reserved
);
669 MyFree(MachineNameW
);
675 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
679 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
680 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
681 case CR_SUCCESS
: return ERROR_SUCCESS
;
684 return ERROR_GEN_FAILURE
;
687 /* Does not happen */
690 /***********************************************************************
691 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
694 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
699 struct DeviceInfoSet
*list
;
700 LPWSTR UNCServerName
= NULL
;
704 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
706 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
707 debugstr_w(MachineName
), Reserved
);
709 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
711 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
712 list
= HeapAlloc(GetProcessHeap(), 0, size
);
715 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
718 memset(list
, 0, sizeof(struct DeviceInfoSet
));
720 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
723 ClassGuid
? ClassGuid
: &GUID_NULL
,
724 sizeof(list
->ClassGuid
));
725 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
726 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
727 list
->InstallParams
.hwndParent
= hwndParent
;
730 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
731 if (rc
!= ERROR_SUCCESS
)
736 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
739 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
743 strcpyW(UNCServerName
+ 2, MachineName
);
744 list
->szData
[0] = list
->szData
[1] = '\\';
745 strcpyW(list
->szData
+ 2, MachineName
);
746 list
->MachineName
= list
->szData
;
750 DWORD Size
= MAX_PATH
;
751 list
->HKLM
= HKEY_LOCAL_MACHINE
;
752 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
755 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
758 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
760 list
->MachineName
= NULL
;
763 UNCServerName
[0] = UNCServerName
[1] = '\\';
764 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
765 if (cr
!= CR_SUCCESS
)
767 SetLastError(GetErrorCodeFromCrCode(cr
));
771 InitializeListHead(&list
->DriverListHead
);
772 InitializeListHead(&list
->ListHead
);
774 ret
= (HDEVINFO
)list
;
777 if (ret
== INVALID_HANDLE_VALUE
)
779 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
780 RegCloseKey(list
->HKLM
);
781 HeapFree(GetProcessHeap(), 0, list
);
783 HeapFree(GetProcessHeap(), 0, UNCServerName
);
787 /***********************************************************************
788 * SetupDiEnumDeviceInfo (SETUPAPI.@)
790 BOOL WINAPI
SetupDiEnumDeviceInfo(
791 HDEVINFO DeviceInfoSet
,
793 PSP_DEVINFO_DATA DeviceInfoData
)
797 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
799 SetLastError(ERROR_INVALID_PARAMETER
);
800 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
802 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
804 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
805 SetLastError(ERROR_INVALID_HANDLE
);
806 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
807 SetLastError(ERROR_INVALID_USER_BUFFER
);
810 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
811 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
812 ItemList
= ItemList
->Flink
;
813 if (ItemList
== &list
->ListHead
)
814 SetLastError(ERROR_NO_MORE_ITEMS
);
817 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
818 memcpy(&DeviceInfoData
->ClassGuid
,
821 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
822 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
828 SetLastError(ERROR_INVALID_HANDLE
);
832 /***********************************************************************
833 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
836 SetupDiGetActualSectionToInstallA(
838 IN PCSTR InfSectionName
,
839 OUT PSTR InfSectionWithExt OPTIONAL
,
840 IN DWORD InfSectionWithExtSize
,
841 OUT PDWORD RequiredSize OPTIONAL
,
842 OUT PSTR
*Extension OPTIONAL
)
844 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
845 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
849 /***********************************************************************
850 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
853 SetupDiGetActualSectionToInstallW(
855 IN PCWSTR InfSectionName
,
856 OUT PWSTR InfSectionWithExt OPTIONAL
,
857 IN DWORD InfSectionWithExtSize
,
858 OUT PDWORD RequiredSize OPTIONAL
,
859 OUT PWSTR
*Extension OPTIONAL
)
861 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
862 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
866 /***********************************************************************
867 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
870 SetupDiGetActualSectionToInstallExA(
872 IN PCSTR InfSectionName
,
873 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
874 OUT PSTR InfSectionWithExt OPTIONAL
,
875 IN DWORD InfSectionWithExtSize
,
876 OUT PDWORD RequiredSize OPTIONAL
,
877 OUT PSTR
* Extension OPTIONAL
,
880 LPWSTR InfSectionNameW
= NULL
;
881 LPWSTR InfSectionWithExtW
= NULL
;
883 BOOL bResult
= FALSE
;
889 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
890 if (InfSectionNameW
== NULL
)
893 if (InfSectionWithExt
)
895 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
896 if (InfSectionWithExtW
== NULL
)
900 bResult
= SetupDiGetActualSectionToInstallExW(
901 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
902 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
903 InfSectionWithExtSize
,
905 Extension
? &ExtensionW
: NULL
,
908 if (bResult
&& InfSectionWithExt
)
910 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
911 InfSectionWithExtSize
, NULL
, NULL
) != 0;
913 if (bResult
&& Extension
)
915 if (ExtensionW
== NULL
)
918 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
922 MyFree(InfSectionNameW
);
923 MyFree(InfSectionWithExtW
);
928 /***********************************************************************
929 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
932 SetupDiGetActualSectionToInstallExW(
934 IN PCWSTR InfSectionName
,
935 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
936 OUT PWSTR InfSectionWithExt OPTIONAL
,
937 IN DWORD InfSectionWithExtSize
,
938 OUT PDWORD RequiredSize OPTIONAL
,
939 OUT PWSTR
* Extension OPTIONAL
,
944 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
945 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
946 RequiredSize
, Extension
, Reserved
);
948 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
949 SetLastError(ERROR_INVALID_HANDLE
);
950 else if (!InfSectionName
)
951 SetLastError(ERROR_INVALID_PARAMETER
);
952 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
953 SetLastError(ERROR_INVALID_USER_BUFFER
);
954 else if (Reserved
!= NULL
)
955 SetLastError(ERROR_INVALID_PARAMETER
);
958 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
959 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
960 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
961 WCHAR SectionName
[LINE_LEN
+ 1];
962 LONG lLineCount
= -1;
965 /* Fill platform info if needed */
966 if (AlternatePlatformInfo
)
967 pPlatformInfo
= AlternatePlatformInfo
;
968 else if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
970 /* That's the first time we go here. We need to fill in the structure */
971 OSVERSIONINFO VersionInfo
;
972 SYSTEM_INFO SystemInfo
;
973 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
974 ret
= GetVersionEx(&VersionInfo
);
977 GetSystemInfo(&SystemInfo
);
978 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
979 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
980 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
981 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
982 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
983 CurrentPlatform
.Reserved
= 0;
986 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
987 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
988 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
990 static const WCHAR ExtensionArchitectureNone
[] = {0};
991 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
992 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
993 static const WCHAR ExtensionArchitectureia64
[] = {'i','a','6','4',0};
994 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
995 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
996 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
998 /* Set various extensions values */
999 switch (pPlatformInfo
->Platform
)
1001 case VER_PLATFORM_WIN32_WINDOWS
:
1002 pExtensionPlatform
= ExtensionPlatformWindows
;
1004 case VER_PLATFORM_WIN32_NT
:
1005 pExtensionPlatform
= ExtensionPlatformNT
;
1008 ERR("Unkown platform 0x%lx\n", pPlatformInfo
->Platform
);
1009 pExtensionPlatform
= ExtensionPlatformNone
;
1012 switch (pPlatformInfo
->ProcessorArchitecture
)
1014 case PROCESSOR_ARCHITECTURE_ALPHA
:
1015 pExtensionArchitecture
= ExtensionArchitecturealpha
;
1017 case PROCESSOR_ARCHITECTURE_AMD64
:
1018 pExtensionArchitecture
= ExtensionArchitectureamd64
;
1020 case PROCESSOR_ARCHITECTURE_IA64
:
1021 pExtensionArchitecture
= ExtensionArchitectureia64
;
1023 case PROCESSOR_ARCHITECTURE_INTEL
:
1024 pExtensionArchitecture
= ExtensionArchitecturex86
;
1026 case PROCESSOR_ARCHITECTURE_MIPS
:
1027 pExtensionArchitecture
= ExtensionArchitecturemips
;
1029 case PROCESSOR_ARCHITECTURE_PPC
:
1030 pExtensionArchitecture
= ExtensionArchitectureppc
;
1033 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo
->ProcessorArchitecture
);
1034 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
1035 pExtensionArchitecture
= ExtensionArchitectureNone
;
1039 static const WCHAR FormatPlatformArchitectureMajorMinor
[] = {'%','s','%','s','%','s','.','%','l','u','.','%','l','u',0};
1040 static const WCHAR FormatPlatformMajorMinor
[] = {'%','s','%','s','.','%','l','u','.','%','l','u',0};
1041 static const WCHAR FormatPlatformArchitectureMajor
[] = {'%','s','%','s','%','s','.','%','l','u',0};
1042 static const WCHAR FormatPlatformMajor
[] = {'%','s','%','s','.','%','l','u',0};
1043 static const WCHAR FormatPlatformArchitecture
[] = {'%','s','%','s','%','s',0};
1044 static const WCHAR FormatPlatform
[] = {'%','s','%','s',0};
1045 static const WCHAR FormatNone
[] = {'%','s',0};
1047 SectionName
[LINE_LEN
] = UNICODE_NULL
;
1049 /* Test with platform.architecture.major.minor extension */
1050 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitectureMajorMinor
, InfSectionName
,
1051 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1052 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1053 if (lLineCount
!= -1) goto sectionfound
;
1055 /* Test with platform.major.minor extension */
1056 snprintfW(SectionName
, LINE_LEN
, FormatPlatformMajorMinor
, InfSectionName
,
1057 pExtensionPlatform
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1058 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1059 if (lLineCount
!= -1) goto sectionfound
;
1061 /* Test with platform.architecture.major extension */
1062 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitectureMajor
, InfSectionName
,
1063 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
);
1064 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1065 if (lLineCount
!= -1) goto sectionfound
;
1067 /* Test with platform.major extension */
1068 snprintfW(SectionName
, LINE_LEN
, FormatPlatformMajor
, InfSectionName
,
1069 pExtensionPlatform
, pPlatformInfo
->MajorVersion
);
1070 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1071 if (lLineCount
!= -1) goto sectionfound
;
1073 /* Test with platform.architecture extension */
1074 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitecture
, InfSectionName
,
1075 pExtensionPlatform
, pExtensionArchitecture
);
1076 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1077 if (lLineCount
!= -1) goto sectionfound
;
1079 /* Test with platform extension */
1080 snprintfW(SectionName
, LINE_LEN
, FormatPlatform
, InfSectionName
,
1081 pExtensionPlatform
);
1082 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1083 if (lLineCount
!= -1) goto sectionfound
;
1085 /* Test without extension */
1086 snprintfW(SectionName
, LINE_LEN
, FormatNone
, InfSectionName
);
1087 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1088 if (lLineCount
!= -1) goto sectionfound
;
1090 /* No appropriate section found */
1091 SetLastError(ERROR_INVALID_PARAMETER
);
1095 dwFullLength
= lstrlenW(SectionName
);
1096 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
1098 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
1100 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1104 lstrcpyW(InfSectionWithExt
, SectionName
);
1105 if (Extension
!= NULL
)
1107 DWORD dwLength
= lstrlenW(SectionName
);
1108 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1112 if (RequiredSize
!= NULL
)
1113 *RequiredSize
= dwFullLength
+ 1;
1119 TRACE("Returning %d\n", ret
);
1124 /***********************************************************************
1125 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1127 BOOL WINAPI
SetupDiGetClassDescriptionA(
1128 const GUID
* ClassGuid
,
1129 PSTR ClassDescription
,
1130 DWORD ClassDescriptionSize
,
1131 PDWORD RequiredSize
)
1133 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1134 ClassDescriptionSize
,
1135 RequiredSize
, NULL
, NULL
);
1138 /***********************************************************************
1139 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1141 BOOL WINAPI
SetupDiGetClassDescriptionW(
1142 const GUID
* ClassGuid
,
1143 PWSTR ClassDescription
,
1144 DWORD ClassDescriptionSize
,
1145 PDWORD RequiredSize
)
1147 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1148 ClassDescriptionSize
,
1149 RequiredSize
, NULL
, NULL
);
1152 /***********************************************************************
1153 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1155 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1156 const GUID
* ClassGuid
,
1157 PSTR ClassDescription
,
1158 DWORD ClassDescriptionSize
,
1159 PDWORD RequiredSize
,
1163 PWCHAR ClassDescriptionW
;
1164 LPWSTR MachineNameW
= NULL
;
1168 if (ClassDescriptionSize
> 0)
1170 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1171 if (!ClassDescriptionW
)
1173 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1179 ClassDescriptionW
= NULL
;
1183 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1186 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1192 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1193 NULL
, MachineNameW
, Reserved
);
1196 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1197 ClassDescriptionSize
, NULL
, NULL
);
1199 if (!ClassDescriptionSize
&& RequiredSize
)
1200 *RequiredSize
= len
;
1204 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1205 MyFree(MachineNameW
);
1209 /***********************************************************************
1210 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1212 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1213 const GUID
* ClassGuid
,
1214 PWSTR ClassDescription
,
1215 DWORD ClassDescriptionSize
,
1216 PDWORD RequiredSize
,
1223 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1224 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1226 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1231 if (hKey
== INVALID_HANDLE_VALUE
)
1233 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1237 if (RequiredSize
!= NULL
)
1240 if (RegQueryValueExW(hKey
,
1251 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1254 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1255 if (RegQueryValueExW(hKey
,
1259 (LPBYTE
)ClassDescription
,
1271 /***********************************************************************
1272 * SetupDiGetClassDevsA (SETUPAPI.@)
1274 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1280 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1281 flags
, NULL
, NULL
, NULL
);
1284 /***********************************************************************
1285 * SetupDiGetClassDevsW (SETUPAPI.@)
1287 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1293 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1294 flags
, NULL
, NULL
, NULL
);
1297 /***********************************************************************
1298 * SetupDiGetClassDevsExA (SETUPAPI.@)
1300 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1310 LPWSTR enumstrW
= NULL
;
1311 LPWSTR machineW
= NULL
;
1315 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1316 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1319 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1322 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1326 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1327 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1330 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1333 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1335 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1338 HeapFree(GetProcessHeap(), 0, enumstrW
);
1339 HeapFree(GetProcessHeap(), 0, machineW
);
1344 CreateDeviceInfoElement(
1345 IN
struct DeviceInfoSet
*list
,
1346 IN LPCWSTR InstancePath
,
1347 IN LPCGUID pClassGuid
,
1348 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1352 struct DeviceInfoElement
*deviceInfo
;
1354 *pDeviceInfo
= NULL
;
1356 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
1357 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1360 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1363 memset(deviceInfo
, 0, size
);
1365 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1366 if (cr
!= CR_SUCCESS
)
1368 SetLastError(GetErrorCodeFromCrCode(cr
));
1372 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1373 strcpyW(deviceInfo
->Data
, InstancePath
);
1374 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1375 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
1376 deviceInfo
->DeviceDescription
= NULL
;
1377 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1378 deviceInfo
->CreationFlags
= 0;
1379 InitializeListHead(&deviceInfo
->DriverListHead
);
1380 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1382 *pDeviceInfo
= deviceInfo
;
1387 CreateDeviceInterface(
1388 IN
struct DeviceInfoElement
* deviceInfo
,
1389 IN LPCWSTR SymbolicLink
,
1390 IN LPCGUID pInterfaceGuid
,
1391 OUT
struct DeviceInterface
**pDeviceInterface
)
1393 struct DeviceInterface
*deviceInterface
;
1395 *pDeviceInterface
= NULL
;
1397 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1398 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (strlenW(SymbolicLink
) + 1) * sizeof(WCHAR
));
1399 if (!deviceInterface
)
1401 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1404 deviceInterface
->DeviceInfo
= deviceInfo
;
1405 strcpyW(deviceInterface
->SymbolicLink
, SymbolicLink
);
1406 deviceInterface
->Flags
= 0; /* FIXME */
1407 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1409 *pDeviceInterface
= deviceInterface
;
1413 static LONG
SETUP_CreateDevListFromEnumerator(
1414 struct DeviceInfoSet
*list
,
1415 LPCGUID pClassGuid OPTIONAL
,
1417 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1419 HKEY hDeviceIdKey
, hInstanceIdKey
;
1420 WCHAR KeyBuffer
[MAX_PATH
];
1421 WCHAR InstancePath
[MAX_PATH
];
1422 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1423 struct DeviceInfoElement
*deviceInfo
;
1425 DWORD dwLength
, dwRegType
;
1428 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1431 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1432 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1433 if (rc
== ERROR_NO_MORE_ITEMS
)
1435 if (rc
!= ERROR_SUCCESS
)
1439 /* Open device id sub key */
1440 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1441 if (rc
!= ERROR_SUCCESS
)
1443 strcpyW(InstancePath
, Enumerator
);
1444 strcatW(InstancePath
, L
"\\");
1445 strcatW(InstancePath
, KeyBuffer
);
1446 strcatW(InstancePath
, L
"\\");
1447 pEndOfInstancePath
= &InstancePath
[strlenW(InstancePath
)];
1449 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1455 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1456 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1457 if (rc
== ERROR_NO_MORE_ITEMS
)
1459 if (rc
!= ERROR_SUCCESS
)
1461 RegCloseKey(hDeviceIdKey
);
1466 /* Open instance id sub key */
1467 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1468 if (rc
!= ERROR_SUCCESS
)
1470 RegCloseKey(hDeviceIdKey
);
1473 *pEndOfInstancePath
= '\0';
1474 strcatW(InstancePath
, KeyBuffer
);
1476 /* Read ClassGUID value */
1477 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1478 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1479 RegCloseKey(hInstanceIdKey
);
1480 if (rc
== ERROR_FILE_NOT_FOUND
)
1483 /* Skip this bad entry as we can't verify it */
1485 /* Set a default GUID for this device */
1486 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1488 else if (rc
!= ERROR_SUCCESS
)
1490 RegCloseKey(hDeviceIdKey
);
1493 else if (dwRegType
!= REG_SZ
)
1495 RegCloseKey(hDeviceIdKey
);
1496 return ERROR_GEN_FAILURE
;
1500 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1501 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1502 /* Bad GUID, skip the entry */
1506 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1508 /* Skip this entry as it is not the right device class */
1512 /* Add the entry to the list */
1513 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1515 RegCloseKey(hDeviceIdKey
);
1516 return GetLastError();
1518 TRACE("Adding '%s' to device info set %p\n", debugstr_w(InstancePath
), list
);
1519 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1521 RegCloseKey(hDeviceIdKey
);
1524 return ERROR_SUCCESS
;
1527 static LONG
SETUP_CreateDevList(
1528 struct DeviceInfoSet
*list
,
1529 PCWSTR MachineName OPTIONAL
,
1530 LPGUID
class OPTIONAL
,
1531 PCWSTR Enumerator OPTIONAL
)
1533 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1534 WCHAR KeyBuffer
[MAX_PATH
];
1539 if (class && IsEqualIID(class, &GUID_NULL
))
1543 if (MachineName
!= NULL
)
1545 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1546 if (rc
!= ERROR_SUCCESS
)
1550 HKLM
= HKEY_LOCAL_MACHINE
;
1552 rc
= RegOpenKeyExW(HKLM
,
1553 REGSTR_PATH_SYSTEMENUM
,
1555 KEY_ENUMERATE_SUB_KEYS
,
1557 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1558 if (rc
!= ERROR_SUCCESS
)
1561 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1562 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1571 KEY_ENUMERATE_SUB_KEYS
,
1573 RegCloseKey(hEnumKey
);
1574 if (rc
!= ERROR_SUCCESS
)
1576 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1577 RegCloseKey(hEnumeratorKey
);
1582 /* Enumerate enumerators */
1586 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1587 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1588 if (rc
== ERROR_NO_MORE_ITEMS
)
1590 if (rc
!= ERROR_SUCCESS
)
1592 RegCloseKey(hEnumKey
);
1598 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1599 if (rc
!= ERROR_SUCCESS
)
1601 RegCloseKey(hEnumKey
);
1605 /* Call SETUP_CreateDevListFromEnumerator */
1606 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1607 RegCloseKey(hEnumeratorKey
);
1608 if (rc
!= ERROR_SUCCESS
)
1610 RegCloseKey(hEnumKey
);
1614 RegCloseKey(hEnumKey
);
1615 return ERROR_SUCCESS
;
1619 static LONG
SETUP_CreateInterfaceList(
1620 struct DeviceInfoSet
*list
,
1622 LPGUID InterfaceGuid
,
1623 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1625 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1626 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1627 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1628 HKEY hControlKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */
1629 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1630 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1632 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1635 DWORD dwLength
, dwInstancePathLength
;
1639 struct DeviceInfoElement
*deviceInfo
;
1641 /* Open registry key related to this interface */
1642 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1643 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1644 return GetLastError();
1646 /* Enumerate sub keys of hInterfaceKey */
1650 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1651 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1652 if (rc
== ERROR_NO_MORE_ITEMS
)
1654 if (rc
!= ERROR_SUCCESS
)
1656 RegCloseKey(hInterfaceKey
);
1662 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1663 if (rc
!= ERROR_SUCCESS
)
1665 RegCloseKey(hInterfaceKey
);
1669 /* Read DeviceInstance */
1670 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1671 if (rc
!= ERROR_SUCCESS
)
1673 RegCloseKey(hDeviceInstanceKey
);
1674 RegCloseKey(hInterfaceKey
);
1677 if (dwRegType
!= REG_SZ
)
1679 RegCloseKey(hDeviceInstanceKey
);
1680 RegCloseKey(hInterfaceKey
);
1681 return ERROR_GEN_FAILURE
;
1683 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1686 RegCloseKey(hDeviceInstanceKey
);
1687 RegCloseKey(hInterfaceKey
);
1688 return ERROR_NOT_ENOUGH_MEMORY
;
1690 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1691 if (rc
!= ERROR_SUCCESS
)
1693 HeapFree(GetProcessHeap(), 0, InstancePath
);
1694 RegCloseKey(hDeviceInstanceKey
);
1695 RegCloseKey(hInterfaceKey
);
1698 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1699 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1701 if (DeviceInstanceW
)
1703 /* Check if device enumerator is not the right one */
1704 if (strcmpW(DeviceInstanceW
, InstancePath
) != 0)
1706 HeapFree(GetProcessHeap(), 0, InstancePath
);
1707 RegCloseKey(hDeviceInstanceKey
);
1712 /* Find class GUID associated to the device instance */
1715 REGSTR_PATH_SYSTEMENUM
,
1719 if (rc
!= ERROR_SUCCESS
)
1721 HeapFree(GetProcessHeap(), 0, InstancePath
);
1722 RegCloseKey(hDeviceInstanceKey
);
1723 RegCloseKey(hInterfaceKey
);
1732 RegCloseKey(hEnumKey
);
1733 if (rc
!= ERROR_SUCCESS
)
1735 HeapFree(GetProcessHeap(), 0, InstancePath
);
1736 RegCloseKey(hDeviceInstanceKey
);
1737 RegCloseKey(hInterfaceKey
);
1740 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1741 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1743 if (rc
!= ERROR_SUCCESS
)
1745 HeapFree(GetProcessHeap(), 0, InstancePath
);
1746 RegCloseKey(hDeviceInstanceKey
);
1747 RegCloseKey(hInterfaceKey
);
1750 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1751 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1752 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1754 HeapFree(GetProcessHeap(), 0, InstancePath
);
1755 RegCloseKey(hDeviceInstanceKey
);
1756 RegCloseKey(hInterfaceKey
);
1757 return ERROR_GEN_FAILURE
;
1759 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1761 /* If current device doesn't match the list GUID (if any), skip this entry */
1762 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1764 HeapFree(GetProcessHeap(), 0, InstancePath
);
1765 RegCloseKey(hDeviceInstanceKey
);
1769 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1773 LPWSTR pSymbolicLink
;
1774 struct DeviceInterface
*interfaceInfo
;
1776 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1777 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1778 if (rc
== ERROR_NO_MORE_ITEMS
)
1780 if (rc
!= ERROR_SUCCESS
)
1782 HeapFree(GetProcessHeap(), 0, InstancePath
);
1783 RegCloseKey(hDeviceInstanceKey
);
1784 RegCloseKey(hInterfaceKey
);
1788 if (KeyBuffer
[0] != '#')
1789 /* This entry doesn't represent an interesting entry */
1793 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1794 if (rc
!= ERROR_SUCCESS
)
1796 RegCloseKey(hDeviceInstanceKey
);
1797 RegCloseKey(hInterfaceKey
);
1801 /* Read SymbolicLink value */
1802 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1803 if (rc
!= ERROR_SUCCESS
)
1805 RegCloseKey(hReferenceKey
);
1806 RegCloseKey(hDeviceInstanceKey
);
1807 RegCloseKey(hInterfaceKey
);
1810 if (dwRegType
!= REG_SZ
)
1812 RegCloseKey(hReferenceKey
);
1813 RegCloseKey(hDeviceInstanceKey
);
1814 RegCloseKey(hInterfaceKey
);
1815 return ERROR_GEN_FAILURE
;
1818 /* We have found a device */
1819 /* Step 1. Create a device info element */
1820 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1822 RegCloseKey(hReferenceKey
);
1823 RegCloseKey(hDeviceInstanceKey
);
1824 RegCloseKey(hInterfaceKey
);
1825 return GetLastError();
1827 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1828 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1830 /* Step 2. Create an interface list for this element */
1831 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1834 RegCloseKey(hReferenceKey
);
1835 RegCloseKey(hDeviceInstanceKey
);
1836 RegCloseKey(hInterfaceKey
);
1837 return ERROR_NOT_ENOUGH_MEMORY
;
1839 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1840 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1841 RegCloseKey(hReferenceKey
);
1842 if (rc
!= ERROR_SUCCESS
)
1844 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1845 RegCloseKey(hDeviceInstanceKey
);
1846 RegCloseKey(hInterfaceKey
);
1849 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1851 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1852 RegCloseKey(hDeviceInstanceKey
);
1853 RegCloseKey(hInterfaceKey
);
1854 return GetLastError();
1857 /* Step 3. Update flags */
1858 if (KeyBuffer
[1] == '\0')
1859 interfaceInfo
->Flags
|= SPINT_DEFAULT
;
1860 rc
= RegOpenKeyExW(hReferenceKey
, Control
, 0, KEY_QUERY_VALUE
, &hControlKey
);
1862 interfaceInfo
->Flags
|= SPINT_REMOVED
;
1865 dwLength
= sizeof(DWORD
);
1866 if (RegQueryValueExW(hControlKey
, Linked
, NULL
, &dwRegType
, (LPBYTE
)&LinkedValue
, &dwLength
)
1867 && dwRegType
== REG_DWORD
&& LinkedValue
)
1868 interfaceInfo
->Flags
|= SPINT_ACTIVE
;
1869 RegCloseKey(hControlKey
);
1872 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1873 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1874 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1876 RegCloseKey(hDeviceInstanceKey
);
1878 RegCloseKey(hInterfaceKey
);
1879 return ERROR_SUCCESS
;
1882 /***********************************************************************
1883 * SetupDiGetClassDevsExW (SETUPAPI.@)
1885 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1894 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1895 struct DeviceInfoSet
*list
;
1899 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1900 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1902 /* Create the deviceset if not set */
1905 list
= (struct DeviceInfoSet
*)deviceset
;
1906 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1908 SetLastError(ERROR_INVALID_HANDLE
);
1909 return INVALID_HANDLE_VALUE
;
1911 hDeviceInfo
= deviceset
;
1915 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1916 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1917 NULL
, machine
, NULL
);
1918 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1919 return INVALID_HANDLE_VALUE
;
1920 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1923 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1926 pClassGuid
= &list
->ClassGuid
;
1928 if (flags
& DIGCF_PRESENT
)
1929 FIXME(": flag DIGCF_PRESENT ignored\n");
1930 if (flags
& DIGCF_PROFILE
)
1931 FIXME(": flag DIGCF_PROFILE ignored\n");
1933 if (flags
& DIGCF_ALLCLASSES
)
1935 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1936 if (rc
!= ERROR_SUCCESS
)
1940 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1941 return INVALID_HANDLE_VALUE
;
1945 else if (flags
& DIGCF_DEVICEINTERFACE
)
1949 SetLastError(ERROR_INVALID_PARAMETER
);
1951 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1952 return INVALID_HANDLE_VALUE
;
1955 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1956 if (rc
!= ERROR_SUCCESS
)
1960 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1961 return INVALID_HANDLE_VALUE
;
1967 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1968 if (rc
!= ERROR_SUCCESS
)
1972 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1973 return INVALID_HANDLE_VALUE
;
1979 /***********************************************************************
1980 * SetupDiGetClassImageIndex (SETUPAPI.@)
1983 static BOOL
GetIconIndex(
1985 OUT PINT ImageIndex
)
1987 LPWSTR Buffer
= NULL
;
1988 DWORD dwRegType
, dwLength
;
1992 /* Read icon registry key */
1993 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
1994 if (rc
!= ERROR_SUCCESS
)
1998 } else if (dwRegType
!= REG_SZ
)
2000 SetLastError(ERROR_INVALID_INDEX
);
2003 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2006 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2009 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2010 if (rc
!= ERROR_SUCCESS
)
2015 /* make sure the returned buffer is NULL-terminated */
2016 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2018 /* Transform icon value to a INT */
2019 *ImageIndex
= atoiW(Buffer
);
2027 BOOL WINAPI
SetupDiGetClassImageIndex(
2028 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2029 IN CONST GUID
*ClassGuid
,
2030 OUT PINT ImageIndex
)
2032 struct ClassImageList
*list
;
2035 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2037 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2038 SetLastError(ERROR_INVALID_PARAMETER
);
2039 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2040 SetLastError(ERROR_INVALID_USER_BUFFER
);
2041 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2042 SetLastError(ERROR_INVALID_USER_BUFFER
);
2043 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2044 SetLastError(ERROR_INVALID_USER_BUFFER
);
2045 else if (!ImageIndex
)
2046 SetLastError(ERROR_INVALID_PARAMETER
);
2049 HKEY hKey
= INVALID_HANDLE_VALUE
;
2052 /* Read Icon registry entry into Buffer */
2053 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2054 if (hKey
== INVALID_HANDLE_VALUE
)
2056 if (!GetIconIndex(hKey
, &iconIndex
))
2061 SetLastError(ERROR_INVALID_INDEX
);
2065 *ImageIndex
= -iconIndex
;
2069 if (hKey
!= INVALID_HANDLE_VALUE
)
2073 TRACE("Returning %d\n", ret
);
2077 /***********************************************************************
2078 * SetupDiGetClassImageList(SETUPAPI.@)
2080 BOOL WINAPI
SetupDiGetClassImageList(
2081 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2083 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2086 /***********************************************************************
2087 * SetupDiGetClassImageListExA(SETUPAPI.@)
2089 BOOL WINAPI
SetupDiGetClassImageListExA(
2090 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2091 IN PCSTR MachineName OPTIONAL
,
2094 PWSTR MachineNameW
= NULL
;
2099 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2100 if (MachineNameW
== NULL
)
2104 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2107 MyFree(MachineNameW
);
2112 /***********************************************************************
2113 * SetupDiGetClassImageListExW(SETUPAPI.@)
2115 BOOL WINAPI
SetupDiGetClassImageListExW(
2116 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2117 IN PCWSTR MachineName OPTIONAL
,
2122 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2124 if (!ClassImageListData
)
2125 SetLastError(ERROR_INVALID_PARAMETER
);
2126 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2127 SetLastError(ERROR_INVALID_USER_BUFFER
);
2129 SetLastError(ERROR_INVALID_PARAMETER
);
2132 struct ClassImageList
*list
= NULL
;
2135 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2137 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
2138 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2141 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2144 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2147 list
->szData
[0] = list
->szData
[1] = '\\';
2148 strcpyW(list
->szData
+ 2, MachineName
);
2149 list
->MachineName
= list
->szData
;
2153 list
->MachineName
= NULL
;
2156 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2164 TRACE("Returning %d\n", ret
);
2168 /***********************************************************************
2169 * SetupDiLoadClassIcon(SETUPAPI.@)
2171 BOOL WINAPI
SetupDiLoadClassIcon(
2172 IN CONST GUID
*ClassGuid
,
2173 OUT HICON
*LargeIcon OPTIONAL
,
2174 OUT PINT MiniIconIndex OPTIONAL
)
2179 SetLastError(ERROR_INVALID_PARAMETER
);
2182 LPWSTR Buffer
= NULL
;
2185 HKEY hKey
= INVALID_HANDLE_VALUE
;
2187 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2188 if (hKey
== INVALID_HANDLE_VALUE
)
2191 if (!GetIconIndex(hKey
, &iconIndex
))
2196 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2199 DWORD dwRegType
, dwLength
;
2200 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2201 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2203 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2206 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2209 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2210 if (rc
!= ERROR_SUCCESS
)
2215 /* make sure the returned buffer is NULL-terminated */
2216 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2219 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2220 && dwRegType
== REG_SZ
)
2222 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2225 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2228 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2229 if (rc
!= ERROR_SUCCESS
)
2234 /* make sure the returned buffer is NULL-terminated */
2235 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2239 /* Unable to find where to load the icon */
2240 SetLastError(ERROR_FILE_NOT_FOUND
);
2243 Comma
= strchrW(Buffer
, ',');
2246 SetLastError(ERROR_GEN_FAILURE
);
2254 /* Look up icon in setupapi.dll */
2255 DllName
= L
"setupapi.dll";
2256 iconIndex
= -iconIndex
;
2259 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2262 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2264 SetLastError(ERROR_INVALID_INDEX
);
2269 *MiniIconIndex
= iconIndex
;
2273 if (hKey
!= INVALID_HANDLE_VALUE
)
2278 TRACE("Returning %d\n", ret
);
2282 /***********************************************************************
2283 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2285 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2286 HDEVINFO DeviceInfoSet
,
2287 PSP_DEVINFO_DATA DeviceInfoData
,
2288 CONST GUID
* InterfaceClassGuid
,
2290 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2294 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2295 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2297 if (!DeviceInterfaceData
)
2298 SetLastError(ERROR_INVALID_PARAMETER
);
2299 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2300 SetLastError(ERROR_INVALID_USER_BUFFER
);
2301 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2303 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2305 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2307 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2309 while (ItemList
!= &list
->ListHead
&& !Found
)
2311 PLIST_ENTRY InterfaceListEntry
;
2312 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2313 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2315 /* We are not searching for this element */
2316 ItemList
= ItemList
->Flink
;
2319 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2320 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2322 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2323 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2325 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2328 if (MemberIndex
-- == 0)
2330 /* return this item */
2331 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2332 &DevItf
->InterfaceClassGuid
,
2334 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2335 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2338 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2340 ItemList
= ItemList
->Flink
;
2343 SetLastError(ERROR_NO_MORE_ITEMS
);
2348 SetLastError(ERROR_INVALID_HANDLE
);
2351 SetLastError(ERROR_INVALID_HANDLE
);
2355 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2357 InterlockedIncrement(&infFile
->References
);
2360 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2362 if (InterlockedDecrement(&infFile
->References
) == 0)
2364 SetupCloseInfFile(infFile
->hInf
);
2365 HeapFree(GetProcessHeap(), 0, infFile
);
2369 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2371 DereferenceInfFile(driverInfo
->InfFileDetails
);
2372 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2373 HeapFree(GetProcessHeap(), 0, driverInfo
);
2377 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2379 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2383 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2385 PLIST_ENTRY ListEntry
;
2386 struct DriverInfoElement
*driverInfo
;
2388 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2390 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2391 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2392 if (!DestroyDriverInfoElement(driverInfo
))
2395 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2397 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2398 HeapFree(GetProcessHeap(), 0, ListEntry
);
2400 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2401 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2405 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2407 PLIST_ENTRY ListEntry
;
2408 struct DeviceInfoElement
*deviceInfo
;
2410 while (!IsListEmpty(&list
->ListHead
))
2412 ListEntry
= RemoveHeadList(&list
->ListHead
);
2413 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2414 if (!DestroyDeviceInfoElement(deviceInfo
))
2417 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2418 RegCloseKey(list
->HKLM
);
2419 CM_Disconnect_Machine(list
->hMachine
);
2420 DestroyClassInstallParams(&list
->ClassInstallParams
);
2421 HeapFree(GetProcessHeap(), 0, list
);
2425 /***********************************************************************
2426 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2428 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2432 TRACE("%p\n", devinfo
);
2433 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2435 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2437 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2438 ret
= DestroyDeviceInfoSet(list
);
2440 SetLastError(ERROR_INVALID_HANDLE
);
2443 SetLastError(ERROR_INVALID_HANDLE
);
2445 TRACE("Returning %d\n", ret
);
2449 /***********************************************************************
2450 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2452 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2453 HDEVINFO DeviceInfoSet
,
2454 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2455 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2456 DWORD DeviceInterfaceDetailDataSize
,
2457 PDWORD RequiredSize
,
2458 PSP_DEVINFO_DATA DeviceInfoData
)
2460 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2461 DWORD sizeW
= 0, sizeA
;
2464 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2465 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2466 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2468 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2469 SetLastError(ERROR_INVALID_USER_BUFFER
);
2470 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2471 SetLastError(ERROR_INVALID_PARAMETER
);
2472 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2473 SetLastError(ERROR_INVALID_PARAMETER
);
2476 if (DeviceInterfaceDetailData
!= NULL
)
2478 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2479 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2480 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2481 if (!DeviceInterfaceDetailDataW
)
2483 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2486 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2488 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2489 ret
= SetupDiGetDeviceInterfaceDetailW(
2491 DeviceInterfaceData
,
2492 DeviceInterfaceDetailDataW
,
2496 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2497 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2499 *RequiredSize
= sizeA
;
2500 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2502 if (!WideCharToMultiByte(
2504 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2505 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2512 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2515 TRACE("Returning %d\n", ret
);
2519 /***********************************************************************
2520 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2522 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2523 HDEVINFO DeviceInfoSet
,
2524 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2525 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2526 DWORD DeviceInterfaceDetailDataSize
,
2527 PDWORD RequiredSize
,
2528 PSP_DEVINFO_DATA DeviceInfoData
)
2532 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2533 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2534 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2536 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2537 SetLastError(ERROR_INVALID_PARAMETER
);
2538 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2539 SetLastError(ERROR_INVALID_HANDLE
);
2540 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2541 SetLastError(ERROR_INVALID_HANDLE
);
2542 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2543 SetLastError(ERROR_INVALID_USER_BUFFER
);
2544 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2545 SetLastError(ERROR_INVALID_USER_BUFFER
);
2546 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2547 SetLastError(ERROR_INVALID_USER_BUFFER
);
2548 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2549 SetLastError(ERROR_INVALID_PARAMETER
);
2550 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2551 SetLastError(ERROR_INVALID_PARAMETER
);
2554 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2555 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2556 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2557 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2559 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2561 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2563 *RequiredSize
= sizeRequired
;
2567 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
2568 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2571 memcpy(&DeviceInfoData
->ClassGuid
,
2572 &deviceInterface
->DeviceInfo
->ClassGuid
,
2574 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2575 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2581 TRACE("Returning %d\n", ret
);
2585 /***********************************************************************
2586 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2588 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2590 PSP_DEVINFO_DATA DeviceInfoData
,
2592 PDWORD PropertyRegDataType
,
2593 PBYTE PropertyBuffer
,
2594 DWORD PropertyBufferSize
,
2595 PDWORD RequiredSize
)
2598 BOOL bIsStringProperty
;
2600 DWORD RequiredSizeA
, RequiredSizeW
;
2601 DWORD PropertyBufferSizeW
;
2602 PBYTE PropertyBufferW
;
2604 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2605 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2608 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2609 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2611 bResult
= SetupDiGetDeviceRegistryPropertyW(
2617 PropertyBufferSizeW
,
2620 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2622 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2624 if (bIsStringProperty
)
2625 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2627 RequiredSizeA
= RequiredSizeW
;
2629 *RequiredSize
= RequiredSizeA
;
2630 if (PropertyRegDataType
)
2631 *PropertyRegDataType
= RegType
;
2636 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2640 if (RequiredSizeA
<= PropertyBufferSize
)
2642 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2644 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2646 /* Last error is already set by WideCharToMultiByte */
2651 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2655 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2659 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2663 /***********************************************************************
2664 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2666 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2667 HDEVINFO DeviceInfoSet
,
2668 PSP_DEVINFO_DATA DeviceInfoData
,
2670 PDWORD PropertyRegDataType
,
2671 PBYTE PropertyBuffer
,
2672 DWORD PropertyBufferSize
,
2673 PDWORD RequiredSize
)
2675 HKEY hEnumKey
, hKey
;
2679 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2680 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2683 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2684 SetLastError(ERROR_INVALID_HANDLE
);
2685 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2686 SetLastError(ERROR_INVALID_HANDLE
);
2687 else if (!DeviceInfoData
)
2688 SetLastError(ERROR_INVALID_PARAMETER
);
2689 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2690 SetLastError(ERROR_INVALID_USER_BUFFER
);
2691 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2692 SetLastError(ERROR_INVALID_PARAMETER
);
2695 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2696 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2700 case SPDRP_CAPABILITIES
:
2702 case SPDRP_CLASSGUID
:
2703 case SPDRP_COMPATIBLEIDS
:
2704 case SPDRP_CONFIGFLAGS
:
2705 case SPDRP_DEVICEDESC
:
2707 case SPDRP_FRIENDLYNAME
:
2708 case SPDRP_HARDWAREID
:
2709 case SPDRP_LOCATION_INFORMATION
:
2710 case SPDRP_LOWERFILTERS
:
2712 case SPDRP_SECURITY
:
2714 case SPDRP_UI_NUMBER
:
2715 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2716 case SPDRP_UPPERFILTERS
:
2718 LPCWSTR RegistryPropertyName
;
2723 case SPDRP_CAPABILITIES
:
2724 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2726 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2727 case SPDRP_CLASSGUID
:
2728 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2729 case SPDRP_COMPATIBLEIDS
:
2730 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2731 case SPDRP_CONFIGFLAGS
:
2732 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2733 case SPDRP_DEVICEDESC
:
2734 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2736 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2737 case SPDRP_FRIENDLYNAME
:
2738 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2739 case SPDRP_HARDWAREID
:
2740 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2741 case SPDRP_LOCATION_INFORMATION
:
2742 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2743 case SPDRP_LOWERFILTERS
:
2744 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2746 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2747 case SPDRP_SECURITY
:
2748 RegistryPropertyName
= REGSTR_SECURITY
; break;
2750 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2751 case SPDRP_UI_NUMBER
:
2752 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2753 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2754 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
; break;
2755 case SPDRP_UPPERFILTERS
:
2756 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2758 /* Should not happen */
2759 RegistryPropertyName
= NULL
; break;
2762 /* Open registry key name */
2765 REGSTR_PATH_SYSTEMENUM
,
2769 if (rc
!= ERROR_SUCCESS
)
2780 RegCloseKey(hEnumKey
);
2781 if (rc
!= ERROR_SUCCESS
)
2786 /* Read registry entry */
2787 BufferSize
= PropertyBufferSize
;
2788 rc
= RegQueryValueExW(
2790 RegistryPropertyName
,
2791 NULL
, /* Reserved */
2792 PropertyRegDataType
,
2796 *RequiredSize
= BufferSize
;
2799 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2802 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2804 case ERROR_MORE_DATA
:
2805 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2814 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2816 DWORD required
= (strlenW(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2818 if (PropertyRegDataType
)
2819 *PropertyRegDataType
= REG_SZ
;
2821 *RequiredSize
= required
;
2822 if (PropertyBufferSize
>= required
)
2824 strcpyW((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2828 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2832 /*case SPDRP_BUSTYPEGUID:
2833 case SPDRP_LEGACYBUSTYPE:
2834 case SPDRP_BUSNUMBER:
2835 case SPDRP_ENUMERATOR_NAME:
2836 case SPDRP_SECURITY_SDS:
2838 case SPDRP_EXCLUSIVE:
2839 case SPDRP_CHARACTERISTICS:
2841 case SPDRP_DEVICE_POWER_DATA:*/
2842 #if (WINVER >= 0x501)
2843 /*case SPDRP_REMOVAL_POLICY:
2844 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2845 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2846 case SPDRP_INSTALL_STATE:*/
2851 ERR("Property 0x%lx not implemented\n", Property
);
2852 SetLastError(ERROR_NOT_SUPPORTED
);
2857 TRACE("Returning %d\n", ret
);
2861 /***********************************************************************
2862 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2864 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2865 IN HDEVINFO DeviceInfoSet
,
2866 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2868 IN CONST BYTE
*PropertyBuffer
,
2869 IN DWORD PropertyBufferSize
)
2871 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2872 Property
, PropertyBuffer
, PropertyBufferSize
);
2873 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2877 /***********************************************************************
2878 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2880 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2881 IN HDEVINFO DeviceInfoSet
,
2882 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2884 IN
const BYTE
*PropertyBuffer
,
2885 IN DWORD PropertyBufferSize
)
2887 struct DeviceInfoSet
*list
;
2890 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2891 Property
, PropertyBuffer
, PropertyBufferSize
);
2894 SetLastError(ERROR_INVALID_HANDLE
);
2895 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2896 SetLastError(ERROR_INVALID_HANDLE
);
2897 else if (!DeviceInfoData
)
2898 SetLastError(ERROR_INVALID_HANDLE
);
2899 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2900 SetLastError(ERROR_INVALID_USER_BUFFER
);
2905 case SPDRP_COMPATIBLEIDS
:
2906 case SPDRP_CONFIGFLAGS
:
2907 case SPDRP_FRIENDLYNAME
:
2908 case SPDRP_HARDWAREID
:
2909 case SPDRP_LOCATION_INFORMATION
:
2910 case SPDRP_LOWERFILTERS
:
2911 case SPDRP_SECURITY
:
2913 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2914 case SPDRP_UPPERFILTERS
:
2916 LPCWSTR RegistryPropertyName
;
2917 DWORD RegistryDataType
;
2923 case SPDRP_COMPATIBLEIDS
:
2924 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2925 RegistryDataType
= REG_MULTI_SZ
;
2927 case SPDRP_CONFIGFLAGS
:
2928 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2929 RegistryDataType
= REG_DWORD
;
2931 case SPDRP_FRIENDLYNAME
:
2932 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2933 RegistryDataType
= REG_SZ
;
2935 case SPDRP_HARDWAREID
:
2936 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2937 RegistryDataType
= REG_MULTI_SZ
;
2939 case SPDRP_LOCATION_INFORMATION
:
2940 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2941 RegistryDataType
= REG_SZ
;
2943 case SPDRP_LOWERFILTERS
:
2944 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2945 RegistryDataType
= REG_MULTI_SZ
;
2947 case SPDRP_SECURITY
:
2948 RegistryPropertyName
= REGSTR_SECURITY
;
2949 RegistryDataType
= REG_BINARY
;
2952 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2953 RegistryDataType
= REG_SZ
;
2955 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2956 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
;
2957 RegistryDataType
= REG_SZ
;
2959 case SPDRP_UPPERFILTERS
:
2960 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
2961 RegistryDataType
= REG_MULTI_SZ
;
2964 /* Should not happen */
2965 RegistryPropertyName
= NULL
;
2966 RegistryDataType
= REG_BINARY
;
2969 /* Open device registry key */
2970 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2971 if (hKey
!= INVALID_HANDLE_VALUE
)
2973 /* Write new data */
2974 rc
= RegSetValueExW(
2976 RegistryPropertyName
,
2980 PropertyBufferSize
);
2981 if (rc
== ERROR_SUCCESS
)
2990 /*case SPDRP_CHARACTERISTICS:
2992 case SPDRP_EXCLUSIVE:*/
2993 #if (WINVER >= 0x501)
2994 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2996 //case SPDRP_SECURITY_SDS:
3000 ERR("Property 0x%lx not implemented\n", Property
);
3001 SetLastError(ERROR_NOT_SUPPORTED
);
3006 TRACE("Returning %d\n", ret
);
3011 /***********************************************************************
3012 * SetupDiInstallClassA (SETUPAPI.@)
3014 BOOL WINAPI
SetupDiInstallClassA(
3015 IN HWND hwndParent OPTIONAL
,
3016 IN PCSTR InfFileName
,
3018 IN HSPFILEQ FileQueue OPTIONAL
)
3020 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3024 /***********************************************************************
3025 * SetupDiInstallClassW (SETUPAPI.@)
3027 BOOL WINAPI
SetupDiInstallClassW(
3028 IN HWND hwndParent OPTIONAL
,
3029 IN PCWSTR InfFileName
,
3031 IN HSPFILEQ FileQueue OPTIONAL
)
3033 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3037 /***********************************************************************
3038 * SetupDiInstallClassExA (SETUPAPI.@)
3040 BOOL WINAPI
SetupDiInstallClassExA(
3041 IN HWND hwndParent OPTIONAL
,
3042 IN PCSTR InfFileName OPTIONAL
,
3044 IN HSPFILEQ FileQueue OPTIONAL
,
3045 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3049 PWSTR InfFileNameW
= NULL
;
3054 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3055 if (InfFileNameW
== NULL
)
3057 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3062 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3063 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3065 MyFree(InfFileNameW
);
3071 static HKEY
CreateClassKey(HINF hInf
)
3073 WCHAR FullBuffer
[MAX_PATH
];
3074 WCHAR Buffer
[MAX_PATH
];
3079 if (!SetupGetLineTextW(NULL
,
3087 return INVALID_HANDLE_VALUE
;
3090 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3091 lstrcatW(FullBuffer
, Buffer
);
3094 if (!SetupGetLineTextW(NULL
,
3102 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3103 return INVALID_HANDLE_VALUE
;
3106 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3110 REG_OPTION_NON_VOLATILE
,
3116 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3117 return INVALID_HANDLE_VALUE
;
3120 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3125 RequiredSize
* sizeof(WCHAR
)))
3127 RegCloseKey(hClassKey
);
3128 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3129 return INVALID_HANDLE_VALUE
;
3136 /***********************************************************************
3137 * SetupDiInstallClassExW (SETUPAPI.@)
3139 BOOL WINAPI
SetupDiInstallClassExW(
3140 IN HWND hwndParent OPTIONAL
,
3141 IN PCWSTR InfFileName OPTIONAL
,
3143 IN HSPFILEQ FileQueue OPTIONAL
,
3144 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3150 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3151 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3155 FIXME("Case not implemented: InfFileName NULL\n");
3156 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3158 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3160 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3161 SetLastError(ERROR_INVALID_FLAGS
);
3163 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3164 SetLastError(ERROR_INVALID_PARAMETER
);
3165 else if (Reserved1
!= NULL
)
3166 SetLastError(ERROR_INVALID_PARAMETER
);
3167 else if (Reserved2
!= NULL
)
3168 SetLastError(ERROR_INVALID_PARAMETER
);
3171 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
3172 SP_DEVINSTALL_PARAMS_W InstallParams
;
3173 WCHAR SectionName
[MAX_PATH
];
3174 HINF hInf
= INVALID_HANDLE_VALUE
;
3175 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3176 PVOID callback_context
= NULL
;
3178 hDeviceInfo
= SetupDiCreateDeviceInfoList(NULL
, NULL
);
3180 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3181 if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3183 InstallParams
.Flags
&= ~(DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3184 InstallParams
.Flags
|= Flags
& (DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3185 if (Flags
& DI_NOVCP
)
3186 InstallParams
.FileQueue
= FileQueue
;
3187 if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3190 /* Open the .inf file */
3191 hInf
= SetupOpenInfFileW(
3196 if (hInf
== INVALID_HANDLE_VALUE
)
3199 /* Try to append a layout file */
3200 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3204 if (InterfaceClassGuid
)
3206 /* Retrieve the actual section name */
3207 ret
= SetupDiGetActualSectionToInstallW(
3217 /* Open registry key related to this interface */
3218 /* FIXME: What happens if the key doesn't exist? */
3219 hRootKey
= SetupDiOpenClassRegKeyExW(InterfaceClassGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, NULL
, NULL
);
3220 if (hRootKey
== INVALID_HANDLE_VALUE
)
3223 /* SetupDiCreateDeviceInterface??? */
3224 FIXME("Installing an interface is not implemented\n");
3225 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3229 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3230 hRootKey
= CreateClassKey(hInf
);
3231 if (hRootKey
== INVALID_HANDLE_VALUE
)
3234 /* Retrieve the actual section name */
3235 ret
= SetupDiGetActualSectionToInstallW(
3239 MAX_PATH
- strlenW(DotServices
),
3245 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3246 if (!callback_context
)
3249 ret
= SetupInstallFromInfSectionW(
3253 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3255 NULL
, /* SourceRootPath */
3256 !(Flags
& DI_NOVCP
) && (Flags
& DI_FORCECOPY
) ? SP_COPY_FORCE_IN_USE
: 0, /* CopyFlags */
3257 SetupDefaultQueueCallbackW
,
3264 /* Install .Services section */
3265 lstrcatW(SectionName
, DotServices
);
3266 ret
= SetupInstallServicesFromInfSectionExW(
3281 if (hDeviceInfo
!= INVALID_HANDLE_VALUE
)
3282 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
3283 if (hInf
!= INVALID_HANDLE_VALUE
)
3284 SetupCloseInfFile(hInf
);
3285 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3286 RegCloseKey(hRootKey
);
3287 SetupTermDefaultQueueCallback(callback_context
);
3290 TRACE("Returning %d\n", ret
);
3295 /***********************************************************************
3296 * SetupDiOpenClassRegKey (SETUPAPI.@)
3298 HKEY WINAPI
SetupDiOpenClassRegKey(
3299 const GUID
* ClassGuid
,
3302 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3303 DIOCR_INSTALLER
, NULL
, NULL
);
3307 /***********************************************************************
3308 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3310 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3311 const GUID
* ClassGuid OPTIONAL
,
3314 PCSTR MachineName OPTIONAL
,
3317 PWSTR MachineNameW
= NULL
;
3324 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3325 if (MachineNameW
== NULL
)
3326 return INVALID_HANDLE_VALUE
;
3329 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3330 Flags
, MachineNameW
, Reserved
);
3333 MyFree(MachineNameW
);
3339 /***********************************************************************
3340 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3342 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3343 const GUID
* ClassGuid OPTIONAL
,
3346 PCWSTR MachineName OPTIONAL
,
3349 LPWSTR lpGuidString
;
3350 LPWSTR lpFullGuidString
;
3358 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3359 Flags
, debugstr_w(MachineName
), Reserved
);
3361 if (Flags
== DIOCR_INSTALLER
)
3363 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3365 else if (Flags
== DIOCR_INTERFACE
)
3367 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3371 ERR("Invalid Flags parameter!\n");
3372 SetLastError(ERROR_INVALID_FLAGS
);
3373 return INVALID_HANDLE_VALUE
;
3376 if (MachineName
!= NULL
)
3378 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3379 if (rc
!= ERROR_SUCCESS
)
3382 return INVALID_HANDLE_VALUE
;
3386 HKLM
= HKEY_LOCAL_MACHINE
;
3388 rc
= RegOpenKeyExW(HKLM
,
3391 ClassGuid
? 0 : samDesired
,
3393 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3394 if (rc
!= ERROR_SUCCESS
)
3397 return INVALID_HANDLE_VALUE
;
3400 if (ClassGuid
== NULL
)
3403 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3405 SetLastError(ERROR_GEN_FAILURE
);
3406 RegCloseKey(hClassesKey
);
3407 return INVALID_HANDLE_VALUE
;
3410 dwLength
= lstrlenW(lpGuidString
);
3411 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3412 if (!lpFullGuidString
)
3414 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3415 RpcStringFreeW(&lpGuidString
);
3416 return INVALID_HANDLE_VALUE
;
3418 lpFullGuidString
[0] = '{';
3419 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3420 lpFullGuidString
[dwLength
+ 1] = '}';
3421 lpFullGuidString
[dwLength
+ 2] = '\0';
3422 RpcStringFreeW(&lpGuidString
);
3424 rc
= RegOpenKeyExW(hClassesKey
,
3429 if (rc
!= ERROR_SUCCESS
)
3432 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3433 RegCloseKey(hClassesKey
);
3434 return INVALID_HANDLE_VALUE
;
3437 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3438 RegCloseKey(hClassesKey
);
3443 /***********************************************************************
3444 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3446 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3447 HDEVINFO DeviceInfoSet
,
3450 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3452 FIXME("%p %s %08lx %p\n",
3453 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3457 /***********************************************************************
3458 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3460 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3461 HDEVINFO DeviceInfoSet
,
3464 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3466 LPWSTR DevicePathW
= NULL
;
3469 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3471 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3472 if (DevicePathW
== NULL
)
3475 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3476 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3478 MyFree(DevicePathW
);
3483 /***********************************************************************
3484 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3486 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3487 HDEVINFO DeviceInfoSet
,
3488 PSP_DEVINFO_DATA DeviceInfoData
,
3489 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3490 DWORD ClassInstallParamsSize
)
3492 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3493 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3497 /***********************************************************************
3498 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3500 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3501 IN HDEVINFO DeviceInfoSet
,
3502 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3503 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3504 IN DWORD ClassInstallParamsSize
)
3506 struct DeviceInfoSet
*list
;
3509 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3510 ClassInstallParams
, ClassInstallParamsSize
);
3513 SetLastError(ERROR_INVALID_PARAMETER
);
3514 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3515 SetLastError(ERROR_INVALID_HANDLE
);
3516 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3517 SetLastError(ERROR_INVALID_HANDLE
);
3518 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3519 SetLastError(ERROR_INVALID_USER_BUFFER
);
3520 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3521 SetLastError(ERROR_INVALID_USER_BUFFER
);
3522 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3523 SetLastError(ERROR_INVALID_PARAMETER
);
3524 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3525 SetLastError(ERROR_INVALID_PARAMETER
);
3528 SP_DEVINSTALL_PARAMS_W InstallParams
;
3531 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3532 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3536 if (ClassInstallParams
)
3538 /* Check parameters in ClassInstallParams */
3539 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3540 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3542 SetLastError(ERROR_INVALID_USER_BUFFER
);
3545 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3547 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3548 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3551 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3554 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3558 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3561 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3565 TRACE("Returning %d\n", ret
);
3569 static BOOL
PropertyChangeHandler(
3570 IN HDEVINFO DeviceInfoSet
,
3571 IN PSP_DEVINFO_DATA DeviceInfoData
,
3572 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3573 IN DWORD ClassInstallParamsSize
)
3575 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3578 if (!DeviceInfoData
)
3579 SetLastError(ERROR_INVALID_PARAMETER
);
3580 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3581 SetLastError(ERROR_INVALID_PARAMETER
);
3582 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3583 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3584 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3585 SetLastError(ERROR_INVALID_FLAGS
);
3586 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3587 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3588 SetLastError(ERROR_INVALID_FLAGS
);
3589 else if (PropChangeParams
3590 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3591 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3592 SetLastError(ERROR_INVALID_USER_BUFFER
);
3595 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3596 if (!DeviceInfoData
)
3598 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3599 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3603 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3604 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3606 if (*CurrentPropChangeParams
)
3608 MyFree(*CurrentPropChangeParams
);
3609 *CurrentPropChangeParams
= NULL
;
3611 if (PropChangeParams
)
3613 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3614 if (!*CurrentPropChangeParams
)
3616 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3619 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3630 IN PWSTR InstallerName
,
3631 OUT HMODULE
* ModulePointer
,
3632 OUT PVOID
* FunctionPointer
)
3634 HMODULE hModule
= NULL
;
3635 LPSTR FunctionNameA
= NULL
;
3639 *ModulePointer
= NULL
;
3640 *FunctionPointer
= NULL
;
3642 Comma
= strchrW(InstallerName
, ',');
3645 rc
= ERROR_INVALID_PARAMETER
;
3651 hModule
= LoadLibraryW(InstallerName
);
3655 rc
= GetLastError();
3659 /* Skip comma spaces */
3660 while (*Comma
== ',' || isspaceW(*Comma
))
3663 /* W->A conversion for function name */
3664 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3667 rc
= GetLastError();
3671 /* Search function */
3672 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3673 if (!*FunctionPointer
)
3675 rc
= GetLastError();
3679 *ModulePointer
= hModule
;
3683 if (rc
!= ERROR_SUCCESS
&& hModule
)
3684 FreeLibrary(hModule
);
3685 MyFree(FunctionNameA
);
3690 FreeFunctionPointer(
3691 IN HMODULE ModulePointer
,
3692 IN PVOID FunctionPointer
)
3694 if (ModulePointer
== NULL
)
3695 return ERROR_SUCCESS
;
3696 if (FreeLibrary(ModulePointer
))
3697 return ERROR_SUCCESS
;
3699 return GetLastError();
3703 IntSetupDiRegisterDeviceInfo(
3704 IN HDEVINFO DeviceInfoSet
,
3705 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
3707 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
3710 /***********************************************************************
3711 * SetupDiCallClassInstaller (SETUPAPI.@)
3713 BOOL WINAPI
SetupDiCallClassInstaller(
3714 IN DI_FUNCTION InstallFunction
,
3715 IN HDEVINFO DeviceInfoSet
,
3716 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3720 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3723 SetLastError(ERROR_INVALID_PARAMETER
);
3724 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3725 SetLastError(ERROR_INVALID_HANDLE
);
3726 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3727 SetLastError(ERROR_INVALID_HANDLE
);
3728 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3729 SetLastError(ERROR_INVALID_HANDLE
);
3730 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3731 SetLastError(ERROR_INVALID_USER_BUFFER
);
3734 SP_DEVINSTALL_PARAMS_W InstallParams
;
3735 #define CLASS_COINSTALLER 0x1
3736 #define DEVICE_COINSTALLER 0x2
3737 #define CLASS_INSTALLER 0x4
3738 UCHAR CanHandle
= 0;
3739 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3741 switch (InstallFunction
)
3743 case DIF_ADDPROPERTYPAGE_ADVANCED
:
3744 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3746 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
3747 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3749 case DIF_ALLOW_INSTALL
:
3750 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3753 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3755 case DIF_DESTROYPRIVATEDATA
:
3756 CanHandle
= CLASS_INSTALLER
;
3758 case DIF_INSTALLDEVICE
:
3759 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3760 DefaultHandler
= SetupDiInstallDevice
;
3762 case DIF_INSTALLDEVICEFILES
:
3763 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3764 DefaultHandler
= SetupDiInstallDriverFiles
;
3766 case DIF_INSTALLINTERFACES
:
3767 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3768 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3770 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3771 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3773 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3774 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3776 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3777 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3779 case DIF_NEWDEVICEWIZARD_PRESELECT
:
3780 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3782 case DIF_NEWDEVICEWIZARD_SELECT
:
3783 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3785 case DIF_POWERMESSAGEWAKE
:
3786 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3788 case DIF_PROPERTYCHANGE
:
3789 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3790 DefaultHandler
= SetupDiChangeState
;
3792 case DIF_REGISTER_COINSTALLERS
:
3793 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3794 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3796 case DIF_REGISTERDEVICE
:
3797 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3798 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
3801 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3802 DefaultHandler
= SetupDiRemoveDevice
;
3804 case DIF_SELECTBESTCOMPATDRV
:
3805 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3806 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3808 case DIF_SELECTDEVICE
:
3809 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3810 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3812 case DIF_TROUBLESHOOTER
:
3813 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3816 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3817 DefaultHandler
= SetupDiUnremoveDevice
;
3820 ERR("Install function %u not supported\n", InstallFunction
);
3821 SetLastError(ERROR_NOT_SUPPORTED
);
3824 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3825 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3826 /* Don't process this call, as a parameter is invalid */
3831 LIST_ENTRY ClassCoInstallersListHead
;
3832 LIST_ENTRY DeviceCoInstallersListHead
;
3833 HMODULE ClassInstallerLibrary
= NULL
;
3834 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3835 COINSTALLER_CONTEXT_DATA Context
;
3836 PLIST_ENTRY ListEntry
;
3838 DWORD dwRegType
, dwLength
;
3839 DWORD rc
= NO_ERROR
;
3841 InitializeListHead(&ClassCoInstallersListHead
);
3842 InitializeListHead(&DeviceCoInstallersListHead
);
3844 if (CanHandle
& DEVICE_COINSTALLER
)
3846 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3847 if (hKey
!= INVALID_HANDLE_VALUE
)
3849 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3850 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3852 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3853 if (KeyBuffer
!= NULL
)
3855 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3856 if (rc
== ERROR_SUCCESS
)
3859 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3861 /* Add coinstaller to DeviceCoInstallersListHead list */
3862 struct CoInstallerElement
*coinstaller
;
3863 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3864 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3867 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3868 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3869 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3871 HeapFree(GetProcessHeap(), 0, coinstaller
);
3874 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3880 if (CanHandle
& CLASS_COINSTALLER
)
3884 REGSTR_PATH_CODEVICEINSTALLERS
,
3888 if (rc
== ERROR_SUCCESS
)
3890 LPWSTR lpGuidString
;
3891 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3893 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3894 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3896 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3897 if (KeyBuffer
!= NULL
)
3899 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3900 if (rc
== ERROR_SUCCESS
)
3903 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3905 /* Add coinstaller to ClassCoInstallersListHead list */
3906 struct CoInstallerElement
*coinstaller
;
3907 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3908 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3911 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3912 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3913 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3915 HeapFree(GetProcessHeap(), 0, coinstaller
);
3918 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3921 RpcStringFreeW(&lpGuidString
);
3926 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3928 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3929 if (hKey
!= INVALID_HANDLE_VALUE
)
3931 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3932 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3934 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3935 if (KeyBuffer
!= NULL
)
3937 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3938 if (rc
== ERROR_SUCCESS
)
3940 /* Get ClassInstaller function pointer */
3941 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3942 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3944 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3945 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3948 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3955 /* Call Class co-installers */
3956 Context
.PostProcessing
= FALSE
;
3958 ListEntry
= ClassCoInstallersListHead
.Flink
;
3959 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3961 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3962 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3963 coinstaller
->PrivateData
= Context
.PrivateData
;
3964 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3966 coinstaller
->DoPostProcessing
= TRUE
;
3969 ListEntry
= ListEntry
->Flink
;
3972 /* Call Device co-installers */
3973 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3974 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3976 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3977 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3978 coinstaller
->PrivateData
= Context
.PrivateData
;
3979 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3981 coinstaller
->DoPostProcessing
= TRUE
;
3984 ListEntry
= ListEntry
->Flink
;
3987 /* Call Class installer */
3990 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3991 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3994 rc
= ERROR_DI_DO_DEFAULT
;
3996 /* Call default handler */
3997 if (rc
== ERROR_DI_DO_DEFAULT
)
3999 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
4001 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
4004 rc
= GetLastError();
4010 /* Call Class co-installers that required postprocessing */
4011 Context
.PostProcessing
= TRUE
;
4012 ListEntry
= ClassCoInstallersListHead
.Flink
;
4013 while (ListEntry
!= &ClassCoInstallersListHead
)
4015 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
4016 if (coinstaller
->DoPostProcessing
)
4018 Context
.InstallResult
= rc
;
4019 Context
.PrivateData
= coinstaller
->PrivateData
;
4020 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4022 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4023 ListEntry
= ListEntry
->Flink
;
4026 /* Call Device co-installers that required postprocessing */
4027 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4028 while (ListEntry
!= &DeviceCoInstallersListHead
)
4030 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
4031 if (coinstaller
->DoPostProcessing
)
4033 Context
.InstallResult
= rc
;
4034 Context
.PrivateData
= coinstaller
->PrivateData
;
4035 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4037 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4038 ListEntry
= ListEntry
->Flink
;
4041 /* Free allocated memory */
4042 while (!IsListEmpty(&ClassCoInstallersListHead
))
4044 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4045 HeapFree(GetProcessHeap(), 0, ListEntry
);
4047 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4049 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4050 HeapFree(GetProcessHeap(), 0, ListEntry
);
4053 ret
= (rc
== NO_ERROR
);
4057 TRACE("Returning %d\n", ret
);
4061 /***********************************************************************
4062 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4064 BOOL WINAPI
SetupDiGetDeviceInfoListClass(
4065 IN HDEVINFO DeviceInfoSet
,
4066 OUT LPGUID ClassGuid
)
4068 struct DeviceInfoSet
*list
;
4071 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4074 SetLastError(ERROR_INVALID_HANDLE
);
4075 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4076 SetLastError(ERROR_INVALID_HANDLE
);
4077 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4078 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4081 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4086 TRACE("Returning %d\n", ret
);
4090 /***********************************************************************
4091 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4093 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
4094 IN HDEVINFO DeviceInfoSet
,
4095 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
4097 struct DeviceInfoSet
*list
;
4100 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
4103 SetLastError(ERROR_INVALID_HANDLE
);
4104 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4105 SetLastError(ERROR_INVALID_HANDLE
);
4106 else if (!DeviceInfoListDetailData
)
4107 SetLastError(ERROR_INVALID_PARAMETER
);
4108 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
4109 SetLastError(ERROR_INVALID_USER_BUFFER
);
4113 &DeviceInfoListDetailData
->ClassGuid
,
4116 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
4117 if (list
->MachineName
)
4118 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
4120 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
4125 TRACE("Returning %d\n", ret
);
4129 /***********************************************************************
4130 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4132 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4133 IN HDEVINFO DeviceInfoSet
,
4134 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4135 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4137 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4140 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4142 if (DeviceInstallParams
== NULL
)
4143 SetLastError(ERROR_INVALID_PARAMETER
);
4144 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4145 SetLastError(ERROR_INVALID_USER_BUFFER
);
4148 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4149 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4153 /* Do W->A conversion */
4155 DeviceInstallParams
,
4156 &deviceInstallParamsW
,
4157 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4158 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4159 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4161 DeviceInstallParams
->DriverPath
[0] = '\0';
4167 TRACE("Returning %d\n", ret
);
4171 /***********************************************************************
4172 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4174 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
4175 IN HDEVINFO DeviceInfoSet
,
4176 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4177 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4179 struct DeviceInfoSet
*list
;
4182 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4185 SetLastError(ERROR_INVALID_HANDLE
);
4186 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4187 SetLastError(ERROR_INVALID_HANDLE
);
4188 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4189 SetLastError(ERROR_INVALID_USER_BUFFER
);
4190 else if (!DeviceInstallParams
)
4191 SetLastError(ERROR_INVALID_PARAMETER
);
4192 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4193 SetLastError(ERROR_INVALID_USER_BUFFER
);
4196 PSP_DEVINSTALL_PARAMS_W Source
;
4199 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4201 Source
= &list
->InstallParams
;
4202 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4206 TRACE("Returning %d\n", ret
);
4211 CheckDeviceInstallParameters(
4212 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4214 DWORD SupportedFlags
=
4215 DI_NOVCP
| /* 0x00000008 */
4216 DI_DIDCOMPAT
| /* 0x00000010 */
4217 DI_DIDCLASS
| /* 0x00000020 */
4218 DI_NEEDRESTART
| /* 0x00000080 */
4219 DI_NEEDREBOOT
| /* 0x00000100 */
4220 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4221 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4222 DI_ENUMSINGLEINF
| /* 0x00010000 */
4223 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4224 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4225 DI_QUIETINSTALL
| /* 0x00800000 */
4226 DI_NOFILECOPY
| /* 0x01000000 */
4227 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4228 DWORD SupportedFlagsEx
=
4229 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4230 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4231 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4232 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4233 DI_FLAGSEX_NO_DRVREG_MODIFY
; /* 0x00008000 */
4236 /* FIXME: add support for more flags */
4238 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4239 * It should be checked before accessing to other values
4240 * of the SP_DEVINSTALL_PARAMS structure */
4242 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4244 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4245 SetLastError(ERROR_INVALID_FLAGS
);
4247 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4249 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4250 SetLastError(ERROR_INVALID_FLAGS
);
4252 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4253 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4254 SetLastError(ERROR_INVALID_USER_BUFFER
);
4257 /* FIXME: check Reserved field */
4264 /***********************************************************************
4265 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4267 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
4268 IN HDEVINFO DeviceInfoSet
,
4269 IN PSP_DEVINFO_DATA DeviceInfoData
,
4270 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4272 struct DeviceInfoSet
*list
;
4275 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4278 SetLastError(ERROR_INVALID_HANDLE
);
4279 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4280 SetLastError(ERROR_INVALID_HANDLE
);
4281 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4282 SetLastError(ERROR_INVALID_USER_BUFFER
);
4283 else if (!DeviceInstallParams
)
4284 SetLastError(ERROR_INVALID_PARAMETER
);
4285 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4286 SetLastError(ERROR_INVALID_USER_BUFFER
);
4287 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4289 PSP_DEVINSTALL_PARAMS_W Destination
;
4292 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4294 Destination
= &list
->InstallParams
;
4295 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4299 TRACE("Returning %d\n", ret
);
4303 /***********************************************************************
4304 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4306 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
4307 IN HDEVINFO DeviceInfoSet
,
4308 IN PSP_DEVINFO_DATA DeviceInfoData
,
4309 OUT PSTR DeviceInstanceId OPTIONAL
,
4310 IN DWORD DeviceInstanceIdSize
,
4311 OUT PDWORD RequiredSize OPTIONAL
)
4313 PWSTR DeviceInstanceIdW
= NULL
;
4316 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4317 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4319 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4320 SetLastError(ERROR_INVALID_PARAMETER
);
4323 if (DeviceInstanceIdSize
!= 0)
4325 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4326 if (DeviceInstanceIdW
== NULL
)
4330 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4331 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4334 if (ret
&& DeviceInstanceIdW
!= NULL
)
4336 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4337 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4339 DeviceInstanceId
[0] = '\0';
4345 TRACE("Returning %d\n", ret
);
4349 /***********************************************************************
4350 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4352 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
4353 IN HDEVINFO DeviceInfoSet
,
4354 IN PSP_DEVINFO_DATA DeviceInfoData
,
4355 OUT PWSTR DeviceInstanceId OPTIONAL
,
4356 IN DWORD DeviceInstanceIdSize
,
4357 OUT PDWORD RequiredSize OPTIONAL
)
4361 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4362 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4365 SetLastError(ERROR_INVALID_HANDLE
);
4366 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4367 SetLastError(ERROR_INVALID_HANDLE
);
4368 else if (!DeviceInfoData
)
4369 SetLastError(ERROR_INVALID_PARAMETER
);
4370 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4371 SetLastError(ERROR_INVALID_USER_BUFFER
);
4372 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4373 SetLastError(ERROR_INVALID_PARAMETER
);
4374 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4375 SetLastError(ERROR_INVALID_PARAMETER
);
4378 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4381 required
= (strlenW(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4383 *RequiredSize
= required
;
4385 if (required
<= DeviceInstanceIdSize
)
4387 strcpyW(DeviceInstanceId
, DevInfo
->DeviceName
);
4391 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4394 TRACE("Returning %d\n", ret
);
4398 /***********************************************************************
4399 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4401 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
4402 IN HDEVINFO DeviceInfoSet
,
4403 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4404 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4405 IN DWORD PropertySheetHeaderPageListSize
,
4406 OUT PDWORD RequiredSize OPTIONAL
,
4407 IN DWORD PropertySheetType
)
4409 PROPSHEETHEADERW psh
;
4412 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4413 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4414 RequiredSize
, PropertySheetType
);
4416 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4417 psh
.phpage
= PropertySheetHeader
->phpage
;
4418 psh
.nPages
= PropertySheetHeader
->nPages
;
4420 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4421 PropertySheetHeaderPageListSize
, RequiredSize
,
4425 PropertySheetHeader
->nPages
= psh
.nPages
;
4428 TRACE("Returning %d\n", ret
);
4432 struct ClassDevPropertySheetsData
4434 HPROPSHEETPAGE
*PropertySheetPages
;
4435 DWORD MaximumNumberOfPages
;
4436 DWORD NumberOfPages
;
4439 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
4440 IN HPROPSHEETPAGE hPropSheetPage
,
4441 IN OUT LPARAM lParam
)
4443 struct ClassDevPropertySheetsData
*PropPageData
;
4445 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4447 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4449 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4450 PropPageData
->PropertySheetPages
++;
4453 PropPageData
->NumberOfPages
++;
4457 /***********************************************************************
4458 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4460 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
4461 IN HDEVINFO DeviceInfoSet
,
4462 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4463 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4464 IN DWORD PropertySheetHeaderPageListSize
,
4465 OUT PDWORD RequiredSize OPTIONAL
,
4466 IN DWORD PropertySheetType
)
4468 struct DeviceInfoSet
*list
;
4471 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4472 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4473 RequiredSize
, PropertySheetType
);
4476 SetLastError(ERROR_INVALID_HANDLE
);
4477 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4478 SetLastError(ERROR_INVALID_HANDLE
);
4479 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4480 SetLastError(ERROR_INVALID_HANDLE
);
4481 else if (!PropertySheetHeader
)
4482 SetLastError(ERROR_INVALID_PARAMETER
);
4483 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4484 SetLastError(ERROR_INVALID_FLAGS
);
4485 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4486 SetLastError(ERROR_INVALID_USER_BUFFER
);
4487 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4488 SetLastError(ERROR_INVALID_PARAMETER
);
4489 else if (!PropertySheetHeader
)
4490 SetLastError(ERROR_INVALID_PARAMETER
);
4491 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4492 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4493 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4494 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4495 SetLastError(ERROR_INVALID_PARAMETER
);
4498 HKEY hKey
= INVALID_HANDLE_VALUE
;
4499 SP_PROPSHEETPAGE_REQUEST Request
;
4500 LPWSTR PropPageProvider
= NULL
;
4501 HMODULE hModule
= NULL
;
4502 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4503 struct ClassDevPropertySheetsData PropPageData
;
4504 DWORD dwLength
, dwRegType
;
4508 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4511 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4512 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4514 if (hKey
== INVALID_HANDLE_VALUE
)
4517 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4518 if (rc
== ERROR_FILE_NOT_FOUND
)
4520 /* No registry key. As it is optional, don't say it's a bad error */
4526 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4532 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4533 if (!PropPageProvider
)
4535 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4538 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4539 if (rc
!= ERROR_SUCCESS
)
4544 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4546 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4547 if (rc
!= ERROR_SUCCESS
)
4549 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4553 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4554 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4555 Request
.DeviceInfoSet
= DeviceInfoSet
;
4556 Request
.DeviceInfoData
= DeviceInfoData
;
4557 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4558 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4559 PropPageData
.NumberOfPages
= 0;
4560 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4565 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4566 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4568 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4573 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4574 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4578 if (hKey
!= INVALID_HANDLE_VALUE
)
4580 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4581 FreeFunctionPointer(hModule
, pPropPageProvider
);
4584 TRACE("Returning %d\n", ret
);
4588 /***********************************************************************
4589 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4591 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4592 IN HDEVINFO DeviceInfoSet
,
4593 IN PSP_DEVINFO_DATA DeviceInfoData
,
4597 IN HINF InfHandle OPTIONAL
,
4598 IN PCSTR InfSectionName OPTIONAL
)
4600 PCWSTR InfSectionNameW
= NULL
;
4601 HKEY ret
= INVALID_HANDLE_VALUE
;
4605 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4606 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4609 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4617 if (InfSectionNameW
!= NULL
)
4618 MyFree((PVOID
)InfSectionNameW
);
4624 OpenHardwareProfileKey(
4627 IN DWORD samDesired
)
4629 HKEY hHWProfilesKey
= INVALID_HANDLE_VALUE
;
4630 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4631 HKEY ret
= INVALID_HANDLE_VALUE
;
4634 rc
= RegOpenKeyExW(HKLM
,
4635 REGSTR_PATH_HWPROFILES
,
4639 if (rc
!= ERROR_SUCCESS
)
4656 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4665 if (rc
!= ERROR_SUCCESS
)
4670 ret
= hHWProfileKey
;
4673 if (hHWProfilesKey
!= INVALID_HANDLE_VALUE
)
4674 RegCloseKey(hHWProfilesKey
);
4675 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
&& hHWProfileKey
!= ret
)
4676 RegCloseKey(hHWProfileKey
);
4680 /***********************************************************************
4681 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4683 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4684 IN HDEVINFO DeviceInfoSet
,
4685 IN PSP_DEVINFO_DATA DeviceInfoData
,
4689 IN HINF InfHandle OPTIONAL
,
4690 IN PCWSTR InfSectionName OPTIONAL
)
4692 struct DeviceInfoSet
*list
;
4693 HKEY ret
= INVALID_HANDLE_VALUE
;
4695 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4696 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4699 SetLastError(ERROR_INVALID_HANDLE
);
4700 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4701 SetLastError(ERROR_INVALID_HANDLE
);
4702 else if (!DeviceInfoData
)
4703 SetLastError(ERROR_INVALID_PARAMETER
);
4704 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4705 SetLastError(ERROR_INVALID_USER_BUFFER
);
4706 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4707 SetLastError(ERROR_INVALID_PARAMETER
);
4708 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4709 SetLastError(ERROR_INVALID_PARAMETER
);
4710 else if (InfHandle
&& !InfSectionName
)
4711 SetLastError(ERROR_INVALID_PARAMETER
);
4712 else if (!InfHandle
&& InfSectionName
)
4713 SetLastError(ERROR_INVALID_PARAMETER
);
4716 LPWSTR lpGuidString
= NULL
;
4717 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4718 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4719 DWORD Index
; /* Index used in the DriverKey name */
4721 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4722 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4723 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4724 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4725 HKEY hKey
= INVALID_HANDLE_VALUE
;
4728 if (Scope
== DICS_FLAG_GLOBAL
)
4729 RootKey
= list
->HKLM
;
4730 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4732 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
4733 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4735 RootKey
= hHWProfileKey
;
4738 if (KeyType
== DIREG_DEV
)
4740 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4742 rc
= RegCreateKeyExW(
4744 REGSTR_PATH_SYSTEMENUM
,
4747 REG_OPTION_NON_VOLATILE
,
4752 if (rc
!= ERROR_SUCCESS
)
4757 rc
= RegCreateKeyExW(
4759 deviceInfo
->DeviceName
,
4762 REG_OPTION_NON_VOLATILE
,
4763 #if _WIN32_WINNT >= 0x502
4764 KEY_READ
| KEY_WRITE
,
4771 if (rc
!= ERROR_SUCCESS
)
4777 else /* KeyType == DIREG_DRV */
4779 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4781 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4782 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4785 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4788 strcpyW(DriverKey
, L
"{");
4789 strcatW(DriverKey
, lpGuidString
);
4790 strcatW(DriverKey
, L
"}\\");
4791 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
4792 rc
= RegOpenKeyExW(RootKey
,
4793 REGSTR_PATH_CLASS_NT
,
4797 if (rc
!= ERROR_SUCCESS
)
4803 /* Try all values for Index between 0 and 9999 */
4805 while (Index
<= 9999)
4808 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4809 rc
= RegCreateKeyEx(hClassKey
,
4813 REG_OPTION_NON_VOLATILE
,
4814 #if _WIN32_WINNT >= 0x502
4815 KEY_READ
| KEY_WRITE
,
4822 if (rc
!= ERROR_SUCCESS
)
4827 if (Disposition
== REG_CREATED_NEW_KEY
)
4830 hKey
= INVALID_HANDLE_VALUE
;
4835 /* Unable to create more than 9999 devices within the same class */
4836 SetLastError(ERROR_GEN_FAILURE
);
4840 /* Open device key, to write Driver value */
4841 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4842 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4844 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
4845 if (rc
!= ERROR_SUCCESS
)
4852 /* Do installation of the specified section */
4855 FIXME("Need to install section %s in file %p\n",
4856 debugstr_w(InfSectionName
), InfHandle
);
4862 RpcStringFreeW(&lpGuidString
);
4863 HeapFree(GetProcessHeap(), 0, DriverKey
);
4864 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4865 RegCloseKey(hHWProfileKey
);
4866 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4867 RegCloseKey(hEnumKey
);
4868 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4869 RegCloseKey(hClassKey
);
4870 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4871 RegCloseKey(hDeviceKey
);
4872 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4876 TRACE("Returning 0x%p\n", ret
);
4880 /***********************************************************************
4881 * SetupDiOpenDevRegKey (SETUPAPI.@)
4883 HKEY WINAPI
SetupDiOpenDevRegKey(
4884 HDEVINFO DeviceInfoSet
,
4885 PSP_DEVINFO_DATA DeviceInfoData
,
4891 struct DeviceInfoSet
*list
;
4892 HKEY ret
= INVALID_HANDLE_VALUE
;
4894 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4895 Scope
, HwProfile
, KeyType
, samDesired
);
4898 SetLastError(ERROR_INVALID_HANDLE
);
4899 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4900 SetLastError(ERROR_INVALID_HANDLE
);
4901 else if (!DeviceInfoData
)
4902 SetLastError(ERROR_INVALID_PARAMETER
);
4903 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4904 SetLastError(ERROR_INVALID_USER_BUFFER
);
4905 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4906 SetLastError(ERROR_INVALID_PARAMETER
);
4907 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4908 SetLastError(ERROR_INVALID_PARAMETER
);
4911 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4912 LPWSTR DriverKey
= NULL
;
4916 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4917 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4918 HKEY hKey
= INVALID_HANDLE_VALUE
;
4921 if (Scope
== DICS_FLAG_GLOBAL
)
4922 RootKey
= list
->HKLM
;
4923 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4925 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
4926 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4928 RootKey
= hHWProfileKey
;
4933 REGSTR_PATH_SYSTEMENUM
,
4937 if (rc
!= ERROR_SUCCESS
)
4944 deviceInfo
->DeviceName
,
4946 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4948 RegCloseKey(hEnumKey
);
4949 hEnumKey
= INVALID_HANDLE_VALUE
;
4950 if (rc
!= ERROR_SUCCESS
)
4955 if (KeyType
== DIREG_DEV
)
4957 /* We're done. Just return the hKey handle */
4961 /* Read the 'Driver' key */
4962 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
4963 if (rc
!= ERROR_SUCCESS
)
4968 else if (dwRegType
!= REG_SZ
)
4970 SetLastError(ERROR_GEN_FAILURE
);
4973 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4976 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4979 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4980 if (rc
!= ERROR_SUCCESS
)
4986 hKey
= INVALID_HANDLE_VALUE
;
4987 /* Need to open the driver key */
4990 REGSTR_PATH_CLASS_NT
,
4994 if (rc
!= ERROR_SUCCESS
)
5005 if (rc
!= ERROR_SUCCESS
)
5013 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
5014 RegCloseKey(hHWProfileKey
);
5015 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
5016 RegCloseKey(hEnumKey
);
5017 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
5021 TRACE("Returning 0x%p\n", ret
);
5025 /***********************************************************************
5026 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
5028 BOOL WINAPI
SetupDiCreateDeviceInfoA(
5029 HDEVINFO DeviceInfoSet
,
5031 CONST GUID
*ClassGuid
,
5032 PCSTR DeviceDescription
,
5034 DWORD CreationFlags
,
5035 PSP_DEVINFO_DATA DeviceInfoData
)
5037 LPWSTR DeviceNameW
= NULL
;
5038 LPWSTR DeviceDescriptionW
= NULL
;
5045 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
5046 if (DeviceNameW
== NULL
) return FALSE
;
5048 if (DeviceDescription
)
5050 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
5051 if (DeviceDescriptionW
== NULL
)
5053 if (DeviceNameW
) MyFree(DeviceNameW
);
5058 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
5059 ClassGuid
, DeviceDescriptionW
,
5060 hwndParent
, CreationFlags
,
5063 if (DeviceNameW
) MyFree(DeviceNameW
);
5064 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
5069 /***********************************************************************
5070 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
5072 BOOL WINAPI
SetupDiCreateDeviceInfoW(
5073 HDEVINFO DeviceInfoSet
,
5075 CONST GUID
*ClassGuid
,
5076 PCWSTR DeviceDescription
,
5078 DWORD CreationFlags
,
5079 PSP_DEVINFO_DATA DeviceInfoData
)
5081 struct DeviceInfoSet
*list
;
5084 TRACE("%p %s %s %s %p %lx %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
5085 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
5086 hwndParent
, CreationFlags
, DeviceInfoData
);
5089 SetLastError(ERROR_INVALID_HANDLE
);
5090 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5091 SetLastError(ERROR_INVALID_HANDLE
);
5092 else if (!ClassGuid
)
5093 SetLastError(ERROR_INVALID_PARAMETER
);
5094 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
5095 SetLastError(ERROR_CLASS_MISMATCH
);
5096 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
5098 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
5099 SetLastError(ERROR_INVALID_FLAGS
);
5103 SP_DEVINFO_DATA DevInfo
;
5105 if (CreationFlags
& DICD_GENERATE_ID
)
5107 /* Generate a new unique ID for this device */
5108 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5109 FIXME("not implemented\n");
5113 /* Device name is fully qualified. Try to open it */
5116 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
5117 rc
= SetupDiOpenDeviceInfoW(
5120 NULL
, /* hwndParent */
5121 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
5126 /* SetupDiOpenDeviceInfoW has already added
5127 * the device info to the device info set
5129 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
5131 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5133 struct DeviceInfoElement
*deviceInfo
;
5135 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
5137 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5139 if (!DeviceInfoData
)
5143 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
5145 SetLastError(ERROR_INVALID_USER_BUFFER
);
5149 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5150 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5151 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5160 TRACE("Returning %d\n", ret
);
5164 /***********************************************************************
5165 * Helper functions for SetupDiBuildDriverInfoList
5169 IN PLIST_ENTRY DriverListHead
,
5170 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5171 IN LPGUID ClassGuid
,
5172 IN INFCONTEXT ContextDevice
,
5173 IN
struct InfFileDetails
*InfFileDetails
,
5175 IN LPCWSTR ProviderName
,
5176 IN LPCWSTR ManufacturerName
,
5177 IN LPCWSTR MatchingId
,
5178 FILETIME DriverDate
,
5179 DWORDLONG DriverVersion
,
5182 struct DriverInfoElement
*driverInfo
= NULL
;
5183 HANDLE hFile
= INVALID_HANDLE_VALUE
;
5184 DWORD RequiredSize
= 128; /* Initial buffer size */
5185 BOOL Result
= FALSE
;
5186 PLIST_ENTRY PreviousEntry
;
5187 LPWSTR InfInstallSection
= NULL
;
5190 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
5193 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5196 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
5198 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
5199 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
5201 /* Copy InfFileName field */
5202 strncpyW(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
5203 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
5205 /* Fill InfDate field */
5206 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5207 GENERIC_READ, FILE_SHARE_READ,
5208 NULL, OPEN_EXISTING, 0, NULL);
5209 if (hFile == INVALID_HANDLE_VALUE)
5211 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5215 /* Fill SectionName field */
5216 Result
= SetupGetStringFieldW(
5219 driverInfo
->Details
.SectionName
, LINE_LEN
,
5224 /* Fill DrvDescription field */
5225 Result
= SetupGetStringFieldW(
5227 0, /* Field index */
5228 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
5231 /* Copy MatchingId information */
5234 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
5235 if (!driverInfo
->MatchingId
)
5237 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5240 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
5243 driverInfo
->MatchingId
= NULL
;
5245 /* Get inf install section */
5247 RequiredSize
= 128; /* Initial buffer size */
5248 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5249 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5251 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5252 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5253 if (!InfInstallSection
)
5255 Result
= SetupGetStringFieldW(
5257 1, /* Field index */
5258 InfInstallSection
, RequiredSize
,
5264 TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n",
5265 debugstr_w(driverInfo
->Details
.DrvDescription
), debugstr_w(InfFile
),
5266 debugstr_w(InfInstallSection
), Rank
);
5268 driverInfo
->DriverRank
= Rank
;
5269 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
5270 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5271 driverInfo
->Info
.DriverType
= DriverType
;
5272 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
5273 strncpyW(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
5274 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
5275 strncpyW(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
5276 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
5279 strncpyW(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
5280 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
5283 driverInfo
->Info
.ProviderName
[0] = '\0';
5284 driverInfo
->Info
.DriverDate
= DriverDate
;
5285 driverInfo
->Info
.DriverVersion
= DriverVersion
;
5286 ReferenceInfFile(InfFileDetails
);
5287 driverInfo
->InfFileDetails
= InfFileDetails
;
5289 /* Insert current driver in driver list, according to its rank */
5290 PreviousEntry
= DriverListHead
->Flink
;
5291 while (PreviousEntry
!= DriverListHead
)
5293 struct DriverInfoElement
*CurrentDriver
;
5294 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
5295 if (CurrentDriver
->DriverRank
> Rank
||
5296 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
5298 /* Insert before the current item */
5299 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
5302 PreviousEntry
= PreviousEntry
->Flink
;
5304 if (PreviousEntry
== DriverListHead
)
5306 /* Insert at the end of the list */
5307 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
5316 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
5317 HeapFree(GetProcessHeap(), 0, driverInfo
);
5319 if (hFile
!= INVALID_HANDLE_VALUE
)
5321 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5327 GetVersionInformationFromInfFile(
5329 OUT LPGUID ClassGuid
,
5330 OUT LPWSTR
* pProviderName
,
5331 OUT FILETIME
* DriverDate
,
5332 OUT DWORDLONG
* DriverVersion
)
5335 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5336 LPWSTR DriverVer
= NULL
;
5337 LPWSTR ProviderName
= NULL
;
5338 LPWSTR pComma
; /* Points into DriverVer */
5339 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5340 SYSTEMTIME SystemTime
;
5342 BOOL ret
= FALSE
; /* Final result */
5344 /* Get class Guid */
5345 if (!SetupGetLineTextW(
5349 guidW
, sizeof(guidW
),
5350 NULL
/* Required size */))
5354 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5355 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5357 SetLastError(ERROR_GEN_FAILURE
);
5361 /* Get provider name */
5362 Result
= SetupGetLineTextW(
5364 hInf
, Version
, INF_PROVIDER
,
5369 /* We know know the needed buffer size */
5370 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5373 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5376 Result
= SetupGetLineTextW(
5378 hInf
, Version
, INF_PROVIDER
,
5379 ProviderName
, RequiredSize
,
5384 *pProviderName
= ProviderName
;
5386 /* Read the "DriverVer" value */
5387 Result
= SetupGetLineTextW(
5389 hInf
, Version
, INF_DRIVER_VER
,
5394 /* We know know the needed buffer size */
5395 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5398 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5401 Result
= SetupGetLineTextW(
5403 hInf
, Version
, INF_DRIVER_VER
,
5404 DriverVer
, RequiredSize
,
5410 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5411 pComma
= strchrW(DriverVer
, ',');
5414 *pComma
= UNICODE_NULL
;
5415 pVersion
= pComma
+ 1;
5417 /* Get driver date version. Invalid date = 00/00/00 */
5418 memset(DriverDate
, 0, sizeof(FILETIME
));
5419 if (strlenW(DriverVer
) == 10
5420 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5421 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5423 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5424 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5425 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5426 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5427 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5428 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5430 /* Get driver version. Invalid version = 0.0.0.0 */
5434 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5435 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5436 LARGE_INTEGER fullVersion
;
5438 pMinor
= strchrW(pVersion
, '.');
5442 pRevision
= strchrW(++pMinor
, '.');
5443 Minor
= atoiW(pMinor
);
5448 pBuild
= strchrW(++pRevision
, '.');
5449 Revision
= atoiW(pRevision
);
5455 Build
= atoiW(pBuild
);
5457 Major
= atoiW(pVersion
);
5458 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5459 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5460 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5467 HeapFree(GetProcessHeap(), 0, ProviderName
);
5468 HeapFree(GetProcessHeap(), 0, DriverVer
);
5474 GetHardwareAndCompatibleIDsLists(
5475 IN HDEVINFO DeviceInfoSet
,
5476 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
5477 OUT LPWSTR
*pHardwareIDs OPTIONAL
,
5478 OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL
,
5479 OUT LPWSTR
*pCompatibleIDs OPTIONAL
,
5480 OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL
)
5482 LPWSTR HardwareIDs
= NULL
;
5483 LPWSTR CompatibleIDs
= NULL
;
5487 /* Get hardware IDs list */
5489 RequiredSize
= 512; /* Initial buffer size */
5490 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5491 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5493 MyFree(HardwareIDs
);
5494 HardwareIDs
= MyMalloc(RequiredSize
);
5497 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5500 Result
= SetupDiGetDeviceRegistryPropertyW(
5511 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5513 /* No hardware ID for this device */
5514 MyFree(HardwareIDs
);
5522 *pHardwareIDs
= HardwareIDs
;
5523 if (pHardwareIDsRequiredSize
)
5524 *pHardwareIDsRequiredSize
= RequiredSize
;
5526 /* Get compatible IDs list */
5528 RequiredSize
= 512; /* Initial buffer size */
5529 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5530 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5532 MyFree(CompatibleIDs
);
5533 CompatibleIDs
= MyMalloc(RequiredSize
);
5536 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5539 Result
= SetupDiGetDeviceRegistryPropertyW(
5542 SPDRP_COMPATIBLEIDS
,
5544 (PBYTE
)CompatibleIDs
,
5550 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5552 /* No compatible ID for this device */
5553 MyFree(CompatibleIDs
);
5554 CompatibleIDs
= NULL
;
5561 *pCompatibleIDs
= CompatibleIDs
;
5562 if (pCompatibleIDsRequiredSize
)
5563 *pCompatibleIDsRequiredSize
= RequiredSize
;
5570 MyFree(HardwareIDs
);
5571 MyFree(CompatibleIDs
);
5576 /***********************************************************************
5577 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5580 SetupDiBuildDriverInfoList(
5581 IN HDEVINFO DeviceInfoSet
,
5582 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5583 IN DWORD DriverType
)
5585 struct DeviceInfoSet
*list
;
5586 SP_DEVINSTALL_PARAMS_W InstallParams
;
5587 PVOID Buffer
= NULL
;
5588 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5589 LPWSTR ProviderName
= NULL
;
5590 LPWSTR ManufacturerName
= NULL
;
5591 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5592 LPWSTR HardwareIDs
= NULL
;
5593 LPWSTR CompatibleIDs
= NULL
;
5594 LPWSTR FullInfFileName
= NULL
;
5595 LPWSTR ExcludeFromSelect
= NULL
;
5596 FILETIME DriverDate
;
5597 DWORDLONG DriverVersion
= 0;
5601 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5604 SetLastError(ERROR_INVALID_HANDLE
);
5605 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5606 SetLastError(ERROR_INVALID_HANDLE
);
5607 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5608 SetLastError(ERROR_INVALID_HANDLE
);
5609 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5610 SetLastError(ERROR_INVALID_PARAMETER
);
5611 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5612 SetLastError(ERROR_INVALID_PARAMETER
);
5613 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5614 SetLastError(ERROR_INVALID_USER_BUFFER
);
5617 PLIST_ENTRY pDriverListHead
= &list
->DriverListHead
;
5620 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5621 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5627 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5628 if (!(devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
5629 pDriverListHead
= &devInfo
->DriverListHead
;
5632 if (DriverType
== SPDIT_COMPATDRIVER
)
5634 /* Get hardware and compatible IDs lists */
5635 Result
= GetHardwareAndCompatibleIDsLists(
5644 if (!HardwareIDs
&& !CompatibleIDs
)
5646 SetLastError(ERROR_FILE_NOT_FOUND
);
5651 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5653 /* InstallParams.DriverPath contains the name of a .inf file */
5654 RequiredSize
= strlenW(InstallParams
.DriverPath
) + 2;
5655 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5658 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5661 strcpyW(Buffer
, InstallParams
.DriverPath
);
5662 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
5667 /* Enumerate .inf files */
5669 RequiredSize
= 32768; /* Initial buffer size */
5670 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5671 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5673 HeapFree(GetProcessHeap(), 0, Buffer
);
5674 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5678 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5681 Result
= SetupGetInfFileListW(
5682 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5684 Buffer
, RequiredSize
,
5687 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5689 /* No .inf file in specified directory. So, we should
5690 * success as we created an empty driver info list.
5699 LPWSTR pFullFilename
;
5701 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5703 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5704 if (!FullInfFileName
)
5706 pFullFilename
= &FullInfFileName
[0];
5708 else if (*InstallParams
.DriverPath
)
5711 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5714 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5715 if (!FullInfFileName
)
5717 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5720 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
5721 strcatW(FullInfFileName
, L
"\\");
5722 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
5726 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5727 if (!FullInfFileName
)
5729 pFullFilename
= &FullInfFileName
[0];
5732 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= strlenW(filename
) + 1)
5734 INFCONTEXT ContextManufacturer
, ContextDevice
;
5737 strcpyW(pFullFilename
, filename
);
5738 TRACE("Opening file %s\n", debugstr_w(FullInfFileName
));
5740 currentInfFileDetails
= HeapAlloc(
5743 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + strlenW(FullInfFileName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
5744 if (!currentInfFileDetails
)
5746 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5747 strcpyW(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5749 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5750 ReferenceInfFile(currentInfFileDetails
);
5751 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5753 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5754 currentInfFileDetails
= NULL
;
5758 if (!GetVersionInformationFromInfFile(
5759 currentInfFileDetails
->hInf
,
5765 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5766 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5767 currentInfFileDetails
= NULL
;
5771 if (DriverType
== SPDIT_CLASSDRIVER
)
5773 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5774 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5780 if (InstallParams
.FlagsEx
& DI_FLAGSEX_ALLOWEXCLUDEDDRVS
)
5782 /* Read ExcludeFromSelect control flags */
5786 FIXME("ExcludeFromSelect list ignored\n");
5788 /* Get the manufacturers list */
5789 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, INF_MANUFACTURER
, NULL
, &ContextManufacturer
);
5792 Result
= SetupGetStringFieldW(
5793 &ContextManufacturer
,
5794 0, /* Field index */
5799 /* We got the needed size for the buffer */
5800 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5801 if (!ManufacturerName
)
5803 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5806 Result
= SetupGetStringFieldW(
5807 &ContextManufacturer
,
5808 0, /* Field index */
5809 ManufacturerName
, RequiredSize
,
5812 /* Get manufacturer section name */
5813 Result
= SetupGetStringFieldW(
5814 &ContextManufacturer
,
5815 1, /* Field index */
5816 ManufacturerSection
, LINE_LEN
,
5820 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5821 /* Add (possible) extension to manufacturer section name */
5822 Result
= SetupDiGetActualSectionToInstallW(
5823 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5826 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection
));
5827 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5832 if (DriverType
== SPDIT_CLASSDRIVER
)
5834 /* FIXME: Check ExcludeFromSelect list */
5835 if (!AddDriverToList(
5840 currentInfFileDetails
,
5845 DriverDate
, DriverVersion
,
5851 else /* DriverType = SPDIT_COMPATDRIVER */
5853 /* 1. Get all fields */
5854 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5858 BOOL DriverAlreadyAdded
;
5860 for (i
= 2; i
<= FieldCount
; i
++)
5862 LPWSTR DeviceId
= NULL
;
5864 RequiredSize
= 128; /* Initial buffer size */
5865 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5866 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5868 HeapFree(GetProcessHeap(), 0, DeviceId
);
5869 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5872 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5875 Result
= SetupGetStringFieldW(
5878 DeviceId
, RequiredSize
,
5883 HeapFree(GetProcessHeap(), 0, DeviceId
);
5886 /* FIXME: Check ExcludeFromSelect list */
5887 DriverAlreadyAdded
= FALSE
;
5888 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
5890 if (wcsicmp(DeviceId
, currentId
) == 0)
5897 currentInfFileDetails
,
5902 DriverDate
, DriverVersion
,
5903 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5904 DriverAlreadyAdded
= TRUE
;
5909 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
5911 if (wcsicmp(DeviceId
, currentId
) == 0)
5918 currentInfFileDetails
,
5923 DriverDate
, DriverVersion
,
5924 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5925 DriverAlreadyAdded
= TRUE
;
5929 HeapFree(GetProcessHeap(), 0, DeviceId
);
5932 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5935 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5936 ManufacturerName
= NULL
;
5937 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5942 HeapFree(GetProcessHeap(), 0, ProviderName
);
5943 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
5944 ProviderName
= ExcludeFromSelect
= NULL
;
5946 DereferenceInfFile(currentInfFileDetails
);
5947 currentInfFileDetails
= NULL
;
5958 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5959 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5963 InstallParams
.Flags
|= DI_DIDCLASS
;
5964 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5966 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5969 HeapFree(GetProcessHeap(), 0, ProviderName
);
5970 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5971 MyFree(HardwareIDs
);
5972 MyFree(CompatibleIDs
);
5973 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5974 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
5975 if (currentInfFileDetails
)
5976 DereferenceInfFile(currentInfFileDetails
);
5977 HeapFree(GetProcessHeap(), 0, Buffer
);
5979 TRACE("Returning %d\n", ret
);
5983 /***********************************************************************
5984 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5987 SetupDiDeleteDeviceInfo(
5988 IN HDEVINFO DeviceInfoSet
,
5989 IN PSP_DEVINFO_DATA DeviceInfoData
)
5991 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5993 FIXME("not implemented\n");
5994 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5999 /***********************************************************************
6000 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
6003 SetupDiDestroyDriverInfoList(
6004 IN HDEVINFO DeviceInfoSet
,
6005 IN PSP_DEVINFO_DATA DeviceInfoData
,
6006 IN DWORD DriverType
)
6008 struct DeviceInfoSet
*list
;
6011 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
6014 SetLastError(ERROR_INVALID_HANDLE
);
6015 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6016 SetLastError(ERROR_INVALID_HANDLE
);
6017 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6018 SetLastError(ERROR_INVALID_PARAMETER
);
6019 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6020 SetLastError(ERROR_INVALID_PARAMETER
);
6021 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6022 SetLastError(ERROR_INVALID_USER_BUFFER
);
6025 PLIST_ENTRY ListEntry
;
6026 struct DriverInfoElement
*driverInfo
;
6027 SP_DEVINSTALL_PARAMS_W InstallParams
;
6029 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6030 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6033 if (!DeviceInfoData
)
6034 /* Fall back to destroying class driver list */
6035 DriverType
= SPDIT_CLASSDRIVER
;
6037 if (DriverType
== SPDIT_CLASSDRIVER
)
6039 while (!IsListEmpty(&list
->DriverListHead
))
6041 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
6042 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
6043 DestroyDriverInfoElement(driverInfo
);
6045 InstallParams
.Reserved
= 0;
6046 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
6047 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
6048 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
6052 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
6053 struct DeviceInfoElement
*deviceInfo
;
6055 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6056 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
6058 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6059 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
6061 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
6062 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
6063 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
6065 InstallParamsSet
.Reserved
= 0;
6066 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
6068 DestroyDriverInfoElement(driverInfo
);
6070 InstallParams
.Reserved
= 0;
6071 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
6072 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
6073 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6078 TRACE("Returning %d\n", ret
);
6083 /***********************************************************************
6084 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
6087 SetupDiOpenDeviceInfoA(
6088 IN HDEVINFO DeviceInfoSet
,
6089 IN PCSTR DeviceInstanceId
,
6090 IN HWND hwndParent OPTIONAL
,
6092 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6094 LPWSTR DeviceInstanceIdW
= NULL
;
6097 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
6099 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
6100 if (DeviceInstanceIdW
== NULL
)
6103 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
6104 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
6106 MyFree(DeviceInstanceIdW
);
6112 /***********************************************************************
6113 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
6116 SetupDiOpenDeviceInfoW(
6117 IN HDEVINFO DeviceInfoSet
,
6118 IN PCWSTR DeviceInstanceId
,
6119 IN HWND hwndParent OPTIONAL
,
6121 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6123 struct DeviceInfoSet
*list
;
6124 HKEY hEnumKey
, hKey
;
6128 TRACE("%p %s %p %lx %p\n",
6129 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
6130 hwndParent
, OpenFlags
, DeviceInfoData
);
6132 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
6133 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
6136 SetLastError(ERROR_INVALID_HANDLE
);
6137 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6138 SetLastError(ERROR_INVALID_HANDLE
);
6139 else if (!DeviceInstanceId
)
6140 SetLastError(ERROR_INVALID_PARAMETER
);
6141 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
6143 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
6144 SetLastError(ERROR_INVALID_FLAGS
);
6146 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6147 SetLastError(ERROR_INVALID_USER_BUFFER
);
6150 struct DeviceInfoElement
*deviceInfo
= NULL
;
6151 /* Search if device already exists in DeviceInfoSet.
6152 * If yes, return the existing element
6153 * If no, create a new element using informations in registry
6155 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
6156 while (ItemList
!= &list
->ListHead
)
6161 FIXME("not implemented\n");
6162 ItemList
= ItemList
->Flink
;
6167 /* good one found */
6172 /* Open supposed registry key */
6175 REGSTR_PATH_SYSTEMENUM
,
6179 if (rc
!= ERROR_SUCCESS
)
6190 RegCloseKey(hEnumKey
);
6191 if (rc
!= ERROR_SUCCESS
)
6193 if (rc
== ERROR_FILE_NOT_FOUND
)
6194 rc
= ERROR_NO_SUCH_DEVINST
;
6199 /* FIXME: try to get ClassGUID from registry, instead of
6200 * sending GUID_NULL to CreateDeviceInfoElement
6202 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
6207 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
6213 if (ret
&& deviceInfo
&& DeviceInfoData
)
6215 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
6216 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
6217 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
6225 /***********************************************************************
6226 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6229 SetupDiEnumDriverInfoA(
6230 IN HDEVINFO DeviceInfoSet
,
6231 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6232 IN DWORD DriverType
,
6233 IN DWORD MemberIndex
,
6234 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6236 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6239 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6240 DriverType
, MemberIndex
, DriverInfoData
);
6242 if (DriverInfoData
== NULL
)
6243 SetLastError(ERROR_INVALID_PARAMETER
);
6244 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6245 SetLastError(ERROR_INVALID_USER_BUFFER
);
6248 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6249 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
6250 DriverType
, MemberIndex
, &driverInfoData2W
);
6254 /* Do W->A conversion */
6255 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6256 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6257 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6258 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6260 DriverInfoData
->Description
[0] = '\0';
6263 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6264 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6266 DriverInfoData
->MfgName
[0] = '\0';
6269 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6270 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6272 DriverInfoData
->ProviderName
[0] = '\0';
6275 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6277 /* Copy more fields */
6278 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6279 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6284 TRACE("Returning %d\n", ret
);
6289 /***********************************************************************
6290 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6293 SetupDiEnumDriverInfoW(
6294 IN HDEVINFO DeviceInfoSet
,
6295 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6296 IN DWORD DriverType
,
6297 IN DWORD MemberIndex
,
6298 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6300 PLIST_ENTRY ListHead
;
6303 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6304 DriverType
, MemberIndex
, DriverInfoData
);
6306 if (!DeviceInfoSet
|| !DriverInfoData
)
6307 SetLastError(ERROR_INVALID_PARAMETER
);
6308 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6309 SetLastError(ERROR_INVALID_HANDLE
);
6310 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6311 SetLastError(ERROR_INVALID_HANDLE
);
6312 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6313 SetLastError(ERROR_INVALID_PARAMETER
);
6314 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6315 SetLastError(ERROR_INVALID_PARAMETER
);
6316 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6317 SetLastError(ERROR_INVALID_USER_BUFFER
);
6320 struct DeviceInfoElement
*devInfo
= NULL
;
6321 PLIST_ENTRY ItemList
;
6323 devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6324 if (!devInfo
|| (devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
6326 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6330 ListHead
= &devInfo
->DriverListHead
;
6333 ItemList
= ListHead
->Flink
;
6334 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
6335 ItemList
= ItemList
->Flink
;
6336 if (ItemList
== ListHead
)
6337 SetLastError(ERROR_NO_MORE_ITEMS
);
6340 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
6343 &DriverInfoData
->DriverType
,
6344 &DrvInfo
->Info
.DriverType
,
6345 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6350 TRACE("Returning %d\n", ret
);
6355 /***********************************************************************
6356 * SetupDiGetSelectedDevice (SETUPAPI.@)
6359 SetupDiGetSelectedDevice(
6360 IN HDEVINFO DeviceInfoSet
,
6361 OUT PSP_DEVINFO_DATA DeviceInfoData
)
6363 struct DeviceInfoSet
*list
;
6366 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6369 SetLastError(ERROR_INVALID_HANDLE
);
6370 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6371 SetLastError(ERROR_INVALID_HANDLE
);
6372 else if (list
->SelectedDevice
== NULL
)
6373 SetLastError(ERROR_NO_DEVICE_SELECTED
);
6374 else if (!DeviceInfoData
)
6375 SetLastError(ERROR_INVALID_PARAMETER
);
6376 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6377 SetLastError(ERROR_INVALID_USER_BUFFER
);
6380 memcpy(&DeviceInfoData
->ClassGuid
,
6381 &list
->SelectedDevice
->ClassGuid
,
6383 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
6384 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
6388 TRACE("Returning %d\n", ret
);
6393 /***********************************************************************
6394 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6397 SetupDiGetSelectedDriverA(
6398 IN HDEVINFO DeviceInfoSet
,
6399 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6400 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6402 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6405 if (DriverInfoData
== NULL
)
6406 SetLastError(ERROR_INVALID_PARAMETER
);
6407 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6408 SetLastError(ERROR_INVALID_USER_BUFFER
);
6411 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6413 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
6419 /* Do W->A conversion */
6420 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6421 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6422 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6423 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6425 DriverInfoData
->Description
[0] = '\0';
6428 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6429 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6431 DriverInfoData
->MfgName
[0] = '\0';
6434 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6435 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6437 DriverInfoData
->ProviderName
[0] = '\0';
6440 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6442 /* Copy more fields */
6443 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6444 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6453 /***********************************************************************
6454 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6457 SetupDiGetSelectedDriverW(
6458 IN HDEVINFO DeviceInfoSet
,
6459 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6460 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6464 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6466 if (!DeviceInfoSet
|| !DriverInfoData
)
6467 SetLastError(ERROR_INVALID_PARAMETER
);
6468 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6469 SetLastError(ERROR_INVALID_HANDLE
);
6470 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6471 SetLastError(ERROR_INVALID_HANDLE
);
6472 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6473 SetLastError(ERROR_INVALID_USER_BUFFER
);
6474 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6475 SetLastError(ERROR_INVALID_USER_BUFFER
);
6478 SP_DEVINSTALL_PARAMS InstallParams
;
6480 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6481 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6483 struct DriverInfoElement
*driverInfo
;
6484 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6485 if (driverInfo
== NULL
)
6486 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6490 &DriverInfoData
->DriverType
,
6491 &driverInfo
->Info
.DriverType
,
6492 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6498 TRACE("Returning %d\n", ret
);
6503 /***********************************************************************
6504 * SetupDiSetSelectedDevice (SETUPAPI.@)
6507 SetupDiSetSelectedDevice(
6508 IN HDEVINFO DeviceInfoSet
,
6509 IN PSP_DEVINFO_DATA DeviceInfoData
)
6511 struct DeviceInfoSet
*list
;
6514 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6517 SetLastError(ERROR_INVALID_HANDLE
);
6518 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6519 SetLastError(ERROR_INVALID_HANDLE
);
6520 else if (!DeviceInfoData
)
6521 SetLastError(ERROR_INVALID_PARAMETER
);
6522 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6523 SetLastError(ERROR_INVALID_USER_BUFFER
);
6524 else if (DeviceInfoData
->Reserved
== 0)
6525 SetLastError(ERROR_INVALID_USER_BUFFER
);
6528 list
->SelectedDevice
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6532 TRACE("Returning %d\n", ret
);
6537 /***********************************************************************
6538 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6541 SetupDiSetSelectedDriverA(
6542 IN HDEVINFO DeviceInfoSet
,
6543 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6544 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6546 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6547 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6550 if (DriverInfoData
!= NULL
)
6552 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6553 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6555 SetLastError(ERROR_INVALID_PARAMETER
);
6559 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6560 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6562 if (DriverInfoDataW
.Reserved
== 0)
6564 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6566 /* convert the strings to unicode */
6567 if (!MultiByteToWideChar(CP_ACP
,
6569 DriverInfoData
->Description
,
6571 DriverInfoDataW
.Description
,
6573 !MultiByteToWideChar(CP_ACP
,
6575 DriverInfoData
->ProviderName
,
6577 DriverInfoDataW
.ProviderName
,
6584 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6587 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6591 if (ret
&& pDriverInfoDataW
!= NULL
)
6593 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6600 /***********************************************************************
6601 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6604 SetupDiSetSelectedDriverW(
6605 IN HDEVINFO DeviceInfoSet
,
6606 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6607 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6611 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6614 SetLastError(ERROR_INVALID_PARAMETER
);
6615 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6616 SetLastError(ERROR_INVALID_HANDLE
);
6617 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6618 SetLastError(ERROR_INVALID_HANDLE
);
6619 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6620 SetLastError(ERROR_INVALID_USER_BUFFER
);
6621 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6622 SetLastError(ERROR_INVALID_USER_BUFFER
);
6625 struct DriverInfoElement
**pDriverInfo
;
6626 PLIST_ENTRY ListHead
, ItemList
;
6630 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6631 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6635 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6636 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6639 if (!DriverInfoData
)
6641 *pDriverInfo
= NULL
;
6646 /* Search selected driver in list */
6647 ItemList
= ListHead
->Flink
;
6648 while (ItemList
!= ListHead
)
6650 if (DriverInfoData
->Reserved
!= 0)
6652 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6657 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6658 struct DriverInfoElement
*driverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6659 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6660 && strcmpW(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6661 && strcmpW(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6666 ItemList
= ItemList
->Flink
;
6668 if (ItemList
== ListHead
)
6669 SetLastError(ERROR_INVALID_PARAMETER
);
6672 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
6673 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6675 TRACE("Choosing driver whose rank is 0x%lx\n",
6676 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
6678 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6683 TRACE("Returning %d\n", ret
);
6687 /***********************************************************************
6688 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6691 SetupDiGetDriverInfoDetailA(
6692 IN HDEVINFO DeviceInfoSet
,
6693 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6694 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6695 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6696 IN DWORD DriverInfoDetailDataSize
,
6697 OUT PDWORD RequiredSize OPTIONAL
)
6699 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6700 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6702 DWORD HardwareIDLen
= 0;
6705 /* do some sanity checks, the unicode version might do more thorough checks */
6706 if (DriverInfoData
== NULL
||
6707 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6708 (DriverInfoDetailData
!= NULL
&&
6709 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6710 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6712 SetLastError(ERROR_INVALID_PARAMETER
);
6716 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6717 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6719 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6721 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6723 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6727 SetLastError(ERROR_INVALID_PARAMETER
);
6730 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6731 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6733 /* convert the strings to unicode */
6734 if (MultiByteToWideChar(CP_ACP
,
6736 DriverInfoData
->Description
,
6738 DriverInfoDataW
.Description
,
6740 MultiByteToWideChar(CP_ACP
,
6742 DriverInfoData
->MfgName
,
6744 DriverInfoDataW
.MfgName
,
6746 MultiByteToWideChar(CP_ACP
,
6748 DriverInfoData
->ProviderName
,
6750 DriverInfoDataW
.ProviderName
,
6753 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6755 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6756 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6759 if (DriverInfoDetailData
!= NULL
)
6761 /* calculate the unicode buffer size from the ansi buffer size */
6762 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6763 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6764 (HardwareIDLen
* sizeof(WCHAR
));
6766 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6767 if (DriverInfoDetailDataW
== NULL
)
6769 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6773 /* initialize the buffer */
6774 ZeroMemory(DriverInfoDetailDataW
,
6776 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6779 /* call the unicode version */
6780 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6783 DriverInfoDetailDataW
,
6789 if (DriverInfoDetailDataW
!= NULL
)
6791 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6792 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6793 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6794 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6795 if (WideCharToMultiByte(CP_ACP
,
6797 DriverInfoDetailDataW
->SectionName
,
6799 DriverInfoDetailData
->SectionName
,
6803 WideCharToMultiByte(CP_ACP
,
6805 DriverInfoDetailDataW
->InfFileName
,
6807 DriverInfoDetailData
->InfFileName
,
6811 WideCharToMultiByte(CP_ACP
,
6813 DriverInfoDetailDataW
->DrvDescription
,
6815 DriverInfoDetailData
->DrvDescription
,
6819 WideCharToMultiByte(CP_ACP
,
6821 DriverInfoDetailDataW
->HardwareID
,
6823 DriverInfoDetailData
->HardwareID
,
6829 DWORD hwidlen
= HardwareIDLen
;
6830 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6832 /* count the strings in the list */
6835 len
= lstrlenA(s
) + 1;
6844 /* looks like the string list wasn't terminated... */
6845 SetLastError(ERROR_INVALID_USER_BUFFER
);
6851 /* make sure CompatIDsOffset points to the second string in the
6855 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6856 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6857 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6861 DriverInfoDetailData
->CompatIDsOffset
= 0;
6862 DriverInfoDetailData
->CompatIDsLength
= 0;
6871 if (RequiredSize
!= NULL
)
6873 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6874 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6880 if (DriverInfoDetailDataW
!= NULL
)
6882 MyFree(DriverInfoDetailDataW
);
6888 /***********************************************************************
6889 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6892 SetupDiGetDriverInfoDetailW(
6893 IN HDEVINFO DeviceInfoSet
,
6894 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6895 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6896 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6897 IN DWORD DriverInfoDetailDataSize
,
6898 OUT PDWORD RequiredSize OPTIONAL
)
6902 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6903 DriverInfoData
, DriverInfoDetailData
,
6904 DriverInfoDetailDataSize
, RequiredSize
);
6907 SetLastError(ERROR_INVALID_PARAMETER
);
6908 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6909 SetLastError(ERROR_INVALID_HANDLE
);
6910 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6911 SetLastError(ERROR_INVALID_HANDLE
);
6912 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6913 SetLastError(ERROR_INVALID_USER_BUFFER
);
6914 else if (!DriverInfoData
)
6915 SetLastError(ERROR_INVALID_PARAMETER
);
6916 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6917 SetLastError(ERROR_INVALID_PARAMETER
);
6918 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6919 SetLastError(ERROR_INVALID_PARAMETER
);
6920 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6921 SetLastError(ERROR_INVALID_USER_BUFFER
);
6922 else if (DriverInfoData
->Reserved
== 0)
6923 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6926 struct DriverInfoElement
*driverInfoElement
;
6927 LPWSTR HardwareIDs
= NULL
;
6928 LPWSTR CompatibleIDs
= NULL
;
6929 LPWSTR pBuffer
= NULL
;
6930 LPCWSTR DeviceID
= NULL
;
6931 ULONG HardwareIDsSize
, CompatibleIDsSize
;
6932 ULONG sizeNeeded
, sizeLeft
, size
;
6935 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6937 /* Get hardware and compatible IDs lists */
6938 Result
= GetHardwareAndCompatibleIDsLists(
6941 &HardwareIDs
, &HardwareIDsSize
,
6942 &CompatibleIDs
, &CompatibleIDsSize
);
6946 sizeNeeded
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)
6947 + HardwareIDsSize
+ CompatibleIDsSize
;
6949 *RequiredSize
= sizeNeeded
;
6951 if (!DriverInfoDetailData
)
6958 DriverInfoDetailData
,
6959 &driverInfoElement
->Details
,
6960 driverInfoElement
->Details
.cbSize
);
6961 DriverInfoDetailData
->CompatIDsOffset
= 0;
6962 DriverInfoDetailData
->CompatIDsLength
= 0;
6964 sizeLeft
= (DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
);
6965 pBuffer
= DriverInfoDetailData
->HardwareID
;
6966 /* Add as many as possible HardwareIDs in the list */
6967 DeviceID
= HardwareIDs
;
6968 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
6970 TRACE("Adding %S to list\n", DeviceID
);
6971 wcscpy(pBuffer
, DeviceID
);
6972 DeviceID
+= size
+ 1;
6973 pBuffer
+= size
+ 1;
6974 sizeLeft
-= size
+ 1;
6975 DriverInfoDetailData
->CompatIDsOffset
+= size
+ 1;
6979 *pBuffer
= UNICODE_NULL
;
6981 DriverInfoDetailData
->CompatIDsOffset
++;
6983 /* Add as many as possible CompatibleIDs in the list */
6984 DeviceID
= CompatibleIDs
;
6985 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
6987 TRACE("Adding %S to list\n", DeviceID
);
6988 wcscpy(pBuffer
, DeviceID
);
6989 DeviceID
+= size
+ 1;
6990 pBuffer
+= size
+ 1;
6991 sizeLeft
-= size
+ 1;
6992 DriverInfoDetailData
->CompatIDsLength
+= size
+ 1;
6996 *pBuffer
= UNICODE_NULL
;
6998 DriverInfoDetailData
->CompatIDsLength
++;
7001 if (sizeNeeded
> DriverInfoDetailDataSize
)
7002 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
7007 MyFree(HardwareIDs
);
7008 MyFree(CompatibleIDs
);
7011 TRACE("Returning %d\n", ret
);
7015 /* Return the current hardware profile id, or -1 if error */
7017 GetCurrentHwProfile(
7018 IN HDEVINFO DeviceInfoSet
)
7020 HKEY hKey
= INVALID_HANDLE_VALUE
;
7021 DWORD dwRegType
, dwLength
;
7024 DWORD ret
= (DWORD
)-1;
7027 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
7028 REGSTR_PATH_IDCONFIGDB
,
7032 if (rc
!= ERROR_SUCCESS
)
7038 dwLength
= sizeof(DWORD
);
7039 rc
= RegQueryValueExW(
7041 REGSTR_VAL_CURRENTCONFIG
,
7044 (LPBYTE
)&hwProfile
, &dwLength
);
7045 if (rc
!= ERROR_SUCCESS
)
7050 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
7052 SetLastError(ERROR_GEN_FAILURE
);
7059 if (hKey
!= INVALID_HANDLE_VALUE
)
7067 IN HDEVINFO DeviceInfoSet
,
7068 IN PSP_DEVINFO_DATA DeviceInfoData
)
7071 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
7072 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
7075 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
7077 /* At the moment, I only know how to start local devices */
7078 SetLastError(ERROR_INVALID_COMPUTERNAME
);
7082 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
7083 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
7084 SetLastError(RtlNtStatusToDosError(Status
));
7085 return NT_SUCCESS(Status
);
7087 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
7092 static BOOL
StopDevice(
7093 IN HDEVINFO DeviceInfoSet
,
7094 IN PSP_DEVINFO_DATA DeviceInfoData
)
7096 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
7100 /***********************************************************************
7101 * SetupDiChangeState (SETUPAPI.@)
7105 IN HDEVINFO DeviceInfoSet
,
7106 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7108 PSP_PROPCHANGE_PARAMS PropChange
;
7109 HKEY hKey
= INVALID_HANDLE_VALUE
;
7110 LPCWSTR RegistryValueName
;
7111 DWORD dwConfigFlags
, dwLength
, dwRegType
;
7115 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7117 if (!DeviceInfoData
)
7118 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
7120 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
7123 SetLastError(ERROR_INVALID_PARAMETER
);
7127 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
7128 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
7130 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
7132 switch (PropChange
->StateChange
)
7137 /* Enable/disable device in registry */
7138 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
7139 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7140 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
7141 if (hKey
== INVALID_HANDLE_VALUE
)
7143 dwLength
= sizeof(DWORD
);
7144 rc
= RegQueryValueExW(
7149 (LPBYTE
)&dwConfigFlags
, &dwLength
);
7150 if (rc
== ERROR_FILE_NOT_FOUND
)
7152 else if (rc
!= ERROR_SUCCESS
)
7157 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
7159 SetLastError(ERROR_GEN_FAILURE
);
7162 if (PropChange
->StateChange
== DICS_ENABLE
)
7163 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
7165 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
7171 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
7172 if (rc
!= ERROR_SUCCESS
)
7178 /* Enable/disable device if needed */
7179 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
7180 || PropChange
->HwProfile
== 0
7181 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
7183 if (PropChange
->StateChange
== DICS_ENABLE
)
7184 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7186 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
7192 case DICS_PROPCHANGE
:
7194 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7199 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
7200 SetLastError(ERROR_NOT_SUPPORTED
);
7205 if (hKey
!= INVALID_HANDLE_VALUE
)
7208 TRACE("Returning %d\n", ret
);
7212 /***********************************************************************
7213 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
7216 SetupDiSelectBestCompatDrv(
7217 IN HDEVINFO DeviceInfoSet
,
7218 IN PSP_DEVINFO_DATA DeviceInfoData
)
7220 SP_DRVINFO_DATA_W drvInfoData
;
7223 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7225 /* Drivers are sorted by rank in the driver list, so
7226 * the first driver in the list is the best one.
7228 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
7229 ret
= SetupDiEnumDriverInfoW(
7233 0, /* Member index */
7238 ret
= SetupDiSetSelectedDriverW(
7244 TRACE("Returning %d\n", ret
);
7248 /***********************************************************************
7249 * SetupDiInstallDriverFiles (SETUPAPI.@)
7252 SetupDiInstallDriverFiles(
7253 IN HDEVINFO DeviceInfoSet
,
7254 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7258 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7261 SetLastError(ERROR_INVALID_PARAMETER
);
7262 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7263 SetLastError(ERROR_INVALID_HANDLE
);
7264 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7265 SetLastError(ERROR_INVALID_HANDLE
);
7266 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7267 SetLastError(ERROR_INVALID_USER_BUFFER
);
7268 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
7269 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7270 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
7271 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7274 SP_DEVINSTALL_PARAMS_W InstallParams
;
7275 struct DriverInfoElement
*SelectedDriver
;
7276 WCHAR SectionName
[MAX_PATH
];
7277 DWORD SectionNameLength
= 0;
7278 PVOID InstallMsgHandler
;
7279 PVOID InstallMsgHandlerContext
;
7280 PVOID Context
= NULL
;
7282 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7283 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7287 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7288 if (!SelectedDriver
)
7290 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7294 ret
= SetupDiGetActualSectionToInstallW(
7295 SelectedDriver
->InfFileDetails
->hInf
,
7296 SelectedDriver
->Details
.SectionName
,
7297 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
7301 if (InstallParams
.InstallMsgHandler
)
7303 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
7304 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
7308 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7311 InstallMsgHandler
= SetupDefaultQueueCallback
;
7312 InstallMsgHandlerContext
= Context
;
7314 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7315 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7316 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7317 InstallMsgHandler
, InstallMsgHandlerContext
,
7318 DeviceInfoSet
, DeviceInfoData
);
7322 /* Install files from .CoInstallers section */
7323 lstrcatW(SectionName
, DotCoInstallers
);
7324 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7325 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7326 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7327 InstallMsgHandler
, InstallMsgHandlerContext
,
7328 DeviceInfoSet
, DeviceInfoData
);
7332 /* Set the DI_NOFILECOPY flag to prevent another
7333 * installation during SetupDiInstallDevice */
7334 InstallParams
.Flags
|= DI_NOFILECOPY
;
7335 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7339 SetupTermDefaultQueueCallback(Context
);
7343 TRACE("Returning %d\n", ret
);
7347 /***********************************************************************
7348 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7351 SetupDiRegisterCoDeviceInstallers(
7352 IN HDEVINFO DeviceInfoSet
,
7353 IN PSP_DEVINFO_DATA DeviceInfoData
)
7355 BOOL ret
= FALSE
; /* Return value */
7357 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7360 SetLastError(ERROR_INVALID_PARAMETER
);
7361 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7362 SetLastError(ERROR_INVALID_HANDLE
);
7363 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7364 SetLastError(ERROR_INVALID_HANDLE
);
7365 else if (!DeviceInfoData
)
7366 SetLastError(ERROR_INVALID_PARAMETER
);
7367 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7368 SetLastError(ERROR_INVALID_USER_BUFFER
);
7371 SP_DEVINSTALL_PARAMS_W InstallParams
;
7372 struct DriverInfoElement
*SelectedDriver
;
7375 WCHAR SectionName
[MAX_PATH
];
7376 DWORD SectionNameLength
= 0;
7377 HKEY hKey
= INVALID_HANDLE_VALUE
;
7378 PVOID Context
= NULL
;
7380 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7381 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7385 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7386 if (SelectedDriver
== NULL
)
7388 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7392 /* Get .CoInstallers section name */
7393 Result
= SetupDiGetActualSectionToInstallW(
7394 SelectedDriver
->InfFileDetails
->hInf
,
7395 SelectedDriver
->Details
.SectionName
,
7396 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7397 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
7399 lstrcatW(SectionName
, DotCoInstallers
);
7401 /* Open/Create driver key information */
7402 #if _WIN32_WINNT >= 0x502
7403 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7405 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7407 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7408 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7409 if (hKey
== INVALID_HANDLE_VALUE
)
7412 /* Install .CoInstallers section */
7413 DoAction
= SPINST_REGISTRY
;
7414 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7416 DoAction
|= SPINST_FILES
;
7417 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7421 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7422 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7423 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7424 SetupDefaultQueueCallback
, Context
,
7425 DeviceInfoSet
, DeviceInfoData
);
7433 SetupTermDefaultQueueCallback(Context
);
7434 if (hKey
!= INVALID_HANDLE_VALUE
)
7438 TRACE("Returning %d\n", ret
);
7443 InstallOneInterface(
7444 IN LPGUID InterfaceGuid
,
7445 IN LPCWSTR ReferenceString
,
7446 IN LPCWSTR InterfaceSection
,
7447 IN UINT InterfaceFlags
)
7449 if (InterfaceFlags
!= 0)
7451 SetLastError(ERROR_INVALID_PARAMETER
);
7455 FIXME("Need to InstallOneInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid
),
7456 debugstr_w(ReferenceString
), debugstr_w(InterfaceSection
), InterfaceFlags
);
7460 /***********************************************************************
7461 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7464 SetupDiInstallDeviceInterfaces(
7465 IN HDEVINFO DeviceInfoSet
,
7466 IN PSP_DEVINFO_DATA DeviceInfoData
)
7468 struct DeviceInfoSet
*list
= NULL
;
7471 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7474 SetLastError(ERROR_INVALID_PARAMETER
);
7475 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7476 SetLastError(ERROR_INVALID_HANDLE
);
7477 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7478 SetLastError(ERROR_INVALID_HANDLE
);
7479 else if (!DeviceInfoData
)
7480 SetLastError(ERROR_INVALID_PARAMETER
);
7481 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7482 SetLastError(ERROR_INVALID_USER_BUFFER
);
7485 struct DriverInfoElement
*SelectedDriver
;
7486 SP_DEVINSTALL_PARAMS_W InstallParams
;
7487 WCHAR SectionName
[MAX_PATH
];
7488 DWORD SectionNameLength
= 0;
7489 INFCONTEXT ContextInterface
;
7490 LPWSTR InterfaceGuidString
= NULL
;
7491 LPWSTR ReferenceString
= NULL
;
7492 LPWSTR InterfaceSection
= NULL
;
7497 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7498 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7502 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7503 if (SelectedDriver
== NULL
)
7505 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7510 /* Get .Interfaces section name */
7511 Result
= SetupDiGetActualSectionToInstallW(
7512 SelectedDriver
->InfFileDetails
->hInf
,
7513 SelectedDriver
->Details
.SectionName
,
7514 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7515 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotInterfaces
) - 1)
7517 strcatW(SectionName
, DotInterfaces
);
7520 Result
= SetupFindFirstLineW(
7521 SelectedDriver
->InfFileDetails
->hInf
,
7525 while (ret
&& Result
)
7527 ret
= GetStringField(&ContextInterface
, 1, &InterfaceGuidString
);
7530 else if (strlenW(InterfaceGuidString
) != MAX_GUID_STRING_LEN
- 1)
7532 SetLastError(ERROR_INVALID_PARAMETER
);
7537 InterfaceGuidString
[MAX_GUID_STRING_LEN
- 2] = '\0'; /* Replace the } by a NULL character */
7538 if (UuidFromStringW(&InterfaceGuidString
[1], &InterfaceGuid
) != RPC_S_OK
)
7540 /* Bad GUID, skip the entry */
7541 SetLastError(ERROR_INVALID_PARAMETER
);
7546 ret
= GetStringField(&ContextInterface
, 2, &ReferenceString
);
7550 ret
= GetStringField(&ContextInterface
, 3, &InterfaceSection
);
7554 ret
= SetupGetIntField(
7556 4, /* Field index */
7560 if (GetLastError() == ERROR_INVALID_PARAMETER
)
7562 /* The field may be empty. Ignore the error */
7570 /* Install Interface */
7571 ret
= InstallOneInterface(&InterfaceGuid
, ReferenceString
, InterfaceSection
, InterfaceFlags
);
7574 MyFree(InterfaceGuidString
);
7575 MyFree(ReferenceString
);
7576 MyFree(InterfaceSection
);
7577 InterfaceGuidString
= ReferenceString
= InterfaceSection
= NULL
;
7578 Result
= SetupFindNextMatchLineW(&ContextInterface
, AddInterface
, &ContextInterface
);
7582 TRACE("Returning %d\n", ret
);
7587 InfIsFromOEMLocation(
7589 OUT LPBOOL IsOEMLocation
)
7593 last
= strrchrW(FullName
, '\\');
7596 /* No directory specified */
7597 *IsOEMLocation
= FALSE
;
7601 WCHAR Windir
[MAX_PATH
];
7604 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
7605 if (ret
== 0 || ret
>= MAX_PATH
)
7607 SetLastError(ERROR_GEN_FAILURE
);
7611 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
7613 /* The path is %WINDIR%\Inf */
7614 *IsOEMLocation
= FALSE
;
7618 /* The file is in another place */
7619 *IsOEMLocation
= TRUE
;
7625 /***********************************************************************
7626 * SetupDiInstallDevice (SETUPAPI.@)
7629 SetupDiInstallDevice(
7630 IN HDEVINFO DeviceInfoSet
,
7631 IN PSP_DEVINFO_DATA DeviceInfoData
)
7633 SP_DEVINSTALL_PARAMS_W InstallParams
;
7634 struct DriverInfoElement
*SelectedDriver
;
7635 SYSTEMTIME DriverDate
;
7636 WCHAR SectionName
[MAX_PATH
];
7638 DWORD SectionNameLength
= 0;
7639 BOOL Result
= FALSE
;
7642 LPWSTR pSectionName
= NULL
;
7643 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
7645 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
7646 BOOL RebootRequired
= FALSE
;
7647 HKEY hKey
= INVALID_HANDLE_VALUE
;
7648 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
7649 BOOL NeedtoCopyFile
;
7650 LARGE_INTEGER fullVersion
;
7652 PVOID Context
= NULL
;
7653 BOOL ret
= FALSE
; /* Return value */
7655 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7658 SetLastError(ERROR_INVALID_PARAMETER
);
7659 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7660 SetLastError(ERROR_INVALID_HANDLE
);
7661 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7662 SetLastError(ERROR_INVALID_HANDLE
);
7663 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7664 SetLastError(ERROR_INVALID_USER_BUFFER
);
7670 /* One parameter is bad */
7674 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7675 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7679 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
7681 /* Set FAILEDINSTALL in ConfigFlags registry value */
7682 DWORD ConfigFlags
, regType
;
7683 Result
= SetupDiGetDeviceRegistryPropertyW(
7688 (PBYTE
)&ConfigFlags
,
7689 sizeof(ConfigFlags
),
7691 if (!Result
|| regType
!= REG_DWORD
)
7693 SetLastError(ERROR_GEN_FAILURE
);
7696 ConfigFlags
|= DNF_DISABLED
;
7697 Result
= SetupDiSetDeviceRegistryPropertyW(
7701 (PBYTE
)&ConfigFlags
,
7702 sizeof(ConfigFlags
));
7705 SetLastError(ERROR_GEN_FAILURE
);
7713 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7714 if (SelectedDriver
== NULL
)
7716 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7720 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
7722 Result
= SetupDiGetActualSectionToInstallW(
7723 SelectedDriver
->InfFileDetails
->hInf
,
7724 SelectedDriver
->Details
.SectionName
,
7725 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7726 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
7728 pSectionName
= &SectionName
[strlenW(SectionName
)];
7730 /* Get information from [Version] section */
7731 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
7733 /* Format ClassGuid to a string */
7734 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
7736 RequiredSize
= lstrlenW(lpGuidString
);
7737 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
7738 if (!lpFullGuidString
)
7740 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7743 lpFullGuidString
[0] = '{';
7744 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
7745 lpFullGuidString
[RequiredSize
+ 1] = '}';
7746 lpFullGuidString
[RequiredSize
+ 2] = '\0';
7748 /* Open/Create driver key information */
7749 #if _WIN32_WINNT >= 0x502
7750 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7752 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7754 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7755 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7756 if (hKey
== INVALID_HANDLE_VALUE
)
7759 /* Install main section */
7761 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7762 DoAction
|= SPINST_REGISTRY
;
7763 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7765 DoAction
|= SPINST_FILES
;
7766 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7770 *pSectionName
= '\0';
7771 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7772 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7773 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7774 SetupDefaultQueueCallback
, Context
,
7775 DeviceInfoSet
, DeviceInfoData
);
7778 InstallParams
.Flags
|= DI_NOFILECOPY
;
7779 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7781 /* Write information to driver key */
7782 *pSectionName
= UNICODE_NULL
;
7783 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
7784 TRACE("Write information to driver key\n");
7785 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7786 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
7787 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7788 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->Details
.InfFileName
));
7789 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
7790 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
7791 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
7792 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
7793 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7794 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
7795 if (rc
== ERROR_SUCCESS
)
7796 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7797 if (rc
== ERROR_SUCCESS
)
7798 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7799 if (rc
== ERROR_SUCCESS
)
7801 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7802 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
7804 if (rc
== ERROR_SUCCESS
)
7805 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (strlenW(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7806 if (rc
== ERROR_SUCCESS
)
7807 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7808 if (rc
== ERROR_SUCCESS
)
7809 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTIONEXT
, 0, REG_SZ
, (const BYTE
*)&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)], (strlenW(SectionName
) - strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7810 if (rc
== ERROR_SUCCESS
)
7811 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7812 if (rc
== ERROR_SUCCESS
)
7813 rc
= RegSetValueEx(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7814 if (rc
!= ERROR_SUCCESS
)
7820 hKey
= INVALID_HANDLE_VALUE
;
7822 /* FIXME: Process .LogConfigOverride section */
7824 /* Install .Services section */
7825 strcpyW(pSectionName
, DotServices
);
7826 Result
= SetupInstallServicesFromInfSectionExW(
7827 SelectedDriver
->InfFileDetails
->hInf
,
7836 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
7837 RebootRequired
= TRUE
;
7839 /* Copy .inf file to Inf\ directory (if needed) */
7840 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7845 Result
= SetupCopyOEMInfW(
7846 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7849 SP_COPY_NOOVERWRITE
,
7855 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7856 * to release use of current InfFile */
7859 /* Open device registry key */
7860 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7861 if (hKey
== INVALID_HANDLE_VALUE
)
7864 /* Install .HW section */
7866 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7867 DoAction
|= SPINST_REGISTRY
;
7868 strcpyW(pSectionName
, DotHW
);
7869 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7870 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7871 DoAction
, hKey
, NULL
, 0,
7873 DeviceInfoSet
, DeviceInfoData
);
7877 /* Write information to enum key */
7878 TRACE("Write information to enum key\n");
7879 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
7880 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
7881 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
7882 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
7883 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
7884 if (rc
== ERROR_SUCCESS
)
7885 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7886 if (rc
== ERROR_SUCCESS
)
7887 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7888 if (rc
== ERROR_SUCCESS
)
7889 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7890 if (rc
!= ERROR_SUCCESS
)
7896 /* Start the device */
7897 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7898 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7903 /* End of installation */
7904 if (hClassKey
!= INVALID_HANDLE_VALUE
)
7905 RegCloseKey(hClassKey
);
7906 if (hKey
!= INVALID_HANDLE_VALUE
)
7909 RpcStringFreeW(&lpGuidString
);
7910 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7912 SetupTermDefaultQueueCallback(Context
);
7913 TRACE("Returning %d\n", ret
);