Skip to main content
gamedev.net
🔒 Locked

LoadLibrary problem

Started by LordAsm Jan 25, 2008 at 6:48 AM 14 replies 2.5k views
Original Post
LordAsm
LordAsm
hello everybody I'm trying to explicit reference a DLL I've made into my member function, and call one of its function through its name. MY code is:
        bool result;
	HINSTANCE hGetProcIDDLL = LoadLibrary("ServerCall.dll");
	if (hGetProcIDDLL == NULL) {
		FARPROC lpfnGetProcessID = GetProcAddress(HMODULE(hGetProcIDDLL), functionName.c_str());
		typedef bool (__stdcall * pICFUNC)(int);
		pICFUNC MyFunction;
		MyFunction = pICFUNC(lpfnGetProcessID);
		result = MyFunction(argno);
		FreeLibrary(hGetProcIDDLL);
        }

This ServerCall.dll is located right in the same folder as the executable, but LoadLibrary returns me NULL.. What I may be doing wrong? What I can do to make this work.... I tried to pass an absolute path, and nothing.
dmail
dmail
Is this a typo?
if (hGetProcIDDLL == NULL) {...

LordAsm
LordAsm
Yeah, it is an HINSTANCE that LoadLibrary returns. It returns NULL if the DLL is not loaded succesfully.

I've tried already to use SetDllDirectory, without sucess... Both passing the path as a string or using GetModuleFileName() to get the application path, and still the LoadLibrary is NULL.

The DLL I've made is an standard DLL made with VC++ 2005 wizard, with default DllMain (it return true for all paths), and I just added one function to it and added to a definition file and in stdafx too, as the wizard states to do. I've even tried to make a new DLL project with the wizard and call the example function it provides, and no success, so I don't imagine it is an error in my DLL (when debugging, the DLL is indeed called and it returns true, but somewhere in the middle, it returns me 0x10000000 and when compared to NULL to this value, it is true.

The DLL code is:

// ServerCall.cpp : Defines the entry point for the DLL application.//#include "stdafx.h"#include "ServerCall.h"#ifdef _MANAGED#pragma managed(push, off)#endifBOOL APIENTRY DllMain( HMODULE hModule,                       DWORD  ul_reason_for_call,                       LPVOID lpReserved					 ){	switch (ul_reason_for_call)	{	case DLL_PROCESS_ATTACH:	case DLL_THREAD_ATTACH:	case DLL_THREAD_DETACH:	case DLL_PROCESS_DETACH:		break;	}    return TRUE;}#ifdef _MANAGED#pragma managed(pop)#endif// This is an example of an exported variableSERVERCALL_API int nServerCall=0;// This is an example of an exported function.SERVERCALL_API int fnServerCall(void){	return 42;}SERVERCALL_API bool LOGAR(int argno) {	return true;}// This is the constructor of a class that has been exported.// see ServerCall.h for the class definitionCServerCall::CServerCall(){	return;}


and its header is:

// The following ifdef block is the standard way of creating macros which make exporting // from a DLL simpler. All files within this DLL are compiled with the SERVERCALL_EXPORTS// symbol defined on the command line. this symbol should not be defined on any project// that uses this DLL. This way any other project whose source files include this file see // SERVERCALL_API functions as being imported from a DLL, whereas this DLL sees symbols// defined with this macro as being exported.#ifdef SERVERCALL_EXPORTS#define SERVERCALL_API __declspec(dllexport)#else#define SERVERCALL_API __declspec(dllimport)#endif// This class is exported from the ServerCall.dllclass SERVERCALL_API CServerCall {public:	CServerCall(void);	// TODO: add your methods here.};extern SERVERCALL_API int nServerCall;SERVERCALL_API int fnServerCall(void);SERVERCALL_API bool LOGAR(int argno, ...);


The function I try to call is LOGAR.
Evil Steve
Evil Steve
1. Try passing a full path to the DLL, and moving it somewhere "simple", e.g. "C:/ServerCall.dll"

2. What is the return value from GetLastError() immediately after LoadLibrary() fails (And you should plug it into the Error Lookup tool if you have it)? That should tell you if it can't find the file, or if the DLL is invalid.
LordAsm
LordAsm
When I call GetLastError after the LoadLibrary, it returns zero.
When I call LoadLibrary, it returns 0x10000000.

I've tried also to move to C:
When I debug the app, when the DLL is called, the step cursor moves to DllMain, and it returns true, so I suppose it is finding the DLL correctly, as it moves inside the DLL source code (the DLL and the calling code are part of different projects in the same solution in VS). After the DllMain returns TRUE, it goes inside the LoadLibrary function, but at some moment (which I couldn't find yet) something so wrong and i receive the return code 0x10000000.



BloodWarrior
BloodWarrior
Quote:
Original post by LordAsm
When I call GetLastError after the LoadLibrary, it returns zero.
When I call LoadLibrary, it returns 0x10000000.

I've tried also to move to C:
When I debug the app, when the DLL is called, the step cursor moves to DllMain, and it returns true, so I suppose it is finding the DLL correctly, as it moves inside the DLL source code (the DLL and the calling code are part of different projects in the same solution in VS). After the DllMain returns TRUE, it goes inside the LoadLibrary function, but at some moment (which I couldn't find yet) something so wrong and i receive the return code 0x10000000.


if it finds it correctly but fails to launch then maybe that library is statically linked to something that cant be loaded.

Yours Truly
K
Pain is Inevitable, Suffering is Optional.Unknown
Evil Steve
Evil Steve
Quote:
Original post by LordAsm
When I call GetLastError after the LoadLibrary, it returns zero.
When I call LoadLibrary, it returns 0x10000000.
You said that LoadLibrary() returns NULL?

Quote:
Original post by LordAsm
I've tried also to move to C:
When I debug the app, when the DLL is called, the step cursor moves to DllMain, and it returns true, so I suppose it is finding the DLL correctly, as it moves inside the DLL source code (the DLL and the calling code are part of different projects in the same solution in VS). After the DllMain returns TRUE, it goes inside the LoadLibrary function, but at some moment (which I couldn't find yet) something so wrong and i receive the return code 0x10000000.
0x10000000 is the HINSTANCE of the loaded DLL. So it's returning success.

Why are you only calling the rest of the code if LoadLibrary() returns NULL? That doesn't make any sense. You're saying "If I fail to load the DLL, look for a function in the loaded DLL. If I succeed to load the DLL, do nothing and leak the handle".
LordAsm
LordAsm
Mayhap, but what? I just made the DLL from the wizard, I can't imagine why I'm having such problems.... I can only think it should be because my calling app is an win32 console app (but using windows.h), and not a win32 app, but I don't think this should be a problem, so I'm lost...

I'll post the ENTIRE DLL source code here, it has only 1 function more than the DLL wizard template. There is anything that would prevent it from loading correctly? If needed, just PM me and I'll send the entire source code of the calling app too, I'm completely lost here.

ServerCall.h
// The following ifdef block is the standard way of creating macros which make exporting // from a DLL simpler. All files within this DLL are compiled with the SERVERCALL_EXPORTS// symbol defined on the command line. this symbol should not be defined on any project// that uses this DLL. This way any other project whose source files include this file see // SERVERCALL_API functions as being imported from a DLL, whereas this DLL sees symbols// defined with this macro as being exported.#ifdef SERVERCALL_EXPORTS#define SERVERCALL_API __declspec(dllexport)#else#define SERVERCALL_API __declspec(dllimport)#endif// This class is exported from the ServerCall.dllclass SERVERCALL_API CServerCall {public:	CServerCall(void);	// TODO: add your methods here.};extern SERVERCALL_API int nServerCall;SERVERCALL_API int fnServerCall(void);SERVERCALL_API bool LOGAR(int argno);


ServerCall.cpp
// ServerCall.cpp : Defines the entry point for the DLL application.//#include "stdafx.h"#include "ServerCall.h"#ifdef _MANAGED#pragma managed(push, off)#endifBOOL APIENTRY DllMain( HMODULE hModule,                       DWORD  ul_reason_for_call,                       LPVOID lpReserved					 ){	switch (ul_reason_for_call)	{	case DLL_PROCESS_ATTACH:	case DLL_THREAD_ATTACH:	case DLL_THREAD_DETACH:	case DLL_PROCESS_DETACH:		break;	}    return TRUE;}#ifdef _MANAGED#pragma managed(pop)#endif// This is an example of an exported variableSERVERCALL_API int nServerCall=0;// This is an example of an exported function.SERVERCALL_API int fnServerCall(void){	return 42;}SERVERCALL_API bool LOGAR(int argno) {	return true;}// This is the constructor of a class that has been exported.// see ServerCall.h for the class definitionCServerCall::CServerCall(){	return;}


stdafx.h
// stdafx.h : include file for standard system include files,// or project specific include files that are used frequently, but// are changed infrequently//#pragma once#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers// Windows Header Files:#include <windows.h>#include "stdlib.h"#include <iostream>#include <string>#include <vector>#include <list>using namespace std;// TODO: reference additional headers your program requires here


stdafx.cpp
// stdafx.cpp : source file that includes just the standard includes// ServerCall.pch will be the pre-compiled header// stdafx.obj will contain the pre-compiled type information#include "stdafx.h"// TODO: reference any additional headers you need in STDAFX.H// and not in this file


ServerCall.def
EXPORTS  fnServerCall  LOGAR
Evil Steve
Evil Steve
Quote:
Original post by LordAsm
I'll post the ENTIRE DLL source code here, it has only 1 function more than the DLL wizard template. There is anything that would prevent it from loading correctly? If needed, just PM me and I'll send the entire source code of the calling app too, I'm completely lost here.
You keep saying that it's failing to load, but I don't understand how you're getting that conclusion. If LoadLibrary() returns NON-null then it succeeds.
LordAsm
LordAsm
It was really != before, sorry about that, I was messing with some stuff here and posted the code with stupid things :|

Anyway, I still can't get the function pointer correctly... As you see in the code above, there's 2 functions I try to export, LOGAR (which is the one I made) and fnServerCall (which is the one the wizard made as an example). I tried to execute the calling code with these 2 functions and none loads, they return NULL. Above is the full DLL code...

I made the definition file, I specified it with the linker options in Project Properties, what else I need to do to get the pointer to them?
SiCrane
SiCrane
Try running dumpbin /exports on your DLL and make sure that the exported names match the ones you're trying to load.
Evil Steve
Evil Steve
Ahhhh, that makes more sense [smile]

Have you actually told the linker to use the exports file? In VC2005 that's done by going to Project Settings (Alt+F7) -> Configuration Properties -> Linker -> Input -> Module Definition File, and putting the name of your .def file there.

As SiCrane says, check that the function names are being exported correctly (I.e. not name mangled).
LordAsm
LordAsm
Sorry for the delay and the mess, too much for just one head, i need to find another job, I'm getting crazy here lol

The dumpbin gave me that:

Quote:

Microsoft (R) COFF/PE Dumper Version 8.00.50727.762
Copyright (C) Microsoft Corporation. All rights reserved.


Dump of file D:\AppDev\winsock\Server\ServerCall.dll

File Type: DLL

Section contains the following exports for ServerCall.dll

00000000 characteristics
4796506E time date stamp Tue Jan 22 17:22:06 2008
0.00 version
1 ordinal base
5 number of functions
5 number of names

ordinal hint RVA name

1 0 00011096 ??0CServerCall@@QAE@XZ = @ILT+145(??0CServerCall@@QAE@
XZ)
2 1 0001105A ??4CServerCall@@QAEAAV0@ABV0@@Z = @ILT+85(??4CServerCa
ll@@QAEAAV0@ABV0@@Z)
5 2 00019158 ?nServerCall@@3HA = ?nServerCall@@3HA (int nServerCall
)
3 3 00011046 LOGAR = @ILT+65(?LOGAR@@YA_NHZZ)
4 4 00011186 fnServerCall = @ILT+385(?fnServerCall@@YAHXZ)

Summary

1000 .data
1000 .idata
3000 .rdata
1000 .reloc
1000 .rsrc
5000 .text
10000 .textbss


LOGAR and fnServerCall are both there, nicely...
Also, yes, the file ServerCall.def is referenced in the Module Definition File, in the Input panel in the Linker configuration.. The def file contents is above, where I posted the full DLL code.

What ELSE may be tried?

[Edited by - LordAsm on January 25, 2008 11:50:02 AM]
LordAsm
LordAsm
Anyone???
janta
janta
Give it a try with declaring your exported functions extern "C"

(I haven't read all the topic extra-carefully so sorry if this has been said or is irrelevant)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.