unit BDEreset;

// Place this unit at the top of your USES clause
// to ensure that BDE is configured for Vista.
//
// by Randy Beck
//    4-June-2008
//   modified
//    9-June-2008
//   modified
//    2-July-2008
//   http://www.randybeck.com
//   email:  rb@randybeck.com
//
// note: this unit must be placed before
//       other units that use the BDE.

// It runs function CheckNetDir on startup to check the location of
// NET DIR, and move it elsewhere to accommodate Microsoft Vista.
//
// Previous versions moved it to the temporary directory, and then
// to the common AppData folder.  Now it uses the BDE folder itself.
//
// You can modify the code to send it to another folder if you like.
// You may also have it quit the program if there is no BDE installed.
// Details within the source.


interface

uses
  SysUtils, WinTypes, BDE, Registry;

implementation

var  TempDir: string = '?';
     AppDataDir: string = '?';
     BDEdir: string = '?';

function  TempDirectory : string;
var  TempFileName: array[0..255] of char;
begin
  If TempDir = '?' then
  begin
    GetTempPath(255, @TempFileName);
    TempDir := StrPas(@TempFileName);
    While (TempDir <> '') and (TempDir[length(TempDir)] <> '\') do
      SetLength(TempDir, pred(length(TempDir)));
    If (length(TempDir) > 0) and (TempDir[length(TempDir)] <> '\') then
      TempDir := TempDir + '\';
  end;
  Result := TempDir;
end;


function  GetRegistryKeyValue(ARoot: HKEY; AKey,AName: string) : string;
var  Reg: TRegistry;
begin
  Result := '';
  try
    Reg := TRegistry.Create;
    Reg.RootKey := ARoot;
    If Reg.OpenKey(AKey, FALSE) then
      Result := Reg.ReadString(AName);
  finally
    Reg.Free;
  end;
end;


function  CommonAppDataDirectory : string;
// no longer used by this unit, but it remains in case anyone prefers it
begin
  If AppDataDir = '?' then
  begin
    AppDataDir := GetRegistryKeyValue(HKEY_LOCAL_MACHINE,
                                   'SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders',
                                   'Common AppData');
    If (length(AppDataDir) > 0) and (AppDataDir[length(AppDataDir)] <> '\') then
      AppDataDir := AppDataDir + '\';
  end;
  Result := AppDataDir;
end;


function  BDEdirectory : string;
var  S: string;
begin
  If BDEdir = '?' then
  begin
    S := GetRegistryKeyValue(HKEY_LOCAL_MACHINE,
                             'Software\Borland\Database Engine',
                             'DLLPATH');
    BDEdir := ExtractFilePath(FileSearch('IDAPI32.DLL', S));
    If (length(BDEdir) > 0) and (BDEdir[length(BDEdir)] <> '\') then
      BDEdir := BDEdir + '\';
  end;
  Result := BDEdir;
end;


procedure CheckNetDir;
var  A,S,TheDir: string;
     hCur: hDBICur;
     Config: CFGDesc;
begin

(*
  Note:  This function had previously moved NET DIR to the common
         AppData folder.  But that requires the user have permission
         to create a folder.  So, I'm trying the BDE folder instead,
         while keeping this section marked off in case anyone prefers
         to use it anyway.

  // find common AppData directory
  TheDir := CommonAppDataDirectory + 'BDE';
 *)

  // find BDE directory
  TheDir := BDEdirectory;
  If TheDir = '' then
  begin
    // BDE not installed:
    // If you wish, you could display a message here and then halt the program.
  end;

  If (length(TheDir) <= 2) or
     (TheDir[2] <> ':') or
     (TheDir = '')
  then
    Exit;  // BDE directory not valid; so don't do anything

  If DbiInit(nil) = DBIERR_NONE then
  begin
    hCur := nil;
    If DbiOpenCfgInfoList(nil, dbiREADWRITE, cfgPersistent, '\DRIVERS\PARADOX\INIT', hCur) = DBIERR_NONE then
    begin
      If DbiSetToBegin(hCur) = DBIERR_NONE then
      begin
        While DbiGetNextRecord(hCur, dbiWRITELOCK, @Config, nil) = DBIERR_NONE do
        begin
          If StrIComp(Config.szNodeName, 'NET DIR') = 0 then
          begin
            // find the current value of "NET DIR"
            S := Config.szValue;
            If FileExists(TempDirectory + 'resetbde.ini') then
            begin
              // presence of this file forces reset
              S := '';
              SysUtils.DeleteFile(TempDirectory + 'resetbde.ini');
            end;
            If (length(S) <= 3) or not DirectoryExists(S) then
            begin
              // current "NET DIR" no good; so set a new one
              If (not DirectoryExists(TheDir)) and (not CreateDir(TheDir)) then
                Exit;
              StrPCopy(Config.szValue, TheDir);
              DbiModifyRecord(hCur, @Config, TRUE);
            end;
          end;
        end;
      end;
    end;
    DbiExit();
  end;
end;

initialization
  CheckNetDir;
end.

