2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 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
22 #include "setupapi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
26 /* Unicode constants */
27 static const WCHAR AddInterface
[] = {'A','d','d','I','n','t','e','r','f','a','c','e',0};
28 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class
[] = {'C','l','a','s','s',0};
30 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
31 static const WCHAR Control
[] = {'C','o','n','t','r','o','l',0};
32 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
33 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
34 static const WCHAR DotHW
[] = {'.','H','W',0};
35 static const WCHAR DotInterfaces
[] = {'.','I','n','t','e','r','f','a','c','e','s',0};
36 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
37 static const WCHAR InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
38 static const WCHAR Linked
[] = {'L','i','n','k','e','d',0};
39 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
40 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
42 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
43 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
44 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
45 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
46 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT
[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
48 static const WCHAR INF_MANUFACTURER
[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
49 static const WCHAR INF_PROVIDER
[] = {'P','r','o','v','i','d','e','r',0};
50 static const WCHAR INF_DRIVER_VER
[] = {'D','r','i','v','e','r','V','e','r',0};
53 (CALLBACK
* CLASS_INSTALL_PROC
) (
54 IN DI_FUNCTION InstallFunction
,
55 IN HDEVINFO DeviceInfoSet
,
56 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
58 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
59 IN HDEVINFO DeviceInfoSet
,
60 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
62 (CALLBACK
* COINSTALLER_PROC
) (
63 IN DI_FUNCTION InstallFunction
,
64 IN HDEVINFO DeviceInfoSet
,
65 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
66 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
68 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
69 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
70 IN LPFNADDPROPSHEETPAGE fAddFunc
,
73 (*UPDATE_CLASS_PARAM_HANDLER
) (
74 IN HDEVINFO DeviceInfoSet
,
75 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
76 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
77 IN DWORD ClassInstallParamsSize
);
79 struct CoInstallerElement
84 COINSTALLER_PROC Function
;
85 BOOL DoPostProcessing
;
90 PropertyChangeHandler(
91 IN HDEVINFO DeviceInfoSet
,
92 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
93 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
94 IN DWORD ClassInstallParamsSize
);
96 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
97 NULL
, /* DIF_SELECTDEVICE */
98 NULL
, /* DIF_INSTALLDEVICE */
99 NULL
, /* DIF_ASSIGNRESOURCES */
100 NULL
, /* DIF_PROPERTIES */
101 NULL
, /* DIF_REMOVE */
102 NULL
, /* DIF_FIRSTTIMESETUP */
103 NULL
, /* DIF_FOUNDDEVICE */
104 NULL
, /* DIF_SELECTCLASSDRIVERS */
105 NULL
, /* DIF_VALIDATECLASSDRIVERS */
106 NULL
, /* DIF_INSTALLCLASSDRIVERS */
107 NULL
, /* DIF_CALCDISKSPACE */
108 NULL
, /* DIF_DESTROYPRIVATEDATA */
109 NULL
, /* DIF_VALIDATEDRIVER */
110 NULL
, /* DIF_MOVEDEVICE */
111 NULL
, /* DIF_DETECT */
112 NULL
, /* DIF_INSTALLWIZARD */
113 NULL
, /* DIF_DESTROYWIZARDDATA */
114 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
115 NULL
, /* DIF_ENABLECLASS */
116 NULL
, /* DIF_DETECTVERIFY */
117 NULL
, /* DIF_INSTALLDEVICEFILES */
118 NULL
, /* DIF_UNREMOVE */
119 NULL
, /* DIF_SELECTBESTCOMPATDRV */
120 NULL
, /* DIF_ALLOW_INSTALL */
121 NULL
, /* DIF_REGISTERDEVICE */
122 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
123 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
124 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
125 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
126 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
127 NULL
, /* DIF_UNUSED1 */
128 NULL
, /* DIF_INSTALLINTERFACES */
129 NULL
, /* DIF_DETECTCANCEL */
130 NULL
, /* DIF_REGISTER_COINSTALLERS */
131 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
132 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
133 NULL
, /* DIF_RESERVED1 */
134 NULL
, /* DIF_TROUBLESHOOTER */
135 NULL
, /* DIF_POWERMESSAGEWAKE */
136 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
137 NULL
, /* DIF_UPDATEDRIVER_UI */
138 NULL
/* DIF_RESERVED2 */
141 /***********************************************************************
142 * SetupDiBuildClassInfoList (SETUPAPI.@)
144 BOOL WINAPI
SetupDiBuildClassInfoList(
146 LPGUID ClassGuidList
,
147 DWORD ClassGuidListSize
,
151 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
152 ClassGuidListSize
, RequiredSize
,
156 /***********************************************************************
157 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
159 BOOL WINAPI
SetupDiBuildClassInfoListExA(
161 LPGUID ClassGuidList
,
162 DWORD ClassGuidListSize
,
167 LPWSTR MachineNameW
= NULL
;
174 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
175 if (MachineNameW
== NULL
) return FALSE
;
178 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
179 ClassGuidListSize
, RequiredSize
,
180 MachineNameW
, Reserved
);
183 MyFree(MachineNameW
);
188 /***********************************************************************
189 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
191 BOOL WINAPI
SetupDiBuildClassInfoListExW(
193 LPGUID ClassGuidList
,
194 DWORD ClassGuidListSize
,
199 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
205 DWORD dwGuidListIndex
= 0;
207 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
208 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
210 if (RequiredSize
!= NULL
)
213 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
214 KEY_ENUMERATE_SUB_KEYS
,
218 if (hClassesKey
== INVALID_HANDLE_VALUE
)
223 for (dwIndex
= 0; ; dwIndex
++)
225 dwLength
= MAX_GUID_STRING_LEN
+ 1;
226 lError
= RegEnumKeyExW(hClassesKey
,
234 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
235 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
237 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
239 if (RegOpenKeyExW(hClassesKey
,
245 RegCloseKey(hClassesKey
);
249 if (!RegQueryValueExW(hClassKey
,
250 REGSTR_VAL_NOUSECLASS
,
256 TRACE("'NoUseClass' value found!\n");
257 RegCloseKey(hClassKey
);
261 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
262 (!RegQueryValueExW(hClassKey
,
263 REGSTR_VAL_NOINSTALLCLASS
,
269 TRACE("'NoInstallClass' value found!\n");
270 RegCloseKey(hClassKey
);
274 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
275 (!RegQueryValueExW(hClassKey
,
276 REGSTR_VAL_NODISPLAYCLASS
,
282 TRACE("'NoDisplayClass' value found!\n");
283 RegCloseKey(hClassKey
);
287 RegCloseKey(hClassKey
);
289 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
290 if (dwGuidListIndex
< ClassGuidListSize
)
292 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
296 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
298 UuidFromStringW(&szKeyName
[1],
299 &ClassGuidList
[dwGuidListIndex
]);
305 if (lError
!= ERROR_SUCCESS
)
309 RegCloseKey(hClassesKey
);
311 if (RequiredSize
!= NULL
)
312 *RequiredSize
= dwGuidListIndex
;
314 if (ClassGuidListSize
< dwGuidListIndex
)
316 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
323 /***********************************************************************
324 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
326 BOOL WINAPI
SetupDiClassGuidsFromNameA(
328 LPGUID ClassGuidList
,
329 DWORD ClassGuidListSize
,
332 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
333 ClassGuidListSize
, RequiredSize
,
337 /***********************************************************************
338 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
340 BOOL WINAPI
SetupDiClassGuidsFromNameW(
342 LPGUID ClassGuidList
,
343 DWORD ClassGuidListSize
,
346 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
347 ClassGuidListSize
, RequiredSize
,
351 /***********************************************************************
352 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
354 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
356 LPGUID ClassGuidList
,
357 DWORD ClassGuidListSize
,
362 LPWSTR ClassNameW
= NULL
;
363 LPWSTR MachineNameW
= NULL
;
368 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
369 if (ClassNameW
== NULL
)
374 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
375 if (MachineNameW
== NULL
)
382 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
383 ClassGuidListSize
, RequiredSize
,
384 MachineNameW
, Reserved
);
387 MyFree(MachineNameW
);
394 /***********************************************************************
395 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
397 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
399 LPGUID ClassGuidList
,
400 DWORD ClassGuidListSize
,
405 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
406 WCHAR szClassName
[256];
412 DWORD dwGuidListIndex
= 0;
414 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
415 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
417 if (RequiredSize
!= NULL
)
420 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
421 KEY_ENUMERATE_SUB_KEYS
,
425 if (hClassesKey
== INVALID_HANDLE_VALUE
)
430 for (dwIndex
= 0; ; dwIndex
++)
432 dwLength
= MAX_GUID_STRING_LEN
+ 1;
433 lError
= RegEnumKeyExW(hClassesKey
,
441 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
442 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
444 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
446 if (RegOpenKeyExW(hClassesKey
,
452 RegCloseKey(hClassesKey
);
456 dwLength
= 256 * sizeof(WCHAR
);
457 if (!RegQueryValueExW(hClassKey
,
464 TRACE("Class name: %s\n", debugstr_w(szClassName
));
466 if (strcmpiW(szClassName
, ClassName
) == 0)
468 TRACE("Found matching class name\n");
470 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
471 if (dwGuidListIndex
< ClassGuidListSize
)
473 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
477 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
479 UuidFromStringW(&szKeyName
[1],
480 &ClassGuidList
[dwGuidListIndex
]);
487 RegCloseKey(hClassKey
);
490 if (lError
!= ERROR_SUCCESS
)
494 RegCloseKey(hClassesKey
);
496 if (RequiredSize
!= NULL
)
497 *RequiredSize
= dwGuidListIndex
;
499 if (ClassGuidListSize
< dwGuidListIndex
)
501 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
508 /***********************************************************************
509 * SetupDiClassNameFromGuidA (SETUPAPI.@)
511 BOOL WINAPI
SetupDiClassNameFromGuidA(
512 const GUID
* ClassGuid
,
517 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
518 ClassNameSize
, RequiredSize
,
522 /***********************************************************************
523 * SetupDiClassNameFromGuidW (SETUPAPI.@)
525 BOOL WINAPI
SetupDiClassNameFromGuidW(
526 const GUID
* ClassGuid
,
531 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
532 ClassNameSize
, RequiredSize
,
536 /***********************************************************************
537 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
539 BOOL WINAPI
SetupDiClassNameFromGuidExA(
540 const GUID
* ClassGuid
,
547 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
548 LPWSTR MachineNameW
= NULL
;
552 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
553 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
554 NULL
, MachineNameW
, Reserved
);
557 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
558 ClassNameSize
, NULL
, NULL
);
560 if (!ClassNameSize
&& RequiredSize
)
563 MyFree(MachineNameW
);
567 /***********************************************************************
568 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
570 BOOL WINAPI
SetupDiClassNameFromGuidExW(
571 const GUID
* ClassGuid
,
582 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
583 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
585 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
590 if (hKey
== INVALID_HANDLE_VALUE
)
595 if (RequiredSize
!= NULL
)
598 rc
= RegQueryValueExW(hKey
,
604 if (rc
!= ERROR_SUCCESS
)
611 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
614 dwLength
= ClassNameSize
* sizeof(WCHAR
);
615 rc
= RegQueryValueExW(hKey
,
621 if (rc
!= ERROR_SUCCESS
)
633 /***********************************************************************
634 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
637 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
640 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
643 /***********************************************************************
644 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
647 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
652 LPWSTR MachineNameW
= NULL
;
655 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
656 debugstr_a(MachineName
), Reserved
);
660 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
661 if (MachineNameW
== NULL
)
662 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
665 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
666 MachineNameW
, Reserved
);
669 MyFree(MachineNameW
);
675 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
679 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
680 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
681 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
682 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
683 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
684 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
685 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
686 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
687 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
688 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
689 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
690 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
691 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
692 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
693 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
694 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
695 case CR_SUCCESS
: return ERROR_SUCCESS
;
696 default: return ERROR_GEN_FAILURE
;
699 /* Does not happen */
702 /***********************************************************************
703 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
706 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
711 struct DeviceInfoSet
*list
;
712 LPWSTR UNCServerName
= NULL
;
716 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
718 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
719 debugstr_w(MachineName
), Reserved
);
721 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
723 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
724 list
= HeapAlloc(GetProcessHeap(), 0, size
);
727 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
730 memset(list
, 0, sizeof(struct DeviceInfoSet
));
732 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
735 ClassGuid
? ClassGuid
: &GUID_NULL
,
736 sizeof(list
->ClassGuid
));
737 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
738 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
739 list
->InstallParams
.hwndParent
= hwndParent
;
742 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
743 if (rc
!= ERROR_SUCCESS
)
748 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
751 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
755 strcpyW(UNCServerName
+ 2, MachineName
);
756 list
->szData
[0] = list
->szData
[1] = '\\';
757 strcpyW(list
->szData
+ 2, MachineName
);
758 list
->MachineName
= list
->szData
;
762 DWORD Size
= MAX_PATH
;
763 list
->HKLM
= HKEY_LOCAL_MACHINE
;
764 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
767 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
770 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
772 list
->MachineName
= NULL
;
775 UNCServerName
[0] = UNCServerName
[1] = '\\';
776 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
777 if (cr
!= CR_SUCCESS
)
779 SetLastError(GetErrorCodeFromCrCode(cr
));
783 InitializeListHead(&list
->DriverListHead
);
784 InitializeListHead(&list
->ListHead
);
786 ret
= (HDEVINFO
)list
;
789 if (ret
== INVALID_HANDLE_VALUE
)
791 if (list
&& list
->HKLM
!= 0 && list
->HKLM
!= HKEY_LOCAL_MACHINE
)
792 RegCloseKey(list
->HKLM
);
793 HeapFree(GetProcessHeap(), 0, list
);
795 HeapFree(GetProcessHeap(), 0, UNCServerName
);
799 /***********************************************************************
800 * SetupDiEnumDeviceInfo (SETUPAPI.@)
802 BOOL WINAPI
SetupDiEnumDeviceInfo(
803 HDEVINFO DeviceInfoSet
,
805 PSP_DEVINFO_DATA DeviceInfoData
)
809 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
811 SetLastError(ERROR_INVALID_PARAMETER
);
812 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
814 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
816 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
817 SetLastError(ERROR_INVALID_HANDLE
);
818 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
819 SetLastError(ERROR_INVALID_USER_BUFFER
);
822 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
823 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
824 ItemList
= ItemList
->Flink
;
825 if (ItemList
== &list
->ListHead
)
826 SetLastError(ERROR_NO_MORE_ITEMS
);
829 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
830 memcpy(&DeviceInfoData
->ClassGuid
,
833 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
834 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
840 SetLastError(ERROR_INVALID_HANDLE
);
844 /***********************************************************************
845 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
848 SetupDiGetActualSectionToInstallA(
850 IN PCSTR InfSectionName
,
851 OUT PSTR InfSectionWithExt OPTIONAL
,
852 IN DWORD InfSectionWithExtSize
,
853 OUT PDWORD RequiredSize OPTIONAL
,
854 OUT PSTR
*Extension OPTIONAL
)
856 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
857 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
861 /***********************************************************************
862 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
865 SetupDiGetActualSectionToInstallW(
867 IN PCWSTR InfSectionName
,
868 OUT PWSTR InfSectionWithExt OPTIONAL
,
869 IN DWORD InfSectionWithExtSize
,
870 OUT PDWORD RequiredSize OPTIONAL
,
871 OUT PWSTR
*Extension OPTIONAL
)
873 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
874 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
878 /***********************************************************************
879 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
882 SetupDiGetActualSectionToInstallExA(
884 IN PCSTR InfSectionName
,
885 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
886 OUT PSTR InfSectionWithExt OPTIONAL
,
887 IN DWORD InfSectionWithExtSize
,
888 OUT PDWORD RequiredSize OPTIONAL
,
889 OUT PSTR
* Extension OPTIONAL
,
892 LPWSTR InfSectionNameW
= NULL
;
893 LPWSTR InfSectionWithExtW
= NULL
;
895 BOOL bResult
= FALSE
;
901 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
902 if (InfSectionNameW
== NULL
)
905 if (InfSectionWithExt
)
907 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
908 if (InfSectionWithExtW
== NULL
)
912 bResult
= SetupDiGetActualSectionToInstallExW(
913 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
914 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
915 InfSectionWithExtSize
,
917 Extension
? &ExtensionW
: NULL
,
920 if (bResult
&& InfSectionWithExt
)
922 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
923 InfSectionWithExtSize
, NULL
, NULL
) != 0;
925 if (bResult
&& Extension
)
927 if (ExtensionW
== NULL
)
930 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
934 MyFree(InfSectionNameW
);
935 MyFree(InfSectionWithExtW
);
940 /***********************************************************************
941 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
944 SetupDiGetActualSectionToInstallExW(
946 IN PCWSTR InfSectionName
,
947 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
948 OUT PWSTR InfSectionWithExt OPTIONAL
,
949 IN DWORD InfSectionWithExtSize
,
950 OUT PDWORD RequiredSize OPTIONAL
,
951 OUT PWSTR
* Extension OPTIONAL
,
956 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
957 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
958 RequiredSize
, Extension
, Reserved
);
960 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
961 SetLastError(ERROR_INVALID_HANDLE
);
962 else if (!InfSectionName
)
963 SetLastError(ERROR_INVALID_PARAMETER
);
964 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
965 SetLastError(ERROR_INVALID_USER_BUFFER
);
966 else if (Reserved
!= NULL
)
967 SetLastError(ERROR_INVALID_PARAMETER
);
970 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
971 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
972 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
973 WCHAR SectionName
[LINE_LEN
+ 1];
974 LONG lLineCount
= -1;
977 /* Fill platform info if needed */
978 if (AlternatePlatformInfo
)
979 pPlatformInfo
= AlternatePlatformInfo
;
980 else if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
982 /* That's the first time we go here. We need to fill in the structure */
983 OSVERSIONINFO VersionInfo
;
984 SYSTEM_INFO SystemInfo
;
985 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
986 ret
= GetVersionEx(&VersionInfo
);
989 GetSystemInfo(&SystemInfo
);
990 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
991 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
992 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
993 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
994 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
995 CurrentPlatform
.Reserved
= 0;
998 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
999 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
1000 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
1002 static const WCHAR ExtensionArchitectureNone
[] = {0};
1003 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
1004 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
1005 static const WCHAR ExtensionArchitectureia64
[] = {'i','a','6','4',0};
1006 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
1007 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
1008 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
1010 /* Set various extensions values */
1011 switch (pPlatformInfo
->Platform
)
1013 case VER_PLATFORM_WIN32_WINDOWS
:
1014 pExtensionPlatform
= ExtensionPlatformWindows
;
1016 case VER_PLATFORM_WIN32_NT
:
1017 pExtensionPlatform
= ExtensionPlatformNT
;
1020 ERR("Unkown platform 0x%lx\n", pPlatformInfo
->Platform
);
1021 pExtensionPlatform
= ExtensionPlatformNone
;
1024 switch (pPlatformInfo
->ProcessorArchitecture
)
1026 case PROCESSOR_ARCHITECTURE_ALPHA
:
1027 pExtensionArchitecture
= ExtensionArchitecturealpha
;
1029 case PROCESSOR_ARCHITECTURE_AMD64
:
1030 pExtensionArchitecture
= ExtensionArchitectureamd64
;
1032 case PROCESSOR_ARCHITECTURE_IA64
:
1033 pExtensionArchitecture
= ExtensionArchitectureia64
;
1035 case PROCESSOR_ARCHITECTURE_INTEL
:
1036 pExtensionArchitecture
= ExtensionArchitecturex86
;
1038 case PROCESSOR_ARCHITECTURE_MIPS
:
1039 pExtensionArchitecture
= ExtensionArchitecturemips
;
1041 case PROCESSOR_ARCHITECTURE_PPC
:
1042 pExtensionArchitecture
= ExtensionArchitectureppc
;
1045 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo
->ProcessorArchitecture
);
1046 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
1047 pExtensionArchitecture
= ExtensionArchitectureNone
;
1051 static const WCHAR FormatPlatformArchitectureMajorMinor
[] = {'%','s','%','s','%','s','.','%','l','u','.','%','l','u',0};
1052 static const WCHAR FormatPlatformMajorMinor
[] = {'%','s','%','s','.','%','l','u','.','%','l','u',0};
1053 static const WCHAR FormatPlatformArchitectureMajor
[] = {'%','s','%','s','%','s','.','%','l','u',0};
1054 static const WCHAR FormatPlatformMajor
[] = {'%','s','%','s','.','%','l','u',0};
1055 static const WCHAR FormatPlatformArchitecture
[] = {'%','s','%','s','%','s',0};
1056 static const WCHAR FormatPlatform
[] = {'%','s','%','s',0};
1057 static const WCHAR FormatNone
[] = {'%','s',0};
1059 SectionName
[LINE_LEN
] = UNICODE_NULL
;
1061 /* Test with platform.architecture.major.minor extension */
1062 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitectureMajorMinor
, InfSectionName
,
1063 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1064 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1065 if (lLineCount
!= -1) goto sectionfound
;
1067 /* Test with platform.major.minor extension */
1068 snprintfW(SectionName
, LINE_LEN
, FormatPlatformMajorMinor
, InfSectionName
,
1069 pExtensionPlatform
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1070 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1071 if (lLineCount
!= -1) goto sectionfound
;
1073 /* Test with platform.architecture.major extension */
1074 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitectureMajor
, InfSectionName
,
1075 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
);
1076 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1077 if (lLineCount
!= -1) goto sectionfound
;
1079 /* Test with platform.major extension */
1080 snprintfW(SectionName
, LINE_LEN
, FormatPlatformMajor
, InfSectionName
,
1081 pExtensionPlatform
, pPlatformInfo
->MajorVersion
);
1082 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1083 if (lLineCount
!= -1) goto sectionfound
;
1085 /* Test with platform.architecture extension */
1086 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitecture
, InfSectionName
,
1087 pExtensionPlatform
, pExtensionArchitecture
);
1088 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1089 if (lLineCount
!= -1) goto sectionfound
;
1091 /* Test with platform extension */
1092 snprintfW(SectionName
, LINE_LEN
, FormatPlatform
, InfSectionName
,
1093 pExtensionPlatform
);
1094 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1095 if (lLineCount
!= -1) goto sectionfound
;
1097 /* Test without extension */
1098 snprintfW(SectionName
, LINE_LEN
, FormatNone
, InfSectionName
);
1099 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1100 if (lLineCount
!= -1) goto sectionfound
;
1102 /* No appropriate section found */
1103 SetLastError(ERROR_INVALID_PARAMETER
);
1107 dwFullLength
= lstrlenW(SectionName
);
1108 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
1110 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
1112 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1116 lstrcpyW(InfSectionWithExt
, SectionName
);
1117 if (Extension
!= NULL
)
1119 DWORD dwLength
= lstrlenW(SectionName
);
1120 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1124 if (RequiredSize
!= NULL
)
1125 *RequiredSize
= dwFullLength
+ 1;
1131 TRACE("Returning %d\n", ret
);
1136 /***********************************************************************
1137 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1139 BOOL WINAPI
SetupDiGetClassDescriptionA(
1140 const GUID
* ClassGuid
,
1141 PSTR ClassDescription
,
1142 DWORD ClassDescriptionSize
,
1143 PDWORD RequiredSize
)
1145 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1146 ClassDescriptionSize
,
1147 RequiredSize
, NULL
, NULL
);
1150 /***********************************************************************
1151 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1153 BOOL WINAPI
SetupDiGetClassDescriptionW(
1154 const GUID
* ClassGuid
,
1155 PWSTR ClassDescription
,
1156 DWORD ClassDescriptionSize
,
1157 PDWORD RequiredSize
)
1159 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1160 ClassDescriptionSize
,
1161 RequiredSize
, NULL
, NULL
);
1164 /***********************************************************************
1165 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1167 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1168 const GUID
* ClassGuid
,
1169 PSTR ClassDescription
,
1170 DWORD ClassDescriptionSize
,
1171 PDWORD RequiredSize
,
1175 PWCHAR ClassDescriptionW
;
1176 LPWSTR MachineNameW
= NULL
;
1180 if (ClassDescriptionSize
> 0)
1182 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1183 if (!ClassDescriptionW
)
1185 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1191 ClassDescriptionW
= NULL
;
1195 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1198 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1204 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1205 NULL
, MachineNameW
, Reserved
);
1208 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1209 ClassDescriptionSize
, NULL
, NULL
);
1211 if (!ClassDescriptionSize
&& RequiredSize
)
1212 *RequiredSize
= len
;
1216 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1217 MyFree(MachineNameW
);
1221 /***********************************************************************
1222 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1224 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1225 const GUID
* ClassGuid
,
1226 PWSTR ClassDescription
,
1227 DWORD ClassDescriptionSize
,
1228 PDWORD RequiredSize
,
1235 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1236 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1238 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1243 if (hKey
== INVALID_HANDLE_VALUE
)
1245 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1249 if (RequiredSize
!= NULL
)
1252 if (RegQueryValueExW(hKey
,
1263 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1266 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1267 if (RegQueryValueExW(hKey
,
1271 (LPBYTE
)ClassDescription
,
1283 /***********************************************************************
1284 * SetupDiGetClassDevsA (SETUPAPI.@)
1286 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1292 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1293 flags
, NULL
, NULL
, NULL
);
1296 /***********************************************************************
1297 * SetupDiGetClassDevsW (SETUPAPI.@)
1299 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1305 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1306 flags
, NULL
, NULL
, NULL
);
1309 /***********************************************************************
1310 * SetupDiGetClassDevsExA (SETUPAPI.@)
1312 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1322 LPWSTR enumstrW
= NULL
;
1323 LPWSTR machineW
= NULL
;
1327 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1328 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1331 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1334 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1338 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1339 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1342 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1345 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1347 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1350 HeapFree(GetProcessHeap(), 0, enumstrW
);
1351 HeapFree(GetProcessHeap(), 0, machineW
);
1356 CreateDeviceInfoElement(
1357 IN
struct DeviceInfoSet
*list
,
1358 IN LPCWSTR InstancePath
,
1359 IN LPCGUID pClassGuid
,
1360 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1364 struct DeviceInfoElement
*deviceInfo
;
1366 *pDeviceInfo
= NULL
;
1368 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
1369 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1372 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1375 memset(deviceInfo
, 0, size
);
1377 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1378 if (cr
!= CR_SUCCESS
)
1380 SetLastError(GetErrorCodeFromCrCode(cr
));
1384 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1385 strcpyW(deviceInfo
->Data
, InstancePath
);
1386 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1387 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
1388 deviceInfo
->DeviceDescription
= NULL
;
1389 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1390 deviceInfo
->CreationFlags
= 0;
1391 InitializeListHead(&deviceInfo
->DriverListHead
);
1392 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1394 *pDeviceInfo
= deviceInfo
;
1399 CreateDeviceInterface(
1400 IN
struct DeviceInfoElement
* deviceInfo
,
1401 IN LPCWSTR SymbolicLink
,
1402 IN LPCGUID pInterfaceGuid
,
1403 OUT
struct DeviceInterface
**pDeviceInterface
)
1405 struct DeviceInterface
*deviceInterface
;
1407 *pDeviceInterface
= NULL
;
1409 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1410 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (strlenW(SymbolicLink
) + 1) * sizeof(WCHAR
));
1411 if (!deviceInterface
)
1413 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1416 deviceInterface
->DeviceInfo
= deviceInfo
;
1417 strcpyW(deviceInterface
->SymbolicLink
, SymbolicLink
);
1418 deviceInterface
->Flags
= 0; /* Flags will be updated later */
1419 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1421 *pDeviceInterface
= deviceInterface
;
1425 static LONG
SETUP_CreateDevListFromEnumerator(
1426 struct DeviceInfoSet
*list
,
1427 LPCGUID pClassGuid OPTIONAL
,
1429 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1431 HKEY hDeviceIdKey
, hInstanceIdKey
;
1432 WCHAR KeyBuffer
[MAX_PATH
];
1433 WCHAR InstancePath
[MAX_PATH
];
1434 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1435 struct DeviceInfoElement
*deviceInfo
;
1437 DWORD dwLength
, dwRegType
;
1440 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1443 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1444 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1445 if (rc
== ERROR_NO_MORE_ITEMS
)
1447 if (rc
!= ERROR_SUCCESS
)
1451 /* Open device id sub key */
1452 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1453 if (rc
!= ERROR_SUCCESS
)
1455 strcpyW(InstancePath
, Enumerator
);
1456 strcatW(InstancePath
, L
"\\");
1457 strcatW(InstancePath
, KeyBuffer
);
1458 strcatW(InstancePath
, L
"\\");
1459 pEndOfInstancePath
= &InstancePath
[strlenW(InstancePath
)];
1461 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1467 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1468 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1469 if (rc
== ERROR_NO_MORE_ITEMS
)
1471 if (rc
!= ERROR_SUCCESS
)
1473 RegCloseKey(hDeviceIdKey
);
1478 /* Open instance id sub key */
1479 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1480 if (rc
!= ERROR_SUCCESS
)
1482 RegCloseKey(hDeviceIdKey
);
1485 *pEndOfInstancePath
= '\0';
1486 strcatW(InstancePath
, KeyBuffer
);
1488 /* Read ClassGUID value */
1489 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1490 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1491 RegCloseKey(hInstanceIdKey
);
1492 if (rc
== ERROR_FILE_NOT_FOUND
)
1495 /* Skip this bad entry as we can't verify it */
1497 /* Set a default GUID for this device */
1498 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1500 else if (rc
!= ERROR_SUCCESS
)
1502 RegCloseKey(hDeviceIdKey
);
1505 else if (dwRegType
!= REG_SZ
)
1507 RegCloseKey(hDeviceIdKey
);
1508 return ERROR_GEN_FAILURE
;
1512 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1513 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1514 /* Bad GUID, skip the entry */
1518 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1520 /* Skip this entry as it is not the right device class */
1524 /* Add the entry to the list */
1525 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1527 RegCloseKey(hDeviceIdKey
);
1528 return GetLastError();
1530 TRACE("Adding '%s' to device info set %p\n", debugstr_w(InstancePath
), list
);
1531 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1533 RegCloseKey(hDeviceIdKey
);
1536 return ERROR_SUCCESS
;
1539 static LONG
SETUP_CreateDevList(
1540 struct DeviceInfoSet
*list
,
1541 PCWSTR MachineName OPTIONAL
,
1542 LPGUID
class OPTIONAL
,
1543 PCWSTR Enumerator OPTIONAL
)
1545 HKEY HKLM
, hEnumKey
, hEnumeratorKey
;
1546 WCHAR KeyBuffer
[MAX_PATH
];
1551 if (class && IsEqualIID(class, &GUID_NULL
))
1555 if (MachineName
!= NULL
)
1557 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1558 if (rc
!= ERROR_SUCCESS
)
1562 HKLM
= HKEY_LOCAL_MACHINE
;
1564 rc
= RegOpenKeyExW(HKLM
,
1565 REGSTR_PATH_SYSTEMENUM
,
1567 KEY_ENUMERATE_SUB_KEYS
,
1569 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
1570 if (rc
!= ERROR_SUCCESS
)
1573 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1574 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1583 KEY_ENUMERATE_SUB_KEYS
,
1585 RegCloseKey(hEnumKey
);
1586 if (rc
!= ERROR_SUCCESS
)
1588 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1589 RegCloseKey(hEnumeratorKey
);
1594 /* Enumerate enumerators */
1598 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1599 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1600 if (rc
== ERROR_NO_MORE_ITEMS
)
1602 if (rc
!= ERROR_SUCCESS
)
1604 RegCloseKey(hEnumKey
);
1610 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1611 if (rc
!= ERROR_SUCCESS
)
1613 RegCloseKey(hEnumKey
);
1617 /* Call SETUP_CreateDevListFromEnumerator */
1618 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1619 RegCloseKey(hEnumeratorKey
);
1620 if (rc
!= ERROR_SUCCESS
)
1622 RegCloseKey(hEnumKey
);
1626 RegCloseKey(hEnumKey
);
1627 return ERROR_SUCCESS
;
1631 static BOOL
DestroyDeviceInterface(struct DeviceInterface
* deviceInterface
)
1633 HeapFree(GetProcessHeap(), 0, deviceInterface
);
1637 static LONG
SETUP_CreateInterfaceList(
1638 struct DeviceInfoSet
*list
,
1640 LPGUID InterfaceGuid
,
1641 PCWSTR DeviceInstanceW
/* OPTIONAL */,
1642 BOOL OnlyPresentInterfaces
1645 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1646 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1647 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1648 HKEY hControlKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */
1649 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1650 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1652 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1653 PWSTR pSymbolicLink
= NULL
;
1654 PWSTR InstancePath
= NULL
;
1656 DWORD dwLength
, dwInstancePathLength
;
1660 struct DeviceInfoElement
*deviceInfo
;
1662 hInterfaceKey
= INVALID_HANDLE_VALUE
;
1663 hDeviceInstanceKey
= INVALID_HANDLE_VALUE
;
1665 /* Open registry key related to this interface */
1666 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1667 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1669 rc
= GetLastError();
1673 /* Enumerate sub keys of hInterfaceKey */
1677 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1678 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1679 if (rc
== ERROR_NO_MORE_ITEMS
)
1681 if (rc
!= ERROR_SUCCESS
)
1686 if (hDeviceInstanceKey
!= INVALID_HANDLE_VALUE
)
1687 RegCloseKey(hDeviceInstanceKey
);
1688 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1689 if (rc
!= ERROR_SUCCESS
)
1692 /* Read DeviceInstance */
1693 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1694 if (rc
!= ERROR_SUCCESS
)
1696 if (dwRegType
!= REG_SZ
)
1698 rc
= ERROR_GEN_FAILURE
;
1701 if (InstancePath
!= NULL
)
1702 HeapFree(GetProcessHeap(), 0, InstancePath
);
1703 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1706 rc
= ERROR_NOT_ENOUGH_MEMORY
;
1709 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1710 if (rc
!= ERROR_SUCCESS
)
1712 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1713 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1715 if (DeviceInstanceW
)
1717 /* Check if device enumerator is not the right one */
1718 if (strcmpW(DeviceInstanceW
, InstancePath
) != 0)
1722 /* Find class GUID associated to the device instance */
1725 REGSTR_PATH_SYSTEMENUM
,
1729 if (rc
!= ERROR_SUCCESS
)
1737 RegCloseKey(hEnumKey
);
1738 if (rc
!= ERROR_SUCCESS
)
1740 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1741 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1743 if (rc
!= ERROR_SUCCESS
)
1745 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1746 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1747 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1749 rc
= ERROR_GEN_FAILURE
;
1752 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1754 /* If current device doesn't match the list GUID (if any), skip this entry */
1755 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1758 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1762 struct DeviceInterface
*interfaceInfo
;
1764 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1765 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1766 if (rc
== ERROR_NO_MORE_ITEMS
)
1768 if (rc
!= ERROR_SUCCESS
)
1771 if (KeyBuffer
[0] != '#')
1772 /* This entry doesn't represent an interesting entry */
1776 if (hReferenceKey
!= INVALID_HANDLE_VALUE
)
1777 RegCloseKey(hReferenceKey
);
1778 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1779 if (rc
!= ERROR_SUCCESS
)
1782 /* Read SymbolicLink value */
1783 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1784 if (rc
!= ERROR_SUCCESS
)
1786 if (dwRegType
!= REG_SZ
)
1788 rc
= ERROR_GEN_FAILURE
;
1792 /* We have found a device */
1793 /* Step 1. Create a device info element */
1794 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1796 rc
= GetLastError();
1799 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1800 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1802 /* Step 2. Create an interface list for this element */
1803 if (pSymbolicLink
!= NULL
)
1804 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1805 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1808 rc
= ERROR_NOT_ENOUGH_MEMORY
;
1811 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1812 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1813 RegCloseKey(hReferenceKey
);
1814 if (rc
!= ERROR_SUCCESS
)
1816 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1818 rc
= GetLastError();
1822 /* Step 3. Update flags */
1823 if (KeyBuffer
[1] == '\0')
1824 interfaceInfo
->Flags
|= SPINT_DEFAULT
;
1825 rc
= RegOpenKeyExW(hReferenceKey
, Control
, 0, KEY_QUERY_VALUE
, &hControlKey
);
1826 if (rc
!= ERROR_SUCCESS
)
1828 if (OnlyPresentInterfaces
)
1830 DestroyDeviceInterface(interfaceInfo
);
1834 interfaceInfo
->Flags
|= SPINT_REMOVED
;
1838 dwLength
= sizeof(DWORD
);
1839 if (RegQueryValueExW(hControlKey
, Linked
, NULL
, &dwRegType
, (LPBYTE
)&LinkedValue
, &dwLength
)
1840 && dwRegType
== REG_DWORD
&& LinkedValue
)
1841 interfaceInfo
->Flags
|= SPINT_ACTIVE
;
1842 RegCloseKey(hControlKey
);
1845 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1846 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1852 if (hReferenceKey
!= INVALID_HANDLE_VALUE
)
1853 RegCloseKey(hReferenceKey
);
1854 if (hDeviceInstanceKey
!= INVALID_HANDLE_VALUE
)
1855 RegCloseKey(hDeviceInstanceKey
);
1856 if (hInterfaceKey
!= INVALID_HANDLE_VALUE
)
1857 RegCloseKey(hInterfaceKey
);
1858 if (InstancePath
!= NULL
)
1859 HeapFree(GetProcessHeap(), 0, InstancePath
);
1860 if (pSymbolicLink
!= NULL
)
1861 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1865 /***********************************************************************
1866 * SetupDiGetClassDevsExW (SETUPAPI.@)
1868 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1877 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1878 struct DeviceInfoSet
*list
;
1882 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1883 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1885 /* Create the deviceset if not set */
1888 list
= (struct DeviceInfoSet
*)deviceset
;
1889 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1891 SetLastError(ERROR_INVALID_HANDLE
);
1892 return INVALID_HANDLE_VALUE
;
1894 hDeviceInfo
= deviceset
;
1898 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1899 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1900 NULL
, machine
, NULL
);
1901 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1902 return INVALID_HANDLE_VALUE
;
1903 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1906 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1909 pClassGuid
= &list
->ClassGuid
;
1911 if (flags
& DIGCF_PROFILE
)
1912 FIXME(": flag DIGCF_PROFILE ignored\n");
1914 if (flags
& DIGCF_ALLCLASSES
)
1916 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1917 if (rc
!= ERROR_SUCCESS
)
1921 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1922 return INVALID_HANDLE_VALUE
;
1926 else if (flags
& DIGCF_DEVICEINTERFACE
)
1930 SetLastError(ERROR_INVALID_PARAMETER
);
1932 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1933 return INVALID_HANDLE_VALUE
;
1936 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
, flags
& DIGCF_PRESENT
);
1937 if (rc
!= ERROR_SUCCESS
)
1941 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1942 return INVALID_HANDLE_VALUE
;
1948 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1949 if (rc
!= ERROR_SUCCESS
)
1953 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1954 return INVALID_HANDLE_VALUE
;
1960 /***********************************************************************
1961 * SetupDiGetClassImageIndex (SETUPAPI.@)
1964 static BOOL
GetIconIndex(
1966 OUT PINT ImageIndex
)
1968 LPWSTR Buffer
= NULL
;
1969 DWORD dwRegType
, dwLength
;
1973 /* Read icon registry key */
1974 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
1975 if (rc
!= ERROR_SUCCESS
)
1979 } else if (dwRegType
!= REG_SZ
)
1981 SetLastError(ERROR_INVALID_INDEX
);
1984 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
1987 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1990 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
1991 if (rc
!= ERROR_SUCCESS
)
1996 /* make sure the returned buffer is NULL-terminated */
1997 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
1999 /* Transform icon value to a INT */
2000 *ImageIndex
= atoiW(Buffer
);
2008 BOOL WINAPI
SetupDiGetClassImageIndex(
2009 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2010 IN CONST GUID
*ClassGuid
,
2011 OUT PINT ImageIndex
)
2013 struct ClassImageList
*list
;
2016 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2018 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2019 SetLastError(ERROR_INVALID_PARAMETER
);
2020 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2021 SetLastError(ERROR_INVALID_USER_BUFFER
);
2022 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2023 SetLastError(ERROR_INVALID_USER_BUFFER
);
2024 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2025 SetLastError(ERROR_INVALID_USER_BUFFER
);
2026 else if (!ImageIndex
)
2027 SetLastError(ERROR_INVALID_PARAMETER
);
2030 HKEY hKey
= INVALID_HANDLE_VALUE
;
2033 /* Read Icon registry entry into Buffer */
2034 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2035 if (hKey
== INVALID_HANDLE_VALUE
)
2037 if (!GetIconIndex(hKey
, &iconIndex
))
2042 SetLastError(ERROR_INVALID_INDEX
);
2046 *ImageIndex
= -iconIndex
;
2050 if (hKey
!= INVALID_HANDLE_VALUE
)
2054 TRACE("Returning %d\n", ret
);
2058 /***********************************************************************
2059 * SetupDiGetClassImageList(SETUPAPI.@)
2061 BOOL WINAPI
SetupDiGetClassImageList(
2062 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2064 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2067 /***********************************************************************
2068 * SetupDiGetClassImageListExA(SETUPAPI.@)
2070 BOOL WINAPI
SetupDiGetClassImageListExA(
2071 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2072 IN PCSTR MachineName OPTIONAL
,
2075 PWSTR MachineNameW
= NULL
;
2080 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2081 if (MachineNameW
== NULL
)
2085 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2088 MyFree(MachineNameW
);
2093 /***********************************************************************
2094 * SetupDiGetClassImageListExW(SETUPAPI.@)
2096 BOOL WINAPI
SetupDiGetClassImageListExW(
2097 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2098 IN PCWSTR MachineName OPTIONAL
,
2103 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2105 if (!ClassImageListData
)
2106 SetLastError(ERROR_INVALID_PARAMETER
);
2107 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2108 SetLastError(ERROR_INVALID_USER_BUFFER
);
2110 SetLastError(ERROR_INVALID_PARAMETER
);
2113 struct ClassImageList
*list
= NULL
;
2116 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2118 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
2119 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2122 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2125 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2128 list
->szData
[0] = list
->szData
[1] = '\\';
2129 strcpyW(list
->szData
+ 2, MachineName
);
2130 list
->MachineName
= list
->szData
;
2134 list
->MachineName
= NULL
;
2137 ClassImageListData
->Reserved
= (DWORD
)list
; /* FIXME: 64 bit portability issue */
2145 TRACE("Returning %d\n", ret
);
2149 /***********************************************************************
2150 * SetupDiLoadClassIcon(SETUPAPI.@)
2152 BOOL WINAPI
SetupDiLoadClassIcon(
2153 IN CONST GUID
*ClassGuid
,
2154 OUT HICON
*LargeIcon OPTIONAL
,
2155 OUT PINT MiniIconIndex OPTIONAL
)
2160 SetLastError(ERROR_INVALID_PARAMETER
);
2163 LPWSTR Buffer
= NULL
;
2166 HKEY hKey
= INVALID_HANDLE_VALUE
;
2168 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2169 if (hKey
== INVALID_HANDLE_VALUE
)
2172 if (!GetIconIndex(hKey
, &iconIndex
))
2177 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2180 DWORD dwRegType
, dwLength
;
2181 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2182 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2184 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2187 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2190 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2191 if (rc
!= ERROR_SUCCESS
)
2196 /* make sure the returned buffer is NULL-terminated */
2197 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2200 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2201 && dwRegType
== REG_SZ
)
2203 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2206 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2209 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2210 if (rc
!= ERROR_SUCCESS
)
2215 /* make sure the returned buffer is NULL-terminated */
2216 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2220 /* Unable to find where to load the icon */
2221 SetLastError(ERROR_FILE_NOT_FOUND
);
2224 Comma
= strchrW(Buffer
, ',');
2227 SetLastError(ERROR_GEN_FAILURE
);
2235 /* Look up icon in setupapi.dll */
2236 DllName
= L
"setupapi.dll";
2237 iconIndex
= -iconIndex
;
2240 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2243 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2245 SetLastError(ERROR_INVALID_INDEX
);
2250 *MiniIconIndex
= iconIndex
;
2254 if (hKey
!= INVALID_HANDLE_VALUE
)
2259 TRACE("Returning %d\n", ret
);
2263 /***********************************************************************
2264 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2266 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2267 HDEVINFO DeviceInfoSet
,
2268 PSP_DEVINFO_DATA DeviceInfoData
,
2269 CONST GUID
* InterfaceClassGuid
,
2271 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2275 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2276 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2278 if (!DeviceInterfaceData
)
2279 SetLastError(ERROR_INVALID_PARAMETER
);
2280 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2281 SetLastError(ERROR_INVALID_USER_BUFFER
);
2282 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2284 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2286 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2288 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2290 while (ItemList
!= &list
->ListHead
&& !Found
)
2292 PLIST_ENTRY InterfaceListEntry
;
2293 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)ItemList
;
2294 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2296 /* We are not searching for this element */
2297 ItemList
= ItemList
->Flink
;
2300 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2301 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2303 struct DeviceInterface
*DevItf
= (struct DeviceInterface
*)InterfaceListEntry
;
2304 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2306 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2309 if (MemberIndex
-- == 0)
2311 /* return this item */
2312 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2313 &DevItf
->InterfaceClassGuid
,
2315 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2316 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2319 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2321 ItemList
= ItemList
->Flink
;
2324 SetLastError(ERROR_NO_MORE_ITEMS
);
2329 SetLastError(ERROR_INVALID_HANDLE
);
2332 SetLastError(ERROR_INVALID_HANDLE
);
2336 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2338 InterlockedIncrement(&infFile
->References
);
2341 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2343 if (InterlockedDecrement(&infFile
->References
) == 0)
2345 SetupCloseInfFile(infFile
->hInf
);
2346 HeapFree(GetProcessHeap(), 0, infFile
);
2350 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2352 DereferenceInfFile(driverInfo
->InfFileDetails
);
2353 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2354 HeapFree(GetProcessHeap(), 0, driverInfo
);
2358 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2360 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2364 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2366 PLIST_ENTRY ListEntry
;
2367 struct DriverInfoElement
*driverInfo
;
2368 struct DeviceInterface
*deviceInterface
;
2370 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2372 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2373 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
2374 if (!DestroyDriverInfoElement(driverInfo
))
2377 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2379 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2380 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
2381 if (!DestroyDeviceInterface(deviceInterface
))
2384 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2385 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2389 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2391 PLIST_ENTRY ListEntry
;
2392 struct DeviceInfoElement
*deviceInfo
;
2394 while (!IsListEmpty(&list
->ListHead
))
2396 ListEntry
= RemoveHeadList(&list
->ListHead
);
2397 deviceInfo
= (struct DeviceInfoElement
*)ListEntry
;
2398 if (!DestroyDeviceInfoElement(deviceInfo
))
2401 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2402 RegCloseKey(list
->HKLM
);
2403 CM_Disconnect_Machine(list
->hMachine
);
2404 DestroyClassInstallParams(&list
->ClassInstallParams
);
2405 HeapFree(GetProcessHeap(), 0, list
);
2409 /***********************************************************************
2410 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2412 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2416 TRACE("%p\n", devinfo
);
2417 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2419 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2421 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2422 ret
= DestroyDeviceInfoSet(list
);
2424 SetLastError(ERROR_INVALID_HANDLE
);
2427 SetLastError(ERROR_INVALID_HANDLE
);
2429 TRACE("Returning %d\n", ret
);
2433 /***********************************************************************
2434 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2436 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2437 HDEVINFO DeviceInfoSet
,
2438 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2439 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2440 DWORD DeviceInterfaceDetailDataSize
,
2441 PDWORD RequiredSize
,
2442 PSP_DEVINFO_DATA DeviceInfoData
)
2444 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2445 DWORD sizeW
= 0, sizeA
;
2448 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2449 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2450 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2452 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2453 SetLastError(ERROR_INVALID_USER_BUFFER
);
2454 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2455 SetLastError(ERROR_INVALID_PARAMETER
);
2456 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2457 SetLastError(ERROR_INVALID_PARAMETER
);
2460 if (DeviceInterfaceDetailData
!= NULL
)
2462 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2463 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2464 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2465 if (!DeviceInterfaceDetailDataW
)
2467 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2470 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2472 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2473 ret
= SetupDiGetDeviceInterfaceDetailW(
2475 DeviceInterfaceData
,
2476 DeviceInterfaceDetailDataW
,
2480 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2481 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2483 *RequiredSize
= sizeA
;
2484 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2486 if (!WideCharToMultiByte(
2488 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2489 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2496 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2499 TRACE("Returning %d\n", ret
);
2503 /***********************************************************************
2504 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2506 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2507 HDEVINFO DeviceInfoSet
,
2508 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2509 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2510 DWORD DeviceInterfaceDetailDataSize
,
2511 PDWORD RequiredSize
,
2512 PSP_DEVINFO_DATA DeviceInfoData
)
2516 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2517 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2518 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2520 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2521 SetLastError(ERROR_INVALID_PARAMETER
);
2522 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2523 SetLastError(ERROR_INVALID_HANDLE
);
2524 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2525 SetLastError(ERROR_INVALID_HANDLE
);
2526 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2527 SetLastError(ERROR_INVALID_USER_BUFFER
);
2528 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2529 SetLastError(ERROR_INVALID_USER_BUFFER
);
2530 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2531 SetLastError(ERROR_INVALID_USER_BUFFER
);
2532 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2533 SetLastError(ERROR_INVALID_PARAMETER
);
2534 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2535 SetLastError(ERROR_INVALID_PARAMETER
);
2538 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2539 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2540 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2541 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2543 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2545 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2547 *RequiredSize
= sizeRequired
;
2551 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
2552 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2555 memcpy(&DeviceInfoData
->ClassGuid
,
2556 &deviceInterface
->DeviceInfo
->ClassGuid
,
2558 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2559 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2565 TRACE("Returning %d\n", ret
);
2569 /***********************************************************************
2570 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2572 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2574 PSP_DEVINFO_DATA DeviceInfoData
,
2576 PDWORD PropertyRegDataType
,
2577 PBYTE PropertyBuffer
,
2578 DWORD PropertyBufferSize
,
2579 PDWORD RequiredSize
)
2582 BOOL bIsStringProperty
;
2584 DWORD RequiredSizeA
, RequiredSizeW
;
2585 DWORD PropertyBufferSizeW
;
2586 PBYTE PropertyBufferW
;
2588 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2589 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2592 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2593 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2595 bResult
= SetupDiGetDeviceRegistryPropertyW(
2601 PropertyBufferSizeW
,
2604 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2606 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2608 if (bIsStringProperty
)
2609 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2611 RequiredSizeA
= RequiredSizeW
;
2613 *RequiredSize
= RequiredSizeA
;
2614 if (PropertyRegDataType
)
2615 *PropertyRegDataType
= RegType
;
2620 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2624 if (RequiredSizeA
<= PropertyBufferSize
)
2626 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2628 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2630 /* Last error is already set by WideCharToMultiByte */
2635 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2639 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2643 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2647 /***********************************************************************
2648 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2650 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2651 HDEVINFO DeviceInfoSet
,
2652 PSP_DEVINFO_DATA DeviceInfoData
,
2654 PDWORD PropertyRegDataType
,
2655 PBYTE PropertyBuffer
,
2656 DWORD PropertyBufferSize
,
2657 PDWORD RequiredSize
)
2659 HKEY hEnumKey
, hKey
;
2663 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2664 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2667 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2668 SetLastError(ERROR_INVALID_HANDLE
);
2669 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2670 SetLastError(ERROR_INVALID_HANDLE
);
2671 else if (!DeviceInfoData
)
2672 SetLastError(ERROR_INVALID_PARAMETER
);
2673 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2674 SetLastError(ERROR_INVALID_USER_BUFFER
);
2675 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2676 SetLastError(ERROR_INVALID_PARAMETER
);
2679 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2680 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2684 case SPDRP_CAPABILITIES
:
2686 case SPDRP_CLASSGUID
:
2687 case SPDRP_COMPATIBLEIDS
:
2688 case SPDRP_CONFIGFLAGS
:
2689 case SPDRP_DEVICEDESC
:
2691 case SPDRP_FRIENDLYNAME
:
2692 case SPDRP_HARDWAREID
:
2693 case SPDRP_LOCATION_INFORMATION
:
2694 case SPDRP_LOWERFILTERS
:
2696 case SPDRP_SECURITY
:
2698 case SPDRP_UI_NUMBER
:
2699 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2700 case SPDRP_UPPERFILTERS
:
2702 LPCWSTR RegistryPropertyName
;
2707 case SPDRP_CAPABILITIES
:
2708 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2710 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2711 case SPDRP_CLASSGUID
:
2712 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2713 case SPDRP_COMPATIBLEIDS
:
2714 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2715 case SPDRP_CONFIGFLAGS
:
2716 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2717 case SPDRP_DEVICEDESC
:
2718 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2720 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2721 case SPDRP_FRIENDLYNAME
:
2722 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2723 case SPDRP_HARDWAREID
:
2724 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2725 case SPDRP_LOCATION_INFORMATION
:
2726 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2727 case SPDRP_LOWERFILTERS
:
2728 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2730 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2731 case SPDRP_SECURITY
:
2732 RegistryPropertyName
= REGSTR_SECURITY
; break;
2734 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2735 case SPDRP_UI_NUMBER
:
2736 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2737 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2738 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
; break;
2739 case SPDRP_UPPERFILTERS
:
2740 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2742 /* Should not happen */
2743 RegistryPropertyName
= NULL
; break;
2746 /* Open registry key name */
2749 REGSTR_PATH_SYSTEMENUM
,
2753 if (rc
!= ERROR_SUCCESS
)
2764 RegCloseKey(hEnumKey
);
2765 if (rc
!= ERROR_SUCCESS
)
2770 /* Read registry entry */
2771 BufferSize
= PropertyBufferSize
;
2772 rc
= RegQueryValueExW(
2774 RegistryPropertyName
,
2775 NULL
, /* Reserved */
2776 PropertyRegDataType
,
2780 *RequiredSize
= BufferSize
;
2783 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2786 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2788 case ERROR_MORE_DATA
:
2789 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2798 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2800 DWORD required
= (strlenW(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2802 if (PropertyRegDataType
)
2803 *PropertyRegDataType
= REG_SZ
;
2805 *RequiredSize
= required
;
2806 if (PropertyBufferSize
>= required
)
2808 strcpyW((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2812 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2816 /*case SPDRP_BUSTYPEGUID:
2817 case SPDRP_LEGACYBUSTYPE:
2818 case SPDRP_BUSNUMBER:
2819 case SPDRP_ENUMERATOR_NAME:
2820 case SPDRP_SECURITY_SDS:
2822 case SPDRP_EXCLUSIVE:
2823 case SPDRP_CHARACTERISTICS:
2825 case SPDRP_DEVICE_POWER_DATA:*/
2826 #if (WINVER >= 0x501)
2827 /*case SPDRP_REMOVAL_POLICY:
2828 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2829 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2830 case SPDRP_INSTALL_STATE:*/
2835 ERR("Property 0x%lx not implemented\n", Property
);
2836 SetLastError(ERROR_NOT_SUPPORTED
);
2841 TRACE("Returning %d\n", ret
);
2845 /***********************************************************************
2846 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2848 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2849 IN HDEVINFO DeviceInfoSet
,
2850 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2852 IN CONST BYTE
*PropertyBuffer
,
2853 IN DWORD PropertyBufferSize
)
2855 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2856 Property
, PropertyBuffer
, PropertyBufferSize
);
2857 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2861 /***********************************************************************
2862 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2864 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2865 IN HDEVINFO DeviceInfoSet
,
2866 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2868 IN
const BYTE
*PropertyBuffer
,
2869 IN DWORD PropertyBufferSize
)
2871 struct DeviceInfoSet
*list
;
2874 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2875 Property
, PropertyBuffer
, PropertyBufferSize
);
2878 SetLastError(ERROR_INVALID_HANDLE
);
2879 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2880 SetLastError(ERROR_INVALID_HANDLE
);
2881 else if (!DeviceInfoData
)
2882 SetLastError(ERROR_INVALID_HANDLE
);
2883 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2884 SetLastError(ERROR_INVALID_USER_BUFFER
);
2889 case SPDRP_COMPATIBLEIDS
:
2890 case SPDRP_CONFIGFLAGS
:
2891 case SPDRP_FRIENDLYNAME
:
2892 case SPDRP_HARDWAREID
:
2893 case SPDRP_LOCATION_INFORMATION
:
2894 case SPDRP_LOWERFILTERS
:
2895 case SPDRP_SECURITY
:
2897 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2898 case SPDRP_UPPERFILTERS
:
2900 LPCWSTR RegistryPropertyName
;
2901 DWORD RegistryDataType
;
2907 case SPDRP_COMPATIBLEIDS
:
2908 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2909 RegistryDataType
= REG_MULTI_SZ
;
2911 case SPDRP_CONFIGFLAGS
:
2912 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2913 RegistryDataType
= REG_DWORD
;
2915 case SPDRP_FRIENDLYNAME
:
2916 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2917 RegistryDataType
= REG_SZ
;
2919 case SPDRP_HARDWAREID
:
2920 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2921 RegistryDataType
= REG_MULTI_SZ
;
2923 case SPDRP_LOCATION_INFORMATION
:
2924 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2925 RegistryDataType
= REG_SZ
;
2927 case SPDRP_LOWERFILTERS
:
2928 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2929 RegistryDataType
= REG_MULTI_SZ
;
2931 case SPDRP_SECURITY
:
2932 RegistryPropertyName
= REGSTR_SECURITY
;
2933 RegistryDataType
= REG_BINARY
;
2936 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2937 RegistryDataType
= REG_SZ
;
2939 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2940 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
;
2941 RegistryDataType
= REG_SZ
;
2943 case SPDRP_UPPERFILTERS
:
2944 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
2945 RegistryDataType
= REG_MULTI_SZ
;
2948 /* Should not happen */
2949 RegistryPropertyName
= NULL
;
2950 RegistryDataType
= REG_BINARY
;
2953 /* Open device registry key */
2954 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2955 if (hKey
!= INVALID_HANDLE_VALUE
)
2957 /* Write new data */
2958 rc
= RegSetValueExW(
2960 RegistryPropertyName
,
2964 PropertyBufferSize
);
2965 if (rc
== ERROR_SUCCESS
)
2974 /*case SPDRP_CHARACTERISTICS:
2976 case SPDRP_EXCLUSIVE:*/
2977 #if (WINVER >= 0x501)
2978 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2980 //case SPDRP_SECURITY_SDS:
2984 ERR("Property 0x%lx not implemented\n", Property
);
2985 SetLastError(ERROR_NOT_SUPPORTED
);
2990 TRACE("Returning %d\n", ret
);
2995 /***********************************************************************
2996 * SetupDiInstallClassA (SETUPAPI.@)
2998 BOOL WINAPI
SetupDiInstallClassA(
2999 IN HWND hwndParent OPTIONAL
,
3000 IN PCSTR InfFileName
,
3002 IN HSPFILEQ FileQueue OPTIONAL
)
3004 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3008 /***********************************************************************
3009 * SetupDiInstallClassW (SETUPAPI.@)
3011 BOOL WINAPI
SetupDiInstallClassW(
3012 IN HWND hwndParent OPTIONAL
,
3013 IN PCWSTR InfFileName
,
3015 IN HSPFILEQ FileQueue OPTIONAL
)
3017 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3021 /***********************************************************************
3022 * SetupDiInstallClassExA (SETUPAPI.@)
3024 BOOL WINAPI
SetupDiInstallClassExA(
3025 IN HWND hwndParent OPTIONAL
,
3026 IN PCSTR InfFileName OPTIONAL
,
3028 IN HSPFILEQ FileQueue OPTIONAL
,
3029 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3033 PWSTR InfFileNameW
= NULL
;
3038 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3039 if (InfFileNameW
== NULL
)
3041 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3046 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3047 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3049 MyFree(InfFileNameW
);
3055 static HKEY
CreateClassKey(HINF hInf
)
3057 WCHAR FullBuffer
[MAX_PATH
];
3058 WCHAR Buffer
[MAX_PATH
];
3063 if (!SetupGetLineTextW(NULL
,
3071 return INVALID_HANDLE_VALUE
;
3074 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3075 lstrcatW(FullBuffer
, Buffer
);
3078 if (!SetupGetLineTextW(NULL
,
3086 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3087 return INVALID_HANDLE_VALUE
;
3090 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3094 REG_OPTION_NON_VOLATILE
,
3100 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3101 return INVALID_HANDLE_VALUE
;
3104 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3109 RequiredSize
* sizeof(WCHAR
)))
3111 RegCloseKey(hClassKey
);
3112 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3113 return INVALID_HANDLE_VALUE
;
3120 /***********************************************************************
3121 * SetupDiInstallClassExW (SETUPAPI.@)
3123 BOOL WINAPI
SetupDiInstallClassExW(
3124 IN HWND hwndParent OPTIONAL
,
3125 IN PCWSTR InfFileName OPTIONAL
,
3127 IN HSPFILEQ FileQueue OPTIONAL
,
3128 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3134 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3135 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3139 FIXME("Case not implemented: InfFileName NULL\n");
3140 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3142 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3144 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3145 SetLastError(ERROR_INVALID_FLAGS
);
3147 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3148 SetLastError(ERROR_INVALID_PARAMETER
);
3149 else if (Reserved1
!= NULL
)
3150 SetLastError(ERROR_INVALID_PARAMETER
);
3151 else if (Reserved2
!= NULL
)
3152 SetLastError(ERROR_INVALID_PARAMETER
);
3155 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
3156 SP_DEVINSTALL_PARAMS_W InstallParams
;
3157 WCHAR SectionName
[MAX_PATH
];
3158 HINF hInf
= INVALID_HANDLE_VALUE
;
3159 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3160 PVOID callback_context
= NULL
;
3162 hDeviceInfo
= SetupDiCreateDeviceInfoList(NULL
, NULL
);
3164 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3165 if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3167 InstallParams
.Flags
&= ~(DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3168 InstallParams
.Flags
|= Flags
& (DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3169 if (Flags
& DI_NOVCP
)
3170 InstallParams
.FileQueue
= FileQueue
;
3171 if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3174 /* Open the .inf file */
3175 hInf
= SetupOpenInfFileW(
3180 if (hInf
== INVALID_HANDLE_VALUE
)
3183 /* Try to append a layout file */
3184 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3188 if (InterfaceClassGuid
)
3190 /* Retrieve the actual section name */
3191 ret
= SetupDiGetActualSectionToInstallW(
3201 /* Open registry key related to this interface */
3202 /* FIXME: What happens if the key doesn't exist? */
3203 hRootKey
= SetupDiOpenClassRegKeyExW(InterfaceClassGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, NULL
, NULL
);
3204 if (hRootKey
== INVALID_HANDLE_VALUE
)
3207 /* SetupDiCreateDeviceInterface??? */
3208 FIXME("Installing an interface is not implemented\n");
3209 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3213 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3214 hRootKey
= CreateClassKey(hInf
);
3215 if (hRootKey
== INVALID_HANDLE_VALUE
)
3218 /* Retrieve the actual section name */
3219 ret
= SetupDiGetActualSectionToInstallW(
3223 MAX_PATH
- strlenW(DotServices
),
3229 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3230 if (!callback_context
)
3233 ret
= SetupInstallFromInfSectionW(
3237 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3239 NULL
, /* SourceRootPath */
3240 !(Flags
& DI_NOVCP
) && (Flags
& DI_FORCECOPY
) ? SP_COPY_FORCE_IN_USE
: 0, /* CopyFlags */
3241 SetupDefaultQueueCallbackW
,
3248 /* Install .Services section */
3249 lstrcatW(SectionName
, DotServices
);
3250 ret
= SetupInstallServicesFromInfSectionExW(
3265 if (hDeviceInfo
!= INVALID_HANDLE_VALUE
)
3266 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
3267 if (hInf
!= INVALID_HANDLE_VALUE
)
3268 SetupCloseInfFile(hInf
);
3269 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3270 RegCloseKey(hRootKey
);
3271 SetupTermDefaultQueueCallback(callback_context
);
3274 TRACE("Returning %d\n", ret
);
3279 /***********************************************************************
3280 * SetupDiOpenClassRegKey (SETUPAPI.@)
3282 HKEY WINAPI
SetupDiOpenClassRegKey(
3283 const GUID
* ClassGuid
,
3286 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3287 DIOCR_INSTALLER
, NULL
, NULL
);
3291 /***********************************************************************
3292 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3294 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3295 const GUID
* ClassGuid OPTIONAL
,
3298 PCSTR MachineName OPTIONAL
,
3301 PWSTR MachineNameW
= NULL
;
3308 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3309 if (MachineNameW
== NULL
)
3310 return INVALID_HANDLE_VALUE
;
3313 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3314 Flags
, MachineNameW
, Reserved
);
3317 MyFree(MachineNameW
);
3323 /***********************************************************************
3324 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3326 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3327 const GUID
* ClassGuid OPTIONAL
,
3330 PCWSTR MachineName OPTIONAL
,
3333 LPWSTR lpGuidString
;
3334 LPWSTR lpFullGuidString
;
3342 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3343 Flags
, debugstr_w(MachineName
), Reserved
);
3345 if (Flags
== DIOCR_INSTALLER
)
3347 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3349 else if (Flags
== DIOCR_INTERFACE
)
3351 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3355 ERR("Invalid Flags parameter!\n");
3356 SetLastError(ERROR_INVALID_FLAGS
);
3357 return INVALID_HANDLE_VALUE
;
3360 if (MachineName
!= NULL
)
3362 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3363 if (rc
!= ERROR_SUCCESS
)
3366 return INVALID_HANDLE_VALUE
;
3370 HKLM
= HKEY_LOCAL_MACHINE
;
3372 rc
= RegOpenKeyExW(HKLM
,
3375 ClassGuid
? 0 : samDesired
,
3377 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3378 if (rc
!= ERROR_SUCCESS
)
3381 return INVALID_HANDLE_VALUE
;
3384 if (ClassGuid
== NULL
)
3387 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3389 SetLastError(ERROR_GEN_FAILURE
);
3390 RegCloseKey(hClassesKey
);
3391 return INVALID_HANDLE_VALUE
;
3394 dwLength
= lstrlenW(lpGuidString
);
3395 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3396 if (!lpFullGuidString
)
3398 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3399 RpcStringFreeW(&lpGuidString
);
3400 return INVALID_HANDLE_VALUE
;
3402 lpFullGuidString
[0] = '{';
3403 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3404 lpFullGuidString
[dwLength
+ 1] = '}';
3405 lpFullGuidString
[dwLength
+ 2] = '\0';
3406 RpcStringFreeW(&lpGuidString
);
3408 rc
= RegOpenKeyExW(hClassesKey
,
3413 if (rc
!= ERROR_SUCCESS
)
3416 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3417 RegCloseKey(hClassesKey
);
3418 return INVALID_HANDLE_VALUE
;
3421 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3422 RegCloseKey(hClassesKey
);
3427 /***********************************************************************
3428 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3430 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3431 HDEVINFO DeviceInfoSet
,
3434 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3436 FIXME("%p %s %08lx %p\n",
3437 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3441 /***********************************************************************
3442 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3444 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3445 HDEVINFO DeviceInfoSet
,
3448 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3450 LPWSTR DevicePathW
= NULL
;
3453 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3455 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3456 if (DevicePathW
== NULL
)
3459 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3460 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3462 MyFree(DevicePathW
);
3467 /***********************************************************************
3468 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3470 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3471 HDEVINFO DeviceInfoSet
,
3472 PSP_DEVINFO_DATA DeviceInfoData
,
3473 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3474 DWORD ClassInstallParamsSize
)
3476 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3477 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3481 /***********************************************************************
3482 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3484 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3485 IN HDEVINFO DeviceInfoSet
,
3486 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3487 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3488 IN DWORD ClassInstallParamsSize
)
3490 struct DeviceInfoSet
*list
;
3493 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3494 ClassInstallParams
, ClassInstallParamsSize
);
3497 SetLastError(ERROR_INVALID_PARAMETER
);
3498 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3499 SetLastError(ERROR_INVALID_HANDLE
);
3500 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3501 SetLastError(ERROR_INVALID_HANDLE
);
3502 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3503 SetLastError(ERROR_INVALID_USER_BUFFER
);
3504 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3505 SetLastError(ERROR_INVALID_USER_BUFFER
);
3506 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3507 SetLastError(ERROR_INVALID_PARAMETER
);
3508 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3509 SetLastError(ERROR_INVALID_PARAMETER
);
3512 SP_DEVINSTALL_PARAMS_W InstallParams
;
3515 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3516 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3520 if (ClassInstallParams
)
3522 /* Check parameters in ClassInstallParams */
3523 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3524 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3526 SetLastError(ERROR_INVALID_USER_BUFFER
);
3529 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3531 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3532 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3535 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3538 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3542 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3545 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3549 TRACE("Returning %d\n", ret
);
3553 static BOOL
PropertyChangeHandler(
3554 IN HDEVINFO DeviceInfoSet
,
3555 IN PSP_DEVINFO_DATA DeviceInfoData
,
3556 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3557 IN DWORD ClassInstallParamsSize
)
3559 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3562 if (!DeviceInfoData
)
3563 SetLastError(ERROR_INVALID_PARAMETER
);
3564 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3565 SetLastError(ERROR_INVALID_PARAMETER
);
3566 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3567 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3568 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3569 SetLastError(ERROR_INVALID_FLAGS
);
3570 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3571 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3572 SetLastError(ERROR_INVALID_FLAGS
);
3573 else if (PropChangeParams
3574 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3575 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3576 SetLastError(ERROR_INVALID_USER_BUFFER
);
3579 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3580 if (!DeviceInfoData
)
3582 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3583 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3587 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3588 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3590 if (*CurrentPropChangeParams
)
3592 MyFree(*CurrentPropChangeParams
);
3593 *CurrentPropChangeParams
= NULL
;
3595 if (PropChangeParams
)
3597 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3598 if (!*CurrentPropChangeParams
)
3600 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3603 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3614 IN PWSTR InstallerName
,
3615 OUT HMODULE
* ModulePointer
,
3616 OUT PVOID
* FunctionPointer
)
3618 HMODULE hModule
= NULL
;
3619 LPSTR FunctionNameA
= NULL
;
3623 *ModulePointer
= NULL
;
3624 *FunctionPointer
= NULL
;
3626 Comma
= strchrW(InstallerName
, ',');
3629 rc
= ERROR_INVALID_PARAMETER
;
3635 hModule
= LoadLibraryW(InstallerName
);
3639 rc
= GetLastError();
3643 /* Skip comma spaces */
3644 while (*Comma
== ',' || isspaceW(*Comma
))
3647 /* W->A conversion for function name */
3648 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3651 rc
= GetLastError();
3655 /* Search function */
3656 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3657 if (!*FunctionPointer
)
3659 rc
= GetLastError();
3663 *ModulePointer
= hModule
;