chrys
驱动小牛
驱动小牛
  • 注册日期2002-05-30
  • 最后登录2008-07-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:3429回复:22

怎样通过DeviceControl()将驱动中的数据传输给应用程序?

楼主#
更多 发布于:2002-07-19 11:30
大家好:
    我在驱动里要做个硬件检测的功能,并在IRP_MJ_DEVICE_CONTROL分发例程中完成,应用程序通过DeviceIoControl()Win32 API取得驱动程序对硬件检测的结果,我如何在驱动中将检测后的数据传给应用程序呢?
Win32 API 的 DeviceIoControl()函数的原型如下:
BOOL DeviceIoControl( HANDLE hDevice,DWORD dwIoControlCode,LPVOID lpInBuffer,DWORD nInBufferSize,LPVOID lpOutBuffer, DWORD nOutBufferSize,LPDWORD lpBytesReturned,LPOVERLAPPED lpOverlapped);
这里有两个参数: lpOutBuffer,nOutBufferSize,这是不是由驱动程序传输给应用程序的数据?在驱动程序里怎样将数据填入这个缓冲?我试着把数据填入Irp->UserBuffer中,但是应用程序并不能取到填入的数据。我该怎么做?

最新喜欢:

zhangc98zhangc... dongjundongju... Ice_BinIce_Bi...
天才来自勤奋 知识要靠学习 [url= http://ndxz.126.com]――欢迎来我家做客――[/url]
trent
驱动老牛
驱动老牛
  • 注册日期2002-03-01
  • 最后登录2014-09-18
  • 粉丝0
  • 关注0
  • 积分61分
  • 威望185点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-07-19 11:49
看walter oney书的第九章
我不仅要金子,我还要点石成金的手指!
zydcat
驱动老牛
驱动老牛
  • 注册日期2001-12-06
  • 最后登录2006-04-12
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-07-19 11:57
那两个只是缓冲区的指针

要看你在驱动中怎么用了。

[color=red]肥虫虫[/color] [img]http://www.driverdevelop.com/forum/upload/bradley/2002-11-15_ig01.gif[/img]
arthurtu
驱动巨牛
驱动巨牛
  • 注册日期2001-11-08
  • 最后登录2020-12-19
  • 粉丝0
  • 关注0
  • 积分26分
  • 威望161点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
  • 社区居民
地板#
发布于:2002-07-19 18:01
不是UserBuffer,都是SystemBuffer
mengzi
驱动牛犊
驱动牛犊
  • 注册日期2001-08-02
  • 最后登录2004-05-25
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2002-07-19 22:03
这两个参数,InBuffer用于缓冲IO,OutBuffer用于直接IO,后者即可以作为输入又同时可以作为输出,如果需要输入数据,用METHOD_IN_DIRECT类型,在内核获取缓冲区的地址和长度有两种途径,一种是通过MDL,一种是通过I,两者是等效的,由于在外边上网,记不起具体的函数了,但长度的获取还是记得的,通过I.IoctlOutputBufferSize()或m_Mdl.Size()
mengzi
驱动牛犊
驱动牛犊
  • 注册日期2001-08-02
  • 最后登录2004-05-25
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-07-19 22:10
我想起来了,用户缓冲区的地址是这样获取的,
KMemory Mem(I.Mdl());
PULONG pBuffer = (PULONG) Mem.MapToSystemSpace();

CODE的宏如下定义,0x800的位置可能与我这儿的不一样
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)

这是直接IO方式,InBuffer即InBufferSize,这两个参数不需要,只需是NULL和0
magicx
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2014-08-18
  • 粉丝1
  • 关注0
  • 积分-14分
  • 威望13点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2002-07-20 02:17
不是UserBuffer,都是SystemBuffer


???

[color=red]大头鬼! :P[/color]
magicx
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2014-08-18
  • 粉丝1
  • 关注0
  • 积分-14分
  • 威望13点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2002-07-20 02:33
大家好:
    我在驱动里要做个硬件检测的功能,并在IRP_MJ_DEVICE_CONTROL分发例程中完成,应用程序通过DeviceIoControl()Win32 API取得驱动程序对硬件检测的结果,我如何在驱动中将检测后的数据传给应用程序呢?
Win32 API 的 DeviceIoControl()函数的原型如下:
BOOL DeviceIoControl( HANDLE hDevice,DWORD dwIoControlCode,LPVOID lpInBuffer,DWORD nInBufferSize,LPVOID lpOutBuffer, DWORD nOutBufferSize,LPDWORD lpBytesReturned,LPOVERLAPPED lpOverlapped);
这里有两个参数: lpOutBuffer,nOutBufferSize,这是不是由驱动程序传输给应用程序的数据?在驱动程序里怎样将数据填入这个缓冲?我试着把数据填入Irp->UserBuffer中,但是应用程序并不能取到填入的数据。我该怎么做?


这具体要看此时的DeviceIoControl中的参数dwIoControlCode的定义(用法),对于缓冲区的用法大体上有四种。
直接的,入,出缓冲的,非I/O 的。。。。。。。
正如这样的形式:
“CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)”------------

其每位都有含义(决定了缓冲lpInBuffer,lpOutBuffer的用法方式)。。。。。。。

“我试着把数据填入Irp->UserBuffer中,但是应用程序并不能取到填入的数据。”
---------------- 只有当你指明为“非I/O方式”时才可看到,其他的方式时不是通过Irp->UserBuffer!!!

以上只是一些提示,具体的,建议你自己再仔细看。。。。。

不懂再来。。。。

嘿嘿。。。。。

 :)
[color=red]大头鬼! :P[/color]
chrys
驱动小牛
驱动小牛
  • 注册日期2002-05-30
  • 最后登录2008-07-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-07-22 09:12
很感谢大家给我的解答,但我仍然有很多疑问:
1、请问walter oney书在哪可买到,是什么书?
2、我仍然不知道,在DeviceIoCtrol()里要怎样做才能把驱动程序里的数据传送到应用程序?能举个简单点的例子吗?
3、耽误你们的时间我深表歉意。
天才来自勤奋 知识要靠学习 [url= http://ndxz.126.com]――欢迎来我家做客――[/url]
arthurtu
驱动巨牛
驱动巨牛
  • 注册日期2001-11-08
  • 最后登录2020-12-19
  • 粉丝0
  • 关注0
  • 积分26分
  • 威望161点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
  • 社区居民
9楼#
发布于:2002-07-22 15:31
programming the windows driver model
本站好像有下的。
wangxdong
驱动小牛
驱动小牛
  • 注册日期2002-07-08
  • 最后登录2003-01-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2002-07-22 16:20
给你一段例程,我试过。如果有用,请给我加点分。
在用户应用程序中:
void Test_BAUD_IOCTL_GETBAUD(void)
{
CHAR bufInput[IOCTL_INBUF_SIZE]; // Input to device
CHAR bufOutput[IOCTL_OUTBUF_SIZE]; // Output from device
ULONG nOutput; // Count written to bufOutput

// Call device IO Control interface (READ_DATA) in driver
bufOutput[0]=\'w\';
bufOutput[1]=\'a\';
bufOutput[2]=\'h\';
printf(\"Received data : \");
if (!DeviceIoControl(hDevice,
BAUD_IOCTL_GETBAUD,
bufInput,
IOCTL_INBUF_SIZE,
bufOutput,
IOCTL_OUTBUF_SIZE,
&nOutput,
NULL)
  )
{
printf(\"ERROR: DeviceIoControl returns %0x.\", GetLastError());
exit(1);
}
printf(\"%s\\n\", bufOutput);*/
}

然后,在驱动程序中:

NTSTATUS BaudDevice::BAUD_IOCTL_GETBAUD_Handler(KIrp I)
{
const char* TEST_WAH = \"TEST OK! - WAH,It\'s written by wangxdong!\";
ULONG fwLength=0;
NTSTATUS status;

    fwLength = strlen(TEST_WAH)+1;

    if (I.IoctlOutputBufferSize() >= fwLength)
    {
strcpy((PCHAR)I.IoctlBuffer(),TEST_WAH);
// KMemory Mem(I.Mdl());
// strcpy((PCHAR)Mem.MapToSystemSpace(),TEST_WAH);
// PVOID pa=MmGetSystemAddressForMdl(I.Mdl());//DDK的用法
// strcpy((PCHAR)pa,TEST_WAH);
// strcpy((PCHAR)I.UserBuffer(),TEST_WAH);
        I.Information() = fwLength;
        status = STATUS_SUCCESS;
    }
    else
    {
        I.Information() = 0;
        status = STATUS_BUFFER_TOO_SMALL;
}

return status;
}

这样,就能把驱动程序缓冲区的东西复制到应用程序中了!
应用程序执行结果显示TEST OK! - WAH,It\'s written by wangxdong! 变量 I.Information是要复制的字节数,如改为4,则只显示TEST四个字符
呵呵,我也是刚明白,大家共享一下经验!
请多多指教!
chrys
驱动小牛
驱动小牛
  • 注册日期2002-05-30
  • 最后登录2008-07-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2002-07-22 16:34
wangxdong 你好:
    感谢你给我的回答,你说的情况(用driverstudio)确实可行,只是我现在是用ddk做驱动,实在不知道要怎么做,你能帮我吗?再次感谢你。
天才来自勤奋 知识要靠学习 [url= http://ndxz.126.com]――欢迎来我家做客――[/url]
wangxdong
驱动小牛
驱动小牛
  • 注册日期2002-07-08
  • 最后登录2003-01-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2002-07-22 17:10
不好意思,我刚接触DS,DDK所知尚浅,帮不了你乐。
请多多指教!
wangxdong
驱动小牛
驱动小牛
  • 注册日期2002-07-08
  • 最后登录2003-01-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2002-07-22 17:21
我还是把我所知的一二全倒出来吧,其实原理是一样的,DS只是把DDK的东西封装起来了,里面还是DDK,lpOutBuffer确实是驱动程序传递给应用程序的缓冲,它对应于驱动程序中的I.IoctlBuffer,DDK中就是AssociatedIrp.SystemBuffer ,只要这两个缓冲区设置为类型相匹配,再把IoStatus.Information设成需要传递数据的字节数,就可以了。
DDK开发的那本书有7M,不便作为附件,本站的下载区有下载,去找找吧。
请多多指教!
chrys
驱动小牛
驱动小牛
  • 注册日期2002-05-30
  • 最后登录2008-07-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2002-07-22 17:40
wangxdong 你好:
    我试过将驱动里的数据存入到AssociatedIrp.SystemBuffer中,然后在应用层中lpOutBuffer却没有得到相应的数据,要将AssociatedIrp.SystemBuffer做为输出缓冲(即填入该缓冲的数据应用程序可以通过lpOutBuffer取到)是不是要设置缓冲方式为“METHOD_IN_DIRECT”?我用的方式是“METHOD_BUFFERED”,是不是不正确?“METHOD_IN_DIRECT”不是只有在dma中才用的吗?我现在不是dma方式的啊?
天才来自勤奋 知识要靠学习 [url= http://ndxz.126.com]――欢迎来我家做客――[/url]
wangxdong
驱动小牛
驱动小牛
  • 注册日期2002-07-08
  • 最后登录2003-01-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2002-07-22 18:37
METHOD_BUFFERED没错,但要记得IoStatus.Information设成需要传递数据的字节数,还有两个缓冲区的类型要转换为相匹配。
请多多指教!
chrys
驱动小牛
驱动小牛
  • 注册日期2002-05-30
  • 最后登录2008-07-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2002-07-22 20:40
我还是把我所知的一二全倒出来吧,其实原理是一样的,DS只是把DDK的东西封装起来了,里面还是DDK,lpOutBuffer确实是驱动程序传递给应用程序的缓冲,它对应于驱动程序中的I.IoctlBuffer,DDK中就是AssociatedIrp.SystemBuffer ,只要这两个缓冲区设置为类型相匹配,再把IoStatus.Information设成需要传递数据的字节数,就可以了。
DDK开发的那本书有7M,不便作为附件,本站的下载区有下载,去找找吧。


我找不到你说的这本书,请你告诉我下载地址好吗?发到我邮箱也可以(xiehw@zhongjie.com.cn)不胜感激!
天才来自勤奋 知识要靠学习 [url= http://ndxz.126.com]――欢迎来我家做客――[/url]
Reehac
驱动牛犊
驱动牛犊
  • 注册日期2001-06-27
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2002-07-23 07:44
有一点很奇怪,我作这个事情的时候,却是用AssociatedIrp.SystemBuffer怎么也无法传出,调了两天才发现用Irp->UserBuff倒对了,给你看看我的程序:

//得到参数:
 PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(pIrp);
  ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  ULONG OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

//输入:
   RtlCopyMemory(Buf,pIrp->AssociatedIrp.SystemBuffer,InputLength);
 DBuf=Buf+200;
//输出:
  RtlCopyMemory(pIrp->UserBuffer,DBuf,OutputLength);
chrys
驱动小牛
驱动小牛
  • 注册日期2002-05-30
  • 最后登录2008-07-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2002-07-23 08:47
有一点很奇怪,我作这个事情的时候,却是用AssociatedIrp.SystemBuffer怎么也无法传出,调了两天才发现用Irp->UserBuff倒对了,给你看看我的程序:

//得到参数:
 PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(pIrp);
  ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  ULONG OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

//输入:
   RtlCopyMemory(Buf,pIrp->AssociatedIrp.SystemBuffer,InputLength);
 DBuf=Buf+200;
//输出:
  RtlCopyMemory(pIrp->UserBuffer,DBuf,OutputLength);
 

这个实验我也做过,但没有成功,我是这样做的:

//在驱动中
PUCHAR OutBuffer = pIrp->UserBuffer;
OutBuffer[0] = 0;
OutBuffer[1] = 1;
OutBuffer[2] = 2;
OutBuffer[3] = 3;

//在应用程序中
DWORD BytesReturned;
WORD rv[4];
UCHAR ConnectToInterrupts[128];
if( DeviceIoControl( g_ZjMdmHandle, dwIoControlCode,
ConnectToInterrupts, length(ConnectToInterrupts), // Input
rv, sizeof(rv), // Output
&BytesReturned, NULL))
return (UCHAR)BytesReturned;
else
return FALSE;
我希望应用程序中的rv[4]能取得驱动里OutBuffer缓冲中的四个数据“0,1,2,3”,可我失败了,请问,我应该怎么做?
天才来自勤奋 知识要靠学习 [url= http://ndxz.126.com]――欢迎来我家做客――[/url]
Reehac
驱动牛犊
驱动牛犊
  • 注册日期2001-06-27
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2002-07-23 09:35
那你用这种的话缓冲方式设对没?有两个地方要设的。
我的应用程序是这样:
 DWORD result[32];
DWORD ret;
CString str;
    
if(WDM_Handle!=NULL)
    {
      if(!DeviceIoControl(WDM_Handle,
              IOCTL_READ_DDC,
   NULL,
  0,
                        &result,
  sizeof(result),
  &ret,
  NULL))
 {
   AfxMessageBox(\"调用失败!\");
return;
 }
}
for(int i=0;i<32;i++)
{
str.Format(\"%x\",result);
AfxMessageBox(str);
}
上一页
游客

返回顶部