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

📄 pnp.c

📁 鼠标Windows驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) 1997-1998 Microsoft Corporation, All Rights Reserved

Module Name:

    pnp.c

Abstract:

    This module contains plug & play code for the serial Mouse Filter Driver,
    including code for the creation and removal of serial mouse device contexts.

Environment:

    Kernel & user mode.

Revision History:

--*/

#include "mouser.h"
#include "sermlog.h"
#include "debug.h"

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, SerialMouseAddDevice)
#pragma alloc_text(PAGE, SerialMousePnP)
#pragma alloc_text(PAGE, SerialMousePower)
#pragma alloc_text(PAGE, SerialMouseRemoveDevice)
#pragma alloc_text(PAGE, SerialMouseSendIrpSynchronously)
#endif

NTSTATUS
SerialMouseAddDevice (
    IN PDRIVER_OBJECT   Driver,
    IN PDEVICE_OBJECT   PDO
    )
/*++

Routine Description:


Arguments:


Return Value:

    NTSTATUS result code.

--*/
{
    NTSTATUS            status = STATUS_SUCCESS;
    PDEVICE_EXTENSION   deviceExtension;
    PDEVICE_OBJECT      device;
    KIRQL               oldIrql;

    PAGED_CODE();

    status = IoCreateDevice(Driver,
                            sizeof(DEVICE_EXTENSION),
                            NULL, // no name for this Filter DO
                            FILE_DEVICE_SERIAL_MOUSE_PORT,
                            0,
                            FALSE,
                            &device);

    if (!NT_SUCCESS(status)) {
        return status;
    }

    deviceExtension = (PDEVICE_EXTENSION) device->DeviceExtension;

    Print(deviceExtension, DBG_PNP_TRACE, ("enter Add Device\n"));

    //
    // Initialize the fields.
    //
    RtlZeroMemory(deviceExtension, sizeof(DEVICE_EXTENSION));

    deviceExtension->TopOfStack = IoAttachDeviceToDeviceStack(device, PDO);

    if (deviceExtension->TopOfStack == NULL) {
        PIO_ERROR_LOG_PACKET errorLogEntry;

        //
        // Not good; in only extreme cases will this fail
        //
        errorLogEntry = (PIO_ERROR_LOG_PACKET)
            IoAllocateErrorLogEntry(Driver,
                                    (UCHAR) sizeof(IO_ERROR_LOG_PACKET));

        if (errorLogEntry) {
            errorLogEntry->ErrorCode = SERMOUSE_ATTACH_DEVICE_FAILED;
            errorLogEntry->DumpDataSize = 0;
            errorLogEntry->SequenceNumber = 0;
            errorLogEntry->MajorFunctionCode = 0;
            errorLogEntry->IoControlCode = 0;
            errorLogEntry->RetryCount = 0;
            errorLogEntry->UniqueErrorValue = 0;
            errorLogEntry->FinalStatus =  STATUS_DEVICE_NOT_CONNECTED;

            IoWriteErrorLogEntry(errorLogEntry);
        }

        IoDeleteDevice(device);
        return STATUS_DEVICE_NOT_CONNECTED;
    }

    ASSERT(deviceExtension->TopOfStack);

    deviceExtension->PDO = PDO;
    deviceExtension->Self = device;
    deviceExtension->Removed = FALSE;
    deviceExtension->Started = FALSE;
    deviceExtension->Stopped = FALSE;


    deviceExtension->PowerState = PowerDeviceD0;
    deviceExtension->WaitWakePending = FALSE;

    KeInitializeSpinLock(&deviceExtension->PnpStateLock);
    KeInitializeEvent(&deviceExtension->StopEvent, SynchronizationEvent, FALSE);
    IoInitializeRemoveLock(&deviceExtension->RemoveLock, SERMOU_POOL_TAG, 0, 10);

    deviceExtension->ReadIrp = IoAllocateIrp( device->StackSize, FALSE );
    if (!deviceExtension->ReadIrp) {
        //
        // The ReadIrp is critical to this driver, if we can't get one, no use
        // in going any further
        //
        IoDetachDevice(deviceExtension->TopOfStack);
        IoDeleteDevice(device);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    deviceExtension->WmiLibInfo.GuidCount = sizeof(WmiGuidList) /
                                            sizeof(WMIGUIDREGINFO);

    deviceExtension->WmiLibInfo.GuidList = WmiGuidList;
    deviceExtension->WmiLibInfo.QueryWmiRegInfo = SerialMouseQueryWmiRegInfo;
    deviceExtension->WmiLibInfo.QueryWmiDataBlock = SerialMouseQueryWmiDataBlock;
    deviceExtension->WmiLibInfo.SetWmiDataBlock = SerialMouseSetWmiDataBlock;
    deviceExtension->WmiLibInfo.SetWmiDataItem = SerialMouseSetWmiDataItem;
    deviceExtension->WmiLibInfo.ExecuteWmiMethod = NULL;
    deviceExtension->WmiLibInfo.WmiFunctionControl = NULL;

    IoWMIRegistrationControl(deviceExtension->Self, WMIREG_ACTION_REGISTER);

    KeInitializeTimer(&deviceExtension->DelayTimer);

    //
    // Set all the appropriate device object flags
    //
    device->Flags &= ~DO_DEVICE_INITIALIZING;
    device->Flags |= DO_BUFFERED_IO;
    device->Flags |= DO_POWER_PAGABLE;

    return status;
}

VOID
SerialMouseRemoveDevice(
    PDEVICE_EXTENSION DeviceExtension,
    PIRP Irp
    )
{
    BOOLEAN closePort = FALSE;

    PAGED_CODE();

    //
    // Run the (surprise remove code).  If we are surprise removed, then this
    // will be called twice.  We only run the removal code once.
    //
    if (!DeviceExtension->SurpriseRemoved) {
        DeviceExtension->SurpriseRemoved = TRUE;

        //
        // Here if we had any outstanding requests in a personal queue we should
        // complete them all now.
        //
        // Note, the device could be GONE so we cannot send it any non-
        // PNP IRPS.
        //
        IoWMIRegistrationControl(DeviceExtension->Self, WMIREG_ACTION_DEREGISTER);

        if (DeviceExtension->Started && DeviceExtension->EnableCount > 0) {
            Print(DeviceExtension, DBG_PNP_INFO,
                  ("Cancelling and stopping detection for remove\n"));
            IoCancelIrp(DeviceExtension->ReadIrp);

            //
            // Cancel the detection timer, SerialMouseRemoveLockAndWait will
            // guarantee that we don't yank the device from under the polling
            // routine
            //
            SerialMouseStopDetection(DeviceExtension);

        }
    }

    //
    // The stack is about to be torn down, make sure that the underlying serial
    // port is closed.  No other piece of code will be looking at EnableCount if
    // Remove is true, so there is no need for InterlockedXxx.
    //
    if (DeviceExtension->Removed && DeviceExtension->EnableCount > 0) {
        Print(DeviceExtension, DBG_PNP_INFO | DBG_PNP_ERROR,
              ("sending final close, enable count %d\n",
              DeviceExtension->EnableCount));

        DeviceExtension->EnableCount = 0;

        SerialMouseClosePort(DeviceExtension, Irp);
    }
}

NTSTATUS
SerialMouseCompletionRoutine (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp,
    IN PKEVENT        Event
    )
/*++

Routine Description:
    The pnp IRP is in the process of completing.
    signal

Arguments:
    Context set to the device object in question.

--*/
{
    UNREFERENCED_PARAMETER(DeviceObject);
    UNREFERENCED_PARAMETER(Irp);

    KeSetEvent(Event, 0, FALSE);

    return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
SerialMouseSendIrpSynchronously (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN BOOLEAN          CopyToNext
    )
{
    KEVENT      event;
    NTSTATUS    status;

    PAGED_CODE();

    KeInitializeEvent(&event, SynchronizationEvent, FALSE);

    if (CopyToNext) {
        IoCopyCurrentIrpStackLocationToNext(Irp);
    }

    IoSetCompletionRoutine(Irp,
                           SerialMouseCompletionRoutine,
                           &event,
                           TRUE,                // on success
                           TRUE,                // on error
                           TRUE                 // on cancel
                           );

    status = IoCallDriver(DeviceObject, 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;
    }

    return status;
}

void
SerialMouseHandleStartStopStart(
    IN PDEVICE_EXTENSION DeviceExtension
    )
{
    KIRQL irql;

    KeAcquireSpinLock(&DeviceExtension->PnpStateLock, &irql);

    if (DeviceExtension->Stopped) {
        DeviceExtension->Stopped = FALSE;
        IoReuseIrp(DeviceExtension->ReadIrp, STATUS_SUCCESS);
    }

    KeReleaseSpinLock(&DeviceExtension->PnpStateLock, irql);
}

void
SerialMouseStopDevice (
    IN PDEVICE_EXTENSION DeviceExtension
    )
{
    KIRQL irql;

    KeAcquireSpinLock(&DeviceExtension->PnpStateLock, &irql);
    DeviceExtension->Stopped = TRUE;
    KeReleaseSpinLock(&DeviceExtension->PnpStateLock, irql);

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

        DeviceExtension->Started = FALSE;

        //
        // Stop detection and cancel the read
        //
        SerialMouseStopDetection(DeviceExtension);

        //
        // BUGBUG:  should I only wait if IoCancelIrp fails?

⌨️ 快捷键说明

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