首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何解决使用FARPROC调用GetProcAddress周围的C4191警告?

使用FARPROC调用GetProcAddress周围的C4191警告可以通过以下方法解决:

  1. 理解警告的含义:C4191警告是指在使用FARPROC类型指针调用GetProcAddress函数时可能会出现的警告。FARPROC是一个通用的函数指针类型,而GetProcAddress是用于获取动态链接库中函数地址的函数。警告的原因是FARPROC类型的指针可能无法正确地表示GetProcAddress返回的函数地址。
  2. 强制类型转换:可以通过将GetProcAddress的返回值强制转换为正确的函数指针类型来解决警告。例如,如果要调用一个返回int类型的函数,可以将GetProcAddress的返回值强制转换为int(*)(void)类型的函数指针。
  3. 使用函数指针类型定义:可以使用函数指针类型定义来避免警告。首先,根据要调用的函数的签名定义一个函数指针类型,然后使用该类型定义一个函数指针变量,并将GetProcAddress的返回值赋给该变量。最后,通过函数指针变量调用函数。
  4. 使用宏定义:可以使用宏定义来简化解决警告的过程。定义一个宏,将GetProcAddress的返回值强制转换为正确的函数指针类型,并使用该宏来调用函数。

总结起来,解决使用FARPROC调用GetProcAddress周围的C4191警告的方法包括强制类型转换、使用函数指针类型定义、使用宏定义等。这些方法可以确保在调用GetProcAddress返回的函数地址时不会出现警告,并保证代码的正确性和稳定性。

腾讯云相关产品和产品介绍链接地址:

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C# —— GetProcAddress函数检索指定的动态链接库(DLL)中的输出库函数地址。

GetProcAddress函数检索指定的动态链接库(DLL)中的输出库函数地址。 函数原型: FARPROC GetProcAddress( HMODULE hModule, // DLL模块句柄 LPCSTR lpProcName // 函数名 ); 参数: hModule [in] 包含此函数的DLL模块的句柄。LoadLibrary或者GetModuleHandle函数可以返回此句柄。 lpProcName [in] 包含函数名的以NULL结尾的字符串,或者指定函数的序数值。如果此参数是一个序数值,它必须在一个字的底字节,高字节必须为0。 返回值: 如果函数调用成功,返回值是DLL中的输出函数地址。 如果函数调用失败,返回值是NULL。得到进一步的错误信息,调用函数GetLastError。 注释: GetProcAddress函数被用来检索在DLL中的输出函数地址。 lpProcName指针指向的函数名,拼写和大小写必须和DLL源代码中的模块定义文件(.DEF)中输出段(EXPORTS)中指定的相同。Win32 API函数的输出名可能不同于你在代码中调用的这些函数名,这个不同被宏隐含在相关的SDK头文件中。如果想得到更多信息,请参考Win32函数原型(Win32 Function Prototypes)。 lpProcName参数能够识别DLL中的函数,通过指定一个与函数相联系的序数值(在.DEF中的EXPORTS段)。GetProcAddress函数验证那个指定的序数值是否在输出的序数1和最高序数值之间(在.DEF中)。函数用这个序数值作为索引从函数表中读函数地址,假如.DEF 文件不连续地定义函数的序数值,如从1到N(N是输出的函数序数值),错误将会发生,GetProcAddress将会返回一个错误的、非空的地址,虽然指定的序数没有对应的函数。 为了防止函数不存在,函数应该通过名字指定而不是序数值。 要求: Windows NT/2000: 要求Windows NT 3.1 或以后版本。 Windows 95/98: 要求Windows 95 或以后版本。 头文件: 在Winbase.h中声明,include Windows.h。 库文件: Use Kernel32.lib。 参看: 动态链接库纵览(Dynamic-Link Libraries Overview), 动态链接库函数(Dynamic-Link Library Functions),FreeLibrary, GetModuleHandle, LoadLibrary 示例代码: 调用KERNEL32.DLL中的RegisterServiceProcess(仅在Windows98中适用) HMODULE hModule=GetModuleHandle("kernel32.dll"); if (hModule) { typedef DWORD (CALLBACK *LPFNREGISTER)(DWORD,DWORD); LPFNREGISTER lpfnRegister; lpfnRegister=(LPFNREGISTER)GetProcAddress(hModule,"RegisterServiceProcess"); if (lpfnRegister) { (*lpfnRegister)(NULL,1L); } }

03

完美实现GetProcAddress

我们知道kernel32.dll里有一个GetProcAddress函数,可以找到模块中的函数地址,函数原型是这样的: WINBASEAPI FARPROC WINAPI GetProcAddress( IN HMODULE hModule, IN LPCSTR lpProcName ); hModule 是模块的句柄,说白了就是内存中dll模块的首地址 loProcName 一般指函数名称的字符串地址,也可能是指序号,如何区分呢? 我们这样 if (((DWORD)lpProcName& 0xFFFF0000) == 0) { //这里是序号导出的; } { //这里是函数名称导出的 } 最终真找到匹配的函数地址,然后返回就ok了,但是前提是你需要了解PE的导出表 下面简单说一下,首先从PE里找到下面这个结构,如果不知道如何找的话,建议在坛子里搜索一下PE结构解析的文章,找到这个结构应该还是很简单的 typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; DWORD AddressOfFunctions; // RVA from base of image DWORD AddressOfNames; // RVA from base of image DWORD AddressOfNameOrdinals; // RVA from base of image } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; 具体什么意思呢? 虽然, kanxue老大在这里写的很漂亮了都 http://www.pediy.com/tutorial/chap8/Chap8-1-7.htm 我还是打算啰嗦一下 Base 函数以序号导出的时候的序号基数,从这个数开始递增 NumberOfFunctions 本dll一共有多少个导出函数,不管是以序号还是以函数名导出 NumberOfFunctions 本dll中以能够以函数名称导出的函数个数(注意,说一下,其实函数里的每一个函数都能通过序号导出,但是为了兼容性等等,也给一些函数提供用函数名称来导出) AddressOfFunctions 指向一个DWORD数组首地址,共有NumberOfFunctions 个元素,每一个元素都是一个函数地址 AddressOfNames 指向一个DWORD数组首地址,共有NumberOfNames个元素,每一个元素都是一个字符串(函数名字符串)首地址 AddressOfNameOrdinals指向一个WORD数组首地址,共有NumberOfNames个元素,每一个元素都是一个函数序号 我们说的最后俩数组,其实是一种一一对应的关系,假如分别叫 dwNames[] 和 dwNamesOrdinals[], 假如dwNames[5]的值(这个指是一个地址,前面都说了)指向的字符串等于“GetValue”,那么dwNamesOrdinals[5]的值(这个指是一个序号,前面都说了),就是GetValue导出函数的序号啦,那么怎样找到地址呢? 这时候就需要用到第一个数组了,假如名字叫dwFuncAddress[], GetValue的导出地址就是 dwFuncAddress[dwNamesOrdinals[5]] + 模块基址 好了,啰嗦了这么多,看代码:

01

完美实现GetProcAddress

我们知道kernel32.dll里有一个GetProcAddress函数,可以找到模块中的函数地址,函数原型是这样的: WINBASEAPI FARPROC WINAPI GetProcAddress( IN HMODULE hModule, IN LPCSTR lpProcName ); hModule 是模块的句柄,说白了就是内存中dll模块的首地址 loProcName 一般指函数名称的字符串地址,也可能是指序号,如何区分呢? 我们这样 if (((DWORD)lpProcName& 0xFFFF0000) == 0) { //这里是序号导出的; } { //这里是函数名称导出的 } 最终真找到匹配的函数地址,然后返回就ok了,但是前提是你需要了解PE的导出表 下面简单说一下,首先从PE里找到下面这个结构,如果不知道如何找的话,建议在坛子里搜索一下PE结构解析的文章,找到这个结构应该还是很简单的 typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; DWORD AddressOfFunctions; // RVA from base of image DWORD AddressOfNames; // RVA from base of image DWORD AddressOfNameOrdinals; // RVA from base of image } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; 具体什么意思呢? 虽然, kanxue老大在这里写的很漂亮了都 http://www.pediy.com/tutorial/chap8/Chap8-1-7.htm 我还是打算啰嗦一下 Base 函数以序号导出的时候的序号基数,从这个数开始递增 NumberOfFunctions 本dll一共有多少个导出函数,不管是以序号还是以函数名导出 NumberOfFunctions 本dll中以能够以函数名称导出的函数个数(注意,说一下,其实函数里的每一个函数都能通过序号导出,但是为了兼容性等等,也给一些函数提供用函数名称来导出) AddressOfFunctions 指向一个DWORD数组首地址,共有NumberOfFunctions 个元素,每一个元素都是一个函数地址 AddressOfNames 指向一个DWORD数组首地址,共有NumberOfNames个元素,每一个元素都是一个字符串(函数名字符串)首地址 AddressOfNameOrdinals指向一个WORD数组首地址,共有NumberOfNames个元素,每一个元素都是一个函数序号 我们说的最后俩数组,其实是一种一一对应的关系,假如分别叫 dwNames[] 和 dwNamesOrdinals[], 假如dwNames[5]的值(这个指是一个地址,前面都说了)指向的字符串等于“GetValue”,那么dwNamesOrdinals[5]的值(这个指是一个序号,前面都说了),就是GetValue导出函数的序号啦,那么怎样找到地址呢? 这时候就需要用到第一个数组了,假如名字叫dwFuncAddress[], GetValue的导出地址就是 dwFuncAddress[dwNamesOrdinals[5]] + 模块基址 好了,啰嗦了这么多,看代码: DWORD MyGetProcAddress( HMODULE hModule, // handle to DLL module LPCSTR lpProcName // function name ) { int i=0; PIMAGE_DOS_HEADER pImageDosHeader = NULL; PIMAGE_NT_HEADERS pImageNtHeader = NULL; PIMAGE_EXPORT_DIRECTORY pImageExportDirectory = NULL; pImageDosHeader=(PIMAGE_DOS_HEADER)hModule; pImageNtHeader=(PIMAGE_NT_HEADERS)((DWORD)hModule+pImageDosHeader->e_lfanew); pImageExportDirectory=(PIMAGE_EXPORT_DIREC

04
领券