2 * SetupAPI device class-related functions
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "setupapi_private.h"
28 /* Unicode constants */
29 static const WCHAR BackSlash
[] = {'\\',0};
30 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
31 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',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 SetupapiDll
[] = {'s','e','t','u','p','a','p','i','.','d','l','l',0};
37 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
38 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
39 IN LPFNADDPROPSHEETPAGE fAddFunc
,
42 (*UPDATE_CLASS_PARAM_HANDLER
) (
43 IN HDEVINFO DeviceInfoSet
,
44 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
45 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
46 IN DWORD ClassInstallParamsSize
);
49 SETUP_PropertyChangeHandler(
50 IN HDEVINFO DeviceInfoSet
,
51 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
52 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
53 IN DWORD ClassInstallParamsSize
);
56 SETUP_PropertyAddPropertyAdvancedHandler(
57 IN HDEVINFO DeviceInfoSet
,
58 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
59 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
60 IN DWORD ClassInstallParamsSize
);
62 typedef struct _INSTALL_PARAMS_DATA
65 UPDATE_CLASS_PARAM_HANDLER UpdateHandler
;
68 } INSTALL_PARAMS_DATA
;
70 #define ADD_PARAM_HANDLER(Function, UpdateHandler, ParamsType, ParamsField) \
71 { Function, UpdateHandler, sizeof(ParamsType), FIELD_OFFSET(struct ClassInstallParams, ParamsField) },
73 static const INSTALL_PARAMS_DATA InstallParamsData
[] = {
74 ADD_PARAM_HANDLER(DIF_PROPERTYCHANGE
, SETUP_PropertyChangeHandler
, SP_PROPCHANGE_PARAMS
, PropChangeParams
)
75 ADD_PARAM_HANDLER(DIF_ADDPROPERTYPAGE_ADVANCED
, SETUP_PropertyAddPropertyAdvancedHandler
, SP_ADDPROPERTYPAGE_DATA
, AddPropertyPageData
)
77 #undef ADD_PARAM_HANDLER
79 #define UNKNOWN_ICON_INDEX 18
81 /***********************************************************************
82 * SetupDiDestroyClassImageList(SETUPAPI.@)
85 SetupDiDestroyClassImageList(
86 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
)
88 struct ClassImageList
*list
;
91 TRACE("%p\n", ClassImageListData
);
93 if (!ClassImageListData
)
94 SetLastError(ERROR_INVALID_PARAMETER
);
95 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
96 SetLastError(ERROR_INVALID_USER_BUFFER
);
97 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
98 SetLastError(ERROR_INVALID_USER_BUFFER
);
99 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
100 SetLastError(ERROR_INVALID_USER_BUFFER
);
103 /* If Reserved wasn't NULL, then this is valid too */
104 if (ClassImageListData
->ImageList
)
106 ImageList_Destroy(ClassImageListData
->ImageList
);
107 ClassImageListData
->ImageList
= NULL
;
111 ClassImageListData
->Reserved
= 0;
116 TRACE("Returning %d\n", ret
);
120 /***********************************************************************
121 * SETUP_CreateDevicesListFromEnumerator
124 * list [IO] Device info set to fill with discovered devices.
125 * pClassGuid [I] If specified, only devices which belong to this class will be added.
126 * Enumerator [I] Location to search devices to add.
127 * hEnumeratorKey [I] Registry key corresponding to Enumerator key. Must have KEY_ENUMERATE_SUB_KEYS right.
130 * Success: ERROR_SUCCESS.
131 * Failure: an error code.
134 SETUP_CreateDevicesListFromEnumerator(
135 IN OUT
struct DeviceInfoSet
*list
,
136 IN CONST GUID
*pClassGuid OPTIONAL
,
137 IN LPCWSTR Enumerator
,
138 IN HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
140 HKEY hDeviceIdKey
= NULL
, hInstanceIdKey
;
141 WCHAR KeyBuffer
[MAX_PATH
];
142 WCHAR InstancePath
[MAX_PATH
];
143 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
144 struct DeviceInfo
*deviceInfo
;
146 DWORD dwLength
, dwRegType
;
149 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
152 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
153 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
154 if (rc
== ERROR_NO_MORE_ITEMS
)
156 if (rc
!= ERROR_SUCCESS
)
160 /* Open device id sub key */
161 if (hDeviceIdKey
!= NULL
)
162 RegCloseKey(hDeviceIdKey
);
163 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
164 if (rc
!= ERROR_SUCCESS
)
167 if (FAILED(StringCchCopyW(InstancePath
, _countof(InstancePath
), Enumerator
)) ||
168 FAILED(StringCchCatW(InstancePath
, _countof(InstancePath
), BackSlash
)) ||
169 FAILED(StringCchCatW(InstancePath
, _countof(InstancePath
), KeyBuffer
)) ||
170 FAILED(StringCchCatW(InstancePath
, _countof(InstancePath
), BackSlash
)))
172 rc
= ERROR_GEN_FAILURE
;
176 pEndOfInstancePath
= &InstancePath
[strlenW(InstancePath
)];
178 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
184 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
185 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
186 if (rc
== ERROR_NO_MORE_ITEMS
)
188 if (rc
!= ERROR_SUCCESS
)
192 /* Open instance id sub key */
193 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
194 if (rc
!= ERROR_SUCCESS
)
196 *pEndOfInstancePath
= '\0';
197 strcatW(InstancePath
, KeyBuffer
);
199 /* Read ClassGUID value */
200 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
201 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
202 RegCloseKey(hInstanceIdKey
);
203 if (rc
== ERROR_FILE_NOT_FOUND
)
206 /* Skip this bad entry as we can't verify it */
208 /* Set a default GUID for this device */
209 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
211 else if (rc
!= ERROR_SUCCESS
)
215 else if (dwRegType
!= REG_SZ
|| dwLength
< MAX_GUID_STRING_LEN
* sizeof(WCHAR
))
217 rc
= ERROR_GEN_FAILURE
;
222 KeyBuffer
[MAX_GUID_STRING_LEN
- 2] = '\0'; /* Replace the } by a NULL character */
223 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
224 /* Bad GUID, skip the entry */
228 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
230 /* Skip this entry as it is not the right device class */
234 /* Add the entry to the list */
235 if (!CreateDeviceInfo(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
240 TRACE("Adding '%s' to device info set %p\n", debugstr_w(InstancePath
), list
);
241 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
248 if (hDeviceIdKey
!= NULL
)
249 RegCloseKey(hDeviceIdKey
);
254 SETUP_CreateDevicesList(
255 IN OUT
struct DeviceInfoSet
*list
,
256 IN PCWSTR MachineName OPTIONAL
,
257 IN CONST GUID
*Class OPTIONAL
,
258 IN PCWSTR Enumerator OPTIONAL
)
260 HKEY HKLM
= HKEY_LOCAL_MACHINE
;
261 HKEY hEnumKey
= NULL
;
262 HKEY hEnumeratorKey
= NULL
;
263 WCHAR KeyBuffer
[MAX_PATH
];
268 if (Class
&& IsEqualIID(Class
, &GUID_NULL
))
271 /* Open Enum key (if applicable) */
272 if (MachineName
!= NULL
)
274 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
275 if (rc
!= ERROR_SUCCESS
)
281 REGSTR_PATH_SYSTEMENUM
,
283 KEY_ENUMERATE_SUB_KEYS
,
285 if (rc
!= ERROR_SUCCESS
)
288 /* If enumerator is provided, call directly SETUP_CreateDevicesListFromEnumerator.
289 * Else, enumerate all enumerators and call SETUP_CreateDevicesListFromEnumerator
298 KEY_ENUMERATE_SUB_KEYS
,
300 if (rc
!= ERROR_SUCCESS
)
302 if (rc
== ERROR_FILE_NOT_FOUND
)
303 rc
= ERROR_INVALID_DATA
;
306 rc
= SETUP_CreateDevicesListFromEnumerator(list
, Class
, Enumerator
, hEnumeratorKey
);
310 /* Enumerate enumerators */
314 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
315 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
316 if (rc
== ERROR_NO_MORE_ITEMS
)
318 else if (rc
!= ERROR_SUCCESS
)
323 if (hEnumeratorKey
!= NULL
)
324 RegCloseKey(hEnumeratorKey
);
325 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
326 if (rc
!= ERROR_SUCCESS
)
329 /* Call SETUP_CreateDevicesListFromEnumerator */
330 rc
= SETUP_CreateDevicesListFromEnumerator(list
, Class
, KeyBuffer
, hEnumeratorKey
);
331 if (rc
!= ERROR_SUCCESS
)
338 if (HKLM
!= HKEY_LOCAL_MACHINE
)
340 if (hEnumKey
!= NULL
)
341 RegCloseKey(hEnumKey
);
342 if (hEnumeratorKey
!= NULL
)
343 RegCloseKey(hEnumeratorKey
);
352 LPWSTR Buffer
= NULL
;
353 DWORD dwRegType
, dwLength
;
357 /* Read icon registry key */
358 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
359 if (rc
!= ERROR_SUCCESS
)
363 } else if (dwRegType
!= REG_SZ
)
365 SetLastError(ERROR_INVALID_INDEX
);
368 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
371 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
374 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
375 if (rc
!= ERROR_SUCCESS
)
380 /* make sure the returned buffer is NULL-terminated */
381 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
383 /* Transform icon value to a INT */
384 *ImageIndex
= atoiW(Buffer
);
392 /***********************************************************************
393 * SetupDiGetClassImageIndex (SETUPAPI.@)
396 SetupDiGetClassImageIndex(
397 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
398 IN CONST GUID
*ClassGuid
,
401 struct ClassImageList
*list
;
404 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
406 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
407 SetLastError(ERROR_INVALID_PARAMETER
);
408 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
409 SetLastError(ERROR_INVALID_USER_BUFFER
);
410 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
411 SetLastError(ERROR_INVALID_USER_BUFFER
);
412 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
413 SetLastError(ERROR_INVALID_USER_BUFFER
);
418 for (i
= 0; i
< list
->NumberOfGuids
; i
++)
420 if (IsEqualIID(ClassGuid
, &list
->Guids
[i
]))
424 if (i
== list
->NumberOfGuids
|| list
->IconIndexes
[i
] < 0)
425 SetLastError(ERROR_FILE_NOT_FOUND
);
428 *ImageIndex
= list
->IconIndexes
[i
];
433 TRACE("Returning %d\n", ret
);
437 /***********************************************************************
438 * SetupDiGetClassImageList(SETUPAPI.@)
441 SetupDiGetClassImageList(
442 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
444 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
447 /***********************************************************************
448 * SetupDiGetClassImageListExA(SETUPAPI.@)
451 SetupDiGetClassImageListExA(
452 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
453 IN PCSTR MachineName OPTIONAL
,
456 PWSTR MachineNameW
= NULL
;
461 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
462 if (MachineNameW
== NULL
)
466 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
468 MyFree(MachineNameW
);
474 SETUP_GetClassIconInfo(IN CONST GUID
*ClassGuid
, OUT PINT OutIndex
, OUT LPWSTR
*OutDllName
)
476 LPWSTR Buffer
= NULL
;
477 INT iconIndex
= -UNKNOWN_ICON_INDEX
;
478 HKEY hKey
= INVALID_HANDLE_VALUE
;
483 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
484 if (hKey
!= INVALID_HANDLE_VALUE
)
486 SETUP_GetIconIndex(hKey
, &iconIndex
);
492 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
495 DWORD dwRegType
, dwLength
;
496 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
497 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
499 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
502 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
505 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
506 if (rc
!= ERROR_SUCCESS
)
511 /* make sure the returned buffer is NULL-terminated */
512 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
515 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
516 && dwRegType
== REG_SZ
)
518 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
521 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
524 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
525 if (rc
!= ERROR_SUCCESS
)
530 /* make sure the returned buffer is NULL-terminated */
531 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
535 /* Unable to find where to load the icon */
536 SetLastError(ERROR_FILE_NOT_FOUND
);
539 Comma
= strchrW(Buffer
, ',');
542 SetLastError(ERROR_GEN_FAILURE
);
546 *OutDllName
= Buffer
;
550 /* Look up icon in setupapi.dll */
551 iconIndex
= -iconIndex
;
555 *OutIndex
= iconIndex
;
558 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(*OutDllName
? *OutDllName
: SetupapiDll
));
562 if (hKey
!= INVALID_HANDLE_VALUE
)
572 /***********************************************************************
573 * SetupDiGetClassImageListExW(SETUPAPI.@)
576 SetupDiGetClassImageListExW(
577 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
578 IN PCWSTR MachineName OPTIONAL
,
583 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
585 if (!ClassImageListData
)
586 SetLastError(ERROR_INVALID_PARAMETER
);
587 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
588 SetLastError(ERROR_INVALID_USER_BUFFER
);
590 SetLastError(ERROR_INVALID_PARAMETER
);
593 struct ClassImageList
*list
= NULL
;
596 DWORD ilMask
, bkColor
;
602 /* Get list of all class GUIDs in given computer */
603 ret
= SetupDiBuildClassInfoListExW(
610 if (!ret
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
613 size
= sizeof(struct ClassImageList
)
614 + (sizeof(GUID
) + sizeof(INT
)) * RequiredSize
;
615 list
= HeapAlloc(GetProcessHeap(), 0, size
);
618 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
621 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
622 list
->NumberOfGuids
= RequiredSize
;
623 list
->Guids
= (GUID
*)(list
+ 1);
624 list
->IconIndexes
= (INT
*)((ULONG_PTR
)(list
+ 1) + sizeof(GUID
) * RequiredSize
);
626 ret
= SetupDiBuildClassInfoListExW(
635 else if (RequiredSize
!= list
->NumberOfGuids
)
637 /* Hm. Class list changed since last call. Ignore
638 * this case as it should be very rare */
639 SetLastError(ERROR_GEN_FAILURE
);
644 /* Prepare a HIMAGELIST */
645 InitCommonControls();
651 bpp
= GetDeviceCaps(hDC
, BITSPIXEL
);
652 ReleaseDC(NULL
, hDC
);
659 ilMask
= ILC_COLOR16
;
661 ilMask
= ILC_COLOR24
;
663 ilMask
= ILC_COLOR32
;
669 ClassImageListData
->ImageList
= ImageList_Create(16, 16, ilMask
, 100, 10);
670 if (!ClassImageListData
->ImageList
)
673 ClassImageListData
->Reserved
= (ULONG_PTR
)list
;
675 /* For some reason, Windows sets the list background to COLOR_WINDOW */
676 bkColor
= GetSysColor(COLOR_WINDOW
);
677 ImageList_SetBkColor(ClassImageListData
->ImageList
, bkColor
);
679 /* Now, we "simply" need to load icons associated with all class guids,
680 * and put their index in the image list in the IconIndexes array */
681 for (i
= 0; i
< list
->NumberOfGuids
; i
++)
684 LPWSTR DllName
= NULL
;
686 if (SETUP_GetClassIconInfo(&list
->Guids
[i
], &miniIconIndex
, &DllName
))
688 if (DllName
&& ExtractIconExW(DllName
, -miniIconIndex
, NULL
, &hIcon
, 1) == 1)
690 list
->IconIndexes
[i
] = ImageList_AddIcon(ClassImageListData
->ImageList
, hIcon
);
694 hIcon
= LoadImage(hInstance
, MAKEINTRESOURCE(miniIconIndex
), IMAGE_ICON
, 16, 16, LR_DEFAULTCOLOR
);
695 list
->IconIndexes
[i
] = ImageList_AddIcon(ClassImageListData
->ImageList
, hIcon
);
701 list
->IconIndexes
[i
] = -1;
708 list
->IconIndexes
[i
] = -1; /* Special value to indicate that the icon is unavailable */
712 /* Finally, add the overlay icons to the image list */
713 for (i
= 0; i
<= 2; i
++)
715 hIcon
= LoadImage(hInstance
, MAKEINTRESOURCE(500 + i
), IMAGE_ICON
, 16, 16, LR_DEFAULTCOLOR
);
718 idx
= ImageList_AddIcon(ClassImageListData
->ImageList
, hIcon
);
720 ImageList_SetOverlayImage(ClassImageListData
->ImageList
, idx
, i
+ 1);
730 if (ClassImageListData
->Reserved
)
731 SetupDiDestroyClassImageList(ClassImageListData
);
737 TRACE("Returning %d\n", ret
);
741 /***********************************************************************
742 * SetupDiGetClassInstallParamsA(SETUPAPI.@)
745 SetupDiGetClassInstallParamsA(
746 IN HDEVINFO DeviceInfoSet
,
747 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
748 OUT PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
749 IN DWORD ClassInstallParamsSize
,
750 OUT PDWORD RequiredSize OPTIONAL
)
752 FIXME("SetupDiGetClassInstallParamsA(%p %p %p %lu %p) Stub\n",
753 DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
, RequiredSize
);
757 /***********************************************************************
758 * SetupDiGetClassInstallParamsW(SETUPAPI.@)
761 SetupDiGetClassInstallParamsW(
762 IN HDEVINFO DeviceInfoSet
,
763 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
764 OUT PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
765 IN DWORD ClassInstallParamsSize
,
766 OUT PDWORD RequiredSize OPTIONAL
)
768 FIXME("SetupDiGetClassInstallParamsW(%p %p %p %lu %p) Stub\n",
769 DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
, RequiredSize
);
773 /***********************************************************************
774 * SetupDiLoadClassIcon(SETUPAPI.@)
777 SetupDiLoadClassIcon(
778 IN CONST GUID
*ClassGuid
,
779 OUT HICON
*LargeIcon OPTIONAL
,
780 OUT PINT MiniIconIndex OPTIONAL
)
783 LPWSTR DllName
= NULL
;
789 if(!SETUP_GetClassIconInfo(ClassGuid
, &iconIndex
, &DllName
))
792 if (!DllName
|| ExtractIconExW(DllName
, -iconIndex
, &hIcon
, NULL
, 1) != 1 || hIcon
== NULL
)
794 /* load the default unknown device icon if ExtractIcon failed */
796 iconIndex
= UNKNOWN_ICON_INDEX
;
798 hIcon
= LoadImage(hInstance
, MAKEINTRESOURCE(iconIndex
), IMAGE_ICON
, 32, 32, LR_DEFAULTCOLOR
);
808 *MiniIconIndex
= iconIndex
;
817 TRACE("Returning %d\n", ret
);
821 /***********************************************************************
822 * SetupDiInstallClassExW (SETUPAPI.@)
825 SETUP_CreateClassKey(HINF hInf
);
827 SetupDiInstallClassExW(
828 IN HWND hwndParent OPTIONAL
,
829 IN PCWSTR InfFileName OPTIONAL
,
831 IN HSPFILEQ FileQueue OPTIONAL
,
832 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
838 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
839 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
843 FIXME("Case not implemented: InfFileName NULL\n");
844 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
846 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
848 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
849 SetLastError(ERROR_INVALID_FLAGS
);
851 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
852 SetLastError(ERROR_INVALID_PARAMETER
);
853 else if (Reserved1
!= NULL
)
854 SetLastError(ERROR_INVALID_PARAMETER
);
855 else if (Reserved2
!= NULL
)
856 SetLastError(ERROR_INVALID_PARAMETER
);
859 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
860 SP_DEVINSTALL_PARAMS_W InstallParams
;
861 WCHAR SectionName
[MAX_PATH
];
862 HINF hInf
= INVALID_HANDLE_VALUE
;
863 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
864 PVOID callback_context
= NULL
;
866 hDeviceInfo
= SetupDiCreateDeviceInfoList(NULL
, NULL
);
867 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
870 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
871 if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
874 InstallParams
.Flags
&= ~(DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
875 InstallParams
.Flags
|= Flags
& (DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
876 if (Flags
& DI_NOVCP
)
877 InstallParams
.FileQueue
= FileQueue
;
878 if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
881 /* Open the .inf file */
882 hInf
= SetupOpenInfFileW(
887 if (hInf
== INVALID_HANDLE_VALUE
)
890 /* Try to append a layout file */
891 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
893 if (InterfaceClassGuid
)
895 /* Retrieve the actual section name */
896 ret
= SetupDiGetActualSectionToInstallW(
906 /* Open registry key related to this interface */
907 /* FIXME: What happens if the key doesn't exist? */
908 hRootKey
= SetupDiOpenClassRegKeyExW(InterfaceClassGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, NULL
, NULL
);
909 if (hRootKey
== INVALID_HANDLE_VALUE
)
912 /* SetupDiCreateDeviceInterface??? */
913 FIXME("Installing an interface is not implemented\n");
914 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
918 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
919 hRootKey
= SETUP_CreateClassKey(hInf
);
920 if (hRootKey
== INVALID_HANDLE_VALUE
)
923 /* Retrieve the actual section name */
924 ret
= SetupDiGetActualSectionToInstallW(
928 MAX_PATH
- strlenW(DotServices
),
934 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
935 if (!callback_context
)
938 ret
= SetupInstallFromInfSectionW(
942 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
944 NULL
, /* FIXME: SourceRootPath */
945 !(Flags
& DI_NOVCP
) && (Flags
& DI_FORCECOPY
) ? SP_COPY_FORCE_IN_USE
: 0, /* CopyFlags */
946 SetupDefaultQueueCallbackW
,
953 /* OPTIONAL: Install .Services section */
954 lstrcatW(SectionName
, DotServices
);
955 SetupInstallServicesFromInfSectionExW(
967 if (hDeviceInfo
!= INVALID_HANDLE_VALUE
)
968 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
969 if (hInf
!= INVALID_HANDLE_VALUE
)
970 SetupCloseInfFile(hInf
);
971 if (hRootKey
!= INVALID_HANDLE_VALUE
)
972 RegCloseKey(hRootKey
);
973 SetupTermDefaultQueueCallback(callback_context
);
976 TRACE("Returning %d\n", ret
);
980 /***********************************************************************
981 * Helper functions for SetupDiSetClassInstallParamsW
984 SETUP_PropertyChangeHandler(
985 IN HDEVINFO DeviceInfoSet
,
986 IN PSP_DEVINFO_DATA DeviceInfoData
,
987 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
988 IN DWORD ClassInstallParamsSize
)
990 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
994 SetLastError(ERROR_INVALID_PARAMETER
);
995 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
996 SetLastError(ERROR_INVALID_PARAMETER
);
997 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
998 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
999 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
1000 SetLastError(ERROR_INVALID_FLAGS
);
1001 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
1002 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1003 SetLastError(ERROR_INVALID_FLAGS
);
1004 else if (PropChangeParams
1005 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
1006 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1007 SetLastError(ERROR_INVALID_USER_BUFFER
);
1010 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
1011 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1012 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChangeParams
;
1014 if (*CurrentPropChangeParams
)
1016 MyFree(*CurrentPropChangeParams
);
1017 *CurrentPropChangeParams
= NULL
;
1019 if (PropChangeParams
)
1021 *CurrentPropChangeParams
= MyMalloc(ClassInstallParamsSize
);
1022 if (!*CurrentPropChangeParams
)
1024 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1027 memcpy(*CurrentPropChangeParams
, PropChangeParams
, ClassInstallParamsSize
);
1037 SETUP_PropertyAddPropertyAdvancedHandler(
1038 IN HDEVINFO DeviceInfoSet
,
1039 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1040 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
1041 IN DWORD ClassInstallParamsSize
)
1043 PSP_ADDPROPERTYPAGE_DATA AddPropertyPageData
= (PSP_ADDPROPERTYPAGE_DATA
)ClassInstallParams
;
1046 if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
1047 SetLastError(ERROR_INVALID_PARAMETER
);
1048 else if (AddPropertyPageData
&& AddPropertyPageData
->Flags
!= 0)
1049 SetLastError(ERROR_INVALID_FLAGS
);
1050 else if (AddPropertyPageData
&& AddPropertyPageData
->NumDynamicPages
>= MAX_INSTALLWIZARD_DYNAPAGES
)
1051 SetLastError(ERROR_INVALID_USER_BUFFER
);
1054 PSP_ADDPROPERTYPAGE_DATA
*CurrentAddPropertyPageData
;
1055 if (!DeviceInfoData
)
1057 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1058 CurrentAddPropertyPageData
= &list
->ClassInstallParams
.AddPropertyPageData
;
1062 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1063 CurrentAddPropertyPageData
= &deviceInfo
->ClassInstallParams
.AddPropertyPageData
;
1065 if (*CurrentAddPropertyPageData
)
1067 MyFree(*CurrentAddPropertyPageData
);
1068 *CurrentAddPropertyPageData
= NULL
;
1070 if (AddPropertyPageData
)
1072 *CurrentAddPropertyPageData
= MyMalloc(ClassInstallParamsSize
);
1073 if (!*CurrentAddPropertyPageData
)
1075 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1078 memcpy(*CurrentAddPropertyPageData
, AddPropertyPageData
, ClassInstallParamsSize
);
1087 /***********************************************************************
1088 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
1091 SetupDiSetClassInstallParamsW(
1092 IN HDEVINFO DeviceInfoSet
,
1093 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1094 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
1095 IN DWORD ClassInstallParamsSize
)
1097 struct DeviceInfoSet
*list
;
1100 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
1101 ClassInstallParams
, ClassInstallParamsSize
);
1104 SetLastError(ERROR_INVALID_PARAMETER
);
1105 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
1106 SetLastError(ERROR_INVALID_HANDLE
);
1107 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1108 SetLastError(ERROR_INVALID_HANDLE
);
1109 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1110 SetLastError(ERROR_INVALID_USER_BUFFER
);
1111 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
1112 SetLastError(ERROR_INVALID_USER_BUFFER
);
1113 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
1114 SetLastError(ERROR_INVALID_PARAMETER
);
1115 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
1116 SetLastError(ERROR_INVALID_PARAMETER
);
1119 SP_DEVINSTALL_PARAMS_W InstallParams
;
1122 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1123 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1127 if (ClassInstallParams
)
1130 /* Check parameters in ClassInstallParams */
1131 for (i
= 0; i
< sizeof(InstallParamsData
) / sizeof(InstallParamsData
[0]); i
++)
1133 if (InstallParamsData
[i
].Function
== ClassInstallParams
->InstallFunction
)
1135 ret
= InstallParamsData
[i
].UpdateHandler(
1139 ClassInstallParamsSize
);
1142 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
1143 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1148 ERR("InstallFunction %u has no associated update handler\n", ClassInstallParams
->InstallFunction
);
1149 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1154 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
1155 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
1160 TRACE("Returning %d\n", ret
);
1164 /***********************************************************************
1165 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
1168 SetupDiGetClassDevPropertySheetsA(
1169 IN HDEVINFO DeviceInfoSet
,
1170 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1171 IN LPPROPSHEETHEADERA PropertySheetHeader
,
1172 IN DWORD PropertySheetHeaderPageListSize
,
1173 OUT PDWORD RequiredSize OPTIONAL
,
1174 IN DWORD PropertySheetType
)
1176 PROPSHEETHEADERW psh
;
1179 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
1180 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
1181 RequiredSize
, PropertySheetType
);
1183 if(PropertySheetHeader
)
1185 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
1186 psh
.phpage
= PropertySheetHeader
->phpage
;
1187 psh
.nPages
= PropertySheetHeader
->nPages
;
1190 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
1191 PropertySheetHeaderPageListSize
, RequiredSize
,
1195 PropertySheetHeader
->nPages
= psh
.nPages
;
1198 TRACE("Returning %d\n", ret
);
1202 struct ClassDevPropertySheetsData
1204 LPPROPSHEETHEADERW PropertySheetHeader
;
1205 DWORD PropertySheetHeaderPageListSize
;
1206 DWORD NumberOfPages
;
1211 SETUP_GetClassDevPropertySheetsCallback(
1212 IN HPROPSHEETPAGE hPropSheetPage
,
1213 IN OUT LPARAM lParam
)
1215 struct ClassDevPropertySheetsData
*PropPageData
;
1217 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
1219 PropPageData
->NumberOfPages
++;
1221 if (PropPageData
->PropertySheetHeader
->nPages
< PropPageData
->PropertySheetHeaderPageListSize
)
1223 PropPageData
->PropertySheetHeader
->phpage
[PropPageData
->PropertySheetHeader
->nPages
] = hPropSheetPage
;
1224 PropPageData
->PropertySheetHeader
->nPages
++;
1228 return PropPageData
->DontCancel
;
1232 SETUP_GetValueString(
1234 IN LPWSTR lpValueName
,
1235 OUT LPWSTR
*lpString
)
1244 RegQueryValueExW(hKey
, lpValueName
, NULL
, &dwRegType
, NULL
, &dwLength
);
1246 if (dwLength
== 0 || dwRegType
!= REG_SZ
)
1247 return ERROR_FILE_NOT_FOUND
;
1249 lpBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
1250 if (lpBuffer
== NULL
)
1251 return ERROR_NOT_ENOUGH_MEMORY
;
1253 rc
= RegQueryValueExW(hKey
, lpValueName
, NULL
, NULL
, (LPBYTE
)lpBuffer
, &dwLength
);
1254 if (rc
!= ERROR_SUCCESS
)
1256 HeapFree(GetProcessHeap(), 0, lpBuffer
);
1260 lpBuffer
[dwLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1262 *lpString
= lpBuffer
;
1264 return ERROR_SUCCESS
;
1269 SETUP_CallInstaller(
1270 IN DI_FUNCTION InstallFunction
,
1271 IN HDEVINFO DeviceInfoSet
,
1272 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1273 IN PSP_ADDPROPERTYPAGE_DATA PageData
)
1275 PSP_CLASSINSTALL_HEADER pClassInstallParams
= NULL
;
1280 /* Get the size of the old class install parameters */
1281 if (!SetupDiGetClassInstallParams(DeviceInfoSet
,
1287 dwError
= GetLastError();
1288 if (dwError
!= ERROR_INSUFFICIENT_BUFFER
)
1290 ERR("SetupDiGetClassInstallParams failed (Error %lu)\n", dwError
);
1295 /* Allocate a buffer for the old class install parameters */
1296 pClassInstallParams
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
1297 if (pClassInstallParams
== NULL
)
1299 ERR("Failed to allocate the parameters buffer!\n");
1303 /* Save the old class install parameters */
1304 if (!SetupDiGetClassInstallParams(DeviceInfoSet
,
1306 pClassInstallParams
,
1310 ERR("SetupDiGetClassInstallParams failed (Error %lu)\n", GetLastError());
1315 /* Set the new class install parameters */
1316 if (!SetupDiSetClassInstallParams(DeviceInfoSet
,
1318 &PageData
->ClassInstallHeader
,
1319 sizeof(SP_ADDPROPERTYPAGE_DATA
)))
1321 ERR("SetupDiSetClassInstallParams failed (Error %lu)\n", dwError
);
1326 /* Call the installer */
1327 ret
= SetupDiCallClassInstaller(InstallFunction
,
1332 ERR("SetupDiCallClassInstaller failed\n");
1336 /* Read the new class installer parameters */
1337 if (!SetupDiGetClassInstallParams(DeviceInfoSet
,
1339 &PageData
->ClassInstallHeader
,
1340 sizeof(SP_ADDPROPERTYPAGE_DATA
),
1343 ERR("SetupDiGetClassInstallParams failed (Error %lu)\n", GetLastError());
1349 /* Restore and free the old class install parameters */
1350 if (pClassInstallParams
!= NULL
)
1352 SetupDiSetClassInstallParams(DeviceInfoSet
,
1354 pClassInstallParams
,
1357 HeapFree(GetProcessHeap(), 0, pClassInstallParams
);
1363 /***********************************************************************
1364 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
1367 SetupDiGetClassDevPropertySheetsW(
1368 IN HDEVINFO DeviceInfoSet
,
1369 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
1370 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
1371 IN DWORD PropertySheetHeaderPageListSize
,
1372 OUT PDWORD RequiredSize OPTIONAL
,
1373 IN DWORD PropertySheetType
)
1375 struct DeviceInfoSet
*devInfoSet
= NULL
;
1376 struct DeviceInfo
*devInfo
= NULL
;
1379 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
1380 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
1381 RequiredSize
, PropertySheetType
);
1384 SetLastError(ERROR_INVALID_HANDLE
);
1385 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1386 SetLastError(ERROR_INVALID_HANDLE
);
1387 else if ((devInfoSet
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1388 SetLastError(ERROR_INVALID_HANDLE
);
1389 else if (!PropertySheetHeader
)
1390 SetLastError(ERROR_INVALID_PARAMETER
);
1391 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
1392 SetLastError(ERROR_INVALID_FLAGS
);
1393 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1394 SetLastError(ERROR_INVALID_USER_BUFFER
);
1395 else if (!DeviceInfoData
&& IsEqualIID(&devInfoSet
->ClassGuid
, &GUID_NULL
))
1396 SetLastError(ERROR_INVALID_PARAMETER
);
1397 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
1398 && PropertySheetType
!= DIGCDP_FLAG_BASIC
1399 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
1400 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
1401 SetLastError(ERROR_INVALID_PARAMETER
);
1404 HKEY hKey
= INVALID_HANDLE_VALUE
;
1405 SP_PROPSHEETPAGE_REQUEST Request
;
1406 LPWSTR PropPageProvider
= NULL
;
1407 HMODULE hModule
= NULL
;
1408 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
1409 struct ClassDevPropertySheetsData PropPageData
;
1410 SP_ADDPROPERTYPAGE_DATA InstallerPropPageData
;
1411 DWORD InitialNumberOfPages
, i
;
1415 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1417 /* Get the class property page provider */
1418 if (devInfoSet
->hmodClassPropPageProvider
== NULL
)
1420 hKey
= SetupDiOpenClassRegKeyExW(devInfo
? &devInfo
->ClassGuid
: &devInfoSet
->ClassGuid
, KEY_QUERY_VALUE
,
1421 DIOCR_INSTALLER
, NULL
/*devInfoSet->MachineName + 2*/, NULL
);
1422 if (hKey
!= INVALID_HANDLE_VALUE
)
1424 rc
= SETUP_GetValueString(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, &PropPageProvider
);
1425 if (rc
== ERROR_SUCCESS
)
1427 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
1428 if (rc
!= ERROR_SUCCESS
)
1430 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
1434 devInfoSet
->hmodClassPropPageProvider
= hModule
;
1435 devInfoSet
->pClassPropPageProvider
= pPropPageProvider
;
1437 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
1438 PropPageProvider
= NULL
;
1442 hKey
= INVALID_HANDLE_VALUE
;
1446 /* Get the device property page provider */
1447 if (devInfo
!= NULL
&& devInfo
->hmodDevicePropPageProvider
== NULL
)
1449 hKey
= SETUPDI_OpenDrvKey(devInfoSet
->HKLM
, devInfo
, KEY_QUERY_VALUE
);
1450 if (hKey
!= INVALID_HANDLE_VALUE
)
1452 rc
= SETUP_GetValueString(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, &PropPageProvider
);
1453 if (rc
== ERROR_SUCCESS
)
1455 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
1456 if (rc
!= ERROR_SUCCESS
)
1458 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
1462 devInfo
->hmodDevicePropPageProvider
= hModule
;
1463 devInfo
->pDevicePropPageProvider
= pPropPageProvider
;
1465 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
1466 PropPageProvider
= NULL
;
1470 hKey
= INVALID_HANDLE_VALUE
;
1474 InitialNumberOfPages
= PropertySheetHeader
->nPages
;
1476 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
1477 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
1478 Request
.DeviceInfoSet
= DeviceInfoSet
;
1479 Request
.DeviceInfoData
= DeviceInfoData
;
1481 PropPageData
.PropertySheetHeader
= PropertySheetHeader
;
1482 PropPageData
.PropertySheetHeaderPageListSize
= PropertySheetHeaderPageListSize
;
1483 PropPageData
.NumberOfPages
= 0;
1484 PropPageData
.DontCancel
= (RequiredSize
!= NULL
) ? TRUE
: FALSE
;
1486 /* Call the class property page provider */
1487 if (devInfoSet
->pClassPropPageProvider
!= NULL
)
1488 ((PROPERTY_PAGE_PROVIDER
)devInfoSet
->pClassPropPageProvider
)(&Request
, SETUP_GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
1490 /* Call the device property page provider */
1491 if (devInfo
!= NULL
&& devInfo
->pDevicePropPageProvider
!= NULL
)
1492 ((PROPERTY_PAGE_PROVIDER
)devInfo
->pDevicePropPageProvider
)(&Request
, SETUP_GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
1494 /* Call the class installer and add the returned pages */
1495 ZeroMemory(&InstallerPropPageData
, sizeof(SP_ADDPROPERTYPAGE_DATA
));
1496 InstallerPropPageData
.ClassInstallHeader
.cbSize
= sizeof(SP_CLASSINSTALL_HEADER
);
1497 InstallerPropPageData
.ClassInstallHeader
.InstallFunction
= DIF_ADDPROPERTYPAGE_ADVANCED
;
1498 InstallerPropPageData
.hwndWizardDlg
= PropertySheetHeader
->hwndParent
;
1500 if (SETUP_CallInstaller(DIF_ADDPROPERTYPAGE_ADVANCED
,
1503 &InstallerPropPageData
))
1505 for (i
= 0; i
< InstallerPropPageData
.NumDynamicPages
; i
++)
1507 if (PropPageData
.PropertySheetHeader
->nPages
< PropertySheetHeaderPageListSize
)
1509 PropPageData
.PropertySheetHeader
->phpage
[PropPageData
.PropertySheetHeader
->nPages
] =
1510 InstallerPropPageData
.DynamicPages
[i
];
1511 PropPageData
.PropertySheetHeader
->nPages
++;
1515 PropPageData
.NumberOfPages
+= InstallerPropPageData
.NumDynamicPages
;
1519 *RequiredSize
= PropPageData
.NumberOfPages
;
1521 if (InitialNumberOfPages
+ PropPageData
.NumberOfPages
<= PropertySheetHeaderPageListSize
)
1527 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1531 if (hKey
!= INVALID_HANDLE_VALUE
)
1534 if (PropPageProvider
!= NULL
)
1535 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
1538 TRACE("Returning %d\n", ret
);