本程序来自<寒江独钓>Windows内核安全编程和<windows内核安全与驱动开发>中串口过滤一章
书中的程序绑定了串口设备0到31,而且只写了过滤发送而没有写过滤接收
程序被我修改为只过滤串口设备\Device\Serial2,而且过滤发送和接收
一般串口助手看到串口名称为COM*,但是在内核中串口设备的路径为"\Device\Serial*"
程序如下
<code class="lang-cpp">#include "DriverEntry.h"
#define DEBUG
#ifdef DEBUG
#define __asm_3 __asm int 3
#define _asm_3 __asm int 3
#else
#define __asm_3
#define _asm_3
#endif
#endif
PDEVICE_OBJECT fltobj = NULL; //过滤设备
PDEVICE_OBJECT nextobj = NULL; //真实设备
//驱动程序是从DriverEntry开始执行的
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,//pDriverObject指向本驱动的驱动对象指针
IN PUNICODE_STRING pRegistryPath)//本驱动所在的注册表路径
{
_asm_3;//中断
NTSTATUS status = 0;//初始化一个状态
UNICODE_STRING Name;//驱动与设备名
pDriverObject->DriverUnload = DriverUnload;//驱动卸载时候调用的派遣函数
for (size_t i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
pDriverObject->MajorFunction<i> = Device_General;//Device_General处理除了读,写,电源事件
}
pDriverObject->MajorFunction[IRP_MJ_READ] = Device_Read;//串口接收时会调用这个派遣函数
pDriverObject->MajorFunction[IRP_MJ_WRITE] = Device_Write;//串口发送时会调用这个派遣函数
pDriverObject->MajorFunction[IRP_MJ_POWER] = Device_Power;
PFILE_OBJECT fileobj = NULL; //文件指针
PDEVICE_OBJECT devobj = NULL; //串口设备
RtlInitUnicodeString(&Name, L"\\Device\\Serial2");//串口设备路径
status = IoGetDeviceObjectPointer(&Name, //打开串口设备\\Device\\Serial2
FILE_ALL_ACCESS, //全部读写权限
&fileobj,//无用的文件对象指针
&devobj);//打开串口
if (!NT_SUCCESS(status)) //如果返回的状态是错误的
{
_asm_3; //中断
return status;//返回驱动加载错误
}
ObDereferenceObject(fileobj);//返回状态为成功立即释放无用的文件对象指针
ccpAttachDevice( //创建一个过滤设备并附加到串口设备\\Device\\Serial2上
pDriverObject,//DriverEntry传进来的本驱动的驱动对象
devobj,//串口设备\\Device\\Serial2
&fltobj,//过滤设备
&nextobj);//真实设备
return STATUS_SUCCESS;
}
NTSTATUS
ccpAttachDevice( //创建一个过滤设备并附加到串口设备上
PDRIVER_OBJECT Driver, //DriverEntry传入
PDEVICE_OBJECT oldobj, //源设备
PDEVICE_OBJECT *fltobj, //创建的过滤设备
PDEVICE_OBJECT *next) //真事的设备
{
NTSTATUS status = 0;
PDRIVER_OBJECT topDev = NULL;
status = IoCreateDevice( //创建一个过滤设备
Driver, //DriverEntry传入
0, //设备扩展
NULL, //过滤设备不需要名称
oldobj->DeviceType,//设备类型
0, //设备特征
FALSE, //是否独占
fltobj //创建好的过滤设备
);
if (!NT_SUCCESS(status)) //如果错误
{
fltobj = NULL;
DbgPrint("%s第%s行发生错误",__FILE__,__LINE__);
return status;
}
//拷贝标记位
//内存传输策略
if (oldobj->Flags & DO_BUFFERED_IO) (*fltobj)->Flags |= DO_BUFFERED_IO;
if (oldobj->Flags & DO_DIRECT_IO) (*fltobj)->Flags |= DO_DIRECT_IO;
if (oldobj->Flags & DO_BUFFERED_IO) (*fltobj)->Flags |= DO_BUFFERED_IO;
if (oldobj->Characteristics & FILE_DEVICE_SECURE_OPEN)
(*fltobj)->Characteristics |= FILE_DEVICE_SECURE_OPEN;
(*fltobj)->Flags |= DO_POWER_PAGABLE;
status = IoAttachDeviceToDeviceStackSafe(*fltobj, oldobj, &topDev); //把创建好的过滤设备附加到串口设备
if ((!NT_SUCCESS(status)) || (topDev == NULL))//如果失败了
{
IoDeleteDevice(*fltobj);//删除创建的过滤设备
*fltobj = NULL;
return status;
}
//此时fltobj是创建好并且附加成功的过滤设备
*next = topDev;//设备栈最下面的真实设备
(*fltobj)->Flags = (*fltobj)->Flags & ~DO_DEVICE_INITIALIZING;
return status;
}
NTSTATUS Device_Read(//读 //如果这个派遣函数被调用了说明单片机往计算机发送了数据
_In_ struct _DEVICE_OBJECT *DeviceObject,
_Inout_ struct _IRP *Irp)
{
_asm_3
PIO_STACK_LOCATION Irpsp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS stayus = Device_General(DeviceObject, Irp);//从真实设备读取数据
//此时单片机发往计算机的数据在Irp->AssociatedIrp->SystemBuffer中
//数据的长度在Irp->IoStatusInformation中
return stayus;
}
NTSTATUS Device_Write(//写 //如果这个派遣函数被调用了说明计算机往单片机发送了数据
_In_ struct _DEVICE_OBJECT *DeviceObject,
_Inout_ struct _IRP *Irp)
{
//此时计算机发出的数据在Irp->AssociatedIrp->SystemBuffer中
PIO_STACK_LOCATION Irpsp = IoGetCurrentIrpStackLocation(Irp);
//数据长度在Irps->Parameters.Write.Length中
_asm_3
return Device_General(DeviceObject, Irp);
}
NTSTATUS Device_General(//通用处理
_In_ struct _DEVICE_OBJECT *DeviceObject,
_Inout_ struct _IRP *Irp)
{
//_asm_3;
IoSkipCurrentIrpStackLocation(Irp);//跳过当前栈空间
return IoCallDriver(nextobj, Irp); //将请求发送给真实的设备
}
NTSTATUS Device_Power(//Power处理
_In_ struct _DEVICE_OBJECT *DeviceObject,
_Inout_ struct _IRP *Irp)
{
//_asm_3;
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);//跳过当前栈空间
return PoCallDriver(nextobj, Irp); //将请求发送给真实的设备
}
VOID DriverUnload(PDRIVER_OBJECT driver)
{
//_asm_3;
if (nextobj != NULL)
IoDetachDevice(nextobj); //解除引用
if (fltobj != NULL)
IoDeleteDevice(fltobj); //删除过滤设备
DbgPrint("%s%d卸载完毕", __FILE__, __LINE__);
}
NTSTATUS Device_Conteol(//设备控制
_In_ struct _DEVICE_OBJECT *DeviceObject,
_Inout_ struct _IRP *Irp)
{
//_asm_3
return 0;
}</i></code>
200字以内,仅用于支线交流,主线讨论请采用回复功能。