windows驱动开发之过滤串口

大家都知道使用驱动过滤设备来获取数据是最好不过的方式了,下面为大家介绍一个简单的串口过滤。


源代码奉上:


#include <ntddk.h>


//为了使用静态的ntstrsafe库
#define NTSTRSAFE_LIB
#include <ntstrsafe.h>
#define CCP_MAX_COM_ID 32
//保存所有过滤设备
static PDEVICE_OBJECT s_fltObj[CCP_MAX_COM_ID] = {0};
//保存所有原始设备
static PDEVICE_OBJECT s_nextobj[CCP_MAX_COM_ID] = {0};


//打开一个设备
PDEVICE_OBJECT ccpOpenCom(ULONG id, NTSTATUS* status)
{
UNICODE_STRING name_str;
static WCHAR name[32] = {0};

PFILE_OBJECT fileobj = NULL;
PDEVICE_OBJECT devobj = NULL;

// 输入字符串。
memset(name, 0, sizeof(WCHAR)*32);

//拼出设备的名字
RtlStringCchPrintfW( name, 32, L"\\Device\\Serial%d", id);
RtlInitUnicodeString(&name_str, name);

//打开设备
*status  =  IoGetDeviceObjectPointer(&name_str, FILE_ALL_ACCESS, &fileobj, &devobj);

//如果打开成功一定要释放fileobj
if( *status == STATUS_SUCCESS)
ObDereferenceObject( fileobj );

return devobj;
}


//绑定一个设备
NTSTATUS ccpAttachCom(PDRIVER_OBJECT pobj, PDEVICE_OBJECT oldObj, PDEVICE_OBJECT* fltObj, PDEVICE_OBJECT* next)
{
NTSTATUS status;
PDRIVER_OBJECT topDev;

//先创建一个设备
status = IoCreateDevice( pobj, 0, NULL, oldObj->DeviceType, 0, FALSE, fltObj);
if( status != STATUS_SUCCESS)
{
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;

//绑定设备
topDev = IoAttachDeviceToDeviceStack(*fltObj, oldObj);
if( NULL == topDev)
{
//如果banding失败了就删除设备
IoDeleteDevice(*fltObj);
*fltObj = NULL;
status = STATUS_UNSUCCESSFUL;
return status;
}

*next = topDev;

//设置这个设备启动
(*fltObj)->Flags = (*fltObj)->Flags & ~DO_DEVICE_INITIALIZING;


return STATUS_SUCCESS;
}






//绑定所有设备
NTSTATUS ccpAttachAllCom(PDRIVER_OBJECT driver)
{
ULONG i;
PDEVICE_OBJECT pDobj;
NTSTATUS status;

for( i = 0; i < CCP_MAX_COM_ID; i++)
{
pDobj = ccpOpenCom(i, &status);
if( pDobj == NULL)
continue;

//绑定一个设备
ccpAttachCom(driver, pDobj, &s_fltObj[i], &s_nextobj[i]);

}
return STATUS_SUCCESS;
}


//分发函数
NTSTATUS ccpDispatch(PDEVICE_OBJECT pDev, PIRP pirp)
{
//获取IRP堆栈
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation( pirp );
NTSTATUS status;
ULONG i,j;

for(i = 0; i < CCP_MAX_COM_ID; i++)
{
if(s_fltObj[i] == pDev)
{
//所有电源操作全部跳过
if(irpsp->MajorFunction == IRP_MJ_POWER)
{
//直接发送
PoStartNextPowerIrp(pirp);
IoSkipCurrentIrpStackLocation(pirp);
return PoCallDriver(s_nextobj[i], pirp);
}
//处理写请求
if(irpsp->MajorFunction  == IRP_MJ_WRITE)
{
//获取写的数据长度
ULONG length = irpsp->Parameters.Write.Length;
//获取缓冲区
PUCHAR buf = NULL; 
if( pirp->MdlAddress != NULL)
{
buf = (PUCHAR)MmGetSystemAddressForMdlSafe( pirp->MdlAddress, NormalPagePriority);
}
else
{
buf = (PUCHAR)pirp->UserBuffer;
}
if(NULL == buf)
{
buf = (PUCHAR)pirp->AssociatedIrp.SystemBuffer;
}

//输出
for(j = 0; j < length; j++)
{
DbgPrint("com:%2x\r\n", buf[j]);
}
}

IoSkipCurrentIrpStackLocation(pirp);
return IoCallDriver(s_nextobj[i], pirp);

}

}

//如果根本不存在就报错
pirp->IoStatus.Information = 0;
pirp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(pirp, IO_NO_INCREMENT);


return STATUS_SUCCESS;
}
//卸载
NTSTATUS AttachUnload(PDRIVER_OBJECT pobj)
{
ULONG i;
LARGE_INTEGER interval;

//首先解除绑定
for(i = 0; i < CCP_MAX_COM_ID; i++)
{

if(s_nextobj[i] != NULL)
IoDetachDevice( s_nextobj[i] );
}

interval.QuadPart = (5 * 1000 *  (-10 * 1000));
KeDelayExecutionThread(KernelMode, FALSE, &interval);

for(i = 0; i < CCP_MAX_COM_ID; i++)
{
if(s_fltObj[i] != NULL)
IoDeleteDevice( s_fltObj[i]  );
}

return STATUS_SUCCESS;
}




NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
size_t i;
for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
driver->MajorFunction[i] = ccpDispatch;
}



driver->DriverUnload = AttachUnload;


ccpAttachAllCom(driver);


return STATUS_SUCCESS;
}


简单的说其实就是:过滤涉笔的IRP 请求并处理然后进行下发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值