|
|
#include "precomp.h"
#include "ntexapi.h"
using namespace ShimLib;
extern BOOL g_bClearSessionLogBeforeRun; extern BOOL g_bUseAVDebugger;
#define AVDB_ID_32 _T("{448850f4-a5ea-4dd1-bf1b-d5fa285dc64b}")
#define AVDB_ID_64 _T("{64646464-a5ea-4dd1-bf1b-d5fa285dc64b}")
/////////////////////////////////////////////////////////////////////////////
//
// Registry keys/values names
//
const TCHAR g_szImageOptionsKeyName[] = _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"); const TCHAR g_szGlobalFlagValueName[] = _T("GlobalFlag"); const TCHAR g_szVerifierFlagsValueName[] = _T("VerifierFlags"); const TCHAR g_szVerifierPathValueName[] = _T("VerifierPath"); const TCHAR g_szDebuggerKeyName[] = _T("Debugger");
CAVAppInfoArray g_aAppInfo;
CTestInfoArray g_aTestInfo;
BOOL SetAppVerifierFlagsForKey( HKEY hKey, DWORD dwDesiredFlags ) { BOOL bRet = FALSE; DWORD dwValueType = 0; DWORD dwDataSize = 0; TCHAR szOldGlobalFlagValue[32]; BOOL bSuccesfullyConverted; BOOL bDesireEnabled = (dwDesiredFlags != 0); LONG lResult; DWORD dwFlags = 0; DWORD dwEnableFlag;
//
// Read the GlobalFlag value
//
dwDataSize = sizeof(szOldGlobalFlagValue);
lResult = RegQueryValueEx(hKey, g_szGlobalFlagValueName, NULL, &dwValueType, (LPBYTE) &szOldGlobalFlagValue[0], &dwDataSize);
if (ERROR_SUCCESS == lResult) { bSuccesfullyConverted = AVRtlCharToInteger(szOldGlobalFlagValue, 0, &dwFlags); if (!bSuccesfullyConverted) { dwFlags = 0; } }
//
// handle Win2K differently.
//
if (g_bWin2KMode) {
//
// we can only do PageHeap on Win2K, so just check that flag
//
bDesireEnabled = ((dwDesiredFlags & RTL_VRF_FLG_FULL_PAGE_HEAP) != 0); dwEnableFlag = FLG_HEAP_PAGE_ALLOCS; } else { dwEnableFlag = FLG_APPLICATION_VERIFIER; }
BOOL bEnabled = (dwFlags & dwEnableFlag) != 0;
//
// write the new global flags, if necessary
//
if (bDesireEnabled != bEnabled) { if (bDesireEnabled) { dwFlags |= dwEnableFlag; } else { dwFlags &= ~dwEnableFlag; }
BOOL bSuccess = AVWriteStringHexValueToRegistry(hKey, g_szGlobalFlagValueName, dwFlags); if (!bSuccess) { goto out; } }
//
// we only write the special app verifier settings if we're not in Win2K mode
//
if (!g_bWin2KMode) { //
// now write the app verifier settings
//
if (bDesireEnabled) { lResult = RegSetValueEx(hKey, g_szVerifierFlagsValueName, 0, REG_DWORD, (PBYTE) &dwDesiredFlags, sizeof(dwDesiredFlags)); if (lResult != ERROR_SUCCESS) { goto out; } } else { lResult = RegDeleteValue(hKey, g_szVerifierFlagsValueName); if (lResult != ERROR_SUCCESS) { goto out; } }
}
bRet = TRUE;
out: return bRet; }
DWORD GetAppVerifierFlagsFromKey( HKEY hKey ) { DWORD dwRet = 0; DWORD dwValueType = 0; DWORD dwDataSize = 0; TCHAR szOldGlobalFlagValue[32]; BOOL bSuccesfullyConverted; LONG lResult; DWORD dwFlags = 0;
//
// Read the GlobalFlag value
//
dwDataSize = sizeof(szOldGlobalFlagValue);
lResult = RegQueryValueEx(hKey, g_szGlobalFlagValueName, NULL, &dwValueType, (LPBYTE)&szOldGlobalFlagValue[0], &dwDataSize);
if (ERROR_SUCCESS == lResult) { bSuccesfullyConverted = AVRtlCharToInteger(szOldGlobalFlagValue, 0, &dwFlags);
if (g_bWin2KMode) { //
// special check for Win2K
//
if ((FALSE != bSuccesfullyConverted) && ((dwFlags & FLG_HEAP_PAGE_ALLOCS) != 0)) {
dwRet = RTL_VRF_FLG_FULL_PAGE_HEAP; } } else { if ((FALSE != bSuccesfullyConverted) && ((dwFlags & FLG_APPLICATION_VERIFIER) != 0)) { //
// App verifier is enabled for this app - read the verifier flags
//
dwDataSize = sizeof(dwRet);
lResult = RegQueryValueEx(hKey, g_szVerifierFlagsValueName, NULL, &dwValueType, (LPBYTE)&dwRet, &dwDataSize);
if (ERROR_SUCCESS != lResult || REG_DWORD != dwValueType) { //
// couldn't get them, for one reason or another
//
dwRet = 0; } } } }
return dwRet; }
void SetAppVerifierFullPathForKey( HKEY hKey, wstring& strPath ) { if (strPath.size() == 0) { RegDeleteValue(hKey, g_szVerifierPathValueName); } else { RegSetValueEx(hKey, g_szVerifierPathValueName, 0, REG_SZ, (PBYTE) strPath.c_str(), (strPath.size() + 1) * sizeof(WCHAR)); } }
void SetDebuggerOptionsForKey( HKEY hKey, CAVAppInfo *pApp ) { WCHAR szName[MAX_PATH];
StringCchCopyW(szName, ARRAY_LENGTH(szName), L"\"");
GetModuleFileName(NULL, szName + 1, MAX_PATH - 10);
StringCchCatW(szName, ARRAY_LENGTH(szName), L"\" /debug");
if (pApp && pApp->bBreakOnLog && pApp->wstrDebugger.size()) {
RegSetValueEx(hKey, g_szDebuggerKeyName, 0, REG_SZ, (PBYTE)pApp->wstrDebugger.c_str(), (pApp->wstrDebugger.size() + 1) * sizeof(WCHAR));
} else {
WCHAR szDbgName[MAX_PATH]; DWORD cbSize;
cbSize = sizeof(szDbgName);
szDbgName[0] = 0;
RegQueryValueEx(hKey, g_szDebuggerKeyName, 0, NULL, (PBYTE)szDbgName, &cbSize); //
// if the current debugger matches either our own debugger or the user selected one,
// delete it, but leave alone any other debugger
//
if ((_wcsicmp(szName, szDbgName) == 0) || (pApp && (_wcsicmp(pApp->wstrDebugger.c_str(), szDbgName) == 0))) { RegDeleteValue(hKey, g_szDebuggerKeyName); } } }
void GetAppVerifierFullPathFromKey( HKEY hKey, wstring& strPath ) { DWORD dwValueType = 0; DWORD dwDataSize = 0; TCHAR szVerifierPath[MAX_PATH]; LONG lResult;
//
// Read the GlobalFlag value
//
dwDataSize = sizeof(szVerifierPath);
szVerifierPath[0] = 0;
lResult = RegQueryValueEx(hKey, g_szVerifierPathValueName, NULL, &dwValueType, (LPBYTE)szVerifierPath, &dwDataSize);
if (ERROR_SUCCESS == lResult && dwValueType == REG_SZ) { strPath = szVerifierPath; } }
void GetCurrentAppSettingsFromRegistry( void ) { HKEY hImageOptionsKey; HKEY hSubKey; DWORD dwSubkeyIndex; DWORD dwDataSize; DWORD dwValueType; DWORD dwFlags; LONG lResult; FILETIME LastWriteTime; TCHAR szOldGlobalFlagValue[32]; TCHAR szKeyNameBuffer[256];
//
// Open the Image File Execution Options regkey
//
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szImageOptionsKeyName, 0, KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS, &hImageOptionsKey);
if (lResult != ERROR_SUCCESS) { if (lResult == ERROR_ACCESS_DENIED) { AVErrorResourceFormat(IDS_ACCESS_IS_DENIED); } else { AVErrorResourceFormat(IDS_REGOPENKEYEX_FAILED, g_szImageOptionsKeyName, (DWORD)lResult); }
return; }
//
// Enumerate all the existing subkeys for app execution options
//
for (dwSubkeyIndex = 0; TRUE; dwSubkeyIndex += 1) { wstring wstrPath;
dwDataSize = ARRAY_LENGTH(szKeyNameBuffer);
lResult = RegEnumKeyEx(hImageOptionsKey, dwSubkeyIndex, szKeyNameBuffer, &dwDataSize, NULL, NULL, NULL, &LastWriteTime);
if (lResult != ERROR_SUCCESS) { if (lResult == ERROR_NO_MORE_ITEMS) { //
// We finished looking at all the existing subkeys
//
break; } else { if (lResult == ERROR_ACCESS_DENIED) { AVErrorResourceFormat(IDS_ACCESS_IS_DENIED); } else { AVErrorResourceFormat(IDS_REGENUMKEYEX_FAILED, g_szImageOptionsKeyName, (DWORD)lResult); }
goto CleanUpAndDone; } }
//
// Open the subkey
//
lResult = RegOpenKeyEx(hImageOptionsKey, szKeyNameBuffer, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hSubKey);
if (lResult != ERROR_SUCCESS) { if (lResult == ERROR_ACCESS_DENIED) { AVErrorResourceFormat(IDS_ACCESS_IS_DENIED); } else { AVErrorResourceFormat(IDS_REGOPENKEYEX_FAILED, szKeyNameBuffer, (DWORD)lResult); }
goto CleanUpAndDone; }
dwFlags = GetAppVerifierFlagsFromKey(hSubKey); GetAppVerifierFullPathFromKey(hSubKey, wstrPath);
if (dwFlags || wstrPath.size()) { //
// Update the info in the array, or add it if necessary
//
CAVAppInfo* pApp; BOOL bFound = FALSE;
for (pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) { if (_wcsicmp(pApp->wstrExeName.c_str(), szKeyNameBuffer) == 0) { bFound = TRUE; pApp->dwRegFlags = dwFlags; pApp->wstrExePath = wstrPath; break; } }
if (!bFound) { CAVAppInfo AppInfo; AppInfo.wstrExeName = szKeyNameBuffer; AppInfo.dwRegFlags = dwFlags; AppInfo.wstrExePath = wstrPath;
g_aAppInfo.push_back(AppInfo); } }
VERIFY(ERROR_SUCCESS == RegCloseKey(hSubKey)); }
CleanUpAndDone:
VERIFY(ERROR_SUCCESS == RegCloseKey(hImageOptionsKey)); }
void GetCurrentAppSettingsFromSDB( void ) { CAVAppInfo AppInfo; TCHAR szPath[MAX_PATH]; PDB pdb = NULL; TAGID tiDB = TAGID_NULL; TAGID tiExe = TAGID_NULL;
//
// go find the SDB
//
szPath[0] = 0; GetSystemWindowsDirectory(szPath, MAX_PATH);
#if defined(_WIN64)
StringCchCatW(szPath, ARRAY_LENGTH(szPath), _T("\\AppPatch\\Custom\\IA64\\") AVDB_ID_64 _T(".sdb")); #else
StringCchCatW(szPath, ARRAY_LENGTH(szPath), _T("\\AppPatch\\Custom\\") AVDB_ID_32 _T(".sdb")); #endif // _WIN64
pdb = SdbOpenDatabase(szPath, DOS_PATH); if (!pdb) { //
// no current DB
//
goto out; }
//
// enumerate all the apps and the shims applied to them
//
tiDB = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE); if (!tiDB) { goto out; }
tiExe = SdbFindFirstTag(pdb, tiDB, TAG_EXE);
while (tiExe) { WCHAR* wszName = NULL; TAGID tiShim = TAGID_NULL; TAGID tiName = SdbFindFirstTag(pdb, tiExe, TAG_NAME);
if (!tiName) { goto nextExe; } wszName = SdbGetStringTagPtr(pdb, tiName); if (!wszName) { goto nextExe; }
CAVAppInfoArray::iterator it; BOOL bFound = FALSE;
for (it = g_aAppInfo.begin(); it != g_aAppInfo.end(); it++) { if (_wcsicmp(it->wstrExeName.c_str(), wszName) == 0) { bFound = TRUE; break; } }
if (!bFound) { AppInfo.wstrExeName = wszName; g_aAppInfo.push_back(AppInfo); it = g_aAppInfo.end() - 1; }
tiShim = SdbFindFirstTag(pdb, tiExe, TAG_SHIM_REF);
while (tiShim) { WCHAR* wszShimName = NULL; TAGID tiShimName = SdbFindFirstTag(pdb, tiShim, TAG_NAME);
if (!tiShimName) { goto nextShim; }
wszShimName = SdbGetStringTagPtr(pdb, tiShimName);
it->awstrShims.push_back(wstring(wszShimName));
nextShim: tiShim = SdbFindNextTag(pdb, tiExe, tiShim); }
nextExe:
tiExe = SdbFindNextTag(pdb, tiDB, tiExe); }
out:
if (pdb) { SdbCloseDatabase(pdb); pdb = NULL; }
return; }
void InitDefaultAppSettings( void ) {
BOOL bFound = FALSE;
//
// see if it's already in the list
//
for (CAVAppInfo *pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) { if (pApp->wstrExeName == AVRF_DEFAULT_SETTINGS_NAME_W) { if (pApp != g_aAppInfo.begin()) { //
// it's not at the beginning, so move it to the beginning
//
CAVAppInfo AppTemp;
AppTemp = *pApp; g_aAppInfo.erase(pApp);
g_aAppInfo.insert(g_aAppInfo.begin(), AppTemp); }
bFound = TRUE; break; } }
//
// it's not, so add it to the beginning
//
if (!bFound) { CAVAppInfo AppInfo; AppInfo.wstrExeName = AVRF_DEFAULT_SETTINGS_NAME_W;
CTestInfo *pTest; for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) { if (pTest->bDefault) { AppInfo.AddTest(*pTest); } }
g_aAppInfo.insert(g_aAppInfo.begin(), AppInfo); } }
void GetCurrentAppSettings( void ) { g_aAppInfo.clear();
//
// make sure default is in the first position
//
CAVAppInfo AppInfo; AppInfo.wstrExeName = AVRF_DEFAULT_SETTINGS_NAME_W;
g_aAppInfo.push_back(AppInfo);
GetCurrentAppSettingsFromRegistry(); GetCurrentAppSettingsFromSDB();
InitDefaultAppSettings(); }
void SetCurrentRegistrySettings( void ) { HKEY hImageOptionsKey; HKEY hSubKey = NULL; DWORD dwSubkeyIndex; DWORD dwDataSize; DWORD dwValueType; DWORD dwFlags; LONG lResult; FILETIME LastWriteTime; TCHAR szKeyNameBuffer[ 256 ]; CAVAppInfo* pApp; wstring wstrEmpty = L"";
//
// Open the Image File Execution Options regkey
//
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szImageOptionsKeyName, 0, KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS, &hImageOptionsKey);
if (lResult != ERROR_SUCCESS) { if (lResult == ERROR_ACCESS_DENIED) { AVErrorResourceFormat(IDS_ACCESS_IS_DENIED); } else { AVErrorResourceFormat(IDS_REGOPENKEYEX_FAILED, g_szImageOptionsKeyName, (DWORD)lResult); }
return; }
//
// Enumerate all the existing subkeys for app execution options
//
for (dwSubkeyIndex = 0; TRUE; dwSubkeyIndex += 1) { dwDataSize = ARRAY_LENGTH(szKeyNameBuffer);
lResult = RegEnumKeyEx(hImageOptionsKey, dwSubkeyIndex, szKeyNameBuffer, &dwDataSize, NULL, NULL, NULL, &LastWriteTime);
if (lResult != ERROR_SUCCESS) { if (lResult == ERROR_NO_MORE_ITEMS) { //
// We finished looking at all the existing subkeys
//
break; } else { if (lResult == ERROR_ACCESS_DENIED) { AVErrorResourceFormat(IDS_ACCESS_IS_DENIED); } else { AVErrorResourceFormat(IDS_REGENUMKEYEX_FAILED, g_szImageOptionsKeyName, (DWORD)lResult); }
goto CleanUpAndDone; } }
//
// Open the subkey
//
lResult = RegOpenKeyEx(hImageOptionsKey, szKeyNameBuffer, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hSubKey);
if (lResult != ERROR_SUCCESS) { if (lResult == ERROR_ACCESS_DENIED) { AVErrorResourceFormat(IDS_ACCESS_IS_DENIED); } else { AVErrorResourceFormat(IDS_REGOPENKEYEX_FAILED, szKeyNameBuffer, (DWORD)lResult); }
goto CleanUpAndDone; }
dwFlags = GetAppVerifierFlagsFromKey(hSubKey);
DWORD dwDesiredFlags = 0; BOOL bFound = FALSE;
for (pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) { if (_wcsicmp(pApp->wstrExeName.c_str(), szKeyNameBuffer) == 0) { dwDesiredFlags = pApp->dwRegFlags; bFound = TRUE;
//
// we found it, so update the full path
//
SetAppVerifierFullPathForKey(hSubKey, pApp->wstrExePath);
//
// and add the debugger as well
//
SetDebuggerOptionsForKey(hSubKey, pApp);
break; } }
if (!bFound) { //
// if this one isn't in our list, make sure it doesn't
// have a full path or our debugger set
//
SetAppVerifierFullPathForKey(hSubKey, wstrEmpty); SetDebuggerOptionsForKey(hSubKey, NULL); }
if (dwFlags != dwDesiredFlags) { SetAppVerifierFlagsForKey(hSubKey, dwDesiredFlags); }
VERIFY(ERROR_SUCCESS == RegCloseKey(hSubKey)); hSubKey = NULL; }
//
// and now go through the list the other way, looking for new ones to add
//
for (pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) { lResult = RegOpenKeyEx(hImageOptionsKey, pApp->wstrExeName.c_str(), 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hSubKey);
//
// if it exists, we've already dealt with it above
//
if (lResult != ERROR_SUCCESS) { //
// it doesn't exist. Try to create it.
//
lResult = RegCreateKeyEx(hImageOptionsKey, pApp->wstrExeName.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, &hSubKey, NULL);
if (lResult == ERROR_SUCCESS) { SetAppVerifierFlagsForKey(hSubKey, pApp->dwRegFlags); SetAppVerifierFullPathForKey(hSubKey, pApp->wstrExePath);
SetDebuggerOptionsForKey(hSubKey, pApp); } }
if (hSubKey) { RegCloseKey(hSubKey); hSubKey = NULL; } }
CleanUpAndDone:
VERIFY(ERROR_SUCCESS == RegCloseKey(hImageOptionsKey)); }
void SetCurrentAppSettings( void ) { SetCurrentRegistrySettings(); AppCompatWriteShimSettings(g_aAppInfo, TRUE); #if defined(_WIN64)
AppCompatWriteShimSettings(g_aAppInfo, FALSE); #endif
}
KERNEL_TEST_INFO g_KernelTests[] = { { IDS_PAGE_HEAP, IDS_PAGE_HEAP_DESC, RTL_VRF_FLG_FULL_PAGE_HEAP, TRUE, L"PageHeap", TRUE }, { IDS_VERIFY_LOCKS_CHECKS, IDS_VERIFY_LOCKS_CHECKS_DESC, RTL_VRF_FLG_LOCK_CHECKS, TRUE, L"Locks", FALSE }, { IDS_VERIFY_HANDLE_CHECKS, IDS_VERIFY_HANDLE_CHECKS_DESC, RTL_VRF_FLG_HANDLE_CHECKS, TRUE, L"Handles", FALSE }, { IDS_VERIFY_STACK_CHECKS, IDS_VERIFY_STACK_CHECKS_DESC, RTL_VRF_FLG_STACK_CHECKS, FALSE, L"Stacks", FALSE }, { IDS_VERIFY_RPC_CHECKS, IDS_VERIFY_RPC_CHECKS_DESC, RTL_VRF_FLG_RPC_CHECKS, FALSE, L"RPC Checks", FALSE } };
BOOL GetKernelTestInfo( CTestInfoArray& TestArray ) { CTestInfo ti; TCHAR szTemp[256]; int i;
ti.eTestType = TEST_KERNEL;
for (i = 0; i < ARRAY_LENGTH(g_KernelTests); ++i) { ti.strTestName = g_KernelTests[i].m_szCommandLine;
if (AVLoadString(g_KernelTests[i].m_uFriendlyNameStringId, szTemp, ARRAY_LENGTH(szTemp))) { ti.strTestFriendlyName = szTemp; } else { ti.strTestFriendlyName = ti.strTestName; }
if (AVLoadString(g_KernelTests[i].m_uDescriptionStringId, szTemp, ARRAY_LENGTH(szTemp))) { ti.strTestDescription = szTemp; } else { ti.strTestDescription = L""; }
ti.dwKernelFlag = g_KernelTests[i].m_dwBit; ti.bDefault = g_KernelTests[i].m_bDefault; ti.bWin2KCompatible = g_KernelTests[i].m_bWin2KCompatible;
TestArray.push_back(ti); }
return TRUE; }
void ParseIncludeList( WCHAR* szList, CIncludeArray& aArray ) { if (!szList) { return; }
BOOL bInclude = TRUE;
WCHAR *szBegin = szList; WCHAR *szEnd = NULL; DWORD dwLen = 0;
while (1) {
//
// skip space
//
while (*szBegin == L' ') { szBegin++; }
//
// check for end
//
if (*szBegin == 0) { break; }
//
// check for E: or I:
//
if (_wcsnicmp(szBegin, L"E:", 2) == 0) { bInclude = FALSE; szBegin += 2; continue; } if (_wcsnicmp(szBegin, L"I:", 2) == 0) { bInclude = TRUE; szBegin += 2; continue; }
szEnd = wcschr(szBegin, L' '); if (szEnd) { dwLen = szEnd - szBegin; } else { dwLen = wcslen(szBegin); }
if (dwLen) { WCHAR szTemp[MAX_PATH]; CIncludeInfo Include;
memcpy(szTemp, szBegin, dwLen * sizeof(WCHAR)); szTemp[dwLen] = 0;
Include.bInclude = bInclude; Include.strModule = szTemp;
aArray.push_back(Include);
szBegin += dwLen; } else {
//
// just in case
//
break; }
} }
BOOL GetShimInfo( CTestInfoArray& TestInfoArray ) { HKEY hKey = NULL; BOOL bRet = FALSE; int nWhich = 0; TCHAR szAppPatch[MAX_PATH]; TCHAR szShimFullPath[MAX_PATH]; HMODULE hMod = NULL; _pfnGetVerifierMagic pGetVerifierMagic = NULL; _pfnQueryShimInfo pQueryShimInfo = NULL; LPWSTR *pShimNames = NULL; DWORD dwShims = 0;
WIN32_FIND_DATA FindData; HANDLE hFind = INVALID_HANDLE_VALUE; TCHAR szDllSearch[MAX_PATH];
szAppPatch[0] = 0; GetSystemWindowsDirectory(szAppPatch, MAX_PATH);
#if defined(_WIN64)
StringCchCatW(szAppPatch, ARRAY_LENGTH(szAppPatch), _T("\\AppPatch\\IA64\\")); #else
StringCchCatW(szAppPatch, ARRAY_LENGTH(szAppPatch), _T("\\AppPatch\\")); #endif // defined(_WIN64)
StringCchCopyW(szDllSearch, ARRAY_LENGTH(szDllSearch), szAppPatch); StringCchCatW(szDllSearch, ARRAY_LENGTH(szDllSearch), _T("*.dll"));
//
// enumerate all the DLLs and look for ones that have Verification
// shims in them
//
hFind = FindFirstFile(szDllSearch, &FindData); while (hFind != INVALID_HANDLE_VALUE) {
BOOL bVerifierShim = FALSE;
StringCchCopyW(szShimFullPath, ARRAY_LENGTH(szShimFullPath), szAppPatch); StringCchCatW(szShimFullPath, ARRAY_LENGTH(szShimFullPath), FindData.cFileName);
hMod = LoadLibrary(szShimFullPath); if (!hMod) { goto nextKey; }
pGetVerifierMagic = (_pfnGetVerifierMagic)GetProcAddress(hMod, "GetVerifierMagic"); if (!pGetVerifierMagic) { //
// not a real verifier shim
//
goto nextKey; }
if (pGetVerifierMagic() != VERIFIER_SHIMS_MAGIC) { //
// not a real verifier shim
//
goto nextKey; }
pQueryShimInfo = (_pfnQueryShimInfo)GetProcAddress(hMod, "QueryShimInfo"); if (!pQueryShimInfo) { //
// not a real verifier shim
//
goto nextKey; } dwShims = 0; if (!pQueryShimInfo(NULL, AVRF_INFO_NUM_SHIMS, (PVOID)&dwShims) || dwShims == 0) { //
// no shims available
//
goto nextKey; }
bVerifierShim = TRUE;
pShimNames = new LPWSTR[dwShims]; if (!pShimNames) { goto out; }
if (!pQueryShimInfo(NULL, AVRF_INFO_SHIM_NAMES, (PVOID)pShimNames)) { goto nextKey; }
for (DWORD i = 0; i < dwShims; ++i) { CTestInfo ti; LPWSTR szTemp = NULL; DWORD dwFlags = 0; DWORD dwVersion = 0;
ti.eTestType = TEST_SHIM; ti.strDllName = FindData.cFileName; ti.strTestName = pShimNames[i];
szTemp = NULL; if (pQueryShimInfo(pShimNames[i], AVRF_INFO_FRIENDLY_NAME, (PVOID)&szTemp) && szTemp) { ti.strTestFriendlyName = szTemp; } else { //
// default to the shim name
//
ti.strTestFriendlyName = pShimNames[i]; }
if (pQueryShimInfo(pShimNames[i], AVRF_INFO_VERSION, (PVOID)&dwVersion)) { WCHAR szVersion[40];
ti.wVersionHigh = HIWORD(dwVersion); ti.wVersionLow = LOWORD(dwVersion);
StringCchPrintfW(szVersion, ARRAY_LENGTH(szVersion), L" (%d.%d)", ti.wVersionHigh, ti.wVersionLow);
ti.strTestFriendlyName += szVersion; }
szTemp = NULL; if (pQueryShimInfo(pShimNames[i], AVRF_INFO_DESCRIPTION, (PVOID)&szTemp) && szTemp) { ti.strTestDescription = szTemp; } if (pQueryShimInfo(pShimNames[i], AVRF_INFO_FLAGS, (PVOID)&dwFlags)) { ti.bDefault = !(dwFlags & AVRF_FLAG_NO_DEFAULT) && !(dwFlags & AVRF_FLAG_RUN_ALONE); ti.bWin2KCompatible = !(dwFlags & AVRF_FLAG_NO_WIN2K); ti.bSetupOK = !(dwFlags & AVRF_FLAG_NOT_SETUP); ti.bNonSetupOK = !(dwFlags & AVRF_FLAG_ONLY_SETUP); ti.bRunAlone = !!(dwFlags & AVRF_FLAG_RUN_ALONE); ti.bPseudoShim = !!(dwFlags & AVRF_FLAG_NO_SHIM); ti.bNonTest = !!(dwFlags & AVRF_FLAG_NO_TEST); ti.bInternal = !(dwFlags & AVRF_FLAG_EXTERNAL_ONLY); ti.bExternal = !(dwFlags & AVRF_FLAG_INTERNAL_ONLY); } else { ti.bDefault = TRUE; ti.bWin2KCompatible = TRUE; ti.bSetupOK = TRUE; ti.bNonSetupOK = TRUE; ti.bRunAlone = FALSE; ti.bPseudoShim = FALSE; ti.bNonTest = FALSE; ti.bInternal = TRUE; ti.bExternal = TRUE; }
szTemp = NULL; if (pQueryShimInfo(pShimNames[i], AVRF_INFO_INCLUDE_EXCLUDE, (PVOID)&szTemp) && szTemp) { ParseIncludeList(szTemp, ti.aIncludes); }
//
// now get the PropSheetPage
//
if (pQueryShimInfo(pShimNames[i], AVRF_INFO_OPTIONS_PAGE, (PVOID)&(ti.PropSheetPage))) { ti.PropSheetPage.dwFlags |= PSP_USETITLE; ti.PropSheetPage.pszTitle = ti.strTestName.c_str();
} else { ZeroMemory(&(ti.PropSheetPage), sizeof(PROPSHEETPAGE)); }
//
// add it to the end
//
TestInfoArray.push_back(ti); }
nextKey: if (pShimNames) { delete [] pShimNames; pShimNames = NULL; }
if (hMod) { //
// if it's a verifier shim, we need to keep it around
//
if (!bVerifierShim) { FreeLibrary(hMod); } hMod = NULL; } if (!FindNextFile(hFind, &FindData)) { FindClose(hFind); hFind = INVALID_HANDLE_VALUE; } }
bRet = TRUE;
out:
if (hMod) { FreeLibrary(hMod); hMod = NULL; } if (hFind != INVALID_HANDLE_VALUE) { FindClose(hFind); hFind = INVALID_HANDLE_VALUE; } return bRet; }
BOOL InitTestInfo( void ) { g_aTestInfo.clear();
if (!GetKernelTestInfo(g_aTestInfo)) { return FALSE; } if (!GetShimInfo(g_aTestInfo)) { return FALSE; }
return TRUE; }
void ResetVerifierLog( void ) { WIN32_FIND_DATA FindData; HANDLE hFind = INVALID_HANDLE_VALUE; BOOL bFound; DWORD cchSize; TCHAR szVLogPath[MAX_PATH]; TCHAR szVLogSearch[MAX_PATH]; TCHAR szPath[MAX_PATH]; HANDLE hFile;
cchSize = GetAppVerifierLogPath(szVLogPath, ARRAY_LENGTH(szVLogPath));
if (cchSize > ARRAY_LENGTH(szVLogPath) || cchSize == 0) { return; }
StringCchCopyW(szVLogSearch, ARRAY_LENGTH(szVLogSearch), szVLogPath); StringCchCatW(szVLogSearch, ARRAY_LENGTH(szVLogSearch), _T("\\")); StringCchCatW(szVLogSearch, ARRAY_LENGTH(szVLogSearch), _T("*.log"));
//
// kill all the .log files
//
hFind = FindFirstFile(szVLogSearch, &FindData); while (hFind != INVALID_HANDLE_VALUE) {
StringCchCopyW(szPath, ARRAY_LENGTH(szPath), szVLogPath); StringCchCatW(szPath, ARRAY_LENGTH(szPath), _T("\\")); StringCchCatW(szPath, ARRAY_LENGTH(szPath), FindData.cFileName);
DeleteFile(szPath);
if (!FindNextFile(hFind, &FindData)) { FindClose(hFind); hFind = INVALID_HANDLE_VALUE; } }
//
// recreate session.log
//
CreateDirectory(szVLogPath, NULL);
StringCchCopyW(szPath, ARRAY_LENGTH(szPath), szVLogPath); StringCchCatW(szPath, ARRAY_LENGTH(szPath), _T("\\")); StringCchCatW(szPath, ARRAY_LENGTH(szPath), _T("session.log"));
hFile = CreateFile(szPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); }
return; }
void EnableVerifierLog(void) { HANDLE hFile; TCHAR szPath[MAX_PATH]; TCHAR szVLogPath[MAX_PATH]; DWORD cchSize;
cchSize = GetAppVerifierLogPath(szVLogPath, ARRAY_LENGTH(szVLogPath));
if (cchSize > ARRAY_LENGTH(szVLogPath) || cchSize == 0) { return; }
//
// make sure log dir and session.log exists
//
CreateDirectory(szVLogPath, NULL);
StringCchCopyW(szPath, ARRAY_LENGTH(szPath), szVLogPath); StringCchCatW(szPath, ARRAY_LENGTH(szPath), _T("\\")); StringCchCatW(szPath, ARRAY_LENGTH(szPath), _T("session.log"));
hFile = CreateFile(szPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } }
CTestInfo* FindShim( wstring& wstrName ) { CTestInfoArray::iterator it;
for (it = g_aTestInfo.begin(); it != g_aTestInfo.end(); it++) { if (it->strTestName == wstrName) { return &(*it); } }
return NULL; }
extern "C" BOOL ShimdbcExecute( LPCWSTR lpszCmdLine );
BOOL AppCompatWriteShimSettings( CAVAppInfoArray& arrAppInfo, BOOL b32bitOnly ) { TCHAR szTempPath[MAX_PATH] = _T(""); TCHAR szXmlFile[MAX_PATH] = _T(""); TCHAR szSdbFile[MAX_PATH] = _T(""); HANDLE hFile = INVALID_HANDLE_VALUE; DWORD bytesWritten; STARTUPINFO si; PROCESS_INFORMATION pi; BOOL bReturn = FALSE; TCHAR szUnicodeHdr[2] = { 0xFEFF, 0}; wstring wstrXML; static WCHAR wszTemp[2048]; static WCHAR wszCmd[1024];
if (0 == arrAppInfo.size()) { return AppCompatDeleteSettings(); }
wszTemp[0] = 0;
//
// Construct the XML...
//
#if defined(_WIN64)
if (!b32bitOnly) { StringCchPrintfW(wszTemp, ARRAYSIZE(wszTemp), _T("%s<?xml version=\"1.0\"?>\r\n") _T("<DATABASE NAME=\"Application Verifier Database (64 bit)\" ID=\"%s\">\r\n") _T(" <LIBRARY>\r\n"), szUnicodeHdr, AVDB_ID_64); } else #endif
{ StringCchPrintfW(wszTemp, ARRAYSIZE(wszTemp), _T("%s<?xml version=\"1.0\"?>\r\n") _T("<DATABASE NAME=\"Application Verifier Database\" ID=\"%s\">\r\n") _T(" <LIBRARY>\r\n"), szUnicodeHdr, AVDB_ID_32); }
wstrXML += wszTemp;
CTestInfoArray::iterator it;
for (it = g_aTestInfo.begin(); it != g_aTestInfo.end(); it++) { if (it->eTestType != TEST_SHIM) { continue; } StringCchPrintfW(wszTemp, ARRAYSIZE(wszTemp), _T(" <SHIM NAME=\"%s\" FILE=\"%s\">\r\n") _T(" <DESCRIPTION>\r\n") _T(" %s\r\n") _T(" </DESCRIPTION>\r\n"), it->strTestName.c_str(), it->strDllName.c_str(), it->strTestDescription.c_str());
wstrXML += wszTemp;
CIncludeArray::iterator iait;
for (iait = it->aIncludes.begin(); iait != it->aIncludes.end(); ++iait) { if (iait->bInclude) { StringCchPrintfW(wszTemp, ARRAYSIZE(wszTemp), _T(" <INCLUDE MODULE=\"%s\"/>\r\n"), iait->strModule.c_str()); } else { StringCchPrintfW(wszTemp, ARRAYSIZE(wszTemp), _T(" <EXCLUDE MODULE=\"%s\"/>\r\n"), iait->strModule.c_str()); }
wstrXML += wszTemp;
}
//
// make sure the EXE is included
//
wstrXML += _T(" <INCLUDE MODULE=\"%EXE%\"/>\r\n");
wstrXML += _T(" </SHIM>\r\n");
}
//
// put in layers for handling propagation of shims -- one layer per EXE
//
CAVAppInfo* aiit;
for (aiit = arrAppInfo.begin(); aiit != arrAppInfo.end(); aiit++) {
//
// if there are no shims, we're done
//
if (aiit->awstrShims.size() == 0) { continue; }
if (aiit->bPropagateTests) { StringCchPrintfW(wszTemp, ARRAYSIZE(wszTemp), _T(" <LAYER NAME=\"LAYER_%s\">\r\n"), aiit->wstrExeName.c_str()); wstrXML += wszTemp;
CWStringArray::iterator wsit;
for (wsit = aiit->awstrShims.begin(); wsit != aiit->awstrShims.end(); wsit++) {
CTestInfo* pTestInfo = FindShim(*wsit);
if (pTestInfo) { StringCchPrintfW(wszTemp, ARRAYSIZE(wszTemp), _T(" <SHIM NAME=\"%s\"/>\r\n"), pTestInfo->strTestName.c_str());
wstrXML += wszTemp; } }
wstrXML += _T(" </LAYER>\r\n"); } }
wstrXML += _T(" </LIBRARY>\r\n\r\n"); wstrXML += _T(" <APP NAME=\"All EXEs to be verified\" VENDOR=\"Various\">\r\n");
for (aiit = arrAppInfo.begin(); aiit != arrAppInfo.end(); aiit++) {
//
// if there are no shims, we're done
//
if (aiit->awstrShims.size() == 0) { continue; }
StringCchPrintfW(wszTemp, ARRAYSIZE(wszTemp), _T(" <EXE NAME=\"%s\">\r\n"), aiit->wstrExeName.c_str()); wstrXML += wszTemp;
if (aiit->bPropagateTests) {
//
// we need to fill in the layer name
//
StringCchPrintfW(wszTemp, ARRAYSIZE(wszTemp), _T(" <LAYER NAME=\"LAYER_%s\"/>\r\n"), aiit->wstrExeName.c_str());
wstrXML += wszTemp; }
//
// we still need to save the shim names, so they won't be lost when we
// load appverifier again. It's redundant, but doesn't hurt anything.
//
CWStringArray::iterator wsit;
for (wsit = aiit->awstrShims.begin(); wsit != aiit->awstrShims.end(); wsit++) {
CTestInfo* pTestInfo = FindShim(*wsit);
if (pTestInfo) { StringCchPrintfW(wszTemp, ARRAYSIZE(wszTemp), _T(" <SHIM NAME=\"%s\"/>\r\n"), pTestInfo->strTestName.c_str());
wstrXML += wszTemp; } }
wstrXML += _T(" </EXE>\r\n"); }
wstrXML += _T(" </APP>\r\n") _T("</DATABASE>");
if (GetTempPath(MAX_PATH, szTempPath) == 0) { DPF("[AppCompatSaveSettings] GetTempPath failed."); goto cleanup; }
//
// Obtain a temp name for the XML file
//
if (GetTempFileName(szTempPath, _T("XML"), NULL, szXmlFile) == 0) { DPF("[AppCompatSaveSettings] GetTempFilePath for XML failed."); goto cleanup; }
hFile = CreateFile(szXmlFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) { DPF("[AppCompatSaveSettings] CreateFile '%s' failed 0x%X.", szXmlFile, GetLastError()); goto cleanup; }
if (WriteFile(hFile, wstrXML.c_str(), wstrXML.length() * sizeof(TCHAR), &bytesWritten, NULL) == 0) { DPF("[AppCompatSaveSettings] WriteFile \"%s\" failed 0x%X.", szXmlFile, GetLastError()); goto cleanup; }
CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE;
//
// Obtain a temp name for the SDB file
//
StringCchPrintfW(szSdbFile, ARRAY_LENGTH(szSdbFile), _T("%stempdb.sdb"), szTempPath);
DeleteFile(szSdbFile);
//
// Invoke the compiler to generate the SDB file
//
ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si);
StringCchPrintfW(wszCmd, ARRAY_LENGTH(wszCmd), _T("shimdbc.exe fix -q \"%s\" \"%s\""), szXmlFile, szSdbFile);
if (!ShimdbcExecute(wszCmd)) { DPF("[AppCompatSaveSettings] CreateProcess \"%s\" failed 0x%X.", wszCmd, GetLastError()); goto cleanup; }
//
// The SDB file is generated. Install the database now.
//
ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si);
#if defined(_WIN64)
if (b32bitOnly) { WCHAR wszSys[MAX_PATH] = L""; int nLen; GetSystemWindowsDirectory(wszSys, MAX_PATH);
nLen = wcslen(wszSys); if (wszSys[nLen - 1] == L'\\') { wszSys[nLen - 1] = 0; }
StringCchPrintfW(wszCmd, ARRAY_LENGTH(wszCmd), _T("%s\\syswow64\\sdbinst.exe -q \"%s\""), wszSys, szSdbFile); } #endif
{ StringCchPrintfW(wszCmd, ARRAY_LENGTH(wszCmd), _T("sdbinst.exe -q \"%s\""), szSdbFile); }
if (!CreateProcess(NULL, wszCmd, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
DPF("[AppCompatSaveSettings] CreateProcess \"%s\" failed 0x%X.", wszCmd, GetLastError()); goto cleanup; }
CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
//
// ensure we've got a fresh log session started
//
EnableVerifierLog();
bReturn = TRUE;
cleanup:
if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); }
DeleteFile(szXmlFile); DeleteFile(szSdbFile);
return bReturn; }
BOOL AppCompatDeleteSettings( void ) { STARTUPINFO si; PROCESS_INFORMATION pi; WCHAR wszCmd[MAX_PATH];
ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si);
#if defined(_WIN64)
StringCchPrintfW(wszCmd, ARRAY_LENGTH(wszCmd), _T("sdbinst.exe -q -u -g ") AVDB_ID_64); #else
StringCchPrintfW(wszCmd, ARRAY_LENGTH(wszCmd), _T("sdbinst.exe -q -u -g ") AVDB_ID_32); #endif
if (!CreateProcess(NULL, wszCmd, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
DPF("[AppCompatDeleteSettings] CreateProcess \"%s\" failed 0x%X.", wszCmd, GetLastError()); return FALSE; }
CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
return TRUE; }
|