Q: Proper way to access data in a data only dll file - c++

My application store some data in data only dll files. Those dll files are loaded with LoadLibrary() when needed at runtime and then discarded with FreeLibrary() after finish using them. The main application access the data stored in the dll files using GetProcAddress(). The program is written in C++ and uses WinAPI calls, no MFC or other libraries. It has two versions x64 and x86. It works fine on most systems. My dll files do not call other libraries or depend on anything else. Each is a stand alone file.
Recently, I discovered the program does not work on one machine. this specific one has Windows 10 x64 installed on it. After investigations I found the following:
LoadLibrary() fails with error message "Could not find module". The dll is in same directory with main program.
I replaced the call to LoadLibrary() with LoadLibraryEx() and tried the following falgs:
LOAD_IGNORE_CODE_AUTHZ_LEVEL did not work. The dll could not be loaded.
DONT_RESOLVE_DLL_REFERENCES ... works?? But, Microsoft strongly recommends not to use it.
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE ... loading the dll succeeds?? But, the call to GetProcessAddress later fails. the program could not access the data in the dll file. So this is not actually working.
I could not find anything wrong with this machine. All other programs are working fine.
I tried the x86 version on this machine and it worked fine using original LoadLibrary().
My installer is dual system and automatically installs x64 version when it finds x64 windows. Normal user can not simply switch to x86 when he gets such error.
My question is how can I eliminate this error and make my program works on any machine:
Should I call LoadLibraryEx() using DONT_RESOLVE_DLL_REFERENCES flag and ignore Microsoft warning?
Is there any way I can get my library loaded with simple call to LoadLibrary()?
If I call LoadLibraryEx() with LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE flag, as recommended by Microsoft, how can I access the data without calling GetProcessAddress()?
Thank you in advance.

Related

Using custom DLL with Inno-Setup

I am having trouble getting Inno-Setup to load my DLL.
I have looked at similar posts, but none of the solutions offered in those seem to help.In particular, this post came very close, but does not seem to be quite the same issue.
My installer runs just fine on my test system. My DLL is written in C++, using VS 2010. There is a DEF file. I have been successful using the VS debugger to attach to the installer's thread and step through my code. Everything is good. The release version runs just fine on my test system with no debuggers involved. Setup calls my DLL and it works.
Then I take my installer to a different, pristine system to try it out. Every time, when I launch the installer, it starts off with the usual UAC prompt: "Do you want to allow the following program from an unknown publisher to make changes to this computer?" And I say "Yes." Then I get a beep and an alert that says:
Runtime Error (at -1:0):
Cannot import
dll:<utf8>C:\Users\Logicrat\AppData\Local\Temp\is-4E245\MyDLL.dll
In my setup script I have
[Files]
Source: "MyDLL.dll"; DestDir: "{app}"; Flags : dontcopy
and
function MyFunc(hWnd: Integer; lpText, lpCaption: AnsiString; uType: Cardinal): Integer;
external 'MyFunc#files:MyDLL.dll stdcall setuponly';
According to the Inno documentation, the dontcopy flag is appropriate if the DLL is not needed for uninstall, which it is not.
I suspect the problem lies in designating exactly where the DLL is supposed to be, as I my script calls for it to be in the {app} directory, yet the error message refers to a temp directory. I've tried a number of variations of the script, all with the same results.
Both my development/test system and my pristine target system are Windows 7 (32-bit). I have been banging on this for weeks with no visible progress. Any suggestions will be most welcome.
Problem solved, thanks to the suggestion by TLama about checking dependencies. When I had initially created the new project for my DLL in MS Visual Studio 2010, I had selected the option to "Use MFC in a shared library." That turned out to be the source of the problem, as the DLL itself was then dependent on mfc100u.dll and msvcr100.dll, which were not present on the target system I used to test my installer. I fixed it by changing the project preference to "Use MFC in a static library." That made the DLL larger, but it also made it work. Then, after I first rebuilt the DLL and then rebuilt the installer that used it, everything was fine.
It might have been nice if the error message I got the first time around named the DLL it was looking for instead of the DLL that tried to call the missing one.

Show an (custom) error when "required" runtime libraries are not present?

I've been making a program in Visual Studio 2012, what comes with it is that when I send my application to someone, they need the VS2012 Runtime, which sometimes they don't know where to download or what they need (for normal users "xxx.dll is missing" is very misleading).
I know exactly which dependencies my application requires (fantom.dll [Lego Mindstorms stuff] and the VC++ 2012 Redist).
I would like to show a dialog when these libraries are missing on application startup and provide the user with download links for these libraries.
Is this possible to accomplish?
Yeah you could do something like:
Move all of the code in your binary into a DLL.
Create an EXE which dynamically loads the DLL using LoadLibrary and unloads it with FreeLibrary.
If LoadLibrary fails, check if its due to missing DLLs, if so then display a MessageBox/your custom message and exit.
Of course this means your EXE project must NOT depend on the runtime itself - this shouldn't be an issue since you'll only need to call 3 win32 API's.
No it's not possible but you can create an installer for your program. The error is thrown during the loading of your program, before your code execution...
You can try with that : http://www.codeproject.com/Articles/24187/Creating-an-Installer
I can't speak for testing the VS2012 Runtime dynamically, but you can certainly validate fantom.dll dynamically. Instead of static-linking to the DLL directly, you can dynamically load it instead. You can configure your project to delay-load the DLL at run-time, and then provide a delay-load callback handler that the RTL will call if the delay-load fails. Or you can simply skip the delay-load feature and load the DLL yourself manually by calling LoadLibrary() and GetProcAddress() directly.
Sure, you can verify if a dependency exists on the deployed system. A few things come to mind...
You can see if the assembly is recognized on the running system by calling AppDomain.AssemblyResolve() . Further reading here
Another more primitive option is to call a File.Exists(your assembly path here) test, but I would advise against this as it's a bad practice to require hard-pathed installation locations.
That said, and as others have stated, it's still by far the best approach to create yourself an installation distribution.

Load DLL at runtime

I'm using the CUDA Driver API in a project. When I execute the project in a PC that doesn't have a NVIDIA GPU, it gives "nvcuda.dll was not found".
The problem is: this DLL is only distributed with the GPU driver, not like in the Runtime API where you can put the DLL needed with your executable. I need to load this DLL in runtime, and if it doesn't exist I will know that CUDA is not available. I'm using Visual Studio 2012 Professional.
Is there a way to do that?
Windows provides an API function (LoadLibrary) to load DLLs into memory at runtime. You provide a LPCTSTR (null terminated pointer to a const TCHAR) containing the name/path of the DLL you want to load. If you provide a relative path, Windows will scan PATH and the executable's current directory for the file. If you provide an absolute path, Windows will use that.
If LoadLibrary returns NULL, Windows couldn't find the file.
Create a small "Launcher" app that will check if system meets your requirements and will launch the main application or display an error depending on the check results.
To check if a DLL is available you can use LoadLibrary() as previously suggested.

C++ DLL fails to load after linking another DLL to project

I'm using Visual Studio 2010 to create a 32-bit DLL as a plug-in to a 3rd party app (AviSynth). The DLL was being correctly loaded by the 3rd party app until I tried to use the FFTW (http://fftw.org) DLL. I took the 32-bit FFTW DLL, ran "lib /def:libfftw3-3.def" to create a .lib file, added that as a resource in the project. Made some calls to the functions. It compiles fine, but when I try to load it in the third party tool, it fails.
I've tried putting the FFTW DLL alongside my DLL, and I've also tried using LoadLibrary from inside my DllMain, but it's still not working.
I am able to stop the debugger in the DllMain function and in the function called by AviSynth (AvisynthPluginInit2), but AviSynth claims to be unable to load the DLL after that, and breakpoints at the tops of functions that were called before are no longer hit.
The AviSynth error message is:
LoadPlugin: unable to load "C:\Program Files (x86)\AviSynth 2.5\plugins\xxxMYPLUGINxxx.dll"
Thanks for your help.
The first thing I try when I get something like this is Dependency Walker:
http://www.dependencywalker.com/
It won't catch every possible problem, but it's very quick to check for simple problems (missing DLLs, missing exports). You can also set it to open any number of file-extensions by double-clicking them. I usually set .dll, .ax, .ocx, .sys, .exe.
IMO one of the essential tools for any Windows developer.
ps: if Dependency Walker doesn't find any problems, try to load your DLL with LoadLibrary() and see what GetLastError() returns.
BTW:
and I've also tried using LoadLibrary from inside my DllMain, but it's still not working.
You cannot call LoadLibrary() from DllMain().
The entry-point function should perform only simple initialization or termination tasks. It must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these functions), because this may create dependency loops in the DLL load order.
(The entry-point function is your DllMain)
Turns out that the FFTW DLL had to be in the same directory as the AVS script, not the AVISynth plugin directory. I guess that's the working directory for Virtual Dub.
Anyway, it works now. Thanks for the help!

Getting a program only to run with certain dlls in the directory

When, for instance, I create a program and compile it with MinGW if I delete the environment variable I need to put the dll in the directory for it to work
ie. libgcc_s_dw2-1.dll
without it the program will not even start.
When developing with QT I noticed I needed another dll in the directory, it was QtCored4.dll, I was wondering how the program knows that the dll is missing?
Also is there anyway to add something like this to a program,
like a define statement or something?
I need an answer that can work with C++ :)
That is taken care by the operating system -- since your program uses functions from the DLL, it is automatically loaded when your program starts, and if the DLL is missing, you will get an error. You can read more about this process on MSDN: Load-Time Dynamic Linking.
when developing with QT I noticed I needed another dll in the directory, it was QtCored4.dll, I was wondering how the program knows that the dll is missing
You can also try to load the DLL yourself at runtime, and handle failure gracefully. See LoadLibrary and GetProcAddress.