windows-nt/Source/XPSP1/NT/admin/pchealth/sysinfo/whqlprov/issigned.cpp

1151 lines
37 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include "StdAfx.h"
#include <initguid.h>
#include <wincrypt.h>
#include "setupapi.h"
#include <WinTrust.h>
#include "mscat.h"
#include "softpub.h"
#include "devguid.h"
#include "regstr.h"
#include "cfgmgr32.h"
//
// This guid is used for file signing/verification.
//
GUID DriverVerifyGuid = DRIVER_ACTION_VERIFY;
BOOL IsInfSigned(LPTSTR FullInfPath , IWbemClassObject *pInstance = NULL);
typedef struct _NOCOPYLIST {
PTSTR pListOfFiles;
ULONG Size;
BOOL MicrosoftDriver;
} NOCOPYLIST, *PNOCOPYLIST;
PCTSTR
MyGetFileTitle(
IN PCTSTR FilePath
)
/*++
Routine Description:
This routine returns a pointer to the first character in the
filename part of the supplied path. If only a filename was given,
then this will be a pointer to the first character in the string
(i.e., the same as what was passed in).
To find the filename part, the routine returns the last component of
the string, beginning with the character immediately following the
last '\', '/' or ':'. (NB NT treats '/' as equivalent to '\' )
Arguments:
FilePath - Supplies the file path from which to retrieve the filename
portion.
Return Value:
A pointer to the beginning of the filename portion of the path.
--*/
{
PCTSTR LastComponent = FilePath;
TCHAR CurChar;
while(CurChar = *FilePath) {
FilePath = CharNext(FilePath);
if((CurChar == TEXT('\\')) || (CurChar == TEXT('/')) || (CurChar == TEXT(':'))) {
LastComponent = FilePath;
}
}
return LastComponent;
}
BOOL
pGetOriginalInfName(
LPTSTR InfName,
LPTSTR OriginalInfName,
LPTSTR OriginalCatalogName
)
{
SP_ORIGINAL_FILE_INFO InfOriginalFileInformation;
PSP_INF_INFORMATION pInfInformation;
DWORD InfInformationSize;
DWORD Error;
BOOL bRet;
//
// Assume that this INF has not been renamed
//
lstrcpy(OriginalInfName, MyGetFileTitle(InfName));
ZeroMemory(&InfOriginalFileInformation, sizeof(InfOriginalFileInformation));
InfInformationSize = 8192; // I'd rather have this too big and succeed first time, than read the INF twice
pInfInformation = (PSP_INF_INFORMATION)LocalAlloc(LPTR, InfInformationSize);
if (pInfInformation != NULL) {
bRet = SetupGetInfInformation(InfName,
INFINFO_INF_NAME_IS_ABSOLUTE,
pInfInformation,
InfInformationSize,
&InfInformationSize
);
Error = GetLastError();
//
// If buffer was too small then make the buffer larger and try again.
//
if (!bRet && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
PVOID newbuff = LocalReAlloc(pInfInformation, InfInformationSize, LPTR);
if (!newbuff) {
LocalFree(pInfInformation);
pInfInformation = NULL;
} else {
pInfInformation = (PSP_INF_INFORMATION)newbuff;
bRet = SetupGetInfInformation(InfName,
INFINFO_INF_NAME_IS_ABSOLUTE,
pInfInformation,
InfInformationSize,
&InfInformationSize
);
}
}
if (bRet) {
InfOriginalFileInformation.cbSize = sizeof(InfOriginalFileInformation);
if (SetupQueryInfOriginalFileInformation(pInfInformation, 0, NULL, &InfOriginalFileInformation)) {
if (InfOriginalFileInformation.OriginalInfName[0]!=0) {
//
// we have a "real" inf name
//
lstrcpy(OriginalInfName, InfOriginalFileInformation.OriginalInfName);
lstrcpy(OriginalCatalogName, InfOriginalFileInformation.OriginalCatalogName);
}
}
}
if (pInfInformation != NULL) {
LocalFree(pInfInformation);
pInfInformation = NULL;
}
}
return TRUE;
}
BOOL
IsInfSigned(
LPTSTR FullInfPath , IWbemClassObject *pInstance
)
{
TCHAR OriginalInfName[MAX_PATH];
TCHAR Catalog[MAX_PATH];
LPBYTE Hash;
DWORD HashSize;
CATALOG_INFO CatInfo;
HANDLE hFile;
HCATADMIN hCatAdmin;
HCATINFO hCatInfo;
HCATINFO PrevCat;
DWORD Err;
WINTRUST_DATA WintrustData;
WINTRUST_CATALOG_INFO WintrustCatalogInfo;
DRIVER_VER_INFO VersionInfo;
OSVERSIONINFO OSVer;
LPTSTR CatalogFullPath;
CRYPT_PROVIDER_DATA const * pProvData = NULL;
CRYPT_PROVIDER_SGNR * pProvSigner = NULL;
GUID defaultProviderGUID = DRIVER_ACTION_VERIFY;
HRESULT hr;
BYTE rgbHash[20];
DWORD cbData;
BOOL bIsSigned = FALSE;
ZeroMemory(Catalog, sizeof(Catalog));
//
// Get the INFs original name (this is needed since it is the hash key)
//
pGetOriginalInfName(FullInfPath, OriginalInfName, Catalog);
//
// Calculate the hash value for the inf.
//
if(CryptCATAdminAcquireContext(&hCatAdmin, &DriverVerifyGuid, 0)) {
hFile = CreateFile(FullInfPath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL
);
if(hFile == INVALID_HANDLE_VALUE) {
Err = GetLastError();
} else {
//
// Start out with a hash buffer size that should be large enough for
// most requests.
//
HashSize = 100;
do {
Hash = (LPBYTE)LocalAlloc(LPTR, HashSize);
if(!Hash) {
Err = ERROR_NOT_ENOUGH_MEMORY;
break;
}
if(CryptCATAdminCalcHashFromFileHandle(hFile, &HashSize, Hash, 0)) {
Err = NO_ERROR;
} else {
Err = GetLastError();
//
// If this API did screw up and not set last error, go ahead
// and set something.
//
if(Err == NO_ERROR) {
Err = ERROR_INVALID_DATA;
}
LocalFree(Hash);
if(Err != ERROR_INSUFFICIENT_BUFFER) {
//
// The API failed for some reason other than
// buffer-too-small. We gotta bail.
//
Hash = NULL; // reset this so we won't try to free it later
break;
}
}
} while(Err != NO_ERROR);
CloseHandle(hFile);
if(Err == NO_ERROR) {
//
// Now we have the file's hash. Initialize the structures that
// will be used later on in calls to WinVerifyTrust.
//
ZeroMemory(&WintrustData, sizeof(WINTRUST_DATA));
WintrustData.cbStruct = sizeof(WINTRUST_DATA);
WintrustData.dwUIChoice = WTD_UI_NONE;
WintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
WintrustData.dwUnionChoice = WTD_CHOICE_CATALOG;
//WintrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE;
WintrustData.dwStateAction = WTD_STATEACTION_VERIFY;
WintrustData.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
WintrustData.pCatalog = &WintrustCatalogInfo;
ZeroMemory(&WintrustCatalogInfo, sizeof(WINTRUST_CATALOG_INFO));
WintrustCatalogInfo.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
WintrustCatalogInfo.pbCalculatedFileHash = Hash;
WintrustCatalogInfo.cbCalculatedFileHash = HashSize;
WintrustData.pPolicyCallbackData = (LPVOID)&VersionInfo;
ZeroMemory(&VersionInfo, sizeof(DRIVER_VER_INFO));
VersionInfo.cbStruct = sizeof(DRIVER_VER_INFO);
ZeroMemory(&OSVer, sizeof(OSVERSIONINFO));
OSVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&OSVer)) {
VersionInfo.dwPlatform = OSVer.dwPlatformId;
VersionInfo.dwVersion = OSVer.dwMajorVersion;
VersionInfo.sOSVersionLow.dwMajor = OSVer.dwMajorVersion;
VersionInfo.sOSVersionLow.dwMinor = OSVer.dwMinorVersion;
VersionInfo.sOSVersionHigh.dwMajor = OSVer.dwMajorVersion;
VersionInfo.sOSVersionHigh.dwMinor = OSVer.dwMinorVersion;
}
//
// WinVerifyTrust is case-sensitive, so ensure that the key
// being used is all lower-case!
//
CharLower(OriginalInfName);
WintrustCatalogInfo.pcwszMemberTag = OriginalInfName;
//
// Search through installed catalogs looking for those that
// contain data for a file with the hash we just calculated.
//
PrevCat = NULL;
hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin,
Hash,
HashSize,
0,
&PrevCat
);
//
// Enumerate through all of the catalogs installed on the system
//CryptCATCatalogInfoFromContext
while(hCatInfo) {
CatInfo.cbStruct = sizeof(CATALOG_INFO);
if(CryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, 0)) {
CatalogFullPath = CatInfo.wszCatalogFile;
DEBUGTRACE(L"Catalog file is %s\n" , CatalogFullPath);
//
// If we have a catalog name we're looking for,
// see if the current catalog matches. If we
// are not validating against a specific catalog, then
// just attempt to validate against each catalog we
// enumerate. Note that the catalog file info we
// get back gives us a fully qualified path.
//
if((Catalog[0] == TEXT('\0')) ||
(!lstrcmpi(MyGetFileTitle(CatalogFullPath), (LPTSTR)Catalog)))
{
//
// We found an applicable catalog, now
// validate the file against that catalog.
//
// NOTE: Because we're using cached
// catalog information (i.e., the
// WTD_STATEACTION_AUTO_CACHE flag), we
// don't need to explicitly validate the
// catalog itself first.
//
WintrustCatalogInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
Err = (DWORD)WinVerifyTrust(NULL,
&DriverVerifyGuid,
&WintrustData
);
//
// If WinVerifyTrust suceeded
//
if (Err == NO_ERROR) {
//BugBug: Changes to the original code
//
bIsSigned = TRUE;
DEBUGTRACE(L"%ws is signed by %ws\n", FullInfPath, VersionInfo.wszSignedBy);
//lstrcpy(FullInfPath , VersionInfo.wszSignedBy);
if(NULL != pInstance)
{
VARIANT v;
VariantInit(&v);
/*v.vt = VT_BOOL;
v.boolVal = bIsSigned;
hr = pInstance->Put(L"IsSigned", 0, &v, 0 );
VariantClear(&v);*/
v.vt = VT_BSTR;
v.bstrVal = VersionInfo.wszSignedBy;
hr = pInstance->Put(L"Signer", 0, &v, 0 );
VariantClear(&v);
CRYPTCATATTRIBUTE *pCatAttribute = NULL;
HANDLE hCat = CryptCATOpen(CatalogFullPath,
GENERIC_READ,
NULL,
NULL,
NULL);
if(hCat != INVALID_HANDLE_VALUE)
do
{
pCatAttribute = CryptCATEnumerateCatAttr(hCat , pCatAttribute);
if(pCatAttribute && pCatAttribute->pbValue && pCatAttribute->pwszReferenceTag)
{
v.vt = VT_BSTR;
v.bstrVal = (LPTSTR)pCatAttribute->pbValue;
hr = pInstance->Put(pCatAttribute->pwszReferenceTag, 0, &v, 0 );
VariantClear(&v);
TRACE(L"Attribute ReferenceTag = %s Value = %s\n" , pCatAttribute->pwszReferenceTag , (LPTSTR)pCatAttribute->pbValue);
}
}while(pCatAttribute);
if(hCat != INVALID_HANDLE_VALUE)
CryptCATClose(hCat);
}
//pProvData = WTHelperProvDataFromStateData(WintrustData.hWVTStateData);
//
// Get the first signer from the chain
//
//pProvSigner = WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA)pProvData,
// 0,
// FALSE,
// 0
// );
if ((pProvData = WTHelperProvDataFromStateData(WintrustData.hWVTStateData)) == NULL ){
DEBUGTRACE(L"WTHelperProvDataDFromStateData failed\n");
break;
}
//
// Get the first signer from the chain
//
if ((pProvSigner = WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA)pProvData,
0,
FALSE,
0
)) == NULL) {
DEBUGTRACE(L"NO Signer\n");
break;
}
//
// Get the sha1 hash from the signing cert
//
//assert(pProvSigner->pChainContext->cChain >= 1);
//assert(pProvSigner->pChainContext->rgpChain[0]->rgpElement[0]->cElement >= 1);
cbData = 20;
if (CertGetCertificateContextProperty(
pProvSigner->pChainContext->rgpChain[0]->rgpElement[0]->pCertContext,
CERT_SHA1_HASH_PROP_ID,
&(rgbHash[0]),
&cbData)) {
DEBUGTRACE(L"rgbHash:\n%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
rgbHash[0], rgbHash[1], rgbHash[2], rgbHash[3], rgbHash[4],
rgbHash[5], rgbHash[6], rgbHash[7], rgbHash[8], rgbHash[9],
rgbHash[10], rgbHash[11], rgbHash[12], rgbHash[13], rgbHash[14],
rgbHash[15], rgbHash[16], rgbHash[17], rgbHash[18], rgbHash[19]);
//
// BUGBUG:
// Compare the Hash to the Microsoft Windows 2000 hash only. If it matches
// then this is NOT an OEM Hal, otherwise it is.
//
//
// if (memcmp(&(rgbHash[0]), &MSHASH, 20) {
// bIsSigned = TRUE;
// } else {
// bIsSignedByMicorsoft = FALSE;
// }
}
}
//
// Free the pcSignerCertContext member of the DRIVER_VER_INFO struct
// that was allocated in our call to WinVerifyTrust.
//
if (VersionInfo.pcSignerCertContext != NULL) {
CertFreeCertificateContext(VersionInfo.pcSignerCertContext);
VersionInfo.pcSignerCertContext = NULL;
}
//
// If we had a specific catalog to compare against then we are
// done.
//
if (Catalog[0] != TEXT('\0')) {
CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
break;
}
//
// If we validated against a catalog and it is NOT signed by Microsoft then
// we are done.
//
// Note that if we did validate against a Microsoft catalog then we want
// to keep going in case the file validates against both a Microsoft
// and OEM catalog.
//
if ((Err == NO_ERROR) && !bIsSigned) {
CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
break;
}
}
}
PrevCat = hCatInfo;
hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin, Hash, HashSize, 0, &PrevCat);
WintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
Err = (DWORD)WinVerifyTrust(NULL,
&DriverVerifyGuid,
&WintrustData
);
}
//else
//{
if(NULL != pInstance)
{
//VARIANT v;
CComVariant v;
//VariantInit(&v);
//v.vt = VT_BOOL;
v = bIsSigned;
hr = pInstance->Put(L"IsSigned", 0, &v, 0 );
//VariantClear(&v);
v.Clear();
}
//}
}
if(Hash) {
LocalFree(Hash);
}
}
CryptCATAdminReleaseContext(hCatAdmin,0);
}
//BugBug: Changes to the original code
//
return bIsSigned;
}
BOOL
IsOemHalInstalled(
VOID
)
{
HDEVINFO DeviceInfoSet;
SP_DEVINFO_DATA DeviceInfoData;
HKEY hKey;
DWORD dwType, cbData;
TCHAR InfName[MAX_PATH];
TCHAR InfPath[MAX_PATH];
BOOL isHalOem = TRUE;
//
// First get the "computer class" devnode
//
DeviceInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_COMPUTER,
NULL,
NULL,
DIGCF_PRESENT
);
if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
goto clean0;
}
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
//
// There should only be one device in the "computer class" so just
// get the 1st device in the DeviceInfoSet.
//
if (!SetupDiEnumDeviceInfo(DeviceInfoSet,
0,
&DeviceInfoData
)) {
goto clean0;
}
//
// Open the device's driver (software) registry key so we can get the InfPath
//
hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
&DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_READ
);
if (hKey != INVALID_HANDLE_VALUE) {
dwType = REG_SZ;
cbData = sizeof(InfPath);
if (RegQueryValueEx(hKey,
REGSTR_VAL_INFPATH,
NULL,
&dwType,
(LPBYTE)InfName,
&cbData
) == ERROR_SUCCESS) {
if (GetWindowsDirectory(InfPath, sizeof(InfPath)/sizeof(TCHAR))) {
if (lstrlen(InfPath)) {
//
// Tack on an extra back slash if one is needed
//
if (InfPath[lstrlen(InfPath) - 1] != TEXT('\\')) {
lstrcat(InfPath, TEXT("\\"));
}
lstrcat(InfPath, TEXT("INF\\"));
lstrcat(InfPath, InfName);
DEBUGTRACE(L"IsOemHalInstalled() HAL Inf is %ws\n", InfPath);
IsInfSigned(InfPath);
}
}
}
RegCloseKey(hKey);
}
clean0:
return isHalOem;
}
DWORD
pSetupGetCurrentlyInstalledDriverNode(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
IN OUT PTSTR InfPath
)
{
HKEY hKey = NULL;
DWORD RegDataType, RegDataLength;
SP_DEVINSTALL_PARAMS DeviceInstallParams;
SP_DRVINFO_DATA DriverInfoData;
DWORD Err = ERROR_SUCCESS;
ZeroMemory(&DeviceInstallParams, sizeof(DeviceInstallParams));
DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
//
// Retrieve the current device install parameters so we can modify them to
// target the driver search to a particular INF.
//
if (!SetupDiGetDeviceInstallParams(DeviceInfoSet,
DeviceInfoData,
&DeviceInstallParams
)) {
return GetLastError();
}
//
// In order to select the currently installed driver we will need to get the
// devices description, manufacturer, and provider. So we will first open the
// devices registry key to retrieve some of this information.
//
hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_READ
);
//
// If we can't open the device's registry key then return FALSE. This means
// we will be on the safe side and treat this as a 3rd party driver.
//
if (hKey == INVALID_HANDLE_VALUE) {
return GetLastError();
}
RegDataLength = sizeof(DeviceInstallParams.DriverPath);
if ((Err = RegQueryValueEx(hKey,
REGSTR_VAL_INFPATH,
NULL,
&RegDataType,
(PBYTE)DeviceInstallParams.DriverPath,
&RegDataLength
)) != ERROR_SUCCESS) {
goto clean0;
}
//
// Save the DriverPath in the InfPath parameter.
//
if (InfPath) {
lstrcpy(InfPath, DeviceInstallParams.DriverPath);
}
//
// Set the DeviceInstallParams flags that indicate DriverPath represents a
// single INF to be searched, and set the flag that says to include all drivers,
// even drivers that are normally excluded.
//
DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
DeviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
//
// Build up a list of drivers from this device's INF.
//
if (!SetupDiBuildDriverInfoList(DeviceInfoSet,
DeviceInfoData,
SPDIT_CLASSDRIVER
)) {
Err = GetLastError();
goto clean0;
}
//
// Now we need to select the driver node from the INF that was used to install
// this device. The three parameters that uniquely identify a driver node are
// INF provider, Device Manufacturer, and Device Description. We will retrieve
// these three pieces of information in preparation for selecting the correct
// driver node in the class list we just built.
//
ZeroMemory(&DriverInfoData, sizeof(SP_DRVINFO_DATA));
DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
RegDataLength = sizeof(DriverInfoData.ProviderName);
RegQueryValueEx(hKey,
REGSTR_VAL_PROVIDER_NAME,
NULL,
&RegDataType,
(PBYTE)DriverInfoData.ProviderName,
&RegDataLength
);
SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
DeviceInfoData,
SPDRP_MFG,
NULL,
(PBYTE)DriverInfoData.MfgName,
sizeof(DriverInfoData.MfgName),
NULL
);
SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
DeviceInfoData,
SPDRP_DEVICEDESC,
NULL,
(PBYTE)DriverInfoData.Description,
sizeof(DriverInfoData.Description),
NULL
);
//
// Set the DriverInfoData.Reserved field to 0 to tell setupapi to match the
// specified criteria and select it if found.
//
DriverInfoData.DriverType = SPDIT_CLASSDRIVER;
DriverInfoData.Reserved = 0;
if (!SetupDiSetSelectedDriver(DeviceInfoSet,
DeviceInfoData,
&DriverInfoData
)) {
//
// This means we could not find the currently installed driver for this
// device.
//
Err = GetLastError();
goto clean0;
}
//
// At this point we have successfully selected the currently installed driver for the specified
// device innformation element.
//
Err = ERROR_SUCCESS;
clean0:
if (hKey != NULL) {
RegCloseKey(hKey);
}
return Err;
}
UINT
pFileQueueCallback(
PVOID Context,
UINT Notification,
UINT Param1,
UINT Param2
)
{
PFILEPATHS FilePaths = (PFILEPATHS)Param1;
if ((Notification == SPFILENOTIFY_QUEUESCAN_EX) && Param1) {
PNOCOPYLIST pncl = (PNOCOPYLIST)Context;
BOOL bAlreadyExists = FALSE;
PTSTR p;
//
// If there is any sort of file not found error or crypto error then
// we'll treat this as a non-MS package.
//
if (FilePaths->Win32Error != NO_ERROR) {
pncl->MicrosoftDriver = FALSE;
}
if (pncl->Size == 0) {
pncl->Size = (lstrlen(FilePaths->Source) + 2) * sizeof(TCHAR);
pncl->pListOfFiles = (PTSTR)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
pncl->Size
);
if (pncl->pListOfFiles) {
lstrcpy(pncl->pListOfFiles, FilePaths->Source);
} else {
pncl->Size = 0;
}
} else {
//
// First check to see if this filename already exists in the list.
//
for (p = pncl->pListOfFiles; *p; p += (lstrlen(p) + 1)) {
if (lstrcmpi(p, FilePaths->Source) == 0) {
bAlreadyExists = TRUE;
}
}
if (!bAlreadyExists) {
PTSTR TempBuffer;
ULONG ulOldSize = pncl->Size;
pncl->Size += (lstrlen(FilePaths->Source) + 1) * sizeof(TCHAR);
//
// Lets add this file to our multi-sz string.
//
TempBuffer = (PTSTR)HeapReAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
pncl->pListOfFiles,
pncl->Size
);
if (TempBuffer) {
pncl->pListOfFiles = TempBuffer;
lstrcpy(&(pncl->pListOfFiles[ulOldSize/sizeof(TCHAR) - 1]), FilePaths->Source);
}
}
}
}
return NO_ERROR;
}
DWORD
pGetListOfFilesForDevice(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
PNOCOPYLIST pncl
)
{
DWORD Err = NO_ERROR;
TCHAR InfName[MAX_PATH];
HSPFILEQ FileQueueHandle = (HSPFILEQ)INVALID_HANDLE_VALUE;
SP_DEVINSTALL_PARAMS DeviceInstallParams;
DWORD dwResult;
BOOL bIsDriverMicrosoft = FALSE;
//
// Get the currently-installed driver node for this element
//
InfName[0] = TEXT('\0');
if (pSetupGetCurrentlyInstalledDriverNode(DeviceInfoSet,
DeviceInfoData,
InfName
) != NO_ERROR) {
Err = GetLastError();
goto clean0;
}
//
// Now queue all files to be copied by this driver node into our own file queue.
//
FileQueueHandle = SetupOpenFileQueue();
if (FileQueueHandle == (HSPFILEQ)INVALID_HANDLE_VALUE) {
Err = GetLastError();
goto clean0;
}
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
if (!SetupDiGetDeviceInstallParams(DeviceInfoSet,
DeviceInfoData,
&DeviceInstallParams
)) {
Err = GetLastError();
goto clean0;
}
DeviceInstallParams.FileQueue = FileQueueHandle;
DeviceInstallParams.Flags |= DI_NOVCP;
if (!SetupDiSetDeviceInstallParams(DeviceInfoSet,
DeviceInfoData,
&DeviceInstallParams
)) {
Err = GetLastError();
goto clean0;
}
//
// Tell setupapi (and class/co-installers to build up a list of driver files
// for this device.
//
if (!SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES,
DeviceInfoSet,
DeviceInfoData
)) {
Err = GetLastError();
goto clean0;
}
//
// Scan the FileQueue adding files to the list.
//
if (!SetupScanFileQueue(FileQueueHandle,
SPQ_SCAN_USE_CALLBACKEX,
NULL,
(PSP_FILE_CALLBACK)pFileQueueCallback,
(PVOID)pncl,
&dwResult
)) {
Err = GetLastError();
goto clean0;
}
//
// If we haven't encountered any errors then the MicrosoftDriver BOOL will
// still be TRUE. That means that we need to verify the INF associated with
// this driver package to make sure it is signed by the build lab.
//
if (pncl->MicrosoftDriver) {
TCHAR FullInfPath[MAX_PATH];
if (GetWindowsDirectory(FullInfPath, sizeof(FullInfPath)/sizeof(TCHAR))) {
if (lstrlen(FullInfPath)) {
//
// Tack on an extra back slash if one is needed
//
if (FullInfPath[lstrlen(FullInfPath) - 1] != TEXT('\\')) {
lstrcat(FullInfPath, TEXT("\\"));
}
lstrcat(FullInfPath, TEXT("INF\\"));
lstrcat(FullInfPath, InfName);
//
// If the INF for this driver node is not signed by the Microsoft build
// lab, then set the MicrosoftDriver BOOL to FALSE.
//
if (!IsInfSigned(FullInfPath)) {
pncl->MicrosoftDriver = FALSE;
}
}
}
}
clean0:
if (FileQueueHandle != (HSPFILEQ)INVALID_HANDLE_VALUE) {
SetupCloseFileQueue(FileQueueHandle);
}
DEBUGTRACE(L"pGetListOfFilesForDevice returned error 0x%X\n", Err);
return Err;
}
BOOL
IsDriverThirdParty(
IN PCTSTR ServiceName
)
{
ULONG ulLen;
PTCHAR deviceList = NULL;
PTCHAR p;
BOOL bIsDriverMicrosoft = FALSE;
HDEVINFO DeviceInfoSet;
SP_DEVINFO_DATA DeviceInfoData;
NOCOPYLIST ncl;
ncl.Size = 0;
ncl.MicrosoftDriver = TRUE;
//
// Get the size of the buffer needed to hold all of the device instance Ids
// that have the specified service.
//
if (CM_Get_Device_ID_List_Size(&ulLen,
ServiceName,
CM_GETIDLIST_FILTER_SERVICE
) != CR_SUCCESS) {
goto clean0;
}
deviceList = (PTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (ulLen * sizeof(TCHAR)));
if (!deviceList) {
goto clean0;
}
//
// Get the multi-sz list of all of the device instance Ids that use the
// specified service.
//
if (CM_Get_Device_ID_List(ServiceName,
deviceList,
ulLen,
CM_GETIDLIST_FILTER_SERVICE
) != CR_SUCCESS) {
goto clean0;
}
//
// Enumerate through the multi_sz list of all of the devices that are using
// the speicifed service.
//
for (p=deviceList; *p; p += (lstrlen(p) + 1)) {
DEBUGTRACE(L"%ws\n", p);
//
// Create a new empty DeviceInfoSet.
//
DeviceInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL);
if (DeviceInfoSet != INVALID_HANDLE_VALUE) {
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
//
// Add the device to the DeviceInfoSet.
//
if (SetupDiOpenDeviceInfo(DeviceInfoSet,
p,
NULL,
0,
&DeviceInfoData
)) {
pGetListOfFilesForDevice(DeviceInfoSet,
&DeviceInfoData,
&ncl
);
}
//
// Destroy the DeviceInfoSet.
//
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
}
//
// By this point we will have all of the files copied for all devices with a
// service name that matches that passed in to this function. The NOCOPYLIST
// MicrosoftDriver parameter will specify whether this is a Microsoft driver
// or NOT. If it is a Microsoft Driver then we will free the lpfileList field
// of this structure and return FALSE to this API, otherwise we will return TRUE
// along with the size of the multi-sz file list.
//
if (ncl.MicrosoftDriver) {
//
// This is a Microsoft driver so we can free the memory allocated to hold all
// of the files.
//
bIsDriverMicrosoft = TRUE;
HeapFree(GetProcessHeap(), 0, ncl.pListOfFiles);
} else {
bIsDriverMicrosoft = FALSE;
}
clean0:
if (deviceList) {
HeapFree(GetProcessHeap(), 0, deviceList);
}
return !bIsDriverMicrosoft;
}
/*int
__cdecl
wmain(
IN int argc,
IN TCHAR **argv
)
{
IsOemHalInstalled();
if (argc > 0) {
IsDriverThirdParty((PCTSTR)argv[1]);
}
return 0;
}
*/