3

I have to use a simple function from a DLL; I am able to load the library but GetProcAddress returns NULL. I think I understood name mangling but maybe I'm doing something wrong. Thanks (Code follows, asap I'll add other information required):

mydll.h

#ifdef MYDLL_EXPORTS
#define MYDLL_API extern "C" __declspec(dllexport)
#else
#define MYDLL_API extern "C" __declspec(dllimport)
#endif

MYDLL_API void testFunction(void);
MYDLL_API LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam, LPARAM lParam);

mydll.cpp

#include "stdafx.h"
#include "mydll.h"

// This is an example of an exported function.
MYDLL_API void testFunction(void)
{
MessageBox(NULL, (LPCWSTR)L"Test", (LPCWSTR)L"Test", MB_OK);
}

MYDLL_API LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// processes the message
if(nCode >= 0)
{
    if(wParam != NULL && wParam == MK_RBUTTON)
    {
        MessageBox(NULL, (LPCWSTR)L"Captured mouse right button", (LPCWSTR)L"Test", MB_OK);
    }
}

// calls next hook in chain
return CallNextHookEx(NULL, nCode, wParam, lParam);
}

code from main.cpp

...
case WM_CREATE:
    {   
        // creates state for window
        stateClassPointer = new stateClass();
        // saves states pointer in a space reserved for user data
        SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) stateClassPointer);

        // now it will load DLL and set up hook procedure for mouse events

        // declares local variables
        HOOKPROC hkprcMouseProc;
        HINSTANCE hinstDLL; 
        HHOOK hhookMouseProc; 
        //FARPROC WINAPI test;
        // loads DLL
        if((hinstDLL = LoadLibrary(TEXT("C:\\Users\\Francesco\\Dropbox\\poli\\bi\\not\\pds\\sp\\wk5\\lsp5\\Debug\\mydll.dll"))) == NULL)
        {
            MessageBox(hWnd, (LPCWSTR)L"Error loading DLL", (LPCWSTR)L"Error", MB_OK | MB_ICONERROR);
            break;
        }
        // saves DLL handle in the state class
        stateClassPointer->setHInstance(hinstDLL);
        // sets up hook procedure for mouse events
        if((hkprcMouseProc = (HOOKPROC)GetProcAddress(hinstDLL, "mouseProc")) == NULL)
        {
            MessageBox(hWnd, (LPCWSTR)L"Error setting windows hook: GetProcAddress", (LPCWSTR)L"Error", MB_OK | MB_ICONERROR);
            break;
        }
        if((hhookMouseProc = SetWindowsHookEx(WH_MOUSE, hkprcMouseProc, hinstDLL, 0)) == NULL)
        {
            MessageBox(hWnd, (LPCWSTR)L"Error setting windows hook: SetWindowsHookEx", (LPCWSTR)L"Error", MB_OK | MB_ICONERROR);
            break;
        }
        // saves hook handle in the state class
        stateClassPointer->setHHook(hhookMouseProc);
        /*test = GetProcAddress(hinstDLL, "testFunction");
        test();*/
    }
    break;
...
gc5
  • 9,468
  • 24
  • 90
  • 151

1 Answers1

6

Yes, the MessageBox() call succeeded without errors. Move the GetLastError() call before it.

The error is otherwise predictable, it couldn't find "mouseProc". The name will be mangled in the DLL, most probably "_mouseProc@12". Use dumpbin.exe /exports on your DLL to be sure.

Fwiw: you can make this code less painful by not dynamically loading the DLL but just linking its import library. The fact that the DLL will be injected into other processes doesn't also mean you have to inject it in yours. All you need is the module handle so you can call SetWindowsHookEx(). Get that from the DllMain() entry point or by using GetModuleHandle().

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 1
    Yes it is :) Procedure name is exactly "_mouseProc@12". I thought that using `extern "C"` would avoid name mangling on function. Is there a way to do it or I have to use "_mouseProc@12"? – gc5 Aug 13 '11 at 10:53
  • 2
    You can add linker's definitions (.DEF) file to change the name to whatever you like. – hamstergene Aug 13 '11 at 11:04
  • @Francesco - that name is a C mangled name, not a C++ mangled name. C++ mangled names have to cope with overloading, so they describe (in a cryptic way) the types of all parameters. The leading underscore has almost always been added to C function names in object files - I don't know why. I don't know what the `@12` represents - maybe someone else does? Anyway, completely undecorated names are very rare these days in an object or target file - it's just an annoyance we all have to get used to. –  Aug 13 '11 at 11:08
  • 2
    This kind of mangling solves a problem in 32-bit code. Which has many different calling conventions, __cdecl, __stdcall and __fastcall being the more common ones. Getting a mismatch produces *very* hard to diagnose runtime errors. By decorating the function like that, the linker can detect such a mismatch. You used __stdcall, the @xx postfix indicates the size of the activation stack frame. Three arguments, each 4 bytes. Don't fix it, use the technique in the last paragraph of my answer instead. – Hans Passant Aug 13 '11 at 11:24