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

📄 fspylib.c

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

#ifdef MEMORY_DBG
                ExFreePoolWithTag( newBuffer, FILESPY_LOGRECORD_TAG );
#else
                ExFreeToNPagedLookasideList( &gFreeBufferList, newBuffer );
#endif

                newBuffer = NULL;
            }
        }

    }  else {

        SetFlag( newRecordType,
                 (RECORD_TYPE_STATIC | RECORD_TYPE_OUT_OF_MEMORY) );
    }

    if (RecordType) {

        *RecordType = newRecordType;
    }

    return newBuffer;
}

VOID
SpyFreeBuffer (
    IN PVOID Buffer,
    IN PLONG Counter
    )
/*++

Routine Description:

    Returns a Buffer to the gFreeBufferList.

Arguments:

    Buffer - the buffer to return to the gFreeBufferList

Return Value:

    None.

--*/
{

#ifdef MEMORY_DBG
    ExFreePoolWithTag( Buffer, FILESPY_LOGRECORD_TAG );
#else
    ExFreeToNPagedLookasideList( &gFreeBufferList, Buffer );
#endif

    //
    // Update the count
    //

    if (Counter) {

        InterlockedDecrement(Counter);
    }
}


////////////////////////////////////////////////////////////////////////
//                                                                    //
//                  Logging routines                                  //
//                                                                    //
////////////////////////////////////////////////////////////////////////

PRECORD_LIST
SpyNewRecord (
    IN ULONG AssignedSequenceNumber
    )
/*++

Routine Description:

    Allocates a new RECORD_LIST structure if there is enough memory to do so. A
    sequence number is updated for each request for a new record.

Arguments:

    AssignedSequenceNumber - 0 if you want this function to generate the
        next sequence number; if not 0, the new record is assigned the
        given sequence number.

Return Value:

    Pointer to the RECORD_LIST allocated, or NULL if no memory is available.

--*/
{
    PRECORD_LIST newRecord = NULL;
    ULONG currentSequenceNumber;
    KIRQL irql;
    ULONG initialRecordType;

    newRecord = (PRECORD_LIST) SpyAllocateBuffer( &gRecordsAllocated,
                                                  gMaxRecordsToAllocate,
                                                  &initialRecordType);

    KeAcquireSpinLock(&gLogSequenceLock, &irql);

    //
    //  Assign a new sequence number if 0 was passed in, otherwise use the
    //  number passed in
    //

    if (AssignedSequenceNumber == 0) {

        gLogSequenceNumber++;
        currentSequenceNumber = gLogSequenceNumber;

    } else {

        currentSequenceNumber = AssignedSequenceNumber;
    }


    if ((newRecord == NULL) &&
        !InterlockedCompareExchange( &gStaticBufferInUse, TRUE, FALSE)) {

        //
        //  Toggle on our gStaticBufferInUse flag and use the static out of
        //  memory buffer to record this log entry.  This special log record is
        //  used to notify the user application that we are out of memory.  Log
        //  request will be dropped until we can get more memory.
        //

        newRecord   = (PRECORD_LIST)gOutOfMemoryBuffer;
        newRecord->LogRecord.RecordType = initialRecordType;
        newRecord->LogRecord.Length = SIZE_OF_LOG_RECORD;
        newRecord->LogRecord.SequenceNumber = currentSequenceNumber;

    } else if (newRecord) {

        //
        //  We were able to allocate a new record so initialize it
        //  appropriately.
        //

        newRecord->LogRecord.RecordType = initialRecordType;
        newRecord->LogRecord.Length = SIZE_OF_LOG_RECORD;
        newRecord->LogRecord.SequenceNumber = currentSequenceNumber;
    }

    KeReleaseSpinLock(&gLogSequenceLock, irql);

    //
    //  Init record specific fields.
    //

    if (newRecord != NULL) {

        newRecord->NewContext = NULL;
        newRecord->WaitEvent = NULL;
        newRecord->Flags = 0;
    }

    return( newRecord );
}

VOID
SpyFreeRecord (
    IN PRECORD_LIST Record
    )
/*++

Routine Description:

    Frees a RECORD_LIST, which returns the memory to the gFreeBufferList
    look-aside list and updates the gRecordsAllocated count.

Arguments:

    Record - the record to free

Return Value:

    None.

--*/
{
    //
    //  If there is a context record defined, release it now
    //

#if USE_STREAM_CONTEXTS
    if (NULL != Record->NewContext) {

        SpyReleaseContext( Record->NewContext );
    }
#endif

    if (FlagOn( Record->LogRecord.RecordType, RECORD_TYPE_STATIC )) {

        //
        //  This is our static record, so reset our gStaticBufferInUse flag.
        //

        InterlockedExchange( &gStaticBufferInUse, FALSE );

    } else {

        //
        //  This isn't our static memory buffer, so free the dynamically
        //  allocated memory.
        //

        SpyFreeBuffer( Record, &gRecordsAllocated );
    }
}


PRECORD_LIST
SpyLogFastIoStart (
    IN FASTIO_TYPE FastIoType,
    IN PDEVICE_OBJECT DeviceObject,
    IN PFILE_OBJECT FileObject OPTIONAL,
    IN PLARGE_INTEGER FileOffset OPTIONAL,
    IN ULONG Length OPTIONAL,
    IN BOOLEAN Wait OPTIONAL
    )
/*++

Routine Description:

    Creates the log record if possible and records the necessary Fast I/O
    information at the beginning of the fast I/O operation in RecordList
    according to LoggingFlags.

    The optional arguments are not recorded for all Fast I/O types.  If
    the argument is not needed for a given Fast I/O type, the parameter
    was ignored.

Arguments:

    FastIoType - The type of fast I/O we are logging (REQUIRED)
    DeviceObject - The device object for our filter. (REQUIRED)
    FileObject - Pointer to the file object this operation is on (OPTIONAL)
    FileOffset - Pointer to the file offset for this operation (OPTIONAL)
    Length - Length of the data for this operation (OPTIONAL)
    Wait - Whether or not this operation can wait for a result (OPTIONAL)

Return Value:

    The RECORD_LIST structure created with the appropriate information
    filled in.  If a RECORD_LIST structure couldn't be allocated, NULL
    is returned.

--*/
{
    PRECORD_LIST    pRecordList;
    PRECORD_FASTIO  pRecordFastIo;
    PFILESPY_DEVICE_EXTENSION devExt;

    //
    //  Try to get a new record
    //

    pRecordList = SpyNewRecord( 0 );

    //
    //  If we didn't get a RECORD_LIST, exit and return NULL
    //

    if (pRecordList == NULL) {

        return NULL;
    }

    //
    //  We got a RECORD_LIST, so now fill in the appropriate information
    //

    pRecordFastIo = &pRecordList->LogRecord.Record.RecordFastIo;

    //
    //  Perform the necessary book keeping for the RECORD_LIST
    //

    SetFlag( pRecordList->LogRecord.RecordType, RECORD_TYPE_FASTIO );

    //
    //  Set the RECORD_FASTIO fields that are set for all Fast I/O types
    //

    pRecordFastIo->Type = FastIoType;
    KeQuerySystemTime( &pRecordFastIo->StartTime );

    //
    //  Get process and thread information
    //

    pRecordFastIo->ProcessId = (ULONG_PTR) PsGetCurrentProcessId();
    pRecordFastIo->ThreadId = (ULONG_PTR) PsGetCurrentThreadId();

    //
    //  Record the information that is appropriate based on the
    //  Fast I/O type
    //

    pRecordFastIo->FileObject = (FILE_ID)FileObject;
    pRecordFastIo->DeviceObject = (DEVICE_ID)DeviceObject;
    pRecordFastIo->FileOffset.QuadPart = ((FileOffset != NULL) ? FileOffset->QuadPart : 0);
    pRecordFastIo->Length = Length;
    pRecordFastIo->Wait = Wait;

    devExt = DeviceObject->DeviceExtension;

    if (FastIoType == CHECK_IF_POSSIBLE) {

        //
        //  On NTFS, locks are sometimes held but top-level IRP is not set,
        //  therefore it is not safe to query the base file system for the
        //  file name at this time.  If we've got it in the cache, we'll
        //  use it.  Otherwise, we will not return a name.
        //

        SpySetName( pRecordList,
                    DeviceObject,
                    FileObject,
                    NLFL_ONLY_CHECK_CACHE,
                    NULL );

    } else {

        SpySetName( pRecordList, DeviceObject, FileObject, 0, NULL );
    }

    return pRecordList;
}

VOID
SpyLogFastIoComplete (
    IN PIO_STATUS_BLOCK ReturnStatus,
    IN PRECORD_LIST RecordList
    )
/*++

Routine Description:

    Records the necessary Fast I/O information in RecordList according to
    LoggingFlags.

    The optional arguments are not recorded for all Fast I/O types.  If
    the argument is not needed for a given Fast I/O type, the parameter
    was ignored.

Arguments:
    ReturnStatus - The return value of the operation (OPTIONAL)
    RecordList - The PRECORD_LIST in which the Fast I/O information is stored.

Return Value:

    None.

--*/
{
    PRECORD_FASTIO pRecordFastIo;

    ASSERT(RecordList);

    pRecordFastIo = &RecordList->LogRecord.Record.RecordFastIo;

    //
    //  Set the RECORD_FASTIO fields that are set for all Fast I/O types
    //

    KeQuerySystemTime( &pRecordFastIo->CompletionTime );

    if (ReturnStatus != NULL) {

        pRecordFastIo->ReturnStatus = ReturnStatus->Status;

    } else {

        pRecordFastIo->ReturnStatus = 0;
    }

    SpyLog( RecordList );
}

#if WINVER >= 0x0501 /* See comment in DriverEntry */

VOID
SpyLogPreFsFilterOperation (
    IN PFS_FILTER_CALLBACK_DATA Data,
    OUT PRECORD_LIST RecordList
    )
{
    NAME_LOOKUP_FLAGS lookupFlags = 0;

    PRECORD_FS_FILTER_OPERATION pRecordFsFilterOp;

    pRecordFsFilterOp = &RecordList->LogRecord.Record.RecordFsFilterOp;

    //
    //  Record the information we use for an originating Irp.  We first
    //  need to initialize some of the RECORD_LIST and RECORD_IRP fields.
    //  Then get the interesting information from the Irp.
    //

    SetFlag( RecordList->LogRecord.RecordType, RECORD_TYPE_FS_FILTER_OP );

    pRecordFsFilterOp->FsFilterOperation = Data->Operation;
    pRecordFsFilterOp->FileObject = (FILE_ID) Data->FileObject;
    pRecordFsFilterOp->DeviceObject = (FILE_ID) Data->DeviceObject;
    pRecordFsFilterOp->ProcessId = (FILE_ID)PsGetCurrentProcessId();
    pRecordFsFilterOp->ThreadId = (FILE_ID)PsGetCurrentThreadId();

    KeQuerySystemTime( &pRecordFsFilterOp->OriginatingTime );

    //
    //  Do not query for the name on any of the release operations
    //  because a file system resource is currently being held and
    //  we may deadlock.
    //

    switch (Data->Operation) {

        case FS_FILTER_RELEASE_FOR_CC_FLUSH:
        case FS_FILTER_RELEASE_FOR_SECTION_SYNCHRONIZATION:
        case FS_FILTER_RELEASE_FOR_MOD_WRITE:

            SPY_LOG_PRINT( SPYDEBUG_TRACE_DETAILED_CONTEXT_OPS,
                           ("FileSpy!SpyLogPreFsFilterOp:   RelOper\n") );

            SetFlag( lookupFlags, NLFL_ONLY_CHECK_CACHE );
            break;
    }

    //
    //  Only set the volumeName if the next device is a file system
    //  since we only want to prepend the volumeName if we are on
    //  top of a local file system.
    //

    SpySetName( RecordList,
                Data->DeviceObject,
                Data->FileObject,
                lookupFlags,
                NULL );

⌨️ 快捷键说明

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