|
|
///////////////////////////////////////////////////////////////////////////////
//
// Rule.cpp
//
///////////////////////////////////////////////////////////////////////////////
#include <pch.hxx>
#include "rule.h"
#include "strconst.h"
#include "goptions.h"
#include "criteria.h"
#include "actions.h"
#include "ruleutil.h"
///////////////////////////////////////////////////////////////////////////////
//
// HrCreateRule
//
// This creates a rule.
//
// ppIRule - pointer to return the rule
//
// Returns: S_OK, on success
// E_OUTOFMEMORY, if can't create the Rule object
//
///////////////////////////////////////////////////////////////////////////////
HRESULT HrCreateRule(IOERule ** ppIRule) { COERule * pRule = NULL; HRESULT hr = S_OK;
// Check the incoming params
if (NULL == ppIRule) { hr = E_INVALIDARG; goto exit; }
// Initialize outgoing params
*ppIRule = NULL;
// Create the rules manager object
pRule = new COERule; if (NULL == pRule) { hr = E_OUTOFMEMORY; goto exit; }
// Get the rules manager interface
hr = pRule->QueryInterface(IID_IOERule, (void **) ppIRule); if (FAILED(hr)) { goto exit; }
pRule = NULL; // Set the proper return value
hr = S_OK; exit: if (NULL != pRule) { delete pRule; } return hr; }
COERule::COERule() { m_cRef = 0; m_dwState = RULE_STATE_NULL; m_pszName = NULL; m_pICrit = NULL; m_pIAct = NULL; m_dwVersion = 0; }
COERule::~COERule() { ULONG ulIndex = 0; AssertSz(m_cRef == 0, "Somebody still has a hold of us!!"); SafeMemFree(m_pszName); SafeRelease(m_pICrit); SafeRelease(m_pIAct); }
STDMETHODIMP_(ULONG) COERule::AddRef() { return ::InterlockedIncrement(&m_cRef); }
STDMETHODIMP_(ULONG) COERule::Release() { LONG cRef = 0;
cRef = ::InterlockedDecrement(&m_cRef); if (0 == cRef) { delete this; return cRef; }
return cRef; }
STDMETHODIMP COERule::QueryInterface(REFIID riid, void ** ppvObject) { HRESULT hr = S_OK;
// Check the incoming params
if (NULL == ppvObject) { hr = E_INVALIDARG; goto exit; }
// Initialize outgoing param
*ppvObject = NULL; if ((riid == IID_IUnknown) || (riid == IID_IOERule)) { *ppvObject = static_cast<IOERule *>(this); } else if ((riid == IID_IPersistStream) || (riid == IID_IPersist)) { *ppvObject = static_cast<IPersistStream *>(this); } else { hr = E_NOINTERFACE; goto exit; }
reinterpret_cast<IUnknown *>(*ppvObject)->AddRef();
hr = S_OK; exit: return hr; }
STDMETHODIMP COERule::Reset(void) { HRESULT hr = S_OK; LPSTR pszKeyPath = NULL; LPCSTR pszKeyStart = NULL;
// Release the criteria
SafeRelease(m_pICrit);
// Release the actions
SafeRelease(m_pIAct);
// Free up the rule name
SafeMemFree(m_pszName); // Set the current state
m_dwState |= RULE_STATE_INIT;
// Clear the dirty bit
m_dwState &= ~RULE_STATE_DIRTY;
// Set the return value
hr = S_OK; return hr; }
STDMETHODIMP COERule::GetState(DWORD * pdwState) { HRESULT hr = S_OK; ULONG ulIndex = 0;
// Check incoming params
if (NULL == pdwState) { hr = E_INVALIDARG; goto exit; }
// If we're not enabled
if ((0 != (m_dwState & RULE_STATE_DISABLED)) || (0 != (m_dwState & RULE_STATE_INVALID))) { *pdwState = RULE_STATE_NULL; } else { *pdwState = m_dwState; } // Set the proper return value
hr = S_OK; exit: return hr; }
STDMETHODIMP COERule::Validate(DWORD dwFlags) { HRESULT hr = S_OK; BOOL fValid = FALSE;
// If we don't have a criteria or actions object then we fail
if ((NULL == m_pICrit) || (NULL == m_pIAct)) { hr = E_FAIL; goto exit; }
// Validate the criteria
hr = m_pICrit->Validate(dwFlags); if (FAILED(hr)) { goto exit; }
fValid = TRUE; if (S_OK != hr) { fValid = FALSE; } // Validate the actions
hr = m_pIAct->Validate(dwFlags); if (FAILED(hr)) { goto exit; }
if (S_OK != hr) { fValid = FALSE; } // If the rule is invalid, make sure we disable it
if (FALSE == fValid) { m_dwState |= RULE_STATE_INVALID; } else { m_dwState &= ~RULE_STATE_INVALID; } // Set the proper return value
hr = fValid ? S_OK : S_FALSE; exit: return hr; }
STDMETHODIMP COERule::GetProp(RULE_PROP prop, DWORD dwFlags, PROPVARIANT * pvarResult) { HRESULT hr = S_OK; LPSTR pszName = NULL; CRIT_ITEM * pCrit = NULL; ACT_ITEM * pAct = NULL; ULONG cItem = 0;
// Check incoming params
if (NULL == pvarResult) { hr = E_INVALIDARG; goto exit; }
// Initialize outgoing params
ZeroMemory(pvarResult, sizeof(*pvarResult)); switch(prop) { case RULE_PROP_NAME: if (NULL == m_pszName) { pszName = PszDupA(""); } else { pszName = PszDupA(m_pszName); } pvarResult->vt = VT_LPSTR; pvarResult->pszVal = pszName; pszName = NULL; break;
case RULE_PROP_DISABLED: pvarResult->vt = VT_BOOL; pvarResult->boolVal = !!(m_dwState & RULE_STATE_DISABLED); break; case RULE_PROP_VERSION: pvarResult->vt = VT_UI4; pvarResult->ulVal = m_dwVersion; break; case RULE_PROP_CRITERIA: if (NULL == m_pICrit) { cItem = 0; pCrit = NULL; } else { hr = m_pICrit->GetCriteria(0, &pCrit, &cItem); if (FAILED(hr)) { goto exit; } } pvarResult->vt = VT_BLOB; pvarResult->blob.cbSize = cItem * sizeof(CRIT_ITEM); pvarResult->blob.pBlobData = (BYTE *) pCrit; pCrit = NULL; break; case RULE_PROP_ACTIONS: if (NULL == m_pIAct) { cItem = 0; pAct = NULL; } else { hr = m_pIAct->GetActions(0, &pAct, &cItem); if (FAILED(hr)) { goto exit; } } pvarResult->vt = VT_BLOB; pvarResult->blob.cbSize = cItem * sizeof(ACT_ITEM); pvarResult->blob.pBlobData = (BYTE *) pAct; pAct = NULL; break; default: hr = E_INVALIDARG; goto exit; } // Set the return value
hr = S_OK; exit: SafeMemFree(pszName); RuleUtil_HrFreeCriteriaItem(pCrit, cItem); SafeMemFree(pCrit); RuleUtil_HrFreeActionsItem(pAct, cItem); SafeMemFree(pAct); return hr; }
STDMETHODIMP COERule::SetProp(RULE_PROP prop, DWORD dwFlags, PROPVARIANT * pvarResult) { HRESULT hr = S_OK; LPSTR pszName = NULL; DWORD dwState = 0; ULONG cItems = 0;
// Check incoming params
if (NULL == pvarResult) { hr = E_INVALIDARG; goto exit; }
switch(prop) { case RULE_PROP_NAME: if ((VT_LPSTR != pvarResult->vt) || (NULL == pvarResult->pszVal)) { hr = E_INVALIDARG; goto exit; } // Create a new copy
pszName = PszDupA(pvarResult->pszVal); if (NULL == pszName) { hr = E_OUTOFMEMORY; goto exit; } // Free up any old value
SafeMemFree(m_pszName); // Set the new value
m_pszName = pszName; pszName = NULL; break;
case RULE_PROP_DISABLED: if (VT_BOOL != pvarResult->vt) { hr = E_INVALIDARG; goto exit; } // Set the new value
if (FALSE != !!(pvarResult->boolVal)) { m_dwState |= RULE_STATE_DISABLED; } else { Assert(0 == (m_dwState & RULE_STATE_INVALID)); m_dwState &= ~RULE_STATE_DISABLED; } break;
case RULE_PROP_VERSION: if (VT_UI4 != pvarResult->vt) { hr = E_INVALIDARG; goto exit; } // Set the new value
m_dwVersion = pvarResult->ulVal; break; case RULE_PROP_CRITERIA: if ((VT_BLOB != pvarResult->vt) || (0 == pvarResult->blob.cbSize) || (NULL == pvarResult->blob.pBlobData)) { hr = E_INVALIDARG; goto exit; }
if (NULL == m_pICrit) { hr = HrCreateCriteria(&m_pICrit); if (FAILED(hr)) { goto exit; } } cItems = pvarResult->blob.cbSize / sizeof(CRIT_ITEM); Assert(cItems * sizeof(CRIT_ITEM) == pvarResult->blob.cbSize); hr = m_pICrit->SetCriteria(0, (CRIT_ITEM *) pvarResult->blob.pBlobData, cItems); if (FAILED(hr)) { goto exit; }
hr = m_pICrit->GetState(&dwState); if (FAILED(hr)) { goto exit; }
m_dwState = (m_dwState & ~CRIT_STATE_MASK) | (dwState & CRIT_STATE_MASK); break; case RULE_PROP_ACTIONS: if ((VT_BLOB != pvarResult->vt) || (0 == pvarResult->blob.cbSize) || (NULL == pvarResult->blob.pBlobData)) { hr = E_INVALIDARG; goto exit; } if (NULL == m_pIAct) { hr = HrCreateActions(&m_pIAct); if (FAILED(hr)) { goto exit; } } cItems = pvarResult->blob.cbSize / sizeof(ACT_ITEM); Assert(cItems * sizeof(ACT_ITEM) == pvarResult->blob.cbSize); hr = m_pIAct->SetActions(0, (ACT_ITEM *) pvarResult->blob.pBlobData, cItems); if (FAILED(hr)) { goto exit; } hr = m_pIAct->GetState(&dwState); if (FAILED(hr)) { goto exit; }
m_dwState = (m_dwState & ~ACT_STATE_MASK) | (dwState & ACT_STATE_MASK); break; default: hr = E_INVALIDARG; goto exit; }
// Mark the rule as dirty
m_dwState |= RULE_STATE_DIRTY; // Set the return value
hr = S_OK; exit: SafeMemFree(pszName); return hr; }
STDMETHODIMP COERule::Evaluate(LPCSTR pszAcct, MESSAGEINFO * pMsgInfo, IMessageFolder * pFolder, IMimePropertySet * pIMPropSet, IMimeMessage * pIMMsg, ULONG cbMsgSize, ACT_ITEM ** ppActions, ULONG * pcActions) { HRESULT hr = S_OK; ACT_ITEM * pAct = NULL; ULONG cAct = 0; // Check incoming variables
if (((NULL == pMsgInfo) && (NULL == pIMPropSet)) || (0 == cbMsgSize) || (NULL == ppActions) || (NULL == pcActions)) { hr = E_INVALIDARG; goto exit; }
// Set outgoing params to default
*ppActions = NULL; *pcActions = 0;
// If we don't have a criteria or actions object then we fail
if ((NULL == m_pICrit) || (NULL == m_pIAct)) { hr = S_FALSE; goto exit; }
// If we ain't valid then we can just bail
if (0 != (m_dwState & RULE_STATE_INVALID)) { hr = S_FALSE; goto exit; } // Do we match??
hr = m_pICrit->MatchMessage(pszAcct, pMsgInfo, pFolder, pIMPropSet, pIMMsg, cbMsgSize); if (FAILED(hr)) { goto exit; }
// If we didn't match then just return
if (S_FALSE == hr) { goto exit; }
// Grab the actions and return them to the caller
hr = m_pIAct->GetActions(0, &pAct, &cAct); if (FAILED(hr)) { goto exit; }
// Set the outgoing parameters
*ppActions = pAct; pAct = NULL; *pcActions = cAct; // Set proper return value
hr = S_OK; exit: RuleUtil_HrFreeActionsItem(pAct, cAct); SafeMemFree(pAct); return hr; }
STDMETHODIMP COERule::LoadReg(LPCSTR pszRegPath) { HRESULT hr = S_OK; LONG lErr = 0; HKEY hkeyRoot = NULL; ULONG cbData = 0; ULONG cbRead = 0; DWORD dwData = 0; LPSTR pszName = NULL; BOOL fDisabled = FALSE; IOECriteria * pICriteria = NULL; IOEActions * pIActions = NULL; LPSTR pszRegPathNew = NULL; ULONG cchRegPath = 0; DWORD dwState = 0; // Check incoming param
if (NULL == pszRegPath) { hr = E_INVALIDARG; goto exit; }
// Should we fail if we're already loaded?
AssertSz(0 == (m_dwState & RULE_STATE_LOADED), "We're already loaded!!!");
// Open the reg key from the path
lErr = AthUserOpenKey(pszRegPath, KEY_ALL_ACCESS, &hkeyRoot); if (ERROR_SUCCESS != lErr) { hr = E_FAIL; goto exit; }
// Get the rule name
hr = RuleUtil_HrGetRegValue(hkeyRoot, c_szRuleName, NULL, (BYTE **) &pszName, NULL); if (FAILED(hr)) { SafeMemFree(pszName); }
// Get the enabled state
cbData = sizeof(dwData); lErr = RegQueryValueEx(hkeyRoot, c_szRuleEnabled, 0, NULL, (BYTE *) &dwData, &cbData); if (ERROR_SUCCESS != lErr) { hr = E_FAIL; goto exit; } Assert(cbData == sizeof(dwData)); fDisabled = ! (BOOL) dwData;
// Get the version of the rule
cbData = sizeof(dwData); lErr = RegQueryValueEx(hkeyRoot, c_szRulesVersion, 0, NULL, (BYTE *) &dwData, &cbData); if ((ERROR_SUCCESS != lErr) && (ERROR_FILE_NOT_FOUND != lErr)) { hr = E_FAIL; goto exit; }
if (ERROR_FILE_NOT_FOUND == lErr) { dwData = 0; lErr = RegSetValueEx(hkeyRoot, c_szRulesVersion, 0, REG_DWORD, (CONST BYTE *) &dwData, sizeof(dwData)); if (ERROR_SUCCESS != lErr) { hr = E_FAIL; goto exit; } }
m_dwVersion = dwData; // Allocate space to hold the new reg path
cchRegPath = lstrlen(pszRegPath); Assert(lstrlen(c_szRuleCriteria) >= lstrlen(c_szRuleActions)); DWORD cchSize = (cchRegPath + lstrlen(c_szRuleCriteria) + 2); if (FAILED(HrAlloc((void **) &pszRegPathNew, cchSize))) { goto exit; }
// Build reg path to criteria
StrCpyN(pszRegPathNew, pszRegPath, cchSize); if ('\\' != pszRegPath[cchRegPath]) { StrCatBuff(pszRegPathNew, g_szBackSlash, cchSize); cchRegPath++; }
StrCatBuff(pszRegPathNew, c_szRuleCriteria, cchSize); // Create a new criteria object
hr = HrCreateCriteria(&pICriteria); if (FAILED(hr)) { goto exit; } // Get the criteria
hr = pICriteria->LoadReg(pszRegPathNew); if (FAILED(hr)) { goto exit; }
// Get the state of the criteria
hr = pICriteria->GetState(&dwState); if (FAILED(hr)) { goto exit; }
m_dwState = (m_dwState & ~CRIT_STATE_MASK) | (dwState & CRIT_STATE_MASK); // Build reg path to actions
StrCpyN(pszRegPathNew + cchRegPath, c_szRuleActions, (cchSize - cchRegPath));
// Create a new actions object
hr = HrCreateActions(&pIActions); if (FAILED(hr)) { goto exit; } // Get the actions
hr = pIActions->LoadReg(pszRegPathNew); if (FAILED(hr)) { goto exit; }
// Get the state of the actions
hr = pIActions->GetState(&dwState); if (FAILED(hr)) { goto exit; }
m_dwState = (m_dwState & ~ACT_STATE_MASK) | (dwState & ACT_STATE_MASK); // Free up the current values
SafeMemFree(m_pszName); SafeRelease(m_pICrit); SafeRelease(m_pIAct);
// Save the new values
m_pszName = pszName; pszName = NULL; if (FALSE == fDisabled) { m_dwState &= ~RULE_STATE_DISABLED; } else { m_dwState |= RULE_STATE_DISABLED; } m_pICrit = pICriteria; pICriteria = NULL; m_pIAct = pIActions; pIActions = NULL;
// Make sure we clear the dirty bit
m_dwState &= ~RULE_STATE_DIRTY;
// Note that we have been loaded
m_dwState |= RULE_STATE_LOADED; // Set the return value
hr = S_OK; exit: SafeMemFree(pszRegPathNew); SafeRelease(pIActions); SafeRelease(pICriteria); SafeMemFree(pszName); if (NULL != hkeyRoot) { RegCloseKey(hkeyRoot); } return hr; }
STDMETHODIMP COERule::SaveReg(LPCSTR pszRegPath, BOOL fClearDirty) { HRESULT hr = S_OK; LONG lErr = 0; HKEY hkeyRoot = NULL; DWORD dwDisp = 0; DWORD dwData = 0; LPSTR pszRegPathNew = NULL; ULONG cchRegPath = 0;
// Check incoming param
if (NULL == pszRegPath) { hr = E_INVALIDARG; goto exit; }
// Can't save out a rule if we don't have criteria or actions
// or a rule name
if ((NULL == m_pICrit) || (NULL == m_pIAct)) { hr = E_FAIL; goto exit; } // Let's make sure we clear out the key first
AthUserDeleteKey(pszRegPath); // Create the reg key from the path
lErr = AthUserCreateKey(pszRegPath, KEY_ALL_ACCESS, &hkeyRoot, &dwDisp); if (ERROR_SUCCESS != lErr) { hr = E_FAIL; goto exit; }
Assert(REG_CREATED_NEW_KEY == dwDisp);
// Write out the rule name
if (NULL != m_pszName) { lErr = RegSetValueEx(hkeyRoot, c_szRuleName, 0, REG_SZ, (BYTE *) m_pszName, lstrlen(m_pszName) + 1); if (ERROR_SUCCESS != lErr) { hr = E_FAIL; goto exit; } } // Write out the disabled state
dwData = !(m_dwState & RULE_STATE_DISABLED); lErr = RegSetValueEx(hkeyRoot, c_szRuleEnabled, 0, REG_DWORD, (BYTE *) &dwData, sizeof(dwData)); if (ERROR_SUCCESS != lErr) { hr = E_FAIL; goto exit; } // Allocate space to hold the new reg path
cchRegPath = lstrlen(pszRegPath); Assert(lstrlen(c_szRuleCriteria) >= lstrlen(c_szRuleActions)); DWORD cchSize = (cchRegPath + lstrlen(c_szRuleCriteria) + 2); if (FAILED(HrAlloc((void **) &pszRegPathNew, cchSize))) { goto exit; }
// Build reg path to criteria
StrCpyN(pszRegPathNew, pszRegPath, cchSize); if ('\\' != pszRegPath[cchRegPath]) { StrCatBuff(pszRegPathNew, g_szBackSlash, cchSize); cchRegPath++; }
StrCatBuff(pszRegPathNew, c_szRuleCriteria, cchSize); // Write out the criteria
hr = m_pICrit->SaveReg(pszRegPathNew, fClearDirty); if (FAILED(hr)) { goto exit; }
// Build reg path to actions
StrCpyN(pszRegPathNew + cchRegPath, c_szRuleActions, (cchSize - cchRegPath));
// Write out the actions
hr = m_pIAct->SaveReg(pszRegPathNew, fClearDirty); if (FAILED(hr)) { goto exit; }
// Bump up the version
if (0 != (m_dwState & RULE_STATE_DIRTY)) { m_dwVersion++; } lErr = RegSetValueEx(hkeyRoot, c_szRulesVersion, 0, REG_DWORD, (BYTE *) &m_dwVersion, sizeof(m_dwVersion)); if (ERROR_SUCCESS != lErr) { hr = E_FAIL; goto exit; } // Should we clear the dirty bit?
if (FALSE != fClearDirty) { m_dwState &= ~RULE_STATE_DIRTY; } // Set the return value
hr = S_OK; exit: SafeMemFree(pszRegPathNew); if (NULL != hkeyRoot) { RegCloseKey(hkeyRoot); } return hr; }
STDMETHODIMP COERule::Clone(IOERule ** ppIRule) { HRESULT hr = S_OK; COERule * pRule = NULL; // Check incoming params
if (NULL == ppIRule) { hr = E_INVALIDARG; goto exit; }
// Initialize the outgoing params
*ppIRule = NULL; // Create a new rule
pRule = new COERule; if (NULL == pRule) { hr = E_OUTOFMEMORY; goto exit; }
// Copy over the rule name
if (NULL != m_pszName) { pRule->m_pszName = PszDupA(m_pszName); if (NULL == pRule->m_pszName) { hr = E_OUTOFMEMORY; goto exit; } } // Copy over the enabled state
pRule->m_dwState = m_dwState;
// Copy over the version
pRule->m_dwVersion = m_dwVersion;
// Clone the criteria
if (FAILED(m_pICrit->Clone(&(pRule->m_pICrit)))) { goto exit; }
// Clone the actions
if (FAILED(m_pIAct->Clone(&(pRule->m_pIAct)))) { goto exit; }
// Get the rule interface
hr = pRule->QueryInterface(IID_IOERule, (void **) ppIRule); if (FAILED(hr)) { goto exit; }
pRule = NULL; // Set the proper return value
hr = S_OK; exit: if (NULL != pRule) { delete pRule; } return hr; }
STDMETHODIMP COERule::GetClassID(CLSID * pclsid) { HRESULT hr = S_OK;
if (NULL == pclsid) { hr = E_INVALIDARG; goto exit; }
*pclsid = CLSID_OERule;
// Set the proper return value
hr = S_OK; exit: return hr; }
STDMETHODIMP COERule::IsDirty(void) { HRESULT hr = S_OK;
hr = (RULE_STATE_DIRTY == (m_dwState & RULE_STATE_DIRTY)) ? S_OK : S_FALSE; return hr; }
STDMETHODIMP COERule::Load(IStream * pStm) { HRESULT hr = S_OK; ULONG cbData = 0; ULONG cbRead = 0; DWORD dwData = 0; LPSTR pszName = NULL; BOOL fDisabled = FALSE; IOECriteria * pICriteria = NULL; IPersistStream * pIPStm = NULL; IOEActions * pIActions = NULL; // Check incoming param
if (NULL == pStm) { hr = E_INVALIDARG; goto exit; }
// Verify we have the correct version
hr = pStm->Read(&dwData, sizeof(dwData), &cbRead); if (FAILED(hr)) { goto exit; }
if ((cbRead != sizeof(dwData)) || (dwData != RULE_VERSION)) { hr = E_FAIL; goto exit; }
// Get the size of the rule name
hr = pStm->Read(&cbData, sizeof(cbData), &cbRead); if (FAILED(hr)) { goto exit; }
if (cbRead != sizeof(cbData)) { hr = E_FAIL; goto exit; }
if (0 != cbData) { // Allocate space to hold the rule name
hr = HrAlloc((void **) &pszName, cbData); if (FAILED(hr)) { goto exit; }
// Get the rule name
hr = pStm->Read(pszName, cbData, &cbRead); if (FAILED(hr)) { goto exit; }
if (cbRead != cbData) { hr = E_FAIL; goto exit; } } // Get the enabled state
hr = pStm->Read(&dwData, sizeof(dwData), &cbRead); if (FAILED(hr)) { goto exit; }
if (cbRead != sizeof(dwData)) { hr = E_FAIL; goto exit; }
fDisabled = ! (BOOL) dwData;
// Create a new criteria object
hr = HrCreateCriteria(&pICriteria); if (FAILED(hr)) { goto exit; } // Get the persistance interface for the criteria
hr = pICriteria->QueryInterface(IID_IPersistStream, (void **) &pIPStm); if (FAILED(hr)) { goto exit; } // Get the criteria
hr = pIPStm->Load(pStm); if (FAILED(hr)) { goto exit; }
// Create a new actions object
hr = HrCreateActions(&pIActions); if (FAILED(hr)) { goto exit; } // Get the persistance interface for the actions
pIPStm->Release(); pIPStm = NULL; hr = pIActions->QueryInterface(IID_IPersistStream, (void **) &pIPStm); if (FAILED(hr)) { goto exit; } // Get the actions
hr = pIPStm->Load(pStm); if (FAILED(hr)) { goto exit; }
// Free up the current values
SafeMemFree(m_pszName); SafeRelease(m_pICrit); SafeRelease(m_pIAct);
// Save the new values
m_pszName = pszName; pszName = NULL; if (FALSE == fDisabled) { m_dwState &= ~RULE_STATE_DISABLED; } else { m_dwState |= RULE_STATE_DISABLED; } m_pICrit = pICriteria; pICriteria = NULL; m_pIAct = pIActions; pIActions = NULL;
// Make sure we clear the dirty bit
m_dwState &= ~RULE_STATE_DIRTY;
// Note that we have been loaded
m_dwState |= RULE_STATE_LOADED; // Set the return value
hr = S_OK; exit: SafeRelease(pIActions); SafeRelease(pICriteria); SafeRelease(pIPStm); SafeMemFree(pszName); return hr; }
STDMETHODIMP COERule::Save(IStream * pStm, BOOL fClearDirty) { HRESULT hr = S_OK; ULONG cbData = 0; ULONG cbWritten = 0; DWORD dwData = 0; ULONG ulIndex = 0; IPersistStream * pIPStm = NULL;
// Check incoming param
if (NULL == pStm) { hr = E_INVALIDARG; goto exit; }
// Can't write out a rule if we don't have criteria or actions
// or a rule name
if ((NULL == m_pICrit) || (NULL == m_pIAct)) { hr = E_FAIL; goto exit; } // Write out the version
dwData = RULE_VERSION; hr = pStm->Write(&dwData, sizeof(dwData), &cbWritten); if (FAILED(hr)) { goto exit; } Assert(cbWritten == sizeof(dwData)); // Write out the size of the rule name
if (NULL != m_pszName) { cbData = lstrlen(m_pszName) + 1; } else { cbData = 0; } hr = pStm->Write(&cbData, sizeof(cbData), &cbWritten); if (FAILED(hr)) { goto exit; } Assert(cbWritten == sizeof(cbData));
if (NULL != m_pszName) { // Write out the rule name
hr = pStm->Write(m_pszName, cbData, &cbWritten); if (FAILED(hr)) { goto exit; } Assert(cbWritten == cbData); } // Write out the enabled state
dwData = !(m_dwState & RULE_STATE_DISABLED); hr = pStm->Write(&dwData, sizeof(dwData), &cbWritten); if (FAILED(hr)) { goto exit; } Assert(cbWritten == sizeof(dwData));
// Get the persistance interface for the criteria
hr = m_pICrit->QueryInterface(IID_IPersistStream, (void **) &pIPStm); if (FAILED(hr)) { goto exit; } // Write out the criteria
hr = pIPStm->Save(pStm, fClearDirty); if (FAILED(hr)) { goto exit; }
// Get the persistance interface for the actions
pIPStm->Release(); pIPStm = NULL; hr = m_pIAct->QueryInterface(IID_IPersistStream, (void **) &pIPStm); if (FAILED(hr)) { goto exit; } // Write out the actions
hr = pIPStm->Save(pStm, fClearDirty); if (FAILED(hr)) { goto exit; }
// Should we clear out the dirty bit
if (FALSE != fClearDirty) { m_dwState &= ~RULE_STATE_DIRTY; }
// Set the return value
hr = S_OK; exit: SafeRelease(pIPStm); return hr; }
|