542 lines
14 KiB
C++
542 lines
14 KiB
C++
/*++
|
||
|
||
© 1998 Seagate Software, Inc. All rights reserved.
|
||
|
||
Module Name:
|
||
|
||
hsmrlstk.cpp
|
||
|
||
Abstract:
|
||
|
||
This component represents the set of rules that are in effect for directory currently
|
||
being scanned for one policy.
|
||
|
||
Author:
|
||
|
||
Chuck Bardeen [cbardeen] 29-Oct-1996
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "stdafx.h"
|
||
|
||
#include "wsb.h"
|
||
#include "job.h"
|
||
#include "hsmrlstk.h"
|
||
|
||
#define WSB_TRACE_IS WSB_TRACE_BIT_JOB
|
||
|
||
|
||
HRESULT
|
||
CHsmRuleStack::Do(
|
||
IN IFsaScanItem* pScanItem
|
||
)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IHsmRuleStack::Do().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRuleStack::Do"), OLESTR(""));
|
||
|
||
try {
|
||
WsbAssert(0 != pScanItem, E_POINTER);
|
||
WsbAssert(m_pAction != 0, E_UNEXPECTED);
|
||
|
||
WsbAffirmHr(m_pAction->Do(pScanItem));
|
||
} WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRuleStack::Do"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRuleStack::DoesMatch(
|
||
IN IFsaScanItem* pScanItem,
|
||
OUT BOOL* pShouldDo
|
||
)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IHsmRuleStack::DoesMatch().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
HRESULT hrNameMatch = S_OK; // Used for event logging only
|
||
CComPtr<IWsbEnum> pEnumCriteria;
|
||
CComPtr<IHsmRule> pRule;
|
||
CComPtr<IHsmCriteria> pCriteria;
|
||
BOOL isMatched = FALSE;
|
||
BOOL ruleMatched = FALSE; // Used for event logging only
|
||
BOOL shouldCheck;
|
||
CWsbStringPtr name;
|
||
CWsbStringPtr path;
|
||
CWsbStringPtr rulePath;
|
||
BOOL shouldDo = FALSE;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRuleStack::DoesMatch"), OLESTR(""));
|
||
|
||
try {
|
||
|
||
WsbAssert(0 != pScanItem, E_POINTER);
|
||
WsbAssert(0 != pShouldDo, E_POINTER);
|
||
|
||
*pShouldDo = FALSE;
|
||
|
||
// NOTE: The matching code starts at the bottom of the list and looks for
|
||
// the first rule that matches. This makes it important how the list is organized.
|
||
// Currently, the Push() method does not make any attempts to organize the list, so
|
||
// it is up to whoever configure the rules in the policy definition to have it
|
||
// organized properly. A proper order within a directory would be to have the specific
|
||
// rules (i.e. no wildcards) after the wildcard rules (i.e. specific searched first).
|
||
|
||
// Start we the last rule in the collection, and search upwards until a
|
||
// rule is found that matches or all rules have been checked.
|
||
WsbAffirmHr(pScanItem->GetName(&name, 0));
|
||
hr = m_pEnumStackRules->Last(IID_IHsmRule, (void**) &pRule);
|
||
|
||
while (SUCCEEDED(hr) && !isMatched) {
|
||
|
||
try {
|
||
|
||
shouldCheck = TRUE;
|
||
|
||
// If the rule only applies to the directory it was defined in, then make
|
||
// sure that the item is from that directory.
|
||
if (pRule->IsUsedInSubDirs() == S_FALSE) {
|
||
|
||
// Unfortunately, these two paths differ by an appended \ when they
|
||
// are otherwise the same, so make them the same.
|
||
WsbAffirmHr(pScanItem->GetPath(&path, 0));
|
||
|
||
if ((wcslen(path) > 1) && (path[(int) (wcslen(path) - 1)] == L'\\')) {
|
||
path[(int) (wcslen(path) - 1)] = 0;
|
||
}
|
||
|
||
rulePath.Free();
|
||
WsbAffirmHr(pRule->GetPath(&rulePath, 0));
|
||
|
||
if ((wcslen(rulePath) > 1) && (rulePath[(int) (wcslen(rulePath) - 1)] == L'\\')) {
|
||
rulePath[(int) (wcslen(rulePath) - 1)] = 0;
|
||
}
|
||
|
||
if (_wcsicmp(path, rulePath) != 0) {
|
||
shouldCheck = FALSE;
|
||
}
|
||
}
|
||
|
||
if (shouldCheck) {
|
||
|
||
|
||
// Does the name of the rule match the name of the file?
|
||
hrNameMatch = pRule->MatchesName(name);
|
||
WsbAffirmHrOk(hrNameMatch);
|
||
|
||
ruleMatched = TRUE;
|
||
// Do the criteria match the attributes of the file?
|
||
isMatched = TRUE;
|
||
pEnumCriteria = 0;
|
||
WsbAffirmHr(pRule->EnumCriteria(&pEnumCriteria));
|
||
pCriteria = 0;
|
||
WsbAffirmHr(pEnumCriteria->First(IID_IHsmCriteria, (void**) &pCriteria));
|
||
|
||
while (isMatched) {
|
||
HRESULT hrShouldDo;
|
||
|
||
hrShouldDo = pCriteria->ShouldDo(pScanItem, m_scale);
|
||
if (S_FALSE == hrShouldDo) {
|
||
isMatched = FALSE;
|
||
} else if (S_OK == hrShouldDo) {
|
||
pCriteria = 0;
|
||
WsbAffirmHr(pEnumCriteria->Next(IID_IHsmCriteria, (void**) &pCriteria));
|
||
} else {
|
||
WsbThrow(hrShouldDo);
|
||
}
|
||
}
|
||
}
|
||
|
||
} WsbCatchAndDo(hr, if (WSB_E_NOTFOUND == hr) {hr = S_OK;} else {isMatched = FALSE;});
|
||
|
||
// If it didn't match, then try the next rule.
|
||
if (SUCCEEDED(hr) && !isMatched) {
|
||
pRule = 0;
|
||
WsbAffirmHr(m_pEnumStackRules->Previous(IID_IHsmRule, (void**) &pRule));
|
||
}
|
||
}
|
||
|
||
// Include rules mean that we should do the operation and exclude rules
|
||
// mean that we should not.
|
||
if (SUCCEEDED(hr)) {
|
||
if (isMatched) {
|
||
hr = S_OK;
|
||
if (pRule->IsInclude() == S_OK) {
|
||
shouldDo = TRUE;
|
||
}
|
||
} else {
|
||
hr = S_FALSE;
|
||
}
|
||
}
|
||
|
||
|
||
if ((FALSE == shouldDo) && (FALSE == ruleMatched)) {
|
||
//
|
||
// Log that we skipped the file because it didn't
|
||
// match a rule
|
||
//
|
||
CWsbStringPtr jobName;
|
||
CWsbStringPtr fileName;
|
||
CComPtr<IHsmSession> pSession;
|
||
|
||
pScanItem->GetFullPathAndName( 0, 0, &fileName, 0);
|
||
pScanItem->GetSession(&pSession);
|
||
pSession->GetName(&jobName, 0);
|
||
|
||
WsbLogEvent(JOB_MESSAGE_SCAN_FILESKIPPED_NORULE, 0, NULL, (OLECHAR *)jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hrNameMatch), NULL);
|
||
}
|
||
|
||
|
||
|
||
*pShouldDo = shouldDo;
|
||
|
||
} WsbCatchAndDo(hr, if (WSB_E_NOTFOUND == hr) {hr = S_FALSE;});
|
||
|
||
WsbTraceOut(OLESTR("CHsmRuleStack::DoesMatch"), OLESTR("hr = <%ls>, shouldDo = <%ls>"), WsbHrAsString(hr), WsbBoolAsString(shouldDo));
|
||
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRuleStack::FinalConstruct(
|
||
void
|
||
)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
CComObjectRoot::FinalConstruct().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
WsbAffirmHr(CWsbObject::FinalConstruct());
|
||
|
||
m_scale = HSM_JOBSCALE_100;
|
||
m_usesDefaults = TRUE;
|
||
|
||
//Create the criteria collection.
|
||
WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, NULL, CLSCTX_ALL, IID_IWsbCollection, (void**) &m_pRules));
|
||
WsbAffirmHr(m_pRules->Enum(&m_pEnumStackRules));
|
||
|
||
} WsbCatch(hr);
|
||
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRuleStack::GetClassID(
|
||
OUT CLSID* pClsid
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IPersist::GetClassID().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRuleStack::GetClassID"), OLESTR(""));
|
||
|
||
try {
|
||
|
||
WsbAssert(0 != pClsid, E_POINTER);
|
||
*pClsid = CLSID_CHsmRuleStack;
|
||
|
||
} WsbCatch(hr);
|
||
WsbTraceOut(OLESTR("CHsmRuleStack::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
|
||
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRuleStack::GetSizeMax(
|
||
OUT ULARGE_INTEGER* pSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IPersistStream::GetSizeMax().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = E_NOTIMPL;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRuleStack::GetSizeMax"), OLESTR(""));
|
||
WsbTraceOut(OLESTR("CHsmRuleStack::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pSize));
|
||
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRuleStack::Init(
|
||
IN IHsmPolicy* pPolicy,
|
||
IN IFsaResource* pResource
|
||
)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IHsmRuleStack::Init().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
|
||
WsbAssert(0 != pPolicy, E_POINTER);
|
||
|
||
WsbAffirmHr(pPolicy->GetScale(&m_scale));
|
||
WsbAffirmHr(pPolicy->GetAction(&m_pAction));
|
||
WsbAffirmHr(pPolicy->EnumRules(&m_pEnumPolicyRules));
|
||
|
||
if (pPolicy->UsesDefaultRules() == S_OK) {
|
||
m_usesDefaults = TRUE;
|
||
} else {
|
||
m_usesDefaults = FALSE;
|
||
}
|
||
|
||
m_pPolicy = pPolicy;
|
||
|
||
WsbAffirmHr(pResource->EnumDefaultRules(&m_pEnumDefaultRules));
|
||
|
||
} WsbCatch(hr);
|
||
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRuleStack::Load(
|
||
IN IStream* /*pStream*/
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IPersistStream::Load().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = E_NOTIMPL;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRuleStack::Load"), OLESTR(""));
|
||
WsbTraceOut(OLESTR("CHsmRuleStack::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRuleStack::Pop(
|
||
IN OLECHAR* path
|
||
)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IHsmRuleStack::Pop().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
CWsbStringPtr rulePath;
|
||
CComPtr<IHsmRule> pRule;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRuleStack::Pop"), OLESTR(""));
|
||
|
||
try {
|
||
|
||
WsbAssert(0 != path, E_POINTER);
|
||
|
||
// Starting at the end of the list, remove any rules that have the same
|
||
// path as the one specified.
|
||
WsbAffirmHr(m_pEnumStackRules->Last(IID_IHsmRule, (void**) &pRule));
|
||
WsbAffirmHr(pRule->GetPath(&rulePath, 0));
|
||
|
||
while(_wcsicmp(path, rulePath) == 0) {
|
||
WsbAffirmHr(m_pRules->RemoveAndRelease(pRule));
|
||
pRule = 0;
|
||
WsbAffirmHr(m_pEnumStackRules->Last(IID_IHsmRule, (void**) &pRule));
|
||
rulePath.Free();
|
||
WsbAffirmHr(pRule->GetPath(&rulePath, 0));
|
||
}
|
||
|
||
} WsbCatchAndDo(hr, if (WSB_E_NOTFOUND == hr) {hr = S_OK;});
|
||
|
||
WsbTraceOut(OLESTR("CHsmRuleStack::Pop"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRuleStack::Push(
|
||
IN OLECHAR* path
|
||
)
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IHsmRuleStack::Push().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
CWsbStringPtr rulePath;
|
||
CComPtr<IHsmRule> pRule;
|
||
CComPtr<IWsbIndexedCollection> pCollection;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRuleStack::Push"), OLESTR(""));
|
||
|
||
try {
|
||
|
||
WsbAssert(0 != path, E_POINTER);
|
||
|
||
// We need to preserve the order of the rules, so use the indexed collection interface.
|
||
WsbAffirmHr(m_pRules->QueryInterface(IID_IWsbIndexedCollection, (void**) &pCollection));
|
||
|
||
// Add any policy rules for this directory to the stack.
|
||
//
|
||
// NOTE: We may want to add some code to check for exclusion rules of the
|
||
// entire directory (with no subdirectory inclusions and return the
|
||
// JOB_E_DIREXCLUDED error to skip scanning of the directory.
|
||
//
|
||
// NOTE: It might be nice if the policy rules were a sorted collection to
|
||
// speed up processing.
|
||
hr = m_pEnumPolicyRules->First(IID_IHsmRule, (void**) &pRule);
|
||
|
||
while (SUCCEEDED(hr)) {
|
||
|
||
rulePath.Free();
|
||
WsbAffirmHr(pRule->GetPath(&rulePath, 0));
|
||
if (_wcsicmp(path, rulePath) == 0) {
|
||
WsbAffirmHr(pCollection->Append(pRule));
|
||
WsbTrace(OLESTR("CHsmRuleStack::Push - Using policy rule <%ls>.\n"), (OLECHAR *)rulePath);
|
||
|
||
}
|
||
|
||
pRule = 0;
|
||
hr = m_pEnumPolicyRules->Next(IID_IHsmRule, (void**) &pRule);
|
||
}
|
||
|
||
if (WSB_E_NOTFOUND == hr) {
|
||
hr = S_OK;
|
||
}
|
||
|
||
// Add any default rules for this directory to the stack.
|
||
if (m_usesDefaults) {
|
||
|
||
hr = m_pEnumDefaultRules->First(IID_IHsmRule, (void**) &pRule);
|
||
|
||
while (SUCCEEDED(hr)) {
|
||
|
||
rulePath.Free();
|
||
WsbAffirmHr(pRule->GetPath(&rulePath, 0));
|
||
if (_wcsicmp(path, rulePath) == 0) {
|
||
WsbAffirmHr(pCollection->Append(pRule));
|
||
WsbTrace(OLESTR("CHsmRuleStack::Push -- Using default rule <%ls>.\n"), (OLECHAR *)rulePath);
|
||
}
|
||
|
||
pRule = 0;
|
||
hr = m_pEnumDefaultRules->Next(IID_IHsmRule, (void**) &pRule);
|
||
}
|
||
} else {
|
||
WsbTrace(OLESTR("CHsmRuleStack::Push -- Not using default rules.\n"));
|
||
|
||
}
|
||
|
||
if (WSB_E_NOTFOUND == hr) {
|
||
hr = S_OK;
|
||
}
|
||
|
||
} WsbCatch(hr);
|
||
|
||
WsbTraceOut(OLESTR("CHsmRuleStack::Push"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRuleStack::Save(
|
||
IN IStream* /*pStream*/,
|
||
IN BOOL clearDirty
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IPersistStream::Save().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = E_NOTIMPL;
|
||
|
||
WsbTraceIn(OLESTR("CHsmRuleStack::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty));
|
||
WsbTraceOut(OLESTR("CHsmRuleStack::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
||
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CHsmRuleStack::Test(
|
||
USHORT* passed,
|
||
USHORT* failed
|
||
)
|
||
|
||
/*++
|
||
|
||
Implements:
|
||
|
||
IWsbTestable::Test().
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
try {
|
||
|
||
WsbAssert(0 != passed, E_POINTER);
|
||
WsbAssert(0 != failed, E_POINTER);
|
||
|
||
*passed = 0;
|
||
*failed = 0;
|
||
|
||
} WsbCatch(hr);
|
||
|
||
return(hr);
|
||
}
|