|
阅读:2309回复:3
串口 IRP_MJ_READ问题
为什么我修改了缓冲区串口调试工具里还是收到正确的数据而不是我修改过的数据?
IRP_MJ_WRITE我已经测试过可以改变的...不管我写什么串口监听工具监听到都是我修改过的数据了 if(irpsp->MajorFunction == IRP_MJ_WRITE)
{
// 如果是写,先获得长度
ULONG len = irpsp->Parameters.Write.Length;
// 然后获得缓冲区
PUCHAR buf = NULL;
if(irp->MdlAddress != NULL)
{
buf = (PUCHAR)MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);
DbgPrint("aaaaaaaaaa");
}
else
{
//memset((PUCHAR)irp->UserBuffer,0x31,len);
buf = (PUCHAR)irp->UserBuffer;
DbgPrint("bbbbbbbbbbb");
}
if(buf == NULL)
{
memset((PUCHAR)irp->AssociatedIrp.SystemBuffer,0x31,len);
buf = (PUCHAR)irp->AssociatedIrp.SystemBuffer;
DbgPrint("cccccccccc");
}
// 打印内容
for(j=0;j<len;++j)
{
DbgPrint("comcap: Send Data: %2x\r\n",
buf[j]);
}
}
if(irpsp->MajorFunction == IRP_MJ_READ)
{
// 如果是写,先获得长度
ULONG len1 = irpsp->Parameters.Read.Length;
// 然后获得缓冲区
PUCHAR buf1 = NULL;
if(irp->MdlAddress != NULL)
{
buf1 =(PUCHAR)MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);
DbgPrint("1111111111111");
}
else
{
memset((PUCHAR)irp->UserBuffer,0x32,len1);
buf1 = (PUCHAR)irp->UserBuffer;
DbgPrint("222222222");
}
if(buf1 == NULL)
{
memset((PUCHAR)irp->AssociatedIrp.SystemBuffer,0x32,len1);
buf1 = (PUCHAR)irp->AssociatedIrp.SystemBuffer;
DbgPrint("33333333");
}
// 打印内容
for(j=0;j<len1;++j)
{
DbgPrint("comcap: Send Data: %2x\r\n",
buf1[j]);
}
}csdn上没有回复特意跑来驱网希望驱网的大大们出手帮助下小弟........(这个好象没有象csdn上给分的吧....不懂将就着吧) |
|
|
沙发#
发布于:2009-10-19 14:03
哈....搞定
|
|
|
板凳#
发布于:2009-10-19 23:38
楼主什么意思?
这传入传出的,不都是你在串口收发的原始数据么? 。。。 |
|
|
地板#
发布于:2009-10-22 17:08
这个才是我后来的版本:
#include <ntddk.h>
#define NTSTRSAFE_LIB
#include <ntstrsafe.h>
#define COM_DRIVER_NAME L"\\Device\\Serial0" //要绑定的设备名
//延时用的
#define DELAY_ONE_MICROSECOND (-10)
#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)
PDEVICE_OBJECT s_fltobj=NULL; //全局指针
PDEVICE_OBJECT s_nextobj=NULL; //全局指针
void ccpUnload(PDRIVER_OBJECT drv); //动态卸载函数
NTSTATUS ccpAttachAllComs(PDRIVER_OBJECT driver); //绑定函数
NTSTATUS ccpDispatch(PDEVICE_OBJECT device,PIRP irp); //过滤IRP函数
NTSTATUS fengReadComplete(PDEVICE_OBJECT DeviectObject,PIRP Irp,PVOID Context); //IRP_MJ_READ回调函数
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) //所有的驱动都是这个入口函数跟c语言的main函数一样
{
size_t i;
for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
{
driver->MajorFunction[i] = ccpDispatch; //所有的分发函数都进入ccpDispatch这个函数里面去
}
driver->DriverUnload = ccpUnload; //支持动态卸载(=号后面是卸载函数)
ccpAttachAllComs(driver); //绑定所有的串口
return STATUS_SUCCESS; //返回成功(STATUS_SUCCESS=成功的意思)
}
void ccpUnload(PDRIVER_OBJECT drv) //动态卸载函数
{
LARGE_INTEGER interval;
UNICODE_STRING uniNtNameString; //定义一个字符串
RtlInitUnicodeString(&uniNtNameString, COM_DRIVER_NAME); // 初始化一个字符串(就是COM驱动的名字)
IoDetachDevice(s_nextobj); // 首先解除绑定
interval.QuadPart = (2*1000 * DELAY_ONE_MILLISECOND); // 睡眠时间(2秒)
KeDelayExecutionThread(KernelMode,FALSE,&interval); //等待所有irp处理结束
IoDeleteDevice(s_fltobj); // 删除设备
}
NTSTATUS ccpAttachAllComs(PDRIVER_OBJECT driver) //绑定函数
{
NTSTATUS status; //定义返回状态数据类型
PFILE_OBJECT fileobj = NULL; //定义一个设备的文件对象指针
PDEVICE_OBJECT devobj = NULL; //定义一个设备对象指针
UNICODE_STRING uniNtNameString; //定义一个字符串
RtlInitUnicodeString(&uniNtNameString, COM_DRIVER_NAME); // 初始化一个字符串(就是COM驱动的名字)
status=IoGetDeviceObjectPointer(&uniNtNameString, FILE_ALL_ACCESS, &fileobj, &devobj); //根据设备名字获取设备对象
if(status == STATUS_SUCCESS) //如果获取设备对象成功
ObDereferenceObject(fileobj); //就取消设备的文件对象引用(因为过滤串口不需要文件对象)
status = IoCreateDevice(driver,0,NULL,devobj->DeviceType,0,FALSE,&s_fltobj); //生成设备
if (status != STATUS_SUCCESS) //如果没有生成设备成功就返回
return status;
// 拷贝重要标志位。
if(devobj->Flags & DO_BUFFERED_IO)
(s_fltobj)->Flags |= DO_BUFFERED_IO;
if(devobj->Flags & DO_DIRECT_IO)
(s_fltobj)->Flags |= DO_DIRECT_IO;
if(devobj->Flags & DO_BUFFERED_IO)
(s_fltobj)->Flags |= DO_BUFFERED_IO;
if(devobj->Characteristics & FILE_DEVICE_SECURE_OPEN)
(s_fltobj)->Characteristics |= FILE_DEVICE_SECURE_OPEN;
(s_fltobj)->Flags |= DO_POWER_PAGABLE;
s_nextobj = IoAttachDeviceToDeviceStack(s_fltobj,devobj); //绑定一个设备到另一个设备上
if (s_nextobj == NULL)
{
// 如果绑定失败了,销毁设备,重新来过。
IoDeleteDevice(s_fltobj);
s_fltobj = NULL;
return STATUS_UNSUCCESSFUL;
}
(s_fltobj)->Flags = (s_fltobj)->Flags & ~DO_DEVICE_INITIALIZING; //设置这个设备已经启动
return STATUS_SUCCESS;
}
NTSTATUS ccpDispatch(PDEVICE_OBJECT device,PIRP irp) //过滤函数
{
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(irp); //获取当前栈空间
NTSTATUS status;
ULONG i;
if(s_fltobj== device)
{
if(irpsp->MajorFunction == IRP_MJ_POWER)
{
//如果是电源直接发送,然后返回说已经被处理了
PoStartNextPowerIrp(irp);
IoSkipCurrentIrpStackLocation(irp);
return PoCallDriver(s_nextobj,irp);
}
if(irpsp->MajorFunction == IRP_MJ_WRITE)
{
ULONG len = irpsp->Parameters.Write.Length; //获取写入数据的长度
PUCHAR buf = (PUCHAR)irp->AssociatedIrp.SystemBuffer; //取得系统缓冲区数据
for(i=0;i<len;++i)
{
DbgPrint("%2x,",buf[i]); //打印内容
}
}
if(irpsp->MajorFunction == IRP_MJ_READ)
{
//因为读的是需要完成后才能得到,所以用回调函数来获取
IoCopyCurrentIrpStackLocationToNext(irp);
IoSetCompletionRoutine(irp, fengReadComplete, device, TRUE, TRUE, TRUE);
return IoCallDriver(s_nextobj,irp);
}
//其它请求直接下发(不禁止也不修改)
IoSkipCurrentIrpStackLocation(irp);
return IoCallDriver(s_nextobj,irp);
}
// 如果根本就不在被绑定的设备中,那是有问题的,直接返回参数错误。
irp->IoStatus.Information = 0;
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(irp,IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS fengReadComplete(PDEVICE_OBJECT DeviectObject,PIRP Irp,PVOID Context) //IRP_MJ_READ回调函数
{
PIO_STACK_LOCATION IrpSp;
ULONG i;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
if(NT_SUCCESS( Irp->IoStatus.Status)) //读成功才处理
{
PUCHAR buf = (PUCHAR)[color=#ff0000]Irp->AssociatedIrp.SystemBuffer[/color]; //取得系统缓冲区数据
for(i=0; i<[color=#ff0000]Irp->IoStatus.Information[/color]; i++)
{
DbgPrint("%02X, ", buf[i]);
}
}
if( Irp->PendingReturned)
IoMarkIrpPending( Irp);
return Irp->IoStatus.Status;
} 经测试dbg里可以显示读写的数据 而且修改IRP_MJ_READ回调函数里面的缓冲区数据最终会导致程序接收到的数据是修改过的(也就是说成功了) 但是我想写个应用程序来动态修改IRP_MJ_READ回调函数里面的缓冲区数据(目的就是修改COM1设备传回的数据) 可是不知道怎么通信...... 刚学驱动开发...以前用VC写程序(于其说写不如说复制)....汗 |
|