#include "precomp.h" #include "RegAnalyzer.h" #include "RegDiffFile.h" #include HREGANL CreateRegAnalyzer ( VOID ) { HREGANL regAnalyzer = (HREGANL) new CRegAnalyzer; return regAnalyzer; } BOOL CloseRegAnalyzer ( IN HREGANL RegAnalyzer ) { delete (CRegAnalyzer*) RegAnalyzer; return TRUE; } BOOL AddRegistryKey ( IN HREGANL RegAnalyzer, IN PCTSTR RootKeyName, IN PCTSTR SubKeyName ) { CRegAnalyzer* pRA = (CRegAnalyzer*)RegAnalyzer; return pRA->AddKey(RootKeyName, SubKeyName); } BOOL ExcludeRegistryKey ( IN HREGANL RegAnalyzer, IN PCTSTR RootKeyName, IN PCTSTR SubKeyName ) { CRegAnalyzer* pRA = (CRegAnalyzer*)RegAnalyzer; return pRA->AddKey(RootKeyName, SubKeyName, true); } ////////////////////////////////////////////////////////////////////////////////////// struct TakeSnapshotParams { HREGANL RegAnalyzer; PCTSTR SnapshotFile; PFNSNAPSHOTPROGRESS ProgressCallback; PVOID Context; DWORD MaxLevel; HANDLE hEvent; }; void __cdecl TakeSnapshotThread(void* pParams) { TakeSnapshotParams* pp = (TakeSnapshotParams*)pParams; if (pp != NULL) { CRegAnalyzer* pRA = (CRegAnalyzer*)pp->RegAnalyzer; pRA->SaveKeysToFile(pp->SnapshotFile, pp->ProgressCallback, pp->Context, pp->MaxLevel); SetEvent(pp->hEvent); delete pp; } return; } BOOL TakeSnapshot ( IN HREGANL RegAnalyzer, IN PCTSTR SnapshotFile, IN PFNSNAPSHOTPROGRESS ProgressCallback, IN PVOID Context, IN DWORD MaxLevel, IN HANDLE hEvent ) { CRegAnalyzer* pRA = (CRegAnalyzer*)RegAnalyzer; if (hEvent == NULL) return pRA->SaveKeysToFile(SnapshotFile, ProgressCallback, Context, MaxLevel); else { TakeSnapshotParams* pParams = new TakeSnapshotParams; if (pParams != NULL) { pParams->RegAnalyzer=RegAnalyzer; pParams->SnapshotFile=SnapshotFile; pParams->ProgressCallback=ProgressCallback; pParams->Context=Context; pParams->MaxLevel=MaxLevel; pParams->hEvent=hEvent; _beginthread(TakeSnapshotThread, 0, (void*)pParams); return TRUE; } else return FALSE; } } ////////////////////////////////////////////////////////////////////////////////////// struct ComputeDifferencesParams { HREGANL RegAnalyzer; PCTSTR Snapshot1; PCTSTR Snapshot2; PCTSTR DiffFile; HANDLE hEvent; }; void __cdecl ComputeDifferencesThread(void* pParams) { ComputeDifferencesParams* pp = (ComputeDifferencesParams*)pParams; if (pp != NULL) { CRegAnalyzer* pRA = (CRegAnalyzer*)pp->RegAnalyzer; pRA->ComputeDifferences1(pp->Snapshot1, pp->Snapshot2, pp->DiffFile); SetEvent(pp->hEvent); delete pp; } return; } BOOL ComputeDifferences ( IN HREGANL RegAnalyzer, IN PCTSTR Snapshot1, IN PCTSTR Snapshot2, IN PCTSTR DiffFile, IN HANDLE hEvent ) { CRegAnalyzer* pRA = (CRegAnalyzer*)RegAnalyzer; // // BUGBUG - ISSUE - what about security settings associated with each registry key? // if (hEvent == NULL) return pRA->ComputeDifferences1(Snapshot1, Snapshot2, DiffFile); else { ComputeDifferencesParams* pParams = new ComputeDifferencesParams; if (pParams != NULL) { pParams->RegAnalyzer=RegAnalyzer; pParams->Snapshot1=Snapshot1; pParams->Snapshot2=Snapshot2; pParams->DiffFile=DiffFile; pParams->hEvent=hEvent; _beginthread(ComputeDifferencesThread, 0, (void*)pParams); return TRUE; } else return FALSE; } } ////////////////////////////////////////////////////////////////////////////////////// BOOL InstallDifferences ( IN PCTSTR DiffFile, IN PCTSTR UndoFile ) { CRegDiffFile diff; if (!diff.Init(DiffFile, TRUE)) { return FALSE; } return diff.ApplyToRegistry(UndoFile); } BOOL CountRegSubkeysInternal ( IN HKEY RootKey, IN PCTSTR SubKey, IN DWORD MaxLevels, OUT PDWORD Nodes ) { MYASSERT (MaxLevels > 0); HKEY parentKey; DWORD rc = RegOpenKeyEx (RootKey, SubKey, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &parentKey); if (rc != ERROR_SUCCESS) { SetLastError (rc); LOG3 (LOG_ERROR, "Failed to open reg subkey (%x,%s) (rc=%u)", RootKey, SubKey, rc); return FALSE; } BOOL b = FALSE; PTSTR subKeyBuffer = NULL; __try { DWORD subKeys; DWORD subKeyMaxLen; rc = RegQueryInfoKey (parentKey, NULL, NULL, NULL, &subKeys, &subKeyMaxLen, NULL, NULL, NULL, NULL, NULL, NULL); if (rc != ERROR_SUCCESS) { SetLastError (rc); LOG3 (LOG_ERROR, "Failed to query reg subkey (%x,%s) (rc=%u)", RootKey, SubKey, rc); __leave; } subKeyMaxLen++; subKeyBuffer = new TCHAR[subKeyMaxLen]; if (!subKeyBuffer) { OOM(); __leave; } if (MaxLevels > 1) { for (DWORD index = 0; index < subKeys; index++) { DWORD len = subKeyMaxLen; rc = RegEnumKeyEx (parentKey, index, subKeyBuffer, &len, NULL, NULL, NULL, NULL); if (rc == ERROR_NO_MORE_ITEMS) { break; } if (rc != ERROR_SUCCESS) { SetLastError (rc); LOG4 (LOG_ERROR, "Failed to enum reg subkey (%x,%s) at index %u (rc=%u)", RootKey, SubKey, index, rc); __leave; } if (!CountRegSubkeysInternal (parentKey, subKeyBuffer, MaxLevels - 1, Nodes)) { __leave; } } } *Nodes += subKeys; delete []subKeyBuffer; subKeyBuffer = NULL; b = TRUE; } __finally { if (!b) { rc = GetLastError (); } if (subKeyBuffer) { delete []subKeyBuffer; } RegCloseKey (parentKey); if (!b) { SetLastError (rc); } } return b; } BOOL CountRegSubkeys ( IN PCTSTR Root, IN PCTSTR SubKey, IN DWORD MaxLevels, OUT PDWORD Nodes ) { HKEY rootKey = GetRootKey (Root); if (!rootKey) { LOG1 (LOG_ERROR, "Invalid root key (%s)", Root); return FALSE; } HKEY parentKey; DWORD rc = RegOpenKeyEx (rootKey, SubKey, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &parentKey); if (rc != ERROR_SUCCESS) { SetLastError (rc); LOG3 (LOG_ERROR, "Failed to open reg key (%s\\%s) (rc=%u)", Root, SubKey, rc); return FALSE; } RegCloseKey (parentKey); *Nodes = 1; // the root itself return MaxLevels ? CountRegSubkeysInternal (rootKey, SubKey, MaxLevels, Nodes) : TRUE; } HKEY GetRootKey ( IN PCTSTR RootStr ) { static struct { PCTSTR RootStr; HKEY RootKey; } map[] = { { TEXT("HKLM"), HKEY_LOCAL_MACHINE }, { TEXT("HKCU"), HKEY_CURRENT_USER }, { TEXT("HKCR"), HKEY_CLASSES_ROOT }, { TEXT("HKU"), HKEY_USERS }, { TEXT("HKCC"), HKEY_CURRENT_CONFIG }, { NULL, 0 } }, *entry; for (entry = map; entry->RootStr; entry++) { if (_tcsicmp (RootStr, entry->RootStr) == 0) { return entry->RootKey; } } SetLastError (ERROR_INVALID_PARAMETER); return 0; }