32位程序在64位系统上调用GetModuleFileNameEx失败
今天客户打来电话说我们公司的服务器程序在新装的64位Windows 2003上以系统服务方式启动不起来。初步怀疑是我们的32位服务程序哪个地方在64位机上不兼容了。结果忙活了一上午,终于找到了问题所在。程序里有一段代码是用来判断程序是以服务方式启动还是以窗口形式启动:在应用程序初始化时获得父进程的句柄。然后通过句柄获得父进程的执行程序全路径。如果全路径中存在"service.exe"字符串,则程序以服务方式启动。伪代码如下:
- HANDLE hParentProc; //Parent proccess handle initialize
- BOOL bRet; //Check if we should run it as service
- if(GetModuleFileNameEx(hParentProc, NULL, pszPath, MAX_PATH))
- {
- if(strstr(pszPath, "services.exe") != NULL)
- {
- bRet = TRUE;
- }
- }
通过调试发现问题出在 GetModuleFileNameEx函数上 。本来它返回的是获取全路径的长度 ,结果在64位机上返回0,pszPath变量并没有取得父进程的全路径。我用GetLastError()查看返回值为error 299——“Only part of a ReadProcessMemory or WriteProcessMemory request was completed.” 。我开始怀疑是因为32位程序调用API处理64位内存地址时出现的问题。
于是我Google了一下,终于找到答案了:
当我们调用GetModuleFileNameEx的API函数时,为了获得指定进程的全路径,它内部需要访问进程的PEB头(process environment block),将PEB中的信息设置到一个叫 PROCESS_BASIC_INFORMATION 的结构体中。结构体声明如下
- typedef struct _PROCESS_BASIC_INFORMATION {
- NTSTATUS ExitStatus;
- PPEB PebBaseAddress;
- ULONG_PTR AffinityMask;
- KPRIORITY BasePriority;
- ULONG_PTR UniqueProcessId;
- ULONG_PTR InheritedFromUniqueProcessId;
- } PROCESS_BASIC_INFORMATION;
其中PEB的地址被设置在PebBaseAddress中。但是64位进程的PEB头地址是保存在64位长度的地址中的(比如上面说道的系统进程Services.exe),而32位进程的PEB头地址只有32位长度。运行在64位系统上32位应用程序是如何将64位的PEB地址转换成32位地址的呢?如果64位PEB地址的高32位为0,则转换不会出现任何问题。但如果高32位也包含地址信息,那么WOW64(Windows 32-bit on Windows 64-bit,windows 64位系统上兼容32位应用程序的技术,作为由32位向64位程序的过渡方案)只是简单的将低32位的PEB地址赋给32位应用程序中的PebBaseAddress变量,当然就会发生错误了!于是Windows就会出发error 299并返回失败。
如果你的32位应用程序是运行在Windows XP或者以上的操作系统上的,推荐的解决方案是使用GetProccessImageFileName来替代GetModuleFileNameEx来取得进程的全路径,这个函数内部的内部操作不会像GetModuleFileName那样麻烦,只返回一个全路径字符串而已。但是返回的全路径是DOS格式的盘符路径( /Device/HarddiskVolumeX),因此需要自己再转换一下。
出了GetModuleFileNameEx之外,还有EnumProcessModule和 EnumProcessModuleEx 也会出现这样的问题,都是因为访问64位进程的PEB头的原因。CreateToolHelpSnapshot调用失败原因也与上面的原理类似。
参考:http://winprogger.com/?p=26
32位程序在64位系统上调用GetModuleFileNameEx失败相关推荐
- 32位程序在64位系统上运行
32位程序在64位系统上运行 32位系统下的MFC文件,怎么在64位的系统上面运行? 先将32位的应用程序转换为64位的应用程序. 从32位应用程序到64位应用程序 编译:starlight 这篇文章 ...
- 使用.netFx4.0提供的方法解决32位程序访问64位系统的64位注册表
原文:使用.netFx4.0提供的方法解决32位程序访问64位系统的64位注册表 我们知道目标平台是32位的程序运行在64位的系统上,去访问部分注册表的时候系统自动重定向到win32node节点对应的 ...
- 32位程序和64位程序
我们有时候会遇到这样一种情况:我们在32位操作系统上下载了64位版本的程序,却发现无法安装,大家可能会很困惑. 下面就来简单解释一下32位程序与64位程序的具体区别. 我们首先要弄明白的: 1.这里所 ...
- 32位程序和64位程序这些区别你知道吗?
我们在编写C/C++程序时,32位程序和64位程序的代码有何区别?如何编写既可以编译成32位程序又可以编译成64位程序的代码? 代码上的区别 实际上,对于32位程序和64位程序来说,代码上的区别不大, ...
- 32位程序注入64位DLL到64位进程
向其他进程注入DLL通常的做法是通过调用CreateRemoteThread这个API在目标进程内创建一个远程线程,用这个线程来调用LoadLibraryA或LoadLibraryW(下文统称Load ...
- Windows 32位程序在64位操作系统下运行
VS2013新建的VC++项目默认的组件平台是32位 要将它编译为64位程序,按以下步骤: 1.点击"Win32"下拉框,打开"配置管理器" 2.点击" ...
- PWN入门(5)32位程序与64位程序和构造ROP链
简介 "pwn"这个词的源起以及它被广泛地普遍使用的原因,源自于魔兽争霸某段讯息上设计师打字时拼错而造成的,原先的字词应该是"own"这个字,因为 'p' 与 ...
- Win32位程序(64位系统)文件对话框的文件重定向问题
目录 附注 问题背景 实验测试 解决方案 方案对比 参考文档 附注 1.解释下问题含义,指在一个64位Windows系统上面(譬如Win7x64,Win10x64),如果一个32位的程序调用系统API ...
- 在64位操作系统上运行32位的程序
运行 32 位程序 WOW64 子系统使 32 位程序能够在基于 x64 版本的 Windows Server 2003 和 Windows XP 专业 x64 版的运行而不用修改.WOW64 子系统 ...
最新文章
- linux内核用什么调试,什么是开发/调试Linux内核最有效和最优雅的方式
- CoreAnimation--CALayer的动画
- SharePoint 2013 Search REST API 使用示例
- 布朗大学和FAIR开源LA-MCTS,及其在神经网络结构搜索的应用
- java 原子量Atomic举例(AtomicReference)
- 解析函數論 Page 28 連續復變函數的最簡單的性質
- js与jQuery操作select大全
- 基于SSM框架的新闻管理系统
- 刘强东宣布:京东减员50%,每天工作3小时!这样的未来是你想要的吗?
- 特征工程之特征选择(3)----F检验和互信息法
- java poi 自动行高,20191012——POI设置单元格自动行高(思路)
- 区分度评估指标-KS
- Excel中的DATEDIF函数
- mysql 5.1 变量专题
- 肿瘤免疫疗法 | 细胞治疗和PD1/PDL1 | Tumor immunotherapy | cell therapy
- 轻松搞定个人虚拟桌面部署之2-安装远程桌面服务
- FFmpeg--一个操作视频音频的强大工具
- 多项式求和(C语言)
- android studio找不到app moudle
- 数学基础从高一开始1、集合的概念
热门文章
- 软路由当文件服务器拒绝了连接,软路由服务器怎么设置方法
- 计算机人用英语怎么说,一大批英语:一万,十万,百万,千万,亿,用英语怎么说哦...
- Python爬取4K图片
- 深度学习入门必学(第三篇:循环神经网络01)
- JS之前台参数提交到后台,双引号转义为quot;解决办法
- 论文笔记《Influence Maximization in Near-Linear Time: A Martingale Approach》
- AVR mega48 ISP下载及熔丝位修正
- Android货币单位获取方法
- Java+Servlet+JSP+Mysql+Tomcat实现Web学生选课管理系统
- 分享113个ASP搜索链接源码,总有一款适合您