WindowsXP/Source/XPSP1/NT/sdktools/verifier/vrfutil.cpp
2024-08-03 16:30:48 +02:00

3001 lines
73 KiB
C++

//
// Driver Verifier UI
// Copyright (c) Microsoft Corporation, 1999
//
//
//
// module: VrfUtil.cpp
// author: DMihai
// created: 11/1/00
//
// Description
//
#include "stdafx.h"
#include "verifier.h"
#include "vrfutil.h"
#include "vglobal.h"
#include "VSetting.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
// Global data
//
const TCHAR RegMemoryManagementKeyName[] =
_T( "System\\CurrentControlSet\\Control\\Session Manager\\Memory Management" );
const TCHAR RegVerifyDriverLevelValueName[] =
_T( "VerifyDriverLevel" );
const TCHAR RegVerifyDriversValueName[] =
_T( "VerifyDrivers" );
///////////////////////////////////////////////////////////////////////////
//
// Report an error using a dialog box or a console message.
// The message format string is loaded from the resources.
//
void __cdecl VrfErrorResourceFormat( UINT uIdResourceFormat,
... )
{
TCHAR szMessage[ 256 ];
TCHAR strFormat[ 256 ];
BOOL bResult;
va_list prms;
//
// Load the format string from the resources
//
bResult = VrfLoadString( uIdResourceFormat,
strFormat,
ARRAY_LENGTH( strFormat ) );
ASSERT( bResult );
if( bResult )
{
va_start (prms, uIdResourceFormat);
//
// Format the message in our local buffer
//
_vsntprintf ( szMessage,
ARRAY_LENGTH( szMessage ),
strFormat,
prms);
if( g_bCommandLineMode )
{
//
// Command console mode
//
_putts( szMessage );
TRACE( _T( "%s\n" ), szMessage );
}
else
{
//
// GUI mode
//
AfxMessageBox( szMessage,
MB_OK | MB_ICONSTOP );
}
va_end (prms);
}
}
///////////////////////////////////////////////////////////////////////////
//
// Print out a message to the console
// The message string is loaded from the resources.
//
void __cdecl VrfTPrintfResourceFormat( UINT uIdResourceFormat,
... )
{
TCHAR szMessage[ 256 ];
TCHAR strFormat[ 256 ];
BOOL bResult;
va_list prms;
ASSERT( g_bCommandLineMode );
//
// Load the format string from the resources
//
bResult = VrfLoadString( uIdResourceFormat,
strFormat,
ARRAY_LENGTH( strFormat ) );
ASSERT( bResult );
if( bResult )
{
va_start (prms, uIdResourceFormat);
//
// Format the message in our local buffer
//
_vsntprintf ( szMessage,
ARRAY_LENGTH( szMessage ),
strFormat,
prms);
_putts( szMessage );
va_end (prms);
}
}
///////////////////////////////////////////////////////////////////////////
//
// Print out a simple (non-formatted) message to the console
// The message string is loaded from the resources.
//
void __cdecl VrfPrintStringFromResources( UINT uIdString )
{
TCHAR szMessage[ 256 ];
ASSERT( g_bCommandLineMode );
VERIFY( VrfLoadString( uIdString,
szMessage,
ARRAY_LENGTH( szMessage ) ) );
_putts( szMessage );
}
///////////////////////////////////////////////////////////////////////////
//
// Report an error using a dialog box or a console message.
// The message string is loaded from the resources.
//
void __cdecl VrfMesssageFromResource( UINT uIdString )
{
TCHAR szMessage[ 256 ];
VERIFY( VrfLoadString( uIdString,
szMessage,
ARRAY_LENGTH( szMessage ) ) );
if( g_bCommandLineMode )
{
//
// Command console mode
//
_putts( szMessage );
}
else
{
//
// GUI mode
//
AfxMessageBox( szMessage,
MB_OK | MB_ICONINFORMATION );
}
}
///////////////////////////////////////////////////////////////////////////
//
// Load a string from resources.
// Return TRUE if we successfully loaded and FALSE if not.
//
BOOL VrfLoadString( ULONG uIdResource,
TCHAR *szBuffer,
ULONG uBufferLength )
{
ULONG uLoadStringResult;
if( uBufferLength < 1 )
{
ASSERT( FALSE );
return FALSE;
}
uLoadStringResult = LoadString (
g_hProgramModule,
uIdResource,
szBuffer,
uBufferLength );
//
// We should never try to load non-existent strings.
//
ASSERT (uLoadStringResult > 0);
return (uLoadStringResult > 0);
}
///////////////////////////////////////////////////////////////////////////
//
// Load a string from resources.
// Return TRUE if we successfully loaded and FALSE if not.
//
BOOL VrfLoadString( ULONG uIdResource,
CString &strText )
{
TCHAR szText[ 256 ];
BOOL bSuccess;
bSuccess = VrfLoadString( uIdResource,
szText,
ARRAY_LENGTH( szText ) );
if( TRUE == bSuccess )
{
strText = szText;
}
else
{
strText = "";
}
return bSuccess;
}
///////////////////////////////////////////////////////////////////////////
VOID
CopyStringArray( const CStringArray &strArraySource,
CStringArray &strArrayDest )
{
INT_PTR nNewSize;
INT_PTR nCrtElem;
strArrayDest.RemoveAll();
nNewSize = strArraySource.GetSize();
for( nCrtElem = 0; nCrtElem < nNewSize; nCrtElem += 1 )
{
strArrayDest.Add( strArraySource.GetAt( nCrtElem ) );
}
}
/////////////////////////////////////////////////////////////////////////////
//
// Copied from sdktools\bvtsigvf
//
BOOL VerifyIsFileSigned( LPCTSTR pcszMatchFile,
PDRIVER_VER_INFO lpVerInfo)
{
HRESULT hRes;
WINTRUST_DATA WinTrustData;
WINTRUST_FILE_INFO WinTrustFile;
GUID gOSVerCheck = DRIVER_ACTION_VERIFY;
GUID gPublishedSoftware = WINTRUST_ACTION_GENERIC_VERIFY_V2;
#ifndef UNICODE
INT iRet;
WCHAR wszFileName[MAX_PATH];
#endif
ZeroMemory(&WinTrustData, sizeof(WINTRUST_DATA));
WinTrustData.cbStruct = sizeof(WINTRUST_DATA);
WinTrustData.dwUIChoice = WTD_UI_NONE;
WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
WinTrustData.dwUnionChoice = WTD_CHOICE_FILE;
WinTrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE;
WinTrustData.pFile = &WinTrustFile;
WinTrustData.pPolicyCallbackData = (LPVOID)lpVerInfo;
ZeroMemory(lpVerInfo, sizeof(DRIVER_VER_INFO));
lpVerInfo->cbStruct = sizeof(DRIVER_VER_INFO);
ZeroMemory(&WinTrustFile, sizeof(WINTRUST_FILE_INFO));
WinTrustFile.cbStruct = sizeof(WINTRUST_FILE_INFO);
#ifndef UNICODE
iRet = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcszMatchFile, -1, wszFileName, ARRAY_LENGTH(wszFileName));
WinTrustFile.pcwszFilePath = wszFileName;
#else
WinTrustFile.pcwszFilePath = pcszMatchFile;
#endif
hRes = WinVerifyTrust( AfxGetMainWnd()->m_hWnd, &gOSVerCheck, &WinTrustData);
if (hRes != ERROR_SUCCESS)
hRes = WinVerifyTrust( AfxGetMainWnd()->m_hWnd, &gPublishedSoftware, &WinTrustData);
//
// Free the pcSignerCertContext member of the DRIVER_VER_INFO struct
// that was allocated in our call to WinVerifyTrust.
//
if (lpVerInfo && lpVerInfo->pcSignerCertContext) {
CertFreeCertificateContext(lpVerInfo->pcSignerCertContext);
lpVerInfo->pcSignerCertContext = NULL;
}
return (hRes == ERROR_SUCCESS);
}
#define HASH_SIZE 100
BOOL IsDriverSigned( LPCTSTR szDriverFileName )
{
HANDLE hFile;
BOOL bSigned;
BOOL bSuccess;
HRESULT hTrustResult;
DWORD dwHashSize;
GUID guidSubSystemDriver = DRIVER_ACTION_VERIFY;
HCATINFO hCatInfo;
HCATINFO hPrevCatInfo;
BYTE Hash[ HASH_SIZE ];
WINTRUST_DATA WinTrustData;
DRIVER_VER_INFO VerInfo;
WINTRUST_CATALOG_INFO WinTrustCatalogInfo;
CATALOG_INFO CatInfo;
#ifndef UNICODE
WCHAR szUnicodeFileName[MAX_PATH];
#endif
ASSERT( NULL != szDriverFileName );
bSigned = FALSE;
//
// Open the file
//
hFile = CreateFile( szDriverFileName,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if( hFile == INVALID_HANDLE_VALUE )
{
//
// ISSUE:
//
// If we cannot find the file we assume it's signed
//
bSigned = TRUE;
goto Done;
}
//
// Generate the hash from the file handle and store it in Hash
//
dwHashSize = ARRAY_LENGTH( Hash );
ZeroMemory( Hash,
sizeof( Hash ) );
bSuccess = CryptCATAdminCalcHashFromFileHandle( hFile,
&dwHashSize,
Hash,
0);
CloseHandle( hFile );
if( TRUE != bSuccess )
{
//
// If we couldn't generate a hash assume the file is not signed
//
goto Done;
}
//
// Now we have the file's hash. Initialize the structures that
// will be used later on in calls to WinVerifyTrust.
//
//
// Initialize the VerInfo structure
//
ZeroMemory( &VerInfo, sizeof( VerInfo ) );
VerInfo.cbStruct = sizeof( VerInfo );
//
// Initialize the WinTrustCatalogInfo structure
//
ZeroMemory( &WinTrustCatalogInfo, sizeof( WinTrustCatalogInfo ) );
WinTrustCatalogInfo.cbStruct = sizeof(WinTrustCatalogInfo);
WinTrustCatalogInfo.pbCalculatedFileHash = Hash;
WinTrustCatalogInfo.cbCalculatedFileHash = dwHashSize;
#ifdef UNICODE
WinTrustCatalogInfo.pcwszMemberTag = szDriverFileName;
#else
MultiByteToWideChar( CP_ACP,
0,
szDriverFileName,
-1,
szUnicodeFileName,
ARRAY_LENGTH( szUnicodeFileName ) );
WinTrustCatalogInfo.pcwszMemberTag = szUnicodeFileName;
#endif
//
// Initialize the WinTrustData structure
//
ZeroMemory( &WinTrustData, sizeof( WinTrustData ) );
WinTrustData.cbStruct = sizeof( WinTrustData );
WinTrustData.dwUIChoice = WTD_UI_NONE;
WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
WinTrustData.dwUnionChoice = WTD_CHOICE_CATALOG;
WinTrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE;
WinTrustData.pPolicyCallbackData = (LPVOID)&VerInfo;
WinTrustData.pCatalog = &WinTrustCatalogInfo;
//
// If we don't have a g_hCatAdmin yet, acquire one
//
if( NULL == g_hCatAdmin )
{
CryptCATAdminAcquireContext( &g_hCatAdmin,
NULL,
0);
if( NULL == g_hCatAdmin )
{
//
// Bad luck - consider that the file is not signed and bail out
//
goto Done;
}
}
//
// Now we try to find the file hash in the catalog list, via CryptCATAdminEnumCatalogFromHash
//
hPrevCatInfo = NULL;
hCatInfo = CryptCATAdminEnumCatalogFromHash(
g_hCatAdmin,
Hash,
dwHashSize,
0,
&hPrevCatInfo );
while( TRUE != bSigned && NULL != hCatInfo )
{
ZeroMemory( &CatInfo, sizeof( CatInfo ) );
CatInfo.cbStruct = sizeof( CatInfo );
bSuccess = CryptCATCatalogInfoFromContext( hCatInfo,
&CatInfo,
0);
if( FALSE != bSuccess )
{
WinTrustCatalogInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
//
// Now verify that the file is an actual member of the catalog.
//
hTrustResult = WinVerifyTrust( AfxGetMainWnd()->m_hWnd,
&guidSubSystemDriver,
&WinTrustData );
bSigned = SUCCEEDED( hTrustResult );
//
// Free the pcSignerCertContext member of the DRIVER_VER_INFO struct
// that was allocated in our call to WinVerifyTrust.
//
if( VerInfo.pcSignerCertContext != NULL )
{
CertFreeCertificateContext( VerInfo.pcSignerCertContext );
VerInfo.pcSignerCertContext = NULL;
}
}
if( TRUE != bSigned )
{
//
// The hash was in this catalog, but the file wasn't a member... so off to the next catalog
//
hPrevCatInfo = hCatInfo;
hCatInfo = CryptCATAdminEnumCatalogFromHash( g_hCatAdmin,
Hash,
dwHashSize,
0,
&hPrevCatInfo );
}
}
if( NULL == hCatInfo )
{
//
// If it wasn't found in the catalogs, check if the file is individually signed.
//
bSigned = VerifyIsFileSigned( szDriverFileName,
&VerInfo );
}
Done:
return bSigned;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfSetWindowText( CWnd &Wnd,
ULONG uIdResourceString )
{
BOOL bLoaded;
CString strText;
//
// It's safe to use CString::LoadString here because we are
// in GUI mode
//
ASSERT( FALSE == g_bCommandLineMode );
bLoaded = strText.LoadString( uIdResourceString );
ASSERT( TRUE == bLoaded );
Wnd.SetWindowText( strText );
return ( TRUE == bLoaded );
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfWriteVerifierSettings( BOOL bHaveNewDrivers,
const CString &strDriversToVerify,
BOOL bHaveNewFlags,
DWORD dwVerifyFlags )
{
HKEY hMmKey = NULL;
LONG lResult;
BOOL bSuccess;
ASSERT( bHaveNewDrivers || bHaveNewFlags );
bSuccess = FALSE;
if( bHaveNewDrivers && strDriversToVerify.GetLength() == 0 )
{
//
// No drivers to verify
//
ASSERT( FALSE && "VrfDeleteAllVerifierSettings should have been called for this" );
return VrfDeleteAllVerifierSettings();
}
if( bHaveNewFlags )
{
TRACE( _T( "VrfWriteVerifierSettings: New verifier flags = %#x\n" ),
dwVerifyFlags );
}
if( bHaveNewDrivers )
{
TRACE( _T( "VrfWriteVerifierSettings: New drivers = %s\n" ),
(LPCTSTR) strDriversToVerify );
}
//
// Open the Mm key
//
lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
RegMemoryManagementKeyName,
0,
KEY_SET_VALUE,
&hMmKey );
if( lResult != ERROR_SUCCESS )
{
if( lResult == ERROR_ACCESS_DENIED )
{
VrfErrorResourceFormat(
IDS_ACCESS_IS_DENIED );
}
else
{
VrfErrorResourceFormat(
IDS_REGOPENKEYEX_FAILED,
RegMemoryManagementKeyName,
(DWORD)lResult);
}
goto Done;
}
if( bHaveNewFlags )
{
//
// Write VerifyDriverLevel value
//
if( VrfWriteRegistryDwordValue( hMmKey,
RegVerifyDriverLevelValueName,
dwVerifyFlags ) == FALSE )
{
RegCloseKey (hMmKey);
goto Done;
}
}
if( bHaveNewDrivers )
{
//
// Write VerifyDrivers value
//
if( VrfWriteRegistryStringValue( hMmKey,
RegVerifyDriversValueName,
strDriversToVerify ) == FALSE )
{
RegCloseKey (hMmKey);
goto Done;
}
}
//
// Close the Mm key and return success
//
RegCloseKey( hMmKey );
bSuccess = TRUE;
if( bSuccess )
{
if( g_bSettingsSaved )
{
VrfMesssageFromResource( IDS_REBOOT );
}
else
{
VrfMesssageFromResource( IDS_NO_SETTINGS_WERE_CHANGED );
}
}
Done:
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfWriteRegistryDwordValue( HKEY hKey,
LPCTSTR szValueName,
DWORD dwValue )
{
LONG lResult;
BOOL bSuccess;
lResult = RegSetValueEx( hKey,
szValueName,
0,
REG_DWORD,
( LPBYTE ) &dwValue,
sizeof( dwValue ) );
bSuccess = ( lResult == ERROR_SUCCESS );
g_bSettingsSaved = g_bSettingsSaved | bSuccess;
if( TRUE != bSuccess )
{
VrfErrorResourceFormat(
IDS_REGSETVALUEEX_FAILED,
szValueName,
(DWORD) lResult );
}
return bSuccess;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfWriteRegistryStringValue( HKEY hKey,
LPCTSTR szValueName,
LPCTSTR szValue )
{
BOOL bSuccess;
LONG lResult;
lResult = RegSetValueEx ( hKey,
szValueName,
0,
REG_SZ,
(LPBYTE) szValue,
( _tcslen( szValue ) + 1 ) * sizeof (TCHAR) );
bSuccess = ( lResult == ERROR_SUCCESS );
g_bSettingsSaved = g_bSettingsSaved | bSuccess;
if( TRUE != bSuccess )
{
VrfErrorResourceFormat(
IDS_REGSETVALUEEX_FAILED,
szValueName,
(DWORD) lResult);
}
return bSuccess;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfReadVerifierSettings( CString &strDriversToVerify,
DWORD &dwVerifyFlags )
{
HKEY hMmKey = NULL;
LONG lResult;
BOOL bSuccess;
bSuccess = FALSE;
//
// Open the Mm key
//
lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
RegMemoryManagementKeyName,
0,
KEY_QUERY_VALUE,
&hMmKey );
if( lResult != ERROR_SUCCESS )
{
if( lResult == ERROR_ACCESS_DENIED )
{
VrfErrorResourceFormat(
IDS_ACCESS_IS_DENIED );
}
else
{
VrfErrorResourceFormat(
IDS_REGOPENKEYEX_FAILED,
RegMemoryManagementKeyName,
(DWORD)lResult);
}
goto Done;
}
//
// Read VerifyDriverLevel value
//
if( VrfReadRegistryDwordValue( hMmKey,
RegVerifyDriverLevelValueName,
dwVerifyFlags ) == FALSE )
{
RegCloseKey (hMmKey);
goto Done;
}
//
// Read VerifyDrivers value
//
if( VrfReadRegistryStringValue( hMmKey,
RegVerifyDriversValueName,
strDriversToVerify ) == FALSE )
{
RegCloseKey (hMmKey);
goto Done;
}
//
// Close the Mm key and return success
//
RegCloseKey( hMmKey );
bSuccess = TRUE;
Done:
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrtLoadCurrentRegistrySettings( BOOL &bAllDriversVerified,
CStringArray &astrDriversToVerify,
DWORD &dwVerifyFlags )
{
BOOL bResult;
CString strDriversToVerify;
astrDriversToVerify.RemoveAll();
dwVerifyFlags = 0;
bAllDriversVerified = FALSE;
bResult = VrfReadVerifierSettings( strDriversToVerify,
dwVerifyFlags );
strDriversToVerify.TrimLeft();
strDriversToVerify.TrimRight();
if( strDriversToVerify.CompareNoCase( _T( "*" ) ) == 0 )
{
bAllDriversVerified = TRUE;
}
else
{
VrfSplitDriverNamesSpaceSeparated( strDriversToVerify,
astrDriversToVerify );
}
return bResult;
}
/////////////////////////////////////////////////////////////////////////////
VOID VrfSplitDriverNamesSpaceSeparated( CString strAllDrivers,
CStringArray &astrVerifyDriverNames )
{
INT nCharIndex;
CString strCrtDriverName;
astrVerifyDriverNames.RemoveAll();
//
// Split the space separated driver names in astrDriversToVerify
//
strAllDrivers.TrimRight();
while( TRUE )
{
strAllDrivers.TrimLeft();
if( strAllDrivers.GetLength() == 0 )
{
//
// We are done parsing the whole string
//
break;
}
//
// Look for a space or a tab
//
nCharIndex = strAllDrivers.Find( _T( ' ' ) );
if( nCharIndex < 0 )
{
nCharIndex = strAllDrivers.Find( _T( '\t' ) );
}
if( nCharIndex >= 0 )
{
//
// Found a separator character
//
strCrtDriverName = strAllDrivers.Left( nCharIndex );
if( strCrtDriverName.GetLength() > 0 &&
FALSE == VrfIsStringInArray( strCrtDriverName,
astrVerifyDriverNames ) )
{
astrVerifyDriverNames.Add( strCrtDriverName );
}
strAllDrivers = strAllDrivers.Right( strAllDrivers.GetLength() - nCharIndex - 1 );
}
else
{
//
// This is the last driver name
//
if( FALSE == VrfIsStringInArray( strAllDrivers,
astrVerifyDriverNames ) )
{
astrVerifyDriverNames.Add( strAllDrivers );
}
break;
}
}
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfIsDriversSetDifferent( CString strAllDrivers1,
const CStringArray &astrVerifyDriverNames2 )
{
BOOL bDifferent;
INT_PTR nDriverNames1;
INT_PTR nDriverNames2;
INT_PTR nCrtDriver1;
INT_PTR nCrtDriver2;
CString strDriver1;
CString strDriver2;
CStringArray astrVerifyDriverNames1;
bDifferent = TRUE;
VrfSplitDriverNamesSpaceSeparated( strAllDrivers1,
astrVerifyDriverNames1 );
nDriverNames1 = astrVerifyDriverNames1.GetSize();
nDriverNames2 = astrVerifyDriverNames2.GetSize();
if( nDriverNames1 == nDriverNames2 )
{
//
// Same number of drivers
//
bDifferent = FALSE;
for( nCrtDriver1 = 0; nCrtDriver1 < nDriverNames1; nCrtDriver1 += 1 )
{
strDriver1 = astrVerifyDriverNames1.GetAt( nCrtDriver1 );
bDifferent = TRUE;
//
// Look for strDriver1 in astrVerifyDriverNames2
//
for( nCrtDriver2 = 0; nCrtDriver2 < nDriverNames2; nCrtDriver2 += 1 )
{
strDriver2 = astrVerifyDriverNames2.GetAt( nCrtDriver2 );
if( strDriver1.CompareNoCase( strDriver2 ) == 0 )
{
bDifferent = FALSE;
break;
}
}
if( TRUE == bDifferent )
{
//
// Did not find strDriver1 in astrVerifyDriverNames2
//
break;
}
}
}
return bDifferent;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfReadRegistryDwordValue( HKEY hKey,
LPCTSTR szValueName,
DWORD &dwValue )
{
LONG lResult;
BOOL bSuccess;
DWORD dwType;
DWORD dwDataSize;
dwDataSize = sizeof( dwValue );
lResult = RegQueryValueEx( hKey,
szValueName,
0,
&dwType,
( LPBYTE ) &dwValue,
&dwDataSize );
if( lResult == ERROR_FILE_NOT_FOUND )
{
//
// The value doesn't currently exist
//
dwValue = 0;
bSuccess = TRUE;
}
else
{
bSuccess = ( ERROR_SUCCESS == lResult &&
REG_DWORD == dwType &&
dwDataSize == sizeof( dwValue ) );
}
if( TRUE != bSuccess )
{
VrfErrorResourceFormat(
IDS_REGQUERYVALUEEX_FAILED,
szValueName,
(DWORD) lResult );
}
return bSuccess;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfReadRegistryStringValue( HKEY hKey,
LPCTSTR szValueName,
CString &strDriversToVerify )
{
BOOL bSuccess;
LONG lResult;
LPTSTR szDriversToVerify;
ULONG uRegKeyLength;
DWORD dwType;
DWORD dwDataSize;
bSuccess = FALSE;
lResult = ERROR_NOT_ENOUGH_MEMORY;
szDriversToVerify = NULL;
for( uRegKeyLength = 128; uRegKeyLength < 4096; uRegKeyLength += 128 )
{
//
// Try allocate a local buffer and use it to query
//
szDriversToVerify = new TCHAR[ uRegKeyLength ];
if( NULL != szDriversToVerify )
{
dwDataSize = uRegKeyLength * sizeof (TCHAR);
lResult = RegQueryValueEx( hKey,
szValueName,
0,
&dwType,
(LPBYTE) szDriversToVerify,
&dwDataSize );
switch( lResult )
{
case ERROR_FILE_NOT_FOUND:
//
// Return an empty string
//
szDriversToVerify[ 0 ] = (TCHAR)0;
bSuccess = TRUE;
break;
case ERROR_SUCCESS:
//
// Got the driver names from the registry
//
bSuccess = ( REG_SZ == dwType );
break;
default:
//
// Try with a bigger buffer
//
break;
}
}
if( FALSE != bSuccess )
{
//
// Got what we needed
//
break;
}
else
{
//
// Delete the current buffer and try with a bigger one
//
ASSERT( NULL != szDriversToVerify );
strDriversToVerify = szDriversToVerify;
delete [] szDriversToVerify;
szDriversToVerify = NULL;
}
}
if( TRUE != bSuccess )
{
VrfErrorResourceFormat(
IDS_REGSETVALUEEX_FAILED,
szValueName,
(DWORD) lResult);
}
else
{
ASSERT( NULL != szDriversToVerify );
strDriversToVerify = szDriversToVerify;
delete [] szDriversToVerify;
szDriversToVerify = NULL;
}
return bSuccess;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfDeleteAllVerifierSettings()
{
HKEY hMmKey = NULL;
LONG lResult;
BOOL bSuccess;
bSuccess = FALSE;
//
// Open the Mm key
//
lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
RegMemoryManagementKeyName,
0,
KEY_SET_VALUE,
&hMmKey );
if( lResult != ERROR_SUCCESS )
{
if( lResult == ERROR_ACCESS_DENIED )
{
VrfErrorResourceFormat(
IDS_ACCESS_IS_DENIED );
}
else
{
VrfErrorResourceFormat(
IDS_REGOPENKEYEX_FAILED,
RegMemoryManagementKeyName,
(DWORD)lResult);
}
goto Done;
}
//
// Delete VerifyDriverLevel value
//
lResult = RegDeleteValue( hMmKey,
RegVerifyDriverLevelValueName );
if( lResult != ERROR_SUCCESS && lResult != ERROR_FILE_NOT_FOUND )
{
VrfErrorResourceFormat(
IDS_REGDELETEVALUE_FAILED,
RegVerifyDriverLevelValueName,
(DWORD) lResult );
goto Done;
}
g_bSettingsSaved = g_bSettingsSaved | ( lResult != ERROR_FILE_NOT_FOUND );
//
// Delete VerifyDrivers value
//
lResult = RegDeleteValue( hMmKey,
RegVerifyDriversValueName );
if( lResult != ERROR_SUCCESS && lResult != ERROR_FILE_NOT_FOUND )
{
VrfErrorResourceFormat(
IDS_REGDELETEVALUE_FAILED,
RegVerifyDriversValueName,
(DWORD) lResult );
RegCloseKey (hMmKey);
goto Done;
}
g_bSettingsSaved = g_bSettingsSaved | ( lResult != ERROR_FILE_NOT_FOUND );
//
// Close the Mm key and return success
//
RegCloseKey( hMmKey );
bSuccess = TRUE;
if( bSuccess && g_bSettingsSaved )
{
VrfMesssageFromResource( IDS_REBOOT );
}
else
{
VrfMesssageFromResource(
IDS_NO_SETTINGS_WERE_CHANGED );
}
Done:
return bSuccess;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfGetRuntimeVerifierData( CRuntimeVerifierData *pRuntimeVerifierData )
{
NTSTATUS Status;
ULONG Length = 0;
ULONG buffersize;
BOOL bSuccess;
PSYSTEM_VERIFIER_INFORMATION VerifierInfo;
PSYSTEM_VERIFIER_INFORMATION VerifierInfoBase;
CRuntimeDriverData *pCrtDriverData;
LPTSTR szName;
ASSERT_VALID( pRuntimeVerifierData );
pRuntimeVerifierData->FillWithDefaults();
pRuntimeVerifierData->m_RuntimeDriverDataArray.DeleteAll();
bSuccess = FALSE;
//
// Try to get the right size for the NtQuery buffer
//
buffersize = 1024;
do
{
VerifierInfo = (PSYSTEM_VERIFIER_INFORMATION)malloc (buffersize);
if (VerifierInfo == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = NtQuerySystemInformation (SystemVerifierInformation,
VerifierInfo,
buffersize,
&Length);
if (Status != STATUS_INFO_LENGTH_MISMATCH)
{
break;
}
free (VerifierInfo);
buffersize += 1024;
} while (1);
if (! NT_SUCCESS(Status))
{
VrfErrorResourceFormat(
IDS_QUERY_SYSINFO_FAILED,
Status);
goto Done;
}
//
// If no info fill out return success but no info.
//
if (Length == 0)
{
free (VerifierInfo);
bSuccess = TRUE;
goto Done;
}
//
// Fill out the cumulative-driver stuff.
//
VerifierInfoBase = VerifierInfo;
pRuntimeVerifierData->m_bSpecialPool = (VerifierInfo->Level & DRIVER_VERIFIER_SPECIAL_POOLING) ? TRUE : FALSE;
pRuntimeVerifierData->m_bForceIrql = (VerifierInfo->Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) ? TRUE : FALSE;
pRuntimeVerifierData->m_bLowRes = (VerifierInfo->Level & DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES) ? TRUE : FALSE;
pRuntimeVerifierData->m_bPoolTracking = (VerifierInfo->Level & DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS) ? TRUE : FALSE;
pRuntimeVerifierData->m_bIo = (VerifierInfo->Level & DRIVER_VERIFIER_IO_CHECKING) ? TRUE : FALSE;
pRuntimeVerifierData->m_bDeadlockDetect = (VerifierInfo->Level & DRIVER_VERIFIER_DEADLOCK_DETECTION) ? TRUE : FALSE;
pRuntimeVerifierData->m_bDMAVerif = (VerifierInfo->Level & DRIVER_VERIFIER_DMA_VERIFIER) ? TRUE : FALSE;
pRuntimeVerifierData->m_bEnhIo = (VerifierInfo->Level & DRIVER_VERIFIER_ENHANCED_IO_CHECKING) ? TRUE : FALSE;
pRuntimeVerifierData->RaiseIrqls = VerifierInfo->RaiseIrqls;
pRuntimeVerifierData->AcquireSpinLocks = VerifierInfo->AcquireSpinLocks;
pRuntimeVerifierData->SynchronizeExecutions = VerifierInfo->SynchronizeExecutions;
pRuntimeVerifierData->AllocationsAttempted = VerifierInfo->AllocationsAttempted;
pRuntimeVerifierData->AllocationsSucceeded = VerifierInfo->AllocationsSucceeded;
pRuntimeVerifierData->AllocationsSucceededSpecialPool = VerifierInfo->AllocationsSucceededSpecialPool;
pRuntimeVerifierData->AllocationsWithNoTag = VerifierInfo->AllocationsWithNoTag;
pRuntimeVerifierData->Trims = VerifierInfo->Trims;
pRuntimeVerifierData->AllocationsFailed = VerifierInfo->AllocationsFailed;
pRuntimeVerifierData->AllocationsFailedDeliberately = VerifierInfo->AllocationsFailedDeliberately;
pRuntimeVerifierData->UnTrackedPool = VerifierInfo->UnTrackedPool;
pRuntimeVerifierData->Level = VerifierInfo->Level;
//
// Fill out the per-driver stuff.
//
VerifierInfo = VerifierInfoBase;
do
{
//
// Allocate a new driver data structure
//
pCrtDriverData = new CRuntimeDriverData;
if( NULL == pCrtDriverData )
{
VrfErrorResourceFormat( IDS_NOT_ENOUGH_MEMORY );
break;
}
#ifndef UNICODE
ANSI_STRING Name;
NTSTATUS Status;
Status = RtlUnicodeStringToAnsiString (
& Name,
& VerifierInfo->DriverName,
TRUE);
if (! (NT_SUCCESS(Status) ) )
{
VrfErrorResourceFormat( IDS_NOT_ENOUGH_MEMORY );
break;
}
szName = pCrtDriverData->m_strName.GetBuffer( Name.Length + 1 );
if( NULL != szName )
{
CopyMemory( szName,
Name.Buffer,
( Name.Length + 1 ) * sizeof( Name.Buffer[ 0 ] ) );
szName[ Name.Length ] = 0;
pCrtDriverData->m_strName.ReleaseBuffer();
}
RtlFreeAnsiString (& Name);
#else
szName = pCrtDriverData->m_strName.GetBuffer( VerifierInfo->DriverName.Length + 1 );
if( NULL != szName )
{
CopyMemory( szName,
VerifierInfo->DriverName.Buffer,
( VerifierInfo->DriverName.Length + 1 ) * sizeof( VerifierInfo->DriverName.Buffer[ 0 ] ) );
szName[ VerifierInfo->DriverName.Length ] = 0;
pCrtDriverData->m_strName.ReleaseBuffer();
}
#endif //#ifndef UNICODE
if( FALSE != pRuntimeVerifierData->IsDriverVerified( pCrtDriverData->m_strName ) )
{
//
// This is a duplicate entry - ignore it.
//
delete pCrtDriverData;
}
else
{
pCrtDriverData->Loads = VerifierInfo->Loads;
pCrtDriverData->Unloads = VerifierInfo->Unloads;
pCrtDriverData->CurrentPagedPoolAllocations = VerifierInfo->CurrentPagedPoolAllocations;
pCrtDriverData->CurrentNonPagedPoolAllocations = VerifierInfo->CurrentNonPagedPoolAllocations;
pCrtDriverData->PeakPagedPoolAllocations = VerifierInfo->PeakPagedPoolAllocations;
pCrtDriverData->PeakNonPagedPoolAllocations = VerifierInfo->PeakNonPagedPoolAllocations;
pCrtDriverData->PagedPoolUsageInBytes = VerifierInfo->PagedPoolUsageInBytes;
pCrtDriverData->NonPagedPoolUsageInBytes = VerifierInfo->NonPagedPoolUsageInBytes;
pCrtDriverData->PeakPagedPoolUsageInBytes = VerifierInfo->PeakPagedPoolUsageInBytes;
pCrtDriverData->PeakNonPagedPoolUsageInBytes = VerifierInfo->PeakNonPagedPoolUsageInBytes;
pRuntimeVerifierData->m_RuntimeDriverDataArray.Add( pCrtDriverData );
}
if (VerifierInfo->NextEntryOffset == 0) {
break;
}
VerifierInfo = (PSYSTEM_VERIFIER_INFORMATION)((PCHAR)VerifierInfo + VerifierInfo->NextEntryOffset);
}
while (1);
free (VerifierInfoBase);
Done:
return TRUE;
}
/////////////////////////////////////////////////////////////////////
PLOADED_IMAGE VrfImageLoad( LPTSTR szBinaryName,
LPTSTR szDirectory )
{
#ifdef UNICODE
char *szOemImageName;
char *szOemDirectory;
int nStringLength;
PLOADED_IMAGE pLoadedImage;
pLoadedImage = NULL;
nStringLength = wcslen( szBinaryName );
szOemImageName = new char [ nStringLength + 1 ];
if( NULL != szOemImageName )
{
CharToOem( szBinaryName,
szOemImageName );
if( NULL == szDirectory )
{
szOemDirectory = NULL;
}
else
{
nStringLength = wcslen( szDirectory );
szOemDirectory = new char [ nStringLength + 1 ];
CharToOem( szDirectory,
szOemDirectory );
}
pLoadedImage = ImageLoad( szOemImageName,
szOemDirectory );
if( NULL != szOemDirectory )
{
delete [] szOemDirectory;
}
delete [] szOemImageName;
}
return pLoadedImage;
#else
//
// Already have ANSI strings
//
return ImageLoad( szBinaryName,
szDirectory );
#endif //#ifdef UNICODE
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfDumpStateToFile( FILE *file )
{
BOOL bSuccess;
INT_PTR nDriversNo;
INT_PTR nCrtDriver;
SYSTEMTIME SystemTime;
TCHAR strLocalTime[ 64 ];
TCHAR strLocalDate[ 64 ];
CRuntimeDriverData *pRunDriverData;
CRuntimeVerifierData RunTimeVerifierData;
//
// Output the date&time in the current user format
//
GetLocalTime( &SystemTime );
if( GetDateFormat(
LOCALE_USER_DEFAULT,
0,
&SystemTime,
NULL,
strLocalDate,
ARRAY_LENGTH( strLocalDate ) ) )
{
VrfFTPrintf(
file,
_T( "%s, " ),
strLocalDate );
}
else
{
ASSERT( FALSE );
}
if( GetTimeFormat(
LOCALE_USER_DEFAULT,
0,
&SystemTime,
NULL,
strLocalTime,
ARRAY_LENGTH( strLocalTime ) ) )
{
VrfFTPrintf(
file,
_T( "%s\n" ),
strLocalTime);
}
else
{
ASSERT( FALSE );
VrfFTPrintf(
file,
_T( "\n" ) );
}
//
// Get the current verifier statistics
//
if( VrfGetRuntimeVerifierData( &RunTimeVerifierData ) == FALSE) {
VrfOuputStringFromResources(
IDS_CANTGET_VERIF_STATE,
file );
bSuccess = FALSE;
goto Done;
}
nDriversNo = RunTimeVerifierData.m_RuntimeDriverDataArray.GetSize();
if( 0 == nDriversNo )
{
//
// no statistics to dump
//
bSuccess = VrfOuputStringFromResources(
IDS_NO_DRIVER_VERIFIED,
file );
}
else
{
//
// dump the counters
//
//
// global counters
//
if( ( ! VrfFTPrintfResourceFormat( file, IDS_LEVEL, RunTimeVerifierData.Level ) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_RAISEIRQLS, RunTimeVerifierData.RaiseIrqls ) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_ACQUIRESPINLOCKS, RunTimeVerifierData.AcquireSpinLocks ) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_SYNCHRONIZEEXECUTIONS, RunTimeVerifierData.SynchronizeExecutions) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_ALLOCATIONSATTEMPTED, RunTimeVerifierData.AllocationsAttempted) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_ALLOCATIONSSUCCEEDED, RunTimeVerifierData.AllocationsSucceeded) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_ALLOCATIONSSUCCEEDEDSPECIALPOOL, RunTimeVerifierData.AllocationsSucceededSpecialPool) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_ALLOCATIONSWITHNOTAG, RunTimeVerifierData.AllocationsWithNoTag) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_ALLOCATIONSFAILED, RunTimeVerifierData.AllocationsFailed) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_ALLOCATIONSFAILEDDELIBERATELY, RunTimeVerifierData.AllocationsFailedDeliberately) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_TRIMS, RunTimeVerifierData.Trims) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_UNTRACKEDPOOL, RunTimeVerifierData.UnTrackedPool) ) )
{
bSuccess = FALSE;
goto Done;
}
//
// per driver counters
//
if( ! VrfOuputStringFromResources(
IDS_THE_VERIFIED_DRIVERS,
file ) )
{
bSuccess = FALSE;
goto Done;
}
for( nCrtDriver = 0; nCrtDriver < nDriversNo; nCrtDriver += 1 )
{
VrfFTPrintf(
file,
_T( "\n" ) );
pRunDriverData = RunTimeVerifierData.m_RuntimeDriverDataArray.GetAt( nCrtDriver ) ;
ASSERT_VALID( pRunDriverData );
if( VrfFTPrintfResourceFormat(
file,
IDS_NAME_LOADS_UNLOADS,
(LPCTSTR)pRunDriverData->m_strName,
pRunDriverData->Loads,
pRunDriverData->Unloads) == FALSE )
{
bSuccess = FALSE;
goto Done;
}
//
// pool statistics
//
if( ( ! VrfFTPrintfResourceFormat( file, IDS_CURRENTPAGEDPOOLALLOCATIONS, pRunDriverData->CurrentPagedPoolAllocations) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_CURRENTNONPAGEDPOOLALLOCATIONS, pRunDriverData->CurrentNonPagedPoolAllocations) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_PEAKPAGEDPOOLALLOCATIONS, pRunDriverData->PeakPagedPoolAllocations) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_PEAKNONPAGEDPOOLALLOCATIONS, pRunDriverData->PeakNonPagedPoolAllocations) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_PAGEDPOOLUSAGEINBYTES, (ULONG) pRunDriverData->PagedPoolUsageInBytes) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_NONPAGEDPOOLUSAGEINBYTES, (ULONG) pRunDriverData->NonPagedPoolUsageInBytes) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_PEAKPAGEDPOOLUSAGEINBYTES, (ULONG) pRunDriverData->PeakPagedPoolUsageInBytes) ) ||
( ! VrfFTPrintfResourceFormat( file, IDS_PEAKNONPAGEDPOOLUSAGEINBYTES, (ULONG) pRunDriverData->PeakNonPagedPoolUsageInBytes) ) )
{
bSuccess = FALSE;
goto Done;
}
}
}
Done:
return bSuccess;
}
/////////////////////////////////////////////////////////////////////////////
BOOL __cdecl VrfFTPrintf( FILE *file,
LPCTSTR szFormat,
... )
{
TCHAR szMessage[ 256 ];
BOOL bResult;
va_list prms;
ASSERT( NULL != file );
ASSERT( g_bCommandLineMode );
va_start (prms, szFormat);
//
// Format the message in our local buffer
//
_vsntprintf ( szMessage,
ARRAY_LENGTH( szMessage ),
szFormat,
prms );
bResult = ( _fputts( szMessage, file ) >= 0 );
va_end (prms);
return bResult;
}
/////////////////////////////////////////////////////////////////////////////
BOOL __cdecl VrfFTPrintfResourceFormat( FILE *file,
UINT uIdResourceFormat,
... )
{
TCHAR szMessage[ 256 ];
TCHAR strFormat[ 256 ];
BOOL bResult;
va_list prms;
ASSERT( NULL != file );
//
// Load the format string from the resources
//
bResult = VrfLoadString( uIdResourceFormat,
strFormat,
ARRAY_LENGTH( strFormat ) );
ASSERT( bResult );
if( bResult )
{
va_start (prms, uIdResourceFormat);
//
// Format the message in our local buffer
//
_vsntprintf ( szMessage,
ARRAY_LENGTH( szMessage ),
strFormat,
prms);
bResult = ( _fputts( szMessage, file ) >= 0 );
va_end (prms);
}
return bResult;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfOuputStringFromResources( UINT uIdString,
FILE *file )
{
TCHAR szText[ 256 ];
BOOL bResult;
ASSERT( NULL != file );
bResult = VrfLoadString( uIdString,
szText,
ARRAY_LENGTH( szText ) );
if( FALSE == bResult )
{
goto Done;
}
bResult = ( _fputts( szText, file ) >= 0 );
Done:
return bResult;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfSetNewFlagsVolatile( DWORD dwNewFlags )
{
BOOL bResult;
NTSTATUS Status;
INT_PTR nCurrentlyVerifiedDrivers;
CRuntimeVerifierData RunTimeVerifierData;
bResult = TRUE;
nCurrentlyVerifiedDrivers = 0;
if( VrfGetRuntimeVerifierData( &RunTimeVerifierData ) == FALSE )
{
//
// Cannot get current verifier settings
//
VrfErrorResourceFormat( IDS_CANTGET_VERIF_STATE );
bResult = FALSE;
goto Done;
}
nCurrentlyVerifiedDrivers = RunTimeVerifierData.m_RuntimeDriverDataArray.GetSize();
if( nCurrentlyVerifiedDrivers > 0 )
{
//
// There are some drivers currently verified
//
if( RunTimeVerifierData.Level != dwNewFlags )
{
//
// Just use NtSetSystemInformation to set the flags
// that can be modified on the fly. Don't write anything to the registry.
//
//
// Enable debug privilege
//
if( g_bPrivegeEnabled != TRUE )
{
g_bPrivegeEnabled = VrfEnableDebugPrivilege();
if( g_bPrivegeEnabled != TRUE )
{
bResult = FALSE;
goto Done;
}
}
//
// Set the new flags
//
Status = NtSetSystemInformation(
SystemVerifierInformation,
&dwNewFlags,
sizeof( dwNewFlags ) );
if( ! NT_SUCCESS( Status ) )
{
if( Status == STATUS_ACCESS_DENIED )
{
//
// Access denied
//
VrfErrorResourceFormat(
IDS_ACCESS_IS_DENIED );
}
else
{
//
// Some other error
//
VrfErrorResourceFormat(
IDS_CANNOT_CHANGE_SETTING_ON_FLY );
}
bResult = FALSE;
goto Done;
}
}
}
Done:
if( g_bCommandLineMode )
{
VrfDumpChangedSettings( RunTimeVerifierData.Level,
dwNewFlags,
nCurrentlyVerifiedDrivers );
}
return bResult;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfAddDriversVolatile( const CStringArray &astrNewDrivers )
{
BOOL bSuccess;
INT_PTR nDrivers;
INT_PTR nCrtDriver;
CString strCrtDriver;
bSuccess = TRUE;
nDrivers = astrNewDrivers.GetSize();
for( nCrtDriver = 0; nCrtDriver < nDrivers; nCrtDriver += 1 )
{
strCrtDriver = astrNewDrivers.GetAt( nCrtDriver );
if( TRUE != VrfAddDriverVolatile( strCrtDriver ) )
{
bSuccess = FALSE;
}
}
return bSuccess;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfAddDriverVolatile( const CString &strCrtDriver )
{
NTSTATUS Status;
UINT uIdErrorString;
BOOL bSuccess;
UNICODE_STRING usDriverName;
#ifndef UNICODE
WCHAR *szUnicodeName = NULL;
INT_PTR nNameLength;
#endif //#ifndef UNICODE
bSuccess = TRUE;
//
// Enable debug privilege
//
if( g_bPrivegeEnabled != TRUE )
{
g_bPrivegeEnabled = VrfEnableDebugPrivilege();
if( g_bPrivegeEnabled != TRUE )
{
bSuccess = FALSE;
goto Done;
}
}
//
// Must have driver name as a UNICODE_STRING
//
#ifdef UNICODE
//
// UNICODE
//
RtlInitUnicodeString(
&usDriverName,
(LPCTSTR) strCrtDriver );
#else
//
// ANSI
//
nNameLength = strCrtDriver.GetLength();
szUnicodeName = new WCHAR[ nNameLength + 1 ];
if( NULL == szUnicodeName )
{
VrfErrorResourceFormat( IDS_NOT_ENOUGH_MEMORY );
bSuccess = FALSE;
goto Done;
}
MultiByteToWideChar( CP_ACP,
0,
(LPCSTR) strCrtDriver,
-1,
szUnicodeName,
nNameLength + 1 );
RtlInitUnicodeString(
&usDriverName,
szUnicodeName );
#endif //#ifdef UNICODE
Status = NtSetSystemInformation(
SystemVerifierAddDriverInformation,
&usDriverName,
sizeof( UNICODE_STRING ) );
if( ! NT_SUCCESS( Status ) )
{
switch( Status )
{
case STATUS_INVALID_INFO_CLASS:
uIdErrorString = IDS_VERIFIER_ADD_NOT_SUPPORTED;
break;
case STATUS_NOT_SUPPORTED:
uIdErrorString = IDS_DYN_ADD_NOT_SUPPORTED;
break;
case STATUS_IMAGE_ALREADY_LOADED:
uIdErrorString = IDS_DYN_ADD_ALREADY_LOADED;
break;
case STATUS_INSUFFICIENT_RESOURCES:
case STATUS_NO_MEMORY:
uIdErrorString = IDS_DYN_ADD_INSUF_RESOURCES;
break;
case STATUS_PRIVILEGE_NOT_HELD:
uIdErrorString = IDS_DYN_ADD_ACCESS_DENIED;
break;
default:
VrfErrorResourceFormat(
IDS_DYN_ADD_MISC_ERROR,
(LPCTSTR) strCrtDriver,
Status );
bSuccess = FALSE;
}
VrfErrorResourceFormat(
uIdErrorString,
(LPCTSTR) strCrtDriver );
bSuccess = FALSE;
}
#ifndef UNICODE
if( NULL != szUnicodeName )
{
delete [] szUnicodeName;
}
#endif //#ifndef UNICODE
Done:
return bSuccess;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfRemoveDriversVolatile( const CStringArray &astrNewDrivers )
{
INT_PTR nDrivers;
INT_PTR nCrtDriver;
BOOL bSuccess;
CString strCrtDriver;
bSuccess = TRUE;
nDrivers = astrNewDrivers.GetSize();
for( nCrtDriver = 0; nCrtDriver < nDrivers; nCrtDriver += 1 )
{
strCrtDriver = astrNewDrivers.GetAt( nCrtDriver );
if( TRUE != VrfRemoveDriverVolatile( strCrtDriver ) )
{
bSuccess = FALSE;
}
}
return bSuccess;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfRemoveDriverVolatile( const CString &strDriverName )
{
NTSTATUS Status;
UINT uIdErrorString;
BOOL bSuccess;
UNICODE_STRING usDriverName;
#ifndef UNICODE
WCHAR *szUnicodeName = NULL;
INT_PTR nNameLength;
#endif //#ifndef UNICODE
bSuccess = TRUE;
//
// Enable debug privilege
//
if( g_bPrivegeEnabled != TRUE )
{
g_bPrivegeEnabled = VrfEnableDebugPrivilege();
if( g_bPrivegeEnabled != TRUE )
{
bSuccess = FALSE;
goto Done;
}
}
//
// Must have driver name as a UNICODE_STRING
//
#ifdef UNICODE
//
// UNICODE
//
RtlInitUnicodeString(
&usDriverName,
(LPCTSTR) strDriverName );
#else
//
// ANSI
//
nNameLength = strDriverName.GetLength();
szUnicodeName = new WCHAR[ nNameLength + 1 ];
if( NULL == szUnicodeName )
{
VrfErrorResourceFormat( IDS_NOT_ENOUGH_MEMORY );
bSuccess = FALSE;
goto Done;
}
MultiByteToWideChar( CP_ACP,
0,
(LPCSTR) strDriverName,
-1,
szUnicodeName,
nNameLength + 1 );
RtlInitUnicodeString(
&usDriverName,
szUnicodeName );
#endif //#ifdef UNICODE
Status = NtSetSystemInformation(
SystemVerifierRemoveDriverInformation,
&usDriverName,
sizeof( UNICODE_STRING ) );
if( ! NT_SUCCESS( Status ) )
{
switch( Status )
{
case STATUS_INVALID_INFO_CLASS:
uIdErrorString = IDS_VERIFIER_REMOVE_NOT_SUPPORTED;
break;
case STATUS_NOT_SUPPORTED:
//
// the driver verifier is not currently active at all -> success
//
case STATUS_NOT_FOUND:
//
// the driver is not currently verified -> success
//
return TRUE;
case STATUS_IMAGE_ALREADY_LOADED:
uIdErrorString = IDS_DYN_REMOVE_ALREADY_LOADED;
break;
case STATUS_INSUFFICIENT_RESOURCES:
case STATUS_NO_MEMORY:
uIdErrorString = IDS_DYN_REMOVE_INSUF_RESOURCES;
break;
case STATUS_PRIVILEGE_NOT_HELD:
uIdErrorString = IDS_DYN_REMOVE_ACCESS_DENIED;
break;
default:
VrfErrorResourceFormat(
IDS_DYN_REMOVE_MISC_ERROR,
(LPCTSTR) strDriverName,
Status );
bSuccess = FALSE;
}
VrfErrorResourceFormat(
uIdErrorString,
(LPCTSTR) strDriverName );
bSuccess = FALSE;
}
Done:
#ifndef UNICODE
if( NULL != szUnicodeName )
{
delete [] szUnicodeName;
}
#endif //#ifndef UNICODE
return bSuccess;
}
//////////////////////////////////////////////////////////////////////
BOOL VrfEnableDebugPrivilege( )
{
struct
{
DWORD Count;
LUID_AND_ATTRIBUTES Privilege [1];
} Info;
HANDLE Token;
BOOL Result;
//
// Open the process token
//
Result = OpenProcessToken (
GetCurrentProcess (),
TOKEN_ADJUST_PRIVILEGES,
& Token);
if( Result != TRUE )
{
VrfErrorResourceFormat(
IDS_ACCESS_IS_DENIED );
return FALSE;
}
//
// Prepare the info structure
//
Info.Count = 1;
Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
Result = LookupPrivilegeValue (
NULL,
SE_DEBUG_NAME,
&(Info.Privilege[0].Luid));
if( Result != TRUE )
{
VrfErrorResourceFormat(
IDS_ACCESS_IS_DENIED );
CloseHandle( Token );
return FALSE;
}
//
// Adjust the privileges
//
Result = AdjustTokenPrivileges (
Token,
FALSE,
(PTOKEN_PRIVILEGES) &Info,
NULL,
NULL,
NULL);
if( Result != TRUE || GetLastError() != ERROR_SUCCESS )
{
VrfErrorResourceFormat(
IDS_ACCESS_IS_DENIED );
CloseHandle( Token );
return FALSE;
}
CloseHandle( Token );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
VOID VrfDumpChangedSettings( UINT OldFlags,
UINT NewFlags,
INT_PTR nDriversVerified )
{
UINT uDifferentFlags;
if( nDriversVerified == 0 )
{
VrfPrintStringFromResources(
IDS_NO_DRIVER_VERIFIED );
goto Done;
}
if( OldFlags == NewFlags )
{
//
// no settings were changed
//
VrfPrintStringFromResources(
IDS_NO_SETTINGS_WERE_CHANGED );
}
else
{
VrfPrintStringFromResources(
IDS_CHANGED_SETTINGS_ARE );
uDifferentFlags = OldFlags ^ NewFlags;
//
// changed DRIVER_VERIFIER_SPECIAL_POOLING ?
//
if( uDifferentFlags & DRIVER_VERIFIER_SPECIAL_POOLING )
{
if( NewFlags & DRIVER_VERIFIER_SPECIAL_POOLING )
{
VrfPrintStringFromResources(
IDS_SPECIAL_POOL_ENABLED_NOW );
}
else
{
VrfPrintStringFromResources(
IDS_SPECIAL_POOL_DISABLED_NOW );
}
}
//
// changed DRIVER_VERIFIER_FORCE_IRQL_CHECKING ?
//
if( uDifferentFlags & DRIVER_VERIFIER_FORCE_IRQL_CHECKING )
{
if( NewFlags & DRIVER_VERIFIER_FORCE_IRQL_CHECKING )
{
VrfPrintStringFromResources(
IDS_FORCE_IRQLCHECK_ENABLED_NOW );
}
else
{
VrfPrintStringFromResources(
IDS_FORCE_IRQLCHECK_DISABLED_NOW );
}
}
//
// changed DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES ?
//
if( uDifferentFlags & DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES )
{
if( NewFlags & DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES )
{
VrfPrintStringFromResources(
IDS_FAULT_INJECTION_ENABLED_NOW );
}
else
{
VrfPrintStringFromResources(
IDS_FAULT_INJECTION_DISABLED_NOW );
}
}
//
// changed DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS ?
//
if( uDifferentFlags & DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS )
{
if( NewFlags & DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS )
{
VrfPrintStringFromResources(
IDS_POOL_TRACK_ENABLED_NOW );
}
else
{
VrfPrintStringFromResources(
IDS_POOL_TRACK_DISABLED_NOW );
}
}
//
// changed DRIVER_VERIFIER_IO_CHECKING ?
//
if( uDifferentFlags & DRIVER_VERIFIER_IO_CHECKING )
{
if( NewFlags & DRIVER_VERIFIER_IO_CHECKING )
{
VrfPrintStringFromResources(
IDS_IO_CHECKING_ENABLED_NOW );
}
else
{
VrfPrintStringFromResources(
IDS_IO_CHECKING_DISABLED_NOW );
}
}
//
// the changes are not saved to the registry
//
VrfPrintStringFromResources(
IDS_CHANGES_ACTIVE_ONLY_BEFORE_REBOOT );
}
Done:
NOTHING;
}
/////////////////////////////////////////////////////////////////////////////
DWORD VrfGetStandardFlags()
{
DWORD dwStandardFlags;
dwStandardFlags = DRIVER_VERIFIER_SPECIAL_POOLING |
DRIVER_VERIFIER_FORCE_IRQL_CHECKING |
DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS |
DRIVER_VERIFIER_IO_CHECKING |
DRIVER_VERIFIER_DEADLOCK_DETECTION |
DRIVER_VERIFIER_DMA_VERIFIER;
return dwStandardFlags;
}
/////////////////////////////////////////////////////////////////////////////
VOID VrfAddMiniports( CStringArray &astrVerifiedDrivers )
{
CStringArray astrToAdd;
CString strCrtDriver;
CString strCrtDriverToAdd;
CString strLinkedDriver;
INT_PTR nVerifiedDrivers;
INT_PTR nCrtDriver;
INT_PTR nDriversToAdd;
INT_PTR nCrtDriverToAdd;
nVerifiedDrivers = astrVerifiedDrivers.GetSize();
for( nCrtDriver = 0; nCrtDriver < nVerifiedDrivers; nCrtDriver += 1 )
{
//
// This will be a verified driver
//
strCrtDriver = astrVerifiedDrivers.GetAt( nCrtDriver );
//
// Check if it is a miniport driver
//
if( VrfIsDriverMiniport( strCrtDriver,
strLinkedDriver ) )
{
//
// Check if we didn't add already strLinkedDriver
//
nDriversToAdd = astrToAdd.GetSize();
for( nCrtDriverToAdd = 0; nCrtDriverToAdd < nDriversToAdd; nCrtDriverToAdd += 1 )
{
strCrtDriverToAdd = astrToAdd.GetAt( nCrtDriverToAdd );
if( strCrtDriverToAdd.CompareNoCase( strLinkedDriver ) == 0 )
{
//
// We already wanted to add this driver
//
break;
}
}
if( nCrtDriverToAdd >= nDriversToAdd )
{
//
// Add this new driver (strLinkedDriver)
//
astrToAdd.Add( strLinkedDriver );
}
}
}
//
// Flush astrToAdd into astrVerifiedDrivers
//
nDriversToAdd = astrToAdd.GetSize();
for( nCrtDriverToAdd = 0; nCrtDriverToAdd < nDriversToAdd; nCrtDriverToAdd += 1 )
{
strCrtDriverToAdd = astrToAdd.GetAt( nCrtDriverToAdd );
astrVerifiedDrivers.Add( strCrtDriverToAdd );
}
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfIsDriverMiniport( CString &strCrtDriver,
CString &strLinkedDriver )
{
//
// N.B.
//
// The imagehlp functions are not multithreading safe
// (see Whistler bug #88373) so if we want to use them from more than
// one thread we will have to aquire some critical section before.
//
// Currently only one thread is using the imagehlp APIs in this app
// (CSlowProgressDlg::LoadDriverDataWorkerThread) so we don't need
// our synchronization.
//
LPTSTR szDriverName;
LPTSTR szDriversDir;
PLOADED_IMAGE pLoadedImage;
BOOL bIsMiniport;
BOOL bUnloaded;
bIsMiniport = FALSE;
ASSERT( strCrtDriver.GetLength() > 0 );
//
// ImageLoad doesn't know about const pointers so
// we have to GetBuffer here :-(
//
szDriverName = strCrtDriver.GetBuffer( strCrtDriver.GetLength() + 1 );
if( NULL == szDriverName )
{
goto Done;
}
szDriversDir = g_strDriversDir.GetBuffer( g_strDriversDir.GetLength() + 1 );
if( NULL == szDriversDir )
{
strCrtDriver.ReleaseBuffer();
goto Done;
}
//
// Load the image
//
pLoadedImage = VrfImageLoad( szDriverName,
szDriversDir );
if( NULL == pLoadedImage )
{
//
// Could not load the image from %windir%\system32\drivers
// Try again from the PATH
//
pLoadedImage = VrfImageLoad( szDriverName,
NULL );
}
//
// Give our string buffers back to MFC
//
strCrtDriver.ReleaseBuffer();
g_strDriversDir.ReleaseBuffer();
if( NULL == pLoadedImage )
{
//
// We couldn't load this image - bad luck
//
TRACE( _T( "ImageLoad failed for %s, error %u\n" ),
(LPCTSTR) strCrtDriver,
GetLastError() );
goto Done;
}
//
// Check if the current driver is a miniport
//
bIsMiniport = VrfIsDriverMiniport( pLoadedImage,
strLinkedDriver );
//
// Clean-up
//
bUnloaded = ImageUnload( pLoadedImage );
//
// If ImageUnload fails we cannot do much about it...
//
ASSERT( bUnloaded );
Done:
return bIsMiniport;
}
/////////////////////////////////////////////////////////////////////////////
LPSTR g_szSpecialDrivers[] =
{
"videoprt.sys",
"scsiport.sys"
};
BOOL VrfpLookForAllImportDescriptors( PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor,
ULONG_PTR uVACorrection,
CString &strLinkedAgainst )
{
PIMAGE_IMPORT_DESCRIPTOR pCurrentDescriptor;
PCHAR pCrtName;
ULONG uCrtSpecialDriver;
BOOL bIsMiniport;
#ifdef UNICODE
//
// UNICODE
//
INT nCrtStringLength;
PWSTR szMiniportName;
#endif //#ifdef UNICODE
bIsMiniport = FALSE;
for( uCrtSpecialDriver = 0; ! bIsMiniport && uCrtSpecialDriver < ARRAY_LENGTH( g_szSpecialDrivers ); uCrtSpecialDriver += 1 )
{
pCurrentDescriptor = pImportDescriptor;
while( pCurrentDescriptor->Characteristics != NULL )
{
pCrtName = (PCHAR)UlongToPtr( pCurrentDescriptor->Name ) + uVACorrection;
if( lstrcmpiA( g_szSpecialDrivers[ uCrtSpecialDriver ] , pCrtName ) == 0 )
{
//
// This is a miniport
//
#ifndef UNICODE
//
// ANSI
//
strLinkedAgainst = g_szSpecialDrivers[ uCrtSpecialDriver ];
#else
//
// UNICODE
//
nCrtStringLength = strlen( g_szSpecialDrivers[ uCrtSpecialDriver ] );
szMiniportName = strLinkedAgainst.GetBuffer( nCrtStringLength + 1 );
if( NULL != szMiniportName )
{
MultiByteToWideChar( CP_ACP,
0,
g_szSpecialDrivers[ uCrtSpecialDriver ],
-1,
szMiniportName,
( nCrtStringLength + 1 ) * sizeof( TCHAR ) );
strLinkedAgainst.ReleaseBuffer();
}
#endif
bIsMiniport = TRUE;
break;
}
pCurrentDescriptor += 1;
}
}
return bIsMiniport;
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfIsDriverMiniport( PLOADED_IMAGE pLoadedImage,
CString &strLinkedDriver )
{
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor;
PIMAGE_SECTION_HEADER pSectionHeader;
ULONG_PTR uVACorrection;
ULONG uDataSize;
BOOL bIsMiniport;
bIsMiniport = FALSE;
//
// We are protecting ourselves against corrupted binaries
// with this exception handler
//
try
{
pSectionHeader = NULL;
pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToDataEx(
pLoadedImage->MappedAddress,
FALSE,
IMAGE_DIRECTORY_ENTRY_IMPORT,
&uDataSize,
&pSectionHeader );
if( NULL == pSectionHeader )
{
goto Done;
}
uVACorrection = (ULONG_PTR) pLoadedImage->MappedAddress +
pSectionHeader->PointerToRawData -
pSectionHeader->VirtualAddress;
bIsMiniport = VrfpLookForAllImportDescriptors( pImportDescriptor,
uVACorrection,
strLinkedDriver );
#ifdef _DEBUG
if( bIsMiniport )
{
TRACE( _T( "%s will be auto-enabled\n" ),
(LPCTSTR) strLinkedDriver );
}
#endif //#ifdef DEBUG
}
catch( ... )
{
TRACE( _T( "VrfIsDriverMiniport: Caught exception\n" ) );
}
Done:
return bIsMiniport;
}
/////////////////////////////////////////////////////////////////////////////
VOID VrfpDumpSettingToConsole( ULONG uIdResourceString,
BOOL bEnabled )
{
CString strTitle;
CString strEnabled;
ULONG uIdEnabledString;
TCHAR szBigBuffer[ 128 ];
VERIFY( VrfLoadString( uIdResourceString, strTitle ) );
if( FALSE == bEnabled )
{
uIdEnabledString = IDS_DISABLED;
}
else
{
uIdEnabledString = IDS_ENABLED;
}
VERIFY( VrfLoadString( uIdEnabledString, strEnabled ) );
_sntprintf( szBigBuffer,
ARRAY_LENGTH( szBigBuffer ),
_T( "%s: %s" ),
(LPCTSTR) strTitle,
(LPCTSTR) strEnabled );
szBigBuffer[ ARRAY_LENGTH( szBigBuffer ) - 1 ] = 0;
_putts( szBigBuffer );
}
/////////////////////////////////////////////////////////////////////////////
VOID VrfDumpRegistrySettingsToConsole()
{
BOOL bLoaded;
BOOL bAllDriversVerified;
DWORD dwVerifyFlags;
INT_PTR nDrivers;
INT_PTR nCrtDriver;
CString strCrtDriver;
CStringArray astrDriversToVerify;
bLoaded = VrtLoadCurrentRegistrySettings( bAllDriversVerified,
astrDriversToVerify,
dwVerifyFlags );
if( FALSE != bLoaded )
{
VrfpDumpSettingToConsole( IDS_SPECIAL_POOL, ( dwVerifyFlags & DRIVER_VERIFIER_SPECIAL_POOLING ) != 0 );
VrfpDumpSettingToConsole( IDS_FORCE_IRQL_CHECKING, ( dwVerifyFlags & DRIVER_VERIFIER_FORCE_IRQL_CHECKING ) != 0 );
VrfpDumpSettingToConsole( IDS_LOW_RESOURCE_SIMULATION, ( dwVerifyFlags & DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES ) != 0 );
VrfpDumpSettingToConsole( IDS_POOL_TRACKING, ( dwVerifyFlags & DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS ) != 0 );
VrfpDumpSettingToConsole( IDS_IO_VERIFICATION, ( dwVerifyFlags & DRIVER_VERIFIER_IO_CHECKING ) != 0 );
VrfpDumpSettingToConsole( IDS_DEADLOCK_DETECTION, ( dwVerifyFlags & DRIVER_VERIFIER_DEADLOCK_DETECTION ) != 0 );
VrfpDumpSettingToConsole( IDS_ENH_IO_VERIFICATION, ( dwVerifyFlags & DRIVER_VERIFIER_ENHANCED_IO_CHECKING ) != 0 );
VrfpDumpSettingToConsole( IDS_DMA_CHECHKING, ( dwVerifyFlags & DRIVER_VERIFIER_DMA_VERIFIER ) != 0 );
VrfPrintStringFromResources( IDS_VERIFIED_DRIVERS );
if( bAllDriversVerified )
{
VrfPrintStringFromResources( IDS_ALL );
}
else
{
nDrivers = astrDriversToVerify.GetSize();
if( nDrivers > 0 )
{
for( nCrtDriver = 0; nCrtDriver < nDrivers; nCrtDriver += 1 )
{
strCrtDriver = astrDriversToVerify.GetAt( nCrtDriver );
_putts( (LPCTSTR) strCrtDriver );
}
}
else
{
VrfPrintStringFromResources( IDS_NONE );
}
}
}
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfIsNameAlreadyInList( LPCTSTR szDriver,
LPCTSTR szAllDrivers )
{
INT nNameLength;
INT nLastIndex;
INT nIndex;
BOOL bFoundIt;
CString strDriver( szDriver );
CString strAllDrivers( szAllDrivers );
bFoundIt = FALSE;
strDriver.MakeLower();
strAllDrivers.MakeLower();
nNameLength = strDriver.GetLength();
nLastIndex = 0;
do
{
nIndex = strAllDrivers.Find( (LPCTSTR)strDriver, nLastIndex );
if( nIndex >= 0 )
{
//
// Found the substring. Verify it is separated of spaces, etc.
//
if( (nIndex == 0 || _T( ' ' ) == strAllDrivers[ nIndex - 1 ]) &&
( (TCHAR)0 == strAllDrivers[ nNameLength + nIndex ] || _T( ' ' ) == strAllDrivers[ nNameLength + nIndex ]) )
{
//
// This is our driver.
//
bFoundIt = TRUE;
break;
}
else
{
//
// Continue searching.
//
nLastIndex = nIndex + 1;
}
}
}
while( nIndex >= 0 );
return bFoundIt;
}
/////////////////////////////////////////////////////////////////////////////
VOID VrfAddDriverNameNoDuplicates( LPCTSTR szDriver,
CString &strAllDrivers )
{
if( FALSE == VrfIsNameAlreadyInList( szDriver,
strAllDrivers ) )
{
if( strAllDrivers.GetLength() > 0 )
{
strAllDrivers += _T( ' ' );
}
strAllDrivers += szDriver;
}
}
/////////////////////////////////////////////////////////////////////////////
BOOL VrfIsStringInArray( LPCTSTR szText,
const CStringArray &astrAllTexts )
{
INT_PTR nTexts;
BOOL bFound;
bFound = FALSE;
nTexts = astrAllTexts.GetSize();
while( nTexts > 0 )
{
nTexts -= 1;
if( 0 == astrAllTexts.GetAt( nTexts ).CompareNoCase( szText ) )
{
bFound = TRUE;
break;
}
}
return bFound;
}