📄 plugplay.c
字号:
return DefaultPnpHandler(
fdo,
pIrp
);
}
/******************************************************************************
*
* Function : HandleCancelRemoveDevice
*
* Description: Handle the IRP_MN_CANCEL_REMOVE_DEVICE PnP request
*
******************************************************************************/
NTSTATUS
HandleCancelRemoveDevice(
PDEVICE_OBJECT fdo,
PIRP pIrp
)
{
// We must succeed the IRP and pass it to the parent
pIrp->IoStatus.Status = STATUS_SUCCESS;
// Forward to parent driver
return DefaultPnpHandler(
fdo,
pIrp
);
}
/******************************************************************************
*
* Function : HandleRemoveDevice
*
* Description: Handle the IRP_MN_REMOVE_DEVICE PnP request
*
******************************************************************************/
NTSTATUS
HandleRemoveDevice(
PDEVICE_OBJECT fdo,
PIRP pIrp
)
{
NTSTATUS status;
DEVICE_EXTENSION *pdx;
// Wait for any pending I/O operations to complete
pdx = fdo->DeviceExtension;
pdx->removing = TRUE;
PlxUnlockDevice(pdx); // once for LockDevice at start of dispatch
PlxUnlockDevice(pdx); // once for initialization during AddDevice
KeWaitForSingleObject(
&pdx->evRemove,
Executive,
KernelMode,
FALSE,
NULL
);
// Halt the device and release its resources
StopDevice(
fdo
);
// Succeed the IRP and pass to next driver
pIrp->IoStatus.Status = STATUS_SUCCESS;
// Pass to next driver in stack
status =
DefaultPnpHandler(
fdo,
pIrp
);
// Remove the device object
RemoveDevice(
fdo
);
return status;
}
/******************************************************************************
*
* Function : HandleStartDevice
*
* Description: Handle the IRP_MN_START_DEVICE PnP request
*
******************************************************************************/
NTSTATUS
HandleStartDevice(
PDEVICE_OBJECT fdo,
PIRP pIrp
)
{
NTSTATUS status;
PIO_STACK_LOCATION stack;
/********************************************************
* First let all lower-level drivers handle this request,
* which is typically just the physical device object
* created by the bus driver.
*******************************************************/
status =
ForwardAndWait(
fdo,
pIrp
);
if (!NT_SUCCESS(status))
{
return PlxCompleteIrp(
pIrp,
status
);
}
stack =
IoGetCurrentIrpStackLocation(
pIrp
);
// Assign resources to the devices
status =
StartDevice(
fdo,
&stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList,
&stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList
);
return PlxCompleteIrpWithInformation(
pIrp,
status,
0
);
}
/******************************************************************************
*
* Function : HandleStopDevice
*
* Description: Handle the IRP_MN_STOP_DEVICE PnP request
*
******************************************************************************/
NTSTATUS
HandleStopDevice(
PDEVICE_OBJECT fdo,
PIRP pIrp
)
{
NTSTATUS status;
status =
DefaultPnpHandler(
fdo,
pIrp
);
StopDevice(
fdo
);
return status;
}
/******************************************************************************
*
* Function : HandleQueryDeviceRelations
*
* Description: Handle the IRP_MN_QUERY_DEVICE_RELATIONS PnP request
*
******************************************************************************/
NTSTATUS
HandleQueryDeviceRelations(
PDEVICE_OBJECT fdo,
PIRP pIrp
)
{
U32 MemNeeded;
PDEVICE_OBJECT pdo;
PDEVICE_OBJECT pDevice;
DEVICE_EXTENSION *pdx;
DEVICE_RELATIONS *pDeviceRelations;
PIO_STACK_LOCATION stack;
/********************************************************
* When a query for device relations is received and the
* request is for "RemovalRelations", the driver may
* report to the PnP manager a list of device relations.
*
* Since the first device loaded by the driver (PciXxx-0)
* is responsible for the common buffer, all subsequently
* owned devices are related to it. An attempt to remove
* the primary device requires the driver to report that
* all other devices must be removed first. The PnP
* manager determines this by the device relations
* provided by this driver.
*******************************************************/
pdx = fdo->DeviceExtension;
// Get I/O Stack
stack =
IoGetCurrentIrpStackLocation(
pIrp
);
// Check if this is for removal and more than one device is owned
if ((stack->Parameters.QueryDeviceRelations.Type == RemovalRelations) &&
(Gbl_DeviceCount > 1))
{
DebugPrintf((
"Query for: RemovalRelations\n"
));
// This is not the only device left, check if it's the primary device
if (_stricmp(
PLX_DRIVER_NAME "-0",
pdx->Device.SerialNumber
) == 0)
{
/********************************************************
* Calculate memory needed for device relations
*
* The default DEVICE_RELATIONS structure includes space
* for one device object. Therefore, the memory needed
* is the total # of devices minus 2. One since the
* primary device is not reported and one for memory
* already provided in the structure.
*******************************************************/
MemNeeded = sizeof(DEVICE_RELATIONS) +
((Gbl_DeviceCount - 2) * sizeof(PDEVICE_OBJECT));
// Allocate memory for device relations structure
pDeviceRelations =
ExAllocatePoolWithTag(
PagedPool,
MemNeeded,
(ULONG)' XLP' // "PLX " in reverse order
);
// Report other devices
DebugPrintf((
"Following device(s) must be removed first:\n"
));
// Get first device object
pDevice = fdo->DriverObject->DeviceObject;
// Reset device count
pDeviceRelations->Count = 0;
// Traverse driver owned devices to build relations
while (pDevice != NULL)
{
if (pDevice->DeviceExtension != pdx)
{
// Get the physical device object
pdo = ((DEVICE_EXTENSION*)(pDevice->DeviceExtension))->pPhysicalDeviceObject;
DebugPrintf_NoInfo((
" * %s (pdo=0x%p)\n",
((DEVICE_EXTENSION*)(pDevice->DeviceExtension))->Device.SerialNumber,
pdo
));
// Increment the reference count to the PDO
ObReferenceObject(
pdo
);
// Add PDO to device relations
pDeviceRelations->Objects[pDeviceRelations->Count] = pdo;
// Increment number of objects
pDeviceRelations->Count++;
}
// Jump to next device
pDevice = pDevice->NextDevice;
}
DebugPrintf_NoInfo((
"\n"
));
// Return address of device relations structure
return PlxCompleteIrpWithInformation(
pIrp,
STATUS_SUCCESS,
(PLX_UINT_PTR)pDeviceRelations
);
}
}
// Just pass to parent
return DefaultPnpHandler(
fdo,
pIrp
);
}
/******************************************************************************
*
* Function : OnRequestComplete
*
* Description: Set an event when a lower driver complete an IRP
*
******************************************************************************/
NTSTATUS
OnRequestComplete(
PDEVICE_OBJECT fdo,
PIRP pIrp,
PKEVENT pKEvent
)
{
KeSetEvent(
pKEvent,
0,
FALSE
);
return STATUS_MORE_PROCESSING_REQUIRED;
}
/******************************************************************************
*
* Function : ForwardAndWait
*
* Description: Forward request to lower level and await completion, used
* in PnP's IRP_MN_START_DEVICE
*
******************************************************************************/
NTSTATUS
ForwardAndWait(
PDEVICE_OBJECT fdo,
PIRP pIrp
)
{
KEVENT event;
NTSTATUS status;
/*
Initialize a kernel event object to use in waiting for the lower-level
driver to finish processing the object. It's a little known fact that the
kernel stack *can* be paged, but only while someone is waiting in user
mode for an event to finish. Since neither we nor a completion routine
can be in the forbidden state, it's okay to put the event object on the
stack.
*/
KeInitializeEvent(
&event,
NotificationEvent,
FALSE
);
IoCopyCurrentIrpStackLocationToNext(
pIrp
);
IoSetCompletionRoutine(
pIrp,
(PIO_COMPLETION_ROUTINE) OnRequestComplete,
(PVOID) &event,
TRUE,
TRUE,
TRUE
);
status =
IoCallDriver(
((DEVICE_EXTENSION *) fdo->DeviceExtension)->pLowerDeviceObject,
pIrp
);
if (status == STATUS_PENDING)
{
// Wait for completion
KeWaitForSingleObject(
&event,
Executive,
KernelMode,
FALSE,
NULL
);
return pIrp->IoStatus.Status;
}
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -