当前位置: 首页 > news >正文

[Windows编程] 使用API函数GetProcAddress的注意事项

Windows API 函数 GetProcAddress 被广泛用于取得函数指针地址。 例如:

typedef BOOL (WINAPI *pfnGetProductInfo)(DWORD, DWORD, DWORD, DWORD, PDWORD);

pGPI = (pfnGetProductInfo) GetProcAddress(GetModuleHandleW(L"kernel32.dll"),"GetProductInfo");

注意函数定义typedef 中的WINAPI, 它指定了函数的调用协议, 这部分是非常必要而且关键的,写代码的时候需要注意。

比如你要想取得标准C++运行库(msvcrt.dll) 中的strcpy函数,函数定义就应该是:

typedef char * (__cdecl *pfnStrRChr)(const char *string, int c);


pSRS = (pfnStrRChR)GetProcAddress(hMSVCRT, "strrchr");

函数调用协议指定了函数参数的传递方式以及栈管理方式。如果你这里不指定调用协议,编译器会用默认的调用协议。 结果可能和DLL 函数原先指定协议的不同,函数被调用时会直接导致程序崩溃

比较主流的函数调用方式有 _cdecl , _stdcall, _fastcall, _thiscall

_cdecl 是C语言默认的函数调用协议:所有参数从右到左依次入栈,栈中的参数由调用者清除。

_stdcall 是Pascal 语言的默认的函数调用协议,所有参数从右到左依次入栈,栈中的参数由被调用的函数在返回后清除。 Windows API 全部采用 _stdcall 方式, 上面例子中的WINAPI 其实就是 ___stdcall

#define WINAPI __stdcall
__fastcall 是前两个(x86机器)或者4个(x64机器)参数由寄存器传递,其余参数还是通过堆栈传递。 栈中的参数由被调用的函数在返回后清除。Borland Delphi, C++ Builder 默认使用这种调用方式。

_thiscall 和_stdcall 类似, 只是_thiscall 把类的this指针放在某个特定的寄存器中,比如Visual C++放在ECX中, Borland C++放在EAX中。

经比较,几种调用协议存在挺大差异,所以GetProcAddress 得到的函数需要指定正确的调用协议。

--

相关文章:

  • TPL Part 4 -- Task的协同
  • [Windows编程] SHLWAPI 和 CRT (C Runtime) 字符串处理函数的区别
  • SSH用户等效性配置
  • TPL Part5 -- 循环和PLINQ
  • 再说Ucweb
  • 使用Xamarin + C#开发应用 -- 使用sqlite做本地存储
  • C# + Xamarin 开发应用-- Call API时遇到错误: Error: NameResolutionFailure
  • 使用C# + Xamarin开发应用-- 使用json.net 遇到错误 Object non reference
  • Asp.net MVC中1个小技巧- HTML 扩展方法 AssignIfTrue
  • MD5 Encrypt...
  • 《ASP.NET程序设计教程》目录
  • MongoDb C#Driver 模糊查询
  • C# + Xamarin开发Android应用 --- Tab的实现
  • Nebula3 SDK (Apr 2009)更新内容
  • 在Google Map中显示多个Marker并画出Polygon
  • 分享的文章《人生如棋》
  • canvas 五子棋游戏
  • CentOS 7 修改主机名
  • eclipse的离线汉化
  • Gradle 5.0 正式版发布
  • IDEA 插件开发入门教程
  • JS笔记四:作用域、变量(函数)提升
  • PAT A1017 优先队列
  • Redis中的lru算法实现
  • vue:响应原理
  • Vue实战(四)登录/注册页的实现
  • Vue学习第二天
  • Yii源码解读-服务定位器(Service Locator)
  • 闭包--闭包作用之保存(一)
  • 后端_ThinkPHP5
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 小试R空间处理新库sf
  • 追踪解析 FutureTask 源码
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • ​虚拟化系列介绍(十)
  • ​学习一下,什么是预包装食品?​
  • !$boo在php中什么意思,php前戏
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • .NET Core引入性能分析引导优化
  • .NET Remoting学习笔记(三)信道
  • .NET分布式缓存Memcached从入门到实战
  • .NET连接MongoDB数据库实例教程
  • .net最好用的JSON类Newtonsoft.Json获取多级数据SelectToken
  • /dev下添加设备节点的方法步骤(通过device_create)
  • @ 代码随想录算法训练营第8周(C语言)|Day53(动态规划)
  • @Autowired和@Resource的区别
  • [ 隧道技术 ] cpolar 工具详解之将内网端口映射到公网
  • [20150321]索引空块的问题.txt
  • [AIGC] SQL中的数据添加和操作:数据类型介绍
  • [C#]DataTable常用操作总结【转】
  • [C#]winform部署yolov5-onnx模型
  • [c++] 什么是平凡类型,标准布局类型,POD类型,聚合体