2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005 Hervé Poussineau (hpoussin@reactos.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "setupapi_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
27 /* Unicode constants */
28 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class
[] = {'C','l','a','s','s',0};
30 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
31 static const WCHAR Control
[] = {'C','o','n','t','r','o','l',0};
32 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
33 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
34 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
35 static const WCHAR InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
36 static const WCHAR Linked
[] = {'L','i','n','k','e','d',0};
37 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
38 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
40 /* FIXME: header mess */
41 DEFINE_GUID(GUID_NULL
,
42 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
44 (CALLBACK
* CLASS_INSTALL_PROC
) (
45 IN DI_FUNCTION InstallFunction
,
46 IN HDEVINFO DeviceInfoSet
,
47 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
49 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
50 IN HDEVINFO DeviceInfoSet
,
51 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
53 (CALLBACK
* COINSTALLER_PROC
) (
54 IN DI_FUNCTION InstallFunction
,
55 IN HDEVINFO DeviceInfoSet
,
56 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
57 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
59 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
60 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
61 IN LPFNADDPROPSHEETPAGE fAddFunc
,
64 (*UPDATE_CLASS_PARAM_HANDLER
) (
65 IN HDEVINFO DeviceInfoSet
,
66 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
67 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
68 IN DWORD ClassInstallParamsSize
);
70 struct CoInstallerElement
75 COINSTALLER_PROC Function
;
76 BOOL DoPostProcessing
;
81 PropertyChangeHandler(
82 IN HDEVINFO DeviceInfoSet
,
83 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
84 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
85 IN DWORD ClassInstallParamsSize
);
87 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
88 NULL
, /* DIF_SELECTDEVICE */
89 NULL
, /* DIF_INSTALLDEVICE */
90 NULL
, /* DIF_ASSIGNRESOURCES */
91 NULL
, /* DIF_PROPERTIES */
92 NULL
, /* DIF_REMOVE */
93 NULL
, /* DIF_FIRSTTIMESETUP */
94 NULL
, /* DIF_FOUNDDEVICE */
95 NULL
, /* DIF_SELECTCLASSDRIVERS */
96 NULL
, /* DIF_VALIDATECLASSDRIVERS */
97 NULL
, /* DIF_INSTALLCLASSDRIVERS */
98 NULL
, /* DIF_CALCDISKSPACE */
99 NULL
, /* DIF_DESTROYPRIVATEDATA */
100 NULL
, /* DIF_VALIDATEDRIVER */
101 NULL
, /* DIF_MOVEDEVICE */
102 NULL
, /* DIF_DETECT */
103 NULL
, /* DIF_INSTALLWIZARD */
104 NULL
, /* DIF_DESTROYWIZARDDATA */
105 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
106 NULL
, /* DIF_ENABLECLASS */
107 NULL
, /* DIF_DETECTVERIFY */
108 NULL
, /* DIF_INSTALLDEVICEFILES */
109 NULL
, /* DIF_UNREMOVE */
110 NULL
, /* DIF_SELECTBESTCOMPATDRV */
111 NULL
, /* DIF_ALLOW_INSTALL */
112 NULL
, /* DIF_REGISTERDEVICE */
113 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
114 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
115 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
116 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
117 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
118 NULL
, /* DIF_UNUSED1 */
119 NULL
, /* DIF_INSTALLINTERFACES */
120 NULL
, /* DIF_DETECTCANCEL */
121 NULL
, /* DIF_REGISTER_COINSTALLERS */
122 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
123 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
124 NULL
, /* DIF_RESERVED1 */
125 NULL
, /* DIF_TROUBLESHOOTER */
126 NULL
, /* DIF_POWERMESSAGEWAKE */
127 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
128 NULL
, /* DIF_UPDATEDRIVER_UI */
129 NULL
/* DIF_RESERVED2 */
132 /***********************************************************************
133 * SetupDiBuildClassInfoList (SETUPAPI.@)
135 BOOL WINAPI
SetupDiBuildClassInfoList(
137 LPGUID ClassGuidList
,
138 DWORD ClassGuidListSize
,
142 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
143 ClassGuidListSize
, RequiredSize
,
147 /***********************************************************************
148 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
150 BOOL WINAPI
SetupDiBuildClassInfoListExA(
152 LPGUID ClassGuidList
,
153 DWORD ClassGuidListSize
,
158 LPWSTR MachineNameW
= NULL
;
165 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
166 if (MachineNameW
== NULL
) return FALSE
;
169 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
170 ClassGuidListSize
, RequiredSize
,
171 MachineNameW
, Reserved
);
174 MyFree(MachineNameW
);
179 /***********************************************************************
180 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
182 BOOL WINAPI
SetupDiBuildClassInfoListExW(
184 LPGUID ClassGuidList
,
185 DWORD ClassGuidListSize
,
190 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
196 DWORD dwGuidListIndex
= 0;
198 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
199 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
201 if (RequiredSize
!= NULL
)
204 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
205 KEY_ENUMERATE_SUB_KEYS
,
209 if (hClassesKey
== INVALID_HANDLE_VALUE
)
214 for (dwIndex
= 0; ; dwIndex
++)
216 dwLength
= MAX_GUID_STRING_LEN
+ 1;
217 lError
= RegEnumKeyExW(hClassesKey
,
225 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
226 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
228 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
230 if (RegOpenKeyExW(hClassesKey
,
236 RegCloseKey(hClassesKey
);
240 if (!RegQueryValueExW(hClassKey
,
241 REGSTR_VAL_NOUSECLASS
,
247 TRACE("'NoUseClass' value found!\n");
248 RegCloseKey(hClassKey
);
252 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
253 (!RegQueryValueExW(hClassKey
,
254 REGSTR_VAL_NOINSTALLCLASS
,
260 TRACE("'NoInstallClass' value found!\n");
261 RegCloseKey(hClassKey
);
265 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
266 (!RegQueryValueExW(hClassKey
,
267 REGSTR_VAL_NODISPLAYCLASS
,
273 TRACE("'NoDisplayClass' value found!\n");
274 RegCloseKey(hClassKey
);
278 RegCloseKey(hClassKey
);
280 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
281 if (dwGuidListIndex
< ClassGuidListSize
)
283 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
287 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
289 UuidFromStringW(&szKeyName
[1],
290 &ClassGuidList
[dwGuidListIndex
]);
296 if (lError
!= ERROR_SUCCESS
)
300 RegCloseKey(hClassesKey
);
302 if (RequiredSize
!= NULL
)
303 *RequiredSize
= dwGuidListIndex
;
305 if (ClassGuidListSize
< dwGuidListIndex
)
307 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
314 /***********************************************************************
315 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
317 BOOL WINAPI
SetupDiClassGuidsFromNameA(
319 LPGUID ClassGuidList
,
320 DWORD ClassGuidListSize
,
323 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
324 ClassGuidListSize
, RequiredSize
,
328 /***********************************************************************
329 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
331 BOOL WINAPI
SetupDiClassGuidsFromNameW(
333 LPGUID ClassGuidList
,
334 DWORD ClassGuidListSize
,
337 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
338 ClassGuidListSize
, RequiredSize
,
342 /***********************************************************************
343 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
345 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
347 LPGUID ClassGuidList
,
348 DWORD ClassGuidListSize
,
353 LPWSTR ClassNameW
= NULL
;
354 LPWSTR MachineNameW
= NULL
;
359 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
360 if (ClassNameW
== NULL
)
365 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
366 if (MachineNameW
== NULL
)
373 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
374 ClassGuidListSize
, RequiredSize
,
375 MachineNameW
, Reserved
);
378 MyFree(MachineNameW
);
385 /***********************************************************************
386 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
388 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
390 LPGUID ClassGuidList
,
391 DWORD ClassGuidListSize
,
396 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
397 WCHAR szClassName
[256];
403 DWORD dwGuidListIndex
= 0;
405 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
406 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
408 if (RequiredSize
!= NULL
)
411 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
412 KEY_ENUMERATE_SUB_KEYS
,
416 if (hClassesKey
== INVALID_HANDLE_VALUE
)
421 for (dwIndex
= 0; ; dwIndex
++)
423 dwLength
= MAX_GUID_STRING_LEN
+ 1;
424 lError
= RegEnumKeyExW(hClassesKey
,
432 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
433 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
435 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
437 if (RegOpenKeyExW(hClassesKey
,
443 RegCloseKey(hClassesKey
);
447 dwLength
= 256 * sizeof(WCHAR
);
448 if (!RegQueryValueExW(hClassKey
,
455 TRACE("Class name: %s\n", debugstr_w(szClassName
));
457 if (strcmpiW(szClassName
, ClassName
) == 0)
459 TRACE("Found matching class name\n");
461 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
462 if (dwGuidListIndex
< ClassGuidListSize
)
464 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
468 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
470 UuidFromStringW(&szKeyName
[1],
471 &ClassGuidList
[dwGuidListIndex
]);
478 RegCloseKey(hClassKey
);
481 if (lError
!= ERROR_SUCCESS
)
485 RegCloseKey(hClassesKey
);
487 if (RequiredSize
!= NULL
)
488 *RequiredSize
= dwGuidListIndex
;
490 if (ClassGuidListSize
< dwGuidListIndex
)
492 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
499 /***********************************************************************
500 * SetupDiClassNameFromGuidA (SETUPAPI.@)
502 BOOL WINAPI
SetupDiClassNameFromGuidA(
503 const GUID
* ClassGuid
,
508 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
509 ClassNameSize
, RequiredSize
,
513 /***********************************************************************
514 * SetupDiClassNameFromGuidW (SETUPAPI.@)
516 BOOL WINAPI
SetupDiClassNameFromGuidW(
517 const GUID
* ClassGuid
,
522 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
523 ClassNameSize
, RequiredSize
,
527 /***********************************************************************
528 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
530 BOOL WINAPI
SetupDiClassNameFromGuidExA(
531 const GUID
* ClassGuid
,
538 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
539 LPWSTR MachineNameW
= NULL
;
543 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
544 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
545 NULL
, MachineNameW
, Reserved
);
548 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
549 ClassNameSize
, NULL
, NULL
);
551 if (!ClassNameSize
&& RequiredSize
)
554 MyFree(MachineNameW
);
558 /***********************************************************************
559 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
561 BOOL WINAPI
SetupDiClassNameFromGuidExW(
562 const GUID
* ClassGuid
,
573 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
574 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
576 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
581 if (hKey
== INVALID_HANDLE_VALUE
)
586 if (RequiredSize
!= NULL
)
589 rc
= RegQueryValueExW(hKey
,
595 if (rc
!= ERROR_SUCCESS
)
602 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
605 dwLength
= ClassNameSize
* sizeof(WCHAR
);
606 rc
= RegQueryValueExW(hKey
,
612 if (rc
!= ERROR_SUCCESS
)
624 /***********************************************************************
625 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
628 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
631 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
634 /***********************************************************************
635 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
638 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
643 LPWSTR MachineNameW
= NULL
;
646 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
647 debugstr_a(MachineName
), Reserved
);
651 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
652 if (MachineNameW
== NULL
)
653 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
656 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
657 MachineNameW
, Reserved
);
660 MyFree(MachineNameW
);
666 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
670 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
671 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
672 case CR_SUCCESS
: return ERROR_SUCCESS
;
675 return ERROR_GEN_FAILURE
;
678 /* Does not happen */
681 /***********************************************************************
682 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
685 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
690 struct DeviceInfoSet
*list
;
691 LPWSTR UNCServerName
= NULL
;
695 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
697 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
698 debugstr_w(MachineName
), Reserved
);
700 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
702 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
703 list
= HeapAlloc(GetProcessHeap(), 0, size
);
706 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
709 memset(list
, 0, sizeof(struct DeviceInfoSet
));
711 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
714 ClassGuid
? ClassGuid
: &GUID_NULL
,
715 sizeof(list
->ClassGuid
));
716 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
717 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
718 list
->InstallParams
.hwndParent
= hwndParent
;
721 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
722 if (rc
!= ERROR_SUCCESS
)
727 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
730 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
734 strcpyW(UNCServerName
+ 2, MachineName
);
735 list
->szData
[0] = list
->szData
[1] = '\\';
736 strcpyW(list
->szData
+ 2, MachineName
);
737 list
->MachineName
= list
->szData
;
741 DWORD Size
= MAX_PATH
;
742 list
->HKLM
= HKEY_LOCAL_MACHINE
;
743 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
746 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
749 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
751 list
->MachineName
= NULL
;
754 UNCServerName
[0] = UNCServerName
[1] = '\\';
755 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
756 if (cr
!= CR_SUCCESS
)
758 SetLastError(GetErrorCodeFromCrCode(cr
));
762 InitializeListHead(&list
->DriverListHead
);
763 InitializeListHead(&list
->ListHead
);
765 ret
= (HDEVINFO
)list
;
768 if (ret
== INVALID_HANDLE_VALUE
)
770 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
771 RegCloseKey(list
->HKLM
);
772 HeapFree(GetProcessHeap(), 0, list
);
774 HeapFree(GetProcessHeap(), 0, UNCServerName
);
778 /***********************************************************************
779 * SetupDiEnumDeviceInfo (SETUPAPI.@)
781 BOOL WINAPI
SetupDiEnumDeviceInfo(
782 HDEVINFO DeviceInfoSet
,
784 PSP_DEVINFO_DATA DeviceInfoData
)
788 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
790 SetLastError(ERROR_INVALID_PARAMETER
);
791 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
793 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
795 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
796 SetLastError(ERROR_INVALID_HANDLE
);
797 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
798 SetLastError(ERROR_INVALID_USER_BUFFER
);
801 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
802 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
803 ItemList
= ItemList
->Flink
;
804 if (ItemList
== &list
->ListHead
)
805 SetLastError(ERROR_NO_MORE_ITEMS
);
808 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
809 memcpy(&DeviceInfoData
->ClassGuid
,
812 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
813 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
819 SetLastError(ERROR_INVALID_HANDLE
);
823 /***********************************************************************
824 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
827 SetupDiGetActualSectionToInstallA(
829 IN PCSTR InfSectionName
,
830 OUT PSTR InfSectionWithExt OPTIONAL
,
831 IN DWORD InfSectionWithExtSize
,
832 OUT PDWORD RequiredSize OPTIONAL
,
833 OUT PSTR
*Extension OPTIONAL
)
835 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
836 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
840 /***********************************************************************
841 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
844 SetupDiGetActualSectionToInstallW(
846 IN PCWSTR InfSectionName
,
847 OUT PWSTR InfSectionWithExt OPTIONAL
,
848 IN DWORD InfSectionWithExtSize
,
849 OUT PDWORD RequiredSize OPTIONAL
,
850 OUT PWSTR
*Extension OPTIONAL
)
852 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
853 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
857 /***********************************************************************
858 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
861 SetupDiGetActualSectionToInstallExA(
863 IN PCSTR InfSectionName
,
864 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
865 OUT PSTR InfSectionWithExt OPTIONAL
,
866 IN DWORD InfSectionWithExtSize
,
867 OUT PDWORD RequiredSize OPTIONAL
,
868 OUT PSTR
* Extension OPTIONAL
,
871 LPWSTR InfSectionNameW
= NULL
;
872 LPWSTR InfSectionWithExtW
= NULL
;
874 BOOL bResult
= FALSE
;
880 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
881 if (InfSectionNameW
== NULL
)
884 if (InfSectionWithExt
)
886 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
887 if (InfSectionWithExtW
== NULL
)
891 bResult
= SetupDiGetActualSectionToInstallExW(
892 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
893 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
894 InfSectionWithExtSize
,
896 Extension
? &ExtensionW
: NULL
,
899 if (bResult
&& InfSectionWithExt
)
901 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
902 InfSectionWithExtSize
, NULL
, NULL
) != 0;
904 if (bResult
&& Extension
)
906 if (ExtensionW
== NULL
)
909 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
913 MyFree(InfSectionNameW
);
914 MyFree(InfSectionWithExtW
);
919 /***********************************************************************
920 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
923 SetupDiGetActualSectionToInstallExW(
925 IN PCWSTR InfSectionName
,
926 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
927 OUT PWSTR InfSectionWithExt OPTIONAL
,
928 IN DWORD InfSectionWithExtSize
,
929 OUT PDWORD RequiredSize OPTIONAL
,
930 OUT PWSTR
* Extension OPTIONAL
,
935 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
936 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
937 RequiredSize
, Extension
, Reserved
);
939 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
940 SetLastError(ERROR_INVALID_HANDLE
);
941 else if (!InfSectionName
)
942 SetLastError(ERROR_INVALID_PARAMETER
);
943 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
944 SetLastError(ERROR_INVALID_USER_BUFFER
);
945 else if (Reserved
!= NULL
)
946 SetLastError(ERROR_INVALID_PARAMETER
);
949 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
950 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
951 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
952 WCHAR SectionName
[LINE_LEN
+ 1];
953 LONG lLineCount
= -1;
956 /* Fill platform info if needed */
957 if (AlternatePlatformInfo
)
958 pPlatformInfo
= AlternatePlatformInfo
;
959 else if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
961 /* That's the first time we go here. We need to fill in the structure */
962 OSVERSIONINFO VersionInfo
;
963 SYSTEM_INFO SystemInfo
;
964 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
965 ret
= GetVersionEx(&VersionInfo
);
968 GetSystemInfo(&SystemInfo
);
969 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
970 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
971 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
972 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
973 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
974 CurrentPlatform
.Reserved
= 0;
977 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
978 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
979 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
981 static const WCHAR ExtensionArchitectureNone
[] = {0};
982 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
983 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
984 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
986 /* Set various extensions values */
987 switch (pPlatformInfo
->Platform
)
989 case VER_PLATFORM_WIN32_WINDOWS
:
990 pExtensionPlatform
= ExtensionPlatformWindows
;
992 case VER_PLATFORM_WIN32_NT
:
993 pExtensionPlatform
= ExtensionPlatformNT
;
996 pExtensionPlatform
= ExtensionPlatformNone
;
999 switch (pPlatformInfo
->ProcessorArchitecture
)
1001 case PROCESSOR_ARCHITECTURE_AMD64
:
1002 pExtensionArchitecture
= ExtensionArchitectureamd64
;
1004 case PROCESSOR_ARCHITECTURE_INTEL
:
1005 pExtensionArchitecture
= ExtensionArchitecturex86
;
1007 case PROCESSOR_ARCHITECTURE_PPC
:
1008 pExtensionArchitecture
= ExtensionArchitectureppc
;
1011 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo
->ProcessorArchitecture
);
1012 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
1013 pExtensionArchitecture
= ExtensionArchitectureNone
;
1017 SectionName
[LINE_LEN
] = UNICODE_NULL
;
1019 /* Test with platform.architecture.major.minor extension */
1020 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s.%lu.%lu", InfSectionName
,
1021 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1022 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1023 if (lLineCount
!= -1) goto sectionfound
;
1025 /* Test with platform.major.minor extension */
1026 snprintfW(SectionName
, LINE_LEN
, L
"%s%s.%lu.%lu", InfSectionName
,
1027 pExtensionPlatform
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1028 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1029 if (lLineCount
!= -1) goto sectionfound
;
1031 /* Test with platform.architecture.major extension */
1032 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s.%lu", InfSectionName
,
1033 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
);
1034 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1035 if (lLineCount
!= -1) goto sectionfound
;
1037 /* Test with platform.major extension */
1038 snprintfW(SectionName
, LINE_LEN
, L
"%s%s.%lu", InfSectionName
,
1039 pExtensionPlatform
, pPlatformInfo
->MajorVersion
);
1040 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1041 if (lLineCount
!= -1) goto sectionfound
;
1043 /* Test with platform.architecture extension */
1044 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s", InfSectionName
,
1045 pExtensionPlatform
, pExtensionArchitecture
);
1046 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1047 if (lLineCount
!= -1) goto sectionfound
;
1049 /* Test with platform extension */
1050 snprintfW(SectionName
, LINE_LEN
, L
"%s%s", InfSectionName
,
1051 pExtensionPlatform
);
1052 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1053 if (lLineCount
!= -1) goto sectionfound
;
1055 /* Test without extension */
1056 snprintfW(SectionName
, LINE_LEN
, L
"%s", InfSectionName
);
1057 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1058 if (lLineCount
!= -1) goto sectionfound
;
1060 /* No appropriate section found */
1061 SetLastError(ERROR_INVALID_PARAMETER
);
1065 dwFullLength
= lstrlenW(SectionName
);
1066 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
1068 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
1070 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1074 lstrcpyW(InfSectionWithExt
, SectionName
);
1075 if (Extension
!= NULL
)
1077 DWORD dwLength
= lstrlenW(SectionName
);
1078 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1082 if (RequiredSize
!= NULL
)
1083 *RequiredSize
= dwFullLength
+ 1;
1089 TRACE("Returning %d\n", ret
);
1094 /***********************************************************************
1095 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1097 BOOL WINAPI
SetupDiGetClassDescriptionA(
1098 const GUID
* ClassGuid
,
1099 PSTR ClassDescription
,
1100 DWORD ClassDescriptionSize
,
1101 PDWORD RequiredSize
)
1103 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1104 ClassDescriptionSize
,
1105 RequiredSize
, NULL
, NULL
);
1108 /***********************************************************************
1109 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1111 BOOL WINAPI
SetupDiGetClassDescriptionW(
1112 const GUID
* ClassGuid
,
1113 PWSTR ClassDescription
,
1114 DWORD ClassDescriptionSize
,
1115 PDWORD RequiredSize
)
1117 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1118 ClassDescriptionSize
,
1119 RequiredSize
, NULL
, NULL
);
1122 /***********************************************************************
1123 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1125 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1126 const GUID
* ClassGuid
,
1127 PSTR ClassDescription
,
1128 DWORD ClassDescriptionSize
,
1129 PDWORD RequiredSize
,
1133 PWCHAR ClassDescriptionW
;
1134 LPWSTR MachineNameW
= NULL
;
1138 if (ClassDescriptionSize
> 0)
1140 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1141 if (!ClassDescriptionW
)
1143 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1149 ClassDescriptionW
= NULL
;
1153 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1156 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1162 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1163 NULL
, MachineNameW
, Reserved
);
1166 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1167 ClassDescriptionSize
, NULL
, NULL
);
1169 if (!ClassDescriptionSize
&& RequiredSize
)
1170 *RequiredSize
= len
;
1174 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1175 MyFree(MachineNameW
);
1179 /***********************************************************************
1180 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1182 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1183 const GUID
* ClassGuid
,
1184 PWSTR ClassDescription
,
1185 DWORD ClassDescriptionSize
,
1186 PDWORD RequiredSize
,
1193 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1194 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1196 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1201 if (hKey
== INVALID_HANDLE_VALUE
)
1203 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1207 if (RequiredSize
!= NULL
)
1210 if (RegQueryValueExW(hKey
,
1221 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1224 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1225 if (RegQueryValueExW(hKey
,
1229 (LPBYTE
)ClassDescription
,
1241 /***********************************************************************
1242 * SetupDiGetClassDevsA (SETUPAPI.@)
1244 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1250 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1251 flags
, NULL
, NULL
, NULL
);
1254 /***********************************************************************
1255 * SetupDiGetClassDevsW (SETUPAPI.@)
1257 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1263 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1264 flags
, NULL
, NULL
, NULL
);
1267 /***********************************************************************
1268 * SetupDiGetClassDevsExA (SETUPAPI.@)
1270 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1280 LPWSTR enumstrW
= NULL
;
1281 LPWSTR machineW
= NULL
;
1285 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1286 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1289 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1292 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1296 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1297 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1300 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1303 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1305 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1308 HeapFree(GetProcessHeap(), 0, enumstrW
);
1309 HeapFree(GetProcessHeap(), 0, machineW
);
1314 CreateDeviceInfoElement(
1315 IN
struct DeviceInfoSet
*list
,
1316 IN LPCWSTR InstancePath
,
1317 IN LPCGUID pClassGuid
,
1318 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1322 struct DeviceInfoElement
*deviceInfo
;
1324 *pDeviceInfo
= NULL
;
1326 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1327 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1330 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1333 memset(deviceInfo
, 0, size
);
1335 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1336 if (cr
!= CR_SUCCESS
)
1338 SetLastError(GetErrorCodeFromCrCode(cr
));
1342 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1343 wcscpy(deviceInfo
->Data
, InstancePath
);
1344 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1345 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1346 deviceInfo
->DeviceDescription
= NULL
;
1347 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1348 deviceInfo
->CreationFlags
= 0;
1349 InitializeListHead(&deviceInfo
->DriverListHead
);
1350 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1352 *pDeviceInfo
= deviceInfo
;
1357 CreateDeviceInterface(
1358 IN
struct DeviceInfoElement
* deviceInfo
,
1359 IN LPCWSTR SymbolicLink
,
1360 IN LPCGUID pInterfaceGuid
,
1361 OUT
struct DeviceInterface
**pDeviceInterface
)
1363 struct DeviceInterface
*deviceInterface
;
1365 *pDeviceInterface
= NULL
;
1367 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1368 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1369 if (!deviceInterface
)
1371 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1374 deviceInterface
->DeviceInfo
= deviceInfo
;
1375 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1376 deviceInterface
->Flags
= 0; /* FIXME */
1377 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1379 *pDeviceInterface
= deviceInterface
;
1383 static LONG
SETUP_CreateDevListFromEnumerator(
1384 struct DeviceInfoSet
*list
,
1385 LPCGUID pClassGuid OPTIONAL
,
1387 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1389 HKEY hDeviceIdKey
, hInstanceIdKey
;
1390 WCHAR KeyBuffer
[MAX_PATH
];
1391 WCHAR InstancePath
[MAX_PATH
];
1392 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1393 struct DeviceInfoElement
*deviceInfo
;
1395 DWORD dwLength
, dwRegType
;
1398 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1401 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1402 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1403 if (rc
== ERROR_NO_MORE_ITEMS
)
1405 if (rc
!= ERROR_SUCCESS
)
1409 /* Open device id sub key */
1410 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1411 if (rc
!= ERROR_SUCCESS
)
1413 wcscpy(InstancePath
, Enumerator
);
1414 wcscat(InstancePath
, L
"\\");
1415 wcscat(InstancePath
, KeyBuffer
);
1416 wcscat(InstancePath
, L
"\\");
1417 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1419 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1425 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1426 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1427 if (rc
== ERROR_NO_MORE_ITEMS
)
1429 if (rc
!= ERROR_SUCCESS
)
1431 RegCloseKey(hDeviceIdKey
);
1436 /* Open instance id sub key */
1437 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1438 if (rc
!= ERROR_SUCCESS
)
1440 RegCloseKey(hDeviceIdKey
);
1443 *pEndOfInstancePath
= '\0';
1444 wcscat(InstancePath
, KeyBuffer
);
1446 /* Read ClassGUID value */
1447 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1448 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1449 RegCloseKey(hInstanceIdKey
);
1450 if (rc
== ERROR_FILE_NOT_FOUND
)
1453 /* Skip this bad entry as we can't verify it */
1455 /* Set a default GUID for this device */
1456 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1458 else if (rc
!= ERROR_SUCCESS
)
1460 RegCloseKey(hDeviceIdKey
);
1463 else if (dwRegType
!= REG_SZ
)
1465 RegCloseKey(hDeviceIdKey
);
1466 return ERROR_GEN_FAILURE
;
1470 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1471 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1472 /* Bad GUID, skip the entry */
1476 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1478 /* Skip this entry as it is not the right device class */
1482 /* Add the entry to the list */
1483 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1485 RegCloseKey(hDeviceIdKey
);
1486 return GetLastError();
1488 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1489 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1491 RegCloseKey(hDeviceIdKey
);
1494 return ERROR_SUCCESS
;
1497 static LONG
SETUP_CreateDevList(
1498 struct DeviceInfoSet
*list
,
1499 PCWSTR MachineName OPTIONAL
,
1500 LPGUID
class OPTIONAL
,
1501 PCWSTR Enumerator OPTIONAL
)
1503 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1504 WCHAR KeyBuffer
[MAX_PATH
];
1509 if (class && IsEqualIID(class, &GUID_NULL
))
1513 if (MachineName
!= NULL
)
1515 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1516 if (rc
!= ERROR_SUCCESS
)
1520 HKLM
= HKEY_LOCAL_MACHINE
;
1522 rc
= RegOpenKeyExW(HKLM
,
1523 REGSTR_PATH_SYSTEMENUM
,
1525 KEY_ENUMERATE_SUB_KEYS
,
1527 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1528 if (rc
!= ERROR_SUCCESS
)
1531 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1532 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1541 KEY_ENUMERATE_SUB_KEYS
,
1543 RegCloseKey(hEnumKey
);
1544 if (rc
!= ERROR_SUCCESS
)
1546 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1547 RegCloseKey(hEnumeratorKey
);
1552 /* Enumerate enumerators */
1556 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1557 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1558 if (rc
== ERROR_NO_MORE_ITEMS
)
1560 if (rc
!= ERROR_SUCCESS
)
1562 RegCloseKey(hEnumKey
);
1568 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1569 if (rc
!= ERROR_SUCCESS
)
1571 RegCloseKey(hEnumKey
);
1575 /* Call SETUP_CreateDevListFromEnumerator */
1576 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1577 RegCloseKey(hEnumeratorKey
);
1578 if (rc
!= ERROR_SUCCESS
)
1580 RegCloseKey(hEnumKey
);
1584 RegCloseKey(hEnumKey
);
1585 return ERROR_SUCCESS
;
1590 static LONG
SETUP_CreateSerialDeviceList(
1591 struct DeviceInfoSet
*list
,
1593 LPGUID InterfaceGuid
,
1594 PCWSTR DeviceInstanceW
)
1596 static const size_t initialSize
= 100;
1598 WCHAR buf
[initialSize
];
1600 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1602 struct DeviceInfoElement
*deviceInfo
;
1605 WARN("'MachineName' is ignored on Wine!\n");
1606 if (DeviceInstanceW
)
1607 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1613 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1615 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1619 HeapFree(GetProcessHeap(), 0, devices
);
1620 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1622 return ERROR_NOT_ENOUGH_MEMORY
;
1628 HeapFree(GetProcessHeap(), 0, devices
);
1629 return GetLastError();
1633 /* 'devices' is a MULTI_SZ string */
1634 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1636 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1638 /* We have found a device */
1639 struct DeviceInterface
*interfaceInfo
;
1640 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1641 /* Step 1. Create a device info element */
1642 if (!CreateDeviceInfoElement(list
, ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1645 HeapFree(GetProcessHeap(), 0, devices
);
1646 return GetLastError();
1648 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1650 /* Step 2. Create an interface list for this element */
1651 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1654 HeapFree(GetProcessHeap(), 0, devices
);
1655 return GetLastError();
1657 interfaceInfo
->Flags
|= SPINT_ACTIVE
| SPINT_DEFAULT
;
1658 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1662 HeapFree(GetProcessHeap(), 0, devices
);
1663 return ERROR_SUCCESS
;
1666 #else /* __REACTOS__ */
1668 static LONG
SETUP_CreateInterfaceList(
1669 struct DeviceInfoSet
*list
,
1671 LPGUID InterfaceGuid
,
1672 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1674 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1675 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1676 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1677 HKEY hControlKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */
1678 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1679 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1681 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1684 DWORD dwLength
, dwInstancePathLength
;
1688 struct DeviceInfoElement
*deviceInfo
;
1690 /* Open registry key related to this interface */
1691 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1692 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1693 return GetLastError();
1695 /* Enumerate sub keys of hInterfaceKey */
1699 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1700 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1701 if (rc
== ERROR_NO_MORE_ITEMS
)
1703 if (rc
!= ERROR_SUCCESS
)
1705 RegCloseKey(hInterfaceKey
);
1711 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1712 if (rc
!= ERROR_SUCCESS
)
1714 RegCloseKey(hInterfaceKey
);
1718 /* Read DeviceInstance */
1719 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1720 if (rc
!= ERROR_SUCCESS
)
1722 RegCloseKey(hDeviceInstanceKey
);
1723 RegCloseKey(hInterfaceKey
);
1726 if (dwRegType
!= REG_SZ
)
1728 RegCloseKey(hDeviceInstanceKey
);
1729 RegCloseKey(hInterfaceKey
);
1730 return ERROR_GEN_FAILURE
;
1732 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1735 RegCloseKey(hDeviceInstanceKey
);
1736 RegCloseKey(hInterfaceKey
);
1737 return ERROR_NOT_ENOUGH_MEMORY
;
1739 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1740 if (rc
!= ERROR_SUCCESS
)
1742 HeapFree(GetProcessHeap(), 0, InstancePath
);
1743 RegCloseKey(hDeviceInstanceKey
);
1744 RegCloseKey(hInterfaceKey
);
1747 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1748 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1750 if (DeviceInstanceW
)
1752 /* Check if device enumerator is not the right one */
1753 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1755 HeapFree(GetProcessHeap(), 0, InstancePath
);
1756 RegCloseKey(hDeviceInstanceKey
);
1761 /* Find class GUID associated to the device instance */
1764 REGSTR_PATH_SYSTEMENUM
,
1768 if (rc
!= ERROR_SUCCESS
)
1770 HeapFree(GetProcessHeap(), 0, InstancePath
);
1771 RegCloseKey(hDeviceInstanceKey
);
1772 RegCloseKey(hInterfaceKey
);
1781 RegCloseKey(hEnumKey
);
1782 if (rc
!= ERROR_SUCCESS
)
1784 HeapFree(GetProcessHeap(), 0, InstancePath
);
1785 RegCloseKey(hDeviceInstanceKey
);
1786 RegCloseKey(hInterfaceKey
);
1789 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1790 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1792 if (rc
!= ERROR_SUCCESS
)
1794 HeapFree(GetProcessHeap(), 0, InstancePath
);
1795 RegCloseKey(hDeviceInstanceKey
);
1796 RegCloseKey(hInterfaceKey
);
1799 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1800 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1801 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1803 HeapFree(GetProcessHeap(), 0, InstancePath
);
1804 RegCloseKey(hDeviceInstanceKey
);
1805 RegCloseKey(hInterfaceKey
);
1806 return ERROR_GEN_FAILURE
;
1808 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1810 /* If current device doesn't match the list GUID (if any), skip this entry */
1811 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1813 HeapFree(GetProcessHeap(), 0, InstancePath
);
1814 RegCloseKey(hDeviceInstanceKey
);
1818 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1822 LPWSTR pSymbolicLink
;
1823 struct DeviceInterface
*interfaceInfo
;
1825 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1826 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1827 if (rc
== ERROR_NO_MORE_ITEMS
)
1829 if (rc
!= ERROR_SUCCESS
)
1831 HeapFree(GetProcessHeap(), 0, InstancePath
);
1832 RegCloseKey(hDeviceInstanceKey
);
1833 RegCloseKey(hInterfaceKey
);
1837 if (KeyBuffer
[0] != '#')
1838 /* This entry doesn't represent an interesting entry */
1842 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1843 if (rc
!= ERROR_SUCCESS
)
1845 RegCloseKey(hDeviceInstanceKey
);
1846 RegCloseKey(hInterfaceKey
);
1850 /* Read SymbolicLink value */
1851 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1852 if (rc
!= ERROR_SUCCESS
)
1854 RegCloseKey(hReferenceKey
);
1855 RegCloseKey(hDeviceInstanceKey
);
1856 RegCloseKey(hInterfaceKey
);
1859 if (dwRegType
!= REG_SZ
)
1861 RegCloseKey(hReferenceKey
);
1862 RegCloseKey(hDeviceInstanceKey
);
1863 RegCloseKey(hInterfaceKey
);
1864 return ERROR_GEN_FAILURE
;
1867 /* We have found a device */
1868 /* Step 1. Create a device info element */
1869 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1871 RegCloseKey(hReferenceKey
);
1872 RegCloseKey(hDeviceInstanceKey
);
1873 RegCloseKey(hInterfaceKey
);
1874 return GetLastError();
1876 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1877 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1879 /* Step 2. Create an interface list for this element */
1880 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1883 RegCloseKey(hReferenceKey
);
1884 RegCloseKey(hDeviceInstanceKey
);
1885 RegCloseKey(hInterfaceKey
);
1886 return ERROR_NOT_ENOUGH_MEMORY
;
1888 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1889 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1890 RegCloseKey(hReferenceKey
);
1891 if (rc
!= ERROR_SUCCESS
)
1893 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1894 RegCloseKey(hDeviceInstanceKey
);
1895 RegCloseKey(hInterfaceKey
);
1898 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1900 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1901 RegCloseKey(hDeviceInstanceKey
);
1902 RegCloseKey(hInterfaceKey
);
1903 return GetLastError();
1906 /* Step 3. Update flags */
1907 if (KeyBuffer
[1] == '\0')
1908 interfaceInfo
->Flags
|= SPINT_DEFAULT
;
1909 rc
= RegOpenKeyExW(hReferenceKey
, Control
, 0, KEY_QUERY_VALUE
, &hControlKey
);
1911 interfaceInfo
->Flags
|= SPINT_REMOVED
;
1914 dwLength
= sizeof(DWORD
);
1915 if (RegQueryValueExW(hControlKey
, Linked
, NULL
, &dwRegType
, (LPBYTE
)&LinkedValue
, &dwLength
)
1916 && dwRegType
== REG_DWORD
&& LinkedValue
)
1917 interfaceInfo
->Flags
|= SPINT_ACTIVE
;
1918 RegCloseKey(hControlKey
);
1921 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1922 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1923 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1925 RegCloseKey(hDeviceInstanceKey
);
1927 RegCloseKey(hInterfaceKey
);
1928 return ERROR_SUCCESS
;
1930 #endif /* __REACTOS__ */
1932 /***********************************************************************
1933 * SetupDiGetClassDevsExW (SETUPAPI.@)
1935 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1944 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1945 struct DeviceInfoSet
*list
;
1949 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1950 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1952 /* Create the deviceset if not set */
1955 list
= (struct DeviceInfoSet
*)deviceset
;
1956 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1958 SetLastError(ERROR_INVALID_HANDLE
);
1959 return INVALID_HANDLE_VALUE
;
1961 hDeviceInfo
= deviceset
;
1965 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1966 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1967 NULL
, machine
, NULL
);
1968 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1969 return INVALID_HANDLE_VALUE
;
1970 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1973 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1976 pClassGuid
= &list
->ClassGuid
;
1978 if (flags
& DIGCF_PRESENT
)
1979 FIXME(": flag DIGCF_PRESENT ignored\n");
1980 if (flags
& DIGCF_PROFILE
)
1981 FIXME(": flag DIGCF_PROFILE ignored\n");
1983 if (flags
& DIGCF_ALLCLASSES
)
1985 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1986 if (rc
!= ERROR_SUCCESS
)
1990 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1991 return INVALID_HANDLE_VALUE
;
1995 else if (flags
& DIGCF_DEVICEINTERFACE
)
1999 SetLastError(ERROR_INVALID_PARAMETER
);
2001 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2002 return INVALID_HANDLE_VALUE
;
2006 /* Special case: find serial ports by calling QueryDosDevice */
2007 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
2008 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
2009 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
2010 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
2013 ERR("Wine can only enumerate serial devices at the moment!\n");
2014 rc
= ERROR_INVALID_PARAMETER
;
2016 #else /* __REACTOS__ */
2017 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
2018 #endif /* __REACTOS__ */
2019 if (rc
!= ERROR_SUCCESS
)
2023 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2024 return INVALID_HANDLE_VALUE
;
2030 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
2031 if (rc
!= ERROR_SUCCESS
)
2035 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2036 return INVALID_HANDLE_VALUE
;
2042 /***********************************************************************
2043 * SetupDiGetClassImageIndex (SETUPAPI.@)
2046 static BOOL
GetIconIndex(
2048 OUT PINT ImageIndex
)
2050 LPWSTR Buffer
= NULL
;
2051 DWORD dwRegType
, dwLength
;
2055 /* Read icon registry key */
2056 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
2057 if (rc
!= ERROR_SUCCESS
)
2061 } else if (dwRegType
!= REG_SZ
)
2063 SetLastError(ERROR_INVALID_INDEX
);
2066 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2069 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2072 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2073 if (rc
!= ERROR_SUCCESS
)
2078 /* make sure the returned buffer is NULL-terminated */
2079 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2081 /* Transform icon value to a INT */
2082 *ImageIndex
= atoiW(Buffer
);
2090 BOOL WINAPI
SetupDiGetClassImageIndex(
2091 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2092 IN CONST GUID
*ClassGuid
,
2093 OUT PINT ImageIndex
)
2095 struct ClassImageList
*list
;
2098 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2100 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2101 SetLastError(ERROR_INVALID_PARAMETER
);
2102 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2103 SetLastError(ERROR_INVALID_USER_BUFFER
);
2104 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2105 SetLastError(ERROR_INVALID_USER_BUFFER
);
2106 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2107 SetLastError(ERROR_INVALID_USER_BUFFER
);
2108 else if (!ImageIndex
)
2109 SetLastError(ERROR_INVALID_PARAMETER
);
2112 HKEY hKey
= INVALID_HANDLE_VALUE
;
2115 /* Read Icon registry entry into Buffer */
2116 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2117 if (hKey
== INVALID_HANDLE_VALUE
)
2119 if (!GetIconIndex(hKey
, &iconIndex
))
2124 SetLastError(ERROR_INVALID_INDEX
);
2128 *ImageIndex
= -iconIndex
;
2132 if (hKey
!= INVALID_HANDLE_VALUE
)
2136 TRACE("Returning %d\n", ret
);
2140 /***********************************************************************
2141 * SetupDiGetClassImageList(SETUPAPI.@)
2143 BOOL WINAPI
SetupDiGetClassImageList(
2144 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2146 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2149 /***********************************************************************
2150 * SetupDiGetClassImageListExA(SETUPAPI.@)
2152 BOOL WINAPI
SetupDiGetClassImageListExA(
2153 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2154 IN PCSTR MachineName OPTIONAL
,
2157 PWSTR MachineNameW
= NULL
;
2162 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2163 if (MachineNameW
== NULL
)
2167 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2170 MyFree(MachineNameW
);
2175 /***********************************************************************
2176 * SetupDiGetClassImageListExW(SETUPAPI.@)
2178 BOOL WINAPI
SetupDiGetClassImageListExW(
2179 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2180 IN PCWSTR MachineName OPTIONAL
,
2185 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2187 if (!ClassImageListData
)
2188 SetLastError(ERROR_INVALID_PARAMETER
);
2189 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2190 SetLastError(ERROR_INVALID_USER_BUFFER
);
2192 SetLastError(ERROR_INVALID_PARAMETER
);
2195 struct ClassImageList
*list
= NULL
;
2198 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2200 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
2201 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2204 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2207 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2210 list
->szData
[0] = list
->szData
[1] = '\\';
2211 strcpyW(list
->szData
+ 2, MachineName
);
2212 list
->MachineName
= list
->szData
;
2216 list
->MachineName
= NULL
;
2219 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2227 TRACE("Returning %d\n", ret
);
2231 /***********************************************************************
2232 * SetupDiLoadClassIcon(SETUPAPI.@)
2234 BOOL WINAPI
SetupDiLoadClassIcon(
2235 IN CONST GUID
*ClassGuid
,
2236 OUT HICON
*LargeIcon OPTIONAL
,
2237 OUT PINT MiniIconIndex OPTIONAL
)
2242 SetLastError(ERROR_INVALID_PARAMETER
);
2245 LPWSTR Buffer
= NULL
;
2248 HKEY hKey
= INVALID_HANDLE_VALUE
;
2250 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2251 if (hKey
== INVALID_HANDLE_VALUE
)
2254 if (!GetIconIndex(hKey
, &iconIndex
))
2259 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2262 DWORD dwRegType
, dwLength
;
2263 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2264 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2266 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2269 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2272 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2273 if (rc
!= ERROR_SUCCESS
)
2278 /* make sure the returned buffer is NULL-terminated */
2279 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2282 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2283 && dwRegType
== REG_SZ
)
2285 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2288 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2291 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2292 if (rc
!= ERROR_SUCCESS
)
2297 /* make sure the returned buffer is NULL-terminated */
2298 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2302 /* Unable to find where to load the icon */
2303 SetLastError(ERROR_FILE_NOT_FOUND
);
2306 Comma
= strchrW(Buffer
, ',');
2309 SetLastError(ERROR_GEN_FAILURE
);
2317 /* Look up icon in setupapi.dll */
2318 DllName
= L
"setupapi.dll";
2319 iconIndex
= -iconIndex
;
2322 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2325 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2327 SetLastError(ERROR_INVALID_INDEX
);
2332 *MiniIconIndex
= iconIndex
;
2336 if (hKey
!= INVALID_HANDLE_VALUE
)
2341 TRACE("Returning %d\n", ret
);
2345 /***********************************************************************
2346 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2348 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2349 HDEVINFO DeviceInfoSet
,
2350 PSP_DEVINFO_DATA DeviceInfoData
,
2351 CONST GUID
* InterfaceClassGuid
,
2353 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2357 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2358 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2360 if (!DeviceInterfaceData
)
2361 SetLastError(ERROR_INVALID_PARAMETER
);
2362 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2363 SetLastError(ERROR_INVALID_USER_BUFFER
);
2364 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2366 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2368 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2370 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2372 while (ItemList
!= &list
->ListHead
&& !Found
)
2374 PLIST_ENTRY InterfaceListEntry
;
2375 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2376 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2378 /* We are not searching for this element */
2379 ItemList
= ItemList
->Flink
;
2382 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2383 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2385 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2386 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2388 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2391 if (MemberIndex
-- == 0)
2393 /* return this item */
2394 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2395 &DevItf
->InterfaceClassGuid
,
2397 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2398 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2401 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2403 ItemList
= ItemList
->Flink
;
2406 SetLastError(ERROR_NO_MORE_ITEMS
);
2411 SetLastError(ERROR_INVALID_HANDLE
);
2414 SetLastError(ERROR_INVALID_HANDLE
);
2418 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2420 InterlockedIncrement(&infFile
->References
);
2423 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2425 if (InterlockedDecrement(&infFile
->References
) == 0)
2427 SetupCloseInfFile(infFile
->hInf
);
2428 HeapFree(GetProcessHeap(), 0, infFile
);
2432 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2434 DereferenceInfFile(driverInfo
->InfFileDetails
);
2435 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2436 HeapFree(GetProcessHeap(), 0, driverInfo
);
2440 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2442 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2446 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2448 PLIST_ENTRY ListEntry
;
2449 struct DriverInfoElement
*driverInfo
;
2451 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2453 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2454 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2455 if (!DestroyDriverInfoElement(driverInfo
))
2458 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2460 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2461 HeapFree(GetProcessHeap(), 0, ListEntry
);
2463 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2464 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2468 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2470 PLIST_ENTRY ListEntry
;
2471 struct DeviceInfoElement
*deviceInfo
;
2473 while (!IsListEmpty(&list
->ListHead
))
2475 ListEntry
= RemoveHeadList(&list
->ListHead
);
2476 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2477 if (!DestroyDeviceInfoElement(deviceInfo
))
2480 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2481 RegCloseKey(list
->HKLM
);
2482 CM_Disconnect_Machine(list
->hMachine
);
2483 DestroyClassInstallParams(&list
->ClassInstallParams
);
2484 HeapFree(GetProcessHeap(), 0, list
);
2488 /***********************************************************************
2489 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2491 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2495 TRACE("%p\n", devinfo
);
2496 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2498 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2500 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2501 ret
= DestroyDeviceInfoSet(list
);
2503 SetLastError(ERROR_INVALID_HANDLE
);
2506 SetLastError(ERROR_INVALID_HANDLE
);
2508 TRACE("Returning %d\n", ret
);
2512 /***********************************************************************
2513 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2515 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2516 HDEVINFO DeviceInfoSet
,
2517 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2518 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2519 DWORD DeviceInterfaceDetailDataSize
,
2520 PDWORD RequiredSize
,
2521 PSP_DEVINFO_DATA DeviceInfoData
)
2523 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2524 DWORD sizeW
= 0, sizeA
;
2527 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2528 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2529 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2531 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2532 SetLastError(ERROR_INVALID_USER_BUFFER
);
2533 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2534 SetLastError(ERROR_INVALID_PARAMETER
);
2535 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2536 SetLastError(ERROR_INVALID_PARAMETER
);
2539 if (DeviceInterfaceDetailData
!= NULL
)
2541 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2542 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2543 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2544 if (!DeviceInterfaceDetailDataW
)
2546 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2549 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2551 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2552 ret
= SetupDiGetDeviceInterfaceDetailW(
2554 DeviceInterfaceData
,
2555 DeviceInterfaceDetailDataW
,
2559 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2560 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2562 *RequiredSize
= sizeA
;
2563 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2565 if (!WideCharToMultiByte(
2567 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2568 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2575 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2578 TRACE("Returning %d\n", ret
);
2582 /***********************************************************************
2583 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2585 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2586 HDEVINFO DeviceInfoSet
,
2587 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2588 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2589 DWORD DeviceInterfaceDetailDataSize
,
2590 PDWORD RequiredSize
,
2591 PSP_DEVINFO_DATA DeviceInfoData
)
2595 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2596 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2597 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2599 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2600 SetLastError(ERROR_INVALID_PARAMETER
);
2601 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2602 SetLastError(ERROR_INVALID_HANDLE
);
2603 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2604 SetLastError(ERROR_INVALID_HANDLE
);
2605 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2606 SetLastError(ERROR_INVALID_USER_BUFFER
);
2607 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2608 SetLastError(ERROR_INVALID_USER_BUFFER
);
2609 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2610 SetLastError(ERROR_INVALID_USER_BUFFER
);
2611 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2612 SetLastError(ERROR_INVALID_PARAMETER
);
2613 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2614 SetLastError(ERROR_INVALID_PARAMETER
);
2617 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2618 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2619 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2620 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2622 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2624 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2626 *RequiredSize
= sizeRequired
;
2630 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2631 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2634 memcpy(&DeviceInfoData
->ClassGuid
,
2635 &deviceInterface
->DeviceInfo
->ClassGuid
,
2637 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2638 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2644 TRACE("Returning %d\n", ret
);
2648 /***********************************************************************
2649 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2651 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2653 PSP_DEVINFO_DATA DeviceInfoData
,
2655 PDWORD PropertyRegDataType
,
2656 PBYTE PropertyBuffer
,
2657 DWORD PropertyBufferSize
,
2658 PDWORD RequiredSize
)
2661 BOOL bIsStringProperty
;
2663 DWORD RequiredSizeA
, RequiredSizeW
;
2664 DWORD PropertyBufferSizeW
;
2665 PBYTE PropertyBufferW
;
2667 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2668 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2671 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2672 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2674 bResult
= SetupDiGetDeviceRegistryPropertyW(
2680 PropertyBufferSizeW
,
2683 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2685 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2687 if (bIsStringProperty
)
2688 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2690 RequiredSizeA
= RequiredSizeW
;
2692 *RequiredSize
= RequiredSizeA
;
2693 if (PropertyRegDataType
)
2694 *PropertyRegDataType
= RegType
;
2699 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2703 if (RequiredSizeA
<= PropertyBufferSize
)
2705 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2707 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2709 /* Last error is already set by WideCharToMultiByte */
2714 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2718 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2722 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2726 /***********************************************************************
2727 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2729 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2730 HDEVINFO DeviceInfoSet
,
2731 PSP_DEVINFO_DATA DeviceInfoData
,
2733 PDWORD PropertyRegDataType
,
2734 PBYTE PropertyBuffer
,
2735 DWORD PropertyBufferSize
,
2736 PDWORD RequiredSize
)
2738 HKEY hEnumKey
, hKey
;
2742 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2743 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2746 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2747 SetLastError(ERROR_INVALID_HANDLE
);
2748 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2749 SetLastError(ERROR_INVALID_HANDLE
);
2750 else if (!DeviceInfoData
)
2751 SetLastError(ERROR_INVALID_PARAMETER
);
2752 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2753 SetLastError(ERROR_INVALID_USER_BUFFER
);
2754 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2755 SetLastError(ERROR_INVALID_PARAMETER
);
2758 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2759 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2763 case SPDRP_CAPABILITIES
:
2765 case SPDRP_CLASSGUID
:
2766 case SPDRP_COMPATIBLEIDS
:
2767 case SPDRP_CONFIGFLAGS
:
2768 case SPDRP_DEVICEDESC
:
2770 case SPDRP_FRIENDLYNAME
:
2771 case SPDRP_HARDWAREID
:
2772 case SPDRP_LOCATION_INFORMATION
:
2773 case SPDRP_LOWERFILTERS
:
2775 case SPDRP_SECURITY
:
2777 case SPDRP_UI_NUMBER
:
2778 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2779 case SPDRP_UPPERFILTERS
:
2781 LPCWSTR RegistryPropertyName
;
2786 case SPDRP_CAPABILITIES
:
2787 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2789 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2790 case SPDRP_CLASSGUID
:
2791 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2792 case SPDRP_COMPATIBLEIDS
:
2793 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2794 case SPDRP_CONFIGFLAGS
:
2795 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2796 case SPDRP_DEVICEDESC
:
2797 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2799 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2800 case SPDRP_FRIENDLYNAME
:
2801 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2802 case SPDRP_HARDWAREID
:
2803 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2804 case SPDRP_LOCATION_INFORMATION
:
2805 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2806 case SPDRP_LOWERFILTERS
:
2807 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2809 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2810 case SPDRP_SECURITY
:
2811 RegistryPropertyName
= L
"Security"; break;
2813 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2814 case SPDRP_UI_NUMBER
:
2815 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2816 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2817 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2818 case SPDRP_UPPERFILTERS
:
2819 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2821 /* Should not happen */
2822 RegistryPropertyName
= NULL
; break;
2825 /* Open registry key name */
2828 REGSTR_PATH_SYSTEMENUM
,
2832 if (rc
!= ERROR_SUCCESS
)
2843 RegCloseKey(hEnumKey
);
2844 if (rc
!= ERROR_SUCCESS
)
2849 /* Read registry entry */
2850 BufferSize
= PropertyBufferSize
;
2851 rc
= RegQueryValueExW(
2853 RegistryPropertyName
,
2854 NULL
, /* Reserved */
2855 PropertyRegDataType
,
2859 *RequiredSize
= BufferSize
;
2862 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2865 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2867 case ERROR_MORE_DATA
:
2868 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2877 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2879 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2881 if (PropertyRegDataType
)
2882 *PropertyRegDataType
= REG_SZ
;
2884 *RequiredSize
= required
;
2885 if (PropertyBufferSize
>= required
)
2887 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2891 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2895 /*case SPDRP_BUSTYPEGUID:
2896 case SPDRP_LEGACYBUSTYPE:
2897 case SPDRP_BUSNUMBER:
2898 case SPDRP_ENUMERATOR_NAME:
2899 case SPDRP_SECURITY_SDS:
2901 case SPDRP_EXCLUSIVE:
2902 case SPDRP_CHARACTERISTICS:
2904 case SPDRP_DEVICE_POWER_DATA:*/
2905 #if (WINVER >= 0x501)
2906 /*case SPDRP_REMOVAL_POLICY:
2907 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2908 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2909 case SPDRP_INSTALL_STATE:*/
2914 ERR("Property 0x%lx not implemented\n", Property
);
2915 SetLastError(ERROR_NOT_SUPPORTED
);
2920 TRACE("Returning %d\n", ret
);
2924 /***********************************************************************
2925 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2927 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2928 IN HDEVINFO DeviceInfoSet
,
2929 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2931 IN CONST BYTE
*PropertyBuffer
,
2932 IN DWORD PropertyBufferSize
)
2934 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2935 Property
, PropertyBuffer
, PropertyBufferSize
);
2936 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2940 /***********************************************************************
2941 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2943 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2944 IN HDEVINFO DeviceInfoSet
,
2945 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2947 IN
const BYTE
*PropertyBuffer
,
2948 IN DWORD PropertyBufferSize
)
2950 struct DeviceInfoSet
*list
;
2953 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2954 Property
, PropertyBuffer
, PropertyBufferSize
);
2957 SetLastError(ERROR_INVALID_HANDLE
);
2958 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2959 SetLastError(ERROR_INVALID_HANDLE
);
2960 else if (!DeviceInfoData
)
2961 SetLastError(ERROR_INVALID_HANDLE
);
2962 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2963 SetLastError(ERROR_INVALID_USER_BUFFER
);
2968 case SPDRP_COMPATIBLEIDS
:
2969 case SPDRP_CONFIGFLAGS
:
2970 case SPDRP_FRIENDLYNAME
:
2971 case SPDRP_HARDWAREID
:
2972 case SPDRP_LOCATION_INFORMATION
:
2973 case SPDRP_LOWERFILTERS
:
2974 case SPDRP_SECURITY
:
2976 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2977 case SPDRP_UPPERFILTERS
:
2979 LPCWSTR RegistryPropertyName
;
2980 DWORD RegistryDataType
;
2986 case SPDRP_COMPATIBLEIDS
:
2987 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2988 RegistryDataType
= REG_MULTI_SZ
;
2990 case SPDRP_CONFIGFLAGS
:
2991 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2992 RegistryDataType
= REG_DWORD
;
2994 case SPDRP_FRIENDLYNAME
:
2995 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2996 RegistryDataType
= REG_SZ
;
2998 case SPDRP_HARDWAREID
:
2999 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
3000 RegistryDataType
= REG_MULTI_SZ
;
3002 case SPDRP_LOCATION_INFORMATION
:
3003 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
3004 RegistryDataType
= REG_SZ
;
3006 case SPDRP_LOWERFILTERS
:
3007 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
3008 RegistryDataType
= REG_MULTI_SZ
;
3010 case SPDRP_SECURITY
:
3011 RegistryPropertyName
= L
"Security";
3012 RegistryDataType
= REG_BINARY
;
3015 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
3016 RegistryDataType
= REG_SZ
;
3018 case SPDRP_UI_NUMBER_DESC_FORMAT
:
3019 RegistryPropertyName
= L
"UINumberDescFormat";
3020 RegistryDataType
= REG_SZ
;
3022 case SPDRP_UPPERFILTERS
:
3023 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
3024 RegistryDataType
= REG_MULTI_SZ
;
3027 /* Should not happen */
3028 RegistryPropertyName
= NULL
;
3029 RegistryDataType
= REG_BINARY
;
3032 /* Open device registry key */
3033 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3034 if (hKey
!= INVALID_HANDLE_VALUE
)
3036 /* Write new data */
3037 rc
= RegSetValueExW(
3039 RegistryPropertyName
,
3043 PropertyBufferSize
);
3044 if (rc
== ERROR_SUCCESS
)
3053 /*case SPDRP_CHARACTERISTICS:
3055 case SPDRP_EXCLUSIVE:*/
3056 #if (WINVER >= 0x501)
3057 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
3059 //case SPDRP_SECURITY_SDS:
3063 ERR("Property 0x%lx not implemented\n", Property
);
3064 SetLastError(ERROR_NOT_SUPPORTED
);
3069 TRACE("Returning %d\n", ret
);
3074 /***********************************************************************
3075 * SetupDiInstallClassA (SETUPAPI.@)
3077 BOOL WINAPI
SetupDiInstallClassA(
3078 IN HWND hwndParent OPTIONAL
,
3079 IN PCSTR InfFileName
,
3081 IN HSPFILEQ FileQueue OPTIONAL
)
3083 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3087 /***********************************************************************
3088 * SetupDiInstallClassW (SETUPAPI.@)
3090 BOOL WINAPI
SetupDiInstallClassW(
3091 IN HWND hwndParent OPTIONAL
,
3092 IN PCWSTR InfFileName
,
3094 IN HSPFILEQ FileQueue OPTIONAL
)
3096 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3100 /***********************************************************************
3101 * SetupDiInstallClassExA (SETUPAPI.@)
3103 BOOL WINAPI
SetupDiInstallClassExA(
3104 IN HWND hwndParent OPTIONAL
,
3105 IN PCSTR InfFileName OPTIONAL
,
3107 IN HSPFILEQ FileQueue OPTIONAL
,
3108 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3112 PWSTR InfFileNameW
= NULL
;
3117 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3118 if (InfFileNameW
== NULL
)
3120 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3125 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3126 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3128 MyFree(InfFileNameW
);
3134 static HKEY
CreateClassKey(HINF hInf
)
3136 WCHAR FullBuffer
[MAX_PATH
];
3137 WCHAR Buffer
[MAX_PATH
];
3142 if (!SetupGetLineTextW(NULL
,
3150 return INVALID_HANDLE_VALUE
;
3153 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3154 lstrcatW(FullBuffer
, Buffer
);
3157 if (!SetupGetLineTextW(NULL
,
3165 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3166 return INVALID_HANDLE_VALUE
;
3169 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3173 REG_OPTION_NON_VOLATILE
,
3179 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3180 return INVALID_HANDLE_VALUE
;
3183 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3188 RequiredSize
* sizeof(WCHAR
)))
3190 RegCloseKey(hClassKey
);
3191 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3192 return INVALID_HANDLE_VALUE
;
3199 /***********************************************************************
3200 * SetupDiInstallClassExW (SETUPAPI.@)
3202 BOOL WINAPI
SetupDiInstallClassExW(
3203 IN HWND hwndParent OPTIONAL
,
3204 IN PCWSTR InfFileName OPTIONAL
,
3206 IN HSPFILEQ FileQueue OPTIONAL
,
3207 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3213 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3214 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3216 if (!InfFileName
&& !InterfaceClassGuid
)
3217 SetLastError(ERROR_INVALID_PARAMETER
);
3218 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3220 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3221 SetLastError(ERROR_INVALID_FLAGS
);
3223 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3224 SetLastError(ERROR_INVALID_PARAMETER
);
3225 else if (Reserved1
!= NULL
)
3226 SetLastError(ERROR_INVALID_PARAMETER
);
3227 else if (Reserved2
!= NULL
)
3228 SetLastError(ERROR_INVALID_PARAMETER
);
3231 WCHAR SectionName
[MAX_PATH
];
3232 HINF hInf
= INVALID_HANDLE_VALUE
;
3233 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3234 PVOID callback_context
= NULL
;
3236 if (InterfaceClassGuid
)
3238 /* SetupDiCreateDeviceInterface??? */
3239 FIXME("Installing an interface is not implemented\n");
3240 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3244 if (Flags
& DI_NOVCP
)
3245 FIXME("FileQueue argument ignored\n");
3246 if (Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3247 FIXME("Flags 0x%lx ignored\n", Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3249 /* Open the .inf file */
3250 hInf
= SetupOpenInfFileW(
3255 if (hInf
== INVALID_HANDLE_VALUE
)
3258 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3259 hClassKey
= CreateClassKey(hInf
);
3260 if (hClassKey
== INVALID_HANDLE_VALUE
)
3263 /* Try to append a layout file */
3264 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3268 /* Retrieve the actual section name */
3269 ret
= SetupDiGetActualSectionToInstallW(
3273 MAX_PATH
- wcslen(DotServices
),
3279 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3280 if (!callback_context
)
3283 ret
= SetupInstallFromInfSectionW(
3287 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3289 NULL
, /* SourceRootPath */
3291 SetupDefaultQueueCallbackW
,
3298 /* Install .Services section */
3299 lstrcatW(SectionName
, DotServices
);
3300 ret
= SetupInstallServicesFromInfSectionW(hInf
, SectionName
, 0);
3308 if (hInf
!= INVALID_HANDLE_VALUE
)
3309 SetupCloseInfFile(hInf
);
3310 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3311 RegCloseKey(hClassKey
);
3312 SetupTermDefaultQueueCallback(callback_context
);
3315 TRACE("Returning %d\n", ret
);
3320 /***********************************************************************
3321 * SetupDiOpenClassRegKey (SETUPAPI.@)
3323 HKEY WINAPI
SetupDiOpenClassRegKey(
3324 const GUID
* ClassGuid
,
3327 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3328 DIOCR_INSTALLER
, NULL
, NULL
);
3332 /***********************************************************************
3333 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3335 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3336 const GUID
* ClassGuid OPTIONAL
,
3339 PCSTR MachineName OPTIONAL
,
3342 PWSTR MachineNameW
= NULL
;
3349 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3350 if (MachineNameW
== NULL
)
3351 return INVALID_HANDLE_VALUE
;
3354 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3355 Flags
, MachineNameW
, Reserved
);
3358 MyFree(MachineNameW
);
3364 /***********************************************************************
3365 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3367 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3368 const GUID
* ClassGuid OPTIONAL
,
3371 PCWSTR MachineName OPTIONAL
,
3374 LPWSTR lpGuidString
;
3375 LPWSTR lpFullGuidString
;
3383 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3384 Flags
, debugstr_w(MachineName
), Reserved
);
3386 if (Flags
== DIOCR_INSTALLER
)
3388 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3390 else if (Flags
== DIOCR_INTERFACE
)
3392 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3396 ERR("Invalid Flags parameter!\n");
3397 SetLastError(ERROR_INVALID_FLAGS
);
3398 return INVALID_HANDLE_VALUE
;
3401 if (MachineName
!= NULL
)
3403 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3404 if (rc
!= ERROR_SUCCESS
)
3407 return INVALID_HANDLE_VALUE
;
3411 HKLM
= HKEY_LOCAL_MACHINE
;
3413 rc
= RegOpenKeyExW(HKLM
,
3416 ClassGuid
? 0 : samDesired
,
3418 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3419 if (rc
!= ERROR_SUCCESS
)
3422 return INVALID_HANDLE_VALUE
;
3425 if (ClassGuid
== NULL
)
3428 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3430 SetLastError(ERROR_GEN_FAILURE
);
3431 RegCloseKey(hClassesKey
);
3432 return INVALID_HANDLE_VALUE
;
3435 dwLength
= lstrlenW(lpGuidString
);
3436 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3437 if (!lpFullGuidString
)
3439 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3440 RpcStringFreeW(&lpGuidString
);
3441 return INVALID_HANDLE_VALUE
;
3443 lpFullGuidString
[0] = '{';
3444 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3445 lpFullGuidString
[dwLength
+ 1] = '}';
3446 lpFullGuidString
[dwLength
+ 2] = '\0';
3447 RpcStringFreeW(&lpGuidString
);
3449 rc
= RegOpenKeyExW(hClassesKey
,
3454 if (rc
!= ERROR_SUCCESS
)
3457 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3458 RegCloseKey(hClassesKey
);
3459 return INVALID_HANDLE_VALUE
;
3462 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3463 RegCloseKey(hClassesKey
);
3468 /***********************************************************************
3469 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3471 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3472 HDEVINFO DeviceInfoSet
,
3475 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3477 FIXME("%p %s %08lx %p\n",
3478 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3482 /***********************************************************************
3483 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3485 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3486 HDEVINFO DeviceInfoSet
,
3489 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3491 LPWSTR DevicePathW
= NULL
;
3494 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3496 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3497 if (DevicePathW
== NULL
)
3500 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3501 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3503 MyFree(DevicePathW
);
3508 /***********************************************************************
3509 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3511 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3512 HDEVINFO DeviceInfoSet
,
3513 PSP_DEVINFO_DATA DeviceInfoData
,
3514 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3515 DWORD ClassInstallParamsSize
)
3517 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3518 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3522 /***********************************************************************
3523 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3525 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3526 IN HDEVINFO DeviceInfoSet
,
3527 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3528 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3529 IN DWORD ClassInstallParamsSize
)
3531 struct DeviceInfoSet
*list
;
3534 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3535 ClassInstallParams
, ClassInstallParamsSize
);
3538 SetLastError(ERROR_INVALID_PARAMETER
);
3539 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3540 SetLastError(ERROR_INVALID_HANDLE
);
3541 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3542 SetLastError(ERROR_INVALID_HANDLE
);
3543 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3544 SetLastError(ERROR_INVALID_USER_BUFFER
);
3545 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3546 SetLastError(ERROR_INVALID_USER_BUFFER
);
3547 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3548 SetLastError(ERROR_INVALID_PARAMETER
);
3549 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3550 SetLastError(ERROR_INVALID_PARAMETER
);
3553 SP_DEVINSTALL_PARAMS_W InstallParams
;
3556 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3557 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3561 if (ClassInstallParams
)
3563 /* Check parameters in ClassInstallParams */
3564 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3565 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3567 SetLastError(ERROR_INVALID_USER_BUFFER
);
3570 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3572 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3573 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3576 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3579 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3583 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3586 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3590 TRACE("Returning %d\n", ret
);
3594 static BOOL
PropertyChangeHandler(
3595 IN HDEVINFO DeviceInfoSet
,
3596 IN PSP_DEVINFO_DATA DeviceInfoData
,
3597 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3598 IN DWORD ClassInstallParamsSize
)
3600 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3603 if (!DeviceInfoData
)
3604 SetLastError(ERROR_INVALID_PARAMETER
);
3605 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3606 SetLastError(ERROR_INVALID_PARAMETER
);
3607 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3608 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3609 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3610 SetLastError(ERROR_INVALID_FLAGS
);
3611 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3612 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3613 SetLastError(ERROR_INVALID_FLAGS
);
3614 else if (PropChangeParams
3615 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3616 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3617 SetLastError(ERROR_INVALID_USER_BUFFER
);
3620 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3621 if (!DeviceInfoData
)
3623 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3624 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3628 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3629 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3631 if (*CurrentPropChangeParams
)
3633 MyFree(*CurrentPropChangeParams
);
3634 *CurrentPropChangeParams
= NULL
;
3636 if (PropChangeParams
)
3638 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3639 if (!*CurrentPropChangeParams
)
3641 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3644 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3655 IN PWSTR InstallerName
,
3656 OUT HMODULE
* ModulePointer
,
3657 OUT PVOID
* FunctionPointer
)
3659 HMODULE hModule
= NULL
;
3660 LPSTR FunctionNameA
= NULL
;
3664 *ModulePointer
= NULL
;
3665 *FunctionPointer
= NULL
;
3667 Comma
= strchrW(InstallerName
, ',');
3670 rc
= ERROR_INVALID_PARAMETER
;
3676 hModule
= LoadLibraryW(InstallerName
);
3680 rc
= GetLastError();
3684 /* Skip comma spaces */
3685 while (*Comma
== ',' || isspaceW(*Comma
))
3688 /* W->A conversion for function name */
3689 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3692 rc
= GetLastError();
3696 /* Search function */
3697 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3698 if (!*FunctionPointer
)
3700 rc
= GetLastError();
3704 *ModulePointer
= hModule
;
3708 if (rc
!= ERROR_SUCCESS
&& hModule
)
3709 FreeLibrary(hModule
);
3710 MyFree(FunctionNameA
);
3715 FreeFunctionPointer(
3716 IN HMODULE ModulePointer
,
3717 IN PVOID FunctionPointer
)
3719 if (ModulePointer
== NULL
)
3720 return ERROR_SUCCESS
;
3721 if (FreeLibrary(ModulePointer
))
3722 return ERROR_SUCCESS
;
3724 return GetLastError();
3727 /***********************************************************************
3728 * SetupDiCallClassInstaller (SETUPAPI.@)
3730 BOOL WINAPI
SetupDiCallClassInstaller(
3731 IN DI_FUNCTION InstallFunction
,
3732 IN HDEVINFO DeviceInfoSet
,
3733 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3737 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3740 SetLastError(ERROR_INVALID_PARAMETER
);
3741 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3742 SetLastError(ERROR_INVALID_HANDLE
);
3743 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3744 SetLastError(ERROR_INVALID_HANDLE
);
3745 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3746 SetLastError(ERROR_INVALID_HANDLE
);
3747 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3748 SetLastError(ERROR_INVALID_USER_BUFFER
);
3751 SP_DEVINSTALL_PARAMS_W InstallParams
;
3752 #define CLASS_COINSTALLER 0x1
3753 #define DEVICE_COINSTALLER 0x2
3754 #define CLASS_INSTALLER 0x4
3755 UCHAR CanHandle
= 0;
3756 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3758 switch (InstallFunction
)
3760 case DIF_ALLOW_INSTALL
:
3761 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3763 case DIF_DESTROYPRIVATEDATA
:
3764 CanHandle
= CLASS_INSTALLER
;
3766 case DIF_INSTALLDEVICE
:
3767 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3768 DefaultHandler
= SetupDiInstallDevice
;
3770 case DIF_INSTALLDEVICEFILES
:
3771 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3772 DefaultHandler
= SetupDiInstallDriverFiles
;
3774 case DIF_INSTALLINTERFACES
:
3775 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3776 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3778 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3779 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3781 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3782 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3784 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3785 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3787 case DIF_PROPERTYCHANGE
:
3788 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3789 DefaultHandler
= SetupDiChangeState
;
3791 case DIF_REGISTER_COINSTALLERS
:
3792 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3793 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3795 case DIF_SELECTBESTCOMPATDRV
:
3796 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3797 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3800 ERR("Install function %u not supported\n", InstallFunction
);
3801 SetLastError(ERROR_NOT_SUPPORTED
);
3804 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3805 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3806 /* Don't process this call, as a parameter is invalid */
3811 LIST_ENTRY ClassCoInstallersListHead
;
3812 LIST_ENTRY DeviceCoInstallersListHead
;
3813 HMODULE ClassInstallerLibrary
= NULL
;
3814 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3815 COINSTALLER_CONTEXT_DATA Context
;
3816 PLIST_ENTRY ListEntry
;
3818 DWORD dwRegType
, dwLength
;
3819 DWORD rc
= NO_ERROR
;
3821 InitializeListHead(&ClassCoInstallersListHead
);
3822 InitializeListHead(&DeviceCoInstallersListHead
);
3824 if (CanHandle
& DEVICE_COINSTALLER
)
3826 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3827 if (hKey
!= INVALID_HANDLE_VALUE
)
3829 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3830 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3832 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3833 if (KeyBuffer
!= NULL
)
3835 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3836 if (rc
== ERROR_SUCCESS
)
3839 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3841 /* Add coinstaller to DeviceCoInstallersListHead list */
3842 struct CoInstallerElement
*coinstaller
;
3843 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3844 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3847 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3848 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3849 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3851 HeapFree(GetProcessHeap(), 0, coinstaller
);
3854 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3860 if (CanHandle
& CLASS_COINSTALLER
)
3864 REGSTR_PATH_CODEVICEINSTALLERS
,
3868 if (rc
== ERROR_SUCCESS
)
3870 LPWSTR lpGuidString
;
3871 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3873 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3874 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3876 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3877 if (KeyBuffer
!= NULL
)
3879 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3880 if (rc
== ERROR_SUCCESS
)
3883 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3885 /* Add coinstaller to ClassCoInstallersListHead list */
3886 struct CoInstallerElement
*coinstaller
;
3887 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3888 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3891 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3892 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3893 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3895 HeapFree(GetProcessHeap(), 0, coinstaller
);
3898 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3901 RpcStringFreeW(&lpGuidString
);
3906 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3908 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3909 if (hKey
!= INVALID_HANDLE_VALUE
)
3911 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3912 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3914 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3915 if (KeyBuffer
!= NULL
)
3917 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3918 if (rc
== ERROR_SUCCESS
)
3920 /* Get ClassInstaller function pointer */
3921 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3922 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3924 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3925 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3928 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3935 /* Call Class co-installers */
3936 Context
.PostProcessing
= FALSE
;
3938 ListEntry
= ClassCoInstallersListHead
.Flink
;
3939 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3941 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3942 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3943 coinstaller
->PrivateData
= Context
.PrivateData
;
3944 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3946 coinstaller
->DoPostProcessing
= TRUE
;
3949 ListEntry
= ListEntry
->Flink
;
3952 /* Call Device co-installers */
3953 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3954 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3956 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3957 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3958 coinstaller
->PrivateData
= Context
.PrivateData
;
3959 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3961 coinstaller
->DoPostProcessing
= TRUE
;
3964 ListEntry
= ListEntry
->Flink
;
3967 /* Call Class installer */
3970 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3971 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3974 rc
= ERROR_DI_DO_DEFAULT
;
3976 /* Call default handler */
3977 if (rc
== ERROR_DI_DO_DEFAULT
)
3979 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3981 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3984 rc
= GetLastError();
3990 /* Call Class co-installers that required postprocessing */
3991 Context
.PostProcessing
= TRUE
;
3992 ListEntry
= ClassCoInstallersListHead
.Flink
;
3993 while (ListEntry
!= &ClassCoInstallersListHead
)
3995 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3996 if (coinstaller
->DoPostProcessing
)
3998 Context
.InstallResult
= rc
;
3999 Context
.PrivateData
= coinstaller
->PrivateData
;
4000 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4002 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4003 ListEntry
= ListEntry
->Flink
;
4006 /* Call Device co-installers that required postprocessing */
4007 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4008 while (ListEntry
!= &DeviceCoInstallersListHead
)
4010 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
4011 if (coinstaller
->DoPostProcessing
)
4013 Context
.InstallResult
= rc
;
4014 Context
.PrivateData
= coinstaller
->PrivateData
;
4015 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4017 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4018 ListEntry
= ListEntry
->Flink
;
4021 /* Free allocated memory */
4022 while (!IsListEmpty(&ClassCoInstallersListHead
))
4024 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4025 HeapFree(GetProcessHeap(), 0, ListEntry
);
4027 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4029 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4030 HeapFree(GetProcessHeap(), 0, ListEntry
);
4033 ret
= (rc
== NO_ERROR
);
4037 TRACE("Returning %d\n", ret
);
4041 /***********************************************************************
4042 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4044 BOOL WINAPI
SetupDiGetDeviceInfoListClass(
4045 IN HDEVINFO DeviceInfoSet
,
4046 OUT LPGUID ClassGuid
)
4048 struct DeviceInfoSet
*list
;
4051 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4054 SetLastError(ERROR_INVALID_HANDLE
);
4055 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4056 SetLastError(ERROR_INVALID_HANDLE
);
4057 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4058 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4061 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4066 TRACE("Returning %d\n", ret
);
4070 /***********************************************************************
4071 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4073 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
4074 IN HDEVINFO DeviceInfoSet
,
4075 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
4077 struct DeviceInfoSet
*list
;
4080 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
4083 SetLastError(ERROR_INVALID_HANDLE
);
4084 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4085 SetLastError(ERROR_INVALID_HANDLE
);
4086 else if (!DeviceInfoListDetailData
)
4087 SetLastError(ERROR_INVALID_PARAMETER
);
4088 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
4089 SetLastError(ERROR_INVALID_USER_BUFFER
);
4093 &DeviceInfoListDetailData
->ClassGuid
,
4096 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
4097 if (list
->MachineName
)
4098 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
4100 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
4105 TRACE("Returning %d\n", ret
);
4109 /***********************************************************************
4110 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4112 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4113 IN HDEVINFO DeviceInfoSet
,
4114 IN PSP_DEVINFO_DATA DeviceInfoData
,
4115 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4117 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4120 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4122 if (DeviceInstallParams
== NULL
)
4123 SetLastError(ERROR_INVALID_PARAMETER
);
4124 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4125 SetLastError(ERROR_INVALID_USER_BUFFER
);
4128 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4129 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4133 /* Do W->A conversion */
4135 DeviceInstallParams
,
4136 &deviceInstallParamsW
,
4137 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4138 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4139 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4141 DeviceInstallParams
->DriverPath
[0] = '\0';
4147 TRACE("Returning %d\n", ret
);
4151 /***********************************************************************
4152 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4154 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
4155 IN HDEVINFO DeviceInfoSet
,
4156 IN PSP_DEVINFO_DATA DeviceInfoData
,
4157 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4159 struct DeviceInfoSet
*list
;
4162 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4165 SetLastError(ERROR_INVALID_HANDLE
);
4166 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4167 SetLastError(ERROR_INVALID_HANDLE
);
4168 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4169 SetLastError(ERROR_INVALID_USER_BUFFER
);
4170 else if (!DeviceInstallParams
)
4171 SetLastError(ERROR_INVALID_PARAMETER
);
4172 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4173 SetLastError(ERROR_INVALID_USER_BUFFER
);
4176 PSP_DEVINSTALL_PARAMS_W Source
;
4179 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4181 Source
= &list
->InstallParams
;
4182 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4186 TRACE("Returning %d\n", ret
);
4190 /***********************************************************************
4191 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4193 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
4194 IN HDEVINFO DeviceInfoSet
,
4195 IN PSP_DEVINFO_DATA DeviceInfoData
,
4196 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4198 struct DeviceInfoSet
*list
;
4201 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4204 SetLastError(ERROR_INVALID_HANDLE
);
4205 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4206 SetLastError(ERROR_INVALID_HANDLE
);
4207 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4208 SetLastError(ERROR_INVALID_USER_BUFFER
);
4209 else if (!DeviceInstallParams
)
4210 SetLastError(ERROR_INVALID_PARAMETER
);
4211 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4212 SetLastError(ERROR_INVALID_USER_BUFFER
);
4215 PSP_DEVINSTALL_PARAMS_W Destination
;
4217 /* FIXME: Validate parameters */
4220 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4222 Destination
= &list
->InstallParams
;
4223 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4227 TRACE("Returning %d\n", ret
);
4231 /***********************************************************************
4232 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4234 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
4235 IN HDEVINFO DeviceInfoSet
,
4236 IN PSP_DEVINFO_DATA DeviceInfoData
,
4237 OUT PSTR DeviceInstanceId OPTIONAL
,
4238 IN DWORD DeviceInstanceIdSize
,
4239 OUT PDWORD RequiredSize OPTIONAL
)
4241 PWSTR DeviceInstanceIdW
= NULL
;
4244 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4245 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4247 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4248 SetLastError(ERROR_INVALID_PARAMETER
);
4251 if (DeviceInstanceIdSize
!= 0)
4253 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4254 if (DeviceInstanceIdW
== NULL
)
4258 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4259 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4262 if (ret
&& DeviceInstanceIdW
!= NULL
)
4264 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4265 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4267 DeviceInstanceId
[0] = '\0';
4273 TRACE("Returning %d\n", ret
);
4277 /***********************************************************************
4278 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4280 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
4281 IN HDEVINFO DeviceInfoSet
,
4282 IN PSP_DEVINFO_DATA DeviceInfoData
,
4283 OUT PWSTR DeviceInstanceId OPTIONAL
,
4284 IN DWORD DeviceInstanceIdSize
,
4285 OUT PDWORD RequiredSize OPTIONAL
)
4289 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4290 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4293 SetLastError(ERROR_INVALID_HANDLE
);
4294 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4295 SetLastError(ERROR_INVALID_HANDLE
);
4296 else if (!DeviceInfoData
)
4297 SetLastError(ERROR_INVALID_PARAMETER
);
4298 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4299 SetLastError(ERROR_INVALID_USER_BUFFER
);
4300 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4301 SetLastError(ERROR_INVALID_PARAMETER
);
4302 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4303 SetLastError(ERROR_INVALID_PARAMETER
);
4306 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4309 required
= (wcslen(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4311 *RequiredSize
= required
;
4313 if (required
<= DeviceInstanceIdSize
)
4315 wcscpy(DeviceInstanceId
, DevInfo
->DeviceName
);
4319 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4322 TRACE("Returning %d\n", ret
);
4326 /***********************************************************************
4327 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4329 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
4330 IN HDEVINFO DeviceInfoSet
,
4331 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4332 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4333 IN DWORD PropertySheetHeaderPageListSize
,
4334 OUT PDWORD RequiredSize OPTIONAL
,
4335 IN DWORD PropertySheetType
)
4337 PROPSHEETHEADERW psh
;
4340 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4341 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4342 RequiredSize
, PropertySheetType
);
4344 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4345 psh
.phpage
= PropertySheetHeader
->phpage
;
4346 psh
.nPages
= PropertySheetHeader
->nPages
;
4348 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4349 PropertySheetHeaderPageListSize
, RequiredSize
,
4353 PropertySheetHeader
->nPages
= psh
.nPages
;
4356 TRACE("Returning %d\n", ret
);
4360 struct ClassDevPropertySheetsData
4362 HPROPSHEETPAGE
*PropertySheetPages
;
4363 DWORD MaximumNumberOfPages
;
4364 DWORD NumberOfPages
;
4367 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
4368 IN HPROPSHEETPAGE hPropSheetPage
,
4369 IN OUT LPARAM lParam
)
4371 struct ClassDevPropertySheetsData
*PropPageData
;
4373 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4375 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4377 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4378 PropPageData
->PropertySheetPages
++;
4381 PropPageData
->NumberOfPages
++;
4385 /***********************************************************************
4386 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4388 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
4389 IN HDEVINFO DeviceInfoSet
,
4390 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4391 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4392 IN DWORD PropertySheetHeaderPageListSize
,
4393 OUT PDWORD RequiredSize OPTIONAL
,
4394 IN DWORD PropertySheetType
)
4396 struct DeviceInfoSet
*list
;
4399 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4400 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4401 RequiredSize
, PropertySheetType
);
4404 SetLastError(ERROR_INVALID_HANDLE
);
4405 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4406 SetLastError(ERROR_INVALID_HANDLE
);
4407 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4408 SetLastError(ERROR_INVALID_HANDLE
);
4409 else if (!PropertySheetHeader
)
4410 SetLastError(ERROR_INVALID_PARAMETER
);
4411 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4412 SetLastError(ERROR_INVALID_FLAGS
);
4413 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4414 SetLastError(ERROR_INVALID_USER_BUFFER
);
4415 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4416 SetLastError(ERROR_INVALID_PARAMETER
);
4417 else if (!PropertySheetHeader
)
4418 SetLastError(ERROR_INVALID_PARAMETER
);
4419 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4420 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4421 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4422 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4423 SetLastError(ERROR_INVALID_PARAMETER
);
4426 HKEY hKey
= INVALID_HANDLE_VALUE
;
4427 SP_PROPSHEETPAGE_REQUEST Request
;
4428 LPWSTR PropPageProvider
= NULL
;
4429 HMODULE hModule
= NULL
;
4430 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4431 struct ClassDevPropertySheetsData PropPageData
;
4432 DWORD dwLength
, dwRegType
;
4436 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4439 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4440 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4442 if (hKey
== INVALID_HANDLE_VALUE
)
4445 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4446 if (rc
== ERROR_FILE_NOT_FOUND
)
4448 /* No registry key. As it is optional, don't say it's a bad error */
4454 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4460 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4461 if (!PropPageProvider
)
4463 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4466 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4467 if (rc
!= ERROR_SUCCESS
)
4472 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4474 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4475 if (rc
!= ERROR_SUCCESS
)
4477 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4481 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4482 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4483 Request
.DeviceInfoSet
= DeviceInfoSet
;
4484 Request
.DeviceInfoData
= DeviceInfoData
;
4485 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4486 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4487 PropPageData
.NumberOfPages
= 0;
4488 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4493 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4494 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4496 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4501 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4502 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4506 if (hKey
!= INVALID_HANDLE_VALUE
)
4508 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4509 FreeFunctionPointer(hModule
, pPropPageProvider
);
4512 TRACE("Returning %d\n", ret
);
4516 /***********************************************************************
4517 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4519 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4520 IN HDEVINFO DeviceInfoSet
,
4521 IN PSP_DEVINFO_DATA DeviceInfoData
,
4525 IN HINF InfHandle OPTIONAL
,
4526 IN PCSTR InfSectionName OPTIONAL
)
4528 PCWSTR InfSectionNameW
= NULL
;
4529 HKEY ret
= INVALID_HANDLE_VALUE
;
4533 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4534 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4537 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4545 if (InfSectionNameW
!= NULL
)
4546 MyFree((PVOID
)InfSectionNameW
);
4552 OpenHardwareProfileKey(
4555 IN DWORD samDesired
)
4557 HKEY hHWProfilesKey
= INVALID_HANDLE_VALUE
;
4558 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4559 HKEY ret
= INVALID_HANDLE_VALUE
;
4562 rc
= RegOpenKeyExW(HKLM
,
4563 REGSTR_PATH_HWPROFILES
,
4567 if (rc
!= ERROR_SUCCESS
)
4584 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4593 if (rc
!= ERROR_SUCCESS
)
4598 ret
= hHWProfileKey
;
4601 if (hHWProfilesKey
!= INVALID_HANDLE_VALUE
)
4602 RegCloseKey(hHWProfilesKey
);
4603 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
&& hHWProfileKey
!= ret
)
4604 RegCloseKey(hHWProfileKey
);
4608 /***********************************************************************
4609 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4611 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4612 IN HDEVINFO DeviceInfoSet
,
4613 IN PSP_DEVINFO_DATA DeviceInfoData
,
4617 IN HINF InfHandle OPTIONAL
,
4618 IN PCWSTR InfSectionName OPTIONAL
)
4620 struct DeviceInfoSet
*list
;
4621 HKEY ret
= INVALID_HANDLE_VALUE
;
4623 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4624 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4627 SetLastError(ERROR_INVALID_HANDLE
);
4628 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4629 SetLastError(ERROR_INVALID_HANDLE
);
4630 else if (!DeviceInfoData
)
4631 SetLastError(ERROR_INVALID_PARAMETER
);
4632 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4633 SetLastError(ERROR_INVALID_USER_BUFFER
);
4634 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4635 SetLastError(ERROR_INVALID_PARAMETER
);
4636 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4637 SetLastError(ERROR_INVALID_PARAMETER
);
4638 else if (InfHandle
&& !InfSectionName
)
4639 SetLastError(ERROR_INVALID_PARAMETER
);
4640 else if (!InfHandle
&& InfSectionName
)
4641 SetLastError(ERROR_INVALID_PARAMETER
);
4644 LPWSTR lpGuidString
= NULL
;
4645 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4646 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4647 DWORD Index
; /* Index used in the DriverKey name */
4649 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4650 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4651 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4652 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4653 HKEY hKey
= INVALID_HANDLE_VALUE
;
4656 if (Scope
== DICS_FLAG_GLOBAL
)
4657 RootKey
= list
->HKLM
;
4658 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4660 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
4661 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4663 RootKey
= hHWProfileKey
;
4666 if (KeyType
== DIREG_DEV
)
4668 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4670 rc
= RegCreateKeyExW(
4672 REGSTR_PATH_SYSTEMENUM
,
4675 REG_OPTION_NON_VOLATILE
,
4680 if (rc
!= ERROR_SUCCESS
)
4685 rc
= RegCreateKeyExW(
4687 deviceInfo
->DeviceName
,
4690 REG_OPTION_NON_VOLATILE
,
4691 #if _WIN32_WINNT >= 0x502
4692 KEY_READ
| KEY_WRITE
,
4699 if (rc
!= ERROR_SUCCESS
)
4705 else /* KeyType == DIREG_DRV */
4707 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4709 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4710 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4713 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4716 wcscpy(DriverKey
, L
"{");
4717 wcscat(DriverKey
, lpGuidString
);
4718 wcscat(DriverKey
, L
"}\\");
4719 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4720 rc
= RegOpenKeyExW(RootKey
,
4721 REGSTR_PATH_CLASS_NT
,
4725 if (rc
!= ERROR_SUCCESS
)
4731 /* Try all values for Index between 0 and 9999 */
4733 while (Index
<= 9999)
4736 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4737 rc
= RegCreateKeyEx(hClassKey
,
4741 REG_OPTION_NON_VOLATILE
,
4742 #if _WIN32_WINNT >= 0x502
4743 KEY_READ
| KEY_WRITE
,
4750 if (rc
!= ERROR_SUCCESS
)
4755 if (Disposition
== REG_CREATED_NEW_KEY
)
4758 hKey
= INVALID_HANDLE_VALUE
;
4763 /* Unable to create more than 9999 devices within the same class */
4764 SetLastError(ERROR_GEN_FAILURE
);
4768 /* Open device key, to write Driver value */
4769 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4770 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4772 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4773 if (rc
!= ERROR_SUCCESS
)
4780 /* Do installation of the specified section */
4783 FIXME("Need to install section %s in file %p\n",
4784 debugstr_w(InfSectionName
), InfHandle
);
4790 RpcStringFreeW(&lpGuidString
);
4791 HeapFree(GetProcessHeap(), 0, DriverKey
);
4792 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4793 RegCloseKey(hHWProfileKey
);
4794 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4795 RegCloseKey(hEnumKey
);
4796 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4797 RegCloseKey(hClassKey
);
4798 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4799 RegCloseKey(hDeviceKey
);
4800 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4804 TRACE("Returning 0x%p\n", ret
);
4808 /***********************************************************************
4809 * SetupDiOpenDevRegKey (SETUPAPI.@)
4811 HKEY WINAPI
SetupDiOpenDevRegKey(
4812 HDEVINFO DeviceInfoSet
,
4813 PSP_DEVINFO_DATA DeviceInfoData
,
4819 struct DeviceInfoSet
*list
;
4820 HKEY ret
= INVALID_HANDLE_VALUE
;
4822 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4823 Scope
, HwProfile
, KeyType
, samDesired
);
4826 SetLastError(ERROR_INVALID_HANDLE
);
4827 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4828 SetLastError(ERROR_INVALID_HANDLE
);
4829 else if (!DeviceInfoData
)
4830 SetLastError(ERROR_INVALID_PARAMETER
);
4831 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4832 SetLastError(ERROR_INVALID_USER_BUFFER
);
4833 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4834 SetLastError(ERROR_INVALID_PARAMETER
);
4835 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4836 SetLastError(ERROR_INVALID_PARAMETER
);
4839 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4840 LPWSTR DriverKey
= NULL
;
4844 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4845 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4846 HKEY hKey
= INVALID_HANDLE_VALUE
;
4849 if (Scope
== DICS_FLAG_GLOBAL
)
4850 RootKey
= list
->HKLM
;
4851 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4853 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
4854 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4856 RootKey
= hHWProfileKey
;
4861 REGSTR_PATH_SYSTEMENUM
,
4865 if (rc
!= ERROR_SUCCESS
)
4872 deviceInfo
->DeviceName
,
4874 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4876 RegCloseKey(hEnumKey
);
4877 hEnumKey
= INVALID_HANDLE_VALUE
;
4878 if (rc
!= ERROR_SUCCESS
)
4883 if (KeyType
== DIREG_DEV
)
4885 /* We're done. Just return the hKey handle */
4889 /* Read the 'Driver' key */
4890 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
4891 if (rc
!= ERROR_SUCCESS
)
4896 else if (dwRegType
!= REG_SZ
)
4898 SetLastError(ERROR_GEN_FAILURE
);
4901 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4904 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4907 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4908 if (rc
!= ERROR_SUCCESS
)
4914 hKey
= INVALID_HANDLE_VALUE
;
4915 /* Need to open the driver key */
4918 REGSTR_PATH_CLASS_NT
,
4922 if (rc
!= ERROR_SUCCESS
)
4933 if (rc
!= ERROR_SUCCESS
)
4941 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4942 RegCloseKey(hHWProfileKey
);
4943 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4944 RegCloseKey(hEnumKey
);
4945 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4949 TRACE("Returning 0x%p\n", ret
);
4953 /***********************************************************************
4954 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
4956 BOOL WINAPI
SetupDiCreateDeviceInfoA(
4957 HDEVINFO DeviceInfoSet
,
4959 CONST GUID
*ClassGuid
,
4960 PCSTR DeviceDescription
,
4962 DWORD CreationFlags
,
4963 PSP_DEVINFO_DATA DeviceInfoData
)
4965 LPWSTR DeviceNameW
= NULL
;
4966 LPWSTR DeviceDescriptionW
= NULL
;
4973 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
4974 if (DeviceNameW
== NULL
) return FALSE
;
4976 if (DeviceDescription
)
4978 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
4979 if (DeviceDescriptionW
== NULL
)
4981 if (DeviceNameW
) MyFree(DeviceNameW
);
4986 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
4987 ClassGuid
, DeviceDescriptionW
,
4988 hwndParent
, CreationFlags
,
4991 if (DeviceNameW
) MyFree(DeviceNameW
);
4992 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
4997 /***********************************************************************
4998 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
5000 BOOL WINAPI
SetupDiCreateDeviceInfoW(
5001 HDEVINFO DeviceInfoSet
,
5003 CONST GUID
*ClassGuid
,
5004 PCWSTR DeviceDescription
,
5006 DWORD CreationFlags
,
5007 PSP_DEVINFO_DATA DeviceInfoData
)
5009 struct DeviceInfoSet
*list
;
5012 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
5013 debugstr_guid(ClassGuid
), DeviceDescription
,
5014 hwndParent
, CreationFlags
, DeviceInfoData
);
5017 SetLastError(ERROR_INVALID_HANDLE
);
5018 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5019 SetLastError(ERROR_INVALID_HANDLE
);
5020 else if (!ClassGuid
)
5021 SetLastError(ERROR_INVALID_PARAMETER
);
5022 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
5023 SetLastError(ERROR_CLASS_MISMATCH
);
5024 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
5026 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
5027 SetLastError(ERROR_INVALID_FLAGS
);
5031 SP_DEVINFO_DATA DevInfo
;
5033 if (CreationFlags
& DICD_GENERATE_ID
)
5035 /* Generate a new unique ID for this device */
5036 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5037 FIXME("not implemented\n");
5041 /* Device name is fully qualified. Try to open it */
5044 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
5045 rc
= SetupDiOpenDeviceInfoW(
5048 NULL
, /* hwndParent */
5049 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
5054 /* SetupDiOpenDeviceInfoW has already added
5055 * the device info to the device info set
5057 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
5059 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5061 struct DeviceInfoElement
*deviceInfo
;
5063 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
5065 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5067 if (!DeviceInfoData
)
5071 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
5073 SetLastError(ERROR_INVALID_USER_BUFFER
);
5077 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5078 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5079 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5088 TRACE("Returning %d\n", ret
);
5092 /***********************************************************************
5093 * Helper functions for SetupDiBuildDriverInfoList
5097 IN PLIST_ENTRY DriverListHead
,
5098 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5099 IN LPGUID ClassGuid
,
5100 IN INFCONTEXT ContextDevice
,
5101 IN
struct InfFileDetails
*InfFileDetails
,
5103 IN LPCWSTR ProviderName
,
5104 IN LPCWSTR ManufacturerName
,
5105 IN LPCWSTR MatchingId
,
5106 FILETIME DriverDate
,
5107 DWORDLONG DriverVersion
,
5110 struct DriverInfoElement
*driverInfo
= NULL
;
5111 HANDLE hFile
= INVALID_HANDLE_VALUE
;
5112 DWORD RequiredSize
= 128; /* Initial buffer size */
5113 BOOL Result
= FALSE
;
5114 PLIST_ENTRY PreviousEntry
;
5115 LPWSTR InfInstallSection
= NULL
;
5118 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
5121 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5124 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
5126 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
5127 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
5129 /* Copy InfFileName field */
5130 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
5131 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
5133 /* Fill InfDate field */
5134 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5135 GENERIC_READ, FILE_SHARE_READ,
5136 NULL, OPEN_EXISTING, 0, NULL);
5137 if (hFile == INVALID_HANDLE_VALUE)
5139 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5143 /* Fill SectionName field */
5144 Result
= SetupGetStringFieldW(
5147 driverInfo
->Details
.SectionName
, LINE_LEN
,
5152 /* Fill DrvDescription field */
5153 Result
= SetupGetStringFieldW(
5155 0, /* Field index */
5156 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
5159 /* Copy MatchingId information */
5162 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5163 if (!driverInfo
->MatchingId
)
5165 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5168 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5171 driverInfo
->MatchingId
= NULL
;
5173 /* Get inf install section */
5175 RequiredSize
= 128; /* Initial buffer size */
5176 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5177 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5179 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5180 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5181 if (!InfInstallSection
)
5183 Result
= SetupGetStringFieldW(
5185 1, /* Field index */
5186 InfInstallSection
, RequiredSize
,
5192 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
5193 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
5195 driverInfo
->DriverRank
= Rank
;
5196 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
5197 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5198 driverInfo
->Info
.DriverType
= DriverType
;
5199 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
5200 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
5201 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
5202 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
5203 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
5206 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
5207 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
5210 driverInfo
->Info
.ProviderName
[0] = '\0';
5211 driverInfo
->Info
.DriverDate
= DriverDate
;
5212 driverInfo
->Info
.DriverVersion
= DriverVersion
;
5213 ReferenceInfFile(InfFileDetails
);
5214 driverInfo
->InfFileDetails
= InfFileDetails
;
5216 /* Insert current driver in driver list, according to its rank */
5217 PreviousEntry
= DriverListHead
->Flink
;
5218 while (PreviousEntry
!= DriverListHead
)
5220 struct DriverInfoElement
*CurrentDriver
;
5221 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
5222 if (CurrentDriver
->DriverRank
> Rank
||
5223 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
5225 /* Insert before the current item */
5226 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
5229 PreviousEntry
= PreviousEntry
->Flink
;
5231 if (PreviousEntry
== DriverListHead
)
5233 /* Insert at the end of the list */
5234 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
5243 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
5244 HeapFree(GetProcessHeap(), 0, driverInfo
);
5246 if (hFile
!= INVALID_HANDLE_VALUE
)
5248 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5254 GetVersionInformationFromInfFile(
5256 OUT LPGUID ClassGuid
,
5257 OUT LPWSTR
* pProviderName
,
5258 OUT FILETIME
* DriverDate
,
5259 OUT DWORDLONG
* DriverVersion
)
5262 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5263 LPWSTR DriverVer
= NULL
;
5264 LPWSTR ProviderName
= NULL
;
5265 LPWSTR pComma
; /* Points into DriverVer */
5266 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5267 SYSTEMTIME SystemTime
;
5269 BOOL ret
= FALSE
; /* Final result */
5271 /* Get class Guid */
5272 if (!SetupGetLineTextW(
5275 L
"Version", L
"ClassGUID",
5276 guidW
, sizeof(guidW
),
5277 NULL
/* Required size */))
5281 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5282 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5284 SetLastError(ERROR_GEN_FAILURE
);
5288 /* Get provider name */
5289 Result
= SetupGetLineTextW(
5291 hInf
, L
"Version", L
"Provider",
5296 /* We know know the needed buffer size */
5297 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5300 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5303 Result
= SetupGetLineTextW(
5305 hInf
, L
"Version", L
"Provider",
5306 ProviderName
, RequiredSize
,
5311 *pProviderName
= ProviderName
;
5313 /* Read the "DriverVer" value */
5314 Result
= SetupGetLineTextW(
5316 hInf
, L
"Version", L
"DriverVer",
5321 /* We know know the needed buffer size */
5322 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5325 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5328 Result
= SetupGetLineTextW(
5330 hInf
, L
"Version", L
"DriverVer",
5331 DriverVer
, RequiredSize
,
5337 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5338 pComma
= wcschr(DriverVer
, ',');
5341 *pComma
= UNICODE_NULL
;
5342 pVersion
= pComma
+ 1;
5344 /* Get driver date version. Invalid date = 00/00/00 */
5345 memset(DriverDate
, 0, sizeof(FILETIME
));
5346 if (wcslen(DriverVer
) == 10
5347 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5348 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5350 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5351 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5352 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5353 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5354 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5355 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5357 /* Get driver version. Invalid version = 0.0.0.0 */
5361 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5362 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5363 LARGE_INTEGER fullVersion
;
5365 pMinor
= strchrW(pVersion
, '.');
5369 pRevision
= strchrW(++pMinor
, '.');
5370 Minor
= atoiW(pMinor
);
5375 pBuild
= strchrW(++pRevision
, '.');
5376 Revision
= atoiW(pRevision
);
5382 Build
= atoiW(pBuild
);
5384 Major
= atoiW(pVersion
);
5385 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5386 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5387 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5394 HeapFree(GetProcessHeap(), 0, ProviderName
);
5395 HeapFree(GetProcessHeap(), 0, DriverVer
);
5400 /***********************************************************************
5401 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5404 SetupDiBuildDriverInfoList(
5405 IN HDEVINFO DeviceInfoSet
,
5406 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5407 IN DWORD DriverType
)
5409 struct DeviceInfoSet
*list
;
5410 SP_DEVINSTALL_PARAMS_W InstallParams
;
5411 PVOID Buffer
= NULL
;
5412 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5413 LPWSTR ProviderName
= NULL
;
5414 LPWSTR ManufacturerName
= NULL
;
5415 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5416 LPWSTR HardwareIDs
= NULL
;
5417 LPWSTR CompatibleIDs
= NULL
;
5418 LPWSTR FullInfFileName
= NULL
;
5419 FILETIME DriverDate
;
5420 DWORDLONG DriverVersion
= 0;
5424 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5427 SetLastError(ERROR_INVALID_HANDLE
);
5428 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5429 SetLastError(ERROR_INVALID_HANDLE
);
5430 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5431 SetLastError(ERROR_INVALID_HANDLE
);
5432 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5433 SetLastError(ERROR_INVALID_PARAMETER
);
5434 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5435 SetLastError(ERROR_INVALID_PARAMETER
);
5436 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5437 SetLastError(ERROR_INVALID_USER_BUFFER
);
5442 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5443 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5447 if (DriverType
== SPDIT_COMPATDRIVER
)
5449 /* Get hardware IDs list */
5451 RequiredSize
= 512; /* Initial buffer size */
5452 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5453 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5455 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5456 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5459 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5462 Result
= SetupDiGetDeviceRegistryPropertyW(
5474 /* Get compatible IDs list */
5476 RequiredSize
= 512; /* Initial buffer size */
5477 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5478 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5480 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5481 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5484 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5487 Result
= SetupDiGetDeviceRegistryPropertyW(
5490 SPDRP_COMPATIBLEIDS
,
5492 (PBYTE
)CompatibleIDs
,
5495 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5497 /* No compatible ID for this device */
5498 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5499 CompatibleIDs
= NULL
;
5507 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5509 /* InstallParams.DriverPath contains the name of a .inf file */
5510 RequiredSize
= wcslen(InstallParams
.DriverPath
) + 2;
5511 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5514 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5517 wcscpy(Buffer
, InstallParams
.DriverPath
);
5518 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
5523 /* Enumerate .inf files */
5525 RequiredSize
= 32768; /* Initial buffer size */
5526 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5527 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5529 HeapFree(GetProcessHeap(), 0, Buffer
);
5530 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5534 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5537 Result
= SetupGetInfFileListW(
5538 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5540 Buffer
, RequiredSize
,
5543 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5545 /* No .inf file in specified directory. So, we should
5546 * success as we created an empty driver info list.
5555 LPWSTR pFullFilename
;
5557 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5559 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5560 if (!FullInfFileName
)
5562 pFullFilename
= &FullInfFileName
[0];
5564 else if (*InstallParams
.DriverPath
)
5567 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5570 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5571 if (!FullInfFileName
)
5573 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5576 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
5577 wcscat(FullInfFileName
, L
"\\");
5578 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
5582 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5583 if (!FullInfFileName
)
5585 pFullFilename
= &FullInfFileName
[0];
5588 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
5590 INFCONTEXT ContextManufacturer
, ContextDevice
;
5593 wcscpy(pFullFilename
, filename
);
5594 TRACE("Opening file %S\n", FullInfFileName
);
5596 currentInfFileDetails
= HeapAlloc(
5599 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
5600 if (!currentInfFileDetails
)
5602 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5603 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5605 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5606 ReferenceInfFile(currentInfFileDetails
);
5607 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5609 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5610 currentInfFileDetails
= NULL
;
5614 if (!GetVersionInformationFromInfFile(
5615 currentInfFileDetails
->hInf
,
5621 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5622 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5623 currentInfFileDetails
= NULL
;
5627 if (DriverType
== SPDIT_CLASSDRIVER
)
5629 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5630 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5636 /* Get the manufacturers list */
5637 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
5640 Result
= SetupGetStringFieldW(
5641 &ContextManufacturer
,
5642 0, /* Field index */
5647 /* We got the needed size for the buffer */
5648 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5649 if (!ManufacturerName
)
5651 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5654 Result
= SetupGetStringFieldW(
5655 &ContextManufacturer
,
5656 0, /* Field index */
5657 ManufacturerName
, RequiredSize
,
5660 /* Get manufacturer section name */
5661 Result
= SetupGetStringFieldW(
5662 &ContextManufacturer
,
5663 1, /* Field index */
5664 ManufacturerSection
, LINE_LEN
,
5668 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5669 /* Add (possible) extension to manufacturer section name */
5670 Result
= SetupDiGetActualSectionToInstallW(
5671 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5674 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
5675 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5680 if (DriverType
== SPDIT_CLASSDRIVER
)
5682 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5683 if (!AddDriverToList(
5684 &list
->DriverListHead
,
5688 currentInfFileDetails
,
5693 DriverDate
, DriverVersion
,
5699 else /* DriverType = SPDIT_COMPATDRIVER */
5701 /* 1. Get all fields */
5702 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5706 BOOL DriverAlreadyAdded
;
5708 for (i
= 2; i
<= FieldCount
; i
++)
5710 LPWSTR DeviceId
= NULL
;
5712 RequiredSize
= 128; /* Initial buffer size */
5713 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5714 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5716 HeapFree(GetProcessHeap(), 0, DeviceId
);
5717 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5720 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5723 Result
= SetupGetStringFieldW(
5726 DeviceId
, RequiredSize
,
5731 HeapFree(GetProcessHeap(), 0, DeviceId
);
5734 DriverAlreadyAdded
= FALSE
;
5735 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5737 if (wcsicmp(DeviceId
, currentId
) == 0)
5740 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5744 currentInfFileDetails
,
5749 DriverDate
, DriverVersion
,
5750 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5751 DriverAlreadyAdded
= TRUE
;
5756 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5758 if (wcsicmp(DeviceId
, currentId
) == 0)
5761 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5765 currentInfFileDetails
,
5770 DriverDate
, DriverVersion
,
5771 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5772 DriverAlreadyAdded
= TRUE
;
5776 HeapFree(GetProcessHeap(), 0, DeviceId
);
5779 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5782 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5783 ManufacturerName
= NULL
;
5784 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5789 HeapFree(GetProcessHeap(), 0, ProviderName
);
5790 ProviderName
= NULL
;
5792 DereferenceInfFile(currentInfFileDetails
);
5793 currentInfFileDetails
= NULL
;
5804 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5805 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5809 InstallParams
.Flags
|= DI_DIDCLASS
;
5810 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5812 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5815 HeapFree(GetProcessHeap(), 0, ProviderName
);
5816 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5817 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5818 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5819 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5820 if (currentInfFileDetails
)
5821 DereferenceInfFile(currentInfFileDetails
);
5822 HeapFree(GetProcessHeap(), 0, Buffer
);
5824 TRACE("Returning %d\n", ret
);
5828 /***********************************************************************
5829 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5832 SetupDiDeleteDeviceInfo(
5833 IN HDEVINFO DeviceInfoSet
,
5834 IN PSP_DEVINFO_DATA DeviceInfoData
)
5836 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5838 FIXME("not implemented\n");
5839 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5844 /***********************************************************************
5845 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5848 SetupDiDestroyDriverInfoList(
5849 IN HDEVINFO DeviceInfoSet
,
5850 IN PSP_DEVINFO_DATA DeviceInfoData
,
5851 IN DWORD DriverType
)
5853 struct DeviceInfoSet
*list
;
5856 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5859 SetLastError(ERROR_INVALID_HANDLE
);
5860 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5861 SetLastError(ERROR_INVALID_HANDLE
);
5862 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5863 SetLastError(ERROR_INVALID_PARAMETER
);
5864 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5865 SetLastError(ERROR_INVALID_PARAMETER
);
5866 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5867 SetLastError(ERROR_INVALID_USER_BUFFER
);
5870 PLIST_ENTRY ListEntry
;
5871 struct DriverInfoElement
*driverInfo
;
5872 SP_DEVINSTALL_PARAMS_W InstallParams
;
5874 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5875 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5878 if (!DeviceInfoData
)
5879 /* Fall back to destroying class driver list */
5880 DriverType
= SPDIT_CLASSDRIVER
;
5882 if (DriverType
== SPDIT_CLASSDRIVER
)
5884 while (!IsListEmpty(&list
->DriverListHead
))
5886 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
5887 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5888 DestroyDriverInfoElement(driverInfo
);
5890 InstallParams
.Reserved
= 0;
5891 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
5892 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
5893 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
5897 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
5898 struct DeviceInfoElement
*deviceInfo
;
5900 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5901 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
5903 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5904 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
5906 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
5907 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5908 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
5910 InstallParamsSet
.Reserved
= 0;
5911 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
5913 DestroyDriverInfoElement(driverInfo
);
5915 InstallParams
.Reserved
= 0;
5916 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
5917 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
5918 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5923 TRACE("Returning %d\n", ret
);
5928 /***********************************************************************
5929 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
5932 SetupDiOpenDeviceInfoA(
5933 IN HDEVINFO DeviceInfoSet
,
5934 IN PCSTR DeviceInstanceId
,
5935 IN HWND hwndParent OPTIONAL
,
5937 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5939 LPWSTR DeviceInstanceIdW
= NULL
;
5942 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5944 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
5945 if (DeviceInstanceIdW
== NULL
)
5948 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
5949 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
5951 MyFree(DeviceInstanceIdW
);
5957 /***********************************************************************
5958 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
5961 SetupDiOpenDeviceInfoW(
5962 IN HDEVINFO DeviceInfoSet
,
5963 IN PCWSTR DeviceInstanceId
,
5964 IN HWND hwndParent OPTIONAL
,
5966 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5968 struct DeviceInfoSet
*list
;
5969 HKEY hEnumKey
, hKey
;
5973 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5975 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
5976 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
5979 SetLastError(ERROR_INVALID_HANDLE
);
5980 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5981 SetLastError(ERROR_INVALID_HANDLE
);
5982 else if (!DeviceInstanceId
)
5983 SetLastError(ERROR_INVALID_PARAMETER
);
5984 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
5986 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
5987 SetLastError(ERROR_INVALID_FLAGS
);
5989 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5990 SetLastError(ERROR_INVALID_USER_BUFFER
);
5993 struct DeviceInfoElement
*deviceInfo
= NULL
;
5994 /* Search if device already exists in DeviceInfoSet.
5995 * If yes, return the existing element
5996 * If no, create a new element using informations in registry
5998 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
5999 while (ItemList
!= &list
->ListHead
)
6004 FIXME("not implemented\n");
6005 ItemList
= ItemList
->Flink
;
6010 /* good one found */
6015 /* Open supposed registry key */
6018 REGSTR_PATH_SYSTEMENUM
,
6022 if (rc
!= ERROR_SUCCESS
)
6033 RegCloseKey(hEnumKey
);
6034 if (rc
!= ERROR_SUCCESS
)
6036 if (rc
== ERROR_FILE_NOT_FOUND
)
6037 rc
= ERROR_NO_SUCH_DEVINST
;
6042 /* FIXME: try to get ClassGUID from registry, instead of
6043 * sending GUID_NULL to CreateDeviceInfoElement
6045 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
6050 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
6056 if (ret
&& deviceInfo
&& DeviceInfoData
)
6058 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
6059 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
6060 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
6068 /***********************************************************************
6069 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6072 SetupDiEnumDriverInfoA(
6073 IN HDEVINFO DeviceInfoSet
,
6074 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6075 IN DWORD DriverType
,
6076 IN DWORD MemberIndex
,
6077 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6079 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6082 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6083 DriverType
, MemberIndex
, DriverInfoData
);
6085 if (DriverInfoData
== NULL
)
6086 SetLastError(ERROR_INVALID_PARAMETER
);
6087 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6088 SetLastError(ERROR_INVALID_USER_BUFFER
);
6091 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6092 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
6093 DriverType
, MemberIndex
, &driverInfoData2W
);
6097 /* Do W->A conversion */
6098 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6099 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6100 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6101 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6103 DriverInfoData
->Description
[0] = '\0';
6106 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6107 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6109 DriverInfoData
->MfgName
[0] = '\0';
6112 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6113 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6115 DriverInfoData
->ProviderName
[0] = '\0';
6118 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6120 /* Copy more fields */
6121 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6122 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6127 TRACE("Returning %d\n", ret
);
6132 /***********************************************************************
6133 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6136 SetupDiEnumDriverInfoW(
6137 IN HDEVINFO DeviceInfoSet
,
6138 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6139 IN DWORD DriverType
,
6140 IN DWORD MemberIndex
,
6141 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6143 PLIST_ENTRY ListHead
;
6146 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6147 DriverType
, MemberIndex
, DriverInfoData
);
6149 if (!DeviceInfoSet
|| !DriverInfoData
)
6150 SetLastError(ERROR_INVALID_PARAMETER
);
6151 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6152 SetLastError(ERROR_INVALID_HANDLE
);
6153 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6154 SetLastError(ERROR_INVALID_HANDLE
);
6155 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6156 SetLastError(ERROR_INVALID_PARAMETER
);
6157 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
6158 SetLastError(ERROR_INVALID_PARAMETER
);
6159 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6160 SetLastError(ERROR_INVALID_PARAMETER
);
6161 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6162 SetLastError(ERROR_INVALID_USER_BUFFER
);
6165 struct DeviceInfoElement
*devInfo
= NULL
;
6166 PLIST_ENTRY ItemList
;
6168 devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6169 if (DriverType
== SPDIT_CLASSDRIVER
||
6170 (devInfo
&& devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
6172 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6176 ListHead
= &devInfo
->DriverListHead
;
6179 ItemList
= ListHead
->Flink
;
6180 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
6181 ItemList
= ItemList
->Flink
;
6182 if (ItemList
== ListHead
)
6183 SetLastError(ERROR_NO_MORE_ITEMS
);
6186 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
6189 &DriverInfoData
->DriverType
,
6190 &DrvInfo
->Info
.DriverType
,
6191 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6196 TRACE("Returning %d\n", ret
);
6201 /***********************************************************************
6202 * SetupDiGetSelectedDevice (SETUPAPI.@)
6205 SetupDiGetSelectedDevice(
6206 IN HDEVINFO DeviceInfoSet
,
6207 OUT PSP_DEVINFO_DATA DeviceInfoData
)
6209 struct DeviceInfoSet
*list
;
6212 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6215 SetLastError(ERROR_INVALID_HANDLE
);
6216 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6217 SetLastError(ERROR_INVALID_HANDLE
);
6218 else if (list
->SelectedDevice
== NULL
)
6219 SetLastError(ERROR_NO_DEVICE_SELECTED
);
6220 else if (!DeviceInfoData
)
6221 SetLastError(ERROR_INVALID_PARAMETER
);
6222 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6223 SetLastError(ERROR_INVALID_USER_BUFFER
);
6226 memcpy(&DeviceInfoData
->ClassGuid
,
6227 &list
->SelectedDevice
->ClassGuid
,
6229 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
6230 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
6234 TRACE("Returning %d\n", ret
);
6239 /***********************************************************************
6240 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6243 SetupDiGetSelectedDriverA(
6244 IN HDEVINFO DeviceInfoSet
,
6245 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6246 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6248 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6251 if (DriverInfoData
== NULL
)
6252 SetLastError(ERROR_INVALID_PARAMETER
);
6253 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6254 SetLastError(ERROR_INVALID_USER_BUFFER
);
6257 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6259 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
6265 /* Do W->A conversion */
6266 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6267 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6268 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6269 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6271 DriverInfoData
->Description
[0] = '\0';
6274 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6275 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6277 DriverInfoData
->MfgName
[0] = '\0';
6280 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6281 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6283 DriverInfoData
->ProviderName
[0] = '\0';
6286 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6288 /* Copy more fields */
6289 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6290 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6299 /***********************************************************************
6300 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6303 SetupDiGetSelectedDriverW(
6304 IN HDEVINFO DeviceInfoSet
,
6305 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6306 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6310 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6312 if (!DeviceInfoSet
|| !DriverInfoData
)
6313 SetLastError(ERROR_INVALID_PARAMETER
);
6314 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6315 SetLastError(ERROR_INVALID_HANDLE
);
6316 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6317 SetLastError(ERROR_INVALID_HANDLE
);
6318 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6319 SetLastError(ERROR_INVALID_USER_BUFFER
);
6320 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6321 SetLastError(ERROR_INVALID_USER_BUFFER
);
6324 SP_DEVINSTALL_PARAMS InstallParams
;
6326 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6327 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6329 struct DriverInfoElement
*driverInfo
;
6330 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6331 if (driverInfo
== NULL
)
6332 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6336 &DriverInfoData
->DriverType
,
6337 &driverInfo
->Info
.DriverType
,
6338 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6344 TRACE("Returning %d\n", ret
);
6349 /***********************************************************************
6350 * SetupDiSetSelectedDevice (SETUPAPI.@)
6353 SetupDiSetSelectedDevice(
6354 IN HDEVINFO DeviceInfoSet
,
6355 IN PSP_DEVINFO_DATA DeviceInfoData
)
6357 struct DeviceInfoSet
*list
;
6360 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6363 SetLastError(ERROR_INVALID_HANDLE
);
6364 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6365 SetLastError(ERROR_INVALID_HANDLE
);
6366 else if (!DeviceInfoData
)
6367 SetLastError(ERROR_INVALID_PARAMETER
);
6368 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6369 SetLastError(ERROR_INVALID_USER_BUFFER
);
6370 else if (DeviceInfoData
->Reserved
== 0)
6371 SetLastError(ERROR_INVALID_USER_BUFFER
);
6374 list
->SelectedDevice
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6378 TRACE("Returning %d\n", ret
);
6383 /***********************************************************************
6384 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6387 SetupDiSetSelectedDriverA(
6388 IN HDEVINFO DeviceInfoSet
,
6389 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6390 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6392 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6393 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6396 if (DriverInfoData
!= NULL
)
6398 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6399 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6401 SetLastError(ERROR_INVALID_PARAMETER
);
6405 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6406 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6408 if (DriverInfoDataW
.Reserved
== 0)
6410 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6412 /* convert the strings to unicode */
6413 if (!MultiByteToWideChar(CP_ACP
,
6415 DriverInfoData
->Description
,
6417 DriverInfoDataW
.Description
,
6419 !MultiByteToWideChar(CP_ACP
,
6421 DriverInfoData
->ProviderName
,
6423 DriverInfoDataW
.ProviderName
,
6430 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6433 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6437 if (ret
&& pDriverInfoDataW
!= NULL
)
6439 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6446 /***********************************************************************
6447 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6450 SetupDiSetSelectedDriverW(
6451 IN HDEVINFO DeviceInfoSet
,
6452 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6453 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6457 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6460 SetLastError(ERROR_INVALID_PARAMETER
);
6461 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6462 SetLastError(ERROR_INVALID_HANDLE
);
6463 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6464 SetLastError(ERROR_INVALID_HANDLE
);
6465 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6466 SetLastError(ERROR_INVALID_USER_BUFFER
);
6467 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6468 SetLastError(ERROR_INVALID_USER_BUFFER
);
6471 struct DriverInfoElement
**pDriverInfo
;
6472 PLIST_ENTRY ListHead
, ItemList
;
6476 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6477 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6481 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6482 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6485 if (!DriverInfoData
)
6487 *pDriverInfo
= NULL
;
6492 /* Search selected driver in list */
6493 ItemList
= ListHead
->Flink
;
6494 while (ItemList
!= ListHead
)
6496 if (DriverInfoData
->Reserved
!= 0)
6498 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6503 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6504 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
6505 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6506 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6507 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6513 if (ItemList
== ListHead
)
6514 SetLastError(ERROR_INVALID_PARAMETER
);
6517 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
6518 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6520 TRACE("Choosing driver whose rank is 0x%lx\n",
6521 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
6523 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6528 TRACE("Returning %d\n", ret
);
6532 /***********************************************************************
6533 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6536 SetupDiGetDriverInfoDetailA(
6537 IN HDEVINFO DeviceInfoSet
,
6538 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6539 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6540 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6541 IN DWORD DriverInfoDetailDataSize
,
6542 OUT PDWORD RequiredSize OPTIONAL
)
6544 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6545 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6547 DWORD HardwareIDLen
= 0;
6550 /* do some sanity checks, the unicode version might do more thorough checks */
6551 if (DriverInfoData
== NULL
||
6552 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6553 (DriverInfoDetailData
!= NULL
&&
6554 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6555 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6557 SetLastError(ERROR_INVALID_PARAMETER
);
6561 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6562 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6564 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6566 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6568 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6572 SetLastError(ERROR_INVALID_PARAMETER
);
6575 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6576 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6578 /* convert the strings to unicode */
6579 if (MultiByteToWideChar(CP_ACP
,
6581 DriverInfoData
->Description
,
6583 DriverInfoDataW
.Description
,
6585 MultiByteToWideChar(CP_ACP
,
6587 DriverInfoData
->MfgName
,
6589 DriverInfoDataW
.MfgName
,
6591 MultiByteToWideChar(CP_ACP
,
6593 DriverInfoData
->ProviderName
,
6595 DriverInfoDataW
.ProviderName
,
6598 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6600 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6601 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6604 if (DriverInfoDetailData
!= NULL
)
6606 /* calculate the unicode buffer size from the ansi buffer size */
6607 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6608 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6609 (HardwareIDLen
* sizeof(WCHAR
));
6611 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6612 if (DriverInfoDetailDataW
== NULL
)
6614 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6618 /* initialize the buffer */
6619 ZeroMemory(DriverInfoDetailDataW
,
6621 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6624 /* call the unicode version */
6625 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6628 DriverInfoDetailDataW
,
6634 if (DriverInfoDetailDataW
!= NULL
)
6636 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6637 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6638 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6639 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6640 if (WideCharToMultiByte(CP_ACP
,
6642 DriverInfoDetailDataW
->SectionName
,
6644 DriverInfoDetailData
->SectionName
,
6648 WideCharToMultiByte(CP_ACP
,
6650 DriverInfoDetailDataW
->InfFileName
,
6652 DriverInfoDetailData
->InfFileName
,
6656 WideCharToMultiByte(CP_ACP
,
6658 DriverInfoDetailDataW
->DrvDescription
,
6660 DriverInfoDetailData
->DrvDescription
,
6664 WideCharToMultiByte(CP_ACP
,
6666 DriverInfoDetailDataW
->HardwareID
,
6668 DriverInfoDetailData
->HardwareID
,
6674 DWORD hwidlen
= HardwareIDLen
;
6675 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6677 /* count the strings in the list */
6680 len
= lstrlenA(s
) + 1;
6689 /* looks like the string list wasn't terminated... */
6690 SetLastError(ERROR_INVALID_USER_BUFFER
);
6696 /* make sure CompatIDsOffset points to the second string in the
6700 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6701 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6702 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6706 DriverInfoDetailData
->CompatIDsOffset
= 0;
6707 DriverInfoDetailData
->CompatIDsLength
= 0;
6716 if (RequiredSize
!= NULL
)
6718 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6719 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6725 if (DriverInfoDetailDataW
!= NULL
)
6727 MyFree(DriverInfoDetailDataW
);
6733 /***********************************************************************
6734 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6737 SetupDiGetDriverInfoDetailW(
6738 IN HDEVINFO DeviceInfoSet
,
6739 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6740 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6741 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6742 IN DWORD DriverInfoDetailDataSize
,
6743 OUT PDWORD RequiredSize OPTIONAL
)
6747 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6748 DriverInfoData
, DriverInfoDetailData
,
6749 DriverInfoDetailDataSize
, RequiredSize
);
6752 SetLastError(ERROR_INVALID_PARAMETER
);
6753 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6754 SetLastError(ERROR_INVALID_HANDLE
);
6755 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6756 SetLastError(ERROR_INVALID_HANDLE
);
6757 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6758 SetLastError(ERROR_INVALID_USER_BUFFER
);
6759 else if (!DriverInfoData
)
6760 SetLastError(ERROR_INVALID_PARAMETER
);
6761 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6762 SetLastError(ERROR_INVALID_PARAMETER
);
6763 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6764 SetLastError(ERROR_INVALID_PARAMETER
);
6765 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6766 SetLastError(ERROR_INVALID_USER_BUFFER
);
6767 else if (DriverInfoData
->Reserved
== 0)
6768 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6771 struct DriverInfoElement
*driverInfoElement
;
6772 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6775 DriverInfoDetailData
,
6776 &driverInfoElement
->Details
,
6777 driverInfoElement
->Details
.cbSize
);
6778 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6779 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6784 TRACE("Returning %d\n", ret
);
6788 /* Return the current hardware profile id, or -1 if error */
6790 GetCurrentHwProfile(
6791 IN HDEVINFO DeviceInfoSet
)
6793 HKEY hKey
= INVALID_HANDLE_VALUE
;
6794 DWORD dwRegType
, dwLength
;
6797 DWORD ret
= (DWORD
)-1;
6800 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
6801 REGSTR_PATH_IDCONFIGDB
,
6805 if (rc
!= ERROR_SUCCESS
)
6811 dwLength
= sizeof(DWORD
);
6812 rc
= RegQueryValueExW(
6814 REGSTR_VAL_CURRENTCONFIG
,
6817 (LPBYTE
)&hwProfile
, &dwLength
);
6818 if (rc
!= ERROR_SUCCESS
)
6823 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6825 SetLastError(ERROR_GEN_FAILURE
);
6832 if (hKey
!= INVALID_HANDLE_VALUE
)
6840 IN HDEVINFO DeviceInfoSet
,
6841 IN PSP_DEVINFO_DATA DeviceInfoData
)
6843 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6844 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6847 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
6849 /* At the moment, I only know how to start local devices */
6850 SetLastError(ERROR_INVALID_COMPUTERNAME
);
6854 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
6855 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6856 SetLastError(RtlNtStatusToDosError(Status
));
6857 return NT_SUCCESS(Status
);
6860 static BOOL
StopDevice(
6861 IN HDEVINFO DeviceInfoSet
,
6862 IN PSP_DEVINFO_DATA DeviceInfoData
)
6864 FIXME("Stub %p %p\n", DeviceInfoSet
, DeviceInfoData
);
6868 /***********************************************************************
6869 * SetupDiChangeState (SETUPAPI.@)
6873 IN HDEVINFO DeviceInfoSet
,
6874 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6876 PSP_PROPCHANGE_PARAMS PropChange
;
6877 HKEY hKey
= INVALID_HANDLE_VALUE
;
6878 LPCWSTR RegistryValueName
;
6879 DWORD dwConfigFlags
, dwLength
, dwRegType
;
6883 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6885 if (!DeviceInfoData
)
6886 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
6888 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
6891 SetLastError(ERROR_INVALID_PARAMETER
);
6895 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
6896 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
6898 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
6900 switch (PropChange
->StateChange
)
6905 /* Enable/disable device in registry */
6906 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
6907 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6908 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
6909 if (hKey
== INVALID_HANDLE_VALUE
)
6911 dwLength
= sizeof(DWORD
);
6912 rc
= RegQueryValueExW(
6917 (LPBYTE
)&dwConfigFlags
, &dwLength
);
6918 if (rc
== ERROR_FILE_NOT_FOUND
)
6920 else if (rc
!= ERROR_SUCCESS
)
6925 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6927 SetLastError(ERROR_GEN_FAILURE
);
6930 if (PropChange
->StateChange
== DICS_ENABLE
)
6931 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6933 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6939 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
6940 if (rc
!= ERROR_SUCCESS
)
6946 /* Enable/disable device if needed */
6947 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
6948 || PropChange
->HwProfile
== 0
6949 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
6951 if (PropChange
->StateChange
== DICS_ENABLE
)
6952 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6954 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
6960 case DICS_PROPCHANGE
:
6962 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6967 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
6968 SetLastError(ERROR_NOT_SUPPORTED
);
6973 if (hKey
!= INVALID_HANDLE_VALUE
)
6976 TRACE("Returning %d\n", ret
);
6980 /***********************************************************************
6981 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
6984 SetupDiSelectBestCompatDrv(
6985 IN HDEVINFO DeviceInfoSet
,
6986 IN PSP_DEVINFO_DATA DeviceInfoData
)
6988 SP_DRVINFO_DATA_W drvInfoData
;
6991 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6993 /* Drivers are sorted by rank in the driver list, so
6994 * the first driver in the list is the best one.
6996 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
6997 ret
= SetupDiEnumDriverInfoW(
7001 0, /* Member index */
7006 ret
= SetupDiSetSelectedDriverW(
7012 TRACE("Returning %d\n", ret
);
7016 /***********************************************************************
7017 * SetupDiInstallDriverFiles (SETUPAPI.@)
7020 SetupDiInstallDriverFiles(
7021 IN HDEVINFO DeviceInfoSet
,
7022 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7026 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7029 SetLastError(ERROR_INVALID_PARAMETER
);
7030 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7031 SetLastError(ERROR_INVALID_HANDLE
);
7032 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7033 SetLastError(ERROR_INVALID_HANDLE
);
7034 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7035 SetLastError(ERROR_INVALID_USER_BUFFER
);
7036 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
7037 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7038 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
7039 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7042 SP_DEVINSTALL_PARAMS_W InstallParams
;
7043 struct DriverInfoElement
*SelectedDriver
;
7044 WCHAR SectionName
[MAX_PATH
];
7045 DWORD SectionNameLength
= 0;
7046 PVOID InstallMsgHandler
;
7047 PVOID InstallMsgHandlerContext
;
7048 PVOID Context
= NULL
;
7050 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7051 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7055 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7056 if (!SelectedDriver
)
7058 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7062 ret
= SetupDiGetActualSectionToInstallW(
7063 SelectedDriver
->InfFileDetails
->hInf
,
7064 SelectedDriver
->Details
.SectionName
,
7065 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
7069 if (InstallParams
.InstallMsgHandler
)
7071 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
7072 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
7076 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7079 InstallMsgHandler
= SetupDefaultQueueCallback
;
7080 InstallMsgHandlerContext
= Context
;
7082 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7083 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7084 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7085 InstallMsgHandler
, InstallMsgHandlerContext
,
7086 DeviceInfoSet
, DeviceInfoData
);
7090 /* Install files from .CoInstallers section */
7091 lstrcatW(SectionName
, DotCoInstallers
);
7092 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7093 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7094 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7095 InstallMsgHandler
, InstallMsgHandlerContext
,
7096 DeviceInfoSet
, DeviceInfoData
);
7100 /* Set the DI_NOFILECOPY flag to prevent another
7101 * installation during SetupDiInstallDevice */
7102 InstallParams
.Flags
|= DI_NOFILECOPY
;
7103 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7107 SetupTermDefaultQueueCallback(Context
);
7111 TRACE("Returning %d\n", ret
);
7115 /***********************************************************************
7116 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7119 SetupDiRegisterCoDeviceInstallers(
7120 IN HDEVINFO DeviceInfoSet
,
7121 IN PSP_DEVINFO_DATA DeviceInfoData
)
7123 BOOL ret
= FALSE
; /* Return value */
7125 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7128 SetLastError(ERROR_INVALID_PARAMETER
);
7129 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7130 SetLastError(ERROR_INVALID_HANDLE
);
7131 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7132 SetLastError(ERROR_INVALID_HANDLE
);
7133 else if (!DeviceInfoData
)
7134 SetLastError(ERROR_INVALID_PARAMETER
);
7135 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7136 SetLastError(ERROR_INVALID_USER_BUFFER
);
7139 SP_DEVINSTALL_PARAMS_W InstallParams
;
7140 struct DriverInfoElement
*SelectedDriver
;
7143 WCHAR SectionName
[MAX_PATH
];
7144 DWORD SectionNameLength
= 0;
7145 HKEY hKey
= INVALID_HANDLE_VALUE
;
7146 PVOID Context
= NULL
;
7148 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7149 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7153 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7154 if (SelectedDriver
== NULL
)
7156 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7160 /* Get .CoInstallers section name */
7161 Result
= SetupDiGetActualSectionToInstallW(
7162 SelectedDriver
->InfFileDetails
->hInf
,
7163 SelectedDriver
->Details
.SectionName
,
7164 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7165 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
7167 lstrcatW(SectionName
, DotCoInstallers
);
7169 /* Open/Create driver key information */
7170 #if _WIN32_WINNT >= 0x502
7171 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7173 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7175 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7176 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7177 if (hKey
== INVALID_HANDLE_VALUE
)
7180 /* Install .CoInstallers section */
7181 DoAction
= SPINST_REGISTRY
;
7182 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7184 DoAction
|= SPINST_FILES
;
7185 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7189 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7190 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7191 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7192 SetupDefaultQueueCallback
, Context
,
7193 DeviceInfoSet
, DeviceInfoData
);
7201 SetupTermDefaultQueueCallback(Context
);
7202 if (hKey
!= INVALID_HANDLE_VALUE
)
7206 TRACE("Returning %d\n", ret
);
7211 InstallOneInterface(
7212 IN LPGUID InterfaceGuid
,
7213 IN LPCWSTR ReferenceString
,
7214 IN LPCWSTR InterfaceSection
,
7215 IN UINT InterfaceFlags
)
7217 if (InterfaceFlags
!= 0)
7219 SetLastError(ERROR_INVALID_PARAMETER
);
7223 FIXME("Need to AddInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid
),
7224 debugstr_w(ReferenceString
), debugstr_w(InterfaceSection
), InterfaceFlags
);
7228 /***********************************************************************
7229 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7232 SetupDiInstallDeviceInterfaces(
7233 IN HDEVINFO DeviceInfoSet
,
7234 IN PSP_DEVINFO_DATA DeviceInfoData
)
7236 struct DeviceInfoSet
*list
= NULL
;
7239 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7242 SetLastError(ERROR_INVALID_PARAMETER
);
7243 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7244 SetLastError(ERROR_INVALID_HANDLE
);
7245 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7246 SetLastError(ERROR_INVALID_HANDLE
);
7247 else if (!DeviceInfoData
)
7248 SetLastError(ERROR_INVALID_PARAMETER
);
7249 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7250 SetLastError(ERROR_INVALID_USER_BUFFER
);
7253 struct DriverInfoElement
*SelectedDriver
;
7254 SP_DEVINSTALL_PARAMS_W InstallParams
;
7255 WCHAR SectionName
[MAX_PATH
];
7256 DWORD SectionNameLength
= 0;
7257 INFCONTEXT ContextInterface
;
7258 LPWSTR InterfaceGuidString
= NULL
;
7259 LPWSTR ReferenceString
= NULL
;
7260 LPWSTR InterfaceSection
= NULL
;
7261 UINT InterfaceFlags
;
7265 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7266 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7270 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7271 if (SelectedDriver
== NULL
)
7273 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7278 /* Get .Interfaces section name */
7279 Result
= SetupDiGetActualSectionToInstallW(
7280 SelectedDriver
->InfFileDetails
->hInf
,
7281 SelectedDriver
->Details
.SectionName
,
7282 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7283 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".Interfaces") - 1)
7285 wcscat(SectionName
, L
".Interfaces");
7288 Result
= SetupFindFirstLineW(
7289 SelectedDriver
->InfFileDetails
->hInf
,
7293 while (ret
&& Result
)
7295 ret
= GetStringField(&ContextInterface
, 1, &InterfaceGuidString
);
7298 else if (strlenW(InterfaceGuidString
) != MAX_GUID_STRING_LEN
- 1)
7300 SetLastError(ERROR_INVALID_PARAMETER
);
7305 InterfaceGuidString
[MAX_GUID_STRING_LEN
- 2] = '\0'; /* Replace the } by a NULL character */
7306 if (UuidFromStringW(&InterfaceGuidString
[1], &InterfaceGuid
) != RPC_S_OK
)
7308 /* Bad GUID, skip the entry */
7309 SetLastError(ERROR_INVALID_PARAMETER
);
7314 ret
= GetStringField(&ContextInterface
, 2, &ReferenceString
);
7318 ret
= GetStringField(&ContextInterface
, 3, &InterfaceSection
);
7322 ret
= SetupGetIntField(
7324 4, /* Field index */
7328 if (GetLastError() == ERROR_INVALID_PARAMETER
)
7330 /* The field may be empty. Ignore the error */
7338 /* Install Interface */
7339 ret
= InstallOneInterface(&InterfaceGuid
, ReferenceString
, InterfaceSection
, InterfaceFlags
);
7342 MyFree(InterfaceGuidString
);
7343 MyFree(ReferenceString
);
7344 MyFree(InterfaceSection
);
7345 InterfaceGuidString
= ReferenceString
= InterfaceSection
= NULL
;
7346 Result
= SetupFindNextMatchLineW(&ContextInterface
, L
"AddInterface", &ContextInterface
);
7350 TRACE("Returning %d\n", ret
);
7355 InfIsFromOEMLocation(
7357 OUT LPBOOL IsOEMLocation
)
7361 last
= strrchrW(FullName
, '\\');
7364 /* No directory specified */
7365 *IsOEMLocation
= FALSE
;
7369 WCHAR Windir
[MAX_PATH
];
7372 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
7373 if (ret
== 0 || ret
>= MAX_PATH
)
7375 SetLastError(ERROR_GEN_FAILURE
);
7379 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
7381 /* The path is %SYSTEMROOT%\Inf */
7382 *IsOEMLocation
= FALSE
;
7386 /* The file is in another place */
7387 *IsOEMLocation
= TRUE
;
7393 /***********************************************************************
7394 * SetupDiInstallDevice (SETUPAPI.@)
7397 SetupDiInstallDevice(
7398 IN HDEVINFO DeviceInfoSet
,
7399 IN PSP_DEVINFO_DATA DeviceInfoData
)
7401 SP_DEVINSTALL_PARAMS_W InstallParams
;
7402 struct DriverInfoElement
*SelectedDriver
;
7403 SYSTEMTIME DriverDate
;
7404 WCHAR SectionName
[MAX_PATH
];
7406 DWORD SectionNameLength
= 0;
7407 BOOL Result
= FALSE
;
7410 LPWSTR pSectionName
= NULL
;
7411 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
7413 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
7414 BOOL RebootRequired
= FALSE
;
7415 HKEY hKey
= INVALID_HANDLE_VALUE
;
7416 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
7417 BOOL NeedtoCopyFile
;
7418 LARGE_INTEGER fullVersion
;
7420 PVOID Context
= NULL
;
7421 BOOL ret
= FALSE
; /* Return value */
7423 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7426 SetLastError(ERROR_INVALID_PARAMETER
);
7427 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7428 SetLastError(ERROR_INVALID_HANDLE
);
7429 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7430 SetLastError(ERROR_INVALID_HANDLE
);
7431 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7432 SetLastError(ERROR_INVALID_USER_BUFFER
);
7438 /* One parameter is bad */
7442 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7443 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7447 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
7449 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
7453 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7454 if (SelectedDriver
== NULL
)
7456 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7460 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
7462 Result
= SetupDiGetActualSectionToInstallW(
7463 SelectedDriver
->InfFileDetails
->hInf
,
7464 SelectedDriver
->Details
.SectionName
,
7465 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7466 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(DotServices
))
7468 pSectionName
= &SectionName
[wcslen(SectionName
)];
7470 /* Get information from [Version] section */
7471 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
7473 /* Format ClassGuid to a string */
7474 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
7476 RequiredSize
= lstrlenW(lpGuidString
);
7477 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
7478 if (!lpFullGuidString
)
7480 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7483 lpFullGuidString
[0] = '{';
7484 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
7485 lpFullGuidString
[RequiredSize
+ 1] = '}';
7486 lpFullGuidString
[RequiredSize
+ 2] = '\0';
7488 /* Open/Create driver key information */
7489 #if _WIN32_WINNT >= 0x502
7490 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7492 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7494 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7495 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7496 if (hKey
== INVALID_HANDLE_VALUE
)
7499 /* Install main section */
7501 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7502 DoAction
|= SPINST_REGISTRY
;
7503 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7505 DoAction
|= SPINST_FILES
;
7506 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7510 *pSectionName
= '\0';
7511 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7512 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7513 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7514 SetupDefaultQueueCallback
, Context
,
7515 DeviceInfoSet
, DeviceInfoData
);
7518 InstallParams
.Flags
|= DI_NOFILECOPY
;
7519 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7521 /* Write information to driver key */
7522 *pSectionName
= UNICODE_NULL
;
7523 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
7524 TRACE("Write information to driver key\n");
7525 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7526 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7527 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7528 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
7529 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
7530 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
7531 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
7532 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
7533 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7534 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7535 if (rc
== ERROR_SUCCESS
)
7536 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7537 if (rc
== ERROR_SUCCESS
)
7538 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7539 if (rc
== ERROR_SUCCESS
)
7541 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7542 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7544 if (rc
== ERROR_SUCCESS
)
7545 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7546 if (rc
== ERROR_SUCCESS
)
7547 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7548 if (rc
== ERROR_SUCCESS
)
7549 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTIONEXT
, 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7550 if (rc
== ERROR_SUCCESS
)
7551 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7552 if (rc
== ERROR_SUCCESS
)
7553 rc
= RegSetValueEx(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7554 if (rc
!= ERROR_SUCCESS
)
7560 hKey
= INVALID_HANDLE_VALUE
;
7562 /* FIXME: Process .LogConfigOverride section */
7564 /* Install .Services section */
7565 wcscpy(pSectionName
, DotServices
);
7566 Result
= SetupInstallServicesFromInfSectionExW(
7567 SelectedDriver
->InfFileDetails
->hInf
,
7576 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
7577 RebootRequired
= TRUE
;
7579 /* Copy .inf file to Inf\ directory (if needed) */
7580 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7585 Result
= SetupCopyOEMInfW(
7586 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7589 SP_COPY_NOOVERWRITE
,
7595 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7596 * to release use of current InfFile */
7599 /* Open device registry key */
7600 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7601 if (hKey
== INVALID_HANDLE_VALUE
)
7604 /* Install .HW section */
7606 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7607 DoAction
|= SPINST_REGISTRY
;
7608 wcscpy(pSectionName
, L
".HW");
7609 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7610 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7611 DoAction
, hKey
, NULL
, 0,
7613 DeviceInfoSet
, DeviceInfoData
);
7617 /* Write information to enum key */
7618 TRACE("Write information to enum key\n");
7619 TRACE("Class : '%S'\n", ClassName
);
7620 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
7621 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7622 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
7623 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
7624 if (rc
== ERROR_SUCCESS
)
7625 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7626 if (rc
== ERROR_SUCCESS
)
7627 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7628 if (rc
== ERROR_SUCCESS
)
7629 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7630 if (rc
!= ERROR_SUCCESS
)
7636 /* Start the device */
7637 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7638 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7643 /* End of installation */
7644 if (hClassKey
!= INVALID_HANDLE_VALUE
)
7645 RegCloseKey(hClassKey
);
7646 if (hKey
!= INVALID_HANDLE_VALUE
)
7649 RpcStringFreeW(&lpGuidString
);
7650 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7652 SetupTermDefaultQueueCallback(Context
);
7653 TRACE("Returning %d\n", ret
);