2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005 Hervé Poussineau (hpoussin@reactos.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "setupapi_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
27 /* Unicode constants */
28 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class
[] = {'C','l','a','s','s',0};
30 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
31 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
32 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
33 static const WCHAR InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
34 static const WCHAR NtExtension
[] = {'.','N','T',0};
35 static const WCHAR NtPlatformExtension
[] = {'.','N','T','x','8','6',0};
36 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
37 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
38 static const WCHAR WinExtension
[] = {'.','W','i','n',0};
40 /* FIXME: header mess */
41 DEFINE_GUID(GUID_NULL
,
42 0x00000000L
, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
44 (CALLBACK
* CLASS_INSTALL_PROC
) (
45 IN DI_FUNCTION InstallFunction
,
46 IN HDEVINFO DeviceInfoSet
,
47 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
49 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
50 IN HDEVINFO DeviceInfoSet
,
51 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
53 (CALLBACK
* COINSTALLER_PROC
) (
54 IN DI_FUNCTION InstallFunction
,
55 IN HDEVINFO DeviceInfoSet
,
56 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
57 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
59 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
60 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
61 IN LPFNADDPROPSHEETPAGE fAddFunc
,
64 (*UPDATE_CLASS_PARAM_HANDLER
) (
65 IN HDEVINFO DeviceInfoSet
,
66 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
67 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
68 IN DWORD ClassInstallParamsSize
);
70 struct CoInstallerElement
75 COINSTALLER_PROC Function
;
76 BOOL DoPostProcessing
;
81 PropertyChangeHandler(
82 IN HDEVINFO DeviceInfoSet
,
83 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
84 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
85 IN DWORD ClassInstallParamsSize
);
87 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
88 NULL
, /* DIF_SELECTDEVICE */
89 NULL
, /* DIF_INSTALLDEVICE */
90 NULL
, /* DIF_ASSIGNRESOURCES */
91 NULL
, /* DIF_PROPERTIES */
92 NULL
, /* DIF_REMOVE */
93 NULL
, /* DIF_FIRSTTIMESETUP */
94 NULL
, /* DIF_FOUNDDEVICE */
95 NULL
, /* DIF_SELECTCLASSDRIVERS */
96 NULL
, /* DIF_VALIDATECLASSDRIVERS */
97 NULL
, /* DIF_INSTALLCLASSDRIVERS */
98 NULL
, /* DIF_CALCDISKSPACE */
99 NULL
, /* DIF_DESTROYPRIVATEDATA */
100 NULL
, /* DIF_VALIDATEDRIVER */
101 NULL
, /* DIF_MOVEDEVICE */
102 NULL
, /* DIF_DETECT */
103 NULL
, /* DIF_INSTALLWIZARD */
104 NULL
, /* DIF_DESTROYWIZARDDATA */
105 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
106 NULL
, /* DIF_ENABLECLASS */
107 NULL
, /* DIF_DETECTVERIFY */
108 NULL
, /* DIF_INSTALLDEVICEFILES */
109 NULL
, /* DIF_UNREMOVE */
110 NULL
, /* DIF_SELECTBESTCOMPATDRV */
111 NULL
, /* DIF_ALLOW_INSTALL */
112 NULL
, /* DIF_REGISTERDEVICE */
113 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
114 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
115 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
116 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
117 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
118 NULL
, /* DIF_UNUSED1 */
119 NULL
, /* DIF_INSTALLINTERFACES */
120 NULL
, /* DIF_DETECTCANCEL */
121 NULL
, /* DIF_REGISTER_COINSTALLERS */
122 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
123 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
124 NULL
, /* DIF_RESERVED1 */
125 NULL
, /* DIF_TROUBLESHOOTER */
126 NULL
, /* DIF_POWERMESSAGEWAKE */
127 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
128 NULL
, /* DIF_UPDATEDRIVER_UI */
129 NULL
/* DIF_RESERVED2 */
132 /***********************************************************************
133 * SetupDiBuildClassInfoList (SETUPAPI.@)
135 BOOL WINAPI
SetupDiBuildClassInfoList(
137 LPGUID ClassGuidList
,
138 DWORD ClassGuidListSize
,
142 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
143 ClassGuidListSize
, RequiredSize
,
147 /***********************************************************************
148 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
150 BOOL WINAPI
SetupDiBuildClassInfoListExA(
152 LPGUID ClassGuidList
,
153 DWORD ClassGuidListSize
,
158 LPWSTR MachineNameW
= NULL
;
165 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
166 if (MachineNameW
== NULL
) return FALSE
;
169 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
170 ClassGuidListSize
, RequiredSize
,
171 MachineNameW
, Reserved
);
174 MyFree(MachineNameW
);
179 /***********************************************************************
180 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
182 BOOL WINAPI
SetupDiBuildClassInfoListExW(
184 LPGUID ClassGuidList
,
185 DWORD ClassGuidListSize
,
190 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
196 DWORD dwGuidListIndex
= 0;
198 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
199 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
201 if (RequiredSize
!= NULL
)
204 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
205 KEY_ENUMERATE_SUB_KEYS
,
209 if (hClassesKey
== INVALID_HANDLE_VALUE
)
214 for (dwIndex
= 0; ; dwIndex
++)
216 dwLength
= MAX_GUID_STRING_LEN
+ 1;
217 lError
= RegEnumKeyExW(hClassesKey
,
225 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
226 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
228 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
230 if (RegOpenKeyExW(hClassesKey
,
236 RegCloseKey(hClassesKey
);
240 if (!RegQueryValueExW(hClassKey
,
241 REGSTR_VAL_NOUSECLASS
,
247 TRACE("'NoUseClass' value found!\n");
248 RegCloseKey(hClassKey
);
252 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
253 (!RegQueryValueExW(hClassKey
,
254 REGSTR_VAL_NOINSTALLCLASS
,
260 TRACE("'NoInstallClass' value found!\n");
261 RegCloseKey(hClassKey
);
265 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
266 (!RegQueryValueExW(hClassKey
,
267 REGSTR_VAL_NODISPLAYCLASS
,
273 TRACE("'NoDisplayClass' value found!\n");
274 RegCloseKey(hClassKey
);
278 RegCloseKey(hClassKey
);
280 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
281 if (dwGuidListIndex
< ClassGuidListSize
)
283 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
287 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
289 UuidFromStringW(&szKeyName
[1],
290 &ClassGuidList
[dwGuidListIndex
]);
296 if (lError
!= ERROR_SUCCESS
)
300 RegCloseKey(hClassesKey
);
302 if (RequiredSize
!= NULL
)
303 *RequiredSize
= dwGuidListIndex
;
305 if (ClassGuidListSize
< dwGuidListIndex
)
307 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
314 /***********************************************************************
315 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
317 BOOL WINAPI
SetupDiClassGuidsFromNameA(
319 LPGUID ClassGuidList
,
320 DWORD ClassGuidListSize
,
323 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
324 ClassGuidListSize
, RequiredSize
,
328 /***********************************************************************
329 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
331 BOOL WINAPI
SetupDiClassGuidsFromNameW(
333 LPGUID ClassGuidList
,
334 DWORD ClassGuidListSize
,
337 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
338 ClassGuidListSize
, RequiredSize
,
342 /***********************************************************************
343 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
345 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
347 LPGUID ClassGuidList
,
348 DWORD ClassGuidListSize
,
353 LPWSTR ClassNameW
= NULL
;
354 LPWSTR MachineNameW
= NULL
;
359 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
360 if (ClassNameW
== NULL
)
365 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
366 if (MachineNameW
== NULL
)
373 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
374 ClassGuidListSize
, RequiredSize
,
375 MachineNameW
, Reserved
);
378 MyFree(MachineNameW
);
385 /***********************************************************************
386 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
388 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
390 LPGUID ClassGuidList
,
391 DWORD ClassGuidListSize
,
396 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
397 WCHAR szClassName
[256];
403 DWORD dwGuidListIndex
= 0;
405 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
406 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
408 if (RequiredSize
!= NULL
)
411 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
412 KEY_ENUMERATE_SUB_KEYS
,
416 if (hClassesKey
== INVALID_HANDLE_VALUE
)
421 for (dwIndex
= 0; ; dwIndex
++)
423 dwLength
= MAX_GUID_STRING_LEN
+ 1;
424 lError
= RegEnumKeyExW(hClassesKey
,
432 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
433 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
435 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
437 if (RegOpenKeyExW(hClassesKey
,
443 RegCloseKey(hClassesKey
);
447 dwLength
= 256 * sizeof(WCHAR
);
448 if (!RegQueryValueExW(hClassKey
,
455 TRACE("Class name: %s\n", debugstr_w(szClassName
));
457 if (strcmpiW(szClassName
, ClassName
) == 0)
459 TRACE("Found matching class name\n");
461 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
462 if (dwGuidListIndex
< ClassGuidListSize
)
464 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
468 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
470 UuidFromStringW(&szKeyName
[1],
471 &ClassGuidList
[dwGuidListIndex
]);
478 RegCloseKey(hClassKey
);
481 if (lError
!= ERROR_SUCCESS
)
485 RegCloseKey(hClassesKey
);
487 if (RequiredSize
!= NULL
)
488 *RequiredSize
= dwGuidListIndex
;
490 if (ClassGuidListSize
< dwGuidListIndex
)
492 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
499 /***********************************************************************
500 * SetupDiClassNameFromGuidA (SETUPAPI.@)
502 BOOL WINAPI
SetupDiClassNameFromGuidA(
503 const GUID
* ClassGuid
,
508 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
509 ClassNameSize
, RequiredSize
,
513 /***********************************************************************
514 * SetupDiClassNameFromGuidW (SETUPAPI.@)
516 BOOL WINAPI
SetupDiClassNameFromGuidW(
517 const GUID
* ClassGuid
,
522 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
523 ClassNameSize
, RequiredSize
,
527 /***********************************************************************
528 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
530 BOOL WINAPI
SetupDiClassNameFromGuidExA(
531 const GUID
* ClassGuid
,
538 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
539 LPWSTR MachineNameW
= NULL
;
543 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
544 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
545 NULL
, MachineNameW
, Reserved
);
548 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
549 ClassNameSize
, NULL
, NULL
);
551 if (!ClassNameSize
&& RequiredSize
)
554 MyFree(MachineNameW
);
558 /***********************************************************************
559 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
561 BOOL WINAPI
SetupDiClassNameFromGuidExW(
562 const GUID
* ClassGuid
,
573 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
574 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
576 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
581 if (hKey
== INVALID_HANDLE_VALUE
)
586 if (RequiredSize
!= NULL
)
589 rc
= RegQueryValueExW(hKey
,
595 if (rc
!= ERROR_SUCCESS
)
602 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
605 dwLength
= ClassNameSize
* sizeof(WCHAR
);
606 rc
= RegQueryValueExW(hKey
,
612 if (rc
!= ERROR_SUCCESS
)
624 /***********************************************************************
625 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
628 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
631 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
634 /***********************************************************************
635 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
638 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
643 LPWSTR MachineNameW
= NULL
;
646 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
647 debugstr_a(MachineName
), Reserved
);
651 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
652 if (MachineNameW
== NULL
)
653 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
656 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
657 MachineNameW
, Reserved
);
660 MyFree(MachineNameW
);
666 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
670 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
671 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
672 case CR_SUCCESS
: return ERROR_SUCCESS
;
675 return ERROR_GEN_FAILURE
;
678 /* Does not happen */
681 /***********************************************************************
682 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
685 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
690 struct DeviceInfoSet
*list
;
691 LPWSTR UNCServerName
= NULL
;
695 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
697 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
698 debugstr_w(MachineName
), Reserved
);
700 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
702 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
703 list
= HeapAlloc(GetProcessHeap(), 0, size
);
706 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
709 memset(list
, 0, sizeof(struct DeviceInfoSet
));
711 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
714 ClassGuid
? ClassGuid
: &GUID_NULL
,
715 sizeof(list
->ClassGuid
));
716 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
717 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
718 list
->InstallParams
.hwndParent
= hwndParent
;
721 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
722 if (rc
!= ERROR_SUCCESS
)
727 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
730 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
734 strcpyW(UNCServerName
+ 2, MachineName
);
735 list
->szData
[0] = list
->szData
[1] = '\\';
736 strcpyW(list
->szData
+ 2, MachineName
);
737 list
->MachineName
= list
->szData
;
741 DWORD Size
= MAX_PATH
;
742 list
->HKLM
= HKEY_LOCAL_MACHINE
;
743 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
746 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
749 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
751 list
->MachineName
= NULL
;
754 UNCServerName
[0] = UNCServerName
[1] = '\\';
755 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
756 if (cr
!= CR_SUCCESS
)
758 SetLastError(GetErrorCodeFromCrCode(cr
));
762 InitializeListHead(&list
->DriverListHead
);
763 InitializeListHead(&list
->ListHead
);
765 ret
= (HDEVINFO
)list
;
768 if (ret
== INVALID_HANDLE_VALUE
)
770 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
771 RegCloseKey(list
->HKLM
);
772 HeapFree(GetProcessHeap(), 0, list
);
774 HeapFree(GetProcessHeap(), 0, UNCServerName
);
778 /***********************************************************************
779 * SetupDiEnumDeviceInfo (SETUPAPI.@)
781 BOOL WINAPI
SetupDiEnumDeviceInfo(
782 HDEVINFO DeviceInfoSet
,
784 PSP_DEVINFO_DATA DeviceInfoData
)
788 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
790 SetLastError(ERROR_INVALID_PARAMETER
);
791 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
793 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
795 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
796 SetLastError(ERROR_INVALID_HANDLE
);
797 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
798 SetLastError(ERROR_INVALID_USER_BUFFER
);
801 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
802 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
803 ItemList
= ItemList
->Flink
;
804 if (ItemList
== &list
->ListHead
)
805 SetLastError(ERROR_NO_MORE_ITEMS
);
808 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
809 memcpy(&DeviceInfoData
->ClassGuid
,
812 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
813 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
819 SetLastError(ERROR_INVALID_HANDLE
);
823 /***********************************************************************
824 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
826 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
828 PCSTR InfSectionName
,
829 PSTR InfSectionWithExt
,
830 DWORD InfSectionWithExtSize
,
834 LPWSTR InfSectionNameW
= NULL
;
835 PWSTR InfSectionWithExtW
= NULL
;
837 BOOL bResult
= FALSE
;
843 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
844 if (InfSectionNameW
== NULL
) goto end
;
846 if (InfSectionWithExt
)
848 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
849 if (InfSectionWithExtW
== NULL
) goto end
;
852 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
853 InfSectionWithExt
? InfSectionNameW
: NULL
,
854 InfSectionWithExtSize
, RequiredSize
,
855 Extension
? &ExtensionW
: NULL
);
857 if (bResult
&& InfSectionWithExt
)
859 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
860 InfSectionWithExtSize
, NULL
, NULL
) != 0;
862 if (bResult
&& Extension
)
864 if (ExtensionW
== NULL
)
867 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
871 if (InfSectionNameW
) MyFree(InfSectionNameW
);
872 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
877 /***********************************************************************
878 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
880 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
882 PCWSTR InfSectionName
,
883 PWSTR InfSectionWithExt
,
884 DWORD InfSectionWithExtSize
,
888 WCHAR szBuffer
[MAX_PATH
];
891 LONG lLineCount
= -1;
893 TRACE("%p %s %p %lu %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
894 InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
, Extension
);
896 lstrcpyW(szBuffer
, InfSectionName
);
897 dwLength
= lstrlenW(szBuffer
);
899 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
901 /* Test section name with '.NTx86' extension */
902 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
903 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
905 if (lLineCount
== -1)
907 /* Test section name with '.NT' extension */
908 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
909 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
914 /* Test section name with '.Win' extension */
915 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
916 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
919 if (lLineCount
== -1)
921 /* Test section name without extension */
922 szBuffer
[dwLength
] = 0;
923 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
926 if (lLineCount
== -1)
928 SetLastError(ERROR_INVALID_PARAMETER
);
932 dwFullLength
= lstrlenW(szBuffer
);
934 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
936 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
938 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
942 lstrcpyW(InfSectionWithExt
, szBuffer
);
943 if (Extension
!= NULL
)
945 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
949 if (RequiredSize
!= NULL
)
951 *RequiredSize
= dwFullLength
+ 1;
957 /***********************************************************************
958 * SetupDiGetClassDescriptionA (SETUPAPI.@)
960 BOOL WINAPI
SetupDiGetClassDescriptionA(
961 const GUID
* ClassGuid
,
962 PSTR ClassDescription
,
963 DWORD ClassDescriptionSize
,
966 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
967 ClassDescriptionSize
,
968 RequiredSize
, NULL
, NULL
);
971 /***********************************************************************
972 * SetupDiGetClassDescriptionW (SETUPAPI.@)
974 BOOL WINAPI
SetupDiGetClassDescriptionW(
975 const GUID
* ClassGuid
,
976 PWSTR ClassDescription
,
977 DWORD ClassDescriptionSize
,
980 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
981 ClassDescriptionSize
,
982 RequiredSize
, NULL
, NULL
);
985 /***********************************************************************
986 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
988 BOOL WINAPI
SetupDiGetClassDescriptionExA(
989 const GUID
* ClassGuid
,
990 PSTR ClassDescription
,
991 DWORD ClassDescriptionSize
,
996 PWCHAR ClassDescriptionW
;
997 LPWSTR MachineNameW
= NULL
;
1001 if (ClassDescriptionSize
> 0)
1003 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1004 if (!ClassDescriptionW
)
1006 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1012 ClassDescriptionW
= NULL
;
1016 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1019 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1025 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1026 NULL
, MachineNameW
, Reserved
);
1029 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1030 ClassDescriptionSize
, NULL
, NULL
);
1032 if (!ClassDescriptionSize
&& RequiredSize
)
1033 *RequiredSize
= len
;
1037 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1038 MyFree(MachineNameW
);
1042 /***********************************************************************
1043 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1045 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1046 const GUID
* ClassGuid
,
1047 PWSTR ClassDescription
,
1048 DWORD ClassDescriptionSize
,
1049 PDWORD RequiredSize
,
1056 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1057 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1059 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1064 if (hKey
== INVALID_HANDLE_VALUE
)
1066 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1070 if (RequiredSize
!= NULL
)
1073 if (RegQueryValueExW(hKey
,
1084 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1087 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1088 if (RegQueryValueExW(hKey
,
1092 (LPBYTE
)ClassDescription
,
1104 /***********************************************************************
1105 * SetupDiGetClassDevsA (SETUPAPI.@)
1107 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1113 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1114 flags
, NULL
, NULL
, NULL
);
1117 /***********************************************************************
1118 * SetupDiGetClassDevsW (SETUPAPI.@)
1120 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1126 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1127 flags
, NULL
, NULL
, NULL
);
1130 /***********************************************************************
1131 * SetupDiGetClassDevsExA (SETUPAPI.@)
1133 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1143 LPWSTR enumstrW
= NULL
;
1144 LPWSTR machineW
= NULL
;
1148 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1149 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1152 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1155 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1159 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1160 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1163 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1166 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1168 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1171 HeapFree(GetProcessHeap(), 0, enumstrW
);
1172 HeapFree(GetProcessHeap(), 0, machineW
);
1177 CreateDeviceInfoElement(
1178 IN
struct DeviceInfoSet
*list
,
1179 IN LPCWSTR InstancePath
,
1180 IN LPCGUID pClassGuid
,
1181 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1185 struct DeviceInfoElement
*deviceInfo
;
1187 *pDeviceInfo
= NULL
;
1189 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (wcslen(InstancePath
) + 1) * sizeof(WCHAR
);
1190 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1193 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1196 memset(deviceInfo
, 0, size
);
1198 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1199 if (cr
!= CR_SUCCESS
)
1201 SetLastError(GetErrorCodeFromCrCode(cr
));
1205 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1206 wcscpy(deviceInfo
->Data
, InstancePath
);
1207 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1208 deviceInfo
->UniqueId
= wcsrchr(deviceInfo
->Data
, '\\');
1209 deviceInfo
->DeviceDescription
= NULL
;
1210 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1211 deviceInfo
->CreationFlags
= 0;
1212 InitializeListHead(&deviceInfo
->DriverListHead
);
1213 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1215 *pDeviceInfo
= deviceInfo
;
1220 CreateDeviceInterface(
1221 IN
struct DeviceInfoElement
* deviceInfo
,
1222 IN LPCWSTR SymbolicLink
,
1223 IN LPCGUID pInterfaceGuid
,
1224 OUT
struct DeviceInterface
**pDeviceInterface
)
1226 struct DeviceInterface
*deviceInterface
;
1228 *pDeviceInterface
= NULL
;
1230 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1231 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (wcslen(SymbolicLink
) + 1) * sizeof(WCHAR
));
1232 if (!deviceInterface
)
1234 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1237 deviceInterface
->DeviceInfo
= deviceInfo
;
1238 wcscpy(deviceInterface
->SymbolicLink
, SymbolicLink
);
1239 deviceInterface
->Flags
= 0; /* FIXME */
1240 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1242 *pDeviceInterface
= deviceInterface
;
1246 static LONG
SETUP_CreateDevListFromEnumerator(
1247 struct DeviceInfoSet
*list
,
1248 LPCGUID pClassGuid OPTIONAL
,
1250 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1252 HKEY hDeviceIdKey
, hInstanceIdKey
;
1253 WCHAR KeyBuffer
[MAX_PATH
];
1254 WCHAR InstancePath
[MAX_PATH
];
1255 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1256 struct DeviceInfoElement
*deviceInfo
;
1258 DWORD dwLength
, dwRegType
;
1261 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1264 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1265 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1266 if (rc
== ERROR_NO_MORE_ITEMS
)
1268 if (rc
!= ERROR_SUCCESS
)
1272 /* Open device id sub key */
1273 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1274 if (rc
!= ERROR_SUCCESS
)
1276 wcscpy(InstancePath
, Enumerator
);
1277 wcscat(InstancePath
, L
"\\");
1278 wcscat(InstancePath
, KeyBuffer
);
1279 wcscat(InstancePath
, L
"\\");
1280 pEndOfInstancePath
= &InstancePath
[wcslen(InstancePath
)];
1282 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1288 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1289 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1290 if (rc
== ERROR_NO_MORE_ITEMS
)
1292 if (rc
!= ERROR_SUCCESS
)
1294 RegCloseKey(hDeviceIdKey
);
1299 /* Open instance id sub key */
1300 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1301 if (rc
!= ERROR_SUCCESS
)
1303 RegCloseKey(hDeviceIdKey
);
1306 *pEndOfInstancePath
= '\0';
1307 wcscat(InstancePath
, KeyBuffer
);
1309 /* Read ClassGUID value */
1310 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1311 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1312 RegCloseKey(hInstanceIdKey
);
1313 if (rc
== ERROR_FILE_NOT_FOUND
)
1316 /* Skip this bad entry as we can't verify it */
1318 /* Set a default GUID for this device */
1319 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1321 else if (rc
!= ERROR_SUCCESS
)
1323 RegCloseKey(hDeviceIdKey
);
1326 else if (dwRegType
!= REG_SZ
)
1328 RegCloseKey(hDeviceIdKey
);
1329 return ERROR_GEN_FAILURE
;
1333 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1334 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1335 /* Bad GUID, skip the entry */
1339 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1341 /* Skip this entry as it is not the right device class */
1345 /* Add the entry to the list */
1346 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1348 RegCloseKey(hDeviceIdKey
);
1349 return GetLastError();
1351 TRACE("Adding '%S' to device info set %p\n", InstancePath
, list
);
1352 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1354 RegCloseKey(hDeviceIdKey
);
1357 return ERROR_SUCCESS
;
1360 static LONG
SETUP_CreateDevList(
1361 struct DeviceInfoSet
*list
,
1362 PCWSTR MachineName OPTIONAL
,
1363 LPGUID
class OPTIONAL
,
1364 PCWSTR Enumerator OPTIONAL
)
1366 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1367 WCHAR KeyBuffer
[MAX_PATH
];
1372 if (class && IsEqualIID(class, &GUID_NULL
))
1376 if (MachineName
!= NULL
)
1378 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1379 if (rc
!= ERROR_SUCCESS
)
1383 HKLM
= HKEY_LOCAL_MACHINE
;
1385 rc
= RegOpenKeyExW(HKLM
,
1386 REGSTR_PATH_SYSTEMENUM
,
1388 KEY_ENUMERATE_SUB_KEYS
,
1390 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1391 if (rc
!= ERROR_SUCCESS
)
1394 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1395 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1404 KEY_ENUMERATE_SUB_KEYS
,
1406 RegCloseKey(hEnumKey
);
1407 if (rc
!= ERROR_SUCCESS
)
1409 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1410 RegCloseKey(hEnumeratorKey
);
1415 /* Enumerate enumerators */
1419 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1420 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1421 if (rc
== ERROR_NO_MORE_ITEMS
)
1423 if (rc
!= ERROR_SUCCESS
)
1425 RegCloseKey(hEnumKey
);
1431 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1432 if (rc
!= ERROR_SUCCESS
)
1434 RegCloseKey(hEnumKey
);
1438 /* Call SETUP_CreateDevListFromEnumerator */
1439 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1440 RegCloseKey(hEnumeratorKey
);
1441 if (rc
!= ERROR_SUCCESS
)
1443 RegCloseKey(hEnumKey
);
1447 RegCloseKey(hEnumKey
);
1448 return ERROR_SUCCESS
;
1453 static LONG
SETUP_CreateSerialDeviceList(
1454 struct DeviceInfoSet
*list
,
1456 LPGUID InterfaceGuid
,
1457 PCWSTR DeviceInstanceW
)
1459 static const size_t initialSize
= 100;
1461 WCHAR buf
[initialSize
];
1463 static const WCHAR devicePrefixW
[] = { 'C','O','M',0 };
1465 struct DeviceInfoElement
*deviceInfo
;
1468 WARN("'MachineName' is ignored on Wine!\n");
1469 if (DeviceInstanceW
)
1470 WARN("'DeviceInstanceW' can't be set on Wine!\n");
1476 if (QueryDosDeviceW(NULL
, devices
, size
) != 0)
1478 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1482 HeapFree(GetProcessHeap(), 0, devices
);
1483 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
1485 return ERROR_NOT_ENOUGH_MEMORY
;
1491 HeapFree(GetProcessHeap(), 0, devices
);
1492 return GetLastError();
1496 /* 'devices' is a MULTI_SZ string */
1497 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
1499 if (strncmpW(devicePrefixW
, ptr
, sizeof(devicePrefixW
) / sizeof(devicePrefixW
[0]) - 1) == 0)
1501 /* We have found a device */
1502 struct DeviceInterface
*interfaceInfo
;
1503 TRACE("Adding %s to list\n", debugstr_w(ptr
));
1504 /* Step 1. Create a device info element */
1505 if (!CreateDeviceInfoElement(list
, ptr
, &GUID_SERENUM_BUS_ENUMERATOR
, &deviceInfo
))
1508 HeapFree(GetProcessHeap(), 0, devices
);
1509 return GetLastError();
1511 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1513 /* Step 2. Create an interface list for this element */
1514 if (!CreateDeviceInterface(deviceInfo
, ptr
, InterfaceGuid
, &interfaceInfo
))
1517 HeapFree(GetProcessHeap(), 0, devices
);
1518 return GetLastError();
1520 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1524 HeapFree(GetProcessHeap(), 0, devices
);
1525 return ERROR_SUCCESS
;
1528 #else /* __REACTOS__ */
1530 static LONG
SETUP_CreateInterfaceList(
1531 struct DeviceInfoSet
*list
,
1533 LPGUID InterfaceGuid
,
1534 PCWSTR DeviceInstanceW
/* OPTIONAL */)
1536 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1537 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1538 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1539 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1540 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1542 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1545 DWORD dwLength
, dwInstancePathLength
;
1548 struct DeviceInfoElement
*deviceInfo
;
1550 /* Open registry key related to this interface */
1551 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1552 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1553 return GetLastError();
1555 /* Enumerate sub keys of hInterfaceKey */
1559 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1560 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1561 if (rc
== ERROR_NO_MORE_ITEMS
)
1563 if (rc
!= ERROR_SUCCESS
)
1565 RegCloseKey(hInterfaceKey
);
1571 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1572 if (rc
!= ERROR_SUCCESS
)
1574 RegCloseKey(hInterfaceKey
);
1578 /* Read DeviceInstance */
1579 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1580 if (rc
!= ERROR_SUCCESS
)
1582 RegCloseKey(hDeviceInstanceKey
);
1583 RegCloseKey(hInterfaceKey
);
1586 if (dwRegType
!= REG_SZ
)
1588 RegCloseKey(hDeviceInstanceKey
);
1589 RegCloseKey(hInterfaceKey
);
1590 return ERROR_GEN_FAILURE
;
1592 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1595 RegCloseKey(hDeviceInstanceKey
);
1596 RegCloseKey(hInterfaceKey
);
1597 return ERROR_NOT_ENOUGH_MEMORY
;
1599 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1600 if (rc
!= ERROR_SUCCESS
)
1602 HeapFree(GetProcessHeap(), 0, InstancePath
);
1603 RegCloseKey(hDeviceInstanceKey
);
1604 RegCloseKey(hInterfaceKey
);
1607 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1608 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1610 if (DeviceInstanceW
)
1612 /* Check if device enumerator is not the right one */
1613 if (wcscmp(DeviceInstanceW
, InstancePath
) != 0)
1615 HeapFree(GetProcessHeap(), 0, InstancePath
);
1616 RegCloseKey(hDeviceInstanceKey
);
1621 /* Find class GUID associated to the device instance */
1624 REGSTR_PATH_SYSTEMENUM
,
1628 if (rc
!= ERROR_SUCCESS
)
1630 HeapFree(GetProcessHeap(), 0, InstancePath
);
1631 RegCloseKey(hDeviceInstanceKey
);
1632 RegCloseKey(hInterfaceKey
);
1641 RegCloseKey(hEnumKey
);
1642 if (rc
!= ERROR_SUCCESS
)
1644 HeapFree(GetProcessHeap(), 0, InstancePath
);
1645 RegCloseKey(hDeviceInstanceKey
);
1646 RegCloseKey(hInterfaceKey
);
1649 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1650 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1652 if (rc
!= ERROR_SUCCESS
)
1654 HeapFree(GetProcessHeap(), 0, InstancePath
);
1655 RegCloseKey(hDeviceInstanceKey
);
1656 RegCloseKey(hInterfaceKey
);
1659 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1660 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1661 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1663 HeapFree(GetProcessHeap(), 0, InstancePath
);
1664 RegCloseKey(hDeviceInstanceKey
);
1665 RegCloseKey(hInterfaceKey
);
1666 return ERROR_GEN_FAILURE
;
1668 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1670 /* If current device doesn't match the list GUID (if any), skip this entry */
1671 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1673 HeapFree(GetProcessHeap(), 0, InstancePath
);
1674 RegCloseKey(hDeviceInstanceKey
);
1678 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1682 LPWSTR pSymbolicLink
;
1683 struct DeviceInterface
*interfaceInfo
;
1685 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1686 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1687 if (rc
== ERROR_NO_MORE_ITEMS
)
1689 if (rc
!= ERROR_SUCCESS
)
1691 HeapFree(GetProcessHeap(), 0, InstancePath
);
1692 RegCloseKey(hDeviceInstanceKey
);
1693 RegCloseKey(hInterfaceKey
);
1697 if (KeyBuffer
[0] != '#')
1698 /* This entry doesn't represent an interesting entry */
1702 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1703 if (rc
!= ERROR_SUCCESS
)
1705 RegCloseKey(hDeviceInstanceKey
);
1706 RegCloseKey(hInterfaceKey
);
1710 /* Read SymbolicLink value */
1711 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1712 if (rc
!= ERROR_SUCCESS
)
1714 RegCloseKey(hReferenceKey
);
1715 RegCloseKey(hDeviceInstanceKey
);
1716 RegCloseKey(hInterfaceKey
);
1719 if (dwRegType
!= REG_SZ
)
1721 RegCloseKey(hReferenceKey
);
1722 RegCloseKey(hDeviceInstanceKey
);
1723 RegCloseKey(hInterfaceKey
);
1724 return ERROR_GEN_FAILURE
;
1727 /* We have found a device */
1728 /* Step 1. Create a device info element */
1729 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1731 RegCloseKey(hReferenceKey
);
1732 RegCloseKey(hDeviceInstanceKey
);
1733 RegCloseKey(hInterfaceKey
);
1734 return GetLastError();
1736 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1737 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1739 /* Step 2. Create an interface list for this element */
1740 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1743 RegCloseKey(hReferenceKey
);
1744 RegCloseKey(hDeviceInstanceKey
);
1745 RegCloseKey(hInterfaceKey
);
1746 return ERROR_NOT_ENOUGH_MEMORY
;
1748 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1749 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1750 RegCloseKey(hReferenceKey
);
1751 if (rc
!= ERROR_SUCCESS
)
1753 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1754 RegCloseKey(hDeviceInstanceKey
);
1755 RegCloseKey(hInterfaceKey
);
1758 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1760 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1761 RegCloseKey(hDeviceInstanceKey
);
1762 RegCloseKey(hInterfaceKey
);
1763 return GetLastError();
1765 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1766 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1767 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1769 RegCloseKey(hDeviceInstanceKey
);
1771 RegCloseKey(hInterfaceKey
);
1772 return ERROR_SUCCESS
;
1774 #endif /* __REACTOS__ */
1776 /***********************************************************************
1777 * SetupDiGetClassDevsExW (SETUPAPI.@)
1779 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1788 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1789 struct DeviceInfoSet
*list
;
1793 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1794 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1796 /* Create the deviceset if not set */
1799 list
= (struct DeviceInfoSet
*)deviceset
;
1800 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1802 SetLastError(ERROR_INVALID_HANDLE
);
1803 return INVALID_HANDLE_VALUE
;
1805 hDeviceInfo
= deviceset
;
1809 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1810 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1811 NULL
, machine
, NULL
);
1812 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1813 return INVALID_HANDLE_VALUE
;
1814 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1817 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1820 pClassGuid
= &list
->ClassGuid
;
1822 if (flags
& DIGCF_PRESENT
)
1823 FIXME(": flag DIGCF_PRESENT ignored\n");
1824 if (flags
& DIGCF_PROFILE
)
1825 FIXME(": flag DIGCF_PROFILE ignored\n");
1827 if (flags
& DIGCF_ALLCLASSES
)
1829 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1830 if (rc
!= ERROR_SUCCESS
)
1834 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1835 return INVALID_HANDLE_VALUE
;
1839 else if (flags
& DIGCF_DEVICEINTERFACE
)
1843 SetLastError(ERROR_INVALID_PARAMETER
);
1845 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1846 return INVALID_HANDLE_VALUE
;
1850 /* Special case: find serial ports by calling QueryDosDevice */
1851 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
1852 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1853 if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
1854 rc
= SETUP_CreateSerialDeviceList(list
, machine
, (LPGUID
)class, enumstr
);
1857 ERR("Wine can only enumerate serial devices at the moment!\n");
1858 rc
= ERROR_INVALID_PARAMETER
;
1860 #else /* __REACTOS__ */
1861 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
);
1862 #endif /* __REACTOS__ */
1863 if (rc
!= ERROR_SUCCESS
)
1867 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1868 return INVALID_HANDLE_VALUE
;
1874 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1875 if (rc
!= ERROR_SUCCESS
)
1879 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1880 return INVALID_HANDLE_VALUE
;
1886 /***********************************************************************
1887 * SetupDiGetClassImageIndex (SETUPAPI.@)
1890 static BOOL
GetIconIndex(
1892 OUT PINT ImageIndex
)
1894 LPWSTR Buffer
= NULL
;
1895 DWORD dwRegType
, dwLength
;
1899 /* Read icon registry key */
1900 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
1901 if (rc
!= ERROR_SUCCESS
)
1905 } else if (dwRegType
!= REG_SZ
)
1907 SetLastError(ERROR_INVALID_INDEX
);
1910 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
1913 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1916 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
1917 if (rc
!= ERROR_SUCCESS
)
1922 /* make sure the returned buffer is NULL-terminated */
1923 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
1925 /* Transform icon value to a INT */
1926 *ImageIndex
= atoiW(Buffer
);
1934 BOOL WINAPI
SetupDiGetClassImageIndex(
1935 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1936 IN CONST GUID
*ClassGuid
,
1937 OUT PINT ImageIndex
)
1939 struct ClassImageList
*list
;
1942 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
1944 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
1945 SetLastError(ERROR_INVALID_PARAMETER
);
1946 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
1947 SetLastError(ERROR_INVALID_USER_BUFFER
);
1948 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
1949 SetLastError(ERROR_INVALID_USER_BUFFER
);
1950 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
1951 SetLastError(ERROR_INVALID_USER_BUFFER
);
1952 else if (!ImageIndex
)
1953 SetLastError(ERROR_INVALID_PARAMETER
);
1956 HKEY hKey
= INVALID_HANDLE_VALUE
;
1959 /* Read Icon registry entry into Buffer */
1960 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
1961 if (hKey
== INVALID_HANDLE_VALUE
)
1963 if (!GetIconIndex(hKey
, &iconIndex
))
1968 SetLastError(ERROR_INVALID_INDEX
);
1972 *ImageIndex
= -iconIndex
;
1976 if (hKey
!= INVALID_HANDLE_VALUE
)
1980 TRACE("Returning %d\n", ret
);
1984 /***********************************************************************
1985 * SetupDiGetClassImageList(SETUPAPI.@)
1987 BOOL WINAPI
SetupDiGetClassImageList(
1988 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
1990 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
1993 /***********************************************************************
1994 * SetupDiGetClassImageListExA(SETUPAPI.@)
1996 BOOL WINAPI
SetupDiGetClassImageListExA(
1997 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
1998 IN PCSTR MachineName OPTIONAL
,
2001 PWSTR MachineNameW
= NULL
;
2006 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2007 if (MachineNameW
== NULL
)
2011 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2014 MyFree(MachineNameW
);
2019 /***********************************************************************
2020 * SetupDiGetClassImageListExW(SETUPAPI.@)
2022 BOOL WINAPI
SetupDiGetClassImageListExW(
2023 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2024 IN PCWSTR MachineName OPTIONAL
,
2029 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2031 if (!ClassImageListData
)
2032 SetLastError(ERROR_INVALID_PARAMETER
);
2033 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2034 SetLastError(ERROR_INVALID_USER_BUFFER
);
2036 SetLastError(ERROR_INVALID_PARAMETER
);
2039 struct ClassImageList
*list
= NULL
;
2042 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2044 size
+= (wcslen(MachineName
) + 3) * sizeof(WCHAR
);
2045 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2048 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2051 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2054 list
->szData
[0] = list
->szData
[1] = '\\';
2055 strcpyW(list
->szData
+ 2, MachineName
);
2056 list
->MachineName
= list
->szData
;
2060 list
->MachineName
= NULL
;
2063 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2071 TRACE("Returning %d\n", ret
);
2075 /***********************************************************************
2076 * SetupDiLoadClassIcon(SETUPAPI.@)
2078 BOOL WINAPI
SetupDiLoadClassIcon(
2079 IN CONST GUID
*ClassGuid
,
2080 OUT HICON
*LargeIcon OPTIONAL
,
2081 OUT PINT MiniIconIndex OPTIONAL
)
2086 SetLastError(ERROR_INVALID_PARAMETER
);
2089 LPWSTR Buffer
= NULL
;
2092 HKEY hKey
= INVALID_HANDLE_VALUE
;
2094 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2095 if (hKey
== INVALID_HANDLE_VALUE
)
2098 if (!GetIconIndex(hKey
, &iconIndex
))
2103 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2106 DWORD dwRegType
, dwLength
;
2107 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2108 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2110 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2113 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2116 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2117 if (rc
!= ERROR_SUCCESS
)
2122 /* make sure the returned buffer is NULL-terminated */
2123 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2126 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2127 && dwRegType
== REG_SZ
)
2129 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2132 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2135 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2136 if (rc
!= ERROR_SUCCESS
)
2141 /* make sure the returned buffer is NULL-terminated */
2142 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2146 /* Unable to find where to load the icon */
2147 SetLastError(ERROR_FILE_NOT_FOUND
);
2150 Comma
= strchrW(Buffer
, ',');
2153 SetLastError(ERROR_GEN_FAILURE
);
2161 /* Look up icon in setupapi.dll */
2162 DllName
= L
"setupapi.dll";
2163 iconIndex
= -iconIndex
;
2166 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2169 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2171 SetLastError(ERROR_INVALID_INDEX
);
2176 *MiniIconIndex
= iconIndex
;
2180 if (hKey
!= INVALID_HANDLE_VALUE
)
2185 TRACE("Returning %d\n", ret
);
2189 /***********************************************************************
2190 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2192 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2193 HDEVINFO DeviceInfoSet
,
2194 PSP_DEVINFO_DATA DeviceInfoData
,
2195 CONST GUID
* InterfaceClassGuid
,
2197 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2201 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2202 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2204 if (!DeviceInterfaceData
)
2205 SetLastError(ERROR_INVALID_PARAMETER
);
2206 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2207 SetLastError(ERROR_INVALID_USER_BUFFER
);
2208 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2210 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2212 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2214 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2216 while (ItemList
!= &list
->ListHead
&& !Found
)
2218 PLIST_ENTRY InterfaceListEntry
;
2219 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2220 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2222 /* We are not searching for this element */
2223 ItemList
= ItemList
->Flink
;
2226 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2227 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2229 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2230 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2232 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2235 if (MemberIndex
-- == 0)
2237 /* return this item */
2238 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2239 &DevItf
->InterfaceClassGuid
,
2241 DeviceInterfaceData
->Flags
= 0; /* FIXME */
2242 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2245 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2247 ItemList
= ItemList
->Flink
;
2250 SetLastError(ERROR_NO_MORE_ITEMS
);
2255 SetLastError(ERROR_INVALID_HANDLE
);
2258 SetLastError(ERROR_INVALID_HANDLE
);
2262 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2264 InterlockedIncrement(&infFile
->References
);
2267 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2269 if (InterlockedDecrement(&infFile
->References
) == 0)
2271 SetupCloseInfFile(infFile
->hInf
);
2272 HeapFree(GetProcessHeap(), 0, infFile
);
2276 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2278 DereferenceInfFile(driverInfo
->InfFileDetails
);
2279 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2280 HeapFree(GetProcessHeap(), 0, driverInfo
);
2284 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2286 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2290 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2292 PLIST_ENTRY ListEntry
;
2293 struct DriverInfoElement
*driverInfo
;
2295 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2297 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2298 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
2299 if (!DestroyDriverInfoElement(driverInfo
))
2302 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2304 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2305 HeapFree(GetProcessHeap(), 0, ListEntry
);
2307 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2308 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2312 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2314 PLIST_ENTRY ListEntry
;
2315 struct DeviceInfoElement
*deviceInfo
;
2317 while (!IsListEmpty(&list
->ListHead
))
2319 ListEntry
= RemoveHeadList(&list
->ListHead
);
2320 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2321 if (!DestroyDeviceInfoElement(deviceInfo
))
2324 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2325 RegCloseKey(list
->HKLM
);
2326 CM_Disconnect_Machine(list
->hMachine
);
2327 DestroyClassInstallParams(&list
->ClassInstallParams
);
2328 HeapFree(GetProcessHeap(), 0, list
);
2332 /***********************************************************************
2333 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2335 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2339 TRACE("%p\n", devinfo
);
2340 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2342 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2344 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2345 ret
= DestroyDeviceInfoSet(list
);
2347 SetLastError(ERROR_INVALID_HANDLE
);
2350 SetLastError(ERROR_INVALID_HANDLE
);
2352 TRACE("Returning %d\n", ret
);
2356 /***********************************************************************
2357 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2359 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2360 HDEVINFO DeviceInfoSet
,
2361 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2362 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2363 DWORD DeviceInterfaceDetailDataSize
,
2364 PDWORD RequiredSize
,
2365 PSP_DEVINFO_DATA DeviceInfoData
)
2367 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2368 DWORD sizeW
= 0, sizeA
;
2371 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2372 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2373 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2375 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2376 SetLastError(ERROR_INVALID_USER_BUFFER
);
2377 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2378 SetLastError(ERROR_INVALID_PARAMETER
);
2379 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2380 SetLastError(ERROR_INVALID_PARAMETER
);
2383 if (DeviceInterfaceDetailData
!= NULL
)
2385 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2386 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2387 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2388 if (!DeviceInterfaceDetailDataW
)
2390 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2393 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2395 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2396 ret
= SetupDiGetDeviceInterfaceDetailW(
2398 DeviceInterfaceData
,
2399 DeviceInterfaceDetailDataW
,
2403 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2404 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2406 *RequiredSize
= sizeA
;
2407 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2409 if (!WideCharToMultiByte(
2411 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2412 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2419 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2422 TRACE("Returning %d\n", ret
);
2426 /***********************************************************************
2427 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2429 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2430 HDEVINFO DeviceInfoSet
,
2431 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2432 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2433 DWORD DeviceInterfaceDetailDataSize
,
2434 PDWORD RequiredSize
,
2435 PSP_DEVINFO_DATA DeviceInfoData
)
2439 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2440 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2441 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2443 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2444 SetLastError(ERROR_INVALID_PARAMETER
);
2445 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2446 SetLastError(ERROR_INVALID_HANDLE
);
2447 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2448 SetLastError(ERROR_INVALID_HANDLE
);
2449 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2450 SetLastError(ERROR_INVALID_USER_BUFFER
);
2451 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2452 SetLastError(ERROR_INVALID_USER_BUFFER
);
2453 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2454 SetLastError(ERROR_INVALID_USER_BUFFER
);
2455 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2456 SetLastError(ERROR_INVALID_PARAMETER
);
2457 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2458 SetLastError(ERROR_INVALID_PARAMETER
);
2461 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2462 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2463 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2464 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2466 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2468 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2470 *RequiredSize
= sizeRequired
;
2474 wcscpy(DeviceInterfaceDetailData
->DevicePath
, devName
);
2475 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2478 memcpy(&DeviceInfoData
->ClassGuid
,
2479 &deviceInterface
->DeviceInfo
->ClassGuid
,
2481 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2482 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2488 TRACE("Returning %d\n", ret
);
2492 /***********************************************************************
2493 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2495 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2497 PSP_DEVINFO_DATA DeviceInfoData
,
2499 PDWORD PropertyRegDataType
,
2500 PBYTE PropertyBuffer
,
2501 DWORD PropertyBufferSize
,
2502 PDWORD RequiredSize
)
2505 BOOL bIsStringProperty
;
2507 DWORD RequiredSizeA
, RequiredSizeW
;
2508 DWORD PropertyBufferSizeW
;
2509 PBYTE PropertyBufferW
;
2511 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2512 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2515 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2516 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2518 bResult
= SetupDiGetDeviceRegistryPropertyW(
2524 PropertyBufferSizeW
,
2527 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2529 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2531 if (bIsStringProperty
)
2532 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2534 RequiredSizeA
= RequiredSizeW
;
2536 *RequiredSize
= RequiredSizeA
;
2537 if (PropertyRegDataType
)
2538 *PropertyRegDataType
= RegType
;
2543 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2547 if (RequiredSizeA
<= PropertyBufferSize
)
2549 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2551 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2553 /* Last error is already set by WideCharToMultiByte */
2558 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2562 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2566 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2570 /***********************************************************************
2571 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2573 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2574 HDEVINFO DeviceInfoSet
,
2575 PSP_DEVINFO_DATA DeviceInfoData
,
2577 PDWORD PropertyRegDataType
,
2578 PBYTE PropertyBuffer
,
2579 DWORD PropertyBufferSize
,
2580 PDWORD RequiredSize
)
2582 HKEY hEnumKey
, hKey
;
2586 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2587 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2590 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2591 SetLastError(ERROR_INVALID_HANDLE
);
2592 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2593 SetLastError(ERROR_INVALID_HANDLE
);
2594 else if (!DeviceInfoData
)
2595 SetLastError(ERROR_INVALID_PARAMETER
);
2596 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2597 SetLastError(ERROR_INVALID_USER_BUFFER
);
2598 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2599 SetLastError(ERROR_INVALID_PARAMETER
);
2602 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2603 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2607 case SPDRP_CAPABILITIES
:
2609 case SPDRP_CLASSGUID
:
2610 case SPDRP_COMPATIBLEIDS
:
2611 case SPDRP_CONFIGFLAGS
:
2612 case SPDRP_DEVICEDESC
:
2614 case SPDRP_FRIENDLYNAME
:
2615 case SPDRP_HARDWAREID
:
2616 case SPDRP_LOCATION_INFORMATION
:
2617 case SPDRP_LOWERFILTERS
:
2619 case SPDRP_SECURITY
:
2621 case SPDRP_UI_NUMBER
:
2622 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2623 case SPDRP_UPPERFILTERS
:
2625 LPCWSTR RegistryPropertyName
;
2630 case SPDRP_CAPABILITIES
:
2631 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2633 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2634 case SPDRP_CLASSGUID
:
2635 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2636 case SPDRP_COMPATIBLEIDS
:
2637 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2638 case SPDRP_CONFIGFLAGS
:
2639 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2640 case SPDRP_DEVICEDESC
:
2641 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2643 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2644 case SPDRP_FRIENDLYNAME
:
2645 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2646 case SPDRP_HARDWAREID
:
2647 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2648 case SPDRP_LOCATION_INFORMATION
:
2649 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2650 case SPDRP_LOWERFILTERS
:
2651 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2653 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2654 case SPDRP_SECURITY
:
2655 RegistryPropertyName
= L
"Security"; break;
2657 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2658 case SPDRP_UI_NUMBER
:
2659 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2660 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2661 RegistryPropertyName
= L
"UINumberDescFormat"; break;
2662 case SPDRP_UPPERFILTERS
:
2663 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2665 /* Should not happen */
2666 RegistryPropertyName
= NULL
; break;
2669 /* Open registry key name */
2672 REGSTR_PATH_SYSTEMENUM
,
2676 if (rc
!= ERROR_SUCCESS
)
2687 RegCloseKey(hEnumKey
);
2688 if (rc
!= ERROR_SUCCESS
)
2693 /* Read registry entry */
2694 BufferSize
= PropertyBufferSize
;
2695 rc
= RegQueryValueExW(
2697 RegistryPropertyName
,
2698 NULL
, /* Reserved */
2699 PropertyRegDataType
,
2703 *RequiredSize
= BufferSize
;
2706 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2709 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2711 case ERROR_MORE_DATA
:
2712 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2721 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2723 DWORD required
= (wcslen(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2725 if (PropertyRegDataType
)
2726 *PropertyRegDataType
= REG_SZ
;
2728 *RequiredSize
= required
;
2729 if (PropertyBufferSize
>= required
)
2731 wcscpy((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2735 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2739 /*case SPDRP_BUSTYPEGUID:
2740 case SPDRP_LEGACYBUSTYPE:
2741 case SPDRP_BUSNUMBER:
2742 case SPDRP_ENUMERATOR_NAME:
2743 case SPDRP_SECURITY_SDS:
2745 case SPDRP_EXCLUSIVE:
2746 case SPDRP_CHARACTERISTICS:
2748 case SPDRP_DEVICE_POWER_DATA:*/
2749 #if (WINVER >= 0x501)
2750 /*case SPDRP_REMOVAL_POLICY:
2751 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2752 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2753 case SPDRP_INSTALL_STATE:*/
2758 ERR("Property 0x%lx not implemented\n", Property
);
2759 SetLastError(ERROR_NOT_SUPPORTED
);
2764 TRACE("Returning %d\n", ret
);
2768 /***********************************************************************
2769 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2771 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2772 IN HDEVINFO DeviceInfoSet
,
2773 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2775 IN CONST BYTE
*PropertyBuffer
,
2776 IN DWORD PropertyBufferSize
)
2778 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2779 Property
, PropertyBuffer
, PropertyBufferSize
);
2780 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2784 /***********************************************************************
2785 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2787 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2788 IN HDEVINFO DeviceInfoSet
,
2789 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2791 IN
const BYTE
*PropertyBuffer
,
2792 IN DWORD PropertyBufferSize
)
2794 struct DeviceInfoSet
*list
;
2797 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2798 Property
, PropertyBuffer
, PropertyBufferSize
);
2801 SetLastError(ERROR_INVALID_HANDLE
);
2802 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2803 SetLastError(ERROR_INVALID_HANDLE
);
2804 else if (!DeviceInfoData
)
2805 SetLastError(ERROR_INVALID_HANDLE
);
2806 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2807 SetLastError(ERROR_INVALID_USER_BUFFER
);
2812 case SPDRP_COMPATIBLEIDS
:
2813 case SPDRP_CONFIGFLAGS
:
2814 case SPDRP_FRIENDLYNAME
:
2815 case SPDRP_HARDWAREID
:
2816 case SPDRP_LOCATION_INFORMATION
:
2817 case SPDRP_LOWERFILTERS
:
2818 case SPDRP_SECURITY
:
2820 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2821 case SPDRP_UPPERFILTERS
:
2823 LPCWSTR RegistryPropertyName
;
2824 DWORD RegistryDataType
;
2830 case SPDRP_COMPATIBLEIDS
:
2831 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2832 RegistryDataType
= REG_MULTI_SZ
;
2834 case SPDRP_CONFIGFLAGS
:
2835 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2836 RegistryDataType
= REG_DWORD
;
2838 case SPDRP_FRIENDLYNAME
:
2839 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2840 RegistryDataType
= REG_SZ
;
2842 case SPDRP_HARDWAREID
:
2843 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2844 RegistryDataType
= REG_MULTI_SZ
;
2846 case SPDRP_LOCATION_INFORMATION
:
2847 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2848 RegistryDataType
= REG_SZ
;
2850 case SPDRP_LOWERFILTERS
:
2851 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2852 RegistryDataType
= REG_MULTI_SZ
;
2854 case SPDRP_SECURITY
:
2855 RegistryPropertyName
= L
"Security";
2856 RegistryDataType
= REG_BINARY
;
2859 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2860 RegistryDataType
= REG_SZ
;
2862 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2863 RegistryPropertyName
= L
"UINumberDescFormat";
2864 RegistryDataType
= REG_SZ
;
2866 case SPDRP_UPPERFILTERS
:
2867 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
2868 RegistryDataType
= REG_MULTI_SZ
;
2871 /* Should not happen */
2872 RegistryPropertyName
= NULL
;
2873 RegistryDataType
= REG_BINARY
;
2876 /* Open device registry key */
2877 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2878 if (hKey
!= INVALID_HANDLE_VALUE
)
2880 /* Write new data */
2881 rc
= RegSetValueExW(
2883 RegistryPropertyName
,
2887 PropertyBufferSize
);
2888 if (rc
== ERROR_SUCCESS
)
2897 /*case SPDRP_CHARACTERISTICS:
2899 case SPDRP_EXCLUSIVE:*/
2900 #if (WINVER >= 0x501)
2901 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2903 //case SPDRP_SECURITY_SDS:
2907 ERR("Property 0x%lx not implemented\n", Property
);
2908 SetLastError(ERROR_NOT_SUPPORTED
);
2913 TRACE("Returning %d\n", ret
);
2918 /***********************************************************************
2919 * SetupDiInstallClassA (SETUPAPI.@)
2921 BOOL WINAPI
SetupDiInstallClassA(
2922 IN HWND hwndParent OPTIONAL
,
2923 IN PCSTR InfFileName
,
2925 IN HSPFILEQ FileQueue OPTIONAL
)
2927 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
2931 /***********************************************************************
2932 * SetupDiInstallClassW (SETUPAPI.@)
2934 BOOL WINAPI
SetupDiInstallClassW(
2935 IN HWND hwndParent OPTIONAL
,
2936 IN PCWSTR InfFileName
,
2938 IN HSPFILEQ FileQueue OPTIONAL
)
2940 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
2944 /***********************************************************************
2945 * SetupDiInstallClassExA (SETUPAPI.@)
2947 BOOL WINAPI
SetupDiInstallClassExA(
2948 IN HWND hwndParent OPTIONAL
,
2949 IN PCSTR InfFileName OPTIONAL
,
2951 IN HSPFILEQ FileQueue OPTIONAL
,
2952 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
2956 PWSTR InfFileNameW
= NULL
;
2961 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
2962 if (InfFileNameW
== NULL
)
2964 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2969 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
2970 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
2972 MyFree(InfFileNameW
);
2978 static HKEY
CreateClassKey(HINF hInf
)
2980 WCHAR FullBuffer
[MAX_PATH
];
2981 WCHAR Buffer
[MAX_PATH
];
2986 if (!SetupGetLineTextW(NULL
,
2994 return INVALID_HANDLE_VALUE
;
2997 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
2998 lstrcatW(FullBuffer
, Buffer
);
3001 if (!SetupGetLineTextW(NULL
,
3009 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3010 return INVALID_HANDLE_VALUE
;
3013 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3017 REG_OPTION_NON_VOLATILE
,
3023 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3024 return INVALID_HANDLE_VALUE
;
3027 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3032 RequiredSize
* sizeof(WCHAR
)))
3034 RegCloseKey(hClassKey
);
3035 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3036 return INVALID_HANDLE_VALUE
;
3044 InstallServicesSection(
3046 IN PCWSTR SectionName
,
3047 IN HDEVINFO DeviceInfoSet OPTIONAL
,
3048 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3049 OUT PCWSTR
* pAssociatedService OPTIONAL
,
3050 OUT PBOOL pRebootRequired OPTIONAL
)
3052 INFCONTEXT ContextService
;
3057 ret
= SetupFindFirstLineW(hInf
, SectionName
, NULL
, &ContextService
);
3060 LPWSTR ServiceName
= NULL
;
3061 LPWSTR ServiceSection
= NULL
;
3063 ret
= SetupGetStringFieldW(
3065 1, /* Field index */
3070 if (RequiredSize
> 0)
3072 /* We got the needed size for the buffer */
3073 ServiceName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3076 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3079 ret
= SetupGetStringFieldW(
3081 1, /* Field index */
3082 ServiceName
, RequiredSize
,
3087 ret
= SetupGetIntField(
3089 2, /* Field index */
3093 /* The field may be empty. Ignore the error */
3096 ret
= SetupGetStringFieldW(
3098 3, /* Field index */
3103 if (GetLastError() == ERROR_INVALID_PARAMETER
)
3105 /* This first is probably missing. It is not
3106 * required, so ignore the error */
3113 if (RequiredSize
> 0)
3115 /* We got the needed size for the buffer */
3116 ServiceSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
3117 if (!ServiceSection
)
3119 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3122 ret
= SetupGetStringFieldW(
3124 3, /* Field index */
3125 ServiceSection
, RequiredSize
,
3130 SetLastError(ERROR_SUCCESS
);
3131 ret
= SetupInstallServicesFromInfSectionExW(
3133 ServiceSection
, Flags
, DeviceInfoSet
, DeviceInfoData
, ServiceName
, NULL
);
3135 if (ret
&& (Flags
& SPSVCINST_ASSOCSERVICE
))
3137 if (pAssociatedService
)
3139 *pAssociatedService
= ServiceName
;
3142 if (pRebootRequired
&& GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
3143 *pRebootRequired
= TRUE
;
3146 HeapFree(GetProcessHeap(), 0, ServiceName
);
3147 HeapFree(GetProcessHeap(), 0, ServiceSection
);
3150 ret
= SetupFindNextLine(&ContextService
, &ContextService
);
3159 /***********************************************************************
3160 * SetupDiInstallClassExW (SETUPAPI.@)
3162 BOOL WINAPI
SetupDiInstallClassExW(
3163 IN HWND hwndParent OPTIONAL
,
3164 IN PCWSTR InfFileName OPTIONAL
,
3166 IN HSPFILEQ FileQueue OPTIONAL
,
3167 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3173 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3174 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3176 if (!InfFileName
&& !InterfaceClassGuid
)
3177 SetLastError(ERROR_INVALID_PARAMETER
);
3178 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3180 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3181 SetLastError(ERROR_INVALID_FLAGS
);
3183 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3184 SetLastError(ERROR_INVALID_PARAMETER
);
3185 else if (Reserved1
!= NULL
)
3186 SetLastError(ERROR_INVALID_PARAMETER
);
3187 else if (Reserved2
!= NULL
)
3188 SetLastError(ERROR_INVALID_PARAMETER
);
3191 WCHAR SectionName
[MAX_PATH
];
3192 HINF hInf
= INVALID_HANDLE_VALUE
;
3193 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
3194 PVOID callback_context
= NULL
;
3196 if (InterfaceClassGuid
)
3198 /* SetupDiCreateDeviceInterface??? */
3199 FIXME("Installing an interface is not implemented\n");
3200 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3204 if (Flags
& DI_NOVCP
)
3205 FIXME("FileQueue argument ignored\n");
3206 if (Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3207 FIXME("Flags 0x%lx ignored\n", Flags
& (DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3209 /* Open the .inf file */
3210 hInf
= SetupOpenInfFileW(
3215 if (hInf
== INVALID_HANDLE_VALUE
)
3218 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3219 hClassKey
= CreateClassKey(hInf
);
3220 if (hClassKey
== INVALID_HANDLE_VALUE
)
3223 /* Try to append a layout file */
3224 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3228 /* Retrieve the actual section name */
3229 ret
= SetupDiGetActualSectionToInstallW(
3233 MAX_PATH
- wcslen(DotServices
),
3239 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3240 if (!callback_context
)
3243 ret
= SetupInstallFromInfSectionW(
3247 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3249 NULL
, /* SourceRootPath */
3251 SetupDefaultQueueCallbackW
,
3258 /* Install .Services section */
3259 lstrcatW(SectionName
, DotServices
);
3260 ret
= InstallServicesSection(hInf
, SectionName
, NULL
, NULL
, NULL
, NULL
);
3268 if (hInf
!= INVALID_HANDLE_VALUE
)
3269 SetupCloseInfFile(hInf
);
3270 if (hClassKey
!= INVALID_HANDLE_VALUE
)
3271 RegCloseKey(hClassKey
);
3272 SetupTermDefaultQueueCallback(callback_context
);
3275 TRACE("Returning %d\n", ret
);
3280 /***********************************************************************
3281 * SetupDiOpenClassRegKey (SETUPAPI.@)
3283 HKEY WINAPI
SetupDiOpenClassRegKey(
3284 const GUID
* ClassGuid
,
3287 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3288 DIOCR_INSTALLER
, NULL
, NULL
);
3292 /***********************************************************************
3293 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3295 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3296 const GUID
* ClassGuid OPTIONAL
,
3299 PCSTR MachineName OPTIONAL
,
3302 PWSTR MachineNameW
= NULL
;
3309 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3310 if (MachineNameW
== NULL
)
3311 return INVALID_HANDLE_VALUE
;
3314 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3315 Flags
, MachineNameW
, Reserved
);
3318 MyFree(MachineNameW
);
3324 /***********************************************************************
3325 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3327 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3328 const GUID
* ClassGuid OPTIONAL
,
3331 PCWSTR MachineName OPTIONAL
,
3334 LPWSTR lpGuidString
;
3335 LPWSTR lpFullGuidString
;
3343 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3344 Flags
, debugstr_w(MachineName
), Reserved
);
3346 if (Flags
== DIOCR_INSTALLER
)
3348 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3350 else if (Flags
== DIOCR_INTERFACE
)
3352 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3356 ERR("Invalid Flags parameter!\n");
3357 SetLastError(ERROR_INVALID_FLAGS
);
3358 return INVALID_HANDLE_VALUE
;
3361 if (MachineName
!= NULL
)
3363 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3364 if (rc
!= ERROR_SUCCESS
)
3367 return INVALID_HANDLE_VALUE
;
3371 HKLM
= HKEY_LOCAL_MACHINE
;
3373 rc
= RegOpenKeyExW(HKLM
,
3376 ClassGuid
? 0 : samDesired
,
3378 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3379 if (rc
!= ERROR_SUCCESS
)
3382 return INVALID_HANDLE_VALUE
;
3385 if (ClassGuid
== NULL
)
3388 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3390 SetLastError(ERROR_GEN_FAILURE
);
3391 RegCloseKey(hClassesKey
);
3392 return INVALID_HANDLE_VALUE
;
3395 dwLength
= lstrlenW(lpGuidString
);
3396 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3397 if (!lpFullGuidString
)
3399 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3400 RpcStringFreeW(&lpGuidString
);
3401 return INVALID_HANDLE_VALUE
;
3403 lpFullGuidString
[0] = '{';
3404 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3405 lpFullGuidString
[dwLength
+ 1] = '}';
3406 lpFullGuidString
[dwLength
+ 2] = '\0';
3407 RpcStringFreeW(&lpGuidString
);
3409 rc
= RegOpenKeyExW(hClassesKey
,
3414 if (rc
!= ERROR_SUCCESS
)
3417 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3418 RegCloseKey(hClassesKey
);
3419 return INVALID_HANDLE_VALUE
;
3422 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3423 RegCloseKey(hClassesKey
);
3428 /***********************************************************************
3429 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3431 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3432 HDEVINFO DeviceInfoSet
,
3435 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3437 FIXME("%p %s %08lx %p\n",
3438 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3442 /***********************************************************************
3443 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3445 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3446 HDEVINFO DeviceInfoSet
,
3449 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3451 LPWSTR DevicePathW
= NULL
;
3454 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3456 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3457 if (DevicePathW
== NULL
)
3460 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3461 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3463 MyFree(DevicePathW
);
3468 /***********************************************************************
3469 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3471 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3472 HDEVINFO DeviceInfoSet
,
3473 PSP_DEVINFO_DATA DeviceInfoData
,
3474 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3475 DWORD ClassInstallParamsSize
)
3477 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3478 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3482 /***********************************************************************
3483 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3485 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3486 IN HDEVINFO DeviceInfoSet
,
3487 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3488 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3489 IN DWORD ClassInstallParamsSize
)
3491 struct DeviceInfoSet
*list
;
3494 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3495 ClassInstallParams
, ClassInstallParamsSize
);
3498 SetLastError(ERROR_INVALID_PARAMETER
);
3499 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3500 SetLastError(ERROR_INVALID_HANDLE
);
3501 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3502 SetLastError(ERROR_INVALID_HANDLE
);
3503 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3504 SetLastError(ERROR_INVALID_USER_BUFFER
);
3505 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3506 SetLastError(ERROR_INVALID_USER_BUFFER
);
3507 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3508 SetLastError(ERROR_INVALID_PARAMETER
);
3509 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3510 SetLastError(ERROR_INVALID_PARAMETER
);
3513 SP_DEVINSTALL_PARAMS_W InstallParams
;
3516 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3517 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3521 if (ClassInstallParams
)
3523 /* Check parameters in ClassInstallParams */
3524 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3525 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3527 SetLastError(ERROR_INVALID_USER_BUFFER
);
3530 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3532 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3533 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3536 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3539 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3543 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3546 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3550 TRACE("Returning %d\n", ret
);
3554 static BOOL
PropertyChangeHandler(
3555 IN HDEVINFO DeviceInfoSet
,
3556 IN PSP_DEVINFO_DATA DeviceInfoData
,
3557 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3558 IN DWORD ClassInstallParamsSize
)
3560 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3563 if (!DeviceInfoData
)
3564 SetLastError(ERROR_INVALID_PARAMETER
);
3565 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3566 SetLastError(ERROR_INVALID_PARAMETER
);
3567 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3568 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3569 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3570 SetLastError(ERROR_INVALID_FLAGS
);
3571 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3572 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3573 SetLastError(ERROR_INVALID_FLAGS
);
3574 else if (PropChangeParams
3575 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3576 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3577 SetLastError(ERROR_INVALID_USER_BUFFER
);
3580 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3581 if (!DeviceInfoData
)
3583 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3584 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3588 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3589 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3591 if (*CurrentPropChangeParams
)
3593 MyFree(*CurrentPropChangeParams
);
3594 *CurrentPropChangeParams
= NULL
;
3596 if (PropChangeParams
)
3598 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3599 if (!*CurrentPropChangeParams
)
3601 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3604 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3615 IN PWSTR InstallerName
,
3616 OUT HMODULE
* ModulePointer
,
3617 OUT PVOID
* FunctionPointer
)
3619 HMODULE hModule
= NULL
;
3620 LPSTR FunctionNameA
= NULL
;
3624 *ModulePointer
= NULL
;
3625 *FunctionPointer
= NULL
;
3627 Comma
= strchrW(InstallerName
, ',');
3630 rc
= ERROR_INVALID_PARAMETER
;
3636 hModule
= LoadLibraryW(InstallerName
);
3640 rc
= GetLastError();
3644 /* Skip comma spaces */
3645 while (*Comma
== ',' || isspaceW(*Comma
))
3648 /* W->A conversion for function name */
3649 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3652 rc
= GetLastError();
3656 /* Search function */
3657 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3658 if (!*FunctionPointer
)
3660 rc
= GetLastError();
3664 *ModulePointer
= hModule
;
3668 if (rc
!= ERROR_SUCCESS
&& hModule
)
3669 FreeLibrary(hModule
);
3670 MyFree(FunctionNameA
);
3675 FreeFunctionPointer(
3676 IN HMODULE ModulePointer
,
3677 IN PVOID FunctionPointer
)
3679 if (ModulePointer
== NULL
)
3680 return ERROR_SUCCESS
;
3681 if (FreeLibrary(ModulePointer
))
3682 return ERROR_SUCCESS
;
3684 return GetLastError();
3687 /***********************************************************************
3688 * SetupDiCallClassInstaller (SETUPAPI.@)
3690 BOOL WINAPI
SetupDiCallClassInstaller(
3691 IN DI_FUNCTION InstallFunction
,
3692 IN HDEVINFO DeviceInfoSet
,
3693 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3697 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3700 SetLastError(ERROR_INVALID_PARAMETER
);
3701 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3702 SetLastError(ERROR_INVALID_HANDLE
);
3703 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3704 SetLastError(ERROR_INVALID_HANDLE
);
3705 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3706 SetLastError(ERROR_INVALID_HANDLE
);
3707 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3708 SetLastError(ERROR_INVALID_USER_BUFFER
);
3711 SP_DEVINSTALL_PARAMS_W InstallParams
;
3712 #define CLASS_COINSTALLER 0x1
3713 #define DEVICE_COINSTALLER 0x2
3714 #define CLASS_INSTALLER 0x4
3715 UCHAR CanHandle
= 0;
3716 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3718 switch (InstallFunction
)
3720 case DIF_ALLOW_INSTALL
:
3721 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3723 case DIF_DESTROYPRIVATEDATA
:
3724 CanHandle
= CLASS_INSTALLER
;
3726 case DIF_INSTALLDEVICE
:
3727 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3728 DefaultHandler
= SetupDiInstallDevice
;
3730 case DIF_INSTALLDEVICEFILES
:
3731 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3732 DefaultHandler
= SetupDiInstallDriverFiles
;
3734 case DIF_INSTALLINTERFACES
:
3735 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3736 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3738 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3739 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3741 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3742 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3744 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3745 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3747 case DIF_PROPERTYCHANGE
:
3748 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3749 DefaultHandler
= SetupDiChangeState
;
3751 case DIF_REGISTER_COINSTALLERS
:
3752 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3753 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3755 case DIF_SELECTBESTCOMPATDRV
:
3756 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3757 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3760 ERR("Install function %u not supported\n", InstallFunction
);
3761 SetLastError(ERROR_NOT_SUPPORTED
);
3764 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3765 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3766 /* Don't process this call, as a parameter is invalid */
3771 LIST_ENTRY ClassCoInstallersListHead
;
3772 LIST_ENTRY DeviceCoInstallersListHead
;
3773 HMODULE ClassInstallerLibrary
= NULL
;
3774 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3775 COINSTALLER_CONTEXT_DATA Context
;
3776 PLIST_ENTRY ListEntry
;
3778 DWORD dwRegType
, dwLength
;
3779 DWORD rc
= NO_ERROR
;
3781 InitializeListHead(&ClassCoInstallersListHead
);
3782 InitializeListHead(&DeviceCoInstallersListHead
);
3784 if (CanHandle
& DEVICE_COINSTALLER
)
3786 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3787 if (hKey
!= INVALID_HANDLE_VALUE
)
3789 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3790 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3792 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3793 if (KeyBuffer
!= NULL
)
3795 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3796 if (rc
== ERROR_SUCCESS
)
3799 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3801 /* Add coinstaller to DeviceCoInstallersListHead list */
3802 struct CoInstallerElement
*coinstaller
;
3803 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3804 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3807 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3808 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3809 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3811 HeapFree(GetProcessHeap(), 0, coinstaller
);
3814 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3820 if (CanHandle
& CLASS_COINSTALLER
)
3824 REGSTR_PATH_CODEVICEINSTALLERS
,
3828 if (rc
== ERROR_SUCCESS
)
3830 LPWSTR lpGuidString
;
3831 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3833 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3834 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3836 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3837 if (KeyBuffer
!= NULL
)
3839 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3840 if (rc
== ERROR_SUCCESS
)
3843 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3845 /* Add coinstaller to ClassCoInstallersListHead list */
3846 struct CoInstallerElement
*coinstaller
;
3847 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3848 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3851 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3852 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3853 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3855 HeapFree(GetProcessHeap(), 0, coinstaller
);
3858 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3861 RpcStringFreeW(&lpGuidString
);
3866 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3868 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3869 if (hKey
!= INVALID_HANDLE_VALUE
)
3871 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3872 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3874 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3875 if (KeyBuffer
!= NULL
)
3877 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3878 if (rc
== ERROR_SUCCESS
)
3880 /* Get ClassInstaller function pointer */
3881 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3882 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3884 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3885 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3888 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3895 /* Call Class co-installers */
3896 Context
.PostProcessing
= FALSE
;
3898 ListEntry
= ClassCoInstallersListHead
.Flink
;
3899 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3901 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3902 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3903 coinstaller
->PrivateData
= Context
.PrivateData
;
3904 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3906 coinstaller
->DoPostProcessing
= TRUE
;
3909 ListEntry
= ListEntry
->Flink
;
3912 /* Call Device co-installers */
3913 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3914 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3916 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3917 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3918 coinstaller
->PrivateData
= Context
.PrivateData
;
3919 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3921 coinstaller
->DoPostProcessing
= TRUE
;
3924 ListEntry
= ListEntry
->Flink
;
3927 /* Call Class installer */
3930 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3931 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3934 rc
= ERROR_DI_DO_DEFAULT
;
3936 /* Call default handler */
3937 if (rc
== ERROR_DI_DO_DEFAULT
)
3939 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3941 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3944 rc
= GetLastError();
3950 /* Call Class co-installers that required postprocessing */
3951 Context
.PostProcessing
= TRUE
;
3952 ListEntry
= ClassCoInstallersListHead
.Flink
;
3953 while (ListEntry
!= &ClassCoInstallersListHead
)
3955 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3956 if (coinstaller
->DoPostProcessing
)
3958 Context
.InstallResult
= rc
;
3959 Context
.PrivateData
= coinstaller
->PrivateData
;
3960 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3962 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3963 ListEntry
= ListEntry
->Flink
;
3966 /* Call Device co-installers that required postprocessing */
3967 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3968 while (ListEntry
!= &DeviceCoInstallersListHead
)
3970 struct CoInstallerElement
*coinstaller
= (struct CoInstallerElement
*)ListEntry
;
3971 if (coinstaller
->DoPostProcessing
)
3973 Context
.InstallResult
= rc
;
3974 Context
.PrivateData
= coinstaller
->PrivateData
;
3975 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3977 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
3978 ListEntry
= ListEntry
->Flink
;
3981 /* Free allocated memory */
3982 while (!IsListEmpty(&ClassCoInstallersListHead
))
3984 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
3985 HeapFree(GetProcessHeap(), 0, ListEntry
);
3987 while (!IsListEmpty(&DeviceCoInstallersListHead
))
3989 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
3990 HeapFree(GetProcessHeap(), 0, ListEntry
);
3993 ret
= (rc
== NO_ERROR
);
3997 TRACE("Returning %d\n", ret
);
4001 /***********************************************************************
4002 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4004 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
4005 IN HDEVINFO DeviceInfoSet
,
4006 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
4008 struct DeviceInfoSet
*list
;
4011 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
4014 SetLastError(ERROR_INVALID_HANDLE
);
4015 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4016 SetLastError(ERROR_INVALID_HANDLE
);
4017 else if (!DeviceInfoListDetailData
)
4018 SetLastError(ERROR_INVALID_PARAMETER
);
4019 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
4020 SetLastError(ERROR_INVALID_USER_BUFFER
);
4024 &DeviceInfoListDetailData
->ClassGuid
,
4027 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
4028 if (list
->MachineName
)
4029 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
4031 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
4036 TRACE("Returning %d\n", ret
);
4040 /***********************************************************************
4041 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4043 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4044 IN HDEVINFO DeviceInfoSet
,
4045 IN PSP_DEVINFO_DATA DeviceInfoData
,
4046 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4048 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4051 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4053 if (DeviceInstallParams
== NULL
)
4054 SetLastError(ERROR_INVALID_PARAMETER
);
4055 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4056 SetLastError(ERROR_INVALID_USER_BUFFER
);
4059 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4060 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4064 /* Do W->A conversion */
4066 DeviceInstallParams
,
4067 &deviceInstallParamsW
,
4068 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4069 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4070 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4072 DeviceInstallParams
->DriverPath
[0] = '\0';
4078 TRACE("Returning %d\n", ret
);
4082 /***********************************************************************
4083 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4085 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
4086 IN HDEVINFO DeviceInfoSet
,
4087 IN PSP_DEVINFO_DATA DeviceInfoData
,
4088 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4090 struct DeviceInfoSet
*list
;
4093 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4096 SetLastError(ERROR_INVALID_HANDLE
);
4097 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4098 SetLastError(ERROR_INVALID_HANDLE
);
4099 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4100 SetLastError(ERROR_INVALID_USER_BUFFER
);
4101 else if (!DeviceInstallParams
)
4102 SetLastError(ERROR_INVALID_PARAMETER
);
4103 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4104 SetLastError(ERROR_INVALID_USER_BUFFER
);
4107 PSP_DEVINSTALL_PARAMS_W Source
;
4110 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4112 Source
= &list
->InstallParams
;
4113 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4117 TRACE("Returning %d\n", ret
);
4121 /***********************************************************************
4122 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4124 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
4125 IN HDEVINFO DeviceInfoSet
,
4126 IN PSP_DEVINFO_DATA DeviceInfoData
,
4127 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4129 struct DeviceInfoSet
*list
;
4132 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4135 SetLastError(ERROR_INVALID_HANDLE
);
4136 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4137 SetLastError(ERROR_INVALID_HANDLE
);
4138 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4139 SetLastError(ERROR_INVALID_USER_BUFFER
);
4140 else if (!DeviceInstallParams
)
4141 SetLastError(ERROR_INVALID_PARAMETER
);
4142 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4143 SetLastError(ERROR_INVALID_USER_BUFFER
);
4146 PSP_DEVINSTALL_PARAMS_W Destination
;
4148 /* FIXME: Validate parameters */
4151 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4153 Destination
= &list
->InstallParams
;
4154 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4158 TRACE("Returning %d\n", ret
);
4162 /***********************************************************************
4163 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4165 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
4166 IN HDEVINFO DeviceInfoSet
,
4167 IN PSP_DEVINFO_DATA DeviceInfoData
,
4168 OUT PSTR DeviceInstanceId OPTIONAL
,
4169 IN DWORD DeviceInstanceIdSize
,
4170 OUT PDWORD RequiredSize OPTIONAL
)
4172 PWSTR DeviceInstanceIdW
= NULL
;
4175 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4176 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4178 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4179 SetLastError(ERROR_INVALID_PARAMETER
);
4182 if (DeviceInstanceIdSize
!= 0)
4184 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4185 if (DeviceInstanceIdW
== NULL
)
4189 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4190 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4193 if (ret
&& DeviceInstanceIdW
!= NULL
)
4195 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4196 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4198 DeviceInstanceId
[0] = '\0';
4204 TRACE("Returning %d\n", ret
);
4208 /***********************************************************************
4209 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4211 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
4212 IN HDEVINFO DeviceInfoSet
,
4213 IN PSP_DEVINFO_DATA DeviceInfoData
,
4214 OUT PWSTR DeviceInstanceId OPTIONAL
,
4215 IN DWORD DeviceInstanceIdSize
,
4216 OUT PDWORD RequiredSize OPTIONAL
)
4220 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4221 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4224 SetLastError(ERROR_INVALID_HANDLE
);
4225 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4226 SetLastError(ERROR_INVALID_HANDLE
);
4227 else if (!DeviceInfoData
)
4228 SetLastError(ERROR_INVALID_PARAMETER
);
4229 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4230 SetLastError(ERROR_INVALID_USER_BUFFER
);
4231 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4232 SetLastError(ERROR_INVALID_PARAMETER
);
4233 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4234 SetLastError(ERROR_INVALID_PARAMETER
);
4237 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4240 required
= (wcslen(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4242 *RequiredSize
= required
;
4244 if (required
<= DeviceInstanceIdSize
)
4246 wcscpy(DeviceInstanceId
, DevInfo
->DeviceName
);
4250 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4253 TRACE("Returning %d\n", ret
);
4257 /***********************************************************************
4258 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4260 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
4261 IN HDEVINFO DeviceInfoSet
,
4262 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4263 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4264 IN DWORD PropertySheetHeaderPageListSize
,
4265 OUT PDWORD RequiredSize OPTIONAL
,
4266 IN DWORD PropertySheetType
)
4268 PROPSHEETHEADERW psh
;
4271 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4272 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4273 RequiredSize
, PropertySheetType
);
4275 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4276 psh
.phpage
= PropertySheetHeader
->phpage
;
4277 psh
.nPages
= PropertySheetHeader
->nPages
;
4279 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4280 PropertySheetHeaderPageListSize
, RequiredSize
,
4284 PropertySheetHeader
->nPages
= psh
.nPages
;
4287 TRACE("Returning %d\n", ret
);
4291 struct ClassDevPropertySheetsData
4293 HPROPSHEETPAGE
*PropertySheetPages
;
4294 DWORD MaximumNumberOfPages
;
4295 DWORD NumberOfPages
;
4298 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
4299 IN HPROPSHEETPAGE hPropSheetPage
,
4300 IN OUT LPARAM lParam
)
4302 struct ClassDevPropertySheetsData
*PropPageData
;
4304 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4306 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4308 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4309 PropPageData
->PropertySheetPages
++;
4312 PropPageData
->NumberOfPages
++;
4316 /***********************************************************************
4317 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4319 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
4320 IN HDEVINFO DeviceInfoSet
,
4321 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4322 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4323 IN DWORD PropertySheetHeaderPageListSize
,
4324 OUT PDWORD RequiredSize OPTIONAL
,
4325 IN DWORD PropertySheetType
)
4327 struct DeviceInfoSet
*list
;
4330 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4331 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4332 RequiredSize
, PropertySheetType
);
4335 SetLastError(ERROR_INVALID_HANDLE
);
4336 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4337 SetLastError(ERROR_INVALID_HANDLE
);
4338 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4339 SetLastError(ERROR_INVALID_HANDLE
);
4340 else if (!PropertySheetHeader
)
4341 SetLastError(ERROR_INVALID_PARAMETER
);
4342 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4343 SetLastError(ERROR_INVALID_FLAGS
);
4344 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4345 SetLastError(ERROR_INVALID_USER_BUFFER
);
4346 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4347 SetLastError(ERROR_INVALID_PARAMETER
);
4348 else if (!PropertySheetHeader
)
4349 SetLastError(ERROR_INVALID_PARAMETER
);
4350 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4351 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4352 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4353 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4354 SetLastError(ERROR_INVALID_PARAMETER
);
4357 HKEY hKey
= INVALID_HANDLE_VALUE
;
4358 SP_PROPSHEETPAGE_REQUEST Request
;
4359 LPWSTR PropPageProvider
= NULL
;
4360 HMODULE hModule
= NULL
;
4361 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4362 struct ClassDevPropertySheetsData PropPageData
;
4363 DWORD dwLength
, dwRegType
;
4367 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4370 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4371 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4373 if (hKey
== INVALID_HANDLE_VALUE
)
4376 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4377 if (rc
== ERROR_FILE_NOT_FOUND
)
4379 /* No registry key. As it is optional, don't say it's a bad error */
4385 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4391 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4392 if (!PropPageProvider
)
4394 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4397 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4398 if (rc
!= ERROR_SUCCESS
)
4403 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4405 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4406 if (rc
!= ERROR_SUCCESS
)
4408 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4412 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4413 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4414 Request
.DeviceInfoSet
= DeviceInfoSet
;
4415 Request
.DeviceInfoData
= DeviceInfoData
;
4416 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4417 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4418 PropPageData
.NumberOfPages
= 0;
4419 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4424 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4425 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4427 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4432 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4433 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4437 if (hKey
!= INVALID_HANDLE_VALUE
)
4439 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4440 FreeFunctionPointer(hModule
, pPropPageProvider
);
4443 TRACE("Returning %d\n", ret
);
4447 /***********************************************************************
4448 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4450 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4451 IN HDEVINFO DeviceInfoSet
,
4452 IN PSP_DEVINFO_DATA DeviceInfoData
,
4456 IN HINF InfHandle OPTIONAL
,
4457 IN PCSTR InfSectionName OPTIONAL
)
4459 PCWSTR InfSectionNameW
= NULL
;
4460 HKEY ret
= INVALID_HANDLE_VALUE
;
4464 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4465 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4468 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4476 if (InfSectionNameW
!= NULL
)
4477 MyFree((PVOID
)InfSectionNameW
);
4483 OpenHardwareProfileKey(
4486 IN DWORD samDesired
)
4488 HKEY hHWProfilesKey
= INVALID_HANDLE_VALUE
;
4489 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4490 HKEY ret
= INVALID_HANDLE_VALUE
;
4493 rc
= RegOpenKeyExW(HKLM
,
4494 REGSTR_PATH_HWPROFILES
,
4498 if (rc
!= ERROR_SUCCESS
)
4515 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4524 if (rc
!= ERROR_SUCCESS
)
4529 ret
= hHWProfileKey
;
4532 if (hHWProfilesKey
!= INVALID_HANDLE_VALUE
)
4533 RegCloseKey(hHWProfilesKey
);
4534 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
&& hHWProfileKey
!= ret
)
4535 RegCloseKey(hHWProfileKey
);
4539 /***********************************************************************
4540 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4542 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4543 IN HDEVINFO DeviceInfoSet
,
4544 IN PSP_DEVINFO_DATA DeviceInfoData
,
4548 IN HINF InfHandle OPTIONAL
,
4549 IN PCWSTR InfSectionName OPTIONAL
)
4551 struct DeviceInfoSet
*list
;
4552 HKEY ret
= INVALID_HANDLE_VALUE
;
4554 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4555 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4558 SetLastError(ERROR_INVALID_HANDLE
);
4559 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4560 SetLastError(ERROR_INVALID_HANDLE
);
4561 else if (!DeviceInfoData
)
4562 SetLastError(ERROR_INVALID_PARAMETER
);
4563 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4564 SetLastError(ERROR_INVALID_USER_BUFFER
);
4565 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4566 SetLastError(ERROR_INVALID_PARAMETER
);
4567 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4568 SetLastError(ERROR_INVALID_PARAMETER
);
4569 else if (InfHandle
&& !InfSectionName
)
4570 SetLastError(ERROR_INVALID_PARAMETER
);
4571 else if (!InfHandle
&& InfSectionName
)
4572 SetLastError(ERROR_INVALID_PARAMETER
);
4575 LPWSTR lpGuidString
= NULL
;
4576 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4577 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4578 DWORD Index
; /* Index used in the DriverKey name */
4580 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4581 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4582 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
4583 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4584 HKEY hKey
= INVALID_HANDLE_VALUE
;
4587 if (Scope
== DICS_FLAG_GLOBAL
)
4588 RootKey
= list
->HKLM
;
4589 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4591 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
4592 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4594 RootKey
= hHWProfileKey
;
4597 if (KeyType
== DIREG_DEV
)
4599 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4601 rc
= RegCreateKeyExW(
4603 REGSTR_PATH_SYSTEMENUM
,
4606 REG_OPTION_NON_VOLATILE
,
4611 if (rc
!= ERROR_SUCCESS
)
4616 rc
= RegCreateKeyExW(
4618 deviceInfo
->DeviceName
,
4621 REG_OPTION_NON_VOLATILE
,
4622 #if _WIN32_WINNT >= 0x502
4623 KEY_READ
| KEY_WRITE
,
4630 if (rc
!= ERROR_SUCCESS
)
4636 else /* KeyType == DIREG_DRV */
4638 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4640 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4641 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4644 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4647 wcscpy(DriverKey
, L
"{");
4648 wcscat(DriverKey
, lpGuidString
);
4649 wcscat(DriverKey
, L
"}\\");
4650 pDeviceInstance
= &DriverKey
[wcslen(DriverKey
)];
4651 rc
= RegOpenKeyExW(RootKey
,
4652 REGSTR_PATH_CLASS_NT
,
4656 if (rc
!= ERROR_SUCCESS
)
4662 /* Try all values for Index between 0 and 9999 */
4664 while (Index
<= 9999)
4667 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4668 rc
= RegCreateKeyEx(hClassKey
,
4672 REG_OPTION_NON_VOLATILE
,
4673 #if _WIN32_WINNT >= 0x502
4674 KEY_READ
| KEY_WRITE
,
4681 if (rc
!= ERROR_SUCCESS
)
4686 if (Disposition
== REG_CREATED_NEW_KEY
)
4689 hKey
= INVALID_HANDLE_VALUE
;
4694 /* Unable to create more than 9999 devices within the same class */
4695 SetLastError(ERROR_GEN_FAILURE
);
4699 /* Open device key, to write Driver value */
4700 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4701 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4703 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (wcslen(DriverKey
) + 1) * sizeof(WCHAR
));
4704 if (rc
!= ERROR_SUCCESS
)
4711 /* Do installation of the specified section */
4714 FIXME("Need to install section %s in file %p\n",
4715 debugstr_w(InfSectionName
), InfHandle
);
4721 RpcStringFreeW(&lpGuidString
);
4722 HeapFree(GetProcessHeap(), 0, DriverKey
);
4723 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4724 RegCloseKey(hHWProfileKey
);
4725 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4726 RegCloseKey(hEnumKey
);
4727 if (hClassKey
!= INVALID_HANDLE_VALUE
)
4728 RegCloseKey(hClassKey
);
4729 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4730 RegCloseKey(hDeviceKey
);
4731 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4735 TRACE("Returning 0x%p\n", ret
);
4739 /***********************************************************************
4740 * SetupDiOpenDevRegKey (SETUPAPI.@)
4742 HKEY WINAPI
SetupDiOpenDevRegKey(
4743 HDEVINFO DeviceInfoSet
,
4744 PSP_DEVINFO_DATA DeviceInfoData
,
4750 struct DeviceInfoSet
*list
;
4751 HKEY ret
= INVALID_HANDLE_VALUE
;
4753 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4754 Scope
, HwProfile
, KeyType
, samDesired
);
4757 SetLastError(ERROR_INVALID_HANDLE
);
4758 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4759 SetLastError(ERROR_INVALID_HANDLE
);
4760 else if (!DeviceInfoData
)
4761 SetLastError(ERROR_INVALID_PARAMETER
);
4762 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4763 SetLastError(ERROR_INVALID_USER_BUFFER
);
4764 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4765 SetLastError(ERROR_INVALID_PARAMETER
);
4766 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4767 SetLastError(ERROR_INVALID_PARAMETER
);
4770 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4771 LPWSTR DriverKey
= NULL
;
4775 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4776 HKEY hEnumKey
= INVALID_HANDLE_VALUE
;
4777 HKEY hKey
= INVALID_HANDLE_VALUE
;
4780 if (Scope
== DICS_FLAG_GLOBAL
)
4781 RootKey
= list
->HKLM
;
4782 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4784 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
4785 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4787 RootKey
= hHWProfileKey
;
4792 REGSTR_PATH_SYSTEMENUM
,
4796 if (rc
!= ERROR_SUCCESS
)
4803 deviceInfo
->DeviceName
,
4805 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4807 RegCloseKey(hEnumKey
);
4808 hEnumKey
= INVALID_HANDLE_VALUE
;
4809 if (rc
!= ERROR_SUCCESS
)
4814 if (KeyType
== DIREG_DEV
)
4816 /* We're done. Just return the hKey handle */
4820 /* Read the 'Driver' key */
4821 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
4822 if (rc
!= ERROR_SUCCESS
)
4827 else if (dwRegType
!= REG_SZ
)
4829 SetLastError(ERROR_GEN_FAILURE
);
4832 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4835 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4838 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4839 if (rc
!= ERROR_SUCCESS
)
4845 hKey
= INVALID_HANDLE_VALUE
;
4846 /* Need to open the driver key */
4849 REGSTR_PATH_CLASS_NT
,
4853 if (rc
!= ERROR_SUCCESS
)
4864 if (rc
!= ERROR_SUCCESS
)
4872 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4873 RegCloseKey(hHWProfileKey
);
4874 if (hEnumKey
!= INVALID_HANDLE_VALUE
)
4875 RegCloseKey(hEnumKey
);
4876 if (hKey
!= INVALID_HANDLE_VALUE
&& hKey
!= ret
)
4880 TRACE("Returning 0x%p\n", ret
);
4884 /***********************************************************************
4885 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
4887 BOOL WINAPI
SetupDiCreateDeviceInfoA(
4888 HDEVINFO DeviceInfoSet
,
4890 CONST GUID
*ClassGuid
,
4891 PCSTR DeviceDescription
,
4893 DWORD CreationFlags
,
4894 PSP_DEVINFO_DATA DeviceInfoData
)
4896 LPWSTR DeviceNameW
= NULL
;
4897 LPWSTR DeviceDescriptionW
= NULL
;
4904 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
4905 if (DeviceNameW
== NULL
) return FALSE
;
4907 if (DeviceDescription
)
4909 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
4910 if (DeviceDescriptionW
== NULL
)
4912 if (DeviceNameW
) MyFree(DeviceNameW
);
4917 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
4918 ClassGuid
, DeviceDescriptionW
,
4919 hwndParent
, CreationFlags
,
4922 if (DeviceNameW
) MyFree(DeviceNameW
);
4923 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
4928 /***********************************************************************
4929 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
4931 BOOL WINAPI
SetupDiCreateDeviceInfoW(
4932 HDEVINFO DeviceInfoSet
,
4934 CONST GUID
*ClassGuid
,
4935 PCWSTR DeviceDescription
,
4937 DWORD CreationFlags
,
4938 PSP_DEVINFO_DATA DeviceInfoData
)
4940 struct DeviceInfoSet
*list
;
4943 TRACE("%p %S %s %S %p %lx %p\n", DeviceInfoSet
, DeviceName
,
4944 debugstr_guid(ClassGuid
), DeviceDescription
,
4945 hwndParent
, CreationFlags
, DeviceInfoData
);
4948 SetLastError(ERROR_INVALID_HANDLE
);
4949 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4950 SetLastError(ERROR_INVALID_HANDLE
);
4951 else if (!ClassGuid
)
4952 SetLastError(ERROR_INVALID_PARAMETER
);
4953 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
4954 SetLastError(ERROR_CLASS_MISMATCH
);
4955 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
4957 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
4958 SetLastError(ERROR_INVALID_FLAGS
);
4962 SP_DEVINFO_DATA DevInfo
;
4964 if (CreationFlags
& DICD_GENERATE_ID
)
4966 /* Generate a new unique ID for this device */
4967 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
4968 FIXME("not implemented\n");
4972 /* Device name is fully qualified. Try to open it */
4975 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
4976 rc
= SetupDiOpenDeviceInfoW(
4979 NULL
, /* hwndParent */
4980 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
4985 /* SetupDiOpenDeviceInfoW has already added
4986 * the device info to the device info set
4988 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
4990 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
4992 struct DeviceInfoElement
*deviceInfo
;
4994 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
4996 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4998 if (!DeviceInfoData
)
5002 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
5004 SetLastError(ERROR_INVALID_USER_BUFFER
);
5008 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5009 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5010 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5019 TRACE("Returning %d\n", ret
);
5023 /***********************************************************************
5024 * Helper functions for SetupDiBuildDriverInfoList
5028 IN PLIST_ENTRY DriverListHead
,
5029 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5030 IN LPGUID ClassGuid
,
5031 IN INFCONTEXT ContextDevice
,
5032 IN
struct InfFileDetails
*InfFileDetails
,
5034 IN LPCWSTR ProviderName
,
5035 IN LPCWSTR ManufacturerName
,
5036 IN LPCWSTR MatchingId
,
5037 FILETIME DriverDate
,
5038 DWORDLONG DriverVersion
,
5041 struct DriverInfoElement
*driverInfo
= NULL
;
5042 HANDLE hFile
= INVALID_HANDLE_VALUE
;
5043 DWORD RequiredSize
= 128; /* Initial buffer size */
5044 BOOL Result
= FALSE
;
5045 PLIST_ENTRY PreviousEntry
;
5046 LPWSTR InfInstallSection
= NULL
;
5049 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
5052 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5055 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
5057 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
5058 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
5060 /* Copy InfFileName field */
5061 wcsncpy(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
5062 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
5064 /* Fill InfDate field */
5065 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5066 GENERIC_READ, FILE_SHARE_READ,
5067 NULL, OPEN_EXISTING, 0, NULL);
5068 if (hFile == INVALID_HANDLE_VALUE)
5070 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5074 /* Fill SectionName field */
5075 Result
= SetupGetStringFieldW(
5078 driverInfo
->Details
.SectionName
, LINE_LEN
,
5083 /* Fill DrvDescription field */
5084 Result
= SetupGetStringFieldW(
5086 0, /* Field index */
5087 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
5090 /* Copy MatchingId information */
5091 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5092 if (!driverInfo
->MatchingId
)
5094 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5097 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (wcslen(MatchingId
) + 1) * sizeof(WCHAR
));
5099 /* Get inf install section */
5101 RequiredSize
= 128; /* Initial buffer size */
5102 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5103 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5105 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5106 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5107 if (!InfInstallSection
)
5109 Result
= SetupGetStringFieldW(
5111 1, /* Field index */
5112 InfInstallSection
, RequiredSize
,
5118 TRACE("Adding driver '%S' [%S/%S] (Rank 0x%lx)\n",
5119 driverInfo
->Details
.DrvDescription
, InfFile
, InfInstallSection
, Rank
);
5121 driverInfo
->DriverRank
= Rank
;
5122 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
5123 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5124 driverInfo
->Info
.DriverType
= DriverType
;
5125 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
5126 wcsncpy(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
5127 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
5128 wcsncpy(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
5129 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
5132 wcsncpy(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
5133 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
5136 driverInfo
->Info
.ProviderName
[0] = '\0';
5137 driverInfo
->Info
.DriverDate
= DriverDate
;
5138 driverInfo
->Info
.DriverVersion
= DriverVersion
;
5139 ReferenceInfFile(InfFileDetails
);
5140 driverInfo
->InfFileDetails
= InfFileDetails
;
5142 /* Insert current driver in driver list, according to its rank */
5143 PreviousEntry
= DriverListHead
->Flink
;
5144 while (PreviousEntry
!= DriverListHead
)
5146 struct DriverInfoElement
*CurrentDriver
;
5147 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
5148 if (CurrentDriver
->DriverRank
> Rank
||
5149 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
5151 /* Insert before the current item */
5152 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
5155 PreviousEntry
= PreviousEntry
->Flink
;
5157 if (PreviousEntry
== DriverListHead
)
5159 /* Insert at the end of the list */
5160 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
5169 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
5170 HeapFree(GetProcessHeap(), 0, driverInfo
);
5172 if (hFile
!= INVALID_HANDLE_VALUE
)
5174 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5180 GetVersionInformationFromInfFile(
5182 OUT LPGUID ClassGuid
,
5183 OUT LPWSTR
* pProviderName
,
5184 OUT FILETIME
* DriverDate
,
5185 OUT DWORDLONG
* DriverVersion
)
5188 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5189 LPWSTR DriverVer
= NULL
;
5190 LPWSTR ProviderName
= NULL
;
5191 LPWSTR pComma
; /* Points into DriverVer */
5192 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5193 SYSTEMTIME SystemTime
;
5195 BOOL ret
= FALSE
; /* Final result */
5197 /* Get class Guid */
5198 if (!SetupGetLineTextW(
5201 L
"Version", L
"ClassGUID",
5202 guidW
, sizeof(guidW
),
5203 NULL
/* Required size */))
5207 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5208 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5210 SetLastError(ERROR_GEN_FAILURE
);
5214 /* Get provider name */
5215 Result
= SetupGetLineTextW(
5217 hInf
, L
"Version", L
"Provider",
5222 /* We know know the needed buffer size */
5223 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5226 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5229 Result
= SetupGetLineTextW(
5231 hInf
, L
"Version", L
"Provider",
5232 ProviderName
, RequiredSize
,
5237 *pProviderName
= ProviderName
;
5239 /* Read the "DriverVer" value */
5240 Result
= SetupGetLineTextW(
5242 hInf
, L
"Version", L
"DriverVer",
5247 /* We know know the needed buffer size */
5248 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5251 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5254 Result
= SetupGetLineTextW(
5256 hInf
, L
"Version", L
"DriverVer",
5257 DriverVer
, RequiredSize
,
5263 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5264 pComma
= wcschr(DriverVer
, ',');
5267 *pComma
= UNICODE_NULL
;
5268 pVersion
= pComma
+ 1;
5270 /* Get driver date version. Invalid date = 00/00/00 */
5271 memset(DriverDate
, 0, sizeof(FILETIME
));
5272 if (wcslen(DriverVer
) == 10
5273 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5274 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5276 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5277 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5278 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5279 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5280 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5281 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5283 /* Get driver version. Invalid version = 0.0.0.0 */
5287 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5288 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5289 LARGE_INTEGER fullVersion
;
5291 pMinor
= strchrW(pVersion
, '.');
5295 pRevision
= strchrW(++pMinor
, '.');
5296 Minor
= atoiW(pMinor
);
5301 pBuild
= strchrW(++pRevision
, '.');
5302 Revision
= atoiW(pRevision
);
5308 Build
= atoiW(pBuild
);
5310 Major
= atoiW(pVersion
);
5311 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5312 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5313 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5320 HeapFree(GetProcessHeap(), 0, ProviderName
);
5321 HeapFree(GetProcessHeap(), 0, DriverVer
);
5326 /***********************************************************************
5327 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5330 SetupDiBuildDriverInfoList(
5331 IN HDEVINFO DeviceInfoSet
,
5332 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5333 IN DWORD DriverType
)
5335 struct DeviceInfoSet
*list
;
5336 SP_DEVINSTALL_PARAMS_W InstallParams
;
5337 PVOID Buffer
= NULL
;
5338 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5339 LPWSTR ProviderName
= NULL
;
5340 LPWSTR ManufacturerName
= NULL
;
5341 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5342 LPWSTR HardwareIDs
= NULL
;
5343 LPWSTR CompatibleIDs
= NULL
;
5344 LPWSTR FullInfFileName
= NULL
;
5345 FILETIME DriverDate
;
5346 DWORDLONG DriverVersion
= 0;
5350 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5353 SetLastError(ERROR_INVALID_HANDLE
);
5354 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5355 SetLastError(ERROR_INVALID_HANDLE
);
5356 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5357 SetLastError(ERROR_INVALID_HANDLE
);
5358 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5359 SetLastError(ERROR_INVALID_PARAMETER
);
5360 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
5361 SetLastError(ERROR_INVALID_PARAMETER
);
5362 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5363 SetLastError(ERROR_INVALID_PARAMETER
);
5364 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5365 SetLastError(ERROR_INVALID_USER_BUFFER
);
5370 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
5371 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5375 if (DriverType
== SPDIT_COMPATDRIVER
)
5377 /* Get hardware IDs list */
5379 RequiredSize
= 512; /* Initial buffer size */
5380 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5381 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5383 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5384 HardwareIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5387 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5390 Result
= SetupDiGetDeviceRegistryPropertyW(
5402 /* Get compatible IDs list */
5404 RequiredSize
= 512; /* Initial buffer size */
5405 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5406 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5408 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5409 CompatibleIDs
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
5412 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5415 Result
= SetupDiGetDeviceRegistryPropertyW(
5418 SPDRP_COMPATIBLEIDS
,
5420 (PBYTE
)CompatibleIDs
,
5423 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5425 /* No compatible ID for this device */
5426 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5427 CompatibleIDs
= NULL
;
5435 /* Enumerate .inf files */
5437 RequiredSize
= 32768; /* Initial buffer size */
5438 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5439 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5441 HeapFree(GetProcessHeap(), 0, Buffer
);
5442 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5446 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5449 Result
= SetupGetInfFileListW(
5450 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5452 Buffer
, RequiredSize
,
5455 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5457 /* No .inf file in specified directory. So, we should
5458 * success as we created an empty driver info list.
5466 LPWSTR pFullFilename
;
5468 if (*InstallParams
.DriverPath
)
5471 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5474 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5475 if (!FullInfFileName
)
5477 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5480 if (*FullInfFileName
&& FullInfFileName
[wcslen(FullInfFileName
) - 1] != '\\')
5481 wcscat(FullInfFileName
, L
"\\");
5482 pFullFilename
= &FullInfFileName
[wcslen(FullInfFileName
)];
5486 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5487 if (!FullInfFileName
)
5489 pFullFilename
= &FullInfFileName
[0];
5492 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= wcslen(filename
) + 1)
5494 INFCONTEXT ContextManufacturer
, ContextDevice
;
5497 wcscpy(pFullFilename
, filename
);
5498 TRACE("Opening file %S\n", FullInfFileName
);
5500 currentInfFileDetails
= HeapAlloc(
5503 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + wcslen(FullInfFileName
) * sizeof(WCHAR
) + UNICODE_NULL
);
5504 if (!currentInfFileDetails
)
5506 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5507 wcscpy(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5509 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5510 ReferenceInfFile(currentInfFileDetails
);
5511 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5513 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5514 currentInfFileDetails
= NULL
;
5518 if (!GetVersionInformationFromInfFile(
5519 currentInfFileDetails
->hInf
,
5525 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5526 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5527 currentInfFileDetails
= NULL
;
5531 if (DriverType
== SPDIT_CLASSDRIVER
)
5533 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5534 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5540 /* Get the manufacturers list */
5541 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, L
"Manufacturer", NULL
, &ContextManufacturer
);
5544 Result
= SetupGetStringFieldW(
5545 &ContextManufacturer
,
5546 0, /* Field index */
5551 /* We got the needed size for the buffer */
5552 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5553 if (!ManufacturerName
)
5555 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5558 Result
= SetupGetStringFieldW(
5559 &ContextManufacturer
,
5560 0, /* Field index */
5561 ManufacturerName
, RequiredSize
,
5564 /* Get manufacturer section name */
5565 Result
= SetupGetStringFieldW(
5566 &ContextManufacturer
,
5567 1, /* Field index */
5568 ManufacturerSection
, LINE_LEN
,
5572 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5573 /* Add (possible) extension to manufacturer section name */
5574 Result
= SetupDiGetActualSectionToInstallW(
5575 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5578 TRACE("Enumerating devices in manufacturer %S\n", ManufacturerSection
);
5579 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5584 if (DriverType
== SPDIT_CLASSDRIVER
)
5586 /* FIXME: read [ControlFlags] / ExcludeFromSelect */
5587 if (!AddDriverToList(
5588 &list
->DriverListHead
,
5592 currentInfFileDetails
,
5597 DriverDate
, DriverVersion
,
5603 else /* DriverType = SPDIT_COMPATDRIVER */
5605 /* 1. Get all fields */
5606 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5610 BOOL DriverAlreadyAdded
;
5612 for (i
= 2; i
<= FieldCount
; i
++)
5614 LPWSTR DeviceId
= NULL
;
5616 RequiredSize
= 128; /* Initial buffer size */
5617 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5618 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5620 HeapFree(GetProcessHeap(), 0, DeviceId
);
5621 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5624 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5627 Result
= SetupGetStringFieldW(
5630 DeviceId
, RequiredSize
,
5635 HeapFree(GetProcessHeap(), 0, DeviceId
);
5638 DriverAlreadyAdded
= FALSE
;
5639 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5641 if (wcsicmp(DeviceId
, currentId
) == 0)
5644 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5648 currentInfFileDetails
,
5653 DriverDate
, DriverVersion
,
5654 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5655 DriverAlreadyAdded
= TRUE
;
5660 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= wcslen(currentId
) + 1, DriverRank
++)
5662 if (wcsicmp(DeviceId
, currentId
) == 0)
5665 &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
,
5669 currentInfFileDetails
,
5674 DriverDate
, DriverVersion
,
5675 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5676 DriverAlreadyAdded
= TRUE
;
5680 HeapFree(GetProcessHeap(), 0, DeviceId
);
5683 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5686 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5687 ManufacturerName
= NULL
;
5688 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5693 HeapFree(GetProcessHeap(), 0, ProviderName
);
5694 ProviderName
= NULL
;
5696 DereferenceInfFile(currentInfFileDetails
);
5697 currentInfFileDetails
= NULL
;
5708 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5709 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5713 InstallParams
.Flags
|= DI_DIDCLASS
;
5714 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5716 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5719 HeapFree(GetProcessHeap(), 0, ProviderName
);
5720 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5721 HeapFree(GetProcessHeap(), 0, HardwareIDs
);
5722 HeapFree(GetProcessHeap(), 0, CompatibleIDs
);
5723 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5724 if (currentInfFileDetails
)
5725 DereferenceInfFile(currentInfFileDetails
);
5726 HeapFree(GetProcessHeap(), 0, Buffer
);
5728 TRACE("Returning %d\n", ret
);
5732 /***********************************************************************
5733 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5736 SetupDiDeleteDeviceInfo(
5737 IN HDEVINFO DeviceInfoSet
,
5738 IN PSP_DEVINFO_DATA DeviceInfoData
)
5740 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5742 FIXME("not implemented\n");
5743 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5748 /***********************************************************************
5749 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5752 SetupDiDestroyDriverInfoList(
5753 IN HDEVINFO DeviceInfoSet
,
5754 IN PSP_DEVINFO_DATA DeviceInfoData
,
5755 IN DWORD DriverType
)
5757 struct DeviceInfoSet
*list
;
5760 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5763 SetLastError(ERROR_INVALID_HANDLE
);
5764 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5765 SetLastError(ERROR_INVALID_HANDLE
);
5766 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5767 SetLastError(ERROR_INVALID_PARAMETER
);
5768 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5769 SetLastError(ERROR_INVALID_PARAMETER
);
5770 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5771 SetLastError(ERROR_INVALID_USER_BUFFER
);
5774 PLIST_ENTRY ListEntry
;
5775 struct DriverInfoElement
*driverInfo
;
5776 SP_DEVINSTALL_PARAMS_W InstallParams
;
5778 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5779 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
5782 if (!DeviceInfoData
)
5783 /* Fall back to destroying class driver list */
5784 DriverType
= SPDIT_CLASSDRIVER
;
5786 if (DriverType
== SPDIT_CLASSDRIVER
)
5788 while (!IsListEmpty(&list
->DriverListHead
))
5790 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
5791 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5792 DestroyDriverInfoElement(driverInfo
);
5794 InstallParams
.Reserved
= 0;
5795 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
5796 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
5797 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
5801 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
5802 struct DeviceInfoElement
*deviceInfo
;
5804 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5805 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
5807 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5808 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
5810 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
5811 driverInfo
= (struct DriverInfoElement
*)ListEntry
;
5812 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
5814 InstallParamsSet
.Reserved
= 0;
5815 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
5817 DestroyDriverInfoElement(driverInfo
);
5819 InstallParams
.Reserved
= 0;
5820 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
5821 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
5822 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5827 TRACE("Returning %d\n", ret
);
5832 /***********************************************************************
5833 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
5836 SetupDiOpenDeviceInfoA(
5837 IN HDEVINFO DeviceInfoSet
,
5838 IN PCSTR DeviceInstanceId
,
5839 IN HWND hwndParent OPTIONAL
,
5841 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5843 LPWSTR DeviceInstanceIdW
= NULL
;
5846 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5848 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
5849 if (DeviceInstanceIdW
== NULL
)
5852 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
5853 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
5855 MyFree(DeviceInstanceIdW
);
5861 /***********************************************************************
5862 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
5865 SetupDiOpenDeviceInfoW(
5866 IN HDEVINFO DeviceInfoSet
,
5867 IN PCWSTR DeviceInstanceId
,
5868 IN HWND hwndParent OPTIONAL
,
5870 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5872 struct DeviceInfoSet
*list
;
5873 HKEY hEnumKey
, hKey
;
5877 TRACE("%p %S %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
5879 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
5880 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
5883 SetLastError(ERROR_INVALID_HANDLE
);
5884 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5885 SetLastError(ERROR_INVALID_HANDLE
);
5886 else if (!DeviceInstanceId
)
5887 SetLastError(ERROR_INVALID_PARAMETER
);
5888 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
5890 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
5891 SetLastError(ERROR_INVALID_FLAGS
);
5893 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5894 SetLastError(ERROR_INVALID_USER_BUFFER
);
5897 struct DeviceInfoElement
*deviceInfo
= NULL
;
5898 /* Search if device already exists in DeviceInfoSet.
5899 * If yes, return the existing element
5900 * If no, create a new element using informations in registry
5902 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
5903 while (ItemList
!= &list
->ListHead
)
5908 FIXME("not implemented\n");
5909 ItemList
= ItemList
->Flink
;
5914 /* good one found */
5919 /* Open supposed registry key */
5922 REGSTR_PATH_SYSTEMENUM
,
5926 if (rc
!= ERROR_SUCCESS
)
5937 RegCloseKey(hEnumKey
);
5938 if (rc
!= ERROR_SUCCESS
)
5940 if (rc
== ERROR_FILE_NOT_FOUND
)
5941 rc
= ERROR_NO_SUCH_DEVINST
;
5946 /* FIXME: try to get ClassGUID from registry, instead of
5947 * sending GUID_NULL to CreateDeviceInfoElement
5949 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
5954 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5960 if (ret
&& deviceInfo
&& DeviceInfoData
)
5962 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
5963 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5964 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5972 /***********************************************************************
5973 * SetupDiEnumDriverInfoA (SETUPAPI.@)
5976 SetupDiEnumDriverInfoA(
5977 IN HDEVINFO DeviceInfoSet
,
5978 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5979 IN DWORD DriverType
,
5980 IN DWORD MemberIndex
,
5981 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
5983 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
5986 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
5987 DriverType
, MemberIndex
, DriverInfoData
);
5989 if (DriverInfoData
== NULL
)
5990 SetLastError(ERROR_INVALID_PARAMETER
);
5991 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
5992 SetLastError(ERROR_INVALID_USER_BUFFER
);
5995 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
5996 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
5997 DriverType
, MemberIndex
, &driverInfoData2W
);
6001 /* Do W->A conversion */
6002 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6003 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6004 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6005 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6007 DriverInfoData
->Description
[0] = '\0';
6010 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6011 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6013 DriverInfoData
->MfgName
[0] = '\0';
6016 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6017 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6019 DriverInfoData
->ProviderName
[0] = '\0';
6022 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6024 /* Copy more fields */
6025 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6026 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6031 TRACE("Returning %d\n", ret
);
6036 /***********************************************************************
6037 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6040 SetupDiEnumDriverInfoW(
6041 IN HDEVINFO DeviceInfoSet
,
6042 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6043 IN DWORD DriverType
,
6044 IN DWORD MemberIndex
,
6045 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6047 PLIST_ENTRY ListHead
;
6050 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6051 DriverType
, MemberIndex
, DriverInfoData
);
6053 if (!DeviceInfoSet
|| !DriverInfoData
)
6054 SetLastError(ERROR_INVALID_PARAMETER
);
6055 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6056 SetLastError(ERROR_INVALID_HANDLE
);
6057 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6058 SetLastError(ERROR_INVALID_HANDLE
);
6059 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6060 SetLastError(ERROR_INVALID_PARAMETER
);
6061 else if (DriverType
== SPDIT_CLASSDRIVER
&& DeviceInfoData
)
6062 SetLastError(ERROR_INVALID_PARAMETER
);
6063 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6064 SetLastError(ERROR_INVALID_PARAMETER
);
6065 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6066 SetLastError(ERROR_INVALID_USER_BUFFER
);
6069 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6070 PLIST_ENTRY ItemList
;
6071 if (DriverType
== SPDIT_CLASSDRIVER
||
6072 devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
)
6074 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6078 ListHead
= &devInfo
->DriverListHead
;
6081 ItemList
= ListHead
->Flink
;
6082 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
6083 ItemList
= ItemList
->Flink
;
6084 if (ItemList
== ListHead
)
6085 SetLastError(ERROR_NO_MORE_ITEMS
);
6088 struct DriverInfoElement
*DrvInfo
= (struct DriverInfoElement
*)ItemList
;
6091 &DriverInfoData
->DriverType
,
6092 &DrvInfo
->Info
.DriverType
,
6093 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6098 TRACE("Returning %d\n", ret
);
6103 /***********************************************************************
6104 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6107 SetupDiGetSelectedDriverA(
6108 IN HDEVINFO DeviceInfoSet
,
6109 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6110 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6112 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6115 if (DriverInfoData
== NULL
)
6116 SetLastError(ERROR_INVALID_PARAMETER
);
6117 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6118 SetLastError(ERROR_INVALID_USER_BUFFER
);
6121 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6123 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
6129 /* Do W->A conversion */
6130 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6131 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6132 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6133 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6135 DriverInfoData
->Description
[0] = '\0';
6138 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6139 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6141 DriverInfoData
->MfgName
[0] = '\0';
6144 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6145 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6147 DriverInfoData
->ProviderName
[0] = '\0';
6150 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6152 /* Copy more fields */
6153 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6154 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6163 /***********************************************************************
6164 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6167 SetupDiGetSelectedDriverW(
6168 IN HDEVINFO DeviceInfoSet
,
6169 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6170 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6174 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6176 if (!DeviceInfoSet
|| !DriverInfoData
)
6177 SetLastError(ERROR_INVALID_PARAMETER
);
6178 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6179 SetLastError(ERROR_INVALID_HANDLE
);
6180 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6181 SetLastError(ERROR_INVALID_HANDLE
);
6182 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6183 SetLastError(ERROR_INVALID_USER_BUFFER
);
6184 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6185 SetLastError(ERROR_INVALID_USER_BUFFER
);
6188 SP_DEVINSTALL_PARAMS InstallParams
;
6190 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
6191 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6193 struct DriverInfoElement
*driverInfo
;
6194 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6195 if (driverInfo
== NULL
)
6196 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6200 &DriverInfoData
->DriverType
,
6201 &driverInfo
->Info
.DriverType
,
6202 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6208 TRACE("Returning %d\n", ret
);
6213 /***********************************************************************
6214 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6217 SetupDiSetSelectedDriverA(
6218 IN HDEVINFO DeviceInfoSet
,
6219 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6220 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6222 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6223 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6226 if (DriverInfoData
!= NULL
)
6228 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6229 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6231 SetLastError(ERROR_INVALID_PARAMETER
);
6235 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6236 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6238 if (DriverInfoDataW
.Reserved
== 0)
6240 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6242 /* convert the strings to unicode */
6243 if (!MultiByteToWideChar(CP_ACP
,
6245 DriverInfoData
->Description
,
6247 DriverInfoDataW
.Description
,
6249 !MultiByteToWideChar(CP_ACP
,
6251 DriverInfoData
->ProviderName
,
6253 DriverInfoDataW
.ProviderName
,
6260 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6263 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6267 if (ret
&& pDriverInfoDataW
!= NULL
)
6269 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6276 /***********************************************************************
6277 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6280 SetupDiSetSelectedDriverW(
6281 IN HDEVINFO DeviceInfoSet
,
6282 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6283 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6287 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6290 SetLastError(ERROR_INVALID_PARAMETER
);
6291 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6292 SetLastError(ERROR_INVALID_HANDLE
);
6293 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6294 SetLastError(ERROR_INVALID_HANDLE
);
6295 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6296 SetLastError(ERROR_INVALID_USER_BUFFER
);
6297 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6298 SetLastError(ERROR_INVALID_USER_BUFFER
);
6301 struct DriverInfoElement
**pDriverInfo
;
6302 PLIST_ENTRY ListHead
, ItemList
;
6306 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6307 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6311 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6312 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6315 if (!DriverInfoData
)
6317 *pDriverInfo
= NULL
;
6322 /* Search selected driver in list */
6323 ItemList
= ListHead
->Flink
;
6324 while (ItemList
!= ListHead
)
6326 if (DriverInfoData
->Reserved
!= 0)
6328 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6333 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6334 struct DriverInfoElement
*driverInfo
= (struct DriverInfoElement
*)ItemList
;
6335 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6336 && wcscmp(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6337 && wcscmp(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6343 if (ItemList
== ListHead
)
6344 SetLastError(ERROR_INVALID_PARAMETER
);
6347 *pDriverInfo
= (struct DriverInfoElement
*)ItemList
;
6348 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6350 TRACE("Choosing driver whose rank is 0x%lx\n",
6351 ((struct DriverInfoElement
*)ItemList
)->DriverRank
);
6353 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6358 TRACE("Returning %d\n", ret
);
6362 /***********************************************************************
6363 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6366 SetupDiGetDriverInfoDetailA(
6367 IN HDEVINFO DeviceInfoSet
,
6368 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6369 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6370 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6371 IN DWORD DriverInfoDetailDataSize
,
6372 OUT PDWORD RequiredSize OPTIONAL
)
6374 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6375 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6377 DWORD HardwareIDLen
= 0;
6380 /* do some sanity checks, the unicode version might do more thorough checks */
6381 if (DriverInfoData
== NULL
||
6382 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6383 (DriverInfoDetailData
!= NULL
&&
6384 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6385 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6387 SetLastError(ERROR_INVALID_PARAMETER
);
6391 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6392 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6394 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6396 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6398 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6402 SetLastError(ERROR_INVALID_PARAMETER
);
6405 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6406 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6408 /* convert the strings to unicode */
6409 if (MultiByteToWideChar(CP_ACP
,
6411 DriverInfoData
->Description
,
6413 DriverInfoDataW
.Description
,
6415 MultiByteToWideChar(CP_ACP
,
6417 DriverInfoData
->MfgName
,
6419 DriverInfoDataW
.MfgName
,
6421 MultiByteToWideChar(CP_ACP
,
6423 DriverInfoData
->ProviderName
,
6425 DriverInfoDataW
.ProviderName
,
6428 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6430 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6431 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6434 if (DriverInfoDetailData
!= NULL
)
6436 /* calculate the unicode buffer size from the ansi buffer size */
6437 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6438 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6439 (HardwareIDLen
* sizeof(WCHAR
));
6441 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6442 if (DriverInfoDetailDataW
== NULL
)
6444 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6448 /* initialize the buffer */
6449 ZeroMemory(DriverInfoDetailDataW
,
6451 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6454 /* call the unicode version */
6455 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6458 DriverInfoDetailDataW
,
6464 if (DriverInfoDetailDataW
!= NULL
)
6466 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6467 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6468 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6469 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6470 if (WideCharToMultiByte(CP_ACP
,
6472 DriverInfoDetailDataW
->SectionName
,
6474 DriverInfoDetailData
->SectionName
,
6478 WideCharToMultiByte(CP_ACP
,
6480 DriverInfoDetailDataW
->InfFileName
,
6482 DriverInfoDetailData
->InfFileName
,
6486 WideCharToMultiByte(CP_ACP
,
6488 DriverInfoDetailDataW
->DrvDescription
,
6490 DriverInfoDetailData
->DrvDescription
,
6494 WideCharToMultiByte(CP_ACP
,
6496 DriverInfoDetailDataW
->HardwareID
,
6498 DriverInfoDetailData
->HardwareID
,
6504 DWORD hwidlen
= HardwareIDLen
;
6505 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6507 /* count the strings in the list */
6510 len
= lstrlenA(s
) + 1;
6519 /* looks like the string list wasn't terminated... */
6520 SetLastError(ERROR_INVALID_USER_BUFFER
);
6526 /* make sure CompatIDsOffset points to the second string in the
6530 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6531 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6532 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6536 DriverInfoDetailData
->CompatIDsOffset
= 0;
6537 DriverInfoDetailData
->CompatIDsLength
= 0;
6546 if (RequiredSize
!= NULL
)
6548 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6549 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6555 if (DriverInfoDetailDataW
!= NULL
)
6557 MyFree(DriverInfoDetailDataW
);
6563 /***********************************************************************
6564 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6567 SetupDiGetDriverInfoDetailW(
6568 IN HDEVINFO DeviceInfoSet
,
6569 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6570 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6571 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6572 IN DWORD DriverInfoDetailDataSize
,
6573 OUT PDWORD RequiredSize OPTIONAL
)
6577 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6578 DriverInfoData
, DriverInfoDetailData
,
6579 DriverInfoDetailDataSize
, RequiredSize
);
6582 SetLastError(ERROR_INVALID_PARAMETER
);
6583 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6584 SetLastError(ERROR_INVALID_HANDLE
);
6585 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6586 SetLastError(ERROR_INVALID_HANDLE
);
6587 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6588 SetLastError(ERROR_INVALID_USER_BUFFER
);
6589 else if (!DriverInfoData
)
6590 SetLastError(ERROR_INVALID_PARAMETER
);
6591 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6592 SetLastError(ERROR_INVALID_PARAMETER
);
6593 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6594 SetLastError(ERROR_INVALID_PARAMETER
);
6595 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6596 SetLastError(ERROR_INVALID_USER_BUFFER
);
6597 else if (DriverInfoData
->Reserved
== 0)
6598 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6601 struct DriverInfoElement
*driverInfoElement
;
6602 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6605 DriverInfoDetailData
,
6606 &driverInfoElement
->Details
,
6607 driverInfoElement
->Details
.cbSize
);
6608 /* FIXME: copy HardwareIDs/CompatibleIDs if buffer is big enough
6609 * Don't forget to set CompatIDsOffset and CompatIDsLength fields.
6614 TRACE("Returning %d\n", ret
);
6618 /* Return the current hardware profile id, or -1 if error */
6620 GetCurrentHwProfile(
6621 IN HDEVINFO DeviceInfoSet
)
6623 HKEY hKey
= INVALID_HANDLE_VALUE
;
6624 DWORD dwRegType
, dwLength
;
6627 DWORD ret
= (DWORD
)-1;
6630 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
6631 REGSTR_PATH_IDCONFIGDB
,
6635 if (rc
!= ERROR_SUCCESS
)
6641 dwLength
= sizeof(DWORD
);
6642 rc
= RegQueryValueExW(
6644 REGSTR_VAL_CURRENTCONFIG
,
6647 (LPBYTE
)&hwProfile
, &dwLength
);
6648 if (rc
!= ERROR_SUCCESS
)
6653 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6655 SetLastError(ERROR_GEN_FAILURE
);
6662 if (hKey
!= INVALID_HANDLE_VALUE
)
6670 IN HDEVINFO DeviceInfoSet
,
6671 IN PSP_DEVINFO_DATA DeviceInfoData
)
6673 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
6674 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6677 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
6679 /* At the moment, I only know how to start local devices */
6680 SetLastError(ERROR_INVALID_COMPUTERNAME
);
6684 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
6685 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
6686 SetLastError(RtlNtStatusToDosError(Status
));
6687 return NT_SUCCESS(Status
);
6690 static BOOL
StopDevice(
6691 IN HDEVINFO DeviceInfoSet
,
6692 IN PSP_DEVINFO_DATA DeviceInfoData
)
6694 FIXME("Stub %p %p\n", DeviceInfoSet
, DeviceInfoData
);
6698 /***********************************************************************
6699 * SetupDiChangeState (SETUPAPI.@)
6703 IN HDEVINFO DeviceInfoSet
,
6704 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6706 PSP_PROPCHANGE_PARAMS PropChange
;
6707 HKEY hKey
= INVALID_HANDLE_VALUE
;
6708 LPCWSTR RegistryValueName
;
6709 DWORD dwConfigFlags
, dwLength
, dwRegType
;
6713 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6715 if (!DeviceInfoData
)
6716 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
6718 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
6721 SetLastError(ERROR_INVALID_PARAMETER
);
6725 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
6726 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
6728 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
6730 switch (PropChange
->StateChange
)
6735 /* Enable/disable device in registry */
6736 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
6737 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6738 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
6739 if (hKey
== INVALID_HANDLE_VALUE
)
6741 dwLength
= sizeof(DWORD
);
6742 rc
= RegQueryValueExW(
6747 (LPBYTE
)&dwConfigFlags
, &dwLength
);
6748 if (rc
== ERROR_FILE_NOT_FOUND
)
6750 else if (rc
!= ERROR_SUCCESS
)
6755 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
6757 SetLastError(ERROR_GEN_FAILURE
);
6760 if (PropChange
->StateChange
== DICS_ENABLE
)
6761 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6763 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
6769 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
6770 if (rc
!= ERROR_SUCCESS
)
6776 /* Enable/disable device if needed */
6777 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
6778 || PropChange
->HwProfile
== 0
6779 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
6781 if (PropChange
->StateChange
== DICS_ENABLE
)
6782 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6784 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
6790 case DICS_PROPCHANGE
:
6792 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
6797 FIXME("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
6798 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
6803 if (hKey
!= INVALID_HANDLE_VALUE
)
6806 TRACE("Returning %d\n", ret
);
6810 /***********************************************************************
6811 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
6814 SetupDiSelectBestCompatDrv(
6815 IN HDEVINFO DeviceInfoSet
,
6816 IN PSP_DEVINFO_DATA DeviceInfoData
)
6818 SP_DRVINFO_DATA_W drvInfoData
;
6821 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6823 /* Drivers are sorted by rank in the driver list, so
6824 * the first driver in the list is the best one.
6826 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
6827 ret
= SetupDiEnumDriverInfoW(
6831 0, /* Member index */
6836 ret
= SetupDiSetSelectedDriverW(
6842 TRACE("Returning %d\n", ret
);
6846 /***********************************************************************
6847 * SetupDiInstallDriverFiles (SETUPAPI.@)
6850 SetupDiInstallDriverFiles(
6851 IN HDEVINFO DeviceInfoSet
,
6852 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6856 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6859 SetLastError(ERROR_INVALID_PARAMETER
);
6860 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6861 SetLastError(ERROR_INVALID_HANDLE
);
6862 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6863 SetLastError(ERROR_INVALID_HANDLE
);
6864 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6865 SetLastError(ERROR_INVALID_USER_BUFFER
);
6866 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
6867 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6868 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
6869 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6872 SP_DEVINSTALL_PARAMS_W InstallParams
;
6873 struct DriverInfoElement
*SelectedDriver
;
6874 WCHAR SectionName
[MAX_PATH
];
6875 DWORD SectionNameLength
= 0;
6877 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6878 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6882 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6883 if (!SelectedDriver
)
6885 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6889 ret
= SetupDiGetActualSectionToInstallW(
6890 SelectedDriver
->InfFileDetails
->hInf
,
6891 SelectedDriver
->Details
.SectionName
,
6892 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6896 if (!InstallParams
.InstallMsgHandler
)
6898 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6899 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6900 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6902 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6903 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6904 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
6905 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6906 DeviceInfoSet
, DeviceInfoData
);
6910 TRACE("Returning %d\n", ret
);
6914 /***********************************************************************
6915 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
6918 SetupDiRegisterCoDeviceInstallers(
6919 IN HDEVINFO DeviceInfoSet
,
6920 IN PSP_DEVINFO_DATA DeviceInfoData
)
6922 BOOL ret
= FALSE
; /* Return value */
6924 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6927 SetLastError(ERROR_INVALID_PARAMETER
);
6928 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6929 SetLastError(ERROR_INVALID_HANDLE
);
6930 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6931 SetLastError(ERROR_INVALID_HANDLE
);
6932 else if (!DeviceInfoData
)
6933 SetLastError(ERROR_INVALID_PARAMETER
);
6934 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6935 SetLastError(ERROR_INVALID_USER_BUFFER
);
6938 SP_DEVINSTALL_PARAMS_W InstallParams
;
6939 struct DriverInfoElement
*SelectedDriver
;
6942 WCHAR SectionName
[MAX_PATH
];
6943 DWORD SectionNameLength
= 0;
6944 HKEY hKey
= INVALID_HANDLE_VALUE
;
6946 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6947 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6951 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6952 if (SelectedDriver
== NULL
)
6954 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6958 /* Get .CoInstallers section name */
6959 Result
= SetupDiGetActualSectionToInstallW(
6960 SelectedDriver
->InfFileDetails
->hInf
,
6961 SelectedDriver
->Details
.SectionName
,
6962 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
6963 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(L
".CoInstallers") - 1)
6965 wcscat(SectionName
, L
".CoInstallers");
6967 /* Open/Create driver key information */
6968 #if _WIN32_WINNT >= 0x502
6969 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
6971 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
6973 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6974 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
6975 if (hKey
== INVALID_HANDLE_VALUE
)
6978 /* Install .CoInstallers section */
6979 DoAction
= SPINST_REGISTRY
;
6980 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
6982 DoAction
|= SPINST_FILES
;
6983 if (!InstallParams
.InstallMsgHandler
)
6985 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
6986 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
6987 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6990 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
6991 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
6992 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
6993 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
6994 DeviceInfoSet
, DeviceInfoData
);
7001 if (hKey
!= INVALID_HANDLE_VALUE
)
7005 TRACE("Returning %d\n", ret
);
7009 /***********************************************************************
7010 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7013 SetupDiInstallDeviceInterfaces(
7014 IN HDEVINFO DeviceInfoSet
,
7015 IN PSP_DEVINFO_DATA DeviceInfoData
)
7017 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7019 FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n");
7020 //SetLastError(ERROR_GEN_FAILURE);
7026 InfIsFromOEMLocation(
7028 OUT LPBOOL IsOEMLocation
)
7032 last
= strrchrW(FullName
, '\\');
7035 /* No directory specified */
7036 *IsOEMLocation
= FALSE
;
7040 WCHAR Windir
[MAX_PATH
];
7043 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
7044 if (ret
== 0 || ret
>= MAX_PATH
)
7046 SetLastError(ERROR_GEN_FAILURE
);
7050 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
7052 /* The path is %SYSTEMROOT%\Inf */
7053 *IsOEMLocation
= FALSE
;
7057 /* The file is in another place */
7058 *IsOEMLocation
= TRUE
;
7064 /***********************************************************************
7065 * SetupDiInstallDevice (SETUPAPI.@)
7068 SetupDiInstallDevice(
7069 IN HDEVINFO DeviceInfoSet
,
7070 IN PSP_DEVINFO_DATA DeviceInfoData
)
7072 SP_DEVINSTALL_PARAMS_W InstallParams
;
7073 struct DriverInfoElement
*SelectedDriver
;
7074 SYSTEMTIME DriverDate
;
7075 WCHAR SectionName
[MAX_PATH
];
7077 DWORD SectionNameLength
= 0;
7078 BOOL Result
= FALSE
;
7081 LPCWSTR AssociatedService
= NULL
;
7082 LPWSTR pSectionName
= NULL
;
7083 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
7085 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
7086 BOOL RebootRequired
= FALSE
;
7087 HKEY hKey
= INVALID_HANDLE_VALUE
;
7088 HKEY hClassKey
= INVALID_HANDLE_VALUE
;
7089 BOOL NeedtoCopyFile
;
7090 LARGE_INTEGER fullVersion
;
7092 BOOL ret
= FALSE
; /* Return value */
7094 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7097 SetLastError(ERROR_INVALID_PARAMETER
);
7098 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7099 SetLastError(ERROR_INVALID_HANDLE
);
7100 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7101 SetLastError(ERROR_INVALID_HANDLE
);
7102 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7103 SetLastError(ERROR_INVALID_USER_BUFFER
);
7109 /* One parameter is bad */
7113 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7114 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7118 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
7120 /* FIXME: set FAILEDINSTALL in ConfigFlags registry value */
7124 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7125 if (SelectedDriver
== NULL
)
7127 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7131 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
7133 Result
= SetupDiGetActualSectionToInstallW(
7134 SelectedDriver
->InfFileDetails
->hInf
,
7135 SelectedDriver
->Details
.SectionName
,
7136 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7137 if (!Result
|| SectionNameLength
> MAX_PATH
- wcslen(DotServices
))
7139 pSectionName
= &SectionName
[wcslen(SectionName
)];
7141 /* Get information from [Version] section */
7142 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
7144 /* Format ClassGuid to a string */
7145 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
7147 RequiredSize
= lstrlenW(lpGuidString
);
7148 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
7149 if (!lpFullGuidString
)
7151 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7154 lpFullGuidString
[0] = '{';
7155 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
7156 lpFullGuidString
[RequiredSize
+ 1] = '}';
7157 lpFullGuidString
[RequiredSize
+ 2] = '\0';
7159 /* Open/Create driver key information */
7160 #if _WIN32_WINNT >= 0x502
7161 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7163 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7165 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7166 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7167 if (hKey
== INVALID_HANDLE_VALUE
)
7170 /* Install main section */
7171 DoAction
= SPINST_REGISTRY
;
7172 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7174 DoAction
|= SPINST_FILES
;
7175 if (!InstallParams
.InstallMsgHandler
)
7177 InstallParams
.InstallMsgHandler
= SetupDefaultQueueCallbackW
;
7178 InstallParams
.InstallMsgHandlerContext
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7179 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7182 *pSectionName
= '\0';
7183 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7184 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7185 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7186 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7187 DeviceInfoSet
, DeviceInfoData
);
7190 if (!(InstallParams
.Flags
& DI_NOFILECOPY
) && !(InstallParams
.Flags
& DI_NOVCP
))
7192 if (Result
&& InstallParams
.InstallMsgHandler
== SetupDefaultQueueCallbackW
)
7194 /* Delete resources allocated by SetupInitDefaultQueueCallback */
7195 SetupTermDefaultQueueCallback(InstallParams
.InstallMsgHandlerContext
);
7198 InstallParams
.Flags
|= DI_NOFILECOPY
;
7199 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7201 /* Write information to driver key */
7202 *pSectionName
= UNICODE_NULL
;
7203 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
7204 TRACE("Write information to driver key\n");
7205 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7206 TRACE("DriverDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7207 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7208 TRACE("InfPath : '%S'\n", SelectedDriver
->Details
.InfFileName
);
7209 TRACE("InfSection : '%S'\n", SelectedDriver
->Details
.SectionName
);
7210 TRACE("InfSectionExt : '%S'\n", &SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)]);
7211 TRACE("MatchingDeviceId: '%S'\n", SelectedDriver
->MatchingId
);
7212 TRACE("ProviderName : '%S'\n", SelectedDriver
->Info
.ProviderName
);
7213 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7214 rc
= RegSetValueEx(hKey
, L
"DriverDate", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7215 if (rc
== ERROR_SUCCESS
)
7216 rc
= RegSetValueEx(hKey
, L
"DriverDateData", 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7217 if (rc
== ERROR_SUCCESS
)
7218 rc
= RegSetValueEx(hKey
, L
"DriverDesc", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7219 if (rc
== ERROR_SUCCESS
)
7221 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7222 rc
= RegSetValueEx(hKey
, L
"DriverVersion", 0, REG_SZ
, (const BYTE
*)Buffer
, (wcslen(Buffer
) + 1) * sizeof(WCHAR
));
7224 if (rc
== ERROR_SUCCESS
)
7225 rc
= RegSetValueEx(hKey
, L
"InfPath", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (wcslen(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7226 if (rc
== ERROR_SUCCESS
)
7227 rc
= RegSetValueEx(hKey
, L
"InfSection", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7228 if (rc
== ERROR_SUCCESS
)
7229 rc
= RegSetValueEx(hKey
, L
"InfSectionExt", 0, REG_SZ
, (const BYTE
*)&SectionName
[wcslen(SelectedDriver
->Details
.SectionName
)], (wcslen(SectionName
) - wcslen(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7230 if (rc
== ERROR_SUCCESS
)
7231 rc
= RegSetValueEx(hKey
, L
"MatchingDeviceId", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (wcslen(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7232 if (rc
== ERROR_SUCCESS
)
7233 rc
= RegSetValueEx(hKey
, L
"ProviderName", 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (wcslen(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7234 if (rc
!= ERROR_SUCCESS
)
7240 hKey
= INVALID_HANDLE_VALUE
;
7242 /* FIXME: Process .LogConfigOverride section */
7244 /* Install .Services section */
7245 wcscpy(pSectionName
, DotServices
);
7246 Result
= InstallServicesSection(
7247 SelectedDriver
->InfFileDetails
->hInf
,
7256 /* Copy .inf file to Inf\ directory (if needed) */
7257 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7262 Result
= SetupCopyOEMInfW(
7263 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7266 SP_COPY_NOOVERWRITE
,
7272 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7273 * to release use of current InfFile */
7276 /* Open device registry key */
7277 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7278 if (hKey
== INVALID_HANDLE_VALUE
)
7281 /* Install .HW section */
7282 wcscpy(pSectionName
, L
".HW");
7283 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7284 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7285 SPINST_REGISTRY
, hKey
, NULL
, 0,
7286 InstallParams
.InstallMsgHandler
, InstallParams
.InstallMsgHandlerContext
,
7287 DeviceInfoSet
, DeviceInfoData
);
7291 /* Write information to enum key */
7292 TRACE("Write information to enum key\n");
7293 TRACE("Class : '%S'\n", ClassName
);
7294 TRACE("ClassGUID : '%S'\n", lpFullGuidString
);
7295 TRACE("DeviceDesc : '%S'\n", SelectedDriver
->Info
.Description
);
7296 TRACE("Mfg : '%S'\n", SelectedDriver
->Info
.MfgName
);
7297 TRACE("Service : '%S'\n", AssociatedService
);
7298 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (wcslen(ClassName
) + 1) * sizeof(WCHAR
));
7299 if (rc
== ERROR_SUCCESS
)
7300 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (wcslen(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7301 if (rc
== ERROR_SUCCESS
)
7302 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (wcslen(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7303 if (rc
== ERROR_SUCCESS
)
7304 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (wcslen(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7305 if (rc
== ERROR_SUCCESS
&& AssociatedService
&& *AssociatedService
)
7306 rc
= RegSetValueEx(hKey
, REGSTR_VAL_SERVICE
, 0, REG_SZ
, (const BYTE
*)AssociatedService
, (wcslen(AssociatedService
) + 1) * sizeof(WCHAR
));
7307 if (rc
!= ERROR_SUCCESS
)
7313 /* Start the device */
7314 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7315 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7320 /* End of installation */
7321 if (hClassKey
!= INVALID_HANDLE_VALUE
)
7322 RegCloseKey(hClassKey
);
7323 if (hKey
!= INVALID_HANDLE_VALUE
)
7326 RpcStringFreeW(&lpGuidString
);
7327 HeapFree(GetProcessHeap(), 0, (LPWSTR
)AssociatedService
);
7328 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7330 TRACE("Returning %d\n", ret
);