LLLXXXIIIAAAOOO
驱动牛犊
驱动牛犊
  • 注册日期2012-09-27
  • 最后登录2013-03-14
  • 粉丝2
  • 关注2
  • 积分6分
  • 威望41点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:3126回复:4

WriteFile 和ReadFile的派遣函数的问题

楼主#
更多 发布于:2012-10-03 22:08
我写了一个简单的驱动程序。
写了WriteFile, ReadFile的派遣函数,想实现用WriteFile写设备,然后使用ReadFile将写的内容又读出来。但是在读的过程中出现了问题。前面的四个四节读不到

 
代码是《windows驱动开发技术详解》里面的,我做了一些修改, 下面是WriteFile的派遣函数。我自己觉得应该是memcpy函数处的问题,第一个参数应该是操作系统提供的缓冲区,这里我不确定我写的对不对。
ReadFile的派遣函数什么都没做。然后输出的结果就上上图所示。
希望高手能帮忙找到原因。谢谢~~~

NTSTATUS HelloDDKWrite(IN PDEVICE_OBJECT pDevObj,
       IN PIRP pIrp)
{
 KdPrint(("Enter HelloDDKWrite\n"));
 
 //对一般IRP的简单操作,后面会介绍对IRP更复杂的操作
 NTSTATUS status = STATUS_SUCCESS;
 
 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
 
 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
 ULONG ulWriteLength = stack->Parameters.Write.Length;
 KdPrint(("ulWriteLength : %d\n",ulWriteLength));
 
 ULONG ulWriteOffset = (ULONG)stack->Parameters.Write.ByteOffset.QuadPart;
 KdPrint(("ulWriteOffset : %d\n",ulWriteOffset));
 KdPrint(("pDevExt->ustrDeviceName.MaximumLength : %d\n",pDevExt->ustrDeviceName.MaximumLength));
 KdPrint(("pDevExt->ustrDeviceName.Length : %d\n",pDevExt->ustrDeviceName.Length));
 
 if(ulWriteOffset + ulWriteLength > pDevExt->ustrDeviceName.MaximumLength)
 {
  //如果存储长度+偏移量大于缓冲区长度,则返回无效
  status =  STATUS_FILE_INVALID;
  
  ulWriteLength = 0;
 }
 else
 {
  memcpy(pDevExt->ustrDeviceName.Buffer + ulWriteOffset + 8, pIrp->AssociatedIrp.SystemBuffer, ulWriteLength);
  //memset(pIrp->AssociatedIrp.Sys temBuffer,0xCC,ulWriteLength);
  status = STATUS_SUCCESS;
  if (ulWriteLength + ulWriteOffset > pDevExt->ustrDeviceName.MaximumLength)
  {
   //pDevExt->ustrDeviceName.MaximumLength = ulWriteLength + ulWriteOffset;
  }
 }
 
 pIrp->IoStatus.Status = status;
 
 pIrp->IoStatus.Information = ulWriteLength;
 
 //处理IRP
 IoCompleteRequest( pIrp, IO_NO_INCREMENT );
 
 KdPrint(("Leave HelloDDKWrite\n"));
 
 return status;
}
 
 

NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,
         IN PIRP pIrp)
{
 KdPrint(("Enter HelloDDKRead\n")); //对一般IRP的简单操作,后面会介绍对IRP更复杂的操作
 NTSTATUS status = STATUS_SUCCESS;
 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp); ULONG ulReadLength = stack->Parameters.Read.Length;
 KdPrint(("ulReadLength : %d\n",ulReadLength));
 
 // 完成IRP
 //设置IRP完成状态
 pIrp->IoStatus.Status = status; //设置IRP操作了多少字节
 pIrp->IoStatus.Information = ulReadLength; // bytes xfered
 //memset(pIrp->AssociatedIrp.SystemBuffer,0xCC,ulReadLength); //处理IRP
 IoCompleteRequest( pIrp, IO_NO_INCREMENT );
 KdPrint(("Leave HelloDDKRead\n")); return status;
}
wangbosi
驱动牛犊
驱动牛犊
  • 注册日期2011-06-16
  • 最后登录2013-12-21
  • 粉丝1
  • 关注4
  • 积分3788分
  • 威望281点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2012-10-04 00:25
在你的HelloDDKRead() Routine中没有拷贝的语句。应该把你的先前的保存在设备扩展中的数据拷贝到SystemBuffer中。
LLLXXXIIIAAAOOO
驱动牛犊
驱动牛犊
  • 注册日期2012-09-27
  • 最后登录2013-03-14
  • 粉丝2
  • 关注2
  • 积分6分
  • 威望41点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2012-10-04 15:43
是ReadFile 派遣函数的问题吗?
我在ReadFile派遣函数中,注释掉的memset函数,就是将SystemBuffer 全部设置为0xAA。
pIrp->associatedirp.Systembuffer应该指向的是用户模式下,WriteFile ReadFile 的缓冲区地址吧?
在ReadFile的派遣函数中,memset那一行代码的作用是给这个用户模式的缓冲区赋值。那么在WriteFile的派遣函数中,
应该是从pIrp->associateed.SystemBuffer里面读出要写入设备的内容,然后把这个内容放到操作系统的内核缓冲区中去。
我现在的问题是: 不知道怎样表示操作系统的内核模式下的缓冲区的地址。
我现在用的是:pDevExt->ustrDeviceName.Buffer。我不知道这个对不对?
LLLXXXIIIAAAOOO
驱动牛犊
驱动牛犊
  • 注册日期2012-09-27
  • 最后登录2013-03-14
  • 粉丝2
  • 关注2
  • 积分6分
  • 威望41点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2012-10-05 10:37
谢谢高手指点。
我已经在ReadFile函数中加入了将内核缓冲区的数据复制到用户模式缓冲区的代码。并且已经运行成功了。
这是ReadFile派遣函数中的代码:
memcpy(pIrp->AssociatedIrp.SystemBuffer, pDevExt->ustrDeviceName.Buffer + ulReadOffset, ulReadLength);
将内核缓冲区的数据复制到用户模式缓冲区。
memcpy(pDevExt->ustrDeviceName.Buffer + ulWriteOffset, pIrp->AssociatedIrp.SystemBuffer, ulWriteLength);
这是WriteFile派遣函数的代码,将用户模式缓冲区复制到内核缓冲区中。
 
用户模式的缓冲区pIrp->AssociatedIrp.SystemBuffer
内核模式的缓冲区pDevExt->ustrDeviceName.Buffer + ulWriteOffset
sunsea
驱动牛犊
驱动牛犊
  • 注册日期2013-03-09
  • 最后登录2013-06-01
  • 粉丝0
  • 关注0
  • 积分39分
  • 威望231点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分2分
地下室#
发布于:2013-04-05 20:50
SystemBuffer是内核地址,UserBuffer才是用户地址
游客

返回顶部