1

If I try to use the LoadLibrary to load User32.dll the function returns error 14007 (ERROR_SXS_KEY_NOT_FOUND). This is the code I use:

SetLastError(0); //To make sure there are no previous errors.
HINSTANCE hUserModule = LoadLibrary(L"User32.dll");
if (hUserModule == NULL) { //Checking if hUserModule is NULL
    MessageBoxA(NULL, "Fatal error", "", 16);
    ExitProcess(0);
} //hUserModule is not NULL
printf("%d\n", GetLastError()); //14007
DWORD paMessageBoxA = (DWORD)GetProcAddress(hUserModule, "MessageBoxA");
__MessageBoxA MsgBox = (__MessageBoxA)paMessageBoxA; //typedef int(__stdcall *__MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
MsgBox(NULL, "", "", 64); //Application crahses

So the hUserModule is not NULL, but also not valid. Why is this?

EDIT: GetModuleHandle also doesn't work

  • Generally you should check the error code (as returned by `GetLastError`) *only* if a function failed. Otherwise you might get false positives. – Some programmer dude Jun 29 '17 at 11:02
  • As for your crash, did you check that `GetProcAddress` didn't fail? – Some programmer dude Jun 29 '17 at 11:02
  • Lastly, and totally unrelated to your problem, but don't have your own symbols starting with double underscore. Those are reserved by the "implementation" (compiler and standard library) in all scopes. [See this old question and its answers](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) for more information. – Some programmer dude Jun 29 '17 at 11:03
  • Nothing is stopping `LoadLibrary` from using other functions (internally) which may call `SetLastError`. When value from `GetLastError` is valid is described in the documentation. – Richard Critten Jun 29 '17 at 11:04
  • I did and it returned error code 0 –  Jun 29 '17 at 11:04
  • By the way (and this is *very* related to your problem), are you on a 64-bit system? `DWORD` is defined as `long` which using the Visual C++ compiler is 32 bits. On a 64 bit system addresses (like the ones returned by [`GetProcAddress`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85).aspx)) are 64 bits, and storing it in a 32 bit variable can truncate the address. – Some programmer dude Jun 29 '17 at 11:06
  • Yes I am using a 64 bit system and its being compiled in a 64 bit application –  Jun 29 '17 at 11:08
  • You are truncating the result from `GetProcAddress`. `FARPROC` is bigger than `DWORD` on 64 bit systems see the definition of `GetProcAddress`: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85).aspx – Richard Critten Jun 29 '17 at 11:09
  • Farproc worked. I didn't know that FARPROC is required when using function addresses on 64 bit machines / applications –  Jun 29 '17 at 11:15
  • Why are you doing this? Instead of linking to the dynamic library? – user207421 Jun 29 '17 at 11:26

1 Answers1

1

On a 64-bit system addresses are 64 bits wide. The DWORD type is "A 32-bit unsigned integer" (quoted from this MSDN type reference).

That means you truncate the address you receive from GetProcAddress making it invalid.

The solution is to use a proper pointer type, casting to that type instead of to DWORD. Perhaps something like

__MessageBoxA MsgBox = (__MessageBoxA) GetProcAddress(hUserModule, "MessageBoxA");

(Assuming __MessageBoxA is a proper pointer.)

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621