#include <wingdi.h>
#include <shellapi.h>
+#include <strsafe.h>
/* Unicode constants */
static const WCHAR BackSlash[] = {'\\',0};
-static const WCHAR Class[] = {'C','l','a','s','s',0};
static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
static const WCHAR InterfaceInstall32[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
static const WCHAR SetupapiDll[] = {'s','e','t','u','p','a','p','i','.','d','l','l',0};
-static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
typedef BOOL
(WINAPI* PROPERTY_PAGE_PROVIDER) (
SetLastError(ERROR_INVALID_USER_BUFFER);
else
{
- //DestroyIcon()
- //ImageList_Destroy();
- FIXME("Stub %p\n", ClassImageListData);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ /* If Reserved wasn't NULL, then this is valid too */
+ if (ClassImageListData->ImageList)
+ {
+ ImageList_Destroy(ClassImageListData->ImageList);
+ ClassImageListData->ImageList = NULL;
+ }
+
+ MyFree(list);
+ ClassImageListData->Reserved = 0;
+
+ ret = TRUE;
}
TRACE("Returning %d\n", ret);
rc = RegOpenKeyExW(hEnumeratorKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hDeviceIdKey);
if (rc != ERROR_SUCCESS)
goto cleanup;
- strcpyW(InstancePath, Enumerator);
- strcatW(InstancePath, BackSlash);
- strcatW(InstancePath, KeyBuffer);
- strcatW(InstancePath, BackSlash);
+
+ if (FAILED(StringCchCopyW(InstancePath, _countof(InstancePath), Enumerator)) ||
+ FAILED(StringCchCatW(InstancePath, _countof(InstancePath), BackSlash)) ||
+ FAILED(StringCchCatW(InstancePath, _countof(InstancePath), KeyBuffer)) ||
+ FAILED(StringCchCatW(InstancePath, _countof(InstancePath), BackSlash)))
+ {
+ rc = ERROR_GEN_FAILURE;
+ goto cleanup;
+ }
+
pEndOfInstancePath = &InstancePath[strlenW(InstancePath)];
/* Enumerate instance IDs (subkeys of hDeviceIdKey) */
SetLastError(ERROR_INVALID_USER_BUFFER);
else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC)
SetLastError(ERROR_INVALID_USER_BUFFER);
- else if (!ImageIndex)
- SetLastError(ERROR_INVALID_PARAMETER);
else
{
DWORD i;
if (hKey != INVALID_HANDLE_VALUE)
RegCloseKey(hKey);
+ if (Buffer && !ret)
+ MyFree(Buffer);
+
return ret;
}
}
/* Finally, add the overlay icons to the image list */
- for (i = 0; i < 2; i++)
+ for (i = 0; i <= 2; i++)
{
hIcon = LoadImage(hInstance, MAKEINTRESOURCE(500 + i), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
if (hIcon)
{
idx = ImageList_AddIcon(ClassImageListData->ImageList, hIcon);
if (idx != -1)
- ImageList_SetOverlayImage(ClassImageListData->ImageList, idx, i);
+ ImageList_SetOverlayImage(ClassImageListData->ImageList, idx, i + 1);
DestroyIcon(hIcon);
}
}
if (LargeIcon)
{
if(!SETUP_GetClassIconInfo(ClassGuid, &iconIndex, &DllName))
- return FALSE;
+ goto cleanup;
- if (DllName && ExtractIconExW(DllName, -iconIndex, &hIcon, NULL, 1) == 1 && hIcon != NULL)
- {
- ret = TRUE;
- }
- else
+ if (!DllName || ExtractIconExW(DllName, -iconIndex, &hIcon, NULL, 1) != 1 || hIcon == NULL)
{
/* load the default unknown device icon if ExtractIcon failed */
if(DllName)
hIcon = LoadImage(hInstance, MAKEINTRESOURCE(iconIndex), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
- if(!LargeIcon)
+ if(!hIcon)
goto cleanup;
}
+
+ *LargeIcon = hIcon;
}
if (MiniIconIndex)
*MiniIconIndex = iconIndex;
ret = TRUE;
- *LargeIcon = hIcon;
cleanup:
InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams))
goto cleanup;
+
InstallParams.Flags &= ~(DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL);
InstallParams.Flags |= Flags & (DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL);
if (Flags & DI_NOVCP)
if (!ret)
goto cleanup;
- /* Install .Services section */
+ /* OPTIONAL: Install .Services section */
lstrcatW(SectionName, DotServices);
- ret = SetupInstallServicesFromInfSectionExW(
+ SetupInstallServicesFromInfSectionExW(
hInf,
SectionName,
0,
NULL,
NULL,
NULL);
- if (!ret)
- goto cleanup;
-
ret = TRUE;
}
PropertySheetHeader, PropertySheetHeaderPageListSize,
RequiredSize, PropertySheetType);
- psh.dwFlags = PropertySheetHeader->dwFlags;
- psh.phpage = PropertySheetHeader->phpage;
- psh.nPages = PropertySheetHeader->nPages;
+ if(PropertySheetHeader)
+ {
+ psh.dwFlags = PropertySheetHeader->dwFlags;
+ psh.phpage = PropertySheetHeader->phpage;
+ psh.nPages = PropertySheetHeader->nPages;
+ }
ret = SetupDiGetClassDevPropertySheetsW(DeviceInfoSet, DeviceInfoData, PropertySheetHeader ? &psh : NULL,
PropertySheetHeaderPageListSize, RequiredSize,
return PropPageData->DontCancel;
}
+static DWORD
+SETUP_GetValueString(
+ IN HKEY hKey,
+ IN LPWSTR lpValueName,
+ OUT LPWSTR *lpString)
+{
+ LPWSTR lpBuffer;
+ DWORD dwLength = 0;
+ DWORD dwRegType;
+ DWORD rc;
+
+ *lpString = NULL;
+
+ RegQueryValueExW(hKey, lpValueName, NULL, &dwRegType, NULL, &dwLength);
+
+ if (dwLength == 0 || dwRegType != REG_SZ)
+ return ERROR_FILE_NOT_FOUND;
+
+ lpBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR));
+ if (lpBuffer == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ rc = RegQueryValueExW(hKey, lpValueName, NULL, NULL, (LPBYTE)lpBuffer, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ HeapFree(GetProcessHeap(), 0, lpBuffer);
+ return rc;
+ }
+
+ lpBuffer[dwLength / sizeof(WCHAR)] = UNICODE_NULL;
+
+ *lpString = lpBuffer;
+
+ return ERROR_SUCCESS;
+}
+
+static
+BOOL
+SETUP_CallInstaller(
+ IN DI_FUNCTION InstallFunction,
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN PSP_ADDPROPERTYPAGE_DATA PageData)
+{
+ PSP_CLASSINSTALL_HEADER pClassInstallParams = NULL;
+ DWORD dwSize = 0;
+ DWORD dwError;
+ BOOL ret = TRUE;
+
+ /* Get the size of the old class install parameters */
+ if (!SetupDiGetClassInstallParams(DeviceInfoSet,
+ DeviceInfoData,
+ NULL,
+ 0,
+ &dwSize))
+ {
+ dwError = GetLastError();
+ if (dwError != ERROR_INSUFFICIENT_BUFFER)
+ {
+ ERR("SetupDiGetClassInstallParams failed (Error %lu)\n", dwError);
+ return FALSE;
+ }
+ }
+
+ /* Allocate a buffer for the old class install parameters */
+ pClassInstallParams = HeapAlloc(GetProcessHeap(), 0, dwSize);
+ if (pClassInstallParams == NULL)
+ {
+ ERR("Failed to allocate the parameters buffer!\n");
+ return FALSE;
+ }
+
+ /* Save the old class install parameters */
+ if (!SetupDiGetClassInstallParams(DeviceInfoSet,
+ DeviceInfoData,
+ pClassInstallParams,
+ dwSize,
+ &dwSize))
+ {
+ ERR("SetupDiGetClassInstallParams failed (Error %lu)\n", GetLastError());
+ ret = FALSE;
+ goto done;
+ }
+
+ /* Set the new class install parameters */
+ if (!SetupDiSetClassInstallParams(DeviceInfoSet,
+ DeviceInfoData,
+ &PageData->ClassInstallHeader,
+ sizeof(SP_ADDPROPERTYPAGE_DATA)))
+ {
+ ERR("SetupDiSetClassInstallParams failed (Error %lu)\n", dwError);
+ ret = FALSE;
+ goto done;
+ }
+
+ /* Call the installer */
+ ret = SetupDiCallClassInstaller(InstallFunction,
+ DeviceInfoSet,
+ DeviceInfoData);
+ if (ret == FALSE)
+ {
+ ERR("SetupDiCallClassInstaller failed\n");
+ goto done;
+ }
+
+ /* Read the new class installer parameters */
+ if (!SetupDiGetClassInstallParams(DeviceInfoSet,
+ DeviceInfoData,
+ &PageData->ClassInstallHeader,
+ sizeof(SP_ADDPROPERTYPAGE_DATA),
+ NULL))
+ {
+ ERR("SetupDiGetClassInstallParams failed (Error %lu)\n", GetLastError());
+ ret = FALSE;
+ goto done;
+ }
+
+done:
+ /* Restore and free the old class install parameters */
+ if (pClassInstallParams != NULL)
+ {
+ SetupDiSetClassInstallParams(DeviceInfoSet,
+ DeviceInfoData,
+ pClassInstallParams,
+ dwSize);
+
+ HeapFree(GetProcessHeap(), 0, pClassInstallParams);
+ }
+
+ return ret;
+}
+
/***********************************************************************
* SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
*/
OUT PDWORD RequiredSize OPTIONAL,
IN DWORD PropertySheetType)
{
- struct DeviceInfoSet *list;
+ struct DeviceInfoSet *devInfoSet = NULL;
+ struct DeviceInfo *devInfo = NULL;
BOOL ret = FALSE;
TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
SetLastError(ERROR_INVALID_HANDLE);
else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
SetLastError(ERROR_INVALID_HANDLE);
- else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ else if ((devInfoSet = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
SetLastError(ERROR_INVALID_HANDLE);
else if (!PropertySheetHeader)
SetLastError(ERROR_INVALID_PARAMETER);
SetLastError(ERROR_INVALID_FLAGS);
else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
- else if (!DeviceInfoData && IsEqualIID(&list->ClassGuid, &GUID_NULL))
+ else if (!DeviceInfoData && IsEqualIID(&devInfoSet->ClassGuid, &GUID_NULL))
SetLastError(ERROR_INVALID_PARAMETER);
else if (PropertySheetType != DIGCDP_FLAG_ADVANCED
&& PropertySheetType != DIGCDP_FLAG_BASIC
HMODULE hModule = NULL;
PROPERTY_PAGE_PROVIDER pPropPageProvider = NULL;
struct ClassDevPropertySheetsData PropPageData;
- DWORD dwLength, dwRegType;
- DWORD InitialNumberOfPages;
+ SP_ADDPROPERTYPAGE_DATA InstallerPropPageData;
+ DWORD InitialNumberOfPages, i;
DWORD rc;
if (DeviceInfoData)
- hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
- else
- {
- hKey = SetupDiOpenClassRegKeyExW(&list->ClassGuid, KEY_QUERY_VALUE,
- DIOCR_INSTALLER, list->MachineName + 2, NULL);
- }
- if (hKey == INVALID_HANDLE_VALUE)
- goto cleanup;
-
- rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength);
- if (rc == ERROR_FILE_NOT_FOUND)
- {
- /* No registry key. As it is optional, don't say it's a bad error */
- if (RequiredSize)
- *RequiredSize = 0;
- ret = TRUE;
- goto cleanup;
- }
- else if (rc != ERROR_SUCCESS && dwRegType != REG_SZ)
- {
- SetLastError(rc);
- goto cleanup;
- }
+ devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
- PropPageProvider = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR));
- if (!PropPageProvider)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto cleanup;
- }
- rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)PropPageProvider, &dwLength);
- if (rc != ERROR_SUCCESS)
+ /* Get the class property page provider */
+ if (devInfoSet->hmodClassPropPageProvider == NULL)
{
- SetLastError(rc);
- goto cleanup;
- }
- PropPageProvider[dwLength / sizeof(WCHAR)] = 0;
+ hKey = SetupDiOpenClassRegKeyExW(devInfo ? &devInfo->ClassGuid : &devInfoSet->ClassGuid, KEY_QUERY_VALUE,
+ DIOCR_INSTALLER, NULL/*devInfoSet->MachineName + 2*/, NULL);
+ if (hKey != INVALID_HANDLE_VALUE)
+ {
+ rc = SETUP_GetValueString(hKey, REGSTR_VAL_ENUMPROPPAGES_32, &PropPageProvider);
+ if (rc == ERROR_SUCCESS)
+ {
+ rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER);
+ goto cleanup;
+ }
- rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider);
- if (rc != ERROR_SUCCESS)
- {
- SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER);
- goto cleanup;
- }
+ devInfoSet->hmodClassPropPageProvider = hModule;
+ devInfoSet->pClassPropPageProvider = pPropPageProvider;
- if (DeviceInfoData)
- {
- struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
+ HeapFree(GetProcessHeap(), 0, PropPageProvider);
+ PropPageProvider = NULL;
+ }
- if (devInfo->hmodDevicePropPageProvider == NULL)
- {
- devInfo->hmodDevicePropPageProvider = hModule;
- devInfo->pDevicePropPageProvider = pPropPageProvider;
+ RegCloseKey(hKey);
+ hKey = INVALID_HANDLE_VALUE;
}
}
- else
- {
- struct DeviceInfoSet *devInfoSet = (struct DeviceInfoSet *)DeviceInfoSet;
- if (devInfoSet->hmodClassPropPageProvider == NULL)
+ /* Get the device property page provider */
+ if (devInfo != NULL && devInfo->hmodDevicePropPageProvider == NULL)
+ {
+ hKey = SETUPDI_OpenDrvKey(devInfoSet->HKLM, devInfo, KEY_QUERY_VALUE);
+ if (hKey != INVALID_HANDLE_VALUE)
{
- devInfoSet->hmodClassPropPageProvider = hModule;
- devInfoSet->pClassPropPageProvider = pPropPageProvider;
+ rc = SETUP_GetValueString(hKey, REGSTR_VAL_ENUMPROPPAGES_32, &PropPageProvider);
+ if (rc == ERROR_SUCCESS)
+ {
+ rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER);
+ goto cleanup;
+ }
+
+ devInfo->hmodDevicePropPageProvider = hModule;
+ devInfo->pDevicePropPageProvider = pPropPageProvider;
+
+ HeapFree(GetProcessHeap(), 0, PropPageProvider);
+ PropPageProvider = NULL;
+ }
+
+ RegCloseKey(hKey);
+ hKey = INVALID_HANDLE_VALUE;
}
}
PropPageData.NumberOfPages = 0;
PropPageData.DontCancel = (RequiredSize != NULL) ? TRUE : FALSE;
- pPropPageProvider(&Request, SETUP_GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData);
+ /* Call the class property page provider */
+ if (devInfoSet->pClassPropPageProvider != NULL)
+ ((PROPERTY_PAGE_PROVIDER)devInfoSet->pClassPropPageProvider)(&Request, SETUP_GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData);
+
+ /* Call the device property page provider */
+ if (devInfo != NULL && devInfo->pDevicePropPageProvider != NULL)
+ ((PROPERTY_PAGE_PROVIDER)devInfo->pDevicePropPageProvider)(&Request, SETUP_GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData);
+
+ /* Call the class installer and add the returned pages */
+ ZeroMemory(&InstallerPropPageData, sizeof(SP_ADDPROPERTYPAGE_DATA));
+ InstallerPropPageData.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ InstallerPropPageData.ClassInstallHeader.InstallFunction = DIF_ADDPROPERTYPAGE_ADVANCED;
+ InstallerPropPageData.hwndWizardDlg = PropertySheetHeader->hwndParent;
+
+ if (SETUP_CallInstaller(DIF_ADDPROPERTYPAGE_ADVANCED,
+ DeviceInfoSet,
+ DeviceInfoData,
+ &InstallerPropPageData))
+ {
+ for (i = 0; i < InstallerPropPageData.NumDynamicPages; i++)
+ {
+ if (PropPageData.PropertySheetHeader->nPages < PropertySheetHeaderPageListSize)
+ {
+ PropPageData.PropertySheetHeader->phpage[PropPageData.PropertySheetHeader->nPages] =
+ InstallerPropPageData.DynamicPages[i];
+ PropPageData.PropertySheetHeader->nPages++;
+ }
+ }
+
+ PropPageData.NumberOfPages += InstallerPropPageData.NumDynamicPages;
+ }
if (RequiredSize)
*RequiredSize = PropPageData.NumberOfPages;
cleanup:
if (hKey != INVALID_HANDLE_VALUE)
RegCloseKey(hKey);
- HeapFree(GetProcessHeap(), 0, PropPageProvider);
+
+ if (PropPageProvider != NULL)
+ HeapFree(GetProcessHeap(), 0, PropPageProvider);
}
TRACE("Returning %d\n", ret);