From 3f47783c543bdbfdf935e60d951c5890d620f20b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sat, 30 Sep 2006 20:42:47 +0000 Subject: [PATCH] Implement SetupDiGetDriverInstallParamsW Add support for DI_FLAGSEX_INSTALLEDDRIVER svn path=/trunk/; revision=24322 --- reactos/dll/win32/setupapi/devinst.c | 3 +- reactos/dll/win32/setupapi/driver.c | 422 ++++++++++++++++-- reactos/dll/win32/setupapi/setupapi.spec | 2 +- reactos/dll/win32/setupapi/setupapi_private.h | 2 +- 4 files changed, 382 insertions(+), 47 deletions(-) diff --git a/reactos/dll/win32/setupapi/devinst.c b/reactos/dll/win32/setupapi/devinst.c index 909196359d7..0d6acb63aca 100644 --- a/reactos/dll/win32/setupapi/devinst.c +++ b/reactos/dll/win32/setupapi/devinst.c @@ -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 */ diff --git a/reactos/dll/win32/setupapi/driver.c b/reactos/dll/win32/setupapi/driver.c index 571a774f903..1f0ce615439 100644 --- a/reactos/dll/win32/setupapi/driver.c +++ b/reactos/dll/win32/setupapi/driver.c @@ -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.@) */ diff --git a/reactos/dll/win32/setupapi/setupapi.spec b/reactos/dll/win32/setupapi/setupapi.spec index 83298e0eb8e..87887db48b0 100644 --- a/reactos/dll/win32/setupapi/setupapi.spec +++ b/reactos/dll/win32/setupapi/setupapi.spec @@ -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) diff --git a/reactos/dll/win32/setupapi/setupapi_private.h b/reactos/dll/win32/setupapi/setupapi_private.h index 8977a33cb4b..26290498bbb 100644 --- a/reactos/dll/win32/setupapi/setupapi_private.h +++ b/reactos/dll/win32/setupapi/setupapi_private.h @@ -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;