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 NtExtension
[] = {'.','N','T',0};
34 static const WCHAR NtPlatformExtension
[] = {'.','N','T','x','8','6',0};
35 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
36 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
37 static const WCHAR WinExtension
[] = {'.','W','i','n',0};
39 /* FIXME: header mess */
40 DEFINE_GUID(GUID_NULL
,
41 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
43 (CALLBACK
* CLASS_INSTALL_PROC
) (
44 IN DI_FUNCTION InstallFunction
,
45 IN HDEVINFO DeviceInfoSet
,
46 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
48 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
49 IN HDEVINFO DeviceInfoSet
,
50 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
52 (CALLBACK
* COINSTALLER_PROC
) (
53 IN DI_FUNCTION InstallFunction
,
54 IN HDEVINFO DeviceInfoSet
,
55 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
56 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
58 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
59 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
60 IN LPFNADDPROPSHEETPAGE fAddFunc
,
63 (*UPDATE_CLASS_PARAM_HANDLER
) (
64 IN HDEVINFO DeviceInfoSet
,
65 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
66 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
67 IN DWORD ClassInstallParamsSize
);
69 struct CoInstallerElement
74 COINSTALLER_PROC Function
;
75 BOOL DoPostProcessing
;
80 PropertyChangeHandler(
81 IN HDEVINFO DeviceInfoSet
,
82 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
83 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
84 IN DWORD ClassInstallParamsSize
);
86 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
87 NULL
, /* DIF_SELECTDEVICE */
88 NULL
, /* DIF_INSTALLDEVICE */
89 NULL
, /* DIF_ASSIGNRESOURCES */
90 NULL
, /* DIF_PROPERTIES */
91 NULL
, /* DIF_REMOVE */
92 NULL
, /* DIF_FIRSTTIMESETUP */
93 NULL
, /* DIF_FOUNDDEVICE */
94 NULL
, /* DIF_SELECTCLASSDRIVERS */
95 NULL
, /* DIF_VALIDATECLASSDRIVERS */
96 NULL
, /* DIF_INSTALLCLASSDRIVERS */
97 NULL
, /* DIF_CALCDISKSPACE */
98 NULL
, /* DIF_DESTROYPRIVATEDATA */
99 NULL
, /* DIF_VALIDATEDRIVER */
100 NULL
, /* DIF_MOVEDEVICE */
101 NULL
, /* DIF_DETECT */
102 NULL
, /* DIF_INSTALLWIZARD */
103 NULL
, /* DIF_DESTROYWIZARDDATA */
104 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
105 NULL
, /* DIF_ENABLECLASS */
106 NULL
, /* DIF_DETECTVERIFY */
107 NULL
, /* DIF_INSTALLDEVICEFILES */
108 NULL
, /* DIF_UNREMOVE */
109 NULL
, /* DIF_SELECTBESTCOMPATDRV */
110 NULL
, /* DIF_ALLOW_INSTALL */
111 NULL
, /* DIF_REGISTERDEVICE */
112 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
113 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
114 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
115 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
116 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
117 NULL
, /* DIF_UNUSED1 */
118 NULL
, /* DIF_INSTALLINTERFACES */
119 NULL
, /* DIF_DETECTCANCEL */
120 NULL
, /* DIF_REGISTER_COINSTALLERS */
121 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
122 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
123 NULL
, /* DIF_RESERVED1 */
124 NULL
, /* DIF_TROUBLESHOOTER */
125 NULL
, /* DIF_POWERMESSAGEWAKE */
126 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
127 NULL
, /* DIF_UPDATEDRIVER_UI */
128 NULL
/* DIF_RESERVED2 */
131 /***********************************************************************
132 * SetupDiBuildClassInfoList (SETUPAPI.@)
134 BOOL WINAPI
SetupDiBuildClassInfoList(
136 LPGUID ClassGuidList
,
137 DWORD ClassGuidListSize
,
141 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
142 ClassGuidListSize
, RequiredSize
,
146 /***********************************************************************
147 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
149 BOOL WINAPI
SetupDiBuildClassInfoListExA(
151 LPGUID ClassGuidList
,
152 DWORD ClassGuidListSize
,
157 LPWSTR MachineNameW
= NULL
;
164 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
165 if (MachineNameW
== NULL
) return FALSE
;
168 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
169 ClassGuidListSize
, RequiredSize
,
170 MachineNameW
, Reserved
);
173 MyFree(MachineNameW
);
178 /***********************************************************************
179 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
181 BOOL WINAPI
SetupDiBuildClassInfoListExW(
183 LPGUID ClassGuidList
,
184 DWORD ClassGuidListSize
,
189 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
195 DWORD dwGuidListIndex
= 0;
197 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
198 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
200 if (RequiredSize
!= NULL
)
203 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
204 KEY_ENUMERATE_SUB_KEYS
,
208 if (hClassesKey
== INVALID_HANDLE_VALUE
)
213 for (dwIndex
= 0; ; dwIndex
++)
215 dwLength
= MAX_GUID_STRING_LEN
+ 1;
216 lError
= RegEnumKeyExW(hClassesKey
,
224 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
225 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
227 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
229 if (RegOpenKeyExW(hClassesKey
,
235 RegCloseKey(hClassesKey
);
239 if (!RegQueryValueExW(hClassKey
,
240 REGSTR_VAL_NOUSECLASS
,
246 TRACE("'NoUseClass' value found!\n");
247 RegCloseKey(hClassKey
);
251 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
252 (!RegQueryValueExW(hClassKey
,
253 REGSTR_VAL_NOINSTALLCLASS
,
259 TRACE("'NoInstallClass' value found!\n");
260 RegCloseKey(hClassKey
);
264 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
265 (!RegQueryValueExW(hClassKey
,
266 REGSTR_VAL_NODISPLAYCLASS
,
272 TRACE("'NoDisplayClass' value found!\n");
273 RegCloseKey(hClassKey
);
277 RegCloseKey(hClassKey
);
279 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
280 if (dwGuidListIndex
< ClassGuidListSize
)
282 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
286 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
288 UuidFromStringW(&szKeyName
[1],
289 &ClassGuidList
[dwGuidListIndex
]);
295 if (lError
!= ERROR_SUCCESS
)
299 RegCloseKey(hClassesKey
);
301 if (RequiredSize
!= NULL
)
302 *RequiredSize
= dwGuidListIndex
;
304 if (ClassGuidListSize
< dwGuidListIndex
)
306 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
313 /***********************************************************************
314 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
316 BOOL WINAPI
SetupDiClassGuidsFromNameA(
318 LPGUID ClassGuidList
,
319 DWORD ClassGuidListSize
,
322 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
323 ClassGuidListSize
, RequiredSize
,
327 /***********************************************************************
328 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
330 BOOL WINAPI
SetupDiClassGuidsFromNameW(
332 LPGUID ClassGuidList
,
333 DWORD ClassGuidListSize
,
336 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
337 ClassGuidListSize
, RequiredSize
,
341 /***********************************************************************
342 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
344 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
346 LPGUID ClassGuidList
,
347 DWORD ClassGuidListSize
,
352 LPWSTR ClassNameW
= NULL
;
353 LPWSTR MachineNameW
= NULL
;
358 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
359 if (ClassNameW
== NULL
)
364 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
365 if (MachineNameW
== NULL
)
372 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
373 ClassGuidListSize
, RequiredSize
,
374 MachineNameW
, Reserved
);
377 MyFree(MachineNameW
);
384 /***********************************************************************
385 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
387 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
389 LPGUID ClassGuidList
,
390 DWORD ClassGuidListSize
,
395 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
396 WCHAR szClassName
[256];
402 DWORD dwGuidListIndex
= 0;
404 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
405 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
407 if (RequiredSize
!= NULL
)
410 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
411 KEY_ENUMERATE_SUB_KEYS
,
415 if (hClassesKey
== INVALID_HANDLE_VALUE
)
420 for (dwIndex
= 0; ; dwIndex
++)
422 dwLength
= MAX_GUID_STRING_LEN
+ 1;
423 lError
= RegEnumKeyExW(hClassesKey
,
431 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
432 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
434 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
436 if (RegOpenKeyExW(hClassesKey
,
442 RegCloseKey(hClassesKey
);
446 dwLength
= 256 * sizeof(WCHAR
);
447 if (!RegQueryValueExW(hClassKey
,
454 TRACE("Class name: %s\n", debugstr_w(szClassName
));
456 if (strcmpiW(szClassName
, ClassName
) == 0)
458 TRACE("Found matching class name\n");
460 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
461 if (dwGuidListIndex
< ClassGuidListSize
)
463 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
467 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
469 UuidFromStringW(&szKeyName
[1],
470 &ClassGuidList
[dwGuidListIndex
]);
477 RegCloseKey(hClassKey
);
480 if (lError
!= ERROR_SUCCESS
)
484 RegCloseKey(hClassesKey
);
486 if (RequiredSize
!= NULL
)
487 *RequiredSize
= dwGuidListIndex
;
489 if (ClassGuidListSize
< dwGuidListIndex
)
491 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
498 /***********************************************************************
499 * SetupDiClassNameFromGuidA (SETUPAPI.@)
501 BOOL WINAPI
SetupDiClassNameFromGuidA(
502 const GUID
* ClassGuid
,
507 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
508 ClassNameSize
, RequiredSize
,
512 /***********************************************************************
513 * SetupDiClassNameFromGuidW (SETUPAPI.@)
515 BOOL WINAPI
SetupDiClassNameFromGuidW(
516 const GUID
* ClassGuid
,
521 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
522 ClassNameSize
, RequiredSize
,
526 /***********************************************************************
527 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
529 BOOL WINAPI
SetupDiClassNameFromGuidExA(
530 const GUID
* ClassGuid
,
537 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
538 LPWSTR MachineNameW
= NULL
;
542 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
543 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
544 NULL
, MachineNameW
, Reserved
);
547 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
548 ClassNameSize
, NULL
, NULL
);
550 if (!ClassNameSize
&& RequiredSize
)
553 MyFree(MachineNameW
);
557 /***********************************************************************
558 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
560 BOOL WINAPI
SetupDiClassNameFromGuidExW(
561 const GUID
* ClassGuid
,
572 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
573 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
575 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
580 if (hKey
== INVALID_HANDLE_VALUE
)
585 if (RequiredSize
!= NULL
)
588 rc
= RegQueryValueExW(hKey
,
594 if (rc
!= ERROR_SUCCESS
)
601 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
604 dwLength
= ClassNameSize
* sizeof(WCHAR
);
605 rc
= RegQueryValueExW(hKey
,
611 if (rc
!= ERROR_SUCCESS
)
623 /***********************************************************************
624 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
627 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
630 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
633 /***********************************************************************
634 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
637 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
642 LPWSTR MachineNameW
= NULL
;
645 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
646 debugstr_a(MachineName
), Reserved
);
650 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
651 if (MachineNameW
== NULL
)
652 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
655 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
656 MachineNameW
, Reserved
);
659 MyFree(MachineNameW
);
665 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
669 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
670 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
671 case CR_SUCCESS
: return ERROR_SUCCESS
;
674 return ERROR_GEN_FAILURE
;
677 /* Does not happen */
680 /***********************************************************************
681 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
684 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
689 struct DeviceInfoSet
*list
;
690 LPWSTR UNCServerName
= NULL
;
694 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
696 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
697 debugstr_w(MachineName
), Reserved
);
699 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
701 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
702 list
= HeapAlloc(GetProcessHeap(), 0, size
);
705 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
708 memset(list
, 0, sizeof(struct DeviceInfoSet
));
710 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
713 ClassGuid
? ClassGuid
: &GUID_NULL
,
714 sizeof(list
->ClassGuid
));
715 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
716 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
717 list
->InstallParams
.hwndParent
= hwndParent
;
720 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
721 if (rc
!= ERROR_SUCCESS
)
726 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
729 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
733 strcpyW(UNCServerName
+ 2, MachineName
);
734 list
->szData
[0] = list
->szData
[1] = '\\';
735 strcpyW(list
->szData
+ 2, MachineName
);
736 list
->MachineName
= list
->szData
;
740 DWORD Size
= MAX_PATH
;
741 list
->HKLM
= HKEY_LOCAL_MACHINE
;
742 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
745 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
748 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
750 list
->MachineName
= NULL
;
753 UNCServerName
[0] = UNCServerName
[1] = '\\';
754 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
755 if (cr
!= CR_SUCCESS
)
757 SetLastError(GetErrorCodeFromCrCode(cr
));
761 InitializeListHead(&list
->DriverListHead
);
762 InitializeListHead(&list
->ListHead
);
764 ret
= (HDEVINFO
)list
;
767 if (ret
== INVALID_HANDLE_VALUE
)
769 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
770 RegCloseKey(list
->HKLM
);
771 HeapFree(GetProcessHeap(), 0, list
);
773 HeapFree(GetProcessHeap(), 0, UNCServerName
);
777 /***********************************************************************
778 * SetupDiEnumDeviceInfo (SETUPAPI.@)
780 BOOL WINAPI
SetupDiEnumDeviceInfo(
781 HDEVINFO DeviceInfoSet
,
783 PSP_DEVINFO_DATA DeviceInfoData
)
787 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
789 SetLastError(ERROR_INVALID_PARAMETER
);
790 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
792 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
794 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
795 SetLastError(ERROR_INVALID_HANDLE
);
796 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
797 SetLastError(ERROR_INVALID_USER_BUFFER
);
800 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
801 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
802 ItemList
= ItemList
->Flink
;
803 if (ItemList
== &list
->ListHead
)
804 SetLastError(ERROR_NO_MORE_ITEMS
);
807 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
808 memcpy(&DeviceInfoData
->ClassGuid
,
811 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
812 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
818 SetLastError(ERROR_INVALID_HANDLE
);
822 /***********************************************************************
823 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
825 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
827 PCSTR InfSectionName
,
828 PSTR InfSectionWithExt
,
829 DWORD InfSectionWithExtSize
,
833 LPWSTR InfSectionNameW
= NULL
;
834 PWSTR InfSectionWithExtW
= NULL
;
836 BOOL bResult
= FALSE
;
842 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
843 if (InfSectionNameW
== NULL
) goto end
;
845 if (InfSectionWithExt
)
847 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
848 if (InfSectionWithExtW
== NULL
) goto end
;
851 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
852 InfSectionWithExt
? InfSectionNameW
: NULL
,
853 InfSectionWithExtSize
, RequiredSize
,
854 Extension
? &ExtensionW
: NULL
);
856 if (bResult
&& InfSectionWithExt
)
858 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
859 InfSectionWithExtSize
, NULL
, NULL
) != 0;
861 if (bResult
&& Extension
)
863 if (ExtensionW
== NULL
)
866 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
870 if (InfSectionNameW
) MyFree(InfSectionNameW
);
871 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
876 /***********************************************************************
877 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
879 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
881 PCWSTR InfSectionName
,
882 PWSTR InfSectionWithExt
,
883 DWORD InfSectionWithExtSize
,
887 WCHAR szBuffer
[MAX_PATH
];
890 LONG lLineCount
= -1;
892 TRACE("%p %s %p %lu %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
893 InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
, Extension
);
895 lstrcpyW(szBuffer
, InfSectionName
);
896 dwLength
= lstrlenW(szBuffer
);
898 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
900 /* Test section name with '.NTx86' extension */
901 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
902 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
904 if (lLineCount
== -1)
906 /* Test section name with '.NT' extension */
907 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
908 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
913 /* Test section name with '.Win' extension */
914 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
915 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
918 if (lLineCount
== -1)
920 /* Test section name without extension */
921 szBuffer
[dwLength
] = 0;
922 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
925 if (lLineCount
== -1)
927 SetLastError(ERROR_INVALID_PARAMETER
);
931 dwFullLength
= lstrlenW(szBuffer
);
933 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
935 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
937 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
941 lstrcpyW(InfSectionWithExt
, szBuffer
);
942 if (Extension
!= NULL
)
944 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
948 if (RequiredSize
!= NULL
)
950 *RequiredSize
= dwFullLength
+ 1;
956 /***********************************************************************
957 * SetupDiGetClassDescriptionA (SETUPAPI.@)
959 BOOL WINAPI
SetupDiGetClassDescriptionA(
960 const GUID
* ClassGuid
,
961 PSTR ClassDescription
,
962 DWORD ClassDescriptionSize
,
965 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
966 ClassDescriptionSize
,
967 RequiredSize
, NULL
, NULL
);
970 /***********************************************************************
971 * SetupDiGetClassDescriptionW (SETUPAPI.@)
973 BOOL WINAPI
SetupDiGetClassDescriptionW(
974 const GUID
* ClassGuid
,
975 PWSTR ClassDescription
,
976 DWORD ClassDescriptionSize
,
979 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
980 ClassDescriptionSize
,
981 RequiredSize
, NULL
, NULL
);
984 /***********************************************************************
985 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
987 BOOL WINAPI
SetupDiGetClassDescriptionExA(
988 const GUID
* ClassGuid
,
989 PSTR ClassDescription
,
990 DWORD ClassDescriptionSize
,
995 PWCHAR ClassDescriptionW
;
996 LPWSTR MachineNameW
= NULL
;
1000 if (ClassDescriptionSize
> 0)
1002 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1003 if (!ClassDescriptionW
)
1005 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1011 ClassDescriptionW
= NULL
;
1015 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1018 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1024 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1025 NULL
, MachineNameW
, Reserved
);
1028 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1029 ClassDescriptionSize
, NULL
, NULL
);
1031 if (!ClassDescriptionSize
&& RequiredSize
)
1032 *RequiredSize
= len
;
1036 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1037 MyFree(MachineNameW
);
1041 /***********************************************************************
1042 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1044 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1045 const GUID
* ClassGuid
,
1046 PWSTR ClassDescription
,
1047 DWORD ClassDescriptionSize
,
1048 PDWORD RequiredSize
,
1055 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1056 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1058 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1063 if (hKey
== INVALID_HANDLE_VALUE
)
1065 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1069 if (RequiredSize
!= NULL
)
1072 if (RegQueryValueExW(hKey
,
1083 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1086 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1087 if (RegQueryValueExW(hKey
,
1091 (LPBYTE
)ClassDescription
,
1103 /***********************************************************************
1104 * SetupDiGetClassDevsA (SETUPAPI.@)
1106 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1112 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1113 flags
, NULL
, NULL
, NULL
);
1116 /***********************************************************************
1117 * SetupDiGetClassDevsW (SETUPAPI.@)
1119 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1125 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1126 flags
, NULL
, NULL
, NULL
);
1129 /***********************************************************************
1130 * SetupDiGetClassDevsExA (SETUPAPI.@)
1132 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1142 LPWSTR enumstrW
= NULL
;
1143 LPWSTR machineW
= NULL
;
1147 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1148 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1151 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1154 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1158 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1159 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1162 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1165 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1167 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1170 HeapFree(GetProcessHeap(), 0, enumstrW
);
1171 HeapFree(GetProcessHeap(), 0, machineW
);
1176 CreateDeviceInfoElement(
1177 IN
struct DeviceInfoSet
*list
,
1178 IN LPCWSTR InstancePath
,
1179 IN LPCGUID pClassGuid
,
1180 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1184 struct DeviceInfoElement
*deviceInfo
;
1186 *pDeviceInfo
= NULL
;
1188 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1189 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1192 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1195 memset(deviceInfo
, 0, size
);
1197 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1198 if (cr
!= CR_SUCCESS
)
1200 SetLastError(GetErrorCodeFromCrCode(cr
));
1204 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1205 wcscpy(deviceInfo
->Data
, InstancePath
);
1206 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1207 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1208 deviceInfo
->DeviceDescription
= NULL
;
1209 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1210 deviceInfo
->CreationFlags
= 0;
1211 InitializeListHead(&deviceInfo
->DriverListHead
);
1212 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1214 *pDeviceInfo
= deviceInfo
;
1219 CreateDeviceInterface(
1220 IN
struct DeviceInfoElement
* deviceInfo
,
1221 IN LPCWSTR SymbolicLink
,
1222 IN LPCGUID pInterfaceGuid
,
1223 OUT
struct DeviceInterface
**pDeviceInterface
)
1225 struct DeviceInterface
*deviceInterface
;
1227 *pDeviceInterface
= NULL
;
1229 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1230 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1231 if (!deviceInterface
)
1233 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1236 deviceInterface
->DeviceInfo
= deviceInfo
;
1237 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1238 deviceInterface
->Flags
= 0; /* FIXME */
1239 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1241 *pDeviceInterface
= deviceInterface
;
1245 static LONG
SETUP_CreateDevListFromEnumerator(
1246 struct DeviceInfoSet
*list
,
1247 LPCGUID pClassGuid OPTIONAL
,
1249 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1251 HKEY hDeviceIdKey
, hInstanceIdKey
;
1252 WCHAR KeyBuffer
[MAX_PATH
];
1253 WCHAR InstancePath
[MAX_PATH
];
1254 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1255 struct DeviceInfoElement
*deviceInfo
;
1257 DWORD dwLength
, dwRegType
;
1260 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1263 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1264 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1265 if (rc
== ERROR_NO_MORE_ITEMS
)
1267 if (rc
!= ERROR_SUCCESS
)
1271 /* Open device id sub key */
1272 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1273 if (rc
!= ERROR_SUCCESS
)
1275 wcscpy(InstancePath
, Enumerator
);
1276 wcscat(InstancePath
, L
"\\");
1277 wcscat(InstancePath
, KeyBuffer
);
1278 wcscat(InstancePath
, L
"\\");
1279 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1281 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1287 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1288 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1289 if (rc
== ERROR_NO_MORE_ITEMS
)
1291 if (rc
!= ERROR_SUCCESS
)
1293 RegCloseKey(hDeviceIdKey
);
1298 /* Open instance id sub key */
1299 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1300 if (rc
!= ERROR_SUCCESS
)
1302 RegCloseKey(hDeviceIdKey
);
1305 *pEndOfInstancePath
= '\0';
1306 wcscat(InstancePath
, KeyBuffer
);
1308 /* Read ClassGUID value */
1309 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1310 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1311 RegCloseKey(hInstanceIdKey
);
1312 if (rc
== ERROR_FILE_NOT_FOUND
)
1315 /* Skip this bad entry as we can't verify it */
1317 /* Set a default GUID for this device */
1318 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1320 else if (rc
!= ERROR_SUCCESS
)
1322 RegCloseKey(hDeviceIdKey
);
1325 else if (dwRegType
!= REG_SZ
)
1327 RegCloseKey(hDeviceIdKey
);
1328 return ERROR_GEN_FAILURE
;
1332 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1333 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1334 /* Bad GUID, skip the entry */
1338 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1340 /* Skip this entry as it is not the right device class */
1344 /* Add the entry to the list */
1345 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1347 RegCloseKey(hDeviceIdKey
);
1348 return GetLastError();
1350 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1351 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1353 RegCloseKey(hDeviceIdKey
);
1356 return ERROR_SUCCESS
;
1359 static LONG
SETUP_CreateDevList(
1360 struct DeviceInfoSet
*list
,
1361 PCWSTR MachineName OPTIONAL
,
1362 LPGUID
class OPTIONAL
,
1363 PCWSTR Enumerator OPTIONAL
)
1365 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1366 WCHAR KeyBuffer
[MAX_PATH
];
1371 if (class && IsEqualIID(class, &GUID_NULL
))
1375 if (MachineName
!= NULL
)
1377 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1378 if (rc
!= ERROR_SUCCESS
)
1382 HKLM
= HKEY_LOCAL_MACHINE
;
1384 rc
= RegOpenKeyExW(HKLM
,
1385 REGSTR_PATH_SYSTEMENUM
,
1387 KEY_ENUMERATE_SUB_KEYS
,
1389 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1390 if (rc
!= ERROR_SUCCESS
)
1393 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1394 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1403 KEY_ENUMERATE_SUB_KEYS
,
1405 RegCloseKey(hEnumKey
);
1406 if (rc
!= ERROR_SUCCESS
)
1408 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1409 RegCloseKey(hEnumeratorKey
);
1414 /* Enumerate enumerators */
1418 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1419 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1420 if (rc
== ERROR_NO_MORE_ITEMS
)
1422 if (rc
!= ERROR_SUCCESS
)
1424 RegCloseKey(hEnumKey
);
1430 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1431 if (rc
!= ERROR_SUCCESS
)
1433 RegCloseKey(hEnumKey
);
1437 /* Call SETUP_CreateDevListFromEnumerator */
1438 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1439 RegCloseKey(hEnumeratorKey
);
1440 if (rc
!= ERROR_SUCCESS
)
1442 RegCloseKey(hEnumKey
);
1446 RegCloseKey(hEnumKey
);
1447 return ERROR_SUCCESS
;
1452 static LONG
SETUP_CreateSerialDeviceList(
1453 struct DeviceInfoSet
*list
,
1455 LPGUID InterfaceGuid
,
1456 PCWSTR DeviceInstanceW
)
1458 static const size_t initialSize
= 100;
1460 WCHAR buf
[initialSize
];
1462 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1464 struct DeviceInfoElement
*deviceInfo
;
1467 WARN("'MachineName' is ignored on Wine!\n");
1468 if (DeviceInstanceW
)
1469 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1475 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1477 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1481 HeapFree(GetProcessHeap(), 0, devices
);
1482 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1484 return ERROR_NOT_ENOUGH_MEMORY
;
1490 HeapFree(GetProcessHeap(), 0, devices
);
1491 return GetLastError();
1495 /* 'devices' is a MULTI_SZ string */
1496 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1498 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1500 /* We have found a device */
1501 struct DeviceInterface
*interfaceInfo
;
1502 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1503 /* Step 1. Create a device info element */
1504 if (!CreateDeviceInfoElement(list
, ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1507 HeapFree(GetProcessHeap(), 0, devices
);
1508 return GetLastError();
1510 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1512 /* Step 2. Create an interface list for this element */
1513 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1516 HeapFree(GetProcessHeap(), 0, devices
);
1517 return GetLastError();
1519 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1523 HeapFree(GetProcessHeap(), 0, devices
);
1524 return ERROR_SUCCESS
;
1527 #else /* __REACTOS__ */
1529 static LONG
SETUP_CreateInterfaceList(
1530 struct DeviceInfoSet
*list
,
1532 LPGUID InterfaceGuid
,
1533 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1535 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1536 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1537 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1538 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1539 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1541 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1544 DWORD dwLength
, dwInstancePathLength
;
1547 struct DeviceInfoElement
*deviceInfo
;
1549 /* Open registry key related to this interface */
1550 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1551 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1552 return GetLastError();
1554 /* Enumerate sub keys of hInterfaceKey */
1558 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1559 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1560 if (rc
== ERROR_NO_MORE_ITEMS
)
1562 if (rc
!= ERROR_SUCCESS
)
1564 RegCloseKey(hInterfaceKey
);
1570 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1571 if (rc
!= ERROR_SUCCESS
)
1573 RegCloseKey(hInterfaceKey
);
1577 /* Read DeviceInstance */
1578 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1579 if (rc
!= ERROR_SUCCESS
)
1581 RegCloseKey(hDeviceInstanceKey
);
1582 RegCloseKey(hInterfaceKey
);
1585 if (dwRegType
!= REG_SZ
)
1587 RegCloseKey(hDeviceInstanceKey
);
1588 RegCloseKey(hInterfaceKey
);
1589 return ERROR_GEN_FAILURE
;
1591 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1594 RegCloseKey(hDeviceInstanceKey
);
1595 RegCloseKey(hInterfaceKey
);
1596 return ERROR_NOT_ENOUGH_MEMORY
;
1598 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1599 if (rc
!= ERROR_SUCCESS
)
1601 HeapFree(GetProcessHeap(), 0, InstancePath
);
1602 RegCloseKey(hDeviceInstanceKey
);
1603 RegCloseKey(hInterfaceKey
);
1606 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1607 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1609 if (DeviceInstanceW
)
1611 /* Check if device enumerator is not the right one */
1612 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1614 HeapFree(GetProcessHeap(), 0, InstancePath
);
1615 RegCloseKey(hDeviceInstanceKey
);
1620 /* Find class GUID associated to the device instance */
1623 REGSTR_PATH_SYSTEMENUM
,
1627 if (rc
!= ERROR_SUCCESS
)
1629 HeapFree(GetProcessHeap(), 0, InstancePath
);
1630 RegCloseKey(hDeviceInstanceKey
);
1631 RegCloseKey(hInterfaceKey
);
1640 RegCloseKey(hEnumKey
);
1641 if (rc
!= ERROR_SUCCESS
)
1643 HeapFree(GetProcessHeap(), 0, InstancePath
);
1644 RegCloseKey(hDeviceInstanceKey
);
1645 RegCloseKey(hInterfaceKey
);
1648 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1649 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1651 if (rc
!= ERROR_SUCCESS
)
1653 HeapFree(GetProcessHeap(), 0, InstancePath
);
1654 RegCloseKey(hDeviceInstanceKey
);
1655 RegCloseKey(hInterfaceKey
);
1658 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1659 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1660 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1662 HeapFree(GetProcessHeap(), 0, InstancePath
);
1663 RegCloseKey(hDeviceInstanceKey
);
1664 RegCloseKey(hInterfaceKey
);
1665 return ERROR_GEN_FAILURE
;
1667 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1669 /* If current device doesn't match the list GUID (if any), skip this entry */
1670 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1672 HeapFree(GetProcessHeap(), 0, InstancePath
);
1673 RegCloseKey(hDeviceInstanceKey
);
1677 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1681 LPWSTR pSymbolicLink
;
1682 struct DeviceInterface
*interfaceInfo
;
1684 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1685 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1686 if (rc
== ERROR_NO_MORE_ITEMS
)
1688 if (rc
!= ERROR_SUCCESS
)
1690 HeapFree(GetProcessHeap(), 0, InstancePath
);
1691 RegCloseKey(hDeviceInstanceKey
);
1692 RegCloseKey(hInterfaceKey
);
1696 if (KeyBuffer
[0] != '#')
1697 /* This entry doesn't represent an interesting entry */
1701 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1702 if (rc
!= ERROR_SUCCESS
)
1704 RegCloseKey(hDeviceInstanceKey
);
1705 RegCloseKey(hInterfaceKey
);
1709 /* Read SymbolicLink value */
1710 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1711 if (rc
!= ERROR_SUCCESS
)
1713 RegCloseKey(hReferenceKey
);
1714 RegCloseKey(hDeviceInstanceKey
);
1715 RegCloseKey(hInterfaceKey
);
1718 if (dwRegType
!= REG_SZ
)
1720 RegCloseKey(hReferenceKey
);
1721 RegCloseKey(hDeviceInstanceKey
);
1722 RegCloseKey(hInterfaceKey
);
1723 return ERROR_GEN_FAILURE
;
1726 /* We have found a device */
1727 /* Step 1. Create a device info element */
1728 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1730 RegCloseKey(hReferenceKey
);
1731 RegCloseKey(hDeviceInstanceKey
);
1732 RegCloseKey(hInterfaceKey
);
1733 return GetLastError();
1735 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1736 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1738 /* Step 2. Create an interface list for this element */
1739 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1742 RegCloseKey(hReferenceKey
);
1743 RegCloseKey(hDeviceInstanceKey
);
1744 RegCloseKey(hInterfaceKey
);
1745 return ERROR_NOT_ENOUGH_MEMORY
;
1747 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1748 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1749 RegCloseKey(hReferenceKey
);
1750 if (rc
!= ERROR_SUCCESS
)
1752 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1753 RegCloseKey(hDeviceInstanceKey
);
1754 RegCloseKey(hInterfaceKey
);
1757 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1759 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1760 RegCloseKey(hDeviceInstanceKey
);
1761 RegCloseKey(hInterfaceKey
);
1762 return GetLastError();
1764 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1765 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1766 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1768 RegCloseKey(hDeviceInstanceKey
);
1770 RegCloseKey(hInterfaceKey
);
1771 return ERROR_SUCCESS
;
1773 #endif /* __REACTOS__ */
1775 /***********************************************************************
1776 * SetupDiGetClassDevsExW (SETUPAPI.@)
1778 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1787 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1788 struct DeviceInfoSet
*list
;
1792 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1793 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1795 /* Create the deviceset if not set */
1798 list
= (struct DeviceInfoSet
*)deviceset
;
1799 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1801 SetLastError(ERROR_INVALID_HANDLE
);
1802 return INVALID_HANDLE_VALUE
;
1804 hDeviceInfo
= deviceset
;
1808 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1809 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1810 NULL
, machine
, NULL
);
1811 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1812 return INVALID_HANDLE_VALUE
;
1813 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1816 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1819 pClassGuid
= &list
->ClassGuid
;
1821 if (flags
& DIGCF_PRESENT
)
1822 FIXME(": flag DIGCF_PRESENT ignored\n");
1823 if (flags
& DIGCF_PROFILE
)
1824 FIXME(": flag DIGCF_PROFILE ignored\n");
1826 if (flags
& DIGCF_ALLCLASSES
)
1828 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1829 if (rc
!= ERROR_SUCCESS
)
1833 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1834 return INVALID_HANDLE_VALUE
;
1838 else if (flags
& DIGCF_DEVICEINTERFACE
)
1842 SetLastError(ERROR_INVALID_PARAMETER
);
1844 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1845 return INVALID_HANDLE_VALUE
;
1849 /* Special case: find serial ports by calling QueryDosDevice */
1850 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1851 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1852 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1853 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1856 ERR("Wine can only enumerate serial devices at the moment!\n");
1857 rc
= ERROR_INVALID_PARAMETER
;
1859 #else /* __REACTOS__ */
1860 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1861 #endif /* __REACTOS__ */
1862 if (rc
!= ERROR_SUCCESS
)
1866 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1867 return INVALID_HANDLE_VALUE
;
1873 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1874 if (rc
!= ERROR_SUCCESS
)
1878 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1879 return INVALID_HANDLE_VALUE
;
1885 /***********************************************************************
1886 * SetupDiGetClassImageIndex (SETUPAPI.@)
1889 static BOOL
GetIconIndex(
1891 OUT PINT ImageIndex
)
1893 LPWSTR Buffer
= NULL
;
1894 DWORD dwRegType
, dwLength
;
1898 /* Read icon registry key */
1899 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
1900 if (rc
!= ERROR_SUCCESS
)
1904 } else if (dwRegType
!= REG_SZ
)
1906 SetLastError(ERROR_INVALID_INDEX
);
1909 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
1912 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1915 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
1916 if (rc
!= ERROR_SUCCESS
)
1921 /* make sure the returned buffer is NULL-terminated */
1922 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
1924 /* Transform icon value to a INT */
1925 *ImageIndex
= atoiW(Buffer
);
1933 BOOL WINAPI
SetupDiGetClassImageIndex(
1934 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1935 IN CONST GUID
*ClassGuid
,
1936 OUT PINT ImageIndex
)
1938 struct ClassImageList
*list
;
1941 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
1943 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
1944 SetLastError(ERROR_INVALID_PARAMETER
);
1945 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
1946 SetLastError(ERROR_INVALID_USER_BUFFER
);
1947 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
1948 SetLastError(ERROR_INVALID_USER_BUFFER
);
1949 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
1950 SetLastError(ERROR_INVALID_USER_BUFFER
);
1951 else if (!ImageIndex
)
1952 SetLastError(ERROR_INVALID_PARAMETER
);
1955 HKEY hKey
= INVALID_HANDLE_VALUE
;
1958 /* Read Icon registry entry into Buffer */
1959 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
1960 if (hKey
== INVALID_HANDLE_VALUE
)
1962 if (!GetIconIndex(hKey
, &iconIndex
))
1967 SetLastError(ERROR_INVALID_INDEX
);
1971 *ImageIndex
= -iconIndex
;
1975 if (hKey
!= INVALID_HANDLE_VALUE
)
1979 TRACE("Returning %d\n", ret
);
1983 /***********************************************************************
1984 * SetupDiGetClassImageList(SETUPAPI.@)
1986 BOOL WINAPI
SetupDiGetClassImageList(
1987 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
1989 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
1992 /***********************************************************************
1993 * SetupDiGetClassImageListExA(SETUPAPI.@)
1995 BOOL WINAPI
SetupDiGetClassImageListExA(
1996 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1997 IN PCSTR MachineName OPTIONAL
,
2000 PWSTR MachineNameW
= NULL
;
2005 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2006 if (MachineNameW
== NULL
)
2010 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2013 MyFree(MachineNameW
);
2018 /***********************************************************************
2019 * SetupDiGetClassImageListExW(SETUPAPI.@)
2021 BOOL WINAPI
SetupDiGetClassImageListExW(
2022 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2023 IN PCWSTR MachineName OPTIONAL
,
2028 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2030 if (!ClassImageListData
)
2031 SetLastError(ERROR_INVALID_PARAMETER
);
2032 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2033 SetLastError(ERROR_INVALID_USER_BUFFER
);
2035 SetLastError(ERROR_INVALID_PARAMETER
);
2038 struct ClassImageList
*list
= NULL
;
2041 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2043 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
2044 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2047 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2050 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2053 list
->szData
[0] = list
->szData
[1] = '\\';
2054 strcpyW(list
->szData
+ 2, MachineName
);
2055 list
->MachineName
= list
->szData
;
2059 list
->MachineName
= NULL
;
2062 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2070 TRACE("Returning %d\n", ret
);
2074 /***********************************************************************
2075 * SetupDiLoadClassIcon(SETUPAPI.@)
2077 BOOL WINAPI
SetupDiLoadClassIcon(
2078 IN CONST GUID
*ClassGuid
,
2079 OUT HICON
*LargeIcon OPTIONAL
,
2080 OUT PINT MiniIconIndex OPTIONAL
)
2085 SetLastError(ERROR_INVALID_PARAMETER
);
2088 LPWSTR Buffer
= NULL
;
2091 HKEY hKey
= INVALID_HANDLE_VALUE
;
2093 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2094 if (hKey
== INVALID_HANDLE_VALUE
)
2097 if (!GetIconIndex(hKey
, &iconIndex
))
2102 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2105 DWORD dwRegType
, dwLength
;
2106 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2107 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2109 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2112 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2115 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2116 if (rc
!= ERROR_SUCCESS
)
2121 /* make sure the returned buffer is NULL-terminated */
2122 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2125 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2126 && dwRegType
== REG_SZ
)
2128 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2131 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2134 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, 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;
2145 /* Unable to find where to load the icon */
2146 SetLastError(ERROR_FILE_NOT_FOUND
);
2149 Comma
= strchrW(Buffer
, ',');
2152 SetLastError(ERROR_GEN_FAILURE
);
2160 /* Look up icon in setupapi.dll */
2161 DllName
= L
"setupapi.dll";
2162 iconIndex
= -iconIndex
;
2165 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2168 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2170 SetLastError(ERROR_INVALID_INDEX
);
2175 *MiniIconIndex
= iconIndex
;
2179 if (hKey
!= INVALID_HANDLE_VALUE
)
2184 TRACE("Returning %d\n", ret
);
2188 /***********************************************************************
2189 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2191 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2192 HDEVINFO DeviceInfoSet
,
2193 PSP_DEVINFO_DATA DeviceInfoData
,
2194 CONST GUID
* InterfaceClassGuid
,
2196 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2200 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2201 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2203 if (!DeviceInterfaceData
)
2204 SetLastError(ERROR_INVALID_PARAMETER
);
2205 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2206 SetLastError(ERROR_INVALID_USER_BUFFER
);
2207 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2209 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2211 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2213 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2215 while (ItemList
!= &list
->ListHead
&& !Found
)
2217 PLIST_ENTRY InterfaceListEntry
;
2218 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2219 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2221 /* We are not searching for this element */
2222 ItemList
= ItemList
->Flink
;
2225 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2226 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2228 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2229 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2231 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2234 if (MemberIndex
-- == 0)
2236 /* return this item */
2237 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2238 &DevItf
->InterfaceClassGuid
,
2240 DeviceInterfaceData
->Flags
= 0; /* FIXME */
2241 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2244 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2246 ItemList
= ItemList
->Flink
;
2249 SetLastError(ERROR_NO_MORE_ITEMS
);
2254 SetLastError(ERROR_INVALID_HANDLE
);
2257 SetLastError(ERROR_INVALID_HANDLE
);
2261 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2263 InterlockedIncrement(&infFile
->References
);
2266 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2268 if (InterlockedDecrement(&infFile
->References
) == 0)
2270 SetupCloseInfFile(infFile
->hInf
);
2271 HeapFree(GetProcessHeap(), 0, infFile
);
2275 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2277 DereferenceInfFile(driverInfo
->InfFileDetails
);
2278 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2279 HeapFree(GetProcessHeap(), 0, driverInfo
);
2283 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2285 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2289 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2291 PLIST_ENTRY ListEntry
;
2292 struct DriverInfoElement
*driverInfo
;
2294 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2296 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2297 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2298 if (!DestroyDriverInfoElement(driverInfo
))
2301 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2303 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2304 HeapFree(GetProcessHeap(), 0, ListEntry
);
2306 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2307 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2311 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2313 PLIST_ENTRY ListEntry
;
2314 struct DeviceInfoElement
*deviceInfo
;
2316 while (!IsListEmpty(&list
->ListHead
))
2318 ListEntry
= RemoveHeadList(&list
->ListHead
);
2319 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2320 if (!DestroyDeviceInfoElement(deviceInfo
))
2323 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2324 RegCloseKey(list
->HKLM
);
2325 CM_Disconnect_Machine(list
->hMachine
);
2326 DestroyClassInstallParams(&list
->ClassInstallParams
);
2327 HeapFree(GetProcessHeap(), 0, list
);
2331 /***********************************************************************
2332 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2334 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2338 TRACE("%p\n", devinfo
);
2339 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2341 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2343 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2344 ret
= DestroyDeviceInfoSet(list
);
2346 SetLastError(ERROR_INVALID_HANDLE
);
2349 SetLastError(ERROR_INVALID_HANDLE
);
2351 TRACE("Returning %d\n", ret
);
2355 /***********************************************************************
2356 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2358 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2359 HDEVINFO DeviceInfoSet
,
2360 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2361 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2362 DWORD DeviceInterfaceDetailDataSize
,
2363 PDWORD RequiredSize
,
2364 PSP_DEVINFO_DATA DeviceInfoData
)
2366 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2367 DWORD sizeW
= 0, sizeA
;
2370 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2371 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2372 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2374 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2375 SetLastError(ERROR_INVALID_USER_BUFFER
);
2376 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2377 SetLastError(ERROR_INVALID_PARAMETER
);
2378 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2379 SetLastError(ERROR_INVALID_PARAMETER
);
2382 if (DeviceInterfaceDetailData
!= NULL
)
2384 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2385 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2386 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2387 if (!DeviceInterfaceDetailDataW
)
2389 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2392 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2394 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2395 ret
= SetupDiGetDeviceInterfaceDetailW(
2397 DeviceInterfaceData
,
2398 DeviceInterfaceDetailDataW
,
2402 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2403 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2405 *RequiredSize
= sizeA
;
2406 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2408 if (!WideCharToMultiByte(
2410 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2411 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2418 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2421 TRACE("Returning %d\n", ret
);
2425 /***********************************************************************
2426 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2428 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2429 HDEVINFO DeviceInfoSet
,
2430 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2431 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2432 DWORD DeviceInterfaceDetailDataSize
,
2433 PDWORD RequiredSize
,
2434 PSP_DEVINFO_DATA DeviceInfoData
)
2438 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2439 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2440 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2442 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2443 SetLastError(ERROR_INVALID_PARAMETER
);
2444 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2445 SetLastError(ERROR_INVALID_HANDLE
);
2446 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2447 SetLastError(ERROR_INVALID_HANDLE
);
2448 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2449 SetLastError(ERROR_INVALID_USER_BUFFER
);
2450 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2451 SetLastError(ERROR_INVALID_USER_BUFFER
);
2452 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2453 SetLastError(ERROR_INVALID_USER_BUFFER
);
2454 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2455 SetLastError(ERROR_INVALID_PARAMETER
);
2456 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2457 SetLastError(ERROR_INVALID_PARAMETER
);
2460 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2461 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2462 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2463 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2465 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2467 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2469 *RequiredSize
= sizeRequired
;
2473 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2474 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2477 memcpy(&DeviceInfoData
->ClassGuid
,
2478 &deviceInterface
->DeviceInfo
->ClassGuid
,
2480 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2481 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2487 TRACE("Returning %d\n", ret
);
2491 /***********************************************************************
2492 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2494 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2496 PSP_DEVINFO_DATA DeviceInfoData
,
2498 PDWORD PropertyRegDataType
,
2499 PBYTE PropertyBuffer
,
2500 DWORD PropertyBufferSize
,
2501 PDWORD RequiredSize
)
2504 BOOL bIsStringProperty
;
2506 DWORD RequiredSizeA
, RequiredSizeW
;
2507 DWORD PropertyBufferSizeW
;
2508 PBYTE PropertyBufferW
;
2510 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2511 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2514 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2515 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2517 bResult
= SetupDiGetDeviceRegistryPropertyW(
2523 PropertyBufferSizeW
,
2526 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2528 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2530 if (bIsStringProperty
)
2531 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2533 RequiredSizeA
= RequiredSizeW
;
2535 *RequiredSize
= RequiredSizeA
;
2536 if (PropertyRegDataType
)
2537 *PropertyRegDataType
= RegType
;
2542 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2546 if (RequiredSizeA
<= PropertyBufferSize
)
2548 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2550 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2552 /* Last error is already set by WideCharToMultiByte */
2557 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2561 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2565 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2569 /***********************************************************************
2570 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2572 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2573 HDEVINFO DeviceInfoSet
,
2574 PSP_DEVINFO_DATA DeviceInfoData
,
2576 PDWORD PropertyRegDataType
,
2577 PBYTE PropertyBuffer
,
2578 DWORD PropertyBufferSize
,
2579 PDWORD RequiredSize
)
2581 HKEY hEnumKey
, hKey
;
2585 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2586 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2589 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2590 SetLastError(ERROR_INVALID_HANDLE
);
2591 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2592 SetLastError(ERROR_INVALID_HANDLE
);
2593 else if (!DeviceInfoData
)
2594 SetLastError(ERROR_INVALID_PARAMETER
);
2595 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2596 SetLastError(ERROR_INVALID_USER_BUFFER
);
2597 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2598 SetLastError(ERROR_INVALID_PARAMETER
);
2601 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2602 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2606 case SPDRP_CAPABILITIES
:
2608 case SPDRP_CLASSGUID
:
2609 case SPDRP_COMPATIBLEIDS
:
2610 case SPDRP_CONFIGFLAGS
:
2611 case SPDRP_DEVICEDESC
:
2613 case SPDRP_FRIENDLYNAME
:
2614 case SPDRP_HARDWAREID
:
2615 case SPDRP_LOCATION_INFORMATION
:
2616 case SPDRP_LOWERFILTERS
:
2618 case SPDRP_SECURITY
:
2620 case SPDRP_UI_NUMBER
:
2621 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2622 case SPDRP_UPPERFILTERS
:
2624 LPCWSTR RegistryPropertyName
;
2629 case SPDRP_CAPABILITIES
:
2630 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2632 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2633 case SPDRP_CLASSGUID
:
2634 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2635 case SPDRP_COMPATIBLEIDS
:
2636 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2637 case SPDRP_CONFIGFLAGS
:
2638 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2639 case SPDRP_DEVICEDESC
:
2640 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2642 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2643 case SPDRP_FRIENDLYNAME
:
2644 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2645 case SPDRP_HARDWAREID
:
2646 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2647 case SPDRP_LOCATION_INFORMATION
:
2648 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2649 case SPDRP_LOWERFILTERS
:
2650 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2652 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2653 case SPDRP_SECURITY
:
2654 RegistryPropertyName
= L
"Security"; break;
2656 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2657 case SPDRP_UI_NUMBER
:
2658 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2659 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2660 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2661 case SPDRP_UPPERFILTERS
:
2662 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2664 /* Should not happen */
2665 RegistryPropertyName
= NULL
; break;
2668 /* Open registry key name */
2671 REGSTR_PATH_SYSTEMENUM
,
2675 if (rc
!= ERROR_SUCCESS
)
2686 RegCloseKey(hEnumKey
);
2687 if (rc
!= ERROR_SUCCESS
)
2692 /* Read registry entry */
2693 BufferSize
= PropertyBufferSize
;
2694 rc
= RegQueryValueExW(
2696 RegistryPropertyName
,
2697 NULL
, /* Reserved */
2698 PropertyRegDataType
,
2702 *RequiredSize
= BufferSize
;
2705 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2708 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2710 case ERROR_MORE_DATA
:
2711 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2720 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2722 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2724 if (PropertyRegDataType
)
2725 *PropertyRegDataType
= REG_SZ
;
2727 *RequiredSize
= required
;
2728 if (PropertyBufferSize
>= required
)
2730 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2734 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2738 /*case SPDRP_BUSTYPEGUID:
2739 case SPDRP_LEGACYBUSTYPE:
2740 case SPDRP_BUSNUMBER:
2741 case SPDRP_ENUMERATOR_NAME:
2742 case SPDRP_SECURITY_SDS:
2744 case SPDRP_EXCLUSIVE:
2745 case SPDRP_CHARACTERISTICS:
2747 case SPDRP_DEVICE_POWER_DATA:*/
2748 #if (WINVER >= 0x501)
2749 /*case SPDRP_REMOVAL_POLICY:
2750 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2751 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2752 case SPDRP_INSTALL_STATE:*/
2757 ERR("Property 0x%lx not implemented\n", Property
);
2758 SetLastError(ERROR_NOT_SUPPORTED
);
2763 TRACE("Returning %d\n", ret
);
2767 /***********************************************************************
2768 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2770 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2771 IN HDEVINFO DeviceInfoSet
,
2772 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2774 IN CONST BYTE
*PropertyBuffer
,
2775 IN DWORD PropertyBufferSize
)
2777 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2778 Property
, PropertyBuffer
, PropertyBufferSize
);
2779 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2783 /***********************************************************************
2784 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2786 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2787 IN HDEVINFO DeviceInfoSet
,
2788 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2790 IN
const BYTE
*PropertyBuffer
,
2791 IN DWORD PropertyBufferSize
)
2793 struct DeviceInfoSet
*list
;
2796 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2797 Property
, PropertyBuffer
, PropertyBufferSize
);
2800 SetLastError(ERROR_INVALID_HANDLE
);
2801 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2802 SetLastError(ERROR_INVALID_HANDLE
);
2803 else if (!DeviceInfoData
)
2804 SetLastError(ERROR_INVALID_HANDLE
);
2805 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2806 SetLastError(ERROR_INVALID_USER_BUFFER
);
2811 case SPDRP_COMPATIBLEIDS
:
2812 case SPDRP_CONFIGFLAGS
:
2813 case SPDRP_FRIENDLYNAME
:
2814 case SPDRP_HARDWAREID
:
2815 case SPDRP_LOCATION_INFORMATION
:
2816 case SPDRP_LOWERFILTERS
:
2817 case SPDRP_SECURITY
:
2819 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2820 case SPDRP_UPPERFILTERS
:
2822 LPCWSTR RegistryPropertyName
;
2823 DWORD RegistryDataType
;
2829 case SPDRP_COMPATIBLEIDS
:
2830 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2831 RegistryDataType
= REG_MULTI_SZ
;
2833 case SPDRP_CONFIGFLAGS
:
2834 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2835 RegistryDataType
= REG_DWORD
;
2837 case SPDRP_FRIENDLYNAME
:
2838 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2839 RegistryDataType
= REG_SZ
;
2841 case SPDRP_HARDWAREID
:
2842 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2843 RegistryDataType
= REG_MULTI_SZ
;
2845 case SPDRP_LOCATION_INFORMATION
:
2846 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2847 RegistryDataType
= REG_SZ
;
2849 case SPDRP_LOWERFILTERS
:
2850 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2851 RegistryDataType
= REG_MULTI_SZ
;
2853 case SPDRP_SECURITY
:
2854 RegistryPropertyName
= L
"Security";
2855 RegistryDataType
= REG_BINARY
;
2858 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2859 RegistryDataType
= REG_SZ
;
2861 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2862 RegistryPropertyName
= L
"UINumberDescFormat";
2863 RegistryDataType
= REG_SZ
;
2865 case SPDRP_UPPERFILTERS
:
2866 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
2867 RegistryDataType
= REG_MULTI_SZ
;
2870 /* Should not happen */
2871 RegistryPropertyName
= NULL
;
2872 RegistryDataType
= REG_BINARY
;
2875 /* Open device registry key */
2876 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2877 if (hKey
!= INVALID_HANDLE_VALUE
)
2879 /* Write new data */
2880 rc
= RegSetValueExW(
2882 RegistryPropertyName
,
2886 PropertyBufferSize
);
2887 if (rc
== ERROR_SUCCESS
)
2896 /*case SPDRP_CHARACTERISTICS:
2898 case SPDRP_EXCLUSIVE:*/
2899 #if (WINVER >= 0x501)
2900 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2902 //case SPDRP_SECURITY_SDS:
2906 ERR("Property 0x%lx not implemented\n", Property
);
2907 SetLastError(ERROR_NOT_SUPPORTED
);
2912 TRACE("Returning %d\n", ret
);
2916 /***********************************************************************
2917 * SetupDiInstallClassA (SETUPAPI.@)
2919 BOOL WINAPI
SetupDiInstallClassA(
2925 UNICODE_STRING FileNameW
;
2928 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
2930 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2934 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
2936 RtlFreeUnicodeString(&FileNameW
);
2941 static HKEY
CreateClassKey(HINF hInf
)
2943 WCHAR FullBuffer
[MAX_PATH
];
2944 WCHAR Buffer
[MAX_PATH
];
2949 if (!SetupGetLineTextW(NULL
,
2957 return INVALID_HANDLE_VALUE
;
2960 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
2961 lstrcatW(FullBuffer
, Buffer
);
2964 if (!SetupGetLineTextW(NULL
,
2972 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2973 return INVALID_HANDLE_VALUE
;
2976 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
2980 REG_OPTION_NON_VOLATILE
,
2986 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2987 return INVALID_HANDLE_VALUE
;
2990 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
2995 RequiredSize
* sizeof(WCHAR
)))
2997 RegCloseKey(hClassKey
);
2998 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
2999 return INVALID_HANDLE_VALUE
;
3005 /***********************************************************************
3006 * SetupDiInstallClassW (SETUPAPI.@)
3008 BOOL WINAPI
SetupDiInstallClassW(
3014 WCHAR SectionName
[MAX_PATH
];
3015 DWORD SectionNameLength
= 0;
3017 BOOL bFileQueueCreated
= FALSE
;
3020 TRACE("%p %s 0x%lx %p\n", hwndParent
, debugstr_w(InfFileName
),
3023 FIXME("not fully implemented\n");
3025 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
3027 SetLastError(ERROR_INVALID_PARAMETER
);
3031 /* Open the .inf file */
3032 hInf
= SetupOpenInfFileW(InfFileName
,
3036 if (hInf
== INVALID_HANDLE_VALUE
)
3042 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
3043 hClassKey
= CreateClassKey(hInf
);
3044 if (hClassKey
== INVALID_HANDLE_VALUE
)
3046 SetupCloseInfFile(hInf
);
3052 /* Try to append a layout file */
3054 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3057 /* Retrieve the actual section name */
3058 SetupDiGetActualSectionToInstallW(hInf
,
3066 if (!(Flags
& DI_NOVCP
))
3068 FileQueue
= SetupOpenFileQueue();
3069 if (FileQueue
== INVALID_HANDLE_VALUE
)
3071 SetupCloseInfFile(hInf
);
3072 RegCloseKey(hClassKey
);
3076 bFileQueueCreated
= TRUE
;
3081 SetupInstallFromInfSectionW(NULL
,
3090 INVALID_HANDLE_VALUE
,
3093 /* FIXME: Process InterfaceInstall32 section */
3095 if (bFileQueueCreated
)
3096 SetupCloseFileQueue(FileQueue
);
3098 SetupCloseInfFile(hInf
);
3100 RegCloseKey(hClassKey
);
3105 /***********************************************************************
3106 * SetupDiOpenClassRegKey (SETUPAPI.@)
3108 HKEY WINAPI
SetupDiOpenClassRegKey(
3109 const GUID
* ClassGuid
,
3112 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3113 DIOCR_INSTALLER
, NULL
, NULL
);
3117 /***********************************************************************
3118 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3120 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3121 const GUID
* ClassGuid OPTIONAL
,
3124 PCSTR MachineName OPTIONAL
,
3127 PWSTR MachineNameW
= NULL
;
3134 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3135 if (MachineNameW
== NULL
)
3136 return INVALID_HANDLE_VALUE
;
3139 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3140 Flags
, MachineNameW
, Reserved
);
3143 MyFree(MachineNameW
);
3149 /***********************************************************************
3150 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3152 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3153 const GUID
* ClassGuid OPTIONAL
,
3156 PCWSTR MachineName OPTIONAL
,
3159 LPWSTR lpGuidString
;
3160 LPWSTR lpFullGuidString
;
3168 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3169 Flags
, debugstr_w(MachineName
), Reserved
);
3171 if (Flags
== DIOCR_INSTALLER
)
3173 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3175 else if (Flags
== DIOCR_INTERFACE
)
3177 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3181 ERR("Invalid Flags parameter!\n");
3182 SetLastError(ERROR_INVALID_FLAGS
);
3183 return INVALID_HANDLE_VALUE
;
3186 if (MachineName
!= NULL
)
3188 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3189 if (rc
!= ERROR_SUCCESS
)
3192 return INVALID_HANDLE_VALUE
;
3196 HKLM
= HKEY_LOCAL_MACHINE
;
3198 rc
= RegOpenKeyExW(HKLM
,
3201 ClassGuid
? 0 : samDesired
,
3203 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3204 if (rc
!= ERROR_SUCCESS
)
3207 return INVALID_HANDLE_VALUE
;
3210 if (ClassGuid
== NULL
)
3213 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3215 SetLastError(ERROR_GEN_FAILURE
);
3216 RegCloseKey(hClassesKey
);
3217 return INVALID_HANDLE_VALUE
;
3220 dwLength
= lstrlenW(lpGuidString
);
3221 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3222 if (!lpFullGuidString
)
3224 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3225 RpcStringFreeW(&lpGuidString
);
3226 return INVALID_HANDLE_VALUE
;
3228 lpFullGuidString
[0] = '{';
3229 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3230 lpFullGuidString
[dwLength
+ 1] = '}';
3231 lpFullGuidString
[dwLength
+ 2] = '\0';
3232 RpcStringFreeW(&lpGuidString
);
3234 rc
= RegOpenKeyExW(hClassesKey
,
3239 if (rc
!= ERROR_SUCCESS
)
3242 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3243 RegCloseKey(hClassesKey
);
3244 return INVALID_HANDLE_VALUE
;
3247 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3248 RegCloseKey(hClassesKey
);
3253 /***********************************************************************
3254 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3256 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3257 HDEVINFO DeviceInfoSet
,
3260 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3262 FIXME("%p %s %08lx %p\n",
3263 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3267 /***********************************************************************
3268 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3270 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3271 HDEVINFO DeviceInfoSet
,
3274 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3276 LPWSTR DevicePathW
= NULL
;
3279 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3281 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3282 if (DevicePathW
== NULL
)
3285 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3286 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3288 MyFree(DevicePathW
);
3293 /***********************************************************************
3294 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3296 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3297 HDEVINFO DeviceInfoSet
,
3298 PSP_DEVINFO_DATA DeviceInfoData
,
3299 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3300 DWORD ClassInstallParamsSize
)
3302 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3303 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3307 /***********************************************************************
3308 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3310 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3311 IN HDEVINFO DeviceInfoSet
,
3312 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3313 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3314 IN DWORD ClassInstallParamsSize
)
3316 struct DeviceInfoSet
*list
;
3319 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3320 ClassInstallParams
, ClassInstallParamsSize
);
3323 SetLastError(ERROR_INVALID_PARAMETER
);
3324 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3325 SetLastError(ERROR_INVALID_HANDLE
);
3326 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3327 SetLastError(ERROR_INVALID_HANDLE
);
3328 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3329 SetLastError(ERROR_INVALID_USER_BUFFER
);
3330 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3331 SetLastError(ERROR_INVALID_USER_BUFFER
);
3332 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3333 SetLastError(ERROR_INVALID_PARAMETER
);
3334 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3335 SetLastError(ERROR_INVALID_PARAMETER
);
3338 SP_DEVINSTALL_PARAMS_W InstallParams
;
3341 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3342 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3346 if (ClassInstallParams
)
3348 /* Check parameters in ClassInstallParams */
3349 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3350 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3352 SetLastError(ERROR_INVALID_USER_BUFFER
);
3355 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3357 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3358 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3361 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3364 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3368 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3371 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3375 TRACE("Returning %d\n", ret
);
3379 static BOOL
PropertyChangeHandler(
3380 IN HDEVINFO DeviceInfoSet
,
3381 IN PSP_DEVINFO_DATA DeviceInfoData
,
3382 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3383 IN DWORD ClassInstallParamsSize
)
3385 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3388 if (!DeviceInfoData
)
3389 SetLastError(ERROR_INVALID_PARAMETER
);
3390 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3391 SetLastError(ERROR_INVALID_PARAMETER
);
3392 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3393 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3394 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3395 SetLastError(ERROR_INVALID_FLAGS
);
3396 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3397 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3398 SetLastError(ERROR_INVALID_FLAGS
);
3399 else if (PropChangeParams
3400 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3401 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3402 SetLastError(ERROR_INVALID_USER_BUFFER
);
3405 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3406 if (!DeviceInfoData
)
3408 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3409 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3413 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3414 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3416 if (*CurrentPropChangeParams
)
3418 MyFree(*CurrentPropChangeParams
);
3419 *CurrentPropChangeParams
= NULL
;
3421 if (PropChangeParams
)
3423 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3424 if (!*CurrentPropChangeParams
)
3426 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3429 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3440 IN PWSTR InstallerName
,
3441 OUT HMODULE
* ModulePointer
,
3442 OUT PVOID
* FunctionPointer
)
3444 HMODULE hModule
= NULL
;
3445 LPSTR FunctionNameA
= NULL
;
3449 *ModulePointer
= NULL
;
3450 *FunctionPointer
= NULL
;
3452 Comma
= strchrW(InstallerName
, ',');
3455 rc
= ERROR_INVALID_PARAMETER
;
3461 hModule
= LoadLibraryW(InstallerName
);
3465 rc
= GetLastError();
3469 /* Skip comma spaces */
3470 while (*Comma
== ',' || isspaceW(*Comma
))
3473 /* W->A conversion for function name */
3474 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3477 rc
= GetLastError();
3481 /* Search function */
3482 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3483 if (!*FunctionPointer
)
3485 rc
= GetLastError();
3489 *ModulePointer
= hModule
;
3493 if (rc
!= ERROR_SUCCESS
&& hModule
)
3494 FreeLibrary(hModule
);
3495 MyFree(FunctionNameA
);
3500 FreeFunctionPointer(
3501 IN HMODULE ModulePointer
,
3502 IN PVOID FunctionPointer
)
3504 if (ModulePointer
== NULL
)
3505 return ERROR_SUCCESS
;
3506 if (FreeLibrary(ModulePointer
))
3507 return ERROR_SUCCESS
;
3509 return GetLastError();
3512 /***********************************************************************
3513 * SetupDiCallClassInstaller (SETUPAPI.@)
3515 BOOL WINAPI
SetupDiCallClassInstaller(
3516 IN DI_FUNCTION InstallFunction
,
3517 IN HDEVINFO DeviceInfoSet
,
3518 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3522 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3525 SetLastError(ERROR_INVALID_PARAMETER
);
3526 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3527 SetLastError(ERROR_INVALID_HANDLE
);
3528 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3529 SetLastError(ERROR_INVALID_HANDLE
);
3530 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3531 SetLastError(ERROR_INVALID_HANDLE
);
3532 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3533 SetLastError(ERROR_INVALID_USER_BUFFER
);
3536 SP_DEVINSTALL_PARAMS_W InstallParams
;
3537 #define CLASS_COINSTALLER 0x1
3538 #define DEVICE_COINSTALLER 0x2
3539 #define CLASS_INSTALLER 0x4
3540 UCHAR CanHandle
= 0;
3541 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3543 switch (InstallFunction
)
3545 case DIF_ALLOW_INSTALL
:
3546 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3548 case DIF_DESTROYPRIVATEDATA
:
3549 CanHandle
= CLASS_INSTALLER
;
3551 case DIF_INSTALLDEVICE
:
3552 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3553 DefaultHandler
= SetupDiInstallDevice
;
3555 case DIF_INSTALLDEVICEFILES
:
3556 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3557 DefaultHandler
= SetupDiInstallDriverFiles
;
3559 case DIF_INSTALLINTERFACES
:
3560 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3561 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3563 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3564 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3566 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3567 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3569 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3570 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3572 case DIF_PROPERTYCHANGE
:
3573 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3574 DefaultHandler
= SetupDiChangeState
;
3576 case DIF_REGISTER_COINSTALLERS
:
3577 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3578 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3580 case DIF_SELECTBESTCOMPATDRV
:
3581 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3582 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3585 ERR("Install function %u not supported\n", InstallFunction
);
3586 SetLastError(ERROR_NOT_SUPPORTED
);
3589 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3590 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3591 /* Don't process this call, as a parameter is invalid */
3596 LIST_ENTRY ClassCoInstallersListHead
;
3597 LIST_ENTRY DeviceCoInstallersListHead
;
3598 HMODULE ClassInstallerLibrary
= NULL
;
3599 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3600 COINSTALLER_CONTEXT_DATA Context
;
3601 PLIST_ENTRY ListEntry
;
3603 DWORD dwRegType
, dwLength
;
3604 DWORD rc
= NO_ERROR
;
3606 InitializeListHead(&ClassCoInstallersListHead
);
3607 InitializeListHead(&DeviceCoInstallersListHead
);
3609 if (CanHandle
& DEVICE_COINSTALLER
)
3611 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3612 if (hKey
!= INVALID_HANDLE_VALUE
)
3614 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3615 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3617 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3618 if (KeyBuffer
!= NULL
)
3620 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3621 if (rc
== ERROR_SUCCESS
)
3624 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3626 /* Add coinstaller to DeviceCoInstallersListHead list */
3627 struct CoInstallerElement
*coinstaller
;
3628 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3629 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3632 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3633 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3634 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3636 HeapFree(GetProcessHeap(), 0, coinstaller
);
3639 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3645 if (CanHandle
& CLASS_COINSTALLER
)
3649 REGSTR_PATH_CODEVICEINSTALLERS
,
3653 if (rc
== ERROR_SUCCESS
)
3655 LPWSTR lpGuidString
;
3656 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3658 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3659 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3661 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3662 if (KeyBuffer
!= NULL
)
3664 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3665 if (rc
== ERROR_SUCCESS
)
3668 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3670 /* Add coinstaller to ClassCoInstallersListHead list */
3671 struct CoInstallerElement
*coinstaller
;
3672 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3673 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3676 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3677 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3678 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3680 HeapFree(GetProcessHeap(), 0, coinstaller
);
3683 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3686 RpcStringFreeW(&lpGuidString
);
3691 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3693 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3694 if (hKey
!= INVALID_HANDLE_VALUE
)
3696 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3697 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3699 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3700 if (KeyBuffer
!= NULL
)
3702 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3703 if (rc
== ERROR_SUCCESS
)
3705 /* Get ClassInstaller function pointer */
3706 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3707 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3709 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3710 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3713 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3720 /* Call Class co-installers */
3721 Context
.PostProcessing
= FALSE
;
3723 ListEntry
= ClassCoInstallersListHead
.Flink
;
3724 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3726 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3727 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3728 coinstaller
->PrivateData
= Context
.PrivateData
;
3729 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3731 coinstaller
->DoPostProcessing
= TRUE
;
3734 ListEntry
= ListEntry
->Flink
;
3737 /* Call Device co-installers */
3738 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3739 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3741 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3742 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3743 coinstaller
->PrivateData
= Context
.PrivateData
;
3744 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3746 coinstaller
->DoPostProcessing
= TRUE
;
3749 ListEntry
= ListEntry
->Flink
;
3752 /* Call Class installer */
3755 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3756 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3759 rc
= ERROR_DI_DO_DEFAULT
;
3761 /* Call default handler */
3762 if (rc
== ERROR_DI_DO_DEFAULT
)
3764 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3766 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3769 rc
= GetLastError();
3775 /* Call Class co-installers that required postprocessing */
3776 Context
.PostProcessing
= TRUE
;
3777 ListEntry
= ClassCoInstallersListHead
.Flink
;
3778 while (ListEntry
!= &ClassCoInstallersListHead
)
3780 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3781 if (coinstaller
->DoPostProcessing
)
3783 Context
.InstallResult
= rc
;
3784 Context
.PrivateData
= coinstaller
->PrivateData
;
3785 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3787 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3788 ListEntry
= ListEntry
->Flink
;
3791 /* Call Device co-installers that required postprocessing */
3792 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3793 while (ListEntry
!= &DeviceCoInstallersListHead
)
3795 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3796 if (coinstaller
->DoPostProcessing
)
3798 Context
.InstallResult
= rc
;
3799 Context
.PrivateData
= coinstaller
->PrivateData
;
3800 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3802 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3803 ListEntry
= ListEntry
->Flink
;
3806 /* Free allocated memory */
3807 while (!IsListEmpty(&ClassCoInstallersListHead
))
3809 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3810 HeapFree(GetProcessHeap(), 0, ListEntry
);
3812 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3814 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3815 HeapFree(GetProcessHeap(), 0, ListEntry
);
3818 ret
= (rc
== NO_ERROR
);
3822 TRACE("Returning %d\n", ret
);
3826 /***********************************************************************
3827 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
3829 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
3830 IN HDEVINFO DeviceInfoSet
,
3831 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
3833 struct DeviceInfoSet
*list
;
3836 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
3839 SetLastError(ERROR_INVALID_HANDLE
);
3840 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3841 SetLastError(ERROR_INVALID_HANDLE
);
3842 else if (!DeviceInfoListDetailData
)
3843 SetLastError(ERROR_INVALID_PARAMETER
);
3844 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
3845 SetLastError(ERROR_INVALID_USER_BUFFER
);
3849 &DeviceInfoListDetailData
->ClassGuid
,
3852 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
3853 if (list
->MachineName
)
3854 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
3856 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
3861 TRACE("Returning %d\n", ret
);
3865 /***********************************************************************
3866 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
3868 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
3869 IN HDEVINFO DeviceInfoSet
,
3870 IN PSP_DEVINFO_DATA DeviceInfoData
,
3871 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
3873 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
3876 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3878 if (DeviceInstallParams
== NULL
)
3879 SetLastError(ERROR_INVALID_PARAMETER
);
3880 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
3881 SetLastError(ERROR_INVALID_USER_BUFFER
);
3884 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3885 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
3889 /* Do W->A conversion */
3891 DeviceInstallParams
,
3892 &deviceInstallParamsW
,
3893 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
3894 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
3895 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
3897 DeviceInstallParams
->DriverPath
[0] = '\0';
3903 TRACE("Returning %d\n", ret
);
3907 /***********************************************************************
3908 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
3910 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
3911 IN HDEVINFO DeviceInfoSet
,
3912 IN PSP_DEVINFO_DATA DeviceInfoData
,
3913 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3915 struct DeviceInfoSet
*list
;
3918 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3921 SetLastError(ERROR_INVALID_HANDLE
);
3922 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3923 SetLastError(ERROR_INVALID_HANDLE
);
3924 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3925 SetLastError(ERROR_INVALID_USER_BUFFER
);
3926 else if (!DeviceInstallParams
)
3927 SetLastError(ERROR_INVALID_PARAMETER
);
3928 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3929 SetLastError(ERROR_INVALID_USER_BUFFER
);
3932 PSP_DEVINSTALL_PARAMS_W Source
;
3935 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3937 Source
= &list
->InstallParams
;
3938 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
3942 TRACE("Returning %d\n", ret
);
3946 /***********************************************************************
3947 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
3949 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
3950 IN HDEVINFO DeviceInfoSet
,
3951 IN PSP_DEVINFO_DATA DeviceInfoData
,
3952 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
3954 struct DeviceInfoSet
*list
;
3957 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
3960 SetLastError(ERROR_INVALID_HANDLE
);
3961 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3962 SetLastError(ERROR_INVALID_HANDLE
);
3963 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3964 SetLastError(ERROR_INVALID_USER_BUFFER
);
3965 else if (!DeviceInstallParams
)
3966 SetLastError(ERROR_INVALID_PARAMETER
);
3967 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
3968 SetLastError(ERROR_INVALID_USER_BUFFER
);
3971 PSP_DEVINSTALL_PARAMS_W Destination
;
3973 /* FIXME: Validate parameters */
3976 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
3978 Destination
= &list
->InstallParams
;
3979 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
3983 TRACE("Returning %d\n", ret
);
3987 /***********************************************************************
3988 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
3990 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
3991 IN HDEVINFO DeviceInfoSet
,
3992 IN PSP_DEVINFO_DATA DeviceInfoData
,
3993 OUT PSTR DeviceInstanceId OPTIONAL
,
3994 IN DWORD DeviceInstanceIdSize
,
3995 OUT PDWORD RequiredSize OPTIONAL
)
3997 PWSTR DeviceInstanceIdW
= NULL
;
4000 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4001 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4003 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4004 SetLastError(ERROR_INVALID_PARAMETER
);
4007 if (DeviceInstanceIdSize
!= 0)
4009 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4010 if (DeviceInstanceIdW
== NULL
)
4014 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4015 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4018 if (ret
&& DeviceInstanceIdW
!= NULL
)
4020 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4021 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4023 DeviceInstanceId
[0] = '\0';
4029 TRACE("Returning %d\n", ret
);
4033 /***********************************************************************
4034 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4036 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
4037 IN HDEVINFO DeviceInfoSet
,
4038 IN PSP_DEVINFO_DATA DeviceInfoData
,
4039 OUT PWSTR DeviceInstanceId OPTIONAL
,
4040 IN DWORD DeviceInstanceIdSize
,
4041 OUT PDWORD RequiredSize OPTIONAL
)
4045 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4046 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4049 SetLastError(ERROR_INVALID_HANDLE
);
4050 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4051 SetLastError(ERROR_INVALID_HANDLE
);
4052 else if (!DeviceInfoData
)
4053 SetLastError(ERROR_INVALID_PARAMETER
);
4054 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4055 SetLastError(ERROR_INVALID_USER_BUFFER
);
4056 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4057 SetLastError(ERROR_INVALID_PARAMETER
);
4058 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4059 SetLastError(ERROR_INVALID_PARAMETER
);
4062 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4065 required
= (wcslen(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4067 *RequiredSize
= required
;
4069 if (required
<= DeviceInstanceIdSize
)
4071 wcscpy(DeviceInstanceId
, DevInfo
->DeviceName
);
4075 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4078 TRACE("Returning %d\n", ret
);
4082 /***********************************************************************
4083 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4085 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
4086 IN HDEVINFO DeviceInfoSet
,
4087 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4088 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4089 IN DWORD PropertySheetHeaderPageListSize
,
4090 OUT PDWORD RequiredSize OPTIONAL
,
4091 IN DWORD PropertySheetType
)
4093 PROPSHEETHEADERW psh
;
4096 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4097 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4098 RequiredSize
, PropertySheetType
);
4100 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4101 psh
.phpage
= PropertySheetHeader
->phpage
;
4102 psh
.nPages
= PropertySheetHeader
->nPages
;
4104 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4105 PropertySheetHeaderPageListSize
, RequiredSize
,
4109 PropertySheetHeader
->nPages
= psh
.nPages
;
4112 TRACE("Returning %d\n", ret
);
4116 struct ClassDevPropertySheetsData
4118 HPROPSHEETPAGE
*PropertySheetPages
;
4119 DWORD MaximumNumberOfPages
;
4120 DWORD NumberOfPages
;
4123 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
4124 IN HPROPSHEETPAGE hPropSheetPage
,
4125 IN OUT LPARAM lParam
)
4127 struct ClassDevPropertySheetsData
*PropPageData
;
4129 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4131 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4133 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4134 PropPageData
->PropertySheetPages
++;
4137 PropPageData
->NumberOfPages
++;
4141 /***********************************************************************
4142 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4144 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
4145 IN HDEVINFO DeviceInfoSet
,
4146 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4147 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4148 IN DWORD PropertySheetHeaderPageListSize
,
4149 OUT PDWORD RequiredSize OPTIONAL
,
4150 IN DWORD PropertySheetType
)
4152 struct DeviceInfoSet
*list
;
4155 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4156 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4157 RequiredSize
, PropertySheetType
);
4160 SetLastError(ERROR_INVALID_HANDLE
);
4161 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4162 SetLastError(ERROR_INVALID_HANDLE
);
4163 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4164 SetLastError(ERROR_INVALID_HANDLE
);
4165 else if (!PropertySheetHeader
)
4166 SetLastError(ERROR_INVALID_PARAMETER
);
4167 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4168 SetLastError(ERROR_INVALID_FLAGS
);
4169 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4170 SetLastError(ERROR_INVALID_USER_BUFFER
);
4171 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4172 SetLastError(ERROR_INVALID_PARAMETER
);
4173 else if (!PropertySheetHeader
)
4174 SetLastError(ERROR_INVALID_PARAMETER
);
4175 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4176 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4177 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4178 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4179 SetLastError(ERROR_INVALID_PARAMETER
);
4182 HKEY hKey
= INVALID_HANDLE_VALUE
;
4183 SP_PROPSHEETPAGE_REQUEST Request
;
4184 LPWSTR PropPageProvider
= NULL
;
4185 HMODULE hModule
= NULL
;
4186 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4187 struct ClassDevPropertySheetsData PropPageData
;
4188 DWORD dwLength
, dwRegType
;
4192 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4195 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4196 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4198 if (hKey
== INVALID_HANDLE_VALUE
)
4201 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4202 if (rc
== ERROR_FILE_NOT_FOUND
)
4204 /* No registry key. As it is optional, don't say it's a bad error */
4210 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4216 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4217 if (!PropPageProvider
)
4219 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4222 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4223 if (rc
!= ERROR_SUCCESS
)
4228 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4230 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4231 if (rc
!= ERROR_SUCCESS
)
4233 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4237 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4238 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4239 Request
.DeviceInfoSet
= DeviceInfoSet
;
4240 Request
.DeviceInfoData
= DeviceInfoData
;
4241 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4242 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4243 PropPageData
.NumberOfPages
= 0;
4244 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4249 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4250 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4252 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4257 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4258 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4262 if (hKey
!= INVALID_HANDLE_VALUE
)
4264 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4265 FreeFunctionPointer(hModule
, pPropPageProvider
);
4268 TRACE("Returning %d\n", ret
);
4272 /***********************************************************************
4273 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4275 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4276 IN HDEVINFO DeviceInfoSet
,
4277 IN PSP_DEVINFO_DATA DeviceInfoData
,
4281 IN HINF InfHandle OPTIONAL
,
4282 IN PCSTR InfSectionName OPTIONAL
)
4284 PCWSTR InfSectionNameW
= NULL
;
4285 HKEY ret
= INVALID_HANDLE_VALUE
;
4289 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4290 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4293 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4301 if (InfSectionNameW
!= NULL
)
4302 MyFree((PVOID
)InfSectionNameW
);
4308 OpenHardwareProfileKey(
4311 IN DWORD samDesired
)
4313 HKEY hHWProfilesKey
= INVALID_HANDLE_VALUE
;
4314 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4315 HKEY ret
= INVALID_HANDLE_VALUE
;
4318 rc
= RegOpenKeyExW(HKLM
,
4319 REGSTR_PATH_HWPROFILES
,
4323 if (rc
!= ERROR_SUCCESS
)
4340 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4349 if (rc
!= ERROR_SUCCESS
)
4354 ret
= hHWProfileKey
;
4357 if (hHWProfilesKey
!= INVALID_HANDLE_VALUE
)
4358 RegCloseKey(hHWProfilesKey
);
4359 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
&& hHWProfileKey
!= ret
)
4360 RegCloseKey(hHWProfileKey
);
4364 /***********************************************************************
4365 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4367 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4368 IN HDEVINFO DeviceInfoSet
,
4369 IN PSP_DEVINFO_DATA DeviceInfoData
,
4373 IN HINF InfHandle OPTIONAL
,
4374 IN PCWSTR InfSectionName OPTIONAL
)
4376 struct DeviceInfoSet
*list
;
4377 HKEY ret
= INVALID_HANDLE_VALUE
;
4379 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4380 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4383 SetLastError(ERROR_INVALID_HANDLE
);
4384 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4385 SetLastError(ERROR_INVALID_HANDLE
);
4386 else if (!DeviceInfoData
)
4387 SetLastError(ERROR_INVALID_PARAMETER
);
4388 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4389 SetLastError(ERROR_INVALID_USER_BUFFER
);
4390 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4391 SetLastError(ERROR_INVALID_PARAMETER
);
4392 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4393 SetLastError(ERROR_INVALID_PARAMETER
);
4394 else if (InfHandle
&& !InfSectionName
)
4395 SetLastError(ERROR_INVALID_PARAMETER
);
4396 else if (!InfHandle
&& InfSectionName
)
4397 SetLastError(ERROR_INVALID_PARAMETER
);
4400 LPWSTR lpGuidString
= NULL
;
4401 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4402 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4403 DWORD Index
; /* Index used in the DriverKey name */
4405 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4406 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4407 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4408 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4409 HKEY hKey
= INVALID_HANDLE_VALUE
;
4412 if (Scope
== DICS_FLAG_GLOBAL
)
4413 RootKey
= list
->HKLM
;
4414 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4416 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
4417 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4419 RootKey
= hHWProfileKey
;
4422 if (KeyType
== DIREG_DEV
)
4424 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4426 rc
= RegCreateKeyExW(
4428 REGSTR_PATH_SYSTEMENUM
,
4431 REG_OPTION_NON_VOLATILE
,
4436 if (rc
!= ERROR_SUCCESS
)
4441 rc
= RegCreateKeyExW(
4443 deviceInfo
->DeviceName
,
4446 REG_OPTION_NON_VOLATILE
,
4447 #if _WIN32_WINNT >= 0x502
4448 KEY_READ
| KEY_WRITE
,
4455 if (rc
!= ERROR_SUCCESS
)
4461 else /* KeyType == DIREG_DRV */
4463 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4465 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4466 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4469 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4472 wcscpy(DriverKey
, L
"{");
4473 wcscat(DriverKey
, lpGuidString
);
4474 wcscat(DriverKey
, L
"}\\");
4475 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4476 rc
= RegOpenKeyExW(RootKey
,
4477 REGSTR_PATH_CLASS_NT
,
4481 if (rc
!= ERROR_SUCCESS
)
4487 /* Try all values for Index between 0 and 9999 */
4489 while (Index
<= 9999)
4492 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4493 rc
= RegCreateKeyEx(hClassKey
,
4497 REG_OPTION_NON_VOLATILE
,
4498 #if _WIN32_WINNT >= 0x502
4499 KEY_READ
| KEY_WRITE
,
4506 if (rc
!= ERROR_SUCCESS
)
4511 if (Disposition
== REG_CREATED_NEW_KEY
)
4514 hKey
= INVALID_HANDLE_VALUE
;
4519 /* Unable to create more than 9999 devices within the same class */
4520 SetLastError(ERROR_GEN_FAILURE
);
4524 /* Open device key, to write Driver value */
4525 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4526 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4528 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4529 if (rc
!= ERROR_SUCCESS
)
4536 /* Do installation of the specified section */
4539 FIXME("Need to install section %s in file %p\n",
4540 debugstr_w(InfSectionName
), InfHandle
);
4546 RpcStringFreeW(&lpGuidString
);
4547 HeapFree(GetProcessHeap(), 0, DriverKey
);
4548 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4549 RegCloseKey(hHWProfileKey
);
4550 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4551 RegCloseKey(hEnumKey
);
4552 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4553 RegCloseKey(hClassKey
);
4554 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4555 RegCloseKey(hDeviceKey
);
4556 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4560 TRACE("Returning 0x%p\n", ret
);
4564 /***********************************************************************
4565 * SetupDiOpenDevRegKey (SETUPAPI.@)
4567 HKEY WINAPI
SetupDiOpenDevRegKey(
4568 HDEVINFO DeviceInfoSet
,
4569 PSP_DEVINFO_DATA DeviceInfoData
,
4575 struct DeviceInfoSet
*list
;
4576 HKEY ret
= INVALID_HANDLE_VALUE
;
4578 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4579 Scope
, HwProfile
, KeyType
, samDesired
);
4582 SetLastError(ERROR_INVALID_HANDLE
);
4583 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4584 SetLastError(ERROR_INVALID_HANDLE
);
4585 else if (!DeviceInfoData
)
4586 SetLastError(ERROR_INVALID_PARAMETER
);
4587 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4588 SetLastError(ERROR_INVALID_USER_BUFFER
);
4589 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4590 SetLastError(ERROR_INVALID_PARAMETER
);
4591 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4592 SetLastError(ERROR_INVALID_PARAMETER
);
4595 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4596 LPWSTR DriverKey
= NULL
;
4600 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4601 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4602 HKEY hKey
= INVALID_HANDLE_VALUE
;
4605 if (Scope
== DICS_FLAG_GLOBAL
)
4606 RootKey
= list
->HKLM
;
4607 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4609 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
4610 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4612 RootKey
= hHWProfileKey
;
4617 REGSTR_PATH_SYSTEMENUM
,
4621 if (rc
!= ERROR_SUCCESS
)
4628 deviceInfo
->DeviceName
,
4630 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4632 RegCloseKey(hEnumKey
);
4633 hEnumKey
= INVALID_HANDLE_VALUE
;
4634 if (rc
!= ERROR_SUCCESS
)
4639 if (KeyType
== DIREG_DEV
)
4641 /* We're done. Just return the hKey handle */
4646 /* Read the 'Driver' key */
4647 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
4648 if (rc
!= ERROR_SUCCESS
)
4653 else if (dwRegType
!= REG_SZ
)
4655 SetLastError(ERROR_GEN_FAILURE
);
4658 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4661 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4664 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4665 if (rc
!= ERROR_SUCCESS
)
4671 hKey
= INVALID_HANDLE_VALUE
;
4672 /* Need to open the driver key */
4675 REGSTR_PATH_CLASS_NT
,
4679 if (rc
!= ERROR_SUCCESS
)
4690 if (rc
!= ERROR_SUCCESS
)
4698 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4699 RegCloseKey(hHWProfileKey
);
4700 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4701 RegCloseKey(hEnumKey
);
4702 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4706 TRACE("Returning 0x%p\n", ret
);
4710 /***********************************************************************
4711 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
4713 BOOL WINAPI
SetupDiCreateDeviceInfoA(
4714 HDEVINFO DeviceInfoSet
,
4716 CONST GUID
*ClassGuid
,
4717 PCSTR DeviceDescription
,
4719 DWORD CreationFlags
,
4720 PSP_DEVINFO_DATA DeviceInfoData
)
4722 LPWSTR DeviceNameW
= NULL
;
4723 LPWSTR DeviceDescriptionW
= NULL
;
4730 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
4731 if (DeviceNameW
== NULL
) return FALSE
;
4733 if (DeviceDescription
)
4735 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
4736 if (DeviceDescriptionW
== NULL
)
4738 if (DeviceNameW
) MyFree(DeviceNameW
);
4743 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
4744 ClassGuid
, DeviceDescriptionW
,
4745 hwndParent
, CreationFlags
,
4748 if (DeviceNameW
) MyFree(DeviceNameW
);
4749 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
4754 /***********************************************************************
4755 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
4757 BOOL WINAPI
SetupDiCreateDeviceInfoW(
4758 HDEVINFO DeviceInfoSet
,
4760 CONST GUID
*ClassGuid
,
4761 PCWSTR DeviceDescription
,
4763 DWORD CreationFlags
,
4764 PSP_DEVINFO_DATA DeviceInfoData
)
4766 struct DeviceInfoSet
*list
;
4769 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
4770 debugstr_guid(ClassGuid
), DeviceDescription
,
4771 hwndParent
, CreationFlags
, DeviceInfoData
);
4774 SetLastError(ERROR_INVALID_HANDLE
);
4775 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4776 SetLastError(ERROR_INVALID_HANDLE
);
4777 else if (!ClassGuid
)
4778 SetLastError(ERROR_INVALID_PARAMETER
);
4779 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
4780 SetLastError(ERROR_CLASS_MISMATCH
);
4781 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
4783 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
4784 SetLastError(ERROR_INVALID_FLAGS
);
4788 SP_DEVINFO_DATA DevInfo
;
4790 if (CreationFlags
& DICD_GENERATE_ID
)
4792 /* Generate a new unique ID for this device */
4793 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
4794 FIXME("not implemented\n");
4798 /* Device name is fully qualified. Try to open it */
4801 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
4802 rc
= SetupDiOpenDeviceInfoW(
4805 NULL
, /* hwndParent */
4806 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
4811 /* SetupDiOpenDeviceInfoW has already added
4812 * the device info to the device info set
4814 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
4816 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
4818 struct DeviceInfoElement
*deviceInfo
;
4820 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
4822 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4824 if (!DeviceInfoData
)
4828 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
4830 SetLastError(ERROR_INVALID_USER_BUFFER
);
4834 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
4835 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
4836 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4845 TRACE("Returning %d\n", ret
);
4849 /***********************************************************************
4850 * Helper functions for SetupDiBuildDriverInfoList
4854 IN PLIST_ENTRY DriverListHead
,
4855 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
4856 IN LPGUID ClassGuid
,
4857 IN INFCONTEXT ContextDevice
,
4858 IN
struct InfFileDetails
*InfFileDetails
,
4860 IN LPCWSTR ProviderName
,
4861 IN LPCWSTR ManufacturerName
,
4862 IN LPCWSTR MatchingId
,
4863 FILETIME DriverDate
,
4864 DWORDLONG DriverVersion
,
4867 struct DriverInfoElement
*driverInfo
= NULL
;
4868 HANDLE hFile
= INVALID_HANDLE_VALUE
;
4869 DWORD RequiredSize
= 128; /* Initial buffer size */
4870 BOOL Result
= FALSE
;
4871 PLIST_ENTRY PreviousEntry
;
4872 LPWSTR InfInstallSection
= NULL
;
4875 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
4878 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4881 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
4883 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
4884 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
4886 /* Copy InfFileName field */
4887 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
4888 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
4890 /* Fill InfDate field */
4891 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
4892 GENERIC_READ, FILE_SHARE_READ,
4893 NULL, OPEN_EXISTING, 0, NULL);
4894 if (hFile == INVALID_HANDLE_VALUE)
4896 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
4900 /* Fill SectionName field */
4901 Result
= SetupGetStringFieldW(
4904 driverInfo
->Details
.SectionName
, LINE_LEN
,
4909 /* Fill DrvDescription field */
4910 Result
= SetupGetStringFieldW(
4912 0, /* Field index */
4913 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
4916 /* Copy MatchingId information */
4917 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4918 if (!driverInfo
->MatchingId
)
4920 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4923 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
4925 /* Get inf install section */
4927 RequiredSize
= 128; /* Initial buffer size */
4928 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4929 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
4931 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
4932 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
4933 if (!InfInstallSection
)
4935 Result
= SetupGetStringFieldW(
4937 1, /* Field index */
4938 InfInstallSection
, RequiredSize
,
4944 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
4945 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
4947 driverInfo
->DriverRank
= Rank
;
4948 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
4949 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
4950 driverInfo
->Info
.DriverType
= DriverType
;
4951 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
4952 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
4953 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
4954 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
4955 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
4958 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
4959 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
4962 driverInfo
->Info
.ProviderName
[0] = '\0';
4963 driverInfo
->Info
.DriverDate
= DriverDate
;
4964 driverInfo
->Info
.DriverVersion
= DriverVersion
;
4965 ReferenceInfFile(InfFileDetails
);
4966 driverInfo
->InfFileDetails
= InfFileDetails
;
4968 /* Insert current driver in driver list, according to its rank */
4969 PreviousEntry
= DriverListHead
->Flink
;
4970 while (PreviousEntry
!= DriverListHead
)
4972 struct DriverInfoElement
*CurrentDriver
;
4973 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
4974 if (CurrentDriver
->DriverRank
> Rank
||
4975 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
4977 /* Insert before the current item */
4978 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
4981 PreviousEntry
= PreviousEntry
->Flink
;
4983 if (PreviousEntry
== DriverListHead
)
4985 /* Insert at the end of the list */
4986 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
4995 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
4996 HeapFree(GetProcessHeap(), 0, driverInfo
);
4998 if (hFile
!= INVALID_HANDLE_VALUE
)
5000 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5006 GetVersionInformationFromInfFile(
5008 OUT LPGUID ClassGuid
,
5009 OUT LPWSTR
* pProviderName
,
5010 OUT FILETIME
* DriverDate
,
5011 OUT DWORDLONG
* DriverVersion
)
5014 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5015 LPWSTR DriverVer
= NULL
;
5016 LPWSTR ProviderName
= NULL
;
5017 LPWSTR pComma
; /* Points into DriverVer */
5018 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5019 SYSTEMTIME SystemTime
;
5021 BOOL ret
= FALSE
; /* Final result */
5023 /* Get class Guid */
5024 if (!SetupGetLineTextW(
5027 L
"Version", L
"ClassGUID",
5028 guidW
, sizeof(guidW
),
5029 NULL
/* Required size */))
5033 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5034 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5036 SetLastError(ERROR_GEN_FAILURE
);
5040 /* Get provider name */
5041 Result
= SetupGetLineTextW(
5043 hInf
, L
"Version", L
"Provider",
5048 /* We know know the needed buffer size */
5049 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5052 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5055 Result
= SetupGetLineTextW(
5057 hInf
, L
"Version", L
"Provider",
5058 ProviderName
, RequiredSize
,
5063 *pProviderName
= ProviderName
;
5065 /* Read the "DriverVer" value */
5066 Result
= SetupGetLineTextW(
5068 hInf
, L
"Version", L
"DriverVer",
5073 /* We know know the needed buffer size */
5074 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5077 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5080 Result
= SetupGetLineTextW(
5082 hInf
, L
"Version", L
"DriverVer",
5083 DriverVer
, RequiredSize
,
5089 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5090 pComma
= wcschr(DriverVer
, ',');
5093 *pComma
= UNICODE_NULL
;
5094 pVersion
= pComma
+ 1;
5096 /* Get driver date version. Invalid date = 00/00/00 */
5097 memset(DriverDate
, 0, sizeof(FILETIME
));
5098 if (wcslen(DriverVer
) == 10
5099 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5100 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5102 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5103 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5104 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5105 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5106 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5107 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5109 /* Get driver version. Invalid version = 0.0.0.0 */
5113 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5114 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5115 LARGE_INTEGER fullVersion
;
5117 pMinor
= strchrW(pVersion
, '.');
5121 pRevision
= strchrW(++pMinor
, '.');
5122 Minor
= atoiW(pMinor
);
5127 pBuild
= strchrW(++pRevision
, '.');
5128 Revision
= atoiW(pRevision
);
5134 Build
= atoiW(pBuild
);
5136 Major
= atoiW(pVersion
);
5137 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5138 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5139 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5146 HeapFree(GetProcessHeap(), 0, ProviderName
);
5147 HeapFree(GetProcessHeap(), 0, DriverVer
);
5152 /***********************************************************************
5153 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5156 SetupDiBuildDriverInfoList(
5157 IN HDEVINFO DeviceInfoSet
,
5158 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5159 IN DWORD DriverType
)
5161 struct DeviceInfoSet
*list
;
5162 SP_DEVINSTALL_PARAMS_W InstallParams
;
5163 PVOID Buffer
= NULL
;
5164 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5165 LPWSTR ProviderName
= NULL
;
5166 LPWSTR ManufacturerName
= NULL
;
5167 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5168 LPWSTR HardwareIDs
= NULL
;
5169 LPWSTR CompatibleIDs
= NULL
;
5170 LPWSTR FullInfFileName
= NULL
;
5171 FILETIME DriverDate
;
5172 DWORDLONG DriverVersion
= 0;
5176 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5179 SetLastError(ERROR_INVALID_HANDLE
);
5180 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5181 SetLastError(ERROR_INVALID_HANDLE
);
5182 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5183 SetLastError(ERROR_INVALID_HANDLE
);
5184 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5185 SetLastError(ERROR_INVALID_PARAMETER
);
5186 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
5187 SetLastError(ERROR_INVALID_PARAMETER
);
5188 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5189 SetLastError(ERROR_INVALID_PARAMETER
);
5190 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5191 SetLastError(ERROR_INVALID_USER_BUFFER
);
5196 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
5197 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5201 if (DriverType
== SPDIT_COMPATDRIVER
)
5203 /* Get hardware IDs list */
5205 RequiredSize
= 512; /* Initial buffer size */
5206 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5207 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5209 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5210 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5213 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5216 Result
= SetupDiGetDeviceRegistryPropertyW(
5228 /* Get compatible IDs list */
5230 RequiredSize
= 512; /* Initial buffer size */
5231 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5232 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5234 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5235 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5238 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5241 Result
= SetupDiGetDeviceRegistryPropertyW(
5244 SPDRP_COMPATIBLEIDS
,
5246 (PBYTE
)CompatibleIDs
,
5249 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5251 /* No compatible ID for this device */
5252 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5253 CompatibleIDs
= NULL
;
5261 /* Enumerate .inf files */
5263 RequiredSize
= 32768; /* Initial buffer size */
5264 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5265 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5267 HeapFree(GetProcessHeap(), 0, Buffer
);
5268 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5272 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5275 Result
= SetupGetInfFileListW(
5276 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5278 Buffer
, RequiredSize
,
5281 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5283 /* No .inf file in specified directory. So, we should
5284 * success as we created an empty driver info list.
5292 LPWSTR pFullFilename
;
5294 if (*InstallParams
.DriverPath
)
5297 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5300 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5301 if (!FullInfFileName
)
5303 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5306 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
5307 wcscat(FullInfFileName
, L
"\\");
5308 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
5312 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5313 if (!FullInfFileName
)
5315 pFullFilename
= &FullInfFileName
[0];
5318 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
5320 INFCONTEXT ContextManufacturer
, ContextDevice
;
5323 wcscpy(pFullFilename
, filename
);
5324 TRACE("Opening file %S\n", FullInfFileName
);
5326 currentInfFileDetails
= HeapAlloc(
5329 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
5330 if (!currentInfFileDetails
)
5332 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5333 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5335 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5336 ReferenceInfFile(currentInfFileDetails
);
5337 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5339 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5340 currentInfFileDetails
= NULL
;
5344 if (!GetVersionInformationFromInfFile(
5345 currentInfFileDetails
->hInf
,
5351 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5352 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5353 currentInfFileDetails
= NULL
;
5357 if (DriverType
== SPDIT_CLASSDRIVER
)
5359 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5360 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5366 /* Get the manufacturers list */
5367 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
5370 Result
= SetupGetStringFieldW(
5371 &ContextManufacturer
,
5372 0, /* Field index */
5377 /* We got the needed size for the buffer */
5378 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5379 if (!ManufacturerName
)
5381 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5384 Result
= SetupGetStringFieldW(
5385 &ContextManufacturer
,
5386 0, /* Field index */
5387 ManufacturerName
, RequiredSize
,
5390 /* Get manufacturer section name */
5391 Result
= SetupGetStringFieldW(
5392 &ContextManufacturer
,
5393 1, /* Field index */
5394 ManufacturerSection
, LINE_LEN
,
5398 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5399 /* Add (possible) extension to manufacturer section name */
5400 Result
= SetupDiGetActualSectionToInstallW(
5401 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5404 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
5405 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5410 if (DriverType
== SPDIT_CLASSDRIVER
)
5412 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5413 if (!AddDriverToList(
5414 &list
->DriverListHead
,
5418 currentInfFileDetails
,
5423 DriverDate
, DriverVersion
,
5429 else /* DriverType = SPDIT_COMPATDRIVER */
5431 /* 1. Get all fields */
5432 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5436 BOOL DriverAlreadyAdded
;
5438 for (i
= 2; i
<= FieldCount
; i
++)
5440 LPWSTR DeviceId
= NULL
;
5442 RequiredSize
= 128; /* Initial buffer size */
5443 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5444 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5446 HeapFree(GetProcessHeap(), 0, DeviceId
);
5447 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5450 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5453 Result
= SetupGetStringFieldW(
5456 DeviceId
, RequiredSize
,
5461 HeapFree(GetProcessHeap(), 0, DeviceId
);
5464 DriverAlreadyAdded
= FALSE
;
5465 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5467 if (wcsicmp(DeviceId
, currentId
) == 0)
5470 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5474 currentInfFileDetails
,
5479 DriverDate
, DriverVersion
,
5480 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5481 DriverAlreadyAdded
= TRUE
;
5486 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5488 if (wcsicmp(DeviceId
, currentId
) == 0)
5491 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5495 currentInfFileDetails
,
5500 DriverDate
, DriverVersion
,
5501 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5502 DriverAlreadyAdded
= TRUE
;
5506 HeapFree(GetProcessHeap(), 0, DeviceId
);
5509 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5512 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5513 ManufacturerName
= NULL
;
5514 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5519 HeapFree(GetProcessHeap(), 0, ProviderName
);
5520 ProviderName
= NULL
;
5522 DereferenceInfFile(currentInfFileDetails
);
5523 currentInfFileDetails
= NULL
;
5534 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5535 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5539 InstallParams
.Flags
|= DI_DIDCLASS
;
5540 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5542 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5545 HeapFree(GetProcessHeap(), 0, ProviderName
);
5546 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5547 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5548 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5549 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5550 if (currentInfFileDetails
)
5551 DereferenceInfFile(currentInfFileDetails
);
5552 HeapFree(GetProcessHeap(), 0, Buffer
);
5554 TRACE("Returning %d\n", ret
);
5558 /***********************************************************************
5559 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5562 SetupDiDeleteDeviceInfo(
5563 IN HDEVINFO DeviceInfoSet
,
5564 IN PSP_DEVINFO_DATA DeviceInfoData
)
5566 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5568 FIXME("not implemented\n");
5569 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5574 /***********************************************************************
5575 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5578 SetupDiDestroyDriverInfoList(
5579 IN HDEVINFO DeviceInfoSet
,
5580 IN PSP_DEVINFO_DATA DeviceInfoData
,
5581 IN DWORD DriverType
)
5583 struct DeviceInfoSet
*list
;
5586 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5589 SetLastError(ERROR_INVALID_HANDLE
);
5590 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5591 SetLastError(ERROR_INVALID_HANDLE
);
5592 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5593 SetLastError(ERROR_INVALID_PARAMETER
);
5594 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5595 SetLastError(ERROR_INVALID_PARAMETER
);
5596 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5597 SetLastError(ERROR_INVALID_USER_BUFFER
);
5600 PLIST_ENTRY ListEntry
;
5601 struct DriverInfoElement
*driverInfo
;
5602 SP_DEVINSTALL_PARAMS_W InstallParams
;
5604 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5605 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5608 if (!DeviceInfoData
)
5609 /* Fall back to destroying class driver list */
5610 DriverType
= SPDIT_CLASSDRIVER
;
5612 if (DriverType
== SPDIT_CLASSDRIVER
)
5614 while (!IsListEmpty(&list
->DriverListHead
))
5616 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
5617 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5618 DestroyDriverInfoElement(driverInfo
);
5620 InstallParams
.Reserved
= 0;
5621 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
5622 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
5623 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
5627 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
5628 struct DeviceInfoElement
*deviceInfo
;
5630 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5631 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
5633 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5634 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
5636 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
5637 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5638 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
5640 InstallParamsSet
.Reserved
= 0;
5641 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
5643 DestroyDriverInfoElement(driverInfo
);
5645 InstallParams
.Reserved
= 0;
5646 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
5647 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
5648 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5653 TRACE("Returning %d\n", ret
);
5658 /***********************************************************************
5659 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
5662 SetupDiOpenDeviceInfoA(
5663 IN HDEVINFO DeviceInfoSet
,
5664 IN PCSTR DeviceInstanceId
,
5665 IN HWND hwndParent OPTIONAL
,
5667 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5669 LPWSTR DeviceInstanceIdW
= NULL
;
5672 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5674 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
5675 if (DeviceInstanceIdW
== NULL
)
5678 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
5679 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
5681 MyFree(DeviceInstanceIdW
);
5687 /***********************************************************************
5688 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
5691 SetupDiOpenDeviceInfoW(
5692 IN HDEVINFO DeviceInfoSet
,
5693 IN PCWSTR DeviceInstanceId
,
5694 IN HWND hwndParent OPTIONAL
,
5696 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5698 struct DeviceInfoSet
*list
;
5699 HKEY hEnumKey
, hKey
;
5703 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5705 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
5706 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
5709 SetLastError(ERROR_INVALID_HANDLE
);
5710 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5711 SetLastError(ERROR_INVALID_HANDLE
);
5712 else if (!DeviceInstanceId
)
5713 SetLastError(ERROR_INVALID_PARAMETER
);
5714 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
5716 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
5717 SetLastError(ERROR_INVALID_FLAGS
);
5719 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5720 SetLastError(ERROR_INVALID_USER_BUFFER
);
5723 struct DeviceInfoElement
*deviceInfo
= NULL
;
5724 /* Search if device already exists in DeviceInfoSet.
5725 * If yes, return the existing element
5726 * If no, create a new element using informations in registry
5728 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
5729 while (ItemList
!= &list
->ListHead
)
5734 FIXME("not implemented\n");
5735 ItemList
= ItemList
->Flink
;
5740 /* good one found */
5745 /* Open supposed registry key */
5748 REGSTR_PATH_SYSTEMENUM
,
5752 if (rc
!= ERROR_SUCCESS
)
5763 RegCloseKey(hEnumKey
);
5764 if (rc
!= ERROR_SUCCESS
)
5766 if (rc
== ERROR_FILE_NOT_FOUND
)
5767 rc
= ERROR_NO_SUCH_DEVINST
;
5772 /* FIXME: try to get ClassGUID from registry, instead of
5773 * sending GUID_NULL to CreateDeviceInfoElement
5775 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
5780 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5786 if (ret
&& deviceInfo
&& DeviceInfoData
)
5788 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
5789 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5790 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5798 /***********************************************************************
5799 * SetupDiEnumDriverInfoA (SETUPAPI.@)
5802 SetupDiEnumDriverInfoA(
5803 IN HDEVINFO DeviceInfoSet
,
5804 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5805 IN DWORD DriverType
,
5806 IN DWORD MemberIndex
,
5807 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
5809 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
5812 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
5813 DriverType
, MemberIndex
, DriverInfoData
);
5815 if (DriverInfoData
== NULL
)
5816 SetLastError(ERROR_INVALID_PARAMETER
);
5817 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
5818 SetLastError(ERROR_INVALID_USER_BUFFER
);
5821 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5822 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
5823 DriverType
, MemberIndex
, &driverInfoData2W
);
5827 /* Do W->A conversion */
5828 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
5829 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
5830 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
5831 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
5833 DriverInfoData
->Description
[0] = '\0';
5836 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
5837 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
5839 DriverInfoData
->MfgName
[0] = '\0';
5842 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
5843 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
5845 DriverInfoData
->ProviderName
[0] = '\0';
5848 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5850 /* Copy more fields */
5851 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
5852 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
5857 TRACE("Returning %d\n", ret
);
5862 /***********************************************************************
5863 * SetupDiEnumDriverInfoW (SETUPAPI.@)
5866 SetupDiEnumDriverInfoW(
5867 IN HDEVINFO DeviceInfoSet
,
5868 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5869 IN DWORD DriverType
,
5870 IN DWORD MemberIndex
,
5871 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
5873 PLIST_ENTRY ListHead
;
5876 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
5877 DriverType
, MemberIndex
, DriverInfoData
);
5879 if (!DeviceInfoSet
|| !DriverInfoData
)
5880 SetLastError(ERROR_INVALID_PARAMETER
);
5881 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5882 SetLastError(ERROR_INVALID_HANDLE
);
5883 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5884 SetLastError(ERROR_INVALID_HANDLE
);
5885 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5886 SetLastError(ERROR_INVALID_PARAMETER
);
5887 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
5888 SetLastError(ERROR_INVALID_PARAMETER
);
5889 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5890 SetLastError(ERROR_INVALID_PARAMETER
);
5891 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
5892 SetLastError(ERROR_INVALID_USER_BUFFER
);
5895 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5896 PLIST_ENTRY ItemList
;
5897 if (DriverType
== SPDIT_CLASSDRIVER
||
5898 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
5900 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
5904 ListHead
= &devInfo
->DriverListHead
;
5907 ItemList
= ListHead
->Flink
;
5908 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
5909 ItemList
= ItemList
->Flink
;
5910 if (ItemList
== ListHead
)
5911 SetLastError(ERROR_NO_MORE_ITEMS
);
5914 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
5917 &DriverInfoData
->DriverType
,
5918 &DrvInfo
->Info
.DriverType
,
5919 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
5924 TRACE("Returning %d\n", ret
);
5929 /***********************************************************************
5930 * SetupDiGetSelectedDriverA (SETUPAPI.@)
5933 SetupDiGetSelectedDriverA(
5934 IN HDEVINFO DeviceInfoSet
,
5935 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5936 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
5938 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
5941 if (DriverInfoData
== NULL
)
5942 SetLastError(ERROR_INVALID_PARAMETER
);
5943 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
5944 SetLastError(ERROR_INVALID_USER_BUFFER
);
5947 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5949 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
5955 /* Do W->A conversion */
5956 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
5957 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
5958 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
5959 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
5961 DriverInfoData
->Description
[0] = '\0';
5964 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
5965 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
5967 DriverInfoData
->MfgName
[0] = '\0';
5970 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
5971 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
5973 DriverInfoData
->ProviderName
[0] = '\0';
5976 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
5978 /* Copy more fields */
5979 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
5980 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
5989 /***********************************************************************
5990 * SetupDiGetSelectedDriverW (SETUPAPI.@)
5993 SetupDiGetSelectedDriverW(
5994 IN HDEVINFO DeviceInfoSet
,
5995 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5996 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6000 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6002 if (!DeviceInfoSet
|| !DriverInfoData
)
6003 SetLastError(ERROR_INVALID_PARAMETER
);
6004 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6005 SetLastError(ERROR_INVALID_HANDLE
);
6006 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6007 SetLastError(ERROR_INVALID_HANDLE
);
6008 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6009 SetLastError(ERROR_INVALID_USER_BUFFER
);
6010 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6011 SetLastError(ERROR_INVALID_USER_BUFFER
);
6014 SP_DEVINSTALL_PARAMS InstallParams
;
6016 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
6017 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6019 struct DriverInfoElement
*driverInfo
;
6020 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6021 if (driverInfo
== NULL
)
6022 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6026 &DriverInfoData
->DriverType
,
6027 &driverInfo
->Info
.DriverType
,
6028 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6034 TRACE("Returning %d\n", ret
);
6039 /***********************************************************************
6040 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6043 SetupDiSetSelectedDriverA(
6044 IN HDEVINFO DeviceInfoSet
,
6045 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6046 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6048 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6049 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6052 if (DriverInfoData
!= NULL
)
6054 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6055 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6057 SetLastError(ERROR_INVALID_PARAMETER
);
6061 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6062 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6064 if (DriverInfoDataW
.Reserved
== 0)
6066 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6068 /* convert the strings to unicode */
6069 if (!MultiByteToWideChar(CP_ACP
,
6071 DriverInfoData
->Description
,
6073 DriverInfoDataW
.Description
,
6075 !MultiByteToWideChar(CP_ACP
,
6077 DriverInfoData
->ProviderName
,
6079 DriverInfoDataW
.ProviderName
,
6086 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6089 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6093 if (ret
&& pDriverInfoDataW
!= NULL
)
6095 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6102 /***********************************************************************
6103 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6106 SetupDiSetSelectedDriverW(
6107 IN HDEVINFO DeviceInfoSet
,
6108 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6109 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6113 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6116 SetLastError(ERROR_INVALID_PARAMETER
);
6117 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6118 SetLastError(ERROR_INVALID_HANDLE
);
6119 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6120 SetLastError(ERROR_INVALID_HANDLE
);
6121 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6122 SetLastError(ERROR_INVALID_USER_BUFFER
);
6123 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6124 SetLastError(ERROR_INVALID_USER_BUFFER
);
6127 struct DriverInfoElement
**pDriverInfo
;
6128 PLIST_ENTRY ListHead
, ItemList
;
6132 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6133 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6137 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6138 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6141 if (!DriverInfoData
)
6143 *pDriverInfo
= NULL
;
6148 /* Search selected driver in list */
6149 ItemList
= ListHead
->Flink
;
6150 while (ItemList
!= ListHead
)
6152 if (DriverInfoData
->Reserved
!= 0)
6154 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6159 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6160 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
6161 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6162 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6163 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6169 if (ItemList
== ListHead
)
6170 SetLastError(ERROR_INVALID_PARAMETER
);
6173 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
6174 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6176 TRACE("Choosing driver whose rank is 0x%lx\n",
6177 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
6179 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6184 TRACE("Returning %d\n", ret
);
6188 /***********************************************************************
6189 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6192 SetupDiGetDriverInfoDetailA(
6193 IN HDEVINFO DeviceInfoSet
,
6194 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6195 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6196 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6197 IN DWORD DriverInfoDetailDataSize
,
6198 OUT PDWORD RequiredSize OPTIONAL
)
6200 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6201 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6203 DWORD HardwareIDLen
= 0;
6206 /* do some sanity checks, the unicode version might do more thorough checks */
6207 if (DriverInfoData
== NULL
||
6208 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6209 (DriverInfoDetailData
!= NULL
&&
6210 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6211 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6213 SetLastError(ERROR_INVALID_PARAMETER
);
6217 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6218 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6220 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6222 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6224 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6228 SetLastError(ERROR_INVALID_PARAMETER
);
6231 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6232 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6234 /* convert the strings to unicode */
6235 if (MultiByteToWideChar(CP_ACP
,
6237 DriverInfoData
->Description
,
6239 DriverInfoDataW
.Description
,
6241 MultiByteToWideChar(CP_ACP
,
6243 DriverInfoData
->MfgName
,
6245 DriverInfoDataW
.MfgName
,
6247 MultiByteToWideChar(CP_ACP
,
6249 DriverInfoData
->ProviderName
,
6251 DriverInfoDataW
.ProviderName
,
6254 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6256 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6257 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6260 if (DriverInfoDetailData
!= NULL
)
6262 /* calculate the unicode buffer size from the ansi buffer size */
6263 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6264 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6265 (HardwareIDLen
* sizeof(WCHAR
));
6267 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6268 if (DriverInfoDetailDataW
== NULL
)
6270 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6274 /* initialize the buffer */
6275 ZeroMemory(DriverInfoDetailDataW
,
6277 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6280 /* call the unicode version */
6281 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6284 DriverInfoDetailDataW
,
6290 if (DriverInfoDetailDataW
!= NULL
)
6292 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6293 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6294 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6295 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6296 if (WideCharToMultiByte(CP_ACP
,
6298 DriverInfoDetailDataW
->SectionName
,
6300 DriverInfoDetailData
->SectionName
,
6304 WideCharToMultiByte(CP_ACP
,
6306 DriverInfoDetailDataW
->InfFileName
,
6308 DriverInfoDetailData
->InfFileName
,
6312 WideCharToMultiByte(CP_ACP
,
6314 DriverInfoDetailDataW
->DrvDescription
,
6316 DriverInfoDetailData
->DrvDescription
,
6320 WideCharToMultiByte(CP_ACP
,
6322 DriverInfoDetailDataW
->HardwareID
,
6324 DriverInfoDetailData
->HardwareID
,
6330 DWORD hwidlen
= HardwareIDLen
;
6331 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6333 /* count the strings in the list */
6336 len
= lstrlenA(s
) + 1;
6345 /* looks like the string list wasn't terminated... */
6346 SetLastError(ERROR_INVALID_USER_BUFFER
);
6352 /* make sure CompatIDsOffset points to the second string in the
6356 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6357 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6358 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6362 DriverInfoDetailData
->CompatIDsOffset
= 0;
6363 DriverInfoDetailData
->CompatIDsLength
= 0;
6372 if (RequiredSize
!= NULL
)
6374 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6375 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6381 if (DriverInfoDetailDataW
!= NULL
)
6383 MyFree(DriverInfoDetailDataW
);
6389 /***********************************************************************
6390 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6393 SetupDiGetDriverInfoDetailW(
6394 IN HDEVINFO DeviceInfoSet
,
6395 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6396 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6397 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6398 IN DWORD DriverInfoDetailDataSize
,
6399 OUT PDWORD RequiredSize OPTIONAL
)
6403 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6404 DriverInfoData
, DriverInfoDetailData
,
6405 DriverInfoDetailDataSize
, RequiredSize
);
6408 SetLastError(ERROR_INVALID_PARAMETER
);
6409 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6410 SetLastError(ERROR_INVALID_HANDLE
);
6411 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6412 SetLastError(ERROR_INVALID_HANDLE
);
6413 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6414 SetLastError(ERROR_INVALID_USER_BUFFER
);
6415 else if (!DriverInfoData
)
6416 SetLastError(ERROR_INVALID_PARAMETER
);
6417 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6418 SetLastError(ERROR_INVALID_PARAMETER
);
6419 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6420 SetLastError(ERROR_INVALID_PARAMETER
);
6421 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6422 SetLastError(ERROR_INVALID_USER_BUFFER
);
6423 else if (DriverInfoData
->Reserved
== 0)
6424 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6427 struct DriverInfoElement
*driverInfoElement
;
6428 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6431 DriverInfoDetailData
,
6432 &driverInfoElement
->Details
,
6433 driverInfoElement
->Details
.cbSize
);
6434 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6435 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6440 TRACE("Returning %d\n", ret
);
6444 /* Return the current hardware profile id, or -1 if error */
6446 GetCurrentHwProfile(
6447 IN HDEVINFO DeviceInfoSet
)
6449 HKEY hKey
= INVALID_HANDLE_VALUE
;
6450 DWORD dwRegType
, dwLength
;
6453 DWORD ret
= (DWORD
)-1;
6456 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
6457 REGSTR_PATH_IDCONFIGDB
,
6461 if (rc
!= ERROR_SUCCESS
)
6467 dwLength
= sizeof(DWORD
);
6468 rc
= RegQueryValueExW(
6470 REGSTR_VAL_CURRENTCONFIG
,
6473 (LPBYTE
)&hwProfile
, &dwLength
);
6474 if (rc
!= ERROR_SUCCESS
)
6479 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6481 SetLastError(ERROR_GEN_FAILURE
);
6488 if (hKey
!= INVALID_HANDLE_VALUE
)
6496 IN HDEVINFO DeviceInfoSet
,
6497 IN PSP_DEVINFO_DATA DeviceInfoData
)
6499 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6500 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6503 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
6505 /* At the moment, I only know how to start local devices */
6506 SetLastError(ERROR_INVALID_COMPUTERNAME
);
6510 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
6511 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6512 SetLastError(RtlNtStatusToDosError(Status
));
6513 return NT_SUCCESS(Status
);
6516 static BOOL
StopDevice(
6517 IN HDEVINFO DeviceInfoSet
,
6518 IN PSP_DEVINFO_DATA DeviceInfoData
)
6520 FIXME("Stub %p %p\n", DeviceInfoSet
, DeviceInfoData
);
6524 /***********************************************************************
6525 * SetupDiChangeState (SETUPAPI.@)
6529 IN HDEVINFO DeviceInfoSet
,
6530 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6532 PSP_PROPCHANGE_PARAMS PropChange
;
6533 HKEY hKey
= INVALID_HANDLE_VALUE
;
6534 LPCWSTR RegistryValueName
;
6535 DWORD dwConfigFlags
, dwLength
, dwRegType
;
6539 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6541 if (!DeviceInfoData
)
6542 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
6544 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
6547 SetLastError(ERROR_INVALID_PARAMETER
);
6551 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
6552 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
6554 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
6556 switch (PropChange
->StateChange
)
6561 /* Enable/disable device in registry */
6562 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
6563 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6564 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
6565 if (hKey
== INVALID_HANDLE_VALUE
)
6567 dwLength
= sizeof(DWORD
);
6568 rc
= RegQueryValueExW(
6573 (LPBYTE
)&dwConfigFlags
, &dwLength
);
6574 if (rc
== ERROR_FILE_NOT_FOUND
)
6576 else if (rc
!= ERROR_SUCCESS
)
6581 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6583 SetLastError(ERROR_GEN_FAILURE
);
6586 if (PropChange
->StateChange
== DICS_ENABLE
)
6587 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6589 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6595 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
6596 if (rc
!= ERROR_SUCCESS
)
6602 /* Enable/disable device if needed */
6603 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
6604 || PropChange
->HwProfile
== 0
6605 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
6607 if (PropChange
->StateChange
== DICS_ENABLE
)
6608 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6610 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
6616 case DICS_PROPCHANGE
:
6618 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6623 FIXME("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
6624 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
6629 if (hKey
!= INVALID_HANDLE_VALUE
)
6632 TRACE("Returning %d\n", ret
);
6636 /***********************************************************************
6637 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
6640 SetupDiSelectBestCompatDrv(
6641 IN HDEVINFO DeviceInfoSet
,
6642 IN PSP_DEVINFO_DATA DeviceInfoData
)
6644 SP_DRVINFO_DATA_W drvInfoData
;
6647 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6649 /* Drivers are sorted by rank in the driver list, so
6650 * the first driver in the list is the best one.
6652 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
6653 ret
= SetupDiEnumDriverInfoW(
6657 0, /* Member index */
6662 ret
= SetupDiSetSelectedDriverW(
6668 TRACE("Returning %d\n", ret
);
6672 /***********************************************************************
6673 * SetupDiInstallDriverFiles (SETUPAPI.@)
6676 SetupDiInstallDriverFiles(
6677 IN HDEVINFO DeviceInfoSet
,
6678 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6682 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6685 SetLastError(ERROR_INVALID_PARAMETER
);
6686 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6687 SetLastError(ERROR_INVALID_HANDLE
);
6688 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6689 SetLastError(ERROR_INVALID_HANDLE
);
6690 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6691 SetLastError(ERROR_INVALID_USER_BUFFER
);
6692 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
6693 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6694 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
6695 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6698 SP_DEVINSTALL_PARAMS_W InstallParams
;
6699 struct DriverInfoElement
*SelectedDriver
;
6700 WCHAR SectionName
[MAX_PATH
];
6701 DWORD SectionNameLength
= 0;
6703 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6704 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6708 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6709 if (!SelectedDriver
)
6711 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6715 ret
= SetupDiGetActualSectionToInstallW(
6716 SelectedDriver
->InfFileDetails
->hInf
,
6717 SelectedDriver
->Details
.SectionName
,
6718 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6722 if (!InstallParams
.InstallMsgHandler
)
6724 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6725 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6726 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6728 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6729 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6730 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
6731 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6732 DeviceInfoSet
, DeviceInfoData
);
6736 TRACE("Returning %d\n", ret
);
6740 /***********************************************************************
6741 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
6744 SetupDiRegisterCoDeviceInstallers(
6745 IN HDEVINFO DeviceInfoSet
,
6746 IN PSP_DEVINFO_DATA DeviceInfoData
)
6748 BOOL ret
= FALSE
; /* Return value */
6750 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6753 SetLastError(ERROR_INVALID_PARAMETER
);
6754 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6755 SetLastError(ERROR_INVALID_HANDLE
);
6756 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6757 SetLastError(ERROR_INVALID_HANDLE
);
6758 else if (!DeviceInfoData
)
6759 SetLastError(ERROR_INVALID_PARAMETER
);
6760 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6761 SetLastError(ERROR_INVALID_USER_BUFFER
);
6764 SP_DEVINSTALL_PARAMS_W InstallParams
;
6765 struct DriverInfoElement
*SelectedDriver
;
6768 WCHAR SectionName
[MAX_PATH
];
6769 DWORD SectionNameLength
= 0;
6770 HKEY hKey
= INVALID_HANDLE_VALUE
;
6772 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6773 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6777 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6778 if (SelectedDriver
== NULL
)
6780 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6784 /* Get .CoInstallers section name */
6785 Result
= SetupDiGetActualSectionToInstallW(
6786 SelectedDriver
->InfFileDetails
->hInf
,
6787 SelectedDriver
->Details
.SectionName
,
6788 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6789 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".CoInstallers") - 1)
6791 wcscat(SectionName
, L
".CoInstallers");
6793 /* Open/Create driver key information */
6794 #if _WIN32_WINNT >= 0x502
6795 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
6797 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
6799 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6800 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
6801 if (hKey
== INVALID_HANDLE_VALUE
)
6804 /* Install .CoInstallers section */
6805 DoAction
= SPINST_REGISTRY
;
6806 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
6808 DoAction
|= SPINST_FILES
;
6809 if (!InstallParams
.InstallMsgHandler
)
6811 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6812 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6813 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6816 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6817 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6818 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
6819 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6820 DeviceInfoSet
, DeviceInfoData
);
6827 if (hKey
!= INVALID_HANDLE_VALUE
)
6831 TRACE("Returning %d\n", ret
);
6835 /***********************************************************************
6836 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
6839 SetupDiInstallDeviceInterfaces(
6840 IN HDEVINFO DeviceInfoSet
,
6841 IN PSP_DEVINFO_DATA DeviceInfoData
)
6843 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6845 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
6846 //SetLastError(ERROR_GEN_FAILURE);
6852 InfIsFromOEMLocation(
6854 OUT LPBOOL IsOEMLocation
)
6858 last
= strrchrW(FullName
, '\\');
6861 /* No directory specified */
6862 *IsOEMLocation
= FALSE
;
6866 WCHAR Windir
[MAX_PATH
];
6869 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
6870 if (ret
== 0 || ret
>= MAX_PATH
)
6872 SetLastError(ERROR_GEN_FAILURE
);
6876 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
6878 /* The path is %SYSTEMROOT%\Inf */
6879 *IsOEMLocation
= FALSE
;
6883 /* The file is in another place */
6884 *IsOEMLocation
= TRUE
;
6890 /***********************************************************************
6891 * SetupDiInstallDevice (SETUPAPI.@)
6894 SetupDiInstallDevice(
6895 IN HDEVINFO DeviceInfoSet
,
6896 IN PSP_DEVINFO_DATA DeviceInfoData
)
6898 SP_DEVINSTALL_PARAMS_W InstallParams
;
6899 struct DriverInfoElement
*SelectedDriver
;
6900 SYSTEMTIME DriverDate
;
6901 WCHAR SectionName
[MAX_PATH
];
6903 DWORD SectionNameLength
= 0;
6904 BOOL Result
= FALSE
;
6905 INFCONTEXT ContextService
;
6909 LPCWSTR AssociatedService
= NULL
;
6910 LPWSTR pSectionName
= NULL
;
6911 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
6913 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
6914 BOOL RebootRequired
= FALSE
;
6915 HKEY hKey
= INVALID_HANDLE_VALUE
;
6916 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
6917 BOOL NeedtoCopyFile
;
6918 LARGE_INTEGER fullVersion
;
6920 BOOL ret
= FALSE
; /* Return value */
6922 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6925 SetLastError(ERROR_INVALID_PARAMETER
);
6926 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6927 SetLastError(ERROR_INVALID_HANDLE
);
6928 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6929 SetLastError(ERROR_INVALID_HANDLE
);
6930 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6931 SetLastError(ERROR_INVALID_USER_BUFFER
);
6937 /* One parameter is bad */
6941 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6942 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6946 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
6948 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
6952 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6953 if (SelectedDriver
== NULL
)
6955 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6959 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
6961 Result
= SetupDiGetActualSectionToInstallW(
6962 SelectedDriver
->InfFileDetails
->hInf
,
6963 SelectedDriver
->Details
.SectionName
,
6964 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6965 if (!Result
|| SectionNameLength
> MAX_PATH
- 9)
6967 pSectionName
= &SectionName
[wcslen(SectionName
)];
6969 /* Get information from [Version] section */
6970 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
6972 /* Format ClassGuid to a string */
6973 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
6975 RequiredSize
= lstrlenW(lpGuidString
);
6976 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
6977 if (!lpFullGuidString
)
6979 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6982 lpFullGuidString
[0] = '{';
6983 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
6984 lpFullGuidString
[RequiredSize
+ 1] = '}';
6985 lpFullGuidString
[RequiredSize
+ 2] = '\0';
6987 /* Open/Create driver key information */
6988 #if _WIN32_WINNT >= 0x502
6989 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
6991 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
6993 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6994 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
6995 if (hKey
== INVALID_HANDLE_VALUE
)
6998 /* Install main section */
6999 DoAction
= SPINST_REGISTRY
;
7000 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7002 DoAction
|= SPINST_FILES
;
7003 if (!InstallParams
.InstallMsgHandler
)
7005 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
7006 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7007 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7010 *pSectionName
= '\0';
7011 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7012 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7013 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7014 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7015 DeviceInfoSet
, DeviceInfoData
);
7018 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
7020 if (Result
&& InstallParams
.InstallMsgHandler
== SetupDefaultQueueCallbackW
)
7022 /* Delete resources allocated by SetupInitDefaultQueueCallback */
7023 SetupTermDefaultQueueCallback(InstallParams
.InstallMsgHandlerContext
);
7026 InstallParams
.Flags
|= DI_NOFILECOPY
;
7027 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7029 /* Write information to driver key */
7030 *pSectionName
= UNICODE_NULL
;
7031 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
7032 TRACE("Write information to driver key\n");
7033 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7034 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7035 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7036 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
7037 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
7038 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
7039 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
7040 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
7041 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7042 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7043 if (rc
== ERROR_SUCCESS
)
7044 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7045 if (rc
== ERROR_SUCCESS
)
7046 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7047 if (rc
== ERROR_SUCCESS
)
7049 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7050 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7052 if (rc
== ERROR_SUCCESS
)
7053 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7054 if (rc
== ERROR_SUCCESS
)
7055 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7056 if (rc
== ERROR_SUCCESS
)
7057 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7058 if (rc
== ERROR_SUCCESS
)
7059 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7060 if (rc
== ERROR_SUCCESS
)
7061 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7062 if (rc
!= ERROR_SUCCESS
)
7068 hKey
= INVALID_HANDLE_VALUE
;
7070 /* FIXME: Process .LogConfigOverride section */
7072 /* Install .Services section */
7073 wcscpy(pSectionName
, L
".Services");
7074 Result
= SetupFindFirstLineW(SelectedDriver
->InfFileDetails
->hInf
, SectionName
, NULL
, &ContextService
);
7077 LPWSTR ServiceName
= NULL
;
7078 LPWSTR ServiceSection
= NULL
;
7080 Result
= SetupGetStringFieldW(
7082 1, /* Field index */
7087 if (RequiredSize
> 0)
7089 /* We got the needed size for the buffer */
7090 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
7093 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7096 Result
= SetupGetStringFieldW(
7098 1, /* Field index */
7099 ServiceName
, RequiredSize
,
7104 Result
= SetupGetIntField(
7106 2, /* Field index */
7110 /* The field may be empty. Ignore the error */
7113 Result
= SetupGetStringFieldW(
7115 3, /* Field index */
7120 if (GetLastError() == ERROR_INVALID_PARAMETER
)
7122 /* This first is probably missing. It is not
7123 * required, so ignore the error */
7130 if (RequiredSize
> 0)
7132 /* We got the needed size for the buffer */
7133 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
7134 if (!ServiceSection
)
7136 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7139 Result
= SetupGetStringFieldW(
7141 3, /* Field index */
7142 ServiceSection
, RequiredSize
,
7147 SetLastError(ERROR_SUCCESS
);
7148 Result
= SetupInstallServicesFromInfSectionExW(
7149 SelectedDriver
->InfFileDetails
->hInf
,
7150 ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
7152 if (Result
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
7154 AssociatedService
= ServiceName
;
7156 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
7157 RebootRequired
= TRUE
;
7160 HeapFree(GetProcessHeap(), 0, ServiceName
);
7161 HeapFree(GetProcessHeap(), 0, ServiceSection
);
7164 Result
= SetupFindNextLine(&ContextService
, &ContextService
);
7167 /* Copy .inf file to Inf\ directory (if needed) */
7168 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7173 Result
= SetupCopyOEMInfW(
7174 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7177 SP_COPY_NOOVERWRITE
,
7183 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7184 * to release use of current InfFile */
7187 /* Open device registry key */
7188 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7189 if (hKey
== INVALID_HANDLE_VALUE
)
7192 /* Install .HW section */
7193 wcscpy(pSectionName
, L
".HW");
7194 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7195 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7196 SPINST_REGISTRY
, hKey
, NULL
, 0,
7197 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7198 DeviceInfoSet
, DeviceInfoData
);
7202 /* Write information to enum key */
7203 TRACE("Write information to enum key\n");
7204 TRACE("Class : '%S'\n", ClassName
);
7205 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
7206 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7207 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
7208 TRACE("Service : '%S'\n", AssociatedService
);
7209 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
7210 if (rc
== ERROR_SUCCESS
)
7211 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7212 if (rc
== ERROR_SUCCESS
)
7213 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7214 if (rc
== ERROR_SUCCESS
)
7215 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7216 if (rc
== ERROR_SUCCESS
&& *AssociatedService
)
7217 rc
= RegSetValueEx(hKey
, REGSTR_VAL_SERVICE
, 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
7218 if (rc
!= ERROR_SUCCESS
)
7224 /* Start the device */
7225 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7226 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7231 /* End of installation */
7232 if (hClassKey
!= INVALID_HANDLE_VALUE
)
7233 RegCloseKey(hClassKey
);
7234 if (hKey
!= INVALID_HANDLE_VALUE
)
7237 RpcStringFreeW(&lpGuidString
);
7238 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
7239 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7241 TRACE("Returning %d\n", ret
);