📄 pnp.c
字号:
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 + -