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

📄 fpfilter.c

📁 FPFilter is a sample disk filter driver that demonstrates how a disk failure prediction filter drive
💻 C
📖 第 1 页 / 共 2 页
字号:
            //
            // if removing last paging device, need to set DO_POWER_PAGABLE
            // bit here, and possible re-set it below on failure.
            //

            setPagable = FALSE;
            if (!irpStack->Parameters.UsageNotification.InPath &&
                deviceExtension->PagingPathCount == 1 ) {

                //
                // removing the last paging file
                // must have DO_POWER_PAGABLE bits set
                //

                if (TEST_FLAG(DeviceObject->Flags, DO_POWER_INRUSH)) {
                    DebugPrint((3, "FPFilterDispatchPnp: last paging file "
                                "removed but DO_POWER_INRUSH set, so not "
                                "setting PAGABLE bit "
                                "for DO %p\n", DeviceObject));
                } else {
                    DebugPrint((2, "FPFilterDispatchPnp: Setting  PAGABLE "
                                "bit for DO %p\n", DeviceObject));
                    SET_FLAG(DeviceObject->Flags, DO_POWER_PAGABLE);
                    setPagable = TRUE;
                }

            }

            //
            // send the irp synchronously
            //

            status = FPFilterForwardIrpSynchronous(DeviceObject, Irp);

            //
            // now deal with the failure and success cases.
            // note that we are not allowed to fail the irp
            // once it is sent to the lower drivers.
            //

            if (NT_SUCCESS(status)) {

                IoAdjustPagingPathCount(
                    &deviceExtension->PagingPathCount,
                    irpStack->Parameters.UsageNotification.InPath);

                if (irpStack->Parameters.UsageNotification.InPath) {
                    if (deviceExtension->PagingPathCount == 1) {

                        //
                        // first paging file addition
                        //

                        DebugPrint((3, "FPFilterDispatchPnp: Clearing PAGABLE bit "
                                    "for DO %p\n", DeviceObject));
                        CLEAR_FLAG(DeviceObject->Flags, DO_POWER_PAGABLE);
                    }
                }

            } else {

                //
                // cleanup the changes done above
                //

                if (setPagable == TRUE) {
                    CLEAR_FLAG(DeviceObject->Flags, DO_POWER_PAGABLE);
                    setPagable = FALSE;
                }

            }

            //
            // set the event so the next one can occur.
            //

            KeSetEvent(&deviceExtension->PagingPathCountEvent,
                       IO_NO_INCREMENT, FALSE);
        }

        default:
        {
            DebugPrint((3,
               "FPFilterDispatchPnp: Forwarding irp"));
            //
            // Simply forward all other Irps
            //
            IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
            lockHeld = FALSE;
            status = FPFilterSendToNextDriver(DeviceObject, Irp);
            irpCompleted = TRUE;
        }
    }

    if (! irpCompleted)
    {
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
    }
    
    if (lockHeld)
    {
        IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
    }

    return status;

} // end FPFilterDispatchPnp()

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

/*++

Routine Description:

    Forwarded IRP completion routine. Set an event and return
    STATUS_MORE_PROCESSING_REQUIRED. Irp forwarder will wait on this
    event and then re-complete the irp after cleaning up.

Arguments:

    DeviceObject is the device object of the WMI driver
    Irp is the WMI irp that was just completed
    Context is a PKEVENT that forwarder will wait on

Return Value:

    STATUS_MORE_PORCESSING_REQUIRED

--*/

{
    PKEVENT Event = (PKEVENT) Context;

    UNREFERENCED_PARAMETER(DeviceObject);
    UNREFERENCED_PARAMETER(Irp);

    KeSetEvent(Event, IO_NO_INCREMENT, FALSE);

    return(STATUS_MORE_PROCESSING_REQUIRED);

} // end FPFilterIrpCompletion()

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

Routine Description:

    This routine is called when a Pnp Start Irp is received.
    It will schedule a completion routine to initialize and register with WMI.

Arguments:

    DeviceObject - a pointer to the device object

    Irp - a pointer to the irp


Return Value:

    Status of processing the Start Irp

--*/
{
    PDEVICE_EXTENSION   deviceExtension;
    KEVENT              event;
    NTSTATUS            status;

    PAGED_CODE();

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    status = FPFilterForwardIrpSynchronous(DeviceObject, Irp);

    FPFilterSyncFilterWithTarget(DeviceObject,
                                 deviceExtension->TargetDeviceObject);

    return status;
}

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

Routine Description:

    This routine is called when the device is to be removed.
    It will de-register itself from WMI first, detach itself from the
    stack before deleting itself.

Arguments:

    DeviceObject - a pointer to the device object

    Irp - a pointer to the irp


Return Value:

    Status of removing the device

--*/
{
    NTSTATUS            status;
    PDEVICE_EXTENSION   deviceExtension;

    PAGED_CODE();

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    status = FPFilterForwardIrpSynchronous(DeviceObject, Irp);

    IoReleaseRemoveLockAndWait(&deviceExtension->RemoveLock, Irp);

    IoDetachDevice(deviceExtension->TargetDeviceObject);
    IoDeleteDevice(DeviceObject);

    return status;
}


NTSTATUS
FPFilterSendToNextDriver(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine sends the Irp to the next driver in line
    when the Irp is not processed by this driver.

Arguments:

    DeviceObject
    Irp

Return Value:

    NTSTATUS

--*/

{
    PDEVICE_EXTENSION   deviceExtension;

    IoSkipCurrentIrpStackLocation(Irp);
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);

} // end FPFilterSendToNextDriver()

NTSTATUS
FPFilterDispatchPower(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    PDEVICE_EXTENSION deviceExtension;

    PoStartNextPowerIrp(Irp);
    IoSkipCurrentIrpStackLocation(Irp);

    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    return PoCallDriver(deviceExtension->TargetDeviceObject, Irp);

} // end FPFilterDispatchPower

NTSTATUS
FPFilterForwardIrpSynchronous(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine sends the Irp to the next driver in line
    when the Irp needs to be processed by the lower drivers
    prior to being processed by this one.

Arguments:

    DeviceObject
    Irp

Return Value:

    NTSTATUS

--*/

{
    PDEVICE_EXTENSION   deviceExtension;
    KEVENT event;
    NTSTATUS status;

    KeInitializeEvent(&event, NotificationEvent, FALSE);
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    //
    // copy the irpstack for the next device
    //

    IoCopyCurrentIrpStackLocationToNext(Irp);

    //
    // set a completion routine
    //

    IoSetCompletionRoutine(Irp, FPFilterIrpCompletion,
                            &event, TRUE, TRUE, TRUE);

    //
    // call the next lower device
    //

    status = IoCallDriver(deviceExtension->TargetDeviceObject, Irp);

    //
    // wait for the actual completion
    //

    if (status == STATUS_PENDING) {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = Irp->IoStatus.Status;
    }

    return status;

} // end FPFilterForwardIrpSynchronous()


NTSTATUS
FPFilterDeviceControl(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp
    )

/*++

Routine Description:

    This device control dispatcher handles only the failure prediction
    device control. All others are passed down to the disk drivers.

Arguments:

    DeviceObject - Context for the activity.
    Irp          - The device control argument block.

Return Value:

    Status is returned.

--*/

{
    PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
    PSTORAGE_PREDICT_FAILURE checkFailure;
    NTSTATUS status;

    DebugPrint((2, "FPFilterDeviceControl: DeviceObject %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, "FpFilterDeviceControl: Remove lock failed IOCTL Irp type [%x]\n",
                 currentIrpStack->Parameters.DeviceIoControl.IoControlCode));
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }


    if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode ==
        IOCTL_STORAGE_PREDICT_FAILURE)
    {

        //
        // Verify user buffer is large enough for the failure prediction data
        //

        if (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
                sizeof(STORAGE_PREDICT_FAILURE))
        {
            //
            // Indicate unsuccessful status and no data transferred.
            //

            status = STATUS_BUFFER_TOO_SMALL;
            Irp->IoStatus.Information = sizeof(STORAGE_PREDICT_FAILURE);

        } else {

            //
            // If underlying device stack supports failure prediction then
            // most likely there is another filter driver and/or support for
            // SMART in the disk stack. We'll call down to get its opinion
            // first before making our own decision as to if the device
            // is predicting failure.

            status = FPFilterForwardIrpSynchronous(DeviceObject, Irp);

            //
            // Here we decide if  we want to predict whether the device
            // will fail or not. We can do many interesting things such
            // as sending a hardware request to the physical device,
            // doing some statistical analysis, whatever makes sense for
            // the device in question.
            //
            checkFailure = Irp->AssociatedIrp.SystemBuffer;

            if (NT_SUCCESS(status))
            {
                //
                // Since a driver lower on the stack has an opinion then we
                // abide by it. We could also do more sophisticated analysis

            } else {
                RtlZeroMemory(checkFailure, sizeof(STORAGE_PREDICT_FAILURE));

                checkFailure->PredictFailure = (deviceExtension->PredictFailure) ?
                                                      1 : 0;
                status = STATUS_SUCCESS;
                Irp->IoStatus.Information = sizeof(STORAGE_PREDICT_FAILURE);
            }
        }

        //
        // Complete request.
        //

        Irp->IoStatus.Status = status;

        IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);

        IoCompleteRequest(Irp, IO_NO_INCREMENT);
    } else {

        //
        // Pass unrecognized device control requests
        // down to next driver layer.
        //

        IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
        status = FPFilterSendToNextDriver(DeviceObject, Irp);
    }
    
    return(status);
} // end FPFilterDeviceControl()



VOID
FPFilterUnload(
    IN PDRIVER_OBJECT DriverObject
    )

/*++

Routine Description:

    Free all the allocated resources, etc.

Arguments:

    DriverObject - pointer to a driver object.

Return Value:

    VOID.

--*/
{
    PAGED_CODE();

    return;
}

#if DBG

VOID
FPFilterDebugPrint(
    ULONG DebugPrintLevel,
    PCCHAR DebugMessage,
    ...
    )

/*++

Routine Description:

    Debug print for all FPFilter

Arguments:

    Debug print level between 0 and 3, with 3 being the most verbose.

Return Value:

    None

--*/

{
    va_list ap;

    va_start(ap, DebugMessage);


    if ((DebugPrintLevel <= (FPFilterDebug & 0x0000ffff)) ||
        ((1 << (DebugPrintLevel + 15)) & FPFilterDebug)) {

        _vsnprintf(FPFilterDebugBuffer, DEBUG_BUFFER_LENGTH, DebugMessage, ap);

        DbgPrint(FPFilterDebugBuffer);
    }

    va_end(ap);

}
#endif

⌨️ 快捷键说明

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