无法使用GetProcAddress()从DLL加载某些函数

时间:2011-08-14 11:15:29

标签: c++ dll

我正在尝试构建一个DLL,后来我想使用SetWindowsHookEx()函数注入一些进程。奇怪的是,当我尝试加载DLL并尝试使用GetProcAddress来获取其中包含的过程的地址时,如果我尝试获取CBT消息处理过程的地址,它将返回NULL,但它可以正常工作其他功能。

这是代码。

DLL HEADER(.h)

#include <windows.h>

extern "C" {
    __declspec(dllexport) LRESULT CALLBACK hookProc(int code, WPARAM wParam, LPARAM lParam);
    __declspec(dllexport) int add(int a, int b);
}

DLL文件(.cpp)

#include "SimpleHook.h"

extern "C" {
    __declspec(dllexport) LRESULT CALLBACK hookProc(int code, WPARAM wParam, LPARAM lParam) {
        return CallNextHookEx(0, code, wParam, lParam);
    }

    __declspec(dllexport) int add(int a, int b) {
        return a + b;
    }
}

主要文件

#include <iostream>
#include <windows.h>
#include <tchar.h>

int main(int argc, char* argv[]) {
    HINSTANCE dllHandle = LoadLibrary(_T("SimpleHook.dll"));

    if (dllHandle) {
        // returns the correct address
        cout << "add address: " << GetProcAddress(dllHandle, "add") << endl;

        // returns NULL
        cout << "hookProc address: " << GetProcAddress(dllHandle, "hookProc") << endl;
    }
}

如果我使用GetLastError(),我会得到127错误代码,意思是:

  

ERROR_PROC_NOT_FOUND:找不到指定的过程。

奇怪的是,正确加载了同一文件中的其他函数。 非常感谢任何帮助!

3 个答案:

答案 0 :(得分:5)

调用约定更改名称mangling。 __stdcall函数的名称总是由_加上前缀,并且在某些其他方面也会受到损坏,因此链接失败,但__cdecl函数没有被破坏,因此它被找到了。

要从使用__declspec(dllexport)构建的DLL导入,您应该始终在要导入的所有内容上包含带__declspec(dllimport)的标头,并链接您从中获​​取的lib构建DLL。这将保证您的所有功能正确链接,并且您不必进行C兼容链接。

您不应该使用GetProcAddressextern "C"__declspec(dllexport)一起使用。

部首:

#include <windows.h>

#ifndef MAIN
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

DLL_API LRESULT CALLBACK hookProc(int code, WPARAM wParam, LPARAM lParam);
DLL_API int add(int a, int b);

DLL .cpp文件:

#include "SimpleHook.h"

DLL_API LRESULT CALLBACK hookProc(int code, WPARAM wParam, LPARAM lParam) {
    return CallNextHookEx(0, code, wParam, lParam);
}

DLL_API int add(int a, int b) {
    return a + b;
}

主.cpp文件:

#define MAIN
#include "SimpleHook.h"

int main(int argc, char* argv[]) {

    if (dllHandle) {
        // returns the correct address
        cout << "add address: " << add << endl;

        // returns NULL
        cout << "hookProc address: " << hookProc << endl;
    }
}

不要忘记将lib添加到链接器。

答案 1 :(得分:3)

CALLBACK宏解析为__stdcall。因此,您必须添加下划线字符并将参数的大小附加到函数的名称:

cout << "hookProc address: " << GetProcAddress(dllHandle, "_hookProc@12")
     << endl;

答案 2 :(得分:1)

您必须使用dumpbin或Dependency Walker等工具来学习错位名称。

或者您可以在链接时使用DEF文件,将您选择的名称放在导出表中。