当要移除设备的时候,IO管理器发送IRP_MN_REMOVE_DEVICE 类型的IRP包,这是一个即插即用型的IRP包。通过调用即插即用例程来处理。
由于在Driver_Entry()函数中,将即插即用的函数和处理Pnp的MajorFunction进行了绑定,即:
pDriverObject->MajorFunction[IRP_MJ_PNP] =xxxPnp;
NTSTATUS xxxPnp(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
…
}
该函数前面都已经提到过,通过调用下面函数来完成:
NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
{
//释放分配的内存
if(pdx->MemBar0)
MmUnmapIoSpace(pdx->MemBar0,pdx->nMem0);
//设置寄存器状态
WRITE_REGISTER_ULONG((PULONG) &pdx->pHBARegs->Dma_wr_en,0x00000000);
//释放DMA资源
pdx->freeCommonBuffer()
…
//删除中断
IoDisconnectInterrupt(pdx->InterruptObject);
//将IRP_MN_REMOVE_DEVICE交给硬件处理
NTSTATUS status = ForwardAndWait(pdx,Irp);
//设置设备接口状态
IoSetDeviceInterfaceState(&pdx->interfaceName, FALSE);
//释放UNICODE字符串
RtlFreeUnicodeString(&pdx->interfaceName);
//调用IoDetachDevice()把fdo从设备栈中脱开:
if (pdx->NextStackDevice)
IoDetachDevice(pdx->NextStackDevice);
//删除设备对象fdo:
IoDeleteDevice(pdx->fdo);
//释放UNICODE字符串
// RtlFreeUnicodeString(&pdx->devName);
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status
}
驱动需要对一些不做特殊处理的IRP包进行默认操作,对这类Pnp类型的操作可以提供一个这样的函数来处理:
NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)
{
PAGED_CODE();
KdPrint(("Enter DefaultPnpHandler\n"));
IoSkipCurrentIrpStackLocation(Irp);
KdPrint(("Leave DefaultPnpHandler\n"));
return IoCallDriver(pdx->NextStackDevice, Irp);
}
通过IoCallDriver()直接交给PDO。
对于非Pnp类的操作,如IRP_MJ_CREATE、IRP_MJ_CLOSE、IRP_MJ_READ、IRP_MJ_WRITE,直接提供下面类似的默认处理函数:
NTSTATUS xxxCreate(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
PAGED_CODE();
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
pdx->open_flag++;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0; // no bytes xfered
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}