2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005 Hervé Poussineau (hpoussin@reactos.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "setupapi_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
27 /* Unicode constants */
28 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class
[] = {'C','l','a','s','s',0};
30 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
31 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
32 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
33 static const WCHAR InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
34 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
35 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
37 /* FIXME: header mess */
38 DEFINE_GUID(GUID_NULL
,
39 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
41 (CALLBACK
* CLASS_INSTALL_PROC
) (
42 IN DI_FUNCTION InstallFunction
,
43 IN HDEVINFO DeviceInfoSet
,
44 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
46 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
47 IN HDEVINFO DeviceInfoSet
,
48 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
50 (CALLBACK
* COINSTALLER_PROC
) (
51 IN DI_FUNCTION InstallFunction
,
52 IN HDEVINFO DeviceInfoSet
,
53 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
54 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
56 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
57 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
58 IN LPFNADDPROPSHEETPAGE fAddFunc
,
61 (*UPDATE_CLASS_PARAM_HANDLER
) (
62 IN HDEVINFO DeviceInfoSet
,
63 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
64 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
65 IN DWORD ClassInstallParamsSize
);
67 struct CoInstallerElement
72 COINSTALLER_PROC Function
;
73 BOOL DoPostProcessing
;
78 PropertyChangeHandler(
79 IN HDEVINFO DeviceInfoSet
,
80 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
81 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
82 IN DWORD ClassInstallParamsSize
);
84 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
85 NULL
, /* DIF_SELECTDEVICE */
86 NULL
, /* DIF_INSTALLDEVICE */
87 NULL
, /* DIF_ASSIGNRESOURCES */
88 NULL
, /* DIF_PROPERTIES */
89 NULL
, /* DIF_REMOVE */
90 NULL
, /* DIF_FIRSTTIMESETUP */
91 NULL
, /* DIF_FOUNDDEVICE */
92 NULL
, /* DIF_SELECTCLASSDRIVERS */
93 NULL
, /* DIF_VALIDATECLASSDRIVERS */
94 NULL
, /* DIF_INSTALLCLASSDRIVERS */
95 NULL
, /* DIF_CALCDISKSPACE */
96 NULL
, /* DIF_DESTROYPRIVATEDATA */
97 NULL
, /* DIF_VALIDATEDRIVER */
98 NULL
, /* DIF_MOVEDEVICE */
99 NULL
, /* DIF_DETECT */
100 NULL
, /* DIF_INSTALLWIZARD */
101 NULL
, /* DIF_DESTROYWIZARDDATA */
102 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
103 NULL
, /* DIF_ENABLECLASS */
104 NULL
, /* DIF_DETECTVERIFY */
105 NULL
, /* DIF_INSTALLDEVICEFILES */
106 NULL
, /* DIF_UNREMOVE */
107 NULL
, /* DIF_SELECTBESTCOMPATDRV */
108 NULL
, /* DIF_ALLOW_INSTALL */
109 NULL
, /* DIF_REGISTERDEVICE */
110 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
111 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
112 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
113 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
114 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
115 NULL
, /* DIF_UNUSED1 */
116 NULL
, /* DIF_INSTALLINTERFACES */
117 NULL
, /* DIF_DETECTCANCEL */
118 NULL
, /* DIF_REGISTER_COINSTALLERS */
119 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
120 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
121 NULL
, /* DIF_RESERVED1 */
122 NULL
, /* DIF_TROUBLESHOOTER */
123 NULL
, /* DIF_POWERMESSAGEWAKE */
124 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
125 NULL
, /* DIF_UPDATEDRIVER_UI */
126 NULL
/* DIF_RESERVED2 */
129 /***********************************************************************
130 * SetupDiBuildClassInfoList (SETUPAPI.@)
132 BOOL WINAPI
SetupDiBuildClassInfoList(
134 LPGUID ClassGuidList
,
135 DWORD ClassGuidListSize
,
139 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
140 ClassGuidListSize
, RequiredSize
,
144 /***********************************************************************
145 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
147 BOOL WINAPI
SetupDiBuildClassInfoListExA(
149 LPGUID ClassGuidList
,
150 DWORD ClassGuidListSize
,
155 LPWSTR MachineNameW
= NULL
;
162 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
163 if (MachineNameW
== NULL
) return FALSE
;
166 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
167 ClassGuidListSize
, RequiredSize
,
168 MachineNameW
, Reserved
);
171 MyFree(MachineNameW
);
176 /***********************************************************************
177 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
179 BOOL WINAPI
SetupDiBuildClassInfoListExW(
181 LPGUID ClassGuidList
,
182 DWORD ClassGuidListSize
,
187 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
193 DWORD dwGuidListIndex
= 0;
195 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
196 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
198 if (RequiredSize
!= NULL
)
201 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
202 KEY_ENUMERATE_SUB_KEYS
,
206 if (hClassesKey
== INVALID_HANDLE_VALUE
)
211 for (dwIndex
= 0; ; dwIndex
++)
213 dwLength
= MAX_GUID_STRING_LEN
+ 1;
214 lError
= RegEnumKeyExW(hClassesKey
,
222 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
223 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
225 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
227 if (RegOpenKeyExW(hClassesKey
,
233 RegCloseKey(hClassesKey
);
237 if (!RegQueryValueExW(hClassKey
,
238 REGSTR_VAL_NOUSECLASS
,
244 TRACE("'NoUseClass' value found!\n");
245 RegCloseKey(hClassKey
);
249 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
250 (!RegQueryValueExW(hClassKey
,
251 REGSTR_VAL_NOINSTALLCLASS
,
257 TRACE("'NoInstallClass' value found!\n");
258 RegCloseKey(hClassKey
);
262 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
263 (!RegQueryValueExW(hClassKey
,
264 REGSTR_VAL_NODISPLAYCLASS
,
270 TRACE("'NoDisplayClass' value found!\n");
271 RegCloseKey(hClassKey
);
275 RegCloseKey(hClassKey
);
277 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
278 if (dwGuidListIndex
< ClassGuidListSize
)
280 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
284 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
286 UuidFromStringW(&szKeyName
[1],
287 &ClassGuidList
[dwGuidListIndex
]);
293 if (lError
!= ERROR_SUCCESS
)
297 RegCloseKey(hClassesKey
);
299 if (RequiredSize
!= NULL
)
300 *RequiredSize
= dwGuidListIndex
;
302 if (ClassGuidListSize
< dwGuidListIndex
)
304 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
311 /***********************************************************************
312 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
314 BOOL WINAPI
SetupDiClassGuidsFromNameA(
316 LPGUID ClassGuidList
,
317 DWORD ClassGuidListSize
,
320 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
321 ClassGuidListSize
, RequiredSize
,
325 /***********************************************************************
326 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
328 BOOL WINAPI
SetupDiClassGuidsFromNameW(
330 LPGUID ClassGuidList
,
331 DWORD ClassGuidListSize
,
334 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
335 ClassGuidListSize
, RequiredSize
,
339 /***********************************************************************
340 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
342 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
344 LPGUID ClassGuidList
,
345 DWORD ClassGuidListSize
,
350 LPWSTR ClassNameW
= NULL
;
351 LPWSTR MachineNameW
= NULL
;
356 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
357 if (ClassNameW
== NULL
)
362 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
363 if (MachineNameW
== NULL
)
370 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
371 ClassGuidListSize
, RequiredSize
,
372 MachineNameW
, Reserved
);
375 MyFree(MachineNameW
);
382 /***********************************************************************
383 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
385 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
387 LPGUID ClassGuidList
,
388 DWORD ClassGuidListSize
,
393 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
394 WCHAR szClassName
[256];
400 DWORD dwGuidListIndex
= 0;
402 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
403 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
405 if (RequiredSize
!= NULL
)
408 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
409 KEY_ENUMERATE_SUB_KEYS
,
413 if (hClassesKey
== INVALID_HANDLE_VALUE
)
418 for (dwIndex
= 0; ; dwIndex
++)
420 dwLength
= MAX_GUID_STRING_LEN
+ 1;
421 lError
= RegEnumKeyExW(hClassesKey
,
429 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
430 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
432 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
434 if (RegOpenKeyExW(hClassesKey
,
440 RegCloseKey(hClassesKey
);
444 dwLength
= 256 * sizeof(WCHAR
);
445 if (!RegQueryValueExW(hClassKey
,
452 TRACE("Class name: %s\n", debugstr_w(szClassName
));
454 if (strcmpiW(szClassName
, ClassName
) == 0)
456 TRACE("Found matching class name\n");
458 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
459 if (dwGuidListIndex
< ClassGuidListSize
)
461 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
465 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
467 UuidFromStringW(&szKeyName
[1],
468 &ClassGuidList
[dwGuidListIndex
]);
475 RegCloseKey(hClassKey
);
478 if (lError
!= ERROR_SUCCESS
)
482 RegCloseKey(hClassesKey
);
484 if (RequiredSize
!= NULL
)
485 *RequiredSize
= dwGuidListIndex
;
487 if (ClassGuidListSize
< dwGuidListIndex
)
489 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
496 /***********************************************************************
497 * SetupDiClassNameFromGuidA (SETUPAPI.@)
499 BOOL WINAPI
SetupDiClassNameFromGuidA(
500 const GUID
* ClassGuid
,
505 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
506 ClassNameSize
, RequiredSize
,
510 /***********************************************************************
511 * SetupDiClassNameFromGuidW (SETUPAPI.@)
513 BOOL WINAPI
SetupDiClassNameFromGuidW(
514 const GUID
* ClassGuid
,
519 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
520 ClassNameSize
, RequiredSize
,
524 /***********************************************************************
525 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
527 BOOL WINAPI
SetupDiClassNameFromGuidExA(
528 const GUID
* ClassGuid
,
535 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
536 LPWSTR MachineNameW
= NULL
;
540 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
541 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
542 NULL
, MachineNameW
, Reserved
);
545 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
546 ClassNameSize
, NULL
, NULL
);
548 if (!ClassNameSize
&& RequiredSize
)
551 MyFree(MachineNameW
);
555 /***********************************************************************
556 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
558 BOOL WINAPI
SetupDiClassNameFromGuidExW(
559 const GUID
* ClassGuid
,
570 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
571 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
573 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
578 if (hKey
== INVALID_HANDLE_VALUE
)
583 if (RequiredSize
!= NULL
)
586 rc
= RegQueryValueExW(hKey
,
592 if (rc
!= ERROR_SUCCESS
)
599 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
602 dwLength
= ClassNameSize
* sizeof(WCHAR
);
603 rc
= RegQueryValueExW(hKey
,
609 if (rc
!= ERROR_SUCCESS
)
621 /***********************************************************************
622 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
625 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
628 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
631 /***********************************************************************
632 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
635 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
640 LPWSTR MachineNameW
= NULL
;
643 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
644 debugstr_a(MachineName
), Reserved
);
648 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
649 if (MachineNameW
== NULL
)
650 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
653 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
654 MachineNameW
, Reserved
);
657 MyFree(MachineNameW
);
663 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
667 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
668 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
669 case CR_SUCCESS
: return ERROR_SUCCESS
;
672 return ERROR_GEN_FAILURE
;
675 /* Does not happen */
678 /***********************************************************************
679 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
682 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
687 struct DeviceInfoSet
*list
;
688 LPWSTR UNCServerName
= NULL
;
692 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
694 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
695 debugstr_w(MachineName
), Reserved
);
697 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
699 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
700 list
= HeapAlloc(GetProcessHeap(), 0, size
);
703 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
706 memset(list
, 0, sizeof(struct DeviceInfoSet
));
708 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
711 ClassGuid
? ClassGuid
: &GUID_NULL
,
712 sizeof(list
->ClassGuid
));
713 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
714 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
715 list
->InstallParams
.hwndParent
= hwndParent
;
718 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
719 if (rc
!= ERROR_SUCCESS
)
724 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
727 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
731 strcpyW(UNCServerName
+ 2, MachineName
);
732 list
->szData
[0] = list
->szData
[1] = '\\';
733 strcpyW(list
->szData
+ 2, MachineName
);
734 list
->MachineName
= list
->szData
;
738 DWORD Size
= MAX_PATH
;
739 list
->HKLM
= HKEY_LOCAL_MACHINE
;
740 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
743 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
746 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
748 list
->MachineName
= NULL
;
751 UNCServerName
[0] = UNCServerName
[1] = '\\';
752 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
753 if (cr
!= CR_SUCCESS
)
755 SetLastError(GetErrorCodeFromCrCode(cr
));
759 InitializeListHead(&list
->DriverListHead
);
760 InitializeListHead(&list
->ListHead
);
762 ret
= (HDEVINFO
)list
;
765 if (ret
== INVALID_HANDLE_VALUE
)
767 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
768 RegCloseKey(list
->HKLM
);
769 HeapFree(GetProcessHeap(), 0, list
);
771 HeapFree(GetProcessHeap(), 0, UNCServerName
);
775 /***********************************************************************
776 * SetupDiEnumDeviceInfo (SETUPAPI.@)
778 BOOL WINAPI
SetupDiEnumDeviceInfo(
779 HDEVINFO DeviceInfoSet
,
781 PSP_DEVINFO_DATA DeviceInfoData
)
785 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
787 SetLastError(ERROR_INVALID_PARAMETER
);
788 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
790 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
792 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
793 SetLastError(ERROR_INVALID_HANDLE
);
794 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
795 SetLastError(ERROR_INVALID_USER_BUFFER
);
798 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
799 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
800 ItemList
= ItemList
->Flink
;
801 if (ItemList
== &list
->ListHead
)
802 SetLastError(ERROR_NO_MORE_ITEMS
);
805 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
806 memcpy(&DeviceInfoData
->ClassGuid
,
809 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
810 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
816 SetLastError(ERROR_INVALID_HANDLE
);
820 /***********************************************************************
821 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
824 SetupDiGetActualSectionToInstallA(
826 IN PCSTR InfSectionName
,
827 OUT PSTR InfSectionWithExt OPTIONAL
,
828 IN DWORD InfSectionWithExtSize
,
829 OUT PDWORD RequiredSize OPTIONAL
,
830 OUT PSTR
*Extension OPTIONAL
)
832 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
833 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
837 /***********************************************************************
838 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
841 SetupDiGetActualSectionToInstallW(
843 IN PCWSTR InfSectionName
,
844 OUT PWSTR InfSectionWithExt OPTIONAL
,
845 IN DWORD InfSectionWithExtSize
,
846 OUT PDWORD RequiredSize OPTIONAL
,
847 OUT PWSTR
*Extension OPTIONAL
)
849 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
850 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
854 /***********************************************************************
855 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
858 SetupDiGetActualSectionToInstallExA(
860 IN PCSTR InfSectionName
,
861 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
862 OUT PSTR InfSectionWithExt OPTIONAL
,
863 IN DWORD InfSectionWithExtSize
,
864 OUT PDWORD RequiredSize OPTIONAL
,
865 OUT PSTR
* Extension OPTIONAL
,
868 LPWSTR InfSectionNameW
= NULL
;
869 LPWSTR InfSectionWithExtW
= NULL
;
871 BOOL bResult
= FALSE
;
877 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
878 if (InfSectionNameW
== NULL
)
881 if (InfSectionWithExt
)
883 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
884 if (InfSectionWithExtW
== NULL
)
888 bResult
= SetupDiGetActualSectionToInstallExW(
889 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
890 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
891 InfSectionWithExtSize
,
893 Extension
? &ExtensionW
: NULL
,
896 if (bResult
&& InfSectionWithExt
)
898 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
899 InfSectionWithExtSize
, NULL
, NULL
) != 0;
901 if (bResult
&& Extension
)
903 if (ExtensionW
== NULL
)
906 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
910 MyFree(InfSectionNameW
);
911 MyFree(InfSectionWithExtW
);
916 /***********************************************************************
917 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
920 SetupDiGetActualSectionToInstallExW(
922 IN PCWSTR InfSectionName
,
923 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
924 OUT PWSTR InfSectionWithExt OPTIONAL
,
925 IN DWORD InfSectionWithExtSize
,
926 OUT PDWORD RequiredSize OPTIONAL
,
927 OUT PWSTR
* Extension OPTIONAL
,
932 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
933 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
934 RequiredSize
, Extension
, Reserved
);
936 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
937 SetLastError(ERROR_INVALID_HANDLE
);
938 else if (!InfSectionName
)
939 SetLastError(ERROR_INVALID_PARAMETER
);
940 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
941 SetLastError(ERROR_INVALID_USER_BUFFER
);
942 else if (Reserved
!= NULL
)
943 SetLastError(ERROR_INVALID_PARAMETER
);
946 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
947 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
948 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
949 WCHAR SectionName
[LINE_LEN
+ 1];
950 LONG lLineCount
= -1;
953 /* Fill platform info if needed */
954 if (AlternatePlatformInfo
)
955 pPlatformInfo
= AlternatePlatformInfo
;
956 else if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
958 /* That's the first time we go here. We need to fill in the structure */
959 OSVERSIONINFO VersionInfo
;
960 SYSTEM_INFO SystemInfo
;
961 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
962 ret
= GetVersionEx(&VersionInfo
);
965 GetSystemInfo(&SystemInfo
);
966 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
967 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
968 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
969 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
970 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
971 CurrentPlatform
.Reserved
= 0;
974 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
975 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
976 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
978 static const WCHAR ExtensionArchitectureNone
[] = {0};
979 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
980 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
981 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
983 /* Set various extensions values */
984 switch (pPlatformInfo
->Platform
)
986 case VER_PLATFORM_WIN32_WINDOWS
:
987 pExtensionPlatform
= ExtensionPlatformWindows
;
989 case VER_PLATFORM_WIN32_NT
:
990 pExtensionPlatform
= ExtensionPlatformNT
;
993 pExtensionPlatform
= ExtensionPlatformNone
;
996 switch (pPlatformInfo
->ProcessorArchitecture
)
998 case PROCESSOR_ARCHITECTURE_AMD64
:
999 pExtensionArchitecture
= ExtensionArchitectureamd64
;
1001 case PROCESSOR_ARCHITECTURE_INTEL
:
1002 pExtensionArchitecture
= ExtensionArchitecturex86
;
1004 case PROCESSOR_ARCHITECTURE_PPC
:
1005 pExtensionArchitecture
= ExtensionArchitectureppc
;
1008 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo
->ProcessorArchitecture
);
1009 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
1010 pExtensionArchitecture
= ExtensionArchitectureNone
;
1014 SectionName
[LINE_LEN
] = UNICODE_NULL
;
1016 /* Test with platform.architecture.major.minor extension */
1017 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s.%lu.%lu", InfSectionName
,
1018 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1019 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1020 if (lLineCount
!= -1) goto sectionfound
;
1022 /* Test with platform.major.minor extension */
1023 snprintfW(SectionName
, LINE_LEN
, L
"%s%s.%lu.%lu", InfSectionName
,
1024 pExtensionPlatform
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1025 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1026 if (lLineCount
!= -1) goto sectionfound
;
1028 /* Test with platform.architecture.major extension */
1029 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s.%lu", InfSectionName
,
1030 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
);
1031 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1032 if (lLineCount
!= -1) goto sectionfound
;
1034 /* Test with platform.major extension */
1035 snprintfW(SectionName
, LINE_LEN
, L
"%s%s.%lu", InfSectionName
,
1036 pExtensionPlatform
, pPlatformInfo
->MajorVersion
);
1037 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1038 if (lLineCount
!= -1) goto sectionfound
;
1040 /* Test with platform.architecture extension */
1041 snprintfW(SectionName
, LINE_LEN
, L
"%s%s%s", InfSectionName
,
1042 pExtensionPlatform
, pExtensionArchitecture
);
1043 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1044 if (lLineCount
!= -1) goto sectionfound
;
1046 /* Test with platform extension */
1047 snprintfW(SectionName
, LINE_LEN
, L
"%s%s", InfSectionName
,
1048 pExtensionPlatform
);
1049 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1050 if (lLineCount
!= -1) goto sectionfound
;
1052 /* Test without extension */
1053 snprintfW(SectionName
, LINE_LEN
, L
"%s", InfSectionName
);
1054 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1055 if (lLineCount
!= -1) goto sectionfound
;
1057 /* No appropriate section found */
1058 SetLastError(ERROR_INVALID_PARAMETER
);
1062 dwFullLength
= lstrlenW(SectionName
);
1063 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
1065 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
1067 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1071 lstrcpyW(InfSectionWithExt
, SectionName
);
1072 if (Extension
!= NULL
)
1074 DWORD dwLength
= lstrlenW(SectionName
);
1075 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1079 if (RequiredSize
!= NULL
)
1080 *RequiredSize
= dwFullLength
+ 1;
1086 TRACE("Returning %d\n", ret
);
1091 /***********************************************************************
1092 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1094 BOOL WINAPI
SetupDiGetClassDescriptionA(
1095 const GUID
* ClassGuid
,
1096 PSTR ClassDescription
,
1097 DWORD ClassDescriptionSize
,
1098 PDWORD RequiredSize
)
1100 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1101 ClassDescriptionSize
,
1102 RequiredSize
, NULL
, NULL
);
1105 /***********************************************************************
1106 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1108 BOOL WINAPI
SetupDiGetClassDescriptionW(
1109 const GUID
* ClassGuid
,
1110 PWSTR ClassDescription
,
1111 DWORD ClassDescriptionSize
,
1112 PDWORD RequiredSize
)
1114 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1115 ClassDescriptionSize
,
1116 RequiredSize
, NULL
, NULL
);
1119 /***********************************************************************
1120 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1122 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1123 const GUID
* ClassGuid
,
1124 PSTR ClassDescription
,
1125 DWORD ClassDescriptionSize
,
1126 PDWORD RequiredSize
,
1130 PWCHAR ClassDescriptionW
;
1131 LPWSTR MachineNameW
= NULL
;
1135 if (ClassDescriptionSize
> 0)
1137 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1138 if (!ClassDescriptionW
)
1140 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1146 ClassDescriptionW
= NULL
;
1150 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1153 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1159 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1160 NULL
, MachineNameW
, Reserved
);
1163 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1164 ClassDescriptionSize
, NULL
, NULL
);
1166 if (!ClassDescriptionSize
&& RequiredSize
)
1167 *RequiredSize
= len
;
1171 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1172 MyFree(MachineNameW
);
1176 /***********************************************************************
1177 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1179 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1180 const GUID
* ClassGuid
,
1181 PWSTR ClassDescription
,
1182 DWORD ClassDescriptionSize
,
1183 PDWORD RequiredSize
,
1190 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1191 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1193 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1198 if (hKey
== INVALID_HANDLE_VALUE
)
1200 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1204 if (RequiredSize
!= NULL
)
1207 if (RegQueryValueExW(hKey
,
1218 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1221 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1222 if (RegQueryValueExW(hKey
,
1226 (LPBYTE
)ClassDescription
,
1238 /***********************************************************************
1239 * SetupDiGetClassDevsA (SETUPAPI.@)
1241 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1247 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1248 flags
, NULL
, NULL
, NULL
);
1251 /***********************************************************************
1252 * SetupDiGetClassDevsW (SETUPAPI.@)
1254 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1260 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1261 flags
, NULL
, NULL
, NULL
);
1264 /***********************************************************************
1265 * SetupDiGetClassDevsExA (SETUPAPI.@)
1267 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1277 LPWSTR enumstrW
= NULL
;
1278 LPWSTR machineW
= NULL
;
1282 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1283 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1286 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1289 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1293 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1294 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1297 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1300 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1302 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1305 HeapFree(GetProcessHeap(), 0, enumstrW
);
1306 HeapFree(GetProcessHeap(), 0, machineW
);
1311 CreateDeviceInfoElement(
1312 IN
struct DeviceInfoSet
*list
,
1313 IN LPCWSTR InstancePath
,
1314 IN LPCGUID pClassGuid
,
1315 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1319 struct DeviceInfoElement
*deviceInfo
;
1321 *pDeviceInfo
= NULL
;
1323 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1324 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1327 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1330 memset(deviceInfo
, 0, size
);
1332 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1333 if (cr
!= CR_SUCCESS
)
1335 SetLastError(GetErrorCodeFromCrCode(cr
));
1339 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1340 wcscpy(deviceInfo
->Data
, InstancePath
);
1341 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1342 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1343 deviceInfo
->DeviceDescription
= NULL
;
1344 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1345 deviceInfo
->CreationFlags
= 0;
1346 InitializeListHead(&deviceInfo
->DriverListHead
);
1347 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1349 *pDeviceInfo
= deviceInfo
;
1354 CreateDeviceInterface(
1355 IN
struct DeviceInfoElement
* deviceInfo
,
1356 IN LPCWSTR SymbolicLink
,
1357 IN LPCGUID pInterfaceGuid
,
1358 OUT
struct DeviceInterface
**pDeviceInterface
)
1360 struct DeviceInterface
*deviceInterface
;
1362 *pDeviceInterface
= NULL
;
1364 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1365 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1366 if (!deviceInterface
)
1368 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1371 deviceInterface
->DeviceInfo
= deviceInfo
;
1372 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1373 deviceInterface
->Flags
= 0; /* FIXME */
1374 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1376 *pDeviceInterface
= deviceInterface
;
1380 static LONG
SETUP_CreateDevListFromEnumerator(
1381 struct DeviceInfoSet
*list
,
1382 LPCGUID pClassGuid OPTIONAL
,
1384 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1386 HKEY hDeviceIdKey
, hInstanceIdKey
;
1387 WCHAR KeyBuffer
[MAX_PATH
];
1388 WCHAR InstancePath
[MAX_PATH
];
1389 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1390 struct DeviceInfoElement
*deviceInfo
;
1392 DWORD dwLength
, dwRegType
;
1395 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1398 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1399 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1400 if (rc
== ERROR_NO_MORE_ITEMS
)
1402 if (rc
!= ERROR_SUCCESS
)
1406 /* Open device id sub key */
1407 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1408 if (rc
!= ERROR_SUCCESS
)
1410 wcscpy(InstancePath
, Enumerator
);
1411 wcscat(InstancePath
, L
"\\");
1412 wcscat(InstancePath
, KeyBuffer
);
1413 wcscat(InstancePath
, L
"\\");
1414 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1416 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1422 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1423 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1424 if (rc
== ERROR_NO_MORE_ITEMS
)
1426 if (rc
!= ERROR_SUCCESS
)
1428 RegCloseKey(hDeviceIdKey
);
1433 /* Open instance id sub key */
1434 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1435 if (rc
!= ERROR_SUCCESS
)
1437 RegCloseKey(hDeviceIdKey
);
1440 *pEndOfInstancePath
= '\0';
1441 wcscat(InstancePath
, KeyBuffer
);
1443 /* Read ClassGUID value */
1444 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1445 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1446 RegCloseKey(hInstanceIdKey
);
1447 if (rc
== ERROR_FILE_NOT_FOUND
)
1450 /* Skip this bad entry as we can't verify it */
1452 /* Set a default GUID for this device */
1453 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1455 else if (rc
!= ERROR_SUCCESS
)
1457 RegCloseKey(hDeviceIdKey
);
1460 else if (dwRegType
!= REG_SZ
)
1462 RegCloseKey(hDeviceIdKey
);
1463 return ERROR_GEN_FAILURE
;
1467 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1468 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1469 /* Bad GUID, skip the entry */
1473 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1475 /* Skip this entry as it is not the right device class */
1479 /* Add the entry to the list */
1480 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1482 RegCloseKey(hDeviceIdKey
);
1483 return GetLastError();
1485 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1486 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1488 RegCloseKey(hDeviceIdKey
);
1491 return ERROR_SUCCESS
;
1494 static LONG
SETUP_CreateDevList(
1495 struct DeviceInfoSet
*list
,
1496 PCWSTR MachineName OPTIONAL
,
1497 LPGUID
class OPTIONAL
,
1498 PCWSTR Enumerator OPTIONAL
)
1500 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1501 WCHAR KeyBuffer
[MAX_PATH
];
1506 if (class && IsEqualIID(class, &GUID_NULL
))
1510 if (MachineName
!= NULL
)
1512 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1513 if (rc
!= ERROR_SUCCESS
)
1517 HKLM
= HKEY_LOCAL_MACHINE
;
1519 rc
= RegOpenKeyExW(HKLM
,
1520 REGSTR_PATH_SYSTEMENUM
,
1522 KEY_ENUMERATE_SUB_KEYS
,
1524 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1525 if (rc
!= ERROR_SUCCESS
)
1528 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1529 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1538 KEY_ENUMERATE_SUB_KEYS
,
1540 RegCloseKey(hEnumKey
);
1541 if (rc
!= ERROR_SUCCESS
)
1543 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1544 RegCloseKey(hEnumeratorKey
);
1549 /* Enumerate enumerators */
1553 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1554 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1555 if (rc
== ERROR_NO_MORE_ITEMS
)
1557 if (rc
!= ERROR_SUCCESS
)
1559 RegCloseKey(hEnumKey
);
1565 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1566 if (rc
!= ERROR_SUCCESS
)
1568 RegCloseKey(hEnumKey
);
1572 /* Call SETUP_CreateDevListFromEnumerator */
1573 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1574 RegCloseKey(hEnumeratorKey
);
1575 if (rc
!= ERROR_SUCCESS
)
1577 RegCloseKey(hEnumKey
);
1581 RegCloseKey(hEnumKey
);
1582 return ERROR_SUCCESS
;
1587 static LONG
SETUP_CreateSerialDeviceList(
1588 struct DeviceInfoSet
*list
,
1590 LPGUID InterfaceGuid
,
1591 PCWSTR DeviceInstanceW
)
1593 static const size_t initialSize
= 100;
1595 WCHAR buf
[initialSize
];
1597 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1599 struct DeviceInfoElement
*deviceInfo
;
1602 WARN("'MachineName' is ignored on Wine!\n");
1603 if (DeviceInstanceW
)
1604 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1610 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1612 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1616 HeapFree(GetProcessHeap(), 0, devices
);
1617 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1619 return ERROR_NOT_ENOUGH_MEMORY
;
1625 HeapFree(GetProcessHeap(), 0, devices
);
1626 return GetLastError();
1630 /* 'devices' is a MULTI_SZ string */
1631 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1633 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1635 /* We have found a device */
1636 struct DeviceInterface
*interfaceInfo
;
1637 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1638 /* Step 1. Create a device info element */
1639 if (!CreateDeviceInfoElement(list
, ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1642 HeapFree(GetProcessHeap(), 0, devices
);
1643 return GetLastError();
1645 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1647 /* Step 2. Create an interface list for this element */
1648 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1651 HeapFree(GetProcessHeap(), 0, devices
);
1652 return GetLastError();
1654 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1658 HeapFree(GetProcessHeap(), 0, devices
);
1659 return ERROR_SUCCESS
;
1662 #else /* __REACTOS__ */
1664 static LONG
SETUP_CreateInterfaceList(
1665 struct DeviceInfoSet
*list
,
1667 LPGUID InterfaceGuid
,
1668 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1670 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1671 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1672 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1673 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1674 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1676 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1679 DWORD dwLength
, dwInstancePathLength
;
1682 struct DeviceInfoElement
*deviceInfo
;
1684 /* Open registry key related to this interface */
1685 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1686 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1687 return GetLastError();
1689 /* Enumerate sub keys of hInterfaceKey */
1693 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1694 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1695 if (rc
== ERROR_NO_MORE_ITEMS
)
1697 if (rc
!= ERROR_SUCCESS
)
1699 RegCloseKey(hInterfaceKey
);
1705 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1706 if (rc
!= ERROR_SUCCESS
)
1708 RegCloseKey(hInterfaceKey
);
1712 /* Read DeviceInstance */
1713 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1714 if (rc
!= ERROR_SUCCESS
)
1716 RegCloseKey(hDeviceInstanceKey
);
1717 RegCloseKey(hInterfaceKey
);
1720 if (dwRegType
!= REG_SZ
)
1722 RegCloseKey(hDeviceInstanceKey
);
1723 RegCloseKey(hInterfaceKey
);
1724 return ERROR_GEN_FAILURE
;
1726 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1729 RegCloseKey(hDeviceInstanceKey
);
1730 RegCloseKey(hInterfaceKey
);
1731 return ERROR_NOT_ENOUGH_MEMORY
;
1733 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1734 if (rc
!= ERROR_SUCCESS
)
1736 HeapFree(GetProcessHeap(), 0, InstancePath
);
1737 RegCloseKey(hDeviceInstanceKey
);
1738 RegCloseKey(hInterfaceKey
);
1741 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1742 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1744 if (DeviceInstanceW
)
1746 /* Check if device enumerator is not the right one */
1747 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1749 HeapFree(GetProcessHeap(), 0, InstancePath
);
1750 RegCloseKey(hDeviceInstanceKey
);
1755 /* Find class GUID associated to the device instance */
1758 REGSTR_PATH_SYSTEMENUM
,
1762 if (rc
!= ERROR_SUCCESS
)
1764 HeapFree(GetProcessHeap(), 0, InstancePath
);
1765 RegCloseKey(hDeviceInstanceKey
);
1766 RegCloseKey(hInterfaceKey
);
1775 RegCloseKey(hEnumKey
);
1776 if (rc
!= ERROR_SUCCESS
)
1778 HeapFree(GetProcessHeap(), 0, InstancePath
);
1779 RegCloseKey(hDeviceInstanceKey
);
1780 RegCloseKey(hInterfaceKey
);
1783 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1784 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1786 if (rc
!= ERROR_SUCCESS
)
1788 HeapFree(GetProcessHeap(), 0, InstancePath
);
1789 RegCloseKey(hDeviceInstanceKey
);
1790 RegCloseKey(hInterfaceKey
);
1793 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1794 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1795 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1797 HeapFree(GetProcessHeap(), 0, InstancePath
);
1798 RegCloseKey(hDeviceInstanceKey
);
1799 RegCloseKey(hInterfaceKey
);
1800 return ERROR_GEN_FAILURE
;
1802 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1804 /* If current device doesn't match the list GUID (if any), skip this entry */
1805 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1807 HeapFree(GetProcessHeap(), 0, InstancePath
);
1808 RegCloseKey(hDeviceInstanceKey
);
1812 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1816 LPWSTR pSymbolicLink
;
1817 struct DeviceInterface
*interfaceInfo
;
1819 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1820 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1821 if (rc
== ERROR_NO_MORE_ITEMS
)
1823 if (rc
!= ERROR_SUCCESS
)
1825 HeapFree(GetProcessHeap(), 0, InstancePath
);
1826 RegCloseKey(hDeviceInstanceKey
);
1827 RegCloseKey(hInterfaceKey
);
1831 if (KeyBuffer
[0] != '#')
1832 /* This entry doesn't represent an interesting entry */
1836 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1837 if (rc
!= ERROR_SUCCESS
)
1839 RegCloseKey(hDeviceInstanceKey
);
1840 RegCloseKey(hInterfaceKey
);
1844 /* Read SymbolicLink value */
1845 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1846 if (rc
!= ERROR_SUCCESS
)
1848 RegCloseKey(hReferenceKey
);
1849 RegCloseKey(hDeviceInstanceKey
);
1850 RegCloseKey(hInterfaceKey
);
1853 if (dwRegType
!= REG_SZ
)
1855 RegCloseKey(hReferenceKey
);
1856 RegCloseKey(hDeviceInstanceKey
);
1857 RegCloseKey(hInterfaceKey
);
1858 return ERROR_GEN_FAILURE
;
1861 /* We have found a device */
1862 /* Step 1. Create a device info element */
1863 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1865 RegCloseKey(hReferenceKey
);
1866 RegCloseKey(hDeviceInstanceKey
);
1867 RegCloseKey(hInterfaceKey
);
1868 return GetLastError();
1870 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1871 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1873 /* Step 2. Create an interface list for this element */
1874 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1877 RegCloseKey(hReferenceKey
);
1878 RegCloseKey(hDeviceInstanceKey
);
1879 RegCloseKey(hInterfaceKey
);
1880 return ERROR_NOT_ENOUGH_MEMORY
;
1882 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1883 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1884 RegCloseKey(hReferenceKey
);
1885 if (rc
!= ERROR_SUCCESS
)
1887 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1888 RegCloseKey(hDeviceInstanceKey
);
1889 RegCloseKey(hInterfaceKey
);
1892 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1894 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1895 RegCloseKey(hDeviceInstanceKey
);
1896 RegCloseKey(hInterfaceKey
);
1897 return GetLastError();
1899 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1900 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1901 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1903 RegCloseKey(hDeviceInstanceKey
);
1905 RegCloseKey(hInterfaceKey
);
1906 return ERROR_SUCCESS
;
1908 #endif /* __REACTOS__ */
1910 /***********************************************************************
1911 * SetupDiGetClassDevsExW (SETUPAPI.@)
1913 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1922 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1923 struct DeviceInfoSet
*list
;
1927 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1928 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1930 /* Create the deviceset if not set */
1933 list
= (struct DeviceInfoSet
*)deviceset
;
1934 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1936 SetLastError(ERROR_INVALID_HANDLE
);
1937 return INVALID_HANDLE_VALUE
;
1939 hDeviceInfo
= deviceset
;
1943 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1944 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1945 NULL
, machine
, NULL
);
1946 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1947 return INVALID_HANDLE_VALUE
;
1948 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1951 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1954 pClassGuid
= &list
->ClassGuid
;
1956 if (flags
& DIGCF_PRESENT
)
1957 FIXME(": flag DIGCF_PRESENT ignored\n");
1958 if (flags
& DIGCF_PROFILE
)
1959 FIXME(": flag DIGCF_PROFILE ignored\n");
1961 if (flags
& DIGCF_ALLCLASSES
)
1963 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1964 if (rc
!= ERROR_SUCCESS
)
1968 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1969 return INVALID_HANDLE_VALUE
;
1973 else if (flags
& DIGCF_DEVICEINTERFACE
)
1977 SetLastError(ERROR_INVALID_PARAMETER
);
1979 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1980 return INVALID_HANDLE_VALUE
;
1984 /* Special case: find serial ports by calling QueryDosDevice */
1985 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1986 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1987 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1988 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1991 ERR("Wine can only enumerate serial devices at the moment!\n");
1992 rc
= ERROR_INVALID_PARAMETER
;
1994 #else /* __REACTOS__ */
1995 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1996 #endif /* __REACTOS__ */
1997 if (rc
!= ERROR_SUCCESS
)
2001 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2002 return INVALID_HANDLE_VALUE
;
2008 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
2009 if (rc
!= ERROR_SUCCESS
)
2013 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2014 return INVALID_HANDLE_VALUE
;
2020 /***********************************************************************
2021 * SetupDiGetClassImageIndex (SETUPAPI.@)
2024 static BOOL
GetIconIndex(
2026 OUT PINT ImageIndex
)
2028 LPWSTR Buffer
= NULL
;
2029 DWORD dwRegType
, dwLength
;
2033 /* Read icon registry key */
2034 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
2035 if (rc
!= ERROR_SUCCESS
)
2039 } else if (dwRegType
!= REG_SZ
)
2041 SetLastError(ERROR_INVALID_INDEX
);
2044 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2047 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2050 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2051 if (rc
!= ERROR_SUCCESS
)
2056 /* make sure the returned buffer is NULL-terminated */
2057 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2059 /* Transform icon value to a INT */
2060 *ImageIndex
= atoiW(Buffer
);
2068 BOOL WINAPI
SetupDiGetClassImageIndex(
2069 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2070 IN CONST GUID
*ClassGuid
,
2071 OUT PINT ImageIndex
)
2073 struct ClassImageList
*list
;
2076 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2078 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2079 SetLastError(ERROR_INVALID_PARAMETER
);
2080 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2081 SetLastError(ERROR_INVALID_USER_BUFFER
);
2082 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2083 SetLastError(ERROR_INVALID_USER_BUFFER
);
2084 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2085 SetLastError(ERROR_INVALID_USER_BUFFER
);
2086 else if (!ImageIndex
)
2087 SetLastError(ERROR_INVALID_PARAMETER
);
2090 HKEY hKey
= INVALID_HANDLE_VALUE
;
2093 /* Read Icon registry entry into Buffer */
2094 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2095 if (hKey
== INVALID_HANDLE_VALUE
)
2097 if (!GetIconIndex(hKey
, &iconIndex
))
2102 SetLastError(ERROR_INVALID_INDEX
);
2106 *ImageIndex
= -iconIndex
;
2110 if (hKey
!= INVALID_HANDLE_VALUE
)
2114 TRACE("Returning %d\n", ret
);
2118 /***********************************************************************
2119 * SetupDiGetClassImageList(SETUPAPI.@)
2121 BOOL WINAPI
SetupDiGetClassImageList(
2122 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2124 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2127 /***********************************************************************
2128 * SetupDiGetClassImageListExA(SETUPAPI.@)
2130 BOOL WINAPI
SetupDiGetClassImageListExA(
2131 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2132 IN PCSTR MachineName OPTIONAL
,
2135 PWSTR MachineNameW
= NULL
;
2140 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2141 if (MachineNameW
== NULL
)
2145 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2148 MyFree(MachineNameW
);
2153 /***********************************************************************
2154 * SetupDiGetClassImageListExW(SETUPAPI.@)
2156 BOOL WINAPI
SetupDiGetClassImageListExW(
2157 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2158 IN PCWSTR MachineName OPTIONAL
,
2163 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2165 if (!ClassImageListData
)
2166 SetLastError(ERROR_INVALID_PARAMETER
);
2167 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2168 SetLastError(ERROR_INVALID_USER_BUFFER
);
2170 SetLastError(ERROR_INVALID_PARAMETER
);
2173 struct ClassImageList
*list
= NULL
;
2176 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2178 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
2179 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2182 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2185 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2188 list
->szData
[0] = list
->szData
[1] = '\\';
2189 strcpyW(list
->szData
+ 2, MachineName
);
2190 list
->MachineName
= list
->szData
;
2194 list
->MachineName
= NULL
;
2197 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2205 TRACE("Returning %d\n", ret
);
2209 /***********************************************************************
2210 * SetupDiLoadClassIcon(SETUPAPI.@)
2212 BOOL WINAPI
SetupDiLoadClassIcon(
2213 IN CONST GUID
*ClassGuid
,
2214 OUT HICON
*LargeIcon OPTIONAL
,
2215 OUT PINT MiniIconIndex OPTIONAL
)
2220 SetLastError(ERROR_INVALID_PARAMETER
);
2223 LPWSTR Buffer
= NULL
;
2226 HKEY hKey
= INVALID_HANDLE_VALUE
;
2228 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2229 if (hKey
== INVALID_HANDLE_VALUE
)
2232 if (!GetIconIndex(hKey
, &iconIndex
))
2237 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2240 DWORD dwRegType
, dwLength
;
2241 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2242 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2244 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2247 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2250 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2251 if (rc
!= ERROR_SUCCESS
)
2256 /* make sure the returned buffer is NULL-terminated */
2257 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2260 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2261 && dwRegType
== REG_SZ
)
2263 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2266 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2269 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2270 if (rc
!= ERROR_SUCCESS
)
2275 /* make sure the returned buffer is NULL-terminated */
2276 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2280 /* Unable to find where to load the icon */
2281 SetLastError(ERROR_FILE_NOT_FOUND
);
2284 Comma
= strchrW(Buffer
, ',');
2287 SetLastError(ERROR_GEN_FAILURE
);
2295 /* Look up icon in setupapi.dll */
2296 DllName
= L
"setupapi.dll";
2297 iconIndex
= -iconIndex
;
2300 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2303 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2305 SetLastError(ERROR_INVALID_INDEX
);
2310 *MiniIconIndex
= iconIndex
;
2314 if (hKey
!= INVALID_HANDLE_VALUE
)
2319 TRACE("Returning %d\n", ret
);
2323 /***********************************************************************
2324 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2326 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2327 HDEVINFO DeviceInfoSet
,
2328 PSP_DEVINFO_DATA DeviceInfoData
,
2329 CONST GUID
* InterfaceClassGuid
,
2331 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2335 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2336 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2338 if (!DeviceInterfaceData
)
2339 SetLastError(ERROR_INVALID_PARAMETER
);
2340 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2341 SetLastError(ERROR_INVALID_USER_BUFFER
);
2342 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2344 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2346 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2348 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2350 while (ItemList
!= &list
->ListHead
&& !Found
)
2352 PLIST_ENTRY InterfaceListEntry
;
2353 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2354 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2356 /* We are not searching for this element */
2357 ItemList
= ItemList
->Flink
;
2360 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2361 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2363 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2364 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2366 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2369 if (MemberIndex
-- == 0)
2371 /* return this item */
2372 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2373 &DevItf
->InterfaceClassGuid
,
2375 DeviceInterfaceData
->Flags
= 0; /* FIXME */
2376 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2379 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2381 ItemList
= ItemList
->Flink
;
2384 SetLastError(ERROR_NO_MORE_ITEMS
);
2389 SetLastError(ERROR_INVALID_HANDLE
);
2392 SetLastError(ERROR_INVALID_HANDLE
);
2396 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2398 InterlockedIncrement(&infFile
->References
);
2401 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2403 if (InterlockedDecrement(&infFile
->References
) == 0)
2405 SetupCloseInfFile(infFile
->hInf
);
2406 HeapFree(GetProcessHeap(), 0, infFile
);
2410 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2412 DereferenceInfFile(driverInfo
->InfFileDetails
);
2413 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2414 HeapFree(GetProcessHeap(), 0, driverInfo
);
2418 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2420 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2424 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2426 PLIST_ENTRY ListEntry
;
2427 struct DriverInfoElement
*driverInfo
;
2429 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2431 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2432 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2433 if (!DestroyDriverInfoElement(driverInfo
))
2436 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2438 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2439 HeapFree(GetProcessHeap(), 0, ListEntry
);
2441 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2442 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2446 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2448 PLIST_ENTRY ListEntry
;
2449 struct DeviceInfoElement
*deviceInfo
;
2451 while (!IsListEmpty(&list
->ListHead
))
2453 ListEntry
= RemoveHeadList(&list
->ListHead
);
2454 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2455 if (!DestroyDeviceInfoElement(deviceInfo
))
2458 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2459 RegCloseKey(list
->HKLM
);
2460 CM_Disconnect_Machine(list
->hMachine
);
2461 DestroyClassInstallParams(&list
->ClassInstallParams
);
2462 HeapFree(GetProcessHeap(), 0, list
);
2466 /***********************************************************************
2467 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2469 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2473 TRACE("%p\n", devinfo
);
2474 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2476 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2478 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2479 ret
= DestroyDeviceInfoSet(list
);
2481 SetLastError(ERROR_INVALID_HANDLE
);
2484 SetLastError(ERROR_INVALID_HANDLE
);
2486 TRACE("Returning %d\n", ret
);
2490 /***********************************************************************
2491 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2493 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2494 HDEVINFO DeviceInfoSet
,
2495 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2496 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2497 DWORD DeviceInterfaceDetailDataSize
,
2498 PDWORD RequiredSize
,
2499 PSP_DEVINFO_DATA DeviceInfoData
)
2501 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2502 DWORD sizeW
= 0, sizeA
;
2505 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2506 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2507 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2509 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2510 SetLastError(ERROR_INVALID_USER_BUFFER
);
2511 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2512 SetLastError(ERROR_INVALID_PARAMETER
);
2513 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2514 SetLastError(ERROR_INVALID_PARAMETER
);
2517 if (DeviceInterfaceDetailData
!= NULL
)
2519 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2520 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2521 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2522 if (!DeviceInterfaceDetailDataW
)
2524 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2527 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2529 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2530 ret
= SetupDiGetDeviceInterfaceDetailW(
2532 DeviceInterfaceData
,
2533 DeviceInterfaceDetailDataW
,
2537 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2538 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2540 *RequiredSize
= sizeA
;
2541 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2543 if (!WideCharToMultiByte(
2545 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2546 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2553 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2556 TRACE("Returning %d\n", ret
);
2560 /***********************************************************************
2561 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2563 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2564 HDEVINFO DeviceInfoSet
,
2565 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2566 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2567 DWORD DeviceInterfaceDetailDataSize
,
2568 PDWORD RequiredSize
,
2569 PSP_DEVINFO_DATA DeviceInfoData
)
2573 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2574 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2575 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2577 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2578 SetLastError(ERROR_INVALID_PARAMETER
);
2579 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2580 SetLastError(ERROR_INVALID_HANDLE
);
2581 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2582 SetLastError(ERROR_INVALID_HANDLE
);
2583 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2584 SetLastError(ERROR_INVALID_USER_BUFFER
);
2585 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2586 SetLastError(ERROR_INVALID_USER_BUFFER
);
2587 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2588 SetLastError(ERROR_INVALID_USER_BUFFER
);
2589 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2590 SetLastError(ERROR_INVALID_PARAMETER
);
2591 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2592 SetLastError(ERROR_INVALID_PARAMETER
);
2595 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2596 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2597 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2598 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2600 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2602 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2604 *RequiredSize
= sizeRequired
;
2608 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2609 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2612 memcpy(&DeviceInfoData
->ClassGuid
,
2613 &deviceInterface
->DeviceInfo
->ClassGuid
,
2615 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2616 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2622 TRACE("Returning %d\n", ret
);
2626 /***********************************************************************
2627 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2629 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2631 PSP_DEVINFO_DATA DeviceInfoData
,
2633 PDWORD PropertyRegDataType
,
2634 PBYTE PropertyBuffer
,
2635 DWORD PropertyBufferSize
,
2636 PDWORD RequiredSize
)
2639 BOOL bIsStringProperty
;
2641 DWORD RequiredSizeA
, RequiredSizeW
;
2642 DWORD PropertyBufferSizeW
;
2643 PBYTE PropertyBufferW
;
2645 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2646 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2649 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2650 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2652 bResult
= SetupDiGetDeviceRegistryPropertyW(
2658 PropertyBufferSizeW
,
2661 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2663 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2665 if (bIsStringProperty
)
2666 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2668 RequiredSizeA
= RequiredSizeW
;
2670 *RequiredSize
= RequiredSizeA
;
2671 if (PropertyRegDataType
)
2672 *PropertyRegDataType
= RegType
;
2677 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2681 if (RequiredSizeA
<= PropertyBufferSize
)
2683 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2685 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2687 /* Last error is already set by WideCharToMultiByte */
2692 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2696 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2700 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2704 /***********************************************************************
2705 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2707 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2708 HDEVINFO DeviceInfoSet
,
2709 PSP_DEVINFO_DATA DeviceInfoData
,
2711 PDWORD PropertyRegDataType
,
2712 PBYTE PropertyBuffer
,
2713 DWORD PropertyBufferSize
,
2714 PDWORD RequiredSize
)
2716 HKEY hEnumKey
, hKey
;
2720 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2721 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2724 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2725 SetLastError(ERROR_INVALID_HANDLE
);
2726 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2727 SetLastError(ERROR_INVALID_HANDLE
);
2728 else if (!DeviceInfoData
)
2729 SetLastError(ERROR_INVALID_PARAMETER
);
2730 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2731 SetLastError(ERROR_INVALID_USER_BUFFER
);
2732 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2733 SetLastError(ERROR_INVALID_PARAMETER
);
2736 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2737 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2741 case SPDRP_CAPABILITIES
:
2743 case SPDRP_CLASSGUID
:
2744 case SPDRP_COMPATIBLEIDS
:
2745 case SPDRP_CONFIGFLAGS
:
2746 case SPDRP_DEVICEDESC
:
2748 case SPDRP_FRIENDLYNAME
:
2749 case SPDRP_HARDWAREID
:
2750 case SPDRP_LOCATION_INFORMATION
:
2751 case SPDRP_LOWERFILTERS
:
2753 case SPDRP_SECURITY
:
2755 case SPDRP_UI_NUMBER
:
2756 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2757 case SPDRP_UPPERFILTERS
:
2759 LPCWSTR RegistryPropertyName
;
2764 case SPDRP_CAPABILITIES
:
2765 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2767 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2768 case SPDRP_CLASSGUID
:
2769 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2770 case SPDRP_COMPATIBLEIDS
:
2771 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2772 case SPDRP_CONFIGFLAGS
:
2773 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2774 case SPDRP_DEVICEDESC
:
2775 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2777 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2778 case SPDRP_FRIENDLYNAME
:
2779 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2780 case SPDRP_HARDWAREID
:
2781 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2782 case SPDRP_LOCATION_INFORMATION
:
2783 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2784 case SPDRP_LOWERFILTERS
:
2785 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2787 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2788 case SPDRP_SECURITY
:
2789 RegistryPropertyName
= L
"Security"; break;
2791 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2792 case SPDRP_UI_NUMBER
:
2793 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2794 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2795 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2796 case SPDRP_UPPERFILTERS
:
2797 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2799 /* Should not happen */
2800 RegistryPropertyName
= NULL
; break;
2803 /* Open registry key name */
2806 REGSTR_PATH_SYSTEMENUM
,
2810 if (rc
!= ERROR_SUCCESS
)
2821 RegCloseKey(hEnumKey
);
2822 if (rc
!= ERROR_SUCCESS
)
2827 /* Read registry entry */
2828 BufferSize
= PropertyBufferSize
;
2829 rc
= RegQueryValueExW(
2831 RegistryPropertyName
,
2832 NULL
, /* Reserved */
2833 PropertyRegDataType
,
2837 *RequiredSize
= BufferSize
;
2840 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2843 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2845 case ERROR_MORE_DATA
:
2846 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2855 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2857 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2859 if (PropertyRegDataType
)
2860 *PropertyRegDataType
= REG_SZ
;
2862 *RequiredSize
= required
;
2863 if (PropertyBufferSize
>= required
)
2865 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2869 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2873 /*case SPDRP_BUSTYPEGUID:
2874 case SPDRP_LEGACYBUSTYPE:
2875 case SPDRP_BUSNUMBER:
2876 case SPDRP_ENUMERATOR_NAME:
2877 case SPDRP_SECURITY_SDS:
2879 case SPDRP_EXCLUSIVE:
2880 case SPDRP_CHARACTERISTICS:
2882 case SPDRP_DEVICE_POWER_DATA:*/
2883 #if (WINVER >= 0x501)
2884 /*case SPDRP_REMOVAL_POLICY:
2885 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2886 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2887 case SPDRP_INSTALL_STATE:*/
2892 ERR("Property 0x%lx not implemented\n", Property
);
2893 SetLastError(ERROR_NOT_SUPPORTED
);
2898 TRACE("Returning %d\n", ret
);
2902 /***********************************************************************
2903 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2905 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2906 IN HDEVINFO DeviceInfoSet
,
2907 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2909 IN CONST BYTE
*PropertyBuffer
,
2910 IN DWORD PropertyBufferSize
)
2912 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2913 Property
, PropertyBuffer
, PropertyBufferSize
);
2914 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2918 /***********************************************************************
2919 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2921 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2922 IN HDEVINFO DeviceInfoSet
,
2923 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2925 IN
const BYTE
*PropertyBuffer
,
2926 IN DWORD PropertyBufferSize
)
2928 struct DeviceInfoSet
*list
;
2931 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2932 Property
, PropertyBuffer
, PropertyBufferSize
);
2935 SetLastError(ERROR_INVALID_HANDLE
);
2936 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2937 SetLastError(ERROR_INVALID_HANDLE
);
2938 else if (!DeviceInfoData
)
2939 SetLastError(ERROR_INVALID_HANDLE
);
2940 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2941 SetLastError(ERROR_INVALID_USER_BUFFER
);
2946 case SPDRP_COMPATIBLEIDS
:
2947 case SPDRP_CONFIGFLAGS
:
2948 case SPDRP_FRIENDLYNAME
:
2949 case SPDRP_HARDWAREID
:
2950 case SPDRP_LOCATION_INFORMATION
:
2951 case SPDRP_LOWERFILTERS
:
2952 case SPDRP_SECURITY
:
2954 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2955 case SPDRP_UPPERFILTERS
:
2957 LPCWSTR RegistryPropertyName
;
2958 DWORD RegistryDataType
;
2964 case SPDRP_COMPATIBLEIDS
:
2965 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2966 RegistryDataType
= REG_MULTI_SZ
;
2968 case SPDRP_CONFIGFLAGS
:
2969 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2970 RegistryDataType
= REG_DWORD
;
2972 case SPDRP_FRIENDLYNAME
:
2973 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2974 RegistryDataType
= REG_SZ
;
2976 case SPDRP_HARDWAREID
:
2977 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2978 RegistryDataType
= REG_MULTI_SZ
;
2980 case SPDRP_LOCATION_INFORMATION
:
2981 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2982 RegistryDataType
= REG_SZ
;
2984 case SPDRP_LOWERFILTERS
:
2985 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2986 RegistryDataType
= REG_MULTI_SZ
;
2988 case SPDRP_SECURITY
:
2989 RegistryPropertyName
= L
"Security";
2990 RegistryDataType
= REG_BINARY
;
2993 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2994 RegistryDataType
= REG_SZ
;
2996 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2997 RegistryPropertyName
= L
"UINumberDescFormat";
2998 RegistryDataType
= REG_SZ
;
3000 case SPDRP_UPPERFILTERS
:
3001 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
3002 RegistryDataType
= REG_MULTI_SZ
;
3005 /* Should not happen */
3006 RegistryPropertyName
= NULL
;
3007 RegistryDataType
= REG_BINARY
;
3010 /* Open device registry key */
3011 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3012 if (hKey
!= INVALID_HANDLE_VALUE
)
3014 /* Write new data */
3015 rc
= RegSetValueExW(
3017 RegistryPropertyName
,
3021 PropertyBufferSize
);
3022 if (rc
== ERROR_SUCCESS
)
3031 /*case SPDRP_CHARACTERISTICS:
3033 case SPDRP_EXCLUSIVE:*/
3034 #if (WINVER >= 0x501)
3035 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
3037 //case SPDRP_SECURITY_SDS:
3041 ERR("Property 0x%lx not implemented\n", Property
);
3042 SetLastError(ERROR_NOT_SUPPORTED
);
3047 TRACE("Returning %d\n", ret
);
3052 /***********************************************************************
3053 * SetupDiInstallClassA (SETUPAPI.@)
3055 BOOL WINAPI
SetupDiInstallClassA(
3056 IN HWND hwndParent OPTIONAL
,
3057 IN PCSTR InfFileName
,
3059 IN HSPFILEQ FileQueue OPTIONAL
)
3061 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3065 /***********************************************************************
3066 * SetupDiInstallClassW (SETUPAPI.@)
3068 BOOL WINAPI
SetupDiInstallClassW(
3069 IN HWND hwndParent OPTIONAL
,
3070 IN PCWSTR InfFileName
,
3072 IN HSPFILEQ FileQueue OPTIONAL
)
3074 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3078 /***********************************************************************
3079 * SetupDiInstallClassExA (SETUPAPI.@)
3081 BOOL WINAPI
SetupDiInstallClassExA(
3082 IN HWND hwndParent OPTIONAL
,
3083 IN PCSTR InfFileName OPTIONAL
,
3085 IN HSPFILEQ FileQueue OPTIONAL
,
3086 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3090 PWSTR InfFileNameW
= NULL
;
3095 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3096 if (InfFileNameW
== NULL
)
3098 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3103 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3104 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3106 MyFree(InfFileNameW
);
3112 static HKEY
CreateClassKey(HINF hInf
)
3114 WCHAR FullBuffer
[MAX_PATH
];
3115 WCHAR Buffer
[MAX_PATH
];
3120 if (!SetupGetLineTextW(NULL
,
3128 return INVALID_HANDLE_VALUE
;
3131 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3132 lstrcatW(FullBuffer
, Buffer
);
3135 if (!SetupGetLineTextW(NULL
,
3143 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3144 return INVALID_HANDLE_VALUE
;
3147 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3151 REG_OPTION_NON_VOLATILE
,
3157 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3158 return INVALID_HANDLE_VALUE
;
3161 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3166 RequiredSize
* sizeof(WCHAR
)))
3168 RegCloseKey(hClassKey
);
3169 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3170 return INVALID_HANDLE_VALUE
;
3178 InstallServicesSection(
3180 IN PCWSTR SectionName
,
3181 IN HDEVINFO DeviceInfoSet OPTIONAL
,
3182 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3183 OUT PCWSTR
* pAssociatedService OPTIONAL
,
3184 OUT PBOOL pRebootRequired OPTIONAL
)
3186 INFCONTEXT ContextService
;
3187 INFCONTEXT ContextInclude
;
3192 /* Parse 'Include' line */
3193 if (SetupFindFirstLineW(hInf
, SectionName
, L
"Include", &ContextInclude
))
3198 static WCHAR szBuffer
[MAX_PATH
];
3199 PWSTR pBuffer
= NULL
;
3202 ret
= SetupGetStringFieldW(&ContextInclude
, Index
, szBuffer
, MAX_PATH
, &required
);
3203 if (!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
)
3205 else if (!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3207 pBuffer
= MyMalloc(required
);
3208 ret
= SetupGetStringFieldW(&ContextInclude
, Index
, pBuffer
, required
, &required
);
3211 ret
= SetupOpenAppendInfFileW(pBuffer
? pBuffer
: szBuffer
, hInf
, NULL
);
3220 /* Parse 'Needs' line */
3221 if (SetupFindFirstLineW(hInf
, SectionName
, L
"Needs", &ContextInclude
))
3226 static WCHAR szBuffer
[MAX_PATH
];
3227 PWSTR pBuffer
= NULL
;
3230 ret
= SetupGetStringFieldW(&ContextInclude
, Index
, szBuffer
, MAX_PATH
, &required
);
3231 if (!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
)
3233 else if (!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3235 pBuffer
= MyMalloc(required
);
3236 ret
= SetupGetStringFieldW(&ContextInclude
, Index
, pBuffer
, required
, &required
);
3240 ret
= InstallServicesSection(hInf
, pBuffer
? pBuffer
: szBuffer
,
3241 DeviceInfoSet
, DeviceInfoData
, pAssociatedService
, pRebootRequired
);
3251 ret
= SetupFindFirstLineW(hInf
, SectionName
, NULL
, &ContextService
);
3254 LPWSTR ServiceName
= NULL
;
3255 LPWSTR ServiceSection
= NULL
;
3257 ret
= SetupGetStringFieldW(
3259 1, /* Field index */
3264 if (RequiredSize
> 0)
3266 /* We got the needed size for the buffer */
3267 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3270 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3273 ret
= SetupGetStringFieldW(
3275 1, /* Field index */
3276 ServiceName
, RequiredSize
,
3281 ret
= SetupGetIntField(
3283 2, /* Field index */
3287 /* The field may be empty. Ignore the error */
3290 ret
= SetupGetStringFieldW(
3292 3, /* Field index */
3297 if (GetLastError() == ERROR_INVALID_PARAMETER
)
3299 /* This first is probably missing. It is not
3300 * required, so ignore the error */
3307 if (RequiredSize
> 0)
3309 /* We got the needed size for the buffer */
3310 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3311 if (!ServiceSection
)
3313 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3316 ret
= SetupGetStringFieldW(
3318 3, /* Field index */
3319 ServiceSection
, RequiredSize
,
3324 SetLastError(ERROR_SUCCESS
);
3325 ret
= SetupInstallServicesFromInfSectionExW(
3327 ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
3329 if (ret
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
3331 if (pAssociatedService
)
3333 *pAssociatedService
= ServiceName
;
3336 if (pRebootRequired
&& GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
3337 *pRebootRequired
= TRUE
;
3340 HeapFree(GetProcessHeap(), 0, ServiceName
);
3341 HeapFree(GetProcessHeap(), 0, ServiceSection
);
3344 ret
= SetupFindNextLine(&ContextService
, &ContextService
);
3353 /***********************************************************************
3354 * SetupDiInstallClassExW (SETUPAPI.@)
3356 BOOL WINAPI
SetupDiInstallClassExW(
3357 IN HWND hwndParent OPTIONAL
,
3358 IN PCWSTR InfFileName OPTIONAL
,
3360 IN HSPFILEQ FileQueue OPTIONAL
,
3361 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3367 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3368 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3370 if (!InfFileName
&& !InterfaceClassGuid
)
3371 SetLastError(ERROR_INVALID_PARAMETER
);
3372 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3374 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3375 SetLastError(ERROR_INVALID_FLAGS
);
3377 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3378 SetLastError(ERROR_INVALID_PARAMETER
);
3379 else if (Reserved1
!= NULL
)
3380 SetLastError(ERROR_INVALID_PARAMETER
);
3381 else if (Reserved2
!= NULL
)
3382 SetLastError(ERROR_INVALID_PARAMETER
);
3385 WCHAR SectionName
[MAX_PATH
];
3386 HINF hInf
= INVALID_HANDLE_VALUE
;
3387 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3388 PVOID callback_context
= NULL
;
3390 if (InterfaceClassGuid
)
3392 /* SetupDiCreateDeviceInterface??? */
3393 FIXME("Installing an interface is not implemented\n");
3394 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3398 if (Flags
& DI_NOVCP
)
3399 FIXME("FileQueue argument ignored\n");
3400 if (Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3401 FIXME("Flags 0x%lx ignored\n", Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3403 /* Open the .inf file */
3404 hInf
= SetupOpenInfFileW(
3409 if (hInf
== INVALID_HANDLE_VALUE
)
3412 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3413 hClassKey
= CreateClassKey(hInf
);
3414 if (hClassKey
== INVALID_HANDLE_VALUE
)
3417 /* Try to append a layout file */
3418 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3422 /* Retrieve the actual section name */
3423 ret
= SetupDiGetActualSectionToInstallW(
3427 MAX_PATH
- wcslen(DotServices
),
3433 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3434 if (!callback_context
)
3437 ret
= SetupInstallFromInfSectionW(
3441 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3443 NULL
, /* SourceRootPath */
3445 SetupDefaultQueueCallbackW
,
3452 /* Install .Services section */
3453 lstrcatW(SectionName
, DotServices
);
3454 ret
= InstallServicesSection(hInf
, SectionName
, NULL
, NULL
, NULL
, NULL
);
3462 if (hInf
!= INVALID_HANDLE_VALUE
)
3463 SetupCloseInfFile(hInf
);
3464 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3465 RegCloseKey(hClassKey
);
3466 SetupTermDefaultQueueCallback(callback_context
);
3469 TRACE("Returning %d\n", ret
);
3474 /***********************************************************************
3475 * SetupDiOpenClassRegKey (SETUPAPI.@)
3477 HKEY WINAPI
SetupDiOpenClassRegKey(
3478 const GUID
* ClassGuid
,
3481 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3482 DIOCR_INSTALLER
, NULL
, NULL
);
3486 /***********************************************************************
3487 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3489 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3490 const GUID
* ClassGuid OPTIONAL
,
3493 PCSTR MachineName OPTIONAL
,
3496 PWSTR MachineNameW
= NULL
;
3503 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3504 if (MachineNameW
== NULL
)
3505 return INVALID_HANDLE_VALUE
;
3508 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3509 Flags
, MachineNameW
, Reserved
);
3512 MyFree(MachineNameW
);
3518 /***********************************************************************
3519 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3521 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3522 const GUID
* ClassGuid OPTIONAL
,
3525 PCWSTR MachineName OPTIONAL
,
3528 LPWSTR lpGuidString
;
3529 LPWSTR lpFullGuidString
;
3537 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3538 Flags
, debugstr_w(MachineName
), Reserved
);
3540 if (Flags
== DIOCR_INSTALLER
)
3542 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3544 else if (Flags
== DIOCR_INTERFACE
)
3546 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3550 ERR("Invalid Flags parameter!\n");
3551 SetLastError(ERROR_INVALID_FLAGS
);
3552 return INVALID_HANDLE_VALUE
;
3555 if (MachineName
!= NULL
)
3557 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3558 if (rc
!= ERROR_SUCCESS
)
3561 return INVALID_HANDLE_VALUE
;
3565 HKLM
= HKEY_LOCAL_MACHINE
;
3567 rc
= RegOpenKeyExW(HKLM
,
3570 ClassGuid
? 0 : samDesired
,
3572 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3573 if (rc
!= ERROR_SUCCESS
)
3576 return INVALID_HANDLE_VALUE
;
3579 if (ClassGuid
== NULL
)
3582 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3584 SetLastError(ERROR_GEN_FAILURE
);
3585 RegCloseKey(hClassesKey
);
3586 return INVALID_HANDLE_VALUE
;
3589 dwLength
= lstrlenW(lpGuidString
);
3590 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3591 if (!lpFullGuidString
)
3593 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3594 RpcStringFreeW(&lpGuidString
);
3595 return INVALID_HANDLE_VALUE
;
3597 lpFullGuidString
[0] = '{';
3598 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3599 lpFullGuidString
[dwLength
+ 1] = '}';
3600 lpFullGuidString
[dwLength
+ 2] = '\0';
3601 RpcStringFreeW(&lpGuidString
);
3603 rc
= RegOpenKeyExW(hClassesKey
,
3608 if (rc
!= ERROR_SUCCESS
)
3611 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3612 RegCloseKey(hClassesKey
);
3613 return INVALID_HANDLE_VALUE
;
3616 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3617 RegCloseKey(hClassesKey
);
3622 /***********************************************************************
3623 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3625 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3626 HDEVINFO DeviceInfoSet
,
3629 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3631 FIXME("%p %s %08lx %p\n",
3632 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3636 /***********************************************************************
3637 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3639 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3640 HDEVINFO DeviceInfoSet
,
3643 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3645 LPWSTR DevicePathW
= NULL
;
3648 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3650 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3651 if (DevicePathW
== NULL
)
3654 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3655 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3657 MyFree(DevicePathW
);
3662 /***********************************************************************
3663 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3665 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3666 HDEVINFO DeviceInfoSet
,
3667 PSP_DEVINFO_DATA DeviceInfoData
,
3668 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3669 DWORD ClassInstallParamsSize
)
3671 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3672 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3676 /***********************************************************************
3677 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3679 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3680 IN HDEVINFO DeviceInfoSet
,
3681 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3682 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3683 IN DWORD ClassInstallParamsSize
)
3685 struct DeviceInfoSet
*list
;
3688 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3689 ClassInstallParams
, ClassInstallParamsSize
);
3692 SetLastError(ERROR_INVALID_PARAMETER
);
3693 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3694 SetLastError(ERROR_INVALID_HANDLE
);
3695 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3696 SetLastError(ERROR_INVALID_HANDLE
);
3697 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3698 SetLastError(ERROR_INVALID_USER_BUFFER
);
3699 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3700 SetLastError(ERROR_INVALID_USER_BUFFER
);
3701 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3702 SetLastError(ERROR_INVALID_PARAMETER
);
3703 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3704 SetLastError(ERROR_INVALID_PARAMETER
);
3707 SP_DEVINSTALL_PARAMS_W InstallParams
;
3710 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3711 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3715 if (ClassInstallParams
)
3717 /* Check parameters in ClassInstallParams */
3718 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3719 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3721 SetLastError(ERROR_INVALID_USER_BUFFER
);
3724 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3726 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3727 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3730 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3733 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3737 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3740 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3744 TRACE("Returning %d\n", ret
);
3748 static BOOL
PropertyChangeHandler(
3749 IN HDEVINFO DeviceInfoSet
,
3750 IN PSP_DEVINFO_DATA DeviceInfoData
,
3751 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3752 IN DWORD ClassInstallParamsSize
)
3754 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3757 if (!DeviceInfoData
)
3758 SetLastError(ERROR_INVALID_PARAMETER
);
3759 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3760 SetLastError(ERROR_INVALID_PARAMETER
);
3761 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3762 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3763 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3764 SetLastError(ERROR_INVALID_FLAGS
);
3765 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3766 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3767 SetLastError(ERROR_INVALID_FLAGS
);
3768 else if (PropChangeParams
3769 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3770 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3771 SetLastError(ERROR_INVALID_USER_BUFFER
);
3774 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3775 if (!DeviceInfoData
)
3777 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3778 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3782 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3783 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3785 if (*CurrentPropChangeParams
)
3787 MyFree(*CurrentPropChangeParams
);
3788 *CurrentPropChangeParams
= NULL
;
3790 if (PropChangeParams
)
3792 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3793 if (!*CurrentPropChangeParams
)
3795 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3798 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3809 IN PWSTR InstallerName
,
3810 OUT HMODULE
* ModulePointer
,
3811 OUT PVOID
* FunctionPointer
)
3813 HMODULE hModule
= NULL
;
3814 LPSTR FunctionNameA
= NULL
;
3818 *ModulePointer
= NULL
;
3819 *FunctionPointer
= NULL
;
3821 Comma
= strchrW(InstallerName
, ',');
3824 rc
= ERROR_INVALID_PARAMETER
;
3830 hModule
= LoadLibraryW(InstallerName
);
3834 rc
= GetLastError();
3838 /* Skip comma spaces */
3839 while (*Comma
== ',' || isspaceW(*Comma
))
3842 /* W->A conversion for function name */
3843 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3846 rc
= GetLastError();
3850 /* Search function */
3851 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3852 if (!*FunctionPointer
)
3854 rc
= GetLastError();
3858 *ModulePointer
= hModule
;
3862 if (rc
!= ERROR_SUCCESS
&& hModule
)
3863 FreeLibrary(hModule
);
3864 MyFree(FunctionNameA
);
3869 FreeFunctionPointer(
3870 IN HMODULE ModulePointer
,
3871 IN PVOID FunctionPointer
)
3873 if (ModulePointer
== NULL
)
3874 return ERROR_SUCCESS
;
3875 if (FreeLibrary(ModulePointer
))
3876 return ERROR_SUCCESS
;
3878 return GetLastError();
3881 /***********************************************************************
3882 * SetupDiCallClassInstaller (SETUPAPI.@)
3884 BOOL WINAPI
SetupDiCallClassInstaller(
3885 IN DI_FUNCTION InstallFunction
,
3886 IN HDEVINFO DeviceInfoSet
,
3887 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3891 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3894 SetLastError(ERROR_INVALID_PARAMETER
);
3895 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3896 SetLastError(ERROR_INVALID_HANDLE
);
3897 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3898 SetLastError(ERROR_INVALID_HANDLE
);
3899 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3900 SetLastError(ERROR_INVALID_HANDLE
);
3901 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3902 SetLastError(ERROR_INVALID_USER_BUFFER
);
3905 SP_DEVINSTALL_PARAMS_W InstallParams
;
3906 #define CLASS_COINSTALLER 0x1
3907 #define DEVICE_COINSTALLER 0x2
3908 #define CLASS_INSTALLER 0x4
3909 UCHAR CanHandle
= 0;
3910 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3912 switch (InstallFunction
)
3914 case DIF_ALLOW_INSTALL
:
3915 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3917 case DIF_DESTROYPRIVATEDATA
:
3918 CanHandle
= CLASS_INSTALLER
;
3920 case DIF_INSTALLDEVICE
:
3921 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3922 DefaultHandler
= SetupDiInstallDevice
;
3924 case DIF_INSTALLDEVICEFILES
:
3925 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3926 DefaultHandler
= SetupDiInstallDriverFiles
;
3928 case DIF_INSTALLINTERFACES
:
3929 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3930 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3932 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3933 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3935 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3936 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3938 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3939 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3941 case DIF_PROPERTYCHANGE
:
3942 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3943 DefaultHandler
= SetupDiChangeState
;
3945 case DIF_REGISTER_COINSTALLERS
:
3946 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3947 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3949 case DIF_SELECTBESTCOMPATDRV
:
3950 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3951 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3954 ERR("Install function %u not supported\n", InstallFunction
);
3955 SetLastError(ERROR_NOT_SUPPORTED
);
3958 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3959 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3960 /* Don't process this call, as a parameter is invalid */
3965 LIST_ENTRY ClassCoInstallersListHead
;
3966 LIST_ENTRY DeviceCoInstallersListHead
;
3967 HMODULE ClassInstallerLibrary
= NULL
;
3968 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3969 COINSTALLER_CONTEXT_DATA Context
;
3970 PLIST_ENTRY ListEntry
;
3972 DWORD dwRegType
, dwLength
;
3973 DWORD rc
= NO_ERROR
;
3975 InitializeListHead(&ClassCoInstallersListHead
);
3976 InitializeListHead(&DeviceCoInstallersListHead
);
3978 if (CanHandle
& DEVICE_COINSTALLER
)
3980 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3981 if (hKey
!= INVALID_HANDLE_VALUE
)
3983 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3984 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3986 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3987 if (KeyBuffer
!= NULL
)
3989 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3990 if (rc
== ERROR_SUCCESS
)
3993 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3995 /* Add coinstaller to DeviceCoInstallersListHead list */
3996 struct CoInstallerElement
*coinstaller
;
3997 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3998 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4001 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
4002 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4003 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
4005 HeapFree(GetProcessHeap(), 0, coinstaller
);
4008 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4014 if (CanHandle
& CLASS_COINSTALLER
)
4018 REGSTR_PATH_CODEVICEINSTALLERS
,
4022 if (rc
== ERROR_SUCCESS
)
4024 LPWSTR lpGuidString
;
4025 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
4027 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
4028 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4030 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4031 if (KeyBuffer
!= NULL
)
4033 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4034 if (rc
== ERROR_SUCCESS
)
4037 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4039 /* Add coinstaller to ClassCoInstallersListHead list */
4040 struct CoInstallerElement
*coinstaller
;
4041 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
4042 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4045 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
4046 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4047 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
4049 HeapFree(GetProcessHeap(), 0, coinstaller
);
4052 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4055 RpcStringFreeW(&lpGuidString
);
4060 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
4062 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
4063 if (hKey
!= INVALID_HANDLE_VALUE
)
4065 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4066 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
4068 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4069 if (KeyBuffer
!= NULL
)
4071 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4072 if (rc
== ERROR_SUCCESS
)
4074 /* Get ClassInstaller function pointer */
4075 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
4076 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
4078 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
4079 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4082 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4089 /* Call Class co-installers */
4090 Context
.PostProcessing
= FALSE
;
4092 ListEntry
= ClassCoInstallersListHead
.Flink
;
4093 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
4095 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
4096 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4097 coinstaller
->PrivateData
= Context
.PrivateData
;
4098 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4100 coinstaller
->DoPostProcessing
= TRUE
;
4103 ListEntry
= ListEntry
->Flink
;
4106 /* Call Device co-installers */
4107 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4108 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
4110 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
4111 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4112 coinstaller
->PrivateData
= Context
.PrivateData
;
4113 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4115 coinstaller
->DoPostProcessing
= TRUE
;
4118 ListEntry
= ListEntry
->Flink
;
4121 /* Call Class installer */
4124 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4125 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
4128 rc
= ERROR_DI_DO_DEFAULT
;
4130 /* Call default handler */
4131 if (rc
== ERROR_DI_DO_DEFAULT
)
4133 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
4135 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
4138 rc
= GetLastError();
4144 /* Call Class co-installers that required postprocessing */
4145 Context
.PostProcessing
= TRUE
;
4146 ListEntry
= ClassCoInstallersListHead
.Flink
;
4147 while (ListEntry
!= &ClassCoInstallersListHead
)
4149 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
4150 if (coinstaller
->DoPostProcessing
)
4152 Context
.InstallResult
= rc
;
4153 Context
.PrivateData
= coinstaller
->PrivateData
;
4154 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4156 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4157 ListEntry
= ListEntry
->Flink
;
4160 /* Call Device co-installers that required postprocessing */
4161 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4162 while (ListEntry
!= &DeviceCoInstallersListHead
)
4164 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
4165 if (coinstaller
->DoPostProcessing
)
4167 Context
.InstallResult
= rc
;
4168 Context
.PrivateData
= coinstaller
->PrivateData
;
4169 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4171 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4172 ListEntry
= ListEntry
->Flink
;
4175 /* Free allocated memory */
4176 while (!IsListEmpty(&ClassCoInstallersListHead
))
4178 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4179 HeapFree(GetProcessHeap(), 0, ListEntry
);
4181 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4183 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4184 HeapFree(GetProcessHeap(), 0, ListEntry
);
4187 ret
= (rc
== NO_ERROR
);
4191 TRACE("Returning %d\n", ret
);
4195 /***********************************************************************
4196 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4198 BOOL WINAPI
SetupDiGetDeviceInfoListClass(
4199 IN HDEVINFO DeviceInfoSet
,
4200 OUT LPGUID ClassGuid
)
4202 struct DeviceInfoSet
*list
;
4205 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4208 SetLastError(ERROR_INVALID_HANDLE
);
4209 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4210 SetLastError(ERROR_INVALID_HANDLE
);
4211 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4212 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4215 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4220 TRACE("Returning %d\n", ret
);
4224 /***********************************************************************
4225 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4227 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
4228 IN HDEVINFO DeviceInfoSet
,
4229 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
4231 struct DeviceInfoSet
*list
;
4234 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
4237 SetLastError(ERROR_INVALID_HANDLE
);
4238 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4239 SetLastError(ERROR_INVALID_HANDLE
);
4240 else if (!DeviceInfoListDetailData
)
4241 SetLastError(ERROR_INVALID_PARAMETER
);
4242 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
4243 SetLastError(ERROR_INVALID_USER_BUFFER
);
4247 &DeviceInfoListDetailData
->ClassGuid
,
4250 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
4251 if (list
->MachineName
)
4252 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
4254 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
4259 TRACE("Returning %d\n", ret
);
4263 /***********************************************************************
4264 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4266 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4267 IN HDEVINFO DeviceInfoSet
,
4268 IN PSP_DEVINFO_DATA DeviceInfoData
,
4269 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4271 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4274 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4276 if (DeviceInstallParams
== NULL
)
4277 SetLastError(ERROR_INVALID_PARAMETER
);
4278 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4279 SetLastError(ERROR_INVALID_USER_BUFFER
);
4282 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4283 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4287 /* Do W->A conversion */
4289 DeviceInstallParams
,
4290 &deviceInstallParamsW
,
4291 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4292 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4293 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4295 DeviceInstallParams
->DriverPath
[0] = '\0';
4301 TRACE("Returning %d\n", ret
);
4305 /***********************************************************************
4306 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4308 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
4309 IN HDEVINFO DeviceInfoSet
,
4310 IN PSP_DEVINFO_DATA DeviceInfoData
,
4311 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4313 struct DeviceInfoSet
*list
;
4316 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4319 SetLastError(ERROR_INVALID_HANDLE
);
4320 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4321 SetLastError(ERROR_INVALID_HANDLE
);
4322 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4323 SetLastError(ERROR_INVALID_USER_BUFFER
);
4324 else if (!DeviceInstallParams
)
4325 SetLastError(ERROR_INVALID_PARAMETER
);
4326 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4327 SetLastError(ERROR_INVALID_USER_BUFFER
);
4330 PSP_DEVINSTALL_PARAMS_W Source
;
4333 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4335 Source
= &list
->InstallParams
;
4336 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4340 TRACE("Returning %d\n", ret
);
4344 /***********************************************************************
4345 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4347 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
4348 IN HDEVINFO DeviceInfoSet
,
4349 IN PSP_DEVINFO_DATA DeviceInfoData
,
4350 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4352 struct DeviceInfoSet
*list
;
4355 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4358 SetLastError(ERROR_INVALID_HANDLE
);
4359 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4360 SetLastError(ERROR_INVALID_HANDLE
);
4361 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4362 SetLastError(ERROR_INVALID_USER_BUFFER
);
4363 else if (!DeviceInstallParams
)
4364 SetLastError(ERROR_INVALID_PARAMETER
);
4365 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4366 SetLastError(ERROR_INVALID_USER_BUFFER
);
4369 PSP_DEVINSTALL_PARAMS_W Destination
;
4371 /* FIXME: Validate parameters */
4374 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4376 Destination
= &list
->InstallParams
;
4377 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4381 TRACE("Returning %d\n", ret
);
4385 /***********************************************************************
4386 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4388 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
4389 IN HDEVINFO DeviceInfoSet
,
4390 IN PSP_DEVINFO_DATA DeviceInfoData
,
4391 OUT PSTR DeviceInstanceId OPTIONAL
,
4392 IN DWORD DeviceInstanceIdSize
,
4393 OUT PDWORD RequiredSize OPTIONAL
)
4395 PWSTR DeviceInstanceIdW
= NULL
;
4398 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4399 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4401 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4402 SetLastError(ERROR_INVALID_PARAMETER
);
4405 if (DeviceInstanceIdSize
!= 0)
4407 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4408 if (DeviceInstanceIdW
== NULL
)
4412 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4413 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4416 if (ret
&& DeviceInstanceIdW
!= NULL
)
4418 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4419 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4421 DeviceInstanceId
[0] = '\0';
4427 TRACE("Returning %d\n", ret
);
4431 /***********************************************************************
4432 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4434 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
4435 IN HDEVINFO DeviceInfoSet
,
4436 IN PSP_DEVINFO_DATA DeviceInfoData
,
4437 OUT PWSTR DeviceInstanceId OPTIONAL
,
4438 IN DWORD DeviceInstanceIdSize
,
4439 OUT PDWORD RequiredSize OPTIONAL
)
4443 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4444 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4447 SetLastError(ERROR_INVALID_HANDLE
);
4448 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4449 SetLastError(ERROR_INVALID_HANDLE
);
4450 else if (!DeviceInfoData
)
4451 SetLastError(ERROR_INVALID_PARAMETER
);
4452 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4453 SetLastError(ERROR_INVALID_USER_BUFFER
);
4454 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4455 SetLastError(ERROR_INVALID_PARAMETER
);
4456 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4457 SetLastError(ERROR_INVALID_PARAMETER
);
4460 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4463 required
= (wcslen(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4465 *RequiredSize
= required
;
4467 if (required
<= DeviceInstanceIdSize
)
4469 wcscpy(DeviceInstanceId
, DevInfo
->DeviceName
);
4473 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4476 TRACE("Returning %d\n", ret
);
4480 /***********************************************************************
4481 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4483 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
4484 IN HDEVINFO DeviceInfoSet
,
4485 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4486 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4487 IN DWORD PropertySheetHeaderPageListSize
,
4488 OUT PDWORD RequiredSize OPTIONAL
,
4489 IN DWORD PropertySheetType
)
4491 PROPSHEETHEADERW psh
;
4494 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4495 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4496 RequiredSize
, PropertySheetType
);
4498 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4499 psh
.phpage
= PropertySheetHeader
->phpage
;
4500 psh
.nPages
= PropertySheetHeader
->nPages
;
4502 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4503 PropertySheetHeaderPageListSize
, RequiredSize
,
4507 PropertySheetHeader
->nPages
= psh
.nPages
;
4510 TRACE("Returning %d\n", ret
);
4514 struct ClassDevPropertySheetsData
4516 HPROPSHEETPAGE
*PropertySheetPages
;
4517 DWORD MaximumNumberOfPages
;
4518 DWORD NumberOfPages
;
4521 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
4522 IN HPROPSHEETPAGE hPropSheetPage
,
4523 IN OUT LPARAM lParam
)
4525 struct ClassDevPropertySheetsData
*PropPageData
;
4527 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4529 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4531 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4532 PropPageData
->PropertySheetPages
++;
4535 PropPageData
->NumberOfPages
++;
4539 /***********************************************************************
4540 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4542 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
4543 IN HDEVINFO DeviceInfoSet
,
4544 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4545 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4546 IN DWORD PropertySheetHeaderPageListSize
,
4547 OUT PDWORD RequiredSize OPTIONAL
,
4548 IN DWORD PropertySheetType
)
4550 struct DeviceInfoSet
*list
;
4553 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4554 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4555 RequiredSize
, PropertySheetType
);
4558 SetLastError(ERROR_INVALID_HANDLE
);
4559 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4560 SetLastError(ERROR_INVALID_HANDLE
);
4561 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4562 SetLastError(ERROR_INVALID_HANDLE
);
4563 else if (!PropertySheetHeader
)
4564 SetLastError(ERROR_INVALID_PARAMETER
);
4565 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4566 SetLastError(ERROR_INVALID_FLAGS
);
4567 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4568 SetLastError(ERROR_INVALID_USER_BUFFER
);
4569 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4570 SetLastError(ERROR_INVALID_PARAMETER
);
4571 else if (!PropertySheetHeader
)
4572 SetLastError(ERROR_INVALID_PARAMETER
);
4573 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4574 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4575 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4576 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4577 SetLastError(ERROR_INVALID_PARAMETER
);
4580 HKEY hKey
= INVALID_HANDLE_VALUE
;
4581 SP_PROPSHEETPAGE_REQUEST Request
;
4582 LPWSTR PropPageProvider
= NULL
;
4583 HMODULE hModule
= NULL
;
4584 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4585 struct ClassDevPropertySheetsData PropPageData
;
4586 DWORD dwLength
, dwRegType
;
4590 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4593 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4594 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4596 if (hKey
== INVALID_HANDLE_VALUE
)
4599 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4600 if (rc
== ERROR_FILE_NOT_FOUND
)
4602 /* No registry key. As it is optional, don't say it's a bad error */
4608 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4614 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4615 if (!PropPageProvider
)
4617 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4620 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4621 if (rc
!= ERROR_SUCCESS
)
4626 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4628 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4629 if (rc
!= ERROR_SUCCESS
)
4631 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4635 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4636 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4637 Request
.DeviceInfoSet
= DeviceInfoSet
;
4638 Request
.DeviceInfoData
= DeviceInfoData
;
4639 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4640 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4641 PropPageData
.NumberOfPages
= 0;
4642 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4647 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4648 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4650 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4655 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4656 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4660 if (hKey
!= INVALID_HANDLE_VALUE
)
4662 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4663 FreeFunctionPointer(hModule
, pPropPageProvider
);
4666 TRACE("Returning %d\n", ret
);
4670 /***********************************************************************
4671 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4673 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4674 IN HDEVINFO DeviceInfoSet
,
4675 IN PSP_DEVINFO_DATA DeviceInfoData
,
4679 IN HINF InfHandle OPTIONAL
,
4680 IN PCSTR InfSectionName OPTIONAL
)
4682 PCWSTR InfSectionNameW
= NULL
;
4683 HKEY ret
= INVALID_HANDLE_VALUE
;
4687 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4688 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4691 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4699 if (InfSectionNameW
!= NULL
)
4700 MyFree((PVOID
)InfSectionNameW
);
4706 OpenHardwareProfileKey(
4709 IN DWORD samDesired
)
4711 HKEY hHWProfilesKey
= INVALID_HANDLE_VALUE
;
4712 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4713 HKEY ret
= INVALID_HANDLE_VALUE
;
4716 rc
= RegOpenKeyExW(HKLM
,
4717 REGSTR_PATH_HWPROFILES
,
4721 if (rc
!= ERROR_SUCCESS
)
4738 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4747 if (rc
!= ERROR_SUCCESS
)
4752 ret
= hHWProfileKey
;
4755 if (hHWProfilesKey
!= INVALID_HANDLE_VALUE
)
4756 RegCloseKey(hHWProfilesKey
);
4757 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
&& hHWProfileKey
!= ret
)
4758 RegCloseKey(hHWProfileKey
);
4762 /***********************************************************************
4763 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4765 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4766 IN HDEVINFO DeviceInfoSet
,
4767 IN PSP_DEVINFO_DATA DeviceInfoData
,
4771 IN HINF InfHandle OPTIONAL
,
4772 IN PCWSTR InfSectionName OPTIONAL
)
4774 struct DeviceInfoSet
*list
;
4775 HKEY ret
= INVALID_HANDLE_VALUE
;
4777 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4778 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4781 SetLastError(ERROR_INVALID_HANDLE
);
4782 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4783 SetLastError(ERROR_INVALID_HANDLE
);
4784 else if (!DeviceInfoData
)
4785 SetLastError(ERROR_INVALID_PARAMETER
);
4786 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4787 SetLastError(ERROR_INVALID_USER_BUFFER
);
4788 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4789 SetLastError(ERROR_INVALID_PARAMETER
);
4790 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4791 SetLastError(ERROR_INVALID_PARAMETER
);
4792 else if (InfHandle
&& !InfSectionName
)
4793 SetLastError(ERROR_INVALID_PARAMETER
);
4794 else if (!InfHandle
&& InfSectionName
)
4795 SetLastError(ERROR_INVALID_PARAMETER
);
4798 LPWSTR lpGuidString
= NULL
;
4799 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4800 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4801 DWORD Index
; /* Index used in the DriverKey name */
4803 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4804 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4805 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4806 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4807 HKEY hKey
= INVALID_HANDLE_VALUE
;
4810 if (Scope
== DICS_FLAG_GLOBAL
)
4811 RootKey
= list
->HKLM
;
4812 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4814 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
4815 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4817 RootKey
= hHWProfileKey
;
4820 if (KeyType
== DIREG_DEV
)
4822 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4824 rc
= RegCreateKeyExW(
4826 REGSTR_PATH_SYSTEMENUM
,
4829 REG_OPTION_NON_VOLATILE
,
4834 if (rc
!= ERROR_SUCCESS
)
4839 rc
= RegCreateKeyExW(
4841 deviceInfo
->DeviceName
,
4844 REG_OPTION_NON_VOLATILE
,
4845 #if _WIN32_WINNT >= 0x502
4846 KEY_READ
| KEY_WRITE
,
4853 if (rc
!= ERROR_SUCCESS
)
4859 else /* KeyType == DIREG_DRV */
4861 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4863 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4864 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4867 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4870 wcscpy(DriverKey
, L
"{");
4871 wcscat(DriverKey
, lpGuidString
);
4872 wcscat(DriverKey
, L
"}\\");
4873 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4874 rc
= RegOpenKeyExW(RootKey
,
4875 REGSTR_PATH_CLASS_NT
,
4879 if (rc
!= ERROR_SUCCESS
)
4885 /* Try all values for Index between 0 and 9999 */
4887 while (Index
<= 9999)
4890 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4891 rc
= RegCreateKeyEx(hClassKey
,
4895 REG_OPTION_NON_VOLATILE
,
4896 #if _WIN32_WINNT >= 0x502
4897 KEY_READ
| KEY_WRITE
,
4904 if (rc
!= ERROR_SUCCESS
)
4909 if (Disposition
== REG_CREATED_NEW_KEY
)
4912 hKey
= INVALID_HANDLE_VALUE
;
4917 /* Unable to create more than 9999 devices within the same class */
4918 SetLastError(ERROR_GEN_FAILURE
);
4922 /* Open device key, to write Driver value */
4923 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4924 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4926 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4927 if (rc
!= ERROR_SUCCESS
)
4934 /* Do installation of the specified section */
4937 FIXME("Need to install section %s in file %p\n",
4938 debugstr_w(InfSectionName
), InfHandle
);
4944 RpcStringFreeW(&lpGuidString
);
4945 HeapFree(GetProcessHeap(), 0, DriverKey
);
4946 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4947 RegCloseKey(hHWProfileKey
);
4948 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4949 RegCloseKey(hEnumKey
);
4950 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4951 RegCloseKey(hClassKey
);
4952 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4953 RegCloseKey(hDeviceKey
);
4954 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4958 TRACE("Returning 0x%p\n", ret
);
4962 /***********************************************************************
4963 * SetupDiOpenDevRegKey (SETUPAPI.@)
4965 HKEY WINAPI
SetupDiOpenDevRegKey(
4966 HDEVINFO DeviceInfoSet
,
4967 PSP_DEVINFO_DATA DeviceInfoData
,
4973 struct DeviceInfoSet
*list
;
4974 HKEY ret
= INVALID_HANDLE_VALUE
;
4976 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4977 Scope
, HwProfile
, KeyType
, samDesired
);
4980 SetLastError(ERROR_INVALID_HANDLE
);
4981 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4982 SetLastError(ERROR_INVALID_HANDLE
);
4983 else if (!DeviceInfoData
)
4984 SetLastError(ERROR_INVALID_PARAMETER
);
4985 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4986 SetLastError(ERROR_INVALID_USER_BUFFER
);
4987 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4988 SetLastError(ERROR_INVALID_PARAMETER
);
4989 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4990 SetLastError(ERROR_INVALID_PARAMETER
);
4993 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4994 LPWSTR DriverKey
= NULL
;
4998 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4999 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
5000 HKEY hKey
= INVALID_HANDLE_VALUE
;
5003 if (Scope
== DICS_FLAG_GLOBAL
)
5004 RootKey
= list
->HKLM
;
5005 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
5007 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
5008 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
5010 RootKey
= hHWProfileKey
;
5015 REGSTR_PATH_SYSTEMENUM
,
5019 if (rc
!= ERROR_SUCCESS
)
5026 deviceInfo
->DeviceName
,
5028 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
5030 RegCloseKey(hEnumKey
);
5031 hEnumKey
= INVALID_HANDLE_VALUE
;
5032 if (rc
!= ERROR_SUCCESS
)
5037 if (KeyType
== DIREG_DEV
)
5039 /* We're done. Just return the hKey handle */
5043 /* Read the 'Driver' key */
5044 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
5045 if (rc
!= ERROR_SUCCESS
)
5050 else if (dwRegType
!= REG_SZ
)
5052 SetLastError(ERROR_GEN_FAILURE
);
5055 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
5058 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5061 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
5062 if (rc
!= ERROR_SUCCESS
)
5068 hKey
= INVALID_HANDLE_VALUE
;
5069 /* Need to open the driver key */
5072 REGSTR_PATH_CLASS_NT
,
5076 if (rc
!= ERROR_SUCCESS
)
5087 if (rc
!= ERROR_SUCCESS
)
5095 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
5096 RegCloseKey(hHWProfileKey
);
5097 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
5098 RegCloseKey(hEnumKey
);
5099 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
5103 TRACE("Returning 0x%p\n", ret
);
5107 /***********************************************************************
5108 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
5110 BOOL WINAPI
SetupDiCreateDeviceInfoA(
5111 HDEVINFO DeviceInfoSet
,
5113 CONST GUID
*ClassGuid
,
5114 PCSTR DeviceDescription
,
5116 DWORD CreationFlags
,
5117 PSP_DEVINFO_DATA DeviceInfoData
)
5119 LPWSTR DeviceNameW
= NULL
;
5120 LPWSTR DeviceDescriptionW
= NULL
;
5127 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
5128 if (DeviceNameW
== NULL
) return FALSE
;
5130 if (DeviceDescription
)
5132 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
5133 if (DeviceDescriptionW
== NULL
)
5135 if (DeviceNameW
) MyFree(DeviceNameW
);
5140 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
5141 ClassGuid
, DeviceDescriptionW
,
5142 hwndParent
, CreationFlags
,
5145 if (DeviceNameW
) MyFree(DeviceNameW
);
5146 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
5151 /***********************************************************************
5152 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
5154 BOOL WINAPI
SetupDiCreateDeviceInfoW(
5155 HDEVINFO DeviceInfoSet
,
5157 CONST GUID
*ClassGuid
,
5158 PCWSTR DeviceDescription
,
5160 DWORD CreationFlags
,
5161 PSP_DEVINFO_DATA DeviceInfoData
)
5163 struct DeviceInfoSet
*list
;
5166 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
5167 debugstr_guid(ClassGuid
), DeviceDescription
,
5168 hwndParent
, CreationFlags
, DeviceInfoData
);
5171 SetLastError(ERROR_INVALID_HANDLE
);
5172 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5173 SetLastError(ERROR_INVALID_HANDLE
);
5174 else if (!ClassGuid
)
5175 SetLastError(ERROR_INVALID_PARAMETER
);
5176 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
5177 SetLastError(ERROR_CLASS_MISMATCH
);
5178 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
5180 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
5181 SetLastError(ERROR_INVALID_FLAGS
);
5185 SP_DEVINFO_DATA DevInfo
;
5187 if (CreationFlags
& DICD_GENERATE_ID
)
5189 /* Generate a new unique ID for this device */
5190 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5191 FIXME("not implemented\n");
5195 /* Device name is fully qualified. Try to open it */
5198 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
5199 rc
= SetupDiOpenDeviceInfoW(
5202 NULL
, /* hwndParent */
5203 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
5208 /* SetupDiOpenDeviceInfoW has already added
5209 * the device info to the device info set
5211 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
5213 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5215 struct DeviceInfoElement
*deviceInfo
;
5217 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
5219 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5221 if (!DeviceInfoData
)
5225 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
5227 SetLastError(ERROR_INVALID_USER_BUFFER
);
5231 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5232 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5233 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5242 TRACE("Returning %d\n", ret
);
5246 /***********************************************************************
5247 * Helper functions for SetupDiBuildDriverInfoList
5251 IN PLIST_ENTRY DriverListHead
,
5252 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5253 IN LPGUID ClassGuid
,
5254 IN INFCONTEXT ContextDevice
,
5255 IN
struct InfFileDetails
*InfFileDetails
,
5257 IN LPCWSTR ProviderName
,
5258 IN LPCWSTR ManufacturerName
,
5259 IN LPCWSTR MatchingId
,
5260 FILETIME DriverDate
,
5261 DWORDLONG DriverVersion
,
5264 struct DriverInfoElement
*driverInfo
= NULL
;
5265 HANDLE hFile
= INVALID_HANDLE_VALUE
;
5266 DWORD RequiredSize
= 128; /* Initial buffer size */
5267 BOOL Result
= FALSE
;
5268 PLIST_ENTRY PreviousEntry
;
5269 LPWSTR InfInstallSection
= NULL
;
5272 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
5275 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5278 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
5280 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
5281 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
5283 /* Copy InfFileName field */
5284 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
5285 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
5287 /* Fill InfDate field */
5288 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5289 GENERIC_READ, FILE_SHARE_READ,
5290 NULL, OPEN_EXISTING, 0, NULL);
5291 if (hFile == INVALID_HANDLE_VALUE)
5293 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5297 /* Fill SectionName field */
5298 Result
= SetupGetStringFieldW(
5301 driverInfo
->Details
.SectionName
, LINE_LEN
,
5306 /* Fill DrvDescription field */
5307 Result
= SetupGetStringFieldW(
5309 0, /* Field index */
5310 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
5313 /* Copy MatchingId information */
5314 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5315 if (!driverInfo
->MatchingId
)
5317 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5320 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5322 /* Get inf install section */
5324 RequiredSize
= 128; /* Initial buffer size */
5325 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5326 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5328 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5329 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5330 if (!InfInstallSection
)
5332 Result
= SetupGetStringFieldW(
5334 1, /* Field index */
5335 InfInstallSection
, RequiredSize
,
5341 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
5342 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
5344 driverInfo
->DriverRank
= Rank
;
5345 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
5346 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5347 driverInfo
->Info
.DriverType
= DriverType
;
5348 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
5349 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
5350 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
5351 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
5352 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
5355 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
5356 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
5359 driverInfo
->Info
.ProviderName
[0] = '\0';
5360 driverInfo
->Info
.DriverDate
= DriverDate
;
5361 driverInfo
->Info
.DriverVersion
= DriverVersion
;
5362 ReferenceInfFile(InfFileDetails
);
5363 driverInfo
->InfFileDetails
= InfFileDetails
;
5365 /* Insert current driver in driver list, according to its rank */
5366 PreviousEntry
= DriverListHead
->Flink
;
5367 while (PreviousEntry
!= DriverListHead
)
5369 struct DriverInfoElement
*CurrentDriver
;
5370 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
5371 if (CurrentDriver
->DriverRank
> Rank
||
5372 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
5374 /* Insert before the current item */
5375 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
5378 PreviousEntry
= PreviousEntry
->Flink
;
5380 if (PreviousEntry
== DriverListHead
)
5382 /* Insert at the end of the list */
5383 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
5392 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
5393 HeapFree(GetProcessHeap(), 0, driverInfo
);
5395 if (hFile
!= INVALID_HANDLE_VALUE
)
5397 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5403 GetVersionInformationFromInfFile(
5405 OUT LPGUID ClassGuid
,
5406 OUT LPWSTR
* pProviderName
,
5407 OUT FILETIME
* DriverDate
,
5408 OUT DWORDLONG
* DriverVersion
)
5411 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5412 LPWSTR DriverVer
= NULL
;
5413 LPWSTR ProviderName
= NULL
;
5414 LPWSTR pComma
; /* Points into DriverVer */
5415 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5416 SYSTEMTIME SystemTime
;
5418 BOOL ret
= FALSE
; /* Final result */
5420 /* Get class Guid */
5421 if (!SetupGetLineTextW(
5424 L
"Version", L
"ClassGUID",
5425 guidW
, sizeof(guidW
),
5426 NULL
/* Required size */))
5430 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5431 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5433 SetLastError(ERROR_GEN_FAILURE
);
5437 /* Get provider name */
5438 Result
= SetupGetLineTextW(
5440 hInf
, L
"Version", L
"Provider",
5445 /* We know know the needed buffer size */
5446 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5449 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5452 Result
= SetupGetLineTextW(
5454 hInf
, L
"Version", L
"Provider",
5455 ProviderName
, RequiredSize
,
5460 *pProviderName
= ProviderName
;
5462 /* Read the "DriverVer" value */
5463 Result
= SetupGetLineTextW(
5465 hInf
, L
"Version", L
"DriverVer",
5470 /* We know know the needed buffer size */
5471 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5474 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5477 Result
= SetupGetLineTextW(
5479 hInf
, L
"Version", L
"DriverVer",
5480 DriverVer
, RequiredSize
,
5486 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5487 pComma
= wcschr(DriverVer
, ',');
5490 *pComma
= UNICODE_NULL
;
5491 pVersion
= pComma
+ 1;
5493 /* Get driver date version. Invalid date = 00/00/00 */
5494 memset(DriverDate
, 0, sizeof(FILETIME
));
5495 if (wcslen(DriverVer
) == 10
5496 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5497 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5499 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5500 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5501 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5502 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5503 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5504 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5506 /* Get driver version. Invalid version = 0.0.0.0 */
5510 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5511 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5512 LARGE_INTEGER fullVersion
;
5514 pMinor
= strchrW(pVersion
, '.');
5518 pRevision
= strchrW(++pMinor
, '.');
5519 Minor
= atoiW(pMinor
);
5524 pBuild
= strchrW(++pRevision
, '.');
5525 Revision
= atoiW(pRevision
);
5531 Build
= atoiW(pBuild
);
5533 Major
= atoiW(pVersion
);
5534 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5535 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5536 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5543 HeapFree(GetProcessHeap(), 0, ProviderName
);
5544 HeapFree(GetProcessHeap(), 0, DriverVer
);
5549 /***********************************************************************
5550 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5553 SetupDiBuildDriverInfoList(
5554 IN HDEVINFO DeviceInfoSet
,
5555 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5556 IN DWORD DriverType
)
5558 struct DeviceInfoSet
*list
;
5559 SP_DEVINSTALL_PARAMS_W InstallParams
;
5560 PVOID Buffer
= NULL
;
5561 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5562 LPWSTR ProviderName
= NULL
;
5563 LPWSTR ManufacturerName
= NULL
;
5564 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5565 LPWSTR HardwareIDs
= NULL
;
5566 LPWSTR CompatibleIDs
= NULL
;
5567 LPWSTR FullInfFileName
= NULL
;
5568 FILETIME DriverDate
;
5569 DWORDLONG DriverVersion
= 0;
5573 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5576 SetLastError(ERROR_INVALID_HANDLE
);
5577 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5578 SetLastError(ERROR_INVALID_HANDLE
);
5579 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5580 SetLastError(ERROR_INVALID_HANDLE
);
5581 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5582 SetLastError(ERROR_INVALID_PARAMETER
);
5583 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
5584 SetLastError(ERROR_INVALID_PARAMETER
);
5585 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5586 SetLastError(ERROR_INVALID_PARAMETER
);
5587 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5588 SetLastError(ERROR_INVALID_USER_BUFFER
);
5593 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
5594 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5598 if (DriverType
== SPDIT_COMPATDRIVER
)
5600 /* Get hardware IDs list */
5602 RequiredSize
= 512; /* Initial buffer size */
5603 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5604 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5606 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5607 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5610 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5613 Result
= SetupDiGetDeviceRegistryPropertyW(
5625 /* Get compatible IDs list */
5627 RequiredSize
= 512; /* Initial buffer size */
5628 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5629 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5631 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5632 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5635 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5638 Result
= SetupDiGetDeviceRegistryPropertyW(
5641 SPDRP_COMPATIBLEIDS
,
5643 (PBYTE
)CompatibleIDs
,
5646 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5648 /* No compatible ID for this device */
5649 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5650 CompatibleIDs
= NULL
;
5658 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5660 /* InstallParams.DriverPath contains the name of a .inf file */
5661 RequiredSize
= wcslen(InstallParams
.DriverPath
) + 2;
5662 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5665 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5668 wcscpy(Buffer
, InstallParams
.DriverPath
);
5669 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
5674 /* Enumerate .inf files */
5676 RequiredSize
= 32768; /* Initial buffer size */
5677 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5678 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5680 HeapFree(GetProcessHeap(), 0, Buffer
);
5681 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5685 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5688 Result
= SetupGetInfFileListW(
5689 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5691 Buffer
, RequiredSize
,
5694 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5696 /* No .inf file in specified directory. So, we should
5697 * success as we created an empty driver info list.
5706 LPWSTR pFullFilename
;
5708 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5710 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5711 if (!FullInfFileName
)
5713 pFullFilename
= &FullInfFileName
[0];
5715 else if (*InstallParams
.DriverPath
)
5718 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5721 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5722 if (!FullInfFileName
)
5724 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5727 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
5728 wcscat(FullInfFileName
, L
"\\");
5729 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
5733 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5734 if (!FullInfFileName
)
5736 pFullFilename
= &FullInfFileName
[0];
5739 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
5741 INFCONTEXT ContextManufacturer
, ContextDevice
;
5744 wcscpy(pFullFilename
, filename
);
5745 TRACE("Opening file %S\n", FullInfFileName
);
5747 currentInfFileDetails
= HeapAlloc(
5750 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
5751 if (!currentInfFileDetails
)
5753 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5754 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5756 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5757 ReferenceInfFile(currentInfFileDetails
);
5758 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5760 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5761 currentInfFileDetails
= NULL
;
5765 if (!GetVersionInformationFromInfFile(
5766 currentInfFileDetails
->hInf
,
5772 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5773 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5774 currentInfFileDetails
= NULL
;
5778 if (DriverType
== SPDIT_CLASSDRIVER
)
5780 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5781 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5787 /* Get the manufacturers list */
5788 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
5791 Result
= SetupGetStringFieldW(
5792 &ContextManufacturer
,
5793 0, /* Field index */
5798 /* We got the needed size for the buffer */
5799 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5800 if (!ManufacturerName
)
5802 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5805 Result
= SetupGetStringFieldW(
5806 &ContextManufacturer
,
5807 0, /* Field index */
5808 ManufacturerName
, RequiredSize
,
5811 /* Get manufacturer section name */
5812 Result
= SetupGetStringFieldW(
5813 &ContextManufacturer
,
5814 1, /* Field index */
5815 ManufacturerSection
, LINE_LEN
,
5819 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5820 /* Add (possible) extension to manufacturer section name */
5821 Result
= SetupDiGetActualSectionToInstallW(
5822 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5825 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
5826 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5831 if (DriverType
== SPDIT_CLASSDRIVER
)
5833 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5834 if (!AddDriverToList(
5835 &list
->DriverListHead
,
5839 currentInfFileDetails
,
5844 DriverDate
, DriverVersion
,
5850 else /* DriverType = SPDIT_COMPATDRIVER */
5852 /* 1. Get all fields */
5853 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5857 BOOL DriverAlreadyAdded
;
5859 for (i
= 2; i
<= FieldCount
; i
++)
5861 LPWSTR DeviceId
= NULL
;
5863 RequiredSize
= 128; /* Initial buffer size */
5864 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5865 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5867 HeapFree(GetProcessHeap(), 0, DeviceId
);
5868 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5871 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5874 Result
= SetupGetStringFieldW(
5877 DeviceId
, RequiredSize
,
5882 HeapFree(GetProcessHeap(), 0, DeviceId
);
5885 DriverAlreadyAdded
= FALSE
;
5886 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5888 if (wcsicmp(DeviceId
, currentId
) == 0)
5891 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5895 currentInfFileDetails
,
5900 DriverDate
, DriverVersion
,
5901 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5902 DriverAlreadyAdded
= TRUE
;
5907 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5909 if (wcsicmp(DeviceId
, currentId
) == 0)
5912 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5916 currentInfFileDetails
,
5921 DriverDate
, DriverVersion
,
5922 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5923 DriverAlreadyAdded
= TRUE
;
5927 HeapFree(GetProcessHeap(), 0, DeviceId
);
5930 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5933 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5934 ManufacturerName
= NULL
;
5935 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5940 HeapFree(GetProcessHeap(), 0, ProviderName
);
5941 ProviderName
= NULL
;
5943 DereferenceInfFile(currentInfFileDetails
);
5944 currentInfFileDetails
= NULL
;
5955 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5956 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5960 InstallParams
.Flags
|= DI_DIDCLASS
;
5961 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5963 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5966 HeapFree(GetProcessHeap(), 0, ProviderName
);
5967 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5968 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5969 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5970 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5971 if (currentInfFileDetails
)
5972 DereferenceInfFile(currentInfFileDetails
);
5973 HeapFree(GetProcessHeap(), 0, Buffer
);
5975 TRACE("Returning %d\n", ret
);
5979 /***********************************************************************
5980 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5983 SetupDiDeleteDeviceInfo(
5984 IN HDEVINFO DeviceInfoSet
,
5985 IN PSP_DEVINFO_DATA DeviceInfoData
)
5987 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5989 FIXME("not implemented\n");
5990 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5995 /***********************************************************************
5996 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5999 SetupDiDestroyDriverInfoList(
6000 IN HDEVINFO DeviceInfoSet
,
6001 IN PSP_DEVINFO_DATA DeviceInfoData
,
6002 IN DWORD DriverType
)
6004 struct DeviceInfoSet
*list
;
6007 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
6010 SetLastError(ERROR_INVALID_HANDLE
);
6011 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6012 SetLastError(ERROR_INVALID_HANDLE
);
6013 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6014 SetLastError(ERROR_INVALID_PARAMETER
);
6015 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6016 SetLastError(ERROR_INVALID_PARAMETER
);
6017 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6018 SetLastError(ERROR_INVALID_USER_BUFFER
);
6021 PLIST_ENTRY ListEntry
;
6022 struct DriverInfoElement
*driverInfo
;
6023 SP_DEVINSTALL_PARAMS_W InstallParams
;
6025 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6026 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6029 if (!DeviceInfoData
)
6030 /* Fall back to destroying class driver list */
6031 DriverType
= SPDIT_CLASSDRIVER
;
6033 if (DriverType
== SPDIT_CLASSDRIVER
)
6035 while (!IsListEmpty(&list
->DriverListHead
))
6037 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
6038 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
6039 DestroyDriverInfoElement(driverInfo
);
6041 InstallParams
.Reserved
= 0;
6042 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
6043 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
6044 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
6048 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
6049 struct DeviceInfoElement
*deviceInfo
;
6051 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6052 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
6054 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6055 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
6057 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
6058 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
6059 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
6061 InstallParamsSet
.Reserved
= 0;
6062 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
6064 DestroyDriverInfoElement(driverInfo
);
6066 InstallParams
.Reserved
= 0;
6067 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
6068 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
6069 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6074 TRACE("Returning %d\n", ret
);
6079 /***********************************************************************
6080 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
6083 SetupDiOpenDeviceInfoA(
6084 IN HDEVINFO DeviceInfoSet
,
6085 IN PCSTR DeviceInstanceId
,
6086 IN HWND hwndParent OPTIONAL
,
6088 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6090 LPWSTR DeviceInstanceIdW
= NULL
;
6093 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
6095 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
6096 if (DeviceInstanceIdW
== NULL
)
6099 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
6100 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
6102 MyFree(DeviceInstanceIdW
);
6108 /***********************************************************************
6109 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
6112 SetupDiOpenDeviceInfoW(
6113 IN HDEVINFO DeviceInfoSet
,
6114 IN PCWSTR DeviceInstanceId
,
6115 IN HWND hwndParent OPTIONAL
,
6117 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6119 struct DeviceInfoSet
*list
;
6120 HKEY hEnumKey
, hKey
;
6124 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
6126 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
6127 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
6130 SetLastError(ERROR_INVALID_HANDLE
);
6131 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6132 SetLastError(ERROR_INVALID_HANDLE
);
6133 else if (!DeviceInstanceId
)
6134 SetLastError(ERROR_INVALID_PARAMETER
);
6135 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
6137 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
6138 SetLastError(ERROR_INVALID_FLAGS
);
6140 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6141 SetLastError(ERROR_INVALID_USER_BUFFER
);
6144 struct DeviceInfoElement
*deviceInfo
= NULL
;
6145 /* Search if device already exists in DeviceInfoSet.
6146 * If yes, return the existing element
6147 * If no, create a new element using informations in registry
6149 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
6150 while (ItemList
!= &list
->ListHead
)
6155 FIXME("not implemented\n");
6156 ItemList
= ItemList
->Flink
;
6161 /* good one found */
6166 /* Open supposed registry key */
6169 REGSTR_PATH_SYSTEMENUM
,
6173 if (rc
!= ERROR_SUCCESS
)
6184 RegCloseKey(hEnumKey
);
6185 if (rc
!= ERROR_SUCCESS
)
6187 if (rc
== ERROR_FILE_NOT_FOUND
)
6188 rc
= ERROR_NO_SUCH_DEVINST
;
6193 /* FIXME: try to get ClassGUID from registry, instead of
6194 * sending GUID_NULL to CreateDeviceInfoElement
6196 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
6201 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
6207 if (ret
&& deviceInfo
&& DeviceInfoData
)
6209 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
6210 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
6211 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
6219 /***********************************************************************
6220 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6223 SetupDiEnumDriverInfoA(
6224 IN HDEVINFO DeviceInfoSet
,
6225 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6226 IN DWORD DriverType
,
6227 IN DWORD MemberIndex
,
6228 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6230 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6233 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6234 DriverType
, MemberIndex
, DriverInfoData
);
6236 if (DriverInfoData
== NULL
)
6237 SetLastError(ERROR_INVALID_PARAMETER
);
6238 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6239 SetLastError(ERROR_INVALID_USER_BUFFER
);
6242 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6243 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
6244 DriverType
, MemberIndex
, &driverInfoData2W
);
6248 /* Do W->A conversion */
6249 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6250 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6251 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6252 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6254 DriverInfoData
->Description
[0] = '\0';
6257 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6258 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6260 DriverInfoData
->MfgName
[0] = '\0';
6263 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6264 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6266 DriverInfoData
->ProviderName
[0] = '\0';
6269 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6271 /* Copy more fields */
6272 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6273 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6278 TRACE("Returning %d\n", ret
);
6283 /***********************************************************************
6284 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6287 SetupDiEnumDriverInfoW(
6288 IN HDEVINFO DeviceInfoSet
,
6289 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6290 IN DWORD DriverType
,
6291 IN DWORD MemberIndex
,
6292 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6294 PLIST_ENTRY ListHead
;
6297 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6298 DriverType
, MemberIndex
, DriverInfoData
);
6300 if (!DeviceInfoSet
|| !DriverInfoData
)
6301 SetLastError(ERROR_INVALID_PARAMETER
);
6302 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6303 SetLastError(ERROR_INVALID_HANDLE
);
6304 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6305 SetLastError(ERROR_INVALID_HANDLE
);
6306 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6307 SetLastError(ERROR_INVALID_PARAMETER
);
6308 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
6309 SetLastError(ERROR_INVALID_PARAMETER
);
6310 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6311 SetLastError(ERROR_INVALID_PARAMETER
);
6312 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6313 SetLastError(ERROR_INVALID_USER_BUFFER
);
6316 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6317 PLIST_ENTRY ItemList
;
6318 if (DriverType
== SPDIT_CLASSDRIVER
||
6319 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
6321 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6325 ListHead
= &devInfo
->DriverListHead
;
6328 ItemList
= ListHead
->Flink
;
6329 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
6330 ItemList
= ItemList
->Flink
;
6331 if (ItemList
== ListHead
)
6332 SetLastError(ERROR_NO_MORE_ITEMS
);
6335 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
6338 &DriverInfoData
->DriverType
,
6339 &DrvInfo
->Info
.DriverType
,
6340 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6345 TRACE("Returning %d\n", ret
);
6350 /***********************************************************************
6351 * SetupDiGetSelectedDevice (SETUPAPI.@)
6354 SetupDiGetSelectedDevice(
6355 IN HDEVINFO DeviceInfoSet
,
6356 OUT PSP_DEVINFO_DATA DeviceInfoData
)
6358 struct DeviceInfoSet
*list
;
6361 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6364 SetLastError(ERROR_INVALID_HANDLE
);
6365 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6366 SetLastError(ERROR_INVALID_HANDLE
);
6367 else if (list
->SelectedDevice
== NULL
)
6368 SetLastError(ERROR_NO_DEVICE_SELECTED
);
6369 else if (!DeviceInfoData
)
6370 SetLastError(ERROR_INVALID_PARAMETER
);
6371 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6372 SetLastError(ERROR_INVALID_USER_BUFFER
);
6375 memcpy(&DeviceInfoData
->ClassGuid
,
6376 &list
->SelectedDevice
->ClassGuid
,
6378 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
6379 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
6383 TRACE("Returning %d\n", ret
);
6388 /***********************************************************************
6389 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6392 SetupDiGetSelectedDriverA(
6393 IN HDEVINFO DeviceInfoSet
,
6394 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6395 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6397 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6400 if (DriverInfoData
== NULL
)
6401 SetLastError(ERROR_INVALID_PARAMETER
);
6402 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6403 SetLastError(ERROR_INVALID_USER_BUFFER
);
6406 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6408 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
6414 /* Do W->A conversion */
6415 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6416 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6417 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6418 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6420 DriverInfoData
->Description
[0] = '\0';
6423 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6424 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6426 DriverInfoData
->MfgName
[0] = '\0';
6429 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6430 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6432 DriverInfoData
->ProviderName
[0] = '\0';
6435 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6437 /* Copy more fields */
6438 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6439 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6448 /***********************************************************************
6449 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6452 SetupDiGetSelectedDriverW(
6453 IN HDEVINFO DeviceInfoSet
,
6454 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6455 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6459 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6461 if (!DeviceInfoSet
|| !DriverInfoData
)
6462 SetLastError(ERROR_INVALID_PARAMETER
);
6463 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6464 SetLastError(ERROR_INVALID_HANDLE
);
6465 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6466 SetLastError(ERROR_INVALID_HANDLE
);
6467 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6468 SetLastError(ERROR_INVALID_USER_BUFFER
);
6469 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6470 SetLastError(ERROR_INVALID_USER_BUFFER
);
6473 SP_DEVINSTALL_PARAMS InstallParams
;
6475 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
6476 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6478 struct DriverInfoElement
*driverInfo
;
6479 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6480 if (driverInfo
== NULL
)
6481 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6485 &DriverInfoData
->DriverType
,
6486 &driverInfo
->Info
.DriverType
,
6487 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6493 TRACE("Returning %d\n", ret
);
6498 /***********************************************************************
6499 * SetupDiSetSelectedDevice (SETUPAPI.@)
6502 SetupDiSetSelectedDevice(
6503 IN HDEVINFO DeviceInfoSet
,
6504 IN PSP_DEVINFO_DATA DeviceInfoData
)
6506 struct DeviceInfoSet
*list
;
6509 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6512 SetLastError(ERROR_INVALID_HANDLE
);
6513 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6514 SetLastError(ERROR_INVALID_HANDLE
);
6515 else if (!DeviceInfoData
)
6516 SetLastError(ERROR_INVALID_PARAMETER
);
6517 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6518 SetLastError(ERROR_INVALID_USER_BUFFER
);
6519 else if (DeviceInfoData
->Reserved
== 0)
6520 SetLastError(ERROR_INVALID_USER_BUFFER
);
6523 list
->SelectedDevice
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6527 TRACE("Returning %d\n", ret
);
6532 /***********************************************************************
6533 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6536 SetupDiSetSelectedDriverA(
6537 IN HDEVINFO DeviceInfoSet
,
6538 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6539 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6541 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6542 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6545 if (DriverInfoData
!= NULL
)
6547 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6548 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6550 SetLastError(ERROR_INVALID_PARAMETER
);
6554 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6555 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6557 if (DriverInfoDataW
.Reserved
== 0)
6559 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6561 /* convert the strings to unicode */
6562 if (!MultiByteToWideChar(CP_ACP
,
6564 DriverInfoData
->Description
,
6566 DriverInfoDataW
.Description
,
6568 !MultiByteToWideChar(CP_ACP
,
6570 DriverInfoData
->ProviderName
,
6572 DriverInfoDataW
.ProviderName
,
6579 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6582 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6586 if (ret
&& pDriverInfoDataW
!= NULL
)
6588 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6595 /***********************************************************************
6596 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6599 SetupDiSetSelectedDriverW(
6600 IN HDEVINFO DeviceInfoSet
,
6601 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6602 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6606 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6609 SetLastError(ERROR_INVALID_PARAMETER
);
6610 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6611 SetLastError(ERROR_INVALID_HANDLE
);
6612 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6613 SetLastError(ERROR_INVALID_HANDLE
);
6614 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6615 SetLastError(ERROR_INVALID_USER_BUFFER
);
6616 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6617 SetLastError(ERROR_INVALID_USER_BUFFER
);
6620 struct DriverInfoElement
**pDriverInfo
;
6621 PLIST_ENTRY ListHead
, ItemList
;
6625 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6626 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6630 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6631 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6634 if (!DriverInfoData
)
6636 *pDriverInfo
= NULL
;
6641 /* Search selected driver in list */
6642 ItemList
= ListHead
->Flink
;
6643 while (ItemList
!= ListHead
)
6645 if (DriverInfoData
->Reserved
!= 0)
6647 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6652 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6653 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
6654 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6655 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6656 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6662 if (ItemList
== ListHead
)
6663 SetLastError(ERROR_INVALID_PARAMETER
);
6666 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
6667 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6669 TRACE("Choosing driver whose rank is 0x%lx\n",
6670 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
6672 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6677 TRACE("Returning %d\n", ret
);
6681 /***********************************************************************
6682 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6685 SetupDiGetDriverInfoDetailA(
6686 IN HDEVINFO DeviceInfoSet
,
6687 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6688 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6689 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6690 IN DWORD DriverInfoDetailDataSize
,
6691 OUT PDWORD RequiredSize OPTIONAL
)
6693 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6694 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6696 DWORD HardwareIDLen
= 0;
6699 /* do some sanity checks, the unicode version might do more thorough checks */
6700 if (DriverInfoData
== NULL
||
6701 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6702 (DriverInfoDetailData
!= NULL
&&
6703 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6704 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6706 SetLastError(ERROR_INVALID_PARAMETER
);
6710 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6711 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6713 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6715 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6717 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6721 SetLastError(ERROR_INVALID_PARAMETER
);
6724 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6725 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6727 /* convert the strings to unicode */
6728 if (MultiByteToWideChar(CP_ACP
,
6730 DriverInfoData
->Description
,
6732 DriverInfoDataW
.Description
,
6734 MultiByteToWideChar(CP_ACP
,
6736 DriverInfoData
->MfgName
,
6738 DriverInfoDataW
.MfgName
,
6740 MultiByteToWideChar(CP_ACP
,
6742 DriverInfoData
->ProviderName
,
6744 DriverInfoDataW
.ProviderName
,
6747 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6749 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6750 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6753 if (DriverInfoDetailData
!= NULL
)
6755 /* calculate the unicode buffer size from the ansi buffer size */
6756 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6757 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6758 (HardwareIDLen
* sizeof(WCHAR
));
6760 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6761 if (DriverInfoDetailDataW
== NULL
)
6763 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6767 /* initialize the buffer */
6768 ZeroMemory(DriverInfoDetailDataW
,
6770 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6773 /* call the unicode version */
6774 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6777 DriverInfoDetailDataW
,
6783 if (DriverInfoDetailDataW
!= NULL
)
6785 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6786 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6787 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6788 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6789 if (WideCharToMultiByte(CP_ACP
,
6791 DriverInfoDetailDataW
->SectionName
,
6793 DriverInfoDetailData
->SectionName
,
6797 WideCharToMultiByte(CP_ACP
,
6799 DriverInfoDetailDataW
->InfFileName
,
6801 DriverInfoDetailData
->InfFileName
,
6805 WideCharToMultiByte(CP_ACP
,
6807 DriverInfoDetailDataW
->DrvDescription
,
6809 DriverInfoDetailData
->DrvDescription
,
6813 WideCharToMultiByte(CP_ACP
,
6815 DriverInfoDetailDataW
->HardwareID
,
6817 DriverInfoDetailData
->HardwareID
,
6823 DWORD hwidlen
= HardwareIDLen
;
6824 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6826 /* count the strings in the list */
6829 len
= lstrlenA(s
) + 1;
6838 /* looks like the string list wasn't terminated... */
6839 SetLastError(ERROR_INVALID_USER_BUFFER
);
6845 /* make sure CompatIDsOffset points to the second string in the
6849 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6850 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6851 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6855 DriverInfoDetailData
->CompatIDsOffset
= 0;
6856 DriverInfoDetailData
->CompatIDsLength
= 0;
6865 if (RequiredSize
!= NULL
)
6867 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6868 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6874 if (DriverInfoDetailDataW
!= NULL
)
6876 MyFree(DriverInfoDetailDataW
);
6882 /***********************************************************************
6883 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6886 SetupDiGetDriverInfoDetailW(
6887 IN HDEVINFO DeviceInfoSet
,
6888 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6889 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6890 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6891 IN DWORD DriverInfoDetailDataSize
,
6892 OUT PDWORD RequiredSize OPTIONAL
)
6896 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6897 DriverInfoData
, DriverInfoDetailData
,
6898 DriverInfoDetailDataSize
, RequiredSize
);
6901 SetLastError(ERROR_INVALID_PARAMETER
);
6902 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6903 SetLastError(ERROR_INVALID_HANDLE
);
6904 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6905 SetLastError(ERROR_INVALID_HANDLE
);
6906 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6907 SetLastError(ERROR_INVALID_USER_BUFFER
);
6908 else if (!DriverInfoData
)
6909 SetLastError(ERROR_INVALID_PARAMETER
);
6910 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6911 SetLastError(ERROR_INVALID_PARAMETER
);
6912 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6913 SetLastError(ERROR_INVALID_PARAMETER
);
6914 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6915 SetLastError(ERROR_INVALID_USER_BUFFER
);
6916 else if (DriverInfoData
->Reserved
== 0)
6917 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6920 struct DriverInfoElement
*driverInfoElement
;
6921 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6924 DriverInfoDetailData
,
6925 &driverInfoElement
->Details
,
6926 driverInfoElement
->Details
.cbSize
);
6927 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6928 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6933 TRACE("Returning %d\n", ret
);
6937 /* Return the current hardware profile id, or -1 if error */
6939 GetCurrentHwProfile(
6940 IN HDEVINFO DeviceInfoSet
)
6942 HKEY hKey
= INVALID_HANDLE_VALUE
;
6943 DWORD dwRegType
, dwLength
;
6946 DWORD ret
= (DWORD
)-1;
6949 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
6950 REGSTR_PATH_IDCONFIGDB
,
6954 if (rc
!= ERROR_SUCCESS
)
6960 dwLength
= sizeof(DWORD
);
6961 rc
= RegQueryValueExW(
6963 REGSTR_VAL_CURRENTCONFIG
,
6966 (LPBYTE
)&hwProfile
, &dwLength
);
6967 if (rc
!= ERROR_SUCCESS
)
6972 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6974 SetLastError(ERROR_GEN_FAILURE
);
6981 if (hKey
!= INVALID_HANDLE_VALUE
)
6989 IN HDEVINFO DeviceInfoSet
,
6990 IN PSP_DEVINFO_DATA DeviceInfoData
)
6992 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6993 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6996 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
6998 /* At the moment, I only know how to start local devices */
6999 SetLastError(ERROR_INVALID_COMPUTERNAME
);
7003 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
7004 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
7005 SetLastError(RtlNtStatusToDosError(Status
));
7006 return NT_SUCCESS(Status
);
7009 static BOOL
StopDevice(
7010 IN HDEVINFO DeviceInfoSet
,
7011 IN PSP_DEVINFO_DATA DeviceInfoData
)
7013 FIXME("Stub %p %p\n", DeviceInfoSet
, DeviceInfoData
);
7017 /***********************************************************************
7018 * SetupDiChangeState (SETUPAPI.@)
7022 IN HDEVINFO DeviceInfoSet
,
7023 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7025 PSP_PROPCHANGE_PARAMS PropChange
;
7026 HKEY hKey
= INVALID_HANDLE_VALUE
;
7027 LPCWSTR RegistryValueName
;
7028 DWORD dwConfigFlags
, dwLength
, dwRegType
;
7032 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7034 if (!DeviceInfoData
)
7035 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
7037 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
7040 SetLastError(ERROR_INVALID_PARAMETER
);
7044 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
7045 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
7047 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
7049 switch (PropChange
->StateChange
)
7054 /* Enable/disable device in registry */
7055 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
7056 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7057 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
7058 if (hKey
== INVALID_HANDLE_VALUE
)
7060 dwLength
= sizeof(DWORD
);
7061 rc
= RegQueryValueExW(
7066 (LPBYTE
)&dwConfigFlags
, &dwLength
);
7067 if (rc
== ERROR_FILE_NOT_FOUND
)
7069 else if (rc
!= ERROR_SUCCESS
)
7074 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
7076 SetLastError(ERROR_GEN_FAILURE
);
7079 if (PropChange
->StateChange
== DICS_ENABLE
)
7080 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
7082 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
7088 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
7089 if (rc
!= ERROR_SUCCESS
)
7095 /* Enable/disable device if needed */
7096 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
7097 || PropChange
->HwProfile
== 0
7098 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
7100 if (PropChange
->StateChange
== DICS_ENABLE
)
7101 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7103 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
7109 case DICS_PROPCHANGE
:
7111 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7116 FIXME("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
7117 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
7122 if (hKey
!= INVALID_HANDLE_VALUE
)
7125 TRACE("Returning %d\n", ret
);
7129 /***********************************************************************
7130 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
7133 SetupDiSelectBestCompatDrv(
7134 IN HDEVINFO DeviceInfoSet
,
7135 IN PSP_DEVINFO_DATA DeviceInfoData
)
7137 SP_DRVINFO_DATA_W drvInfoData
;
7140 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7142 /* Drivers are sorted by rank in the driver list, so
7143 * the first driver in the list is the best one.
7145 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
7146 ret
= SetupDiEnumDriverInfoW(
7150 0, /* Member index */
7155 ret
= SetupDiSetSelectedDriverW(
7161 TRACE("Returning %d\n", ret
);
7165 /***********************************************************************
7166 * SetupDiInstallDriverFiles (SETUPAPI.@)
7169 SetupDiInstallDriverFiles(
7170 IN HDEVINFO DeviceInfoSet
,
7171 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7175 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7178 SetLastError(ERROR_INVALID_PARAMETER
);
7179 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7180 SetLastError(ERROR_INVALID_HANDLE
);
7181 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7182 SetLastError(ERROR_INVALID_HANDLE
);
7183 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7184 SetLastError(ERROR_INVALID_USER_BUFFER
);
7185 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
7186 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7187 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
7188 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7191 SP_DEVINSTALL_PARAMS_W InstallParams
;
7192 struct DriverInfoElement
*SelectedDriver
;
7193 WCHAR SectionName
[MAX_PATH
];
7194 DWORD SectionNameLength
= 0;
7196 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7197 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7201 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7202 if (!SelectedDriver
)
7204 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7208 ret
= SetupDiGetActualSectionToInstallW(
7209 SelectedDriver
->InfFileDetails
->hInf
,
7210 SelectedDriver
->Details
.SectionName
,
7211 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7215 if (!InstallParams
.InstallMsgHandler
)
7217 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
7218 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7219 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7221 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7222 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7223 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7224 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7225 DeviceInfoSet
, DeviceInfoData
);
7229 TRACE("Returning %d\n", ret
);
7233 /***********************************************************************
7234 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7237 SetupDiRegisterCoDeviceInstallers(
7238 IN HDEVINFO DeviceInfoSet
,
7239 IN PSP_DEVINFO_DATA DeviceInfoData
)
7241 BOOL ret
= FALSE
; /* Return value */
7243 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7246 SetLastError(ERROR_INVALID_PARAMETER
);
7247 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7248 SetLastError(ERROR_INVALID_HANDLE
);
7249 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7250 SetLastError(ERROR_INVALID_HANDLE
);
7251 else if (!DeviceInfoData
)
7252 SetLastError(ERROR_INVALID_PARAMETER
);
7253 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7254 SetLastError(ERROR_INVALID_USER_BUFFER
);
7257 SP_DEVINSTALL_PARAMS_W InstallParams
;
7258 struct DriverInfoElement
*SelectedDriver
;
7261 WCHAR SectionName
[MAX_PATH
];
7262 DWORD SectionNameLength
= 0;
7263 HKEY hKey
= INVALID_HANDLE_VALUE
;
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
);
7277 /* Get .CoInstallers section name */
7278 Result
= SetupDiGetActualSectionToInstallW(
7279 SelectedDriver
->InfFileDetails
->hInf
,
7280 SelectedDriver
->Details
.SectionName
,
7281 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7282 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".CoInstallers") - 1)
7284 wcscat(SectionName
, L
".CoInstallers");
7286 /* Open/Create driver key information */
7287 #if _WIN32_WINNT >= 0x502
7288 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7290 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7292 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7293 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7294 if (hKey
== INVALID_HANDLE_VALUE
)
7297 /* Install .CoInstallers section */
7298 DoAction
= SPINST_REGISTRY
;
7299 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7301 DoAction
|= SPINST_FILES
;
7302 if (!InstallParams
.InstallMsgHandler
)
7304 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
7305 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7306 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7309 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7310 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7311 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7312 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7313 DeviceInfoSet
, DeviceInfoData
);
7320 if (hKey
!= INVALID_HANDLE_VALUE
)
7324 TRACE("Returning %d\n", ret
);
7328 /***********************************************************************
7329 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7332 SetupDiInstallDeviceInterfaces(
7333 IN HDEVINFO DeviceInfoSet
,
7334 IN PSP_DEVINFO_DATA DeviceInfoData
)
7336 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7338 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
7339 //SetLastError(ERROR_GEN_FAILURE);
7345 InfIsFromOEMLocation(
7347 OUT LPBOOL IsOEMLocation
)
7351 last
= strrchrW(FullName
, '\\');
7354 /* No directory specified */
7355 *IsOEMLocation
= FALSE
;
7359 WCHAR Windir
[MAX_PATH
];
7362 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
7363 if (ret
== 0 || ret
>= MAX_PATH
)
7365 SetLastError(ERROR_GEN_FAILURE
);
7369 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
7371 /* The path is %SYSTEMROOT%\Inf */
7372 *IsOEMLocation
= FALSE
;
7376 /* The file is in another place */
7377 *IsOEMLocation
= TRUE
;
7383 /***********************************************************************
7384 * SetupDiInstallDevice (SETUPAPI.@)
7387 SetupDiInstallDevice(
7388 IN HDEVINFO DeviceInfoSet
,
7389 IN PSP_DEVINFO_DATA DeviceInfoData
)
7391 SP_DEVINSTALL_PARAMS_W InstallParams
;
7392 struct DriverInfoElement
*SelectedDriver
;
7393 SYSTEMTIME DriverDate
;
7394 WCHAR SectionName
[MAX_PATH
];
7396 DWORD SectionNameLength
= 0;
7397 BOOL Result
= FALSE
;
7400 LPCWSTR AssociatedService
= NULL
;
7401 LPWSTR pSectionName
= NULL
;
7402 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
7404 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
7405 BOOL RebootRequired
= FALSE
;
7406 HKEY hKey
= INVALID_HANDLE_VALUE
;
7407 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
7408 BOOL NeedtoCopyFile
;
7409 LARGE_INTEGER fullVersion
;
7411 BOOL ret
= FALSE
; /* Return value */
7413 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7416 SetLastError(ERROR_INVALID_PARAMETER
);
7417 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7418 SetLastError(ERROR_INVALID_HANDLE
);
7419 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7420 SetLastError(ERROR_INVALID_HANDLE
);
7421 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7422 SetLastError(ERROR_INVALID_USER_BUFFER
);
7428 /* One parameter is bad */
7432 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7433 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7437 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
7439 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
7443 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7444 if (SelectedDriver
== NULL
)
7446 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7450 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
7452 Result
= SetupDiGetActualSectionToInstallW(
7453 SelectedDriver
->InfFileDetails
->hInf
,
7454 SelectedDriver
->Details
.SectionName
,
7455 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7456 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(DotServices
))
7458 pSectionName
= &SectionName
[wcslen(SectionName
)];
7460 /* Get information from [Version] section */
7461 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
7463 /* Format ClassGuid to a string */
7464 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
7466 RequiredSize
= lstrlenW(lpGuidString
);
7467 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
7468 if (!lpFullGuidString
)
7470 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7473 lpFullGuidString
[0] = '{';
7474 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
7475 lpFullGuidString
[RequiredSize
+ 1] = '}';
7476 lpFullGuidString
[RequiredSize
+ 2] = '\0';
7478 /* Open/Create driver key information */
7479 #if _WIN32_WINNT >= 0x502
7480 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7482 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7484 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7485 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7486 if (hKey
== INVALID_HANDLE_VALUE
)
7489 /* Install main section */
7490 DoAction
= SPINST_REGISTRY
;
7491 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7493 DoAction
|= SPINST_FILES
;
7494 if (!InstallParams
.InstallMsgHandler
)
7496 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
7497 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7498 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7501 *pSectionName
= '\0';
7502 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7503 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7504 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7505 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7506 DeviceInfoSet
, DeviceInfoData
);
7509 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
7511 if (Result
&& InstallParams
.InstallMsgHandler
== SetupDefaultQueueCallbackW
)
7513 /* Delete resources allocated by SetupInitDefaultQueueCallback */
7514 SetupTermDefaultQueueCallback(InstallParams
.InstallMsgHandlerContext
);
7517 InstallParams
.Flags
|= DI_NOFILECOPY
;
7518 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7520 /* Write information to driver key */
7521 *pSectionName
= UNICODE_NULL
;
7522 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
7523 TRACE("Write information to driver key\n");
7524 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7525 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7526 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7527 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
7528 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
7529 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
7530 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
7531 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
7532 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7533 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7534 if (rc
== ERROR_SUCCESS
)
7535 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7536 if (rc
== ERROR_SUCCESS
)
7537 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7538 if (rc
== ERROR_SUCCESS
)
7540 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7541 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7543 if (rc
== ERROR_SUCCESS
)
7544 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7545 if (rc
== ERROR_SUCCESS
)
7546 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7547 if (rc
== ERROR_SUCCESS
)
7548 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7549 if (rc
== ERROR_SUCCESS
)
7550 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7551 if (rc
== ERROR_SUCCESS
)
7552 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7553 if (rc
!= ERROR_SUCCESS
)
7559 hKey
= INVALID_HANDLE_VALUE
;
7561 /* FIXME: Process .LogConfigOverride section */
7563 /* Install .Services section */
7564 wcscpy(pSectionName
, DotServices
);
7565 Result
= InstallServicesSection(
7566 SelectedDriver
->InfFileDetails
->hInf
,
7575 /* Copy .inf file to Inf\ directory (if needed) */
7576 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7581 Result
= SetupCopyOEMInfW(
7582 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7585 SP_COPY_NOOVERWRITE
,
7591 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7592 * to release use of current InfFile */
7595 /* Open device registry key */
7596 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7597 if (hKey
== INVALID_HANDLE_VALUE
)
7600 /* Install .HW section */
7601 wcscpy(pSectionName
, L
".HW");
7602 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7603 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7604 SPINST_REGISTRY
, hKey
, NULL
, 0,
7605 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7606 DeviceInfoSet
, DeviceInfoData
);
7610 /* Write information to enum key */
7611 TRACE("Write information to enum key\n");
7612 TRACE("Class : '%S'\n", ClassName
);
7613 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
7614 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7615 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
7616 TRACE("Service : '%S'\n", AssociatedService
);
7617 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
7618 if (rc
== ERROR_SUCCESS
)
7619 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7620 if (rc
== ERROR_SUCCESS
)
7621 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7622 if (rc
== ERROR_SUCCESS
)
7623 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7624 if (rc
== ERROR_SUCCESS
&& AssociatedService
&& *AssociatedService
)
7625 rc
= RegSetValueEx(hKey
, REGSTR_VAL_SERVICE
, 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
7626 if (rc
!= ERROR_SUCCESS
)
7632 /* Start the device */
7633 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7634 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7639 /* End of installation */
7640 if (hClassKey
!= INVALID_HANDLE_VALUE
)
7641 RegCloseKey(hClassKey
);
7642 if (hKey
!= INVALID_HANDLE_VALUE
)
7645 RpcStringFreeW(&lpGuidString
);
7646 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
7647 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7649 TRACE("Returning %d\n", ret
);