📄 plugplayfdo.cpp
字号:
if (pdx->sarefcnt)
return CompleteRequest(Irp, STATUS_UNSUCCESSFUL); // have referenced suballoc interface
if (pdx->state == WORKING)
{ // currently working
#ifdef _X86_
// Win98 doesn't check for open handles before allowing a remove to proceed,
// and it may deadlock in IoReleaseRemoveLockAndWait if handles are still
// open.
if (win98 && pdx->DeviceObject->ReferenceCount)
{
KdPrint((DRIVERNAME " - Failing removal query due to open handles\n"));
return CompleteRequest(Irp, STATUS_DEVICE_BUSY, 0);
}
#endif
KdPrint((DRIVERNAME " - To PENDINGREMOVE from %s\n", statenames[pdx->state]));
} // currently working
// Save current state for restoration if the query gets cancelled.
// (We can now be stopped or working)
pdx->prevstate = pdx->state;
pdx->state = PENDINGREMOVE;
return DefaultPnpHandler(fdo, Irp);
} // HandleQueryRemove
///////////////////////////////////////////////////////////////////////////////
static NTSTATUS HandleQueryStop(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleQueryStop
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
if (pdx->sarefcnt)
return CompleteRequest(Irp, STATUS_UNSUCCESSFUL); // have referenced suballoc interface
// Boot devices may get this query before they even start, so check to see
// if we're in the WORKING state before doing anything.
if (pdx->state != WORKING)
return DefaultPnpHandler(fdo, Irp);
KdPrint((DRIVERNAME " - To PENDINGSTOP from %s\n", statenames[pdx->state]));
pdx->state = PENDINGSTOP;
return DefaultPnpHandler(fdo, Irp);
} // HandleQueryStop
///////////////////////////////////////////////////////////////////////////////
static NTSTATUS HandleRemoveDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleRemoveDevice
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
// Win98 doesn't send a SURPRISE_REMOVE, so now is the first time we'll
// know that the device was removed.
if (pdx->state != PENDINGREMOVE && pdx->state != SURPRISEREMOVED)
{ // Win98 surprise removal
KdPrint((DRIVERNAME " - IRP_MN_REMOVE_DEVICE received by surprise\n"));
StopDevice(fdo, FALSE);
} // Win98 surprise removal
KdPrint((DRIVERNAME " - To REMOVED from %s\n", statenames[pdx->state]));
pdx->state = REMOVED;
IoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp);
// Do any processing required for *us* to remove the device. This
// would include completing any outstanding requests, etc. In general,
// the routine we call here should not touch the hardware because it
// may already be gone.
StopDevice(fdo, FALSE);
// Let lower-level drivers handle this request. Ignore whatever
// result eventuates.
NTSTATUS status = DefaultPnpHandler(fdo, Irp);
// Remove the device object
RemoveDevice(fdo);
return status; // lower-level completed IoStatus already
} // HandleRemoveDevice
///////////////////////////////////////////////////////////////////////////////
static NTSTATUS HandleStartDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleStartDevice
NTSTATUS status = ForwardAndWait(fdo, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, Irp->IoStatus.Information);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
PCM_PARTIAL_RESOURCE_LIST raw;
if (stack->Parameters.StartDevice.AllocatedResources)
raw = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
else
raw = NULL;
PCM_PARTIAL_RESOURCE_LIST translated;
if (stack->Parameters.StartDevice.AllocatedResourcesTranslated)
translated = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
else
translated = NULL;
#if DBG
if (raw)
{
KdPrint((DRIVERNAME " - Resources:\n"));
ShowResources(raw);
}
if (translated)
{
KdPrint((DRIVERNAME " - Translated Resources:\n"));
ShowResources(translated);
}
#endif // DBG
status = StartDevice(fdo, raw, translated);
// While we were in the stopped state, we were stalling incoming requests.
// Now we can release any pending IRPs and start processing new ones
if (NT_SUCCESS(status))
{ // started okay
KdPrint((DRIVERNAME " - To WORKING from %s\n", statenames[pdx->state]));
pdx->state = WORKING;
} // started okay
return CompleteRequest(Irp, status, 0);
} // HandleStartDevice
///////////////////////////////////////////////////////////////////////////////
static NTSTATUS HandleStopDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleStopDevice
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
// We're supposed to always get a query before we're stopped, so
// we should already be in the PENDINGSTOP state
if (pdx->state != PENDINGSTOP)
return DefaultPnpHandler(fdo, Irp);
StopDevice(fdo, TRUE); // TRUE means okay to touch hardware
KdPrint((DRIVERNAME " - To STOPPED from %s\n", statenames[pdx->state]));
pdx->state = STOPPED;
return DefaultPnpHandler(fdo, Irp);
} // HandleStopDevice
///////////////////////////////////////////////////////////////////////////////
static NTSTATUS HandleSurpriseRemoval(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleSurpriseRemoval
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
KdPrint((DRIVERNAME " - To SURPRISEREMOVED from %s\n", statenames[pdx->state]));
pdx->state = SURPRISEREMOVED;
// Release I/O resources without touching the hardware
StopDevice(fdo, FALSE);
// Set status field as a signal to PDO that we've handled this IRP
Irp->IoStatus.Status = STATUS_SUCCESS;
return DefaultPnpHandler(fdo, Irp);
} // HandleSurpriseRemoval
///////////////////////////////////////////////////////////////////////////////
#if DBG
static VOID ShowResources(IN PCM_PARTIAL_RESOURCE_LIST list)
{ // ShowResources
PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = list->PartialDescriptors;
ULONG nres = list->Count;
ULONG i;
for (i = 0; i < nres; ++i, ++resource)
{ // for each resource
ULONG type = resource->Type;
static char* name[] = {
"CmResourceTypeNull",
"CmResourceTypePort",
"CmResourceTypeInterrupt",
"CmResourceTypeMemory",
"CmResourceTypeDma",
"CmResourceTypeDeviceSpecific",
"CmResourceTypeBusNumber",
"CmResourceTypeDevicePrivate",
"CmResourceTypeAssignedResource",
"CmResourceTypeSubAllocateFrom",
};
KdPrint((" type %s", type < arraysize(name) ? name[type] : "unknown"));
switch (type)
{ // select on resource type
case CmResourceTypePort:
case CmResourceTypeMemory:
KdPrint((" start %8X%8.8lX length %X\n",
resource->u.Port.Start.HighPart, resource->u.Port.Start.LowPart,
resource->u.Port.Length));
break;
case CmResourceTypeInterrupt:
KdPrint((" level %X, vector %X, affinity %X\n",
resource->u.Interrupt.Level, resource->u.Interrupt.Vector,
resource->u.Interrupt.Affinity));
break;
case CmResourceTypeDma:
KdPrint((" channel %d, port %X\n",
resource->u.Dma.Channel, resource->u.Dma.Port));
} // select on resource type
} // for each resource
} // ShowResources
#endif // DBG
///////////////////////////////////////////////////////////////////////////////
static NTSTATUS StartDevice(PDEVICE_OBJECT fdo, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PARTIAL_RESOURCE_LIST translated)
{ // StartDevice
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
NTSTATUS status = STATUS_SUCCESS;
// Scan raw and translated resource descriptor lists to save description of the
// two port resources we expect to find. The 1-port resource is for child A,
// the 2-port resource is for child B.
BOOLEAN gotportAraw = FALSE;
BOOLEAN gotportBraw = FALSE;
BOOLEAN gotportAtranslated = FALSE;
BOOLEAN gotportBtranslated = FALSE;
if (!raw || !translated)
return STATUS_DEVICE_CONFIGURATION_ERROR;
PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = raw->PartialDescriptors;
ULONG nres = raw->Count;
for (ULONG i = 0; i < nres; ++i, ++resource)
{ // scan raw resources
if (resource->Type != CmResourceTypePort)
continue; // ignore unexpected resource
if (resource->u.Port.Length == 1)
pdx->PortARaw = *resource, gotportAraw = TRUE;
else
pdx->PortBRaw = *resource, gotportBraw = TRUE;
} // scan raw resources
resource = translated->PartialDescriptors;
nres = raw->Count;
for (i = 0; i < nres; ++i, ++resource)
{ // scan raw resources
if (resource->Type != CmResourceTypePort)
continue; // ignore unexpected resource
if (resource->u.Port.Length == 1)
pdx->PortATranslated = *resource, gotportAtranslated = TRUE;
else
pdx->PortBTranslated = *resource, gotportBtranslated = TRUE;
} // scan raw resources
if (!(gotportAraw && gotportBraw && gotportAtranslated && gotportBtranslated))
return STATUS_DEVICE_CONFIGURATION_ERROR;
// Create device objects (PDOs) for the two child devices this sample has.
// Real multifunction or controller devices might have more elaborate
// ways of detecting their children, of course.
if (!pdx->ChildA)
status = CreateChild(pdx, CHILDTYPEA, &pdx->ChildA);
if (!pdx->ChildB && NT_SUCCESS(status))
{
status = CreateChild(pdx, CHILDTYPEB, &pdx->ChildB);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(pdx->ChildA);
pdx->ChildA = NULL;
}
}
return status;
} // StartDevice
///////////////////////////////////////////////////////////////////////////////
static VOID StopDevice(PDEVICE_OBJECT fdo, BOOLEAN oktouch)
{ // StopDevice
} // StopDevice
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -