|
|
#include "acBrowser.h"
#include <wchar.h>
#include <commctrl.h>
#include <psapi.h>
#include "shimdb.h"
#define SHIM_LOG_FILE "shimlog.txt"
#define Alloc(cb) \
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb)
#define Free(p) \
HeapFree(GetProcessHeap(), 0, p)
PDBENTRY g_pEntries; PFIX g_pFixes;
#define MAX_DATA_SIZE 1024
#define MAX_NAME 256
#define MAX_DESCRIPTION 1024
WCHAR g_wszData[MAX_DATA_SIZE];
char g_szName[MAX_NAME]; char g_szDescription[MAX_DESCRIPTION];
#define APPCOMPAT_DISABLED 0x03
//
// REGISTRY STUFF. Needs to be revised
//
#define APPCOMPAT_KEY "Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags"
BOOL CheckRegistry( HKEY hkeyRoot, char* pszGUID ) { LONG status; HKEY hkey = NULL; BOOL bDisabled = FALSE; DWORD dwFlags; DWORD type; DWORD cbSize = sizeof(DWORD);
status = RegOpenKey(hkeyRoot, APPCOMPAT_KEY, &hkey);
if (status != ERROR_SUCCESS) { return FALSE; }
status = RegQueryValueEx(hkey, pszGUID, NULL, &type, (LPBYTE)&dwFlags, &cbSize);
if (status == ERROR_SUCCESS && type == REG_DWORD && (dwFlags & APPCOMPAT_DISABLED)) { bDisabled = TRUE; }
RegCloseKey(hkey);
return bDisabled; }
BOOL WriteRegistry( HKEY hkeyRoot, char* pszKeyName ) { LONG status; HKEY hkey; DWORD dwValue = 0x03; DWORD dwDisposition = 0; BOOL bDisabled = FALSE;
status = RegCreateKeyEx(hkeyRoot, APPCOMPAT_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition);
if (status != ERROR_SUCCESS) { LogMsg("Failed to set the value for \"%s\"\n", pszKeyName); return FALSE; }
status = RegSetValueEx(hkey, pszKeyName, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
RegCloseKey(hkey);
if (status != ERROR_SUCCESS) { LogMsg("Failed to set the value for \"%s\"\n", pszKeyName); return FALSE; }
return TRUE; }
BOOL DeleteRegistry( HKEY hkeyRoot, char* pszKeyName ) { LONG status; HKEY hkey = NULL; DWORD dwValue = 0; DWORD dwDisposition = 0; BOOL bDisabled = FALSE;
status = RegOpenKey(hkeyRoot, APPCOMPAT_KEY, &hkey);
if (status != ERROR_SUCCESS) { return TRUE; }
status = RegDeleteValue(hkey, pszKeyName);
RegCloseKey(hkey);
return TRUE; }
typedef void (*PFNFLUSHCACHE)(HWND, HINSTANCE, LPSTR, int);
void FlushTheCache( void ) { HINSTANCE hmod; PFNFLUSHCACHE pfnFlushCache; char szPath[MAX_PATH];
GetSystemDirectory(szPath, MAX_PATH);
lstrcat(szPath, "\\apphelp.dll");
hmod = LoadLibrary(szPath);
if (hmod != NULL) { pfnFlushCache = (PFNFLUSHCACHE)GetProcAddress(hmod, "ShimFlushCache");
if (pfnFlushCache != NULL) { (*pfnFlushCache)(0, 0, NULL, 0); } } }
void UpdateFixStatus( char* pszGUID, BOOL bPerUser, BOOL bPerMachine ) { if (bPerUser) { WriteRegistry(HKEY_CURRENT_USER, pszGUID); } else { DeleteRegistry(HKEY_CURRENT_USER, pszGUID); }
if (bPerMachine) { WriteRegistry(HKEY_LOCAL_MACHINE, pszGUID); } else { DeleteRegistry(HKEY_LOCAL_MACHINE, pszGUID); }
FlushTheCache(); }
PFIX AllocFix( char* pszFixName, char* pszFixDescription, FIXTYPE type ) { PFIX pFix; char* pszAlloc;
pFix = (PFIX)Alloc(sizeof(FIX)); if (pFix == NULL) { LogMsg("Cannot allocate %d bytes\n", sizeof(FIX)); return NULL; }
if (pszFixName == NULL || *pszFixName == 0) { pFix->pszName = NULL; } else { pszAlloc = (char*)Alloc(lstrlen(pszFixName) + 1); pFix->pszName = pszAlloc; if (pszAlloc != NULL) { lstrcpy(pszAlloc, pszFixName); } else { LogMsg("Cannot allocate %d bytes\n", lstrlen(pszFixName) + 1); goto Error; } }
if (pszFixDescription == NULL || *pszFixDescription == 0) { pFix->pszDescription = NULL; } else { pszAlloc = (char*)Alloc(lstrlen(pszFixDescription) + 1); pFix->pszDescription = pszAlloc; if (pszAlloc != NULL) { lstrcpy(pszAlloc, pszFixDescription); } else { LogMsg("Cannot allocate %d bytes\n", lstrlen(pszFixDescription) + 1); goto Error; } } pFix->fixType = type; pFix->pNext = NULL;
return pFix;
Error: if (pFix->pszName != NULL) { Free(pFix->pszName); } if (pFix->pszDescription != NULL) { Free(pFix->pszDescription); } Free(pFix);
return NULL; }
void ReadFix( PDB pdb, TAGID tiFix, FIXTYPE type ) { TAGID tiInfo; TAG tWhich; PFIX pFix; ULONGLONG ullUser = 0; ULONGLONG ullKernel = 0;
tiInfo = SdbGetFirstChild(pdb, tiFix);
g_szName[0] = 0; g_szDescription[0] = 0;
while (tiInfo != 0) { tWhich = SdbGetTagFromTagID(pdb, tiInfo);
switch (tWhich) {
case TAG_NAME: if (SdbReadStringTag(pdb, tiInfo, g_wszData, MAX_NAME * sizeof(WCHAR))) { wsprintf(g_szName, "%ws", g_wszData); } break;
case TAG_DESCRIPTION: if (SdbReadStringTag(pdb, tiInfo, g_wszData, MAX_DESCRIPTION * sizeof(WCHAR))) { wsprintf(g_szDescription, "%ws", g_wszData); } break;
case TAG_FLAG_MASK_USER: ullUser = SdbReadQWORDTag(pdb, tiInfo, 0); break;
case TAG_FLAG_MASK_KERNEL: ullKernel = SdbReadQWORDTag(pdb, tiInfo, 0); break;
default: break; }
tiInfo = SdbGetNextChild(pdb, tiFix, tiInfo); }
pFix = AllocFix(g_szName, g_szDescription, type);
if (pFix != NULL) { if (type == FIX_FLAG) { if (ullKernel == 0) { pFix->flagType = FLAG_USER; pFix->ullMask = ullUser; } else { pFix->flagType = FLAG_KERNEL; pFix->ullMask = ullKernel; } } pFix->pNext = g_pFixes; g_pFixes = pFix; } }
void ReadFixes( PDB pdb, TAGID tiDatabase, TAGID tiLibrary ) { TAGID tiFix;
tiFix = SdbFindFirstTag(pdb, tiLibrary, TAG_SHIM);
while (tiFix != 0) { ReadFix(pdb, tiFix, FIX_SHIM); tiFix = SdbFindNextTag(pdb, tiLibrary, tiFix); }
tiFix = SdbFindFirstTag(pdb, tiLibrary, TAG_PATCH);
while (tiFix != 0) { ReadFix(pdb, tiFix, FIX_PATCH); tiFix = SdbFindNextTag(pdb, tiLibrary, tiFix); }
tiFix = SdbFindFirstTag(pdb, tiLibrary, TAG_FLAG);
while (tiFix != 0) { ReadFix(pdb, tiFix, FIX_FLAG); tiFix = SdbFindNextTag(pdb, tiLibrary, tiFix); }
//
// The LAYERs are under the DATABASE tag instead of LIBRARY :-(
//
tiFix = SdbFindFirstTag(pdb, tiDatabase, TAG_LAYER);
while (tiFix != 0) { ReadFix(pdb, tiFix, FIX_LAYER); tiFix = SdbFindNextTag(pdb, tiDatabase, tiFix); } }
PFIX FindFix( char* pszFixName, FIXTYPE fixType ) { PFIX pFix = g_pFixes;
while (pFix != NULL) {
if (pFix->pszName && lstrcmpi(pszFixName, pFix->pszName) == 0) { return pFix; }
pFix = pFix->pNext; } return NULL; }
PFIX FindFlagFix( ULONGLONG ullMask, FLAGTYPE flagType ) { PFIX pFix = g_pFixes;
while (pFix != NULL) {
if (pFix->fixType == FIX_FLAG && pFix->flagType == flagType && pFix->ullMask == ullMask) { return pFix; } pFix = pFix->pNext; } return NULL; }
BOOL AddFlags( PDB pdb, TAGID tiFlags, PDBENTRY pEntry, FLAGTYPE flagType ) { ULONGLONG ullFlags; ULONGLONG ullMask = 1; PFIX pFix; PFIXLIST pFixList; int i; ullFlags = SdbReadQWORDTag(pdb, tiFlags, 0);
for (i = 0; i < sizeof(ULONGLONG) * 8; i++) {
if (ullFlags & ullMask) {
pFix = FindFlagFix(ullMask, flagType);
if (pFix == NULL) { LogMsg("Cannot find flag fix ref\n"); }
pFixList = (PFIXLIST)Alloc(sizeof(FIXLIST));
if (pFixList == NULL) { LogMsg("Cannot allocate %d bytes\n", sizeof(FIXLIST)); return FALSE; }
pFixList->pFix = pFix; pFixList->pNext = pEntry->pFirstFlag;
pEntry->pFirstFlag = pFixList; } ullMask <<= 1; } return TRUE; }
BOOL AddFix( PDB pdb, TAGID tiFix, PDBENTRY pEntry, FIXTYPE fixType ) { TAGID tiName; char szFixName[MAX_NAME]; PFIX pFix; PFIXLIST* ppHead; PFIXLIST pFixList;
tiName = SdbFindFirstTag(pdb, tiFix, TAG_NAME);
if (!SdbReadStringTag(pdb, tiName, g_wszData, MAX_NAME * sizeof(WCHAR))) { LogMsg("Cannot read the name of the fix\n"); return FALSE; }
wsprintf(szFixName, "%ws", g_wszData);
pFix = FindFix(szFixName, fixType);
if (pFix == NULL) { LogMsg("Cannot find fix ref for: \"%s\" type %d\n", szFixName, fixType); return FALSE; }
switch (fixType) { case FIX_SHIM: ppHead = &pEntry->pFirstShim; break; case FIX_PATCH: ppHead = &pEntry->pFirstPatch; break; case FIX_FLAG: ppHead = &pEntry->pFirstFlag; break; case FIX_LAYER: ppHead = &pEntry->pFirstLayer; break; }
pFixList = (PFIXLIST)Alloc(sizeof(FIXLIST));
if (pFixList == NULL) { LogMsg("Cannot allocate %d bytes\n", sizeof(FIXLIST)); return FALSE; }
pFixList->pFix = pFix; pFixList->pNext = *ppHead;
*ppHead = pFixList; return TRUE; }
void AddAttr( char* pszAttr, PMATCHINGFILE pMatch ) { PATTRIBUTE pAttr;
pAttr = (PATTRIBUTE)Alloc(sizeof(ATTRIBUTE));
if (pAttr) { pAttr->pszText = (char*)Alloc(lstrlen(pszAttr) + 1);
if (pAttr->pszText) { lstrcpy(pAttr->pszText, pszAttr);
pAttr->pNext = pMatch->pFirstAttribute;
pMatch->pFirstAttribute = pAttr; } else { Free(pAttr); } } }
VOID PrintBinVer( char* pszText, LARGE_INTEGER* pliBinVer ) { wsprintf(pszText, "%d", HIWORD(pliBinVer->HighPart)); pszText += lstrlen(pszText);
if (LOWORD(pliBinVer->HighPart) == 0xFFFF) { return; } wsprintf(pszText, ".%d", LOWORD(pliBinVer->HighPart)); pszText += lstrlen(pszText);
if (HIWORD(pliBinVer->LowPart) == 0xFFFF) { return; } wsprintf(pszText, ".%d", HIWORD(pliBinVer->LowPart)); pszText += lstrlen(pszText); if (LOWORD(pliBinVer->LowPart) == 0xFFFF) { return; } wsprintf(pszText, ".%d", LOWORD(pliBinVer->LowPart)); pszText += lstrlen(pszText); }
BOOL AddMatchingFile( PDB pdb, TAGID tiMatch, PDBENTRY pEntry ) { TAGID tiMatchInfo; TAG tWhich; DWORD dw; LARGE_INTEGER li; PMATCHINGFILE pMatch; char szStr[128]; char szAttr[256];
pMatch = (PMATCHINGFILE)Alloc(sizeof(MATCHINGFILE));
if (pMatch == NULL) { return FALSE; }
tiMatchInfo = SdbGetFirstChild(pdb, tiMatch);
while (tiMatchInfo != 0) { tWhich = SdbGetTagFromTagID(pdb, tiMatchInfo);
switch (tWhich) {
case TAG_NAME: if (SdbReadStringTag(pdb, tiMatchInfo, g_wszData, MAX_NAME * sizeof(WCHAR))) { wsprintf(szAttr, "%ws", g_wszData); pMatch->pszName = (char*)Alloc(lstrlen(szAttr) + 1);
if (pMatch->pszName) { lstrcpy(pMatch->pszName, szAttr); } } break;
case TAG_SIZE: dw = SdbReadDWORDTag(pdb, tiMatchInfo, 0); if (dw != 0) { wsprintf(szAttr, "File Size: 0x%X", dw); AddAttr(szAttr, pMatch); } break;
case TAG_CHECKSUM: dw = SdbReadDWORDTag(pdb, tiMatchInfo, 0); if (dw != 0) { wsprintf(szAttr, "File CheckSum: 0x%X", dw); AddAttr(szAttr, pMatch); } break;
case TAG_COMPANY_NAME: if (SdbReadStringTag(pdb, tiMatchInfo, g_wszData, MAX_DATA_SIZE * sizeof(WCHAR))) { wsprintf(szStr, "%ws", g_wszData);
wsprintf(szAttr, "Company Name: %s", szStr); AddAttr(szAttr, pMatch); } break;
case TAG_PRODUCT_NAME: if (SdbReadStringTag(pdb, tiMatchInfo, g_wszData, MAX_DATA_SIZE * sizeof(WCHAR))) { wsprintf(szStr, "%ws", g_wszData);
wsprintf(szAttr, "Product Name: %s", szStr); AddAttr(szAttr, pMatch); } break;
case TAG_PRODUCT_VERSION: if (SdbReadStringTag(pdb, tiMatchInfo, g_wszData, MAX_DATA_SIZE * sizeof(WCHAR))) { wsprintf(szStr, "%ws", g_wszData);
wsprintf(szAttr, "Product Version: %s", szStr); AddAttr(szAttr, pMatch); } break;
case TAG_FILE_DESCRIPTION: if (SdbReadStringTag(pdb, tiMatchInfo, g_wszData, MAX_DATA_SIZE * sizeof(WCHAR))) { wsprintf(szStr, "%ws", g_wszData);
wsprintf(szAttr, "File Description: %s", szStr); AddAttr(szAttr, pMatch); } break;
case TAG_BIN_FILE_VERSION: li.QuadPart = SdbReadQWORDTag(pdb, tiMatchInfo, 0); if (li.HighPart != 0 || li.LowPart != 0) {
PrintBinVer(szStr, &li); wsprintf(szAttr, "Binary File Version: %s", szStr); AddAttr(szAttr, pMatch); } break;
case TAG_BIN_PRODUCT_VERSION: li.QuadPart = SdbReadQWORDTag(pdb, tiMatchInfo, 0); if (li.HighPart != 0 || li.LowPart != 0) {
PrintBinVer(szStr, &li); wsprintf(szAttr, "Binary Product Version: %s", szStr); AddAttr(szAttr, pMatch); } break;
default: break; } tiMatchInfo = SdbGetNextChild(pdb, tiMatch, tiMatchInfo); }
pMatch->pNext = pEntry->pFirstMatchingFile;
pEntry->pFirstMatchingFile = pMatch;
(pEntry->nMatchingFiles)++;
return TRUE; }
void AddEntry( PDB pdb, TAGID tiExe ) { TAGID tiExeInfo; TAGID tiSeverity, tiHelpId; char szStr[MAX_NAME]; TAG tWhich; PDBENTRY pEntry;
tiExeInfo = SdbGetFirstChild(pdb, tiExe);
pEntry = (PDBENTRY)Alloc(sizeof(DBENTRY));
if (pEntry == NULL) { LogMsg("Cannot allocate %d bytes\n", sizeof(DBENTRY)); return; }
pEntry->pNext = g_pEntries; g_pEntries = pEntry;
while (tiExeInfo != 0) { tWhich = SdbGetTagFromTagID(pdb, tiExeInfo);
switch (tWhich) {
case TAG_NAME: if (SdbReadStringTag(pdb, tiExeInfo, g_wszData, MAX_NAME * sizeof(WCHAR))) { wsprintf(szStr, "%ws", g_wszData);
pEntry->pszExeName = (char*)Alloc(lstrlen(szStr) + 1);
if (pEntry->pszExeName) { lstrcpy(pEntry->pszExeName, szStr); } } break;
case TAG_APP_NAME: if (SdbReadStringTag(pdb, tiExeInfo, g_wszData, MAX_NAME * sizeof(WCHAR))) { wsprintf(szStr, "%ws", g_wszData);
pEntry->pszAppName = (char*)Alloc(lstrlen(szStr) + 1);
if (pEntry->pszAppName) { lstrcpy(pEntry->pszAppName, szStr); } } break;
case TAG_MATCHING_FILE: AddMatchingFile(pdb, tiExeInfo, pEntry); break;
case TAG_APPHELP: pEntry->appHelp.bPresent = TRUE; tiSeverity = SdbFindFirstTag(pdb, tiExeInfo, TAG_PROBLEMSEVERITY); pEntry->appHelp.severity = (SEVERITY)SdbReadDWORDTag(pdb, tiSeverity, 0);
tiHelpId = SdbFindFirstTag(pdb, tiExeInfo, TAG_HTMLHELPID); pEntry->appHelp.htmlHelpId = SdbReadDWORDTag(pdb, tiHelpId, 0);
break;
case TAG_SHIM_REF: AddFix(pdb, tiExeInfo, pEntry, FIX_SHIM); break;
case TAG_PATCH_REF: AddFix(pdb, tiExeInfo, pEntry, FIX_PATCH); break;
case TAG_LAYER: AddFix(pdb, tiExeInfo, pEntry, FIX_LAYER); break;
case TAG_FLAG_MASK_USER: AddFlags(pdb, tiExeInfo, pEntry, FLAG_USER); break;
case TAG_FLAG_MASK_KERNEL: AddFlags(pdb, tiExeInfo, pEntry, FLAG_KERNEL); break;
case TAG_EXE_ID: { GUID guid; PVOID p;
p = SdbGetBinaryTagData(pdb, tiExeInfo);
if (p != NULL) { memcpy(&guid, p, sizeof(GUID)); wsprintf(pEntry->szGUID, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); } break; }
default: break; } tiExeInfo = SdbGetNextChild(pdb, tiExe, tiExeInfo); } pEntry->bDisablePerMachine = CheckRegistry(HKEY_LOCAL_MACHINE, pEntry->szGUID); pEntry->bDisablePerUser = CheckRegistry(HKEY_CURRENT_USER, pEntry->szGUID); }
PDBENTRY GetDatabaseEntries( void ) { WCHAR wszShimDB[MAX_PATH] = L""; PDB pdb; TAGID tiDatabase, tiLibrary, tiExe;
GetSystemWindowsDirectoryW(wszShimDB, MAX_PATH); wcscat(wszShimDB, L"\\AppPatch\\sysmain.sdb");
//
// Open sysmain.sdb shim database
//
pdb = SdbOpenDatabase(wszShimDB, DOS_PATH);
if (pdb == NULL) { LogMsg("Cannot open shim DB \"%ws\"\n", wszShimDB); goto Cleanup; }
tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
if (tiDatabase == 0) { LogMsg("Cannot find TAG_DATABASE\n"); goto Cleanup; }
tiLibrary = SdbFindFirstTag(pdb, tiDatabase, TAG_LIBRARY);
if (tiLibrary == 0) { LogMsg("Cannot find TAG_LIBRARY\n"); goto Cleanup; }
ReadFixes(pdb, tiDatabase, tiLibrary); //
// Loop through the EXEs.
//
tiExe = SdbFindFirstTag(pdb, tiDatabase, TAG_EXE);
while (tiExe != 0) { AddEntry(pdb, tiExe);
tiExe = SdbFindNextTag(pdb, tiDatabase, tiExe); }
Cleanup: if (pdb != NULL) { SdbCloseDatabase(pdb); }
return g_pEntries; }
|