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

📄 pnp.c

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

Copyright GG Lab Corporation, All Rights Reserved

Module Name:

    pnp.c

*/

#include "GG.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, SerialGGemoveDevice)
#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);
    ASSERT(deviceExtension->TopOfStack);

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

    deviceExtension->PowerState = PowerDeviceD0;
    deviceExtension->WaitWakePending = 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
SerialGGemoveDevice(
    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, SerialGGemoveLockAndWait 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;
}

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);
            }
        
            //
            // 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 screw 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);

⌨️ 快捷键说明

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