Implement SetupDiGetDriverInstallParamsW

Add support for DI_FLAGSEX_INSTALLEDDRIVER

svn path=/trunk/; revision=24322
This commit is contained in:
Hervé Poussineau 2006-09-30 20:42:47 +00:00
parent b0e0c40c5d
commit 3f47783c54
4 changed files with 382 additions and 47 deletions

View file

@ -1898,7 +1898,8 @@ CheckDeviceInstallParameters(
DI_FLAGSEX_DIDINFOLIST | /* 0x00000010 */
DI_FLAGSEX_DIDCOMPATINFO | /* 0x00000020 */
DI_FLAGSEX_ALLOWEXCLUDEDDRVS | /* 0x00000800 */
DI_FLAGSEX_NO_DRVREG_MODIFY; /* 0x00008000 */
DI_FLAGSEX_NO_DRVREG_MODIFY | /* 0x00008000 */
DI_FLAGSEX_INSTALLEDDRIVER; /* 0x04000000 */
BOOL ret = FALSE;
/* FIXME: add support for more flags */

View file

@ -105,26 +105,26 @@ DestroyDriverInfoElement(struct DriverInfoElement* driverInfo)
* Helper functions for SetupDiBuildDriverInfoList
*/
static BOOL
AddDriverToList(
AddKnownDriverToList(
IN PLIST_ENTRY DriverListHead,
IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
IN LPGUID ClassGuid,
IN INFCONTEXT ContextDevice,
IN struct InfFileDetails *InfFileDetails,
IN LPCWSTR InfFile,
IN LPCWSTR SectionName,
IN LPCWSTR DriverDescription,
IN LPCWSTR ProviderName,
IN LPCWSTR ManufacturerName,
IN LPCWSTR MatchingId,
FILETIME DriverDate,
DWORDLONG DriverVersion,
IN FILETIME DriverDate,
IN DWORDLONG DriverVersion,
IN DWORD Rank)
{
struct DriverInfoElement *driverInfo = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD RequiredSize = 128; /* Initial buffer size */
BOOL Result = FALSE;
PLIST_ENTRY PreviousEntry;
LPWSTR InfInstallSection = NULL;
LPWSTR pDot;
BOOL ret = FALSE;
driverInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement));
@ -135,6 +135,9 @@ AddDriverToList(
}
memset(driverInfo, 0, sizeof(struct DriverInfoElement));
driverInfo->Params.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
driverInfo->Params.Reserved = (ULONG_PTR)driverInfo;
driverInfo->Details.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
driverInfo->Details.Reserved = (ULONG_PTR)driverInfo;
@ -154,20 +157,13 @@ AddDriverToList(
goto cleanup;
/* Fill SectionName field */
Result = SetupGetStringFieldW(
&ContextDevice,
1,
driverInfo->Details.SectionName, LINE_LEN,
NULL);
if (!Result)
goto cleanup;
strncpyW(driverInfo->Details.SectionName, SectionName, LINE_LEN);
pDot = strchrW(driverInfo->Details.SectionName, '.');
if (pDot)
*pDot = UNICODE_NULL;
/* Fill DrvDescription field */
Result = SetupGetStringFieldW(
&ContextDevice,
0, /* Field index */
driverInfo->Details.DrvDescription, LINE_LEN,
NULL);
strncpyW(driverInfo->Details.DrvDescription, DriverDescription, LINE_LEN);
/* Copy MatchingId information */
if (MatchingId)
@ -183,30 +179,11 @@ AddDriverToList(
else
driverInfo->MatchingId = NULL;
/* Get inf install section */
Result = FALSE;
RequiredSize = 128; /* Initial buffer size */
SetLastError(ERROR_INSUFFICIENT_BUFFER);
while (!Result && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
HeapFree(GetProcessHeap(), 0, InfInstallSection);
InfInstallSection = HeapAlloc(GetProcessHeap(), 0, RequiredSize * sizeof(WCHAR));
if (!InfInstallSection)
goto cleanup;
Result = SetupGetStringFieldW(
&ContextDevice,
1, /* Field index */
InfInstallSection, RequiredSize,
&RequiredSize);
}
if (!Result)
goto cleanup;
TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n",
debugstr_w(driverInfo->Details.DrvDescription), debugstr_w(InfFile),
debugstr_w(InfInstallSection), Rank);
debugstr_w(SectionName), Rank);
driverInfo->DriverRank = Rank;
driverInfo->Params.Rank = Rank;
memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME));
memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
driverInfo->Info.DriverType = DriverType;
@ -233,8 +210,8 @@ AddDriverToList(
{
struct DriverInfoElement *CurrentDriver;
CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry);
if (CurrentDriver->DriverRank > Rank ||
(CurrentDriver->DriverRank == Rank && CurrentDriver->DriverDate.QuadPart < driverInfo->DriverDate.QuadPart))
if (CurrentDriver->Params.Rank > Rank ||
(CurrentDriver->Params.Rank == Rank && CurrentDriver->DriverDate.QuadPart < driverInfo->DriverDate.QuadPart))
{
/* Insert before the current item */
InsertHeadList(PreviousEntry->Blink, &driverInfo->ListEntry);
@ -259,7 +236,78 @@ cleanup:
}
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
HeapFree(GetProcessHeap(), 0, InfInstallSection);
return ret;
}
static BOOL
AddDriverToList(
IN PLIST_ENTRY DriverListHead,
IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
IN LPGUID ClassGuid,
IN INFCONTEXT ContextDevice,
IN struct InfFileDetails *InfFileDetails,
IN LPCWSTR InfFile,
IN LPCWSTR ProviderName,
IN LPCWSTR ManufacturerName,
IN LPCWSTR MatchingId,
IN FILETIME DriverDate,
IN DWORDLONG DriverVersion,
IN DWORD Rank)
{
LPWSTR SectionName = NULL;
LPWSTR DriverDescription = NULL;
BOOL Result;
BOOL ret = FALSE;
/* Read SectionName */
SectionName = MyMalloc(LINE_LEN);
if (!SectionName)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto cleanup;
}
ZeroMemory(SectionName, LINE_LEN);
Result = SetupGetStringFieldW(
&ContextDevice,
1,
SectionName, LINE_LEN,
NULL);
if (!Result)
goto cleanup;
/* Read DriverDescription */
DriverDescription = MyMalloc(LINE_LEN);
if (!DriverDescription)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto cleanup;
}
ZeroMemory(DriverDescription, LINE_LEN);
Result = SetupGetStringFieldW(
&ContextDevice,
0, /* Field index */
DriverDescription, LINE_LEN,
NULL);
ret = AddKnownDriverToList(
DriverListHead,
DriverType,
ClassGuid,
InfFileDetails,
InfFile,
SectionName,
DriverDescription,
ProviderName,
ManufacturerName,
MatchingId,
DriverDate,
DriverVersion,
Rank);
cleanup:
MyFree(SectionName);
MyFree(DriverDescription);
return ret;
}
@ -517,6 +565,152 @@ done:
return Result;
}
#if WIN32_WINNT < 0x0600
/* WARNING:
* This code has been copied from advapi32/reg/reg.c,
* so this dll can be tested as is on Windows XP
*/
#define RRF_RT_REG_NONE (1 << 0)
#define RRF_RT_REG_SZ (1 << 1)
#define RRF_RT_REG_EXPAND_SZ (1 << 2)
#define RRF_RT_REG_BINARY (1 << 3)
#define RRF_RT_REG_DWORD (1 << 4)
#define RRF_RT_REG_MULTI_SZ (1 << 5)
#define RRF_RT_REG_QWORD (1 << 6)
#define RRF_RT_DWORD (RRF_RT_REG_BINARY | RRF_RT_REG_DWORD)
#define RRF_RT_QWORD (RRF_RT_REG_BINARY | RRF_RT_REG_QWORD)
#define RRF_NOEXPAND (1 << 28)
#define RRF_ZEROONFAILURE (1 << 29)
static VOID
RegpApplyRestrictions( DWORD dwFlags, DWORD dwType, DWORD cbData,
PLONG ret )
{
/* Check if the type is restricted by the passed flags */
if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA)
{
DWORD dwMask = 0;
switch (dwType)
{
case REG_NONE: dwMask = RRF_RT_REG_NONE; break;
case REG_SZ: dwMask = RRF_RT_REG_SZ; break;
case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break;
case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break;
case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break;
case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break;
case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break;
}
if (dwFlags & dwMask)
{
/* Type is not restricted, check for size mismatch */
if (dwType == REG_BINARY)
{
DWORD cbExpect = 0;
if ((dwFlags & RRF_RT_DWORD) == RRF_RT_DWORD)
cbExpect = 4;
else if ((dwFlags & RRF_RT_DWORD) == RRF_RT_QWORD)
cbExpect = 8;
if (cbExpect && cbData != cbExpect)
*ret = ERROR_DATATYPE_MISMATCH;
}
}
else *ret = ERROR_UNSUPPORTED_TYPE;
}
}
static LONG WINAPI
RegGetValueW( HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue,
DWORD dwFlags, LPDWORD pdwType, PVOID pvData,
LPDWORD pcbData )
{
DWORD dwType, cbData = pcbData ? *pcbData : 0;
PVOID pvBuf = NULL;
LONG ret;
TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
hKey, debugstr_w(pszSubKey), debugstr_w(pszValue), dwFlags, pdwType,
pvData, pcbData, cbData);
if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND))
return ERROR_INVALID_PARAMETER;
if (pszSubKey && pszSubKey[0])
{
ret = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
if (ret != ERROR_SUCCESS) return ret;
}
ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, pvData, &cbData);
/* If we are going to expand we need to read in the whole the value even
* if the passed buffer was too small as the expanded string might be
* smaller than the unexpanded one and could fit into cbData bytes. */
if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
(dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)))
{
do {
if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
if (!pvBuf)
{
ret = ERROR_NOT_ENOUGH_MEMORY;
break;
}
if (ret == ERROR_MORE_DATA)
ret = RegQueryValueExW(hKey, pszValue, NULL,
&dwType, pvBuf, &cbData);
else
{
/* Even if cbData was large enough we have to copy the
* string since ExpandEnvironmentStrings can't handle
* overlapping buffers. */
CopyMemory(pvBuf, pvData, cbData);
}
/* Both the type or the value itself could have been modified in
* between so we have to keep retrying until the buffer is large
* enough or we no longer have to expand the value. */
} while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
if (ret == ERROR_SUCCESS)
{
if (dwType == REG_EXPAND_SZ)
{
cbData = ExpandEnvironmentStringsW(pvBuf, pvData,
pcbData ? *pcbData : 0);
dwType = REG_SZ;
if(pcbData && cbData > *pcbData)
ret = ERROR_MORE_DATA;
}
else if (pcbData)
CopyMemory(pvData, pvBuf, *pcbData);
}
if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
}
if (pszSubKey && pszSubKey[0])
RegCloseKey(hKey);
RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
if (pcbData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE))
ZeroMemory(pvData, *pcbData);
if (pdwType) *pdwType = dwType;
if (pcbData) *pcbData = cbData;
return ret;
}
#endif /* End of code copied from advapi32/reg/reg.c */
/***********************************************************************
* SetupDiBuildDriverInfoList (SETUPAPI.@)
*/
@ -592,7 +786,95 @@ SetupDiBuildDriverInfoList(
}
}
if (InstallParams.Flags & DI_ENUMSINGLEINF)
if (InstallParams.FlagsEx & DI_FLAGSEX_INSTALLEDDRIVER)
{
HKEY hDriverKey;
WCHAR InfFileName[MAX_PATH];
WCHAR InfFileSection[MAX_PATH];
ULONG RequiredSize;
struct DeviceInfoElement *devInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
struct InfFileDetails *infFileDetails = NULL;
FILETIME DriverDate;
LONG rc;
DWORD len;
/* Prepend inf directory name to file name */
len = sizeof(InfFileName) / sizeof(InfFileName[0]);
RequiredSize = GetSystemWindowsDirectoryW(InfFileName, len);
if (RequiredSize == 0 || RequiredSize >= len)
goto done;
if (*InfFileName && InfFileName[strlenW(InfFileName) - 1] != '\\')
strcatW(InfFileName, BackSlash);
strcatW(InfFileName, InfDirectory);
/* Read some information from registry, before creating the driver structure */
hDriverKey = SetupDiOpenDevRegKey(
DeviceInfoSet,
DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_QUERY_VALUE);
if (hDriverKey == INVALID_HANDLE_VALUE)
goto done;
RequiredSize = len - strlenW(InfFileName);
rc = RegGetValueW(
hDriverKey,
NULL,
REGSTR_VAL_INFPATH,
RRF_RT_REG_SZ,
NULL,
&InfFileName[strlenW(InfFileName)],
&RequiredSize);
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
CloseHandle(hDriverKey);
goto done;
}
RequiredSize = sizeof(InfFileSection);
rc = RegGetValueW(
hDriverKey,
NULL,
REGSTR_VAL_INFSECTION,
RRF_RT_REG_SZ,
NULL,
InfFileSection,
&RequiredSize);
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
CloseHandle(hDriverKey);
goto done;
}
TRACE("Current driver in %s/%s\n", debugstr_w(InfFileName), debugstr_w(InfFileSection));
infFileDetails = CreateInfFileDetails(InfFileName);
if (!infFileDetails)
{
CloseHandle(hDriverKey);
goto done;
}
DriverDate.dwLowDateTime = DriverDate.dwHighDateTime = 0; /* FIXME */
CloseHandle(hDriverKey);
ret = AddKnownDriverToList(
pDriverListHead,
SPDIT_COMPATDRIVER,
&devInfo->ClassGuid,
infFileDetails,
InfFileName,
InfFileSection, /* Yes, we don't care of section extension */
L"DriverDescription", /* FIXME */
L"ProviderName", /* FIXME */
L"ManufacturerName", /* FIXME */
L"MatchingId", /* FIXME */
DriverDate,
0, /* FIXME: DriverVersion */
0);
if (!ret)
DereferenceInfFile(infFileDetails);
Result = FALSE;
}
else if (InstallParams.Flags & DI_ENUMSINGLEINF)
{
/* InstallParams.DriverPath contains the name of a .inf file */
RequiredSize = strlenW(InstallParams.DriverPath) + 2;
@ -1380,7 +1662,7 @@ SetupDiSetSelectedDriverW(
DriverInfoData->Reserved = (ULONG_PTR)ItemList;
ret = TRUE;
TRACE("Choosing driver whose rank is 0x%lx\n",
(*pDriverInfo)->DriverRank);
(*pDriverInfo)->Params.Rank);
if (DeviceInfoData)
memcpy(&DeviceInfoData->ClassGuid, &(*pDriverInfo)->ClassGuid, sizeof(GUID));
}
@ -1719,6 +2001,58 @@ done:
return ret;
}
/***********************************************************************
* SetupDiGetDriverInstallParamsW (SETUPAPI.@)
*/
BOOL WINAPI
SetupDiGetDriverInstallParamsW(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
IN PSP_DRVINFO_DATA_W DriverInfoData,
OUT PSP_DRVINSTALL_PARAMS DriverInstallParams)
{
BOOL ret = FALSE;
TRACE("%p %p %p %p\n", DeviceInfoSet, DeviceInfoData, DriverInfoData, DriverInstallParams);
if (!DeviceInfoSet || !DriverInfoData || !DriverInstallParams)
SetLastError(ERROR_INVALID_PARAMETER);
else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
SetLastError(ERROR_INVALID_HANDLE);
else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
SetLastError(ERROR_INVALID_HANDLE);
else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
else if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_W) && DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_W))
SetLastError(ERROR_INVALID_USER_BUFFER);
else if (DriverInstallParams->cbSize != sizeof(SP_DRVINSTALL_PARAMS))
SetLastError(ERROR_INVALID_USER_BUFFER);
else
{
SP_DEVINSTALL_PARAMS InstallParams;
InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
{
struct DriverInfoElement *driverInfo;
driverInfo = (struct DriverInfoElement *)InstallParams.Reserved;
if (driverInfo == NULL)
SetLastError(ERROR_NO_DRIVER_SELECTED);
else
{
memcpy(
DriverInstallParams,
&driverInfo->Params,
DriverInstallParams->cbSize);
ret = TRUE;
}
}
}
TRACE("Returning %d\n", ret);
return ret;
}
/***********************************************************************
* SetupDiSelectBestCompatDrv (SETUPAPI.@)
*/

View file

@ -332,7 +332,7 @@
@ stdcall SetupDiGetDriverInfoDetailA(ptr ptr ptr ptr long ptr)
@ stdcall SetupDiGetDriverInfoDetailW(ptr ptr ptr ptr long ptr)
@ stub SetupDiGetDriverInstallParamsA
@ stub SetupDiGetDriverInstallParamsW
@ stdcall SetupDiGetDriverInstallParamsW(ptr ptr ptr ptr)
@ stub SetupDiGetDeviceInterfaceAlias
@ stdcall SetupDiGetDeviceInterfaceDetailA(long ptr ptr long ptr ptr)
@ stdcall SetupDiGetDeviceInterfaceDetailW(long ptr ptr long ptr ptr)

View file

@ -95,7 +95,7 @@ struct DriverInfoElement /* Element of DeviceInfoSet.DriverListHead and DeviceIn
{
LIST_ENTRY ListEntry;
DWORD DriverRank;
SP_DRVINSTALL_PARAMS Params;
ULARGE_INTEGER DriverDate;
SP_DRVINFO_DATA_V2_W Info;
SP_DRVINFO_DETAIL_DATA_W Details;