?? fspyctx.c
字號(hào):
//
if (FlagOn(RecordList->Flags,RLFL_IS_DIRECTORY)) {
//
// We were renaming a directory, decrement the
// AllContexts temporary flag. We need to always
// do this, even on a failure
//
ASSERT(devExt->AllContextsTemporary > 0);
InterlockedDecrement( &devExt->AllContextsTemporary );
ASSERT(!FlagOn(pContext->Flags,CTXFL_DoNotUse));
} else {
//
// We were renaming a file, delete the given context
// if the operation was successful
//
ASSERT(FlagOn(pContext->Flags,CTXFL_DoNotUse));
if (NT_SUCCESS(Irp->IoStatus.Status)) {
SpyDeleteContext( deviceObject, pContext );
}
}
SpyReleaseContext( pContext );
}
}
break;
default:
//
// Validate this field isn't set for anything else
//
ASSERT(RecordList->NewContext == NULL);
break;
}
//
// Process the log record
//
if (SHOULD_LOG( deviceObject )) {
pRecordIrp = &RecordList->LogRecord.Record.RecordIrp;
//
// Record the information we use for a completion Irp.
//
pRecordIrp->ReturnStatus = Irp->IoStatus.Status;
pRecordIrp->ReturnInformation = Irp->IoStatus.Information;
KeQuerySystemTime(&pRecordIrp->CompletionTime);
//
// Add RecordList to our gOutputBufferList so that it gets up to
// the user
//
SpyLog( RecordList );
} else {
if (RecordList) {
//
// Context is set with a RECORD_LIST, but we are no longer
// logging so free this record.
//
SpyFreeRecord( RecordList );
}
}
}
VOID
SpySetName (
IN PRECORD_LIST RecordList,
IN PDEVICE_OBJECT DeviceObject,
IN PFILE_OBJECT FileObject,
IN NAME_LOOKUP_FLAGS LookupFlags,
IN PSPY_STREAM_CONTEXT Context OPTIONAL
)
/*++
Routine Description:
This routine is used to set the file name. This routine first tries to
locate a context structure associated with the given stream. If one is
found the name is used from it. If not found the name is looked up, and
a context structure is created and attached to the given stream.
In all cases some sort of name will be set.
Arguments:
RecordList - RecordList to copy name to.
LookupFlags - holds state flags for the lookup
Context - optional context parameter. If not defined one will be looked
up.
Return Value:
None.
--*/
{
PRECORD_IRP pRecordIrp = &RecordList->LogRecord.Record.RecordIrp;
PFILESPY_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
BOOLEAN releaseContext = FALSE;
PNAME_CONTROL fileName;
NTSTATUS status;
PUNICODE_STRING nameToUse;
ASSERT(IS_FILESPY_DEVICE_OBJECT( DeviceObject ));
if (!ARGUMENT_PRESENT(Context) &&
!FlagOn(LookupFlags,NLFL_NO_LOOKUP)) {
//
// If no FileObject, just return
//
if (NULL == FileObject) {
return;
}
//
// This will set the return context to NULL if no context
// could be created.
//
SpyGetContext( DeviceObject,
FileObject,
LookupFlags,
&Context );
//
// Mark that we need to release this context (since we grabbed it)
//
releaseContext = TRUE;
}
//
// If we got a context, use the name from it. If we didn't, at least
// put the device name out there
//
if (NULL != Context) {
SpyCopyFileNameToLogRecord( &RecordList->LogRecord,
&Context->Name );
} else {
SPY_LOG_PRINT( SPYDEBUG_TRACE_DETAILED_CONTEXT_OPS,
("FileSpy!SpySetName: NoCtx \"%wZ\"\n",
&devExt->NLExtHeader.DeviceName) );
status = NLAllocateNameControl( &fileName,
&gFileSpyNameBufferLookasideList );
if (NT_SUCCESS( status )) {
//
// Use the DOS device name if the proper flag is set and a DOS
// device name is available.
//
if (FlagOn( LookupFlags, NLFL_USE_DOS_DEVICE_NAME ) &&
devExt->NLExtHeader.DosName.Length != 0) {
nameToUse = &devExt->NLExtHeader.DosName;
} else {
nameToUse = &devExt->NLExtHeader.DeviceName;
}
NLCheckAndGrowNameControl( fileName,
(USHORT)(nameToUse->Length +
sizeof(L"[-=Context Not Found=-]")) );
RtlCopyUnicodeString( &fileName->Name,
nameToUse );
RtlAppendUnicodeToString( &fileName->Name,
L"[-=Context Not Found=-]" );
SpyCopyFileNameToLogRecord( &RecordList->LogRecord,
&fileName->Name );
NLFreeNameControl( fileName, &gFileSpyNameBufferLookasideList );
}
}
//
// Release the context if we grabbed it in this routine
//
if ((NULL != Context) && releaseContext) {
SpyReleaseContext( Context );
}
}
VOID
SpyNameDeleteAllNames (
VOID
)
/*++
Routine Description:
This routine will walk through all attaches volumes and delete all
contexts in each volume.
Arguments:
None
Return Value:
None
--*/
{
PLIST_ENTRY link;
PFILESPY_DEVICE_EXTENSION devExt;
ExAcquireFastMutex( &gSpyDeviceExtensionListLock );
for (link = gSpyDeviceExtensionList.Flink;
link != &gSpyDeviceExtensionList;
link = link->Flink)
{
devExt = CONTAINING_RECORD(link, FILESPY_DEVICE_EXTENSION, NextFileSpyDeviceLink);
SpyDeleteAllContexts( devExt->NLExtHeader.ThisDeviceObject );
}
ExReleaseFastMutex( &gSpyDeviceExtensionListLock );
}
///////////////////////////////////////////////////////////////////////////
//
// Context support routines
//
///////////////////////////////////////////////////////////////////////////
VOID
SpyInitDeviceNamingEnvironment (
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Initializes context information for a given device
Arguments:
DeviceObject - Device to init
Return Value:
None.
--*/
{
PFILESPY_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
PAGED_CODE();
ASSERT(IS_FILESPY_DEVICE_OBJECT(DeviceObject));
InitializeListHead( &devExt->CtxList );
ExInitializeResourceLite( &devExt->CtxLock );
SetFlag( devExt->Flags, ContextsInitialized );
}
VOID
SpyCleanupDeviceNamingEnvironment (
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Cleans up the context information for a given device
Arguments:
DeviceObject - Device to cleanup
Return Value:
None.
--*/
{
PFILESPY_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
PAGED_CODE();
ASSERT(IS_FILESPY_DEVICE_OBJECT(DeviceObject));
//
// Cleanup if initialized
//
if (FlagOn(devExt->Flags,ContextsInitialized)) {
//
// Delete all existing contexts
//
SpyDeleteAllContexts( DeviceObject );
ASSERT(IsListEmpty( &devExt->CtxList ));
//
// Release resource
//
ExDeleteResourceLite( &devExt->CtxLock );
//
// Flag not initialized
//
ClearFlag( devExt->Flags, ContextsInitialized );
}
}
VOID
SpyDeleteAllContexts (
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This will free all existing contexts for the given device
Arguments:
DeviceObject - Device to operate on
Return Value:
None.
--*/
{
PFILESPY_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
PLIST_ENTRY link;
PSPY_STREAM_CONTEXT pContext;
PFSRTL_PER_STREAM_CONTEXT ctxCtrl;
LIST_ENTRY localHead;
ULONG deleteNowCount = 0;
ULONG deleteDeferredCount = 0;
ULONG deleteInCallbackCount = 0;
PAGED_CODE();
ASSERT(IS_FILESPY_DEVICE_OBJECT(DeviceObject));
INC_STATS(TotalContextDeleteAlls);
InitializeListHead( &localHead );
try {
//
// Acquire list lock
//
SpyAcquireContextLockExclusive( devExt );
//
// Walk the list of contexts and release each one
//
while (!IsListEmpty( &devExt->CtxList )) {
//
// Unlink from top of list
//
link = RemoveHeadList( &devExt->CtxList );
pContext = CONTAINING_RECORD( link, SPY_STREAM_CONTEXT, ExtensionLink );
//
// Mark that we are unlinked from the list. We need to do this
// because of the race condition between this routine and the
// deleteCallback from the FS.
//
ASSERT(FlagOn(pContext->Flags,CTXFL_InExtensionList));
RtlInterlockedClearBitsDiscardReturn(&pContext->Flags,CTXFL_InExtensionList);
//
// Try and remove ourselves from the File Systems context control
// structure. Note that the file system could be trying to tear
// down their context control right now. If they are then we
// will get a NULL back from this call. This is OK because it
// just means that they are going to free the memory, not us.
// NOTE: This will be safe because we are holding the ContextLock
// exclusively. If this were happening then they would be
// blocked in the callback routine on this lock which
// means the file system has not freed the memory for
// this yet.
//
if (FlagOn(pContext->Flags,CTXFL_InStreamList)) {
ctxCtrl = FsRtlRemovePerStreamContext( pContext->Stream,
devExt,
NULL );
//
// Always clear the flag wether we found it in the list or
// not. We can have the flag set and not be in the list if
// after we acquired the context list lock we context swapped
// and the file system is right now in SpyDeleteContextCallback
// waiting on the list lock.
//
RtlInterlockedClearBitsDiscardReturn(&pContext->Flags,CTXFL_InStreamList);
//
// Handle wether we were still attached to the file or not.
//
if (NULL != ctxCtrl) {
ASSERT(pContext == CONTAINING_RECORD(ctxCtrl,SPY_STREAM_CONTEXT,ContextCtrl));
//
// To save time we don't do the free now (with the lock
// held). We link into a local list and then free it
// later (in this routine). We can do this because it
// is no longer on any list.
//
InsertHeadList( &localHead, &pContext->ExtensionLink );
} else {
//
// The context is in the process of being freed by the file
// system. Don't do anything with it here, it will be
// freed in the callback.
//
INC_STATS(TotalContextsNotFoundInStreamList);
INC_LOCAL_STATS(deleteInCallbackCount);
}
}
}
} finally {
SpyReleaseContextLock( devExt );
}
//
// We have removed everything from the list and released the list lock.
// Go through and figure out what entries we can free and then do it.
//
while (!IsListEmpty( &localHead )) {
//
// Get next entry of the list and get our context back
//
link = RemoveHeadList( &localHead );
pContext = CONTAINING_RECORD( link, SPY_STREAM_CONTEXT, ExtensionLink );
//
// Decrement the USE count and see if we can free it now
//
ASSERT(pContext->UseCount > 0);
if (InterlockedDecrement( &pContext->UseCount ) <= 0) {
//
// No one is using it, free it now
//
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -