⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fspyctx.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 4 页
字号:

                    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
            //

            SpyFreeContext( pContext );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -