981 lines
24 KiB
C
981 lines
24 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1998-1999 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
lookup.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
this is the sr lookup functionlity implementation
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Kanwaljit Marok (kmarok) 01-May-2000
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
//
|
||
|
// Include hlist.c to use the inline funtions
|
||
|
//
|
||
|
|
||
|
#include "hlist.c"
|
||
|
#include "ptree.c"
|
||
|
|
||
|
//
|
||
|
// Internal helper APIs
|
||
|
//
|
||
|
|
||
|
static
|
||
|
NTSTATUS
|
||
|
SrOpenLookupBlob(
|
||
|
IN PUNICODE_STRING pFileName,
|
||
|
IN PDEVICE_OBJECT pTargetDevice,
|
||
|
OUT PBLOB_INFO pBlobInfo
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// linker commands
|
||
|
//
|
||
|
|
||
|
#ifdef ALLOC_PRAGMA
|
||
|
|
||
|
#pragma alloc_text( PAGE, SrOpenLookupBlob )
|
||
|
#pragma alloc_text( PAGE, SrLoadLookupBlob )
|
||
|
#pragma alloc_text( PAGE, SrReloadLookupBlob )
|
||
|
#pragma alloc_text( PAGE, SrFreeLookupBlob )
|
||
|
#pragma alloc_text( PAGE, SrIsExtInteresting )
|
||
|
#pragma alloc_text( PAGE, SrIsPathInteresting )
|
||
|
|
||
|
#endif // ALLOC_PRAGMA
|
||
|
|
||
|
//++
|
||
|
// Function:
|
||
|
// SrOpenLookupBlob
|
||
|
//
|
||
|
// Description:
|
||
|
// This function loads the lookup blob in memory and
|
||
|
// sets the appropriate pointers for lookup.
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
// This function returns STATUS_XXX
|
||
|
//--
|
||
|
|
||
|
static
|
||
|
NTSTATUS
|
||
|
SrOpenLookupBlob(
|
||
|
IN PUNICODE_STRING pFileName,
|
||
|
IN PDEVICE_OBJECT pTargetDevice,
|
||
|
OUT PBLOB_INFO pBlobInfo
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
OBJECT_ATTRIBUTES oa;
|
||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||
|
HANDLE Handle = NULL;
|
||
|
PLIST_ENTRY pListEntry;
|
||
|
PSR_DEVICE_EXTENSION pExtension;
|
||
|
static char blobFailureMessage[] = "sr!System Restore's BLOB file \"%wZ\" is invalid.\n";
|
||
|
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ASSERT(pFileName);
|
||
|
ASSERT(pBlobInfo);
|
||
|
|
||
|
ASSERT( IS_BLOB_LOCK_ACQUIRED() );
|
||
|
|
||
|
try
|
||
|
{
|
||
|
//
|
||
|
// Zero out the pointers that get initialized when the
|
||
|
// blob is successfully read into the memory from disk
|
||
|
//
|
||
|
|
||
|
pBlobInfo->LookupBlob = NULL;
|
||
|
pBlobInfo->LookupTree = NULL;
|
||
|
pBlobInfo->LookupList = NULL;
|
||
|
pBlobInfo->DefaultType= NODE_TYPE_UNKNOWN;
|
||
|
|
||
|
//
|
||
|
// open and read the file
|
||
|
//
|
||
|
|
||
|
InitializeObjectAttributes( &oa,
|
||
|
pFileName,
|
||
|
OBJ_KERNEL_HANDLE,
|
||
|
NULL,
|
||
|
NULL );
|
||
|
|
||
|
Status = SrIoCreateFile(
|
||
|
&Handle,
|
||
|
GENERIC_READ | SYNCHRONIZE,
|
||
|
&oa,
|
||
|
&IoStatusBlock,
|
||
|
0,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
FILE_SHARE_READ,
|
||
|
FILE_OPEN,
|
||
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
||
|
NULL,
|
||
|
0,
|
||
|
0,
|
||
|
pTargetDevice );
|
||
|
|
||
|
if (NT_SUCCESS(Status))
|
||
|
{
|
||
|
DWORD dwBytesRead = 0, dwBytes = 0;
|
||
|
LARGE_INTEGER nOffset;
|
||
|
BlobHeader blobHeader;
|
||
|
|
||
|
//
|
||
|
// Read the blob header
|
||
|
//
|
||
|
|
||
|
nOffset.QuadPart = 0;
|
||
|
dwBytes = sizeof(blobHeader);
|
||
|
|
||
|
Status = ZwReadFile(
|
||
|
Handle,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&IoStatusBlock,
|
||
|
&blobHeader,
|
||
|
dwBytes,
|
||
|
&nOffset,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (NT_SUCCESS(Status))
|
||
|
{
|
||
|
//
|
||
|
// need to do some sanity check on the header
|
||
|
//
|
||
|
|
||
|
if ( !VERIFY_BLOB_VERSION(&blobHeader) ||
|
||
|
!VERIFY_BLOB_MAGIC (&blobHeader) )
|
||
|
{
|
||
|
SrTrace( BLOB_VERIFICATION, (blobFailureMessage, pFileName) );
|
||
|
|
||
|
Status = STATUS_FILE_CORRUPT_ERROR;
|
||
|
leave;
|
||
|
}
|
||
|
|
||
|
pBlobInfo->LookupBlob = SR_ALLOCATE_POOL(
|
||
|
NonPagedPool,
|
||
|
blobHeader.m_dwMaxSize,
|
||
|
SR_LOOKUP_TABLE_TAG );
|
||
|
|
||
|
if( pBlobInfo->LookupBlob )
|
||
|
{
|
||
|
//
|
||
|
// Read the entire file now
|
||
|
//
|
||
|
|
||
|
nOffset.QuadPart = 0;
|
||
|
dwBytes = blobHeader.m_dwMaxSize;
|
||
|
|
||
|
Status = ZwReadFile(
|
||
|
Handle,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&IoStatusBlock,
|
||
|
pBlobInfo->LookupBlob,
|
||
|
dwBytes,
|
||
|
&nOffset,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (NT_SUCCESS(Status))
|
||
|
{
|
||
|
//
|
||
|
// TODO: verify that size of the file matched the
|
||
|
// size from the header
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Setup the lookup pointers properly in blobinfo
|
||
|
//
|
||
|
|
||
|
pBlobInfo->LookupTree = pBlobInfo->LookupBlob +
|
||
|
sizeof(blobHeader);
|
||
|
|
||
|
pBlobInfo->LookupList = pBlobInfo->LookupTree +
|
||
|
BLOB_MAXSIZE((pBlobInfo->LookupTree));
|
||
|
|
||
|
pBlobInfo->DefaultType = TREE_HEADER((pBlobInfo->LookupTree))->m_dwDefault;
|
||
|
|
||
|
//
|
||
|
// Verify the individual blobs
|
||
|
//
|
||
|
|
||
|
if (!SrVerifyBlob(pBlobInfo->LookupBlob)) {
|
||
|
|
||
|
SrTrace( BLOB_VERIFICATION,
|
||
|
(blobFailureMessage,pFileName) );
|
||
|
Status = STATUS_FILE_CORRUPT_ERROR;
|
||
|
leave;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SrTrace( VERBOSE_ERRORS,
|
||
|
("sr!SrOpenLookupBlob: Cannot Open Blob file \"%wZ\"\n",
|
||
|
pFileName) );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The new blob was loaded successfully, perge all contexts on all
|
||
|
// volumes since what is interesting and what is not interesting
|
||
|
// may have changed.
|
||
|
//
|
||
|
|
||
|
ASSERT(!IS_DEVICE_EXTENSION_LIST_LOCK_ACQUIRED());
|
||
|
|
||
|
try
|
||
|
{
|
||
|
SrAcquireDeviceExtensionListLockShared();
|
||
|
|
||
|
for (pListEntry = _globals.DeviceExtensionListHead.Flink;
|
||
|
pListEntry != &_globals.DeviceExtensionListHead;
|
||
|
pListEntry = pListEntry->Flink)
|
||
|
{
|
||
|
pExtension = CONTAINING_RECORD( pListEntry,
|
||
|
SR_DEVICE_EXTENSION,
|
||
|
ListEntry );
|
||
|
|
||
|
ASSERT(IS_VALID_SR_DEVICE_EXTENSION(pExtension));
|
||
|
|
||
|
//
|
||
|
// Skip Control Device Objects.
|
||
|
//
|
||
|
|
||
|
if (!FlagOn(pExtension->FsType,SrFsControlDeviceObject))
|
||
|
{
|
||
|
SrDeleteAllContexts( pExtension );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
SrReleaseDeviceExtensionListLock();
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
Status = FinallyUnwind(SrOpenLookupBlob, Status);
|
||
|
|
||
|
//
|
||
|
// close the blob file handle
|
||
|
//
|
||
|
|
||
|
if (Handle)
|
||
|
{
|
||
|
ZwClose( Handle );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// incase of a failure free up the resources
|
||
|
//
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
if( pBlobInfo->LookupBlob )
|
||
|
{
|
||
|
SR_FREE_POOL( pBlobInfo->LookupBlob, SR_LOOKUP_TABLE_TAG );
|
||
|
}
|
||
|
|
||
|
pBlobInfo->LookupBlob = NULL;
|
||
|
pBlobInfo->LookupTree = NULL;
|
||
|
pBlobInfo->LookupList = NULL;
|
||
|
pBlobInfo->DefaultType= NODE_TYPE_UNKNOWN;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RETURN(Status);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Public APIs called by the filer
|
||
|
//
|
||
|
|
||
|
//++
|
||
|
// Function:
|
||
|
// SrLoadLookupBlob
|
||
|
//
|
||
|
// Description:
|
||
|
// This function loads the lookup blob in memory and
|
||
|
// sets the appropriate pointers for lookup.
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
// This function returns STATUS_XXX
|
||
|
//--
|
||
|
|
||
|
NTSTATUS
|
||
|
SrLoadLookupBlob(
|
||
|
IN PUNICODE_STRING pFileName,
|
||
|
IN PDEVICE_OBJECT pTargetDevice,
|
||
|
OUT PBLOB_INFO pBlobInfo
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ASSERT( pFileName );
|
||
|
ASSERT( pBlobInfo );
|
||
|
|
||
|
try
|
||
|
{
|
||
|
SrAcquireBlobLockExclusive();
|
||
|
|
||
|
//
|
||
|
// if somebody else did it, bail out
|
||
|
//
|
||
|
|
||
|
if (global->BlobInfoLoaded)
|
||
|
{
|
||
|
Status = STATUS_SUCCESS;
|
||
|
leave;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// initialize return information
|
||
|
//
|
||
|
|
||
|
RtlZeroMemory( pBlobInfo, sizeof( BLOB_INFO ) );
|
||
|
|
||
|
//
|
||
|
// Try and open the lookup blob
|
||
|
//
|
||
|
|
||
|
Status = SrOpenLookupBlob( pFileName,
|
||
|
pTargetDevice,
|
||
|
pBlobInfo );
|
||
|
|
||
|
//
|
||
|
// If we failed to read the file for some reason,
|
||
|
// reinitlialize the return info
|
||
|
//
|
||
|
|
||
|
if ( NT_SUCCESS( Status ) )
|
||
|
{
|
||
|
SrTrace(LOOKUP, ("Loaded lookup blob :%wZ\n", pFileName) );
|
||
|
global->BlobInfoLoaded = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SrFreeLookupBlob( pBlobInfo );
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
SrReleaseBlobLock();
|
||
|
}
|
||
|
|
||
|
RETURN(Status);
|
||
|
}
|
||
|
|
||
|
//++
|
||
|
// Function:
|
||
|
// SrReloadLookupBlob
|
||
|
//
|
||
|
// Description:
|
||
|
// This function loads the lookup blob in memory and
|
||
|
// sets the appropriate pointers for lookup.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// Pointer to LookupBlob
|
||
|
// Pointer to BlobInfo structure
|
||
|
//
|
||
|
// Return Value:
|
||
|
// This function returns STATUS_XXX
|
||
|
//--
|
||
|
|
||
|
NTSTATUS
|
||
|
SrReloadLookupBlob(
|
||
|
IN PUNICODE_STRING pFileName,
|
||
|
IN PDEVICE_OBJECT pTargetDevice,
|
||
|
OUT PBLOB_INFO pBlobInfo
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||
|
BLOB_INFO OldBlobInfo;
|
||
|
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ASSERT( pFileName != NULL );
|
||
|
ASSERT( pBlobInfo != NULL );
|
||
|
|
||
|
ASSERT( !IS_BLOB_LOCK_ACQUIRED() );
|
||
|
|
||
|
try
|
||
|
{
|
||
|
SrAcquireBlobLockExclusive();
|
||
|
|
||
|
if (global->BlobInfoLoaded == 0)
|
||
|
{
|
||
|
Status = SrLoadLookupBlob( pFileName,
|
||
|
pTargetDevice,
|
||
|
pBlobInfo );
|
||
|
leave;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Save the current blob info
|
||
|
//
|
||
|
|
||
|
RtlCopyMemory( &OldBlobInfo, pBlobInfo, sizeof( BLOB_INFO ) );
|
||
|
|
||
|
//
|
||
|
// Open the new blob file
|
||
|
//
|
||
|
|
||
|
Status = SrOpenLookupBlob( pFileName,
|
||
|
pTargetDevice,
|
||
|
pBlobInfo );
|
||
|
|
||
|
if(NT_SUCCESS(Status))
|
||
|
{
|
||
|
//
|
||
|
// Free up the memory taken up by the old blob
|
||
|
//
|
||
|
|
||
|
if (OldBlobInfo.LookupBlob)
|
||
|
{
|
||
|
SR_FREE_POOL( OldBlobInfo.LookupBlob, SR_LOOKUP_TABLE_TAG );
|
||
|
}
|
||
|
|
||
|
SrTrace(LOOKUP, ("Reloaded lookup blob :%wZ\n", pFileName) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Copy the old information back in the original context
|
||
|
//
|
||
|
|
||
|
RtlCopyMemory( pBlobInfo, &OldBlobInfo, sizeof( BLOB_INFO ) );
|
||
|
|
||
|
SrTrace(LOOKUP, (" Cannot reload blob :%wZ\n", pFileName) );
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
if (NT_SUCCESS_NO_DBGBREAK( Status ))
|
||
|
{
|
||
|
//
|
||
|
// The blob has been reload successfully, so make sure that the
|
||
|
// global BlobError flag is cleared.
|
||
|
//
|
||
|
// We do this here because we are still holding the blob lock.
|
||
|
//
|
||
|
|
||
|
_globals.HitErrorLoadingBlob = FALSE;
|
||
|
}
|
||
|
|
||
|
SrReleaseBlobLock();
|
||
|
}
|
||
|
|
||
|
RETURN(Status);
|
||
|
}
|
||
|
|
||
|
|
||
|
//++
|
||
|
// Function:
|
||
|
// SrFreeLookupBlob
|
||
|
//
|
||
|
// Description:
|
||
|
// This function Frees the lookup blob in memory
|
||
|
//
|
||
|
// Arguments:
|
||
|
// Pointer to BlobInfo structure
|
||
|
//
|
||
|
// Return Value:
|
||
|
// This function returns STATUS_XXX
|
||
|
//--
|
||
|
|
||
|
NTSTATUS
|
||
|
SrFreeLookupBlob(
|
||
|
IN PBLOB_INFO pBlobInfo
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ASSERT( pBlobInfo );
|
||
|
|
||
|
try
|
||
|
{
|
||
|
SrAcquireBlobLockExclusive();
|
||
|
|
||
|
if (_globals.BlobInfoLoaded == 0)
|
||
|
{
|
||
|
//
|
||
|
// Reset our error flag here.
|
||
|
//
|
||
|
|
||
|
_globals.HitErrorLoadingBlob = FALSE;
|
||
|
leave;
|
||
|
}
|
||
|
|
||
|
if( pBlobInfo->LookupBlob )
|
||
|
{
|
||
|
SR_FREE_POOL( pBlobInfo->LookupBlob, SR_LOOKUP_TABLE_TAG );
|
||
|
pBlobInfo->LookupBlob = NULL;
|
||
|
}
|
||
|
|
||
|
RtlZeroMemory( pBlobInfo, sizeof(BLOB_INFO) );
|
||
|
pBlobInfo->DefaultType = NODE_TYPE_UNKNOWN;
|
||
|
|
||
|
SrTrace(LOOKUP, ("Freed lookup blob\n") );
|
||
|
|
||
|
global->BlobInfoLoaded = 0;
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
SrReleaseBlobLock();
|
||
|
}
|
||
|
|
||
|
RETURN(Status);
|
||
|
}
|
||
|
|
||
|
|
||
|
//++
|
||
|
// Function:
|
||
|
// SrIsExtInteresting
|
||
|
//
|
||
|
// Description:
|
||
|
// This function checks the file extension in the blob to
|
||
|
// see if we care about it
|
||
|
//
|
||
|
// Arguments:
|
||
|
// Pointer to BlobInfo structure
|
||
|
// Pointer to Path
|
||
|
// Pointer to boolean return value
|
||
|
//
|
||
|
// Return Value:
|
||
|
// This function returns TRUE/FALSE
|
||
|
//--
|
||
|
|
||
|
NTSTATUS
|
||
|
SrIsExtInteresting(
|
||
|
IN PUNICODE_STRING pFileName,
|
||
|
OUT PBOOLEAN pInteresting
|
||
|
)
|
||
|
{
|
||
|
BOOL fRet = FALSE;
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
INT iType = 0;
|
||
|
BOOL fPathHasExt = FALSE;
|
||
|
BOOL fMatch = FALSE;
|
||
|
|
||
|
PAGED_CODE();
|
||
|
|
||
|
//
|
||
|
// check parameters and lookup info
|
||
|
//
|
||
|
|
||
|
ASSERT(pFileName);
|
||
|
ASSERT(pInteresting);
|
||
|
|
||
|
//
|
||
|
// Lookup code is enclosed in an exception handler to protect against
|
||
|
// bad memroy accesses generated by corrupt lookup data
|
||
|
//
|
||
|
|
||
|
try
|
||
|
{
|
||
|
|
||
|
*pInteresting = FALSE;
|
||
|
|
||
|
//
|
||
|
// CODEWORK : put some blob verification code,
|
||
|
// magicnum, type etc
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Take the blob lock so that other threads won't change
|
||
|
// the blob while we are looking up. Note that the blob
|
||
|
// can be gone after we get the lock.
|
||
|
//
|
||
|
|
||
|
SrAcquireBlobLockShared();
|
||
|
|
||
|
if ( !global->BlobInfoLoaded ||
|
||
|
!global->BlobInfo.LookupList )
|
||
|
{
|
||
|
Status = SR_STATUS_VOLUME_DISABLED;
|
||
|
leave;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// parse the filename for lookup in the mem blob
|
||
|
//
|
||
|
|
||
|
fMatch = MatchExtension(
|
||
|
global->BlobInfo.LookupList,
|
||
|
pFileName,
|
||
|
&iType,
|
||
|
&fPathHasExt );
|
||
|
|
||
|
if ( !fMatch )
|
||
|
{
|
||
|
//
|
||
|
// Extension didn't match, so setting to default type
|
||
|
//
|
||
|
|
||
|
iType = global->BlobInfo.DefaultType;
|
||
|
}
|
||
|
|
||
|
if ( !fPathHasExt )
|
||
|
{
|
||
|
//
|
||
|
// If the path didn't contain an extension then we should
|
||
|
// treat it as an exclude
|
||
|
//
|
||
|
|
||
|
iType = NODE_TYPE_EXCLUDE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If type is still unknown then set the type to the default.
|
||
|
//
|
||
|
|
||
|
if ( NODE_TYPE_UNKNOWN == iType )
|
||
|
{
|
||
|
iType = global->BlobInfo.DefaultType;
|
||
|
}
|
||
|
|
||
|
*pInteresting = (iType != NODE_TYPE_EXCLUDE);
|
||
|
|
||
|
// SrTrace(LOOKUP, ("Extention Interest:%d\n", *pInteresting) );
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
Status = FinallyUnwind(SrIsExtInteresting, Status);
|
||
|
|
||
|
SrReleaseBlobLock();
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
*pInteresting = FALSE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
RETURN(Status);
|
||
|
}
|
||
|
|
||
|
|
||
|
//++
|
||
|
// Function:
|
||
|
// SrIsPathInteresting
|
||
|
//
|
||
|
// Description:
|
||
|
// This function checks the file name in the blob to
|
||
|
// see if we care about it
|
||
|
//
|
||
|
// Arguments:
|
||
|
// Pointer to BlobInfo structure
|
||
|
// Pointer to Full Path
|
||
|
// Pointer to Volume Prefix
|
||
|
// Boolean to indicate if this path is a directory
|
||
|
// Pointer to boolean return value
|
||
|
//
|
||
|
// Return Value:
|
||
|
// This function returns TRUE/FALSE
|
||
|
//--
|
||
|
|
||
|
NTSTATUS
|
||
|
SrIsPathInteresting(
|
||
|
IN PUNICODE_STRING pFullPath,
|
||
|
IN PUNICODE_STRING pVolPrefix,
|
||
|
IN BOOLEAN IsDirectory,
|
||
|
OUT PBOOLEAN pInteresting
|
||
|
)
|
||
|
{
|
||
|
BOOL fRet = FALSE;
|
||
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||
|
PBYTE pFileName = NULL;
|
||
|
WORD FileNameSize = 0;
|
||
|
UNICODE_STRING localName;
|
||
|
|
||
|
PAGED_CODE();
|
||
|
|
||
|
//
|
||
|
// check parameters and lookup info
|
||
|
//
|
||
|
|
||
|
ASSERT(pFullPath);
|
||
|
ASSERT(pVolPrefix);
|
||
|
ASSERT(pFullPath->Length >= pVolPrefix->Length);
|
||
|
ASSERT(pInteresting);
|
||
|
|
||
|
try
|
||
|
{
|
||
|
*pInteresting = FALSE;
|
||
|
|
||
|
//
|
||
|
// Take the blob lock so that other threads won't change
|
||
|
//
|
||
|
|
||
|
SrAcquireBlobLockShared();
|
||
|
|
||
|
if ( !global->BlobInfoLoaded ||
|
||
|
!global->BlobInfo.LookupList ||
|
||
|
!global->BlobInfo.LookupTree )
|
||
|
{
|
||
|
Status = SR_STATUS_VOLUME_DISABLED;
|
||
|
leave;
|
||
|
}
|
||
|
|
||
|
ASSERT(global->BlobInfo.DefaultType != NODE_TYPE_UNKNOWN );
|
||
|
|
||
|
//
|
||
|
// allocate space for a parsed path
|
||
|
//
|
||
|
|
||
|
FileNameSize = CALC_PPATH_SIZE( pFullPath->Length/sizeof(WCHAR) );
|
||
|
pFileName = ExAllocatePoolWithTag( PagedPool,
|
||
|
FileNameSize,
|
||
|
SR_FILENAME_BUFFER_TAG );
|
||
|
|
||
|
if (NULL == pFileName)
|
||
|
{
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
leave;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// parse the filename for lookup in the mem blob
|
||
|
//
|
||
|
|
||
|
fRet = ConvertToParsedPath(
|
||
|
pFullPath->Buffer,
|
||
|
pFullPath->Length/sizeof(WCHAR),
|
||
|
pFileName,
|
||
|
FileNameSize );
|
||
|
|
||
|
if(fRet)
|
||
|
{
|
||
|
INT iNode = -1;
|
||
|
INT iType = 0;
|
||
|
INT iLevel = 0;
|
||
|
BOOL fExactMatch = FALSE;
|
||
|
BOOL fMatch = FALSE;
|
||
|
|
||
|
//
|
||
|
// Lookup the parsed path in the tree blob
|
||
|
//
|
||
|
|
||
|
fMatch = MatchPrefix(
|
||
|
global->BlobInfo.LookupTree,
|
||
|
TREE_ROOT_NODE,
|
||
|
((path_t)pFileName)->pp_elements,
|
||
|
&iNode,
|
||
|
&iLevel,
|
||
|
&iType,
|
||
|
NULL,
|
||
|
&fExactMatch);
|
||
|
|
||
|
if (fMatch)
|
||
|
{
|
||
|
SrTrace(LOOKUP,
|
||
|
("Found match in pathtree N: %d L:%d T:%d\n",
|
||
|
iNode, iLevel, iType));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Lookup in __ALLVOLUMES__ to see is there is a match
|
||
|
//
|
||
|
|
||
|
if ( NODE_TYPE_UNKNOWN == iType ||
|
||
|
(!fExactMatch && NODE_TYPE_EXCLUDE != iType )
|
||
|
)
|
||
|
{
|
||
|
PBYTE pRelFileName = NULL;
|
||
|
INT RelFileNameLen = 0;
|
||
|
|
||
|
//
|
||
|
// Lookup only volume relative filename
|
||
|
//
|
||
|
|
||
|
RelFileNameLen = sizeof(L'\\' ) +
|
||
|
sizeof(ALLVOLUMES_PATH_W) +
|
||
|
(pFullPath->Length - pVolPrefix->Length);
|
||
|
|
||
|
pRelFileName = ExAllocatePoolWithTag( PagedPool,
|
||
|
RelFileNameLen,
|
||
|
SR_FILENAME_BUFFER_TAG );
|
||
|
|
||
|
if (NULL == pRelFileName)
|
||
|
{
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
leave;
|
||
|
}
|
||
|
|
||
|
localName.Buffer = &pFullPath->Buffer[pVolPrefix->Length/sizeof(WCHAR)];
|
||
|
localName.Length = pFullPath->Length - pVolPrefix->Length;
|
||
|
localName.MaximumLength = localName.Length;
|
||
|
|
||
|
RelFileNameLen = swprintf(
|
||
|
(LPWSTR)pRelFileName,
|
||
|
L"\\%s%wZ",
|
||
|
ALLVOLUMES_PATH_W,
|
||
|
&localName );
|
||
|
|
||
|
fRet = ConvertToParsedPath(
|
||
|
(LPWSTR)pRelFileName,
|
||
|
(USHORT)RelFileNameLen,
|
||
|
pFileName,
|
||
|
FileNameSize );
|
||
|
|
||
|
if(fRet)
|
||
|
{
|
||
|
//
|
||
|
// Lookup the parsed path in the appropriate protion of
|
||
|
// the tree blob NTROOT\\__ALLVOLUMES__
|
||
|
//
|
||
|
|
||
|
fMatch = MatchPrefix(
|
||
|
global->BlobInfo.LookupTree,
|
||
|
TREE_ROOT_NODE,
|
||
|
((path_t)pFileName)->pp_elements,
|
||
|
&iNode,
|
||
|
&iLevel,
|
||
|
&iType,
|
||
|
NULL,
|
||
|
&fExactMatch);
|
||
|
|
||
|
if (fMatch)
|
||
|
{
|
||
|
SrTrace(LOOKUP,
|
||
|
("Found match in pathtree N: %d L:%d T:%d\n",
|
||
|
iNode, iLevel, iType));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CHECK_STATUS( Status );
|
||
|
}
|
||
|
|
||
|
ExFreePoolWithTag( pRelFileName, SR_FILENAME_BUFFER_TAG );
|
||
|
NULLPTR( pRelFileName );
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( !IsDirectory )
|
||
|
{
|
||
|
//
|
||
|
// If path didn't match or matched partially, we need to
|
||
|
// lookup the extension list also
|
||
|
//
|
||
|
|
||
|
if ( NODE_TYPE_UNKNOWN == iType ||
|
||
|
(!fExactMatch && NODE_TYPE_EXCLUDE != iType )
|
||
|
)
|
||
|
{
|
||
|
BOOL fPathHasExt = FALSE;
|
||
|
|
||
|
fMatch = MatchExtension(
|
||
|
global->BlobInfo.LookupList,
|
||
|
pFullPath,
|
||
|
&iType,
|
||
|
&fPathHasExt );
|
||
|
|
||
|
if ( !fMatch )
|
||
|
{
|
||
|
//
|
||
|
// Extension didn't match, setting to default type
|
||
|
//
|
||
|
|
||
|
iType = global->BlobInfo.DefaultType;
|
||
|
}
|
||
|
|
||
|
if ( !fPathHasExt )
|
||
|
{
|
||
|
//
|
||
|
// If path didn't contain an extension then
|
||
|
// treat it as an exclude
|
||
|
//
|
||
|
|
||
|
iType = NODE_TYPE_EXCLUDE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If still type is unknown then set type to the default.
|
||
|
//
|
||
|
|
||
|
if ( NODE_TYPE_UNKNOWN == iType )
|
||
|
{
|
||
|
iType = global->BlobInfo.DefaultType;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// If this is directory operation and no match found in
|
||
|
// tree then treat is as include.
|
||
|
//
|
||
|
|
||
|
if ( NODE_TYPE_UNKNOWN == iType )
|
||
|
{
|
||
|
iType = NODE_TYPE_INCLUDE;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*pInteresting = (iType != NODE_TYPE_EXCLUDE);
|
||
|
Status = STATUS_SUCCESS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SrTrace( LOOKUP,
|
||
|
( "ConvertToParsedPath Failed : %wZ\n", pFullPath )
|
||
|
);
|
||
|
CHECK_STATUS( Status );
|
||
|
}
|
||
|
|
||
|
// SrTrace(LOOKUP, ("Path Interest:%d\n", *pInteresting) );
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
Status = FinallyUnwind(SrIsPathInteresting, Status);
|
||
|
|
||
|
SrReleaseBlobLock();
|
||
|
|
||
|
if (pFileName != NULL)
|
||
|
{
|
||
|
ExFreePoolWithTag( pFileName, SR_FILENAME_BUFFER_TAG );
|
||
|
NULLPTR( pFileName );;
|
||
|
}
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
*pInteresting = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RETURN(Status);
|
||
|
}
|