PDEVICE_OBJECT IoAttachDeviceToDeviceStack(
IN PDEVICE_OBJECT SourceDevice,//用来过滤的虚拟设备
IN PDEVICE_OBJECT TargetDevice)//要被绑定的设备名称
函数返回最终被绑定的设备指针(如果为NULL,绑定失败)
3)从名字获得设备对象
NTSTATUS IoGetDeivceObjectPointer(
IN PUNICODE_STRING ObjectName,//设备名称
IN ACESS_MASK DesiredAccess,//预期的访问权限(FILE_ALL_ACCESS)
OUT PFILE_OBJECT *FileObject,
OUT PDEVICE_OBJECT*DeviceObject);
注意:使用完了以后要将文件对象“解除引用”,否则会引起内存泄漏ObDereferenceObject(fileobj)
4) IRP的栈空间
PIO_STACK_LOCATION irpsp=IoGetCurrentIrpStackLocation(irp)//PIRP irp
if(irpsp->MajorFunction==IRP_MJ_WRITE)
{
}
//IRP_MJ_POWER比较特殊
if(irpsp->MajorFunction == IRP_MJ_POWER)
{
// 直接发送,然后返回说已经被处理了。
PoStartNextPowerIrp(irp);
IoSkipCurrentIrpStackLocation(irp);
return PoCallDriver(s_nextobj[i],irp);
}
// 这些请求直接下发执行即可。我们并不禁止或者改变它。
IoSkipCurrentIrpStackLocation(irp);
return IoCallDriver(s_nextobj[i],irp);
5)IRP结构中的缓冲区
irp->MDLAddress将应用层地址空间映射到内核空间
irp->UserBuffer应用层缓冲区中的地址直接放在内核空间中进行访问(如果内核进程切换访问就出错了)
irp->AssociatedIrp.SystemBuffer把应用层(R3)中内存空间中的缓冲数据拷贝到内核空间
//获得缓冲区
PUCHAR buf = NULL;
if(irp->MdlAddress != NULL)
buf = PUCHAR)MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);
else
buf = (PUCHAR)irp->UserBuffer;
if(buf == NULL)
buf = (PUCHAR)irp->AssociatedIrp.SystemBuffer;
6) 动态卸载
要在卸载函数中完成解除绑定的功能,否则一旦卸载就会蓝屏
IoDetachDevice负责将绑定的设备解除绑定
IoDeleteDevice负责把我们前面用IoCreateDevice生成的设备删除掉以回收内存
KeDelayExecutionThread延时函数
IoDetachDevice(s_nextobj[i]);//被绑定的设备
KeDelayExecutionThread(KernelMode,FALSE,&interval);
IoDeleteDevice(s_fltobj[i]);//删除过滤设备