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 InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
33 static const WCHAR NoDisplayClass
[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
34 static const WCHAR NoInstallClass
[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0};
35 static const WCHAR NoUseClass
[] = {'N','o','U','s','e','C','l','a','s','s',0};
36 static const WCHAR NtExtension
[] = {'.','N','T',0};
37 static const WCHAR NtPlatformExtension
[] = {'.','N','T','x','8','6',0};
38 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
39 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
40 static const WCHAR WinExtension
[] = {'.','W','i','n',0};
42 /* Registry key and value names */
43 static const WCHAR ControlClass
[] = {'S','y','s','t','e','m','\\',
44 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
45 'C','o','n','t','r','o','l','\\',
46 'C','l','a','s','s',0};
48 static const WCHAR DeviceClasses
[] = {'S','y','s','t','e','m','\\',
49 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
50 'C','o','n','t','r','o','l','\\',
51 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
53 static const WCHAR EnumKeyName
[] = {'S','y','s','t','e','m','\\',
54 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
58 /* FIXME: header mess */
59 DEFINE_GUID(GUID_NULL
,
60 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
62 (CALLBACK
* CLASS_INSTALL_PROC
) (
63 IN DI_FUNCTION InstallFunction
,
64 IN HDEVINFO DeviceInfoSet
,
65 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
67 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
68 IN HDEVINFO DeviceInfoSet
,
69 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
71 (CALLBACK
* COINSTALLER_PROC
) (
72 IN DI_FUNCTION InstallFunction
,
73 IN HDEVINFO DeviceInfoSet
,
74 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
75 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
77 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
78 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
79 IN LPFNADDPROPSHEETPAGE fAddFunc
,
82 (*UPDATE_CLASS_PARAM_HANDLER
) (
83 IN HDEVINFO DeviceInfoSet
,
84 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
85 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
86 IN DWORD ClassInstallParamsSize
);
88 struct CoInstallerElement
93 COINSTALLER_PROC Function
;
94 BOOL DoPostProcessing
;
99 PropertyChangeHandler(
100 IN HDEVINFO DeviceInfoSet
,
101 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
102 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
103 IN DWORD ClassInstallParamsSize
);
105 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
106 NULL
, /* DIF_SELECTDEVICE */
107 NULL
, /* DIF_INSTALLDEVICE */
108 NULL
, /* DIF_ASSIGNRESOURCES */
109 NULL
, /* DIF_PROPERTIES */
110 NULL
, /* DIF_REMOVE */
111 NULL
, /* DIF_FIRSTTIMESETUP */
112 NULL
, /* DIF_FOUNDDEVICE */
113 NULL
, /* DIF_SELECTCLASSDRIVERS */
114 NULL
, /* DIF_VALIDATECLASSDRIVERS */
115 NULL
, /* DIF_INSTALLCLASSDRIVERS */
116 NULL
, /* DIF_CALCDISKSPACE */
117 NULL
, /* DIF_DESTROYPRIVATEDATA */
118 NULL
, /* DIF_VALIDATEDRIVER */
119 NULL
, /* DIF_MOVEDEVICE */
120 NULL
, /* DIF_DETECT */
121 NULL
, /* DIF_INSTALLWIZARD */
122 NULL
, /* DIF_DESTROYWIZARDDATA */
123 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
124 NULL
, /* DIF_ENABLECLASS */
125 NULL
, /* DIF_DETECTVERIFY */
126 NULL
, /* DIF_INSTALLDEVICEFILES */
127 NULL
, /* DIF_UNREMOVE */
128 NULL
, /* DIF_SELECTBESTCOMPATDRV */
129 NULL
, /* DIF_ALLOW_INSTALL */
130 NULL
, /* DIF_REGISTERDEVICE */
131 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
132 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
133 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
134 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
135 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
136 NULL
, /* DIF_UNUSED1 */
137 NULL
, /* DIF_INSTALLINTERFACES */
138 NULL
, /* DIF_DETECTCANCEL */
139 NULL
, /* DIF_REGISTER_COINSTALLERS */
140 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
141 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
142 NULL
, /* DIF_RESERVED1 */
143 NULL
, /* DIF_TROUBLESHOOTER */
144 NULL
, /* DIF_POWERMESSAGEWAKE */
145 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
146 NULL
, /* DIF_UPDATEDRIVER_UI */
147 NULL
/* DIF_RESERVED2 */
150 /***********************************************************************
151 * SetupDiBuildClassInfoList (SETUPAPI.@)
153 BOOL WINAPI
SetupDiBuildClassInfoList(
155 LPGUID ClassGuidList
,
156 DWORD ClassGuidListSize
,
160 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
161 ClassGuidListSize
, RequiredSize
,
165 /***********************************************************************
166 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
168 BOOL WINAPI
SetupDiBuildClassInfoListExA(
170 LPGUID ClassGuidList
,
171 DWORD ClassGuidListSize
,
176 LPWSTR MachineNameW
= NULL
;
183 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
184 if (MachineNameW
== NULL
) return FALSE
;
187 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
188 ClassGuidListSize
, RequiredSize
,
189 MachineNameW
, Reserved
);
192 MyFree(MachineNameW
);
197 /***********************************************************************
198 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
200 BOOL WINAPI
SetupDiBuildClassInfoListExW(
202 LPGUID ClassGuidList
,
203 DWORD ClassGuidListSize
,
208 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
214 DWORD dwGuidListIndex
= 0;
216 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
217 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
219 if (RequiredSize
!= NULL
)
222 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
223 KEY_ENUMERATE_SUB_KEYS
,
227 if (hClassesKey
== INVALID_HANDLE_VALUE
)
232 for (dwIndex
= 0; ; dwIndex
++)
234 dwLength
= MAX_GUID_STRING_LEN
+ 1;
235 lError
= RegEnumKeyExW(hClassesKey
,
243 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
244 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
246 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
248 if (RegOpenKeyExW(hClassesKey
,
254 RegCloseKey(hClassesKey
);
258 if (!RegQueryValueExW(hClassKey
,
265 TRACE("'NoUseClass' value found!\n");
266 RegCloseKey(hClassKey
);
270 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
271 (!RegQueryValueExW(hClassKey
,
278 TRACE("'NoInstallClass' value found!\n");
279 RegCloseKey(hClassKey
);
283 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
284 (!RegQueryValueExW(hClassKey
,
291 TRACE("'NoDisplayClass' value found!\n");
292 RegCloseKey(hClassKey
);
296 RegCloseKey(hClassKey
);
298 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
299 if (dwGuidListIndex
< ClassGuidListSize
)
301 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
305 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
307 UuidFromStringW(&szKeyName
[1],
308 &ClassGuidList
[dwGuidListIndex
]);
314 if (lError
!= ERROR_SUCCESS
)
318 RegCloseKey(hClassesKey
);
320 if (RequiredSize
!= NULL
)
321 *RequiredSize
= dwGuidListIndex
;
323 if (ClassGuidListSize
< dwGuidListIndex
)
325 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
332 /***********************************************************************
333 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
335 BOOL WINAPI
SetupDiClassGuidsFromNameA(
337 LPGUID ClassGuidList
,
338 DWORD ClassGuidListSize
,
341 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
342 ClassGuidListSize
, RequiredSize
,
346 /***********************************************************************
347 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
349 BOOL WINAPI
SetupDiClassGuidsFromNameW(
351 LPGUID ClassGuidList
,
352 DWORD ClassGuidListSize
,
355 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
356 ClassGuidListSize
, RequiredSize
,
360 /***********************************************************************
361 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
363 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
365 LPGUID ClassGuidList
,
366 DWORD ClassGuidListSize
,
371 LPWSTR ClassNameW
= NULL
;
372 LPWSTR MachineNameW
= NULL
;
377 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
378 if (ClassNameW
== NULL
)
383 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
384 if (MachineNameW
== NULL
)
391 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
392 ClassGuidListSize
, RequiredSize
,
393 MachineNameW
, Reserved
);
396 MyFree(MachineNameW
);
403 /***********************************************************************
404 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
406 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
408 LPGUID ClassGuidList
,
409 DWORD ClassGuidListSize
,
414 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
415 WCHAR szClassName
[256];
421 DWORD dwGuidListIndex
= 0;
423 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
424 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
426 if (RequiredSize
!= NULL
)
429 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
430 KEY_ENUMERATE_SUB_KEYS
,
434 if (hClassesKey
== INVALID_HANDLE_VALUE
)
439 for (dwIndex
= 0; ; dwIndex
++)
441 dwLength
= MAX_GUID_STRING_LEN
+ 1;
442 lError
= RegEnumKeyExW(hClassesKey
,
450 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
451 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
453 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
455 if (RegOpenKeyExW(hClassesKey
,
461 RegCloseKey(hClassesKey
);
465 dwLength
= 256 * sizeof(WCHAR
);
466 if (!RegQueryValueExW(hClassKey
,
473 TRACE("Class name: %s\n", debugstr_w(szClassName
));
475 if (strcmpiW(szClassName
, ClassName
) == 0)
477 TRACE("Found matching class name\n");
479 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
480 if (dwGuidListIndex
< ClassGuidListSize
)
482 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
486 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
488 UuidFromStringW(&szKeyName
[1],
489 &ClassGuidList
[dwGuidListIndex
]);
496 RegCloseKey(hClassKey
);
499 if (lError
!= ERROR_SUCCESS
)
503 RegCloseKey(hClassesKey
);
505 if (RequiredSize
!= NULL
)
506 *RequiredSize
= dwGuidListIndex
;
508 if (ClassGuidListSize
< dwGuidListIndex
)
510 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
517 /***********************************************************************
518 * SetupDiClassNameFromGuidA (SETUPAPI.@)
520 BOOL WINAPI
SetupDiClassNameFromGuidA(
521 const GUID
* ClassGuid
,
526 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
527 ClassNameSize
, RequiredSize
,
531 /***********************************************************************
532 * SetupDiClassNameFromGuidW (SETUPAPI.@)
534 BOOL WINAPI
SetupDiClassNameFromGuidW(
535 const GUID
* ClassGuid
,
540 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
541 ClassNameSize
, RequiredSize
,
545 /***********************************************************************
546 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
548 BOOL WINAPI
SetupDiClassNameFromGuidExA(
549 const GUID
* ClassGuid
,
556 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
557 LPWSTR MachineNameW
= NULL
;
561 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
562 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
563 NULL
, MachineNameW
, Reserved
);
566 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
567 ClassNameSize
, NULL
, NULL
);
569 if (!ClassNameSize
&& RequiredSize
)
572 MyFree(MachineNameW
);
576 /***********************************************************************
577 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
579 BOOL WINAPI
SetupDiClassNameFromGuidExW(
580 const GUID
* ClassGuid
,
591 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
592 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
594 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
599 if (hKey
== INVALID_HANDLE_VALUE
)
604 if (RequiredSize
!= NULL
)
607 rc
= RegQueryValueExW(hKey
,
613 if (rc
!= ERROR_SUCCESS
)
620 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
623 dwLength
= ClassNameSize
* sizeof(WCHAR
);
624 rc
= RegQueryValueExW(hKey
,
630 if (rc
!= ERROR_SUCCESS
)
642 /***********************************************************************
643 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
646 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
649 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
652 /***********************************************************************
653 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
656 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
661 LPWSTR MachineNameW
= NULL
;
664 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
665 debugstr_a(MachineName
), Reserved
);
669 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
670 if (MachineNameW
== NULL
)
671 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
674 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
675 MachineNameW
, Reserved
);
678 MyFree(MachineNameW
);
684 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
688 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
689 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
690 case CR_SUCCESS
: return ERROR_SUCCESS
;
693 return ERROR_GEN_FAILURE
;
696 /* Does not happen */
699 /***********************************************************************
700 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
703 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
708 struct DeviceInfoSet
*list
;
709 LPWSTR UNCServerName
= NULL
;
713 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
715 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
716 debugstr_w(MachineName
), Reserved
);
718 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
720 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
721 list
= HeapAlloc(GetProcessHeap(), 0, size
);
724 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
727 memset(list
, 0, sizeof(struct DeviceInfoSet
));
729 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
732 ClassGuid
? ClassGuid
: &GUID_NULL
,
733 sizeof(list
->ClassGuid
));
734 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
735 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
736 list
->InstallParams
.hwndParent
= hwndParent
;
739 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
740 if (rc
!= ERROR_SUCCESS
)
745 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
748 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
752 strcpyW(UNCServerName
+ 2, MachineName
);
753 list
->szData
[0] = list
->szData
[1] = '\\';
754 strcpyW(list
->szData
+ 2, MachineName
);
755 list
->MachineName
= list
->szData
;
759 DWORD Size
= MAX_PATH
;
760 list
->HKLM
= HKEY_LOCAL_MACHINE
;
761 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
764 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
767 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
769 list
->MachineName
= NULL
;
772 UNCServerName
[0] = UNCServerName
[1] = '\\';
773 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
774 if (cr
!= CR_SUCCESS
)
776 SetLastError(GetErrorCodeFromCrCode(cr
));
780 InitializeListHead(&list
->DriverListHead
);
781 InitializeListHead(&list
->ListHead
);
783 ret
= (HDEVINFO
)list
;
786 if (ret
== INVALID_HANDLE_VALUE
)
788 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
789 RegCloseKey(list
->HKLM
);
790 HeapFree(GetProcessHeap(), 0, list
);
792 HeapFree(GetProcessHeap(), 0, UNCServerName
);
796 /***********************************************************************
797 * SetupDiEnumDeviceInfo (SETUPAPI.@)
799 BOOL WINAPI
SetupDiEnumDeviceInfo(
800 HDEVINFO DeviceInfoSet
,
802 PSP_DEVINFO_DATA DeviceInfoData
)
806 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
808 SetLastError(ERROR_INVALID_PARAMETER
);
809 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
811 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
813 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
814 SetLastError(ERROR_INVALID_HANDLE
);
815 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
816 SetLastError(ERROR_INVALID_USER_BUFFER
);
819 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
820 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
821 ItemList
= ItemList
->Flink
;
822 if (ItemList
== &list
->ListHead
)
823 SetLastError(ERROR_NO_MORE_ITEMS
);
826 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
827 memcpy(&DeviceInfoData
->ClassGuid
,
830 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
831 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
837 SetLastError(ERROR_INVALID_HANDLE
);
841 /***********************************************************************
842 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
844 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
846 PCSTR InfSectionName
,
847 PSTR InfSectionWithExt
,
848 DWORD InfSectionWithExtSize
,
852 LPWSTR InfSectionNameW
= NULL
;
853 PWSTR InfSectionWithExtW
= NULL
;
855 BOOL bResult
= FALSE
;
861 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
862 if (InfSectionNameW
== NULL
) goto end
;
864 if (InfSectionWithExt
)
866 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
867 if (InfSectionWithExtW
== NULL
) goto end
;
870 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
871 InfSectionWithExt
? InfSectionNameW
: NULL
,
872 InfSectionWithExtSize
, RequiredSize
,
873 Extension
? &ExtensionW
: NULL
);
875 if (bResult
&& InfSectionWithExt
)
877 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
878 InfSectionWithExtSize
, NULL
, NULL
) != 0;
880 if (bResult
&& Extension
)
882 if (ExtensionW
== NULL
)
885 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
889 if (InfSectionNameW
) MyFree(InfSectionNameW
);
890 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
895 /***********************************************************************
896 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
898 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
900 PCWSTR InfSectionName
,
901 PWSTR InfSectionWithExt
,
902 DWORD InfSectionWithExtSize
,
906 WCHAR szBuffer
[MAX_PATH
];
909 LONG lLineCount
= -1;
911 TRACE("%p %s %p %lu %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
912 InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
, Extension
);
914 lstrcpyW(szBuffer
, InfSectionName
);
915 dwLength
= lstrlenW(szBuffer
);
917 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
919 /* Test section name with '.NTx86' extension */
920 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
921 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
923 if (lLineCount
== -1)
925 /* Test section name with '.NT' extension */
926 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
927 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
932 /* Test section name with '.Win' extension */
933 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
934 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
937 if (lLineCount
== -1)
939 /* Test section name without extension */
940 szBuffer
[dwLength
] = 0;
941 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
944 if (lLineCount
== -1)
946 SetLastError(ERROR_INVALID_PARAMETER
);
950 dwFullLength
= lstrlenW(szBuffer
);
952 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
954 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
956 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
960 lstrcpyW(InfSectionWithExt
, szBuffer
);
961 if (Extension
!= NULL
)
963 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
967 if (RequiredSize
!= NULL
)
969 *RequiredSize
= dwFullLength
+ 1;
975 /***********************************************************************
976 * SetupDiGetClassDescriptionA (SETUPAPI.@)
978 BOOL WINAPI
SetupDiGetClassDescriptionA(
979 const GUID
* ClassGuid
,
980 PSTR ClassDescription
,
981 DWORD ClassDescriptionSize
,
984 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
985 ClassDescriptionSize
,
986 RequiredSize
, NULL
, NULL
);
989 /***********************************************************************
990 * SetupDiGetClassDescriptionW (SETUPAPI.@)
992 BOOL WINAPI
SetupDiGetClassDescriptionW(
993 const GUID
* ClassGuid
,
994 PWSTR ClassDescription
,
995 DWORD ClassDescriptionSize
,
998 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
999 ClassDescriptionSize
,
1000 RequiredSize
, NULL
, NULL
);
1003 /***********************************************************************
1004 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1006 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1007 const GUID
* ClassGuid
,
1008 PSTR ClassDescription
,
1009 DWORD ClassDescriptionSize
,
1010 PDWORD RequiredSize
,
1014 PWCHAR ClassDescriptionW
;
1015 LPWSTR MachineNameW
= NULL
;
1019 if (ClassDescriptionSize
> 0)
1021 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1022 if (!ClassDescriptionW
)
1024 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1030 ClassDescriptionW
= NULL
;
1034 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1037 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1043 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1044 NULL
, MachineNameW
, Reserved
);
1047 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1048 ClassDescriptionSize
, NULL
, NULL
);
1050 if (!ClassDescriptionSize
&& RequiredSize
)
1051 *RequiredSize
= len
;
1055 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1056 MyFree(MachineNameW
);
1060 /***********************************************************************
1061 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1063 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1064 const GUID
* ClassGuid
,
1065 PWSTR ClassDescription
,
1066 DWORD ClassDescriptionSize
,
1067 PDWORD RequiredSize
,
1074 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1075 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1077 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1082 if (hKey
== INVALID_HANDLE_VALUE
)
1084 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1088 if (RequiredSize
!= NULL
)
1091 if (RegQueryValueExW(hKey
,
1102 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1105 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1106 if (RegQueryValueExW(hKey
,
1110 (LPBYTE
)ClassDescription
,
1122 /***********************************************************************
1123 * SetupDiGetClassDevsA (SETUPAPI.@)
1125 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1131 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1132 flags
, NULL
, NULL
, NULL
);
1135 /***********************************************************************
1136 * SetupDiGetClassDevsW (SETUPAPI.@)
1138 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1144 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1145 flags
, NULL
, NULL
, NULL
);
1148 /***********************************************************************
1149 * SetupDiGetClassDevsExA (SETUPAPI.@)
1151 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1161 LPWSTR enumstrW
= NULL
;
1162 LPWSTR machineW
= NULL
;
1166 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1167 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1170 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1173 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1177 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1178 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1181 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1184 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1186 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1189 HeapFree(GetProcessHeap(), 0, enumstrW
);
1190 HeapFree(GetProcessHeap(), 0, machineW
);
1195 CreateDeviceInfoElement(
1196 IN
struct DeviceInfoSet
*list
,
1197 IN LPCWSTR InstancePath
,
1198 IN LPCGUID pClassGuid
,
1199 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1203 struct DeviceInfoElement
*deviceInfo
;
1205 *pDeviceInfo
= NULL
;
1207 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1208 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1211 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1214 memset(deviceInfo
, 0, size
);
1216 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1217 if (cr
!= CR_SUCCESS
)
1219 SetLastError(GetErrorCodeFromCrCode(cr
));
1223 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1224 wcscpy(deviceInfo
->Data
, InstancePath
);
1225 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1226 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1227 deviceInfo
->DeviceDescription
= NULL
;
1228 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1229 deviceInfo
->CreationFlags
= 0;
1230 InitializeListHead(&deviceInfo
->DriverListHead
);
1231 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1233 *pDeviceInfo
= deviceInfo
;
1238 CreateDeviceInterface(
1239 IN
struct DeviceInfoElement
* deviceInfo
,
1240 IN LPCWSTR SymbolicLink
,
1241 IN LPCGUID pInterfaceGuid
,
1242 OUT
struct DeviceInterface
**pDeviceInterface
)
1244 struct DeviceInterface
*deviceInterface
;
1246 *pDeviceInterface
= NULL
;
1248 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1249 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1250 if (!deviceInterface
)
1252 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1255 deviceInterface
->DeviceInfo
= deviceInfo
;
1256 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1257 deviceInterface
->Flags
= 0; /* FIXME */
1258 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1260 *pDeviceInterface
= deviceInterface
;
1264 static LONG
SETUP_CreateDevListFromEnumerator(
1265 struct DeviceInfoSet
*list
,
1266 LPCGUID pClassGuid OPTIONAL
,
1268 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1270 HKEY hDeviceIdKey
, hInstanceIdKey
;
1271 WCHAR KeyBuffer
[MAX_PATH
];
1272 WCHAR InstancePath
[MAX_PATH
];
1273 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1274 struct DeviceInfoElement
*deviceInfo
;
1276 DWORD dwLength
, dwRegType
;
1279 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1282 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1283 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1284 if (rc
== ERROR_NO_MORE_ITEMS
)
1286 if (rc
!= ERROR_SUCCESS
)
1290 /* Open device id sub key */
1291 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1292 if (rc
!= ERROR_SUCCESS
)
1294 wcscpy(InstancePath
, Enumerator
);
1295 wcscat(InstancePath
, L
"\\");
1296 wcscat(InstancePath
, KeyBuffer
);
1297 wcscat(InstancePath
, L
"\\");
1298 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1300 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1306 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1307 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1308 if (rc
== ERROR_NO_MORE_ITEMS
)
1310 if (rc
!= ERROR_SUCCESS
)
1312 RegCloseKey(hDeviceIdKey
);
1317 /* Open instance id sub key */
1318 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1319 if (rc
!= ERROR_SUCCESS
)
1321 RegCloseKey(hDeviceIdKey
);
1324 *pEndOfInstancePath
= '\0';
1325 wcscat(InstancePath
, KeyBuffer
);
1327 /* Read ClassGUID value */
1328 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1329 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1330 RegCloseKey(hInstanceIdKey
);
1331 if (rc
== ERROR_FILE_NOT_FOUND
)
1334 /* Skip this bad entry as we can't verify it */
1336 /* Set a default GUID for this device */
1337 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1339 else if (rc
!= ERROR_SUCCESS
)
1341 RegCloseKey(hDeviceIdKey
);
1344 else if (dwRegType
!= REG_SZ
)
1346 RegCloseKey(hDeviceIdKey
);
1347 return ERROR_GEN_FAILURE
;
1351 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1352 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1353 /* Bad GUID, skip the entry */
1357 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1359 /* Skip this entry as it is not the right device class */
1363 /* Add the entry to the list */
1364 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1366 RegCloseKey(hDeviceIdKey
);
1367 return GetLastError();
1369 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1370 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1372 RegCloseKey(hDeviceIdKey
);
1375 return ERROR_SUCCESS
;
1378 static LONG
SETUP_CreateDevList(
1379 struct DeviceInfoSet
*list
,
1380 PCWSTR MachineName OPTIONAL
,
1381 LPGUID
class OPTIONAL
,
1382 PCWSTR Enumerator OPTIONAL
)
1384 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1385 WCHAR KeyBuffer
[MAX_PATH
];
1390 if (class && IsEqualIID(class, &GUID_NULL
))
1394 if (MachineName
!= NULL
)
1396 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1397 if (rc
!= ERROR_SUCCESS
)
1401 HKLM
= HKEY_LOCAL_MACHINE
;
1403 rc
= RegOpenKeyExW(HKLM
,
1406 KEY_ENUMERATE_SUB_KEYS
,
1408 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1409 if (rc
!= ERROR_SUCCESS
)
1412 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1413 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1422 KEY_ENUMERATE_SUB_KEYS
,
1424 RegCloseKey(hEnumKey
);
1425 if (rc
!= ERROR_SUCCESS
)
1427 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1428 RegCloseKey(hEnumeratorKey
);
1433 /* Enumerate enumerators */
1437 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1438 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1439 if (rc
== ERROR_NO_MORE_ITEMS
)
1441 if (rc
!= ERROR_SUCCESS
)
1443 RegCloseKey(hEnumKey
);
1449 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1450 if (rc
!= ERROR_SUCCESS
)
1452 RegCloseKey(hEnumKey
);
1456 /* Call SETUP_CreateDevListFromEnumerator */
1457 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1458 RegCloseKey(hEnumeratorKey
);
1459 if (rc
!= ERROR_SUCCESS
)
1461 RegCloseKey(hEnumKey
);
1465 RegCloseKey(hEnumKey
);
1466 return ERROR_SUCCESS
;
1471 static LONG
SETUP_CreateSerialDeviceList(
1472 struct DeviceInfoSet
*list
,
1474 LPGUID InterfaceGuid
,
1475 PCWSTR DeviceInstanceW
)
1477 static const size_t initialSize
= 100;
1479 WCHAR buf
[initialSize
];
1481 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1483 struct DeviceInfoElement
*deviceInfo
;
1486 WARN("'MachineName' is ignored on Wine!\n");
1487 if (DeviceInstanceW
)
1488 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1494 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1496 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1500 HeapFree(GetProcessHeap(), 0, devices
);
1501 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1503 return ERROR_NOT_ENOUGH_MEMORY
;
1509 HeapFree(GetProcessHeap(), 0, devices
);
1510 return GetLastError();
1514 /* 'devices' is a MULTI_SZ string */
1515 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1517 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1519 /* We have found a device */
1520 struct DeviceInterface
*interfaceInfo
;
1521 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1522 /* Step 1. Create a device info element */
1523 if (!CreateDeviceInfoElement(list
, ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1526 HeapFree(GetProcessHeap(), 0, devices
);
1527 return GetLastError();
1529 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1531 /* Step 2. Create an interface list for this element */
1532 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1535 HeapFree(GetProcessHeap(), 0, devices
);
1536 return GetLastError();
1538 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1542 HeapFree(GetProcessHeap(), 0, devices
);
1543 return ERROR_SUCCESS
;
1546 #else /* __REACTOS__ */
1548 static LONG
SETUP_CreateInterfaceList(
1549 struct DeviceInfoSet
*list
,
1551 LPGUID InterfaceGuid
,
1552 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1554 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1555 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1556 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1557 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1558 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1560 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1563 DWORD dwLength
, dwInstancePathLength
;
1566 struct DeviceInfoElement
*deviceInfo
;
1568 /* Open registry key related to this interface */
1569 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1570 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1571 return GetLastError();
1573 /* Enumerate sub keys of hInterfaceKey */
1577 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1578 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1579 if (rc
== ERROR_NO_MORE_ITEMS
)
1581 if (rc
!= ERROR_SUCCESS
)
1583 RegCloseKey(hInterfaceKey
);
1589 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1590 if (rc
!= ERROR_SUCCESS
)
1592 RegCloseKey(hInterfaceKey
);
1596 /* Read DeviceInstance */
1597 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1598 if (rc
!= ERROR_SUCCESS
)
1600 RegCloseKey(hDeviceInstanceKey
);
1601 RegCloseKey(hInterfaceKey
);
1604 if (dwRegType
!= REG_SZ
)
1606 RegCloseKey(hDeviceInstanceKey
);
1607 RegCloseKey(hInterfaceKey
);
1608 return ERROR_GEN_FAILURE
;
1610 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1613 RegCloseKey(hDeviceInstanceKey
);
1614 RegCloseKey(hInterfaceKey
);
1615 return ERROR_NOT_ENOUGH_MEMORY
;
1617 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1618 if (rc
!= ERROR_SUCCESS
)
1620 HeapFree(GetProcessHeap(), 0, InstancePath
);
1621 RegCloseKey(hDeviceInstanceKey
);
1622 RegCloseKey(hInterfaceKey
);
1625 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1626 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1628 if (DeviceInstanceW
)
1630 /* Check if device enumerator is not the right one */
1631 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1633 HeapFree(GetProcessHeap(), 0, InstancePath
);
1634 RegCloseKey(hDeviceInstanceKey
);
1639 /* Find class GUID associated to the device instance */
1644 KEY_ENUMERATE_SUB_KEYS
,
1646 if (rc
!= ERROR_SUCCESS
)
1648 HeapFree(GetProcessHeap(), 0, InstancePath
);
1649 RegCloseKey(hDeviceInstanceKey
);
1650 RegCloseKey(hInterfaceKey
);
1659 RegCloseKey(hEnumKey
);
1660 if (rc
!= ERROR_SUCCESS
)
1662 HeapFree(GetProcessHeap(), 0, InstancePath
);
1663 RegCloseKey(hDeviceInstanceKey
);
1664 RegCloseKey(hInterfaceKey
);
1667 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1668 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1670 if (rc
!= ERROR_SUCCESS
)
1672 HeapFree(GetProcessHeap(), 0, InstancePath
);
1673 RegCloseKey(hDeviceInstanceKey
);
1674 RegCloseKey(hInterfaceKey
);
1677 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1678 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1679 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1681 HeapFree(GetProcessHeap(), 0, InstancePath
);
1682 RegCloseKey(hDeviceInstanceKey
);
1683 RegCloseKey(hInterfaceKey
);
1684 return ERROR_GEN_FAILURE
;
1686 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1688 /* If current device doesn't match the list GUID (if any), skip this entry */
1689 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1691 HeapFree(GetProcessHeap(), 0, InstancePath
);
1692 RegCloseKey(hDeviceInstanceKey
);
1696 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1700 LPWSTR pSymbolicLink
;
1701 struct DeviceInterface
*interfaceInfo
;
1703 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1704 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1705 if (rc
== ERROR_NO_MORE_ITEMS
)
1707 if (rc
!= ERROR_SUCCESS
)
1709 HeapFree(GetProcessHeap(), 0, InstancePath
);
1710 RegCloseKey(hDeviceInstanceKey
);
1711 RegCloseKey(hInterfaceKey
);
1715 if (KeyBuffer
[0] != '#')
1716 /* This entry doesn't represent an interesting entry */
1720 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1721 if (rc
!= ERROR_SUCCESS
)
1723 RegCloseKey(hDeviceInstanceKey
);
1724 RegCloseKey(hInterfaceKey
);
1728 /* Read SymbolicLink value */
1729 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1730 if (rc
!= ERROR_SUCCESS
)
1732 RegCloseKey(hReferenceKey
);
1733 RegCloseKey(hDeviceInstanceKey
);
1734 RegCloseKey(hInterfaceKey
);
1737 if (dwRegType
!= REG_SZ
)
1739 RegCloseKey(hReferenceKey
);
1740 RegCloseKey(hDeviceInstanceKey
);
1741 RegCloseKey(hInterfaceKey
);
1742 return ERROR_GEN_FAILURE
;
1745 /* We have found a device */
1746 /* Step 1. Create a device info element */
1747 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1749 RegCloseKey(hReferenceKey
);
1750 RegCloseKey(hDeviceInstanceKey
);
1751 RegCloseKey(hInterfaceKey
);
1752 return GetLastError();
1754 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1755 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1757 /* Step 2. Create an interface list for this element */
1758 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1761 RegCloseKey(hReferenceKey
);
1762 RegCloseKey(hDeviceInstanceKey
);
1763 RegCloseKey(hInterfaceKey
);
1764 return ERROR_NOT_ENOUGH_MEMORY
;
1766 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1767 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1768 RegCloseKey(hReferenceKey
);
1769 if (rc
!= ERROR_SUCCESS
)
1771 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1772 RegCloseKey(hDeviceInstanceKey
);
1773 RegCloseKey(hInterfaceKey
);
1776 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1778 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1779 RegCloseKey(hDeviceInstanceKey
);
1780 RegCloseKey(hInterfaceKey
);
1781 return GetLastError();
1783 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1784 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1785 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1787 RegCloseKey(hDeviceInstanceKey
);
1789 RegCloseKey(hInterfaceKey
);
1790 return ERROR_SUCCESS
;
1792 #endif /* __REACTOS__ */
1794 /***********************************************************************
1795 * SetupDiGetClassDevsExW (SETUPAPI.@)
1797 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1806 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1807 struct DeviceInfoSet
*list
;
1811 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1812 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1814 /* Create the deviceset if not set */
1817 list
= (struct DeviceInfoSet
*)deviceset
;
1818 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1820 SetLastError(ERROR_INVALID_HANDLE
);
1821 return INVALID_HANDLE_VALUE
;
1823 hDeviceInfo
= deviceset
;
1827 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1828 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1829 NULL
, machine
, NULL
);
1830 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1831 return INVALID_HANDLE_VALUE
;
1832 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1835 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1838 pClassGuid
= &list
->ClassGuid
;
1840 if (flags
& DIGCF_PRESENT
)
1841 FIXME(": flag DIGCF_PRESENT ignored\n");
1842 if (flags
& DIGCF_PROFILE
)
1843 FIXME(": flag DIGCF_PROFILE ignored\n");
1845 if (flags
& DIGCF_ALLCLASSES
)
1847 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1848 if (rc
!= ERROR_SUCCESS
)
1852 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1853 return INVALID_HANDLE_VALUE
;
1857 else if (flags
& DIGCF_DEVICEINTERFACE
)
1861 SetLastError(ERROR_INVALID_PARAMETER
);
1863 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1864 return INVALID_HANDLE_VALUE
;
1868 /* Special case: find serial ports by calling QueryDosDevice */
1869 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1870 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1871 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1872 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1875 ERR("Wine can only enumerate serial devices at the moment!\n");
1876 rc
= ERROR_INVALID_PARAMETER
;
1878 #else /* __REACTOS__ */
1879 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1880 #endif /* __REACTOS__ */
1881 if (rc
!= ERROR_SUCCESS
)
1885 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1886 return INVALID_HANDLE_VALUE
;
1892 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1893 if (rc
!= ERROR_SUCCESS
)
1897 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1898 return INVALID_HANDLE_VALUE
;
1904 /***********************************************************************
1905 * SetupDiGetClassImageIndex (SETUPAPI.@)
1908 static BOOL
GetIconIndex(
1910 OUT PINT ImageIndex
)
1912 LPWSTR Buffer
= NULL
;
1913 DWORD dwRegType
, dwLength
;
1917 /* Read "Icon" registry key */
1918 rc
= RegQueryValueExW(hClassKey
, L
"Icon", NULL
, &dwRegType
, NULL
, &dwLength
);
1919 if (rc
!= ERROR_SUCCESS
)
1923 } else if (dwRegType
!= REG_SZ
)
1925 SetLastError(ERROR_INVALID_INDEX
);
1928 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
1931 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1934 rc
= RegQueryValueExW(hClassKey
, L
"Icon", NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
1935 if (rc
!= ERROR_SUCCESS
)
1940 /* make sure the returned buffer is NULL-terminated */
1941 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
1943 /* Transform "Icon" value to a INT */
1944 *ImageIndex
= atoiW(Buffer
);
1952 BOOL WINAPI
SetupDiGetClassImageIndex(
1953 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1954 IN CONST GUID
*ClassGuid
,
1955 OUT PINT ImageIndex
)
1957 struct ClassImageList
*list
;
1960 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
1962 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
1963 SetLastError(ERROR_INVALID_PARAMETER
);
1964 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
1965 SetLastError(ERROR_INVALID_USER_BUFFER
);
1966 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
1967 SetLastError(ERROR_INVALID_USER_BUFFER
);
1968 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
1969 SetLastError(ERROR_INVALID_USER_BUFFER
);
1970 else if (!ImageIndex
)
1971 SetLastError(ERROR_INVALID_PARAMETER
);
1974 HKEY hKey
= INVALID_HANDLE_VALUE
;
1977 /* Read Icon registry entry into Buffer */
1978 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
1979 if (hKey
== INVALID_HANDLE_VALUE
)
1981 if (!GetIconIndex(hKey
, &iconIndex
))
1986 SetLastError(ERROR_INVALID_INDEX
);
1990 *ImageIndex
= -iconIndex
;
1994 if (hKey
!= INVALID_HANDLE_VALUE
)
1998 TRACE("Returning %d\n", ret
);
2002 /***********************************************************************
2003 * SetupDiGetClassImageList(SETUPAPI.@)
2005 BOOL WINAPI
SetupDiGetClassImageList(
2006 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2008 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2011 /***********************************************************************
2012 * SetupDiGetClassImageListExA(SETUPAPI.@)
2014 BOOL WINAPI
SetupDiGetClassImageListExA(
2015 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2016 IN PCSTR MachineName OPTIONAL
,
2019 PWSTR MachineNameW
= NULL
;
2024 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2025 if (MachineNameW
== NULL
)
2029 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2032 MyFree(MachineNameW
);
2037 /***********************************************************************
2038 * SetupDiGetClassImageListExW(SETUPAPI.@)
2040 BOOL WINAPI
SetupDiGetClassImageListExW(
2041 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2042 IN PCWSTR MachineName OPTIONAL
,
2047 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2049 if (!ClassImageListData
)
2050 SetLastError(ERROR_INVALID_PARAMETER
);
2051 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2052 SetLastError(ERROR_INVALID_USER_BUFFER
);
2054 SetLastError(ERROR_INVALID_PARAMETER
);
2057 struct ClassImageList
*list
= NULL
;
2060 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2062 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
2063 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2066 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2069 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2072 list
->szData
[0] = list
->szData
[1] = '\\';
2073 strcpyW(list
->szData
+ 2, MachineName
);
2074 list
->MachineName
= list
->szData
;
2078 list
->MachineName
= NULL
;
2081 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2089 TRACE("Returning %d\n", ret
);
2093 /***********************************************************************
2094 * SetupDiLoadClassIcon(SETUPAPI.@)
2096 BOOL WINAPI
SetupDiLoadClassIcon(
2097 IN CONST GUID
*ClassGuid
,
2098 OUT HICON
*LargeIcon OPTIONAL
,
2099 OUT PINT MiniIconIndex OPTIONAL
)
2104 SetLastError(ERROR_INVALID_PARAMETER
);
2107 LPWSTR Buffer
= NULL
;
2110 HKEY hKey
= INVALID_HANDLE_VALUE
;
2112 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2113 if (hKey
== INVALID_HANDLE_VALUE
)
2116 if (!GetIconIndex(hKey
, &iconIndex
))
2121 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2124 DWORD dwRegType
, dwLength
;
2125 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
2126 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2128 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2131 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2134 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2135 if (rc
!= ERROR_SUCCESS
)
2140 /* make sure the returned buffer is NULL-terminated */
2141 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2144 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, &dwRegType
, NULL
, &dwLength
))
2145 && dwRegType
== REG_SZ
)
2147 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2150 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2153 rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2154 if (rc
!= ERROR_SUCCESS
)
2159 /* make sure the returned buffer is NULL-terminated */
2160 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2164 /* Unable to find where to load the icon */
2165 SetLastError(ERROR_FILE_NOT_FOUND
);
2168 Comma
= strchrW(Buffer
, ',');
2171 SetLastError(ERROR_GEN_FAILURE
);
2179 /* Look up icon in setupapi.dll */
2180 DllName
= L
"setupapi.dll";
2181 iconIndex
= -iconIndex
;
2184 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2187 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2189 SetLastError(ERROR_INVALID_INDEX
);
2194 *MiniIconIndex
= iconIndex
;
2198 if (hKey
!= INVALID_HANDLE_VALUE
)
2203 TRACE("Returning %d\n", ret
);
2207 /***********************************************************************
2208 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2210 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2211 HDEVINFO DeviceInfoSet
,
2212 PSP_DEVINFO_DATA DeviceInfoData
,
2213 CONST GUID
* InterfaceClassGuid
,
2215 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2219 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2220 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2222 if (!DeviceInterfaceData
)
2223 SetLastError(ERROR_INVALID_PARAMETER
);
2224 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2225 SetLastError(ERROR_INVALID_USER_BUFFER
);
2226 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2228 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2230 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2232 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2234 while (ItemList
!= &list
->ListHead
&& !Found
)
2236 PLIST_ENTRY InterfaceListEntry
;
2237 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2238 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2240 /* We are not searching for this element */
2241 ItemList
= ItemList
->Flink
;
2244 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2245 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2247 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2248 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2250 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2253 if (MemberIndex
-- == 0)
2255 /* return this item */
2256 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2257 &DevItf
->InterfaceClassGuid
,
2259 DeviceInterfaceData
->Flags
= 0; /* FIXME */
2260 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2263 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2265 ItemList
= ItemList
->Flink
;
2268 SetLastError(ERROR_NO_MORE_ITEMS
);
2273 SetLastError(ERROR_INVALID_HANDLE
);
2276 SetLastError(ERROR_INVALID_HANDLE
);
2280 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2282 InterlockedIncrement(&infFile
->References
);
2285 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2287 if (InterlockedDecrement(&infFile
->References
) == 0)
2289 SetupCloseInfFile(infFile
->hInf
);
2290 HeapFree(GetProcessHeap(), 0, infFile
);
2294 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2296 DereferenceInfFile(driverInfo
->InfFileDetails
);
2297 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2298 HeapFree(GetProcessHeap(), 0, driverInfo
);
2302 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2304 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2308 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2310 PLIST_ENTRY ListEntry
;
2311 struct DriverInfoElement
*driverInfo
;
2313 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2315 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2316 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2317 if (!DestroyDriverInfoElement(driverInfo
))
2320 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2322 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2323 HeapFree(GetProcessHeap(), 0, ListEntry
);
2325 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2326 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2330 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2332 PLIST_ENTRY ListEntry
;
2333 struct DeviceInfoElement
*deviceInfo
;
2335 while (!IsListEmpty(&list
->ListHead
))
2337 ListEntry
= RemoveHeadList(&list
->ListHead
);
2338 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2339 if (!DestroyDeviceInfoElement(deviceInfo
))
2342 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2343 RegCloseKey(list
->HKLM
);
2344 CM_Disconnect_Machine(list
->hMachine
);
2345 DestroyClassInstallParams(&list
->ClassInstallParams
);
2346 HeapFree(GetProcessHeap(), 0, list
);
2350 /***********************************************************************
2351 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2353 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2357 TRACE("%p\n", devinfo
);
2358 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2360 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2362 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2363 ret
= DestroyDeviceInfoSet(list
);
2365 SetLastError(ERROR_INVALID_HANDLE
);
2368 SetLastError(ERROR_INVALID_HANDLE
);
2370 TRACE("Returning %d\n", ret
);
2374 /***********************************************************************
2375 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2377 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2378 HDEVINFO DeviceInfoSet
,
2379 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2380 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2381 DWORD DeviceInterfaceDetailDataSize
,
2382 PDWORD RequiredSize
,
2383 PSP_DEVINFO_DATA DeviceInfoData
)
2385 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2386 DWORD sizeW
= 0, sizeA
;
2389 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2390 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2391 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2393 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2394 SetLastError(ERROR_INVALID_USER_BUFFER
);
2395 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2396 SetLastError(ERROR_INVALID_PARAMETER
);
2397 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2398 SetLastError(ERROR_INVALID_PARAMETER
);
2401 if (DeviceInterfaceDetailData
!= NULL
)
2403 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2404 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2405 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2406 if (!DeviceInterfaceDetailDataW
)
2408 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2411 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2413 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2414 ret
= SetupDiGetDeviceInterfaceDetailW(
2416 DeviceInterfaceData
,
2417 DeviceInterfaceDetailDataW
,
2421 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2422 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2424 *RequiredSize
= sizeA
;
2425 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2427 if (!WideCharToMultiByte(
2429 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2430 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2437 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2440 TRACE("Returning %d\n", ret
);
2444 /***********************************************************************
2445 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2447 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2448 HDEVINFO DeviceInfoSet
,
2449 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2450 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2451 DWORD DeviceInterfaceDetailDataSize
,
2452 PDWORD RequiredSize
,
2453 PSP_DEVINFO_DATA DeviceInfoData
)
2457 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2458 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2459 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2461 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2462 SetLastError(ERROR_INVALID_PARAMETER
);
2463 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2464 SetLastError(ERROR_INVALID_HANDLE
);
2465 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2466 SetLastError(ERROR_INVALID_HANDLE
);
2467 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2468 SetLastError(ERROR_INVALID_USER_BUFFER
);
2469 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2470 SetLastError(ERROR_INVALID_USER_BUFFER
);
2471 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2472 SetLastError(ERROR_INVALID_USER_BUFFER
);
2473 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2474 SetLastError(ERROR_INVALID_PARAMETER
);
2475 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2476 SetLastError(ERROR_INVALID_PARAMETER
);
2479 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2480 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2481 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2482 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2484 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2486 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2488 *RequiredSize
= sizeRequired
;
2492 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2493 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2496 memcpy(&DeviceInfoData
->ClassGuid
,
2497 &deviceInterface
->DeviceInfo
->ClassGuid
,
2499 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2500 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2506 TRACE("Returning %d\n", ret
);
2510 /***********************************************************************
2511 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2513 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2515 PSP_DEVINFO_DATA DeviceInfoData
,
2517 PDWORD PropertyRegDataType
,
2518 PBYTE PropertyBuffer
,
2519 DWORD PropertyBufferSize
,
2520 PDWORD RequiredSize
)
2523 BOOL bIsStringProperty
;
2525 DWORD RequiredSizeA
, RequiredSizeW
;
2526 DWORD PropertyBufferSizeW
;
2527 PBYTE PropertyBufferW
;
2529 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2530 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2533 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2534 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2536 bResult
= SetupDiGetDeviceRegistryPropertyW(
2542 PropertyBufferSizeW
,
2545 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2547 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2549 if (bIsStringProperty
)
2550 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2552 RequiredSizeA
= RequiredSizeW
;
2554 *RequiredSize
= RequiredSizeA
;
2555 if (PropertyRegDataType
)
2556 *PropertyRegDataType
= RegType
;
2561 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2565 if (RequiredSizeA
<= PropertyBufferSize
)
2567 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2569 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2571 /* Last error is already set by WideCharToMultiByte */
2576 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2580 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2584 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2588 /***********************************************************************
2589 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2591 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2592 HDEVINFO DeviceInfoSet
,
2593 PSP_DEVINFO_DATA DeviceInfoData
,
2595 PDWORD PropertyRegDataType
,
2596 PBYTE PropertyBuffer
,
2597 DWORD PropertyBufferSize
,
2598 PDWORD RequiredSize
)
2600 HKEY hEnumKey
, hKey
;
2604 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2605 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2608 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2609 SetLastError(ERROR_INVALID_HANDLE
);
2610 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2611 SetLastError(ERROR_INVALID_HANDLE
);
2612 else if (!DeviceInfoData
)
2613 SetLastError(ERROR_INVALID_PARAMETER
);
2614 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2615 SetLastError(ERROR_INVALID_USER_BUFFER
);
2616 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2617 SetLastError(ERROR_INVALID_PARAMETER
);
2620 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2621 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2625 case SPDRP_CAPABILITIES
:
2627 case SPDRP_CLASSGUID
:
2628 case SPDRP_COMPATIBLEIDS
:
2629 case SPDRP_CONFIGFLAGS
:
2630 case SPDRP_DEVICEDESC
:
2632 case SPDRP_FRIENDLYNAME
:
2633 case SPDRP_HARDWAREID
:
2634 case SPDRP_LOCATION_INFORMATION
:
2635 case SPDRP_LOWERFILTERS
:
2637 case SPDRP_SECURITY
:
2639 case SPDRP_UI_NUMBER
:
2640 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2641 case SPDRP_UPPERFILTERS
:
2643 LPCWSTR RegistryPropertyName
;
2648 case SPDRP_CAPABILITIES
:
2649 RegistryPropertyName
= L
"Capabilities"; break;
2651 RegistryPropertyName
= L
"Class"; break;
2652 case SPDRP_CLASSGUID
:
2653 RegistryPropertyName
= L
"ClassGUID"; break;
2654 case SPDRP_COMPATIBLEIDS
:
2655 RegistryPropertyName
= L
"CompatibleIDs"; break;
2656 case SPDRP_CONFIGFLAGS
:
2657 RegistryPropertyName
= L
"ConfigFlags"; break;
2658 case SPDRP_DEVICEDESC
:
2659 RegistryPropertyName
= L
"DeviceDesc"; break;
2661 RegistryPropertyName
= L
"Driver"; break;
2662 case SPDRP_FRIENDLYNAME
:
2663 RegistryPropertyName
= L
"FriendlyName"; break;
2664 case SPDRP_HARDWAREID
:
2665 RegistryPropertyName
= L
"HardwareID"; break;
2666 case SPDRP_LOCATION_INFORMATION
:
2667 RegistryPropertyName
= L
"LocationInformation"; break;
2668 case SPDRP_LOWERFILTERS
:
2669 RegistryPropertyName
= L
"LowerFilters"; break;
2671 RegistryPropertyName
= L
"Mfg"; break;
2672 case SPDRP_SECURITY
:
2673 RegistryPropertyName
= L
"Security"; break;
2675 RegistryPropertyName
= L
"Service"; break;
2676 case SPDRP_UI_NUMBER
:
2677 RegistryPropertyName
= L
"UINumber"; break;
2678 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2679 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2680 case SPDRP_UPPERFILTERS
:
2681 RegistryPropertyName
= L
"UpperFilters"; break;
2683 /* Should not happen */
2684 RegistryPropertyName
= NULL
; break;
2687 /* Open registry key name */
2692 KEY_ENUMERATE_SUB_KEYS
,
2694 if (rc
!= ERROR_SUCCESS
)
2705 RegCloseKey(hEnumKey
);
2706 if (rc
!= ERROR_SUCCESS
)
2711 /* Read registry entry */
2712 BufferSize
= PropertyBufferSize
;
2713 rc
= RegQueryValueExW(
2715 RegistryPropertyName
,
2716 NULL
, /* Reserved */
2717 PropertyRegDataType
,
2721 *RequiredSize
= BufferSize
;
2724 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2727 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2729 case ERROR_MORE_DATA
:
2730 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2739 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2741 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2743 if (PropertyRegDataType
)
2744 *PropertyRegDataType
= REG_SZ
;
2746 *RequiredSize
= required
;
2747 if (PropertyBufferSize
>= required
)
2749 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2753 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2757 /*case SPDRP_BUSTYPEGUID:
2758 case SPDRP_LEGACYBUSTYPE:
2759 case SPDRP_BUSNUMBER:
2760 case SPDRP_ENUMERATOR_NAME:
2761 case SPDRP_SECURITY_SDS:
2763 case SPDRP_EXCLUSIVE:
2764 case SPDRP_CHARACTERISTICS:
2766 case SPDRP_DEVICE_POWER_DATA:*/
2767 #if (WINVER >= 0x501)
2768 /*case SPDRP_REMOVAL_POLICY:
2769 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2770 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2771 case SPDRP_INSTALL_STATE:*/
2776 ERR("Property 0x%lx not implemented\n", Property
);
2777 SetLastError(ERROR_NOT_SUPPORTED
);
2782 TRACE("Returning %d\n", ret
);
2786 /***********************************************************************
2787 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2789 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2790 IN HDEVINFO DeviceInfoSet
,
2791 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2793 IN CONST BYTE
*PropertyBuffer
,
2794 IN DWORD PropertyBufferSize
)
2796 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2797 Property
, PropertyBuffer
, PropertyBufferSize
);
2798 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2802 /***********************************************************************
2803 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2805 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2806 IN HDEVINFO DeviceInfoSet
,
2807 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2809 IN
const BYTE
*PropertyBuffer
,
2810 IN DWORD PropertyBufferSize
)
2812 struct DeviceInfoSet
*list
;
2815 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2816 Property
, PropertyBuffer
, PropertyBufferSize
);
2819 SetLastError(ERROR_INVALID_HANDLE
);
2820 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2821 SetLastError(ERROR_INVALID_HANDLE
);
2822 else if (!DeviceInfoData
)
2823 SetLastError(ERROR_INVALID_HANDLE
);
2824 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2825 SetLastError(ERROR_INVALID_USER_BUFFER
);
2830 case SPDRP_COMPATIBLEIDS
:
2831 case SPDRP_CONFIGFLAGS
:
2832 case SPDRP_FRIENDLYNAME
:
2833 case SPDRP_HARDWAREID
:
2834 case SPDRP_LOCATION_INFORMATION
:
2835 case SPDRP_LOWERFILTERS
:
2836 case SPDRP_SECURITY
:
2838 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2839 case SPDRP_UPPERFILTERS
:
2841 LPCWSTR RegistryPropertyName
;
2842 DWORD RegistryDataType
;
2848 case SPDRP_COMPATIBLEIDS
:
2849 RegistryPropertyName
= L
"CompatibleIDs";
2850 RegistryDataType
= REG_MULTI_SZ
;
2852 case SPDRP_CONFIGFLAGS
:
2853 RegistryPropertyName
= L
"ConfigFlags";
2854 RegistryDataType
= REG_DWORD
;
2856 case SPDRP_FRIENDLYNAME
:
2857 RegistryPropertyName
= L
"FriendlyName";
2858 RegistryDataType
= REG_SZ
;
2860 case SPDRP_HARDWAREID
:
2861 RegistryPropertyName
= L
"HardwareID";
2862 RegistryDataType
= REG_MULTI_SZ
;
2864 case SPDRP_LOCATION_INFORMATION
:
2865 RegistryPropertyName
= L
"LocationInformation";
2866 RegistryDataType
= REG_SZ
;
2868 case SPDRP_LOWERFILTERS
:
2869 RegistryPropertyName
= L
"LowerFilters";
2870 RegistryDataType
= REG_MULTI_SZ
;
2872 case SPDRP_SECURITY
:
2873 RegistryPropertyName
= L
"Security";
2874 RegistryDataType
= REG_BINARY
;
2877 RegistryPropertyName
= L
"Service";
2878 RegistryDataType
= REG_SZ
;
2880 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2881 RegistryPropertyName
= L
"UINumberDescFormat";
2882 RegistryDataType
= REG_SZ
;
2884 case SPDRP_UPPERFILTERS
:
2885 RegistryPropertyName
= L
"UpperFilters";
2886 RegistryDataType
= REG_MULTI_SZ
;
2889 /* Should not happen */
2890 RegistryPropertyName
= NULL
;
2891 RegistryDataType
= REG_BINARY
;
2894 /* Open device registry key */
2895 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2896 if (hKey
!= INVALID_HANDLE_VALUE
)
2898 /* Write new data */
2899 rc
= RegSetValueExW(
2901 RegistryPropertyName
,
2905 PropertyBufferSize
);
2906 if (rc
== ERROR_SUCCESS
)
2915 /*case SPDRP_CHARACTERISTICS:
2917 case SPDRP_EXCLUSIVE:*/
2918 #if (WINVER >= 0x501)
2919 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2921 //case SPDRP_SECURITY_SDS:
2925 ERR("Property 0x%lx not implemented\n", Property
);
2926 SetLastError(ERROR_NOT_SUPPORTED
);
2931 TRACE("Returning %d\n", ret
);
2935 /***********************************************************************
2936 * SetupDiInstallClassA (SETUPAPI.@)
2938 BOOL WINAPI
SetupDiInstallClassA(
2944 UNICODE_STRING FileNameW
;
2947 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2949 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2953 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2955 RtlFreeUnicodeString(&FileNameW
);
2960 static HKEY
CreateClassKey(HINF hInf
)
2962 WCHAR FullBuffer
[MAX_PATH
];
2963 WCHAR Buffer
[MAX_PATH
];
2968 if (!SetupGetLineTextW(NULL
,
2976 return INVALID_HANDLE_VALUE
;
2979 lstrcpyW(FullBuffer
, ControlClass
);
2980 lstrcatW(FullBuffer
, Buffer
);
2983 if (!SetupGetLineTextW(NULL
,
2991 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2992 return INVALID_HANDLE_VALUE
;
2995 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2999 REG_OPTION_NON_VOLATILE
,
3005 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3006 return INVALID_HANDLE_VALUE
;
3009 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3014 RequiredSize
* sizeof(WCHAR
)))
3016 RegCloseKey(hClassKey
);
3017 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3018 return INVALID_HANDLE_VALUE
;
3024 /***********************************************************************
3025 * SetupDiInstallClassW (SETUPAPI.@)
3027 BOOL WINAPI
SetupDiInstallClassW(
3033 WCHAR SectionName
[MAX_PATH
];
3034 DWORD SectionNameLength
= 0;
3036 BOOL bFileQueueCreated
= FALSE
;
3039 TRACE("%p %s 0x%lx %p\n", hwndParent
, debugstr_w(InfFileName
),
3042 FIXME("not fully implemented\n");
3044 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
3046 SetLastError(ERROR_INVALID_PARAMETER
);
3050 /* Open the .inf file */
3051 hInf
= SetupOpenInfFileW(InfFileName
,
3055 if (hInf
== INVALID_HANDLE_VALUE
)
3061 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
3062 hClassKey
= CreateClassKey(hInf
);
3063 if (hClassKey
== INVALID_HANDLE_VALUE
)
3065 SetupCloseInfFile(hInf
);
3071 /* Try to append a layout file */
3073 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3076 /* Retrieve the actual section name */
3077 SetupDiGetActualSectionToInstallW(hInf
,
3085 if (!(Flags
& DI_NOVCP
))
3087 FileQueue
= SetupOpenFileQueue();
3088 if (FileQueue
== INVALID_HANDLE_VALUE
)
3090 SetupCloseInfFile(hInf
);
3091 RegCloseKey(hClassKey
);
3095 bFileQueueCreated
= TRUE
;
3100 SetupInstallFromInfSectionW(NULL
,
3109 INVALID_HANDLE_VALUE
,
3112 /* FIXME: Process InterfaceInstall32 section */
3114 if (bFileQueueCreated
)
3115 SetupCloseFileQueue(FileQueue
);
3117 SetupCloseInfFile(hInf
);
3119 RegCloseKey(hClassKey
);
3124 /***********************************************************************
3125 * SetupDiOpenClassRegKey (SETUPAPI.@)
3127 HKEY WINAPI
SetupDiOpenClassRegKey(
3128 const GUID
* ClassGuid
,
3131 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3132 DIOCR_INSTALLER
, NULL
, NULL
);
3136 /***********************************************************************
3137 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3139 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3140 const GUID
* ClassGuid OPTIONAL
,
3143 PCSTR MachineName OPTIONAL
,
3146 PWSTR MachineNameW
= NULL
;
3153 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3154 if (MachineNameW
== NULL
)
3155 return INVALID_HANDLE_VALUE
;
3158 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3159 Flags
, MachineNameW
, Reserved
);
3162 MyFree(MachineNameW
);
3168 /***********************************************************************
3169 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3171 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3172 const GUID
* ClassGuid OPTIONAL
,
3175 PCWSTR MachineName OPTIONAL
,
3178 LPWSTR lpGuidString
;
3179 LPWSTR lpFullGuidString
;
3187 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3188 Flags
, debugstr_w(MachineName
), Reserved
);
3190 if (Flags
== DIOCR_INSTALLER
)
3192 lpKeyName
= ControlClass
;
3194 else if (Flags
== DIOCR_INTERFACE
)
3196 lpKeyName
= DeviceClasses
;
3200 ERR("Invalid Flags parameter!\n");
3201 SetLastError(ERROR_INVALID_FLAGS
);
3202 return INVALID_HANDLE_VALUE
;
3205 if (MachineName
!= NULL
)
3207 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3208 if (rc
!= ERROR_SUCCESS
)
3211 return INVALID_HANDLE_VALUE
;
3215 HKLM
= HKEY_LOCAL_MACHINE
;
3217 rc
= RegOpenKeyExW(HKLM
,
3220 ClassGuid
? KEY_ENUMERATE_SUB_KEYS
: samDesired
,
3222 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3223 if (rc
!= ERROR_SUCCESS
)
3226 return INVALID_HANDLE_VALUE
;
3229 if (ClassGuid
== NULL
)
3232 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3234 SetLastError(ERROR_GEN_FAILURE
);
3235 RegCloseKey(hClassesKey
);
3236 return INVALID_HANDLE_VALUE
;
3239 dwLength
= lstrlenW(lpGuidString
);
3240 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3241 if (!lpFullGuidString
)
3243 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3244 RpcStringFreeW(&lpGuidString
);
3245 return INVALID_HANDLE_VALUE
;
3247 lpFullGuidString
[0] = '{';
3248 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3249 lpFullGuidString
[dwLength
+ 1] = '}';
3250 lpFullGuidString
[dwLength
+ 2] = '\0';
3251 RpcStringFreeW(&lpGuidString
);
3253 rc
= RegOpenKeyExW(hClassesKey
,
3258 if (rc
!= ERROR_SUCCESS
)
3261 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3262 RegCloseKey(hClassesKey
);
3263 return INVALID_HANDLE_VALUE
;
3266 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3267 RegCloseKey(hClassesKey
);
3272 /***********************************************************************
3273 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3275 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3276 HDEVINFO DeviceInfoSet
,
3279 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3281 FIXME("%p %s %08lx %p\n",
3282 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3286 /***********************************************************************
3287 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3289 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3290 HDEVINFO DeviceInfoSet
,
3293 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3295 LPWSTR DevicePathW
= NULL
;
3298 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3300 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3301 if (DevicePathW
== NULL
)
3304 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3305 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3307 MyFree(DevicePathW
);
3312 /***********************************************************************
3313 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3315 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3316 HDEVINFO DeviceInfoSet
,
3317 PSP_DEVINFO_DATA DeviceInfoData
,
3318 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3319 DWORD ClassInstallParamsSize
)
3321 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3322 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3326 /***********************************************************************
3327 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3329 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3330 IN HDEVINFO DeviceInfoSet
,
3331 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3332 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3333 IN DWORD ClassInstallParamsSize
)
3335 struct DeviceInfoSet
*list
;
3338 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3339 ClassInstallParams
, ClassInstallParamsSize
);
3342 SetLastError(ERROR_INVALID_PARAMETER
);
3343 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3344 SetLastError(ERROR_INVALID_HANDLE
);
3345 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3346 SetLastError(ERROR_INVALID_HANDLE
);
3347 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3348 SetLastError(ERROR_INVALID_USER_BUFFER
);
3349 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3350 SetLastError(ERROR_INVALID_USER_BUFFER
);
3351 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3352 SetLastError(ERROR_INVALID_PARAMETER
);
3353 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3354 SetLastError(ERROR_INVALID_PARAMETER
);
3357 SP_DEVINSTALL_PARAMS_W InstallParams
;
3360 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3361 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3365 if (ClassInstallParams
)
3367 /* Check parameters in ClassInstallParams */
3368 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3369 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3371 SetLastError(ERROR_INVALID_USER_BUFFER
);
3374 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3376 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3377 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3380 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3383 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3387 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3390 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3394 TRACE("Returning %d\n", ret
);
3398 static BOOL
PropertyChangeHandler(
3399 IN HDEVINFO DeviceInfoSet
,
3400 IN PSP_DEVINFO_DATA DeviceInfoData
,
3401 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3402 IN DWORD ClassInstallParamsSize
)
3404 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3407 if (!DeviceInfoData
)
3408 SetLastError(ERROR_INVALID_PARAMETER
);
3409 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3410 SetLastError(ERROR_INVALID_PARAMETER
);
3411 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3412 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3413 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3414 SetLastError(ERROR_INVALID_FLAGS
);
3415 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3416 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3417 SetLastError(ERROR_INVALID_FLAGS
);
3418 else if (PropChangeParams
3419 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3420 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3421 SetLastError(ERROR_INVALID_USER_BUFFER
);
3424 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3425 if (!DeviceInfoData
)
3427 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3428 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3432 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3433 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3435 if (*CurrentPropChangeParams
)
3437 MyFree(*CurrentPropChangeParams
);
3438 *CurrentPropChangeParams
= NULL
;
3440 if (PropChangeParams
)
3442 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3443 if (!*CurrentPropChangeParams
)
3445 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3448 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3459 IN PWSTR InstallerName
,
3460 OUT HMODULE
* ModulePointer
,
3461 OUT PVOID
* FunctionPointer
)
3463 HMODULE hModule
= NULL
;
3464 LPSTR FunctionNameA
= NULL
;
3468 *ModulePointer
= NULL
;
3469 *FunctionPointer
= NULL
;
3471 Comma
= strchrW(InstallerName
, ',');
3474 rc
= ERROR_INVALID_PARAMETER
;
3480 hModule
= LoadLibraryW(InstallerName
);
3484 rc
= GetLastError();
3488 /* Skip comma spaces */
3489 while (*Comma
== ',' || isspaceW(*Comma
))
3492 /* W->A conversion for function name */
3493 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3496 rc
= GetLastError();
3500 /* Search function */
3501 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3502 if (!*FunctionPointer
)
3504 rc
= GetLastError();
3508 *ModulePointer
= hModule
;
3512 if (rc
!= ERROR_SUCCESS
&& hModule
)
3513 FreeLibrary(hModule
);
3514 MyFree(FunctionNameA
);
3519 FreeFunctionPointer(
3520 IN HMODULE ModulePointer
,
3521 IN PVOID FunctionPointer
)
3523 if (ModulePointer
== NULL
)
3524 return ERROR_SUCCESS
;
3525 if (FreeLibrary(ModulePointer
))
3526 return ERROR_SUCCESS
;
3528 return GetLastError();
3531 /***********************************************************************
3532 * SetupDiCallClassInstaller (SETUPAPI.@)
3534 BOOL WINAPI
SetupDiCallClassInstaller(
3535 IN DI_FUNCTION InstallFunction
,
3536 IN HDEVINFO DeviceInfoSet
,
3537 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3541 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3544 SetLastError(ERROR_INVALID_PARAMETER
);
3545 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3546 SetLastError(ERROR_INVALID_HANDLE
);
3547 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3548 SetLastError(ERROR_INVALID_HANDLE
);
3549 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3550 SetLastError(ERROR_INVALID_HANDLE
);
3551 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3552 SetLastError(ERROR_INVALID_USER_BUFFER
);
3555 SP_DEVINSTALL_PARAMS_W InstallParams
;
3556 #define CLASS_COINSTALLER 0x1
3557 #define DEVICE_COINSTALLER 0x2
3558 #define CLASS_INSTALLER 0x4
3559 UCHAR CanHandle
= 0;
3560 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3562 switch (InstallFunction
)
3564 case DIF_ALLOW_INSTALL
:
3565 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3567 case DIF_DESTROYPRIVATEDATA
:
3568 CanHandle
= CLASS_INSTALLER
;
3570 case DIF_INSTALLDEVICE
:
3571 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3572 DefaultHandler
= SetupDiInstallDevice
;
3574 case DIF_INSTALLDEVICEFILES
:
3575 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3576 DefaultHandler
= SetupDiInstallDriverFiles
;
3578 case DIF_INSTALLINTERFACES
:
3579 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3580 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3582 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3583 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3585 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3586 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3588 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3589 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3591 case DIF_PROPERTYCHANGE
:
3592 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3593 DefaultHandler
= SetupDiChangeState
;
3595 case DIF_REGISTER_COINSTALLERS
:
3596 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3597 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3599 case DIF_SELECTBESTCOMPATDRV
:
3600 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3601 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3604 ERR("Install function %u not supported\n", InstallFunction
);
3605 SetLastError(ERROR_NOT_SUPPORTED
);
3608 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3609 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3610 /* Don't process this call, as a parameter is invalid */
3615 LIST_ENTRY ClassCoInstallersListHead
;
3616 LIST_ENTRY DeviceCoInstallersListHead
;
3617 HMODULE ClassInstallerLibrary
= NULL
;
3618 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3619 COINSTALLER_CONTEXT_DATA Context
;
3620 PLIST_ENTRY ListEntry
;
3622 DWORD dwRegType
, dwLength
;
3623 DWORD rc
= NO_ERROR
;
3625 InitializeListHead(&ClassCoInstallersListHead
);
3626 InitializeListHead(&DeviceCoInstallersListHead
);
3628 if (CanHandle
& DEVICE_COINSTALLER
)
3630 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3631 if (hKey
!= INVALID_HANDLE_VALUE
)
3633 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, &dwRegType
, NULL
, &dwLength
);
3634 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3636 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3637 if (KeyBuffer
!= NULL
)
3639 rc
= RegQueryValueExW(hKey
, L
"CoInstallers32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3640 if (rc
== ERROR_SUCCESS
)
3643 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3645 /* Add coinstaller to DeviceCoInstallersListHead list */
3646 struct CoInstallerElement
*coinstaller
;
3647 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3648 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3651 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3652 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3653 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3655 HeapFree(GetProcessHeap(), 0, coinstaller
);
3658 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3664 if (CanHandle
& CLASS_COINSTALLER
)
3668 L
"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
3672 if (rc
== ERROR_SUCCESS
)
3674 LPWSTR lpGuidString
;
3675 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3677 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3678 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3680 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3681 if (KeyBuffer
!= NULL
)
3683 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3684 if (rc
== ERROR_SUCCESS
)
3687 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3689 /* Add coinstaller to ClassCoInstallersListHead list */
3690 struct CoInstallerElement
*coinstaller
;
3691 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3692 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3695 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3696 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3697 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3699 HeapFree(GetProcessHeap(), 0, coinstaller
);
3702 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3705 RpcStringFreeW(&lpGuidString
);
3710 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3712 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3713 if (hKey
!= INVALID_HANDLE_VALUE
)
3715 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, &dwRegType
, NULL
, &dwLength
);
3716 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3718 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3719 if (KeyBuffer
!= NULL
)
3721 rc
= RegQueryValueExW(hKey
, L
"Installer32", NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3722 if (rc
== ERROR_SUCCESS
)
3724 /* Get ClassInstaller function pointer */
3725 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3726 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3728 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3729 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3732 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3739 /* Call Class co-installers */
3740 Context
.PostProcessing
= FALSE
;
3742 ListEntry
= ClassCoInstallersListHead
.Flink
;
3743 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3745 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3746 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3747 coinstaller
->PrivateData
= Context
.PrivateData
;
3748 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3750 coinstaller
->DoPostProcessing
= TRUE
;
3753 ListEntry
= ListEntry
->Flink
;
3756 /* Call Device co-installers */
3757 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3758 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3760 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3761 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3762 coinstaller
->PrivateData
= Context
.PrivateData
;
3763 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3765 coinstaller
->DoPostProcessing
= TRUE
;
3768 ListEntry
= ListEntry
->Flink
;
3771 /* Call Class installer */
3774 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3775 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3778 rc
= ERROR_DI_DO_DEFAULT
;
3780 /* Call default handler */
3781 if (rc
== ERROR_DI_DO_DEFAULT
)
3783 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3785 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3788 rc
= GetLastError();
3794 /* Call Class co-installers that required postprocessing */
3795 Context
.PostProcessing
= TRUE
;
3796 ListEntry
= ClassCoInstallersListHead
.Flink
;
3797 while (ListEntry
!= &ClassCoInstallersListHead
)
3799 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3800 if (coinstaller
->DoPostProcessing
)
3802 Context
.InstallResult
= rc
;
3803 Context
.PrivateData
= coinstaller
->PrivateData
;
3804 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3806 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3807 ListEntry
= ListEntry
->Flink
;
3810 /* Call Device co-installers that required postprocessing */
3811 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3812 while (ListEntry
!= &DeviceCoInstallersListHead
)
3814 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3815 if (coinstaller
->DoPostProcessing
)
3817 Context
.InstallResult
= rc
;
3818 Context
.PrivateData
= coinstaller
->PrivateData
;
3819 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3821 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3822 ListEntry
= ListEntry
->Flink
;
3825 /* Free allocated memory */
3826 while (!IsListEmpty(&ClassCoInstallersListHead
))
3828 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3829 HeapFree(GetProcessHeap(), 0, ListEntry
);
3831 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3833 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3834 HeapFree(GetProcessHeap(), 0, ListEntry
);
3837 ret
= (rc
== NO_ERROR
);
3841 TRACE("Returning %d\n", ret
);
3845 /***********************************************************************
3846 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
3848 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
3849 IN HDEVINFO DeviceInfoSet
,
3850 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
3852 struct DeviceInfoSet
*list
;
3855 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
3858 SetLastError(ERROR_INVALID_HANDLE
);
3859 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3860 SetLastError(ERROR_INVALID_HANDLE
);
3861 else if (!DeviceInfoListDetailData
)
3862 SetLastError(ERROR_INVALID_PARAMETER
);
3863 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
3864 SetLastError(ERROR_INVALID_USER_BUFFER
);
3868 &DeviceInfoListDetailData
->ClassGuid
,
3871 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
3872 if (list
->MachineName
)
3873 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
3875 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
3880 TRACE("Returning %d\n", ret
);
3884 /***********************************************************************
3885 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3887 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3888 IN HDEVINFO DeviceInfoSet
,
3889 IN PSP_DEVINFO_DATA DeviceInfoData
,
3890 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3892 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3895 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3897 if (DeviceInstallParams
== NULL
)
3898 SetLastError(ERROR_INVALID_PARAMETER
);
3899 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3900 SetLastError(ERROR_INVALID_USER_BUFFER
);
3903 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3904 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3908 /* Do W->A conversion */
3910 DeviceInstallParams
,
3911 &deviceInstallParamsW
,
3912 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3913 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3914 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3916 DeviceInstallParams
->DriverPath
[0] = '\0';
3922 TRACE("Returning %d\n", ret
);
3926 /***********************************************************************
3927 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3929 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3930 IN HDEVINFO DeviceInfoSet
,
3931 IN PSP_DEVINFO_DATA DeviceInfoData
,
3932 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3934 struct DeviceInfoSet
*list
;
3937 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3940 SetLastError(ERROR_INVALID_HANDLE
);
3941 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3942 SetLastError(ERROR_INVALID_HANDLE
);
3943 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3944 SetLastError(ERROR_INVALID_USER_BUFFER
);
3945 else if (!DeviceInstallParams
)
3946 SetLastError(ERROR_INVALID_PARAMETER
);
3947 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3948 SetLastError(ERROR_INVALID_USER_BUFFER
);
3951 PSP_DEVINSTALL_PARAMS_W Source
;
3954 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3956 Source
= &list
->InstallParams
;
3957 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
3961 TRACE("Returning %d\n", ret
);
3965 /***********************************************************************
3966 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3968 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
3969 IN HDEVINFO DeviceInfoSet
,
3970 IN PSP_DEVINFO_DATA DeviceInfoData
,
3971 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3973 struct DeviceInfoSet
*list
;
3976 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3979 SetLastError(ERROR_INVALID_HANDLE
);
3980 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3981 SetLastError(ERROR_INVALID_HANDLE
);
3982 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3983 SetLastError(ERROR_INVALID_USER_BUFFER
);
3984 else if (!DeviceInstallParams
)
3985 SetLastError(ERROR_INVALID_PARAMETER
);
3986 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3987 SetLastError(ERROR_INVALID_USER_BUFFER
);
3990 PSP_DEVINSTALL_PARAMS_W Destination
;
3992 /* FIXME: Validate parameters */
3995 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3997 Destination
= &list
->InstallParams
;
3998 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4002 TRACE("Returning %d\n", ret
);
4006 /***********************************************************************
4007 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4009 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
4010 IN HDEVINFO DeviceInfoSet
,
4011 IN PSP_DEVINFO_DATA DeviceInfoData
,
4012 OUT PSTR DeviceInstanceId OPTIONAL
,
4013 IN DWORD DeviceInstanceIdSize
,
4014 OUT PDWORD RequiredSize OPTIONAL
)
4016 PWSTR DeviceInstanceIdW
= NULL
;
4019 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4020 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4022 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4023 SetLastError(ERROR_INVALID_PARAMETER
);
4026 if (DeviceInstanceIdSize
!= 0)
4028 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4029 if (DeviceInstanceIdW
== NULL
)
4033 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4034 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4037 if (ret
&& DeviceInstanceIdW
!= NULL
)
4039 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4040 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4042 DeviceInstanceId
[0] = '\0';
4048 TRACE("Returning %d\n", ret
);
4052 /***********************************************************************
4053 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4055 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
4056 IN HDEVINFO DeviceInfoSet
,
4057 IN PSP_DEVINFO_DATA DeviceInfoData
,
4058 OUT PWSTR DeviceInstanceId OPTIONAL
,
4059 IN DWORD DeviceInstanceIdSize
,
4060 OUT PDWORD RequiredSize OPTIONAL
)
4064 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4065 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4068 SetLastError(ERROR_INVALID_HANDLE
);
4069 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4070 SetLastError(ERROR_INVALID_HANDLE
);
4071 else if (!DeviceInfoData
)
4072 SetLastError(ERROR_INVALID_PARAMETER
);
4073 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4074 SetLastError(ERROR_INVALID_USER_BUFFER
);
4075 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4076 SetLastError(ERROR_INVALID_PARAMETER
);
4077 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4078 SetLastError(ERROR_INVALID_PARAMETER
);
4081 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4084 required
= (wcslen(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4086 *RequiredSize
= required
;
4088 if (required
<= DeviceInstanceIdSize
)
4090 wcscpy(DeviceInstanceId
, DevInfo
->DeviceName
);
4094 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4097 TRACE("Returning %d\n", ret
);
4101 /***********************************************************************
4102 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4104 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
4105 IN HDEVINFO DeviceInfoSet
,
4106 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4107 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4108 IN DWORD PropertySheetHeaderPageListSize
,
4109 OUT PDWORD RequiredSize OPTIONAL
,
4110 IN DWORD PropertySheetType
)
4112 PROPSHEETHEADERW psh
;
4115 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4116 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4117 RequiredSize
, PropertySheetType
);
4119 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4120 psh
.phpage
= PropertySheetHeader
->phpage
;
4121 psh
.nPages
= PropertySheetHeader
->nPages
;
4123 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4124 PropertySheetHeaderPageListSize
, RequiredSize
,
4128 PropertySheetHeader
->nPages
= psh
.nPages
;
4131 TRACE("Returning %d\n", ret
);
4135 struct ClassDevPropertySheetsData
4137 HPROPSHEETPAGE
*PropertySheetPages
;
4138 DWORD MaximumNumberOfPages
;
4139 DWORD NumberOfPages
;
4142 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
4143 IN HPROPSHEETPAGE hPropSheetPage
,
4144 IN OUT LPARAM lParam
)
4146 struct ClassDevPropertySheetsData
*PropPageData
;
4148 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4150 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4152 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4153 PropPageData
->PropertySheetPages
++;
4156 PropPageData
->NumberOfPages
++;
4160 /***********************************************************************
4161 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4163 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
4164 IN HDEVINFO DeviceInfoSet
,
4165 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4166 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4167 IN DWORD PropertySheetHeaderPageListSize
,
4168 OUT PDWORD RequiredSize OPTIONAL
,
4169 IN DWORD PropertySheetType
)
4171 struct DeviceInfoSet
*list
;
4174 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4175 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4176 RequiredSize
, PropertySheetType
);
4179 SetLastError(ERROR_INVALID_HANDLE
);
4180 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4181 SetLastError(ERROR_INVALID_HANDLE
);
4182 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4183 SetLastError(ERROR_INVALID_HANDLE
);
4184 else if (!PropertySheetHeader
)
4185 SetLastError(ERROR_INVALID_PARAMETER
);
4186 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4187 SetLastError(ERROR_INVALID_FLAGS
);
4188 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4189 SetLastError(ERROR_INVALID_USER_BUFFER
);
4190 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4191 SetLastError(ERROR_INVALID_PARAMETER
);
4192 else if (!PropertySheetHeader
)
4193 SetLastError(ERROR_INVALID_PARAMETER
);
4194 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4195 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4196 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4197 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4198 SetLastError(ERROR_INVALID_PARAMETER
);
4201 HKEY hKey
= INVALID_HANDLE_VALUE
;
4202 SP_PROPSHEETPAGE_REQUEST Request
;
4203 LPWSTR PropPageProvider
= NULL
;
4204 HMODULE hModule
= NULL
;
4205 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4206 struct ClassDevPropertySheetsData PropPageData
;
4207 DWORD dwLength
, dwRegType
;
4211 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4214 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4215 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4217 if (hKey
== INVALID_HANDLE_VALUE
)
4220 rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, &dwRegType
, NULL
, &dwLength
);
4221 if (rc
== ERROR_FILE_NOT_FOUND
)
4223 /* No registry key. As it is optional, don't say it's a bad error */
4229 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4235 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4236 if (!PropPageProvider
)
4238 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4241 rc
= RegQueryValueExW(hKey
, L
"EnumPropPages32", NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4242 if (rc
!= ERROR_SUCCESS
)
4247 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4249 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4250 if (rc
!= ERROR_SUCCESS
)
4252 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4256 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4257 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4258 Request
.DeviceInfoSet
= DeviceInfoSet
;
4259 Request
.DeviceInfoData
= DeviceInfoData
;
4260 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4261 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4262 PropPageData
.NumberOfPages
= 0;
4263 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4268 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4269 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4271 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4276 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4277 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4281 if (hKey
!= INVALID_HANDLE_VALUE
)
4283 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4284 FreeFunctionPointer(hModule
, pPropPageProvider
);
4287 TRACE("Returning %d\n", ret
);
4291 /***********************************************************************
4292 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4294 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4295 IN HDEVINFO DeviceInfoSet
,
4296 IN PSP_DEVINFO_DATA DeviceInfoData
,
4300 IN HINF InfHandle OPTIONAL
,
4301 IN PCSTR InfSectionName OPTIONAL
)
4303 PCWSTR InfSectionNameW
= NULL
;
4304 HKEY ret
= INVALID_HANDLE_VALUE
;
4308 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4309 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4312 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4320 if (InfSectionNameW
!= NULL
)
4321 MyFree((PVOID
)InfSectionNameW
);
4326 /***********************************************************************
4327 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4329 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4330 IN HDEVINFO DeviceInfoSet
,
4331 IN PSP_DEVINFO_DATA DeviceInfoData
,
4335 IN HINF InfHandle OPTIONAL
,
4336 IN PCWSTR InfSectionName OPTIONAL
)
4338 struct DeviceInfoSet
*list
;
4339 HKEY ret
= INVALID_HANDLE_VALUE
;
4341 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4342 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4345 SetLastError(ERROR_INVALID_HANDLE
);
4346 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4347 SetLastError(ERROR_INVALID_HANDLE
);
4348 else if (!DeviceInfoData
)
4349 SetLastError(ERROR_INVALID_PARAMETER
);
4350 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4351 SetLastError(ERROR_INVALID_USER_BUFFER
);
4352 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4353 SetLastError(ERROR_INVALID_PARAMETER
);
4354 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4355 SetLastError(ERROR_INVALID_PARAMETER
);
4356 else if (InfHandle
&& !InfSectionName
)
4357 SetLastError(ERROR_INVALID_PARAMETER
);
4358 else if (!InfHandle
&& InfSectionName
)
4359 SetLastError(ERROR_INVALID_PARAMETER
);
4362 LPWSTR lpGuidString
= NULL
;
4363 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4364 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4365 DWORD Index
; /* Index used in the DriverKey name */
4367 HKEY hHWProfilesKey
= INVALID_HANDLE_VALUE
;
4368 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4369 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4370 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4371 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4372 HKEY hKey
= INVALID_HANDLE_VALUE
;
4375 if (Scope
== DICS_FLAG_GLOBAL
)
4376 RootKey
= list
->HKLM
;
4377 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4379 rc
= RegOpenKeyExW(list
->HKLM
,
4380 L
"SYSTEM\\CurrentControlSet\\Hardware Profiles",
4384 if (rc
!= ERROR_SUCCESS
)
4401 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4410 if (rc
!= ERROR_SUCCESS
)
4415 RootKey
= hHWProfileKey
;
4418 if (KeyType
== DIREG_DEV
)
4420 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4422 rc
= RegCreateKeyExW(
4427 REG_OPTION_NON_VOLATILE
,
4432 if (rc
!= ERROR_SUCCESS
)
4437 rc
= RegCreateKeyExW(
4439 deviceInfo
->DeviceName
,
4442 REG_OPTION_NON_VOLATILE
,
4443 #if _WIN32_WINNT >= 0x502
4444 KEY_READ
| KEY_WRITE
,
4451 if (rc
!= ERROR_SUCCESS
)
4457 else /* KeyType == DIREG_DRV */
4459 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4461 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4462 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4465 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4468 wcscpy(DriverKey
, L
"{");
4469 wcscat(DriverKey
, lpGuidString
);
4470 wcscat(DriverKey
, L
"}\\");
4471 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4472 rc
= RegOpenKeyExW(RootKey
,
4477 if (rc
!= ERROR_SUCCESS
)
4483 /* Try all values for Index between 0 and 9999 */
4485 while (Index
<= 9999)
4488 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4489 rc
= RegCreateKeyEx(hClassKey
,
4493 REG_OPTION_NON_VOLATILE
,
4494 #if _WIN32_WINNT >= 0x502
4495 KEY_READ
| KEY_WRITE
,
4502 if (rc
!= ERROR_SUCCESS
)
4507 if (Disposition
== REG_CREATED_NEW_KEY
)
4510 hKey
= INVALID_HANDLE_VALUE
;
4515 /* Unable to create more than 9999 devices within the same class */
4516 SetLastError(ERROR_GEN_FAILURE
);
4520 /* Open device key, to write Driver value */
4521 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4522 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4524 rc
= RegSetValueEx(hDeviceKey
, L
"Driver", 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4525 if (rc
!= ERROR_SUCCESS
)
4532 /* Do installation of the specified section */
4535 FIXME("Need to install section %s in file %p\n",
4536 debugstr_w(InfSectionName
), InfHandle
);
4542 RpcStringFreeW(&lpGuidString
);
4543 HeapFree(GetProcessHeap(), 0, DriverKey
);
4544 if (hHWProfilesKey
!= INVALID_HANDLE_VALUE
)
4545 RegCloseKey(hHWProfilesKey
);
4546 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4547 RegCloseKey(hHWProfileKey
);
4548 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4549 RegCloseKey(hEnumKey
);
4550 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4551 RegCloseKey(hClassKey
);
4552 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4553 RegCloseKey(hDeviceKey
);
4554 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4558 TRACE("Returning 0x%p\n", ret
);
4562 /***********************************************************************
4563 * SetupDiOpenDevRegKey (SETUPAPI.@)
4565 HKEY WINAPI
SetupDiOpenDevRegKey(
4566 HDEVINFO DeviceInfoSet
,
4567 PSP_DEVINFO_DATA DeviceInfoData
,
4573 struct DeviceInfoSet
*list
;
4574 HKEY ret
= INVALID_HANDLE_VALUE
;
4576 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4577 Scope
, HwProfile
, KeyType
, samDesired
);
4580 SetLastError(ERROR_INVALID_HANDLE
);
4581 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4582 SetLastError(ERROR_INVALID_HANDLE
);
4583 else if (!DeviceInfoData
)
4584 SetLastError(ERROR_INVALID_PARAMETER
);
4585 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4586 SetLastError(ERROR_INVALID_USER_BUFFER
);
4587 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4588 SetLastError(ERROR_INVALID_PARAMETER
);
4589 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4590 SetLastError(ERROR_INVALID_PARAMETER
);
4593 HKEY hKey
= INVALID_HANDLE_VALUE
;
4594 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
4595 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4596 LPWSTR DriverKey
= NULL
;
4601 if (Scope
== DICS_FLAG_CONFIGSPECIFIC
)
4603 FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
4605 else /* Scope == DICS_FLAG_GLOBAL */
4611 KEY_ENUMERATE_SUB_KEYS
,
4613 if (rc
!= ERROR_SUCCESS
)
4620 deviceInfo
->DeviceName
,
4622 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4624 RegCloseKey(hRootKey
);
4625 hRootKey
= INVALID_HANDLE_VALUE
;
4626 if (rc
!= ERROR_SUCCESS
)
4631 if (KeyType
== DIREG_DEV
)
4633 /* We're done. Just return the hKey handle */
4637 /* Read the 'Driver' key */
4638 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, NULL
, &dwLength
);
4639 if (rc
!= ERROR_SUCCESS
)
4644 if (dwRegType
!= REG_SZ
)
4646 SetLastError(ERROR_GEN_FAILURE
);
4649 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4652 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4655 rc
= RegQueryValueExW(hKey
, L
"Driver", NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4656 if (rc
!= ERROR_SUCCESS
)
4662 hKey
= INVALID_HANDLE_VALUE
;
4663 /* Need to open the driver key */
4668 KEY_ENUMERATE_SUB_KEYS
,
4670 if (rc
!= ERROR_SUCCESS
)
4681 if (rc
!= ERROR_SUCCESS
)
4689 if (hRootKey
!= INVALID_HANDLE_VALUE
)
4690 RegCloseKey(hRootKey
);
4691 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4695 TRACE("Returning 0x%p\n", ret
);
4699 /***********************************************************************
4700 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
4702 BOOL WINAPI
SetupDiCreateDeviceInfoA(
4703 HDEVINFO DeviceInfoSet
,
4705 CONST GUID
*ClassGuid
,
4706 PCSTR DeviceDescription
,
4708 DWORD CreationFlags
,
4709 PSP_DEVINFO_DATA DeviceInfoData
)
4711 LPWSTR DeviceNameW
= NULL
;
4712 LPWSTR DeviceDescriptionW
= NULL
;
4719 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
4720 if (DeviceNameW
== NULL
) return FALSE
;
4722 if (DeviceDescription
)
4724 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
4725 if (DeviceDescriptionW
== NULL
)
4727 if (DeviceNameW
) MyFree(DeviceNameW
);
4732 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
4733 ClassGuid
, DeviceDescriptionW
,
4734 hwndParent
, CreationFlags
,
4737 if (DeviceNameW
) MyFree(DeviceNameW
);
4738 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
4743 /***********************************************************************
4744 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
4746 BOOL WINAPI
SetupDiCreateDeviceInfoW(
4747 HDEVINFO DeviceInfoSet
,
4749 CONST GUID
*ClassGuid
,
4750 PCWSTR DeviceDescription
,
4752 DWORD CreationFlags
,
4753 PSP_DEVINFO_DATA DeviceInfoData
)
4755 struct DeviceInfoSet
*list
;
4758 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
4759 debugstr_guid(ClassGuid
), DeviceDescription
,
4760 hwndParent
, CreationFlags
, DeviceInfoData
);
4763 SetLastError(ERROR_INVALID_HANDLE
);
4764 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4765 SetLastError(ERROR_INVALID_HANDLE
);
4766 else if (!ClassGuid
)
4767 SetLastError(ERROR_INVALID_PARAMETER
);
4768 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
4769 SetLastError(ERROR_CLASS_MISMATCH
);
4770 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
4772 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
4773 SetLastError(ERROR_INVALID_FLAGS
);
4777 SP_DEVINFO_DATA DevInfo
;
4779 if (CreationFlags
& DICD_GENERATE_ID
)
4781 /* Generate a new unique ID for this device */
4782 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
4783 FIXME("not implemented\n");
4787 /* Device name is fully qualified. Try to open it */
4790 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
4791 rc
= SetupDiOpenDeviceInfoW(
4794 NULL
, /* hwndParent */
4795 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
4800 /* SetupDiOpenDeviceInfoW has already added
4801 * the device info to the device info set
4803 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
4805 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
4807 struct DeviceInfoElement
*deviceInfo
;
4809 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
4811 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4813 if (!DeviceInfoData
)
4817 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
4819 SetLastError(ERROR_INVALID_USER_BUFFER
);
4823 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
4824 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
4825 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4834 TRACE("Returning %d\n", ret
);
4838 /***********************************************************************
4839 * Helper functions for SetupDiBuildDriverInfoList
4843 IN PLIST_ENTRY DriverListHead
,
4844 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
4845 IN LPGUID ClassGuid
,
4846 IN INFCONTEXT ContextDevice
,
4847 IN
struct InfFileDetails
*InfFileDetails
,
4849 IN LPCWSTR ProviderName
,
4850 IN LPCWSTR ManufacturerName
,
4851 IN LPCWSTR MatchingId
,
4852 FILETIME DriverDate
,
4853 DWORDLONG DriverVersion
,
4856 struct DriverInfoElement
*driverInfo
= NULL
;
4857 HANDLE hFile
= INVALID_HANDLE_VALUE
;
4858 DWORD RequiredSize
= 128; /* Initial buffer size */
4859 BOOL Result
= FALSE
;
4860 PLIST_ENTRY PreviousEntry
;
4861 LPWSTR InfInstallSection
= NULL
;
4864 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
4867 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4870 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
4872 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
4873 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
4875 /* Copy InfFileName field */
4876 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
4877 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
4879 /* Fill InfDate field */
4880 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
4881 GENERIC_READ, FILE_SHARE_READ,
4882 NULL, OPEN_EXISTING, 0, NULL);
4883 if (hFile == INVALID_HANDLE_VALUE)
4885 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
4889 /* Fill SectionName field */
4890 Result
= SetupGetStringFieldW(
4893 driverInfo
->Details
.SectionName
, LINE_LEN
,
4898 /* Fill DrvDescription field */
4899 Result
= SetupGetStringFieldW(
4901 0, /* Field index */
4902 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
4905 /* Copy MatchingId information */
4906 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4907 if (!driverInfo
->MatchingId
)
4909 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4912 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4914 /* Get inf install section */
4916 RequiredSize
= 128; /* Initial buffer size */
4917 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4918 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4920 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4921 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4922 if (!InfInstallSection
)
4924 Result
= SetupGetStringFieldW(
4926 1, /* Field index */
4927 InfInstallSection
, RequiredSize
,
4933 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
4934 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
4936 driverInfo
->DriverRank
= Rank
;
4937 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
4938 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
4939 driverInfo
->Info
.DriverType
= DriverType
;
4940 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
4941 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
4942 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
4943 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
4944 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
4947 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
4948 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
4951 driverInfo
->Info
.ProviderName
[0] = '\0';
4952 driverInfo
->Info
.DriverDate
= DriverDate
;
4953 driverInfo
->Info
.DriverVersion
= DriverVersion
;
4954 ReferenceInfFile(InfFileDetails
);
4955 driverInfo
->InfFileDetails
= InfFileDetails
;
4957 /* Insert current driver in driver list, according to its rank */
4958 PreviousEntry
= DriverListHead
->Flink
;
4959 while (PreviousEntry
!= DriverListHead
)
4961 struct DriverInfoElement
*CurrentDriver
;
4962 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
4963 if (CurrentDriver
->DriverRank
> Rank
||
4964 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
4966 /* Insert before the current item */
4967 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
4970 PreviousEntry
= PreviousEntry
->Flink
;
4972 if (PreviousEntry
== DriverListHead
)
4974 /* Insert at the end of the list */
4975 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
4984 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
4985 HeapFree(GetProcessHeap(), 0, driverInfo
);
4987 if (hFile
!= INVALID_HANDLE_VALUE
)
4989 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4995 GetVersionInformationFromInfFile(
4997 OUT LPGUID ClassGuid
,
4998 OUT LPWSTR
* pProviderName
,
4999 OUT FILETIME
* DriverDate
,
5000 OUT DWORDLONG
* DriverVersion
)
5003 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5004 LPWSTR DriverVer
= NULL
;
5005 LPWSTR ProviderName
= NULL
;
5006 LPWSTR pComma
; /* Points into DriverVer */
5007 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5008 SYSTEMTIME SystemTime
;
5010 BOOL ret
= FALSE
; /* Final result */
5012 /* Get class Guid */
5013 if (!SetupGetLineTextW(
5016 L
"Version", L
"ClassGUID",
5017 guidW
, sizeof(guidW
),
5018 NULL
/* Required size */))
5022 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5023 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5025 SetLastError(ERROR_GEN_FAILURE
);
5029 /* Get provider name */
5030 Result
= SetupGetLineTextW(
5032 hInf
, L
"Version", L
"Provider",
5037 /* We know know the needed buffer size */
5038 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5041 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5044 Result
= SetupGetLineTextW(
5046 hInf
, L
"Version", L
"Provider",
5047 ProviderName
, RequiredSize
,
5052 *pProviderName
= ProviderName
;
5054 /* Read the "DriverVer" value */
5055 Result
= SetupGetLineTextW(
5057 hInf
, L
"Version", L
"DriverVer",
5062 /* We know know the needed buffer size */
5063 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5066 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5069 Result
= SetupGetLineTextW(
5071 hInf
, L
"Version", L
"DriverVer",
5072 DriverVer
, RequiredSize
,
5078 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5079 pComma
= wcschr(DriverVer
, ',');
5082 *pComma
= UNICODE_NULL
;
5083 pVersion
= pComma
+ 1;
5085 /* Get driver date version. Invalid date = 00/00/00 */
5086 memset(DriverDate
, 0, sizeof(FILETIME
));
5087 if (wcslen(DriverVer
) == 10
5088 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5089 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5091 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5092 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5093 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5094 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5095 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5096 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5098 /* Get driver version. Invalid version = 0.0.0.0 */
5102 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5103 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5104 LARGE_INTEGER fullVersion
;
5106 pMinor
= strchrW(pVersion
, '.');
5110 pRevision
= strchrW(++pMinor
, '.');
5111 Minor
= atoiW(pMinor
);
5116 pBuild
= strchrW(++pRevision
, '.');
5117 Revision
= atoiW(pRevision
);
5123 Build
= atoiW(pBuild
);
5125 Major
= atoiW(pVersion
);
5126 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5127 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5128 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5135 HeapFree(GetProcessHeap(), 0, ProviderName
);
5136 HeapFree(GetProcessHeap(), 0, DriverVer
);
5141 /***********************************************************************
5142 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5145 SetupDiBuildDriverInfoList(
5146 IN HDEVINFO DeviceInfoSet
,
5147 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5148 IN DWORD DriverType
)
5150 struct DeviceInfoSet
*list
;
5151 SP_DEVINSTALL_PARAMS_W InstallParams
;
5152 PVOID Buffer
= NULL
;
5153 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5154 LPWSTR ProviderName
= NULL
;
5155 LPWSTR ManufacturerName
= NULL
;
5156 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5157 LPWSTR HardwareIDs
= NULL
;
5158 LPWSTR CompatibleIDs
= NULL
;
5159 LPWSTR FullInfFileName
= NULL
;
5160 FILETIME DriverDate
;
5161 DWORDLONG DriverVersion
= 0;
5165 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5168 SetLastError(ERROR_INVALID_HANDLE
);
5169 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5170 SetLastError(ERROR_INVALID_HANDLE
);
5171 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5172 SetLastError(ERROR_INVALID_HANDLE
);
5173 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5174 SetLastError(ERROR_INVALID_PARAMETER
);
5175 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
5176 SetLastError(ERROR_INVALID_PARAMETER
);
5177 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5178 SetLastError(ERROR_INVALID_PARAMETER
);
5179 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5180 SetLastError(ERROR_INVALID_USER_BUFFER
);
5185 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
5186 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5190 if (DriverType
== SPDIT_COMPATDRIVER
)
5192 /* Get hardware IDs list */
5194 RequiredSize
= 512; /* Initial buffer size */
5195 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5196 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5198 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5199 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5202 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5205 Result
= SetupDiGetDeviceRegistryPropertyW(
5217 /* Get compatible IDs list */
5219 RequiredSize
= 512; /* Initial buffer size */
5220 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5221 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5223 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5224 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5227 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5230 Result
= SetupDiGetDeviceRegistryPropertyW(
5233 SPDRP_COMPATIBLEIDS
,
5235 (PBYTE
)CompatibleIDs
,
5238 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5240 /* No compatible ID for this device */
5241 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5242 CompatibleIDs
= NULL
;
5250 /* Enumerate .inf files */
5252 RequiredSize
= 32768; /* Initial buffer size */
5253 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5254 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5256 HeapFree(GetProcessHeap(), 0, Buffer
);
5257 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5261 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5264 Result
= SetupGetInfFileListW(
5265 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5267 Buffer
, RequiredSize
,
5270 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5272 /* No .inf file in specified directory. So, we should
5273 * success as we created an empty driver info list.
5281 LPWSTR pFullFilename
;
5283 if (*InstallParams
.DriverPath
)
5286 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5289 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5290 if (!FullInfFileName
)
5292 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5295 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
5296 wcscat(FullInfFileName
, L
"\\");
5297 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
5301 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5302 if (!FullInfFileName
)
5304 pFullFilename
= &FullInfFileName
[0];
5307 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
5309 INFCONTEXT ContextManufacturer
, ContextDevice
;
5312 wcscpy(pFullFilename
, filename
);
5313 TRACE("Opening file %S\n", FullInfFileName
);
5315 currentInfFileDetails
= HeapAlloc(
5318 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
5319 if (!currentInfFileDetails
)
5321 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5322 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5324 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5325 ReferenceInfFile(currentInfFileDetails
);
5326 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5328 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5329 currentInfFileDetails
= NULL
;
5333 if (!GetVersionInformationFromInfFile(
5334 currentInfFileDetails
->hInf
,
5340 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5341 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5342 currentInfFileDetails
= NULL
;
5346 if (DriverType
== SPDIT_CLASSDRIVER
)
5348 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5349 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5355 /* Get the manufacturers list */
5356 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
5359 Result
= SetupGetStringFieldW(
5360 &ContextManufacturer
,
5361 0, /* Field index */
5366 /* We got the needed size for the buffer */
5367 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5368 if (!ManufacturerName
)
5370 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5373 Result
= SetupGetStringFieldW(
5374 &ContextManufacturer
,
5375 0, /* Field index */
5376 ManufacturerName
, RequiredSize
,
5379 /* Get manufacturer section name */
5380 Result
= SetupGetStringFieldW(
5381 &ContextManufacturer
,
5382 1, /* Field index */
5383 ManufacturerSection
, LINE_LEN
,
5387 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5388 /* Add (possible) extension to manufacturer section name */
5389 Result
= SetupDiGetActualSectionToInstallW(
5390 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5393 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
5394 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5399 if (DriverType
== SPDIT_CLASSDRIVER
)
5401 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5402 if (!AddDriverToList(
5403 &list
->DriverListHead
,
5407 currentInfFileDetails
,
5412 DriverDate
, DriverVersion
,
5418 else /* DriverType = SPDIT_COMPATDRIVER */
5420 /* 1. Get all fields */
5421 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5425 BOOL DriverAlreadyAdded
;
5427 for (i
= 2; i
<= FieldCount
; i
++)
5429 LPWSTR DeviceId
= NULL
;
5431 RequiredSize
= 128; /* Initial buffer size */
5432 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5433 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5435 HeapFree(GetProcessHeap(), 0, DeviceId
);
5436 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5439 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5442 Result
= SetupGetStringFieldW(
5445 DeviceId
, RequiredSize
,
5450 HeapFree(GetProcessHeap(), 0, DeviceId
);
5453 DriverAlreadyAdded
= FALSE
;
5454 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5456 if (wcsicmp(DeviceId
, currentId
) == 0)
5459 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5463 currentInfFileDetails
,
5468 DriverDate
, DriverVersion
,
5469 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5470 DriverAlreadyAdded
= TRUE
;
5475 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5477 if (wcsicmp(DeviceId
, currentId
) == 0)
5480 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5484 currentInfFileDetails
,
5489 DriverDate
, DriverVersion
,
5490 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5491 DriverAlreadyAdded
= TRUE
;
5495 HeapFree(GetProcessHeap(), 0, DeviceId
);
5498 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5501 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5502 ManufacturerName
= NULL
;
5503 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5508 HeapFree(GetProcessHeap(), 0, ProviderName
);
5509 ProviderName
= NULL
;
5511 DereferenceInfFile(currentInfFileDetails
);
5512 currentInfFileDetails
= NULL
;
5523 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5524 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5528 InstallParams
.Flags
|= DI_DIDCLASS
;
5529 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5531 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5534 HeapFree(GetProcessHeap(), 0, ProviderName
);
5535 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5536 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5537 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5538 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5539 if (currentInfFileDetails
)
5540 DereferenceInfFile(currentInfFileDetails
);
5541 HeapFree(GetProcessHeap(), 0, Buffer
);
5543 TRACE("Returning %d\n", ret
);
5547 /***********************************************************************
5548 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5551 SetupDiDeleteDeviceInfo(
5552 IN HDEVINFO DeviceInfoSet
,
5553 IN PSP_DEVINFO_DATA DeviceInfoData
)
5555 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5557 FIXME("not implemented\n");
5558 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5563 /***********************************************************************
5564 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5567 SetupDiDestroyDriverInfoList(
5568 IN HDEVINFO DeviceInfoSet
,
5569 IN PSP_DEVINFO_DATA DeviceInfoData
,
5570 IN DWORD DriverType
)
5572 struct DeviceInfoSet
*list
;
5575 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5578 SetLastError(ERROR_INVALID_HANDLE
);
5579 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5580 SetLastError(ERROR_INVALID_HANDLE
);
5581 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5582 SetLastError(ERROR_INVALID_PARAMETER
);
5583 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5584 SetLastError(ERROR_INVALID_PARAMETER
);
5585 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5586 SetLastError(ERROR_INVALID_USER_BUFFER
);
5589 PLIST_ENTRY ListEntry
;
5590 struct DriverInfoElement
*driverInfo
;
5591 SP_DEVINSTALL_PARAMS_W InstallParams
;
5593 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5594 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5597 if (!DeviceInfoData
)
5598 /* Fall back to destroying class driver list */
5599 DriverType
= SPDIT_CLASSDRIVER
;
5601 if (DriverType
== SPDIT_CLASSDRIVER
)
5603 while (!IsListEmpty(&list
->DriverListHead
))
5605 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
5606 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5607 DestroyDriverInfoElement(driverInfo
);
5609 InstallParams
.Reserved
= 0;
5610 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
5611 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
5612 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
5616 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
5617 struct DeviceInfoElement
*deviceInfo
;
5619 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5620 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
5622 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5623 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
5625 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
5626 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5627 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
5629 InstallParamsSet
.Reserved
= 0;
5630 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
5632 DestroyDriverInfoElement(driverInfo
);
5634 InstallParams
.Reserved
= 0;
5635 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
5636 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
5637 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5642 TRACE("Returning %d\n", ret
);
5647 /***********************************************************************
5648 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
5651 SetupDiOpenDeviceInfoA(
5652 IN HDEVINFO DeviceInfoSet
,
5653 IN PCSTR DeviceInstanceId
,
5654 IN HWND hwndParent OPTIONAL
,
5656 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5658 LPWSTR DeviceInstanceIdW
= NULL
;
5661 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5663 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
5664 if (DeviceInstanceIdW
== NULL
)
5667 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
5668 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
5670 MyFree(DeviceInstanceIdW
);
5676 /***********************************************************************
5677 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
5680 SetupDiOpenDeviceInfoW(
5681 IN HDEVINFO DeviceInfoSet
,
5682 IN PCWSTR DeviceInstanceId
,
5683 IN HWND hwndParent OPTIONAL
,
5685 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5687 struct DeviceInfoSet
*list
;
5688 HKEY hEnumKey
, hKey
;
5692 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5694 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
5695 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
5698 SetLastError(ERROR_INVALID_HANDLE
);
5699 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5700 SetLastError(ERROR_INVALID_HANDLE
);
5701 else if (!DeviceInstanceId
)
5702 SetLastError(ERROR_INVALID_PARAMETER
);
5703 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
5705 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
5706 SetLastError(ERROR_INVALID_FLAGS
);
5708 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5709 SetLastError(ERROR_INVALID_USER_BUFFER
);
5712 struct DeviceInfoElement
*deviceInfo
= NULL
;
5713 /* Search if device already exists in DeviceInfoSet.
5714 * If yes, return the existing element
5715 * If no, create a new element using informations in registry
5717 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
5718 while (ItemList
!= &list
->ListHead
)
5723 FIXME("not implemented\n");
5724 ItemList
= ItemList
->Flink
;
5729 /* good one found */
5734 /* Open supposed registry key */
5739 KEY_ENUMERATE_SUB_KEYS
,
5741 if (rc
!= ERROR_SUCCESS
)
5752 RegCloseKey(hEnumKey
);
5753 if (rc
!= ERROR_SUCCESS
)
5755 if (rc
== ERROR_FILE_NOT_FOUND
)
5756 rc
= ERROR_NO_SUCH_DEVINST
;
5761 /* FIXME: try to get ClassGUID from registry, instead of
5762 * sending GUID_NULL to CreateDeviceInfoElement
5764 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
5769 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5775 if (ret
&& deviceInfo
&& DeviceInfoData
)
5777 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
5778 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5779 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5787 /***********************************************************************
5788 * SetupDiEnumDriverInfoA (SETUPAPI.@)
5791 SetupDiEnumDriverInfoA(
5792 IN HDEVINFO DeviceInfoSet
,
5793 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5794 IN DWORD DriverType
,
5795 IN DWORD MemberIndex
,
5796 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
5798 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
5801 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
5802 DriverType
, MemberIndex
, DriverInfoData
);
5804 if (DriverInfoData
== NULL
)
5805 SetLastError(ERROR_INVALID_PARAMETER
);
5806 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
5807 SetLastError(ERROR_INVALID_USER_BUFFER
);
5810 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5811 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
5812 DriverType
, MemberIndex
, &driverInfoData2W
);
5816 /* Do W->A conversion */
5817 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
5818 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
5819 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
5820 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
5822 DriverInfoData
->Description
[0] = '\0';
5825 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
5826 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
5828 DriverInfoData
->MfgName
[0] = '\0';
5831 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
5832 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
5834 DriverInfoData
->ProviderName
[0] = '\0';
5837 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5839 /* Copy more fields */
5840 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
5841 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
5846 TRACE("Returning %d\n", ret
);
5851 /***********************************************************************
5852 * SetupDiEnumDriverInfoW (SETUPAPI.@)
5855 SetupDiEnumDriverInfoW(
5856 IN HDEVINFO DeviceInfoSet
,
5857 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5858 IN DWORD DriverType
,
5859 IN DWORD MemberIndex
,
5860 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
5862 PLIST_ENTRY ListHead
;
5865 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
5866 DriverType
, MemberIndex
, DriverInfoData
);
5868 if (!DeviceInfoSet
|| !DriverInfoData
)
5869 SetLastError(ERROR_INVALID_PARAMETER
);
5870 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5871 SetLastError(ERROR_INVALID_HANDLE
);
5872 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5873 SetLastError(ERROR_INVALID_HANDLE
);
5874 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5875 SetLastError(ERROR_INVALID_PARAMETER
);
5876 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
5877 SetLastError(ERROR_INVALID_PARAMETER
);
5878 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5879 SetLastError(ERROR_INVALID_PARAMETER
);
5880 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5881 SetLastError(ERROR_INVALID_USER_BUFFER
);
5884 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5885 PLIST_ENTRY ItemList
;
5886 if (DriverType
== SPDIT_CLASSDRIVER
||
5887 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
5889 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
5893 ListHead
= &devInfo
->DriverListHead
;
5896 ItemList
= ListHead
->Flink
;
5897 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
5898 ItemList
= ItemList
->Flink
;
5899 if (ItemList
== ListHead
)
5900 SetLastError(ERROR_NO_MORE_ITEMS
);
5903 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
5906 &DriverInfoData
->DriverType
,
5907 &DrvInfo
->Info
.DriverType
,
5908 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
5913 TRACE("Returning %d\n", ret
);
5918 /***********************************************************************
5919 * SetupDiGetSelectedDriverA (SETUPAPI.@)
5922 SetupDiGetSelectedDriverA(
5923 IN HDEVINFO DeviceInfoSet
,
5924 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5925 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
5927 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
5930 if (DriverInfoData
== NULL
)
5931 SetLastError(ERROR_INVALID_PARAMETER
);
5932 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
5933 SetLastError(ERROR_INVALID_USER_BUFFER
);
5936 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5938 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
5944 /* Do W->A conversion */
5945 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
5946 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
5947 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
5948 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
5950 DriverInfoData
->Description
[0] = '\0';
5953 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
5954 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
5956 DriverInfoData
->MfgName
[0] = '\0';
5959 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
5960 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
5962 DriverInfoData
->ProviderName
[0] = '\0';
5965 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5967 /* Copy more fields */
5968 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
5969 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
5978 /***********************************************************************
5979 * SetupDiGetSelectedDriverW (SETUPAPI.@)
5982 SetupDiGetSelectedDriverW(
5983 IN HDEVINFO DeviceInfoSet
,
5984 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5985 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
5989 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
5991 if (!DeviceInfoSet
|| !DriverInfoData
)
5992 SetLastError(ERROR_INVALID_PARAMETER
);
5993 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5994 SetLastError(ERROR_INVALID_HANDLE
);
5995 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5996 SetLastError(ERROR_INVALID_HANDLE
);
5997 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5998 SetLastError(ERROR_INVALID_USER_BUFFER
);
5999 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6000 SetLastError(ERROR_INVALID_USER_BUFFER
);
6003 SP_DEVINSTALL_PARAMS InstallParams
;
6005 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
6006 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6008 struct DriverInfoElement
*driverInfo
;
6009 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6010 if (driverInfo
== NULL
)
6011 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6015 &DriverInfoData
->DriverType
,
6016 &driverInfo
->Info
.DriverType
,
6017 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6023 TRACE("Returning %d\n", ret
);
6028 /***********************************************************************
6029 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6032 SetupDiSetSelectedDriverA(
6033 IN HDEVINFO DeviceInfoSet
,
6034 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6035 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6037 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6038 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6041 if (DriverInfoData
!= NULL
)
6043 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6044 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6046 SetLastError(ERROR_INVALID_PARAMETER
);
6050 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6051 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6053 if (DriverInfoDataW
.Reserved
== 0)
6055 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6057 /* convert the strings to unicode */
6058 if (!MultiByteToWideChar(CP_ACP
,
6060 DriverInfoData
->Description
,
6062 DriverInfoDataW
.Description
,
6064 !MultiByteToWideChar(CP_ACP
,
6066 DriverInfoData
->ProviderName
,
6068 DriverInfoDataW
.ProviderName
,
6075 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6078 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6082 if (ret
&& pDriverInfoDataW
!= NULL
)
6084 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6091 /***********************************************************************
6092 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6095 SetupDiSetSelectedDriverW(
6096 IN HDEVINFO DeviceInfoSet
,
6097 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6098 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6102 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6105 SetLastError(ERROR_INVALID_PARAMETER
);
6106 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6107 SetLastError(ERROR_INVALID_HANDLE
);
6108 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6109 SetLastError(ERROR_INVALID_HANDLE
);
6110 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6111 SetLastError(ERROR_INVALID_USER_BUFFER
);
6112 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6113 SetLastError(ERROR_INVALID_USER_BUFFER
);
6116 struct DriverInfoElement
**pDriverInfo
;
6117 PLIST_ENTRY ListHead
, ItemList
;
6121 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6122 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6126 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6127 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6130 if (!DriverInfoData
)
6132 *pDriverInfo
= NULL
;
6137 /* Search selected driver in list */
6138 ItemList
= ListHead
->Flink
;
6139 while (ItemList
!= ListHead
)
6141 if (DriverInfoData
->Reserved
!= 0)
6143 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6148 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6149 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
6150 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6151 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6152 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6158 if (ItemList
== ListHead
)
6159 SetLastError(ERROR_INVALID_PARAMETER
);
6162 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
6163 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6165 TRACE("Choosing driver whose rank is 0x%lx\n",
6166 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
6168 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6173 TRACE("Returning %d\n", ret
);
6177 /***********************************************************************
6178 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6181 SetupDiGetDriverInfoDetailA(
6182 IN HDEVINFO DeviceInfoSet
,
6183 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6184 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6185 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6186 IN DWORD DriverInfoDetailDataSize
,
6187 OUT PDWORD RequiredSize OPTIONAL
)
6189 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6190 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6192 DWORD HardwareIDLen
= 0;
6195 /* do some sanity checks, the unicode version might do more thorough checks */
6196 if (DriverInfoData
== NULL
||
6197 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6198 (DriverInfoDetailData
!= NULL
&&
6199 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6200 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6202 SetLastError(ERROR_INVALID_PARAMETER
);
6206 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6207 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6209 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6211 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6213 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6217 SetLastError(ERROR_INVALID_PARAMETER
);
6220 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6221 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6223 /* convert the strings to unicode */
6224 if (MultiByteToWideChar(CP_ACP
,
6226 DriverInfoData
->Description
,
6228 DriverInfoDataW
.Description
,
6230 MultiByteToWideChar(CP_ACP
,
6232 DriverInfoData
->MfgName
,
6234 DriverInfoDataW
.MfgName
,
6236 MultiByteToWideChar(CP_ACP
,
6238 DriverInfoData
->ProviderName
,
6240 DriverInfoDataW
.ProviderName
,
6243 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6245 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6246 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6249 if (DriverInfoDetailData
!= NULL
)
6251 /* calculate the unicode buffer size from the ansi buffer size */
6252 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6253 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6254 (HardwareIDLen
* sizeof(WCHAR
));
6256 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6257 if (DriverInfoDetailDataW
== NULL
)
6259 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6263 /* initialize the buffer */
6264 ZeroMemory(DriverInfoDetailDataW
,
6266 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6269 /* call the unicode version */
6270 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6273 DriverInfoDetailDataW
,
6279 if (DriverInfoDetailDataW
!= NULL
)
6281 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6282 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6283 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6284 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6285 if (WideCharToMultiByte(CP_ACP
,
6287 DriverInfoDetailDataW
->SectionName
,
6289 DriverInfoDetailData
->SectionName
,
6293 WideCharToMultiByte(CP_ACP
,
6295 DriverInfoDetailDataW
->InfFileName
,
6297 DriverInfoDetailData
->InfFileName
,
6301 WideCharToMultiByte(CP_ACP
,
6303 DriverInfoDetailDataW
->DrvDescription
,
6305 DriverInfoDetailData
->DrvDescription
,
6309 WideCharToMultiByte(CP_ACP
,
6311 DriverInfoDetailDataW
->HardwareID
,
6313 DriverInfoDetailData
->HardwareID
,
6319 DWORD hwidlen
= HardwareIDLen
;
6320 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6322 /* count the strings in the list */
6325 len
= lstrlenA(s
) + 1;
6334 /* looks like the string list wasn't terminated... */
6335 SetLastError(ERROR_INVALID_USER_BUFFER
);
6341 /* make sure CompatIDsOffset points to the second string in the
6345 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6346 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6347 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6351 DriverInfoDetailData
->CompatIDsOffset
= 0;
6352 DriverInfoDetailData
->CompatIDsLength
= 0;
6361 if (RequiredSize
!= NULL
)
6363 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6364 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6370 if (DriverInfoDetailDataW
!= NULL
)
6372 MyFree(DriverInfoDetailDataW
);
6378 /***********************************************************************
6379 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6382 SetupDiGetDriverInfoDetailW(
6383 IN HDEVINFO DeviceInfoSet
,
6384 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6385 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6386 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6387 IN DWORD DriverInfoDetailDataSize
,
6388 OUT PDWORD RequiredSize OPTIONAL
)
6392 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6393 DriverInfoData
, DriverInfoDetailData
,
6394 DriverInfoDetailDataSize
, RequiredSize
);
6397 SetLastError(ERROR_INVALID_PARAMETER
);
6398 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6399 SetLastError(ERROR_INVALID_HANDLE
);
6400 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6401 SetLastError(ERROR_INVALID_HANDLE
);
6402 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6403 SetLastError(ERROR_INVALID_USER_BUFFER
);
6404 else if (!DriverInfoData
)
6405 SetLastError(ERROR_INVALID_PARAMETER
);
6406 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6407 SetLastError(ERROR_INVALID_PARAMETER
);
6408 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6409 SetLastError(ERROR_INVALID_PARAMETER
);
6410 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6411 SetLastError(ERROR_INVALID_USER_BUFFER
);
6412 else if (DriverInfoData
->Reserved
== 0)
6413 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6416 struct DriverInfoElement
*driverInfoElement
;
6417 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6420 DriverInfoDetailData
,
6421 &driverInfoElement
->Details
,
6422 driverInfoElement
->Details
.cbSize
);
6423 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6424 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6429 TRACE("Returning %d\n", ret
);
6433 /* Return the current hardware profile id, or -1 if error */
6435 GetCurrentHwProfile(
6436 IN HDEVINFO DeviceInfoSet
)
6438 HKEY hKey
= INVALID_HANDLE_VALUE
;
6439 DWORD dwRegType
, dwLength
;
6442 DWORD ret
= (DWORD
)-1;
6445 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
6446 REGSTR_PATH_IDCONFIGDB
,
6450 if (rc
!= ERROR_SUCCESS
)
6456 dwLength
= sizeof(DWORD
);
6457 rc
= RegQueryValueExW(
6459 REGSTR_VAL_CURRENTCONFIG
,
6462 (LPBYTE
)&hwProfile
, &dwLength
);
6463 if (rc
!= ERROR_SUCCESS
)
6468 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6470 SetLastError(ERROR_GEN_FAILURE
);
6477 if (hKey
!= INVALID_HANDLE_VALUE
)
6483 /***********************************************************************
6484 * SetupDiChangeState (SETUPAPI.@)
6486 static BOOL
StartDevice(VOID
) { FIXME("Stub"); return TRUE
; }
6487 static BOOL
StopDevice(VOID
) { FIXME("Stub"); return TRUE
; }
6490 IN HDEVINFO DeviceInfoSet
,
6491 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6493 PSP_PROPCHANGE_PARAMS PropChange
;
6494 HKEY hKey
= INVALID_HANDLE_VALUE
;
6495 LPCWSTR RegistryValueName
;
6496 DWORD dwConfigFlags
, dwLength
, dwRegType
;
6500 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6502 if (!DeviceInfoData
)
6503 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
6505 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
6508 SetLastError(ERROR_INVALID_PARAMETER
);
6512 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
6513 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
6515 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
6517 switch (PropChange
->StateChange
)
6522 /* Enable/disable device in registry */
6523 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
6524 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6525 hKey
= SetupDiCreateDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
6526 if (hKey
== INVALID_HANDLE_VALUE
)
6528 dwLength
= sizeof(DWORD
);
6529 rc
= RegQueryValueExW(
6534 (LPBYTE
)&dwConfigFlags
, &dwLength
);
6535 if (rc
== ERROR_FILE_NOT_FOUND
)
6537 else if (rc
!= ERROR_SUCCESS
)
6542 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6544 SetLastError(ERROR_GEN_FAILURE
);
6547 if (PropChange
->StateChange
== DICS_ENABLE
)
6548 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6550 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6556 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
6557 if (rc
!= ERROR_SUCCESS
)
6563 /* Enable/disable device if needed */
6564 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
6565 || PropChange
->HwProfile
== 0
6566 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
6568 if (PropChange
->StateChange
== DICS_ENABLE
)
6569 ret
= StartDevice();
6577 case DICS_PROPCHANGE
:
6579 ret
= StopDevice() && StartDevice();
6584 FIXME("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
6585 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
6590 if (hKey
!= INVALID_HANDLE_VALUE
)
6593 TRACE("Returning %d\n", ret
);
6597 /***********************************************************************
6598 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
6601 SetupDiSelectBestCompatDrv(
6602 IN HDEVINFO DeviceInfoSet
,
6603 IN PSP_DEVINFO_DATA DeviceInfoData
)
6605 SP_DRVINFO_DATA_W drvInfoData
;
6608 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6610 /* Drivers are sorted by rank in the driver list, so
6611 * the first driver in the list is the best one.
6613 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
6614 ret
= SetupDiEnumDriverInfoW(
6618 0, /* Member index */
6623 ret
= SetupDiSetSelectedDriverW(
6629 TRACE("Returning %d\n", ret
);
6633 /***********************************************************************
6634 * SetupDiInstallDriverFiles (SETUPAPI.@)
6637 SetupDiInstallDriverFiles(
6638 IN HDEVINFO DeviceInfoSet
,
6639 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6643 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6646 SetLastError(ERROR_INVALID_PARAMETER
);
6647 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6648 SetLastError(ERROR_INVALID_HANDLE
);
6649 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6650 SetLastError(ERROR_INVALID_HANDLE
);
6651 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6652 SetLastError(ERROR_INVALID_USER_BUFFER
);
6653 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
6654 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6655 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
6656 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6659 SP_DEVINSTALL_PARAMS_W InstallParams
;
6660 struct DriverInfoElement
*SelectedDriver
;
6661 WCHAR SectionName
[MAX_PATH
];
6662 DWORD SectionNameLength
= 0;
6664 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6665 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6669 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6670 if (!SelectedDriver
)
6672 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6676 ret
= SetupDiGetActualSectionToInstallW(
6677 SelectedDriver
->InfFileDetails
->hInf
,
6678 SelectedDriver
->Details
.SectionName
,
6679 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6683 if (!InstallParams
.InstallMsgHandler
)
6685 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6686 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6687 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6689 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6690 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6691 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
6692 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6693 DeviceInfoSet
, DeviceInfoData
);
6697 TRACE("Returning %d\n", ret
);
6701 /***********************************************************************
6702 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
6705 SetupDiRegisterCoDeviceInstallers(
6706 IN HDEVINFO DeviceInfoSet
,
6707 IN PSP_DEVINFO_DATA DeviceInfoData
)
6709 BOOL ret
= FALSE
; /* Return value */
6711 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6714 SetLastError(ERROR_INVALID_PARAMETER
);
6715 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6716 SetLastError(ERROR_INVALID_HANDLE
);
6717 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6718 SetLastError(ERROR_INVALID_HANDLE
);
6719 else if (!DeviceInfoData
)
6720 SetLastError(ERROR_INVALID_PARAMETER
);
6721 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6722 SetLastError(ERROR_INVALID_USER_BUFFER
);
6725 SP_DEVINSTALL_PARAMS_W InstallParams
;
6726 struct DriverInfoElement
*SelectedDriver
;
6729 WCHAR SectionName
[MAX_PATH
];
6730 DWORD SectionNameLength
= 0;
6731 HKEY hKey
= INVALID_HANDLE_VALUE
;
6733 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6734 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6738 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6739 if (SelectedDriver
== NULL
)
6741 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6745 /* Get .CoInstallers section name */
6746 Result
= SetupDiGetActualSectionToInstallW(
6747 SelectedDriver
->InfFileDetails
->hInf
,
6748 SelectedDriver
->Details
.SectionName
,
6749 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6750 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".CoInstallers") - 1)
6752 wcscat(SectionName
, L
".CoInstallers");
6754 /* Open/Create driver key information */
6755 #if _WIN32_WINNT >= 0x502
6756 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
6758 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
6760 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6761 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
6762 if (hKey
== INVALID_HANDLE_VALUE
)
6765 /* Install .CoInstallers section */
6766 DoAction
= SPINST_REGISTRY
;
6767 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
6769 DoAction
|= SPINST_FILES
;
6770 if (!InstallParams
.InstallMsgHandler
)
6772 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6773 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6774 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6777 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6778 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6779 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
6780 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6781 DeviceInfoSet
, DeviceInfoData
);
6788 if (hKey
!= INVALID_HANDLE_VALUE
)
6792 TRACE("Returning %d\n", ret
);
6796 /***********************************************************************
6797 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
6800 SetupDiInstallDeviceInterfaces(
6801 IN HDEVINFO DeviceInfoSet
,
6802 IN PSP_DEVINFO_DATA DeviceInfoData
)
6804 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6806 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
6807 //SetLastError(ERROR_GEN_FAILURE);
6813 InfIsFromOEMLocation(
6815 OUT LPBOOL IsOEMLocation
)
6819 last
= strrchrW(FullName
, '\\');
6822 /* No directory specified */
6823 *IsOEMLocation
= FALSE
;
6827 WCHAR Windir
[MAX_PATH
];
6830 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
6831 if (ret
== 0 || ret
>= MAX_PATH
)
6833 SetLastError(ERROR_GEN_FAILURE
);
6837 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
6839 /* The path is %SYSTEMROOT%\Inf */
6840 *IsOEMLocation
= FALSE
;
6844 /* The file is in another place */
6845 *IsOEMLocation
= TRUE
;
6851 /***********************************************************************
6852 * SetupDiInstallDevice (SETUPAPI.@)
6855 SetupDiInstallDevice(
6856 IN HDEVINFO DeviceInfoSet
,
6857 IN PSP_DEVINFO_DATA DeviceInfoData
)
6859 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6860 SP_DEVINSTALL_PARAMS_W InstallParams
;
6861 struct DriverInfoElement
*SelectedDriver
;
6862 SYSTEMTIME DriverDate
;
6863 WCHAR SectionName
[MAX_PATH
];
6865 DWORD SectionNameLength
= 0;
6866 BOOL Result
= FALSE
;
6867 INFCONTEXT ContextService
;
6871 LPCWSTR AssociatedService
= NULL
;
6872 LPWSTR pSectionName
= NULL
;
6873 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
6875 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
6876 BOOL RebootRequired
= FALSE
;
6877 HKEY hKey
= INVALID_HANDLE_VALUE
;
6878 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
6879 BOOL NeedtoCopyFile
;
6880 LARGE_INTEGER fullVersion
;
6882 BOOL ret
= FALSE
; /* Return value */
6884 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6887 SetLastError(ERROR_INVALID_PARAMETER
);
6888 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6889 SetLastError(ERROR_INVALID_HANDLE
);
6890 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6891 SetLastError(ERROR_INVALID_HANDLE
);
6892 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6893 SetLastError(ERROR_INVALID_USER_BUFFER
);
6899 /* One parameter is bad */
6903 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6904 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6908 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
6910 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
6914 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6915 if (SelectedDriver
== NULL
)
6917 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6921 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
6923 Result
= SetupDiGetActualSectionToInstallW(
6924 SelectedDriver
->InfFileDetails
->hInf
,
6925 SelectedDriver
->Details
.SectionName
,
6926 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6927 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
6929 pSectionName
= &SectionName
[wcslen(SectionName
)];
6931 /* Get information from [Version] section */
6932 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
6934 /* Format ClassGuid to a string */
6935 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
6937 RequiredSize
= lstrlenW(lpGuidString
);
6938 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
6939 if (!lpFullGuidString
)
6941 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6944 lpFullGuidString
[0] = '{';
6945 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
6946 lpFullGuidString
[RequiredSize
+ 1] = '}';
6947 lpFullGuidString
[RequiredSize
+ 2] = '\0';
6949 /* Open/Create driver key information */
6950 #if _WIN32_WINNT >= 0x502
6951 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
6953 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
6955 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6956 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
6957 if (hKey
== INVALID_HANDLE_VALUE
)
6960 /* Install main section */
6961 DoAction
= SPINST_REGISTRY
;
6962 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
6964 DoAction
|= SPINST_FILES
;
6965 if (!InstallParams
.InstallMsgHandler
)
6967 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6968 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6969 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6972 *pSectionName
= '\0';
6973 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6974 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6975 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
6976 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6977 DeviceInfoSet
, DeviceInfoData
);
6980 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
6982 if (Result
&& InstallParams
.InstallMsgHandler
== SetupDefaultQueueCallbackW
)
6984 /* Delete resources allocated by SetupInitDefaultQueueCallback */
6985 SetupTermDefaultQueueCallback(InstallParams
.InstallMsgHandlerContext
);
6988 InstallParams
.Flags
|= DI_NOFILECOPY
;
6989 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6991 /* Write information to driver key */
6992 *pSectionName
= UNICODE_NULL
;
6993 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
6994 TRACE("Write information to driver key\n");
6995 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
6996 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
6997 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
6998 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
6999 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
7000 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
7001 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
7002 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
7003 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7004 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7005 if (rc
== ERROR_SUCCESS
)
7006 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7007 if (rc
== ERROR_SUCCESS
)
7008 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7009 if (rc
== ERROR_SUCCESS
)
7011 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7012 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7014 if (rc
== ERROR_SUCCESS
)
7015 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7016 if (rc
== ERROR_SUCCESS
)
7017 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7018 if (rc
== ERROR_SUCCESS
)
7019 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7020 if (rc
== ERROR_SUCCESS
)
7021 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7022 if (rc
== ERROR_SUCCESS
)
7023 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7024 if (rc
!= ERROR_SUCCESS
)
7030 hKey
= INVALID_HANDLE_VALUE
;
7032 /* FIXME: Process .LogConfigOverride section */
7034 /* Install .Services section */
7035 wcscpy(pSectionName
, L
".Services");
7036 Result
= SetupFindFirstLineW(SelectedDriver
->InfFileDetails
->hInf
, SectionName
, NULL
, &ContextService
);
7039 LPWSTR ServiceName
= NULL
;
7040 LPWSTR ServiceSection
= NULL
;
7042 Result
= SetupGetStringFieldW(
7044 1, /* Field index */
7049 if (RequiredSize
> 0)
7051 /* We got the needed size for the buffer */
7052 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
7055 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7058 Result
= SetupGetStringFieldW(
7060 1, /* Field index */
7061 ServiceName
, RequiredSize
,
7066 Result
= SetupGetIntField(
7068 2, /* Field index */
7072 /* The field may be empty. Ignore the error */
7075 Result
= SetupGetStringFieldW(
7077 3, /* Field index */
7082 if (GetLastError() == ERROR_INVALID_PARAMETER
)
7084 /* This first is probably missing. It is not
7085 * required, so ignore the error */
7092 if (RequiredSize
> 0)
7094 /* We got the needed size for the buffer */
7095 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
7096 if (!ServiceSection
)
7098 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7101 Result
= SetupGetStringFieldW(
7103 3, /* Field index */
7104 ServiceSection
, RequiredSize
,
7109 SetLastError(ERROR_SUCCESS
);
7110 Result
= SetupInstallServicesFromInfSectionExW(
7111 SelectedDriver
->InfFileDetails
->hInf
,
7112 ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
7114 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
7116 AssociatedService
= ServiceName
;
7118 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
7119 RebootRequired
= TRUE
;
7122 HeapFree(GetProcessHeap(), 0, ServiceName
);
7123 HeapFree(GetProcessHeap(), 0, ServiceSection
);
7126 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
7129 /* Copy .inf file to Inf\ directory (if needed) */
7130 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7135 Result
= SetupCopyOEMInfW(
7136 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7139 SP_COPY_NOOVERWRITE
,
7145 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7146 * to release use of current InfFile */
7149 /* Open device registry key */
7150 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7151 if (hKey
== INVALID_HANDLE_VALUE
)
7154 /* Install .HW section */
7155 wcscpy(pSectionName
, L
".HW");
7156 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7157 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7158 SPINST_REGISTRY
, hKey
, NULL
, 0,
7159 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7160 DeviceInfoSet
, DeviceInfoData
);
7164 /* Write information to enum key */
7165 TRACE("Write information to enum key\n");
7166 TRACE("Class : '%S'\n", ClassName
);
7167 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
7168 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7169 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
7170 TRACE("Service : '%S'\n", AssociatedService
);
7171 rc
= RegSetValueEx(hKey
, L
"Class", 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
7172 if (rc
== ERROR_SUCCESS
)
7173 rc
= RegSetValueEx(hKey
, L
"ClassGUID", 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7174 if (rc
== ERROR_SUCCESS
)
7175 rc
= RegSetValueEx(hKey
, L
"DeviceDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7176 if (rc
== ERROR_SUCCESS
)
7177 rc
= RegSetValueEx(hKey
, L
"Mfg", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7178 if (rc
== ERROR_SUCCESS
&& *AssociatedService
)
7179 rc
= RegSetValueEx(hKey
, L
"Service", 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
7180 if (rc
!= ERROR_SUCCESS
)
7186 /* Start the device */
7187 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7189 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
7191 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DevInfo
->DeviceName
);
7192 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
7193 ret
= NT_SUCCESS(Status
);
7199 /* End of installation */
7200 if (hClassKey
!= INVALID_HANDLE_VALUE
)
7201 RegCloseKey(hClassKey
);
7202 if (hKey
!= INVALID_HANDLE_VALUE
)
7205 RpcStringFreeW(&lpGuidString
);
7206 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
7207 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7209 TRACE("Returning %d\n", ret
);