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

📄 fspylib.c

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

VOID
SpyLogPostFsFilterOperation (
    IN NTSTATUS OperationStatus,
    OUT PRECORD_LIST RecordList
    )
{
    PRECORD_FS_FILTER_OPERATION pRecordFsFilterOp;

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

    //
    //  Record the information we see in the post operation.
    //

    pRecordFsFilterOp->ReturnStatus = OperationStatus;
    KeQuerySystemTime( &pRecordFsFilterOp->CompletionTime );
}

#endif

NTSTATUS
SpyAttachDeviceToDeviceStack (
    IN PDEVICE_OBJECT SourceDevice,
    IN PDEVICE_OBJECT TargetDevice,
    IN OUT PDEVICE_OBJECT *AttachedToDeviceObject
    )
/*++

Routine Description:

    This routine attaches the SourceDevice to the TargetDevice's stack and
    returns the device object SourceDevice was directly attached to in
    AttachedToDeviceObject.  Note that the SourceDevice does not necessarily
    get attached directly to TargetDevice.  The SourceDevice will get attached
    to the top of the stack of which TargetDevice is a member.

    VERSION NOTE:

    In Windows XP, a new API was introduced to close a rare timing window that
    can cause IOs to start being sent to a device before its
    AttachedToDeviceObject is set in its device extension.  This is possible
    if a filter is attaching to a device stack while the system is actively
    processing IOs.  The new API closes this timing window by setting the
    device extension field that holds the AttachedToDeviceObject while holding
    the IO Manager's lock that protects the device stack.

    A sufficient work around for earlier versions of the OS is to set the
    AttachedToDeviceObject to the device object that the SourceDevice is most
    likely to attach to.  While it is possible that another filter will attach
    in between the SourceDevice and TargetDevice, this will prevent the
    system from bug checking if the SourceDevice receives IOs before the
    AttachedToDeviceObject is correctly set.

    For a driver built in the Windows 2000 build environment, we will always
    use the work-around code to attach.  For a driver that is built in the
    Windows XP or later build environments (therefore you are building a
    multiversion driver), we will determine which method of attachment to use
    based on which APIs are available.


Arguments:

    SourceDevice - The device object to be attached to the stack.

    TargetDevice - The device that we currently think is the top of the stack
        to which SourceDevice should be attached.

    AttachedToDeviceObject - This is set to the device object to which
        SourceDevice is attached if the attach is successful.

Return Value:

    Return STATUS_SUCCESS if the device is successfully attached.  If
    TargetDevice represents a stack to which devices can no longer be attached,
    STATUS_NO_SUCH_DEVICE is returned.

--*/
{

    PAGED_CODE();

#if WINVER >= 0x0501
    if (IS_WINDOWSXP_OR_LATER()) {

        ASSERT( NULL != gSpyDynamicFunctions.AttachDeviceToDeviceStackSafe );

        return (gSpyDynamicFunctions.AttachDeviceToDeviceStackSafe)( SourceDevice,
                                                     TargetDevice,
                                                     AttachedToDeviceObject );

    } else {
#endif

        *AttachedToDeviceObject = TargetDevice;
        *AttachedToDeviceObject = IoAttachDeviceToDeviceStack( SourceDevice,
                                                               TargetDevice );

        if (*AttachedToDeviceObject == NULL) {

            return STATUS_NO_SUCH_DEVICE;
        }

        return STATUS_SUCCESS;

#if WINVER >= 0x0501
    }
#endif

}

NTSTATUS
SpyLog (
    IN PRECORD_LIST NewRecord
    )
/*++

Routine Description:

    This routine appends the completed log record to the gOutputBufferList.

Arguments:

    NewRecord - The record to append to the gOutputBufferList

Return Value:

    The function returns STATUS_SUCCESS.

--*/
{
    KIRQL controlDeviceIrql;
    KIRQL outputBufferIrql;

    KeAcquireSpinLock( &gControlDeviceStateLock, &controlDeviceIrql );

    if (gControlDeviceState == OPENED) {

        //
        //  The device is still open so add this record onto the list
        //

        KeAcquireSpinLock(&gOutputBufferLock, &outputBufferIrql);
        InsertTailList(&gOutputBufferList, &NewRecord->List);
        KeReleaseSpinLock(&gOutputBufferLock, outputBufferIrql);

    } else {

        //
        //  We can no longer log this record, so free the record
        //

        SpyFreeRecord( NewRecord );

    }

    KeReleaseSpinLock( &gControlDeviceStateLock, controlDeviceIrql );

    return STATUS_SUCCESS;
}

////////////////////////////////////////////////////////////////////////
//                                                                    //
//                    FileName cache routines                         //
//                                                                    //
////////////////////////////////////////////////////////////////////////


NTSTATUS
SpyQueryInformationFile (
    IN PDEVICE_OBJECT NextDeviceObject,
    IN PFILE_OBJECT FileObject,
    OUT PVOID FileInformation,
    IN ULONG Length,
    IN FILE_INFORMATION_CLASS FileInformationClass,
    OUT PULONG LengthReturned OPTIONAL
    )

/*++

Routine Description:

    This routine returns the requested information about a specified file.
    The information returned is determined by the FileInformationClass that
    is specified, and it is placed into the caller's FileInformation buffer.

Arguments:

    NextDeviceObject - Supplies the device object where this IO should start
        in the device stack.

    FileObject - Supplies the file object about which the requested
        information should be returned.

    FileInformation - Supplies a buffer to receive the requested information
        returned about the file.  This must be a buffer allocated from kernel
        space.

    Length - Supplies the length, in bytes, of the FileInformation buffer.

    FileInformationClass - Specifies the type of information which should be
        returned about the file.

    LengthReturned - the number of bytes returned if the operation was
        successful.

Return Value:

    The status returned is the final completion status of the operation.

--*/

{
    PIRP irp = NULL;
    PIO_STACK_LOCATION irpSp = NULL;
    IO_STATUS_BLOCK ioStatusBlock;
    KEVENT event;
    NTSTATUS status;

    PAGED_CODE();

    //
    //  In DBG builds, make sure that we have valid parameters before we do
    //  any work here.
    //

    ASSERT( NULL != NextDeviceObject );
    ASSERT( NULL != FileObject );
    ASSERT( NULL != FileInformation );

    //
    //  The parameters look ok, so setup the Irp.
    //

    KeInitializeEvent( &event, NotificationEvent, FALSE );
    ioStatusBlock.Status = STATUS_SUCCESS;
    ioStatusBlock.Information = 0;

    irp = IoAllocateIrp( NextDeviceObject->StackSize, FALSE );

    if (irp == NULL) {

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    //  Set our current thread as the thread for this
    //  IRP so that the IO Manager always knows which
    //  thread to return to if it needs to get back into
    //  the context of the thread that originated this
    //  IRP.
    //

    irp->Tail.Overlay.Thread = PsGetCurrentThread();

    //
    //  Set that this IRP originated from the kernel so that
    //  the IO Manager knows that the buffers do not
    //  need to be probed.
    //

    irp->RequestorMode = KernelMode;

    //
    //  Initialize the UserIosb and UserEvent in the IRP.
    //

    irp->UserIosb = &ioStatusBlock;
    irp->UserEvent = NULL;

    //
    //  Set the IRP_SYNCHRONOUS_API to denote that this
    //  is a synchronous IO request.
    //

    irp->Flags = IRP_SYNCHRONOUS_API;

    irpSp = IoGetNextIrpStackLocation( irp );

    irpSp->MajorFunction = IRP_MJ_QUERY_INFORMATION;
    irpSp->FileObject = FileObject;

    //
    //  Setup the parameters for IRP_MJ_QUERY_INFORMATION.  These
    //  were supplied by the caller of this routine.
    //  The buffer we want to be filled in should be placed in
    //  the system buffer.
    //

    irp->AssociatedIrp.SystemBuffer = FileInformation;

    irpSp->Parameters.QueryFile.Length = Length;
    irpSp->Parameters.QueryFile.FileInformationClass = FileInformationClass;

    //
    //  Set up the completion routine so that we know when our
    //  request for the file name is completed.  At that time,
    //  we can free the IRP.
    //

    IoSetCompletionRoutine( irp,
                            SpyQueryCompletion,
                            &event,
                            TRUE,
                            TRUE,
                            TRUE );

    status = IoCallDriver( NextDeviceObject, irp );

    if (STATUS_PENDING == status) {

        KeWaitForSingleObject( &event,
                               Executive,
                               KernelMode,
                               FALSE,
                               NULL );
    }

    //
    //  Verify the completion has actually been run
    //

    ASSERT(KeReadStateEvent(&event) || !NT_SUCCESS(ioStatusBlock.Status));


    if (ARGUMENT_PRESENT(LengthReturned)) {

        *LengthReturned = (ULONG) ioStatusBlock.Information;
    }

    return ioStatusBlock.Status;
}

NTSTATUS
SpyQueryCompletion (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PKEVENT SynchronizingEvent
    )
/*++

Routine Description:

    This routine does the cleanup necessary once the query request completed
    by the file system.

Arguments:

    DeviceObject - This will be NULL since we originated this
        Irp.

    Irp - The IO request structure containing the information
        about the current state of our file name query.

    SynchronizingEvent - The event to signal to notify the
        originator of this request that the operation is
        complete.

Return Value:

    Returns STATUS_MORE_PROCESSING_REQUIRED so that IO Manager
    will not try to free the Irp again.

--*/
{

    UNREFERENCED_PARAMETER( DeviceObject );

    //
    //  Make sure that the Irp status is copied over to the users
    //  IO_STATUS_BLOCK so that the originator of this IRP will know
    //  the final status of this operation.
    //

    ASSERT( NULL != Irp->UserIosb );
    *Irp->UserIosb = Irp->IoStatus;

    //
    //  Signal SynchronizingEvent so that the originator of this
    //  Irp know that the operation is completed.
    //

    KeSetEvent( SynchronizingEvent, IO_NO_INCREMENT, FALSE );

    //
    //  We are now done, so clean up the IRP that we allocated.
    //

    IoFreeIrp( Irp );

    //
    //  If we return STATUS_SUCCESS here, the IO Manager will
    //  perform the cleanup work that it thinks needs to be done
    //  for this IO operation.
    //
    //  We can do this cleanup work more efficiently than the IO Manager
    //  since we are handling a very specific case.
    //
    //  Since the IO Manager has already performed all the work we want it to
    //  do on this IRP, we do the cleanup work, return
    //  STATUS_MORE_PROCESSING_REQUIRED, and ask the IO Manager to resume
    //  processing by calling IoCompleteRequest.
    //
    //  See NLQueryCompletion for a more verbose comment on this.
    //

    return STATUS_MORE_PROCESSING_REQUIRED;
}



////////////////////////////////////////////////////////////////////////
//                                                                    //
//         Common attachment and detachment routines                  //
//                                                                    //
////////////////////////////////////////////////////////////////////////

//
//  VERSION NOTE:
//
//  To be able to safely find out if our filter is attached to a device given
//  its name on Windows 2000 and later, we need to use the approach in
//  SpyIsAttachedToDeviceByName.  This method uses APIs that are
//  available on Windows 2000 and later.  On Windows XP or later, you could
//  change this routine to separate the translation from DeviceName to device
//  object from the search to see if our filter's device is attached to the
//  device stack.  In Windows XP and later, the logic to translate the
//  DeviceName to the device object is the same, but you can use the logic
//  in SpyIsAttachedToDeviceWXPAndLater to find your filter's device object
//  in the device stack safely.
//

NTSTATUS
SpyIsAttachedToDeviceByName (
    IN PNAME_CONTROL DeviceName,
    IN OUT PBOOLEAN IsAttached,
    IN OUT PDEVICE_OBJECT *StackDeviceObject,
    IN OUT PDEVICE_OBJECT *OurAttachedDeviceObject
    )
/*++

Routine Description:

    This routine maps a device name (DOS or NT style) to a file system device

⌨️ 快捷键说明

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