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

📄 pnp.c

📁 enumerates Plug-n-Play RS-232 devices that are compliant with the current revision of Plug and Play
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++
Copyright (c) 1998  Microsoft Corporation

Module Name:

    PNP.C

Abstract:

    This module contains contains the plugplay calls
    PNP / WDM BUS driver.


Environment:

    kernel mode only

Notes:


--*/

#include "pch.h"

#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, Serenum_AddDevice)
#pragma alloc_text (PAGE, Serenum_PnP)
#pragma alloc_text (PAGE, Serenum_FDO_PnP)
#pragma alloc_text (PAGE, Serenum_PDO_PnP)
#pragma alloc_text (PAGE, Serenum_PnPRemove)
//#pragma alloc_text (PAGE, Serenum_Remove)
#endif


NTSTATUS
Serenum_AddDevice(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT BusPhysicalDeviceObject
    )
/*++
Routine Description.
    A bus has been found.  Attach our FDO to it.
    Allocate any required resources.  Set things up.  And be prepared for the
    first ``start device.''

Arguments:
    BusPhysicalDeviceObject - Device object representing the bus.  That to which
        we attach a new FDO.

    DriverObject - This very self referenced driver.

--*/
{
    NTSTATUS            status;
    PDEVICE_OBJECT      deviceObject;
    PFDO_DEVICE_DATA    DeviceData;
    ULONG               nameLength;

    PAGED_CODE ();

    Serenum_KdPrint_Def (SER_DBG_PNP_TRACE, ("Add Device: 0x%x\n",
                                          BusPhysicalDeviceObject));
    //
    // Create our FDO
    //

    status = IoCreateDevice (
                    DriverObject,  // our driver object
                    sizeof (FDO_DEVICE_DATA), // device object extension size
                    NULL, // FDOs do not have names
                    FILE_DEVICE_BUS_EXTENDER,
                    0, // No special characteristics
                    TRUE, // our FDO is exclusive
                    &deviceObject); // The device object created

    if (NT_SUCCESS (status)) {
        DeviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension;
        RtlFillMemory (DeviceData, sizeof (FDO_DEVICE_DATA), 0);

        DeviceData->IsFDO = TRUE;
        DeviceData->DebugLevel = SER_DEFAULT_DEBUG_OUTPUT_LEVEL;
        DeviceData->Self = deviceObject;
        DeviceData->AttachedPDO = NULL;
        DeviceData->NumPDOs = 0;
        DeviceData->DeviceState = PowerDeviceD0;
        DeviceData->SystemState = PowerSystemWorking;
        DeviceData->LastSetPowerState = PowerDeviceD0;
        DeviceData->PDOLegacyEnumerated = FALSE;
        DeviceData->PDOForcedRemove = FALSE;
        DeviceData->PollingLocks = 0;
        DeviceData->Polling = 0;

        DeviceData->SystemWake=PowerSystemUnspecified;
        DeviceData->DeviceWake=PowerDeviceUnspecified;

        DeviceData->PollingWorker = IoAllocateWorkItem(deviceObject);

        if (DeviceData->PollingWorker == NULL) {
           Serenum_KdPrint(DeviceData, SER_DBG_SS_ERROR,
                           ("Insufficient memory for Polling Routine.\n"));

           return STATUS_INSUFFICIENT_RESOURCES;
        }

        //
        // Initialize the timer used for dynamic detection of attachment
        // and removal of PNP devices.
        //
        KeInitializeTimerEx(
            &DeviceData->PollingTimer,
            NotificationTimer);

        DeviceData->Removed = FALSE;

        // Set the PDO for use with PlugPlay functions
        DeviceData->UnderlyingPDO = BusPhysicalDeviceObject;


        //
        // Attach our filter driver to the device stack.
        // the return value of IoAttachDeviceToDeviceStack is the top of the
        // attachment chain.  This is where all the IRPs should be routed.
        //
        // Our filter will send IRPs to the top of the stack and use the PDO
        // for all PlugPlay functions.
        //
        DeviceData->TopOfStack = IoAttachDeviceToDeviceStack (
                                        deviceObject,
                                        BusPhysicalDeviceObject);

        // Bias outstanding request to 1 so that we can look for a
        // transition to zero when processing the remove device PlugPlay IRP.
        DeviceData->OutstandingIO = 1;

        KeInitializeEvent(&DeviceData->RemoveEvent,
                          SynchronizationEvent,
                          FALSE); // initialized to not signalled

        deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
        deviceObject->Flags |= DO_POWER_PAGABLE;

        //
        // Tell the PlugPlay system that this device will need an interface
        // device class shingle.
        //
        // It may be that the driver cannot hang the shingle until it starts
        // the device itself, so that it can query some of its properties.
        // (Aka the shingles guid (or ref string) is based on the properties
        // of the device.)
        //
        status = IoRegisterDeviceInterface (
                    BusPhysicalDeviceObject,
                    (LPGUID) &GUID_SERENUM_BUS_ENUMERATOR,
                    NULL, // No ref string
                    &DeviceData->DevClassAssocName);

        if (!NT_SUCCESS (status)) {
            Serenum_KdPrint (DeviceData, SER_DBG_PNP_ERROR,
                          ("AddDevice: IoRegisterDCA failed (%x)", status));
            IoFreeWorkItem(DeviceData->PollingWorker);
            IoDetachDevice (DeviceData->TopOfStack);
            IoDeleteDevice (deviceObject);
            return status;
        }

        //
        // If for any reason you need to save values in a safe location that
        // clients of this DeviceClassAssociate might be interested in reading
        // here is the time to do so, with the function
        // IoOpenDeviceClassRegistryKey
        // the symbolic link name used is was returned in
        // DeviceData->DevClassAssocName (the same name which is returned by
        // IoGetDeviceClassAssociations and the SetupAPI equivs.
        //

#if DBG
      {
         PWCHAR deviceName = NULL;

         status = IoGetDeviceProperty (BusPhysicalDeviceObject,
                                       DevicePropertyPhysicalDeviceObjectName,
                                       0,
                                       NULL,
                                       &nameLength);

         if ((nameLength != 0) && (status == STATUS_BUFFER_TOO_SMALL)) {
            deviceName = ExAllocatePool (NonPagedPool, nameLength);

            if (NULL == deviceName) {
               goto someDebugStuffExit;
            }

            IoGetDeviceProperty (BusPhysicalDeviceObject,
                                 DevicePropertyPhysicalDeviceObjectName,
                                 nameLength, deviceName, &nameLength);

            Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                             ("AddDevice: %x to %x->%x (%ws) \n",
                              deviceObject, DeviceData->TopOfStack,
                              BusPhysicalDeviceObject, deviceName));
         }

someDebugStuffExit:;
         if (deviceName != NULL) {
            ExFreePool(deviceName);
         }
      }
#endif

        //
        // Turn on the shingle and point it to the given device object.
        //
        status = IoSetDeviceInterfaceState (
                        &DeviceData->DevClassAssocName,
                        TRUE);

        if (!NT_SUCCESS (status)) {
            Serenum_KdPrint (DeviceData, SER_DBG_PNP_ERROR,
                          ("AddDevice: IoSetDeviceClass failed (%x)", status));
            return status;
        }

        DeviceData->PollingAllowed = 0;
        DeviceData->PollingNotQueued = 1;

        KeInitializeEvent(&DeviceData->PollingEvent, SynchronizationEvent,
                          FALSE);
        KeInitializeEvent(&DeviceData->PollStateEvent, SynchronizationEvent,
                          TRUE);

        KeInitializeDpc(
            &DeviceData->DPCPolling,
            (PKDEFERRED_ROUTINE) Serenum_PollingTimerRoutine,
            DeviceData);
    }

    return status;
}

NTSTATUS
Serenum_FDO_PnPComplete (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Pirp,
    IN PVOID            Context
    );

NTSTATUS
Serenum_PnP (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp
    )
/*++
Routine Description:
    Answer the plethora of Irp Major PnP IRPS.
--*/
{
    PIO_STACK_LOCATION      irpStack;
    NTSTATUS                status;
    PCOMMON_DEVICE_DATA     commonData;
    KIRQL                   oldIrq;

    PAGED_CODE ();

    status = STATUS_SUCCESS;
    irpStack = IoGetCurrentIrpStackLocation (Irp);
    ASSERT (IRP_MJ_PNP == irpStack->MajorFunction);

    commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;

    if (commonData->Removed) {

        Serenum_KdPrint (commonData, SER_DBG_PNP_TRACE,
                      ("PNP: removed DO: %x got IRP: %x\n", DeviceObject, Irp));

        Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

    } else if (commonData->IsFDO) {
        Serenum_KdPrint (commonData, SER_DBG_PNP_TRACE,
                      ("PNP: Functional DO: %x IRP: %x\n", DeviceObject, Irp));

        status = Serenum_FDO_PnP (
                    DeviceObject,
                    Irp,
                    irpStack,
                    (PFDO_DEVICE_DATA) commonData);

    } else {
        Serenum_KdPrint (commonData, SER_DBG_PNP_TRACE,
                      ("PNP: Physical DO: %x IRP: %x\n", DeviceObject, Irp));

        status = Serenum_PDO_PnP (
                    DeviceObject,
                    Irp,
                    irpStack,
                    (PPDO_DEVICE_DATA) commonData);
    }

    return status;
}

NTSTATUS
Serenum_FDO_PnP (
    IN PDEVICE_OBJECT       DeviceObject,
    IN PIRP                 Irp,
    IN PIO_STACK_LOCATION   IrpStack,
    IN PFDO_DEVICE_DATA     DeviceData
    )
/*++
Routine Description:
    Handle requests from the PlugPlay system for the BUS itself

    NB: the various Minor functions of the PlugPlay system will not be
    overlapped and do not have to be reentrant

--*/
{
    NTSTATUS    status;
    KIRQL       oldIrq;
    KEVENT      event;
    ULONG       length;
    ULONG       i;
    PLIST_ENTRY entry;
    PPDO_DEVICE_DATA    pdoData;
    PDEVICE_RELATIONS   relations;
    PIO_STACK_LOCATION  stack;
    PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
    ULONG DebugLevelDefault = SER_DEFAULT_DEBUG_OUTPUT_LEVEL;

    PAGED_CODE ();

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

    stack = IoGetCurrentIrpStackLocation (Irp);

    switch (IrpStack->MinorFunction) {
    case IRP_MN_START_DEVICE:
        //
        // BEFORE you are allowed to ``touch'' the device object to which
        // the FDO is attached (that send an irp from the bus to the Device
        // object to which the bus is attached).   You must first pass down
        // the start IRP.  It might not be powered on, or able to access or
        // something.
        //

        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE, ("Start Device\n"));

        if (DeviceData->Started) {
            Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                ("Device already started\n"));
            status = STATUS_SUCCESS;
            break;
        }

        KeInitializeEvent (&event, NotificationEvent, FALSE);
        IoCopyCurrentIrpStackLocationToNext (Irp);

        IoSetCompletionRoutine (Irp,
                                Serenum_FDO_PnPComplete,
                                &event,
                                TRUE,
                                TRUE,
                                TRUE);

        status = IoCallDriver (DeviceData->TopOfStack, Irp);

        if (STATUS_PENDING == status) {
            // wait for it...

            status = KeWaitForSingleObject (&event,
                                            Executive,
                                            KernelMode,
                                            FALSE, // Not allertable
                                            NULL); // No timeout structure

            ASSERT (STATUS_SUCCESS == status);

            status = Irp->IoStatus.Status;
        }

        if (NT_SUCCESS(status)) {
            //
            // Now we can touch the lower device object as it is now started.
            //

            if (DeviceData->TopOfStack->Flags & DO_BUFFERED_IO) {
                DeviceObject->Flags |= DO_BUFFERED_IO;
            } else if (DeviceData->TopOfStack->Flags & DO_DIRECT_IO) {
                DeviceObject->Flags |= DO_DIRECT_IO;
            }

            //
            // Get the debug level from the registry
            //

            if (NULL == (QueryTable = ExAllocatePool(
                               PagedPool,
                               sizeof(RTL_QUERY_REGISTRY_TABLE)*2
                               ))) {
                Serenum_KdPrint (DeviceData, SER_DBG_PNP_ERROR,
                    ("Failed to allocate memory to query registy\n"));
                DeviceData->DebugLevel = DebugLevelDefault;
            } else {
                RtlZeroMemory(
                         QueryTable,
                         sizeof(RTL_QUERY_REGISTRY_TABLE)*2
                         );

                QueryTable[0].QueryRoutine = NULL;
                QueryTable[0].Flags         = RTL_QUERY_REGISTRY_DIRECT;
                QueryTable[0].EntryContext = &DeviceData->DebugLevel;
                QueryTable[0].Name      = L"DebugLevel";
                QueryTable[0].DefaultType   = REG_DWORD;
                QueryTable[0].DefaultData   = &DebugLevelDefault;
                QueryTable[0].DefaultLength= sizeof(ULONG);

                // CIMEXCIMEX: The rest of the table isn't filled in!

                if (!NT_SUCCESS(RtlQueryRegistryValues(
                    RTL_REGISTRY_SERVICES,
                    L"Serenum",
                    QueryTable,

⌨️ 快捷键说明

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