|
|
//***************************************************************************
//
// ACTION.CPP
//
// Module: HEALTHMON SERVER AGENT
//
// Purpose: To act as the coordinator of actions. WMI actually provides the
// code and support to carry out the actions (like email). This class
// does the scheduling, and throttling of them.
//
// Copyright (c)1999 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
#include <stdio.h>
#include <tchar.h>
#include "system.h"
#include "action.h"
extern CSystem* g_pSystem; extern HMODULE g_hWbemComnModule; static BYTE LocalSystemSID[] = {1,1,0,0,0,0,0,5,18,0,0,0};
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CAction::CAction() {
MY_OUTPUT(L"ENTER ***** CAction::CAction...", 4);
m_szGUID = NULL; m_szName = NULL; m_szDescription = NULL; m_szTypeGUID = NULL; m_pszStatusGUID = NULL; m_lCurrState = HM_GOOD; m_hmStatusType = HMSTATUS_ACTION; m_bValidLoad = FALSE;
wcscpy(m_szDTTime, m_szDTCurrTime); wcscpy(m_szTime, m_szCurrTime);
MY_OUTPUT(L"EXIT ***** CAction::CAction...", 4); }
CAction::~CAction() { MY_OUTPUT(L"ENTER ***** CAction::~CAction...", 4);
Cleanup(TRUE); if (m_szGUID) { delete [] m_szGUID; m_szGUID = NULL; }
m_bValidLoad = FALSE;
MY_OUTPUT(L"EXIT ***** CAction::~CAction...", 4); }
//
// Load a single Action
//
HRESULT CAction::LoadInstanceFromMOF(IWbemClassObject* pActionConfigInst, BOOL bModifyPass/*FALSE*/) { HRESULT hRetRes = S_OK; TCHAR szTemp[1024]; GUID guid; LPTSTR pszStr; LPTSTR pszTemp; BOOL bRetValue = TRUE; QSTRUCT Q; BSTR Language = NULL; BSTR Query = NULL; HRESULT hRes; ULONG uReturned; IWbemClassObject *pAssocObj = NULL; IEnumWbemClassObject *pEnum = NULL; LPTSTR pszUpper = NULL;
MY_OUTPUT(L"ENTER ***** CAction::LoadInstanceFromMOF...", 4);
m_bValidLoad = TRUE; if (m_szGUID == NULL) { // Get the GUID property
hRetRes = GetStrProperty(pActionConfigInst, L"GUID", &m_szGUID); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) return hRetRes; }
if (bModifyPass==FALSE) { Cleanup(TRUE); hRetRes = CoCreateGuid(&guid); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; m_pszStatusGUID = new TCHAR[100]; MY_ASSERT(m_pszStatusGUID); if (!m_pszStatusGUID) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} StringFromGUID2(guid, m_pszStatusGUID, 100); } else { Cleanup(FALSE); }
// Get the Name. If it is NULL then we use the qualifier
hRetRes = GetStrProperty(pActionConfigInst, L"Name", &m_szName); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
// Get the Description. If it is NULL then we use the qualifier
hRetRes = GetStrProperty(pActionConfigInst, L"Description", &m_szDescription); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
hRetRes = GetBoolProperty(pActionConfigInst, L"Enabled", &m_bEnabled); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
hRetRes = GetUint8Property(pActionConfigInst, L"ActiveDays", &m_iActiveDays); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
// The time format looks as follows "********0600**.******+***"; hh is hours and mm is minutes
// All else is ignored.
hRetRes = GetStrProperty(pActionConfigInst, L"BeginTime", &pszTemp); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; pszStr = wcschr(pszTemp, '.'); if (pszStr) { // Back up to look at the minute
pszStr -= 2; *pszStr = '\0'; pszStr -= 2; m_lBeginMinuteTime= _wtol(pszStr); // Back up to look at the hour
*pszStr = '\0'; pszStr -= 2; m_lBeginHourTime= _wtol(pszStr); } else { m_lBeginMinuteTime= -1; m_lBeginHourTime= -1; } delete [] pszTemp;
hRetRes = GetStrProperty(pActionConfigInst, L"EndTime", &pszTemp); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; pszStr = wcschr(pszTemp, '.'); if (pszStr) { // Back up to look at the minute
pszStr -= 2; *pszStr = '\0'; pszStr -= 2; m_lEndMinuteTime= _wtol(pszStr); // Back up to look at the hour
*pszStr = '\0'; pszStr -= 2; m_lEndHourTime= _wtol(pszStr); } else { m_lEndMinuteTime= -1; m_lEndHourTime= -1; } delete [] pszTemp;
hRetRes = GetStrProperty(pActionConfigInst, L"TypeGUID", &m_szTypeGUID); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
//
// Need to create a temporary consumer for each configuration object associated to
// this Action. These are the real events that are happening to cause the actions
// to fire.
//
if (!bModifyPass) { //
// Loop through all Associations to this Action
//
Language = SysAllocString(L"WQL"); MY_ASSERT(Language); if (!Language) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} wcscpy(szTemp, L"REFERENCES OF {MicrosoftHM_ActionConfiguration.GUID=\""); lstrcat(szTemp, m_szGUID); lstrcat(szTemp, L"\"} WHERE ResultClass=MicrosoftHM_ConfigurationActionAssociation"); Query = SysAllocString(szTemp); MY_ASSERT(Query); if (!Query) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
// Initialize IEnumWbemClassObject pointer
pEnum = NULL;
// Issue query
hRetRes = g_pIWbemServices->ExecQuery(Language, Query, WBEM_FLAG_FORWARD_ONLY, 0, &pEnum);
SysFreeString(Query); Query = NULL; SysFreeString(Language); Language = NULL;
if (hRetRes != 0) { MY_HRESASSERT(hRetRes); } else { // Retrieve objects in result set
while (TRUE) { pAssocObj = NULL; uReturned = 0;
hRes = pEnum->Next(0, 1, &pAssocObj, &uReturned); if (uReturned == 0) { break; }
//
// Next, setup the temporary consumer for the event(s) that the actions is
// triggered by, so we can do throttling.
//
hRetRes = GetStrProperty(pAssocObj, L"ParentPath", &Q.szUserConfigPath); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; Q.pBase = g_pSystem->GetParentPointerFromPath(Q.szUserConfigPath); if (!Q.pBase || (Q.pBase && Q.pBase->m_hmStatusType==HMSTATUS_THRESHOLD)) { if (Q.szUserConfigPath) delete [] Q.szUserConfigPath; pAssocObj->Release(); pAssocObj = NULL; continue; }
// hRetRes = GetUint32Property(pAssocObj, L"ThrottleTime", &Q.lThrottleTime);
// MY_HRESASSERT(hRetRes);
Q.lThrottleTime = 0;
hRetRes = GetUint32Property(pAssocObj, L"ReminderTime", &Q.lReminderTime); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
hRetRes = GetStrProperty(pAssocObj, L"Query", &Q.szQuery); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
//
// Look for "...State=0 OR State=9"
//
pszUpper = _wcsdup(Q.szQuery); MY_ASSERT(pszUpper); if (!pszUpper) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} _wcsupr(pszUpper); Q.ulTriggerStates = 0; pszStr = wcsstr(pszUpper, L"STATE"); if (pszStr) { if (wcschr(pszStr, '0')) { Q.ulTriggerStates |= 1<<0; } if (wcschr(pszStr, '4')) { Q.ulTriggerStates |= 1<<4; } if (wcschr(pszStr, '5')) { Q.ulTriggerStates |= 1<<5; } if (wcschr(pszStr, '8')) { Q.ulTriggerStates |= 1<<8; } if (wcschr(pszStr, '9')) { Q.ulTriggerStates |= 1<<9; } } free(pszUpper); pszUpper = NULL;
hRetRes = GetStrProperty(pAssocObj, L"__PATH", &Q.szConfigActionAssocPath); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
hRetRes = GetStrProperty(pAssocObj, L"ChildPath", &Q.szChildPath); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
if (m_bEnabled) { //
// Setup the event query. We need to be able to identify each individual
// use of this Action! Pass in this unique property.
//
Q.pTempSink = new CTempConsumer(Q.szConfigActionAssocPath); MY_ASSERT(Q.pTempSink); if (!Q.pTempSink) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} Q.hRes = 0;
Language = SysAllocString(L"WQL"); MY_ASSERT(Language); if (!Language) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} Query = SysAllocString(Q.szQuery); MY_ASSERT(Query); if (!Query) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} hRes = 1; if (g_pIWbemServices != NULL) { hRes = g_pIWbemServices->ExecNotificationQueryAsync( Language, Query, 0, NULL, Q.pTempSink); Q.hRes = hRes; }
SysFreeString(Query); Query = NULL; SysFreeString(Language); Language = NULL; } else { Q.pTempSink = 0; Q.hRes = 0; }
Q.startTick = 0; Q.reminderTimeTick = 0; Q.bThrottleOn = FALSE; MY_ASSERT(Q.pBase); m_qList.push_back(Q);
// Release it.
pAssocObj->Release(); pAssocObj = NULL; }
// All done
pEnum->Release(); pEnum = NULL; } }
m_bValidLoad = TRUE; MY_OUTPUT(L"EXIT ***** CAction::LoadInstanceFromMOF...", 4); return S_OK;
error: MY_ASSERT(FALSE); if (Query) SysFreeString(Query); if (Language) SysFreeString(Language); if (pszUpper) free(pszUpper); if (pAssocObj) pAssocObj->Release(); if (pEnum) pEnum->Release(); Cleanup(TRUE); m_bValidLoad = FALSE; return hRetRes; }
//
// In the case of Actions, they don't actually have an interval to them, but they
// get called here for each action every second (the base agent interval).
//
BOOL CAction::OnAgentInterval(void) { HRESULT hRetRes = S_OK; HRESULT hRes; IWbemClassObject* pInstance = NULL; HRESULT hRes2; IWbemClassObject* pInstance2 = NULL; DWORD currTick; BOOL bTimeOK; int i, iSize; QSTRUCT *pQ; BSTR Language = NULL; BSTR Query = NULL; GUID guid;
if (m_bValidLoad == FALSE) return FALSE;
//
// Make sure that we are in a valid time to run.
//
bTimeOK = checkTime();
// Remember that the DISABLED state overrides SCHEDULEDOUT.
if ((m_bEnabled==FALSE && m_lCurrState==HM_DISABLED) || (bTimeOK==FALSE && m_lCurrState==HM_SCHEDULEDOUT && m_bEnabled)) { return TRUE; } else if (m_bEnabled==FALSE && m_lCurrState!=HM_DISABLED || bTimeOK==FALSE && m_lCurrState!=HM_SCHEDULEDOUT) { //
// Going into Scheduled Outage OR DISABLED.
// What if we are going from ScheduledOut to Disabled?
// Or from Disabled to ScheduledOut?
// Possible transitions:
// GOOD -> Disabled
// GOOD -> ScheduledOut
// Disabled -> ScheduledOut
// ScheduledOut -> Disabled
//
iSize = m_qList.size(); for (i=0; i<iSize; i++) { MY_ASSERT(i<m_qList.size()); pQ = &m_qList[i];
if (pQ->pTempSink) { g_pIWbemServices->CancelAsyncCall((IWbemObjectSink*)pQ->pTempSink); pQ->pTempSink->Release(); pQ->pTempSink = NULL; } pQ->hRes = 0; } if (m_bEnabled==FALSE) { m_lCurrState = HM_DISABLED; FireEvent(-1, NULL, HMRES_ACTION_DISABLE); } else { m_lCurrState = HM_SCHEDULEDOUT; FireEvent(-1, NULL, HMRES_ACTION_OUTAGE); } return TRUE; } else if (m_lCurrState==HM_DISABLED || m_lCurrState==HM_SCHEDULEDOUT) { //
// Comming out of Scheduled Outage OR DISABLED.
// Might be going from ScheduledOut/Disabled to Disabled,
// or disabled to ScheduledOut.
//
m_lCurrState = HM_GOOD; FireEvent(-1, NULL, HMRES_ACTION_ENABLE);
// Re-setup the event consumer
iSize = m_qList.size(); for (i=0; i<iSize; i++) { MY_ASSERT(i<m_qList.size()); pQ = &m_qList[i]; pQ->pTempSink = new CTempConsumer(pQ->szConfigActionAssocPath); MY_ASSERT(pQ->pTempSink); if (!pQ->pTempSink) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} pQ->hRes = 0;
Language = SysAllocString(L"WQL"); MY_ASSERT(Language); if (!Language) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} Query = SysAllocString(pQ->szQuery); MY_ASSERT(Query); if (!Query) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} hRes = 1; if (g_pIWbemServices != NULL) { hRes = g_pIWbemServices->ExecNotificationQueryAsync( Language, Query, 0, NULL, pQ->pTempSink); pQ->hRes = hRes; }
SysFreeString(Query); Query = NULL; SysFreeString(Language); Language = NULL;
if (hRes != 0) { MY_HRESASSERT(hRes); } else { pQ->startTick = 0; pQ->reminderTimeTick = 0; pQ->bThrottleOn = FALSE; } } }
//
// Determine if the throttle time needs to come into play.
//
currTick = GetTickCount(); iSize = m_qList.size(); for (i=0; i<iSize; i++) { MY_ASSERT(i<m_qList.size()); pQ = &m_qList[i];
if (0<pQ->lThrottleTime) { // May have not gone off yet
if ((0<pQ->startTick)) { // Check to see if alloted time has passed
if ((pQ->lThrottleTime*1000) < (currTick-pQ->startTick)) { pQ->bThrottleOn = FALSE; pQ->startTick = 0; } else { pQ->bThrottleOn = TRUE; } } } }
// Try and prevent problems where we may have had a query fail to register
iSize = m_qList.size(); for (i=0; i<iSize; i++) { MY_ASSERT(i<m_qList.size()); pQ = &m_qList[i];
if (pQ->hRes!=0) { Language = SysAllocString(L"WQL"); MY_ASSERT(Language); if (!Language) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} Query = SysAllocString(pQ->szQuery); MY_ASSERT(Query); if (!Query) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} hRes = 1; if (g_pIWbemServices != NULL && pQ->pTempSink && pQ->hRes!=0) { hRes = g_pIWbemServices->ExecNotificationQueryAsync( Language, Query, 0, NULL, pQ->pTempSink); MY_HRESASSERT(hRes); pQ->hRes = hRes; }
SysFreeString(Query); Query = NULL; SysFreeString(Language); Language = NULL; if (hRes == 0) { pQ->startTick = 0; pQ->reminderTimeTick = 0; pQ->bThrottleOn = FALSE; } } }
//
// Determine if we need to fire off a reminder event.
// We first need to be in the violated state.
//
iSize = m_qList.size(); for (i=0; i<iSize; i++) { MY_ASSERT(i<m_qList.size()); pQ = &m_qList[i]; MY_ASSERT(pQ->pBase); if ((g_pActionEventSink || g_pActionTriggerEventSink) && pQ->pBase && pQ->lReminderTime!=0 && pQ->reminderTimeTick==pQ->lReminderTime) { // Fire event to console, and another one to the event consumer
wcscpy(m_szDTTime, m_szDTCurrTime); wcscpy(m_szTime, m_szCurrTime); m_lCurrState = HM_GOOD; if (m_pszStatusGUID) { delete [] m_pszStatusGUID; m_pszStatusGUID = NULL; } hRetRes = CoCreateGuid(&guid); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; m_pszStatusGUID = new TCHAR[100]; MY_ASSERT(m_pszStatusGUID); if (!m_pszStatusGUID) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} StringFromGUID2(guid, m_pszStatusGUID, 100); hRes = GetHMActionStatus(&pInstance, NULL, L"MicrosoftHM_ActionStatusEvent", HMRES_ACTION_FIRED); hRes2 = GetHMActionStatus(&pInstance2, NULL, L"MicrosoftHM_ActionTriggerEvent", HMRES_ACTION_FIRED); if (SUCCEEDED(hRes) && SUCCEEDED(hRes2)) { pQ->pBase->SendReminderActionIfStateIsSame(g_pActionEventSink, g_pActionTriggerEventSink, pInstance, pInstance2, pQ->ulTriggerStates); } else { MY_OUTPUT(L"failed to get instance!", 1); MY_HRESASSERT(hRes); MY_HRESASSERT(hRes2); } if (pInstance) { pInstance->Release(); pInstance = NULL; } if (pInstance2) { pInstance2->Release(); pInstance2 = NULL; } pQ->reminderTimeTick = 0; } if (pQ->lReminderTime!=0 && pQ->reminderTimeTick==pQ->lReminderTime) pQ->reminderTimeTick = 0; pQ->reminderTimeTick++; }
return TRUE;
error: MY_ASSERT(FALSE); if (Query) SysFreeString(Query); if (Language) SysFreeString(Language); m_bValidLoad = FALSE; Cleanup(TRUE); return FALSE; }
//
// Here we get an event, and since we act as the gatekeeper to pass on the final event
// that the EventConsumer will get fired from, we decide if we need to throttle.
// To send on the event, we embed the incomming event into ours.
//
BOOL CAction::HandleTempEvent(LPTSTR szConfigActionAssocPath, IWbemClassObject* pObj) { BOOL bRetValue = TRUE; IWbemClassObject* pInstance = NULL; HRESULT hRes; BOOL bFound; QSTRUCT *pQ; int i, iSize;
MY_OUTPUT(L"ENTER ***** CAction::HandleTempEvent...", 2);
if (m_bValidLoad == FALSE) return FALSE;
m_lCurrState = HM_GOOD; //
// See if it is one of these
//
bFound = FALSE; iSize = m_qList.size(); for (i=0; i<iSize; i++) { MY_ASSERT(i<m_qList.size()); pQ = &m_qList[i]; if (!_wcsicmp(pQ->szConfigActionAssocPath, szConfigActionAssocPath)) { bFound = TRUE; break; } }
//
// We capture the time that this happened, so that we can throttle in the
// OnAgentInterval call we can disable the action from happening (until time again).
//
if (bFound==FALSE) { return FALSE; }
if (pQ->startTick == 0) { pQ->startTick = GetTickCount(); }
MY_OUTPUT2(L"HandleTempEvent GUID=%s", m_szGUID, 4); MY_OUTPUT2(L"szConfigActionAssocPath=%s", szConfigActionAssocPath, 4);
if (pQ->bThrottleOn == FALSE) { if (pQ->lReminderTime != 0) { pQ->reminderTimeTick = 0; }
// Don't send if no-one is listening!
if (g_pActionTriggerEventSink != NULL) { wcscpy(m_szDTTime, m_szDTCurrTime); wcscpy(m_szTime, m_szCurrTime); FireEvent(-1, NULL, HMRES_ACTION_FIRED); hRes = GetHMActionStatus(&pInstance, pObj, L"MicrosoftHM_ActionTriggerEvent", HMRES_ACTION_FIRED); if (SUCCEEDED(hRes)) { if (g_pActionTriggerEventSink) { hRes = g_pActionTriggerEventSink->Indicate(1, &pInstance); //WBEM_E_SERVER_TOO_BUSY is Ok. Wbem will deliver.
if (FAILED(hRes) && hRes != WBEM_E_SERVER_TOO_BUSY) { bRetValue = FALSE; MY_OUTPUT(L"Failed on Indicate!", 4); } } pInstance->Release(); pInstance = NULL; } else { MY_OUTPUT(L"failed to get instance!", 1); MY_HRESASSERT(hRes); } } }
MY_OUTPUT(L"EXIT ***** CAction::HandleTempEvent...", 2); return bRetValue; }
//oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
HRESULT CAction::FindAndModAction(BSTR szGUID, IWbemClassObject* pObj) { HRESULT hRetRes = S_OK;
//
// Is this us we are looking for?
//
if (!_wcsicmp(m_szGUID, szGUID)) { hRetRes = LoadInstanceFromMOF(pObj, TRUE); return hRetRes; }
return WBEM_S_DIFFERENT; }
BOOL CAction::FindAndCreateActionAssociation(BSTR szGUID, IWbemClassObject* pObj) { HRESULT hRes; HRESULT hRetRes = S_OK; int i, iSize; QSTRUCT *pQ; QSTRUCT Q; BOOL bFound; BOOL bTimeOK; LPTSTR pszStr; BSTR Language = NULL; BSTR Query = NULL; LPTSTR pszConfigActionAssocPath = NULL; LPTSTR pszUpper = NULL;
if (m_bValidLoad == FALSE) return FALSE;
//
// Is this the Action we are looking for?
//
if (!_wcsicmp(m_szGUID, szGUID)) { hRetRes = GetStrProperty(pObj, L"__PATH", &pszConfigActionAssocPath); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
MY_OUTPUT2(L"Association to Action GUID=%s", szGUID, 4); MY_OUTPUT2(L"To PATH=%s", pszConfigActionAssocPath, 4); // Now check to see if this association already exists
bFound = FALSE; iSize = m_qList.size(); for (i=0; i<iSize; i++) { MY_ASSERT(i<m_qList.size()); pQ = &m_qList[i]; if (!_wcsicmp(pQ->szConfigActionAssocPath, pszConfigActionAssocPath)) { bFound = TRUE; break; } }
delete [] pszConfigActionAssocPath; pszConfigActionAssocPath = NULL;
if (bFound == FALSE) { MY_OUTPUT(L"OK: Not found yet.", 4); Q.szUserConfigPath = NULL; Q.szQuery = NULL; Q.szConfigActionAssocPath = NULL; Q.szChildPath = NULL; //
// Next, setup the temporary consumer for the event(s) that the actions is
// triggered by, so we can do throttling.
//
hRetRes = GetStrProperty(pObj, L"ParentPath", &Q.szUserConfigPath); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; Q.pBase = g_pSystem->GetParentPointerFromPath(Q.szUserConfigPath); if (!Q.pBase || (Q.pBase && Q.pBase->m_hmStatusType==HMSTATUS_THRESHOLD)) { if (Q.szUserConfigPath) { delete [] Q.szUserConfigPath; } } else { // hRetRes = GetUint32Property(pObj, L"ThrottleTime", &Q.lThrottleTime);
// MY_HRESASSERT(hRetRes);
Q.lThrottleTime = 0;
hRetRes = GetUint32Property(pObj, L"ReminderTime", &Q.lReminderTime); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
hRetRes = GetStrProperty(pObj, L"Query", &Q.szQuery); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
//
// Look for "...State=0 OR State=9"
//
pszUpper = _wcsdup(Q.szQuery); MY_ASSERT(pszUpper); if (!pszUpper) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} _wcsupr(pszUpper); Q.ulTriggerStates = 0; pszStr = wcsstr(pszUpper, L"STATE"); if (pszStr) { if (wcschr(pszStr, '0')) { Q.ulTriggerStates |= 1<<0; } if (wcschr(pszStr, '4')) { Q.ulTriggerStates |= 1<<4; } if (wcschr(pszStr, '5')) { Q.ulTriggerStates |= 1<<5; } if (wcschr(pszStr, '8')) { Q.ulTriggerStates |= 1<<8; } if (wcschr(pszStr, '9')) { Q.ulTriggerStates |= 1<<9; } } free(pszUpper); pszUpper = NULL;
hRetRes = GetStrProperty(pObj, L"__PATH", &Q.szConfigActionAssocPath); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
hRetRes = GetStrProperty(pObj, L"ChildPath", &Q.szChildPath); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
TCHAR msgbuf[1024]; wsprintf(msgbuf, L"ACTIONASSOCIATION: AGUID=%s parentpath=%s childpath=%s", szGUID, Q.szUserConfigPath, Q.szChildPath); MY_OUTPUT(msgbuf, 4); //
// Setup the event query. We need to be able to identify each individual
// use of this Action! Pass in this unique property.
//
bTimeOK = checkTime(); if (m_bEnabled==TRUE && bTimeOK==TRUE) { Q.pTempSink = new CTempConsumer(Q.szConfigActionAssocPath); MY_ASSERT(Q.pTempSink); if (!Q.pTempSink) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
Language = SysAllocString(L"WQL"); MY_ASSERT(Language); if (!Language) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} Query = SysAllocString(Q.szQuery); MY_ASSERT(Query); if (!Query) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} hRes = 1; Q.hRes = 0; if (g_pIWbemServices != NULL) { hRes = g_pIWbemServices->ExecNotificationQueryAsync( Language, Query, 0, NULL, Q.pTempSink); Q.hRes = hRes; }
SysFreeString(Query); Query = NULL; SysFreeString(Language); Language = NULL;
Q.startTick = 0; Q.reminderTimeTick = 0; Q.bThrottleOn = FALSE; MY_ASSERT(Q.pBase); m_qList.push_back(Q); } else { Q.pTempSink = NULL; Q.startTick = 0; Q.reminderTimeTick = 0; Q.bThrottleOn = FALSE; MY_ASSERT(Q.pBase); m_qList.push_back(Q); } } return TRUE; } else { MY_OUTPUT(L"WHY?: Already There.", 4); return FALSE; }
} else { return FALSE; }
error: MY_ASSERT(FALSE); if (pszUpper) free(pszUpper); if (pszConfigActionAssocPath) delete [] pszConfigActionAssocPath; if (Q.szUserConfigPath) delete [] Q.szUserConfigPath; if (Q.szQuery) delete [] Q.szQuery; if (Q.szConfigActionAssocPath) delete [] Q.szConfigActionAssocPath; if (Q.szChildPath) delete [] Q.szChildPath; if (Query) SysFreeString(Query); if (Language) SysFreeString(Language); return TRUE; }
BOOL CAction::FindAndModActionAssociation(BSTR szGUID, IWbemClassObject* pObj) { HRESULT hRes; HRESULT hRetRes; int i, iSize; QSTRUCT *pQ; LPTSTR pszTemp; BOOL bFound; BSTR Language = NULL; BSTR Query = NULL; BOOL bSameQuery = FALSE; BOOL bTimeOK; LPTSTR pszUpper = NULL; LPTSTR pszStr;
if (m_bValidLoad == FALSE) return FALSE;
//
// Is this the Action we are looking for?
//
if (!_wcsicmp(m_szGUID, szGUID)) { hRetRes = GetStrProperty(pObj, L"__PATH", &pszTemp); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
// Now check to see if this association already exists
bFound = FALSE; iSize = m_qList.size(); for (i=0; i<iSize; i++) { MY_ASSERT(i<m_qList.size()); pQ = &m_qList[i]; if (!_wcsicmp(pQ->szConfigActionAssocPath, pszTemp)) { bFound = TRUE; break; } }
delete [] pszTemp; pszTemp = NULL;
if (bFound == TRUE) { MY_OUTPUT2(L"MODACTIONASSOCIATION: AGUID=%s", szGUID, 4); MY_OUTPUT2(L"parentpath=%s", pQ->szUserConfigPath, 4); MY_OUTPUT2(L"childpath=%s", pQ->szChildPath, 4);
if (pQ->szQuery) { hRetRes = GetStrProperty(pObj, L"Query", &pszTemp); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
if (!wcscmp(pQ->szQuery, pszTemp)) { bSameQuery = TRUE; pQ->reminderTimeTick = 0; }
// Check to See if we have to register a new query.
if (!bSameQuery) { delete [] pQ->szQuery; pQ->szQuery = NULL; hRetRes = GetStrProperty(pObj, L"Query", &pQ->szQuery); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
//
// Look for "...State=0 OR State=9"
//
pszUpper = _wcsdup(pQ->szQuery); MY_ASSERT(pszUpper); if (!pszUpper) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} _wcsupr(pszUpper); pQ->ulTriggerStates = 0; pszStr = wcsstr(pszUpper, L"STATE"); if (pszStr) { if (wcschr(pszStr, '0')) { pQ->ulTriggerStates |= 1<<0; } if (wcschr(pszStr, '4')) { pQ->ulTriggerStates |= 1<<4; } if (wcschr(pszStr, '5')) { pQ->ulTriggerStates |= 1<<5; } if (wcschr(pszStr, '8')) { pQ->ulTriggerStates |= 1<<8; } if (wcschr(pszStr, '9')) { pQ->ulTriggerStates |= 1<<9; } } free(pszUpper); pszUpper = NULL; } delete [] pszTemp; pszTemp = NULL; }
if (pQ->szUserConfigPath) { delete [] pQ->szUserConfigPath; pQ->szUserConfigPath = NULL; }
if (pQ->szChildPath) { delete [] pQ->szChildPath; pQ->szChildPath = NULL; }
if (pQ->pTempSink && !bSameQuery) { g_pIWbemServices->CancelAsyncCall((IWbemObjectSink*)pQ->pTempSink); pQ->pTempSink->Release(); pQ->pTempSink = NULL; }
//
// Next, setup the temporary consumer for the event(s) that the actions is
// triggered by, so we can do throttling.
//
// hRetRes = GetUint32Property(pObj, L"ThrottleTime", &pQ->lThrottleTime);
// MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
pQ->lThrottleTime = 0;
hRetRes = GetUint32Property(pObj, L"ReminderTime", &pQ->lReminderTime); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
hRetRes = GetStrProperty(pObj, L"ParentPath", &pQ->szUserConfigPath); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
hRetRes = GetStrProperty(pObj, L"ChildPath", &pQ->szChildPath); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
//
// Setup the event query. We need to be able to identify each individual
// use of this Action! Pass in this unique property.
//
bTimeOK = checkTime(); if (!bSameQuery && m_bEnabled==TRUE && bTimeOK==TRUE) { pQ->pTempSink = new CTempConsumer(pQ->szConfigActionAssocPath); MY_ASSERT(pQ->pTempSink); if (!pQ->pTempSink) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
Language = SysAllocString(L"WQL"); MY_ASSERT(Language); if (!Language) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} Query = SysAllocString(pQ->szQuery); MY_ASSERT(Query); if (!Query) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} hRes = 1; pQ->hRes = 0; if (g_pIWbemServices != NULL) { hRes = g_pIWbemServices->ExecNotificationQueryAsync( Language, Query, 0, NULL, //XXXm_pContext,
pQ->pTempSink); pQ->hRes = hRes; }
SysFreeString(Query); Query = NULL; SysFreeString(Language); Language = NULL;
if (hRes != 0) { MY_HRESASSERT(hRes); } else { pQ->startTick = 0; pQ->reminderTimeTick = 0; pQ->bThrottleOn = FALSE; } } }
return TRUE; } else { return FALSE; }
error: MY_ASSERT(FALSE); if (pszTemp) free(pszTemp); if (Query) SysFreeString(Query); if (Language) SysFreeString(Language); Cleanup(TRUE); m_bValidLoad = FALSE; return TRUE; }
BOOL CAction::DeleteConfigActionAssoc(LPTSTR pszConfigGUID, LPTSTR pszActionGUID) { TCHAR *pszEventFilter = NULL; BSTR instName = NULL; BOOL bFound = FALSE; TCHAR szGUID[1024]; LPTSTR pStr; LPTSTR pStr2; int i, iSize; QSTRUCT *pQ; QLIST::iterator iaQ; IWbemClassObject* pInst = NULL; HRESULT hRes; HRESULT hRetRes = S_OK;
if (m_bValidLoad == FALSE) return FALSE;
//
// First verify that we have the proper action identified.
//
if (_wcsicmp(m_szGUID, pszActionGUID)) { return FALSE; }
TCHAR msgbuf[1024]; wsprintf(msgbuf, L"DELETECONFIGACTIONASSOCIATION: CONFIGGUID=%s AGUID=%s", pszConfigGUID, pszActionGUID); MY_OUTPUT(msgbuf, 4);
//
// Verify the Configuration instance associated to this Action
// We are not deleting the ActionConfig, or the __EventConsumer,
//__EventFilter, __FilterToConsumerBinding Just usage of it - ConfigActionAssoc
//
iSize = m_qList.size(); iaQ = m_qList.begin(); for (i=0; i<iSize; i++, iaQ++) { MY_ASSERT(i<m_qList.size()); pQ = &m_qList[i]; wcscpy(szGUID, pQ->szUserConfigPath); pStr = wcschr(szGUID, '\"'); if (pStr) { pStr++; pStr2 = wcschr(pStr, '\"'); if (pStr2) { *pStr2 = '\0'; } } else { pStr = wcschr(szGUID, '='); if (pStr) { pStr++; if (*pStr == '@') { pStr2 = pStr; pStr2++; *pStr2 = '\0'; } } }
if (pStr) { if (!_wcsicmp(pStr, pszConfigGUID)) { hRetRes = GetWbemObjectInst(&g_pIWbemServices, pQ->szConfigActionAssocPath, NULL, &pInst); if (!pInst) { MY_HRESASSERT(hRetRes); return FALSE; } hRetRes = GetStrProperty(pInst, L"EventFilter", &pszEventFilter); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; pInst->Release(); pInst = NULL;
delete [] pszEventFilter; pszEventFilter = NULL;
//
// Delete MicrosoftHM_ConfigurationActionAssociation.
//
instName = SysAllocString(pQ->szConfigActionAssocPath); MY_ASSERT(instName); if (!instName) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} if ((hRes = g_pIWbemServices->DeleteInstance(instName, 0L, NULL, NULL)) != S_OK) { MY_OUTPUT(L"ENTER ***** ConfigurationActionAssoc Delete failed...", 4); } SysFreeString(instName); instName = NULL;
if (pQ->szQuery) { delete [] pQ->szQuery; pQ->szQuery = NULL; }
if (pQ->szConfigActionAssocPath) { delete [] pQ->szConfigActionAssocPath; pQ->szConfigActionAssocPath = NULL; }
if (pQ->szUserConfigPath) { delete [] pQ->szUserConfigPath; pQ->szUserConfigPath = NULL; }
if (pQ->szChildPath) { delete [] pQ->szChildPath; pQ->szChildPath = NULL; }
if (pQ->pTempSink) { g_pIWbemServices->CancelAsyncCall((IWbemObjectSink*)pQ->pTempSink); pQ->pTempSink->Release(); pQ->pTempSink = NULL; }
m_qList.erase(iaQ); bFound = TRUE; break; } } }
if (bFound == TRUE) { }
return bFound;
error: MY_ASSERT(FALSE); if (pszEventFilter) delete [] pszEventFilter; if (instName) SysFreeString(instName); if (pInst) pInst->Release(); return TRUE; }
BOOL CAction::DeleteEFAndFTCB(void) { TCHAR szTemp[1024]; TCHAR *pszEventConsumer = NULL; BSTR instName = NULL; LPTSTR pStr; LPTSTR pStr2; IWbemClassObject* pInst = NULL; HRESULT hRes; HRESULT hRetRes = S_OK;
//
// Delete the __EventFilter
//
wcscpy(szTemp, L"__EventFilter.Name=\""); lstrcat(szTemp, m_szGUID); lstrcat(szTemp, L"\""); instName = SysAllocString(szTemp); MY_ASSERT(instName); if (!instName) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} if ((hRes = g_pIWbemServices->DeleteInstance(instName, 0L, NULL, NULL)) != S_OK) { MY_OUTPUT(L"ENTER ***** __EventFilter Delete failed...", 4); } SysFreeString(instName); instName = NULL;
//
// Delete the __FilterToConsumerBinding. Looks as follows -
//__FilterToConsumerBinding.
//Consumer="CommandLineEventConsumer.Name=\"{944E9251-6C58-11d3-90E9-006097919914}\"",
//Filter="__EventFilter.Name=\"{944E9251-6C58-11d3-90E9-006097919914}\""
//
wcscpy(szTemp, L"MicrosoftHM_ActionConfiguration.GUID=\""); lstrcat(szTemp, m_szGUID); lstrcat(szTemp, L"\""); hRetRes = GetWbemObjectInst(&g_pIWbemServices, szTemp, NULL, &pInst); if (!pInst) { return FALSE; } hRetRes = GetStrProperty(pInst, L"EventConsumer", &pszEventConsumer); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; pInst->Release(); pInst = NULL;
// We need to format the strings a bit, need extra backslashes in there
pStr = wcschr(pszEventConsumer, ':'); MY_ASSERT(pStr); if (!pStr) goto Badstring; pStr++; pStr2 = wcschr(pStr, '\"'); MY_ASSERT(pStr2); if (!pStr2) goto Badstring; *pStr2 = '\0'; wcscpy(szTemp, L"__FilterToConsumerBinding.Consumer=\""); lstrcat(szTemp, L"\\\\\\\\.\\\\root\\\\cimv2\\\\MicrosoftHealthMonitor:"); lstrcat(szTemp, pStr); lstrcat(szTemp, L"\\\""); pStr = pStr2; pStr++; pStr2 = wcschr(pStr, '\"'); MY_ASSERT(pStr2); if (!pStr2) goto Badstring; *pStr2 = '\0'; lstrcat(szTemp, pStr); lstrcat(szTemp, L"\\\"\",Filter=\"\\\\\\\\.\\\\root\\\\cimv2\\\\MicrosoftHealthMonitor:");
lstrcat(szTemp, L"__EventFilter.Name=\\\""); lstrcat(szTemp, m_szGUID); lstrcat(szTemp, L"\\\"\"");
instName = SysAllocString(szTemp); MY_ASSERT(instName); if (!instName) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} if ((hRes = g_pIWbemServices->DeleteInstance(instName, 0L, NULL, NULL)) != S_OK) { MY_OUTPUT(L"ENTER ***** __FilterToConsumerBinding Delete failed...", 4); } SysFreeString(instName); instName = NULL; goto Goodstring;
Badstring: MY_OUTPUT(L"ENTER ***** Bad FilterToConsumer string", 4); Goodstring: delete [] pszEventConsumer; pszEventConsumer = NULL;
return TRUE;
error: MY_ASSERT(FALSE); if (pszEventConsumer) delete [] pszEventConsumer; if (instName) SysFreeString(instName); if (pInst) pInst->Release(); return FALSE; }
//
// Delete the Action Configuration instance and everything that goes with it.
// Need to delete the ActionConfiguration, __EventConsumer, all ConfigActionAssoc's,
// __EventFilter's, __FilterToConsumerBinding's
//
BOOL CAction::DeleteAConfig(void) { HRESULT hRes; QLIST qList; QSTRUCT Q; QSTRUCT *pQ; int i, iSize; TCHAR szTemp[1024]; TCHAR *pszEventConsumer = NULL; BSTR instName = NULL; LPTSTR pStr1; LPTSTR pStr2; LPTSTR pStr3; LPTSTR pStr4; BSTR Language = NULL; BSTR Query = NULL; IEnumWbemClassObject *pEnum; IWbemClassObject *pAssocObj = NULL; ULONG uReturned; IWbemClassObject* pInst = NULL; HRESULT hRetRes = S_OK;
MY_OUTPUT(L"ENTER ***** CAction::DeleteAConfig...", 1);
TCHAR msgbuf[1024]; wsprintf(msgbuf, L"DELETE: AGUID=%s", m_szGUID); MY_OUTPUT(msgbuf, 4); //
// Get rid of all associations to the action.
// Make use of other function, loop through all associations
//
Language = SysAllocString(L"WQL"); MY_ASSERT(Language); if (!Language) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} wcscpy(szTemp, L"REFERENCES OF {MicrosoftHM_ActionConfiguration.GUID=\""); lstrcat(szTemp, m_szGUID); lstrcat(szTemp, L"\"} WHERE ResultClass=MicrosoftHM_ConfigurationActionAssociation"); Query = SysAllocString(szTemp); MY_ASSERT(Query); if (!Query) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
// Initialize IEnumWbemClassObject pointer
pEnum = 0;
// Issue query
hRes = g_pIWbemServices->ExecQuery(Language, Query, WBEM_FLAG_FORWARD_ONLY, 0, &pEnum);
SysFreeString(Query); Query = NULL; SysFreeString(Language); Language = NULL;
if (hRes != 0) { MY_OUTPUT(L"ENTER ***** DeleteAConfig failed...", 4); return FALSE; }
// Retrieve objects in result set
while (TRUE) { pAssocObj = NULL; uReturned = 0;
hRes = pEnum->Next(0, 1, &pAssocObj, &uReturned);
if (uReturned == 0) { break; }
hRetRes = GetStrProperty(pAssocObj, L"ParentPath", &Q.szUserConfigPath); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
hRetRes = GetStrProperty(pAssocObj, L"ChildPath", &Q.szChildPath); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
qList.push_back(Q);
// Release it.
pAssocObj->Release(); pAssocObj = NULL; } // All done
pEnum->Release(); pEnum = NULL;
iSize = qList.size(); for (i=0; i<iSize; i++) { MY_ASSERT(i<qList.size()); pQ = &qList[i];
pStr1 = wcschr(pQ->szUserConfigPath, '\"'); if (pStr1) { pStr1++; pStr2 = wcschr(pStr1, '\"'); if (pStr2) { *pStr2 = '\0'; } } pStr3 = wcschr(pQ->szChildPath, '\"'); if (pStr3) { pStr3++; pStr4 = wcschr(pStr3, '\"'); if (pStr4) { *pStr4 = '\0'; } }
DeleteConfigActionAssoc(pStr1, pStr3);
if (pQ->szUserConfigPath) delete [] pQ->szUserConfigPath;
if (pQ->szChildPath) delete [] pQ->szChildPath; } qList.clear();
//
// Finally we can get rid of the __EventFilter and __FilterToConsumerBinding.
//
DeleteEFAndFTCB();
//
// Finally we can get rid of the actual ActionConfiguration instance, and the __EventConsumer.
//
wcscpy(szTemp, L"MicrosoftHM_ActionConfiguration.GUID=\""); lstrcat(szTemp, m_szGUID); lstrcat(szTemp, L"\""); hRetRes = GetWbemObjectInst(&g_pIWbemServices, szTemp, NULL, &pInst); if (!pInst) { MY_HRESASSERT(hRetRes); return FALSE; } hRetRes = GetStrProperty(pInst, L"EventConsumer", &pszEventConsumer); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; pInst->Release(); pInst = NULL;
instName = SysAllocString(szTemp); MY_ASSERT(instName); if (!instName) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} if ((hRes = g_pIWbemServices->DeleteInstance(instName, 0L, NULL, NULL)) != S_OK) { MY_OUTPUT(L"ENTER ***** ActionConfiguration Delete failed...", 4); } SysFreeString(instName); instName = NULL;
instName = SysAllocString(pszEventConsumer); MY_ASSERT(instName); if (!instName) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} if ((hRes = g_pIWbemServices->DeleteInstance(instName, 0L, NULL, NULL)) != S_OK) { MY_OUTPUT(L"ENTER ***** EventConsumer Delete failed...", 4); } SysFreeString(instName); instName = NULL; delete [] pszEventConsumer; pszEventConsumer = NULL;
MY_OUTPUT(L"EXIT ***** CAction::DeleteAConfig...", 1); return TRUE;
error: MY_ASSERT(FALSE); if (pszEventConsumer) delete [] pszEventConsumer; if (instName) SysFreeString(instName); if (Query) SysFreeString(Query); if (Language) SysFreeString(Language); if (pAssocObj) pAssocObj->Release(); if (pEnum) pEnum->Release(); if (pInst) pInst->Release(); return FALSE; }
// This is only for event sending related to going into a scheduled outage time,
// or the disabling of the action.
BOOL CAction::FireEvent(long lErrorCode, LPTSTR pszErrorDescription, int iResString) { HRESULT hRetRes = S_OK; GUID guid; HRESULT hRes; BOOL bRetValue = TRUE; IWbemClassObject* pInstance = NULL; LPVOID lpMsgBuf = NULL; TCHAR szTemp[1024] = L""; TCHAR buf[256] = L"";
MY_OUTPUT(L"ENTER ***** CAction::FireEvent...", 2);
// Don't send if no-one is listening!
if (g_pActionEventSink == NULL) { return bRetValue; }
if (iResString != HMRES_ACTION_LOADFAIL) { if (m_pszStatusGUID) { delete [] m_pszStatusGUID; m_pszStatusGUID = NULL; } hRetRes = CoCreateGuid(&guid); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; m_pszStatusGUID = new TCHAR[100]; MY_ASSERT(m_pszStatusGUID); if (!m_pszStatusGUID) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} StringFromGUID2(guid, m_pszStatusGUID, 100);
wcscpy(m_szDTTime, m_szDTCurrTime); wcscpy(m_szTime, m_szCurrTime); }
hRes = GetHMActionStatus(&pInstance, NULL, L"MicrosoftHM_ActionStatusEvent", iResString); if (SUCCEEDED(hRes)) { // Add in the extra error info if available
if (lErrorCode != -1) { if (g_hResLib == NULL || !LoadString(g_hResLib, iResString, szTemp, 1024)) { MY_ASSERT(FALSE); wcscpy(szTemp, L"Could not locate resource string."); } wsprintf(buf, L" 0x%08x : ", lErrorCode); wcsncat(szTemp, buf, 1023-wcslen(szTemp)); szTemp[1023] = '\0'; if (g_hWbemComnModule) { FormatMessage(FORMAT_MESSAGE_MAX_WIDTH_MASK|FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_HMODULE, g_hWbemComnModule, lErrorCode, 0, (LPTSTR) &lpMsgBuf, 0, NULL); if (lpMsgBuf) { wcsncat(szTemp, (LPCTSTR)lpMsgBuf, 1023-wcslen(szTemp)); szTemp[1023] = '\0'; LocalFree(lpMsgBuf); wcsncat(szTemp, L". ", 1023-wcslen(szTemp)); szTemp[1023] = '\0'; } } if (pszErrorDescription) { wcsncat(szTemp, pszErrorDescription, 1023-wcslen(szTemp)); szTemp[1023] = '\0'; } PutStrProperty(pInstance, L"Message", szTemp); }
MY_OUTPUT2(L"EVENT: Action State Change=%d", m_lCurrState, 4); if (g_pActionEventSink) { hRes = g_pActionEventSink->Indicate(1, &pInstance); //WBEM_E_SERVER_TOO_BUSY is Ok. Wbem will deliver.
if (FAILED(hRes) && hRes != WBEM_E_SERVER_TOO_BUSY) { MY_HRESASSERT(hRes); bRetValue = FALSE; MY_OUTPUT(L"Failed on Indicate!", 4); } }
pInstance->Release(); pInstance = NULL; } else { MY_HRESASSERT(hRes); MY_OUTPUT(L"failed to get instance!", 1); }
MY_OUTPUT(L"EXIT ***** CAction::FireEvent...", 2); return bRetValue;
error: MY_ASSERT(FALSE); if (pInstance) pInstance->Release(); return FALSE; }
HRESULT CAction::GetHMActionStatus(IWbemClassObject** ppInstance, IWbemClassObject* pObj, LPTSTR pszClass, int iResString) { BOOL bRetValue = TRUE; IWbemClassObject* pClass = NULL; TCHAR szTemp[1024]; BSTR bsString = NULL; HRESULT hRes; HRESULT hRetRes; VARIANT v; long lState; DWORD dwNameLen = MAX_COMPUTERNAME_LENGTH + 2; TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 2]; VariantInit(&v);
MY_OUTPUT(L"ENTER ***** CAction::GetHMActionStatus...", 1);
bsString = SysAllocString(pszClass); MY_ASSERT(bsString); if (!bsString) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} hRes = g_pIWbemServices->GetObject(bsString, 0L, NULL, &pClass, NULL); SysFreeString(bsString); bsString = NULL;
if (FAILED(hRes)) { MY_HRESASSERT(hRes); return hRes; }
hRes = pClass->SpawnInstance(0, ppInstance); pClass->Release(); pClass = NULL;
if (FAILED(hRes)) { MY_HRESASSERT(hRes); return hRes; }
if (iResString != HMRES_ACTION_LOADFAIL) { PutStrProperty(*ppInstance, L"GUID", m_szGUID); PutStrProperty(*ppInstance, L"Name", m_szName);
if (GetComputerName(szComputerName, &dwNameLen)) { PutStrProperty(*ppInstance, L"SystemName", szComputerName); } else { PutStrProperty(*ppInstance, L"SystemName", L"LocalMachine"); }
if (pObj) { hRetRes = GetUint32Property(pObj, L"State", &lState); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; PutUint32Property(*ppInstance, L"State", lState); } else { PutUint32Property(*ppInstance, L"State", m_lCurrState); }
if (pObj) { VariantInit(&v); V_VT(&v) = VT_UNKNOWN; V_UNKNOWN(&v) = (IUnknown*)pObj; (V_UNKNOWN(&v))->AddRef(); hRes = (*ppInstance)->Put(L"EmbeddedStatusEvent", 0L, &v, 0L); VariantClear(&v); MY_HRESASSERT(hRes); }
PutStrProperty(*ppInstance, L"TimeGeneratedGMT", m_szDTCurrTime); PutStrProperty(*ppInstance, L"LocalTimeFormatted", m_szCurrTime); PutStrProperty(*ppInstance, L"StatusGUID", m_pszStatusGUID); } else { PutUint32Property(*ppInstance, L"State", HM_CRITICAL); PutStrProperty(*ppInstance, L"Name", L"..."); }
if (g_hResLib == NULL || !LoadString(g_hResLib, iResString, szTemp, 1024)) { MY_ASSERT(FALSE); wcscpy(szTemp, L"Could not locate resource string."); } PutStrProperty(*ppInstance, L"Message", szTemp);
MY_OUTPUT(L"EXIT ***** CAction::GetHMActionStatus...", 1); return hRes;
error: MY_ASSERT(FALSE); if (bsString) SysFreeString(bsString); if (pClass) pClass->Release(); return hRetRes; }
LPTSTR CAction::GetGUID(void) { return m_szGUID; }
HRESULT CAction::SendHMActionStatusInstances(IWbemObjectSink* pSink) { HRESULT hRes = S_OK; IWbemClassObject* pObj = NULL; int iResString;
MY_OUTPUT(L"ENTER ***** CAction::SendHMActionStatusInstances...", 2);
if (m_bValidLoad == FALSE) return WBEM_E_INVALID_OBJECT;
if (pSink == NULL) { MY_OUTPUT(L"Instances-Invalid Sink", 1); return WBEM_E_INVALID_PARAMETER; }
if (m_lCurrState==HM_SCHEDULEDOUT) { iResString = HMRES_ACTION_OUTAGE; } else if (m_lCurrState==HM_DISABLED) { iResString = HMRES_ACTION_DISABLE; } else if (m_lCurrState==HM_CRITICAL) { iResString = HMRES_ACTION_FAILED; } else { iResString = HMRES_ACTION_ENABLE; } // Provide Instance
hRes = GetHMActionStatus(&pObj, NULL, L"MicrosoftHM_ActionStatus", iResString); if (SUCCEEDED(hRes)) { hRes = pSink->Indicate(1, &pObj);
if (FAILED(hRes) && hRes!=WBEM_E_SERVER_TOO_BUSY && hRes!=WBEM_E_CALL_CANCELLED && hRes!=WBEM_E_TRANSPORT_FAILURE) { MY_HRESASSERT(hRes); MY_OUTPUT(L"SendHMSystemStatusInstances-failed to send status!", 1); }
pObj->Release(); pObj = NULL; } else { MY_HRESASSERT(hRes); MY_OUTPUT(L":SendHMSystemStatusInstances-failed to get instance!", 1); }
MY_OUTPUT(L"EXIT ***** CAction::SendHMSystemStatusInstances...", 2); return hRes; }
// For a single GetObject
HRESULT CAction::SendHMActionStatusInstance(IWbemObjectSink* pSink, LPTSTR pszGUID) { MY_OUTPUT(L"ENTER ***** CAction::SendHMActionStatusInstance...", 1);
//
// Is this the one we are looking for?
//
if (!_wcsicmp(m_szGUID, pszGUID)) { if (m_bValidLoad == FALSE) return WBEM_E_INVALID_OBJECT;
SendHMActionStatusInstances(pSink); return S_OK; }
MY_OUTPUT(L"EXIT ***** CAction::SendHMActionStatusInstance...", 1); return WBEM_S_DIFFERENT; }
BOOL CAction::checkTime(void) { BOOL bTimeOK; SYSTEMTIME st; // system time
//
// Make sure that we are in a valid time to run.
// NULL (-1) means run all the time.
//
bTimeOK = FALSE; if (m_bEnabled==TRUE) { GetLocalTime(&st);
bTimeOK = FALSE; // Check the Day of the Week
if (!(m_iActiveDays&(1<<st.wDayOfWeek))) { } else if (m_lBeginHourTime<0 || m_lEndHourTime<0) { bTimeOK = TRUE; } else if (m_lBeginHourTime==m_lEndHourTime && m_lBeginMinuteTime==m_lEndMinuteTime) { // Check the Hours of operation
// First see if we are doing an inclusive time tests, or an exclusive time test
// Case where the time is exactly equal, and that means run this once per day
if (st.wHour==m_lBeginHourTime && st.wMinute==m_lBeginMinuteTime) { if (st.wSecond <= HM_POLLING_INTERVAL) { bTimeOK = TRUE; } } } else if ((m_lBeginHourTime < m_lEndHourTime) || ((m_lBeginHourTime==m_lEndHourTime) && m_lBeginMinuteTime < m_lEndMinuteTime)) { // Inclusive case
if ((m_lBeginHourTime < st.wHour) || ((m_lBeginHourTime == st.wHour) && m_lBeginMinuteTime <= st.wMinute)) { if ((st.wHour < m_lEndHourTime) || ((st.wHour == m_lEndHourTime) && st.wMinute < m_lEndMinuteTime)) { bTimeOK = TRUE; } } } else { // Exclusive case
if ((m_lEndHourTime > st.wHour) || ((m_lEndHourTime == st.wHour) && m_lEndMinuteTime > st.wMinute)) { bTimeOK = TRUE; } else if ((st.wHour > m_lBeginHourTime) || ((st.wHour == m_lBeginHourTime) && st.wMinute >= m_lBeginMinuteTime)) { bTimeOK = TRUE; } } }
return bTimeOK; }
CBase *CAction::FindImediateChildByName(LPTSTR pszName) { MY_ASSERT(FALSE);
return NULL; }
BOOL CAction::GetNextChildName(LPTSTR pszChildName, LPTSTR pszOutName) { MY_ASSERT(FALSE);
return NULL; }
CBase *CAction::FindPointerFromName(LPTSTR pszName) { MY_ASSERT(FALSE);
return NULL; }
#ifdef SAVE
BOOL CAction::ModifyAssocForMove(CBase *pNewParentBase) { MY_ASSERT(FALSE);
return TRUE; } #endif
BOOL CAction::ReceiveNewChildForMove(CBase *pBase) { MY_ASSERT(FALSE);
return FALSE; }
BOOL CAction::DeleteChildFromList(LPTSTR pszGUID) { MY_ASSERT(FALSE);
return FALSE; }
BOOL CAction::SendReminderActionIfStateIsSame(IWbemObjectSink* pActionEventSink, IWbemObjectSink* pActionTriggerEventSink, IWbemClassObject* pActionInstance, IWbemClassObject* pActionTriggerInstance, unsigned long ulTriggerStates) { MY_ASSERT(FALSE);
return FALSE; }
BOOL CAction::HandleTempErrorEvent(BSTR szGUID, long lErrorCode, LPTSTR pszErrorDescription) { if (m_bValidLoad == FALSE) return FALSE;
//
// Is this us we are looking for?
//
if (!_wcsicmp(m_szGUID, szGUID)) { m_lCurrState = HM_CRITICAL; FireEvent(lErrorCode, pszErrorDescription, HMRES_ACTION_FAILED); return TRUE; }
return FALSE; }
BOOL CAction::Cleanup(BOOL bClearAll) { int i, iSize; QSTRUCT *pQ;
if (m_szName) { delete [] m_szName; m_szName = NULL; } if (m_szDescription) { delete [] m_szDescription; m_szDescription = NULL; } if (m_szTypeGUID) { delete [] m_szTypeGUID; m_szTypeGUID = NULL; }
if (bClearAll) { if (m_pszStatusGUID) { delete [] m_pszStatusGUID; m_pszStatusGUID = NULL; }
iSize = m_qList.size(); for (i=0; i<iSize; i++) { MY_ASSERT(i<m_qList.size()); pQ = &m_qList[i]; if (pQ->szQuery) delete [] pQ->szQuery;
if (pQ->szConfigActionAssocPath) delete [] pQ->szConfigActionAssocPath;
if (pQ->szUserConfigPath) delete [] pQ->szUserConfigPath;
if (pQ->szChildPath) delete [] pQ->szChildPath;
if (pQ->pTempSink) { g_pIWbemServices->CancelAsyncCall((IWbemObjectSink*)pQ->pTempSink); pQ->pTempSink->Release(); pQ->pTempSink = NULL; } } m_qList.clear(); }
return TRUE; }
HRESULT CAction::RemapAction(void) { HRESULT hRetRes = S_OK; QLIST qList; TCHAR szTemp[1024]; LPTSTR pStr2; TCHAR *pszEventConsumer = NULL; LPTSTR pStr; IWbemClassObject* pInst = NULL;
MY_OUTPUT(L"ENTER ***** CAction::RemapAction...", 1);
wcscpy(szTemp, L"MicrosoftHM_ActionConfiguration.GUID=\""); lstrcat(szTemp, m_szGUID); lstrcat(szTemp, L"\""); hRetRes = GetWbemObjectInst(&g_pIWbemServices, szTemp, NULL, &pInst); if (!pInst) { MY_HRESASSERT(hRetRes); return FALSE; } hRetRes = GetStrProperty(pInst, L"EventConsumer", &pszEventConsumer); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; pInst->Release(); pInst = NULL;
//
// __EventConsumer.
//
hRetRes = GetWbemObjectInst(&g_pIWbemServices, pszEventConsumer, NULL, &pInst); if (!pInst) { MY_HRESASSERT(hRetRes); return FALSE; } hRetRes = RemapOneAction(pInst); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; pInst->Release(); pInst = NULL;
//
// __EventFilter.
//
wcscpy(szTemp, L"__EventFilter.Name=\""); lstrcat(szTemp, m_szGUID); lstrcat(szTemp, L"\""); hRetRes = GetWbemObjectInst(&g_pIWbemServices, szTemp, NULL, &pInst); if (!pInst) { MY_HRESASSERT(hRetRes); return FALSE; } hRetRes = RemapOneAction(pInst); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; pInst->Release(); pInst = NULL;
//
// __FilterToConsumerBinding
//
// We need to format the strings a bit, need extra backslashes in there
pStr = wcschr(pszEventConsumer, ':'); MY_ASSERT(pStr); if (!pStr) goto Badstring; pStr++; pStr2 = wcschr(pStr, '\"'); MY_ASSERT(pStr2); if (!pStr2) goto Badstring; *pStr2 = '\0'; wcscpy(szTemp, L"__FilterToConsumerBinding.Consumer=\""); lstrcat(szTemp, L"\\\\\\\\.\\\\root\\\\cimv2\\\\MicrosoftHealthMonitor:"); lstrcat(szTemp, pStr); lstrcat(szTemp, L"\\\""); pStr = pStr2; pStr++; pStr2 = wcschr(pStr, '\"'); MY_ASSERT(pStr2); if (!pStr2) goto Badstring; *pStr2 = '\0'; lstrcat(szTemp, pStr); lstrcat(szTemp, L"\\\"\",Filter=\"\\\\\\\\.\\\\root\\\\cimv2\\\\MicrosoftHealthMonitor:");
lstrcat(szTemp, L"__EventFilter.Name=\\\""); lstrcat(szTemp, m_szGUID); lstrcat(szTemp, L"\\\"\"");
hRetRes = GetWbemObjectInst(&g_pIWbemServices, szTemp, NULL, &pInst); if (!pInst) { MY_HRESASSERT(hRetRes); return FALSE; } hRetRes = RemapOneAction(pInst); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; pInst->Release(); pInst = NULL; goto Goodstring;
Badstring: MY_OUTPUT(L"ENTER ***** Bad FilterToConsumer string", 4); Goodstring: delete [] pszEventConsumer; pszEventConsumer = NULL;
MY_OUTPUT(L"EXIT ***** CAction::RemapAction...", 1); return TRUE;
error: MY_ASSERT(FALSE); if (pszEventConsumer) delete [] pszEventConsumer; if (pInst) pInst->Release(); return FALSE; }
HRESULT CAction::RemapOneAction(IWbemClassObject* pObj) { HANDLE hToken = NULL; HRESULT hRetRes = S_OK; IWbemCallResult *pResult = 0; SAFEARRAY* psa = NULL; VARIANT var; CIMTYPE vtType; long lBound, uBound; BOOL bObjIsLocalSystem; BOOL bSuccess; SID_IDENTIFIER_AUTHORITY ntauth = SECURITY_NT_AUTHORITY; DWORD dwLengthNeeded; void* psid = 0; PTOKEN_USER pUserInfo = NULL;
VariantInit(&var);
// Need to verify that we're in fact running under the LocalSystem SID!
// otherwise we'd end up in an infinite loop! Need an assert to check that
// the current thread is running as LocalSystem.
bSuccess = OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken); MY_ASSERT(bSuccess); if (!bSuccess) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
// Call GetTokenInformation to get the buffer size.
dwLengthNeeded = 0; bSuccess = GetTokenInformation(hToken, TokenUser, NULL, dwLengthNeeded, &dwLengthNeeded);
// Allocate the buffer.
pUserInfo = (PTOKEN_USER) GlobalAlloc(GPTR, dwLengthNeeded); MY_ASSERT(pUserInfo); if (!pUserInfo) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
// Call GetTokenInformation again to get the group information.
bSuccess = GetTokenInformation(hToken, TokenUser, pUserInfo, dwLengthNeeded, &dwLengthNeeded); MY_ASSERT(bSuccess); if (!bSuccess) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
bSuccess = AllocateAndInitializeSid(&ntauth, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &psid); MY_ASSERT(bSuccess); if (!bSuccess) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
// Verify that winmgmt is running under LocalSystem. If not we don't do anything.
if (EqualSid(pUserInfo->User.Sid, psid)) { // get the CreatorSID of this instance
hRetRes = pObj->Get(L"CreatorSID", 0, &var, &vtType, NULL); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; if (vtType != (CIM_UINT8 | CIM_FLAG_ARRAY)) { hRetRes = WBEM_E_FAILED; goto error; }
// make sure it's the right size
psa = var.parray; if (::SafeArrayGetElemsize(psa) != 1) { hRetRes = WBEM_E_FAILED; goto error; }
hRetRes = ::SafeArrayGetLBound(psa, 1, &lBound); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; hRetRes = ::SafeArrayGetUBound(psa, 1, &uBound); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; if (lBound !=0) { hRetRes = WBEM_E_FAILED; goto error; }
// now see if this is LocalSystem by comparing to
// the hardcoded LocalSystem SID
bObjIsLocalSystem = false; if (uBound == (sizeof LocalSystemSID)-1 ) { LPVOID lpCreatorSID = NULL; hRetRes = ::SafeArrayAccessData(psa, &lpCreatorSID); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; if (memcmp (lpCreatorSID, LocalSystemSID, sizeof LocalSystemSID) == 0) { bObjIsLocalSystem = true; } hRetRes = ::SafeArrayUnaccessData(psa); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; }
// If it's not a LocalSystem SID, to replace it with a LocalSytem SID,
// we need to just store the instance in WMI-- WMI will automatically
// replace the SID that's there with our SID-- LocalSystem.
//
if (bObjIsLocalSystem == FALSE) { hRetRes = g_pIWbemServices->PutInstance(pObj, WBEM_FLAG_UPDATE_ONLY, NULL, &pResult); // MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
} VariantClear(&var); }
CloseHandle(hToken); FreeSid(psid); if (pUserInfo) GlobalFree(pUserInfo); return S_OK;
error: MY_OUTPUT2(L"11 0x%08x\n",hRetRes,5); MY_ASSERT(FALSE); VariantClear(&var); CloseHandle(hToken); FreeSid(psid); if (pUserInfo) GlobalFree(pUserInfo); return hRetRes; }
HRESULT CAction::CheckForBadLoad(void) { HRESULT hRetRes = S_OK; IWbemClassObject* pObj = NULL; TCHAR szTemp[1024];
if (m_bValidLoad == FALSE) { wcscpy(szTemp, L"MicrosoftHM_ActionConfiguration.GUID=\""); lstrcat(szTemp, m_szGUID); lstrcat(szTemp, L"\""); hRetRes = GetWbemObjectInst(&g_pIWbemServices, szTemp, NULL, &pObj); if (!pObj) { MY_HRESASSERT(hRetRes); return S_FALSE; } hRetRes = LoadInstanceFromMOF(pObj, FALSE); // Here is where we can try and send out a generic SOS if the load failed each time!!!
if (hRetRes != S_OK) { FireEvent(-1, NULL, HMRES_ACTION_LOADFAIL); } MY_HRESASSERT(hRetRes); pObj->Release(); pObj = NULL; return hRetRes; }
return S_OK; }
|