We help IT Professionals succeed at work.

Dynamic DLL loading problem

Olympus
Olympus asked
on
Whats wrong with this? The pInitialize pointer is never set to the correct function and i get the "plugin not loaded" debug message box...

Client code:


typedef char *(__stdcall *plspInitialize)(void *);
typedef void (__stdcall *plspCleanup)(void);
typedef void (__stdcall *plspParseMsg)(unsigned short, unsigned short, char **, unsigned long *);

     HMODULE Handle;
     
     Handle = LoadLibrary("Plugins\\srv_capture.dll");

     if (Handle != 0) {
          plspInitialize pInitialize = (plspInitialize)GetProcAddress(Handle, "lspInitialize");
          plspCleanup pCleanup = (plspCleanup)GetProcAddress(Handle, "lspCleanup");
          plspParseMsg pParseMsg = (plspParseMsg)GetProcAddress(Handle, "lspParseMsg");
          if (pInitialize && pCleanup && pParseMsg) {
               pInitialize(lspSendMsg);
               MessageBox(0, "plugin loaded", "ya", MB_OK);
          } else
               MessageBox(0, "plugin not loaded", "bah", MB_OK);
     }


Plugin Code:


#include <windows.h>

#define Name "dlltest"

// DLL exports

extern "C" _declspec(dllexport) char *__stdcall lspInitialize(void *pSendMsg);
extern "C" _declspec(dllexport) void __stdcall lspCleanup();
extern "C" _declspec(dllexport) void __stdcall lspParseMsg(unsigned short cmd, unsigned short argc, char **args, unsigned long *argl);
 

char *__stdcall lspInitialize(void *pSendMsg)
{
     MessageBox(0, "hi", "", MB_OK);
     return Name;
}

void __stdcall lspCleanup()
{
}

void __stdcall lspParseMsg(unsigned short cmd, unsigned short argc, char **args, unsigned long *argl)
{
}

BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
     switch (ul_reason_for_call) {
     case DLL_PROCESS_ATTACH:
          break;
     }
     return TRUE;
}
Comment
Watch Question

Commented:
did u try importing it this way:
__declspec(dllimport)char *__stdcall lspInitialize(void *pSendMsg);

Author

Commented:
I need it to be dynamically loaded, not static.. is that what that does?

Author

Commented:
??????????
What about the other pointers pCleanup && pParseMsg, are they ok?

--EC--

Author

Commented:
it doesnt matter.. i just wanna know what im doing wrong thats making the pointer pInitialize NULL.. if i know this i'll be able to fix the other 2 if they're "broke"... im doing this for a plugin api so everything needs to be dynamic.. any suggestions?

Author

Commented:
I've tried making the if statement only if (pInitialize) {

still doesnt work..

Author

Commented:
Alright I've fixed it using a .DEF file.. now a 2nd problem if you guys want points; how do I pass a pointer to a function inside my exe to a dll? It crashes when i do it right now.. I will increase points if people are actually going to answer this time:

Client code:


typedef void (__stdcall *plspSendMsg)(unsigned short, unsigned short, char **, unsigned long *, unsigned short);

typedef char *(__stdcall *plspInitialize)(void *);
typedef void (__stdcall *plspCleanup)(void);
typedef void (__stdcall *plspParseMsg)(unsigned short, unsigned short, char **, unsigned long *, unsigned short);


void __stdcall lspSendMsg(unsigned short cmd, unsigned short argc, char **args, unsigned long *argl, unsigned short ci)
{
     for (unsigned short i = 0; i < ArraySize; i ++) {
          if (Clients[i] != NULL) {
               if (Clients[i]->ClientIndex == ci) {
                    Clients[i]->SendMsg(cmd, argc, args,argl);
                    break;
               }
          }
     }
}

void LoadPlugins()
{
     HMODULE Handle;
     
     Handle = LoadLibrary("Plugins\\srv_capture.dll");

     if (Handle != 0) {
          plspInitialize pInitialize = (plspInitialize)GetProcAddress(Handle, "lspInitialize");
          plspCleanup pCleanup = (plspCleanup)GetProcAddress(Handle, "lspCleanup");
          plspParseMsg pParseMsg = (plspParseMsg)GetProcAddress(Handle, "lspParseMsg");
          if (pInitialize && pCleanup && pParseMsg) {
               Plugins = (LithiumPlugin **)realloc(Plugins, sizeof(LithiumPlugin));
               Plugins[0]->lspInitialize = pInitialize;
               Plugins[0]->lspCleanup = pCleanup;
               Plugins[0]->lspParseMsg = pParseMsg;
               Plugins[0]->Handle = Handle;
               Plugins[0]->FileName = "Plugins\\srv_capture.dll";
               Plugins[0]->Name = pInitialize(lspSendMsg);
          }
     }
}



Plugin Code:

#include <windows.h>
#include "..\Server\Shared.h"

#define Name "dlltest"

typedef void (__stdcall *plspSendMsg)(unsigned short, unsigned short, char **, unsigned long *, unsigned short);

// DLL exports

extern "C" _declspec(dllexport) char *__stdcall lspInitialize(void *pSendMsg);
extern "C" _declspec(dllexport) void __stdcall lspCleanup();
extern "C" _declspec(dllexport) void __stdcall lspParseMsg(unsigned short cmd, unsigned short argc, char **args, unsigned long *argl, unsigned short ci);
 
// EXE imports

plspSendMsg lspSendMsg;

char *__stdcall lspInitialize(void *pSendMsg)
{
     lspSendMsg = (plspSendMsg)pSendMsg;
     return Name;
}

void __stdcall lspCleanup()
{
}

void __stdcall lspParseMsg(unsigned short cmd, unsigned short argc, char **args, unsigned long *argl, unsigned short ci)
{
     switch (cmd) {
          case 0:
               char *Msg = "hi";
               unsigned long MsgLn = 2;
               lspSendMsg(LCC_CONSOLEMSG, 1, &Msg, &MsgLn, ci);
               MessageBox(0, "hi", "hi", MB_OK);
               break;
     }
}

BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
     switch (ul_reason_for_call) {
     case DLL_PROCESS_ATTACH:
          break;
     }
     return TRUE;
}
Basically You do not suppose to have any problem to pass any kind of pointer since the dll and the exe are running in the same memory space. Can you indicate at what line your program crashes and what message do you get?

--EC--

Commented:
To answer your original question, you might want to take a look at the DLL that you are importing.  From the command line, type
    DUMPBIN /EXPORTS Plugins\srv_capture.dll

I expect that your variable names have been mangled by the compiler (it changes the names so the linker can determine not only the function name, but also the type information.)  To get around this, you can either add the specifier:
extern "C" {
    _declspec( dllexport) void myFunction()
    { }
}
to the source of the DLL function (if you have source) which causes the name not to be mangled, or you can fix the parameter that you pass to GetProcAddress so that it looks like the actual function name.

Commented:
Run it under the debugger and tell us which on which line the crash appears

Author

Commented:
I dont know, it doesnt tell me.. i start the program in debug and it just exists with this in the console:

The thread 0x610 has exited with code 0 (0x0).
The thread 0x5E4 has exited with code 0 (0x0).
The program 'D:\Lithium\Server\Debug\LithiumServer.exe' has exited with code 0 (0x0).

Commented:
Maybe it threw an exception that wasn't caught?  Add a top level try/catch block.

Maybe it reached an exit point?

Try single-stepping.

Author

Commented:
The app quits after executing the client line "Plugins[0]->Name = pInitialize(0);"  Any ideas?

Author

Commented:
(Does the same with lspSendMsg as a parameter, used 0 for testing.)

Author

Commented:
Hmm.. weird.. the app does not exit in debug mode, but does in release.  Wtf?

Explore More ContentExplore courses, solutions, and other research materials related to this topic.