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

📄 pnp.c

📁 This is a serial mouse driver, which is compliant with Plug and Play, supports dynamic detection (vi
💻 C
📖 第 1 页 / 共 3 页
字号:
        //
        if (!IoCancelIrp(DeviceExtension->ReadIrp)) {
            //
            // Wait for the read irp to complete
            //
            Print(DeviceExtension, DBG_PNP_INFO, ("Waiting for stop event\n"));

            KeWaitForSingleObject(&DeviceExtension->StopEvent,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL
                                  );

            Print(DeviceExtension, DBG_PNP_INFO, ("Done waiting for stop event\n"));
        }
    }
}

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

Routine Description:

    The plug and play dispatch routines.

    Most of these this filter driver will completely ignore.
    In all cases it must pass on the IRP to the lower driver.

Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

      NT status code

--*/
{
    PDEVICE_EXTENSION   deviceExtension;
    PIO_STACK_LOCATION  stack;
    HANDLE              keyHandle;
    NTSTATUS            status;
    KIRQL               oldIrql;
    BOOLEAN             skipIt = FALSE;

    PAGED_CODE();

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    stack = IoGetCurrentIrpStackLocation(Irp);

    status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, Irp);
    if (!NT_SUCCESS(status)) {
        //
        // Someone gave us a pnp irp after a remove.  Unthinkable!
        //
        ASSERT(FALSE);
        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }

    Print(deviceExtension, DBG_PNP_TRACE,
          ("PnP Enter (min func=0x%x)\n", stack->MinorFunction));

    switch (stack->MinorFunction) {
    case IRP_MN_START_DEVICE:

        //
        // Send the actual start down the stack
        //
        status = SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
                                                 Irp,
                                                 TRUE);

        if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
            PIO_STACK_LOCATION  nextStack;

            //
            // If a create has not been sent down the stack yet, then send one
            // now.  The serial port driver reequires a create before
            // any reads or IOCTLS are to be sent.
            //
            if (InterlockedIncrement(&deviceExtension->EnableCount) == 1) {
                NTSTATUS    prevStatus;
                ULONG_PTR   prevInformation;

                //
                // No previous create has been sent, send one now
                //
                prevStatus = Irp->IoStatus.Status;
                prevInformation = Irp->IoStatus.Information;

                nextStack = IoGetNextIrpStackLocation (Irp);
                RtlZeroMemory(nextStack, sizeof(IO_STACK_LOCATION));
                nextStack->MajorFunction = IRP_MJ_CREATE;

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

                Print(deviceExtension, DBG_PNP_NOISE,
                      ("Create for start 0x%x\n", status));

                if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
                    Irp->IoStatus.Status = prevStatus;
                    Irp->IoStatus.Information = prevInformation;
                }
                else {
                    Print(deviceExtension, DBG_CC_ERROR | DBG_PNP_ERROR,
                          ("Create for start failed, 0x%x!\n", status));

                    goto SerialMouseStartFinished;
                }
            }

            //
            // Open the device registry key and read the devnode stored values
            //
            status = IoOpenDeviceRegistryKey(deviceExtension->PDO,
                                             PLUGPLAY_REGKEY_DEVICE,
                                             STANDARD_RIGHTS_READ,
                                             &keyHandle);

            if (NT_SUCCESS(status)) {
                SerialMouseServiceParameters(deviceExtension, keyHandle);
                ZwClose(keyHandle);
            }

            //
            // Handle the transition from start to stop to start correctly
            //
            SerialMouseHandleStartStopStart(deviceExtension);

            //
            // Initialize the device to make sure we can start it and report
            // data from it
            //
            status = SerialMouseInitializeDevice(deviceExtension);

            Print(deviceExtension, DBG_PNP_INFO,
                  ("Start InitializeDevice 0x%x\n", status));

            if (InterlockedDecrement(&deviceExtension->EnableCount) == 0) {
                //
                // We will start the read loop when we receive a "real" create
                // from the raw input thread.   We do not keep our own create
                // around after the start device because it will mess up the
                // logic for handling QUERY_REMOVE (our "fake" create will still
                // be in effect and the QUERY_REMOVE will fail).
                //
                Print(deviceExtension, DBG_PNP_NOISE,
                      ("sending close for start\n"));

                SerialMouseClosePort(deviceExtension, Irp);
            }
            else {
                //
                // We already have an outstanding create, just spin up the read
                // loop again
                //
                ASSERT(deviceExtension->EnableCount >= 1);

                Print(deviceExtension, DBG_PNP_INFO,
                      ("spinning up read in start\n"));

                status = SerialMouseSpinUpRead(deviceExtension);
            }
        }

SerialMouseStartFinished:
        Irp->IoStatus.Status = status;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        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.
        //

        SerialMouseStopDevice(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:
        SerialMouseRemoveDevice(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;
        SerialMouseRemoveDevice(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)) {
            PDEVICE_CAPABILITIES devCaps;

            devCaps = stack->Parameters.DeviceCapabilities.Capabilities;

            if (devCaps) {
                SYSTEM_POWER_STATE i;

                //
                // We do not want to show up in the hot plug removal applet
                //
                devCaps->SurpriseRemovalOK = TRUE;

                //
                // While the underlying serial bus might be able to wake the
                // machine from low power (via wake on ring), the mouse cannot.
                //
                devCaps->SystemWake = PowerSystemUnspecified;
                devCaps->DeviceWake = PowerDeviceUnspecified;
                devCaps->WakeFromD0 =
                    devCaps->WakeFromD1 =
                        devCaps->WakeFromD2 =
                            devCaps->WakeFromD3 = FALSE;

                devCaps->DeviceState[PowerSystemWorking] = PowerDeviceD0;
                for (i = PowerSystemSleeping1; i < PowerSystemMaximum; i++) {
                    devCaps->DeviceState[i] = PowerDeviceD3;
                }
            }
        }

        //
        // 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->RemovalDetected) {
            (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;

⌨️ 快捷键说明

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