problem in GetProcAddress

HI All,
I am creating a dll for resource management.
For this I created a resource.dll
the entries i made in this dll file is

in . def

LIBRARY Resource

EXPORTS
LoadStringFromDLL @ 1

in .cpp

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}

TCHAR * _stdcall LoadStringFromDLL(HINSTANCE hInst, int ids)
{

if (!hInst) {
//ASSERT(0);
return NULL;
}
TCHAR *str;
TCHAR szTemp[1028]; // Raise limit of 1028 char if needed.
memset(szTemp,0,1028);
int nLen;
LPCTSTR lpszName = MAKEINTRESOURCE(ids);
if (::FindResource(hInst, lpszName, RT_STRING) != NULL &&
(nLen = ::LoadString(hInst, ids, szTemp, 1028) != 0)) {
str = szTemp;
}
return str;
}

from Main application I am calling as

if((g_LibHandle=LoadLibrary(L"Resource.dll"))==NULL)
{
int x=GetLastError();
MessageBox(NULL,L"LoadLIbrary failed",L"Test",MB_OK);
}
//LoadDllString=//(*importStrFunction)GetProcAddress(g_LibHandle, L"LoadStringFromDLL");
SetLastError(0);
LoadDllString=(importStrFunction)GetProcAddress(g_LibHandle, L"LoadStringFromDLL");
if (LoadDllString == NULL)
{
int x=GetLastError();
MessageBox(NULL,L"ERROR: unable to find DLL function\n",L"Test",MB_OK); FreeLibrary(g_LibHandle);
return 1;
}

In the GetLastError() of GetProcAddress() I am getting error 87 means the parameter is incorrect.

Can any one help me. I am new to dll and almost unable to find what is the error.
Thanks in advance.
Ravi Ranjan
[1815 byte] By [RaviRanjan1774] at [2007-11-20 11:56:30]
# 1 Re: problem in GetProcAddress
//LoadDllString=//(*importStrFunction)GetProcAddress(g_LibHandle, L"LoadStringFromDLL");
SetLastError(0);
LoadDllString=(importStrFunction)GetProcAddress(g_LibHandle, L"LoadStringFromDLL");
...
In the GetLastError() of GetProcAddress() I am getting error 87 means the parameter is incorrect.
Yes it is! The (second) parameter you are passing into the GetProcAddress is incorrect!
You must always read the MSDN documentation about any API you are trying to use. The second parameter must be of the type LPCSTR , not LPCWSTR !GetProcAddress
The GetProcAddress function retrieves the address of the specified exported dynamic-link library (DLL) function.

FARPROC GetProcAddress(
HMODULE hModule, // handle to DLL module
LPCSTR lpProcName // function name
);
The correct code should look like:LoadDllString=(importStrFunction)GetProcAddress(g_LibHandle, "LoadStringFromDLL");
VictorN at 2007-11-11 4:02:05 >
# 2 Re: problem in GetProcAddress
I believe the GetProcAddress api only takes an ANSI string.

While msdn indicates it takes an LPCSTR, doing a dumpbin /export of kernel32.dll shows only one export:

413 19C 0001152A GetPrivateProfileStringA
414 19D 0000FE8E GetPrivateProfileStringW
415 19E 0005DE0F GetPrivateProfileStructA
416 19F 000373D8 GetPrivateProfileStructW
417 1A0 00023D7A GetProcAddress
418 1A1 0001FBAD GetProcessAffinityMask
419 1A2 00063E69 GetProcessHandleCount

If it supported ANSI and UNICODE, it would look like the GetPrivateProfileString exports (with A and W appended).
Arjay at 2007-11-11 4:03:05 >
# 3 Re: problem in GetProcAddress
Thanks VictorN for your reply,
I am using it in VS2005 for PocketPc and its documentation says the signature as
FARPROC GetProcAddress(
HMODULE hModule,
LPCWSTR lpProcName
);

If I try to use LoadDllString=(importStrFunction)GetProcAddress(g_LibHandle, "LoadStringFromDLL"); then it generates a compile time error
"cannot convert parameter 2 from 'const char [18]' to 'LPCWSTR'"

I mean according to documentation I am not doing wrong.

BUt still I am not able to solve it.

Regards:
Ravi Ranjan
RaviRanjan1774 at 2007-11-11 4:04:15 >
# 4 Re: problem in GetProcAddress
Looking at this further, the problem is the signature of the dll function. You can't return the address of a temporary variable from a function. You need to pass in the buffer of the string and size to the function.

Prototype
DWORD _stdcall LoadStringFromDLL(HINSTANCE hInst, int ids, LPTSTR lpBuffer, DWORD nSize );
Arjay at 2007-11-11 4:05:14 >
# 5 Re: problem in GetProcAddress
GetProcAddress wouldn't care what the signature is. It could lead to runtime error on using the function, but GetProcAddress should've worked nevertheless.

RaviRanjan1774, your code seems to be ok. Only thing is , is that the exact code you have ?
I mean, is it possible your g_hLibHandle is invalid. In the code you posted, you are not breaking out if the LoadLibrary fails and you still continue to call GetProcAddress.

Also, please use code tags to post code
kirants at 2007-11-11 4:06:13 >
# 6 Re: problem in GetProcAddress
HI,
I have posted the exact code what I am using. I have also made a check for failure of LoadLibrary

if((g_LibHandle=LoadLibrary(L"Resource.dll"))==NULL)
{
int x=GetLastError();
MessageBox(NULL,L"LoadLIbrary failed",L"Test",MB_OK);
}

this section is not executing. Initilally I was getting this message when some problem was with dll. But now I am not able to solve it I tried with changed signature also but after that also it is giving error 87 in GetLastError.
I donnot kanow how to proceed further.Please help.
Regards:
Ravi Ranjan
RaviRanjan1774 at 2007-11-11 4:07:15 >
# 7 Re: problem in GetProcAddress
HI ,
I am attaching the zip file for both the resourc dll and the application from where I am trying to acccess the dll.
please check where I am doing wrong.
THanks.
Ravi Ranjan
RaviRanjan1774 at 2007-11-11 4:08:09 >
# 8 Re: problem in GetProcAddress
There is no def file in the resource1 project. So, nothing is gonna be exported from it
kirants at 2007-11-11 4:09:12 >
# 9 Re: problem in GetProcAddress
HI,
Thanks for ur reply.
I am sorry, it was there but stored in different location. I have also tried with __declspec(dllexport)

but still it is giving error 87.
I am attaching the new resource1 dll zip file

Regards:
Ravi Ranjan
RaviRanjan1774 at 2007-11-11 4:10:20 >
# 10 Re: problem in GetProcAddress
Attach the DLL you created. Did you check the DLL to see what the exported names are? You're expecting the DLL to have that name, but nowhere did you ever check to see if that exported name really exists. Did you use Dependency Walker (depends.exe) or dumpbin to see what the actual names are that are exported?

The very first thing to do if GetProcAddress returns NULL is to look into the DLL that was created, and not to write or change code -- GetProcAddress() doesn't make mistakes. Once you see what the exported names are (or if they're even there), then you write or change code to handle the problem, and not before.

There is nothing wrong with GetProcAddress() -- the problem is that you don't know what wound up in the DLL as the exported name, so please attach the DLL that you created.

Regards,

Paul McKenzie
Paul McKenzie at 2007-11-11 4:11:21 >
# 11 Re: problem in GetProcAddress
HI,
Thanks for ur reply.
I am sorry, it was there but stored in different location. I have also tried with __declspec(dllexport)

but still it is giving error 87.
I am attaching the new resource1 dll zip file

Regards:
Ravi RanjanThe problem is that the functions are getting decorated when exported.

If I do a dumpbin /exports resource1.dll, I get the following output.

1 0 00001050 ?LoadStringFromDLL@@YAXPAUHINSTANCE__@@HQA_W@Z = ?LoadStringFromDLL@@YAXPAUHINSTANCE__@@HQA_W@
Z (void __cdecl LoadStringFromDLL(struct HINSTANCE__ *,int,wchar_t * const))
2 1 00001024 ?addTwoNumber@@YAHHH@Z = ?addTwoNumber@@YAHHH@Z (int __cdecl addTwoNumber(int,int))

If these are exported without mangling, I would expect something like:

1 0 00001050 LoadStringFromDLL
2 1 00001024 addTwoNumber

As it stands, this will load up if you include the mangling (although I wouldn't recommend loading it up this way):

LoadDllString=(importStrFunction)GetProcAddress(g_LibHandle, L"?addTwoNumber@@YAHHH@Z");

So you'll need to review how you are exporting the functions from the dll. Be sure to deploy the new dll to the emulator after fixing the exports (otherwise the wrong dll will get loaded).
Arjay at 2007-11-11 4:12:13 >
# 12 Re: problem in GetProcAddress
Hi,
Mr. Arjay is rigt I have checked the dll with depends.exe and it is showing the same entries as mentioned by Mr. Ajay.

If it is showing this type of output in depends.exe then what I should do.Please guide me.
What ever code I am using is I have allready attached as .zip file.(Usingdll, and Resource1[2])
I am unable to find where I am doing wrong.
Here I am not able to attach the dll as it is of size almost 41KB and tis size is not acceptable trough this site.
Regards:
Ravi Ranjan
RaviRanjan1774 at 2007-11-11 4:13:23 >
# 13 Re: problem in GetProcAddress
...
I am unable to find where I am doing wrong.
As I already wrote all such calls are wrong: LoadDllString=(importStrFunction)GetProcAddress(g_LibHandle, L"LoadStringFromDLL");Remove this L
It should be LPCSTR type, not LPCWSTR: LoadDllString=(importStrFunction)GetProcAddress(g_LibHandle, "LoadStringFromDLL");
...
LoadSumFn=(importAddFunction)GetProcAddress(g_LibHandle, "addTwoNumber");
VictorN at 2007-11-11 4:14:19 >
# 14 Re: problem in GetProcAddress
Hi,
Mr. Arjay is rigt I have checked the dll with depends.exe and it is showing the same entries as mentioned by Mr. Ajay.Do you know why the names are mangled?

The reason is that for C++ functions, the compiler adds decoration to the name when compiled, since C++ allows functions to be overloaded (same name, different arguments).

Here is a brief explanation:

Since the linker knows nothing about the C++ language, the C++ compiler has to "fool" the linker into believing that for example, "foo(int x)" and "foo(double x)" are two different functions. So the way it does this is to change the name of foo to "foo@whatever1", and "foo@whatever2" (I put the "whatever" there, just for illustrative purposes). Now the linker can do its job correctly, since the linker sees two seperate entries for the "foo" function.

So what ends up in the DLL exports? "foo@whatever1" and "foo@whatever2". So how do you prevent the C++ compiler from mangling the names? You use the "extern "C" modifier:

#ifdef __cplusplus
extern "C" {
#endif
int foo(int x);
double func();
// maybe more functions
#ifdef __cplusplus
}
#endif

So you have to tell the compiler that between the extern "C" and the ending }, the functions declared are not to be mangled. Once you do this, this means that you cannot overload non-mangled names. In other words, those prototypes are now "C" function declarations.

Since they are now "C" function declarations, the names that will show up in the DLL are "foo" and "func" (given that you have a .DEF file also, which you do have), instead of "foo@whatever".

This is all covered in this dev-archive FAQ on building DLL's:

http://www.dev-archive.com/forum/showthread.php?t=231254

Regards,

Paul McKenzie
Paul McKenzie at 2007-11-11 4:15:16 >
# 15 Re: problem in GetProcAddress
As I already wrote all such calls are wrong:Remove this L

Actually, as RaviRanjan1774 has mentioned, the WinCE SDK needs a LPCWSTR for GetProcAddress. So, that part of the code is correct.
kirants at 2007-11-11 4:16:25 >
# 16 Re: problem in GetProcAddress
Actually, as RaviRanjan1774 has mentioned, the WinCE SDK needs a LPCWSTR for GetProcAddress. So, that part of the code is correct.Ahh! :wave:
I mislooked this post! (Unfortunately, RaviRanjan1774 didn't mentioned it in his OP..., and I missed his reply about " VS2005 for PocketPc ")
I am awfully sorry! :blush:
VictorN at 2007-11-11 4:17:18 >
# 17 Re: problem in GetProcAddress
I am unable to find where I am doing wrong.

The root cause was that , though you were including the .def file in the project, the linker wasn't instructed to use it. Hence it was being completely ignored leading to no exports. Remove the declspec(dllexport) and things like that, revert to your initial setup, add the .def file to project and make sure you do this:

Go to project properties, linker, Input .
Here in, specify resource1.def in the Module Definition file item. Do a clean build. All should be well.
kirants at 2007-11-11 4:18:26 >
# 18 Re: problem in GetProcAddress
The root cause was that , though you were including the .def file in the project, the linker wasn't instructed to use it. Hence it was being completely ignored leading to no exports. Remove the declspec(dllexport) and things like that, revert to your initial setup, add the .def file to project and make sure you do this:

Go to project properties, linker, Input .
Here in, specify resource1.def in the Module Definition file item. Do a clean build. All should be well.Also be sure to deploy the resource1.dll to the emulator. Otherwise it will use the old dll with the mangling and drive you crazy.
Arjay at 2007-11-11 4:19:25 >