mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5858 lines
161 KiB
5858 lines
161 KiB
|
|
/*++
|
|
|
|
(c) 1998 Seagate Software, Inc. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
fsarsc.cpp
|
|
|
|
Abstract:
|
|
|
|
This class represents a file system resource (i.e. volume)
|
|
for NTFS 5.0.
|
|
|
|
Author:
|
|
|
|
Chuck Bardeen [cbardeen] 1-Dec-1996
|
|
|
|
--*/
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#define WSB_TRACE_IS WSB_TRACE_BIT_FSA
|
|
|
|
#include "wsb.h"
|
|
#include "fsa.h"
|
|
#include "fsaprem.h"
|
|
#include "fsaprv.h"
|
|
#include "fsarcvy.h"
|
|
#include "fsarsc.h"
|
|
#include "fsasrvr.h"
|
|
#include "engine.h"
|
|
#include "HsmConn.h"
|
|
#include "job.h"
|
|
#include "task.h"
|
|
#include "mstask.h"
|
|
#include <shlobj.h>
|
|
|
|
static short g_InstanceCount = 0;
|
|
static DWORD g_ThreadId;
|
|
|
|
|
|
DWORD FsaStartOnStateChange(
|
|
void* pVoid
|
|
)
|
|
/*++
|
|
|
|
Note: This is done as a separate thread to avoid a deadlock situation
|
|
|
|
--*/
|
|
{
|
|
((CFsaResource*) pVoid)->OnStateChange();
|
|
return(0);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::AddPremigrated(
|
|
IN IFsaScanItem* pScanItem,
|
|
IN LONGLONG offset,
|
|
IN LONGLONG size,
|
|
IN BOOL isWaitingForClose,
|
|
IN LONGLONG usn
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::AddPremigrated().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IWsbDbSession> pDbSession;
|
|
CComPtr<IFsaPremigratedRec> pRec;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::AddPremigrated"), OLESTR("offset = %I64d, size = %I64d, waiting = <%ls>, usn = <%I64d>"),
|
|
offset, size, WsbBoolAsString(isWaitingForClose), usn);
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pScanItem, E_POINTER);
|
|
WsbAffirm(m_pPremigrated != NULL, E_UNEXPECTED);
|
|
WsbAffirm(m_isDbInitialized, S_FALSE); // Not an necessarily an error
|
|
|
|
// Open the data base
|
|
WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
|
|
|
|
try {
|
|
|
|
WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, PREMIGRATED_REC_TYPE, IID_IFsaPremigratedRec, (void**) &pRec));
|
|
WsbAffirmHr(pRec->UseKey(PREMIGRATED_BAGID_OFFSETS_KEY_TYPE));
|
|
WsbAffirmHr(pRec->SetFromScanItem(pScanItem, offset, size, isWaitingForClose));
|
|
WsbAffirmHr(pRec->SetFileUSN(usn));
|
|
|
|
// If the key doesn't exist, then create it.
|
|
if (FAILED(pRec->FindEQ())) {
|
|
WsbAffirmHr(pRec->MarkAsNew());
|
|
WsbAffirmHr(pRec->Write());
|
|
|
|
// Add the size of the section migrated to the amount of premigrated data.
|
|
m_premigratedSize += size;
|
|
}
|
|
|
|
// Otherwise, update it.
|
|
else {
|
|
LONGLONG itemSize;
|
|
|
|
WsbAffirmHr(pRec->GetSize(&itemSize));
|
|
WsbAffirmHr(pRec->SetFromScanItem(pScanItem, offset, size, isWaitingForClose));
|
|
WsbAffirmHr(pRec->Write());
|
|
if (m_isDoingValidate) {
|
|
m_premigratedSize += size;
|
|
} else if (itemSize != size) {
|
|
m_premigratedSize = max(0, (m_premigratedSize - itemSize) + size);
|
|
}
|
|
}
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
// Close the data base
|
|
WsbAffirmHr(m_pPremigrated->Close(pDbSession));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::AddPremigrated"),
|
|
OLESTR("hr = <%ls>, m_premigratedSize = %I64d"), WsbHrAsString(hr),
|
|
m_premigratedSize);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::AddPremigratedSize(
|
|
IN LONGLONG size
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::AddPremigratedSize().
|
|
|
|
--*/
|
|
{
|
|
WsbTraceIn(OLESTR("CFsaResource::AddPremigratedSize"), OLESTR("m_premigratedSize = %I64d"), m_premigratedSize);
|
|
|
|
m_isDirty = TRUE;
|
|
m_premigratedSize += size;
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::AddPremigratedSize"), OLESTR("m_premigratedSize = %I64d"), m_premigratedSize);
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::AddTruncated(
|
|
IN IFsaScanItem* /*pScanItem*/,
|
|
IN LONGLONG /*offset*/,
|
|
IN LONGLONG size
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::AddTruncated().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::AddTruncated"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
m_truncatedSize += size;
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::AddTruncated"),
|
|
OLESTR("hr = <%ls>, m_truncatedSize = %I64d"), WsbHrAsString(hr),
|
|
m_truncatedSize);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::AddTruncatedSize(
|
|
IN LONGLONG size
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::AddTruncatedSize().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::AddTruncatedSize"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
m_truncatedSize += size;
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::AddTruncatedSize"), OLESTR("hr = <%ls>, m_truncatedSize = %I64d"), WsbHrAsString(hr), m_truncatedSize);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::BeginSession(
|
|
IN OLECHAR* name,
|
|
IN ULONG logControl,
|
|
IN ULONG runId,
|
|
IN ULONG subRunId,
|
|
OUT IHsmSession** ppSession
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::BeginSession().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IHsmSession> pSession;
|
|
BOOL bLog = TRUE;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::BeginSession"), OLESTR("name = <%ls>, Log = <%lu>, runId = <%lu>, subRunId = <%lu>"),
|
|
(OLECHAR *)name, logControl, runId, subRunId);
|
|
try {
|
|
|
|
WsbAssert(0 != ppSession, E_POINTER);
|
|
*ppSession = 0;
|
|
|
|
// Create and Initialize a session object.
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CHsmSession, 0, CLSCTX_SERVER, IID_IHsmSession, (void**) &pSession));
|
|
WsbAffirmHr(pSession->Start(name, logControl, m_managingHsm, 0, (IFsaResource*) this, runId, subRunId));
|
|
|
|
// Since begin sesson doesn't use a formal scan, indicate that the scan phase has
|
|
// started.
|
|
WsbAffirmHr(pSession->ProcessState(HSM_JOB_PHASE_SCAN, HSM_JOB_STATE_STARTING, OLESTR(""),bLog));
|
|
|
|
// Return the session to the caller.
|
|
*ppSession = pSession;
|
|
pSession->AddRef();
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::BeginSession"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::BeginValidate(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::BeginValidate().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::BeginValidate"),
|
|
OLESTR("PremigratedSize = %I64d, TruncatedSize = %I64d"),
|
|
m_premigratedSize, m_truncatedSize);
|
|
|
|
try {
|
|
|
|
m_oldPremigratedSize = m_premigratedSize;
|
|
m_premigratedSize = 0;
|
|
m_oldTruncatedSize = m_truncatedSize;
|
|
m_truncatedSize = 0;
|
|
m_isDoingValidate = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::BeginValidate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CheckForJournal(
|
|
BOOL *pValidateNeeded
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::CheckForJournal
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONGLONG usnSize, usnId;
|
|
DWORD spc, bps, freeC, totalC;
|
|
CWsbStringPtr name;
|
|
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::CheckForJournal"),OLESTR("volume = %ls"), m_path);
|
|
//
|
|
// First we check the USN journal and determine if it is out of date.
|
|
//
|
|
try {
|
|
hr = WsbGetUsnJournalId(m_path, &usnId);
|
|
|
|
if (S_OK == hr) {
|
|
WsbTrace(OLESTR("CFsaResource::CheckForJournal - USN Journal ID = %I64x\n"),
|
|
usnId);
|
|
if (0 != m_usnJournalId && usnId != m_usnJournalId) {
|
|
WsbTrace(OLESTR("CFsaResource::CheckForJournal - USN Journal ID changed from %I64\n"),
|
|
m_usnJournalId);
|
|
*pValidateNeeded = TRUE; // No match - we must validate
|
|
// WsbAffirmHr(E_FAIL);
|
|
}
|
|
} else if (WSB_E_NOTFOUND == hr) {
|
|
|
|
hr = S_OK;
|
|
|
|
// The journal is not active, try to create it.
|
|
// Make the max USN journal 1/64 the volume size.
|
|
//
|
|
WsbTrace(OLESTR("CFsaResource::CheckForJournal - Failed to get the journal ID for %ws\n"), m_path);
|
|
|
|
name = m_path;
|
|
WsbAffirmHr(name.Prepend(OLESTR("\\\\?\\")));
|
|
if (GetDiskFreeSpace(name, &spc, &bps, &freeC, &totalC)) {
|
|
ULONGLONG freeBytes, totalBytes;
|
|
ULONGLONG minSize, maxSize;
|
|
ULONG freeSpaceFraction, totalSpaceFraction, minSizeMB, maxSizeMB;
|
|
|
|
WsbTrace(OLESTR("CFsaResource::CheckForJournal - Got disk free space\n"));
|
|
|
|
freeBytes = (ULONGLONG) spc * (ULONGLONG) bps * (ULONGLONG) freeC;
|
|
totalBytes = (ULONGLONG) spc * (ULONGLONG) bps * (ULONGLONG) totalC;
|
|
|
|
// Get constants for USN size calculation
|
|
minSizeMB = FSA_USN_MIN_SIZE_DEFAULT;
|
|
WsbAffirmHr(WsbRegistryValueUlongAsString(NULL, FSA_REGISTRY_PARMS, FSA_USN_MIN_SIZE,
|
|
&minSizeMB));
|
|
minSize = (ULONGLONG)minSizeMB * (ULONGLONG)0x100000;
|
|
|
|
maxSizeMB = FSA_USN_MAX_SIZE_DEFAULT;
|
|
WsbAffirmHr(WsbRegistryValueUlongAsString(NULL, FSA_REGISTRY_PARMS, FSA_USN_MAX_SIZE,
|
|
&maxSizeMB));
|
|
maxSize = (ULONGLONG)maxSizeMB * (ULONGLONG)0x100000;
|
|
|
|
freeSpaceFraction = FSA_USN_FREE_SPACE_FRACTION_DEFAULT;
|
|
WsbAffirmHr(WsbRegistryValueUlongAsString(NULL, FSA_REGISTRY_PARMS, FSA_USN_FREE_SPACE_FRACTION,
|
|
&freeSpaceFraction));
|
|
|
|
totalSpaceFraction = FSA_USN_TOTAL_SPACE_FRACTION_DEFAULT;
|
|
WsbAffirmHr(WsbRegistryValueUlongAsString(NULL, FSA_REGISTRY_PARMS, FSA_USN_TOTAL_SPACE_FRACTION,
|
|
&totalSpaceFraction));
|
|
|
|
// Get a max value out of fraction-of-free=space and a constant
|
|
// This ensures that volume with little free space still gets a decent journal size
|
|
usnSize = MAX( (freeBytes / freeSpaceFraction) , minSize );
|
|
|
|
// Get a min value out of fraction-of-total-bytes and previous number
|
|
// This ensures that small volumes don't allocate unproportional size for the journal
|
|
usnSize = MIN ( (totalBytes / totalSpaceFraction) , usnSize);
|
|
|
|
// Get a min of an NTFS upper-limit const and previous number
|
|
// This ensures that large empty volumes don't allocate a too large journal
|
|
usnSize = MIN ( maxSize , usnSize);
|
|
|
|
WsbTrace(OLESTR("CFsaResource::CheckForJournal - Create USN journal - %u\n"), usnSize);
|
|
|
|
WsbAffirmHr(WsbCreateUsnJournal(m_path, usnSize));
|
|
WsbAffirmHr(WsbGetUsnJournalId(m_path, &m_usnJournalId));
|
|
WsbTrace(OLESTR("CFsaResource::CheckForJournal - USN Journal ID = %I64x\n"),
|
|
m_usnJournalId);
|
|
} else {
|
|
DWORD lErr;
|
|
|
|
lErr = GetLastError();
|
|
WsbTrace(OLESTR("CFsaResource::CheckForJournal - GetDiskFreeSpace failed - %x\n"), lErr);
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
} WsbCatch(hr);
|
|
|
|
|
|
if (hr != S_OK) {
|
|
//
|
|
// Problem - could not find or create the USN journal - we refuse to
|
|
// run without it
|
|
//
|
|
WsbTrace(OLESTR("CFsaResource::CheckForJournal - ERROR creating/accessing the USN journal for %ws\n"),
|
|
m_path);
|
|
if (WSB_E_USNJ_CREATE_DISK_FULL == hr) {
|
|
WsbLogEvent(FSA_MESSAGE_CANNOT_CREATE_USNJ_DISK_FULL, 0, NULL,
|
|
(OLECHAR *) m_path, NULL);
|
|
} else if (WSB_E_USNJ_CREATE == hr) {
|
|
WsbLogEvent(FSA_MESSAGE_CANNOT_CREATE_USNJ, 0, NULL,
|
|
(OLECHAR *) m_path, NULL);
|
|
} else {
|
|
WsbLogEvent(FSA_MESSAGE_CANNOT_ACCESS_USNJ, 0, NULL,
|
|
WsbHrAsString(hr), (OLECHAR *) m_path, NULL);
|
|
}
|
|
m_usnJournalId = (ULONGLONG) 0;
|
|
|
|
}
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::CheckForJournal"),OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CheckForValidate(BOOL bForceValidate)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::CheckForValidate
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SYSTEMTIME sysTime;
|
|
FILETIME curTime;
|
|
LARGE_INTEGER ctime;
|
|
CWsbStringPtr tmpString;
|
|
BOOL validateNeeded = FALSE; // Start out assuming no validate needed
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::CheckForValidate"),OLESTR("bForceValidate"),
|
|
WsbBoolAsString(bForceValidate));
|
|
|
|
try {
|
|
|
|
//
|
|
// First we check the USN journal and determine if it is out of date.
|
|
//
|
|
WsbAffirmHr(CheckForJournal(&validateNeeded));
|
|
|
|
//
|
|
// Check the registry to see if a validate job needs to be run. If the filter detected
|
|
// a HSM reparse point getting set and it was not by us it sets a registry value to
|
|
// indicate it.
|
|
//
|
|
try {
|
|
|
|
WsbAffirmHr(tmpString.Alloc(32));
|
|
swprintf((OLECHAR *) tmpString, L"%x", m_serial);
|
|
WsbTrace(L"CFsaResource::CheckForValidate - Checking registry for validate - %ws\\%ws\n",
|
|
FSA_VALIDATE_LOG_KEY_NAME, (OLECHAR *) tmpString);
|
|
|
|
hr = WsbGetRegistryValueData(NULL, FSA_VALIDATE_LOG_KEY_NAME,
|
|
tmpString, (BYTE *) &ctime, sizeof(ctime), NULL);
|
|
|
|
if ((hr == S_OK) || validateNeeded || bForceValidate) {
|
|
//
|
|
// Regardless of what value the registry entry was we set up the job for 2 hours from now.
|
|
// The actual event may have been well in the past and the task scheduler will not like a
|
|
// time in the past as the start time.
|
|
//
|
|
GetLocalTime(&sysTime);
|
|
WsbAffirmStatus(SystemTimeToFileTime(&sysTime, &curTime));
|
|
ctime.LowPart = curTime.dwLowDateTime;
|
|
ctime.HighPart = curTime.dwHighDateTime;
|
|
|
|
if (validateNeeded || bForceValidate) {
|
|
ctime.QuadPart += WSB_FT_TICKS_PER_MINUTE * 5; // 5 Minutes from now if the USN journal changed
|
|
} else {
|
|
ctime.QuadPart += WSB_FT_TICKS_PER_HOUR * 2; // 2 Hours from now if restore activity took place
|
|
}
|
|
curTime.dwLowDateTime = ctime.LowPart;
|
|
curTime.dwHighDateTime = ctime.HighPart;
|
|
WsbAffirmStatus(FileTimeToSystemTime(&curTime, &sysTime));
|
|
WsbAffirmHr(SetupValidateJob(sysTime));
|
|
WsbLogEvent(FSA_MESSAGE_AUTO_VALIDATE, 0, NULL,
|
|
(OLECHAR *) m_path, NULL);
|
|
} else {
|
|
WsbTrace(L"CFsaResource::CheckForValidate - Registry entry not there - %ws\n", WsbHrAsString(hr));
|
|
}
|
|
hr = S_OK;
|
|
} WsbCatchAndDo(hr,
|
|
//
|
|
// Log an event if we fail to set up the job
|
|
//
|
|
WsbTrace(L"CFsaResource::CheckForValidate - Failed to set the job - %x\n", hr);
|
|
WsbLogEvent(FSA_MESSAGE_AUTOVALIDATE_SCHEDULE_FAILED, 0, NULL, WsbAbbreviatePath(m_path, 120), NULL);
|
|
|
|
);
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::CheckForValidate"),OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CompareBy(
|
|
FSA_RESOURCE_COMPARE by
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::CompareBy().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
m_compareBy = by;
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CompareTo(
|
|
IN IUnknown* pUnknown,
|
|
OUT SHORT* pResult
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IWsbCollectable::CompareTo().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaResource> pResource;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::CompareTo"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
// Did they give us a valid item to compare to?
|
|
WsbAssert(0 != pUnknown, E_POINTER);
|
|
|
|
// We need the IFsaResource interface to get the value of the object.
|
|
WsbAffirmHr(pUnknown->QueryInterface(IID_IFsaResource, (void**) &pResource));
|
|
|
|
// Compare the rules.
|
|
hr = CompareToIResource(pResource, pResult);
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::CompareTo"), OLESTR("hr = <%ls>, result = <%ls>"),
|
|
WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CompareToAlternatePath(
|
|
IN OLECHAR* path,
|
|
OUT SHORT* pResult
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::CompareToAlternatePath().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SHORT aResult = 0;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::CompareToAlternatePath"), OLESTR("path = <%ls>"), (OLECHAR *)path);
|
|
|
|
try {
|
|
|
|
WsbTrace(OLESTR("CFsaResource::CompareToAlternatePath - Compare %ls to %ls\n"),
|
|
(WCHAR *) m_alternatePath, (WCHAR *) path);
|
|
|
|
// Compare the path.
|
|
aResult = WsbSign( _wcsicmp(m_alternatePath, path) );
|
|
|
|
if (0 != aResult) {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
if (0 != pResult) {
|
|
*pResult = aResult;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::CompareToAlternatePath"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CompareToIdentifier(
|
|
IN GUID id,
|
|
OUT SHORT* pResult
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::CompareToIdentifier().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SHORT aResult = 0;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::CompareToIdentifier"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
aResult = WsbSign( memcmp(&m_id, &id, sizeof(GUID)) );
|
|
|
|
if (0 != aResult) {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
if (0 != pResult) {
|
|
*pResult = aResult;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::CompareToIdentifier"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CompareToIResource(
|
|
IN IFsaResource* pResource,
|
|
OUT SHORT* pResult
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::CompareToIResource().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CWsbStringPtr name;
|
|
GUID id;
|
|
ULONG serial;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::CompareToIResource"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
// Did they give us a valid item to compare to?
|
|
WsbAssert(0 != pResource, E_POINTER);
|
|
|
|
// Either compare the name or the id.
|
|
if (m_compareBy == FSA_RESOURCE_COMPARE_PATH) {
|
|
WsbAffirmHr(pResource->GetPath(&name, 0));
|
|
hr = CompareToPath(name, pResult);
|
|
} else if (m_compareBy == FSA_RESOURCE_COMPARE_ALTERNATEPATH) {
|
|
WsbAffirmHr(pResource->GetAlternatePath(&name, 0));
|
|
hr = CompareToAlternatePath(name, pResult);
|
|
} else if (m_compareBy == FSA_RESOURCE_COMPARE_ID) {
|
|
WsbAffirmHr(pResource->GetIdentifier(&id));
|
|
hr = CompareToIdentifier(id, pResult);
|
|
} else if (m_compareBy == FSA_RESOURCE_COMPARE_NAME) {
|
|
WsbAffirmHr(pResource->GetName(&name, 0));
|
|
hr = CompareToName(name, pResult);
|
|
} else if (m_compareBy == FSA_RESOURCE_COMPARE_SERIAL) {
|
|
WsbAffirmHr(pResource->GetSerial(&serial));
|
|
hr = CompareToSerial(serial, pResult);
|
|
} else if (m_compareBy == FSA_RESOURCE_COMPARE_USER_NAME) {
|
|
WsbAffirmHr(pResource->GetUserFriendlyName(&name, 0));
|
|
hr = CompareToUserName(name, pResult);
|
|
} else if (m_compareBy == FSA_RESOURCE_COMPARE_STICKY_NAME) {
|
|
WsbAffirmHr(pResource->GetStickyName(&name, 0));
|
|
hr = CompareToStickyName(name, pResult);
|
|
} else {
|
|
WsbAssert(FALSE, E_FAIL);
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::CompareToIResource"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CompareToName(
|
|
IN OLECHAR* name,
|
|
OUT SHORT* pResult
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::CompareToName().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SHORT aResult = 0;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::CompareToName"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
// Compare the path.
|
|
aResult = WsbSign( _wcsicmp(m_name, name) );
|
|
|
|
if (0 != aResult) {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
if (0 != pResult) {
|
|
*pResult = aResult;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::CompareToName"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CompareToUserName(
|
|
IN OLECHAR* name,
|
|
OUT SHORT* pResult
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::CompareToUserName().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SHORT aResult = 0;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::CompareToUserName"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
// Compare the path.
|
|
aResult = WsbSign( _wcsicmp(m_userName, name) );
|
|
|
|
if (0 != aResult) {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
if (0 != pResult) {
|
|
*pResult = aResult;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::CompareToUserName"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CompareToPath(
|
|
IN OLECHAR* path,
|
|
OUT SHORT* pResult
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::CompareToPath().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SHORT aResult = 0;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::CompareToPath"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
// Compare the path.
|
|
aResult = WsbSign( _wcsicmp(m_path, path) );
|
|
|
|
if (0 != aResult) {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
if (0 != pResult) {
|
|
*pResult = aResult;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::CompareToPath"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CompareToSerial(
|
|
IN ULONG serial,
|
|
OUT SHORT* pResult
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::CompareToSerial().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SHORT aResult = 0;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::CompareToSerial"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
WsbTrace(OLESTR("CFsaResource::CompareToSerial - Compare %lu to %lu\n"),
|
|
m_serial, serial);
|
|
|
|
// Compare the path.
|
|
if (m_serial == serial) {
|
|
aResult = 0;
|
|
} else {
|
|
aResult = 1;
|
|
}
|
|
|
|
if (0 != aResult) {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
if (0 != pResult) {
|
|
*pResult = aResult;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::CompareToSerial"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CompareToStickyName(
|
|
IN OLECHAR* name,
|
|
OUT SHORT* pResult
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::CompareToStickyName().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SHORT aResult = 0;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::CompareToStickyName"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
WsbTrace(OLESTR("CFsaResource::CompareToStickyName - Compare %ws to %ws\n"),
|
|
(WCHAR *) m_stickyName, name);
|
|
|
|
aResult = WsbSign( _wcsicmp(m_stickyName, name) );
|
|
|
|
if (0 != aResult) {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
if (0 != pResult) {
|
|
*pResult = aResult;
|
|
}
|
|
|
|
if (0 != pResult) {
|
|
*pResult = aResult;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::CompareToStickyName"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
AddExclusion(
|
|
const OLECHAR* DrivePath,
|
|
IWsbIndexedCollection* pDefaultRules,
|
|
const OLECHAR* ExcludePath,
|
|
BOOL UserRule
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
try {
|
|
|
|
// If this is resource matches the drive of the folder path, exclude the path.
|
|
if( _wcsnicmp( DrivePath, ExcludePath, 1 ) == 0 ) {
|
|
|
|
CComPtr<IHsmRule> pRule;
|
|
CComPtr<IWsbCollection> pCollection;
|
|
CComPtr<IHsmCriteria> pCriteria;
|
|
|
|
WsbAffirmHr( CoCreateInstance( CLSID_CHsmRule, NULL, CLSCTX_SERVER, IID_IHsmRule, (void**) &pRule ) );
|
|
WsbAffirmHr( pRule->SetIsInclude( FALSE ) );
|
|
WsbAffirmHr( pRule->SetIsUserDefined( UserRule ) );
|
|
WsbAffirmHr( pRule->SetPath( (OLECHAR*) &ExcludePath[2] ) );
|
|
WsbAffirmHr( pRule->SetName( OLESTR("*") ) );
|
|
|
|
WsbAssertHr( CoCreateInstance( CLSID_CHsmCritAlways, NULL, CLSCTX_SERVER, IID_IHsmCriteria, (void**) &pCriteria ) );
|
|
WsbAssertHr( pRule->Criteria( &pCollection ) );
|
|
WsbAssertHr( pCollection->Add( pCriteria ) );
|
|
|
|
WsbAffirmHr( pDefaultRules->Append( pRule ) );
|
|
WsbTrace( L"Excluding <%ls>, <%ls>\n", ExcludePath, UserRule ? "UserRule" : "SystemRule" );
|
|
|
|
}
|
|
|
|
} WsbCatch( hr );
|
|
return( hr );
|
|
}
|
|
|
|
|
|
static
|
|
HRESULT
|
|
AddShellFolderExclusion(
|
|
const OLECHAR* DrivePath,
|
|
IWsbIndexedCollection* pDefaultRules,
|
|
int FolderId,
|
|
BOOL UserRule
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
try {
|
|
|
|
OLECHAR folderPath[_MAX_PATH] = L"";
|
|
WsbAffirmHrOk( SHGetFolderPath( 0, FolderId, 0, 0, folderPath ) );
|
|
WsbAffirmHr( AddExclusion( DrivePath, pDefaultRules, folderPath, UserRule ) );
|
|
|
|
} WsbCatch( hr );
|
|
return( hr );
|
|
}
|
|
|
|
|
|
static
|
|
HRESULT
|
|
AddRegistryPathExclusion(
|
|
const OLECHAR* DrivePath,
|
|
IWsbIndexedCollection* pDefaultRules,
|
|
HKEY hKeyRoot,
|
|
const OLECHAR* KeyName,
|
|
const OLECHAR* ValueName,
|
|
BOOL UserRule
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
try {
|
|
|
|
DWORD pathSize = 0;
|
|
CWsbStringPtr folderPath, regValue;
|
|
|
|
//
|
|
// Open the Key
|
|
//
|
|
CRegKey key;
|
|
WsbAffirmWin32( key.Open( hKeyRoot, KeyName, KEY_QUERY_VALUE ) );
|
|
|
|
//
|
|
// Get the size of the value's data and allocatate buffer
|
|
//
|
|
WsbAffirmWin32( key.QueryValue( 0, ValueName, &pathSize ) );
|
|
WsbAffirmHr( regValue.Alloc( ( pathSize / sizeof( OLECHAR ) ) + 1 ) );
|
|
|
|
//
|
|
// Get the data and expand any environment variables
|
|
//
|
|
WsbAffirmWin32( key.QueryValue( regValue, ValueName, &pathSize ) );
|
|
|
|
pathSize = ExpandEnvironmentStrings( regValue, 0, 0 );
|
|
WsbAffirmHr( folderPath.Alloc( pathSize ) );
|
|
pathSize = ExpandEnvironmentStrings( regValue, folderPath, pathSize );
|
|
WsbAffirmStatus( pathSize > 0 );
|
|
|
|
//
|
|
// And finally add the exclusion
|
|
//
|
|
WsbAffirmHr( AddExclusion( DrivePath, pDefaultRules, folderPath, UserRule ) );
|
|
|
|
} WsbCatch( hr );
|
|
return( hr );
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::CreateDefaultRules(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::CreateDefaultRules().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IHsmRule> pRule;
|
|
CComPtr<IWsbCollection> pCollection;
|
|
CComPtr<IWsbIndexedCollection> pDefaultRules;
|
|
CComPtr<IHsmCriteria> pCriteria;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::CreateDefaultRules"), OLESTR(""));
|
|
try {
|
|
|
|
// Since we are recreating back to the default rules, remove all the existing default
|
|
// rules.
|
|
//
|
|
// NOTE: This will cause any extra rules (non-default) to be removed.
|
|
WsbAffirmHr(m_pDefaultRules->RemoveAllAndRelease());
|
|
|
|
// We need to preserve the order of the rules, so use the indexed collection interface.
|
|
WsbAffirmHr(m_pDefaultRules->QueryInterface(IID_IWsbIndexedCollection, (void**) &pDefaultRules));
|
|
|
|
// Create rules to exclude the following file types:
|
|
// *.cur - cursors
|
|
// *.ico - icons
|
|
// *.lnk - shortcuts
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CHsmRule, NULL, CLSCTX_SERVER, IID_IHsmRule, (void**) &pRule));
|
|
WsbAffirmHr(pRule->SetIsInclude(FALSE));
|
|
WsbAffirmHr(pRule->SetIsUserDefined(FALSE));
|
|
WsbAffirmHr(pRule->SetPath(OLESTR("\\")));
|
|
WsbAffirmHr(pRule->SetName(OLESTR("*.cur")));
|
|
|
|
WsbAssertHr(CoCreateInstance(CLSID_CHsmCritAlways, NULL, CLSCTX_SERVER, IID_IHsmCriteria, (void**) &pCriteria));
|
|
WsbAssertHr(pRule->Criteria(&pCollection));
|
|
WsbAssertHr(pCollection->Add(pCriteria));
|
|
|
|
WsbAffirmHr(pDefaultRules->Append(pRule));
|
|
pCollection = 0;
|
|
pCriteria = 0;
|
|
pRule = 0;
|
|
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CHsmRule, NULL, CLSCTX_SERVER, IID_IHsmRule, (void**) &pRule));
|
|
WsbAffirmHr(pRule->SetIsInclude(FALSE));
|
|
WsbAffirmHr(pRule->SetIsUserDefined(FALSE));
|
|
WsbAffirmHr(pRule->SetPath(OLESTR("\\")));
|
|
WsbAffirmHr(pRule->SetName(OLESTR("*.ico")));
|
|
|
|
WsbAssertHr(CoCreateInstance(CLSID_CHsmCritAlways, NULL, CLSCTX_SERVER, IID_IHsmCriteria, (void**) &pCriteria));
|
|
WsbAssertHr(pRule->Criteria(&pCollection));
|
|
WsbAssertHr(pCollection->Add(pCriteria));
|
|
|
|
WsbAffirmHr(pDefaultRules->Append(pRule));
|
|
pCollection = 0;
|
|
pCriteria = 0;
|
|
pRule = 0;
|
|
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CHsmRule, NULL, CLSCTX_SERVER, IID_IHsmRule, (void**) &pRule));
|
|
WsbAffirmHr(pRule->SetIsInclude(FALSE));
|
|
WsbAffirmHr(pRule->SetIsUserDefined(FALSE));
|
|
WsbAffirmHr(pRule->SetPath(OLESTR("\\")));
|
|
WsbAffirmHr(pRule->SetName(OLESTR("*.lnk")));
|
|
|
|
WsbAssertHr(CoCreateInstance(CLSID_CHsmCritAlways, NULL, CLSCTX_SERVER, IID_IHsmCriteria, (void**) &pCriteria));
|
|
WsbAssertHr(pRule->Criteria(&pCollection));
|
|
WsbAssertHr(pCollection->Add(pCriteria));
|
|
|
|
WsbAffirmHr(pDefaultRules->Append(pRule));
|
|
pCollection = 0;
|
|
pCriteria = 0;
|
|
pRule = 0;
|
|
|
|
WsbAffirmHr( AddShellFolderExclusion( m_path, pDefaultRules, CSIDL_WINDOWS, FALSE ) );
|
|
WsbAffirmHr( AddShellFolderExclusion( m_path, pDefaultRules, CSIDL_PROGRAM_FILES, TRUE ) );\
|
|
|
|
WsbAffirmHr( AddRegistryPathExclusion( m_path, pDefaultRules,
|
|
HKEY_LOCAL_MACHINE,
|
|
WSB_PROFILELIST_REGISTRY_KEY,
|
|
WSB_PROFILES_DIR_REGISTRY_VALUE,
|
|
TRUE ) );
|
|
// If this is the boot drive (i.e. C), then exclude everything in the root, since most of
|
|
// these files are important to boot the system (better safe than sorry, fewer rules).
|
|
if (_wcsnicmp(m_path, OLESTR("C"), 1) == 0) {
|
|
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CHsmRule, NULL, CLSCTX_SERVER, IID_IHsmRule, (void**) &pRule));
|
|
WsbAffirmHr(pRule->SetIsInclude(FALSE));
|
|
WsbAffirmHr(pRule->SetIsUserDefined(FALSE));
|
|
WsbAffirmHr(pRule->SetIsUsedInSubDirs(FALSE));
|
|
WsbAffirmHr(pRule->SetPath(OLESTR("\\")));
|
|
WsbAffirmHr(pRule->SetName(OLESTR("*")));
|
|
|
|
WsbAssertHr(CoCreateInstance(CLSID_CHsmCritAlways, NULL, CLSCTX_SERVER, IID_IHsmCriteria, (void**) &pCriteria));
|
|
WsbAssertHr(pRule->Criteria(&pCollection));
|
|
WsbAssertHr(pCollection->Add(pCriteria));
|
|
|
|
WsbAffirmHr(pDefaultRules->Append(pRule));
|
|
pCollection = 0;
|
|
pCriteria = 0;
|
|
pRule = 0;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::CreateDefaultRules"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::DoRecovery(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::DoRecovery().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrFindFile;
|
|
HRESULT hrFindRec;
|
|
HRESULT hrLoop = S_OK;
|
|
LONGLONG Offset;
|
|
GUID bagId;
|
|
LONGLONG bagOffset;
|
|
LONGLONG fileId;
|
|
OLECHAR * pPath = NULL;
|
|
LONG RecCount;
|
|
ULONG RecStatus;
|
|
LONGLONG Size;
|
|
FSA_PLACEHOLDER placeholder;
|
|
CComPtr<IWsbDbSession> pDbSession;
|
|
CComPtr<IFsaPremigratedRec> pPremRec;
|
|
CComPtr<IFsaScanItem> pScanItem;
|
|
CComPtr<IFsaScanItemPriv> pScanItemPriv;
|
|
CComPtr<IFsaRecoveryRec> pRecRec;
|
|
CComPtr<IHsmSession> pSession;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::DoRecovery"), OLESTR("Path = <%ls>"), WsbAbbreviatePath(m_path,120));
|
|
|
|
try {
|
|
|
|
// Don't bother if we already did recovery
|
|
WsbAffirm(!m_isRecovered, S_FALSE);
|
|
|
|
// Don't bother if this volume isn't managed
|
|
WsbAffirm(S_OK == IsManaged(), S_FALSE);
|
|
|
|
// Don't bother if we don't have a premigration-list DB (since it
|
|
// contains the recovery records)
|
|
if (!m_isDbInitialized) {
|
|
// Set recovered flag so we don't end up in here again
|
|
m_isRecovered = TRUE;
|
|
WsbThrow(S_FALSE);
|
|
}
|
|
|
|
// Create and Initialize a session object.
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CHsmSession, 0, CLSCTX_SERVER, IID_IHsmSession, (void**) &pSession));
|
|
WsbAffirmHr(pSession->Start(OLESTR(""), HSM_JOB_LOG_NONE, m_managingHsm, 0, (IFsaResource*) this, 0, 0));
|
|
|
|
// Loop over recovery records and fix any problems
|
|
WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
|
|
WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE, IID_IFsaRecoveryRec, (void**) &pRecRec));
|
|
|
|
WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, PREMIGRATED_REC_TYPE, IID_IFsaPremigratedRec, (void**) &pPremRec));
|
|
WsbAffirmHr(pPremRec->UseKey(PREMIGRATED_BAGID_OFFSETS_KEY_TYPE));
|
|
|
|
WsbAffirmHr(pRecRec->First());
|
|
|
|
while (TRUE) {
|
|
|
|
// Get record data
|
|
WsbAffirmHr(pRecRec->GetBagId(&bagId));
|
|
WsbAffirmHr(pRecRec->GetBagOffset(&bagOffset));
|
|
WsbAffirmHr(pRecRec->GetFileId(&fileId));
|
|
WsbAffirmHr(pRecRec->GetPath(&pPath, 0));
|
|
WsbAffirmHr(pRecRec->GetStatus(&RecStatus));
|
|
WsbAffirmHr(pRecRec->GetOffsetSize(&Offset, &Size));
|
|
WsbAffirmHr(pRecRec->GetRecoveryCount(&RecCount));
|
|
WsbTrace(OLESTR("CFsaResource::DoRecovery, FileId = %I64u, File = <%ls>, RecStatus = %lx, RecCount = %ld\n"), fileId, WsbAbbreviatePath(pPath, 120), RecStatus, RecCount);
|
|
|
|
RecCount++;
|
|
WsbAffirmHr(pRecRec->SetRecoveryCount(RecCount));
|
|
|
|
// Mark the record as being recovered (in case we crash here)
|
|
WsbAffirmHr(pRecRec->Write());
|
|
|
|
try {
|
|
|
|
// Create a scan item for this file
|
|
hrFindFile = FindFileId(fileId, pSession, &pScanItem);
|
|
|
|
if (SUCCEEDED(hrFindFile) && (pScanItem->IsManaged(Offset, Size) != S_FALSE)) {
|
|
WsbAffirmHr(pScanItem->GetPlaceholder(Offset, Size, &placeholder));
|
|
}
|
|
|
|
WsbAffirmHr(pPremRec->SetBagId(bagId));
|
|
WsbAffirmHr(pPremRec->SetBagOffset(bagOffset));
|
|
WsbAffirmHr(pPremRec->SetOffset(Offset));
|
|
|
|
hrFindRec = pPremRec->FindEQ();
|
|
|
|
// If the file has been deleted, is not managed by HSM or its BAG data is
|
|
// different from the RP data, then it shouldn't be in the premigration list.
|
|
if ( (WSB_E_NOTFOUND == hrFindFile) ||
|
|
(SUCCEEDED(hrFindFile) && (pScanItem->IsManaged(Offset, Size) != S_OK)) ||
|
|
(SUCCEEDED(hrFindFile) && (pScanItem->IsManaged(Offset, Size) == S_OK) &&
|
|
((bagId != placeholder.bagId) || (bagOffset != placeholder.fileStart))) ) {
|
|
|
|
// If the record is in the list, then remove it and adjust the sizes.
|
|
// Note: The removal is not protected within a transaction since the
|
|
// recovery is done only during initialization or when a new volume is
|
|
// managed. In both cases, the auto-truncator does not run yet.
|
|
if (S_OK == hrFindRec) {
|
|
WsbAffirmHr(pPremRec->Remove());
|
|
WsbAffirmHr(RemovePremigratedSize(Size));
|
|
} else {
|
|
WsbAffirmHr(RemoveTruncatedSize(Size));
|
|
}
|
|
}
|
|
|
|
else {
|
|
|
|
WsbAffirmHr(hrFindFile);
|
|
|
|
// Check the status of the file according to the reparse point
|
|
if (S_OK == pScanItem->IsTruncated(Offset, Size)) {
|
|
|
|
// Force a truncate, just in case
|
|
WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItemPriv, (void**)&pScanItemPriv));
|
|
hrLoop = pScanItemPriv->TruncateInternal(Offset, Size);
|
|
|
|
// Remove from premigrated list if there
|
|
if (S_OK == hrFindRec) {
|
|
if ((S_OK == hrLoop) || (FSA_E_ITEMCHANGED == hrLoop)) {
|
|
WsbAffirmHr(pPremRec->Remove());
|
|
WsbAffirmHr(RemovePremigratedSize(Size));
|
|
if (S_OK == hrLoop) {
|
|
WsbAffirmHr(AddTruncatedSize(Size));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
else if (S_OK == pScanItem->IsPremigrated(Offset, Size)) {
|
|
|
|
// Add to premigrated list if not there
|
|
if (WSB_E_NOTFOUND == hrFindRec) {
|
|
WsbAffirmHr(RemoveTruncatedSize(Size));
|
|
WsbAffirmHr(AddPremigratedSize(Size));
|
|
WsbAffirmHr(pPremRec->MarkAsNew());
|
|
WsbAffirmHr(pPremRec->Write());
|
|
}
|
|
}
|
|
}
|
|
|
|
} WsbCatch(hrLoop);
|
|
|
|
if (FAILED(hrLoop)) {
|
|
|
|
if ((RecStatus & FSA_RECOVERY_FLAG_TRUNCATING) != 0) {
|
|
WsbLogEvent(FSA_MESSAGE_TRUNCATE_RECOVERY_FAIL, 0, NULL, WsbAbbreviatePath(pPath, 120), WsbHrAsString(hr), 0);
|
|
} else if ((RecStatus & FSA_RECOVERY_FLAG_RECALLING) != 0) {
|
|
WsbLogEvent(FSA_MESSAGE_RECALL_RECOVERY_FAIL, 0, NULL, WsbAbbreviatePath(pPath, 120), WsbHrAsString(hr), 0);
|
|
}
|
|
|
|
// If we have tried enough, then get rid of the record.
|
|
if (RecCount > 2) {
|
|
WsbTrace(OLESTR("CFsaResource::DoRecovery, unable to do recovery - too many attempts already\n"));
|
|
WsbAffirmHr(pRecRec->Remove());
|
|
}
|
|
|
|
} else {
|
|
|
|
// Log an event to commemorate our success
|
|
WsbTrace(OLESTR("CFsaResource::DoRecovery, recovered <%ls>\n"), WsbAbbreviatePath(pPath, 120));
|
|
if ((RecStatus & FSA_RECOVERY_FLAG_TRUNCATING) != 0) {
|
|
WsbLogEvent(FSA_MESSAGE_TRUNCATE_RECOVERY_OK, 0, NULL, WsbAbbreviatePath(pPath, 120), 0);
|
|
} else if ((RecStatus & FSA_RECOVERY_FLAG_RECALLING) != 0) {
|
|
WsbLogEvent(FSA_MESSAGE_RECALL_RECOVERY_OK, 0, NULL, WsbAbbreviatePath(pPath, 120), 0);
|
|
}
|
|
|
|
// Remove this record from the DB
|
|
WsbAffirmHr(pRecRec->Remove());
|
|
}
|
|
|
|
// Get the next one
|
|
WsbAffirmHr(pRecRec->FindGT());
|
|
|
|
// Release any objects we may have created
|
|
// this time through the loop
|
|
pScanItem = 0;
|
|
pScanItemPriv = 0;
|
|
|
|
hrLoop = S_OK;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
if (WSB_E_NOTFOUND == hr) {
|
|
hr = S_OK;
|
|
}
|
|
|
|
if (pDbSession != 0) {
|
|
m_pPremigrated->Close(pDbSession);
|
|
}
|
|
|
|
m_isRecovered = TRUE;
|
|
|
|
// Now that everything is done, see if we need to start the truncator.
|
|
WsbTrace(OLESTR("CFsaResource::DoRecovery, IsManaged = %ls, isActive = %ls\n"),
|
|
WsbQuickString(WsbBoolAsString(IsManaged() == S_OK)),
|
|
WsbQuickString(WsbBoolAsString(m_isActive)));
|
|
|
|
// Make sure the truncator is started
|
|
WsbAffirmHr(InitializePremigrationList(FALSE));
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::DoRecovery"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::EndSession(
|
|
IN IHsmSession* pSession
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::EndSession().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bLog = TRUE;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::EndSession"), OLESTR(""));
|
|
try {
|
|
|
|
WsbAssert(0 != pSession, E_POINTER);
|
|
|
|
// Tell the session that the scan is done.
|
|
WsbAffirmHr(pSession->ProcessState(HSM_JOB_PHASE_SCAN, HSM_JOB_STATE_DONE, OLESTR(""), bLog));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::EndSession"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::EndValidate(
|
|
HSM_JOB_STATE state
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::EndValidate().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::EndValidate"),
|
|
OLESTR("state = %ld, new PremigratedSize = %I64d, new TruncatedSize = %I64d"),
|
|
(LONG)state, m_premigratedSize, m_truncatedSize);
|
|
|
|
try {
|
|
|
|
if (HSM_JOB_STATE_DONE != state) {
|
|
m_premigratedSize = m_oldPremigratedSize;
|
|
m_truncatedSize = m_oldTruncatedSize;
|
|
}
|
|
m_isDoingValidate = FALSE;
|
|
|
|
// Make sure the truncator is running
|
|
WsbAffirmHr(InitializePremigrationList(FALSE));
|
|
WsbAffirmHr(m_pTruncator->KickStart());
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::EndValidate"),
|
|
OLESTR("hr = <%ls>, PremigratedSize = %I64d, TruncatedSize = %I64d"),
|
|
WsbQuickString(WsbHrAsString(hr)), m_premigratedSize, m_truncatedSize);
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::EnumDefaultRules(
|
|
OUT IWsbEnum** ppEnum
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::EnumDefaultRules().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != ppEnum, E_POINTER);
|
|
|
|
WsbAffirmHr(m_pDefaultRules->Enum(ppEnum));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::FilterSawOpen(
|
|
IN IHsmSession* pSession,
|
|
IN IFsaFilterRecall* pRecall,
|
|
IN OLECHAR* path,
|
|
IN LONGLONG fileId,
|
|
IN LONGLONG requestOffset,
|
|
IN LONGLONG requestSize,
|
|
IN FSA_PLACEHOLDER* pPlaceholder,
|
|
IN ULONG mode,
|
|
IN FSA_RESULT_ACTION resultAction,
|
|
IN DWORD threadId
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::FilterSawOpen().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrFind;
|
|
CComPtr<IFsaPostIt> pWorkItem;
|
|
CComPtr<IHsmFsaTskMgr> pEngine;
|
|
CComPtr<IWsbDbSession> pDbSession;
|
|
CComPtr<IFsaRecoveryRec> pRecRec;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::FilterSawOpen"),
|
|
OLESTR("path = <%ls>, requestOffset = %I64d, requestSize = %I64d"),
|
|
path, requestOffset, requestSize);
|
|
try {
|
|
|
|
WsbAssert(0 != pSession, E_POINTER);
|
|
WsbAssert(0 != pRecall, E_POINTER);
|
|
WsbAssert(0 != path, E_POINTER);
|
|
WsbAssert(0 != pPlaceholder, E_POINTER);
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
|
|
|
|
// Remember which recall is being used to track the open.
|
|
WsbAffirmHr(pWorkItem->SetFilterRecall(pRecall));
|
|
|
|
//
|
|
// Set the session for others to know
|
|
//
|
|
WsbAffirmHr(pWorkItem->SetSession(pSession));
|
|
WsbAffirmHr(pWorkItem->SetMode(mode));
|
|
WsbAffirmHr(pWorkItem->SetFileVersionId(pPlaceholder->fileVersionId));
|
|
|
|
//
|
|
// Set the transfer size
|
|
//
|
|
WsbAffirmHr(pWorkItem->SetRequestOffset(requestOffset));
|
|
WsbAffirmHr(pWorkItem->SetRequestSize(requestSize));
|
|
WsbAffirmHr(pWorkItem->SetPlaceholder(pPlaceholder));
|
|
|
|
//
|
|
// Get a new copy of the path into the workitem
|
|
//
|
|
WsbAffirmHr(pWorkItem->SetPath(path));
|
|
|
|
//
|
|
// Need to check the mode to set the right result action. For now
|
|
// just set it to OPEN.
|
|
//
|
|
WsbAffirmHr(pWorkItem->SetResultAction(resultAction));
|
|
WsbAffirmHr(pWorkItem->SetThreadId(threadId));
|
|
|
|
//
|
|
// Send the request to the task manager. If the file was archived by someone other
|
|
// than the managing HSM, then that HSM will need to be looked up.
|
|
//
|
|
if ( GUID_NULL != m_managingHsm &&
|
|
memcmp(&m_managingHsm, &(pPlaceholder->hsmId), sizeof(GUID)) == 0) {
|
|
WsbAffirmHr(GetHsmEngine(&pEngine));
|
|
} else {
|
|
CComPtr<IHsmServer> pHsmServer;
|
|
|
|
WsbAssertHr(HsmConnectFromId(HSMCONN_TYPE_HSM, (pPlaceholder->hsmId), IID_IHsmServer, (void**) &pHsmServer));
|
|
WsbAffirmHr(pHsmServer->GetHsmFsaTskMgr(&pEngine));
|
|
}
|
|
|
|
//
|
|
// Fill in the rest of the work
|
|
//
|
|
if (mode & FILE_OPEN_NO_RECALL) {
|
|
WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_FILTER_READ));
|
|
} else {
|
|
|
|
WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_FILTER_RECALL));
|
|
|
|
if (m_isDbInitialized) {
|
|
// Save a recovery record in case anything goes wrong
|
|
WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
|
|
WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE, IID_IFsaRecoveryRec, (void**) &pRecRec));
|
|
WsbAffirmHr(pRecRec->SetPath(path));
|
|
|
|
// If the record already exists rewrite it, otherwise create a new record.
|
|
hrFind = pRecRec->FindEQ();
|
|
if (WSB_E_NOTFOUND == hrFind) {
|
|
WsbAffirmHr(pRecRec->MarkAsNew());
|
|
} else if (FAILED(hrFind)) {
|
|
WsbThrow(hrFind);
|
|
}
|
|
|
|
WsbAffirmHr(pRecRec->SetFileId(fileId));
|
|
WsbAffirmHr(pRecRec->SetOffsetSize(requestOffset, requestSize));
|
|
WsbAffirmHr(pRecRec->SetStatus(FSA_RECOVERY_FLAG_RECALLING));
|
|
WsbAffirmHr(pRecRec->Write());
|
|
}
|
|
}
|
|
|
|
// If anything that follows fails, then we need to delete the recovery record.
|
|
try {
|
|
|
|
WsbTrace(OLESTR("CFsaResource::FilterSawOpen calling DoFsaWork\n"));
|
|
WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
|
|
|
|
} WsbCatchAndDo(hr,
|
|
if (pRecRec != 0) {
|
|
hrFind = pRecRec->FindEQ();
|
|
if (hrFind == S_OK) {
|
|
WsbAffirmHr(pRecRec->Remove());
|
|
}
|
|
}
|
|
);
|
|
|
|
} WsbCatch(hr);
|
|
|
|
if (pDbSession != 0) {
|
|
m_pPremigrated->Close(pDbSession);
|
|
}
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::FilterSawOpen"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::FilterSawDelete(
|
|
IN GUID /*filterId*/,
|
|
IN OLECHAR* path,
|
|
IN LONGLONG /*size*/,
|
|
IN FSA_PLACEHOLDER* pPlaceholder
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::FilterSawDelete().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::FilterSawDelete"), OLESTR("path = <%ls>"), (OLECHAR *)path);
|
|
try {
|
|
|
|
WsbAssert(0 != path, E_POINTER);
|
|
WsbAssert(0 != pPlaceholder, E_POINTER);
|
|
|
|
hr = E_NOTIMPL;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::FilterSawDelete"), OLESTR(""));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::FinalConstruct(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
CComObjectRoot::FinalConstruct().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::FinalConstruct"), OLESTR(""));
|
|
try {
|
|
|
|
WsbAffirmHr(CWsbCollectable::FinalConstruct());
|
|
|
|
m_id = GUID_NULL;
|
|
m_compareBy = FSA_RESOURCE_COMPARE_ID;
|
|
m_managingHsm = GUID_NULL;
|
|
m_isActive = TRUE;
|
|
m_isAvailable = TRUE;
|
|
m_isDeletePending = FALSE;
|
|
m_isRecovered = FALSE;
|
|
m_hsmLevel = 0;
|
|
m_premigratedSize = 0;
|
|
m_truncatedSize = 0;
|
|
m_isDoingValidate = FALSE;
|
|
m_usnJournalId = (ULONGLONG) 0;
|
|
m_lastUsnId = (LONGLONG) 0; // Not used yet but persisted for possible future use.
|
|
|
|
// Default Criteria (12Kb, 180 days old)
|
|
m_manageableItemLogicalSize = 12288;
|
|
m_manageableItemAccessTimeIsRelative = TRUE;
|
|
m_manageableItemAccessTime = WsbLLtoFT(180 * WSB_FT_TICKS_PER_DAY);
|
|
|
|
m_isUnmanageDbInitialized = FALSE;
|
|
|
|
//Create the default rule list.
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, NULL, CLSCTX_SERVER, IID_IWsbCollection, (void**) &m_pDefaultRules));
|
|
|
|
// Create the premigrated list DB
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaPremigratedDb, NULL, CLSCTX_SERVER, IID_IFsaPremigratedDb, (void**) &m_pPremigrated));
|
|
m_isDbInitialized = FALSE;
|
|
|
|
// Create the object for the auto truncator.
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaTruncatorNTFS, NULL, CLSCTX_SERVER, IID_IFsaTruncator, (void**) &m_pTruncator));
|
|
|
|
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
g_InstanceCount++;
|
|
}
|
|
WsbTrace(OLESTR("CFsaResource::FinalConstruct: this = %p, instance count = %d\n"),
|
|
this, g_InstanceCount);
|
|
WsbTraceOut(OLESTR("CFsaResource::FinalConstruct"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::FinalRelease(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
CComObjectRoot::FinalRelease
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::FinalRelease"), OLESTR(""));
|
|
try {
|
|
HSM_SYSTEM_STATE SysState;
|
|
|
|
// Terminate Unmanage Db (If it wasn't created, nothing happens...)
|
|
TerminateUnmanageDb();
|
|
m_isUnmanageDbInitialized = FALSE;
|
|
m_pUnmanageDb = NULL;
|
|
|
|
// Shutdown resource
|
|
SysState.State = HSM_STATE_SHUTDOWN;
|
|
ChangeSysState(&SysState);
|
|
CWsbCollectable::FinalRelease();
|
|
|
|
// Free String members
|
|
// Note: Member objects held in smart-pointers are freed when the
|
|
// smart-pointer destructor is being called (as part of this object destruction)
|
|
m_oldPath.Free();
|
|
m_path.Free();
|
|
m_alternatePath.Free();
|
|
m_name.Free();
|
|
m_fsName.Free();
|
|
|
|
} WsbCatch(hr);
|
|
|
|
if (hr == S_OK) {
|
|
g_InstanceCount--;
|
|
}
|
|
WsbTrace(OLESTR("CFsaResource::FinalRelease: this = %p, instance count = %d\n"),
|
|
this, g_InstanceCount);
|
|
WsbTraceOut(OLESTR("CFsaResource::FinalRelease"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::FindFirst(
|
|
IN OLECHAR* path,
|
|
IN IHsmSession* pSession,
|
|
OUT IFsaScanItem** ppScanItem
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::FindFirst().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaScanItemPriv> pScanItem;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != path, E_POINTER);
|
|
WsbAssert(0 != ppScanItem, E_POINTER);
|
|
|
|
// Create an FsaScanItem that will scan for us.
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL, CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
|
|
|
|
// Scan starting at the specified path.
|
|
WsbAffirmHr(pScanItem->FindFirst((IFsaResource*) this, path, pSession));
|
|
|
|
// If we found something, then return the scan item.
|
|
WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItem, (void**) ppScanItem));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::FindFirstInRPIndex(
|
|
IN IHsmSession* pSession,
|
|
OUT IFsaScanItem** ppScanItem
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::FindFirstInRPIndex
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaScanItemPriv> pScanItem;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != ppScanItem, E_POINTER);
|
|
|
|
// Create an FsaScanItem that will scan for us.
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL, CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
|
|
|
|
// Scan starting at the specified path.
|
|
WsbAffirmHr(pScanItem->FindFirstInRPIndex((IFsaResource*) this, pSession));
|
|
|
|
// If we found something, then return the scan item.
|
|
WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItem, (void**) ppScanItem));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT
|
|
CFsaResource::FindFirstInDbIndex(
|
|
IN IHsmSession* pSession,
|
|
OUT IFsaScanItem** ppScanItem
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::FindFirstInDbIndex
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaScanItemPriv> pScanItem;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != ppScanItem, E_POINTER);
|
|
|
|
// Create an FsaScanItem that will scan for us.
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL, CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
|
|
|
|
// Scan starting at the specified path.
|
|
WsbAffirmHr(pScanItem->FindFirstInDbIndex((IFsaResource*) this, pSession));
|
|
|
|
// If we found something, then return the scan item.
|
|
WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItem, (void**) ppScanItem));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::FindNext(
|
|
IN IFsaScanItem* pScanItem
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::FindNext().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaScanItemPriv> pPriv;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pScanItem, E_POINTER);
|
|
|
|
// Continue the scan.
|
|
WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItemPriv, (void**) &pPriv))
|
|
WsbAffirmHr(pPriv->FindNext());
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::FindNextInRPIndex(
|
|
IN IFsaScanItem* pScanItem
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::FindNextInRPIndex
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaScanItemPriv> pPriv;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pScanItem, E_POINTER);
|
|
|
|
// Continue the scan.
|
|
WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItemPriv, (void**) &pPriv))
|
|
WsbAffirmHr(pPriv->FindNextInRPIndex());
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT
|
|
CFsaResource::FindNextInDbIndex(
|
|
IN IFsaScanItem* pScanItem
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::FindNextInDbIndex
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaScanItemPriv> pPriv;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pScanItem, E_POINTER);
|
|
|
|
// Continue the scan.
|
|
WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItemPriv, (void**) &pPriv))
|
|
WsbAffirmHr(pPriv->FindNextInDbIndex());
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::FindFileId(
|
|
IN LONGLONG fileId,
|
|
IN IHsmSession* pSession,
|
|
OUT IFsaScanItem** ppScanItem
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::FindFileId().
|
|
|
|
Creates a scan item for the given file ID.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaScanItemPriv> pScanItem;
|
|
CWsbStringPtr VolumePath;
|
|
CWsbStringPtr filePath;
|
|
HANDLE File = INVALID_HANDLE_VALUE;
|
|
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
NTSTATUS Status;
|
|
NTSTATUS GetNameStatus;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING str;
|
|
PFILE_NAME_INFORMATION FileName;
|
|
DWORD pathSize;
|
|
OLECHAR *buffer = NULL;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::FindFileId"), OLESTR("File ID = %I64x"), fileId);
|
|
|
|
try {
|
|
WsbAssert(0 != ppScanItem, E_POINTER);
|
|
|
|
// If we were passed an existing scan item (special internal code),
|
|
// use it; otherwise, create one.
|
|
if (NULL != *ppScanItem) {
|
|
WsbAffirmHr((*ppScanItem)->QueryInterface(IID_IFsaScanItemPriv,
|
|
(void**) &pScanItem));
|
|
} else {
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL,
|
|
CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
|
|
}
|
|
|
|
//
|
|
// Get the file path from the ID
|
|
//
|
|
|
|
|
|
//
|
|
// Open by File Reference Number (FileID),
|
|
// Relative opens from the Volume Handle.
|
|
//
|
|
|
|
VolumePath = L"\\\\.\\";
|
|
//VolumePath = L"";
|
|
WsbAffirmHr(VolumePath.Append(m_path));
|
|
((OLECHAR *) VolumePath)[wcslen(VolumePath) - 1] = L'\0';
|
|
|
|
WsbTrace(OLESTR("CFsaResource::FindFileId - Volume path is <%ls>\n"),
|
|
static_cast<WCHAR*>(VolumePath));
|
|
|
|
VolumeHandle = CreateFileW( VolumePath,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL );
|
|
|
|
WsbAffirmHandle(VolumeHandle);
|
|
|
|
RtlInitUnicodeString(&str, (WCHAR *) &fileId);
|
|
str.Length = 8;
|
|
str.MaximumLength = 8;
|
|
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&str,
|
|
OBJ_CASE_INSENSITIVE,
|
|
VolumeHandle,
|
|
NULL );
|
|
|
|
Status = NtCreateFile(&File,
|
|
FILE_READ_ATTRIBUTES,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
NULL, // AllocationSize
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN,
|
|
FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_BY_FILE_ID | FILE_OPEN_REPARSE_POINT,
|
|
NULL, // EaBuffer
|
|
0);
|
|
|
|
WsbTrace(OLESTR("CFsaResource::FindFileId - NtCreateFile status = %lx\n"),
|
|
static_cast<LONG>(Status));
|
|
if (STATUS_INVALID_PARAMETER == Status) {
|
|
// This seems to be the error we get if the file is missing so
|
|
// we translate it to something our code will understand
|
|
WsbThrow(WSB_E_NOTFOUND);
|
|
}
|
|
WsbAffirmNtStatus(Status);
|
|
|
|
GetNameStatus = STATUS_BUFFER_OVERFLOW;
|
|
//
|
|
// Take a guess at the path length to start with
|
|
//
|
|
pathSize = 256 + sizeof(FILE_NAME_INFORMATION);
|
|
//
|
|
// Keep trying for the name until we get an error other than buffer overflow or success.
|
|
//
|
|
|
|
WsbAffirmPointer((buffer = (OLECHAR *) malloc(pathSize)));
|
|
|
|
do {
|
|
FileName = (PFILE_NAME_INFORMATION) buffer;
|
|
|
|
GetNameStatus = NtQueryInformationFile( File,
|
|
&IoStatusBlock,
|
|
FileName,
|
|
pathSize - sizeof(WCHAR), // leave room for the NULL we add
|
|
FileNameInformation );
|
|
|
|
WsbTrace(OLESTR("CFsaResource::FindFileId - NtQueryInformationFile status = %ld\n"),
|
|
static_cast<LONG>(GetNameStatus));
|
|
|
|
if (GetNameStatus == STATUS_BUFFER_OVERFLOW) {
|
|
pathSize += 256;
|
|
WsbAffirmPointer((buffer = (OLECHAR *) realloc(buffer, pathSize)));
|
|
}
|
|
} while (GetNameStatus == STATUS_BUFFER_OVERFLOW);
|
|
|
|
WsbAffirmNtStatus(GetNameStatus);
|
|
|
|
FileName->FileName[FileName->FileNameLength / sizeof(WCHAR)] = L'\0';
|
|
filePath = FileName->FileName;
|
|
|
|
// Scan starting at the specified path.
|
|
WsbAffirmHr(pScanItem->FindFirst((IFsaResource*) this, filePath, pSession));
|
|
|
|
// If we found something, then return the scan item.
|
|
WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItem, (void**) ppScanItem));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
// Make sure we clean up
|
|
if (INVALID_HANDLE_VALUE != VolumeHandle) {
|
|
CloseHandle(VolumeHandle);
|
|
}
|
|
|
|
if (INVALID_HANDLE_VALUE != File) {
|
|
NtClose(File);
|
|
}
|
|
|
|
if (buffer != NULL) {
|
|
free(buffer);
|
|
}
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::FindFileId"), OLESTR("hr = <%ls>"),
|
|
WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::FindObjectId(
|
|
IN LONGLONG objIdHi,
|
|
IN LONGLONG objIdLo,
|
|
IN IHsmSession* pSession,
|
|
OUT IFsaScanItem** ppScanItem
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::FindObjectId().
|
|
|
|
Creates a scan item for the given object Id.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaScanItemPriv> pScanItem;
|
|
CWsbStringPtr VolumePath;
|
|
HANDLE File = INVALID_HANDLE_VALUE;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
LONG pathLength;
|
|
WCHAR unicodeStringBuffer[100];
|
|
UNICODE_STRING unicodeString;
|
|
FILE_INTERNAL_INFORMATION iInfo;
|
|
LONGLONG fileId;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::FindObjectId"), OLESTR("Object ID = %I64x %I64x"), objIdHi, objIdLo);
|
|
try {
|
|
WsbAssert(0 != ppScanItem, E_POINTER);
|
|
|
|
// Create an FsaScanItem that will scan for us.
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL, CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
|
|
|
|
|
|
//
|
|
// Open by object ID
|
|
// Relative opens from the Volume Handle.
|
|
//
|
|
|
|
VolumePath = L"\\??\\";
|
|
//VolumePath = L"";
|
|
|
|
WsbAffirmHr(VolumePath.Append((WCHAR *) m_path));
|
|
|
|
|
|
WsbTrace(OLESTR("CFsaResource::FindObjectId - Volume path is %ws.\n"), (OLECHAR *) VolumePath);
|
|
WsbTrace(OLESTR("CFsaResource::FindObjectId - Object ID = %I64x %I64x.\n"), objIdHi, objIdLo);
|
|
|
|
pathLength = wcslen(VolumePath);
|
|
RtlInitUnicodeString(&unicodeString, unicodeStringBuffer);
|
|
unicodeString.Length = (USHORT)((pathLength * sizeof(WCHAR)) + (sizeof(LONGLONG) * 2));
|
|
RtlCopyMemory(&unicodeString.Buffer[0], VolumePath, pathLength * sizeof(WCHAR));
|
|
RtlCopyMemory(&unicodeString.Buffer[pathLength], &objIdHi, sizeof(LONGLONG));
|
|
RtlCopyMemory(&unicodeString.Buffer[pathLength + (sizeof(LONGLONG) / sizeof(WCHAR))], &objIdLo, sizeof(LONGLONG));
|
|
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&unicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
0,
|
|
NULL );
|
|
|
|
WsbAffirmNtStatus(Status = NtCreateFile( &File,
|
|
FILE_READ_ATTRIBUTES,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
NULL, // AllocationSize
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN,
|
|
FILE_OPEN_BY_FILE_ID | FILE_OPEN_REPARSE_POINT,
|
|
NULL, // EaBuffer
|
|
0 ));
|
|
|
|
|
|
//
|
|
// Get the file id from the object ID
|
|
//
|
|
WsbAffirmHr(NtQueryInformationFile(File, &IoStatusBlock, &iInfo, sizeof(FILE_INTERNAL_INFORMATION), FileInternalInformation));
|
|
fileId = iInfo.IndexNumber.QuadPart;
|
|
|
|
WsbAffirmNtStatus(NtClose(File));
|
|
File = INVALID_HANDLE_VALUE;
|
|
|
|
// Now open by file id.
|
|
WsbAffirmHr(FindFileId(fileId, pSession, ppScanItem));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
// Make sure we clean up.
|
|
if (INVALID_HANDLE_VALUE != File) {
|
|
NtClose( File );
|
|
}
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::FindObjectId"), OLESTR("hr = <%ls>"),
|
|
WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetAlternatePath(
|
|
OUT OLECHAR** pPath,
|
|
IN ULONG bufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetAlternatePath().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pPath, E_POINTER);
|
|
WsbAffirmHr(m_alternatePath.CopyTo(pPath, bufferSize));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetClassID(
|
|
OUT CLSID* pClsid
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IPersist::GetClassID().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::GetClassID"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pClsid, E_POINTER);
|
|
*pClsid = CLSID_CFsaResourceNTFS;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetDbPath(
|
|
OUT OLECHAR** pPath,
|
|
IN ULONG bufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetDbPath().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CWsbStringPtr tmpString;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::GetDbPath"), OLESTR(""));
|
|
try {
|
|
|
|
WsbAssert(0 != pPath, E_POINTER);
|
|
|
|
// Use a relative path under the install directory.
|
|
WsbAffirmHr(m_pFsaServer->GetIDbPath(&tmpString, 0));
|
|
tmpString.Append(OLESTR("\\"));
|
|
tmpString.Append(WsbGuidAsString(m_id));
|
|
|
|
WsbAffirmHr(tmpString.CopyTo(pPath, bufferSize));
|
|
|
|
} WsbCatch(hr);
|
|
WsbTraceOut(OLESTR("CFsaResource::GetDbPath"), OLESTR("hr = <%ls>, path = <%ls)"),
|
|
WsbHrAsString(hr), WsbPtrToStringAsString(pPath));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT
|
|
CFsaResource::GetUnmanageDbPath(
|
|
OUT OLECHAR** pPath,
|
|
IN ULONG bufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetDbPath().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CWsbStringPtr tmpString;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::GetUnmanageDbPath"), OLESTR(""));
|
|
try {
|
|
WsbAssert(0 != pPath, E_POINTER);
|
|
|
|
// Use a relative path under the install directory.
|
|
WsbAffirmHr(m_pFsaServer->GetUnmanageIDbPath(&tmpString, 0));
|
|
tmpString.Append(OLESTR("\\"));
|
|
tmpString.Append(UNMANAGE_DB_PREFIX);
|
|
tmpString.Append(WsbGuidAsString(m_id));
|
|
|
|
WsbAffirmHr(tmpString.CopyTo(pPath, bufferSize));
|
|
|
|
} WsbCatch(hr);
|
|
WsbTraceOut(OLESTR("CFsaResource::GetUnmanageDbPath"), OLESTR("hr = <%ls>, path = <%ls)"),
|
|
WsbHrAsString(hr), WsbPtrToStringAsString(pPath));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetDefaultRules(
|
|
OUT IWsbCollection** ppCollection
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetDefaultRules().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != ppCollection, E_POINTER);
|
|
|
|
*ppCollection = m_pDefaultRules;
|
|
m_pDefaultRules->AddRef();
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetFreeLevel(
|
|
OUT ULONG* pLevel
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetFreeLevel().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LONGLONG total;
|
|
LONGLONG free;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pLevel, E_POINTER);
|
|
|
|
// Get the capacities for this resource.
|
|
WsbAffirmHr(GetSizes(&total, &free, 0, 0));
|
|
*pLevel = (ULONG) (((double)free / (double)total) * (double)FSA_HSMLEVEL_100);
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetFsName(
|
|
OUT OLECHAR** pFsName,
|
|
IN ULONG bufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetFsName().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pFsName, E_POINTER);
|
|
WsbAffirmHr(m_fsName.CopyTo(pFsName, bufferSize));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetHsmEngine(
|
|
IHsmFsaTskMgr** ppEngine
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetHsmEngine().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IHsmServer> pHsmServer;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::GetHsmEngine"), OLESTR(""));
|
|
try {
|
|
WsbAssert(0 != ppEngine, E_POINTER);
|
|
|
|
if (m_pHsmEngine != 0) {
|
|
//
|
|
// See if the connection is still valid
|
|
//
|
|
CComPtr<IHsmFsaTskMgr> pTestInterface;
|
|
hr = m_pHsmEngine->ContactOk();
|
|
if (hr != S_OK) {
|
|
// We don't have a valid
|
|
WsbTrace(OLESTR("CHsmServer::GetHsmEngine - Current connection invalid.\n"));
|
|
hr = S_OK;
|
|
m_pHsmEngine = 0;
|
|
}
|
|
}
|
|
// If we haven't already looked it up, then do so now.
|
|
if (m_pHsmEngine == 0) {
|
|
WsbAffirm(IsManaged() == S_OK, E_FAIL);
|
|
WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, m_managingHsm, IID_IHsmServer, (void**) &pHsmServer));
|
|
WsbAffirmHr(pHsmServer->GetHsmFsaTskMgr(&m_pHsmEngine));
|
|
}
|
|
|
|
// Return the pointer that we have stored.
|
|
*ppEngine = m_pHsmEngine;
|
|
m_pHsmEngine->AddRef();
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::GetHsmEngine"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetHsmLevel(
|
|
OUT ULONG* pLevel
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetHsmLevel().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pLevel, E_POINTER);
|
|
|
|
*pLevel = m_hsmLevel;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetIdentifier(
|
|
OUT GUID* pId
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetIdentifier().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pId, E_POINTER);
|
|
|
|
*pId = m_id;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetLogicalName(
|
|
OUT OLECHAR** pName,
|
|
IN ULONG bufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetLogicalName().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CWsbStringPtr tmpString;
|
|
CWsbStringPtr name;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pName, E_POINTER);
|
|
WsbAssert(m_pFsaServer != 0, E_POINTER);
|
|
|
|
WsbAffirmHr(tmpString.TakeFrom(*pName, bufferSize));
|
|
|
|
try {
|
|
|
|
// This is an arbitrary choice for the naming convention. Nothing has been
|
|
// decided upon.
|
|
WsbAffirmHr(m_pFsaServer->GetLogicalName(&tmpString, 0));
|
|
WsbAffirmHr(GetPath(&name, 0));
|
|
//
|
|
// Strip off trailing \ if there
|
|
if (name[(int) wcslen((WCHAR *) name) - 1] == L'\\') {
|
|
name[(int) wcslen((WCHAR *) name) - 1] = L'\0';
|
|
}
|
|
WsbAffirmHr(tmpString.Append(OLESTR("\\")));
|
|
WsbAffirmHr(tmpString.Append(name));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbAffirmHr(tmpString.GiveTo(pName));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetManageableItemLogicalSize(
|
|
OUT LONGLONG* pSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetManageableItemLogicalSize().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pSize, E_POINTER);
|
|
|
|
*pSize = m_manageableItemLogicalSize;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetManageableItemAccessTime(
|
|
OUT BOOL* pIsRelative,
|
|
OUT FILETIME* pTime
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetManageableItemAccessTime().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pIsRelative, E_POINTER);
|
|
WsbAssert(0 != pTime, E_POINTER);
|
|
|
|
*pIsRelative = m_manageableItemAccessTimeIsRelative;
|
|
*pTime = m_manageableItemAccessTime;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetManagingHsm(
|
|
GUID* pId
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetManagingHsm().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pId, E_POINTER);
|
|
|
|
*pId = m_managingHsm;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetName(
|
|
OUT OLECHAR** pName,
|
|
IN ULONG bufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetName().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::GetName"), OLESTR(""));
|
|
try {
|
|
|
|
WsbAssert(0 != pName, E_POINTER);
|
|
WsbAffirmHr(m_name.CopyTo(pName, bufferSize));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::GetName"), OLESTR("hr = <%ls>, name = <%ls>"),
|
|
WsbHrAsString(hr), (OLECHAR *)m_name);
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetOldPath(
|
|
OUT OLECHAR** pPath,
|
|
IN ULONG bufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetOldPath().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pPath, E_POINTER);
|
|
WsbAffirmHr(m_oldPath.CopyTo(pPath, bufferSize));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetPath(
|
|
OUT OLECHAR** pPath,
|
|
IN ULONG bufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetPath().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pPath, E_POINTER);
|
|
WsbAffirmHr(m_path.CopyTo(pPath, bufferSize));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetStickyName(
|
|
OUT OLECHAR** pPath,
|
|
IN ULONG bufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetStickyName().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pPath, E_POINTER);
|
|
WsbAffirmHr(m_stickyName.CopyTo(pPath, bufferSize));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetUserFriendlyName(
|
|
OUT OLECHAR** pPath,
|
|
IN ULONG bufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetUserFriendlyName().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pPath, E_POINTER);
|
|
WsbAffirmHr(m_userName.CopyTo(pPath, bufferSize));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetPremigrated(
|
|
IN REFIID riid,
|
|
OUT void** ppDb
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::GetPremigrated
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
WsbAssert(0 != ppDb, E_POINTER);
|
|
if (m_isDbInitialized) {
|
|
WsbAffirmHr(m_pPremigrated->QueryInterface(riid, ppDb));
|
|
hr = S_OK;
|
|
} else {
|
|
hr = WSB_E_RESOURCE_UNAVAILABLE;
|
|
}
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT
|
|
CFsaResource::GetUnmanageDb(
|
|
IN REFIID riid,
|
|
OUT void** ppDb
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::GetUnmanageDb
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
WsbAssert(0 != ppDb, E_POINTER);
|
|
if ((m_isUnmanageDbInitialized) && (m_pUnmanageDb != NULL)) {
|
|
WsbAffirmHr(m_pUnmanageDb->QueryInterface(riid, ppDb));
|
|
hr = S_OK;
|
|
} else {
|
|
hr = WSB_E_RESOURCE_UNAVAILABLE;
|
|
}
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetSerial(
|
|
OUT ULONG *serial
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv:GetSerial
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::GetSerial"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != serial, E_POINTER);
|
|
|
|
*serial = m_serial;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::GetSerial"), OLESTR("hr = <%ls>, Serial = %u"), WsbHrAsString(hr), m_serial);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetSizeMax(
|
|
OUT ULARGE_INTEGER* pSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IPersistStream::GetSizeMax().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IPersistStream> pPersistStream;
|
|
ULARGE_INTEGER entrySize;
|
|
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::GetSizeMax"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pSize, E_POINTER);
|
|
|
|
// Determine the size for a rule with no criteria.
|
|
pSize->QuadPart = WsbPersistSize((wcslen(m_name) + 1) * sizeof(OLECHAR)) +
|
|
WsbPersistSize((wcslen(m_fsName) + 1) * sizeof(OLECHAR)) +
|
|
WsbPersistSize((wcslen(m_path) + 1) * sizeof(OLECHAR)) +
|
|
WsbPersistSize((wcslen(m_alternatePath) + 1) * sizeof(OLECHAR)) +
|
|
3 * WsbPersistSizeOf(LONGLONG) +
|
|
WsbPersistSizeOf(FILETIME) +
|
|
WsbPersistSizeOf(BOOL) +
|
|
3 * WsbPersistSizeOf(ULONG) +
|
|
WsbPersistSizeOf(FSA_RESOURCE_COMPARE) +
|
|
2 * WsbPersistSizeOf(GUID);
|
|
|
|
// Now allocate space for the default rules list.
|
|
WsbAffirmHr((m_pDefaultRules)->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
|
WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
|
|
pSize->QuadPart += entrySize.QuadPart;
|
|
pPersistStream = 0;
|
|
|
|
// Now allocate space for the premigration list.
|
|
WsbAffirmHr(((IWsbDb*)m_pPremigrated)->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
|
WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
|
|
pSize->QuadPart += entrySize.QuadPart;
|
|
pPersistStream = 0;
|
|
|
|
// Now allocate space for truncator.
|
|
WsbAffirmHr(m_pTruncator->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
|
WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
|
|
pSize->QuadPart += entrySize.QuadPart;
|
|
pPersistStream = 0;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pSize));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetSizes(
|
|
OUT LONGLONG* pTotal,
|
|
OUT LONGLONG* pFree,
|
|
OUT LONGLONG* pPremigrated,
|
|
OUT LONGLONG* pTruncated
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetSizes().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CWsbStringPtr path;
|
|
ULARGE_INTEGER freeCaller;
|
|
ULARGE_INTEGER total;
|
|
ULARGE_INTEGER free;
|
|
|
|
|
|
try {
|
|
|
|
if ((0 != pTotal) || (0 != pFree)) {
|
|
|
|
WsbAffirmHr(GetPath(&path, 0));
|
|
WsbAffirmHr(path.Prepend("\\\\?\\"));
|
|
WsbAffirmStatus(GetDiskFreeSpaceEx(path, &freeCaller, &total, &free));
|
|
|
|
if (0 != pTotal) {
|
|
*pTotal = total.QuadPart;
|
|
}
|
|
|
|
if (0 != pFree) {
|
|
*pFree = free.QuadPart;
|
|
}
|
|
}
|
|
|
|
if (0 != pPremigrated) {
|
|
*pPremigrated = m_premigratedSize;
|
|
}
|
|
|
|
if (0 != pTruncated) {
|
|
*pTruncated = m_truncatedSize;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetTruncator(
|
|
IFsaTruncator** ppTruncator
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetTruncator().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != ppTruncator, E_POINTER);
|
|
|
|
// Return the pointer that we have stored.
|
|
*ppTruncator = m_pTruncator;
|
|
if (m_pTruncator != 0) {
|
|
m_pTruncator->AddRef();
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetUncPath(
|
|
OUT OLECHAR** pPath,
|
|
IN ULONG bufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetUncPath().
|
|
|
|
// Returns system generated UNC path if there is one. If not it returns WSB_E_NOTFOUND
|
|
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CWsbStringPtr tmpString;
|
|
OLECHAR driveName[3];
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pPath, E_POINTER);
|
|
|
|
// The path is either "d:\" where d is a drive letter or "Volume{GUID}" for an
|
|
// unnamed drive. So make sure we have at least that many characters.
|
|
//
|
|
if (wcslen(m_path) >= 3) {
|
|
|
|
// There is no system created UNC path to a volume without a drive letter so
|
|
// see if the path has form of "Volume{GUID}". For a volume with no drive letter we
|
|
// store this PNP (sticky) name as the path also.
|
|
|
|
if (wcsstr(m_path, OLESTR("Volume{")) != 0) {
|
|
WsbAffirmHr(tmpString.GiveTo(pPath)); // give caller an empty string back.
|
|
}
|
|
else {
|
|
// The UNC path is \\ssss\d$, where ssss is the server name and d is the drive
|
|
// letter.
|
|
WsbAffirmHr(tmpString.TakeFrom(*pPath, bufferSize));
|
|
|
|
WsbAffirmHr(m_pFsaServer->GetName(&tmpString, 0));
|
|
WsbAffirmHr(tmpString.Prepend(OLESTR("\\\\")));
|
|
WsbAffirmHr(tmpString.Append(OLESTR("\\")));
|
|
driveName[0] = m_path[0];
|
|
driveName[1] = L'$';
|
|
driveName[2] = 0;
|
|
|
|
WsbAffirmHr(tmpString.Append(driveName));
|
|
|
|
WsbAffirmHr(tmpString.GiveTo(pPath));
|
|
}
|
|
} else {
|
|
hr = WSB_E_NOTFOUND;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::GetUsnId(
|
|
OUT ULONGLONG *usnId
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::GetUsnId().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != usnId, E_POINTER);
|
|
|
|
*usnId = m_usnJournalId;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::Init(
|
|
IN IFsaServer* pFsaServer,
|
|
IN OLECHAR* path,
|
|
IN OLECHAR* dosName
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::Init().
|
|
|
|
Routine Description:
|
|
|
|
This routine implements the COM method for testing a resource to see if it is
|
|
'manageable' by the HSM (Remote Storage) system. (Only NTFS-formatted
|
|
volumes which support sparse files and reparse points are considered to be
|
|
manageable by Sakkara.) If the resource is manageable, it initializes the
|
|
resource object.
|
|
|
|
Arguments:
|
|
|
|
pFsaServer - Interface pointer to the FSA service that is scanning this resource.
|
|
|
|
path - The long ugly PNP name that can be used if there is no drive letter for
|
|
the resource being tested (i.e., it is mounted as a volume without a
|
|
drive letter).
|
|
|
|
dosName - The drive letter (if there is one) of the resource being tested.
|
|
|
|
Return Value:
|
|
|
|
S_OK - The call succeeded (the resource being tested was found to be manageable,
|
|
and the resource object was initialized).
|
|
|
|
FSA_E_UNMANAGEABLE - Thrown if the resource being tested for manageability is
|
|
found to be unmanageable.
|
|
|
|
FSA_E_NOMEDIALOADED - Thrown if the resource being tested for manageability is
|
|
a removable type of drive and no media is presently loaded.
|
|
|
|
E_POINTER - Thrown if the path argument passed in is null.
|
|
|
|
Any other value - The call failed because one of the Remote Storage or Win32 API
|
|
calls contained internally in this method failed. The error value returned
|
|
is specific to the API call which failed.
|
|
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr = FSA_E_UNMANAGABLE;
|
|
UINT type;
|
|
UINT lastErrorMode;
|
|
BOOL gotInfo = FALSE;
|
|
OLECHAR alternatePath[256];
|
|
CWsbStringPtr queryPath;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::Init"), OLESTR("path = <%ls>, dosName = <%ls>"),
|
|
(OLECHAR *)path, (OLECHAR *)dosName);
|
|
try {
|
|
|
|
WsbAssert(0 != path, E_POINTER);
|
|
|
|
// Determine type of drive (removable, fixed, CD-ROM, RAM or network).
|
|
type = GetDriveType(path);
|
|
|
|
// Only FIXED or removable media are candidates for management
|
|
// (ignore network drives, ...).
|
|
//
|
|
// NOTE: For now, it has been decided not to allow removable media.
|
|
// if ((type == DRIVE_FIXED) || (type == DRIVE_REMOVABLE)) {
|
|
if (type == DRIVE_FIXED) {
|
|
|
|
// Get more information about the resource. For removable drives, we want to
|
|
// fail if no volume is located.
|
|
m_name.Realloc(128); // volume name
|
|
m_fsName.Realloc(128); // volume file system type (e.g., FAT, NTFS)
|
|
|
|
if (type == DRIVE_REMOVABLE) {
|
|
// Suppress OS message asking to install a volume in the drive if it is
|
|
// found to be missing.
|
|
|
|
// First get the current error-mode bit flags by clearing them.
|
|
lastErrorMode = SetErrorMode(0);
|
|
// Reset error-mode bit flags by 'or'ing them with the value which
|
|
// suppresses critical error messages.
|
|
SetErrorMode(lastErrorMode | SEM_FAILCRITICALERRORS);
|
|
|
|
gotInfo = GetVolumeInformation(path, m_name, 128, &m_serial,
|
|
&m_maxComponentLength, &m_fsFlags, m_fsName, 128);
|
|
|
|
// Got resource info, reset error-mode bit flags to original setting.
|
|
SetErrorMode(lastErrorMode);
|
|
|
|
// Throw and abort if no volume loaded.
|
|
WsbAffirm(gotInfo, FSA_E_NOMEDIALOADED);
|
|
|
|
} else { // if drive is a fixed drive type:
|
|
|
|
// This call can fail. This should just cause a message to be logged
|
|
// and the resource to be skipped.
|
|
try {
|
|
WsbAffirmStatus(GetVolumeInformation(path, m_name, 128, &m_serial,
|
|
&m_maxComponentLength, &m_fsFlags, m_fsName, 128));
|
|
} WsbCatchAndDo(hr,
|
|
WsbLogEvent(FSA_MESSAGE_RSCFAILEDINIT, 0, NULL, WsbHrAsString(hr),
|
|
WsbAbbreviatePath(path, 120), 0);
|
|
WsbThrow(FSA_E_UNMANAGABLE);
|
|
);
|
|
}
|
|
|
|
// Trace out info about the volume.
|
|
CWsbStringPtr traceString;
|
|
|
|
traceString = m_fsName;
|
|
|
|
traceString.Append(OLESTR(" file system, supports ... "));
|
|
|
|
// Note that MS removed support for Remote Storage bit flag.
|
|
if ((m_fsFlags & FILE_SUPPORTS_REPARSE_POINTS) != 0) {
|
|
traceString.Append(OLESTR("reparse points ... "));
|
|
}
|
|
if ((m_fsFlags & FILE_SUPPORTS_SPARSE_FILES) != 0) {
|
|
traceString.Append(OLESTR("sparse files ... "));
|
|
}
|
|
|
|
traceString.Append(OLESTR("\n"));
|
|
|
|
WsbTrace(traceString);
|
|
|
|
// Currently, we only support NTFS volumes that support sparse files and
|
|
// reparse points (since support for Remote Storage bit flag was removed).
|
|
if ((_wcsicmp(m_fsName, OLESTR("NTFS")) == 0) &&
|
|
((m_fsFlags & FILE_SUPPORTS_SPARSE_FILES) != 0) &&
|
|
((m_fsFlags & FILE_SUPPORTS_REPARSE_POINTS) != 0)) {
|
|
|
|
// Indicate this is a manageable volume.
|
|
hr = S_OK;
|
|
|
|
// Store the parent FSA, but since it is a weak reference, do not AddRef().
|
|
m_pFsaServer = pFsaServer;
|
|
|
|
// Store the "sticky" name - this is the long ugly PNP name that can be
|
|
// used if there is no drive letter. (skip the prefix - \\?\)
|
|
m_stickyName = &path[4];
|
|
|
|
// Store the path to the resource. Use the drive letter if it is present
|
|
// (dosName != NULL and contains drive letter), else store it to be the same as the "sticky name".
|
|
if (NULL != dosName) {
|
|
if ((wcslen(dosName) == 2) && (dosName[wcslen(dosName)-1] == L':')) {
|
|
m_path = dosName;
|
|
m_path.Append(OLESTR("\\"));
|
|
} else {
|
|
// It is a mount point path
|
|
m_path = &path[4];
|
|
}
|
|
} else {
|
|
m_path = &path[4];
|
|
}
|
|
WsbTrace(OLESTR("CFsaResource::Init - m_path = %ws\n"), (WCHAR *) m_path);
|
|
|
|
// Now save the "User Friendly" name for the resource. If there is a
|
|
// drive letter it is used. If it is an unnamed volume then there is
|
|
// no user friendly name and a NULL string is stored. The volume name
|
|
// should also be shown in this case.
|
|
if (NULL != dosName) {
|
|
m_userName = dosName;
|
|
m_userName.Append(OLESTR("\\"));
|
|
} else {
|
|
|
|
m_userName = L"";
|
|
}
|
|
|
|
WsbTrace(OLESTR("CFsaResource::Init - UserPath = %ws\n"), (WCHAR *) m_userName);
|
|
|
|
// Get the alternate path to the resource. This requires removing the '\'
|
|
// from the path.
|
|
queryPath = &path[4];
|
|
if (L'\\' == queryPath[(int) wcslen((WCHAR *) queryPath) - 1]) {
|
|
queryPath[(int) wcslen((WCHAR *) queryPath) - 1] = L'\0';
|
|
}
|
|
|
|
WsbTrace(OLESTR("CFsaResource::Init - QueryPath = %ws\n"),
|
|
(WCHAR *) queryPath);
|
|
|
|
WsbAffirm(QueryDosDevice(queryPath, alternatePath, 256) != 0,
|
|
HRESULT_FROM_WIN32(GetLastError()));
|
|
m_alternatePath = alternatePath;
|
|
//
|
|
// Get the unique id for the volume
|
|
//
|
|
WsbAffirmHr(ReadIdentifier());
|
|
}
|
|
}
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::Init"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::InitializePremigrationList(
|
|
BOOL bStartValidateJob
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
If this volume is managed & active & available: create or
|
|
open the premigration-list DB; schedule a validate job if requested;
|
|
if recovery is also done, start the truncator running.
|
|
|
|
Arguments:
|
|
|
|
bStartValidateJob - If TRUE, schedule a validate job on this volume
|
|
if we just created a new DB
|
|
|
|
Return Value:
|
|
|
|
S_OK - The call succeeded.
|
|
S_FALSE - The actions were skipped because some condition was not met
|
|
E_* - An error occurred.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::InitializePremigrationList"),
|
|
OLESTR("m_managingHsm = %ls, m_isActive = %ls, m_isAvailable = %ls, m_isDbInitialized = %ls, m_isRecovered = %ls"),
|
|
WsbGuidAsString(m_managingHsm), WsbBoolAsString(m_isActive),
|
|
WsbBoolAsString(m_isAvailable), WsbBoolAsString(m_isDbInitialized),
|
|
WsbBoolAsString(m_isRecovered));
|
|
try {
|
|
if ((S_OK == IsManaged()) && m_isActive && m_isAvailable) {
|
|
|
|
// Create/open the DB if not done already
|
|
if (!m_isDbInitialized) {
|
|
BOOL bCreated;
|
|
CWsbStringPtr dbPath;
|
|
CComPtr<IWsbDbSys> pDbSys;
|
|
|
|
WsbAffirmHr(m_pFsaServer->GetIDbSys(&pDbSys));
|
|
WsbAffirmHr(GetDbPath(&dbPath, 0));
|
|
WsbAffirmHr(m_pPremigrated->Init(dbPath, pDbSys, &bCreated));
|
|
m_isDbInitialized = TRUE;
|
|
if (bCreated) {
|
|
// Can't have recovery records if we just created
|
|
// the DB
|
|
m_isRecovered = TRUE;
|
|
}
|
|
|
|
if (bCreated && bStartValidateJob) {
|
|
LARGE_INTEGER ctime;
|
|
FILETIME curTime;
|
|
SYSTEMTIME sysTime;
|
|
CWsbStringPtr tmpString;
|
|
|
|
// Determine if the Engine is up and running. If it isn't
|
|
// we have to set a value in the registry that the Engine
|
|
// will find when it comes up and it will schedule the
|
|
// validate job. If the Engine is up, we can take care of
|
|
// scheduling the validate job ourselves. (If we don't, the
|
|
// Engine won't do it until the next time it starts up.)
|
|
hr = WsbCheckService(NULL, APPID_RemoteStorageEngine);
|
|
if (S_OK != hr) {
|
|
// "Schedule" a validate job to rebuild the premigration list.
|
|
// This is done by putting a value in the registry since the Engine
|
|
// may not be running right now so we can't set up a job.
|
|
WsbLogEvent(FSA_MESSAGE_PREMIGRATION_LIST_MISSING, 0, NULL,
|
|
(OLECHAR *) m_path, NULL);
|
|
WsbAffirmHr(tmpString.Alloc(32));
|
|
swprintf((OLECHAR *) tmpString, L"%x", m_serial);
|
|
GetSystemTime( &sysTime );
|
|
WsbAffirmStatus(SystemTimeToFileTime(&sysTime, &curTime));
|
|
ctime.LowPart = curTime.dwLowDateTime;
|
|
ctime.HighPart = curTime.dwHighDateTime;
|
|
WsbAffirmHr( WsbEnsureRegistryKeyExists( 0, FSA_VALIDATE_LOG_KEY_NAME ) );
|
|
WsbAffirmHr(WsbSetRegistryValueData(NULL, FSA_VALIDATE_LOG_KEY_NAME,
|
|
tmpString, (BYTE *) &ctime, sizeof(ctime)));
|
|
} else {
|
|
WsbAffirmHr(CheckForValidate(TRUE));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Start the auto-truncator if recovery is done
|
|
if (m_pTruncator && m_isRecovered) {
|
|
|
|
// Try starting the truncator; ignore errors (we get one if
|
|
// truncator is already started)
|
|
m_pTruncator->Start((IFsaResource*) this);
|
|
}
|
|
}
|
|
} WsbCatch(hr);
|
|
WsbTraceOut(OLESTR("CFsaResource::InitializePremigrationList"), OLESTR("hr = <%ls>"),
|
|
WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT
|
|
CFsaResource::InitializeUnmanageDb(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::InitializeUnmanageDb().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::InitializeUnmanageDb"),
|
|
OLESTR("m_isActive = %ls, m_isAvailable = %ls, m_isUnmanageDbInitialized = %ls"),
|
|
WsbBoolAsString(m_isActive), WsbBoolAsString(m_isAvailable), WsbBoolAsString(m_isUnmanageDbInitialized));
|
|
try {
|
|
if ((S_OK == IsManaged()) && m_isActive && m_isAvailable) {
|
|
if (! m_pUnmanageDb) {
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaUnmanageDb, NULL, CLSCTX_SERVER, IID_IFsaUnmanageDb, (void**) &m_pUnmanageDb));
|
|
}
|
|
if (! m_isUnmanageDbInitialized) {
|
|
BOOL bCreated;
|
|
CWsbStringPtr dbPath;
|
|
CComPtr<IWsbDbSys> pDbSys;
|
|
|
|
// Get (and init if necessary) the idb instance
|
|
WsbAffirmHr(m_pFsaServer->GetUnmanageIDbSys(&pDbSys));
|
|
|
|
// Initialize the db
|
|
WsbAffirmHr(GetUnmanageDbPath(&dbPath, 0));
|
|
WsbAffirmHr(m_pUnmanageDb->Init(dbPath, pDbSys, &bCreated));
|
|
|
|
// Init succeeded means DB must have been created
|
|
WsbAssert(bCreated, E_UNEXPECTED);
|
|
|
|
m_isUnmanageDbInitialized = TRUE;
|
|
}
|
|
} else {
|
|
hr = WSB_E_RESOURCE_UNAVAILABLE;
|
|
}
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::InitializeUnmanageDb"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT
|
|
CFsaResource::TerminateUnmanageDb(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::TerminateUnmanageDb().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::TerminateUnmanageDb"),
|
|
OLESTR("m_isUnmanageDbInitialized = %ls"), WsbBoolAsString(m_isUnmanageDbInitialized));
|
|
try {
|
|
if (m_isUnmanageDbInitialized) {
|
|
WsbTrace(OLESTR("CFsaResource::TerminateUnmanageDb: Deleting Unmanage Db\n"));
|
|
hr = m_pUnmanageDb->Delete(NULL, IDB_DELETE_FLAG_NO_ERROR);
|
|
WsbTrace(OLESTR("CFsaResource::TerminateUnmanageDb: Deleting of Unmanage Db complete, hr = <%ls>\n"),
|
|
WsbHrAsString(hr));
|
|
if (SUCCEEDED(hr)) {
|
|
m_isUnmanageDbInitialized = FALSE;
|
|
m_pUnmanageDb = NULL;
|
|
}
|
|
}
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::TerminateUnmanageDb"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::IsActive(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::IsActive().
|
|
|
|
--*/
|
|
{
|
|
return(m_isActive ? S_OK : S_FALSE);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::IsAvailable(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::IsAvailable().
|
|
|
|
--*/
|
|
{
|
|
return(m_isAvailable ? S_OK : S_FALSE);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::IsDeletePending(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::IsDeletePending().
|
|
|
|
--*/
|
|
{
|
|
return(m_isDeletePending ? S_OK : S_FALSE);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::IsManaged(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::IsManaged().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (memcmp(&m_managingHsm, &GUID_NULL, sizeof(GUID)) == 0) {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::Load(
|
|
IN IStream* pStream
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IPersistStream::Load().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IPersistStream> pPersistStream;
|
|
CComPtr<IWsbCollectable> pCollectable;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::Load"), OLESTR(""));
|
|
|
|
try {
|
|
ULONG tmp;
|
|
|
|
WsbAssert(0 != pStream, E_POINTER);
|
|
|
|
// Do the easy stuff, but make sure that this order matches the order
|
|
// in the save method.
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_oldPath, 0));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_alternatePath, 0));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_name, 0));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_stickyName, 0));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_fsName, 0));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_maxComponentLength));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_fsFlags));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_id));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_isActive));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &tmp));
|
|
m_compareBy = (FSA_RESOURCE_COMPARE)tmp;
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_managingHsm));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_hsmLevel));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_premigratedSize));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_truncatedSize));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_manageableItemLogicalSize));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_manageableItemAccessTimeIsRelative));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_manageableItemAccessTime));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_usnJournalId));
|
|
WsbAffirmHr(WsbLoadFromStream(pStream, &m_lastUsnId));
|
|
|
|
|
|
// Load the default rules list
|
|
WsbAffirm(m_pDefaultRules != NULL, E_UNEXPECTED);
|
|
WsbAffirmHr((m_pDefaultRules)->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
|
WsbAffirmHr(pPersistStream->Load(pStream));
|
|
pPersistStream = 0;
|
|
|
|
// Load the premigration list DB
|
|
WsbAffirm(m_pPremigrated != NULL, E_UNEXPECTED);
|
|
WsbAffirmHr(((IWsbDb*)m_pPremigrated)->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
|
hr = pPersistStream->Load(pStream);
|
|
WsbTrace(OLESTR("CFsaResource::Load, DB load hr = <%ls>\n"), WsbHrAsString(hr));
|
|
if (S_OK == hr) {
|
|
m_isDbInitialized = TRUE;
|
|
} else {
|
|
m_isDbInitialized = FALSE;
|
|
hr = S_OK;
|
|
}
|
|
|
|
pPersistStream = 0;
|
|
|
|
// Load the truncator.
|
|
WsbAffirm(m_pTruncator != NULL, E_UNEXPECTED);
|
|
WsbAffirmHr(m_pTruncator->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
|
|
WsbAffirmHr(pPersistStream->Load(pStream));
|
|
pPersistStream = 0;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::Manage(
|
|
IN IFsaScanItem* pScanItem,
|
|
IN LONGLONG /*offset*/,
|
|
IN LONGLONG /*size*/,
|
|
IN GUID storagePoolId,
|
|
IN BOOL truncate
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::Manage().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaPostIt> pWorkItem;
|
|
CComPtr<IHsmFsaTskMgr> pEngine;
|
|
CComPtr<IHsmSession> pSession;
|
|
CWsbStringPtr tmpString;
|
|
LONGLONG fileVersionId;
|
|
LONGLONG requestSize;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::Manage"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
// Make sure the Scan Item interface is OK
|
|
WsbAssert(pScanItem != 0, E_POINTER);
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
|
|
|
|
// Get the data from the scan item.
|
|
WsbAffirmHr(pScanItem->GetSession(&pSession));
|
|
WsbAffirmHr(pWorkItem->SetSession(pSession));
|
|
|
|
WsbAffirmHr(pScanItem->GetPathAndName(0, &tmpString, 0));
|
|
WsbAffirmHr(pScanItem->GetVersionId(&fileVersionId));
|
|
WsbAffirmHr(pWorkItem->SetFileVersionId(fileVersionId));
|
|
|
|
// Currently, we only can ask for the whole file.
|
|
WsbAffirmHr(pWorkItem->SetRequestOffset(0));
|
|
WsbAffirmHr(pScanItem->GetLogicalSize(&requestSize));
|
|
WsbAffirmHr(pWorkItem->SetRequestSize(requestSize));
|
|
|
|
// Fill in the rest of the work
|
|
WsbAffirmHr(pWorkItem->SetStoragePoolId(storagePoolId));
|
|
|
|
WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_PREMIGRATE));
|
|
if (truncate) {
|
|
WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_TRUNCATE));
|
|
} else {
|
|
WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_LIST));
|
|
}
|
|
|
|
// Send the request to the task manager
|
|
WsbAffirmHr(GetHsmEngine(&pEngine));
|
|
WsbAffirmHr(pWorkItem->SetPath(tmpString));
|
|
WsbAffirmHr(pScanItem->PrepareForManage(0, requestSize));
|
|
WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::Manage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::ManagedBy(
|
|
IN GUID hsmId,
|
|
IN ULONG hsmLevel,
|
|
IN BOOL release
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::ManagedBy().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IHsmSession> pSession;
|
|
HANDLE threadHandle;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::ManagedBy"), OLESTR("HsmId - <%ls>, hsmLevel - <%lu>, release = <%ls>"),
|
|
WsbGuidAsString(hsmId), hsmLevel, WsbBoolAsString(release));
|
|
try {
|
|
|
|
// Are we releasing or acquiring a managing HSM?
|
|
if (release) {
|
|
|
|
// We can only release if we are the orignal owner. This is to prevent two HSMs from thinking they
|
|
// manage the same resource at the same time. We may want a better way to do this.
|
|
WsbAffirm(memcmp(&m_managingHsm, &hsmId, sizeof(GUID)) == 0, FSA_E_RSCALREADYMANAGED);
|
|
|
|
// If the truncator is running, then ask it to stop.
|
|
WsbAffirmHr(m_pTruncator->GetSession(&pSession));
|
|
if (pSession != 0) {
|
|
WsbAffirmHr(pSession->ProcessEvent(HSM_JOB_PHASE_ALL, HSM_JOB_EVENT_CANCEL));
|
|
}
|
|
|
|
// Clear out the managing Hsm.
|
|
m_managingHsm = GUID_NULL;
|
|
m_pHsmEngine = 0;
|
|
m_isDeletePending = FALSE;
|
|
threadHandle = CreateThread(0, 0, FsaStartOnStateChange, (void*) this, 0, &g_ThreadId);
|
|
if (threadHandle != NULL) {
|
|
CloseHandle(threadHandle);
|
|
}
|
|
|
|
} else {
|
|
// Make sure there is a journal
|
|
// At this point we don't care about the need to
|
|
// validate
|
|
BOOL validateNeeded;
|
|
WsbAffirmHr(CheckForJournal(&validateNeeded));
|
|
|
|
// Is the id changing?
|
|
if (memcmp(&m_managingHsm, &hsmId, sizeof(GUID)) != 0) {
|
|
|
|
// Make sure that they set it to something valid.
|
|
WsbAssert(memcmp(&GUID_NULL, &hsmId, sizeof(GUID)) != 0, E_INVALIDARG);
|
|
|
|
// If the truncator is running, then ask it to stop.
|
|
WsbAffirmHr(m_pTruncator->GetSession(&pSession));
|
|
if (pSession != 0) {
|
|
WsbAffirmHr(pSession->ProcessEvent(HSM_JOB_PHASE_ALL, HSM_JOB_EVENT_CANCEL));
|
|
}
|
|
|
|
// Create/Recreate the default rules.
|
|
WsbAffirmHr(CreateDefaultRules());
|
|
|
|
// Store the Id and level.
|
|
m_managingHsm = hsmId;
|
|
m_hsmLevel = hsmLevel;
|
|
m_pHsmEngine = 0;
|
|
|
|
// Do recovery (if needed) and start truncator
|
|
if (m_isActive) {
|
|
if (m_isDbInitialized && !m_isRecovered) {
|
|
// DoRecovery will start truncator when it is done
|
|
WsbAffirmHr(DoRecovery());
|
|
} else {
|
|
WsbAffirmHr(InitializePremigrationList(TRUE));
|
|
}
|
|
}
|
|
|
|
threadHandle = CreateThread(0, 0, FsaStartOnStateChange, (void*) this, 0, &g_ThreadId);
|
|
if (threadHandle != NULL) {
|
|
CloseHandle(threadHandle);
|
|
}
|
|
|
|
} else {
|
|
BOOL DoKick = FALSE;
|
|
|
|
if (m_hsmLevel < hsmLevel) {
|
|
DoKick = TRUE;
|
|
}
|
|
m_hsmLevel = hsmLevel;
|
|
|
|
// Create/Recreate the default rules.
|
|
WsbAffirmHr(CreateDefaultRules());
|
|
|
|
// Wake up the AutoTruncator if the new level is higher
|
|
if (DoKick) {
|
|
WsbAffirmHr(m_pTruncator->KickStart());
|
|
}
|
|
}
|
|
}
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::ManagedBy"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::NeedsRepair(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::NeedsRepair().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG flag;
|
|
IO_STATUS_BLOCK Iosb;
|
|
CWsbStringPtr volumePath;
|
|
HANDLE volumeHandle = INVALID_HANDLE_VALUE;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::NeedsRepair"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
volumePath = L"\\\\.\\";
|
|
WsbAffirmHr(volumePath.Append(m_path));
|
|
((OLECHAR *) volumePath)[wcslen(volumePath) - 1] = L'\0';
|
|
WsbAffirmHandle(volumeHandle = CreateFileW(volumePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL));
|
|
WsbAffirmNtStatus(NtFsControlFile(volumeHandle, NULL, NULL, NULL, &Iosb, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &flag, sizeof(flag)));
|
|
WsbAffirmNtStatus(Iosb.Status);
|
|
|
|
if ((flag & VOLUME_IS_DIRTY) == 0) {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
if (INVALID_HANDLE_VALUE != volumeHandle) {
|
|
CloseHandle(volumeHandle);
|
|
}
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::NeedsRepair"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::ProcessResult(
|
|
IN IFsaPostIt* pResult
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::ProcessResult().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaScanItem> pScanItem;
|
|
CComPtr<IHsmSession> pSession;
|
|
FILETIME currentTime;
|
|
FSA_RESULT_ACTION resultAction = FSA_RESULT_ACTION_NONE;
|
|
FSA_PLACEHOLDER placeholder;
|
|
CWsbStringPtr path;
|
|
LONGLONG offset;
|
|
LONGLONG size;
|
|
ULONG mode;
|
|
HRESULT resultHr;
|
|
CComPtr<IFsaFilterRecall> pRecall;
|
|
ULONG completionSent = FALSE;
|
|
LONGLONG usn;
|
|
LONGLONG afterPhUsn;
|
|
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::ProcessResult"), OLESTR(""));
|
|
|
|
try {
|
|
BOOL wasPremigrated = FALSE;
|
|
BOOL wasTruncated = FALSE;
|
|
|
|
// Several of the actions need to know the current time, so calculate it now.
|
|
GetSystemTimeAsFileTime(¤tTime);
|
|
|
|
// Since the workItem session is IUnknown, QI for what we want.
|
|
WsbAffirmHr(pResult->GetSession(&pSession));
|
|
|
|
|
|
// Now perform the required action.
|
|
WsbAffirmHr(pResult->GetResultAction(&resultAction));
|
|
WsbAffirmHr(pResult->GetPlaceholder(&placeholder));
|
|
WsbAffirmHr(pResult->GetPath(&path, 0));
|
|
WsbAffirmHr(pResult->GetRequestOffset(&offset));
|
|
WsbAffirmHr(pResult->GetRequestSize(&size));
|
|
WsbAffirmHr(pResult->GetMode(&mode));
|
|
WsbAffirmHr(pResult->GetUSN(&usn));
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult, path = <%ls>, requestOffset = %I64d, requestSize = %I64d\n"),
|
|
WsbAbbreviatePath(path, 120), offset, size);
|
|
|
|
switch(resultAction) {
|
|
|
|
case FSA_RESULT_ACTION_DELETE:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Delete\n"));
|
|
WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
|
|
if (S_OK == pScanItem->IsPremigrated(offset, size)) {
|
|
wasPremigrated = TRUE;
|
|
} else if (S_OK == pScanItem->IsTruncated(offset, size)) {
|
|
wasTruncated = TRUE;
|
|
}
|
|
WsbAffirmHr(pScanItem->Delete());
|
|
if (wasPremigrated) {
|
|
WsbAffirmHr(RemovePremigrated(pScanItem, offset, size));
|
|
} else if (wasTruncated) {
|
|
WsbAffirmHr(RemoveTruncated(pScanItem, offset, size));
|
|
}
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_DELETEPLACEHOLDER:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Delete Placeholder\n"));
|
|
WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
|
|
|
|
// We shouldn't have gotten to here if the file isn't managed,
|
|
// but it's been known to happen
|
|
if (S_OK == pScanItem->IsManaged(offset, size)) {
|
|
HRESULT hrRemove = S_OK;
|
|
|
|
if (S_OK == pScanItem->IsPremigrated(offset, size)) {
|
|
wasPremigrated = TRUE;
|
|
} else if (S_OK == pScanItem->IsTruncated(offset, size)) {
|
|
wasTruncated = TRUE;
|
|
}
|
|
|
|
// RemovePremigrated needs to get some information from the placeholder, therefore, remove
|
|
// from premigrated db first and then (regardless of the result), delete the placeholder
|
|
if (wasPremigrated) {
|
|
hrRemove = RemovePremigrated(pScanItem, offset, size);
|
|
} else if (wasTruncated) {
|
|
hrRemove = RemoveTruncated(pScanItem, offset, size);
|
|
}
|
|
WsbAffirmHr(pScanItem->DeletePlaceholder(offset, size));
|
|
WsbAffirmHr(hrRemove);
|
|
}
|
|
|
|
// Remove the recovery record if we created one
|
|
if (m_isDbInitialized) {
|
|
BOOL bOpenDb = FALSE;
|
|
CComPtr<IWsbDbSession> pDbSession;
|
|
CComPtr<IFsaRecoveryRec> pRecRec;
|
|
|
|
try {
|
|
WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
|
|
bOpenDb = TRUE;
|
|
WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE,
|
|
IID_IFsaRecoveryRec, (void**) &pRecRec));
|
|
WsbAffirmHr(pRecRec->SetPath(path));
|
|
if (S_OK == pRecRec->FindEQ()) {
|
|
WsbAffirmHr(pRecRec->Remove());
|
|
}
|
|
} WsbCatch(hr);
|
|
if (bOpenDb) {
|
|
WsbAffirmHr(m_pPremigrated->Close(pDbSession));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_LIST:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Truncate / Add to Premigration List\n"));
|
|
WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
|
|
(placeholder).isTruncated = FALSE;
|
|
(placeholder).migrationTime = currentTime;
|
|
hr = pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn);
|
|
|
|
if (SUCCEEDED(hr) && (FSA_E_REPARSE_NOT_WRITTEN_FILE_CHANGED != hr)) {
|
|
//
|
|
// Add the file to the premigration list. If this fails, log and error
|
|
// and request that the validation code be run to hopefully correct this
|
|
// problem. This problem should not stop processing, so return OK
|
|
//
|
|
hr = AddPremigrated(pScanItem, offset, size, FALSE, afterPhUsn);
|
|
if (!SUCCEEDED(hr)) {
|
|
WsbLogEvent(FSA_MESSAGE_FILE_NOT_IN_PREMIG_LIST, 0, NULL, WsbAbbreviatePath(path, 120), WsbHrAsString(hr), NULL);
|
|
//
|
|
// TBD - launch validate job
|
|
//
|
|
hr = S_OK;
|
|
}
|
|
//
|
|
// Tell the truncator that we have added something to the list in case we are over the level.
|
|
// This will kick start the truncator to insure quick response.
|
|
//
|
|
WsbAffirmHr(m_pTruncator->KickStart());
|
|
}
|
|
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_NONE:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - None\n"));
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_OPEN:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Open (No longer placeholder)\n"));
|
|
|
|
// If it succeeded, then update the placeholder information.
|
|
WsbAffirmHr(pResult->GetResult(&resultHr));
|
|
WsbAffirmHr(pResult->GetFilterRecall(&pRecall));
|
|
WsbAssert(pRecall != 0, E_POINTER);
|
|
|
|
if (SUCCEEDED(resultHr)) {
|
|
WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
|
|
|
|
// The placeholder info is updated by the filter now.
|
|
// placeholder.recallTime = currentTime;
|
|
// placeholder.recallCount++;
|
|
// placeholder.isTruncated = FALSE;
|
|
// placeholder.truncateOnClose = FALSE;
|
|
// placeholder.premigrateOnClose = FALSE;
|
|
// WsbAffirmHr(pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn));
|
|
}
|
|
|
|
// If it had succeeded, then add the file in the premigration list.
|
|
// (This used to be done after communicating with the filter to
|
|
// give the client time to open the file before the truncator would
|
|
// try to retruncate it. This is no longer needed since we do the
|
|
// recall on first I/O not on the open. Leaving that order created
|
|
// a new problem: the file would have a reparse point saying it was
|
|
// premigrated and test code could then try to retruncate it, but it
|
|
// wouldn't be in the premigration list yet.)
|
|
if (SUCCEEDED(resultHr)) {
|
|
//
|
|
// We do not need to fail the recall if we cannot add the file to the premigration list.
|
|
// Just log a warning, if appropriate, and continue
|
|
//
|
|
try {
|
|
WsbAffirmHr(RemoveTruncated(pScanItem, offset, size));
|
|
WsbAffirmHr(pScanItem->GetFileUsn(&afterPhUsn));
|
|
WsbAffirmHr(AddPremigrated(pScanItem, offset, size, TRUE, afterPhUsn));
|
|
} WsbCatchAndDo(hr,
|
|
//
|
|
// We failed to add it to the premigration list. In some cases this is not an error worth
|
|
// reporting. For instance, when a file is moved to another volume it is copied (causing a recall) and then
|
|
// deleted. We can get an error here if the delete is pending or has completed and the failure to
|
|
// add the original file to the premigration list is not an error since the file is now gone.
|
|
//
|
|
if ( (hr != WSB_E_NOTFOUND) &&
|
|
((hr & ~(FACILITY_NT_BIT)) != STATUS_DELETE_PENDING) ) {
|
|
//
|
|
// Log all other errors
|
|
//
|
|
WsbLogEvent(FSA_MESSAGE_FILE_NOT_IN_PREMIG_LIST, 0, NULL,
|
|
(OLECHAR *) m_path, WsbQuickString(WsbHrAsString(hr)), NULL);
|
|
}
|
|
);
|
|
}
|
|
|
|
// Tell the filter that the recall attempt finished.
|
|
hr = pRecall->HasCompleted(resultHr);
|
|
completionSent = TRUE;
|
|
|
|
// Remove the recovery record if we created one
|
|
if (m_isDbInitialized) {
|
|
BOOL bOpenDb = FALSE;
|
|
CComPtr<IWsbDbSession> pDbSession;
|
|
CComPtr<IFsaRecoveryRec> pRecRec;
|
|
|
|
try {
|
|
WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
|
|
bOpenDb = TRUE;
|
|
WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE,
|
|
IID_IFsaRecoveryRec, (void**) &pRecRec));
|
|
WsbAffirmHr(pRecRec->SetPath(path));
|
|
if (S_OK == pRecRec->FindEQ()) {
|
|
WsbAffirmHr(pRecRec->Remove());
|
|
}
|
|
} WsbCatch(hr);
|
|
if (bOpenDb) {
|
|
WsbAffirmHr(m_pPremigrated->Close(pDbSession));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_PEEK:
|
|
case FSA_RESULT_ACTION_REPARSE:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Peek/Reparse\n"));
|
|
hr = E_NOTIMPL;
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_TRUNCATE:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Truncate\n"));
|
|
WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
|
|
placeholder.isTruncated = FALSE;
|
|
placeholder.migrationTime = currentTime;
|
|
hr = pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn);
|
|
if (SUCCEEDED(hr) && (FSA_E_REPARSE_NOT_WRITTEN_FILE_CHANGED != hr)) {
|
|
WsbAffirmHr(pScanItem->Truncate(offset, size));
|
|
}
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_REWRITEPLACEHOLDER:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Rewrite Placeholder\n"));
|
|
WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
|
|
WsbAffirmHr(pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn));
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_RECALLEDDATA:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Recalled\n"));
|
|
WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
|
|
placeholder.isTruncated = FALSE;
|
|
placeholder.recallTime = currentTime;
|
|
placeholder.recallCount++;
|
|
WsbAffirmHr(pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn));
|
|
WsbAffirmHr(RemoveTruncated(pScanItem, offset, size));
|
|
WsbAffirmHr(AddPremigrated(pScanItem, offset, size, FALSE, afterPhUsn));
|
|
|
|
// Remove the recovery record if we created one
|
|
if (m_isDbInitialized) {
|
|
BOOL bOpenDb = FALSE;
|
|
CComPtr<IWsbDbSession> pDbSession;
|
|
CComPtr<IFsaRecoveryRec> pRecRec;
|
|
|
|
try {
|
|
WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
|
|
bOpenDb = TRUE;
|
|
WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE,
|
|
IID_IFsaRecoveryRec, (void**) &pRecRec));
|
|
WsbAffirmHr(pRecRec->SetPath(path));
|
|
if (S_OK == pRecRec->FindEQ()) {
|
|
WsbAffirmHr(pRecRec->Remove());
|
|
}
|
|
} WsbCatch(hr);
|
|
if (bOpenDb) {
|
|
WsbAffirmHr(m_pPremigrated->Close(pDbSession));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_NORECALL:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Open without recall\n"));
|
|
// Tell the filter that the recall attempt finished.
|
|
WsbAffirmHr(pResult->GetResult(&resultHr));
|
|
WsbAffirmHr(pResult->GetFilterRecall(&pRecall));
|
|
WsbAssert(pRecall != 0, E_POINTER);
|
|
hr = pRecall->HasCompleted(resultHr);
|
|
completionSent = TRUE;
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_VALIDATE_BAD:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Validate Bad\n"));
|
|
WsbAffirmHr(pResult->GetResult(&resultHr));
|
|
WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
|
|
if (S_OK == pScanItem->IsPremigrated(offset, size)) {
|
|
WsbLogEvent(FSA_MESSAGE_VALIDATE_UNMANAGED_FILE_ENGINE, 0, NULL, WsbAbbreviatePath(path, 120), (OLECHAR *)m_path, WsbHrAsString(resultHr), WsbQuickString(WsbHrAsString(resultHr)), NULL);
|
|
WsbAffirmHr(pScanItem->DeletePlaceholder(offset, size));
|
|
} else if (S_OK == pScanItem->IsTruncated(offset, size)) {
|
|
//
|
|
// We no longer delete bad placeholders here - let the diagnostic tool clean them up
|
|
// The message that is logged here has been changed to indicate that the file did not validate
|
|
// and will not be recallable until the problem is fixed.
|
|
//WsbAffirmHr(pScanItem->Delete());
|
|
WsbLogEvent(FSA_MESSAGE_VALIDATE_DELETED_FILE_ENGINE, 0, NULL, WsbAbbreviatePath(path, 120), (OLECHAR *) m_path, WsbHrAsString(resultHr), WsbQuickString(WsbHrAsString(resultHr)), NULL);
|
|
}
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_VALIDATE_OK:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Validate OK\n"));
|
|
if (m_isDoingValidate) {
|
|
WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
|
|
if (S_OK == pScanItem->IsPremigrated(offset, size)) {
|
|
WsbAffirmHr(AddPremigrated(pScanItem, offset, size, FALSE, usn));
|
|
} else if (S_OK == pScanItem->IsTruncated(offset, size)) {
|
|
WsbAffirmHr(AddTruncated(pScanItem, offset, size));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_VALIDATE_FOR_TRUNCATE_BAD:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Validate for truncate Bad\n"));
|
|
//
|
|
// The file did not validate - make it back into a real file
|
|
//
|
|
WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
|
|
if (S_OK == pScanItem->IsPremigrated(offset, size)) {
|
|
WsbAffirmHr(pScanItem->DeletePlaceholder(offset, size));
|
|
}
|
|
break;
|
|
|
|
case FSA_RESULT_ACTION_VALIDATE_FOR_TRUNCATE_OK:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Validate for truncate OK\n"));
|
|
//
|
|
// The file validated - go ahead and truncate it (if it has not changed)
|
|
//
|
|
WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
|
|
WsbAffirmHr(pScanItem->TruncateValidated(offset, size));
|
|
break;
|
|
|
|
default:
|
|
WsbAssert(FALSE, E_FAIL);
|
|
break;
|
|
}
|
|
|
|
} WsbCatchAndDo(hr,
|
|
if (completionSent == FALSE) {
|
|
switch(resultAction) {
|
|
//
|
|
//If it was a demand recall we must make all effort to let them know it failed
|
|
//
|
|
case FSA_RESULT_ACTION_OPEN:
|
|
case FSA_RESULT_ACTION_NORECALL:
|
|
WsbTrace(OLESTR("CFsaResource::ProcessResult - Open (No longer placeholder)\n"));
|
|
// Tell the filter that the recall attempt finished.
|
|
pRecall = 0; // Just in case we already had the interfae we deref it here.
|
|
hr = pResult->GetFilterRecall(&pRecall);
|
|
if (hr == S_OK) {
|
|
hr = pRecall->HasCompleted(E_FAIL);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::ProcessResult"), OLESTR("hr = %ls"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::ReadIdentifier(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CWsbStringPtr tmpString;
|
|
HANDLE aHandle;
|
|
ULONG size;
|
|
UCHAR bytes[sizeof(m_id)];
|
|
PUCHAR bytePtr;
|
|
UCHAR buffer[sizeof(FILE_FS_VOLUME_INFORMATION)+MAX_PATH];
|
|
PFILE_FS_VOLUME_INFORMATION volInfo;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
IO_STATUS_BLOCK ioStatus;
|
|
WCHAR * wString = NULL;
|
|
|
|
try {
|
|
|
|
//
|
|
// The identifier is composed of:
|
|
//
|
|
// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
|
// 0 0 0 0 <---------Volume Creation Time--------> <Volume Serial Number>
|
|
// We need to open a handle to the volume
|
|
//
|
|
tmpString = m_path;
|
|
WsbAffirmHr(tmpString.Prepend("\\\\?\\"));
|
|
|
|
tmpString.CopyTo(&wString);
|
|
//
|
|
// Remove trailing backslash in the path
|
|
//
|
|
wString[wcslen(wString)-1] = L'\0';
|
|
|
|
WsbAffirmHandle(aHandle = CreateFile(wString,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
0,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0));
|
|
WsbFree(wString);
|
|
wString = NULL;
|
|
|
|
try {
|
|
|
|
volInfo = (PFILE_FS_VOLUME_INFORMATION) buffer;
|
|
bytePtr = bytes;
|
|
|
|
status = NtQueryVolumeInformationFile(
|
|
aHandle,
|
|
&ioStatus,
|
|
buffer,
|
|
sizeof(buffer),
|
|
FileFsVolumeInformation);
|
|
|
|
WsbAffirmNtStatus(status);
|
|
//
|
|
// Volume serial number forms the lower 4 bytes of the GUID
|
|
//
|
|
WsbAffirmHr(WsbConvertToBytes(bytePtr, volInfo->VolumeSerialNumber, &size));
|
|
WsbAffirm(size == sizeof(volInfo->VolumeSerialNumber), E_FAIL);
|
|
//
|
|
// Volume creation time forms the next 8 bytes
|
|
//
|
|
bytePtr += size;
|
|
WsbAffirmHr(WsbConvertToBytes(bytePtr, volInfo->VolumeCreationTime.QuadPart, &size));
|
|
WsbAffirm(size == sizeof(volInfo->VolumeCreationTime.QuadPart), E_FAIL);
|
|
//
|
|
// Next 4 bytes: 0's are good as any
|
|
//
|
|
bytePtr += size;
|
|
WsbAffirmHr(WsbConvertToBytes(bytePtr, (ULONG) 0, &size));
|
|
WsbAffirm(size == sizeof(ULONG), E_FAIL);
|
|
|
|
WsbAffirmHr(WsbConvertFromBytes(bytes, &m_id, &size));
|
|
WsbAffirm(size == sizeof(m_id), E_FAIL);
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbAffirmStatus(CloseHandle(aHandle));
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::Recall(
|
|
IN IFsaScanItem* pScanItem,
|
|
IN LONGLONG offset,
|
|
IN LONGLONG size,
|
|
IN BOOL deletePlaceholder
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::Recall().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrFind;
|
|
CComPtr<IFsaPostIt> pWorkItem;
|
|
LONGLONG fileId;
|
|
CComPtr<IHsmFsaTskMgr> pEngine;
|
|
CComPtr<IHsmSession> pSession;
|
|
CComPtr<IWsbDbSession> pDbSession;
|
|
CComPtr<IFsaRecoveryRec> pRecRec;
|
|
CWsbStringPtr tmpString;
|
|
FSA_PLACEHOLDER placeholder;
|
|
LONGLONG fileVersionId;
|
|
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::Recall"), OLESTR(""));
|
|
try {
|
|
|
|
// Make sure the Scan Item interface is OK
|
|
WsbAssert(pScanItem != 0, E_FAIL);
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
|
|
|
|
// Get the data from the scan item.
|
|
WsbAffirmHr(pScanItem->GetSession((IHsmSession**) &(pSession)));
|
|
WsbAffirmHr(pWorkItem->SetSession(pSession));
|
|
|
|
WsbAffirmHr(pScanItem->GetPathAndName(0, &tmpString, 0));
|
|
WsbAffirmHr(pWorkItem->SetPath(tmpString));
|
|
|
|
WsbAffirmHr(pWorkItem->SetRequestOffset(offset));
|
|
WsbAffirmHr(pWorkItem->SetRequestSize(size));
|
|
|
|
WsbAffirmHr(pScanItem->GetPlaceholder(offset, size, &placeholder));
|
|
WsbAffirmHr(pWorkItem->SetPlaceholder(&placeholder));
|
|
|
|
WsbAffirmHr(pScanItem->GetVersionId(&fileVersionId));
|
|
WsbAffirmHr(pWorkItem->SetFileVersionId(fileVersionId));
|
|
|
|
|
|
// Fill in the rest of the work
|
|
WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_RECALL));
|
|
if (deletePlaceholder) {
|
|
WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_DELETEPLACEHOLDER));
|
|
} else {
|
|
WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_RECALLEDDATA));
|
|
}
|
|
|
|
// Send the request to the task manager. If the file was archived by someone other
|
|
// than the managing HSM, then that HSM will need to be looked up.
|
|
if ( GUID_NULL != m_managingHsm &&
|
|
memcmp(&m_managingHsm, &(placeholder.hsmId), sizeof(GUID)) == 0) {
|
|
WsbAffirmHr(GetHsmEngine(&pEngine));
|
|
} else {
|
|
CComPtr<IHsmServer> pHsmServer;
|
|
|
|
WsbAssertHr(HsmConnectFromId(HSMCONN_TYPE_HSM, placeholder.hsmId, IID_IHsmServer, (void**) &pHsmServer));
|
|
WsbAffirmHr(pHsmServer->GetHsmFsaTskMgr(&pEngine));
|
|
}
|
|
|
|
WsbAffirmHr(pScanItem->GetFileId(&fileId));
|
|
|
|
if (m_isDbInitialized) {
|
|
// Save a recovery record in case anything goes wrong
|
|
WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
|
|
WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE, IID_IFsaRecoveryRec, (void**) &pRecRec));
|
|
WsbAffirmHr(pRecRec->SetPath(tmpString));
|
|
|
|
// If the record already exists rewrite it, otherwise create a new record.
|
|
hrFind = pRecRec->FindEQ();
|
|
if (WSB_E_NOTFOUND == hrFind) {
|
|
WsbAffirmHr(pRecRec->MarkAsNew());
|
|
} else if (FAILED(hrFind)) {
|
|
WsbThrow(hrFind);
|
|
}
|
|
|
|
WsbAffirmHr(pRecRec->SetFileId(fileId));
|
|
WsbAffirmHr(pRecRec->SetOffsetSize(offset, size));
|
|
WsbAffirmHr(pRecRec->SetStatus(FSA_RECOVERY_FLAG_RECALLING));
|
|
WsbAffirmHr(pRecRec->Write());
|
|
}
|
|
|
|
try {
|
|
WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
|
|
} WsbCatchAndDo(hr,
|
|
// This FindEQ seems unnecessary, but we can't assume the
|
|
// the Remove will work
|
|
if (pRecRec) {
|
|
if (SUCCEEDED(pRecRec->FindEQ())) {
|
|
hr = pRecRec->Remove();
|
|
}
|
|
}
|
|
);
|
|
|
|
} WsbCatch(hr);
|
|
|
|
if (pDbSession != 0) {
|
|
m_pPremigrated->Close(pDbSession);
|
|
}
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::Recall"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::RemovePremigrated(
|
|
IN IFsaScanItem* pScanItem,
|
|
IN LONGLONG offset,
|
|
IN LONGLONG size
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::RemovePremigrated().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CWsbStringPtr path;
|
|
CComPtr<IWsbDbSession> pDbSession;
|
|
CComPtr<IFsaPremigratedRec> pRec;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::RemovePremigrated"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pScanItem, E_POINTER);
|
|
WsbAffirm(m_pPremigrated != NULL, E_UNEXPECTED);
|
|
|
|
// Open the database.
|
|
WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
|
|
|
|
// Protect the removal with Jet transaction since the auto-truncator thread
|
|
// may try to remove the same record at the same time
|
|
WsbAffirmHr(pDbSession->TransactionBegin());
|
|
|
|
try {
|
|
LONGLONG itemSize;
|
|
HRESULT hrTemp;
|
|
|
|
// Find the record using the bag/offsets key.
|
|
WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, PREMIGRATED_REC_TYPE, IID_IFsaPremigratedRec, (void**) &pRec));
|
|
WsbAffirmHr(pRec->UseKey(PREMIGRATED_BAGID_OFFSETS_KEY_TYPE));
|
|
WsbAffirmHr(pRec->SetFromScanItem(pScanItem, offset, size, FALSE));
|
|
|
|
// The record may already been deleted by the auto-truncator
|
|
hrTemp = pRec->FindEQ();
|
|
if (hrTemp == WSB_E_NOTFOUND) {
|
|
hr = S_OK;
|
|
WsbThrow(hr);
|
|
}
|
|
WsbAffirmHr(hrTemp);
|
|
|
|
WsbAffirmHr(pRec->GetSize(&itemSize));
|
|
|
|
// the record may be involved with another transaction with delete pending
|
|
hrTemp = pRec->Remove();
|
|
if (hrTemp == WSB_E_IDB_UPDATE_CONFLICT) {
|
|
hr = S_OK;
|
|
WsbThrow(hr);
|
|
}
|
|
WsbAffirmHr(hrTemp);
|
|
|
|
// Remove the size of the section from the amount of premigrated data.
|
|
RemovePremigratedSize(itemSize);
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbAffirmHr(pDbSession->TransactionEnd());
|
|
|
|
WsbAffirmHr(m_pPremigrated->Close(pDbSession));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::RemovePremigrated"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::RemoveTruncated(
|
|
IN IFsaScanItem* /*pScanItem*/,
|
|
IN LONGLONG /*offset*/,
|
|
IN LONGLONG size
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::RemoveTruncated().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::RemoveTruncated"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
WsbAffirmHr(RemoveTruncatedSize(size));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::RemoveTruncated"),
|
|
OLESTR("hr = <%ls>, m_truncatedSize = %I64d"), WsbHrAsString(hr),
|
|
m_truncatedSize);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::RemoveTruncatedSize(
|
|
IN LONGLONG size
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::RemoveTruncatedSize().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::RemoveTruncatedSize"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
m_truncatedSize = max(0, m_truncatedSize - size);
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::RemoveTruncatedSize"),
|
|
OLESTR("hr = <%ls>, m_truncatedSize = %I64d"), WsbHrAsString(hr),
|
|
m_truncatedSize);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::RemovePremigratedSize(
|
|
IN LONGLONG size
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::RemovePremigratedSize().
|
|
|
|
--*/
|
|
{
|
|
WsbTraceIn(OLESTR("CFsaResource::RemovePremigratedSize"),
|
|
OLESTR("m_premigratedSize = %I64d"), m_premigratedSize);
|
|
|
|
m_isDirty = TRUE;
|
|
if (size > m_premigratedSize) {
|
|
m_premigratedSize = 0;
|
|
} else {
|
|
m_premigratedSize -= size;
|
|
}
|
|
WsbTraceOut(OLESTR("CFsaResource::RemovePremigratedSize"),
|
|
OLESTR("m_premigratedSize = %I64d"), m_premigratedSize);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::Save(
|
|
IN IStream* pStream,
|
|
IN BOOL clearDirty
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IPersistStream::Save().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IPersistStream> pPersistStream;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::Save"), OLESTR("clearDirty = <%ls>"),
|
|
WsbBoolAsString(clearDirty));
|
|
|
|
try {
|
|
WsbAssert(0 != pStream, E_POINTER);
|
|
|
|
// Do the easy stuff, but make sure that this order matches the order
|
|
// in the Load() method.
|
|
|
|
// Save the path by which this resource is/was last known. Note the
|
|
// Load() method reads it back into the resource's 'm_oldPath' field.
|
|
if ( m_path == NULL ) {
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_oldPath));
|
|
}
|
|
else {
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_path));
|
|
}
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_alternatePath));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_name));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_stickyName));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_fsName));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_maxComponentLength));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_fsFlags));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_id));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_isActive));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, (ULONG) m_compareBy));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_managingHsm));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_hsmLevel));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_premigratedSize));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_truncatedSize));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_manageableItemLogicalSize));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_manageableItemAccessTimeIsRelative));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_manageableItemAccessTime));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_usnJournalId));
|
|
WsbAffirmHr(WsbSaveToStream(pStream, m_lastUsnId));
|
|
|
|
// Save off the default rules.
|
|
WsbAffirmHr(m_pDefaultRules->QueryInterface(IID_IPersistStream,
|
|
(void**) &pPersistStream));
|
|
WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
|
|
pPersistStream = 0;
|
|
|
|
// Save off the premigration list.
|
|
WsbAffirmHr(((IWsbDb*)m_pPremigrated)->QueryInterface(IID_IPersistStream,
|
|
(void**) &pPersistStream));
|
|
WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
|
|
pPersistStream = 0;
|
|
|
|
// Save off the truncator.
|
|
WsbAffirmHr(m_pTruncator->QueryInterface(IID_IPersistStream,
|
|
(void**) &pPersistStream));
|
|
WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
|
|
pPersistStream = 0;
|
|
|
|
// If we got it saved and we were asked to clear the dirty bit, then
|
|
// do so now.
|
|
if (clearDirty) {
|
|
m_isDirty = FALSE;
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetAlternatePath(
|
|
IN OLECHAR* path
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::SetAlternatePath().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != path, E_POINTER);
|
|
m_alternatePath = path;
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetHsmLevel(
|
|
IN ULONG level
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::SetHsmLevel().
|
|
|
|
--*/
|
|
{
|
|
BOOL DoKick = FALSE;
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::SetHsmLevel"),
|
|
OLESTR("current level = %lx, new level = %lx"), m_hsmLevel, level);
|
|
|
|
if (m_hsmLevel < level) {
|
|
DoKick = TRUE;
|
|
}
|
|
m_hsmLevel = level;
|
|
|
|
// Wake up the AutoTruncator if the new level is higher
|
|
if (DoKick) {
|
|
WsbAffirmHr(m_pTruncator->KickStart());
|
|
}
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::SetHsmLevel"), OLESTR("hr = <%ls>"),
|
|
WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetIdentifier(
|
|
IN GUID id
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::SetIdentifier().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
m_id = id;
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetIsActive(
|
|
BOOL isActive
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::SetIsActive().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IHsmSession> pSession;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::SetIsActive"), OLESTR(""));
|
|
// If the flag is changing values, then we may need to do something to the truncator.
|
|
try {
|
|
if (m_isActive != isActive) {
|
|
|
|
// Change the flag.
|
|
m_isActive = isActive;
|
|
|
|
// If we are becoming active, then we need to start the truncator. Otherwise we need to stop it.
|
|
if (m_isActive) {
|
|
|
|
// If we are managed & done with recovery, then the truncator should be running.
|
|
if (IsManaged() == S_OK && m_isRecovered) {
|
|
|
|
// Try to start the truncator
|
|
WsbAffirmHr(InitializePremigrationList(TRUE));
|
|
}
|
|
} else {
|
|
|
|
// If the truncator is running, then ask it to stop.
|
|
WsbAffirmHr(m_pTruncator->GetSession(&pSession));
|
|
if (pSession != 0) {
|
|
WsbAffirmHr(pSession->ProcessEvent(HSM_JOB_PHASE_ALL, HSM_JOB_EVENT_CANCEL));
|
|
}
|
|
}
|
|
|
|
} else {
|
|
m_isActive = isActive;
|
|
}
|
|
|
|
m_isDirty = TRUE;
|
|
} WsbCatch( hr );
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::SetIsActive"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetIsAvailable(
|
|
BOOL isAvailable
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::SetIsAvailable().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::SetIsAvailable"), OLESTR(""));
|
|
|
|
// Change the flag.
|
|
m_isAvailable = isAvailable;
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::SetIsAvailable"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetIsDeletePending(
|
|
BOOL isDeletePending
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::SetIsDeletePending().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HANDLE threadHandle;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::SetIsDeletePending"), OLESTR(""));
|
|
|
|
// Change the flag.
|
|
m_isDeletePending = isDeletePending;
|
|
|
|
threadHandle = CreateThread(0, 0, FsaStartOnStateChange, (void*) this, 0, &g_ThreadId);
|
|
if (threadHandle != NULL) {
|
|
CloseHandle(threadHandle);
|
|
}
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::SetIsDeletePending"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetManageableItemLogicalSize(
|
|
IN LONGLONG size
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::SetManageableItemLogicalSize().
|
|
|
|
--*/
|
|
{
|
|
m_manageableItemLogicalSize = size;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetManageableItemAccessTime(
|
|
IN BOOL isRelative,
|
|
IN FILETIME time
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::SetManageableItemAccessTime().
|
|
|
|
--*/
|
|
{
|
|
m_manageableItemAccessTimeIsRelative = isRelative;
|
|
m_manageableItemAccessTime = time;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetName(
|
|
IN OLECHAR* name
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::SetName().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != name, E_POINTER);
|
|
m_name = name;
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetOldPath(
|
|
IN OLECHAR* oldPath
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::SetOldPath().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != oldPath, E_POINTER);
|
|
m_oldPath = oldPath;
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetPath(
|
|
IN OLECHAR* path
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::SetPath().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != path, E_POINTER);
|
|
m_path = path;
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetSerial(
|
|
IN ULONG serial
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::SetSerial().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
m_serial = serial;
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetStickyName(
|
|
IN OLECHAR* name
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::SetStickyName().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != name, E_POINTER);
|
|
m_stickyName = name;
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetUserFriendlyName(
|
|
IN OLECHAR* name
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::SetUserFriendlyName().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != name, E_POINTER);
|
|
m_userName = name;
|
|
|
|
m_isDirty = TRUE;
|
|
|
|
} WsbCatch(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::ChangeSysState(
|
|
IN OUT HSM_SYSTEM_STATE* pSysState
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IHsmSystemState::ChangeSysState().
|
|
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::ChangeSysState"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
//
|
|
// Make sure the truncater is stopped so it won't
|
|
// try to use the database
|
|
//
|
|
if (m_pTruncator) {
|
|
CComPtr<IHsmSession> pSession;
|
|
|
|
WsbAffirmHr(m_pTruncator->GetSession(&pSession));
|
|
if (pSession != 0) {
|
|
if (pSysState->State & HSM_STATE_SHUTDOWN) {
|
|
WsbAffirmHr(pSession->ProcessEvent(HSM_JOB_PHASE_ALL, HSM_JOB_EVENT_CANCEL));
|
|
}
|
|
}
|
|
m_pTruncator->ChangeSysState(pSysState);
|
|
}
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::ChangeSysState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::StartJob(
|
|
IN OLECHAR* startingPath,
|
|
IN IHsmSession* pSession
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::StartJob().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IHsmScanner> pScanner;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::StartJob"), OLESTR("starting path = %ls"), startingPath);
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pSession, E_POINTER);
|
|
|
|
// Create an initialize the scanner.
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CHsmScanner, 0, CLSCTX_SERVER, IID_IHsmScanner, (void**) &pScanner));
|
|
WsbAffirmHr(pScanner->Start(pSession, startingPath));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::StartJob"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT
|
|
CFsaResource::StartJobSession(
|
|
IN IHsmJob* pJob,
|
|
IN ULONG subRunId,
|
|
OUT IHsmSession** ppSession
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::StartJobSession().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IHsmSession> pSession;
|
|
GUID hsmId;
|
|
ULONG runId;
|
|
CWsbStringPtr name;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::StartJobSession"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
WsbAssert(0 != pJob, E_POINTER);
|
|
WsbAssert(0 != ppSession, E_POINTER);
|
|
*ppSession = 0;
|
|
|
|
// Create and Initialize a session object.
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CHsmSession, 0, CLSCTX_SERVER, IID_IHsmSession, (void**) &pSession));
|
|
|
|
WsbAffirmHr(pJob->GetHsmId(&hsmId));
|
|
WsbAffirmHr(pJob->GetRunId(&runId));
|
|
WsbAffirmHr(pJob->GetName(&name, 0));
|
|
WsbAffirmHr(pSession->Start(name, HSM_JOB_LOG_NORMAL, hsmId, pJob, (IFsaResource*) this, runId, subRunId));
|
|
|
|
// Return the session to the caller.
|
|
*ppSession = pSession;
|
|
pSession->AddRef();
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::StartJobSession"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::SetupValidateJob(SYSTEMTIME runTime)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IWsbCreateLocalObject> pLocalObject;
|
|
CComPtr <IWsbIndexedCollection> pJobs;
|
|
CComPtr<IHsmJob> pExistJob;
|
|
CComPtr<IHsmJob> pNewJob;
|
|
CComPtr<IHsmServer> pHsmServer;
|
|
CWsbStringPtr pszExistJobName;
|
|
CWsbStringPtr szJobName;
|
|
CWsbStringPtr parameters;
|
|
CWsbStringPtr commentString;
|
|
CWsbStringPtr tmpString;
|
|
CWsbStringPtr formatString;
|
|
TASK_TRIGGER_TYPE jobTriggerType;
|
|
BOOL scheduledJob;
|
|
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::SetupValidateJob"), OLESTR(""));
|
|
|
|
try {
|
|
|
|
// Get the volume name
|
|
CWsbStringPtr szWsbVolumeName;
|
|
WsbAffirmHr (GetLogicalName ( &szWsbVolumeName, 0));
|
|
|
|
// Create a job name
|
|
CWsbStringPtr volumeString;
|
|
WsbAffirmHr( volumeString.Alloc( 128 ) );
|
|
|
|
// For now, ignore the user name if it's not a drive letter
|
|
CWsbStringPtr userName = m_userName;
|
|
size_t userLen = 0;
|
|
if ((WCHAR *)userName) {
|
|
userLen = wcslen(userName);
|
|
}
|
|
if ((userLen != 3) || (userName[1] != L':')) {
|
|
userName = L"";
|
|
}
|
|
|
|
if( ! userName || userName.IsEqual ( L"" ) ) {
|
|
|
|
//
|
|
// No drive letter - use the volume name and serial number instead
|
|
//
|
|
if( ! m_name || m_name.IsEqual( L"" ) ) {
|
|
|
|
//
|
|
// No name, no drive letter - just have serial number
|
|
//
|
|
swprintf( volumeString, L"%8.8lx", m_serial );
|
|
|
|
} else {
|
|
|
|
swprintf( volumeString, L"%ls-%8.8lx", (OLECHAR*)m_name, m_serial );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Just want the drive letter (first character)
|
|
//
|
|
volumeString = userName;
|
|
volumeString[1] = L'\0';
|
|
|
|
}
|
|
|
|
WsbAffirmHr(formatString.LoadFromRsc(_Module.m_hInst, IDS_JOB_NAME_PREFIX));
|
|
WsbAffirmHr(szJobName.Alloc(512));
|
|
swprintf((OLECHAR *) szJobName, formatString, (OLECHAR*)volumeString);
|
|
|
|
// Get a pointer to the HSM server
|
|
WsbAffirm(IsManaged() == S_OK, E_FAIL);
|
|
WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, m_managingHsm, IID_IHsmServer,
|
|
(void**) &pHsmServer));
|
|
|
|
// Get a CreateLocalObject interface with which to create the job
|
|
WsbAffirmHr (pHsmServer->QueryInterface( IID_IWsbCreateLocalObject,
|
|
(void **) &pLocalObject));
|
|
|
|
// Create the new job in the engine
|
|
WsbAffirmHr (pLocalObject->CreateInstance( CLSID_CHsmJob, IID_IHsmJob,
|
|
(void**) &pNewJob));
|
|
WsbAffirmHr (pNewJob->InitAs(
|
|
szJobName, NULL, HSM_JOB_DEF_TYPE_VALIDATE, GUID_NULL,
|
|
pHsmServer, TRUE, this));
|
|
|
|
// Get the jobs collection from the engine
|
|
WsbAffirmHr (pHsmServer->GetJobs (&pJobs));
|
|
|
|
// If any jobs exist with this name, delete them
|
|
ULONG cCount;
|
|
WsbAffirmHr (pJobs->GetEntries (&cCount));
|
|
for (UINT i = 0; i < cCount; i++) {
|
|
WsbAffirmHr (pJobs->At (i, IID_IHsmJob, (void **) &pExistJob));
|
|
WsbAffirmHr (pExistJob->GetName (&pszExistJobName, 0));
|
|
if (pszExistJobName.Compare (szJobName) == 0) {
|
|
WsbAffirmHr (pJobs->RemoveAndRelease(pExistJob));
|
|
i--; cCount--;
|
|
}
|
|
pExistJob = 0; // make sure we release this interface.
|
|
}
|
|
|
|
// Add the new job to the engine collection
|
|
WsbAffirmHr (pJobs->Add(pNewJob));
|
|
|
|
// Set up to call the Engine to create an entry in the NT Task Scheduler
|
|
|
|
// Create the parameter string for the program NT Scheduler
|
|
// will run (for Sakkara this is RsLaunch) by putting the
|
|
// job name in as the parameter. This is how RsLaunch knows
|
|
// which job in the Engine to run.
|
|
WsbAffirmHr(parameters.Alloc(256));
|
|
swprintf((OLECHAR *)parameters, L"run \"%ls\"", (OLECHAR *) szJobName);
|
|
|
|
// Create the comment string for the NT Scheduler entry
|
|
WsbAffirmHr(formatString.LoadFromRsc(_Module.m_hInst, IDS_JOB_AUTOVALIDATE_COMMENT));
|
|
WsbAffirmHr(commentString.Alloc(512));
|
|
swprintf((OLECHAR *) commentString, formatString, (OLECHAR *) szWsbVolumeName);
|
|
|
|
// Declare and initialize the schedule components passed to
|
|
// the Engine.
|
|
jobTriggerType = TASK_TIME_TRIGGER_ONCE;
|
|
|
|
// Indicate this is a scheduled job
|
|
scheduledJob = TRUE;
|
|
|
|
// Create the task
|
|
WsbAffirmHr( pHsmServer->CreateTaskEx( szJobName, parameters,
|
|
commentString, jobTriggerType,
|
|
runTime, 0,
|
|
scheduledJob ) );
|
|
//
|
|
// Remove the registry value if it is there.
|
|
//
|
|
WsbAffirmHr(tmpString.Alloc(32));
|
|
swprintf((OLECHAR *) tmpString, L"%x", m_serial);
|
|
(void) WsbRemoveRegistryValue(NULL, FSA_VALIDATE_LOG_KEY_NAME, tmpString);
|
|
|
|
} WsbCatch( hr );
|
|
|
|
WsbTraceOut( L"CFsaResource::SetupValidateJob", L"hr = <%ls>", WsbHrAsString( hr ) );
|
|
return( hr );
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::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);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::UpdateFrom(
|
|
IN IFsaServer* pServer,
|
|
IN IFsaResource* pResource
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResourcePriv::UpdateFrom().
|
|
|
|
Routine Description:
|
|
|
|
This routine implements the COM method for updating a resource object from another.
|
|
It is generally used to update a resource contained in the manageable resources
|
|
collection from a 'working' resource which was just created during a scan for
|
|
resources. Note that both source and target resource objects must represent the
|
|
same physical resource.
|
|
|
|
To capture the latest information about the resource, only the owning FSA and path
|
|
info is updated from the source resource object. All other resource info is
|
|
updated via a direct query contained within this method. This technique allows
|
|
for capturing any updates made by the user since the scan was run.
|
|
|
|
Arguments:
|
|
|
|
pServer - Interface pointer to the FSA service that is updating this resource.
|
|
|
|
pResource - Interface pointer to the resource used as the source during the update.
|
|
|
|
Return Value:
|
|
|
|
S_OK - The call succeeded (the resource being tested was found to be manageable,
|
|
and the resource object was initialized).
|
|
|
|
E_UNEXPECTED - Thrown if the id's (Guids) for the resource to updated and the
|
|
source resource do not match.
|
|
|
|
Any other value - The call failed because one of the Remote Storage or Win32 API
|
|
calls contained internally in this method failed. The error value returned
|
|
is specific to the API call which failed.
|
|
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr = S_OK;
|
|
GUID id;
|
|
CWsbStringPtr tmpString;
|
|
CWsbStringPtr volPath;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::UpdateFrom"), OLESTR(""));
|
|
try {
|
|
|
|
// The identifiers must be the same! (Meaning both resource objects must
|
|
// represent the same physical resource.)
|
|
WsbAffirmHr(pResource->GetIdentifier(&id));
|
|
WsbAssert(m_id == id, E_UNEXPECTED);
|
|
|
|
// Update (store) the owning FSA interface. However, since this is a weak
|
|
// reference, do not AddRef() it.
|
|
m_pFsaServer = pServer;
|
|
|
|
// Update the path specific information, preserving the last known path (if any).
|
|
// If the 'path' of this resource is null, set it to the 'path' of the resource
|
|
// we are updating from. Else, compare the 2 'path' fields. If different, copy
|
|
// this resource's path to 'old path', then update 'path' from the resource we are
|
|
// updating from. If the 2 resources' paths are not null and the same, do nothing.
|
|
//
|
|
WsbAffirmHr(pResource->GetPath(&tmpString, 0));
|
|
if (m_path == 0) {
|
|
WsbAffirmHr(SetPath(tmpString));
|
|
}
|
|
else if (wcscmp(tmpString, m_path) != 0) {
|
|
// copy path to 'old path' field, then update 'path' field.
|
|
WsbAffirmHr(m_path.CopyTo(&m_oldPath, 0));
|
|
WsbAffirmHr(SetPath(tmpString));
|
|
}
|
|
|
|
// Update 'user friendly' name of this resource from the resource we are updating
|
|
// from.
|
|
WsbAffirmHr(pResource->GetUserFriendlyName(&tmpString, 0));
|
|
WsbTrace(OLESTR("CFsaResource::UpdateFrom - setting user friendly name to %ws\n"),
|
|
(WCHAR *) tmpString);
|
|
WsbAffirmHr(SetUserFriendlyName(tmpString));
|
|
|
|
// Update 'sticky' (long, ugly PNP) name of this resource from the resource we are
|
|
// updating from.
|
|
WsbAffirmHr(pResource->GetStickyName(&tmpString, 0));
|
|
WsbAffirmHr(SetStickyName(tmpString));
|
|
|
|
// Since the other data that we would like to refresh is not exposed by an interface,
|
|
// we will query for it again.
|
|
//
|
|
// NOTE: fsFlags and maxComponentLength are the real issues, since name and fsName
|
|
// are done via exposed interfaces.
|
|
//
|
|
// NOTE: To keep every update from making the item seem dirty, we may want to
|
|
// compare all the fields first. (Idea for later enhancement)
|
|
m_name.Realloc(128); // volume name
|
|
m_fsName.Realloc(128); // volume file system type (e.g., FAT, NTFS)
|
|
HRESULT hrAvailable;
|
|
WsbAffirmHr( hrAvailable = pResource->IsAvailable( ) );
|
|
m_isAvailable = S_OK == hrAvailable ? TRUE : FALSE;
|
|
|
|
// Reformat resource's path for 'GetVolumeInfo' call below.
|
|
volPath = m_path;
|
|
WsbAffirmHr(volPath.Prepend("\\\\?\\"));
|
|
|
|
WsbAffirm(GetVolumeInformation(volPath, m_name, 128, &m_serial,
|
|
&m_maxComponentLength, &m_fsFlags, m_fsName, 128), E_FAIL);
|
|
|
|
// Now that everything is updated, initialize the
|
|
// premigration list if necessary
|
|
WsbAffirmHr(InitializePremigrationList(TRUE));
|
|
|
|
m_isDirty = TRUE;
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::UpdateFrom"), OLESTR("hr = <%ls>"),
|
|
WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::Validate(
|
|
IN IFsaScanItem* pScanItem,
|
|
IN LONGLONG offset,
|
|
IN LONGLONG size,
|
|
IN LONGLONG usn
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::Validate().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaPostIt> pWorkItem;
|
|
CComPtr<IHsmFsaTskMgr> pEngine;
|
|
CWsbStringPtr tmpString;
|
|
CComPtr<IHsmSession> pSession;
|
|
FSA_PLACEHOLDER placeholder;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::Validate"), OLESTR("offset = %I64d, size = %I64d, usn = <%I64d>"),
|
|
offset, size, usn);
|
|
try {
|
|
|
|
// Make sure the Scan Item interface is OK
|
|
WsbAssert(pScanItem != 0, E_POINTER);
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
|
|
|
|
// Get the data from the scan item.
|
|
WsbAffirmHr(pScanItem->GetSession(&pSession));
|
|
WsbAffirmHr(pWorkItem->SetSession(pSession));
|
|
|
|
WsbAffirmHr(pScanItem->GetPathAndName(0, &tmpString, 0));
|
|
WsbAffirmHr(pWorkItem->SetPath(tmpString));
|
|
|
|
WsbAffirmHr(pWorkItem->SetRequestOffset(offset));
|
|
WsbAffirmHr(pWorkItem->SetRequestSize(size));
|
|
|
|
WsbAffirmHr(pScanItem->GetPlaceholder(offset, size, &(placeholder)));
|
|
WsbAffirmHr(pWorkItem->SetPlaceholder(&placeholder));
|
|
|
|
// Fill in the rest of the work
|
|
WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_VALIDATE));
|
|
WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_NONE));
|
|
|
|
// Fill in the USN
|
|
WsbAffirmHr(pWorkItem->SetUSN(usn));
|
|
|
|
// Send the request to the task manager
|
|
WsbAffirmHr(GetHsmEngine(&pEngine));
|
|
WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::Validate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::ValidateForTruncate(
|
|
IN IFsaScanItem* pScanItem,
|
|
IN LONGLONG offset,
|
|
IN LONGLONG size,
|
|
IN LONGLONG usn
|
|
)
|
|
|
|
/*++
|
|
|
|
Implements:
|
|
|
|
IFsaResource::ValidateForTruncate().
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IFsaPostIt> pWorkItem;
|
|
CComPtr<IHsmFsaTskMgr> pEngine;
|
|
CWsbStringPtr tmpString;
|
|
CComPtr<IHsmSession> pSession;
|
|
FSA_PLACEHOLDER placeholder;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::ValidateForTruncate"), OLESTR("offset = %I64d, size = %I64d, usn = <%I64d>"),
|
|
offset, size, usn);
|
|
try {
|
|
|
|
// Make sure the Scan Item interface is OK
|
|
WsbAssert(pScanItem != 0, E_POINTER);
|
|
WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
|
|
|
|
// Get the data from the scan item.
|
|
WsbAffirmHr(pScanItem->GetSession(&pSession));
|
|
WsbAffirmHr(pWorkItem->SetSession(pSession));
|
|
|
|
WsbAffirmHr(pScanItem->GetPathAndName(0, &tmpString, 0));
|
|
WsbAffirmHr(pWorkItem->SetPath(tmpString));
|
|
|
|
WsbAffirmHr(pWorkItem->SetRequestOffset(offset));
|
|
WsbAffirmHr(pWorkItem->SetRequestSize(size));
|
|
|
|
WsbAffirmHr(pScanItem->GetPlaceholder(offset, size, &(placeholder)));
|
|
WsbAffirmHr(pWorkItem->SetPlaceholder(&placeholder));
|
|
|
|
// Fill in the rest of the work
|
|
WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_VALIDATE_FOR_TRUNCATE));
|
|
WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_NONE));
|
|
|
|
// Fill in the USN
|
|
WsbAffirmHr(pWorkItem->SetUSN(usn));
|
|
|
|
// Send the request to the task manager
|
|
WsbAffirmHr(GetHsmEngine(&pEngine));
|
|
WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::ValidateForTruncate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CFsaResource::WriteIdentifier(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
This code is no longer called, in time it will be removed
|
|
|
|
--*/
|
|
{
|
|
#if 0
|
|
HRESULT hr = S_OK;
|
|
CWsbStringPtr tmpString;
|
|
HANDLE aHandle;
|
|
ULONG size;
|
|
ULONG bytesWritten;
|
|
FILE_FS_OBJECT_ID_INFORMATION objectId;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
IO_STATUS_BLOCK ioStatus;
|
|
|
|
WsbTraceIn(OLESTR("CFsaResource::WriteIdentifier"), OLESTR(""));
|
|
try {
|
|
|
|
// For now, we will create a file in the root of the volume.
|
|
tmpString = m_path;
|
|
WsbAffirmHr(tmpString.Prepend("\\\\?\\"));
|
|
// WsbAffirmHr(tmpString.Append(":MSHSM_FSAID"));
|
|
|
|
WsbAffirmHandle(aHandle = CreateFile(tmpString,
|
|
GENERIC_WRITE,
|
|
0,
|
|
0,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0));
|
|
|
|
try {
|
|
|
|
WsbAffirmHr(WsbConvertToBytes(objectId.ObjectId, m_id, &size));
|
|
|
|
status = NtSetVolumeInformationFile(
|
|
aHandle,
|
|
&ioStatus,
|
|
&objectId,
|
|
sizeof(objectId),
|
|
FileFsObjectIdInformation);
|
|
|
|
WsbAffirmNtStatus(status);
|
|
|
|
WsbAffirm(bytesWritten == size, E_FAIL);
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbAffirmStatus(CloseHandle(aHandle));
|
|
|
|
} WsbCatch(hr);
|
|
|
|
WsbTraceOut(OLESTR("CFsaResource::WriteIdentifier"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
|
|
return(hr);
|
|
|
|
#else
|
|
return S_OK;
|
|
#endif
|
|
}
|
|
|
|
|
|
void CFsaResource::OnStateChange( )
|
|
/*++
|
|
|
|
Note: This function is run in a separate thread to avoid a deadlock situation
|
|
|
|
--*/
|
|
{
|
|
IConnectionPointImpl<CFsaResource, &IID_IHsmEvent, CComDynamicUnkArray>* p = this;
|
|
Lock();
|
|
HRESULT hr = S_OK;
|
|
IUnknown** pp = p->m_vec.begin();
|
|
while (pp < p->m_vec.end() && hr == S_OK)
|
|
{
|
|
if (*pp != NULL)
|
|
{
|
|
IHsmEvent* pIHsmEvent = (IHsmEvent*)*pp;
|
|
hr = pIHsmEvent->OnStateChange( );
|
|
}
|
|
pp++;
|
|
}
|
|
Unlock();
|
|
}
|
|
|