Delphi DLL Organization - Static and Dynamic Loading - delphi

I imagine this is a common issue, but googling around hasn't presented a solution. I'm just having some trouble loading a library.
The source that I have for the library is utilizing static loading, which is fine. The rest of the libraries I am using are loaded dynamically.
The problem is that my program is now being loaded up as a library (it is a plugin), by a different application (a host). This means that the directory for the HOST executable, is NOT the program directory for my application.
The library that is being statically loaded (just a simple library for font rendering), is inside of my program's directory, and when loading my software as a plugin, it is not found. When I load up my software as a 'standalone' program (without a host), there is no issue.
I was able to resolve the issue by putting the 'missing' library into the folder for the host application, but this is a bad solution.
I was also able to resolve it by providing a direct path to the name of the library, but this is also a bad solution. I do not know where the end user will be installing my software.
Is there any way around this issue without having to rewrite the code to use dynamic loading?
To continue using static loading, must the library be registered? I think that registering this library is too invasive, as other programs may be using a different version of it.
const
ft_lib = 'freetype6.dll'; //here is our problem. I could put a direct path
//here, to fix it, but I will not know this path
//on an end-user's machine
type
FT_Library = Pointer;
function FT_Init_FreeType(out alibrary : FT_Library ) : FT_Error;
cdecl; external ft_lib name 'FT_Init_FreeType';

The program loader looks for DLLs on the system path. Just make sure that your freetype6.dll (and the DLLs that it requires) is either in the same directory as the host exe, or is in a directory that is in the file path (PATH environment variable).
For reference: http://msdn.microsoft.com/en-us/library/7d83bc18(v=vs.71).aspx

I would suggest that modifying PATH is a very invasive solution. I would recommend attempting to avoid that. You may be able to do that using SetDllDirectory. This will add a directory to the search path, but will make that change locally to your process.
Your host app should call SetDllDirectory immediately before loading your DLL. Then any dependencies of the DLL will be resolved using the modified search path. When the DLL has successfully loaded, call SetDllDirectory again to restore the search path to its default value.
If you aren't in control of the host then it might be tricky to implement this. You'd need to call SetDllDirectory in your DLL and then it would be too late. You could put another layer between the host and plugin. That layer could modify the DLL search path and then use LoadLibrary to load the DLL that used implicit linking.
The other obvious option is to stop using implicit linking. Use LoadLibrary to resolve all your dependencies. That's actually not as hard as it sounds.
In a modern Delphi you could use delay loading also. So long as the DLL search path is modified, before you call into the delay loaded imports, they will resolve.

Related

Indy 10 loads SSL libraries even if I remove them

I am currently encoutering a very strange problem. In one of my applications I use OpenSSL and Indy in order to create a secure TCP connection to a host. I wanted to test if the application (and Indy) are recognizing if the OpenSSL-libraries are missing. Those libraries are placed inside the application folder.
The strange thing is that my application still works fine even though I have removed the libraries. I also removed OpenSSL itself from my computer and searched for any other appearance of the OpenSSL-libraries. There are no OpenSSL-libraries on my computer.
So what is going on? I call the Load() method from IndyOpenSSLHeader in order to load the libraries and guess what...they are loading perfectly. How can this be? There are no libraries on my computer ^^
Btw I did NOT set up a custom library path. I am using the default one which - as far as I know - should be the application folder.
I am using Delphi XE5 and Indy 10 for me application.
What is wrong here?
Thanks in advance!
If you are on iOS then Indy links to OpenSSL statically. On any other platform, there is no possible way that Indy can successfully use OpenSSL SSL/TLS without loading its library files first, so they have to be getting loaded from somewhere you missed. If you are running on Windows, use Process Explorer to see where they are actually being loaded from.
Indy defaults to using the OS search path to load external libraries. The OS defaults to looking in the app's folder, but it can also look in other places as well. You can use Indy's IdOpenSSLSetLibPath() function to specify where you want OpenSSL loaded from (there is a similar function for ZLib - IdZLibSetLibPath()). This is good to ensure your app loads the libraries only from your app's folder and nowhere else, in case someone maliciously deletes the libraries from your app's folder in an attempt to trick it into loading the libraries from another path on the OS's search path. It is also good for testing purposes if you just want to see how your app reacts when the libraries are missing, without having to actually delete them.
They may be statically linked into your binary.
Also, there is a lot of places where SSL libraries could be.
See this article (Search Order for Desktop Applications):
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682586%28v=vs.85%29.aspx

Why does FASTMM's full debug mode require the fulldebugmode.dll to be in the same folder with the appllcation's .exe file?

When I copy the DLLs into the same folder where the .exe resides, it works.
There is a (sort of) workaround for this, though: when I open the debugger options and add the original path of the DLL's to the environment block, it works when I start my project INSIDE my IDE, but it doesn't work when I start the project.exe file in explorer. This is not really an issue, I would just like to know the relationship between these files.
When a DLL is linked by its name only, the DLL search path is used to locate it. This search path is a complicated beast that varies depending on a variety of settings. It is documented in some detail on MSDN.
In all variants of the DLL search path, the directory from which the executable was loaded is the first directory searched. This is by far the safest way to load a DLL. Requiring modifications to the global PATH environment variable is invasive. Requiring DLLs to be installed in system directories is invasive and against all recommendations of best practice. Requiring the use of current directory is fragile and brittle and opens security vulnerabilities.
In an ideal world, applications should be isolated. And the most effective way to achieve that is to place dependencies in the same directory as the executable files.

Using EXE's instead of DLL's as plugins - Ways to "one way, one time" transfer information

tldr; at bottom.
Ok, so once again an interesting problem and I'm looking for a fun and interesting solution.
My current project involves being very modular, meaning the program functionality will be easily changed based on different modules and the program would adapt.
So I started out with the typical route, which is using DLL plugins. Now this is just way to normal, I want to think outside the box a bit.
The modules included in my program are long running campaigns that may take weeks to finish, and there will be many running at a time. So stability is a big issue, so I thought about what Google Chrome does. Processes, not DLLs or threads.
So I have a framework going and I need a way to get some information about each module (which are now EXEs). Now for my DLL framework I was exporting a "Register" function that would fill in some information.
So I thought to myself, hey EXEs can export functions, let's see if that actually works...It doesn't. I did some research into how Windows handles theses things and I don't feel like hacking the PE headers on the fly (but it's the out of the box kind of thinking I'm going for).
I'm planning on using named pipes and CLI parameters to transfer data between the main program and the module exe's. I could use that in a register fashion, but I want to here other peoples thoughts.
tldr: I'm using EXE's instead of DLL's for plugins. Looking for a way to easily export one time information like a exported "Register" function would on a DLL. Thoughts?
You might still consider having the modules written as DLLs with defined entrypoints (e.g., the Register function). Then you write the executable that loads the specified DLL. Your main application would fire off the driver executable and give it a name of a plugin DLL.
That way it is still easy to define and export the set of APIs that must be provided yet still run it as a separate process. The one executable that you write can load the specified DLL and then handle the necessary IPC with the main app.
You could define a protocol via the stdin/stdout, named pipes, sockets, etc.
I have successfully used 'plain' COM for several projects, and objects inheriting from TAutoObject. The bonusses here are IDL; the interopability with .Net, VBA and other non-Delphi things; and the fact that implementors still can choose wether to supply a DLL, an exe, an NT-service, and optionally run hosted over the network (COM+/DCOM). There may be several considerations you should handle about multi-threading and locking, but I found all that I needed to know online.
You can, of course, not use symbols exported by a (running) exe since it is running in another boundary. But, you can load an exe as an image (as you would do with a library) using LoadLibrary(Ex) and then, use the functions exported by the exe. I have tested (just for fun) when debugging PeStudio. See the snapshot below of chrome.exe loaded in the process space of PeStudio.exe using LoadLibrary.

Get around 3rd party cyclic dll dependencies?

I am attempting to access text in a TE Edit (from ter32.dll) in a 3rd party application. (first post on this here) I looked through the API and tried to dynamically load the dll in order to access a function. Unfortunately, this (aftermarket rework) of ter32.dll has a load of dependencies. I tried dynamically loading each required dll as needed but ran into a cyclic dependency. ter32.dll requires x. x requires y. y won't load because it requires x. Would I have to statically load these with a delay? I sure hope not as I don't want the overhead/bloat/dependency in my application.
1) what am I missing?
2) is there some way around this?
3) does anybody have any other way of accessing the text in a TE Edit of ter32.dll?
When you load a DLL the loader will load all the dependencies for you. These dependencies are listed in the import tables of each DLL and the loader resolves them. You don't need to do anything.
Therefore I can't understand how you came to the conclusion that you yourself needed to process DLL dependencies. Are you loading this DLL in a non-standard way? Do you need a manifest for WinSxS dependencies, i.e. if the MS C runtime is needed? Is there something else we need to know?
All that said, having this DLL loaded into your process is not likely, in my view, to help much in extracting text from a different process which has its own separate virtual memory. In other words, I am quite confident that your current attempt to extract the text will fail. The way to get around the virtual memory barrier is to run your code in the other process using a hook.

Delphi app calling cobol app -> error

We need to get data out of an older accounting system. We have received a dll that gives us access to the data we need. It includes a type library that we have imported.
If we run our test application from the same directory as the accounting system, everything works fine. If we try to run our application from a different directory, we get the following error:
Dynamically Bound RTS
Runtime DLL 'OOPS', version 3.1, entry point oops
not recorded in registry, not found or incompatible with requirements
of dynamically bound COBOL program. Dynamic binding of RTS requires:
Runtime DLL 'OOLSM', at least Version 3.1
Can anybody provide some helpful information on this?
Are we supposed to have some kind of cobol runtime in our directory? Or in the path? Or registered in the registry?
Thanks,
-Vegar
Updates:
Setting the system %path% to include the path to the accounting system seems to do the trick. Including it as a user variable did not have the same effect for some reason.
What Cobol are you using?
I had done this for year with Microfocus NetExpress 3.1, and all works just fine.
I write COBOL DLL to access COBOL data files, and also write Delphi DLL to add new features to old COBOL systens.
And yes, I use to set the runtime path, that is environment variable called COBDIR, there are others,but usually %PATH% and %COBDIR%is enough.
If you give more detais about what COBOL compiler are you using, and how is the dll interface that you are calling, will me ore easy to help you.
And maybe "Dependence Walker" can help you to identify what run time files are missing, if it is.
http://www.dependencywalker.com/
If it works from the accounting app's directory, but not a different one, the first thing I'd try is adding that directory to your path.
Unless it is already loaded into memory, Windows looks for DLL's that a program is requesting in every location listed in its PATH environment variable, and also in the directory the application is located within.

Resources