stoneabc
驱动牛犊
驱动牛犊
  • 注册日期2004-12-06
  • 最后登录2007-11-28
  • 粉丝0
  • 关注0
  • 积分40分
  • 威望5点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
阅读:14245回复:23

c从kernel里映射出来的地址在applicatinon里为什么不好使?(付有代码,50分)

楼主#
更多 发布于:2005-01-23 22:05
PVOID pBee;
PVOID userAddress;

在DispatchIOControl里的代码:
......
......
pBee = ExAllocatePoolWithTag(NonPagedPool,PAGE_SIZE,'xjuw');
mdl = IoAllocateMdl(pBee,PAGE_SIZE,FALSE,FALSE,NULL);
MmBuildMdlForNonPagedPool(mdl);
outBeeAddress= MmMapLockedPagesSpecifyCachemdl,UserMode,MmCached,
NULL,FALSE,NormalPagePriority);
RtlCopyMemory(pSmartcardExtension->IoRequest.ReplyBuffer,&outBeeAddress,sizeof(PVOID));
*pSmartcardExtension->IoRequest.Information = sizeof(PVOID);
return STATUS_SUCCESS;
我省去了一些检查分配的代码,outBeeAddress de的值是0x630000.

z在application端的代码:
PVOID    pBeeAddress;
unsigned char abc[10] = {0x01,0x02...0x0A};

通过DeviceIOControl得到kernel里传出的outBeeAddress的值,
然后我发现pBeeAddress的是确实也是0x630000.
但是当我做:
memcpy(pBeeAddress,abc,10);
的时候application程序就崩掉了,请问为深么啊?0x630000不是从kernel里映射到user地址空间的地址吗?

最新喜欢:

imlymimlym
KMK
KMK
驱动大牛
驱动大牛
  • 注册日期2001-09-12
  • 最后登录2017-10-06
  • 粉丝2
  • 关注0
  • 积分42分
  • 威望404点
  • 贡献值2点
  • 好评度58点
  • 原创分1分
  • 专家分1分
  • 社区居民
沙发#
发布于:2005-01-23 23:56
 

    {        
        DWORD size = MmSizeOfMdl(pHeader,bufferSize); // map pHeader to user
        pMdl = (PMDL)ExAllocatePool( NonPagedPool, size );
        pMdl = MmCreateMdl( pMdl, pHeader, bufferSize);


        if ( (pMdl->MdlFlags & (MDL_PAGES_LOCKED |
                                MDL_SOURCE_IS_NONPAGED_POOL |
                                MDL_MAPPED_TO_SYSTEM_VA |
                                MDL_PARTIAL) ) == 0)
            MmBuildMdlForNonPagedPool(pMdl);


        PVOID ptr = MmMapLockedPages(pMdl, UserMode);

        if ( ptr == NULL )
            *(PDBGTRAP_HEADER*)outputBuffer = NULL;
        else
            *(PDBGTRAP_HEADER*)outputBuffer = (PDBGTRAP_HEADER) (ULONG(ptr) | MmGetMdlByteOffset(pMdl));
DbgPrint("Pointer %x + Offset %x \n", ptr, MmGetMdlByteOffset(pMdl));    
    }


我是这样造的.
fslife
驱动大牛
驱动大牛
  • 注册日期2004-06-07
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望49点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2005-01-24 09:13
把outBeeAddress= MmMapLockedPagesSpecifyCachemdl,UserMode,MmCached,

改成MmBuildMdlForNonPagedPool(pMdl);

那个pBee应该就是返回的共享地址。
在交流中学习。。。
snowStart
驱动老牛
驱动老牛
  • 注册日期2004-04-06
  • 最后登录2011-06-02
  • 粉丝0
  • 关注0
  • 积分95分
  • 威望19点
  • 贡献值177点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地板#
发布于:2005-01-24 09:15
PVOID pBee;
PVOID userAddress;

在DispatchIOControl里的代码:
......
......
pBee = ExAllocatePoolWithTag(NonPagedPool,PAGE_SIZE,'xjuw');
mdl = IoAllocateMdl(pBee,PAGE_SIZE,FALSE,FALSE,NULL);
MmBuildMdlForNonPagedPool(mdl);
outBeeAddress= MmMapLockedPagesSpecifyCachemdl,UserMode,MmCached,
NULL,FALSE,NormalPagePriority);
RtlCopyMemory(pSmartcardExtension->IoRequest.ReplyBuffer,&outBeeAddress,sizeof(PVOID));
*pSmartcardExtension->IoRequest.Information = sizeof(PVOID);
return STATUS_SUCCESS;
我省去了一些检查分配的代码,outBeeAddress de的值是0x630000.

z在application端的代码:
PVOID    pBeeAddress;
unsigned char abc[10] = {0x01,0x02...0x0A};

通过DeviceIOControl得到kernel里传出的outBeeAddress的值,
然后我发现pBeeAddress的是确实也是0x630000.
但是当我做:
memcpy(pBeeAddress,abc,10);
的时候application程序就崩掉了,请问为深么啊?0x630000不是从kernel里映射到user地址空间的地址吗?


试一试在映射前加一句

MmProbeAndLockPages(Mdl, KernelMode, IoWriteAccess);
学习,关注,交流中... [email=fengyu@163.com]Email:snowstarth@163.com[/email] [url]http://bbs.zndev.com/?a=snowStart[/url]
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
地下室#
发布于:2005-01-24 09:30
你在应用层访问该地址前用SOFTICE看看该地址是否已经存在了?
还有建议你在DRIVERENTRY里分配内存,影射MDL等,而在DispatchIOControl里只需MmMapLockedPages即可.
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
AllenZh
驱动老牛
驱动老牛
  • 注册日期2001-08-19
  • 最后登录2015-11-27
  • 粉丝19
  • 关注10
  • 积分1316分
  • 威望2387点
  • 贡献值7点
  • 好评度321点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2005-01-24 09:39
看看下面的代码
PVOID pBee;
PVOID userAddress;

在DispatchIOControl里的代码:
......
......
pBee = ExAllocatePoolWithTag(NonPagedPool,PAGE_SIZE,'xjuw');
mdl = IoAllocateMdl(pBee,PAGE_SIZE,FALSE,FALSE,NULL);
MmBuildMdlForNonPagedPool(mdl);
outBeeAddress= MmMapLockedPagesSpecifyCachemdl,UserMode,MmCached,
NULL,FALSE,NormalPagePriority);
RtlCopyMemory(pSmartcardExtension->IoRequest.ReplyBuffer,&outBeeAddress,sizeof(PVOID));
*pSmartcardExtension->IoRequest.Information = sizeof(PVOID);
return STATUS_SUCCESS;
我省去了一些检查分配的代码,outBeeAddress de的值是0x630000.

z在application端的代码:
PVOID    pBeeAddress;
unsigned char abc[10] = {0x01,0x02...0x0A};

通过DeviceIOControl得到kernel里传出的outBeeAddress的值,
然后我发现pBeeAddress的是确实也是0x630000.
但是当我做:
memcpy(pBeeAddress,abc,10);
的时候application程序就崩掉了,请问为深么啊?0x630000不是从kernel里映射到user地址空间的地址吗?
1,承接Windows下驱动/应用开发 2,本人原创虚拟鼠标/键盘,触摸屏,虚拟显卡,Mirror驱动,XP无盘的SCSI虚拟磁盘驱动等 3,windows下有尝技术服务(包括BUG调试,员工培训等) 欢迎深圳和海外企业联系.msn:mfczmh@sina.com
AllenZh
驱动老牛
驱动老牛
  • 注册日期2001-08-19
  • 最后登录2015-11-27
  • 粉丝19
  • 关注10
  • 积分1316分
  • 威望2387点
  • 贡献值7点
  • 好评度321点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2005-01-24 09:40
刚才附件没有发上去
附件名称/大小 下载次数 最后更新
2005-01-24_Section.exe (32KB)  56
1,承接Windows下驱动/应用开发 2,本人原创虚拟鼠标/键盘,触摸屏,虚拟显卡,Mirror驱动,XP无盘的SCSI虚拟磁盘驱动等 3,windows下有尝技术服务(包括BUG调试,员工培训等) 欢迎深圳和海外企业联系.msn:mfczmh@sina.com
stoneabc
驱动牛犊
驱动牛犊
  • 注册日期2004-12-06
  • 最后登录2007-11-28
  • 粉丝0
  • 关注0
  • 积分40分
  • 威望5点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2005-01-24 11:46
[quote]
    {        
        DWORD size = MmSizeOfMdl(pHeader,bufferSize); // map pHeader to user
        pMdl = (PMDL)ExAllocatePool( NonPagedPool, size );
        pMdl = MmCreateMdl( pMdl, pHeader, bufferSize);


        if ( (pMdl->MdlFlags & (MDL_PAGES_LOCKED |
                                MDL_SOURCE_IS_NONPAGED_POOL |
                                MDL_MAPPED_TO_SYSTEM_VA |
                                MDL_PARTIAL) ) == 0)
            MmBuildMdlForNonPagedPool(pMdl);


        PVOID ptr = MmMapLockedPages(pMdl, UserMode);

        if ( ptr == NULL )
            *(PDBGTRAP_HEADER*)outputBuffer = NULL;
        else
            *(PDBGTRAP_HEADER*)outputBuffer = (PDBGTRAP_HEADER) (ULONG(ptr) | MmGetMdlByteOffset(pMdl));
DbgPrint("Pointer %x + Offset %x n", ptr, MmGetMdlByteOffset(pMdl));    
    }


我是这样造的. [/quote]

这样不行,我试过了,在app里说access violation,我想也是这样,一个kernel的地址怎么可以直接拿来app里用
stoneabc
驱动牛犊
驱动牛犊
  • 注册日期2004-12-06
  • 最后登录2007-11-28
  • 粉丝0
  • 关注0
  • 积分40分
  • 威望5点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2005-01-24 11:49
你在应用层访问该地址前用SOFTICE看看该地址是否已经存在了?
还有建议你在DRIVERENTRY里分配内存,影射MDL等,而在DispatchIOControl里只需MmMapLockedPages即可.



拿到的0x00630000确实在VC的debug里看到内容都是??????,
那么为什么映射出来的地址会没定义呢,我已经在driverEntry里声明内存和分配mdl了,在ioctrl里进行映射,可是还是没用啊
stoneabc
驱动牛犊
驱动牛犊
  • 注册日期2004-12-06
  • 最后登录2007-11-28
  • 粉丝0
  • 关注0
  • 积分40分
  • 威望5点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2005-01-24 11:56
[quote]
    {        
        DWORD size = MmSizeOfMdl(pHeader,bufferSize); // map pHeader to user
        pMdl = (PMDL)ExAllocatePool( NonPagedPool, size );
        pMdl = MmCreateMdl( pMdl, pHeader, bufferSize);


        if ( (pMdl->MdlFlags & (MDL_PAGES_LOCKED |
                                MDL_SOURCE_IS_NONPAGED_POOL |
                                MDL_MAPPED_TO_SYSTEM_VA |
                                MDL_PARTIAL) ) == 0)
            MmBuildMdlForNonPagedPool(pMdl);


        PVOID ptr = MmMapLockedPages(pMdl, UserMode);

        if ( ptr == NULL )
            *(PDBGTRAP_HEADER*)outputBuffer = NULL;
        else
            *(PDBGTRAP_HEADER*)outputBuffer = (PDBGTRAP_HEADER) (ULONG(ptr) | MmGetMdlByteOffset(pMdl));
DbgPrint("Pointer %x + Offset %x n", ptr, MmGetMdlByteOffset(pMdl));    
    }


我是这样造的. [/quote]


请给一些你的变量说明好吗?
stoneabc
驱动牛犊
驱动牛犊
  • 注册日期2004-12-06
  • 最后登录2007-11-28
  • 粉丝0
  • 关注0
  • 积分40分
  • 威望5点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2005-01-24 12:10


试一试在映射前加一句

MmProbeAndLockPages(Mdl, KernelMode, IoWriteAccess);


试过了,也没用。
stoneabc
驱动牛犊
驱动牛犊
  • 注册日期2004-12-06
  • 最后登录2007-11-28
  • 粉丝0
  • 关注0
  • 积分40分
  • 威望5点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2005-01-24 12:11
救命啊,
有谁能看出问题在哪儿吗?
bmyyyud
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2010-01-21
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望130点
  • 贡献值0点
  • 好评度106点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2005-01-25 16:02
从0x630000这个地址上看,小于2G,肯定是应用层地址,我估计是应用层地址在这段上尚未映射,是空洞。
滚滚长江东逝水 浪花淘尽英雄 是非成败转头空 青山依旧在 几度夕阳红 白发渔樵江渚上 惯看秋月春风 一壶浊酒喜相逢 古今多少事 尽付笑谈中
AllenZh
驱动老牛
驱动老牛
  • 注册日期2001-08-19
  • 最后登录2015-11-27
  • 粉丝19
  • 关注10
  • 积分1316分
  • 威望2387点
  • 贡献值7点
  • 好评度321点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2005-01-25 22:57
救命啊,
有谁能看出问题在哪儿吗?

看了我上面的哪个代码吗?
仔细参考看看,应该可以
1,承接Windows下驱动/应用开发 2,本人原创虚拟鼠标/键盘,触摸屏,虚拟显卡,Mirror驱动,XP无盘的SCSI虚拟磁盘驱动等 3,windows下有尝技术服务(包括BUG调试,员工培训等) 欢迎深圳和海外企业联系.msn:mfczmh@sina.com
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
14楼#
发布于:2005-01-26 09:17
把你完整的工程贴上来看看.......
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
stoneabc
驱动牛犊
驱动牛犊
  • 注册日期2004-12-06
  • 最后登录2007-11-28
  • 粉丝0
  • 关注0
  • 积分40分
  • 威望5点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2005-01-26 17:02
[quote]救命啊,
有谁能看出问题在哪儿吗?

看了我上面的哪个代码吗?
仔细参考看看,应该可以 [/quote]

我看了,可是那个是每次交换数据都要通过DeviceIOControl的,我的要求是映射一次就一直可以用啊,看看我发的新帖子好吗,里面有我的driver的具体需求和实现设想,谢谢
stoneabc
驱动牛犊
驱动牛犊
  • 注册日期2004-12-06
  • 最后登录2007-11-28
  • 粉丝0
  • 关注0
  • 积分40分
  • 威望5点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2005-01-26 17:07
从0x630000这个地址上看,小于2G,肯定是应用层地址,我估计是应用层地址在这段上尚未映射,是空洞。


请问“用层地址在这段上尚未映射,是空洞”是什么意思?

我确实没有在应用层开出一个buffer,
只是声明了一个PVOID pFromKernel 指针,
并把0x630000附给这个指针,然后就直接写诸如:
pFromKernel[0] = 0x01;
这时app就出问题了。

请问我是不是在app里少做了什么啊?多谢各位了
bmyyyud
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2010-01-21
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望130点
  • 贡献值0点
  • 好评度106点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2005-01-27 11:11
就是这个地址在应用程序页表中尚未映射,还未用到这块空间
滚滚长江东逝水 浪花淘尽英雄 是非成败转头空 青山依旧在 几度夕阳红 白发渔樵江渚上 惯看秋月春风 一壶浊酒喜相逢 古今多少事 尽付笑谈中
stoneabc
驱动牛犊
驱动牛犊
  • 注册日期2004-12-06
  • 最后登录2007-11-28
  • 粉丝0
  • 关注0
  • 积分40分
  • 威望5点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2005-01-27 12:24
就是这个地址在应用程序页表中尚未映射,还未用到这块空间


怎么映射呀,在app里有api可以调吗?
bmyyyud
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2010-01-21
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望130点
  • 贡献值0点
  • 好评度106点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2005-01-27 15:59
[quote]就是这个地址在应用程序页表中尚未映射,还未用到这块空间


怎么映射呀,在app里有api可以调吗? [/quote]
看看这个
IoAllocateMdl 创建MDL
IoBuildPartialMdl 创建一个已存在MDL的子MDL
IoFreeMdl 销毁MDL
MmBuildMdlForNonPagedPool 修改MDL以描述内核模式中一个非分页内存区域
MmGetMdlByteCount 取缓冲区字节大小
MmGetMdlByteOffset 取缓冲区在第一个内存页中的偏移
MmGetMdlVirtualAddress 取虚拟地址
MmGetSystemAddressForMdl 创建映射到同一内存位置的内核模式虚拟地址
MmGetSystemAddressForMdlSafe 与MmGetSystemAddressForMdl相同,但Windows 2000首选
MmInitializeMdl (再)初始化MDL以描述一个给定的虚拟缓冲区
MmPrepareMdlForReuse 再初始化MDL
MmProbeAndLockPages 地址有效性校验后锁定内存页
MmSizeOfMdl 取为描述一个给定的虚拟缓冲区的MDL所占用的内存大小
MmUnlockPages 为该MDL解锁内存页

对于I/O管理器执行的Direct方式的读写操作,其过程可以想象为下面代码:

KPROCESSOR_MODE mode;   //  either KernelMode or UserMode
PMDL mdl = IoAllocateMdl(uva, length, FALSE, TRUE, Irp);
MmProbeAndLockPages(mdl, mode, reading ? IoWriteAccess : IoReadAccess);

<code to send and await IRP>

MmUnlockPages(mdl);
ExFreePool(mdl);
 

I/O管理器首先创建一个描述用户缓冲区的MDL。IoAllocateMdl的第三个参数(FALSE)指出这是一个主数据缓冲区。第四个参数(TRUE)指出内存管理器应把该内存充入进程配额。最后一个参数(Irp)指定该MDL应附着的IRP。在内部,IoAllocateMdl把Irp->MdlAddress设置为新创建MDL的地址,以后你将用到这个成员,并且I/O管理器最后也使用该成员来清除MDL。

这段代码的关键地方是调用MmProbeAndLockPages(以粗体字显示)。该函数校验那个数据缓冲区是否有效,是否可以按适当模式访问。如果我们向设备写数据,我们必须能读缓冲区。如果我们从设备读数据,我们必须能写缓冲区。另外,该函数锁定了包含数据缓冲区的物理内存页,并在MDL的后面填写了页号数组。在效果上,一个锁定的内存页将成为非分页内存池的一部分,直到所有对该页内存加锁的调用者都对其解了锁。

在Direct方式的读写操作中,对MDL你最可能做的事是把它作为参数传递给其它函数。例如,DMA传输的MapTransfer步骤需要一个MDL。另外,在内部,USB读写操作总使用MDL。所以你应该把读写操作设置为DO_DIRECT_IO方式,并把结果MDL传递给USB总线驱动程序。

顺便提一下,I/O管理器确实在stack->Parameters联合中保存了读写请求的长度,但驱动程序应该直接从MDL中获得请求数据的长度。

ULONG length = MmGetMdlByteCount(mdl);

不行的话,自己从0开始做就复杂了
 
滚滚长江东逝水 浪花淘尽英雄 是非成败转头空 青山依旧在 几度夕阳红 白发渔樵江渚上 惯看秋月春风 一壶浊酒喜相逢 古今多少事 尽付笑谈中
上一页
游客

返回顶部