1

What is the correct way to use GetProcAddress() on a 32 bit DLL? On win32, there are three calling conventions, cdecl, stdcall and fastcall. If the function in the DLL is foo they will decorate the name in the following ways _foo, _foo@N and @foo@N.

But if the author of the dll has used a .def file, then the exported name will be changed to just "foo" without any decoration.

This spells trouble for me because if I want to load foo from a dll that is using stdcall, should I use the decorated name:

void *h = LoadLibraryEx(L"foo.dll", NULL, 0);
GetProcAddres((HMODULE)h, L"_foo@16");

Or the undecorated one:

void *h = LoadLibraryEx(L"foo.dll", NULL, 0);
GetProcAddres((HMODULE)h, L"foo");

? Should I guess? I've looked at lots of 32 bit DLL files (stdcall and cdecl) and they all seem to export the undecorated name. But can you assume that is always the case?

Björn Lindqvist
  • 19,221
  • 20
  • 87
  • 122

2 Answers2

5

There's really no shortcut or definitive rule here. You have to know the name of the function. The normal scenario is that you know at compile time the name of the function. In which case it does not matter whether the exported name is mangled, decorated, or indeed completely unrelated to the semantic name. Functions can be exported without names, by ordinal. Again, you need to know how the function was exported.

If you are presented with a header file for a library, and want to link to it with explicit linking (LoadLibrary/GetProcAddress) then you will need to find out the names of the function. Use a tool like dumpbin or Dependency Walker to do that.

Now, the other scenario which might lead to you asking the question is that you don't know the name at compile time. For instance, the name is provided by the user of your program in one way or another. Again, it is quite reasonable to require the user to know the exported name of the function.

Finally, you can parse the PE meta data for the executable file to enumerate its exported function. This will give you a list of exported function names, and exported function ordinals. This is what tools like dumpbin and Dependency Walker do.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Then what does everyone else who uses GetProcAddress() to dynamically load libraries do? There are many languages and VM:s that do it fine without knowing beforehand if the names are decorated or not. – Björn Lindqvist Aug 31 '15 at 15:49
  • They do know the names before hand – David Heffernan Sep 01 '15 at 05:43
  • @BjörnLindqvist: can you give us a specific example of what you mean? For example, "if I do *this* in Python *this* happens"? – Harry Johnston Sep 01 '15 at 21:48
  • Not sure I can. Take the languages Julia and Python (using ctypes), you can load and call an arbitrary function using just the dll name, function name and calling convention. I assume that is because you *can* assume that the exported name == the undecorated name (how else can they do it?), so David's answer is correct after all. – Björn Lindqvist Sep 01 '15 at 21:58
  • No. You just know the name by which the function is exported. You don't ever assume. – David Heffernan Sep 01 '15 at 22:35
  • [Why can't I GetProcAddress a function I dllexport'ed?](http://blogs.msdn.com/b/oldnewthing/archive/2004/01/12/57833.aspx) tl;dr; - "C++ decoration varies from compiler vendor to compiler vendor." (And other reasons) – theB Sep 02 '15 at 10:48
  • Well, Python and/or Julia *might* try loading the function using the undecorated name and then, if that fails, try using the decorated name associated with the specified calling convention. It isn't as if a failed GetProcAddress() crashes the process or anything. But I rather suspect that they don't, and the programmer has to use the decorated name if that is the name that is exported. You've perhaps just never happened to need to ctype to a function exported with a decorated name. – Harry Johnston Sep 02 '15 at 21:19
  • @HarryJohnston Python ctypes will only ever pass the name you provide to GetProcAddress. It won't ever attempt to decorate it. I cannot imagine Julia would do so. Doing so would be dangerous and counter intuitive. – David Heffernan Sep 02 '15 at 21:22
  • 1
    @DavidHeffernan: oh, so probably only PHP then? :-) – Harry Johnston Sep 02 '15 at 21:28
0

If __declspec(dllexport) is used during compilation and __declspec(dllimport) in header file, as well as extern "c", then you do not need to decorate those functions. The __declspec helps in using the undecorated names, but function overloads, namespaces, and classes still require same way to distinguish them.

Usually, object oriented functions are exported using function ordinals instead of their decorated names. Cast the ordinal as (char*)(unsigned short)ordinal, thus, GetProcAddress(module, (char*)(unsigned short)ordinal);

Edit: while most of Windows use UTF-16, GetProcAddress uses UTF-8, so it cannot use a wide character string.

GetProcAddress(module, L"foo") is identical to GetProcAddress(module, "f");

Abraham Le
  • 114
  • 3