3

I'm having the following issue:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>


int main() {

HANDLE handle;
DWORD dw;

handle = LoadLibrary("C:\\Folder\\mydll.dll");

dw = GetLastError();

printf("Loading Library: %d", dw);

FreeLibrary(handle);

return 0;
}

When compiling this with Netbeans/MinGW, everything works fine, the DLL is loaded and the output is "Loading Library: 0".

But when compiling the exact same code on the exact same machine with Visual C++ 2008 Express, I get the infamous 126 error: "Loading Library: 126".

The DLL is obviously existent at the specified location and loading it works as well - when I'm using Netbeans with MinGW. But why doesn't it work when using Visual C++?

This is only sample code to outline my problem. It's part of a much larger project which works completely fine when compiled with Netbeans/MinGW, but which doesn't load the DLLs when compiled with Visual C++...

Thanks for all answers!

bluish
  • 26,356
  • 27
  • 122
  • 180
clancy688
  • 71
  • 1
  • 2
  • 6
  • `mydll.dll` might be dependent on other dlls which are found when you are loading with VC++. Try tool like _dependency walker_ and confirm all dependent dlls are present in `%PATH%`. – Rohan May 02 '14 at 11:47
  • I've tried this already and Dependency Walker did indeed show me several DLLs missing: API-MS-WIN-APPMODEL-RUNTIME-L1-1-0.DLL API-MS-WIN-CORE-WINRT-ERROR-L1-1-0.DLL API-MS-WIN-CORE-WINRT-L1-1-0.DLL API-MS-WIN-CORE-WINRT-ROBUFFER-L1-1-0.DLL API-MS-WIN-CORE-WINRT-STRING-L1-1-0.DLL API-MS-WIN-SHCORE-SCALING-L1-1-1.DLL DCOMP.DLL IESHIMS.DLL But why does it work with Netbeans then? Moreover, I found this post where people said that Dependency Walker was misleading: http://stackoverflow.com/questions/17023419/win-7-64-bit-dll-problems – clancy688 May 02 '14 at 11:52
  • Those might be available in Netbeans etc. BTW, your dll name is `"...\mydll.dll"`, while it should be "...\\mydll.dll", you are missing `'\'`. – Rohan May 02 '14 at 11:56
  • Okay... just checked both .exe, the VSC++ file is 30 kb while the Netbeans file is 41 kb... so there's some linking going on I guess. As for the pathname, that's a typo. I changed it when posting the snippet here. In the original, it's \\mydll.dll. – clancy688 May 02 '14 at 12:01
  • I've tried adding all the missing DLLs to the folder (and the DLLs which are included by the missing DLLs...) but it's still not working... I did a quick search on my computer and the DLLs in question hadn't been present before I downloaded them. I still don't understand therefore why it works with Netbeans but not with VSC++...? – clancy688 May 02 '14 at 12:42
  • 1
    Note that the OS doesn't search for dependent DLLs in the folder where the DLL is, but in the folder where EXE is (among others). [This document](http://msdn.microsoft.com/en-us/library/windows/desktop/ms682586.aspx) describes the search process in great detail, but in any case, `C:\Folder` generally will **not** be searched. My guess is, one EXE works and the other doesn't simply because you are running them differently - from different directories and/or with different current working directories. The stars just happen to align in one case, and fail to align in the other. – Igor Tandetnik May 02 '14 at 17:15
  • I put both .exe in the same folder and ran them manually. The netbeans exe worked, the VC++ didn't... – clancy688 May 06 '14 at 08:11

2 Answers2

1

Because your answer is incomplete and misses the real problem, I'll elaborate here.

You are compiling the MSVS version with UNICODE defined, which makes stuff like LoadLibrary be defined as a macro to LoadLibraryW, which takes a const wchar_t* argument. In contrast, when compiling with GCC, you don't define that, and it works.

The reason the UNICODE version actually compiles is somewhat a bug/feature in MSVS that allows you to pass a char* to a wchar_t* without any message (you did turn on warnings, didn't you?). This results in some misinterpreted string being passed to the Win32 API function, which fails to locate the garbled filename.

This is why I always call the *W versions of functions directly, and don't bother with all the funny UNICODE stuff.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
  • 1
    Yeah, thanks. I changed the project's properties to "Multibyte Character Set" and now even the original code works in Visual C++. Is there anything wrong with doing this? Because the fault happens not in my code, but in libraries by a third party which I have to use for my project. It's the first time I'm working with the Microsoft IDE... so what really happened was that because of the macro my LoadLibrary call in MSVS actually called another function than the LoadLibrary call with GCC? – clancy688 May 07 '14 at 10:01
  • `LoadLibrary` (and a bunch of other functions in the Win32 API in a similar way) maps to `LoadLibraryA` or `LoadLibraryW` if `UNICODE` is undefined or defined. Why the mismatched call didn't result in a compile error, I don't know, but I strongly suggest our code is independent of what the build system (i.e. your project's properties in the VS IDE) decides to do. Or at least be consistent everywhere, which is surprisingly difficult to do portably. – rubenvb May 07 '14 at 11:18
  • @clancy688 I had the same problem and setting the project to build with "Multibyte Character Set" also fixed my problem. Thanks! – frogpelt Jan 29 '16 at 17:26
-1

I've found the solution by now. FreeLibrary("mystringpath.dll") apparently doesn't work. But when I call the function with LPCWSTR, it works. So:

handle = LoadLibrary("C:\\Folder\\mydll.dll");

Produces ERROR_MOD_NOT_FOUND when compiled with Visual C++, but works when compiled with MinGW.

But the following works when compiled with Visual C++:

LPCWSTR path = L"C:\\Folder\\mydll.dll";

handle = LoadLibrary(path);

And returns ERROR_SUCCESS (0).

So all the allegedly missing dlls pointed out by dependency walker really weren't the problem.

The funny thing, though, is that using the fix in Netbeans/MinGW results in the Netbeans .exe returning 126. And when compiling, gcc complains about passing an argument from an imcompatible pointer type.

So the first code works only for MinGW, the second only for Visual C++...

Upon further research, I've realized that this fix is unnecessary. Apparently, the problem was that my Visual C++ project used the Unicode character set by default. After I changed it into the Multibyte Character Set in the project properties, the code pasted in the original question is working fine in Visual C++ as well...

bluish
  • 26,356
  • 27
  • 122
  • 180
clancy688
  • 71
  • 1
  • 2
  • 6