windows-nt/Source/XPSP1/NT/admin/wmi/wbem/winmgmt/stdprov/regevent.cpp
2020-09-26 16:20:57 +08:00

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();
}
}