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

📄 filespy.c

📁 文件过滤驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
)
/*++

Routine Description:

    This routine is the main dispatch routine for the general purpose file
    system driver.  It simply passes requests onto the next driver in the
    stack, which is presumably a disk file system, while logging any
    relevant information if logging is turned on for this DeviceObject.

Arguments:

    DeviceObject - Pointer to the device object for this driver.
    Irp - Pointer to the request packet representing the I/O request.

Return Value:

    The function value is the status of the operation.

Note:

    This routine passes the I/O request through to the next driver
    *without* removing itself from the stack (like sfilter) since it could
    want to see the result of this I/O request.
    
    To remain in the stack, we have to copy the caller's parameters to the
    next stack location.  Note that we do not want to copy the caller's I/O
    completion routine into the next stack location, or the caller's routine
    will get invoked twice.  This is why we NULL out the Completion routine.
    If we are logging this device, we set our own Completion routine.
    
--*/
{
    PDEVICE_EXTENSION  pDeviceExtension;
    PIO_STACK_LOCATION pIrpStack,pNextIrpSp;
    UCHAR              loggingFlags = 0;
    KIRQL              oldIrql;

    pDeviceExtension = DeviceObject->DeviceExtension;

    pIrpStack = IoGetCurrentIrpStackLocation( Irp );
    pNextIrpSp = IoGetNextIrpStackLocation( Irp );

    //
    //  FileSpy needs to consume a stack location if it wants to receive
    //  a callback on the I/O operation's completion path.  FileSpy
    //  does not change any of the parameters, so just copy the caller's 
    //  parameters (which includes the caller's completion routine)
    //  to the next stack location.  FileSpy then must clear the completion 
    //  routine since we don't want the caller's routine to be called (resulting
    //  in that completion routine being called twice).  FileSpy will set
    //  its own completion routine in the case that it wants the completion.
    //
    RtlMoveMemory( pNextIrpSp, pIrpStack, sizeof( IO_STACK_LOCATION ) );
    IoSetCompletionRoutine( Irp, NULL, NULL, FALSE, FALSE, FALSE );
           
    if (SHOULD_LOG(DeviceObject)) {
        PRECORD_LIST       recordList;
        //
        // The ControlDevice is opened, so allocate the Record 
        // and log the Irp information if we have the memory.
        //
        recordList = SpyNewRecord(0);
        if (recordList) {
            loggingFlags |= LOG_ORIGINATING_IRP;
            SpyLogIrp( Irp, loggingFlags, recordList );

            //
            //  Since we are logging this operation, we want to 
            //  see its completion so register our completion
            //  routine.
            //
            IoSetCompletionRoutine(
                Irp,
                SpyPassThroughCompletion,
                (PVOID)recordList,
                TRUE,
                TRUE,
                TRUE);
        }
    }

    //
    // If this is a IRP_MJ_CLOSE see if the FileObject's name is being
    // cached and remove it from the cache if it is.  We want to do this
    // as long as the ControlDevice is opened so that we purge the
    // cache as accurately as possible.
    //
    ExAcquireSpinLock( &gControlDeviceStateLock, &oldIrql );
    if (gControlDeviceState == OPENED) {
        if (pIrpStack->MajorFunction == IRP_MJ_CLOSE) {
            SpyNameDelete(pIrpStack->FileObject);
        }
    }
    ExReleaseSpinLock( &gControlDeviceStateLock, oldIrql );

    //
    // Now call the appropriate file system driver with the request.
    //
    return IoCallDriver( pDeviceExtension->NextDriverDeviceObject, Irp );
}

DBGSTATIC
NTSTATUS
SpyPassThroughCompletion(
    IN PDEVICE_OBJECT  DeviceObject,
    IN PIRP            Irp,
    IN PVOID           Context
)
/*++

Routine Description:

    This routine is the completion routine SpyPassThrough.  This is used
    to log the information that can only be gathered after the I/O request
    has been completed.

    Once we are done logging all the information we care about, we append
    the record to the gOutputBufferList to be returned to the user.
    
    Note: This routine will only be set if we were trying to log the
        specified device when the Irp originated and we were able to
        allocate a record to store this logging information.

Arguments:

    DeviceObject - Pointer to the device object for this driver.
    Irp - Pointer to the request packet representing the I/O request.
    Context - Pointer to the RECORD_LIST structure in which we store the
        information we are logging.

Return Value:

    The function value is the status of the operation.

--*/
{
    PRECORD_LIST  recordList;
    UCHAR         loggingFlags = 0;

    recordList = (PRECORD_LIST)Context;

    if (SHOULD_LOG(DeviceObject))
    {
        loggingFlags |= LOG_COMPLETION_IRP;
        SpyLogIrp( Irp, loggingFlags, recordList );
        
        //
        // 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);
        }
    }
    
    //
    // Propogate the IRP pending flag.  All completion routines
    // need to do this.
    //
    if (Irp->PendingReturned) {
        IoMarkIrpPending( Irp );
    }

    return STATUS_SUCCESS;
}

DBGSTATIC
NTSTATUS
SpyDispatch(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
)
/*++

Routine Description:

    This function completes all requests on the gControlDeviceObject 
    (FileSpy's device object) and passes all other requests on to the 
    SpyPassThrough function.

Arguments:

    DeviceObject - Pointer to the device object for this driver.
    Irp - Pointer to the request packet representing the I/O request.

Return Value:

    If this is a request on the gControlDeviceObject, STATUS_SUCCESS 
    will be returned unless the device is already attached.  In that case,
    STATUS_DEVICE_ALREADY_ATTACHED is returned.

    If this is a request on a device other than the gControlDeviceObject,
    the function will return the value of SpyPassThrough().

--*/
{
    ULONG              status = STATUS_SUCCESS;
    PIO_STACK_LOCATION irpStack;
    KIRQL              oldIrql;
    
    
    if (DeviceObject == gControlDeviceObject) {
        //
        //  A request is being made on our device object, gControlDeviceObject.
        //
        Irp->IoStatus.Information = 0;
    
        irpStack = IoGetCurrentIrpStackLocation( Irp );
       
        switch (irpStack->MajorFunction) {
            case IRP_MJ_CLOSE:
        
                SpyCloseControlDevice();
                break;

            default:
                status = STATUS_INVALID_PARAMETER;
        }

        Irp->IoStatus.Status = status;

        //
        //  We have completed all processing for this IRP, so tell the 
        //  I/O Manager.  This IRP will not be passed any further down
        //  the stack since no drivers below FileSpy care about this 
        //  I/O operation that was directed to FileSpy.
        //
        IoCompleteRequest( Irp, IO_NO_INCREMENT );
        return status;
    }

    return SpyPassThrough( DeviceObject, Irp );
}

DBGSTATIC
NTSTATUS
SpyCreate(
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp
)
/*++

Routine Description:

    This is the routine that is associated with IRP_MJ_CREATE irp.  If the 
    DeviceObject is the ControlDevice, we do the creation work for the 
    ControlDevice and complete the irp.  Otherwise, we pass through
    this irp for another device to complete.
    
    Note: Some of the code in this function duplicates the functions 
        SpyDispatch and SpyPassThrough, but a design decision was made that 
        it was worth the code duplication to break out the irp handlers 
        that can be pagable code.
    
Arguments:

    DeviceObject - Pointer to the device object for this driver.
    Irp - Pointer to the request packet representing the I/O request.
    
Return Value:

    If DeviceObject == gControlDeviceObject, then this function will 
    complete the Irp and return the status of that completion.  Otherwise,
    this function returns the result of calling SpyPassThrough.
    
--*/
{
    ULONG               status = STATUS_SUCCESS;
    PIO_STACK_LOCATION  pIrpStack;
    KIRQL               oldIrql;

    if (DeviceObject == gControlDeviceObject) {
        //
        // A CREATE request is being made on our gControlDeviceObject
        //
        ExAcquireSpinLock( &gControlDeviceStateLock, &oldIrql );
        if (gControlDeviceState != CLOSED) {
            status = STATUS_DEVICE_ALREADY_ATTACHED;
        } else {
            gControlDeviceState = OPENED;
        }
        ExReleaseSpinLock( &gControlDeviceStateLock, oldIrql );

        //
        // Since this is our gControlDeviceObject, we complete the
        // irp here.
        //
        Irp->IoStatus.Status = status;
        IoCompleteRequest( Irp, IO_NO_INCREMENT );
        return status;
    }

    //
    //
    // This is a CREATE so we need to invalidate the name currently
    // stored in the name cache for this FileObject.  We need to do
    // this as long as our ControlDevice is open so that we keep the
    // name cache up-to-date.
    //
    pIrpStack = IoGetCurrentIrpStackLocation( Irp );
    ExAcquireSpinLock( &gControlDeviceStateLock, &oldIrql );
    if (gControlDeviceState == OPENED) {
        SpyNameDelete(pIrpStack->FileObject);
    }
    ExReleaseSpinLock( &gControlDeviceStateLock, oldIrql );

    // This is NOT our gControlDeviceObject, so let SpyPassThrough handle
    // it appropriately
    //
    return SpyPassThrough( DeviceObject, Irp );
}

DBGSTATIC
BOOLEAN
SpyFastIoCheckIfPossible(
    IN PFILE_OBJECT      FileObject,
    IN PLARGE_INTEGER    FileOffset,
    IN ULONG             Length,
    IN BOOLEAN           Wait,
    IN ULONG             LockKey,
    IN BOOLEAN           CheckForReadOperation,
    OUT PIO_STATUS_BLOCK IoStatus,
    IN PDEVICE_OBJECT    DeviceObject
)
/*++

Routine Description:

    This routine is the fast I/O "pass through" routine for checking to see
    whether fast I/O is possible for this file.

    This function simply invokes the next driver's cooresponding routine, or
    returns FALSE if the next driver does not implement the function.

Arguments:

    FileObject - Pointer to the file object to be operated on.

    FileOffset - Byte offset in the file for the operation.

    Length - Length of the operation to be performed.

    Wait - Indicates whether or not the caller is willing to wait if the
        appropriate locks, etc. cannot be acquired

    LockKey - Provides the caller's key for file locks.

    CheckForReadOperation - Indicates whether the caller is checking for a
        read (TRUE) or a write operation.

    IoStatus - Pointer to a variable to receive the I/O status of the
        operation.

    DeviceObject - Pointer to this driver's device object, the device on
        which the operation is to occur.

Return Value:

    The function value is TRUE or FALSE based on whether or not fast I/O
    is possible for this file.

--*/
{
    PDEVICE_OBJECT    deviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;
    BOOLEAN           returnValue;
    PRECORD_LIST      recordList;
    BOOLEAN           shouldLog;
    
    PAGED_CODE();

    if (DeviceObject->DeviceExtension == NULL) {
        return FALSE;
    }
    
    if (shouldLog = SHOULD_LOG(DeviceObject)) {
        //
        // Log the necessary information for the start of the Fast I/O 
        // operation
        //
        recordList = SpyLogFastIoStart(
            CHECK_IF_POSSIBLE,
            0,
            FileObject,
            FileOffset,
            Length,
            Wait );
    }

    //
    // Pass through logic for this type of Fast I/O
    //
    deviceObject = 
        ((PDEVICE_EXTENSION) (DeviceObject->DeviceExtension))->
            NextDriverDeviceObject;
    if (!deviceObject) {
        returnValue = FALSE;
        goto SpyFastIoCheckIfPossible_Exit;
    }
    fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;

    if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoCheckIfPossible )) {
        returnValue = (fastIoDispatch->FastIoCheckIfPossible)( FileObject,
                                                               FileOffset,

⌨️ 快捷键说明

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