学习驱动开发一段时间了,在尝试着从最简单的驱动开发着手学习,我再尝试着编写一个最简单的串口过滤驱动,可是多次尝试都没有成功,总是一加载就蓝屏。看了网上的例子他们都是采用的IoAttachDeviceToDeviceStack,而我采用的是IoAttachDevice,现在把网上的代码整理成最简单的形式给大家分享一下,希望初学者能从中受益。我会再后面的博客里详细介绍。
#include
#include
static PDEVICE_OBJECT m_fltobj;
static PDEVICE_OBJECT m_topobj;
//定义一个读的完成处理函数
NTSTATUS fengReadComplete(IN PDEVICE_OBJECT DeviectObject, IN PIRP Irp, IN PVOID Context)
{
PIO_STACK_LOCATION IrpSp;
ULONG i;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
if(NT_SUCCESS( Irp->IoStatus.Status))
{
PUCHAR buf = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
DbgPrint("Driver1 Read:");
for(i=0; iIoStatus.Information; i++)
{
DbgPrint("%02X, ", buf[i]);
}
DbgPrint("\r\n");
}
if( Irp->PendingReturned)
IoMarkIrpPending( Irp);
return Irp->IoStatus.Status;
}
NTSTATUS DRIVER1_DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
ULONG j;
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
DbgPrint(("收到IRP\r\n"));
if(m_fltobj == DeviceObject)
{
if(irpSp->MajorFunction == IRP_MJ_POWER)
{
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(m_topobj, Irp);
}
else if(irpSp->MajorFunction == IRP_MJ_WRITE)
{
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;
DbgPrint("Driver1 Write:");
for(j =0; j< irpSp->Parameters.Write.Length; j++)
{
DbgPrint("%02X, ", buf[j]);
}
DbgPrint("\r\n");
}
else if(irpSp->MajorFunction == IRP_MJ_READ)
{
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, fengReadComplete, DeviceObject, TRUE, TRUE, TRUE);
return IoCallDriver(m_topobj, Irp);
}
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(m_topobj, Irp);
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
VOID DRIVER1_DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
LARGE_INTEGER ilval;
if(m_topobj != NULL)
IoDetachDevice(m_topobj);
ilval.QuadPart = 5 * 1000 * 1000 * (-10); //5秒
KeDelayExecutionThread(KernelMode, FALSE, &ilval);
if(m_fltobj != NULL)
IoDeleteDevice(m_fltobj);
}
#pragma code_seg("INIT")
NTSTATUS DriverEntry(IN OUT PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
size_t i;
NTSTATUS status;
UNICODE_STRING namestr;
PFILE_OBJECT fileobj = NULL;
PDEVICE_OBJECT devobj = NULL;
DbgBreakPoint();
for(i = 0; i< IRP_MJ_MAXIMUM_FUNCTION; i++)
{
DriverObject->MajorFunction[i] = DRIVER1_DispatchDeviceControl;
}
DriverObject->DriverUnload = DRIVER1_DriverUnload;
RtlInitUnicodeString(&namestr, L"\\Device\\Serial0");
status = IoGetDeviceObjectPointer( &namestr, FILE_ALL_ACCESS, &fileobj, &devobj);
if(status == STATUS_SUCCESS)
ObDereferenceObject(fileobj);
if(status == STATUS_SUCCESS)
{
NTSTATUS status;
PDEVICE_OBJECT topdev = NULL;
DbgPrint(("成功打开com1\r\n"));
status = IoCreateDevice(DriverObject, 0, NULL, devobj->DeviceType, 0, FALSE, &m_fltobj);
if(status != STATUS_SUCCESS)
return status;
if(devobj->Flags & DO_BUFFERED_IO)
m_fltobj->Flags |= DO_BUFFERED_IO;
if(devobj->Flags & DO_DIRECT_IO)
m_fltobj->Flags |= DO_DIRECT_IO;
if(devobj->Characteristics & FILE_DEVICE_SECURE_OPEN)
m_fltobj->Characteristics |= FILE_DEVICE_SECURE_OPEN;
m_fltobj->Flags |= DO_POWER_PAGABLE;
topdev = IoAttachDeviceToDeviceStack(m_fltobj, devobj);
if(topdev == NULL)
{
IoDeleteDevice(m_fltobj);
m_fltobj = NULL;
status = STATUS_UNSUCCESSFUL;
return status;
}
DbgPrint(("driverentry 成功\r\n"));
m_topobj= topdev;
m_fltobj->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
return STATUS_SUCCESS;
}
把IRP请求处理再次简化就变成了下面的形式,我为什么要这样简化就是想告诉大家驱动过滤的简单框架。
#include
#include
static PDEVICE_OBJECT m_fltobj;
static PDEVICE_OBJECT m_topobj;
NTSTATUS DRIVER1_DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
DbgPrint(("收到IRP\r\n"));
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(m_topobj, Irp);
}
VOID DRIVER1_DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
LARGE_INTEGER ilval;
if(m_topobj != NULL)
IoDetachDevice(m_topobj);
ilval.QuadPart = 5 * 1000 * 1000 * (-10); //5秒
KeDelayExecutionThread(KernelMode, FALSE, &ilval);
if(m_fltobj != NULL)
IoDeleteDevice(m_fltobj);
}
#pragma code_seg("INIT")
NTSTATUS DriverEntry(IN OUT PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
size_t i;
NTSTATUS status;
UNICODE_STRING namestr;
PFILE_OBJECT fileobj = NULL;
PDEVICE_OBJECT devobj = NULL;
DbgBreakPoint();
for(i = 0; i< IRP_MJ_MAXIMUM_FUNCTION; i++)
{
DriverObject->MajorFunction[i] = DRIVER1_DispatchDeviceControl;
}
DriverObject->DriverUnload = DRIVER1_DriverUnload;
RtlInitUnicodeString(&namestr, L"\\Device\\Serial0");
status = IoGetDeviceObjectPointer( &namestr, FILE_ALL_ACCESS, &fileobj, &devobj);
if(status == STATUS_SUCCESS)
ObDereferenceObject(fileobj);
if(status == STATUS_SUCCESS)
{
NTSTATUS status;
PDEVICE_OBJECT topdev = NULL;
DbgPrint(("成功打开com1\r\n"));
status = IoCreateDevice(DriverObject, 0, NULL, devobj->DeviceType, 0, FALSE, &m_fltobj);
if(status != STATUS_SUCCESS)
return status;
if(devobj->Flags & DO_BUFFERED_IO)
m_fltobj->Flags |= DO_BUFFERED_IO;
if(devobj->Flags & DO_DIRECT_IO)
m_fltobj->Flags |= DO_DIRECT_IO;
if(devobj->Characteristics & FILE_DEVICE_SECURE_OPEN)
m_fltobj->Characteristics |= FILE_DEVICE_SECURE_OPEN;
m_fltobj->Flags |= DO_POWER_PAGABLE;
topdev = IoAttachDeviceToDeviceStack(m_fltobj, devobj);
if(topdev == NULL)
{
IoDeleteDevice(m_fltobj);
m_fltobj = NULL;
status = STATUS_UNSUCCESSFUL;
return status;
}
DbgPrint(("driverentry 成功\r\n"));
m_topobj= topdev;
m_fltobj->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
return STATUS_SUCCESS;
}