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

📄 pnp.c

📁 enumerates Plug-n-Play RS-232 devices that are compliant with the current revision of Plug and Play
💻 C
📖 第 1 页 / 共 3 页
字号:
                    NULL,
                    NULL))) {
                    Serenum_KdPrint (DeviceData,SER_DBG_PNP_ERROR,
                        ("Failed to get debug level from registry.  Using default\n"));
                    DeviceData->DebugLevel = DebugLevelDefault;
                }

                ExFreePool( QueryTable );
            }


            Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                             ("Start Device: Device started successfully\n"));
            DeviceData->Started = TRUE;

            Serenum_StartPolling(DeviceData, SERENUM_STOP_LOCK);
        }

        //
        // We must now complete the IRP, since we stopped it in the
        // completetion routine with MORE_PROCESSING_REQUIRED.
        //
        break;

    case IRP_MN_QUERY_STOP_DEVICE:
        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
            ("Query Stop Device\n"));

        //
        // Test to see if there are any PDO created as children of this FDO
        // If there are then conclude the device is busy and fail the
        // query stop.
        //
        // CIMEXCIMEX
        // We could do better, by seing if the children PDOs are actually
        // currently open.  If they are not then we could stop, get new
        // resouces, fill in the new resouce values, and then when a new client
        // opens the PDO use the new resources.  But this works for now.
        //
        if (DeviceData->AttachedPDO) {
            status = STATUS_UNSUCCESSFUL;

        } else {
            status = STATUS_SUCCESS;
        }

        Irp->IoStatus.Status = status;

        if (NT_SUCCESS(status)) {
           IoSkipCurrentIrpStackLocation (Irp);
           status = IoCallDriver (DeviceData->TopOfStack, Irp);
        } else {
          IoCompleteRequest(Irp, IO_NO_INCREMENT);
        }

        Serenum_DecIoCount (DeviceData);
        return status;

    case IRP_MN_STOP_DEVICE:
        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE, ("Stop Device\n"));

        //
        // 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.
        //
        // Stop device means that the resources given durring Start device
        // are no revoked.  So we need to stop using them
        //

        if (DeviceData->Started) {
            Serenum_StopPolling(DeviceData, SERENUM_STOP_LOCK);
        }

        DeviceData->Started = FALSE;

        //
        // We don't need a completion routine so fire and forget.
        //
        // Set the current stack location to the next stack location and
        // call the next device object.
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation (Irp);
        status = IoCallDriver (DeviceData->TopOfStack, Irp);

        Serenum_DecIoCount (DeviceData);
        return status;

    case IRP_MN_REMOVE_DEVICE:
        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE, ("Remove Device\n"));

        //
        // The PlugPlay system has detected the removal of this device.  We
        // have no choice but to detach and delete the device object.
        // (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.
        // ASSERT (!DeviceData->Removed);

        // We will accept no new requests
        //
        DeviceData->Removed = TRUE;

        //
        // Complete any outstanding IRPs queued by the driver here.
        //

        //
        // Make the DCA go away.  Some drivers may choose to remove the DCA
        // when they receive a stop or even a query stop.  We just don't care.
        //
        IoSetDeviceInterfaceState (&DeviceData->DevClassAssocName, FALSE);

        //
        // Here if we had any outstanding requests in a personal queue we should
        // complete them all now.
        //
        // Note, the device is guarenteed stopped, so we cannot send it any non-
        // PNP IRPS.
        //

        //
        // Fire and forget
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation (Irp);
        IoCallDriver (DeviceData->TopOfStack, Irp);

        //
        // Wait for all outstanding requests to complete
        //
        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
            ("Waiting for outstanding requests\n"));
        i = InterlockedDecrement (&DeviceData->OutstandingIO);

        ASSERT (0 < i);

        if (0 != InterlockedDecrement (&DeviceData->OutstandingIO)) {
            Serenum_KdPrint (DeviceData, SER_DBG_PNP_INFO,
                          ("Remove Device waiting for request to complete\n"));

            KeWaitForSingleObject (&DeviceData->RemoveEvent,
                                   Suspended,
                                   KernelMode,
                                   FALSE, // Not Alertable
                                   NULL); // No timeout
        }
        //
        // Free the associated resources
        //

        //
        // Detach from the underlying devices.
        //
        Serenum_KdPrint(DeviceData, SER_DBG_PNP_INFO,
                        ("IoDetachDevice: 0x%x\n", DeviceData->TopOfStack));
        IoDetachDevice (DeviceData->TopOfStack);

        //
        // Clean up any resources here
        //
        if (DeviceData->Started) {
            Serenum_StopPolling(DeviceData, SERENUM_STOP_LOCK);
        }

	if (DeviceData->PollingWorker != NULL) {
            IoFreeWorkItem(DeviceData->PollingWorker);
	    DeviceData->PollingWorker = NULL;
	}

        ExFreePool (DeviceData->DevClassAssocName.Buffer);
        Serenum_KdPrint(DeviceData, SER_DBG_PNP_INFO,
                        ("IoDeleteDevice: 0x%x\n", DeviceObject));

        //
        // Remove any PDO's we ejected
        //

        if (DeviceData->AttachedPDO != NULL) {
           ASSERT(DeviceData->NumPDOs == 1);

           Serenum_PnPRemove(DeviceData->AttachedPDO, DeviceData->PdoData);
           DeviceData->PdoData = NULL;
           DeviceData->AttachedPDO = NULL;
           DeviceData->NumPDOs = 0;
        }

        IoDeleteDevice(DeviceObject);

        return STATUS_SUCCESS;

    case IRP_MN_QUERY_DEVICE_RELATIONS:
        if (BusRelations != IrpStack->Parameters.QueryDeviceRelations.Type) {
            //
            // We don't support this
            //
            Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                ("Query Device Relations - Non bus\n"));
            goto SER_FDO_PNP_DEFAULT;
        }

        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
            ("Query Bus Relations\n"));
        Serenum_StopPolling(DeviceData, SERENUM_QDR_LOCK);

        // Check for new devices or if old devices still there.
        if (DeviceData->PollingPeriod != (ULONG)-1) {

            status = Serenum_ReenumerateDevices(Irp, DeviceData);
        }

        //
        // Tell the plug and play system about all the PDOs.
        //
        // There might also be device relations below and above this FDO,
        // so, be sure to propagate the relations from the upper drivers.
        //
        // No Completion routine is needed so long as the status is preset
        // to success.  (PDOs complete plug and play irps with the current
        // IoStatus.Status and IoStatus.Information as the default.)
        //

        //KeAcquireSpinLock (&DeviceData->Spin, &oldIrq);

        i = (0 == Irp->IoStatus.Information) ? 0 :
            ((PDEVICE_RELATIONS) Irp->IoStatus.Information)->Count;
        // The current number of PDOs in the device relations structure

        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                           ("#PDOS = %d + %d\n", i, DeviceData->NumPDOs));

        length = sizeof(DEVICE_RELATIONS) +
                ((DeviceData->NumPDOs + i) * sizeof (PDEVICE_OBJECT));

        relations = (PDEVICE_RELATIONS) ExAllocatePool (NonPagedPool, length);

        if (NULL == relations) {
           Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
           IoCompleteRequest(Irp, IO_NO_INCREMENT);
           Serenum_DecIoCount(DeviceData);
           return STATUS_INSUFFICIENT_RESOURCES;
        }

        //
        // Copy in the device objects so far
        //
        if (i) {
            RtlCopyMemory (
                  relations->Objects,
                  ((PDEVICE_RELATIONS) Irp->IoStatus.Information)->Objects,
                  i * sizeof (PDEVICE_OBJECT));
        }
        relations->Count = DeviceData->NumPDOs + i;

        //
        // For each PDO on this bus add a pointer to the device relations
        // buffer, being sure to take out a reference to that object.
        // The PlugPlay system will dereference the object when it is done with
        // it and free the device relations buffer.
        //

        if (DeviceData->NumPDOs) {
            relations->Objects[relations->Count-1] = DeviceData->AttachedPDO;
            ObReferenceObject (DeviceData->AttachedPDO);
        }

        //
        // Set up and pass the IRP further down the stack
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;

        if (0 != Irp->IoStatus.Information) {
            ExFreePool ((PVOID) Irp->IoStatus.Information);
        }
        Irp->IoStatus.Information = (ULONG_PTR)relations;

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

        Serenum_StartPolling(DeviceData, SERENUM_QDR_LOCK);

        Serenum_DecIoCount (DeviceData);

        return status;

    case IRP_MN_QUERY_REMOVE_DEVICE:
        //
        // If we were to fail this call then we would need to complete the
        // IRP here.  Since we are not, set the status to SUCCESS and
        // call the next driver.
        //

        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
            ("Query Remove Device\n"));
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation (Irp);
        status = IoCallDriver (DeviceData->TopOfStack, Irp);
        Serenum_DecIoCount (DeviceData);
        return status;


    case IRP_MN_QUERY_CAPABILITIES: {

        PIO_STACK_LOCATION  irpSp;

        //
        // Send this down to the PDO first
        //

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

            irpSp = IoGetCurrentIrpStackLocation(Irp);

            DeviceData->SystemWake=irpSp->Parameters.DeviceCapabilities.Capabilities->SystemWake;
            DeviceData->DeviceWake=irpSp->Parameters.DeviceCapabilities.Capabilities->DeviceWake;
        }

        break;
    }



SER_FDO_PNP_DEFAULT:
    default:
        //
        // In the default case we merely call the next driver since
        // we don't know what to do.
        //
        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE, ("Default Case\n"));

        //
        // Fire and Forget
        //
        IoSkipCurrentIrpStackLocation (Irp);

        //
        // Done, do NOT complete the IRP, it will be processed by the lower
        // device object, which will complete the IRP
        //

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

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

    Serenum_DecIoCount (DeviceData);
    return status;
}


NTSTATUS
Serenum_FDO_PnPComplete (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
/*++
Routine Description:
    A completion routine for use when calling the lower device objects to
    which our bus (FDO) is attached.

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

    KeSetEvent ((PKEVENT) Context, 1, FALSE);
    // No special priority
    // No Wait

    return STATUS_MORE_PROCESSING_REQUIRED; // Keep this IRP
}

NTSTATUS
Serenum_PDO_PnP (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
                 IN PIO_STACK_LOCATION IrpStack, IN PPDO_DEVICE_DATA DeviceData)
/*++
Routine Description:
    Handle requests from the PlugPlay system for the devices on the BUS

--*/
{
   PDEVICE_CAPABILITIES    deviceCapabilities;
   ULONG                   information;
   PWCHAR                  buffer;
   ULONG                   length, i, j;
   NTSTATUS                status;
   KIRQL                   oldIrq;
   HANDLE                  keyHandle;
   UNICODE_STRING          keyName;
   ULONG                   PollingPeriod;
   PWCHAR returnBuffer = NULL;

   PAGED_CODE();

⌨️ 快捷键说明

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