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

📄 pnp.c

📁 This is a serial mouse driver, which is compliant with Plug and Play, supports dynamic detection (vi
💻 C
📖 第 1 页 / 共 3 页
字号:
    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;
}

typedef struct _MOUSER_START_WORKITEM {
    PDEVICE_EXTENSION   DeviceExtension;
    PIO_WORKITEM        WorkItem;
} MOUSER_START_WORKITEM, *PMOUSER_START_WORKITEM;

VOID
StartDeviceWorker (
    IN PDEVICE_OBJECT DeviceObject,
    IN PMOUSER_START_WORKITEM WorkItemContext
    )
{
    PDEVICE_EXTENSION deviceExtension = WorkItemContext->DeviceExtension;
    NTSTATUS status;
    PIRP irp;

    if (deviceExtension->Started &&
        !deviceExtension->Removed &&
        deviceExtension->EnableCount > 0) {
        irp = IoAllocateIrp( deviceExtension->Self->StackSize, FALSE );
        if (irp) {
            status = SerialMouseStartDevice(deviceExtension,
                                            irp,
                                            FALSE);

            if (!NT_SUCCESS(status)) {
                KEVENT              event;
                IO_STATUS_BLOCK     iosb;

                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
                //
                KeInitializeEvent(&event, SynchronizationEvent, FALSE);

                SerialMouseIoSyncInternalIoctl(
                    IOCTL_INTERNAL_SERENUM_REMOVE_SELF,
                    deviceExtension->TopOfStack,
                    &event,
                    &iosb
                    );
            }
            IoFreeIrp(irp);
        }
    }

    IoFreeWorkItem(WorkItemContext->WorkItem);
    ExFreePool(WorkItemContext);
    IoReleaseRemoveLock(&deviceExtension->RemoveLock, deviceExtension);
}

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);

                    if (NT_SUCCESS(IoAcquireRemoveLock(&deviceExtension->RemoveLock, deviceExtension))) {
                        PIO_WORKITEM workItem;
                        PMOUSER_START_WORKITEM workItemContext;

                        workItem = IoAllocateWorkItem(DeviceObject);

                        if (workItem) {
                            workItemContext = ExAllocatePool(NonPagedPool, sizeof(MOUSER_START_WORKITEM));
                            if (workItemContext) {
                                workItemContext->WorkItem = workItem;
                                workItemContext->DeviceExtension = deviceExtension;
                                IoQueueWorkItem(
                                    workItem,
                                    StartDeviceWorker,
                                    DelayedWorkQueue,
                                    workItemContext);
                            } else {
                                IoFreeWorkItem(workItem);
                                IoReleaseRemoveLock(&deviceExtension->RemoveLock, deviceExtension);
                            }
                        } else {
                            IoReleaseRemoveLock(&deviceExtension->RemoveLock, deviceExtension);
                        }
                    }
                }

                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.QuadPart = (LONGLONG) -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 + -