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

📄 pnp.c

📁 书中的主要程序文件。在打开例题的.dsw文件后,请读者在 tools菜单下的 Options 的 Directories 标签中选择 Executable files
💻 C
📖 第 1 页 / 共 2 页
字号:
        break;

    case IRP_MN_STOP_DEVICE:
        //
        // After the start IRP has been sent to the lower driver object, the
        // bus may NOT send any more IRPS down ``touch'' until another START
        // has occured.
        // What ever access is required must be done before the Irp is passed
        // on.
        //

        if (deviceExtension->Started) {
            Print(deviceExtension, DBG_PNP_INFO,
                  ("Cancelling and stopping detection for stop\n"));

            deviceExtension->Started = FALSE;

            //
            // Cancel the read and stop detection
            //
            IoCancelIrp(deviceExtension->ReadIrp);
            SerialMouseStopDetection(deviceExtension);
        }

        //
        // We don't need a completion routine so fire and forget.
        //
        skipIt = TRUE;
        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_SURPRISE_REMOVAL:
        SerialGGemoveDevice(deviceExtension, Irp);
        skipIt = TRUE;
        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_REMOVE_DEVICE:
        //
        // The PlugPlay system has dictacted the removal of this device.  We
        // have no choise but to detach and delete the device objecct.
        // (If we wanted to express and interest in preventing this removal,
        // we should have filtered the query remove and query stop routines.)
        //
        // Note! we might receive a remove WITHOUT first receiving a stop.
        //
        Print(deviceExtension, DBG_PNP_TRACE, ("enter RemoveDevice \n"));

        deviceExtension->Removed = TRUE;
        SerialGGemoveDevice(deviceExtension, Irp);

        //
        // Send on the remove IRP
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation(Irp);
        status = IoCallDriver(deviceExtension->TopOfStack, Irp);

        //
        // Wait for the remove lock to free.
        //
        IoReleaseRemoveLockAndWait(&deviceExtension->RemoveLock, Irp);

        //
        // Free the associated memory.
        //
        IoFreeIrp(deviceExtension->ReadIrp);
        deviceExtension->ReadIrp = NULL;
        if (deviceExtension->DetectionIrp) {
            IoFreeIrp(deviceExtension->DetectionIrp);
            deviceExtension->DetectionIrp = NULL;
        }

        Print(deviceExtension, DBG_PNP_NOISE, ("remove and wait done\n"));

        IoDetachDevice(deviceExtension->TopOfStack);
        IoDeleteDevice(deviceExtension->Self);

        return status;

    case IRP_MN_QUERY_CAPABILITIES:

        status = SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
                                                 Irp,
                                                 TRUE);

        if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
            stack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK
                = TRUE;
        }

        //
        // status, Irp->IoStatus.Status set above
        //
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        break;

    case IRP_MN_QUERY_PNP_DEVICE_STATE:
        status = SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
                                                 Irp,
                                                 TRUE);
        //
        // If the lower filter does not support this Irp, this is
        // OK, we can ignore this error
        //
        if (status == STATUS_NOT_SUPPORTED ||
            status == STATUS_INVALID_DEVICE_REQUEST) {
            status = STATUS_SUCCESS;
        }

        if (NT_SUCCESS(status) && deviceExtension->RemovalDremoved) {
            (PNP_DEVICE_STATE) Irp->IoStatus.Information |= PNP_DEVICE_REMOVED;
        }

        if (!NT_SUCCESS(status)) {
           Print(deviceExtension, DBG_PNP_ERROR, 
                 ("error pending query pnp device state event (0x%x)\n",
                 status
                 ));
        }
   
        //
        // Irp->IoStatus.Information will contain the new i/o resource 
        // requirements list so leave it alone
        //
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        break;

    case IRP_MN_QUERY_REMOVE_DEVICE:
    case IRP_MN_CANCEL_REMOVE_DEVICE:
    case IRP_MN_QUERY_STOP_DEVICE:
    case IRP_MN_CANCEL_STOP_DEVICE:
    case IRP_MN_QUERY_DEVICE_RELATIONS:
    case IRP_MN_QUERY_INTERFACE:
    case IRP_MN_QUERY_RESOURCES:
    case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
    case IRP_MN_READ_CONFIG:
    case IRP_MN_WRITE_CONFIG:
    case IRP_MN_EJECT:
    case IRP_MN_SET_LOCK:
    case IRP_MN_QUERY_ID:
    default:
        skipIt = TRUE;
        break;
    }

    if (skipIt) {
        //
        // Don't touch the irp...
        //
        IoSkipCurrentIrpStackLocation(Irp);
        status = IoCallDriver(deviceExtension->TopOfStack, Irp);
    }

    IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);

    Print(deviceExtension, DBG_PNP_TRACE, ("PnP exit (%x)\n", status));
    return status;
}

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

Routine Description:

    The power dispatch routine.

    All we care about is the transition from a low D state to D0.
    
Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

      NT status code

--*/
{
    PIO_STACK_LOCATION  stack;
    NTSTATUS            status = STATUS_SUCCESS;
    PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
    POWER_STATE         powerState;
    POWER_STATE_TYPE    powerType;
    KEVENT              event;
    IO_STATUS_BLOCK     iosb;
    LARGE_INTEGER       li;

    PAGED_CODE();

    Print(deviceExtension, DBG_POWER_TRACE, ("Power Enter.\n"));

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    stack = IoGetCurrentIrpStackLocation(Irp);
    powerType = stack->Parameters.Power.Type;
    powerState = stack->Parameters.Power.State;

    status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, Irp);

    if (!NT_SUCCESS(status)) {
        PoStartNextPowerIrp(Irp);
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }

    switch (stack->MinorFunction) {
    case IRP_MN_WAIT_WAKE:
        break;

    case IRP_MN_SET_POWER:
        //
        // Let system power irps fall through
        //
        if (powerType == DevicePowerState &&
            powerState.DeviceState != deviceExtension->PowerState) {
            switch (powerState.DeviceState) {
            case PowerDeviceD0:

                //
                // Transitioning from a low D state to D0
                //
                Print(deviceExtension, DBG_POWER_INFO, 
                      ("Powering up to PowerDeviceD0\n"));
    
                KeInitializeEvent(&event, SynchronizationEvent, FALSE);

                deviceExtension->PoweringDown = FALSE;
                
                deviceExtension->PowerState =
                    stack->Parameters.Power.State.DeviceState;
    
                IoCopyCurrentIrpStackLocationToNext(Irp);
                IoSetCompletionRoutine(Irp,
                                       SerialMouseCompletionRoutine,
                                       &event,
                                       TRUE,                // on success
                                       TRUE,                // on error
                                       TRUE                 // on cancel
                                       );
    
                status = PoCallDriver(deviceExtension->TopOfStack, Irp);
    
                //
                // Wait for lower drivers to be done with the Irp
                //
                if (status == STATUS_PENDING) {
                   KeWaitForSingleObject(&event,
                                         Executive,
                                         KernelMode,
                                         FALSE,
                                         NULL
                                         );
                   status = Irp->IoStatus.Status;
                }

                if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
            
                    PoSetPowerState(DeviceObject, powerType, powerState);
    
                    status = SerialMouseStartDevice(deviceExtension,
                                                    Irp, 
                                                    FALSE);

                    if (!NT_SUCCESS(status)) {
                        Print(deviceExtension, DBG_POWER_INFO,
                              ("mouse not found on power up, 0x%x\n", status));

                        //
                        // The device has been removed or is not detectable
                        // after powering back up ... have serenum do the
                        // removal work 
                        //
                        KeClearEvent(&event);
            
                        SerialMouseIoSyncInternalIoctl(
                            IOCTL_INTERNAL_SERENUM_REMOVE_SELF,
                            deviceExtension->TopOfStack, 
                            &event,
                            &iosb
                            );
                    }
                }

                Irp->IoStatus.Status = status;
                IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
                PoStartNextPowerIrp(Irp);
                IoCompleteRequest(Irp, IO_NO_INCREMENT);
                return status;

            case PowerDeviceD1:
            case PowerDeviceD2:
            case PowerDeviceD3:

                deviceExtension->PoweringDown = TRUE;

                // If a wait wake is pending against the mouse, keep it powered
                //
                if (deviceExtension->WaitWakePending) {
                    Print(deviceExtension, DBG_POWER_INFO,
                          ("Ignoring power down for wait wake (-> D%d)\n",
                          powerState.DeviceState-1
                          ));
                    break;
                }

                Print(deviceExtension, DBG_POWER_INFO,
                      ("Powering down to PowerDeviceD%d\n",
                      powerState.DeviceState-1
                      ));

                //
                // Acquire another reference to the lock so that the decrement
                // in the cancel section of the completion routine will not fall
                // to zero (and have the remlock think we are removed) 
                //
//                 status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, 
  //                                            deviceExtension->ReadIrp);
                ASSERT(NT_SUCCESS(status));

                deviceExtension->PowerState =
                    stack->Parameters.Power.State.DeviceState;
    
                //
                // Cancel the read irp so that it won't conflict with power up
                // initialization (which involves some reads against the port)
                //
                IoCancelIrp(deviceExtension->ReadIrp);

                //
                // We don't want the powering down of the port to be confused
                // with removal
                //
                SerialMouseStopDetection(deviceExtension);

                //
                // Power down the device by clearing RTS and waiting 150 ms
                // 
                Print(deviceExtension, DBG_POWER_INFO, ("Clearing RTS...\n"));
                KeInitializeEvent(&event, NotificationEvent, FALSE);
                status = SerialMouseIoSyncIoctl(IOCTL_SERIAL_CLR_RTS,
                                                deviceExtension->TopOfStack, 
                                                &event,
                                                &iosb
                                                );

                if (NT_SUCCESS(status)) {
                    Print(deviceExtension, DBG_POWER_INFO, ("150ms wait\n"));

                    li = RtlConvertLongToLargeInteger(-PAUSE_150_MS);
                    KeDelayExecutionThread(KernelMode, FALSE, &li);
                }

                PoSetPowerState(DeviceObject,
                                stack->Parameters.Power.Type,
                                stack->Parameters.Power.State);

                IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);

                //
                // Fire and forget
                //
                Irp->IoStatus.Status = STATUS_SUCCESS;
                IoCopyCurrentIrpStackLocationToNext(Irp);
    
                PoStartNextPowerIrp(Irp);
                return  PoCallDriver(deviceExtension->TopOfStack, Irp);
            }
        }

        break;

    case IRP_MN_QUERY_POWER:
        break;

    default:
        Print(deviceExtension, DBG_POWER_ERROR,
              ("Power minor (0x%x) is not handled\n", stack->MinorFunction));
    }

    //
    // Must call the Po versions of these functions or bad things (tm) will happen!
    //
    PoStartNextPowerIrp(Irp);
    IoSkipCurrentIrpStackLocation(Irp);
    status = PoCallDriver(deviceExtension->TopOfStack, Irp);

    IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);

    return status;
}

⌨️ 快捷键说明

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