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

📄 class.c

📁 This is the library for all storage drivers. It simplifies writing a storage driver by implementing
💻 C
📖 第 1 页 / 共 5 页
字号:
                DebugPrint((2, "ClassDispatchPnp (%p,%p): Processing QUERY_%s irp\n",
                            DeviceObject, Irp,
                            ((irpStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) ?
                             "STOP" : "REMOVE")));

                //
                // If this device is in use for some reason (paging, etc...)
                // then we need to fail the request.
                //

                if(commonExtension->PagingPathCount != 0) {

                    DebugPrint((1, "ClassDispatchPnp (%p,%p): device is in paging "
                                "path and cannot be removed\n",
                                DeviceObject, Irp));
                    status = STATUS_DEVICE_BUSY;
                    break;
                }

                //
                // Check with the class driver to see if the query operation
                // can succeed.
                //

                if(irpStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) {
                    status = devInfo->ClassStopDevice(DeviceObject,
                                                      irpStack->MinorFunction);
                } else {
                    status = devInfo->ClassRemoveDevice(DeviceObject,
                                                        irpStack->MinorFunction);
                }

                if(NT_SUCCESS(status)) {

                    //
                    // ASSERT that we never get two queries in a row, as
                    // this will severly mess up the state machine
                    //
                    ASSERT(commonExtension->CurrentState != irpStack->MinorFunction);
                    commonExtension->PreviousState = commonExtension->CurrentState;
                    commonExtension->CurrentState = irpStack->MinorFunction;

                    if(isFdo) {
                        DebugPrint((2, "ClassDispatchPnp (%p,%p): Forwarding QUERY_"
                                    "%s irp\n", DeviceObject, Irp,
                                    ((irpStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) ?
                                     "STOP" : "REMOVE")));
                        status = ClassForwardIrpSynchronous(commonExtension, Irp);
                    }
                }
                DebugPrint((2, "ClassDispatchPnp (%p,%p): Final status == %x\n",
                            DeviceObject, Irp, status));

                break;
            }

            case IRP_MN_CANCEL_STOP_DEVICE:
            case IRP_MN_CANCEL_REMOVE_DEVICE: {

                //
                // Check with the class driver to see if the query or cancel
                // operation can succeed.
                //

                if(irpStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE) {
                    status = devInfo->ClassStopDevice(DeviceObject,
                                                      irpStack->MinorFunction);
                    ASSERTMSG("ClassDispatchPnp !! CANCEL_STOP_DEVICE should "
                              "never be failed\n", NT_SUCCESS(status));
                } else {
                    status = devInfo->ClassRemoveDevice(DeviceObject,
                                                        irpStack->MinorFunction);
                    ASSERTMSG("ClassDispatchPnp !! CANCEL_REMOVE_DEVICE should "
                              "never be failed\n", NT_SUCCESS(status));
                }

                Irp->IoStatus.Status = status;

                //
                // We got a CANCEL - roll back to the previous state only
                // if the current state is the respective QUERY state.
                //

                if(((irpStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE) &&
                    (commonExtension->CurrentState == IRP_MN_QUERY_STOP_DEVICE)
                    ) ||
                   ((irpStack->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE) &&
                    (commonExtension->CurrentState == IRP_MN_QUERY_REMOVE_DEVICE)
                    )
                   ) {

                    commonExtension->CurrentState =
                        commonExtension->PreviousState;
                    commonExtension->PreviousState = 0xff;

                }

                if(isFdo) {
                    IoCopyCurrentIrpStackLocationToNext(Irp);
                    ClassReleaseRemoveLock(DeviceObject, Irp);
                    status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
                    completeRequest = FALSE;
                } else {
                    status = STATUS_SUCCESS;
                }

                break;
            }

            case IRP_MN_STOP_DEVICE: {

                //
                // These all mean nothing to the class driver currently.  The
                // port driver will handle all queueing when necessary.
                //

                DebugPrint((2, "ClassDispatchPnp (%p,%p): got stop request for %s\n",
                            DeviceObject, Irp,
                            (isFdo ? "fdo" : "pdo")
                            ));

                ASSERT(commonExtension->PagingPathCount == 0);

                //
                // ISSUE-2000/02/03-peterwie
                // if we stop the timer here then it means no class driver can
                // do i/o in its ClassStopDevice routine.  This is because the
                // retry (among other things) is tied into the tick handler
                // and disabling retries could cause the class driver to deadlock.
                // Currently no class driver we're aware of issues i/o in its
                // Stop routine but this is a case we may want to defend ourself
                // against.
                //

                if (DeviceObject->Timer) {
                    IoStopTimer(DeviceObject);
                }

                status = devInfo->ClassStopDevice(DeviceObject, IRP_MN_STOP_DEVICE);

                ASSERTMSG("ClassDispatchPnp !! STOP_DEVICE should "
                          "never be failed\n", NT_SUCCESS(status));

                if(isFdo) {
                    status = ClassForwardIrpSynchronous(commonExtension, Irp);
                }

                if(NT_SUCCESS(status)) {
                    commonExtension->CurrentState = irpStack->MinorFunction;
                    commonExtension->PreviousState = 0xff;
                }

                break;
            }

            case IRP_MN_REMOVE_DEVICE:
            case IRP_MN_SURPRISE_REMOVAL: {

                PDEVICE_OBJECT lowerDeviceObject = commonExtension->LowerDeviceObject;
                UCHAR removeType = irpStack->MinorFunction;

                if (commonExtension->PagingPathCount != 0) {
                    DBGTRACE(ClassDebugWarning, ("ClassDispatchPnp (%p,%p): paging device is getting removed!", DeviceObject, Irp));
                }

                //
                // Release the lock for this IRP before calling in.
                //
                ClassReleaseRemoveLock(DeviceObject, Irp);
                lockReleased = TRUE;

                /*
                 *  Set IsRemoved before propagating the REMOVE down the stack.
                 *  This keeps class-initiated I/O (e.g. the MCN irp) from getting sent
                 *  after we propagate the remove.
                 */
                commonExtension->IsRemoved = REMOVE_PENDING;

                /*
                 *  If a timer was started on the device, stop it.
                 */
                if (DeviceObject->Timer) {
                    IoStopTimer(DeviceObject);
                }

                /*
                 *  "Fire-and-forget" the remove irp to the lower stack.
                 *  Don't touch the irp (or the irp stack!) after this.
                 */
                if (isFdo) {
                    IoCopyCurrentIrpStackLocationToNext(Irp);
                    status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
                    ASSERT(NT_SUCCESS(status));
                    completeRequest = FALSE;
                }
                else {
                    status = STATUS_SUCCESS;
                }

                /*
                 *  Do our own cleanup and call the class driver's remove
                 *  cleanup routine.
                 *  For IRP_MN_REMOVE_DEVICE, this also deletes our device object,
                 *  so don't touch the extension after this.
                 */
                commonExtension->PreviousState = commonExtension->CurrentState;
                commonExtension->CurrentState = removeType;
                ClassRemoveDevice(DeviceObject, removeType);

                break;
            }

            case IRP_MN_DEVICE_USAGE_NOTIFICATION: {

                switch(irpStack->Parameters.UsageNotification.Type) {

                    case DeviceUsageTypePaging: {

                        BOOLEAN setPagable;

                        if((irpStack->Parameters.UsageNotification.InPath) &&
                           (commonExtension->CurrentState != IRP_MN_START_DEVICE)) {

                            //
                            // Device isn't started.  Don't allow adding a
                            // paging file, but allow a removal of one.
                            //

                            status = STATUS_DEVICE_NOT_READY;
                            break;
                        }

                        ASSERT(commonExtension->IsInitialized);

                        /*
                         *  Ensure that this user thread is not suspended while we are holding the PathCountEvent.
                         */
                        KeEnterCriticalRegion();

                        status = KeWaitForSingleObject(&commonExtension->PathCountEvent,
                                                       Executive, KernelMode,
                                                       FALSE, NULL);
                        ASSERT(NT_SUCCESS(status));
                        status = STATUS_SUCCESS;

                        //
                        // If the volume is removable we should try to lock it in
                        // place or unlock it once per paging path count
                        //

                        if (commonExtension->IsFdo){
                            status = ClasspEjectionControl(
                                            DeviceObject,
                                            Irp,
                                            InternalMediaLock,
                                            (BOOLEAN)irpStack->Parameters.UsageNotification.InPath);
                        }

                        if (!NT_SUCCESS(status)){
                            KeSetEvent(&commonExtension->PathCountEvent, IO_NO_INCREMENT, FALSE);
                            KeLeaveCriticalRegion();
                            break;
                        }

                        //
                        // 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 &&
                            commonExtension->PagingPathCount == 1
                            ) {

                            //
                            // removing last paging file
                            // must have DO_POWER_PAGABLE bits set, but only
                            // if noone set the DO_POWER_INRUSH bit
                            //


                            if (TEST_FLAG(DeviceObject->Flags, DO_POWER_INRUSH)) {
                                DebugPrint((2, "ClassDispatchPnp (%p,%p): Last "
                                            "paging file removed, but "
                                            "DO_POWER_INRUSH was set, so NOT "
                                            "setting DO_POWER_PAGABLE\n",
                                            DeviceObject, Irp));
                            } else {
                                DebugPrint((2, "ClassDispatchPnp (%p,%p): Last "
                                            "paging file removed, "
                                            "setting DO_POWER_PAGABLE\n",
                                            DeviceObject, Irp));
                                SET_FLAG(DeviceObject->Flags, DO_POWER_PAGABLE);
                                setPagable = TRUE;
                            }

                        }

                        //
                        // forward the irp before finishing handling the
                        // special cases
                        //

                        status = ClassForwardIrpSynchronous(commonExtension, 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(
                                &commonExtension->PagingPathCount,
                                irpStack->Parameters.UsageNotification.InPath);

                            if (irpStack->Parameters.UsageNotification.InPath) {
                                if (commonExtension->PagingPathCount == 1) {
                                    DebugPrint((2, "ClassDispatchPnp (%p,%p): "
                                                "Clearing PAGABLE bit\n",
                                                DeviceObject, Irp));
                                    CLEAR_FLAG(DeviceObject->Flags, DO_POWER_PAGABLE);
                                }
                            }

                        } else {

                            //
                            // cleanup the changes done above
                            //

                            if (setPagable == TRUE) {
                                DebugPrint((2, "ClassDispatchPnp (%p,%p): Unsetting "
                                            "PAGABLE bit due to irp failure\n",
                                            DeviceObject, Irp));
                                CLEAR_FLAG(DeviceObject->Flags, DO_POWER_PAGABLE);
                                setPagable = FALSE;
                            }

                            //
                            // relock or unlock the media if needed.
                            //

                            if (commonExtension->IsFdo) {

                                ClasspEjectionControl(
                                        DeviceObject,
                                        Irp,
                                        InternalMediaLock,
                                        (BOOLEAN)!irpStack->Parameters.UsageNotification.InPath);
                            }
                        }

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

                        KeSetEvent(&commonExtension->PathCountEvent,
                                   IO_NO_INCREMENT, FALSE);
                        KeLeaveCriticalRegion();
                        break;
                    }

                    case DeviceUsageTypeHibernation: {

⌨️ 快捷键说明

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