// // Enable driver verifier support for ntoskrnl // Copyright (c) Microsoft Corporation, 1999 // // // module: regutil.cxx // author: DMihai // created: 04/19/99 // description: registry keys manipulation routines // extern "C" { #include "nt.h" #include "ntrtl.h" #include "nturtl.h" } #include #include #include #include "ResId.hxx" #include "RegUtil.hxx" #include "GenUtil.hxx" #define VRF_MAX_DRIVER_STRING_LENGTH 4196 #define LEVEL2_IO_VERIFIER_ENABLED_VALUE 3 ////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////// Registry Strings ////////////////////////////////////////////////////////////////////// LPCTSTR RegMemoryManagementKeyName = TEXT ("System\\CurrentControlSet\\Control\\Session Manager\\Memory Management"); LPCTSTR RegVerifyDriversValueName = TEXT ("VerifyDrivers"); LPCTSTR RegVerifyDriverLevelValueName = TEXT ("VerifyDriverLevel"); LPCTSTR RegIOVerifyKeyName = TEXT ("System\\CurrentControlSet\\Control\\Session Manager\\I/O System"); LPCTSTR RegIOVerifySubKeyName = TEXT ("I/O System"); LPCTSTR RegIOVerifyLevelValueName = TEXT ("IoVerifierLevel"); LPCTSTR RegSessionManagerKeyName = TEXT ("System\\CurrentControlSet\\Control\\Session Manager"); ////////////////////////////////////////////////////////////////////// /////////////// Forward decl for local registry manipulation functions ////////////////////////////////////////////////////////////////////// BOOL ReadRegistryValue ( HKEY HKey, LPCTSTR Name, DWORD * Value); BOOL WriteRegistryValue ( HKEY MmKey, LPCTSTR Name, DWORD Value); BOOL ReadMmString ( HKEY MmKey, LPCTSTR Name, LPTSTR Value); BOOL WriteMmString ( HKEY MmKey, LPCTSTR Name, LPTSTR Value); ////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////// Public functions ////////////////////////////////////////////////////////////////////// void WriteVerifierKeys( BOOL bEnableKrnVerifier, DWORD dwNewVerifierFlags, DWORD dwNewIoLevel, TCHAR *strKernelModuleName ) { HKEY MmKey = NULL; DWORD dwExitCode; DWORD dwCrtFlags; DWORD dwCrtIoLevel; BOOL bMustAppendName; BOOL bAlreadyInRegistry; LONG lOpenResult; int nKernelModuleNameLen; int nStringLen; TCHAR *pstrCrtNameMatch, *pstrSubstring, *pCrtChar; TCHAR strVrfDriver [VRF_MAX_DRIVER_STRING_LENGTH]; TCHAR strVrfDriverNew [VRF_MAX_DRIVER_STRING_LENGTH]; dwExitCode = EXIT_CODE_NOTHING_CHANGED; // // Open the Mm key // lOpenResult = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, RegMemoryManagementKeyName, 0, KEY_QUERY_VALUE | KEY_WRITE, &MmKey); if (lOpenResult != ERROR_SUCCESS) { // // fatal error // dwExitCode = EXIT_CODE_ERROR; if( lOpenResult == ERROR_ACCESS_DENIED ) { DisplayMessage( IDS_ACCESS_IS_DENIED ); } else { DisplayMessage( IDS_REGOPENKEYEX_FAILED, RegMemoryManagementKeyName, (DWORD)lOpenResult); } } if( dwExitCode != EXIT_CODE_ERROR != 0 ) { // // the IO verifier will be enabled // if( dwNewIoLevel != 2 ) { // // only levels 1 & 2 are supported // dwNewIoLevel = 1; } // // get the current IO level // if( GetIoVerificationLevel( &dwCrtIoLevel ) == FALSE ) { // // fatal error // dwExitCode = EXIT_CODE_ERROR; } } if( dwExitCode != EXIT_CODE_ERROR ) { if( ReadRegistryValue( MmKey, RegVerifyDriverLevelValueName, &dwCrtFlags ) == FALSE ) { dwExitCode = EXIT_CODE_ERROR; } else { if( dwNewVerifierFlags != -1 ) { // // have some new flags // // // modify the flags in registry // if( dwCrtFlags != dwNewVerifierFlags ) { if( WriteRegistryValue( MmKey, RegVerifyDriverLevelValueName, dwNewVerifierFlags ) == FALSE ) { dwExitCode = EXIT_CODE_ERROR; } else { dwExitCode = EXIT_CODE_REBOOT; } } if( dwExitCode != EXIT_CODE_ERROR ) { if( ( dwNewVerifierFlags & DRIVER_VERIFIER_IO_CHECKING ) == 0 ) { // // IO verification is not enabled - disable "level 2" value too // dwNewIoLevel = 1; } // // the IO verifier will be enabled // if( dwCrtIoLevel != dwNewIoLevel ) { // // need to switch the IO verification level // if( SwitchIoVerificationLevel( dwNewIoLevel ) == TRUE ) { dwExitCode = EXIT_CODE_REBOOT; } else { dwExitCode = EXIT_CODE_ERROR; } } } } } if( dwExitCode != EXIT_CODE_ERROR && bEnableKrnVerifier ) { // // enable verifier for the kernel // if( ReadMmString (MmKey, RegVerifyDriversValueName, strVrfDriver) == FALSE) { dwExitCode = EXIT_CODE_ERROR; } else { bAlreadyInRegistry = IsModuleNameAlreadyInRegistry( strKernelModuleName, strVrfDriver ); if( bAlreadyInRegistry == FALSE ) { _tcscpy( strVrfDriverNew, strKernelModuleName ); if( strVrfDriver[ 0 ] != (TCHAR)0 ) { if( strVrfDriver[ 0 ] != _T( ' ' ) && strVrfDriver[ 0 ] != _T( '\t' ) ) { // // add a space first // _tcscat( strVrfDriverNew, _T( " " ) ); } // // add the old verified drivers at the end // _tcscat( strVrfDriverNew, strVrfDriver ); } // // write the value // if (WriteMmString (MmKey, RegVerifyDriversValueName, strVrfDriverNew) == FALSE) { dwExitCode = EXIT_CODE_ERROR; } else { dwExitCode = EXIT_CODE_REBOOT; } } } } RegCloseKey (MmKey); } if( EXIT_CODE_REBOOT == dwExitCode ) { DisplayMessage( IDS_MUST_REBOOT ); } else { if( EXIT_CODE_NOTHING_CHANGED == dwExitCode ) { DisplayMessage( IDS_NOTHING_CHANGED ); } } exit( dwExitCode ); } /////////////////////////////////////////////////////////////////// void RemoveModuleNameFromRegistry( TCHAR *strKernelModuleName ) { HKEY MmKey = NULL; DWORD dwExitCode; LONG lOpenResult; int nKernelModuleNameLen; int nStringLen; int nLeftToCopy; TCHAR *pstrCrtNameMatch, *pstrSubstring; TCHAR strVrfDriver [VRF_MAX_DRIVER_STRING_LENGTH]; TCHAR strVrfDriverNew [VRF_MAX_DRIVER_STRING_LENGTH]; dwExitCode = EXIT_CODE_NOTHING_CHANGED; // // Open the Mm key // lOpenResult = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, RegMemoryManagementKeyName, 0, KEY_QUERY_VALUE | KEY_WRITE, &MmKey); if (lOpenResult != ERROR_SUCCESS) { dwExitCode = EXIT_CODE_ERROR; if( lOpenResult == ERROR_ACCESS_DENIED ) { DisplayMessage( IDS_ACCESS_IS_DENIED ); } else { DisplayMessage( IDS_REGOPENKEYEX_FAILED, RegMemoryManagementKeyName, (DWORD)lOpenResult); } } else { if( ReadMmString (MmKey, RegVerifyDriversValueName, strVrfDriver) == FALSE) { dwExitCode = EXIT_CODE_ERROR; } else { pstrCrtNameMatch = strVrfDriver; do { pstrSubstring = _tcsstr( pstrCrtNameMatch, strKernelModuleName ); if( pstrSubstring != NULL ) { // // the name seems to be there // nKernelModuleNameLen = _tcsclen( strKernelModuleName ); nStringLen = _tcsclen( pstrSubstring ); if( nStringLen > nKernelModuleNameLen && pstrSubstring[ nKernelModuleNameLen ] != _TEXT(' ') && pstrSubstring[ nKernelModuleNameLen ] != _TEXT('\t') ) { // // this is not our name, continue searching // pstrCrtNameMatch += nKernelModuleNameLen; } else { if( pstrSubstring != &strVrfDriver[ 0 ] && (* (pstrSubstring - 1) ) != _TEXT(' ') && (* (pstrSubstring - 1) ) != _TEXT('\t') ) { // // this is not our name, continue searching // pstrCrtNameMatch += min( nKernelModuleNameLen, nStringLen ); } else { // // kernel's module name is in the registry // strVrfDriverNew[0] = (TCHAR)0; _tcsncat( strVrfDriverNew, strVrfDriver, (size_t)(pstrSubstring - &strVrfDriver[0]) ); nLeftToCopy = nStringLen - nKernelModuleNameLen; pstrSubstring += nKernelModuleNameLen; while( nLeftToCopy > 0 ) { if( *pstrSubstring != _TEXT( ' ' ) && *pstrSubstring != _TEXT( '\t' ) ) { // // append what starts from here // _tcscat( strVrfDriverNew, pstrSubstring ); break; } else { // // skip spaces // pstrSubstring ++; nLeftToCopy --; } } // // write the new value to the registry // if (WriteMmString (MmKey, RegVerifyDriversValueName, strVrfDriverNew) == FALSE) { dwExitCode = EXIT_CODE_ERROR; } else { dwExitCode = EXIT_CODE_REBOOT; } break; } } } } while( pstrSubstring != NULL ); } RegCloseKey (MmKey); } if( EXIT_CODE_REBOOT == dwExitCode ) { DisplayMessage( IDS_MUST_REBOOT ); } else { if( EXIT_CODE_NOTHING_CHANGED == dwExitCode ) { DisplayMessage( IDS_NOTHING_CHANGED ); } } exit( dwExitCode ); } ////////////////////////////////////////////////// void DumpStatusFromRegistry( LPCTSTR strKernelModuleName ) { HKEY MmKey = NULL; DWORD dwExitCode; LONG lOpenResult; DWORD dwCrtFlags; DWORD dwIoLevel; int nKernelModuleNameLen; int nStringLen; BOOL bKernelVerified; BOOL bIsModuleNameRegistry; TCHAR *pstrCrtNameMatch, *pstrSubstring, *pCrtChar; TCHAR strVrfDriver [VRF_MAX_DRIVER_STRING_LENGTH]; dwExitCode = EXIT_CODE_NOTHING_CHANGED; bKernelVerified = FALSE; // // Open the Mm key // lOpenResult = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, RegMemoryManagementKeyName, 0, KEY_QUERY_VALUE, &MmKey); if (lOpenResult != ERROR_SUCCESS) { dwExitCode = EXIT_CODE_ERROR; if( lOpenResult == ERROR_ACCESS_DENIED ) { DisplayMessage( IDS_ACCESS_IS_DENIED ); } else { DisplayMessage( IDS_REGOPENKEYEX_FAILED, RegMemoryManagementKeyName, (DWORD)lOpenResult); } } else { if( ReadMmString (MmKey, RegVerifyDriversValueName, strVrfDriver) == FALSE) { dwExitCode = EXIT_CODE_ERROR; } else { bIsModuleNameRegistry = IsModuleNameAlreadyInRegistry( strKernelModuleName, strVrfDriver ); if( bIsModuleNameRegistry == TRUE ) { // // we have 'ntoskrnl.exe' in the registry // // // read the verification flags // if( ReadRegistryValue( MmKey, RegVerifyDriverLevelValueName, &dwCrtFlags ) == FALSE ) { dwExitCode = EXIT_CODE_ERROR; } else { bKernelVerified = TRUE; if( dwCrtFlags != -1 ) { if( ( dwCrtFlags & DRIVER_VERIFIER_IO_CHECKING ) != 0 ) { // // the IO verification is enabled, check the IO verification level ( 1 or 2 ) // if( GetIoVerificationLevel( &dwIoLevel ) == FALSE ) { dwExitCode = EXIT_CODE_ERROR; } else { if( dwIoLevel != 2 ) { // // only levels 1 & 2 are supported // dwIoLevel = 1; } DisplayMessage( IDS_VERIFIER_ENABLED_WITH_IO_FORMAT, strKernelModuleName, dwCrtFlags, dwIoLevel ); } } else { // // the IO verification is not enabled // DisplayMessage( IDS_VERIFIER_ENABLED_FORMAT, strKernelModuleName, dwCrtFlags ); } } else { DisplayMessage( IDS_VERIFIER_ENABLED_NOFLAGS_FORMAT, strKernelModuleName ); } } } if( EXIT_CODE_NOTHING_CHANGED == dwExitCode && ! bKernelVerified ) { DisplayMessage( IDS_VERIFIER_NOT_ENABLED_FORMAT, strKernelModuleName ); } } RegCloseKey (MmKey); } exit( dwExitCode ); } ////////////////////////////////////////////////////////////////////// //////////////////////////////// Local registry manipulation functions ////////////////////////////////////////////////////////////////////// BOOL ReadRegistryValue ( HKEY HKey, LPCTSTR Name, DWORD * Value) { LONG Result; DWORD Reserved; DWORD Type; DWORD Size; // // default value // *Value = -1; Size = sizeof *Value; Result = RegQueryValueEx ( HKey, Name, 0, &Type, (LPBYTE)(Value), &Size); // // Deal with a value that is not defined. // if (Result == ERROR_FILE_NOT_FOUND) { *Value = -1; return TRUE; } if (Result != ERROR_SUCCESS) { DisplayMessage ( IDS_REGQUERYVALUEEX_FAILED, Name, (DWORD)Result); return FALSE; } if (Type != REG_DWORD) { DisplayMessage ( IDS_REGQUERYVALUEEX_UNEXP_TYPE, Name); return FALSE; } if (Size != sizeof *Value) { DisplayMessage ( IDS_REGQUERYVALUEEX_UNEXP_SIZE, Name); return FALSE; } return TRUE; } BOOL WriteRegistryValue ( HKEY HKey, LPCTSTR Name, DWORD Value) { LONG Result; Result = RegSetValueEx ( HKey, Name, 0, REG_DWORD, (LPBYTE)(&Value), sizeof Value); if (Result != ERROR_SUCCESS) { DisplayMessage ( IDS_REGSETVALUEEX_FAILED, Name, (DWORD)Result); return FALSE; } return TRUE; } BOOL ReadMmString ( HKEY MmKey, LPCTSTR Name, LPTSTR Value) { LONG Result; DWORD Reserved; DWORD Type; DWORD Size; // // default value // *Value = 0; Size = VRF_MAX_DRIVER_STRING_LENGTH; Result = RegQueryValueEx ( MmKey, Name, 0, &Type, (LPBYTE)(Value), &Size); // // Deal with a value that is not defined. // if (Result == ERROR_FILE_NOT_FOUND) { *Value = 0; return TRUE; } if (Result != ERROR_SUCCESS) { DisplayMessage ( IDS_REGQUERYVALUEEX_FAILED, Name, (DWORD)Result); return FALSE; } if (Type != REG_SZ) { DisplayMessage ( IDS_REGQUERYVALUEEX_UNEXP_TYPE, Name); return FALSE; } return TRUE; } BOOL WriteMmString ( HKEY MmKey, LPCTSTR Name, LPTSTR Value) { LONG Result; DWORD Reserved; DWORD Type; DWORD Size; Result = RegSetValueEx ( MmKey, Name, 0, REG_SZ, (LPBYTE)(Value), (_tcslen (Value) + 1) * sizeof (TCHAR)); if (Result != ERROR_SUCCESS) { DisplayMessage ( IDS_REGSETVALUEEX_FAILED, Name, (DWORD)Result); return FALSE; } return TRUE; } ////////////////////////////////////////////////// BOOL IsModuleNameAlreadyInRegistry( LPCTSTR strKernelModuleName, LPCTSTR strWholeString ) { BOOL bAlreadyInRegistry; int nKernelNameLength; LPCTSTR strString; LPCTSTR strSubstring; TCHAR cBefore; nKernelNameLength = _tcslen( strKernelModuleName ); // // let's assume 'ntoskrnl.exe" is not already in the registry // bAlreadyInRegistry = FALSE; // // parse the string that's already in the registry // strString = strWholeString; while( *strString != (TCHAR)0 ) { strSubstring = _tcsstr( strString, strKernelModuleName ); if( strSubstring != NULL ) { // // the string from the registry includes "ntoskrnl.exe" // // // let's assume it's nothing like "xyzntoskrnl.exe", "ntoskrnl.exexyz", etc. // bAlreadyInRegistry = TRUE; // // look for a character before the current substring // if( strSubstring > strWholeString ) { // // have at least one character before "ntoskrnl.exe" - look if it is blanc // cBefore = *( strSubstring - 1 ); if( cBefore != _T( ' ' ) && cBefore != _T( '\t' ) ) { // // the character before "ntoskrnl.exe" is non-blanc -> not the name we are searching for // bAlreadyInRegistry = FALSE; } } // // look for a character after the current substring // if( bAlreadyInRegistry == TRUE && strSubstring[ nKernelNameLength ] != (TCHAR)0 && strSubstring[ nKernelNameLength ] != _T( ' ' ) && strSubstring[ nKernelNameLength ] != _T( '\t' ) ) { // // have a non-blanc character after this substring -> not the name we are searching for // bAlreadyInRegistry = FALSE; } if( bAlreadyInRegistry == FALSE ) { // // this is not a real occurence of the name we are serching for, go further on // strString = strSubstring + 1; } if( bAlreadyInRegistry == TRUE ) { // // found it // break; } } else { // // the name is not there // break; } } return bAlreadyInRegistry; } ////////////////////////////////////////////////// BOOL GetIoVerificationLevel( DWORD *pdwIoLevel ) { LONG lResult; HKEY IoKey = NULL; DWORD dwCrtIoVerifLevel; BOOL bFatalError; bFatalError = FALSE; // // default value // *pdwIoLevel = 1; // // open the "I/O" key // lResult = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, RegIOVerifyKeyName, 0, KEY_QUERY_VALUE, &IoKey); if (lResult != ERROR_SUCCESS) { // // cannot open the IO key // if( lResult != ERROR_FILE_NOT_FOUND ) { // // the IO key is there, but we cannot open it // if( lResult == ERROR_ACCESS_DENIED ) { DisplayMessage( IDS_ACCESS_IS_DENIED ); } else { DisplayMessage( IDS_REGOPENKEYEX_FAILED, RegIOVerifyKeyName, (DWORD)lResult); } bFatalError = TRUE; } // else - the IO key doesn't exist - use default value } else { // // read "I/O System\IoVerifierLevel" value // if( ReadRegistryValue( IoKey, RegIOVerifyLevelValueName, &dwCrtIoVerifLevel ) ) { if( LEVEL2_IO_VERIFIER_ENABLED_VALUE == dwCrtIoVerifLevel ) { // // we are at level 2 IO verification // *pdwIoLevel = 2; } } RegCloseKey (IoKey); } return ( ! bFatalError ); } ////////////////////////////////////////////////// BOOL SwitchIoVerificationLevel( DWORD dwNewIoLevel ) { BOOL bFatalError; LONG lResult; HKEY IoKey = NULL; HKEY SmKey = NULL; bFatalError = FALSE; // // Open the "I/O System" key // lResult = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, RegIOVerifyKeyName, 0, KEY_QUERY_VALUE | KEY_WRITE, &IoKey); if( lResult != ERROR_SUCCESS ) { if( dwNewIoLevel == 2 ) { // // cannot open the IO key - maybe a fatal error - anyway, we will try to create it // bFatalError = TRUE; if( lResult == ERROR_ACCESS_DENIED ) { // // access is denied - fatal error // DisplayMessage( IDS_ACCESS_IS_DENIED ); } else { if( lResult == ERROR_FILE_NOT_FOUND ) { // // the "I/O System" key doesn't exist, try to create it // // // open the "Session Manager" key // lResult = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, RegSessionManagerKeyName, 0, KEY_QUERY_VALUE | KEY_WRITE, &SmKey); if( lResult != ERROR_SUCCESS ) { // // cannot open the "Session Manager" key - fatal error // DisplayMessage( IDS_REGOPENKEYEX_FAILED, RegSessionManagerKeyName, (DWORD)lResult); } else { // // create the "I/O System" key // lResult = RegCreateKeyEx( SmKey, RegIOVerifySubKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_QUERY_VALUE, NULL, &IoKey, NULL ); if( lResult != ERROR_SUCCESS ) { // // cannot create key - fatal error // DisplayMessage( IDS_REGCREATEKEYEX_FAILED, RegIOVerifySubKeyName, (DWORD)lResult); } else { // // key created - reset the error code // bFatalError = FALSE; } // // close the "Session Manager" key // lResult = RegCloseKey( SmKey ); } } else { // // other error opening the "I/O System" key // DisplayMessage( IDS_REGOPENKEYEX_FAILED, RegIOVerifyKeyName, (DWORD)lResult); } } } else bFatalError = TRUE; //else // we don't actually need the key in this case, we just want to wipe out // the IO verification registry value // } if( bFatalError == FALSE ) { if( dwNewIoLevel == 2 ) { // // if we reached this point, we should have the IO key opened // // // enable level 2 // if( WriteRegistryValue( IoKey, RegIOVerifyLevelValueName, LEVEL2_IO_VERIFIER_ENABLED_VALUE ) == FALSE ) { // // cannot recover from this // bFatalError = TRUE; } } else { // // disable level 2 // lResult = RegDeleteValue( IoKey, RegIOVerifyLevelValueName ); if( lResult != ERROR_SUCCESS && lResult != ERROR_FILE_NOT_FOUND ) { bFatalError = TRUE; DisplayMessage( IDS_REGDELETEVALUE_FAILED, RegIOVerifyLevelValueName, (DWORD)lResult); } RegCloseKey (IoKey); } } return ( ! bFatalError ); }