Change location of libeay32.dll and ssleay32.dll to subfolder [duplicate] - delphi

I made an application that uses the openssl dlls (libeay32.dll and ssleay32.dll).
It is indy using them, I don't call the dlls directly.
The simplest workaround i found to avoid an installer (i just delpoy an exe and i am ok with this approach) is to:
put the dlls as resources of the exe
on program start I extract them in the exe folder
the exe uses them
This is perfect but I would like to improve the approach by extracting the dlls in a temp folder and not on the exe folder (that in many cases is the desktop).
The problem is that I don't know how to force the application to use the dlls in the temp folder, because now the behaviour is:
if dlls are not in current directory try to search in the directories defined in the system path.
Who knows a solution to force indy to use the dlls in my temp path? (like "temporarly registering the dlls")

If you are using an up-to-date version of Indy 10, the IdSSLOpenSSLHeaders unit has a public IdOpenSSLSetLibPath() function to tell Indy which custom folder to look in for the OpenSSL DLLs:
procedure IdOpenSSLSetLibPath(const APath: String);

Load the DLLs yourself with LoadLibrary as soon as you have written them to the temp folder.
This will make Indy's LoadLibrary use your DLLs when they need them:
If lpFileName does not include a path and there is more than one
loaded module with the same base name and extension, the function
returns a handle to the module that was loaded first.

You can use SetDllDirectory to manipulate the DLL search order.

Related

How to force a dll to load from current directory

I have copied a newer version of GdiPlus.dll to my projects directory.
However windows always loads it form
"C:\WINDOWS\WinSxS\x86_Microsoft.Windows.GdiPlus_6595b64144ccf1df_1.0.6002.23084_x-ww_f3f35550\GdiPlus.dll"
I'm on XP.
To exert complete control over DLL loading, pass the full path of the DLL to LoadLibrary.
This is viable if you use runtime linking. For load time linking you are reliant on the DLL search order. The first thing searched is the directory from where the exe loaded. That said, it is plausible that for an OS component like GDI+ it is plausible that the system will use the SxS DLL no matter what.
Your question title says "current directory" but you never want to rely on the value of the current directory when linking DLLs. The current directory's value is unpredictable.
Finally, GDI+ is a system component and I think it doubtful that providing your own GDI+ DLL is a wise move. It is quite possibly illegal too since redistribution of GDI+ is not permitted. Perhaps you are choosing the wrong solution to your problem.
you can use this declaration to set the directory of dll to a defined path.
function SetDllDirectory(lpPathName:PWideChar): Bool; stdcall; external 'kernel32.dll' name 'SetDllDirectoryW';
remember to change the path after working with your dll.

DELPHI Compiler Path settings after INDY 10 upgrade

I already asked how to upgrade to the latest Indy TCP TP components version ( GET INDY COMPONENTS ) and Installed Indy 10 with DELPHI XE 2 now. For all the Indy projects I defined an outfolder in the project options section of DELPHI XE2, here I found later all the the .bpl files and all the -DCU#s files I need now in order to compile my application using the new INDY components to add this output folder as a library search path in these projects.
I found at my XE2 installation a path/folder with *.dcu files for x32, x64, release and debug mode (C:\Program Files (x86)\Embarcadero\RAD Studio\9.0\lib\win64\release).
Do I need now all the INDY *.dcu I have created also in these different flavours compiled, how to set the path for all project to use the new *.dcu from my folder ?
Should I copy all my dcu's to these many sub folders ??
You should not replace the pre-installed Indy files with the updated compiled files (in case you need the originals in the future, such as for DataSnap projects). Install the newer Indy into its own separate folder, then update the projects search paths to refer to that installation's output folder(s) instread of the pre-installed folder(s).
You should not overwrite the .dcu files that are part of the Delphi installation. What's more, I would not recommend that you do anything with the .dcu files that you used to build these .bpl files.
What you should do is to include the Indy source files, the .pas files, in your project. Personally I prefer to avoid using a search path to achieve that and instead simply add all the necessary .pas files to the project. But you may prefer to use the search path option.
But the main point is that since this project is supplied in source form it is best to compile the source yourself, as part of your project. That makes it much easier for you, whilst debugging, to step through the Indy code. There's no need to have separate DCU files for release and debug. It makes the build process simpler, only one thing to build. It makes it easier if your source code targets multiple Delphi compiler versions.

Renaming DLL in Delphi

Suppose I've got a large ActiveX library written in Delphi, let's call it Lib1.dll. It contains multiple interfaces. The task is to rename the library to Lib2.dll in such a way, that another application can call both methods from Lib1 and Lib2 at the same time.
I thought to do it in next way:
Rename Delphi project to Lib2 (that will rename the library).
Replace *Lib1_TLB.pas* file with *Lib2_TLB.pas* with the same content, but with new GUIDs of interfaces and coclasses.
Paste new GUIDs to Lib2.ridl.
Generate new Lib2.tlb file from that ridl and that should be ok.
But it isn't. I'm getting Delphi error "Couldn't find Lib1.ridl file". Okay, rename both ridl and tlb.pas back to Lib1, compile&build ok, but registering ActiveX server crashes the IDE.
Please suggest me a way to rename the lib or how to make my current progress work.
I assume you are using a recent version of Delphi using .ridl files for COM interfaces so keep in mind that it is the central unit for dealing with COM. You may start with copying and renaming the ridl file from Lib1.ridl to Lib2.ridl. Then inside Lib2.ridl, not _TLB.pas (which is recreated automatically) regenerate the library's GUID and those of coclasses. Interfaces may remain unchanged. After that you should be able to generate tlb and refresh _TLB.pas and finally build and register the new library.

External exception is thrown in function when using DLL's from not application folder

I have a problem which I do not understand. I am using a DLL in my application. This DLL requires other DLL's and I have all of them. If I put the libraries in my appliction folder everything works fine.
However, having a bunch of DLLs in application folder looks quite ugly so I wanted to move them to application\lib subfolder.
After this change now I am getting External Exception when I try to use some of its functions.
I've only changed one line of code:
The original code
DLLHandle := LoadLibrary(Pchar(ExtractFilePath(ParamStr(0)) + 'External.dll'))
The code after change
DLLHandle := LoadLibrary(Pchar(ExtractFilePath(ParamStr(0)) + 'lib\External.dll'))
In both cases DLLHandle have a handle after loading the library. I am also not getting any error after calling GetProcAddress( DLLHandle, '_SomeFunction#8')
No exceptions, and return value of GetLastError is always 0.
Do you have any idea what could be wrong?
Thanks.
Life is far easier if you keep the DLLs in the same folder as the executable. That's the first folder searched when libraries are loaded. To move all the DLLs into a sub folder of the executable directory requires cooperation from all DLLs.
Most likely you have secondary DLL dependencies that are not cooperating. So exe loads A fine, but then A fails to load B. You can debug this further with Dependency Walker running in profile mode. It's quite possible that a secondary DLL is being loaded with implicit linking and that this throws and exception. Whatever the cause, Depenency Walker will lead you to the problem.
Whilst you can modify the PATH variable this is generally not advisable. If you do choose to go down this route then don't modify system wide, just modify the executable process environment at runtime before the first LoadLibrary. This is tenable so long as all your DLL linking is explicit using GetProcAddress.
All accepted wisdom recommends that you put your DLLs in the same folder as your executable. I would echo this recommendation. If you did this then you would be able to use implicit linking which would greatly simplify your code.
Yet another option may be to abandon DLLs and link everything straight into your executable. Unless you have a plugin type architecture, a single big exe is by far the simplest approach.
The other DLL's that need to be loaded must be on the system path for Windows to find them. Your application can find the External.dll as you explicitly define the path. Try adding the lib folder to your system path.

How to delete openssl dlls before closing the application

I made a simple tool (LogAndMailApplication) that sends logs to my gmail account, for this I used the Indy component TIdSSLIOHandlerSocketOpenSSL. To work it needs ssleay32.dll and libeay32.dll.
So at application start I extract from exe resources the 2 dll and I copy them to the application folder.
All the indy compoennts are in a datamodule I destroy before closing the application.
After destroying the datamodule I try to delete the dlls but I cannot.
I just used DeleteFile, but that worked great for all the other files I delete on application exit (incluging an ini file).
I tried to make a simple exe that just deletes the 2 dll and it works. So the problem is that the 2 dll are somehow locked until the LogAndMailApplication is not closed, how to solve the problem?
Indy dynamically loads the OpenSSL DLLs at runtime, and then by default does not unload them until app shutdown. If you want to unload the DLLs sooner, you need to call IdSSLOpenSSL.UnLoadOpenSSLLibrary() directly. This will unload the DLLs and clean up all references and allocated objects related to them.
You can do the following: at the very end of your code use
FreeLibrary(GetModuleHandle('ssleay32.dll'));
FreeLibrary(GetModuleHandle('libeay32.dll'));
DeleteFile(PathToDLL1);
DeleteFile(PathToDLL2);
This should work.
Alternatively you can get rid of OpenSSL and use SSL components from our SecureBlackbox.
Alternatively you can delete the DLL's in the finalization section of the data module unit...

Resources