Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2185 lines
51 KiB

/*++
© 1998 Seagate Software, Inc. All rights reserved.
Module Name:
fsaitem.cpp
Abstract:
This class contains represents a scan item (i.e. file or directory) for NTFS 5.0.
Author:
Chuck Bardeen [cbardeen] 1-Dec-1996
Revision History:
--*/
#include "stdafx.h"
#define WSB_TRACE_IS WSB_TRACE_BIT_FSA
#include "wsb.h"
#include "wsbtrak.h"
#include "fsa.h"
#include "mover.h"
#include "fsaitem.h"
#include "fsaprem.h"
static USHORT iCountItem = 0; // Count of existing objects
HRESULT
CFsaScanItem::CompareTo(
IN IUnknown* pUnknown,
OUT SHORT* pResult
)
/*++
Implements:
IWsbCollectable::CompareTo().
--*/
{
HRESULT hr = S_OK;
CComPtr<IFsaScanItem> pScanItem;
WsbTraceIn(OLESTR("CFsaScanItem::CompareTo"), OLESTR(""));
try {
// Did they give us a valid item to compare to?
WsbAssert(0 != pUnknown, E_POINTER);
// We need the IWsbBool interface to get the value of the object.
WsbAffirmHr(pUnknown->QueryInterface(IID_IFsaScanItem, (void**) &pScanItem));
// Compare the rules.
hr = CompareToIScanItem(pScanItem, pResult);
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::CompareTo"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
return(hr);
}
HRESULT
CFsaScanItem::CompareToIScanItem(
IN IFsaScanItem* pScanItem,
OUT SHORT* pResult
)
/*++
Implements:
IFsaScanItem::CompareToIScanItem().
--*/
{
HRESULT hr = S_OK;
CWsbStringPtr path;
CWsbStringPtr name;
WsbTraceIn(OLESTR("CFsaScanItem::CompareToIScanItem"), OLESTR(""));
try {
// Did they give us a valid item to compare to?
WsbAssert(0 != pScanItem, E_POINTER);
// Either compare the name or the id.
WsbAffirmHr(pScanItem->GetPath(&path, 0));
WsbAffirmHr(pScanItem->GetName(&name, 0));
hr = CompareToPathAndName(path, name, pResult);
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::CompareToIScanItem"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
return(hr);
}
HRESULT
CFsaScanItem::CompareToPathAndName(
IN OLECHAR* path,
IN OLECHAR* name,
OUT SHORT* pResult
)
/*++
Implements:
IFsaScanItem::CompareToPathAndName().
--*/
{
HRESULT hr = S_OK;
SHORT aResult = 0;
WsbTraceIn(OLESTR("CFsaScanItem::CompareToPathAndName"), OLESTR(""));
try {
// Compare the path.
aResult = (SHORT) _wcsicmp(m_path, path);
// Compare the name.
if (0 == aResult) {
aResult = (SHORT) _wcsicmp(m_findData.cFileName, name);
}
if (0 != aResult) {
hr = S_FALSE;
}
if (0 != pResult) {
*pResult = aResult;
}
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::CompareToPathAndName"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
return(hr);
}
HRESULT
CFsaScanItem::Copy(
IN OLECHAR* dest,
IN BOOL /*retainHierarcy*/,
IN BOOL /*expandPlaceholders*/,
IN BOOL overwriteExisting
)
/*++
Implements:
IFsaScanItem::Copy().
--*/
{
HRESULT hr = S_OK;
try {
// NOTE : This default behavior causes placeholders
// to be expanded and probably doesn't retain the heirarchy.
WsbAssert(0 != dest, E_POINTER);
WsbAssert(CopyFile(m_findData.cFileName, dest, overwriteExisting), E_FAIL);
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::CreateLocalStream(
OUT IStream **ppStream
)
/*++
Implements:
IFsaScanItem::CreateLocalStream().
--*/
{
HRESULT hr = S_OK;
LARGE_INTEGER fileSize;
CWsbStringPtr volName;
WsbTraceIn(OLESTR("CFsaScanItem::CreateLocalStream"), OLESTR(""));
try {
CWsbStringPtr localName;
if ( !m_gotPlaceholder) {
//
// Get the placeholder info
//
fileSize.LowPart = m_findData.nFileSizeLow;
fileSize.HighPart = m_findData.nFileSizeHigh;
WsbAffirmHr(IsManaged(0, fileSize.QuadPart));
}
WsbAssert( 0 != ppStream, E_POINTER);
WsbAffirmHr( CoCreateInstance( CLSID_CNtFileIo, 0, CLSCTX_SERVER, IID_IDataMover, (void **)&m_pDataMover ) );
//
// Set the device name for the mover so it can set the source infor for the USN journal.
//
WsbAffirmHr(m_pResource->GetPath(&volName, 0));
WsbAffirmHr( m_pDataMover->SetDeviceName(volName));
//WsbAffirmHr(GetFullPathAndName( NULL, 0, &localName, 0));
WsbAffirmHr(GetFullPathAndName( OLESTR("\\\\?\\"), 0, &localName, 0));
WsbAffirmHr( m_pDataMover->CreateLocalStream(
localName, MVR_MODE_WRITE | MVR_FLAG_HSM_SEMANTICS | MVR_FLAG_POSIX_SEMANTICS, &m_pStream ) );
LARGE_INTEGER seekTo;
ULARGE_INTEGER pos;
seekTo.QuadPart = m_placeholder.dataStreamStart;
WsbAffirmHr( m_pStream->Seek( seekTo, STREAM_SEEK_SET, &pos ) );
*ppStream = m_pStream;
m_pStream.p->AddRef();
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::CreateLocalStream"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::Delete(
void
)
/*++
Implements:
IFsaScanItem::Delete().
--*/
{
HRESULT hr = S_OK;
CWsbStringPtr tmpString;
HANDLE fileHandle;
try {
// This is the name of the file we want to delete.
WsbAffirmHr(GetFullPathAndName(OLESTR("\\\\?\\"), 0, &tmpString, 0));
// Since we want to be POSIX compliant, we can't use DeleteFile() and instead will
// open with the delete on close flag. This doesn't handle read-only files, so we
// have to change that ourselves.
WsbAffirmHr(MakeReadWrite());
fileHandle = CreateFile(tmpString, GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE, 0);
if (INVALID_HANDLE_VALUE == fileHandle) {
WsbThrow(HRESULT_FROM_WIN32(GetLastError()));
} else {
if (!CloseHandle(fileHandle)) {
WsbThrow(HRESULT_FROM_WIN32(GetLastError()));
}
}
} WsbCatch(hr);
return(hr);
}
#pragma optimize("g", off)
HRESULT
CFsaScanItem::FinalConstruct(
void
)
/*++
Implements:
CComObjectRoot::FinalConstruct().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaScanItem::FinalConstruct"), OLESTR(""));
try {
WsbAffirmHr(CComObjectRoot::FinalConstruct());
m_handle = INVALID_HANDLE_VALUE;
m_gotPhysicalSize = FALSE;
m_physicalSize.QuadPart = 0;
m_gotPlaceholder = FALSE;
m_changedAttributes = FALSE;
m_handleRPI = 0;
// Add class to object table
WSB_OBJECT_ADD(CLSID_CFsaScanItemNTFS, this);
} WsbCatch(hr);
iCountItem++;
WsbTraceOut(OLESTR("CFsaScanItem::FinalConstruct"), OLESTR("hr = <%ls>, Count is <%d>"),
WsbHrAsString(hr), iCountItem);
return(hr);
}
#pragma optimize("", on)
void
CFsaScanItem::FinalRelease(
void
)
/*++
Implements:
CComObjectRoot::FinalRelease().
--*/
{
WsbTraceIn(OLESTR("CFsaScanItem::FinalRelease"), OLESTR(""));
// Subtract class from object table
WSB_OBJECT_SUB(CLSID_CFsaScanItemNTFS, this);
// Terminate the scan and free the path memory.
if (INVALID_HANDLE_VALUE != m_handle) {
FindClose(m_handle);
m_handle = INVALID_HANDLE_VALUE;
}
if (0 != m_handleRPI) {
CloseHandle(m_handleRPI);
m_handleRPI = 0;
}
if (m_pUnmanageDb != NULL) {
// Db must be open
(void)m_pUnmanageDb->Close(m_pDbSession);
m_pDbSession = 0;
m_pUnmanageRec = 0;
}
if (TRUE == m_changedAttributes) {
//
// We changed it from read only to read/write - put it back.
//
RestoreAttributes();
}
//
// Detach the data mover stream
if (m_pDataMover != 0) {
WsbAffirmHr( m_pDataMover->CloseStream() );
}
// Let the parent class do his thing.
CComObjectRoot::FinalRelease();
iCountItem--;
WsbTraceOut(OLESTR("CFsaScanItem::FinalRelease"), OLESTR("Count is <%d>"), iCountItem);
}
HRESULT
CFsaScanItem::FindFirst(
IN IFsaResource* pResource,
IN OLECHAR* path,
IN IHsmSession* pSession
)
/*++
Implements:
IFsaScanItem::FindFirst().
--*/
{
HRESULT hr = S_OK;
CWsbStringPtr findPath;
CWsbStringPtr searchName;
OLECHAR* slashPtr;
DWORD lErr;
WsbTraceIn(OLESTR("CFsaScanItem::FindFirst"), OLESTR("path = <%ls>"),
path);
try {
WsbAssert(0 != pResource, E_POINTER);
WsbAssert(0 != path, E_POINTER);
// Store off some of the scan information.
m_pResource = pResource;
m_pSession = pSession;
// Break up the incoming path into a path and a name.
m_path = path;
slashPtr = wcsrchr(m_path, L'\\');
// We could try to support relative path stuff (i.e. current
// directory, but I am not going to do it for now.
WsbAffirm(slashPtr != 0, E_FAIL);
searchName = &(slashPtr[1]);
slashPtr[1] = 0;
// Get a path that can be used by the find function.
WsbAffirmHr(GetPathForFind(searchName, &findPath, 0));
// Scan starting at the specified path.
m_handle = FindFirstFileEx(findPath, FindExInfoStandard, &m_findData, FindExSearchNameMatch, 0, FIND_FIRST_EX_CASE_SENSITIVE);
lErr = GetLastError();
// If we found a file, then remember the scan handle and
// return the scan item.
WsbAffirm(INVALID_HANDLE_VALUE != m_handle, WSB_E_NOTFOUND);
m_gotPhysicalSize = FALSE;
m_physicalSize.QuadPart = 0;
m_gotPlaceholder = FALSE;
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::FindFirst"), OLESTR("hr = <%ls>"),
WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::FindNext(
void
)
/*++
Implements:
IFsaScanItem::FindNext().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaScanItem::FindNext"), OLESTR(""));
try {
WsbAssert(INVALID_HANDLE_VALUE != m_handle, E_FAIL);
if (TRUE == m_changedAttributes) {
//
// We changed it from read only to read/write - put it back.
//
RestoreAttributes();
}
// Continue the scan.
WsbAffirm(FindNextFile(m_handle, &m_findData), WSB_E_NOTFOUND);
m_gotPhysicalSize = FALSE;
m_physicalSize.QuadPart = 0;
m_gotPlaceholder = FALSE;
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::FindNext"), OLESTR("hr = <%ls>"),
WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::GetAccessTime(
OUT FILETIME* pTime
)
/*++
Implements:
IFsaScanItem::GetAccessTime().
--*/
{
HRESULT hr = S_OK;
try {
WsbAssert(0 != pTime, E_POINTER);
*pTime = m_findData.ftLastAccessTime;
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetGroup(
OUT OLECHAR** /*pGroup*/,
IN ULONG /*bufferSize*/
)
/*++
Implements:
IFsaScanItem::GetGroup().
--*/
{
HRESULT hr = S_OK;
try {
hr = E_NOTIMPL;
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetLogicalSize(
OUT LONGLONG* pSize
)
/*++
Implements:
IFsaScanItem::GetLogicalSize().
--*/
{
HRESULT hr = S_OK;
LARGE_INTEGER logSize;
try {
WsbAssert(0 != pSize, E_POINTER);
logSize.LowPart = m_findData.nFileSizeLow;
logSize.HighPart = m_findData.nFileSizeHigh;
*pSize = logSize.QuadPart;
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetModifyTime(
OUT FILETIME* pTime
)
/*++
Implements:
IFsaScanItem::GetModifyTime().
--*/
{
HRESULT hr = S_OK;
try {
WsbAssert(0 != pTime, E_POINTER);
*pTime = m_findData.ftLastWriteTime;
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetName(
OUT OLECHAR** pName,
IN ULONG bufferSize
)
/*++
Implements:
IFsaScanItem::GetName().
--*/
{
HRESULT hr = S_OK;
CWsbStringPtr tmpString = m_findData.cFileName;
try {
WsbAssert(0 != pName, E_POINTER);
WsbAffirmHr(tmpString.CopyTo(pName, bufferSize));
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetOwner(
OUT OLECHAR** /*pOwner*/,
IN ULONG /*bufferSize*/
)
/*++
Implements:
IFsaScanItem::GetOwner().
--*/
{
HRESULT hr = S_OK;
try {
hr = E_NOTIMPL;
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetPath(
OUT OLECHAR** pPath,
IN ULONG bufferSize
)
/*++
Implements:
IFsaScanItem::GetPath().
--*/
{
HRESULT hr = S_OK;
try {
WsbAssert(0 != pPath, E_POINTER);
WsbAffirmHr(m_path.CopyTo(pPath, bufferSize));
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetPathForFind(
IN OLECHAR* searchName,
OUT OLECHAR** pPath,
IN ULONG bufferSize
)
/*++
Implements:
IFsaScanItem::GetPathForFind().
--*/
{
HRESULT hr = S_OK;
CWsbStringPtr tmpString;
try {
WsbAssert(0 != pPath, E_POINTER);
// Get a buffer.
WsbAffirmHr(tmpString.TakeFrom(*pPath, bufferSize));
try {
// Get the path to the resource of the resource.
//
WsbAffirmHr(m_pResource->GetPath(&tmpString, 0));
WsbAffirmHr(tmpString.Prepend(OLESTR("\\\\?\\")));
//WsbAffirmHr(tmpString.Append(OLESTR("\\")));
// Copy in the path.
//WsbAffirmHr(tmpString.Prepend(OLESTR("\\\\?\\")));
WsbAffirmHr(tmpString.Append(&(m_path[1])));
WsbAffirmHr(tmpString.Append(searchName));
} WsbCatch(hr);
WsbAffirmHr(tmpString.GiveTo(pPath));
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetPathAndName(
IN OLECHAR* appendix,
OUT OLECHAR** pPath,
IN ULONG bufferSize
)
/*++
Implements:
IFsaScanItem::GetPathAndName().
--*/
{
HRESULT hr = S_OK;
CWsbStringPtr tmpString;
try {
WsbAssert(0 != pPath, E_POINTER);
// Get a buffer.
WsbAffirmHr(tmpString.TakeFrom(*pPath, bufferSize));
try {
tmpString = m_path;
tmpString.Append(m_findData.cFileName);
if (0 != appendix) {
tmpString.Append(appendix);
}
} WsbCatch(hr);
// Give responsibility for freeing the memory back to the caller.
WsbAffirmHr(tmpString.GiveTo(pPath));
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetFullPathAndName(
IN OLECHAR* prependix,
IN OLECHAR* appendix,
OUT OLECHAR** pPath,
IN ULONG bufferSize
)
/*++
Implements:
IFsaScanItem::GetFullPathAndName().
--*/
{
HRESULT hr = S_OK;
CWsbStringPtr tmpString;
CWsbStringPtr tmpString2;
try {
WsbAssert(0 != pPath, E_POINTER);
// Get a buffer.
WsbAffirmHr(tmpString.TakeFrom(*pPath, bufferSize));
try {
if (0 != prependix) {
tmpString = prependix;
// Get the path to the resource of the resource.
WsbAffirmHr(m_pResource->GetPath(&tmpString2, 0));
WsbAffirmHr(tmpString.Append(tmpString2));
} else {
WsbAffirmHr(m_pResource->GetPath(&tmpString, 0));
}
// Copy in the path.
WsbAffirmHr(tmpString.Append(&(m_path[1])));
WsbAffirmHr(tmpString.Append(m_findData.cFileName));
if (0 != appendix) {
WsbAffirmHr(tmpString.Append(appendix));
}
} WsbCatch(hr);
// Give responsibility for freeing the memory back to the caller.
WsbAffirmHr(tmpString.GiveTo(pPath));
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetPhysicalSize(
OUT LONGLONG* pSize
)
/*++
Implements:
IFsaScanItem::GetPhysicalSize().
--*/
{
HRESULT hr = S_OK;
CWsbStringPtr path;
try {
WsbAssert(0 != pSize, E_POINTER);
//WsbAssertHr(GetFullPathAndName(NULL, 0, &path, 0));
WsbAssertHr(GetFullPathAndName(OLESTR("\\\\?\\"), 0, &path, 0));
// Only read this value in once, but wait until it is asked for
// before reading it in (since this call takes time and many scans
// won't need the information.
if (!m_gotPhysicalSize) {
m_physicalSize.LowPart = GetCompressedFileSize(path, &m_physicalSize.HighPart);
if (MAXULONG == m_physicalSize.LowPart) {
// Have to check last error since MAXULONG could be a valid
// value for the low part of the size.
DWORD err = GetLastError();
if (err != NO_ERROR) {
WsbTrace(OLESTR("CFsaScanItem::GetPhysicalSize of %ws Last error = %u\n"),
(WCHAR *) path, err);
}
WsbAffirm(NO_ERROR == err, E_FAIL);
}
m_gotPhysicalSize = TRUE;
}
*pSize = m_physicalSize.QuadPart;
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetPremigratedUsn(
OUT LONGLONG* pFileUsn
)
/*++
Implements:
Routine Description:
Get the USN Journal number for this file from the premigrated list.
Arguments:
pFileUsn - Pointer to File USN to be returned.
Return Value:
S_OK - success
--*/
{
HRESULT hr = S_OK;
try {
CComPtr<IWsbDbSession> pDbSession;
CComPtr<IFsaPremigratedDb> pPremDb;
CComPtr<IFsaResourcePriv> pResourcePriv;
WsbAssert(pFileUsn, E_POINTER);
// Get the premigrated list DB
WsbAffirmHr(m_pResource->QueryInterface(IID_IFsaResourcePriv,
(void**) &pResourcePriv));
WsbAffirmHr(pResourcePriv->GetPremigrated(IID_IFsaPremigratedDb,
(void**) &pPremDb));
// Open the premigration list
WsbAffirmHr(pPremDb->Open(&pDbSession));
try {
FSA_PLACEHOLDER PlaceHolder;
CComPtr<IFsaPremigratedRec> pPremRec;
LONGLONG usn;
// Get a DB entity for the search
WsbAffirmHr(pPremDb->GetEntity(pDbSession, PREMIGRATED_REC_TYPE,
IID_IFsaPremigratedRec, (void**) &pPremRec));
WsbAffirmHr(pPremRec->UseKey(PREMIGRATED_BAGID_OFFSETS_KEY_TYPE));
// Find the record
WsbAffirmHr(GetPlaceholder(0, 0, &PlaceHolder));
WsbAffirmHr(pPremRec->SetBagId(PlaceHolder.bagId));
WsbAffirmHr(pPremRec->SetBagOffset(PlaceHolder.fileStart));
WsbAffirmHr(pPremRec->SetOffset(PlaceHolder.dataStreamStart));
WsbAffirmHr(pPremRec->FindEQ());
// Get the stored USN
WsbAffirmHr(pPremRec->GetFileUSN(&usn));
*pFileUsn = usn;
} WsbCatch(hr);
// Close the DB
pPremDb->Close(pDbSession);
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetSession(
OUT IHsmSession** ppSession
)
/*++
Implements:
IFsaScanItem::GetSession().
--*/
{
HRESULT hr = S_OK;
try {
WsbAssert(0 != ppSession, E_POINTER);
*ppSession = m_pSession;
m_pSession.p->AddRef();
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::GetUncPathAndName(
IN OLECHAR* prependix,
IN OLECHAR* appendix,
OUT OLECHAR** pPath,
IN ULONG bufferSize
)
/*++
Implements:
IFsaScanItem::GetUncPathAndName().
--*/
{
HRESULT hr = S_OK;
CWsbStringPtr tmpString;
CWsbStringPtr tmpString2;
try {
WsbAssert(0 != pPath, E_POINTER);
// Get a buffer.
WsbAffirmHr(tmpString.TakeFrom(*pPath, bufferSize));
try {
if (0 != prependix) {
tmpString = prependix;
// Get the path to the resource of the resource.
WsbAffirmHr(m_pResource->GetUncPath(&tmpString2, 0));
WsbAffirmHr(tmpString.Append(tmpString2));
} else {
WsbAffirmHr(m_pResource->GetPath(&tmpString, 0));
}
// Copy in the path.
WsbAffirmHr(tmpString.Append(&(m_path[1])));
WsbAffirmHr(tmpString.Append(m_findData.cFileName));
if (0 != appendix) {
WsbAffirmHr(tmpString.Append(appendix));
}
} WsbCatch(hr);
// Give responsibility for freeing the memory back to the caller.
WsbAffirmHr(tmpString.GiveTo(pPath));
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::IsAParent(
void
)
/*++
Implements:
IFsaScanItem::IsAParent().
--*/
{
HRESULT hr = S_FALSE;
if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
hr = S_OK;
}
return(hr);
}
HRESULT
CFsaScanItem::IsARelativeParent(
void
)
/*++
Implements:
IFsaScanItem::IsARelativeParent().
--*/
{
HRESULT hr = S_FALSE;
if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
// looking for "."
if (m_findData.cFileName[0] == L'.') {
if (m_findData.cFileName[1] == 0) {
hr = S_OK;
}
// looking for "."
else if (m_findData.cFileName[1] == L'.') {
if (m_findData.cFileName[2] == 0) {
hr = S_OK;
}
}
}
}
return(hr);
}
HRESULT
CFsaScanItem::IsCompressed(
void
)
/*++
Implements:
IFsaScanItem::IsCompressed().
--*/
{
HRESULT hr = S_FALSE;
if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) != 0) {
hr = S_OK;
}
return(hr);
}
HRESULT
CFsaScanItem::IsEncrypted(
void
)
/*++
Implements:
IFsaScanItem::IsEncrypted().
--*/
{
HRESULT hr = S_FALSE;
if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) != 0) {
hr = S_OK;
}
return(hr);
}
HRESULT
CFsaScanItem::IsDeleteOK(
IN IFsaPostIt *pPostIt
)
/*++
Implements:
IFsaScanItem::IsDeleteOK().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaScanItem::IsDeleteOK"), OLESTR(""));
try {
//
// Get the version ID from the FSA Post it. This is the
// version of the file at the time of the migrate request
//
LONGLONG workVersionId;
WsbAffirmHr(pPostIt->GetFileVersionId(&workVersionId));
//
// Get the version of the file at the time of this scan
//
LONGLONG scanVersionId;
WsbAffirmHr(GetVersionId(&scanVersionId));
//
// See if the versions match
//
WsbTrace(OLESTR("CFsaScanItem::IsDeleteOK: workVersionId:<%I64u> scanVersionId:<%I64u>\n"),
workVersionId, scanVersionId);
if (workVersionId != scanVersionId) {
WsbTrace(OLESTR("CFsaScanItem::IsDeleteOK: File version has changed!\n"));
WsbThrow(FSA_E_FILE_CHANGED);
}
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::IsDeleteOk"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::IsGroupMemberOf(
OLECHAR* /*group*/
)
/*++
Implements:
IFsaScanItem::IsGroupMemberOf().
--*/
{
HRESULT hr = S_FALSE;
hr = E_NOTIMPL;
return(hr);
}
HRESULT
CFsaScanItem::IsHidden(
void
)
/*++
Implements:
IFsaScanItem::IsHidden().
--*/
{
HRESULT hr = S_FALSE;
if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0) {
hr = S_OK;
}
return(hr);
}
HRESULT
CFsaScanItem::IsManageable(
IN LONGLONG offset,
IN LONGLONG size
)
/*++
Implements:
IFsaScanItem::IsManageable().
--*/
{
HRESULT hr = S_FALSE;
HRESULT hr2;
LONGLONG logicalSize;
LONGLONG managableSize;
LONGLONG maxFileSize;
FILETIME time;
FILETIME managableTime;
BOOL isRelative;
//
// Get some strings for logging and tracing
//
CWsbStringPtr fileName;
CWsbStringPtr jobName;
try {
WsbAffirmHr(GetFullPathAndName( 0, 0, &fileName, 0));
WsbAffirmHr(m_pSession->GetName(&jobName, 0));
} WsbCatch( hr );
WsbTraceIn(OLESTR("CFsaScanItem::IsManageable"), OLESTR("<%ls>"), (OLECHAR *)fileName);
try {
// To be managable the item:
// - can't already be managed (premigratted or truncated)
// - can't be a link
// - can't be encrypted
// - can't be sparse
// - can't have extended attributes (reparse point limitation)
// - must have a size bigger than the resource's default size
// - must have a last access time older than the resource's default time
// Managed?
hr2 = IsManaged(offset, size);
if (S_FALSE == hr2) {
// A link?
hr2 = IsALink();
if (S_FALSE == hr2) {
// Encrypted?
hr2 = IsEncrypted();
if (S_FALSE == hr2) {
// A sparse?
hr2 = IsSparse();
if (S_FALSE == hr2) {
// A sparse?
hr2 = HasExtendedAttributes();
if (S_FALSE == hr2) {
// Big enough?
WsbAffirmHr(GetLogicalSize(&logicalSize));
WsbAffirmHr(m_pResource->GetManageableItemLogicalSize(&managableSize));
if (logicalSize >= managableSize) {
// Old enough?
WsbAffirmHr(GetAccessTime(&time));
WsbAffirmHr(m_pResource->GetManageableItemAccessTime(&isRelative, &managableTime));
if (WsbCompareFileTimes(time, managableTime, isRelative, FALSE) >= 0) {
// Small enough? (This is according to media size limit !)
CComPtr<IFsaResourcePriv> pResourcePriv;
WsbAffirmHr(m_pResource->QueryInterface(IID_IFsaResourcePriv,
(void**) &pResourcePriv));
WsbAffirmHr(pResourcePriv->GetMaxFileLogicalSize(&maxFileSize));
if ((logicalSize <= maxFileSize) || (0 == maxFileSize)) {
// It can be managed!!
hr = S_OK;
} else {
WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISTOOLARGE, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
WsbTrace(OLESTR("CFsaScanItem::IsManageable: file not manageable: Logical size = %I64d; Max file size = %I64d\n"),
logicalSize, maxFileSize);
}
} else {
WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISACCESSED, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
}
} else {
WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISTOOSMALL, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
}
} else {
WsbLogEvent(FSA_MESSAGE_FILESKIPPED_HASEA, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
}
} else {
WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISSPARSE, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
}
} else {
WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISENCRYPTED, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
}
} else {
WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISALINK, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
}
} else {
WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISMANAGED, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
}
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::IsManageable"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::IsMigrateOK(
IN IFsaPostIt *pPostIt
)
/*++
Implements:
IFsaScanItem::IsMigrateOK().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaScanItem::IsMigrateOK"), OLESTR(""));
try {
//
// Make sure the file isn't already managed. This could happen if two jobs were scanning
// the same volume.
//
LONGLONG offset;
LONGLONG size;
WsbAffirmHr(pPostIt->GetRequestOffset(&offset));
WsbAffirmHr(pPostIt->GetRequestSize(&size));
if (IsManaged(offset, size) == S_OK) {
//
// The file is already managed so skip it
//
WsbTrace(OLESTR("A manage request for an already managed file - skip it!\n"));
WsbThrow(FSA_E_FILE_ALREADY_MANAGED);
}
//
// Get the version ID from the FSA Post it. This is the
// version of the file at the time of the migrate request
//
LONGLONG workVersionId;
WsbAffirmHr(pPostIt->GetFileVersionId(&workVersionId));
//
// Get the version of the file at the time of this scan
//
LONGLONG scanVersionId;
WsbAffirmHr(GetVersionId(&scanVersionId));
//
// See if the versions match
//
WsbTrace(OLESTR("CFsaScanItem::IsMigrateOK: workVersionId:<%I64u> scanVersionId:<%I64u>\n"),
workVersionId, scanVersionId);
if (workVersionId != scanVersionId) {
WsbTrace(OLESTR("CFsaScanItem::IsMigrateOK: File version has changed!\n"));
WsbThrow(FSA_E_FILE_CHANGED);
}
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::IsMigrateOK"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::IsMbit(
void
)
/*++
Implements:
IFsaScanItem::IsMbit().
--*/
{
HRESULT hr = S_FALSE;
if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) != 0) {
hr = S_OK;
}
return(hr);
}
HRESULT
CFsaScanItem::IsOffline(
void
)
/*++
Implements:
IFsaScanItem::IsOffline().
--*/
{
HRESULT hr = S_FALSE;
if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) != 0) {
hr = S_OK;
}
return(hr);
}
HRESULT
CFsaScanItem::IsOwnerMemberOf(
OLECHAR* /*group*/
)
/*++
Implements:
IFsaScanItem::IsOwnerMemberOf().
--*/
{
HRESULT hr = S_FALSE;
hr = E_NOTIMPL;
return(hr);
}
HRESULT
CFsaScanItem::IsReadOnly(
void
)
/*++
Implements:
IFsaScanItem::IsReadOnly().
--*/
{
HRESULT hr = S_FALSE;
if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0) {
hr = S_OK;
}
return(hr);
}
HRESULT
CFsaScanItem::IsRecallOK(
IN IFsaPostIt *pPostIt
)
/*++
Implements:
IFsaScanItem::IsRecallOK().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaScanItem::IsRecallOK"), OLESTR(""));
try {
LONGLONG offset;
LONGLONG size;
//
// Make sure the file is still truncated
//
WsbAffirmHr(pPostIt->GetRequestOffset(&offset));
WsbAffirmHr(pPostIt->GetRequestSize(&size));
hr = IsTruncated(offset, size);
if (S_OK != hr) {
//
// The file is not truncated, so skip it
//
WsbTrace(OLESTR("CFsaScanItem::IsRecallOK - file isn't truncated.\n"));
WsbThrow(FSA_E_FILE_NOT_TRUNCATED);
}
// Get the version ID from the FSA Post it. This is the
// version of the file at the time of the migrate request
//
LONGLONG workVersionId;
WsbAffirmHr(pPostIt->GetFileVersionId(&workVersionId));
//
// Get the version of the file
//
LONGLONG scanVersionId;
WsbAffirmHr(GetVersionId(&scanVersionId));
//
// See if the versions match
//
WsbTrace(OLESTR("CFsaScanItem::IsRecallOK: workVersionId:<%I64u> scanVersionId:<%I64u>\n"),
workVersionId, scanVersionId);
if (workVersionId != scanVersionId) {
WsbTrace(OLESTR("CFsaScanItem::IsRecallOK: File version has changed!\n"));
//
// If the use has changed alternate data streams
// the file version ID may have changed but it is
// OK to recall the file. So if the version ID's
// don't match, then check to see if the truncated
// part of the file is OK. If so, allow the recall
// to happen.
//
//
// Check to see if the whole file is still sparse
//
if (IsTotallySparse() == S_OK) {
//
// The file is OK so far to recall but we need
// to make the last modify dates match
//
FSA_PLACEHOLDER placeholder;
WsbAffirmHr(pPostIt->GetPlaceholder(&placeholder));;
placeholder.fileVersionId = scanVersionId;
WsbAffirmHr(pPostIt->SetPlaceholder(&placeholder));
} else {
//
// The file has been changed, recalling data will
// overwrite something that has been added since the
// truncation occurred. So don't do anything.
//
WsbTrace(OLESTR("File is no longer sparse.!\n"));
WsbThrow(FSA_E_FILE_CHANGED);
}
}
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::IsRecallOK"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::IsSparse(
void
)
/*++
Implements:
IFsaScanItem::IsSparse().
--*/
{
HRESULT hr = S_FALSE;
LONGLONG size;
WsbTraceIn(OLESTR("CFsaScanItem::IsSparse"), OLESTR(""));
if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0) {
hr = GetLogicalSize( &size ) ;
if ( S_OK == hr ) {
hr = CheckIfSparse(0, size );
if ( (FSA_E_FILE_IS_TOTALLY_SPARSE == hr) ||
(FSA_E_FILE_IS_PARTIALLY_SPARSE == hr) ) {
hr = S_OK;
} else {
hr = S_FALSE;
}
}
}
WsbTraceOut(OLESTR("CFsaScanItem::IsSparse"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::IsTotallySparse(
void
)
/*++
Implements:
IFsaScanItem::IsTotallySparse().
--*/
{
HRESULT hr = S_FALSE;
LONGLONG size;
WsbTraceIn(OLESTR("CFsaScanItem::IsTotallySparse"), OLESTR(""));
if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0) {
hr = GetLogicalSize( &size ) ;
if ( S_OK == hr ) {
hr = CheckIfSparse(0, size );
if (FSA_E_FILE_IS_TOTALLY_SPARSE == hr) {
hr = S_OK;
} else {
hr = S_FALSE;
}
}
}
WsbTraceOut(OLESTR("CFsaScanItem::IsTotallySparse"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::Manage(
IN LONGLONG offset,
IN LONGLONG size,
IN GUID storagePoolId,
IN BOOL truncate
)
/*++
Implements:
IFsaScanItem::Manage().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaScanItem::Manage"), OLESTR(""));
try {
WsbAssert(GUID_NULL != storagePoolId, E_INVALIDARG);
WsbAffirmHr(m_pResource->Manage((IFsaScanItem*) this, offset, size, storagePoolId, truncate));
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::Manage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::Move(
OLECHAR* dest,
BOOL /*retainHierarcy*/,
BOOL /*expandPlaceholders*/,
BOOL overwriteExisting
)
/*++
Implements:
IFsaScanItem::Move().
--*/
{
HRESULT hr = S_OK;
DWORD mode = MOVEFILE_COPY_ALLOWED;
try {
// NOTE : This default behavior causes placeholders
// to be expanded when moving to another volume and probably doesn't
// retain the heirarchy.
WsbAssert(0 != dest, E_POINTER);
if (overwriteExisting) {
mode |= MOVEFILE_REPLACE_EXISTING;
}
WsbAssert(MoveFileEx(m_findData.cFileName, dest, mode), E_FAIL);
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::Recall(
IN LONGLONG offset,
IN LONGLONG size,
IN BOOL deletePlaceholder
)
/*++
Implements:
IFsaScanItem::Recall().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaScanItem::Recall"), OLESTR(""));
try {
WsbAffirmHr(m_pResource->Recall((IFsaScanItem*) this, offset, size, deletePlaceholder));
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::Recall"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::Recycle(
void
)
/*++
Implements:
IFsaScanItem::Recycle().
--*/
{
HRESULT hr = S_OK;
try {
// Probably need to look at SHFileOperation().
hr = E_NOTIMPL;
} WsbCatch(hr);
return(hr);
}
HRESULT
CFsaScanItem::IsSystem(
void
)
/*++
Implements:
IFsaScanItem::IsSystem().
--*/
{
HRESULT hr = S_FALSE;
if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) != 0) {
hr = S_OK;
}
return(hr);
}
HRESULT
CFsaScanItem::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
CFsaScanItem::Unmanage(
IN LONGLONG offset,
IN LONGLONG size
)
/*++
Implements:
IFsaScanItem::Unmanage().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaScanItem::Unmanage"), OLESTR("<%ls>"),
WsbAbbreviatePath(m_path, 120));
try {
// We only need to worry about files that have placeholder information.
if (IsManaged(offset, size) == S_OK) {
// If the file is truncated, then we need to recall the data
// before deleting the placeholder information.
// NOTE: We set a flag on the Recall so the placeholder will
// be deleted after the file is recalled.
if (IsTruncated(offset, size) == S_OK) {
WsbAffirmHr(Recall(offset, size, TRUE));
} else {
// For disaster recovery, it would be better to delete the placeholder
// and THEN remove this file from the premigration list. Unfortunately,
// after deleting the placeholder, the RemovePremigrated call fails
// because it needs to get some information from the placeholder (which
// is gone). So we do it in this order.
hr = m_pResource->RemovePremigrated((IFsaScanItem*) this, offset, size);
if (WSB_E_NOTFOUND == hr) {
// It's no tragedy if this file wasn't in the list since we were
// going to delete it anyway (although it shouldn't happen) so
// let's continue anyway
hr = S_OK;
}
WsbAffirmHr(hr);
WsbAffirmHr(DeletePlaceholder(offset, size));
}
}
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::Unmanage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::Validate(
IN LONGLONG offset,
IN LONGLONG size
)
/*++
Implements:
IFsaScanItem::Validate().
--*/
{
HRESULT hr = S_OK;
BOOL fileIsTruncated = FALSE;
LONGLONG usn = 0;
WsbTraceIn(OLESTR("CFsaScanItem::Validate"), OLESTR("offset = <%I64u>, size = <%I64u>"),
offset, size);
try {
//
// Do some local validation before calling the engine.
//
// We only need to worry about files that have placeholder information.
if (IsManaged(offset, size) == S_OK) {
//
// If the file is marked as truncated, make sure it is still truncated.
//
if (IsTruncated(offset, size) == S_OK) {
//
// Check to see if the file is totally sparse to see if it is truncated.
//
if (IsTotallySparse() != S_OK) {
//
// The file is marked as truncated but is not truncated
// Make it truncated.
//
WsbAffirmHr(Truncate(offset,size));
WsbLogEvent(FSA_MESSAGE_VALIDATE_TRUNCATED_FILE, 0, NULL, WsbAbbreviatePath(m_path, 120), WsbHrAsString(hr), NULL);
}
fileIsTruncated = TRUE;
}
}
//
// The last modify date may be updated on a file if the named data streams
// have been modified. So check to see if the dates match. If they don't,
// if the file is trunctated, see if it is still truncated, if so, update the
// modify date in the placeholder to the file's modify date. If the file is
// premigrated and the modify dates don't match, delete the placeholder.
// Get the version ID from the file
LONGLONG scanVersionId;
WsbAffirmHr(GetVersionId(&scanVersionId));
// Get the version ID from the placeholder
FSA_PLACEHOLDER scanPlaceholder;
WsbAffirmHr(GetPlaceholder(offset, size, &scanPlaceholder));
if (TRUE == fileIsTruncated) {
// Check to see if the dates match
if (scanPlaceholder.fileVersionId != scanVersionId) {
WsbTrace(OLESTR("CFsaScanItem::Validate - placeholer version ID = <%I64u>, file version Id = <%I64u>"),
scanPlaceholder.fileVersionId, scanVersionId);
//
// Update the placeholder information on the reparse point
//
LONGLONG afterPhUsn;
scanPlaceholder.fileVersionId = scanVersionId;
WsbAffirmHr(CreatePlaceholder(offset, size, scanPlaceholder, FALSE, 0, &afterPhUsn));
WsbLogEvent(FSA_MESSAGE_VALIDATE_RESET_PH_MODIFY_TIME, 0, NULL, WsbAbbreviatePath(m_path, 120), WsbHrAsString(hr), NULL);
}
} else {
// The file is pre-migrated. Verify that it has not changed since we managed it and if it has then unmanage it.
if (Verify(offset, size) != S_OK) {
WsbAffirmHr(Unmanage(offset, size));
WsbLogEvent(FSA_MESSAGE_VALIDATE_UNMANAGED_FILE, 0, NULL, WsbAbbreviatePath(m_path, 120), WsbHrAsString(hr), NULL);
}
}
// Now that all of this stuff is OK, call the engine
if (IsManaged(offset, size) == S_OK) {
WsbAffirmHr(m_pResource->Validate((IFsaScanItem*) this, offset, size, usn));
}
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::Validate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::FindFirstInDbIndex(
IN IFsaResource* pResource,
IN IHsmSession* pSession
)
/*++
Implements:
IFsaScanItemPriv::FindFirstInDbIndex().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaScanItem::FindFirstInDbIndex"), OLESTR(""));
try {
CComPtr<IFsaResourcePriv> pResourcePriv;
WsbAssert(0 != pResource, E_POINTER);
// Store off some of the scan information.
m_pResource = pResource;
m_pSession = pSession;
// If Db is already present (could happen if somebody calls First() twice in a row),
// we close the Db and reopen since we cannot be sure that the resource is the same!
if (m_pUnmanageDb != NULL) {
// Db must be open
(void)m_pUnmanageDb->Close(m_pDbSession);
m_pDbSession = 0;
m_pUnmanageRec = 0;
m_pUnmanageDb = 0;
}
// Get and open the Unmanage db
// (Note: if this scanning is ever extended to use another DB,
// this method should get additional parameter for which DB to scan)
WsbAffirmHr(m_pResource->QueryInterface(IID_IFsaResourcePriv,
(void**) &pResourcePriv));
hr = pResourcePriv->GetUnmanageDb(IID_IFsaUnmanageDb,
(void**) &m_pUnmanageDb);
if (WSB_E_RESOURCE_UNAVAILABLE == hr) {
// Db was not created ==> no files to scan
hr = WSB_E_NOTFOUND;
}
WsbAffirmHr(hr);
hr = m_pUnmanageDb->Open(&m_pDbSession);
if (S_OK != hr) {
m_pUnmanageDb = NULL;
WsbAffirmHr(hr);
}
// Get a record to traverse with and set for sequential traversing
WsbAffirmHr(m_pUnmanageDb->GetEntity(m_pDbSession, UNMANAGE_REC_TYPE, IID_IFsaUnmanageRec,
(void**)&m_pUnmanageRec));
WsbAffirmHr(m_pUnmanageRec->SetSequentialScan());
// Get file information
WsbAffirmHr(GetFromDbIndex(TRUE));
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::FindFirstInDbIndex"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::FindNextInDbIndex(
void
)
/*++
Implements:
IFsaScanItemPriv::FindNextInDbIndex().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaScanItem::FindNextInDbIndex"), OLESTR(""));
try {
WsbAssert(m_pUnmanageDb != NULL, E_FAIL);
// Get file information
WsbAffirmHr(GetFromDbIndex(FALSE));
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::FindNextInDbIndex"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}
HRESULT
CFsaScanItem::GetFromDbIndex(
BOOL first
)
/*
Implements:
CFsaScanItem::GetFromDbIndex().
--*/
{
HRESULT hr = S_OK;
WsbTraceIn(OLESTR("CFsaScanItem::GetFromDbIndex"), OLESTR(""));
try {
IFsaScanItem* pScanItem;
HRESULT hrFindFileId = S_OK;
LONGLONG fileId;
BOOL bCont;
WsbAssert(m_pUnmanageDb != NULL, E_FAIL);
WsbAssert(m_pUnmanageRec != NULL, E_FAIL);
do {
bCont = FALSE;
// Get first/next record
if (first) {
hr = m_pUnmanageRec->First();
} else {
hr = m_pUnmanageRec->Next();
}
WsbAffirm(S_OK == hr, WSB_E_NOTFOUND);
// Get file id
WsbAffirmHr(m_pUnmanageRec->GetFileId(&fileId));
// Reset some items in case this isn't the first call to FindFileId
// (FindFileId actually "attach" the object to a different file)
if (INVALID_HANDLE_VALUE != m_handle) {
FindClose(m_handle);
m_handle = INVALID_HANDLE_VALUE;
}
if (TRUE == m_changedAttributes) {
RestoreAttributes();
}
// Find the file from the ID
pScanItem = this;
hrFindFileId = m_pResource->FindFileId(fileId, m_pSession, &pScanItem);
// If the FindFileId failed, we just skip that item and get the
// next one. This is to keep the scan from just stopping on this
// item. FindFileId could fail because the file has been deleted
// or open exclusively by somebody else
if (!SUCCEEDED(hrFindFileId)) {
WsbTrace(OLESTR("CFsaScanItem::GetFromDbIndex: file id %I64d skipped since FindFileId failed with hr = <%ls>\n"),
fileId, WsbHrAsString(hrFindFileId));
first = FALSE;
bCont = TRUE;
}
} while (bCont);
WsbAffirmHr(pScanItem->Release()); // Get rid of extra ref. count (we get extra ref count only when FindFileId succeeds)
} WsbCatch(hr);
WsbTraceOut(OLESTR("CFsaScanItem::GetFromDbIndex"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return(hr);
}