MapPtrToProcess 用法 WINCE驱动分析3
以使用下面的应用程序代码测试这个driver,使用evc编译。
#include windows.h>
#includeWindev.h>
#include stdio.h>
#include "objbase.h"
#include "initguid.h"
#include "foo.h"
//char data1[10];
int WinMain(void)
{
HANDLE hnd;
COPY_STRUCT cs[1];
int i;
//static char data1[10];
auto char data1[10];
auto char data2[10];
static char* p1,*p2;
//cs.pBuffer1 = (char *)malloc(10);
//cs.pBuffer2 = (char*)malloc(10);
//cs.nLen = 10;
p1 = (char *)LocalAlloc(LPTR,10);
p2 = (char *)malloc(10);
//cs[0].pBuffer1 = (char *)malloc(10);
//cs[0].pBuffer2 = (char*)malloc(10);
cs[0].pBuffer1 = data1[0];
cs[0].pBuffer2 = data2[0];
cs[0].nLen = 10;
memset(cs[0].pBuffer1,'a',10);
hnd = CreateFile(FOO_DEV_NAME,GENERIC_READ|GENERIC_WRITE,0,NULL,0,0,NULL);
if(hnd==NULL)
{
printf("Open device falied!\n");
return;
}
DeviceIoControl(hnd,IOCTL_FOO_XER,cs[0],sizeof(COPY_STRUCT),NULL,0,NULL,NULL);
//for(i=0;i9;i++)
//{
//printf(" %c",*(cs.pBuffer2++));
//}
printf("\n");
CloseHandle(hnd);
// free(cs[0].pBuffer1);
// free(cs[0].pBuffer2);
}
可以通过evc的单步调试看结果。好了一切都完成了,我们来看看系统是怎么工作的吧,从应用程序开始,
CreateFile(FOO_DEV_NAME,GENERIC_READ|GENERIC_WRITE,0,NULL,0,0,NULL);
会调用到
FOO_Open(DWORD dwContext, DWORD AccessCode, DWORD ShareMode)
而FOO_DEV_NAME名字定义在foo.h里面。
#define FOO_DEV_NAME L"Foo1:"
注意后面是 1 ,这个是和注册表的这一项匹配的
"Index"=dword:1
当调用CreateFile发生了什么,slot之间的转换,一系列系统操作后,调用到我们自己的driver函数FOO_Open,在这个函数里我们返回了一个句柄,它可以用来存储我们的自己driver的信息。在其它I/O操作中可以使用。
Driver什么时候加载的?在注册表里,device manager会一个个的加载,会调用到FOO_Init函数。这个函数返回一个指针,在调用FOO_Open又传回来了,这样我们就可以实现初始化一些自己driver的东西。
接着一个重要的函数,
DeviceIoControl(hnd,IOCTL_FOO_XER,cs[0],sizeof(COPY_STRUCT),NULL,0,NULL,NULL);
调用到
FOO_IOControl
走到这里
case IOCTL_FOO_XER:
if((pInBuf==NULL))
{
SetLastError(ERROR_INVALID_PARAMETER);
break;
}
pcs = (COPY_STRUCT*)pInBuf;
__try{
pMap1 = MapPtrToProcess(pcs->pBuffer1,GetCallerProcess());
pMap2 = MapPtrToProcess(pcs->pBuffer2,GetCallerProcess());
DEBUG_OUT(1, (TEXT("+FOO_IOControl(0x%x,0x%x)\r\n"),pcs->pBuffer1,pcs->pBuffer2));
memcpy(pcs->pBuffer2,pcs->pBuffer1,pcs->nLen);
bResult = TRUE;
}
__except(EXCEPTION_EXECUTE_HANDLER){
DEBUG_OUT(1,(TEXT("Exception:FOO_IOCTL\r\n")));
break;
}
break;
default:
break;
这里又很多东西要研究,
从应用程序传来的参数有, control code,IOCTL_FOO_XER和一个重要的输入参数cs[0],它是一个指针。cs 是一个结构体,定义在FOO.H
typedef struct {
char* pBuffer1;
char* pBuffer2;
int nLen;
}COPY_STRUCT;
而且这个结构体里有两个指针。
DeviceIoControl 传过来的指针可以用吗?它包含的两个指针可以直接用吗?
按照PB连接帮助文档看,
The operating system (OS ) manages pointers passed directly as parameters. Drivers must map all pointers contained in structures. DeviceIoControl buffers are often structures that contain data, some of which might be pointers.
You can map a pointer contained in a structure by calling MapPtrToProcess, setting the first parameter to the pointer, and then setting the second parameter to GetCallerProcess.
cs指针已经映射好了,但是它指向的结构里的指针我们需要自己使用MapPtrToProcess函数映射。
这也就是:
pMap1 = MapPtrToProcess(pcs->pBuffer1,GetCallerProcess());
pMap2 = MapPtrToProcess(pcs->pBuffer2,GetCallerProcess());
的由来,可是后面的代码没有使用pMap1,pMap2。而是直接使用:
memcpy(pcs->pBuffer2,pcs->pBuffer1,pcs->nLen);
而且它还工作了,没有出现exception。很奇怪。我第一次在一个家伙的代码里看见这种情况,很吃惊,但是它工作的很好,是文档出错了?
我们来分析一
嵌入式新闻 嵌入式资料 嵌入式培训 嵌入式linux 嵌入式系统 嵌入式开发 嵌入式 相关文章:
- 煤矿井下综合自动化系统中的应用(04-06)
- 软件Overlay:程序编写与调试(01-20)
- USB数据通信接□模块的程序设计(10-17)
- 东江产业园:力争2017年产值达千亿(09-30)
- 硅谷数模的SlimPort扩大了Nexus7的显示屏选择(08-01)
- Lonworks控制网络技术在城市排水泵站自动化中的应用(06-06)