0

After converting my Delphi Alexandria 11.3 program from 32 to 64 bits, I noticed that connecting to a (64bit) FireBird database required other DLLs.

In FireDac.Phys.IBWrapper this procedure gets called with

AVendorHome=''
AVendorLib=''
ALibNames=('ibclient64.dll', 'ibtogo64.dll')

procedure TIBLib.LoadBase(const AVendorHome, AVendorLib: String; AThreadSafe: Boolean
  {$IFNDEF FireDAC_IB_STATIC} ; const ALibNames: array of String {$ENDIF});
{$IFNDEF FireDAC_IB_STATIC}
var
  sDLLName: String;
  aDLLNames: array of String;
  i, j, n: Integer;
{$ENDIF}
begin
  FThreadSafe := AThreadSafe;
{$IFNDEF FireDAC_IB_STATIC}
  for j := 1 to 2 do begin
    sDLLName := AVendorHome;
    if sDLLName <> '' then begin
      sDLLName := FDNormPath(sDLLName);
      if j = 2 then
        sDLLName := FDNormPath(sDLLName + C_FD_DLLFolder);
    end
    else if j = 2 then
      Break;
    n := Length(aDLLNames);
    if AVendorLib <> '' then begin
      SetLength(aDLLNames, n + 1);
      aDLLNames[n] := sDLLName + AVendorLib;
    end
    else begin
      SetLength(aDLLNames, n + Length(ALibNames));
      for i := 0 to Length(ALibNames) - 1 do            <-- HERE
        aDLLNames[n + i] := sDLLName + ALibNames[i];
    end;
  end;
  inherited Load(aDLLNames, True);
{$ELSE}
  LoadEntries;
  GetLibraryInfo;
{$ENDIF}
end;

What this does is filling the initially empty aDLLNames with the two entries in ALibNames ('HERE') The inherited Load(aDLLNames, True) (the True meaning Required) then tries to load both DLLs with inherited LoadLibrary(ADLLNames, ARequired)

I copied the two files ibclient64.dll and interbase.msg from c:\Users\Public\Documents\Embarcadero\Interbase\redist\InterBase2020\win64\ to my program directory, but the above code also requires ibtogo64.dll, so this then fails on the ibtogo64.dll with 'Cannot load vendor library':

enter image description here

My code does not use IBToGo.

The array with the two names was set up in ('HERE'):

procedure TIBLib.LoadIB(const AVendorHome, AVendorLib: String;
  AEmbedded, AThreadSafe: Boolean);
{$IFNDEF FireDAC_IB_STATIC}
const
  C_GDS:      String = {$IFDEF MSWINDOWS} {$IFDEF FireDAC_64} 'ibclient64' {$ELSE} 'gds32' {$ENDIF} {$ENDIF}
                       {$IFDEF POSIX} 'libgds' {$ENDIF} + C_FD_DLLExt;
  C_TOGO:     String = {$IFDEF MSWINDOWS} {$IFDEF FireDAC_64} 'ibtogo64' {$ELSE} 'ibtogo' {$ENDIF} {$ENDIF}
                       {$IFDEF POSIX} 'libibtogo' {$ENDIF} + C_FD_DLLExt;
{$ENDIF}
begin
{$IFDEF ANDROID}
  FDSetEnv('INTERBASE', TPath.GetDocumentsPath + PathDelim + 'interbase');
{$ENDIF}
  if AEmbedded then
    // Force ToGo
    LoadBase(AVendorHome, AVendorLib, AThreadSafe
{$IFNDEF FireDAC_IB_STATIC},
      [C_TOGO]
{$ENDIF}
    )
  else
    LoadBase(AVendorHome, AVendorLib, AThreadSafe
{$IFNDEF FireDAC_IB_STATIC},
  {$IF DEFINED(MACOS) and not DEFINED(IOS)}
      // MacOSX: InterBase ToGo is preferred, and thus LIBIBTOGO has a higher priority
      [C_TOGO, C_GDS]
  {$ELSEIF DEFINED(IOS) or DEFINED(ANDROID)}
      // iOS, iOSSim, Android: no client/server, and thus no LIBGDS
      [C_TOGO]
  {$ELSE}
      // Windows: client/server is preferred over ToGo
      [C_GDS, C_TOGO]       <-- HERE
  {$ENDIF}
{$ENDIF}
  );
end;

Isn't that strange? If I have ibclient64.dll, why require ibtogo64.dll? Should I report this as a bug?

And the next question is what the best solution is (assuming that ibtogo64.dll is indeed not necessary). Distribute ibtogo64.dll with my app as well *, or hack the code to not include C_TOGO in the array?

That conditional define FireDAC_IB_STATIC is set in FireDac.Inc as:

{$IF DEFINED(IOS) and (DEFINED(CPUARM) or DEFINED(CPUARM64)) or DEFINED(ANDROID)}
  {$DEFINE FireDAC_IB_STATIC}            // Use IB driver static linking
  {$DEFINE FireDAC_IB_STATIC_IBBRAND}    // Use IbTogo static linking library
{$ENDIF}

Using that define would seem to 'solve' the issue, were it not that the definition of TIBLib.LoadBase changes. I'd probably open a can of worms trying to use that.

* Actually , there are 3 DLLs in c:\Users\Public\Documents\Embarcadero\Interbase\redist\InterBase2020\win64_togo\: ibtogo64.dll, ibxml64.dll and ib_util64.dll

Jan Doggen
  • 8,799
  • 13
  • 70
  • 144
  • 1
    LoadLibrary will only try the second entry when the first fails. You should check why it fails. – Uwe Raabe Jun 01 '23 at 13:50
  • @Uwe Ah yes, you are correct, the ibclient64.dll already fails. Strange, it's in the executable directory and the Windows call from System.SysUtils.SafeLoadLibrary is LoadLibrary(Pchar(Filename)) with Filename = 'ibclient64.dll' – Jan Doggen Jun 01 '23 at 15:16
  • If I move ibclient64.dll to either C;\Windows\System32 or C;\Windows\SysWow64 it still fails. I don't have to register the DLL, do I? – Jan Doggen Jun 01 '23 at 15:23
  • Did you install vcredist_x64.exe? – Uwe Raabe Jun 01 '23 at 15:31
  • What does `GetLastError()` return when `LoadLibrary()` fails on `ibclient64.dll`? – Remy Lebeau Jun 01 '23 at 17:00
  • @UweRaabe I could not see if that was on my system, so I installed the latest X64 version from https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170 This made no difference. – Jan Doggen Jun 02 '23 at 07:01
  • @RemyLebeau GetLastError returns 126 directly after the LoadLibrary call (that's with ibclient64.dll in the directory of the executable). If I look that up it is ERROR_MOD_NOT_FOUND The specified module could not be found. Now trying to get dependency walker installed... – Jan Doggen Jun 02 '23 at 07:01
  • Dependency Walker (from [here](https://stackoverflow.com/a/56275682/512728)) finds a lot of errors. The first one is a missing dependency on MSVCR120.DLL, which is in the Visual C++ Redistributable Packages for Visual Studio **2013**, so I installed that one as well. There were a lot of missing dependencies for API_MS_WIN_... and EXT_MS_WIN_.... DLLS but these are [false alarms](https://stackoverflow.com/a/36244483/512728) The reported missing HVSIFILETRUST.DLL, IESHIMS.DLL and PDMUTILITIES.DLL may also be false alarms – Jan Doggen Jun 02 '23 at 07:50
  • BUT! After installing the Visual C++ Redistributable Packages for Visual Studio **2013** the LoadLibrary call now works, hurrah! – Jan Doggen Jun 02 '23 at 07:51
  • Next question: should I leave this question open or delete it? This comment thread can be useful to others, but ion the question body I was initially looking in the wrong direction (overlooking that the error was already with the first DLL). – Jan Doggen Jun 02 '23 at 07:54
  • 1
    @JanDoggen that is up to you. I would suggest [posting your own answer](https://stackoverflow.com/help/self-answer) detailing the solution you discovered. – Remy Lebeau Jun 02 '23 at 15:02

0 Answers0