您的位置:首页 > 其它

一个简单的串口过滤驱动

2011-08-07 14:04 344 查看
学习驱动开发一段时间了,在尝试着从最简单的驱动开发着手学习,我再尝试着编写一个最简单的串口过滤驱动,可是多次尝试都没有成功,总是一加载就蓝屏。看了网上的例子他们都是采用的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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: