函数C / C ++中的LoadLibrary和GetProcAddress

时间:2014-08-05 23:26:46

标签: c++ c function

我有这段代码:

int main(int argc, char *argv[])
{
    typedef HHOOK(__stdcall *f_funci)(int, HOOKPROC, HINSTANCE, DWORD);
    HINSTANCE hGetProcIDDLL = LoadLibrary(L"User32.dll");

    if (!hGetProcIDDLL) {
        printf("could not load the dynamic library");
        printf("%d", GetLastError());
        return EXIT_FAILURE;
    }

    // resolve function address here
    f_funci SetWindowsHookEx2 = (f_funci)GetProcAddress(hGetProcIDDLL, "SetWindowsHookExW");
    if (!SetWindowsHookEx2) {
        printf("could not locate the function SetWindowsHookExW");
        printf("%d", GetLastError());
        return EXIT_FAILURE;
    }

    hMouseHook = SetWindowsHookEx2(WH_MOUSE_LL, my_function, hInstance, NULL);

    return 0;
}

如何在函数中插入所有这些代码,只需从main调用它来获取SetWindoesHookEx2并稍后再使用它?

这里的问题是返回的值是typedef HHOOK(__stdcall *f_funci)(int, HOOKPROC, HINSTANCE, DWORD),它是HHOOK结构,我不知道如何处理。

在简历中我想要一些像:

int main(void) {
    SetWindowsHook2 = dynamyc_function("User32.dll", "SetWindowsHookExW", int, HOOKPROC, HINSTANCE, DWORD)
    hMouseHook = SetWindowsHookEx2(WH_MOUSE_LL, my_function, hInstance, NULL);
    return 0;
}

我不能这样做:

HHOOK load_hook(){
    typedef HHOOK(__stdcall *f_funci)(int, HOOKPROC, HINSTANCE, DWORD);
    HINSTANCE hGetProcIDDLL = LoadLibrary(L"User32.dll");

    if (!hGetProcIDDLL) {
        printf("could not load the dynamic library");
        printf("%d", GetLastError());
        return EXIT_FAILURE;
    }

    // resolve function address here
    f_funci SetWindowsHookEx2 = (f_funci)GetProcAddress(hGetProcIDDLL, "SetWindowsHookExW");
    if (!SetWindowsHookEx2) {
        printf("could not locate the function SetWindowsHookExW");
        printf("%d", GetLastError());
        return EXIT_FAILURE;

    }
    return SetWindowsHookEx2;
}

有两个错误:'return' : cannot convert from 'int' to 'HHOOK''return' : cannot convert from 'f_funci' to 'HHOOK'第一个引用return EXIT_FAILURE;,第二个引用'返回SetWindowsHookEx2;'

谢谢。

2 个答案:

答案 0 :(得分:2)

尝试这样的事情:

#include <map>
#include <string>

std::map<std::wstring, HINSTANCE> libs;

template<typename T>
bool dynamyc_function(LPCWSTR libname, LPCSTR funcname, T *func)
{
    HINSTANCE hlib = libs[libname];
    if (!hlib)
    {
        hlib = LoadLibraryW(libname);
        if (!hlib)
        {
            wprintf(L"could not load the dynamic library %s! %d", libname, GetLastError());
            return false;
        }
        libs[libname] = hlib;
    }

    *func = (T) GetProcAddress(hlib, funcname);
    if (!*func)
    {
        printf("could not locate the function %s! %d", name, GetLastError());
        return false;
    }

    return true;
}

int main(int argc, char *argv[])
{
    typedef HHOOK(__stdcall *f_funci)(int, HOOKPROC, HINSTANCE, DWORD);

    // resolve function address here
    f_funci SetWindowsHookEx2;
    if (!dynamyc_function(L"User32.dll", "SetWindowsHookExW", &SetWindowsHookEx2))
        return EXIT_FAILURE;

    HHOOK hMouseHook = SetWindowsHookEx2(WH_MOUSE_LL, my_function, hInstance, NULL);
    if (!hMouseHook)
    {
        printf("could not set hook! %d", GetLastError());
        return EXIT_FAILURE;
    }
    ...
    UnhookWindowsHookEx(hMouseHook);

    return 0;
}

或者,如果您只对特定功能感兴趣,可以尝试这样的事情:

typedef HHOOK(__stdcall *f_funci)(int, HOOKPROC, HINSTANCE, DWORD);

HHOOK __stdcall Impl_SetWindowsHookExW(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId);
HHOOK __stdcall Stub_SetWindowsHookExW(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId);
f_funci lpSetWindowsHookExW = &Stub_SetWindowsHookExW;

HHOOK __stdcall Impl_SetWindowsHookExW(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD 
{
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return NULL;
}

HINSTANCE hUser32 = NULL;
HHOOK __stdcall Stub_SetWindowsHookExW(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId)
{
    if (!hUser32)
    {
        hUser32 = LoadLibraryW("User32.dll");
        if (!hUser32)
        {
            DWORD err = GetLastError();
            printf("could not load the dynamic library! %d", err);
            SetLastError(err);
            return NULL;
        }
    }

    f_funci func = (f_funci) GetProcAddress(hUser32, "SetWindowsHookExW");
    if (!func)
    {
        DWORD err = GetLastError();
        printf("could not locate the function! %d", err);
        SetLastError(err);
        func = &Impl_SetWindowsHookExW;
    }

    lpSetWindowsHookExW = func;
    return func(idHook, lpfn, hMod, dwThreadId);
}

int main(int argc, char *argv[])
{
    HHOOK hMouseHook = lpSetWindowsHookExW(WH_MOUSE_LL, my_function, hInstance, NULL);
    if (!hMouseHook)
    {
        printf("could not set hook! %d", GetLastError());
        return EXIT_FAILURE;
    }
    ...
    UnhookWindowsHookEx(hMouseHook);

    return 0;
}

答案 1 :(得分:1)

您不能在C或C ++中将类型作为运行时参数传递。

在C ++中,您可以使用支持类型参数的模板。类似的东西:

auto SetWindowsHook2 = dynamic_function<HHOOK(__stdcall *)(int, HOOKPROC, HINSTANCE, DWORD)>(L"User32.dll", "SetWindowsHookExW");

其中函数定义为:

template<typename FuncPtr>
FuncPtr dynamic_function(const wchar_t* dllname, const char* fn)
{
    HINSTANCE hDLL = LoadLibraryW(dllname);

    if (!hDLL) {
        printf("could not load the dynamic library");
        printf("%d", GetLastError());
        return nullptr;
    }

    // resolve function address here
    auto pf = (FuncPtr)GetProcAddress(hDLL, fn);
    if (!pf) {
        printf("could not locate the function %s", fn);
        printf("%d", GetLastError());
        return nullptr;
    }

    return pf;
}

请注意,这个泄漏库引用计数,所以它确实不是一个好的解决方案。更好的方法是为DLL提供一个RAII类,在其析构函数中释放引用(使用FreeLibrary)。 dynamic_function可以是DLL-referent对象的成员函数。然后,只要您需要从中获得的函数指针,您就有责任保持该对象的存活。