The reason why you run into problems with some DLLS is because LoadLibrary executes code in the DLL it loads - specifically, the DLL's initialization code. In Delphi projects, this includes the unit initialization sections. In the case of borlandmm.dll, the dll initialization code inserts itself into your host exe process's runtime library, replacing your default memory manager with the memory manager in the DLL. This is not intended to be a reversible action - it can't remove itself in the DLL shutdown code (in part because DLL shutdown code is not guaranteed to execute in all circumstances).
So, be careful using LoadLibrary because you are basically executing arbitrary code before you even know what the DLL is. If you really must take a peek into a large number of arbitrary DLLs of unknown origin, a safer way would be to load the DLL as a resource image instead of as an executable image. This loads the file into memory but does not execute the DLL initialization code. See LoadLibraryEx() and the LOAD_LIBRARY_AS_IMAGE_RESOURCE flag.
As you mentioned in an earlier comment, there are a number of things you can do to reduce the number of DLLs you need to load to exactly the DLLs that the user/administrator wants your application to load, instead of loading everything you can find.
- Require the DLL file name have a custom extension or file name pattern. (Plugin*.mod for example)
- Only load DLLs from a special subdirectory. This works well with directory level access control, since on most systems bin directories are not writable by ordinary users. Someone would have to have admin rights to put a DLL into the special subdirectory.
- Only load DLL files that are named in a user-defined config file.
- Any combination of the above