This is a common problem that, it seems to me, is not particularly specific to Delphi programmers. If you have code that calls LoadLibrary in the initialization section or even FreeLibrary in the finalization section, this code is unsafe for use in the library.
Please note that I am not familiar with all the libraries you mentioned and do not confirm at all that they have an initialization section code that is unsafe for use in the library. I think there is something for you to confirm - I would like to stick with the concepts in this answer and not comment on specific Delphi libraries.
I would say that the calls to GetModuleHandle and GetProcAddress in order from DllMain . I say this because you specifically mention GetProcAddress . It is absolutely good to get a module descriptor, for example, a call to GetModuleHandle , and then get the address of the function by calling GetProcAddress . Therefore, if some of the suspicious libraries do this and do not call LoadLibrary , then they may be fine.
In any case, in accordance with the above caveats, you need to establish that any code that will be called from DllMain that violates the rules set by Microsoft is called at a safe time, and not from DllMain . Unfortunately, these rules are unclear at best. Microsoft say the following in the DllMain documentation :
The entry point function should only perform simple initialization or completion tasks. It should not call the LoadLibrary or LoadLibraryEx functions (or the function that calls these functions), as this can create dependency loops in the order in which the DLL loads. This may cause the DLL to be used before the system has executed its initialization code. Similarly, the entry-point function should not call the FreeLibrary function (or the function that calls FreeLibrary) during the process, as this may cause the DLL to be used after the system has executed its exit code.
Since Kernel32.dll is guaranteed to be loaded into the process address space when the entry point function is called, the calling functions in Kernel32.dll do not cause the DLL to be used before the initialization code has been executed. Therefore, a function entry point can call functions in Kernel32.dll that do not load other DLLs. For example, DllMain can create synchronization objects, such as critical sections and mutexes, as well as use TLS. Unfortunately, there is not a complete list of safe functions in Kernel32.dll.
The last paragraph leaves you with a little guidance. To make sure your library is reliable, you will need to do something in the following lines:
- Arrange that each initialization section of any unit whose source code you control registers the initialization and completion procedure with the central registry.
- In an executable project, you invoke the initialization routines when they are registered, and invoke the termination routines in the reverse order when the program terminates.
- In a library project, you put off calling these initialization and completion procedures. Export a couple of functions from the DLL that the consumer of the DLL can call to request that these initialization and termination procedures be called.
This is the approach I used with my libraries, and it has served me well for many years.
This approach involves quite a bit of work and has the disadvantage that you are modifying third-party libraries. However, if these libraries do not work correctly when used as supplied ones, what is your alternative?
Perhaps, at a slower time, you can contact the developers of any libraries that, in your opinion, are incompatible with use in the library. Try to convince them to change their code so that it is compatible with use in the library. As you can see from the Remy comment on your question, it is entirely possible that the library developers may not be aware of this problem and really want to make changes.