学习驱动开发一段时间了,在尝试着从最简单的驱动开发着手学习,我再尝试着编写一个最简单的串口过滤驱动,可是多次尝试都没有成功,总是一加载就蓝屏。看了网上的例子他们都是采用的IoAttachDeviceToDeviceStack,而我采用的是IoAttachDevice,现在把网上的代码整理成最简单的形式给大家分享一下,希望初学者能从中受益。我会再后面的博客里详细介绍。
#include <ntddk.h> #include <string.h> 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; i<Irp->IoStatus.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 <ntddk.h> #include <string.h> 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; }