SetErrorMode has no effect? - windows

I call
"SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);"
before loading a DLL. Nevertheless a windows message pops up
"This application has failed to start
because blabla.dll was not found...".
Why does that happen? I thought that was what SetErrorMode was supposed to prevent?
Thanks!

The call to SetErrorMode is probably never executed - if you statically link to the DLL, it will be loaded along with the executable. The message you see is popped by the operating system, and not by your code. If you want control over the load of the DLL, you should load it using LoadLibrary - but then using exported functions is a bit harder.
You can create your own loader (a different executable), which will make sure all DLLs are available, and then run the main executable. But that might be an overkill...

Related

How is the Windows notification about a missing DLLs implemented?

We've all seen "The code execution cannot proceed because xxxxxx.dll was not found." message box in Windows, that pops up when application launch fails due to a missing dependency.
And yet, I cannot figure out how it works: there seems to be no Windows API that allows to discover which DLL is missing after CreateProcess fails with a STATUS_DLL_NOT_FOUND error code...
Does anyone know how this is implemented?
Edit: And yeah, I'd like to obtain name of the missing DLL programmatically, in the process that calls CreateProcess().
there seems to be no Windows API that allows to discover which DLL is missing after CreateProcess fails with a STATUS_DLL_NOT_FOUND error code
Correct, there is no such API available.
Does anyone know how is this implemented?
When an EXE is being loaded prior to starting the execution of its code, the OS's loader scans the EXE's PE header to discover the required DLLs, and then it attempts to load each of those DLLs. If any of those DLLs fail to load, the loader is the one who is displaying the popup message, and it knows which DLL just failed, so it includes that DLL's name in the error message. But that information is not passed down to the caller who originally asked for the EXE to run.
FYI, when using CreateProcess() to run an EXE, you can disable that popup error message by calling SetErrorMode()/SetThreadErrorMode() beforehand, specifying the SEM_FAILCRITICALERRORS flag:
Value
Meaning
SEM_FAILCRITICALERRORS0x0001
The system does not display the critical-error-handler message box. Instead, the system sends the error to the calling process.Best practice is that all applications call the process-wide SetErrorMode function with a parameter of SEM_FAILCRITICALERRORS at startup. This is to prevent error mode dialogs from hanging the application.

Packaging a Gtk3 app for Windows for the Microsoft store

Has anyone been successful at packaging a Gtk3 app for Windows for the Microsoft store?
I'm playing with this at the moment:
Visual Studio 2019;
Gtk3/Gtkmm distro obtained via vcpkg;
C++ app;
VS Application Packaging Project.
The application runs fine on its own. I then package it, and then run the MSIX bundle installer. When I then run the installed application, it starts but:
an Access Denied error appears in a dialog box;
the application appears with broken icons and incorrect colors (wrong or no theme).
I have tracked the error having to do with Gio-2.DLL where it attempts to spawn a child process, looks like something to do with creating a dbus server/session (??). I believe the child process (dbus server?) starts but then attempts to do something that is not permitted in the sandbox that Windows creates for the app.
Anyone?
After some more investigation, I may have found a workaround. I'll post it here in case it helps anyone else. This workaround allows making a packaged Gtk3 application for Windows. A Windows packaged application runs in a sandbox of sorts, with heavily restricted access to resources outside the package.
First, the issue: during initialization, the version of Gio-2.DLL for Windows spawns a child process to serve as a DBus session daemon (I may get the terminology wrong here as I'm not that familiar with DBus). It does so only for the first instance. If one launches additional instances of applications that use Gio-2.DLL, the additional instances use the existing daemon from the first instance.
To launch the daemon, Gio-2.DLL calls CreateProcess() to fork a RUNDLL32.EXE child, with the full path to Gio-2.DLL (i.e. itself), and g_win32_run_session_bus() as the name of the function to call. It looks like RUNDLL32.EXE does launch successfully, since it is able to display the "RUNDLL" error dialog box. However it fails to make the requested function call into Gio-2.DLL. I gather that at least one of the system calls that RUNDLL32.EXE makes to load the DLL and call the requested function is prohibited when running in a packaged application.
At the moment, my workaround is this. Assume my application executable is called 'myapp.exe':
the application package contains myapp.exe, all the necessary DLLs for Gtk3 and dependencies, and another executable 'dbus_daemon_launcher.exe';
before entering the Gtk main loop, myapp.exe calls CreateProcess() to start dbus_daemon_launcher.exe;
dbus_daemon_launcher.exe is also linked with Gio-2.DLL and makes a call to g_win32_run_session_bus() with the DLL;
myapp.exe then proceeds to start the Gtk main loop. Since the Dbus daemon is then already running, Gio-2.DLL does not attempt to call RUNDLL32.EXE to launch it, which avoids the error.
This workaround has the advantage that it does not require making a custom version of Gio-2.DLL. Also, I'm using Gtk3: perhaps this issue has been addressed in the more recent Gtk4, and the workaround is unnecessary in this case.

What's the lifetime of a DLL after being compiled?

I was reading about it and the part about memory was really confusing. What exactly happens to a DLL after compilation?
Questions that were somewhat bugging me:
Is it loaded into memory only once and all processes that require access to it are given only a pointer to where it is?
When is it loaded? I am sure it isn't just arbitrarily loaded into memory after compilation so is there a special procedure to load it or does Windows load a DLL when a process requires it and keeps it for sharing among other processes?
From the Microsoft docs
Every process that loads the DLL maps it into its virtual address space. After the process loads the DLL into its virtual address, it can call the exported DLL functions.
How does that "mapping" look like? I found that a bit confusing.
I don't know if this is a relevant piece of info but I am specifically interested in custom DLLs (DLLs written by me), not system DLLs
An exe file lists DLLs is wants to link to, so when the loader loads an exe, it loads DLLs that are listed as required, unless they are already loaded. A DLL may run initialization code the first time it loads.
Of course a DLL can be loaded dynamically by name, then it's loaded when the LoadLibrary API call is issued by a program. This is useful to implement dynamically loadable plugins.
Windows keeps a reference counter for each DLL, so when all processes stopped referencing a DLL, either by exiting or explicitly calling FreeLibrary, Windows will unload the DLL, giving it a chance to run any cleanup code.

C++/CLI application hanging after compiling on Windows 10

I have a mixed managed and unmanaged C++ application that's working quite well. I'm using Visual Studio 2013 to compile it, and all is well. Recently I upgraded my computer to Windows 10, and now it's not working.
If I get the executable compiled on Windows 8, it runs properly on Windows 10. It only fails if I compile it on Windows 10.
The failure is peculiar as well. I run the EXE and nothing happens. When I run it from Visual Studio it doesn't even reach the first line of main. Breakpoints are all marked as 'disabled'. When I break the running process the debugger shows an empty stack trace.
UPDATE: Hunch about DLL loading turned into a fact:
I used Process Explorer and I see the process has two threads. The one starting at !CorExeMain is stuck at !LdrLoadDll, but I can't tell which DLL that is.
OK, found the DLL that causes the problem. I've created a C++/CLI console application, used that DLL and got the same behavior. The DLL is part of the application (and part of the VS solution). It's a native C++ DLL, compiled with the same compiler and settings. This DLL references other DLLs unfortunately.
This is a generic problem called "LoaderLock". The operating system makes very strong guarantees when it calls the DllMain() entrypoint of a DLL. Strictly in loading order, they never run at the same time. There is a lock in the OS loader that ensures these promises are kept.
And a lock always has the potential to cause deadlock. It will happen when the DllMain() entrypoint does something unwise like loading the DLL itself with LoadLibrary(). Or call a function that requires the OS to have a DLL already loaded. Can't work, its DllMain() entrypoint can't be called because the loader lock is held. The program will freeze. C++/CLI apps are prone to this problem, lots of stuff tends to happen in DllMain(). Indirectly, you can't see it in your code.
You can only see it with the debugger. You must change its flavor, Project > Properties > Debugging > Debugger Type, change it from "Auto" to "Mixed". You'll now also see the unmanaged code that is running including the OS loader functions, name starts with "Ldr". Be sure to enable the Microsoft Symbol Server with Tools > Options > Debugging > Symbols. And be sure to use the Debug > Windows > Threads debugging window as well, the truly tricky loader deadlocks that don't repeat well or appear to be affected by the OS version are caused by another thread loading a DLL.
Diagnosing and fixing it can be difficult, be sure to reserve the time you need to dig in. If you can't make heads or tails of the stack traces then post them in your question.
Before taking #Hans Passant advice I carefully combed through the code, dumpbin /dependentsed the executables and DLLs and made sure there were no custom DllMains. There were none. DLLs were indeed loaded with LoadLibrary, but that was happening long after the loading DLLs were loaded.
So I took #Hans Passant advice. Set up the debugger properly and checked the state of the process during the deadlock. One of the threads was stuck in LdrLoadDll.
It took a little tinkering to find the name of the DLL that was passed to LdrLoadDll. It was AVGHOOK.DLL .
I disabled AVG, and lo and behold - everything is back to normal.
This is the second time AVG is messing with me. The previous time I nearly replaced a printer until I figured out all the PCL errors disappeared when I disabled AVG. I think I'm not going to use it any more.
I have put our comment ping pong into a full text:
#1:
As you found out, that your application did not load, you needed to check if applications on your system (W10, VS2013) run at all.
Reply: A test console app is running fine.
#2:
If your application doesn't run, build up a similar application and step-by-step put code of your app into the new app until it fails.
If the failure is causes by a DLL (which cannot be loaded, as it was in your case), remove DLLs from your app until it works. Alternatively build a dummy console app, include DLL #1 and use some functions of that DLL. Compile, run, check. Go on until DLL #n...
Reply: faulty DLL was found.
#3:
Reference only this DLL in the test app to ensure it's this DLL only and not a combination of DLLs.
Is it a managed DLL or a native C++ DLL?
If the faulty DLL is from a foreign source: bad luck. Ask the developer for support.
If it's your own: Did you compile the faulty DLL on W10+VS2013, too, or did you copy it from your previous system? I suggest you compile this DLL again on the new system.
Reply: it's a native C++ DLL, which is part of the solution and is compiled together with the main app.
This DLL references other DLLs unfortunately.
#4:
Create a new console app, that references not your faulty application DLL, but the DLLs which are referenced by YOUR DLL. Omit the intermediate step to detect if the failure comes from the other DLLs.
The general procedure is: Split up faulty code to find out out which part is causing trouble. Romans already knew this 2000 years ago: Divide et impera ;-) Though they did it in a different context...
We had the exact same problem here during several weeks ! And we finally found a solution !
In our case, it was the anti-virus Avast which was corrupting the generated .exe !
The solution was to simply disable all agents while generating the release !
If you use another anti-virus, try to disable it.

Access violation inside LoadLibrary() call

I encounter an access violation when calling a DLL inside LabVIEW. Let's call the DLL "extcode.dll". I don't have its code, it comes from an external manufacturer.
Running it in Windbg, it stopped with the message:
(724.1200): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll!RtlNewSecurityObjectWithMultipleInheritance+0x12a:
And call stack is:
ntdll!RtlNewSecurityObjectWithMultipleInheritance+0x12a
ntdll!MD5Final+0xedfc
ntdll!RtlFindClearBitsAndSet+0xdf4
ntdll!RtlFindClearBitsAndSet+0x3a8
ntdll!RtlFindClearBitsAndSet+0x4b9
ntdll!RtlCreateProcessParametersEx+0x829
ntdll!LdrLoadDll+0x9e
KERNELBASE!LoadLibraryExW+0x19c
KERNELBASE!LoadLibraryExA+0x51
LabVIEW!ChangeVINameWrapper+0x36f5
LabVIEW!ChangeVINameWrapper+0x3970
LabVIEW!ExtFuncDynLibWrapper+0x211
Note that dependencies of extcode.dll are loaded before access violation.
The situation is random, but when it happens all subsequent tries lead to it.
The code is a simple LabVIEW function calling a function in the DLL, and prototype is super simple (int function(void)) so it cannot be an misconfiguration of the call parameters, nor pointer arithmetics. I checked every combination of calling conventions and error checking levels.
The DLL runs perfectly fine when called in other environments (.NET and C).
I found that RtlFindClearBitsAndSet is related to bit array manipulations
What does it make you think about? Do you think it is a problem in extcode.dll, LabVIEW, or Windows?
PS: I use LabVIEW 2010 64 bit, on Windows 7 64 bit (and extcode.dll is 64 bit). I didn't manage to reproduce it on 32 bit system.
11/18 EDIT
I ended up making a standalone exe that wraps the DLL; LabVIEW communicates with it through pipes. It works perfectly, but I stil don't understand why loading a DLL into LabVIEW can crash.
If it works ok when called from C, you can quit working with Windbg because the DLL is probably ok. Something is wrong with how the DLL is being called, and once the DLL overwrites some of LabView's memory it is all over, even though it might take 1000 iterations before something actually goes kablooey.
First check your calling conventions, C or StdCall. C calling convention is the default and StdCall is almost certainly what you want. (Check the DLL header file.) LabView 2009 apparently did some auto-checking and fixing of calling conventions, but the switch to LLVM in LV 2010 has made this impossible; now it just tanks.
If it still tanks after changing this, check your calling arguments again. what you are passing, scalars or pointer data? You cannot access memory allocated by the DLL from LabView without doing some sneaky things, although you can allocate memory (i.e. byte array) in LabView and pass a pointer to it to the DLL for it to modify.
Also, if you are getting a pointer (such as a refnum) from an earlier call to DLL and returning it, check your pointer size. LabView's Call Library function now has a "pointer size integer" type, which generates the appropriately-sized type depending on whether it is invoked in 32-bit or 64-bit LabView. (It is always 64 bits on the wire, because that has to be defined at compile time.) The fact that your DLL works in 32 suggests this is a possibility.
Also keep in mind that C structs are often aligned by the (C) compiler. If you are passing a pointer to a struct made of a Uint8 and an UInt16, the C compiler will allocate 32 bits (or maybe even 64 bits) for this. You'll have to pad your struct (cluster) in LabView to make it match, or write a wrapper DLL to assemble the struct.
-Rob
An access violation (0xc0000005) will also be reported if DEP (Data Execution Prevention) is enabled on your machine and disapproves of something your binary (EXE or DLL) is trying to do. DEP is usually off by default on Windows XP, but active on Windows Vista / Windows 7.
DEP is a hardware-supported security measure designed to prevent malicious code executing some bytes that previously were considered "just some data"; I've had a few run-ins with it, all of which required re-compiling the offending binaries with a recent version of Microsoft Visual Studio; this allows to you set a flag which defines whether or not your binary supports DEP.
Some useful resources:
I found this MSDN blog entry
very helpful for gaining an
understanding of what DEP is and does
You might also want to consult this
technet article on how to turn
DEP on and off on Windows XP.
This is hard to diagnose remotely, but here are a couple of ideas.
The fact that your function takes no arguments means that either the function is truly trivial, or there is some stored state in the dll that takes into account previous function calls. Maybe the crash in this function is only an indicator, and you have a problem with a previous function call? Is there an initilization routine you're not calling?
If you only have problem when using 64 bit labview, my first guess would be that there's a problem with the 64 bit version of the dll, but if you are sure you don't have any problem with the exact same calls when using the dll in other environments, I'm stumped. One possibility is that you are using the wrong calling convention (stdcall vs. cdecl) in labview.
Have you tried importing the dll and header using the labview import wizard? This might help avoid silly mistakes with the prototypes.
One other thing to try: right click on the DLL call, choose configure and make sure you're running in the UI thread instead of any thread. Sometimes this helps.
When working with git and cygwin under NTFS, i found that sometimes the executable bit is not set (or un-set during checkout or some file operations) - inside cygwin cd to the folder and do
chmod a+rwx *.dll
and check if it changes a thing (and check if you want it this way!). I found this question while searching for LoadLibrary() failing with GetLastError() returning 5 (not "0xc0000005" btw) and solved the issue with this chmod call.

Resources