3044 lines
74 KiB
3044 lines
74 KiB
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// RulesMgr.cpp
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <pch.hxx>
|
|
#include "rulesmgr.h"
|
|
#include "ruleutil.h"
|
|
#include "rule.h"
|
|
#include "junkrule.h"
|
|
#include <msgfldr.h>
|
|
#include <goptions.h>
|
|
#include <instance.h>
|
|
#include "demand.h"
|
|
|
|
CRulesManager::CRulesManager() : m_cRef(0), m_dwState(STATE_LOADED_INIT),
|
|
m_pMailHead(NULL), m_pNewsHead(NULL), m_pFilterHead(NULL),
|
|
m_pIRuleSenderMail(NULL),m_pIRuleSenderNews(NULL),
|
|
m_pIRuleJunk(NULL)
|
|
{
|
|
// Thread Safety
|
|
InitializeCriticalSection(&m_cs);
|
|
}
|
|
|
|
CRulesManager::~CRulesManager()
|
|
{
|
|
AssertSz(m_cRef == 0, "Somebody still has a hold of us!!");
|
|
if (NULL != m_pMailHead)
|
|
{
|
|
_HrFreeRules(RULE_TYPE_MAIL);
|
|
}
|
|
|
|
if (NULL != m_pNewsHead)
|
|
{
|
|
_HrFreeRules(RULE_TYPE_NEWS);
|
|
}
|
|
|
|
if (NULL != m_pFilterHead)
|
|
{
|
|
_HrFreeRules(RULE_TYPE_FILTER);
|
|
}
|
|
|
|
SafeRelease(m_pIRuleSenderMail);
|
|
SafeRelease(m_pIRuleSenderNews);
|
|
SafeRelease(m_pIRuleJunk);
|
|
|
|
// Thread Safety
|
|
DeleteCriticalSection(&m_cs);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CRulesManager::AddRef()
|
|
{
|
|
return ::InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CRulesManager::Release()
|
|
{
|
|
LONG cRef = 0;
|
|
|
|
cRef = ::InterlockedDecrement(&m_cRef);
|
|
if (0 == cRef)
|
|
{
|
|
delete this;
|
|
return cRef;
|
|
}
|
|
|
|
return cRef;
|
|
}
|
|
|
|
STDMETHODIMP CRulesManager::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_IOERulesManager))
|
|
{
|
|
*ppvObject = static_cast<IOERulesManager *>(this);
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
goto exit;
|
|
}
|
|
|
|
reinterpret_cast<IUnknown *>(*ppvObject)->AddRef();
|
|
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRulesManager::Initialize(DWORD dwFlags)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Check the incoming params
|
|
if (0 != dwFlags)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Set the proper return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRulesManager::GetRule(RULEID ridRule, RULE_TYPE type, DWORD dwFlags, IOERule ** ppIRule)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
RULENODE * pNodeWalk = NULL;
|
|
IOERule * pIRule = NULL;
|
|
|
|
// Thread Safety
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
// Check the incoming params
|
|
if (RULEID_INVALID == ridRule)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the ougoing params
|
|
if (NULL != ppIRule)
|
|
{
|
|
*ppIRule = NULL;
|
|
}
|
|
|
|
// Check to see if we already loaded the rules
|
|
hr = _HrLoadRules(type);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Check the special types
|
|
if (RULEID_SENDERS == ridRule)
|
|
{
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
pIRule = m_pIRuleSenderMail;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
pIRule = m_pIRuleSenderNews;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
}
|
|
else if (RULEID_JUNK == ridRule)
|
|
{
|
|
|
|
if (RULE_TYPE_MAIL != type)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
pIRule = m_pIRuleJunk;
|
|
}
|
|
else
|
|
{
|
|
// Walk the proper list
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
pNodeWalk = m_pMailHead;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
|
|
{
|
|
pNodeWalk = m_pNewsHead;
|
|
}
|
|
else if (RULE_TYPE_FILTER == type)
|
|
{
|
|
pNodeWalk = m_pFilterHead;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
for (; NULL != pNodeWalk; pNodeWalk = pNodeWalk->pNext)
|
|
{
|
|
if (ridRule == pNodeWalk->ridRule)
|
|
{
|
|
pIRule = pNodeWalk->pIRule;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Did we find something?
|
|
if (NULL == pIRule)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Set the outgoing param
|
|
if (NULL != ppIRule)
|
|
{
|
|
*ppIRule = pIRule;
|
|
(*ppIRule)->AddRef();
|
|
}
|
|
|
|
// Set the proper return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
// Thread Safety
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRulesManager::FindRule(LPCSTR pszRuleName, RULE_TYPE type, IOERule ** ppIRule)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
RULENODE * pNodeWalk = NULL;
|
|
PROPVARIANT propvar;
|
|
|
|
ZeroMemory(&propvar, sizeof(propvar));
|
|
|
|
// Thread Safety
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
// Check the incoming params
|
|
if ((NULL == pszRuleName) || (NULL == ppIRule))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the ougoing params
|
|
*ppIRule = NULL;
|
|
|
|
// Check to see if we already loaded the rules
|
|
hr = _HrLoadRules(type);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Walk the proper list
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
pNodeWalk = m_pMailHead;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
pNodeWalk = m_pNewsHead;
|
|
}
|
|
else if (RULE_TYPE_FILTER == type)
|
|
{
|
|
pNodeWalk = m_pFilterHead;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
while (NULL != pNodeWalk)
|
|
{
|
|
// Check to see if the name of the rule is the same
|
|
hr = pNodeWalk->pIRule->GetProp(RULE_PROP_NAME , 0, &propvar);
|
|
if (FAILED(hr))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (0 == lstrcmpi(propvar.pszVal, pszRuleName))
|
|
{
|
|
*ppIRule = pNodeWalk->pIRule;
|
|
(*ppIRule)->AddRef();
|
|
break;
|
|
}
|
|
|
|
// Move to the next one
|
|
PropVariantClear(&propvar);
|
|
pNodeWalk = pNodeWalk->pNext;
|
|
}
|
|
|
|
// Set the proper return value
|
|
if (NULL == pNodeWalk)
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
exit:
|
|
PropVariantClear(&propvar);
|
|
// Thread Safety
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRulesManager::GetRules(DWORD dwFlags, RULE_TYPE typeRule, RULEINFO ** ppinfoRule, ULONG * pcpinfoRule)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG cpinfoRule = 0;
|
|
RULEINFO * pinfoRuleAlloc = NULL;
|
|
IOERule * pIRuleSender = NULL;
|
|
RULENODE * prnodeList = NULL;
|
|
RULENODE * prnodeWalk = NULL;
|
|
ULONG ulIndex = 0;
|
|
|
|
// Thread Safety
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
// Check the incoming params
|
|
if (NULL == ppinfoRule)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the outgoing param
|
|
*ppinfoRule = NULL;
|
|
if (NULL != pcpinfoRule)
|
|
{
|
|
*pcpinfoRule = 0;
|
|
}
|
|
|
|
// Check to see if we already loaded the rules
|
|
hr = _HrLoadRules(typeRule);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Figure out which type of rules to work on
|
|
switch (typeRule)
|
|
{
|
|
case RULE_TYPE_MAIL:
|
|
prnodeList = m_pMailHead;
|
|
break;
|
|
|
|
case RULE_TYPE_NEWS:
|
|
prnodeList = m_pNewsHead;
|
|
break;
|
|
|
|
case RULE_TYPE_FILTER:
|
|
prnodeList = m_pFilterHead;
|
|
break;
|
|
|
|
default:
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Count the number of rules
|
|
prnodeWalk = prnodeList;
|
|
for (cpinfoRule = 0; NULL != prnodeWalk; prnodeWalk = prnodeWalk->pNext)
|
|
{
|
|
// Check to see if we should add this item
|
|
if (RULE_TYPE_FILTER == typeRule)
|
|
{
|
|
if (0 != (dwFlags & GETF_POP3))
|
|
{
|
|
if (RULEID_VIEW_DOWNLOADED == prnodeWalk->ridRule)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
cpinfoRule++;
|
|
}
|
|
|
|
// Allocate space to hold the rules
|
|
if (0 != cpinfoRule)
|
|
{
|
|
hr = HrAlloc((VOID **) &pinfoRuleAlloc, cpinfoRule * sizeof(*pinfoRuleAlloc));
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize it to known values
|
|
ZeroMemory(pinfoRuleAlloc, cpinfoRule * sizeof(*pinfoRuleAlloc));
|
|
|
|
// Fill up the info
|
|
for (ulIndex = 0, prnodeWalk = prnodeList; NULL != prnodeWalk; prnodeWalk = prnodeWalk->pNext)
|
|
{
|
|
// Check to see if we should add this item
|
|
if (RULE_TYPE_FILTER == typeRule)
|
|
{
|
|
if (0 != (dwFlags & GETF_POP3))
|
|
{
|
|
if (RULEID_VIEW_DOWNLOADED == prnodeWalk->ridRule)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
pinfoRuleAlloc[ulIndex].ridRule = prnodeWalk->ridRule;
|
|
|
|
pinfoRuleAlloc[ulIndex].pIRule = prnodeWalk->pIRule;
|
|
pinfoRuleAlloc[ulIndex].pIRule->AddRef();
|
|
ulIndex++;
|
|
}
|
|
}
|
|
|
|
// Set the outgoing values
|
|
*ppinfoRule = pinfoRuleAlloc;
|
|
pinfoRuleAlloc = NULL;
|
|
if (NULL != pcpinfoRule)
|
|
{
|
|
*pcpinfoRule = cpinfoRule;
|
|
}
|
|
|
|
// Set the proper return type
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
SafeMemFree(pinfoRuleAlloc);
|
|
// Thread Safety
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CRulesManager::SetRules(DWORD dwFlags, RULE_TYPE typeRule, RULEINFO * pinfoRule, ULONG cpinfoRule)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0;
|
|
IOERule * pIRuleSender = NULL;
|
|
|
|
// Thread Safety
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
// Check the incoming params
|
|
if ((NULL == pinfoRule) && (0 != cpinfoRule))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Check to see if we already loaded the rules
|
|
hr = _HrLoadRules(typeRule);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Do we have to free all the current rules
|
|
if (0 != (dwFlags & SETF_SENDER))
|
|
{
|
|
if (RULE_TYPE_MAIL == typeRule)
|
|
{
|
|
SafeRelease(m_pIRuleSenderMail);
|
|
m_pIRuleSenderMail = pinfoRule->pIRule;
|
|
if (NULL != m_pIRuleSenderMail)
|
|
{
|
|
m_pIRuleSenderMail->AddRef();
|
|
}
|
|
}
|
|
else if (RULE_TYPE_NEWS == typeRule)
|
|
{
|
|
SafeRelease(m_pIRuleSenderNews);
|
|
m_pIRuleSenderNews = pinfoRule->pIRule;
|
|
if (NULL != m_pIRuleSenderNews)
|
|
{
|
|
m_pIRuleSenderNews->AddRef();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
}
|
|
else if (0 != (dwFlags & SETF_JUNK))
|
|
{
|
|
if (RULE_TYPE_MAIL != typeRule)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
SafeRelease(m_pIRuleJunk);
|
|
m_pIRuleJunk = pinfoRule->pIRule;
|
|
if (NULL != m_pIRuleJunk)
|
|
{
|
|
m_pIRuleJunk->AddRef();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (0 != (dwFlags & SETF_CLEAR))
|
|
{
|
|
_HrFreeRules(typeRule);
|
|
}
|
|
|
|
// for each new rule
|
|
for (ulIndex = 0; ulIndex < cpinfoRule; ulIndex++)
|
|
{
|
|
if (0 != (dwFlags & SETF_REPLACE))
|
|
{
|
|
// Add the rule to the list
|
|
hr = _HrReplaceRule(pinfoRule[ulIndex].ridRule, pinfoRule[ulIndex].pIRule, typeRule);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Add the rule to the list
|
|
hr = _HrAddRule(pinfoRule[ulIndex].ridRule, pinfoRule[ulIndex].pIRule, typeRule);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Save the rules
|
|
hr = _HrSaveRules(typeRule);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if ((0 == (dwFlags & SETF_SENDER)) && (0 == (dwFlags & SETF_JUNK)))
|
|
{
|
|
// Fix up the rule ids
|
|
hr = _HrFixupRuleInfo(typeRule, pinfoRule, cpinfoRule);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// Set the proper return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
// Thread Safety
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRulesManager::EnumRules(DWORD dwFlags, RULE_TYPE type, IOEEnumRules ** ppIEnumRules)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CEnumRules * pEnumRules = NULL;
|
|
RULENODE rnode;
|
|
RULENODE * prnode = NULL;
|
|
IOERule * pIRuleSender = NULL;
|
|
|
|
// Thread Safety
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
// Check the incoming params
|
|
if (NULL == ppIEnumRules)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize outgoing params
|
|
*ppIEnumRules = NULL;
|
|
|
|
// Check to see if we already loaded the rules
|
|
hr = _HrLoadRules(type);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Create the rules enumerator object
|
|
pEnumRules = new CEnumRules;
|
|
if (NULL == pEnumRules)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the rules enumerator
|
|
if (0 != (dwFlags & ENUMF_SENDER))
|
|
{
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
pIRuleSender = m_pIRuleSenderMail;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
pIRuleSender = m_pIRuleSenderNews;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
if (NULL != pIRuleSender)
|
|
{
|
|
ZeroMemory(&rnode, sizeof(rnode));
|
|
|
|
rnode.pIRule = pIRuleSender;
|
|
prnode = &rnode;
|
|
}
|
|
else
|
|
{
|
|
prnode = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
prnode = m_pMailHead;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
prnode = m_pNewsHead;
|
|
}
|
|
else if (RULE_TYPE_FILTER == type)
|
|
{
|
|
prnode = m_pFilterHead;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
hr = pEnumRules->_HrInitialize(0, type, prnode);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the rules enumerator interface
|
|
hr = pEnumRules->QueryInterface(IID_IOEEnumRules, (void **) ppIEnumRules);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
pEnumRules = NULL;
|
|
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
if (NULL != pEnumRules)
|
|
{
|
|
delete pEnumRules;
|
|
}
|
|
// Thread Safety
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRulesManager::ExecRules(DWORD dwFlags, RULE_TYPE type, IOEExecRules ** ppIExecRules)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CExecRules * pExecRules = NULL;
|
|
RULENODE rnode;
|
|
RULENODE * prnodeList = NULL;
|
|
|
|
// Thread Safety
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
// Check the incoming params
|
|
if (NULL == ppIExecRules)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize outgoing params
|
|
*ppIExecRules = NULL;
|
|
|
|
// Check to see if we already loaded the rules
|
|
hr = _HrLoadRules(type);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Create the rules enumerator object
|
|
pExecRules = new CExecRules;
|
|
if (NULL == pExecRules)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
prnodeList = m_pMailHead;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
prnodeList = m_pNewsHead;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the rules enumerator
|
|
hr = pExecRules->_HrInitialize(ERF_ONLY_ENABLED | ERF_ONLY_VALID, prnodeList);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the rules enumerator interface
|
|
hr = pExecRules->QueryInterface(IID_IOEExecRules, (void **) ppIExecRules);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
pExecRules = NULL;
|
|
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
if (NULL != pExecRules)
|
|
{
|
|
delete pExecRules;
|
|
}
|
|
// Thread Safety
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRulesManager::ExecuteRules(RULE_TYPE typeRule, DWORD dwFlags, HWND hwndUI, IOEExecRules * pIExecRules,
|
|
MESSAGEINFO * pMsgInfo, IMessageFolder * pFolder, IMimeMessage * pIMMsg)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0;
|
|
RULENODE * prnodeHead = NULL;
|
|
PROPVARIANT propvar = {0};
|
|
ACT_ITEM * pActions = NULL;
|
|
ULONG cActions = 0;
|
|
ACT_ITEM * pActionsList = NULL;
|
|
ULONG cActionsList = 0;
|
|
ACT_ITEM * pActionsNew = NULL;
|
|
ULONG cActionsNew = 0;
|
|
BOOL fStopProcessing = FALSE;
|
|
BOOL fMatch = FALSE;
|
|
|
|
// Thread Safety
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
// Check incoming params
|
|
if ((NULL == pIExecRules) || (NULL == pMsgInfo))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Check to see if we already loaded the rules
|
|
hr = _HrLoadRules(typeRule);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Figure out which list to use
|
|
switch (typeRule)
|
|
{
|
|
case RULE_TYPE_MAIL:
|
|
prnodeHead = m_pMailHead;
|
|
break;
|
|
|
|
case RULE_TYPE_NEWS:
|
|
prnodeHead = m_pNewsHead;
|
|
break;
|
|
|
|
default:
|
|
Assert(FALSE);
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// For each rule
|
|
for (; NULL != prnodeHead; prnodeHead = prnodeHead->pNext)
|
|
{
|
|
// Skip if we don't have a rule
|
|
if (NULL == prnodeHead)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Skip if it isn't enabled
|
|
hr = prnodeHead->pIRule->GetProp(RULE_PROP_DISABLED, 0, &propvar);
|
|
Assert(VT_BOOL == propvar.vt);
|
|
if (FAILED(hr) || (FALSE != propvar.boolVal))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Execute rule
|
|
hr = prnodeHead->pIRule->Evaluate(pMsgInfo->pszAcctId, pMsgInfo, pFolder,
|
|
NULL, pIMMsg, pMsgInfo->cbMessage, &pActions, &cActions);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Did we have a match
|
|
if (S_OK == hr)
|
|
{
|
|
// We've matched at least once
|
|
fMatch = TRUE;
|
|
|
|
// If these are server actions
|
|
if ((1 == cActions) && ((ACT_TYPE_DELETESERVER == pActions[ulIndex].type) ||
|
|
(ACT_TYPE_DONTDOWNLOAD == pActions[ulIndex].type)))
|
|
{
|
|
// If this is our only action
|
|
if (0 == cActionsList)
|
|
{
|
|
// Save the action
|
|
pActionsList = pActions;
|
|
pActions = NULL;
|
|
cActionsList = cActions;
|
|
|
|
// We are done
|
|
fStopProcessing = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// We already have to do something with it
|
|
// so skip over this action
|
|
RuleUtil_HrFreeActionsItem(pActions, cActions);
|
|
SafeMemFree(pActions);
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Should we stop after merging these?
|
|
for (ulIndex = 0; ulIndex < cActions; ulIndex++)
|
|
{
|
|
if (ACT_TYPE_STOP == pActions[ulIndex].type)
|
|
{
|
|
fStopProcessing = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Merge these items with the previous ones
|
|
hr = RuleUtil_HrMergeActions(pActionsList, cActionsList, pActions, cActions, &pActionsNew, &cActionsNew);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Free up the previous ones
|
|
RuleUtil_HrFreeActionsItem(pActionsList, cActionsList);
|
|
SafeMemFree(pActionsList);
|
|
RuleUtil_HrFreeActionsItem(pActions, cActions);
|
|
SafeMemFree(pActions);
|
|
|
|
// Save off the new ones
|
|
pActionsList = pActionsNew;
|
|
pActionsNew = NULL;
|
|
cActionsList = cActionsNew;
|
|
}
|
|
|
|
// Should we continue...
|
|
if (FALSE != fStopProcessing)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Apply the actions if need be
|
|
if ((FALSE != fMatch) && (NULL != pActionsList) && (0 != cActionsList))
|
|
{
|
|
if (FAILED(RuleUtil_HrApplyActions(hwndUI, pIExecRules, pMsgInfo, pFolder, pIMMsg,
|
|
(RULE_TYPE_MAIL != typeRule) ? DELETE_MESSAGE_NOTRASHCAN : 0, pActionsList, cActionsList, NULL, NULL)))
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// Set the return value
|
|
hr = (FALSE != fMatch) ? S_OK : S_FALSE;
|
|
|
|
exit:
|
|
// Thread Safety
|
|
RuleUtil_HrFreeActionsItem(pActionsNew, cActionsNew);
|
|
SafeMemFree(pActionsNew);
|
|
RuleUtil_HrFreeActionsItem(pActions, cActions);
|
|
SafeMemFree(pActions);
|
|
RuleUtil_HrFreeActionsItem(pActionsList, cActionsList);
|
|
SafeMemFree(pActionsList);
|
|
LeaveCriticalSection(&m_cs);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRulesManager::_HrLoadRules(RULE_TYPE type)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPCSTR pszSubKey = NULL;
|
|
LPSTR pszOrderAlloc = NULL;
|
|
LPSTR pszOrder = NULL;
|
|
LPSTR pszWalk = NULL;
|
|
HKEY hkeyRoot = NULL;
|
|
DWORD dwDisp = 0;
|
|
LONG lErr = 0;
|
|
ULONG cbData = 0;
|
|
IOERule * pIRule = NULL;
|
|
DWORD dwData = 0;
|
|
CHAR rgchRulePath[MAX_PATH];
|
|
ULONG cchRulePath = 0;
|
|
PROPVARIANT propvar = {0};
|
|
RULEID ridRule = RULEID_INVALID;
|
|
CHAR rgchTagBuff[CCH_INDEX_MAX + 2];
|
|
|
|
// Check to see if we're already initialized
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
if (0 != (m_dwState & STATE_LOADED_MAIL))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Make sure we loaded the sender rules
|
|
_HrLoadSenders();
|
|
|
|
// Make sure we loaded the junk rule
|
|
if (0 != (g_dwAthenaMode & MODE_JUNKMAIL))
|
|
{
|
|
_HrLoadJunk();
|
|
}
|
|
|
|
// Set the key path
|
|
pszSubKey = c_szRulesMail;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
if (0 != (m_dwState & STATE_LOADED_NEWS))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Make sure we loaded the sender rules
|
|
_HrLoadSenders();
|
|
|
|
// Set the key path
|
|
pszSubKey = c_szRulesNews;
|
|
}
|
|
else if (RULE_TYPE_FILTER == type)
|
|
{
|
|
if (0 != (m_dwState & STATE_LOADED_FILTERS))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Set the key path
|
|
pszSubKey = c_szRulesFilter;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Check to see if the Rule node already exists
|
|
lErr = AthUserCreateKey(pszSubKey, KEY_ALL_ACCESS, &hkeyRoot, &dwDisp);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(lErr);
|
|
goto exit;
|
|
}
|
|
|
|
// Check the current version
|
|
cbData = sizeof(dwData);
|
|
lErr = RegQueryValueEx(hkeyRoot, c_szRulesVersion, NULL, NULL, (BYTE *) &dwData, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
// Push out the correct rules manager version
|
|
dwData = RULESMGR_VERSION;
|
|
lErr = RegSetValueEx(hkeyRoot, c_szRulesVersion, 0, REG_DWORD, (CONST BYTE *) &dwData, sizeof(dwData));
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(lErr);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
Assert(RULESMGR_VERSION == dwData);
|
|
|
|
// Create the default rules if needed
|
|
hr = RuleUtil_HrUpdateDefaultRules(type);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Figure out the size of the order
|
|
lErr = AthUserGetValue(pszSubKey, c_szRulesOrder, NULL, NULL, &cbData);
|
|
if ((ERROR_SUCCESS != lErr) && (ERROR_FILE_NOT_FOUND != lErr))
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
if (ERROR_FILE_NOT_FOUND != lErr)
|
|
{
|
|
// Allocate the space to hold the order
|
|
hr = HrAlloc((void **) &pszOrderAlloc, cbData);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Get the order from the registry
|
|
lErr = AthUserGetValue(pszSubKey, c_szRulesOrder, NULL, (LPBYTE) pszOrderAlloc, &cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Build up the rule registry path
|
|
StrCpyN(rgchRulePath, pszSubKey, ARRAYSIZE(rgchRulePath));
|
|
StrCatBuff(rgchRulePath, g_szBackSlash, ARRAYSIZE(rgchRulePath));
|
|
cchRulePath = lstrlen(rgchRulePath);
|
|
|
|
// Initialize the rule tag buffer
|
|
rgchTagBuff[0] = '0';
|
|
rgchTagBuff[1] = 'X';
|
|
|
|
// Parse the order string to create the rules
|
|
pszOrder = pszOrderAlloc;
|
|
while ('\0' != *pszOrder)
|
|
{
|
|
SafeRelease(pIRule);
|
|
|
|
// Create a new rule
|
|
hr = HrCreateRule(&pIRule);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Find the name of the new rule
|
|
pszWalk = StrStr(pszOrder, g_szSpace);
|
|
if (NULL != pszWalk)
|
|
{
|
|
*pszWalk = '\0';
|
|
pszWalk++;
|
|
}
|
|
|
|
// Build the path to the rule
|
|
StrCpyN(rgchRulePath + cchRulePath, pszOrder, ARRAYSIZE(rgchRulePath) - cchRulePath);
|
|
|
|
// Load the rule
|
|
hr = pIRule->LoadReg(rgchRulePath);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Build the correct hex string
|
|
StrCpyN(rgchTagBuff + 2, pszOrder, ARRAYSIZE(rgchTagBuff) - 2);
|
|
|
|
// Get the new rule handle
|
|
ridRule = ( ( RULEID ) 0);
|
|
SideAssert(FALSE != StrToIntEx(rgchTagBuff, STIF_SUPPORT_HEX, (INT *) &ridRule));
|
|
|
|
// Add the new rule to the manager
|
|
hr = _HrAddRule(ridRule, pIRule, type);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// Move to the next item in the order
|
|
if (NULL == pszWalk)
|
|
{
|
|
pszOrder += lstrlen(pszOrder);
|
|
}
|
|
else
|
|
{
|
|
pszOrder = pszWalk;
|
|
}
|
|
}
|
|
}
|
|
|
|
// We've loaded the rules successfully
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
m_dwState |= STATE_LOADED_MAIL;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
m_dwState |= STATE_LOADED_NEWS;
|
|
}
|
|
else
|
|
{
|
|
m_dwState |= STATE_LOADED_FILTERS;
|
|
}
|
|
|
|
// Set the return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
SafeMemFree(pszOrderAlloc);
|
|
SafeRelease(pIRule);
|
|
if (NULL != hkeyRoot)
|
|
{
|
|
RegCloseKey(hkeyRoot);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRulesManager::_HrLoadSenders(VOID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HKEY hkeyRoot = NULL;
|
|
DWORD dwDisp = 0;
|
|
DWORD dwData = 0;
|
|
LONG lErr = 0;
|
|
ULONG cbData = 0;
|
|
IOERule * pIRule = NULL;
|
|
CHAR rgchSenderPath[MAX_PATH];
|
|
|
|
// Do we have anything to do?
|
|
if (0 != (m_dwState & STATE_LOADED_SENDERS))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Let's get access to the sender root key
|
|
lErr = AthUserCreateKey(c_szSenders, KEY_ALL_ACCESS, &hkeyRoot, &dwDisp);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Are the senders the correct version?
|
|
cbData = sizeof(dwData);
|
|
lErr = RegQueryValueEx(hkeyRoot, c_szSendersVersion, 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 = RULESMGR_VERSION;
|
|
cbData = sizeof(dwData);
|
|
lErr = RegSetValueEx(hkeyRoot, c_szSendersVersion, 0, REG_DWORD, (BYTE *) &dwData, cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
Assert(dwData == RULESMGR_VERSION);
|
|
|
|
// Is there anything to do?
|
|
if (REG_CREATED_NEW_KEY != dwDisp)
|
|
{
|
|
// Create the path to the sender
|
|
StrCpyN(rgchSenderPath, c_szSenders, ARRAYSIZE(rgchSenderPath));
|
|
StrCatBuff(rgchSenderPath, g_szBackSlash, ARRAYSIZE(rgchSenderPath));
|
|
StrCatBuff(rgchSenderPath, c_szMailDir, ARRAYSIZE(rgchSenderPath));
|
|
|
|
// Create the mail sender rule
|
|
hr = RuleUtil_HrLoadSender(rgchSenderPath, 0, &pIRule);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Save the loaded rule
|
|
if (S_OK == hr)
|
|
{
|
|
m_pIRuleSenderMail = pIRule;
|
|
pIRule = NULL;
|
|
}
|
|
|
|
// Create the path to the sender
|
|
StrCpyN(rgchSenderPath, c_szSenders, ARRAYSIZE(rgchSenderPath));
|
|
StrCatBuff(rgchSenderPath, g_szBackSlash, ARRAYSIZE(rgchSenderPath));
|
|
StrCatBuff(rgchSenderPath, c_szNewsDir, ARRAYSIZE(rgchSenderPath));
|
|
|
|
// Create the news sender rule
|
|
hr = RuleUtil_HrLoadSender(rgchSenderPath, 0, &pIRule);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Save the loaded rule
|
|
if (S_OK == hr)
|
|
{
|
|
m_pIRuleSenderNews = pIRule;
|
|
pIRule = NULL;
|
|
}
|
|
}
|
|
|
|
// Note that we've loaded the senders
|
|
m_dwState |= STATE_LOADED_SENDERS;
|
|
|
|
// Set the return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
SafeRelease(pIRule);
|
|
if (NULL != hkeyRoot)
|
|
{
|
|
RegCloseKey(hkeyRoot);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRulesManager::_HrLoadJunk(VOID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HKEY hkeyRoot = NULL;
|
|
DWORD dwDisp = 0;
|
|
DWORD dwData = 0;
|
|
ULONG cbData = 0;
|
|
LONG lErr = 0;
|
|
IOERule * pIRule = NULL;
|
|
|
|
// Do we have anything to do?
|
|
if (0 != (m_dwState & STATE_LOADED_JUNK))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Let's get access to the Junk mail root key
|
|
lErr = AthUserCreateKey(c_szRulesJunkMail, KEY_ALL_ACCESS, &hkeyRoot, &dwDisp);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Is the junk mail the correct version?
|
|
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 = RULESMGR_VERSION;
|
|
cbData = sizeof(dwData);
|
|
lErr = RegSetValueEx(hkeyRoot, c_szRulesVersion, 0, REG_DWORD, (BYTE *) &dwData, cbData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
Assert(dwData == RULESMGR_VERSION);
|
|
|
|
// Create the rule
|
|
hr = HrCreateJunkRule(&pIRule);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Load the junk rule
|
|
hr = pIRule->LoadReg(c_szRulesJunkMail);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
m_pIRuleJunk = pIRule;
|
|
pIRule = NULL;
|
|
|
|
// Note that we've loaded the junk rule
|
|
m_dwState |= STATE_LOADED_JUNK;
|
|
|
|
// Set the return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
SafeRelease(pIRule);
|
|
if (NULL != hkeyRoot)
|
|
{
|
|
RegCloseKey(hkeyRoot);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRulesManager::_HrSaveRules(RULE_TYPE type)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPCSTR pszRegPath = NULL;
|
|
DWORD dwData = 0;
|
|
LONG lErr = 0;
|
|
RULENODE * pRuleNode = NULL;
|
|
RULENODE * pNodeWalk = NULL;
|
|
ULONG cpIRule = 0;
|
|
LPSTR pszOrder = NULL;
|
|
HKEY hkeyRoot = NULL;
|
|
DWORD dwIndex = 0;
|
|
CHAR rgchOrder[CCH_INDEX_MAX];
|
|
ULONG cchOrder = 0;
|
|
CHAR rgchRulePath[MAX_PATH];
|
|
ULONG cchRulePath = 0;
|
|
BOOL fNewRule = FALSE;
|
|
ULONG ulRuleID = 0;
|
|
HKEY hkeyDummy = NULL;
|
|
LONG cSubKeys = 0;
|
|
|
|
// Make sure we loaded the sender rules
|
|
_HrSaveSenders();
|
|
|
|
// Make sure we loaded the junk rules
|
|
if (0 != (g_dwAthenaMode & MODE_JUNKMAIL))
|
|
{
|
|
_HrSaveJunk();
|
|
}
|
|
|
|
// Check to see if we have anything to save
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
if (0 == (m_dwState & STATE_LOADED_MAIL))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Set the key path
|
|
pszRegPath = c_szRulesMail;
|
|
|
|
pRuleNode = m_pMailHead;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
if (0 == (m_dwState & STATE_LOADED_NEWS))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Set the key path
|
|
pszRegPath = c_szRulesNews;
|
|
|
|
pRuleNode = m_pNewsHead;
|
|
}
|
|
else if (RULE_TYPE_FILTER == type)
|
|
{
|
|
if (0 == (m_dwState & STATE_LOADED_FILTERS))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Set the key path
|
|
pszRegPath = c_szRulesFilter;
|
|
|
|
pRuleNode = m_pFilterHead;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
lErr = AthUserCreateKey(pszRegPath, KEY_ALL_ACCESS, &hkeyRoot, &dwData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Save out the rules version
|
|
dwData = RULESMGR_VERSION;
|
|
lErr = RegSetValueEx(hkeyRoot, c_szRulesVersion, 0, REG_DWORD, (CONST BYTE *) &dwData, sizeof(dwData));
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Get the number of rules
|
|
cpIRule = 0;
|
|
for (pNodeWalk = pRuleNode; NULL != pNodeWalk; pNodeWalk = pNodeWalk->pNext)
|
|
{
|
|
cpIRule++;
|
|
}
|
|
|
|
// Allocate space to hold the order
|
|
DWORD cchSize = ((cpIRule * CCH_INDEX_MAX) + 1);
|
|
hr = HrAlloc((void **) &pszOrder, cchSize);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
pszOrder[0] = '\0';
|
|
|
|
// Delete all the old rules
|
|
lErr = SHQueryInfoKey(hkeyRoot, (LPDWORD) (&cSubKeys), NULL, NULL, NULL);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Delete all the old rules
|
|
for (cSubKeys--; cSubKeys >= 0; cSubKeys--)
|
|
{
|
|
cchOrder = sizeof(rgchOrder);
|
|
lErr = SHEnumKeyEx(hkeyRoot, cSubKeys, rgchOrder, &cchOrder);
|
|
|
|
if (ERROR_NO_MORE_ITEMS == lErr)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
SHDeleteKey(hkeyRoot, rgchOrder);
|
|
}
|
|
|
|
// Delete the old order string
|
|
RegDeleteValue(hkeyRoot, c_szRulesOrder);
|
|
|
|
// Build up the rule registry path
|
|
StrCpyN(rgchRulePath, pszRegPath, ARRAYSIZE(rgchRulePath));
|
|
StrCatBuff(rgchRulePath, g_szBackSlash, ARRAYSIZE(rgchRulePath));
|
|
cchRulePath = lstrlen(rgchRulePath);
|
|
|
|
// Write out the rules with good tags
|
|
for (dwIndex = 0, pNodeWalk = pRuleNode; NULL != pNodeWalk; pNodeWalk = pNodeWalk->pNext, dwIndex++)
|
|
{
|
|
if (RULEID_INVALID == pNodeWalk->ridRule)
|
|
{
|
|
fNewRule = TRUE;
|
|
continue;
|
|
}
|
|
|
|
// Get a new index from the order
|
|
wnsprintf(rgchOrder, ARRAYSIZE(rgchOrder), "%03X", pNodeWalk->ridRule);
|
|
|
|
// Build the path to the rule
|
|
StrCpyN(rgchRulePath + cchRulePath, rgchOrder, ARRAYSIZE(rgchRulePath) - cchRulePath);
|
|
|
|
// Save the rule
|
|
hr = pNodeWalk->pIRule->SaveReg(rgchRulePath, TRUE);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// Fill in the new tags
|
|
if (FALSE != fNewRule)
|
|
{
|
|
ulRuleID = 0;
|
|
|
|
// Write out the updated rule
|
|
for (dwIndex = 0, pNodeWalk = pRuleNode; NULL != pNodeWalk; pNodeWalk = pNodeWalk->pNext, dwIndex++)
|
|
{
|
|
if (RULEID_INVALID != pNodeWalk->ridRule)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Find the first open entry
|
|
for (; ulRuleID < PtrToUlong(RULEID_JUNK); ulRuleID++)
|
|
{
|
|
// Get a new index from the order
|
|
wnsprintf(rgchOrder, ARRAYSIZE(rgchOrder), "%03X", ulRuleID);
|
|
|
|
lErr = RegOpenKeyEx(hkeyRoot, rgchOrder, 0, KEY_READ, &hkeyDummy);
|
|
if (ERROR_SUCCESS == lErr)
|
|
{
|
|
RegCloseKey(hkeyDummy);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ERROR_FILE_NOT_FOUND != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Set the rule tag
|
|
pNodeWalk->ridRule = (RULEID) IntToPtr(ulRuleID);
|
|
|
|
// Build the path to the rule
|
|
StrCpyN(rgchRulePath + cchRulePath, rgchOrder, ARRAYSIZE(rgchRulePath) - cchRulePath);
|
|
|
|
// Save the rule
|
|
hr = pNodeWalk->pIRule->SaveReg(rgchRulePath, TRUE);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Write out the new order string
|
|
for (dwIndex = 0, pNodeWalk = pRuleNode; NULL != pNodeWalk; pNodeWalk = pNodeWalk->pNext, dwIndex++)
|
|
{
|
|
// Get a new index from the order
|
|
wnsprintf(rgchOrder, ARRAYSIZE(rgchOrder), "%03X", pNodeWalk->ridRule);
|
|
|
|
// Add rule to the order
|
|
if ('\0' != pszOrder[0])
|
|
{
|
|
StrCatBuff(pszOrder, g_szSpace, cchSize);
|
|
}
|
|
StrCatBuff(pszOrder, rgchOrder, cchSize);
|
|
}
|
|
|
|
// Save the order string
|
|
if (ERROR_SUCCESS != AthUserSetValue(pszRegPath, c_szRulesOrder, REG_SZ, (CONST BYTE *) pszOrder, lstrlen(pszOrder) + 1))
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Set the return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
SafeMemFree(pszOrder);
|
|
if (NULL != hkeyRoot)
|
|
{
|
|
RegCloseKey(hkeyRoot);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRulesManager::_HrSaveSenders(VOID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwData = 0;
|
|
LONG lErr = 0;
|
|
HKEY hkeyRoot = NULL;
|
|
DWORD dwIndex = 0;
|
|
CHAR rgchSenderPath[MAX_PATH];
|
|
|
|
// Check to see if we have anything to save
|
|
if (0 == (m_dwState & STATE_LOADED_SENDERS))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
lErr = AthUserCreateKey(c_szSenders, KEY_ALL_ACCESS, &hkeyRoot, &dwData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Save out the senders version
|
|
dwData = RULESMGR_VERSION;
|
|
lErr = RegSetValueEx(hkeyRoot, c_szSendersVersion, 0, REG_DWORD, (CONST BYTE *) &dwData, sizeof(dwData));
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Delete the old sender list
|
|
SHDeleteKey(hkeyRoot, c_szMailDir);
|
|
|
|
// Build up the sender registry path
|
|
StrCpyN(rgchSenderPath, c_szSenders, ARRAYSIZE(rgchSenderPath));
|
|
StrCatBuff(rgchSenderPath, g_szBackSlash, ARRAYSIZE(rgchSenderPath));
|
|
StrCatBuff(rgchSenderPath, c_szMailDir, ARRAYSIZE(rgchSenderPath));
|
|
|
|
// Save the rule
|
|
if (NULL != m_pIRuleSenderMail)
|
|
{
|
|
hr = m_pIRuleSenderMail->SaveReg(rgchSenderPath, TRUE);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// Delete the old sender list
|
|
SHDeleteKey(hkeyRoot, c_szNewsDir);
|
|
|
|
// Build up the sender registry path
|
|
StrCpyN(rgchSenderPath, c_szSenders, ARRAYSIZE(rgchSenderPath));
|
|
StrCatBuff(rgchSenderPath, g_szBackSlash, ARRAYSIZE(rgchSenderPath));
|
|
StrCatBuff(rgchSenderPath, c_szNewsDir, ARRAYSIZE(rgchSenderPath));
|
|
|
|
// Save the rule
|
|
if (NULL != m_pIRuleSenderNews)
|
|
{
|
|
hr = m_pIRuleSenderNews->SaveReg(rgchSenderPath, TRUE);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// Set the return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
if (NULL != hkeyRoot)
|
|
{
|
|
RegCloseKey(hkeyRoot);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRulesManager::_HrSaveJunk(VOID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwData = 0;
|
|
LONG lErr = 0;
|
|
HKEY hkeyRoot = NULL;
|
|
DWORD dwIndex = 0;
|
|
CHAR rgchSenderPath[MAX_PATH];
|
|
|
|
// Check to see if we have anything to save
|
|
if (0 == (m_dwState & STATE_LOADED_JUNK))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
lErr = AthUserCreateKey(c_szRulesJunkMail, KEY_ALL_ACCESS, &hkeyRoot, &dwData);
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Save out the senders version
|
|
dwData = RULESMGR_VERSION;
|
|
lErr = RegSetValueEx(hkeyRoot, c_szRulesVersion, 0, REG_DWORD, (CONST BYTE *) &dwData, sizeof(dwData));
|
|
if (ERROR_SUCCESS != lErr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Save the rule
|
|
if (NULL != m_pIRuleJunk)
|
|
{
|
|
hr = m_pIRuleJunk->SaveReg(c_szRulesJunkMail, TRUE);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// Set the return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
if (NULL != hkeyRoot)
|
|
{
|
|
RegCloseKey(hkeyRoot);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRulesManager::_HrFreeRules(RULE_TYPE type)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
RULENODE * pNodeWalk = NULL;
|
|
RULENODE * pNodeNext = NULL;
|
|
|
|
// Initialize the params
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
pNodeWalk = m_pMailHead;
|
|
pNodeNext = m_pMailHead;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
pNodeWalk = m_pNewsHead;
|
|
pNodeNext = m_pNewsHead;
|
|
}
|
|
else if (RULE_TYPE_FILTER == type)
|
|
{
|
|
pNodeWalk = m_pFilterHead;
|
|
pNodeNext = m_pFilterHead;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Walk the list and free each item
|
|
while (NULL != pNodeWalk)
|
|
{
|
|
// Save off the next item
|
|
pNodeNext = pNodeWalk->pNext;
|
|
|
|
// Release the rule
|
|
AssertSz(NULL != pNodeWalk->pIRule, "Where the heck is the rule???");
|
|
pNodeWalk->pIRule->Release();
|
|
|
|
// Free up the node
|
|
delete pNodeWalk;
|
|
|
|
// Move to the next item
|
|
pNodeWalk = pNodeNext;
|
|
}
|
|
|
|
// Clear out the list head
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
m_pMailHead = NULL;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
m_pNewsHead = NULL;
|
|
}
|
|
else
|
|
{
|
|
m_pFilterHead = NULL;
|
|
}
|
|
|
|
exit:
|
|
// Set the return param
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRulesManager::_HrAddRule(RULEID ridRule, IOERule * pIRule, RULE_TYPE type)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
RULENODE * pRuleNode = NULL;
|
|
RULENODE * pNodeWalk = NULL;
|
|
|
|
// Check incoming params
|
|
if (NULL == pIRule)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Create a new rule node
|
|
pRuleNode = new RULENODE;
|
|
if (NULL == pRuleNode)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the node
|
|
pRuleNode->pNext = NULL;
|
|
pRuleNode->ridRule = ridRule;
|
|
pRuleNode->pIRule = pIRule;
|
|
pRuleNode->pIRule->AddRef();
|
|
|
|
// Add the node to the proper list
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
pNodeWalk = m_pMailHead;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
pNodeWalk = m_pNewsHead;
|
|
}
|
|
else
|
|
{
|
|
pNodeWalk = m_pFilterHead;
|
|
}
|
|
|
|
if (NULL == pNodeWalk)
|
|
{
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
m_pMailHead = pRuleNode;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
m_pNewsHead = pRuleNode;
|
|
}
|
|
else
|
|
{
|
|
m_pFilterHead = pRuleNode;
|
|
}
|
|
pRuleNode = NULL;
|
|
}
|
|
else
|
|
{
|
|
while (NULL != pNodeWalk->pNext)
|
|
{
|
|
pNodeWalk = pNodeWalk->pNext;
|
|
}
|
|
|
|
pNodeWalk->pNext = pRuleNode;
|
|
pRuleNode = NULL;
|
|
}
|
|
|
|
// Set return values
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
if (NULL != pRuleNode)
|
|
{
|
|
pRuleNode->pIRule->Release();
|
|
delete pRuleNode;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRulesManager::_HrReplaceRule(RULEID ridRule, IOERule * pIRule, RULE_TYPE type)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
RULENODE * pNodeWalk = NULL;
|
|
RULENODE * pNodePrev = NULL;
|
|
|
|
// Nothing to do if we don't have a rule
|
|
if (NULL == pIRule)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the params
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
pNodeWalk = m_pMailHead;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
pNodeWalk = m_pNewsHead;
|
|
}
|
|
else
|
|
{
|
|
pNodeWalk = m_pFilterHead;
|
|
}
|
|
|
|
// Walk the list and free each item
|
|
for (; NULL != pNodeWalk; pNodeWalk = pNodeWalk->pNext)
|
|
{
|
|
if (pNodeWalk->ridRule == ridRule)
|
|
{
|
|
// We found it
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Couldn't find the rule in the list
|
|
if (NULL == pNodeWalk)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Replace the rule
|
|
SafeRelease(pNodeWalk->pIRule);
|
|
pNodeWalk->pIRule = pIRule;
|
|
pNodeWalk->pIRule->AddRef();
|
|
|
|
// Set the return param
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRulesManager::_HrRemoveRule(IOERule * pIRule, RULE_TYPE type)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
RULENODE * pNodeWalk = NULL;
|
|
RULENODE * pNodePrev = NULL;
|
|
|
|
// Initialize the params
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
pNodeWalk = m_pMailHead;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
pNodeWalk = m_pNewsHead;
|
|
}
|
|
else
|
|
{
|
|
pNodeWalk = m_pFilterHead;
|
|
}
|
|
|
|
// Walk the list and free each item
|
|
pNodePrev = NULL;
|
|
while (NULL != pNodeWalk)
|
|
{
|
|
if (pNodeWalk->pIRule == pIRule)
|
|
{
|
|
// We found it
|
|
break;
|
|
}
|
|
|
|
// Save off the next item
|
|
pNodePrev = pNodeWalk;
|
|
|
|
// Move to the next item
|
|
pNodeWalk = pNodeWalk->pNext;
|
|
}
|
|
|
|
// Couldn't find the rule in the list
|
|
if (NULL == pNodeWalk)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
if (NULL == pNodePrev)
|
|
{
|
|
// Clear out the list head
|
|
if (RULE_TYPE_MAIL == type)
|
|
{
|
|
m_pMailHead = pNodeWalk->pNext;
|
|
}
|
|
else if (RULE_TYPE_NEWS == type)
|
|
{
|
|
m_pNewsHead = pNodeWalk->pNext;
|
|
}
|
|
else
|
|
{
|
|
m_pFilterHead = pNodeWalk->pNext;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNodePrev->pNext = pNodeWalk->pNext;
|
|
}
|
|
|
|
// Free up the node
|
|
pNodeWalk->pIRule->Release();
|
|
pNodeWalk->pNext = NULL;
|
|
delete pNodeWalk;
|
|
|
|
// Set the return param
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRulesManager::_HrFixupRuleInfo(RULE_TYPE typeRule, RULEINFO * pinfoRule, ULONG cpinfoRule)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0;
|
|
RULENODE * pNodeHead = NULL;
|
|
RULENODE * pNodeWalk = NULL;
|
|
|
|
// Check incoming args
|
|
if ((NULL == pinfoRule) && (0 != cpinfoRule))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Walk the proper list
|
|
if (RULE_TYPE_MAIL == typeRule)
|
|
{
|
|
pNodeHead = m_pMailHead;
|
|
}
|
|
else if (RULE_TYPE_NEWS == typeRule)
|
|
{
|
|
pNodeHead = m_pNewsHead;
|
|
}
|
|
else if (RULE_TYPE_FILTER == typeRule)
|
|
{
|
|
pNodeHead = m_pFilterHead;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Search the rule info list for an unknown ruleid
|
|
for (ulIndex = 0; ulIndex < cpinfoRule; ulIndex++)
|
|
{
|
|
// If the rule id is invalid try to find it
|
|
if (RULEID_INVALID == pinfoRule[ulIndex].ridRule)
|
|
{
|
|
|
|
for (pNodeWalk = pNodeHead; NULL != pNodeWalk; pNodeWalk = pNodeWalk->pNext)
|
|
{
|
|
// Check to see if the rule is the same
|
|
if (pNodeWalk->pIRule == pinfoRule[ulIndex].pIRule)
|
|
{
|
|
pinfoRule[ulIndex].ridRule = pNodeWalk->ridRule;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NULL == pNodeWalk)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set the return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
CEnumRules::CEnumRules()
|
|
{
|
|
m_cRef = 0;
|
|
m_pNodeHead = NULL;
|
|
m_pNodeCurr = NULL;
|
|
m_dwFlags = 0;
|
|
m_typeRule = RULE_TYPE_MAIL;
|
|
}
|
|
|
|
CEnumRules::~CEnumRules()
|
|
{
|
|
RULENODE * pNodeNext = NULL;
|
|
|
|
AssertSz(m_cRef == 0, "Somebody still has a hold of us!!");
|
|
|
|
// Walk the list and free each item
|
|
while (NULL != m_pNodeHead)
|
|
{
|
|
// Save off the next item
|
|
pNodeNext = m_pNodeHead->pNext;
|
|
|
|
// Release the rule
|
|
AssertSz(NULL != m_pNodeHead->pIRule, "Where the heck is the rule???");
|
|
m_pNodeHead->pIRule->Release();
|
|
|
|
// Free up the node
|
|
delete m_pNodeHead;
|
|
|
|
// Move to the next item
|
|
m_pNodeHead = pNodeNext;
|
|
}
|
|
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CEnumRules::AddRef()
|
|
{
|
|
return ::InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CEnumRules::Release()
|
|
{
|
|
LONG cRef = 0;
|
|
|
|
cRef = ::InterlockedDecrement(&m_cRef);
|
|
if (0 == cRef)
|
|
{
|
|
delete this;
|
|
return cRef;
|
|
}
|
|
|
|
return cRef;
|
|
}
|
|
|
|
STDMETHODIMP CEnumRules::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_IOEEnumRules))
|
|
{
|
|
*ppvObject = static_cast<IOEEnumRules *>(this);
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
goto exit;
|
|
}
|
|
|
|
reinterpret_cast<IUnknown *>(*ppvObject)->AddRef();
|
|
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CEnumRules::Next(ULONG cpIRule, IOERule ** rgpIRule, ULONG * pcpIRuleFetched)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG cpIRuleRet = 0;
|
|
|
|
// Check incoming params
|
|
if (NULL == rgpIRule)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize outgoing params
|
|
*rgpIRule = NULL;
|
|
if (NULL != pcpIRuleFetched)
|
|
{
|
|
*pcpIRuleFetched = 0;
|
|
}
|
|
|
|
// If we're at the end then just return
|
|
if (NULL == m_pNodeCurr)
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
for (cpIRuleRet = 0; cpIRuleRet < cpIRule; cpIRuleRet++)
|
|
{
|
|
rgpIRule[cpIRuleRet] = m_pNodeCurr->pIRule;
|
|
(rgpIRule[cpIRuleRet])->AddRef();
|
|
|
|
m_pNodeCurr = m_pNodeCurr->pNext;
|
|
|
|
if (NULL == m_pNodeCurr)
|
|
{
|
|
cpIRuleRet++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set outgoing params
|
|
if (NULL != pcpIRuleFetched)
|
|
{
|
|
*pcpIRuleFetched = cpIRuleRet;
|
|
}
|
|
|
|
// Set return value
|
|
hr = (cpIRuleRet == cpIRule) ? S_OK : S_FALSE;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CEnumRules::Skip(ULONG cpIRule)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG cpIRuleWalk = 0;
|
|
|
|
for (cpIRuleWalk = 0; cpIRuleWalk < cpIRule; cpIRuleWalk++)
|
|
{
|
|
if (NULL == m_pNodeCurr)
|
|
{
|
|
break;
|
|
}
|
|
|
|
m_pNodeCurr = m_pNodeCurr->pNext;
|
|
}
|
|
|
|
hr = (cpIRuleWalk == cpIRule) ? S_OK : S_FALSE;
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CEnumRules::Reset(void)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
m_pNodeCurr = m_pNodeHead;
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CEnumRules::Clone(IOEEnumRules ** ppIEnumRules)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CEnumRules * pEnumRules = NULL;
|
|
|
|
// Check incoming params
|
|
if (NULL == ppIEnumRules)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize outgoing params
|
|
*ppIEnumRules = NULL;
|
|
|
|
pEnumRules = new CEnumRules;
|
|
if (NULL == pEnumRules)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the rules enumerator
|
|
hr = pEnumRules->_HrInitialize(m_dwFlags, m_typeRule, m_pNodeHead);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Set the state of the new one to match the current one
|
|
pEnumRules->m_pNodeCurr = m_pNodeHead;
|
|
|
|
// Get the rules enumerator interface
|
|
hr = pEnumRules->QueryInterface(IID_IOEEnumRules, (void **) ppIEnumRules);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
pEnumRules = NULL;
|
|
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
if (NULL != pEnumRules)
|
|
{
|
|
delete pEnumRules;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CEnumRules::_HrInitialize(DWORD dwFlags, RULE_TYPE typeRule, RULENODE * pNodeHead)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
RULENODE * pNodeNew = NULL;
|
|
RULENODE * pNodeWalk = NULL;
|
|
|
|
if (NULL == pNodeHead)
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
m_dwFlags = dwFlags;
|
|
m_typeRule = typeRule;
|
|
|
|
for (pNodeWalk = m_pNodeHead; NULL != pNodeHead; pNodeHead = pNodeHead->pNext)
|
|
{
|
|
// Check to see if we should add this item
|
|
if (RULE_TYPE_FILTER == m_typeRule)
|
|
{
|
|
if (0 != (dwFlags & ENUMF_POP3))
|
|
{
|
|
if (RULEID_VIEW_DOWNLOADED == pNodeHead->ridRule)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
pNodeNew = new RULENODE;
|
|
if (NULL == pNodeNew)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize new node
|
|
pNodeNew->pNext = NULL;
|
|
pNodeNew->pIRule = pNodeHead->pIRule;
|
|
pNodeNew->pIRule->AddRef();
|
|
|
|
// Add the new node to the list
|
|
if (NULL == pNodeWalk)
|
|
{
|
|
m_pNodeHead = pNodeNew;
|
|
pNodeWalk = pNodeNew;
|
|
}
|
|
else
|
|
{
|
|
pNodeWalk->pNext = pNodeNew;
|
|
pNodeWalk = pNodeNew;
|
|
}
|
|
pNodeNew = NULL;
|
|
}
|
|
|
|
// Set the current to the front of the chain
|
|
m_pNodeCurr = m_pNodeHead;
|
|
|
|
// Set return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
if (pNodeNew)
|
|
delete pNodeNew;
|
|
return hr;
|
|
}
|
|
|
|
// The Rule Executor object
|
|
CExecRules::~CExecRules()
|
|
{
|
|
RULENODE * pNodeNext = NULL;
|
|
|
|
AssertSz(m_cRef == 0, "Somebody still has a hold of us!!");
|
|
|
|
// Walk the list and free each item
|
|
while (NULL != m_pNodeHead)
|
|
{
|
|
// Save off the next item
|
|
pNodeNext = m_pNodeHead->pNext;
|
|
|
|
// Release the rule
|
|
AssertSz(NULL != m_pNodeHead->pIRule, "Where the heck is the rule???");
|
|
m_pNodeHead->pIRule->Release();
|
|
|
|
// Free up the node
|
|
delete m_pNodeHead;
|
|
|
|
// Move to the next item
|
|
m_pNodeHead = pNodeNext;
|
|
}
|
|
|
|
// Free up the cached objects
|
|
_HrReleaseFolderObjects();
|
|
_HrReleaseFileObjects();
|
|
_HrReleaseSoundFiles();
|
|
|
|
// Free the folder list
|
|
SafeMemFree(m_pRuleFolder);
|
|
m_cRuleFolderAlloc = 0;
|
|
|
|
// Free the file list
|
|
SafeMemFree(m_pRuleFile);
|
|
m_cRuleFileAlloc = 0;
|
|
|
|
// Free the file list
|
|
SafeMemFree(m_ppszSndFile);
|
|
m_cpszSndFileAlloc = 0;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CExecRules::AddRef()
|
|
{
|
|
return ::InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CExecRules::Release()
|
|
{
|
|
LONG cRef = 0;
|
|
|
|
cRef = ::InterlockedDecrement(&m_cRef);
|
|
if (0 == cRef)
|
|
{
|
|
delete this;
|
|
return cRef;
|
|
}
|
|
|
|
return cRef;
|
|
}
|
|
|
|
STDMETHODIMP CExecRules::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_IOEExecRules))
|
|
{
|
|
*ppvObject = static_cast<IOEExecRules *>(this);
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
goto exit;
|
|
}
|
|
|
|
reinterpret_cast<IUnknown *>(*ppvObject)->AddRef();
|
|
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CExecRules::GetState(DWORD * pdwState)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Check incoming params
|
|
if (NULL == pdwState)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
*pdwState = m_dwState;
|
|
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CExecRules::ExecuteRules(DWORD dwFlags, LPCSTR pszAcct, MESSAGEINFO * pMsgInfo,
|
|
IMessageFolder * pFolder, IMimePropertySet * pIMPropSet,
|
|
IMimeMessage * pIMMsg, ULONG cbMsgSize,
|
|
ACT_ITEM ** ppActions, ULONG * pcActions)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0;
|
|
RULENODE * pNodeWalk = NULL;
|
|
ACT_ITEM * pActions = NULL;
|
|
ULONG cActions = 0;
|
|
ACT_ITEM * pActionsList = NULL;
|
|
ULONG cActionsList = 0;
|
|
ACT_ITEM * pActionsNew = NULL;
|
|
ULONG cActionsNew = 0;
|
|
BOOL fStopProcessing = FALSE;
|
|
BOOL fMatch = FALSE;
|
|
DWORD dwState = 0;
|
|
|
|
// Check incoming params
|
|
if (((NULL == pMsgInfo) && (NULL == pIMPropSet)) ||
|
|
(0 == cbMsgSize) || (NULL == ppActions) || (NULL == pcActions))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize outgoing param
|
|
*ppActions = NULL;
|
|
*pcActions = 0;
|
|
|
|
// Should we skip partial messages?
|
|
if ((NULL != pIMPropSet) &&
|
|
(S_OK == pIMPropSet->IsContentType(STR_CNT_MESSAGE, STR_SUB_PARTIAL)) &&
|
|
(0 != (dwFlags & ERF_SKIPPARTIALS)))
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Walk the list of rules executing each one
|
|
pNodeWalk = m_pNodeHead;
|
|
while (NULL != pNodeWalk)
|
|
{
|
|
Assert(NULL != pNodeWalk->pIRule);
|
|
|
|
// If we are only checking server rules
|
|
// Bail if we need more information...
|
|
if (0 != (dwFlags & ERF_ONLYSERVER))
|
|
{
|
|
hr = pNodeWalk->pIRule->GetState(&dwState);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Do we need more information...
|
|
if (0 != (dwState & CRIT_STATE_ALL))
|
|
{
|
|
hr = S_FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Evaluate the rule
|
|
hr = pNodeWalk->pIRule->Evaluate(pszAcct, pMsgInfo, pFolder, pIMPropSet, pIMMsg, cbMsgSize, &pActions, &cActions);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Did we have a match
|
|
if (S_OK == hr)
|
|
{
|
|
// We've matched at least once
|
|
fMatch = TRUE;
|
|
ulIndex = 0;
|
|
|
|
// If these are server actions
|
|
if ((1 == cActions) && ((ACT_TYPE_DELETESERVER == pActions[ulIndex].type) ||
|
|
(ACT_TYPE_DONTDOWNLOAD == pActions[ulIndex].type)))
|
|
{
|
|
// If this is our only action
|
|
if (0 == cActionsList)
|
|
{
|
|
// Save the action
|
|
pActionsList = pActions;
|
|
pActions = NULL;
|
|
cActionsList = cActions;
|
|
|
|
// We are done
|
|
fStopProcessing = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// We already have to do something with it
|
|
// so skip over this action
|
|
RuleUtil_HrFreeActionsItem(pActions, cActions);
|
|
SafeMemFree(pActions);
|
|
|
|
// Move to the next rule
|
|
pNodeWalk = pNodeWalk->pNext;
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Should we stop after merging these?
|
|
for (ulIndex = 0; ulIndex < cActions; ulIndex++)
|
|
{
|
|
if (ACT_TYPE_STOP == pActions[ulIndex].type)
|
|
{
|
|
fStopProcessing = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Merge these items with the previous ones
|
|
hr = RuleUtil_HrMergeActions(pActionsList, cActionsList, pActions, cActions, &pActionsNew, &cActionsNew);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Free up the previous ones
|
|
RuleUtil_HrFreeActionsItem(pActionsList, cActionsList);
|
|
SafeMemFree(pActionsList);
|
|
RuleUtil_HrFreeActionsItem(pActions, cActions);
|
|
SafeMemFree(pActions);
|
|
|
|
// Save off the new ones
|
|
pActionsList = pActionsNew;
|
|
pActionsNew = NULL;
|
|
cActionsList = cActionsNew;
|
|
}
|
|
|
|
// Should we continue...
|
|
if (FALSE != fStopProcessing)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Move to the next rule
|
|
pNodeWalk = pNodeWalk->pNext;
|
|
}
|
|
|
|
// Set outgoing param
|
|
*ppActions = pActionsList;
|
|
pActionsList = NULL;
|
|
*pcActions = cActionsList;
|
|
|
|
// Set the return value
|
|
hr = (FALSE != fMatch) ? S_OK : S_FALSE;
|
|
|
|
exit:
|
|
RuleUtil_HrFreeActionsItem(pActionsNew, cActionsNew);
|
|
SafeMemFree(pActionsNew);
|
|
RuleUtil_HrFreeActionsItem(pActions, cActions);
|
|
SafeMemFree(pActions);
|
|
RuleUtil_HrFreeActionsItem(pActionsList, cActionsList);
|
|
SafeMemFree(pActionsList);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CExecRules::ReleaseObjects(VOID)
|
|
{
|
|
// Free up the folders
|
|
_HrReleaseFolderObjects();
|
|
|
|
// Free up the files
|
|
_HrReleaseFileObjects();
|
|
|
|
// Free up the sound files
|
|
_HrReleaseSoundFiles();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CExecRules::GetRuleFolder(FOLDERID idFolder, DWORD_PTR * pdwFolder)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0;
|
|
RULE_FOLDER * pRuleFolderWalk = NULL;
|
|
IMessageFolder *pFolder = NULL;
|
|
|
|
// Check incoming param
|
|
if ((FOLDERID_INVALID == idFolder) || (NULL == pdwFolder))
|
|
{
|
|
hr =E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize outgoing param
|
|
*pdwFolder = NULL;
|
|
|
|
// Let's search for the folder
|
|
for (ulIndex = 0; ulIndex < m_cRuleFolder; ulIndex++)
|
|
{
|
|
pRuleFolderWalk = &(m_pRuleFolder[ulIndex]);
|
|
if (idFolder == pRuleFolderWalk->idFolder)
|
|
{
|
|
Assert(NULL != pRuleFolderWalk->pFolder);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If we didn't find it then let's open it and lock it...
|
|
if (ulIndex >= m_cRuleFolder)
|
|
{
|
|
// Do we need to alloc any more spaces
|
|
if (m_cRuleFolder >= m_cRuleFolderAlloc)
|
|
{
|
|
hr = HrRealloc((LPVOID *) &m_pRuleFolder, sizeof(*m_pRuleFolder) * (m_cRuleFolderAlloc + RULE_FOLDER_ALLOC));
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the new rule folders
|
|
ZeroMemory(m_pRuleFolder + m_cRuleFolderAlloc, sizeof(*m_pRuleFolder) * RULE_FOLDER_ALLOC);
|
|
for (ulIndex = m_cRuleFolderAlloc; ulIndex < (m_cRuleFolderAlloc + RULE_FOLDER_ALLOC); ulIndex++)
|
|
{
|
|
m_pRuleFolder[ulIndex].idFolder = FOLDERID_INVALID;
|
|
}
|
|
m_cRuleFolderAlloc += RULE_FOLDER_ALLOC;
|
|
}
|
|
|
|
// Open the folder
|
|
hr = g_pStore->OpenFolder(idFolder, NULL, NOFLAGS, &pFolder);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
m_pRuleFolder[m_cRuleFolder].idFolder = idFolder;
|
|
m_pRuleFolder[m_cRuleFolder].pFolder = pFolder;
|
|
pFolder = NULL;
|
|
pRuleFolderWalk = &(m_pRuleFolder[m_cRuleFolder]);
|
|
m_cRuleFolder++;
|
|
}
|
|
|
|
*pdwFolder = (DWORD_PTR) (pRuleFolderWalk->pFolder);
|
|
|
|
// Set the proper return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
if (NULL != pFolder)
|
|
pFolder->Release();
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CExecRules::GetRuleFile(LPCSTR pszFile, IStream ** ppstmFile, DWORD * pdwType)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0;
|
|
RULE_FILE * pRuleFileWalk = NULL;
|
|
IStream * pIStmFile = NULL;
|
|
LPSTR pszExt = NULL;
|
|
DWORD dwType = RFT_FILE;
|
|
|
|
// Check incoming param
|
|
if ((NULL == pszFile) || (NULL == ppstmFile) || (NULL == pdwType))
|
|
{
|
|
hr =E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize outgoing param
|
|
*ppstmFile = NULL;
|
|
*pdwType = NULL;
|
|
|
|
// Let's search for the file
|
|
for (ulIndex = 0; ulIndex < m_cRuleFile; ulIndex++)
|
|
{
|
|
pRuleFileWalk = &(m_pRuleFile[ulIndex]);
|
|
if (0 == lstrcmpi(pRuleFileWalk->pszFile, pszFile))
|
|
{
|
|
Assert(NULL != pRuleFileWalk->pstmFile);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If we didn't find it then let's open it...
|
|
if (ulIndex >= m_cRuleFile)
|
|
{
|
|
// Do we need to alloc any more space
|
|
if (m_cRuleFile >= m_cRuleFileAlloc)
|
|
{
|
|
hr = HrRealloc((LPVOID *) &m_pRuleFile, sizeof(*m_pRuleFile) * (m_cRuleFileAlloc + RULE_FILE_ALLOC));
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the new rule file
|
|
ZeroMemory(m_pRuleFile + m_cRuleFileAlloc, sizeof(*m_pRuleFile) * RULE_FILE_ALLOC);
|
|
m_cRuleFileAlloc += RULE_FILE_ALLOC;
|
|
}
|
|
|
|
// Open a stream on the file
|
|
hr = CreateStreamOnHFile((LPTSTR) pszFile, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL, &pIStmFile);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Lets split the file name and get the extension
|
|
pszExt = PathFindExtension(pszFile);
|
|
if ((0 == lstrcmpi(pszExt, c_szHtmExt)) || (0 == lstrcmpi(pszExt, c_szHtmlExt)))
|
|
{
|
|
dwType = RFT_HTML;
|
|
}
|
|
// Text File...
|
|
else if (0 == lstrcmpi(pszExt, c_szTxtExt))
|
|
{
|
|
dwType = RFT_TEXT;
|
|
}
|
|
// Else .nws or .eml file...
|
|
else if ((0 == lstrcmpi(pszExt, c_szEmlExt)) || (0 == lstrcmpi(pszExt, c_szNwsExt)))
|
|
{
|
|
dwType = RFT_MESSAGE;
|
|
}
|
|
// Otherwise, its an attachment
|
|
else
|
|
{
|
|
dwType = RFT_FILE;
|
|
}
|
|
|
|
// Save off the info
|
|
m_pRuleFile[m_cRuleFile].pszFile = PszDupA(pszFile);
|
|
if (NULL == m_pRuleFile[m_cRuleFile].pszFile)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
m_pRuleFile[m_cRuleFile].pstmFile = pIStmFile;
|
|
pIStmFile = NULL;
|
|
m_pRuleFile[m_cRuleFile].dwType = dwType;
|
|
|
|
pRuleFileWalk = &(m_pRuleFile[m_cRuleFile]);
|
|
m_cRuleFile++;
|
|
}
|
|
|
|
*ppstmFile = pRuleFileWalk->pstmFile;
|
|
(*ppstmFile)->AddRef();
|
|
*pdwType = pRuleFileWalk->dwType;
|
|
|
|
// Set the proper return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
SafeRelease(pIStmFile);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CExecRules::AddSoundFile(DWORD dwFlags, LPCSTR pszSndFile)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0;
|
|
|
|
// Check incoming param
|
|
if (NULL == pszSndFile)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
// Let's search for the file
|
|
for (ulIndex = 0; ulIndex < m_cpszSndFile; ulIndex++)
|
|
{
|
|
Assert(NULL != m_ppszSndFile[ulIndex]);
|
|
if (0 == lstrcmpi(m_ppszSndFile[ulIndex], pszSndFile))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If we didn't find it then let's open it...
|
|
if (ulIndex >= m_cpszSndFile)
|
|
{
|
|
// Do we need to alloc any more space
|
|
if (m_cpszSndFile >= m_cpszSndFileAlloc)
|
|
{
|
|
hr = HrRealloc((LPVOID *) &m_ppszSndFile, sizeof(*m_ppszSndFile) * (m_cpszSndFileAlloc + SND_FILE_ALLOC));
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize the new rule file
|
|
ZeroMemory(m_ppszSndFile + m_cpszSndFileAlloc, sizeof(*m_ppszSndFile) * SND_FILE_ALLOC);
|
|
m_cpszSndFileAlloc += SND_FILE_ALLOC;
|
|
}
|
|
|
|
// Save off the info
|
|
m_ppszSndFile[m_cpszSndFile] = PszDupA(pszSndFile);
|
|
if (NULL == m_ppszSndFile[m_cpszSndFile])
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
// Should we play it?
|
|
if (0 != (dwFlags & ASF_PLAYIFNEW))
|
|
{
|
|
sndPlaySound(m_ppszSndFile[m_cpszSndFile], SND_NODEFAULT | SND_SYNC);
|
|
}
|
|
|
|
m_cpszSndFile++;
|
|
|
|
}
|
|
|
|
// Set the proper return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CExecRules::PlaySounds(DWORD dwFlags)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0;
|
|
|
|
// Let's search for the file
|
|
for (ulIndex = 0; ulIndex < m_cpszSndFile; ulIndex++)
|
|
{
|
|
Assert(NULL != m_ppszSndFile[ulIndex]);
|
|
sndPlaySound(m_ppszSndFile[ulIndex], SND_NODEFAULT | SND_SYNC);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CExecRules::_HrReleaseFolderObjects(VOID)
|
|
{
|
|
RULE_FOLDER * pRuleFolder = NULL;
|
|
ULONG ulIndex = 0;
|
|
|
|
for (ulIndex = 0; ulIndex < m_cRuleFolder; ulIndex++)
|
|
{
|
|
pRuleFolder = &(m_pRuleFolder[ulIndex]);
|
|
|
|
Assert(FOLDERID_INVALID != pRuleFolder->idFolder);
|
|
|
|
// If we have the folder opened then close it
|
|
SafeRelease(pRuleFolder->pFolder);
|
|
|
|
// Reset the folder list
|
|
pRuleFolder->idFolder = FOLDERID_INVALID;
|
|
}
|
|
|
|
// Let's clear out the number of messages
|
|
m_cRuleFolder = 0;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CExecRules::_HrReleaseFileObjects(VOID)
|
|
{
|
|
RULE_FILE * pRuleFile = NULL;
|
|
ULONG ulIndex = 0;
|
|
|
|
for (ulIndex = 0; ulIndex < m_cRuleFile; ulIndex++)
|
|
{
|
|
pRuleFile = &(m_pRuleFile[ulIndex]);
|
|
|
|
Assert(NULL != pRuleFile->pszFile);
|
|
|
|
// If we have the file opened then close it
|
|
SafeRelease(pRuleFile->pstmFile);
|
|
|
|
// Clear the file
|
|
SafeMemFree(pRuleFile->pszFile);
|
|
pRuleFile->dwType = RFT_FILE;
|
|
}
|
|
|
|
// Let's clear out the number of file
|
|
m_cRuleFile = 0;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CExecRules::_HrReleaseSoundFiles(VOID)
|
|
{
|
|
ULONG ulIndex = 0;
|
|
|
|
for (ulIndex = 0; ulIndex < m_cpszSndFile; ulIndex++)
|
|
{
|
|
Assert(NULL != m_ppszSndFile[ulIndex]);
|
|
|
|
// Clear the file
|
|
SafeMemFree(m_ppszSndFile[ulIndex]);
|
|
}
|
|
|
|
// Let's clear out the number of file
|
|
m_cpszSndFile = 0;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CExecRules::_HrInitialize(DWORD dwFlags, RULENODE * pNodeHead)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
RULENODE * pNodeNew = NULL;
|
|
RULENODE * pNodeWalk = NULL;
|
|
DWORD dwState = 0;
|
|
PROPVARIANT propvar;
|
|
|
|
if (NULL == pNodeHead)
|
|
{
|
|
hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
for (pNodeWalk = m_pNodeHead; NULL != pNodeHead; pNodeHead = pNodeHead->pNext)
|
|
{
|
|
// Skip rules that are disabled
|
|
if (0 != (dwFlags & ERF_ONLY_ENABLED))
|
|
{
|
|
hr = pNodeHead->pIRule->GetProp(RULE_PROP_DISABLED, 0, &propvar);
|
|
Assert(VT_BOOL == propvar.vt);
|
|
if (FAILED(hr) || (FALSE != propvar.boolVal))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Skip rules that are invalid
|
|
if (0 != (dwFlags & ERF_ONLY_VALID))
|
|
{
|
|
hr = pNodeHead->pIRule->Validate(dwFlags);
|
|
if (FAILED(hr) || (S_FALSE == hr))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
pNodeNew = new RULENODE;
|
|
if (NULL == pNodeNew)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize new node
|
|
pNodeNew->pNext = NULL;
|
|
pNodeNew->pIRule = pNodeHead->pIRule;
|
|
pNodeNew->pIRule->AddRef();
|
|
|
|
// Add the new node to the list
|
|
if (NULL == pNodeWalk)
|
|
{
|
|
m_pNodeHead = pNodeNew;
|
|
pNodeWalk = pNodeNew;
|
|
}
|
|
else
|
|
{
|
|
pNodeWalk->pNext = pNodeNew;
|
|
pNodeWalk = pNodeNew;
|
|
}
|
|
pNodeNew = NULL;
|
|
|
|
// Calculate state from message
|
|
if (SUCCEEDED(pNodeWalk->pIRule->GetState(&dwState)))
|
|
{
|
|
// Let's set the proper Criteria state
|
|
if ((m_dwState & CRIT_STATE_MASK) < (dwState & CRIT_STATE_MASK))
|
|
{
|
|
m_dwState = (m_dwState & ~CRIT_STATE_MASK) | (dwState & CRIT_STATE_MASK);
|
|
}
|
|
|
|
// Let's set the proper Action state
|
|
if (0 != (dwState & ACT_STATE_MASK))
|
|
{
|
|
m_dwState |= (dwState & ACT_STATE_MASK);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set return value
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
if (pNodeNew)
|
|
delete pNodeNew;
|
|
return hr;
|
|
}
|
|
|