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

📄 fspyctx.c

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

Routine Description:

    Allocate and initialize a context structure including retrieving the name.

Arguments:

    DeviceObject - Device to operate on

    FileObject - The stream the context is being created for

    LookupFlags - Flag telling how to do this create

    pRetContext - Receives the created context

Return Value:

    Status of the operation

--*/
{
    PFILESPY_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
    PSPY_STREAM_CONTEXT ctx;
    ULONG contextSize;
    PNAME_CONTROL fileName = NULL;
    BOOLEAN cacheName;
    NTSTATUS status;

    PAGED_CODE();
    ASSERT(IS_FILESPY_DEVICE_OBJECT(DeviceObject));

    //
    //  Setup locals
    //

    *pRetContext = NULL;

    //
    //  Get the filename string
    //

    status = NLAllocateNameControl( &fileName, &gFileSpyNameBufferLookasideList );

    if (!NT_SUCCESS( status )) {

        return status;
    }

    status = NLGetFullPathName( FileObject,
                                fileName,
                                &devExt->NLExtHeader,
                                LookupFlags | NLFL_USE_DOS_DEVICE_NAME,
                                &gFileSpyNameBufferLookasideList,
                                &cacheName );

    if (!NT_SUCCESS( status )) {

        NLFreeNameControl( fileName, &gFileSpyNameBufferLookasideList );
        return status;
    }

    //
    //  Allocate the context structure with space for the name
    //  added to the end.
    //

    contextSize = sizeof(SPY_STREAM_CONTEXT);

    contextSize += fileName->Name.Length;

    ctx = ExAllocatePoolWithTag( NonPagedPool,
                                 contextSize,
                                 FILESPY_CONTEXT_TAG );

    if (!ctx) {

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    //  Init the context structure
    //

    RtlZeroMemory( ctx, sizeof(SPY_STREAM_CONTEXT) );
    ctx->UseCount = 1;

    //
    //  Insert the file name
    //

    RtlInitEmptyUnicodeString( &ctx->Name,
                               (PWCHAR)(ctx + 1),
                               (USHORT)(contextSize -
                                        sizeof(SPY_STREAM_CONTEXT)) );

    RtlCopyUnicodeString( &ctx->Name, &fileName->Name );

    //
    //  If they don't want to keep this context, mark it temporary
    //

    if (!cacheName) {

        SetFlag(ctx->Flags, CTXFL_Temporary);
        INC_STATS(TotalContextTemporary);
    }

    //
    //  Return the object context
    //

    INC_STATS(TotalContextCreated);
    *pRetContext = ctx;

    //
    //  Cleanup the local NameControl structure
    //

    NLFreeNameControl( fileName, &gFileSpyNameBufferLookasideList );

    return STATUS_SUCCESS;
}


NTSTATUS
SpyGetContext (
    IN PDEVICE_OBJECT DeviceObject,
    IN PFILE_OBJECT FileObject,
    IN NAME_LOOKUP_FLAGS LookupFlags,
    OUT PSPY_STREAM_CONTEXT *pRetContext
    )
/*++

Routine Description:

    This will see if a given context already exists.  If not it will create
    one and return it.  Note:  the return context pointer is NULL on a
    failure.

    This will also see if all contexts are to be temporary (global flag in
    the extension).  If so, a temporary context is always created.  It also
    sees if the found context is marked temporary (because it is being
    renamed).  If so, a temporary context is also created and returned.

Arguments:

    DeviceObject - Device to operate on

    FileObject - The stream the context is being looked up/created for

    LookupFlags - State flags incase a context is created

    pRetContext - Receives the found/created context

Return Value:

    Status of the operation

--*/
{
    PFILESPY_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
    PSPY_STREAM_CONTEXT pContext;
    PFSRTL_PER_STREAM_CONTEXT ctxCtrl;
    NTSTATUS status;
    BOOLEAN makeTemporary = FALSE;

    ASSERT(IS_FILESPY_DEVICE_OBJECT(DeviceObject));

    //
    //  Bump total search count
    //

    INC_STATS(TotalContextSearches);

    //
    //  See if the all-contexts-temporary state is on.  If not then do
    //  the normal search.
    //

    if (devExt->AllContextsTemporary != 0) {

        //
        //  Mark that we want this context to be temporary
        //

        makeTemporary = TRUE;

    } else {

        //
        //                      NOT-TEMPORARY
        //  Try and locate the context structure.  We acquire the list lock
        //  so that we can guarantee that the context will not go away between
        //  the time when we find it and can increment the use count
        //

        SpyAcquireContextLockShared( devExt );

        ctxCtrl = FsRtlLookupPerStreamContext( FsRtlGetPerStreamContextPointer(FileObject),
                                               devExt,
                                               NULL );

        if (NULL != ctxCtrl) {

            //
            //  A context was attached to the given stream
            //

            pContext = CONTAINING_RECORD( ctxCtrl,
                                          SPY_STREAM_CONTEXT,
                                          ContextCtrl );

            ASSERT(pContext->Stream == FsRtlGetPerStreamContextPointer(FileObject));
            ASSERT(FlagOn(pContext->Flags,CTXFL_InExtensionList));
            ASSERT(!FlagOn(pContext->Flags,CTXFL_Temporary));
            ASSERT(pContext->UseCount > 0);

            //
            //  See if this is marked that we should not use it (happens when a
            //  file is being renamed).
            //

            if (FlagOn(pContext->Flags,CTXFL_DoNotUse)) {

                //
                //  We should not use this context, unlock and set flag so we
                //  will create a temporary context.
                //

                SpyReleaseContextLock( devExt );
                makeTemporary = TRUE;

            } else {

                //
                //  We want this context so bump the use count and release
                //  the lock
                //

                InterlockedIncrement( &pContext->UseCount );

                SpyReleaseContextLock( devExt );
                INC_STATS(TotalContextFound);

                SPY_LOG_PRINT( SPYDEBUG_TRACE_CONTEXT_OPS,
                               ("FileSpy!SpyGetContext:         Found:      (%p) Fl=%02x Use=%d \"%wZ\"\n",
                                pContext,
                                pContext->Flags,
                                pContext->UseCount,
                                &pContext->Name) );

                //
                //  Return the found context
                //

                *pRetContext = pContext;
                return STATUS_SUCCESS;
            }

        } else {

            //
            //  We didn't find a context, release the lock
            //

            SpyReleaseContextLock( devExt );
        }
    }

    //
    //  For whatever reason, we did not find a context.
    //  See if contexts are supported for this particular file.  Note that
    //  NTFS does not presently support contexts on paging files.
    //

    if (!FsRtlSupportsPerStreamContexts(FileObject)) {

        INC_STATS(TotalContextsNotSupported);
        *pRetContext = NULL;
        return STATUS_NOT_SUPPORTED;
    }

    //
    //  If we get here we need to create a context, do it
    //

    status = SpyCreateContext( DeviceObject,
                               FileObject,
                               LookupFlags,
                               &pContext );

    if (!NT_SUCCESS( status )) {

        *pRetContext = NULL;
        return status;
    }

    //
    //  Mark context temporary (if requested)
    //

    if (makeTemporary) {

        SetFlag(pContext->Flags,CTXFL_Temporary);

        INC_STATS(TotalContextTemporary);

        SPY_LOG_PRINT( SPYDEBUG_TRACE_CONTEXT_OPS,
                       ("FileSpy!SpyGetContext:         RenAllTmp:  (%p) Fl=%02x Use=%d \"%wZ\"\n",
                        pContext,
                        pContext->Flags,
                        pContext->UseCount,
                        &pContext->Name) );

    } else {

        //
        //  Insert the context into the linked list.  Note that the
        //  link routine will see if this entry has already been added to
        //  the list (could happen while we were building it).  If so it
        //  will release the one we created and use the one it found in
        //  the list.  It will return the new entry (if it was changed).
        //  The link routine properly handles temporary contexts.
        //

        SpyLinkContext( DeviceObject,
                        FileObject,
                        &pContext );
    }

    SPY_LOG_PRINT( SPYDEBUG_TRACE_CONTEXT_OPS,
                   ("FileSpy!SrGetContext:          Created%s (%p) Fl=%02x Use=%d \"%wZ\"\n",
                    (FlagOn(pContext->Flags,CTXFL_Temporary) ? "Tmp:" : ":   "),
                    pContext,
                    pContext->Flags,
                    pContext->UseCount,
                    &pContext->Name) );

    //
    //  Return the context
    //

    ASSERT(pContext->UseCount > 0);

    *pRetContext = pContext;
    return STATUS_SUCCESS;
}


PSPY_STREAM_CONTEXT
SpyFindExistingContext (
    IN PDEVICE_OBJECT DeviceObject,
    IN PFILE_OBJECT FileObject
    )
/*++

Routine Description:

    See if a context for the given stream already exists.  If so it will
    bump the reference count and return the context.  If not, NULL
    is returned.

Arguments:

    DeviceObject - Device to operate on

    FileObject - The stream the context is being looked up for

Return Value:

    Returns the found context


--*/
{
    PFILESPY_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
    PSPY_STREAM_CONTEXT pContext;
    PFSRTL_PER_STREAM_CONTEXT ctxCtrl;

    PAGED_CODE();
    ASSERT(IS_FILESPY_DEVICE_OBJECT(DeviceObject));

    //
    //  Try and locate the context structure.  We acquire the list lock
    //  so that we can guarantee that the context will not go away between
    //  the time when we find it and can increment the use count
    //

    INC_STATS(TotalContextSearches);

    SpyAcquireContextLockShared( devExt );

    ctxCtrl = FsRtlLookupPerStreamContext( FsRtlGetPerStreamContextPointer(FileObject),
                                           devExt,
                                           NULL );

    if (NULL != ctxCtrl) {

        //
        //  We found the entry, increment use count
        //

        pContext = CONTAINING_RECORD(ctxCtrl,SPY_STREAM_CONTEXT,ContextCtrl);

        ASSERT(pContext->Stream == FsRtlGetPerStreamContextPointer(FileObject));
        ASSERT(pContext->UseCount > 0);

        InterlockedIncrement( &pContext->UseCount );

        //
        //  Release the list lock
        //

        SpyReleaseContextLock( devExt );
        INC_STATS(TotalContextFound);

        SPY_LOG_PRINT( SPYDEBUG_TRACE_CONTEXT_OPS,
                       ("FileSpy!SpyFindExistingContext:Found:      (%p) Fl=%02x Use=%d \"%wZ\"\n",
                        pContext,
                        pContext->Flags,
                        pContext->UseCount,
                        &pContext->Name) );

    } else {

        //
        //  Release the list lock while we create the new context.
        //

        SpyReleaseContextLock( devExt );

        pContext = NULL;
    }

    return pContext;
}


VOID
SpyReleaseContext (
    IN PSPY_STREAM_CONTEXT pContext
    )
/*++

Routine Description:

    Decrement the use count for the given context.  If it goes to zero, free it

Arguments:

    pContext - The context to operate on

Return Value:

    None.

--*/
{
    PAGED_CODE();

    SPY_LOG_PRINT( SPYDEBUG_TRACE_DETAILED_CONTEXT_OPS,
                   ("FileSpy!SpyReleaseContext:     Release     (%p) Fl=%02x Use=%d \"%wZ\"\n",
                    pContext,
                    pContext->Flags,
                    pContext->UseCount,
                    &pContext->Name) );

    //
    //  Decrement USE count, free context if zero
    //

    ASSERT(pContext->UseCount > 0);

    if (InterlockedDecrement( &pContext->UseCount ) <= 0) {

        ASSERT(!FlagOn(pContext->Flags,CTXFL_InExtensionList));

        //
        //  Free the memory
        //

        SPY_LOG_PRINT( SPYDEBUG_TRACE_CONTEXT_OPS,
                       ("FileSpy!SpyReleaseContext:     Freeing     (%p) Fl=%02x Use=%d \"%wZ\"\n",
                         pContext,
                         pContext->Flags,
                         pContext->UseCount,
                         &pContext->Name) );

        INC_STATS(TotalContextDeferredFrees);
        SpyFreeContext( pContext );
    }
}

#endif

⌨️ 快捷键说明

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