DamurDamuros
DamurDamuros

Reputation: 63

How to detect FTDI driver in system

I have an app that requires FTDI D2XX Direct Drivers drivers to be installed in system. Now I am creating an installation script using Inno Setup. How can I get an information whether FTDI drivers are installed in system (Windows). Is there any path or registry entry that could be checked to gain unambiguous information about that?

Upvotes: 4

Views: 3529

Answers (1)

TLama
TLama

Reputation: 76693

There were two ways I was thinking of when posting this answer, but I've decided to show my preferred one that time. For the sake of completeness, I'm including also a generic way to check whether a library is present in the system.

1. Try to call an FTDI driver library function

I think the best you can do is trying to call a function from the driver's library itself using delayed loading (delayload option). A good function to call is e.g. the FT_GetLibraryVersion function, by which you can get the library version, and which does not require opened device. In the following example code is shown just how to test whether the library is present in the system:

[Code]
type
  ULONG = Cardinal;
  FT_STATUS = ULONG;

function FT_GetLibraryVersion(out lpdwVersion: DWORD): FT_STATUS;
  external '[email protected] stdcall delayload';

function IsFTD2xxInstalled: Boolean;
var
  Version: DWORD;
begin
  Result := True;
  try
    FT_GetLibraryVersion(Version);
  except
    Result := False;
  end;
end;

It's just a probe if a library function can be called. Hence there is no result nor error checking.

2. Check the library presence in a generic way

Since the functions like LoadDLL and FreeDLL are deprecated (and there's no function to check if the library is already loaded), a generic way for checking whether a library is present in the system requires importing a few WinAPI functions. The following function LibraryExists checks whether a library of a given name is already loaded by Inno Setup and if not, it tries to load and unload it:

[Code]
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif

const
  ERROR_MOD_NOT_FOUND = 126;

type
  HINSTANCE = THandle;
  HMODULE = HINSTANCE;

function LoadLibrary(lpLibFileName: string): HMODULE;
  external 'LoadLibrary{#AW}@kernel32.dll stdcall';
function FreeLibrary(hLibModule: HMODULE): BOOL;
  external '[email protected] stdcall';
function GetModuleHandle(lpModuleName: string): HMODULE;
  external 'GetModuleHandle{#AW}@kernel32.dll stdcall';

procedure RaiseLastError(const Message: string; const Exclude: array of LongInt);
var
  I: Integer;
  LastError: LongInt;
begin
  LastError := DLLGetLastError;
  for I := 0 to GetArrayLength(Exclude) - 1 do
    if Exclude[I] = LastError then
      Exit;
  RaiseException(Format('%s' + #13#10 + '%d: %s', [Message, LastError,
    SysErrorMessage(LastError)]));
end;

function IsModuleLoaded(const Name: string): Boolean;
begin
  Result := GetModuleHandle(Name) <> 0;
  if not Result then
    RaiseLastError('GetModuleHandle call failed.', [ERROR_MOD_NOT_FOUND]);
end;

function LibraryExists(const Name: string): Boolean;
var
  Handle: HMODULE;
begin
  Result := IsModuleLoaded(Name);
  if not Result then
  begin
    Handle := LoadLibrary(Name);
    if Handle <> 0 then
    begin
      Result := True;
      FreeLibrary(Handle);
    end
    else
      RaiseLastError('LoadLibrary call failed.', [ERROR_MOD_NOT_FOUND]);
  end;
end;

And a possible usage for your case:

function IsFTD2xxInstalled: Boolean;
begin
  Result := LibraryExists('ftd2xx.dll');
end;

Upvotes: 4

Related Questions