GetProcAddress() failing, error 127
Asked Answered
R

5

5

Here's my DLL code:

#include <Windows.h>
#include <iostream>

int sysLol(char *arg);

int sysLol(char *arg)
{
   std::cout<<arg<<"\n";
   return 1;
}

And here's my application code:

#include <Windows.h>
#include <iostream>
#include <TlHelp32.h>
#include <stdlib.h>

typedef int (WINAPI* Lol)(char* argv);
struct PARAMETERS
{
    DWORD Lol;
};

int main()
{
    PARAMETERS testData;
    HMODULE e = LoadLibrary(L"LIB.dll"); //This executes without problem
    if (!e) std::cout<<"LOADLIBRARY: "<<GetLastError()<<"\n";
    else std::cout<<"LOADLIBRARY: "<<e<<"\n";
    testData.Lol = (DWORD)GetProcAddress(e,"sysLol"); //Error 127?
    if (!testData.Lol) std::cout<<testData.Lol<<" "<<GetLastError()<<"\n";
    else std::cout<<"MESSAGEBOX: "<<testData.Lol<<"\n";
    std::cin.ignore();
    return 1;
}

So, my LIB.dll is successfully loaded using LoadLibrary(), yet GetProcAddress() fails with 127. This seems to be because it's not finding my function name, but I don't see why that would fail.

Assistance is greatly appreciated! :) ~P

Rinse answered 16/9, 2014 at 20:5 Comment(0)
C
5

Since that tag is C++, you'll need to declare a C name for the function:

extern "C" int sysLol(char *arg);

You can see the actual name the compiler gave your C++ function with Dependency Walker.

When successful, cast the function to pointer returned by GetProcAddress to the actual function type:

typedef int (*sysLol_t)(char *arg);
sysLol_t pFunc = GetProcAddress(e,"sysLol");
Ciera answered 16/9, 2014 at 20:32 Comment(0)
X
2

That is ERROR_PROC_NOT_FOUND which means that there is no exported function with that name.

There's not much more to say. Perhaps you've got the name wrong. It could be a simple mismatch of letter case. Perhaps the DLL has been built incorrectly and is not exporting the function. Perhaps the DLL is decorating or mangling the names. Certainly from the code in the question, there's no evidence that you attempted to export the function, or indeed suppress decoration/mangling.

Use a tool like dumpbin or Dependency Walker to inspect the names of the functions that are exported. That may shed some light on the problem.

Rather than linking at runtime with LoadLibrary and GetProcAddress, it is much more convenient to link at load time. Use the .lib import library generated when you build the DLL to do that.

It's also worth pointing out that the calling conventions don't match. You have cdecl on the DLL side, and stdcall on the executable side. And don't cast pointers to DWORD. That ends badly when you compile for 64 bit.

Xylia answered 16/9, 2014 at 20:9 Comment(5)
Well, this is intended to be used with process injection, so load-time linking isn't an option for me. The calling conventions don't match because the actual sources are much more complex than the ones I posted, so I had to go through and quickly compress the code into what you see above. It's likely I made a quick typing error. As far as casting to DWORD, right now my process injection is pointed at 32-bit processes, and is being compiled as a 32-bit executable, but I do plan to expand it to 64-bit eventually, so thanks for the tip. :)Rinse
That's fine. I answered from what I could see. I still think I answered your question.Xylia
Put your function in an extern "C" block. Use __declspec(dllexport) and cdecl to have no mangling. If you need different calling convention use a def file to export.Xylia
@TamásSzelei No. That results in ERROR_MOD_NOT_FOUND.Xylia
@tamás perhaps we can tidy up these commentsXylia
C
1

Symbols must be explicitly exported from Windows DLLs. Either declare your function as __declspec(dllexport) or pass a DEF file to the linker to instruct it to export your function. See this description of dllexport.

Counterword answered 16/9, 2014 at 20:48 Comment(1)
It seems to be a start, but apparently my function name is decorated. I'm googling now, but while I'm here, do you know of any way to solve this in a Visual Studio 2012 environment?Rinse
P
1

Please use Dependancy Walker and it will give hint about the method name which is registered inside dll.

http://www.dependencywalker.com/

If method name is - getNumber Dependency Walker will show the actual method name as- _Z9GetNumberd

Ex -

lpGetNumber = (LPGETNUMBER)GetProcAddress(hDLL, "_Z9GetNumberd");

Now LoadLibrary and GetProcAddress() both will work.

Pilarpilaster answered 5/4, 2019 at 12:36 Comment(3)
Please edit your answer to improve the formatting and remove all the caps.Appetizer
Augen , please clarify why this answer is not useful and why you downvoted me ?Pilarpilaster
I had downvoted this because the poor formatting made it very hard to read, and thus close to useless. I see it is fixed now. Though the actual usefulness is still debatable, as the answer is pretty much the same as the accepted one, sans the extern "C" alternative. Anyway, downvote removed for now.Appetizer
C
0

Using DependencyWalker you can view function decorated/undecorated (View->Undecorate C++ functions)

Try to call GetProcAddress with decorated function name form.

Cundiff answered 7/11, 2021 at 13:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.