Delphi Always Pass SEM_FAILCRITICALERRORS to SafeLoadLibrary by jpluimers

emailx45

Местный
Регистрация
5 Май 2008
Сообщения
3,571
Реакции
2,439
Credits
574
Delphi – always pass SEM_FAILCRITICALERRORS to SafeLoadLibrary
jpluimers - 19/May/2020
[SHOWTOGROUPS=4,20]
The below is based on [WayBack] delphi – Is there any way to catch the error if loading a dll cannot find a dependency? – Stack Overflow which I got via:
  • [WayBack] Error regarding rtl240.bpl not found in stand alone version of GExperts Grep – twm’s blog
  • [WayBack] Do not call SafeLoadLibrary(‘dllname.dll’) – twm’s blog
The problem is that the [WayBack] SysUtils.SafeLoadLibrary Function (present since at least Delphi 2007, and a wrapper around the [WayBack] LoadLibrary function (Windows)) does many good things – maybe even too many – so you need to take all of them into account:
function SafeLoadLibrary(const FileName: string; ErrorMode: UINT = SEM_NOOPENFILEERRORBOX): HMODULE;
  1. SafeLoadLibrary loads a Windows DLL or Linux shared object file, as specified by Filename.
  2. SafeLoadLibrary preserves the current FPU control word, preventing library initialization code from permanently overwriting precision and exception masks.
  3. Note:
    • On Windows, SafeLoadLibrary temporarily sets the system error mode to ErrorMode. The default, SEM_NOOPENFILEERRORBOX, suppresses error dialogs. The previous error mode is restored before SafeLoadLibrary exits. For a list of error modes, refer to SetErrorMode in the Microsoft documentation.
    • Note: On Linux, the Dummy argument is ignored.
Most important tips
Do not ever pass 0 (the number zero) as ErrorMode; I’ve seen lots of applications just passing zero for parameters they are not sure about, but in this case it is the worst solution as it will show all errors as a popup.

Do not forget a parameter either: the default value SEM_NOOPENFILEERRORBOX will only suppress a message box when it fails to find a file. But it will fail to enable SEM_FAILCRITICALERRORS which is what you really want.

Loading DLLs from resources
LoadLibrary and SafeLoadLibrary load the DLL from a file. But what if you want to load it from a resource?

Then this post from Thomas Mueller applies: he adopted the SafeLoadLibrary logic to load from a resource:
  • [WayBack] If your floating point calculations differ after a trivial change – twm’s blog
  • some additional comments at [WayBack] Today I had a curious bug: After changing the way GPS coordinates were read from a file (not calculated!) all of a sudden lots of unrelated floating poi… – Thomas Mueller (dummzeuch) – Google+
Other thoughts to keep in mind
The way Delphi sets the FPU control word is not thread safe: QualityCentral Report # 106943: Set8087CW/SetMXCSR are not thread-safe (you could work around in your implementation by using thread safe versions like mentioned in [WayBack] FastMM / Discussion / Open Discussion:Call to GetStackTrace changes 8087CW).
Calling SetErrorMode sets a global application wide setting (by default including all threads) of error code, so it is better to either:
  • decide for your whole application up front which error mode to use, save it and use the same value everywhere:
Because the error mode is set for the entire process, you must ensure that multi-threaded applications do not set different error-mode flags. Doing so can lead to inconsistent error handling.
  • decide between the global or local error mode methods:
    • [WayBack] SetErrorMode function (Windows)
    • [WayBack] GetErrorMode function (Windows)
    • [WayBack] SetThreadErrorMode function (Windows)
    • [WayBack] GetThreadErrorMode function (Windows)
Second, SEM_FAILCRITICALERRORS prevents an error to pop up when dependencies of the loaded file are not available. You might want to combine (bitwise or) it with other values like SEM_NOGPFAULTERRORBOX.

ErrorMode values
There are many more modes you can pass to the [WayBack] SetErrorMode function (Windows):

  • ValueMeaning
    0Use the system default, which is to display all error dialog boxes.


    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.


    SEM_NOALIGNMENTFAULTEXCEPT0x0004
    The system automatically fixes memory alignment faults and makes them invisible to the application. It does this for the calling process and any descendant processes. This feature is only supported by certain processor architectures. For more information, see the Remarks section.

    After this value is set for a process, subsequent attempts to clear the value are ignored.


    SEM_NOGPFAULTERRORBOX0x0002
    The system does not display the Windows Error Reporting dialog.


    SEM_NOOPENFILEERRORBOX0x8000
    The OpenFile function does not display a message box when it fails to find a file. Instead, the error is returned to the caller. This error mode overrides the OF_PROMPT flag.
–jeroen

My NOTE: Links to "anothers", was removed by default!

[/SHOWTOGROUPS]