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

📄 fpfilter.c

📁 FPFilter is a sample disk filter driver that demonstrates how a disk failure prediction filter drive
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++
Copyright (c) 1991-1999  Microsoft Corporation

Module Name:

    fpfilter.c

Abstract:

    This driver is a sample that shows how a Failure Prediction Filter
    driver could be written. A failure prediction filter driver allows
    hardware or software to predict if a disk will fail and if so report
    this fact to the operating system.

    NT automatically supports failure prediction for SCSI and ATAPI disks
    that follow the SMART specification. A failure prediction filter driver
    can enhance or ignore this support as it sees fit.

    A failure prediction filter driver is polled periodically by disk.sys
    to determine if the disk might fail in the future. And it is called
    whenever an application requests the current failure prediction status.

    Note that the underlying disk stack can support failure prediction.
    This would be the case if another failure prediction filter driver
    was installed lower in the stack and/or the disk supports SMART
    and the disk stack itself uses SMART to predict failure. This driver
    can forward the failure prediction ioctl to the stack to find out
    if the lower filter drivers and/or device stack are predicting failure
    and then include that information in its results.

Environment:

    kernel mode only

Notes:

--*/


#define INITGUID

#include "ntddk.h"
#include "ntdddisk.h"
#include "stdarg.h"
#include "stdio.h"


//
// Bit Flag Macros
//

#define SET_FLAG(Flags, Bit)    ((Flags) |= (Bit))
#define CLEAR_FLAG(Flags, Bit)  ((Flags) &= ~(Bit))
#define TEST_FLAG(Flags, Bit)   (((Flags) & (Bit)) != 0)

//
// Remove lock
//
#define REMLOCK_TAG 'lfpF'
#define REMLOCK_MAXIMUM 1      // Max minutes system allows lock to be held
#define REMLOCK_HIGHWATER 250  // Max number of irps holding lock at one time


//
// Device Extension
//

typedef struct _DEVICE_EXTENSION {

    //
    // Back pointer to device object
    //

    PDEVICE_OBJECT DeviceObject;

    //
    // Target Device Object
    //

    PDEVICE_OBJECT TargetDeviceObject;

    //
    // must synchronize paging path notifications
    //
    KEVENT PagingPathCountEvent;
    ULONG  PagingPathCount;

    //
    // Since we may hold onto irps for an arbitrarily long time
    // we need a remove lock so that our device does not get removed
    // while an irp is being processed.
    IO_REMOVE_LOCK RemoveLock;

    //
    // Flag that specifies if we should predict failure or not. More
    // sophisticated drivers can use statistical or proprietary hardware
    // mechanisms to predict failure.
    BOOLEAN PredictFailure;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

#define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION)


//
// Function declarations
//

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    );

NTSTATUS
FPFilterForwardIrpSynchronous(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

NTSTATUS
FPFilterAddDevice(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT PhysicalDeviceObject
    );


NTSTATUS
FPFilterDispatchPnp(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

NTSTATUS
FPFilterDispatchPower(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

NTSTATUS
FPFilterStartDevice(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

NTSTATUS
FPFilterRemoveDevice(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

NTSTATUS
FPFilterSendToNextDriver(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

NTSTATUS
FPFilterCreate(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

NTSTATUS
FPFilterReadWrite(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

NTSTATUS
FPFilterDeviceControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

NTSTATUS
FPFilterShutdownFlush(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

VOID
FPFilterUnload(
    IN PDRIVER_OBJECT DriverObject
    );

NTSTATUS FPFilterWmi(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

NTSTATUS
FPFilterIrpCompletion(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    );


VOID
FPFilterSyncFilterWithTarget(
    IN PDEVICE_OBJECT FilterDevice,
    IN PDEVICE_OBJECT TargetDevice
    );

#if DBG

#define DEBUG_BUFFER_LENGTH 256

ULONG FPFilterDebug = 0;
UCHAR FPFilterDebugBuffer[DEBUG_BUFFER_LENGTH];

VOID
FPFilterDebugPrint(
    ULONG DebugPrintLevel,
    PCCHAR DebugMessage,
    ...
    );

#define DebugPrint(x)   FPFilterDebugPrint x

#else

#define DebugPrint(x)

#endif

//
// Define the sections that allow for discarding (i.e. paging) some of
// the code.
//

#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, FPFilterAddDevice)
#pragma alloc_text (PAGE, FPFilterDispatchPnp)
#pragma alloc_text (PAGE, FPFilterStartDevice)
#pragma alloc_text (PAGE, FPFilterRemoveDevice)
#pragma alloc_text (PAGE, FPFilterUnload)
#pragma alloc_text (PAGE, FPFilterWmi)
#pragma alloc_text (PAGE, FPFilterSyncFilterWithTarget)
#endif


NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )

/*++

Routine Description:

    Installable driver initialization entry point.
    This entry point is called directly by the I/O manager to set up the disk
    failure prediction filter driver. The driver object is set up and
    then the Pnp manager calls FPFilterAddDevice to attach to the boot
    devices.

Arguments:

    DriverObject - The disk performance driver object.

    RegistryPath - pointer to a unicode string representing the path,
                   to driver-specific key in the registry.

Return Value:

    STATUS_SUCCESS if successful

--*/

{

    ULONG               ulIndex;
    PDRIVER_DISPATCH  * dispatch;

    //
    // Create dispatch points
    //
    for (ulIndex = 0, dispatch = DriverObject->MajorFunction;
         ulIndex <= IRP_MJ_MAXIMUM_FUNCTION;
         ulIndex++, dispatch++) {

        *dispatch = FPFilterSendToNextDriver;
    }

    //
    // Set up the device driver entry points.
    //

    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = FPFilterDeviceControl;
    DriverObject->MajorFunction[IRP_MJ_PNP]             = FPFilterDispatchPnp;
    DriverObject->MajorFunction[IRP_MJ_POWER]           = FPFilterDispatchPower;

    DriverObject->DriverExtension->AddDevice            = FPFilterAddDevice;
    DriverObject->DriverUnload                          = FPFilterUnload;

    return(STATUS_SUCCESS);

} // end DriverEntry()

#define FILTER_DEVICE_PROPOGATE_FLAGS            0
#define FILTER_DEVICE_PROPOGATE_CHARACTERISTICS (FILE_REMOVABLE_MEDIA |  \
                                                 FILE_READ_ONLY_DEVICE | \
                                                 FILE_FLOPPY_DISKETTE    \
                                                 )

VOID
FPFilterSyncFilterWithTarget(
    IN PDEVICE_OBJECT FilterDevice,
    IN PDEVICE_OBJECT TargetDevice
    )
{
    ULONG                   propFlags;

    PAGED_CODE();

    //
    // Propogate all useful flags from target to FPFilter. MountMgr will look
    // at the FPFilter object capabilities to figure out if the disk is
    // a removable and perhaps other things.
    //
    propFlags = TargetDevice->Flags & FILTER_DEVICE_PROPOGATE_FLAGS;
    SET_FLAG(FilterDevice->Flags, propFlags);

    propFlags = TargetDevice->Characteristics & FILTER_DEVICE_PROPOGATE_CHARACTERISTICS;
    SET_FLAG(FilterDevice->Characteristics, propFlags);


}

NTSTATUS
FPFilterAddDevice(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT PhysicalDeviceObject
    )
/*++
Routine Description:

    Creates and initializes a new filter device object FiDO for the
    corresponding PDO.  Then it attaches the device object to the device
    stack of the drivers for the device.

Arguments:

    DriverObject - Disk performance driver object.
    PhysicalDeviceObject - Physical Device Object from the underlying layered driver

Return Value:

    NTSTATUS
--*/

{
    NTSTATUS                status;
    PDEVICE_OBJECT          filterDeviceObject;
    PDEVICE_EXTENSION       deviceExtension;
    PIRP                    irp;
    ULONG                   registrationFlag = 0;
    PCHAR                   buffer;
    ULONG                   buffersize;

    PAGED_CODE();

    //
    // Create a filter device object for this device (partition).
    //

    DebugPrint((2, "FPFilterAddDevice: Driver %p Device %p\n",
            DriverObject, PhysicalDeviceObject));

    status = IoCreateDevice(DriverObject,
                            DEVICE_EXTENSION_SIZE,
                            NULL,
                            FILE_DEVICE_DISK,
                            0,
                            FALSE,
                            &filterDeviceObject);

    if (!NT_SUCCESS(status)) {
       DebugPrint((1, "FPFilterAddDevice: Cannot create filterDeviceObject\n"));
       return status;
    }

    SET_FLAG(filterDeviceObject->Flags, DO_DIRECT_IO);

    deviceExtension = (PDEVICE_EXTENSION) filterDeviceObject->DeviceExtension;

    RtlZeroMemory(deviceExtension, DEVICE_EXTENSION_SIZE);

    //
    // Attaches the device object to the highest device object in the chain and
    // return the previously highest device object, which is passed to
    // IoCallDriver when pass IRPs down the device stack
    //

    deviceExtension->TargetDeviceObject =
        IoAttachDeviceToDeviceStack(filterDeviceObject, PhysicalDeviceObject);

    if (deviceExtension->TargetDeviceObject == NULL) {
        IoDeleteDevice(filterDeviceObject);
        DebugPrint((1, "FPFilterAddDevice: Unable to attach %X to target %X\n",
            filterDeviceObject, PhysicalDeviceObject));
        return STATUS_NO_SUCH_DEVICE;
    }

    //
    // Save the filter device object in the device extension
    //
    deviceExtension->DeviceObject = filterDeviceObject;

    KeInitializeEvent(&deviceExtension->PagingPathCountEvent,
                      NotificationEvent, TRUE);

    //
    // default to DO_POWER_PAGABLE
    //

    SET_FLAG(filterDeviceObject->Flags,  DO_POWER_PAGABLE);

    //
    // Initialize the remove lock
    //
    IoInitializeRemoveLock(&deviceExtension->RemoveLock,
                           REMLOCK_TAG,
                           REMLOCK_MAXIMUM,
                           REMLOCK_HIGHWATER);

    //
    // Clear the DO_DEVICE_INITIALIZING flag
    //

    CLEAR_FLAG(filterDeviceObject->Flags, DO_DEVICE_INITIALIZING);

    return STATUS_SUCCESS;

} // end FPFilterAddDevice()


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

Routine Description:

    Dispatch for PNP

Arguments:

    DeviceObject    - Supplies the device object.

    Irp             - Supplies the I/O request packet.

Return Value:

    NTSTATUS

--*/

{
    PIO_STACK_LOCATION  irpSp = IoGetCurrentIrpStackLocation(Irp);
    NTSTATUS            status;
    PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
    BOOLEAN lockHeld;
    BOOLEAN irpCompleted;

    PAGED_CODE();

    DebugPrint((2, "FPFilterDispatchPnp: Device %X Irp %X\n",
        DeviceObject, Irp));


    //
    // Acquire the remove lock so that device will not be removed while
    // processing this irp.
    //
    status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, Irp);

    if (!NT_SUCCESS(status))
    {
        DebugPrint((3, "FpFilterPnp: Remove lock failed PNP Irp type [%#02x]\n",
                      irpSp->MinorFunction));
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }

    lockHeld = TRUE;
    irpCompleted = FALSE;

    switch(irpSp->MinorFunction) {

        case IRP_MN_START_DEVICE:
        {
            //
            // Call the Start Routine handler. 
            //
            DebugPrint((3,
               "FPFilterDispatchPnp: Schedule completion for START_DEVICE"));
            status = FPFilterStartDevice(DeviceObject, Irp);
            break;
        }

        case IRP_MN_REMOVE_DEVICE:
        {
            //
            // Call the Remove Routine handler. 
            //
            DebugPrint((3,
               "FPFilterDispatchPnp: Schedule completion for REMOVE_DEVICE"));
            status = FPFilterRemoveDevice(DeviceObject, Irp);
            
            //
            // Remove locked released by FpFilterRemoveDevice
            //
            lockHeld = FALSE;
            break;
        }
        
        case IRP_MN_DEVICE_USAGE_NOTIFICATION:
        {
            PIO_STACK_LOCATION irpStack;
            ULONG count;
            BOOLEAN setPagable;

            DebugPrint((3,
               "FPFilterDispatchPnp: Processing DEVICE_USAGE_NOTIFICATION"));
            irpStack = IoGetCurrentIrpStackLocation(Irp);

            if (irpStack->Parameters.UsageNotification.Type != DeviceUsageTypePaging) {
                IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
                lockHeld = FALSE;
                status = FPFilterSendToNextDriver(DeviceObject, Irp);
                irpCompleted = TRUE;
                break; // out of case statement
            }

            deviceExtension = DeviceObject->DeviceExtension;

            //
            // wait on the paging path event
            //

            status = KeWaitForSingleObject(&deviceExtension->PagingPathCountEvent,
                                           Executive, KernelMode,
                                           FALSE, NULL);

⌨️ 快捷键说明

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