408 lines
9.2 KiB
C++
408 lines
9.2 KiB
C++
/*++
|
|
|
|
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 <impdyn.h>
|
|
#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();
|
|
}
|
|
} |