959 lines
26 KiB
C++
959 lines
26 KiB
C++
|
/*++
|
|||
|
|
|||
|
<EFBFBD> 1998 Seagate Software, Inc. All rights reserved.
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
fsascan.cpp
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This class represents a scanning process that is being carried out upon one FsaResource.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Chuck Bardeen [cbardeen] 16-Feb-1997
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "stdafx.h"
|
|||
|
|
|||
|
#include "wsb.h"
|
|||
|
#include "fsa.h"
|
|||
|
#include "job.h"
|
|||
|
#include "hsmscan.h"
|
|||
|
|
|||
|
#define WSB_TRACE_IS WSB_TRACE_BIT_JOB
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD HsmStartScanner(
|
|||
|
void* pVoid
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return(((CHsmScanner*) pVoid)->StartScan());
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::Cancel(
|
|||
|
HSM_JOB_EVENT event
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Implements:
|
|||
|
|
|||
|
IHsmScanner::Cancel().
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
// If we have started, but haven't finished, then change the state of the job. The thread
|
|||
|
// will exit on it's own.
|
|||
|
if ((HSM_JOB_STATE_IDLE != m_state) &&
|
|||
|
(HSM_JOB_STATE_DONE != m_state) &&
|
|||
|
(HSM_JOB_STATE_FAILED != m_state) &&
|
|||
|
(HSM_JOB_STATE_CANCELLED != m_state)) {
|
|||
|
|
|||
|
if (HSM_JOB_EVENT_CANCEL == event) {
|
|||
|
WsbAffirmHr(SetState(HSM_JOB_STATE_CANCELLED));
|
|||
|
} else if (HSM_JOB_EVENT_SUSPEND == event) {
|
|||
|
WsbAffirmHr(SetState(HSM_JOB_STATE_SUSPENDED));
|
|||
|
} else if (HSM_JOB_EVENT_FAIL == event) {
|
|||
|
WsbAffirmHr(SetState(HSM_JOB_STATE_FAILED));
|
|||
|
} else {
|
|||
|
WsbAssert(FALSE, E_UNEXPECTED);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::DoIfMatches(
|
|||
|
IN IFsaScanItem* pScanItem
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Implements:
|
|||
|
|
|||
|
IHsmScanner::DoIfMatches().
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
HRESULT hrDo = S_OK;
|
|||
|
HRESULT hrShould = S_OK;
|
|||
|
BOOL notMatched = TRUE;
|
|||
|
BOOL shouldDo = FALSE;
|
|||
|
CComPtr<IHsmRuleStack> pRuleStack;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CFsaScanner::DoIfMatches"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
// Each policy has it's own rule stack, check each one of until a match is found (if
|
|||
|
// one exists).
|
|||
|
WsbAffirmHr(m_pEnumStacks->First(IID_IHsmRuleStack, (void**) &pRuleStack));
|
|||
|
|
|||
|
while (notMatched) {
|
|||
|
|
|||
|
hr = pRuleStack->DoesMatch(pScanItem, &shouldDo);
|
|||
|
|
|||
|
if (S_OK == hr) {
|
|||
|
notMatched = FALSE;
|
|||
|
if (!shouldDo) {
|
|||
|
hrShould = JOB_E_FILEEXCLUDED;
|
|||
|
}
|
|||
|
} else if (S_FALSE == hr) {
|
|||
|
pRuleStack = 0;
|
|||
|
WsbAffirmHr(m_pEnumStacks->Next(IID_IHsmRuleStack, (void**) &pRuleStack));
|
|||
|
} else {
|
|||
|
// Something totally unexpected happened so we'd better quit
|
|||
|
WsbThrow(hr);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} WsbCatchAndDo(hr,
|
|||
|
|
|||
|
if (WSB_E_NOTFOUND == hr) {
|
|||
|
hrShould = JOB_E_DOESNTMATCH;
|
|||
|
hr = S_OK;
|
|||
|
} else {
|
|||
|
hrShould = hr;
|
|||
|
}
|
|||
|
|
|||
|
);
|
|||
|
|
|||
|
// Just Do It!!
|
|||
|
if (SUCCEEDED(hr) && shouldDo) {
|
|||
|
|
|||
|
hrDo = pRuleStack->Do(pScanItem);
|
|||
|
|
|||
|
// Tell the session if we ended up skipping the file or not.
|
|||
|
m_pSession->ProcessItem(HSM_JOB_PHASE_SCAN, HSM_JOB_ACTION_SCAN, pScanItem, hrDo);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
// Tell the session if we decided to skip the file.
|
|||
|
m_pSession->ProcessItem(HSM_JOB_PHASE_SCAN, HSM_JOB_ACTION_SCAN, pScanItem, hrShould);
|
|||
|
}
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CFsaScanner::DoIfMatches"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
#pragma optimize("g", off)
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::FinalConstruct(
|
|||
|
void
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Implements:
|
|||
|
|
|||
|
CComObjectRoot::FinalConstruct().
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
WsbAffirmHr(CComObjectRoot::FinalConstruct());
|
|||
|
|
|||
|
m_state = HSM_JOB_STATE_IDLE;
|
|||
|
m_priority = HSM_JOB_PRIORITY_NORMAL;
|
|||
|
m_threadHandle = 0;
|
|||
|
m_threadId = 0;
|
|||
|
m_threadHr = S_OK;
|
|||
|
m_eventCookie = 0;
|
|||
|
m_skipHiddenItems = TRUE;
|
|||
|
m_skipSystemItems = TRUE;
|
|||
|
m_useRPIndex = FALSE;
|
|||
|
m_useDbIndex = FALSE;
|
|||
|
m_event = 0;
|
|||
|
|
|||
|
// Create a collection for the rule stacks, and store an enumerator to it.
|
|||
|
WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, NULL, CLSCTX_ALL, IID_IWsbCollection, (void**) &m_pRuleStacks));
|
|||
|
WsbAffirmHr(m_pRuleStacks->Enum(&m_pEnumStacks));
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
#pragma optimize("", on)
|
|||
|
|
|||
|
void
|
|||
|
CHsmScanner::FinalRelease(
|
|||
|
void
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Implements:
|
|||
|
|
|||
|
CComObjectRoot::FinalRelease().
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
// Cleanup the thread we were using.
|
|||
|
if (m_threadHandle != 0) {
|
|||
|
m_state = HSM_JOB_STATE_DONE;
|
|||
|
|
|||
|
if (0 != m_event) {
|
|||
|
SetEvent(m_event);
|
|||
|
}
|
|||
|
|
|||
|
// Should we wait for the thread to end?
|
|||
|
CloseHandle(m_threadHandle);
|
|||
|
m_threadHandle = 0;
|
|||
|
}
|
|||
|
if (m_event) {
|
|||
|
CloseHandle(m_event);
|
|||
|
m_event = 0;
|
|||
|
}
|
|||
|
|
|||
|
CComObjectRoot::FinalRelease();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::LowerPriority(
|
|||
|
void
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
WsbAssert(0 != m_threadHandle, E_UNEXPECTED);
|
|||
|
WsbAssert(m_pSession != 0, E_UNEXPECTED);
|
|||
|
|
|||
|
switch(m_priority) {
|
|||
|
case HSM_JOB_PRIORITY_IDLE:
|
|||
|
WsbAffirm(FALSE, E_UNEXPECTED);
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_PRIORITY_LOWEST:
|
|||
|
WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_IDLE));
|
|||
|
m_priority = HSM_JOB_PRIORITY_IDLE;
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_PRIORITY_LOW:
|
|||
|
WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_LOWEST));
|
|||
|
m_priority = HSM_JOB_PRIORITY_LOWEST;
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_PRIORITY_NORMAL:
|
|||
|
WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_BELOW_NORMAL));
|
|||
|
m_priority = HSM_JOB_PRIORITY_LOW;
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_PRIORITY_HIGH:
|
|||
|
WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_NORMAL));
|
|||
|
m_priority = HSM_JOB_PRIORITY_NORMAL;
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_PRIORITY_HIGHEST:
|
|||
|
WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_ABOVE_NORMAL));
|
|||
|
m_priority = HSM_JOB_PRIORITY_HIGH;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
case HSM_JOB_PRIORITY_CRITICAL:
|
|||
|
WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_HIGHEST));
|
|||
|
m_priority = HSM_JOB_PRIORITY_HIGHEST;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
WsbAffirmHr(m_pSession->ProcessPriority(HSM_JOB_PHASE_SCAN, m_priority));
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::Pause(
|
|||
|
void
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Implements:
|
|||
|
|
|||
|
IHsmScanner::Pause().
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CFsaScanner::Pause"), OLESTR(""));
|
|||
|
|
|||
|
// Lock();
|
|||
|
try {
|
|||
|
|
|||
|
// If we are running, then suspend the thread.
|
|||
|
WsbAssert((HSM_JOB_STATE_STARTING == m_state) || (HSM_JOB_STATE_ACTIVE == m_state)
|
|||
|
|| (HSM_JOB_STATE_RESUMING == m_state), E_UNEXPECTED);
|
|||
|
|
|||
|
// Set state to pausing -- the thread will pause itself when it
|
|||
|
// sees the state
|
|||
|
WsbAffirmHr(SetState(HSM_JOB_STATE_PAUSING));
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
// Unlock();
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CFsaScanner::Pause"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::PopRules(
|
|||
|
IN OLECHAR* path
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
CComPtr<IHsmRuleStack> pRuleStack;
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
// Each policy has it's own rule stack, and each of them will need to have rules removed
|
|||
|
// from it for this directory (if any rules were added).
|
|||
|
for (hr = m_pEnumStacks->First(IID_IHsmRuleStack, (void**) &pRuleStack);
|
|||
|
SUCCEEDED(hr);
|
|||
|
hr = m_pEnumStacks->Next(IID_IHsmRuleStack, (void**) &pRuleStack)) {
|
|||
|
|
|||
|
WsbAffirmHr(pRuleStack->Pop(path));
|
|||
|
pRuleStack = 0;
|
|||
|
}
|
|||
|
|
|||
|
if (WSB_E_NOTFOUND == hr) {
|
|||
|
hr = S_OK;
|
|||
|
}
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::ProcessSessionEvent(
|
|||
|
IN IHsmSession* pSession,
|
|||
|
IN HSM_JOB_PHASE phase,
|
|||
|
IN HSM_JOB_EVENT event
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
WsbAssert(0 != pSession, E_POINTER);
|
|||
|
|
|||
|
// If the phase applies to use (SCAN or ALL), then do any work required by the
|
|||
|
// event.
|
|||
|
if ((HSM_JOB_PHASE_ALL == phase) || (HSM_JOB_PHASE_SCAN == phase)) {
|
|||
|
|
|||
|
switch(event) {
|
|||
|
|
|||
|
case HSM_JOB_EVENT_SUSPEND:
|
|||
|
case HSM_JOB_EVENT_CANCEL:
|
|||
|
case HSM_JOB_EVENT_FAIL:
|
|||
|
WsbAffirmHr(Cancel(event));
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_EVENT_PAUSE:
|
|||
|
WsbAffirmHr(Pause());
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_EVENT_RESUME:
|
|||
|
WsbAffirmHr(Resume());
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_EVENT_RAISE_PRIORITY:
|
|||
|
WsbAffirmHr(RaisePriority());
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_EVENT_LOWER_PRIORITY:
|
|||
|
WsbAffirmHr(LowerPriority());
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
case HSM_JOB_EVENT_START:
|
|||
|
WsbAssert(FALSE, E_UNEXPECTED);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
|
|||
|
return(S_OK);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::PushRules(
|
|||
|
IN OLECHAR* path
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
CComPtr<IHsmRuleStack> pRuleStack;
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
// Save an indicator to where we are in the scan, so we can use it if we are interrupted
|
|||
|
// or need to give an indication to the session.
|
|||
|
m_currentPath = path;
|
|||
|
|
|||
|
// Each policy has it's own rule stack, and each of them will need to have rules added
|
|||
|
// for this directory (if any rules exist).
|
|||
|
for (hr = m_pEnumStacks->First(IID_IHsmRuleStack, (void**) &pRuleStack);
|
|||
|
SUCCEEDED(hr);
|
|||
|
hr = m_pEnumStacks->Next(IID_IHsmRuleStack, (void**) &pRuleStack)) {
|
|||
|
|
|||
|
WsbAffirmHr(pRuleStack->Push(path));
|
|||
|
pRuleStack = 0;
|
|||
|
}
|
|||
|
|
|||
|
if (WSB_E_NOTFOUND == hr) {
|
|||
|
hr = S_OK;
|
|||
|
}
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::RaisePriority(
|
|||
|
void
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
WsbAssert(0 != m_threadHandle, E_UNEXPECTED);
|
|||
|
WsbAssert(m_pSession != 0, E_UNEXPECTED);
|
|||
|
|
|||
|
switch(m_priority) {
|
|||
|
|
|||
|
case HSM_JOB_PRIORITY_IDLE:
|
|||
|
WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_LOWEST));
|
|||
|
m_priority = HSM_JOB_PRIORITY_LOWEST;
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_PRIORITY_LOWEST:
|
|||
|
WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_BELOW_NORMAL));
|
|||
|
m_priority = HSM_JOB_PRIORITY_LOW;
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_PRIORITY_LOW:
|
|||
|
WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_NORMAL));
|
|||
|
m_priority = HSM_JOB_PRIORITY_NORMAL;
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_PRIORITY_NORMAL:
|
|||
|
WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_ABOVE_NORMAL));
|
|||
|
m_priority = HSM_JOB_PRIORITY_HIGH;
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_PRIORITY_HIGH:
|
|||
|
WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_HIGHEST));
|
|||
|
m_priority = HSM_JOB_PRIORITY_HIGHEST;
|
|||
|
break;
|
|||
|
|
|||
|
case HSM_JOB_PRIORITY_HIGHEST:
|
|||
|
WsbAffirmStatus(SetThreadPriority(m_threadHandle, THREAD_PRIORITY_TIME_CRITICAL));
|
|||
|
m_priority = HSM_JOB_PRIORITY_CRITICAL;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
case HSM_JOB_PRIORITY_CRITICAL:
|
|||
|
WsbAffirm(FALSE, E_UNEXPECTED);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
WsbAffirmHr(m_pSession->ProcessPriority(HSM_JOB_PHASE_SCAN, m_priority));
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::Resume(
|
|||
|
void
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Implements:
|
|||
|
|
|||
|
IHsmScanner::Resume().
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
HSM_JOB_STATE oldState;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CFsaScanner::Resume"), OLESTR(""));
|
|||
|
|
|||
|
// Lock();
|
|||
|
try {
|
|||
|
|
|||
|
// If we are paused, then suspend the thread.
|
|||
|
WsbAffirm((HSM_JOB_STATE_PAUSING == m_state) || (HSM_JOB_STATE_PAUSED == m_state), E_UNEXPECTED);
|
|||
|
|
|||
|
oldState = m_state;
|
|||
|
WsbAffirmHr(SetState(HSM_JOB_STATE_RESUMING));
|
|||
|
|
|||
|
// If we are unable to resume, then return to the former state.
|
|||
|
try {
|
|||
|
WsbAffirm(SetEvent(m_event), HRESULT_FROM_WIN32(GetLastError()));
|
|||
|
} WsbCatchAndDo(hr, SetState(oldState););
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
// Unlock();
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CFsaScanner::Resume"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::ScanPath(
|
|||
|
IN OLECHAR* dirPath
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
CComPtr<IFsaScanItem> pScanItem;
|
|||
|
CWsbStringPtr searchPath;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CFsaScanner::ScanPath"), OLESTR("%ls"), WsbAbbreviatePath(dirPath, WSB_TRACE_BUFF_SIZE));
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
WsbAssert(0 != dirPath, E_POINTER);
|
|||
|
WsbAssert(0 != dirPath[0], E_INVALIDARG);
|
|||
|
|
|||
|
// Pop the rules for this files. This sets the context for the scan to follow.
|
|||
|
WsbAffirmHr(PushRules(dirPath));
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
// Iterate over all the files and directories in the specified path.
|
|||
|
searchPath = dirPath;
|
|||
|
if (searchPath[(int) (wcslen(searchPath) - 1)] == L'\\') {
|
|||
|
WsbAffirmHr(searchPath.Append("*"));
|
|||
|
} else {
|
|||
|
WsbAffirmHr(searchPath.Append("\\*"));
|
|||
|
}
|
|||
|
|
|||
|
if (m_useDbIndex) {
|
|||
|
hr = m_pResource->FindFirstInDbIndex(m_pSession, &pScanItem);
|
|||
|
} else if (m_useRPIndex) {
|
|||
|
hr = m_pResource->FindFirstInRPIndex(m_pSession, &pScanItem);
|
|||
|
} else {
|
|||
|
hr = m_pResource->FindFirst(searchPath, m_pSession, &pScanItem);
|
|||
|
}
|
|||
|
while (SUCCEEDED(hr) && ((HSM_JOB_STATE_ACTIVE == m_state) ||
|
|||
|
(HSM_JOB_STATE_RESUMING == m_state) ||
|
|||
|
(HSM_JOB_STATE_PAUSING == m_state))) {
|
|||
|
|
|||
|
// Check for a pause request
|
|||
|
// Lock();
|
|||
|
if (HSM_JOB_STATE_PAUSING == m_state) {
|
|||
|
hr = SetState(HSM_JOB_STATE_PAUSED);
|
|||
|
// Unlock();
|
|||
|
WsbAffirmHr(hr);
|
|||
|
|
|||
|
// Suspend the thread here & wait for resume signal
|
|||
|
WsbTrace(OLESTR("CHsmScanner::ScanPath: pausing\n"));
|
|||
|
WaitForSingleObject(m_event, 0xffffffff);
|
|||
|
WsbTrace(OLESTR("CHsmScanner::ScanPath: woke up, state = %d\n"),
|
|||
|
(int)m_state);
|
|||
|
|
|||
|
// Lock();
|
|||
|
if (HSM_JOB_STATE_RESUMING != m_state) {
|
|||
|
// Unlock();
|
|||
|
break;
|
|||
|
}
|
|||
|
hr = SetState(HSM_JOB_STATE_ACTIVE);
|
|||
|
if (S_OK != hr) {
|
|||
|
// Unlock();
|
|||
|
WsbThrow(hr);
|
|||
|
}
|
|||
|
}
|
|||
|
// Unlock();
|
|||
|
|
|||
|
// Skip hidden and/or system items if so configured.
|
|||
|
if (!((m_skipHiddenItems && (pScanItem->IsHidden() == S_OK)) ||
|
|||
|
(m_skipSystemItems && (pScanItem->IsSystem() == S_OK)))) {
|
|||
|
|
|||
|
// Ignore ".", "..", symbolic links and mount points.
|
|||
|
if ((pScanItem->IsARelativeParent() == S_FALSE) &&
|
|||
|
(pScanItem->IsALink() == S_FALSE)) {
|
|||
|
|
|||
|
// Recursively scan subdirectories.
|
|||
|
if (pScanItem->IsAParent() == S_OK) {
|
|||
|
WsbAffirmHr(pScanItem->GetPathAndName(OLESTR(""), &searchPath, 0));
|
|||
|
WsbAffirmHr(ScanPath(searchPath));
|
|||
|
}
|
|||
|
|
|||
|
// If this file matches a policy then perform the action.
|
|||
|
else {
|
|||
|
WsbAffirmHr(DoIfMatches(pScanItem));
|
|||
|
}
|
|||
|
} else {
|
|||
|
WsbTrace(OLESTR("CHsmScanner::ScanPath skipping - symbolic link, '.', or '..'\n"));
|
|||
|
}
|
|||
|
} else {
|
|||
|
WsbTrace(OLESTR("CHsmScanner::ScanPath skipping - hidden/system\n"));
|
|||
|
}
|
|||
|
if (m_useDbIndex) {
|
|||
|
hr = m_pResource->FindNextInDbIndex(pScanItem);
|
|||
|
} else if (m_useRPIndex) {
|
|||
|
hr = m_pResource->FindNextInRPIndex(pScanItem);
|
|||
|
} else {
|
|||
|
hr = m_pResource->FindNext(pScanItem);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// If we broke out as a result of end of scan or some other error ...
|
|||
|
if (hr != S_OK) {
|
|||
|
WsbAssert(hr == WSB_E_NOTFOUND, hr);
|
|||
|
hr = S_OK;
|
|||
|
}
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
|
|||
|
// Pop the rules for this directory. This restores the context as we pop back up the directory
|
|||
|
// structure.
|
|||
|
WsbAffirmHr(PopRules(dirPath));
|
|||
|
|
|||
|
} WsbCatchAndDo(hr, if (JOB_E_DIREXCLUDED == hr) {hr = S_OK;});
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CFsaScanner::ScanPath"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::SetState(
|
|||
|
IN HSM_JOB_STATE state
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
BOOL bLog = TRUE;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CFsaScanner::SetState"), OLESTR("old state = %d, new state = %d"),
|
|||
|
(int)m_state, (int)state);
|
|||
|
|
|||
|
// Lock();
|
|||
|
try {
|
|||
|
|
|||
|
// Change the state and report the change to the session.
|
|||
|
m_state = state;
|
|||
|
WsbAffirmHr(m_pSession->ProcessState(HSM_JOB_PHASE_SCAN, m_state, m_currentPath, bLog));
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
// Unlock();
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CFsaScanner::SetState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::Start(
|
|||
|
IN IHsmSession* pSession,
|
|||
|
IN OLECHAR* path
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Implements:
|
|||
|
|
|||
|
IHsmScanner::Start().
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
CComPtr<IHsmJobDef> pDef;
|
|||
|
CComPtr<IHsmPolicy> pPolicy;
|
|||
|
CComPtr<IHsmRuleStack> pRuleStack;
|
|||
|
CComPtr<IWsbEnum> pEnumPolicies;
|
|||
|
CComPtr<IConnectionPointContainer> pCPC;
|
|||
|
CComPtr<IConnectionPoint> pCP;
|
|||
|
CComPtr<IHsmSessionSinkEveryEvent> pSink;
|
|||
|
DWORD cookie;
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
// Make sure that we were given a session, and that we haven't started already.
|
|||
|
WsbAssert(0 != pSession, E_POINTER);
|
|||
|
WsbAssert(HSM_JOB_STATE_IDLE == m_state, E_UNEXPECTED);
|
|||
|
|
|||
|
// Store off the session.
|
|||
|
m_pSession = pSession;
|
|||
|
|
|||
|
// If no directory was specified, then start in the root of the resource.
|
|||
|
if ((0 != path) && (0 != *path)) {
|
|||
|
m_startingPath = path;
|
|||
|
} else {
|
|||
|
m_startingPath = OLESTR("\\");
|
|||
|
}
|
|||
|
|
|||
|
m_currentPath = m_startingPath;
|
|||
|
|
|||
|
// Tell them we are starting.
|
|||
|
WsbAffirmHr(SetState(HSM_JOB_STATE_STARTING));
|
|||
|
|
|||
|
// Create an event to control pause/resume for the scan.
|
|||
|
if (0 == m_event) {
|
|||
|
CWsbStringPtr nameString;
|
|||
|
GUID id;
|
|||
|
|
|||
|
WsbAffirmHr(m_pSession->GetIdentifier(&id));
|
|||
|
nameString = id;
|
|||
|
nameString.Prepend(OLESTR("Scanner Pause and Resume Event for session "));
|
|||
|
m_event = CreateEvent(NULL, FALSE, FALSE, nameString);
|
|||
|
}
|
|||
|
|
|||
|
// Ask the session to advise of every event.
|
|||
|
WsbAffirmHr(pSession->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC));
|
|||
|
WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryEvent, &pCP));
|
|||
|
WsbAffirmHr(((IUnknown*) (IHsmScanner*) this)->QueryInterface(IID_IHsmSessionSinkEveryEvent, (void**) &pSink));
|
|||
|
WsbAffirmHr(pCP->Advise(pSink, &cookie));
|
|||
|
|
|||
|
// Store off the information needed to latter unadvise.
|
|||
|
m_eventCookie = cookie;
|
|||
|
|
|||
|
try {
|
|||
|
// Locate the resource that is being scanned.
|
|||
|
WsbAffirmHr(m_pSession->GetResource(&m_pResource));
|
|||
|
|
|||
|
// Create and initialize a rule stack for each policy.
|
|||
|
WsbAffirmHr(pSession->GetJob(&m_pJob));
|
|||
|
WsbAffirmHr(m_pJob->GetDef(&pDef));
|
|||
|
WsbAffirmHr(pDef->EnumPolicies(&pEnumPolicies));
|
|||
|
|
|||
|
for (hr = pEnumPolicies->First(IID_IHsmPolicy, (void**) &pPolicy);
|
|||
|
SUCCEEDED(hr);
|
|||
|
hr = pEnumPolicies->Next(IID_IHsmPolicy, (void**) &pPolicy)) {
|
|||
|
|
|||
|
WsbAffirmHr(CoCreateInstance(CLSID_CHsmRuleStack, NULL, CLSCTX_ALL, IID_IHsmRuleStack, (void**) &pRuleStack));
|
|||
|
WsbAffirmHr(pRuleStack->Init(pPolicy, m_pResource));
|
|||
|
WsbAffirmHr(m_pRuleStacks->Add(pRuleStack));
|
|||
|
|
|||
|
pRuleStack = 0;
|
|||
|
pPolicy = 0;
|
|||
|
}
|
|||
|
|
|||
|
if (WSB_E_NOTFOUND == hr) {
|
|||
|
hr = S_OK;
|
|||
|
}
|
|||
|
|
|||
|
// Determine whether hidden and system items should be skipped?
|
|||
|
if (pDef->SkipHiddenItems() == S_FALSE) {
|
|||
|
m_skipHiddenItems = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if (pDef->SkipSystemItems() == S_FALSE) {
|
|||
|
m_skipSystemItems = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// Determine whether to use the Reparse Point Index for the scan?
|
|||
|
if (pDef->UseRPIndex() == S_OK) {
|
|||
|
m_useRPIndex = TRUE;
|
|||
|
}
|
|||
|
// Determine whether to use the Database Index for the scan?
|
|||
|
if (pDef->UseDbIndex() == S_OK) {
|
|||
|
m_useDbIndex = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
// Now that we have prepared, create the thread that will do the scanning!
|
|||
|
WsbAffirm((m_threadHandle = CreateThread(0, 0, HsmStartScanner, (void*) this, 0, &m_threadId)) != 0, HRESULT_FROM_WIN32(GetLastError()));
|
|||
|
|
|||
|
} WsbCatchAndDo(hr, SetState(HSM_JOB_STATE_FAILED););
|
|||
|
|
|||
|
if (FAILED(hr)) {
|
|||
|
WsbThrow(hr);
|
|||
|
}
|
|||
|
|
|||
|
} WsbCatchAndDo(hr,
|
|||
|
pCP->Unadvise(m_eventCookie);
|
|||
|
m_eventCookie = 0;
|
|||
|
);
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
HRESULT
|
|||
|
CHsmScanner::StartScan(
|
|||
|
void
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
HRESULT hr2 = S_OK;
|
|||
|
CComPtr<IConnectionPointContainer> pCPC;
|
|||
|
CComPtr<IConnectionPoint> pCP;
|
|||
|
|
|||
|
WsbTraceIn(OLESTR("CFsaScanner::StartScan"), OLESTR(""));
|
|||
|
|
|||
|
try {
|
|||
|
CComPtr<IFsaTruncator> pTruncator;
|
|||
|
CComPtr<IHsmSession> pTruncatorSession;
|
|||
|
|
|||
|
CComPtr<IHsmJobDef> pDef;
|
|||
|
CComPtr<IHsmActionOnResourcePreScan> pActionPreScan;
|
|||
|
|
|||
|
// The thread is running.
|
|||
|
WsbAffirmHr(SetState(HSM_JOB_STATE_ACTIVE));
|
|||
|
|
|||
|
// To avoid having the RP Index order changed by the truncator,
|
|||
|
// we pause the truncator
|
|||
|
if (m_useRPIndex) {
|
|||
|
WsbAffirmHr(m_pResource->GetTruncator(&pTruncator));
|
|||
|
if (pTruncator) {
|
|||
|
WsbAffirmHr(pTruncator->GetSession(&pTruncatorSession));
|
|||
|
if (pTruncatorSession) {
|
|||
|
WsbAffirmHr(pTruncatorSession->ProcessEvent(HSM_JOB_PHASE_ALL,
|
|||
|
HSM_JOB_EVENT_PAUSE));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Get the pre-scan action and do it (if exists)
|
|||
|
WsbAffirmHr(m_pJob->GetDef(&pDef));
|
|||
|
WsbAffirmHr(pDef->GetPreScanActionOnResource(&pActionPreScan));
|
|||
|
if (pActionPreScan) {
|
|||
|
WsbTrace(OLESTR("CHsmScanner::StartScan: doing pre-scan action\n"));
|
|||
|
|
|||
|
//Don't throw hr - we need the cleanup code that is done after the scanning
|
|||
|
hr = pActionPreScan->Do(m_pResource, m_pSession);
|
|||
|
}
|
|||
|
|
|||
|
// Start with the first path and scan the resource (only if pre-scan succeeded)
|
|||
|
if (SUCCEEDED(hr)) {
|
|||
|
m_threadHr = ScanPath(m_startingPath);
|
|||
|
}
|
|||
|
|
|||
|
// Resume the truncator if we paused it
|
|||
|
if (pTruncatorSession) {
|
|||
|
pTruncatorSession->ProcessEvent(HSM_JOB_PHASE_ALL,
|
|||
|
HSM_JOB_EVENT_RESUME);
|
|||
|
}
|
|||
|
|
|||
|
// Clear out the information about the thread;
|
|||
|
WsbAffirmStatus(CloseHandle(m_threadHandle));
|
|||
|
m_threadId = 0;
|
|||
|
m_threadHandle = 0;
|
|||
|
|
|||
|
} WsbCatch(hr);
|
|||
|
|
|||
|
// The thread is exiting, so record
|
|||
|
if (FAILED(hr) || FAILED(m_threadHr)) {
|
|||
|
hr2 = SetState(HSM_JOB_STATE_FAILED);
|
|||
|
if (FAILED(hr2)) {
|
|||
|
m_pSession->ProcessHr(HSM_JOB_PHASE_ALL, __FILE__, __LINE__, hr2);
|
|||
|
}
|
|||
|
} else {
|
|||
|
hr2 = SetState(HSM_JOB_STATE_DONE);
|
|||
|
if (FAILED(hr2)) {
|
|||
|
m_pSession->ProcessHr(HSM_JOB_PHASE_ALL, __FILE__, __LINE__, hr2);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// Regardless of how this thread is exiting, we need to unadvise from the session.
|
|||
|
// Indicate that we no longer want to be advised of events.
|
|||
|
if ((m_pSession != 0) && (m_eventCookie != 0)) {
|
|||
|
try {
|
|||
|
WsbAffirmHr(m_pSession->QueryInterface(IID_IConnectionPointContainer, (void**) &pCPC));
|
|||
|
WsbAffirmHr(pCPC->FindConnectionPoint(IID_IHsmSessionSinkEveryEvent, &pCP));
|
|||
|
pCP->Unadvise(m_eventCookie);
|
|||
|
} WsbCatch(hr);
|
|||
|
}
|
|||
|
|
|||
|
WsbTraceOut(OLESTR("CFsaScanner::StartScan"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|||
|
|
|||
|
return(hr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|