/*++ Copyright (C) 1997-2001 Microsoft Corporation Module Name: REGEVENT.CPP Abstract: Declares the CRegEvent class History: a-davj 1-July-97 Created. --*/ #include "precomp.h" #include "node.h" #include "eventreg.h" #include #include "regevent.h" CRegEventSet gSet; struct BaseTypes2 { LPTSTR lpName; HKEY hKey; } Bases2[] = { {TEXT("HKEY_CLASSES_ROOT") , HKEY_CLASSES_ROOT}, {TEXT("HKEY_CURRENT_USER") , HKEY_CURRENT_USER}, {TEXT("HKEY_LOCAL_MACHINE") , HKEY_LOCAL_MACHINE}, {TEXT("HKEY_USERS") , HKEY_USERS}, {TEXT("HKEY_PERFORMANCE_DATA") , HKEY_PERFORMANCE_DATA}, {TEXT("HKEY_CURRENT_CONFIG") , HKEY_CURRENT_CONFIG}, {TEXT("HKEY_DYN_DATA") , HKEY_DYN_DATA}}; DWORD AddToCheckSub(DWORD & dwNewCheckSum, void * pData, DWORD dwDataSize) { return 0; } void CRegEvent::TimerCheck() { DWORD dwError; CNode * pNewHiveImage = NULL; // todo, need some sort of mutex so as not to reenter this. Also need to create // a thread to do this!!!! DWORD dwNewCheckSum = 0; HKEY hSubKey = NULL; // Open the root key TCHAR * pSt = m_sRegPath; TCHAR * pAfter = NULL; HKEY hBase = NULL; int iSlash = m_sRegPath.Find('\\'); if(iSlash < 0) { return; } pSt[iSlash] = 0; pAfter = pSt + iSlash + 1; for(int iCnt = 0; iCnt < sizeof(Bases2) / sizeof(struct BaseTypes2 ); iCnt++) if(!lstrcmpi(Bases2[iCnt].lpName, pSt)) { hBase = Bases2[iCnt].hKey; break; } if(hBase == NULL) { return; //todo, bitch } long lRes = RegOpenKeyEx(hBase, pAfter, 0, KEY_READ, &hSubKey); if(lRes != 0) { dwError = GetLastError(); return; //todo, bitch } if(m_bSaveHiveImage) pNewHiveImage = new CNode; CalcHive(hSubKey, dwNewCheckSum); RegCloseKey(hSubKey); if(dwNewCheckSum != m_dwCheckSum) { //todo, send event m_dwCheckSum = dwNewCheckSum; } if(m_bSaveHiveImage) { if(m_pLastHiveImage) { m_pLastHiveImage->CompareAndReportDiffs(pNewHiveImage); { } delete m_pLastHiveImage; } m_pLastHiveImage = pNewHiveImage; } } DWORD CRegEvent::CalcHive(HKEY hKey,DWORD & dwNewCheckSum) { long lRes; DWORD dwRet = 0; TCHAR * pSubKeyName = NULL; TCHAR * pValueName = NULL; BYTE * pValue = NULL; DWORD dwError; // Get the general info on the directory. DWORD dwSubKeys, dwMaxSubKeyLen, dwValues, dwMaxValueNameLen, dwMaxValueLen; lRes = RegQueryInfoKey(hKey, NULL, NULL, NULL, &dwSubKeys, &dwMaxSubKeyLen, NULL, &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL); if(lRes != ERROR_SUCCESS) { DWORD dwRet = GetLastError(); goto CalcHiveCleanup; } // Allocate space to hold the various names and data pValueName = new TCHAR[dwMaxValueNameLen+1]; if(dwMaxValueLen > 0) pValue = new BYTE[dwMaxValueLen]; if(pValueName == NULL || (dwMaxValueLen > 0 &&pValue == NULL)) { dwRet = WBEM_E_OUT_OF_MEMORY; goto CalcHiveCleanup; } // Enumerate each value, add the name, type, and data to the check sum DWORD dwCnt; for(dwCnt = 0; dwCnt < dwValues ; dwCnt++) { DWORD dwTempNameSize = dwMaxValueNameLen+1; DWORD dwType; DWORD dwTempDataSize = dwMaxValueLen; lRes = RegEnumValue(hKey, dwCnt, pValueName, &dwTempNameSize, 0, &dwType, pValue, &dwTempDataSize); if(lRes != ERROR_SUCCESS) { DWORD dwRet = GetLastError(); goto CalcHiveCleanup; } AddToCheckSub(dwNewCheckSum, pValueName, dwTempNameSize); AddToCheckSub(dwNewCheckSum, &dwType, sizeof(DWORD)); AddToCheckSub(dwNewCheckSum, pValue, dwTempNameSize); } // Free up the memory which is no longer needed if(pValueName) delete pValueName; pValueName = NULL; if(pValue) delete pValue; pValue = NULL; // Enumerate the subkeys and calculate them pSubKeyName = new TCHAR[dwMaxSubKeyLen+1]; for(dwCnt = 0; dwCnt < dwSubKeys ; dwCnt++) { lRes = RegEnumKey(hKey, dwCnt, pSubKeyName, dwMaxSubKeyLen+1); if(lRes != ERROR_SUCCESS) { DWORD dwRet = GetLastError(); goto CalcHiveCleanup; } // Add the name to the check sum, open the key and call this recursively AddToCheckSub(dwNewCheckSum, pSubKeyName, lstrlen(pSubKeyName)); HKEY hSubKey = NULL; long lRes = RegOpenKeyEx(hKey, pSubKeyName, 0, KEY_READ, &hSubKey); if(lRes != 0) { dwError = GetLastError(); return dwError; //todo, bitch } CalcHive(hSubKey, dwNewCheckSum); RegCloseKey(hSubKey); } CalcHiveCleanup: if(pSubKeyName) delete pSubKeyName; if(pValueName) delete pValueName; if(pValue) delete pValue; return dwRet; } SCODE MyCreateInstance(IWbemServices * pGateway, WCHAR * pwcClass, WCHAR * pwcKeyName, WCHAR * pwcKeyValue, IWbemClassObject ** ppNewInst) { SCODE sc; if(pGateway == NULL || pwcClass == NULL || pwcKeyName == NULL || pwcKeyValue == NULL || ppNewInst == NULL) return WBEM_E_INVALID_PARAMETER; *ppNewInst = NULL; // Create the new instance IWbemClassObject * pClassObj = NULL; sc = pGateway->GetObject(pwcClass,0, NULL, &pClassObj,NULL); if(FAILED(sc)) return sc; sc = pClassObj->SpawnInstance(0, ppNewInst); pClassObj->Release(); if(FAILED(sc)) return sc; VARIANT var; var.vt = VT_BSTR; var.bstrVal = SysAllocString(pwcKeyValue); if(var.bstrVal == NULL) return sc; sc = (*ppNewInst)->Put(pwcKeyName,0,&var,0); VariantClear(&var); return sc; } SCODE CreateTimerEvent(WCHAR * pwcName, long lTimeIntSec, IWbemServices * pGateway) { IWbemClassObject * pNewInst = NULL; SCODE sc = MyCreateInstance(pGateway, L"__IntervalTimerInstruction", L"TimerID", pwcName, &pNewInst); if(sc != S_OK) return sc; VARIANT var; VariantInit(&var); var.vt = VT_I4; var.lVal = lTimeIntSec * 1000; sc = pNewInst->Put(L"IntervalBetweenEvents",0,&var,0); var.vt = VT_BOOL; var.boolVal = VARIANT_FALSE; sc = pNewInst->Put(L"SkipIfPassed",0,&var,0); sc = pGateway->PutInstance(pNewInst, 0, NULL, NULL); return sc; } CRegEvent::CRegEvent(IWbemClassObject * pObj, IWbemServices * pWbem) { m_dwCheckSum = 0xffffffff; // indicates that check sum has never been done // Save a pointer to the core m_bSaveHiveImage = FALSE; m_pLastHiveImage = NULL; if(pWbem) { m_pWbem = pWbem; m_pWbem->AddRef(); } else m_pWbem = NULL; // generate a unique name by creating a new GUID and convert it to string format GUID guid; int iLen; SCODE sc = CoCreateGuid(&guid); if(sc == S_OK) iLen = StringFromGUID2(guid,m_wcGuid,39); else m_wcGuid[0] = 0; // Read the path and possibly value field VARIANT var; VariantInit(&var); sc = pObj->Get(L"Key", 0, &var, NULL, NULL); if(sc == S_OK && var.vt == VT_BSTR && var.bstrVal != NULL) m_sRegPath = var.bstrVal; VariantInit(&var); sc = pObj->Get(L"Value", 0, &var, NULL, NULL); if(sc == S_OK && var.vt == VT_BSTR && var.bstrVal != NULL) m_sRegValue = var.bstrVal; VariantInit(&var); sc = pObj->Get(L"PollingIntervalSec", 0, &var, NULL, NULL); if(sc == S_OK && var.vt == VT_I4) { WCHAR wcQuery[256]; wcscpy(wcQuery, L"select * from __TimerEvent where TimerId = \""); wcscat(wcQuery, m_wcGuid); wcscat(wcQuery, L"\""); m_lTimeIntSec = var.lVal; m_TimerEvent.SetQuery(wcQuery); sc = m_TimerEvent.StoreToWBEM(m_pWbem); sc = CreateTimerEvent(m_wcGuid, m_lTimeIntSec, m_pWbem); } } CRegEvent::~CRegEvent() { if(m_pWbem) m_pWbem->Release(); if(m_pLastHiveImage) delete m_pLastHiveImage; //todo, release the timer objects???? } CRegEventSet::CRegEventSet() { } SCODE CRegEventSet::Initialize(IWbemServices * pWbem) { SCODE sc; m_pWbem = pWbem; if(m_pWbem) { m_pWbem->AddRef(); //fornow, loop through the list of RegEvent instances and create an entry for each IWbemClassObject * pNewInst = NULL; IEnumWbemClassObject FAR* pIEnum = NULL; sc = m_pWbem->CreateInstanceEnum(L"RegEvent", 0, NULL, &pIEnum); while (sc == S_OK) { ULONG uRet; sc = pIEnum->Next(-1, 1,&pNewInst,&uRet); if(sc == S_OK) { CRegEvent * pNewEvent = new CRegEvent(pNewInst,m_pWbem); if(pNewEvent) m_Set.Add(pNewEvent); pNewInst->Release(); } } if(pIEnum) pIEnum->Release(); // fornow, register to get change events for that class. m_Event.SetQuery(L"select * from __InstanceCreationEvent where newinstance.__class = \"regevent\""); sc = m_Event.StoreToWBEM(m_pWbem); } return WBEM_E_INVALID_PARAMETER; } CRegEventSet::~CRegEventSet() { if(m_pWbem) m_pWbem->Release(); m_Set.Empty(); } void CRegEventSet::FindEvent(WCHAR * pwcID) { CRegEvent * pEvent; for(long lEvent = 0; lEvent < m_Set.Size(); lEvent++) { pEvent = (CRegEvent *)m_Set.GetAt(lEvent); if(pEvent && pEvent->IsMatch(pwcID)) pEvent->TimerCheck(); } }