(*****************************************************************************)
(* MODULE: BSESESS                                                           *)
(* RIGHTS: Reggatta Systems, Inc. - COPYRIGHT 1995 - 2000                    *)
(* DESCR.: This module contains the Database Session classes.                *)
(*                                                                           *)
(* TBaseSession:       This is the base class for the sesson class.          *)
(*                     All Session related functions are handled by this     *)
(*                     class.                                                *)
(*                                                                           *)
(*****************************************************************************)
Unit BseSess;
{$I BSE.INC}
{$I BAPI.INC}
Interface
Uses
  Windows,
  BDE,
  Registry,

  BseBapi,
  BseTypes,
  BseColl,
  BseTable;

Type
  TBaseSession =
  Class( TBapiListItem )
    Protected
      FTitanEnv          : TTitanEnvInfo;
      FIgnoreAnsiOEM     : Boolean;
      FIgnoreOEMAnsi     : Boolean;
      FLocale            : Pointer;
      FLockWait          : Integer;

      Procedure   SetLockRetry( iWait : SmallInt ); Virtual;
      Function    GetName : PChar;
      Procedure   SetName( P : PChar );
    Public
      FNoDBNameBackSlash : Boolean;
      Databases          : TTitanCollection;
      CfgRecords         : TTitanCollection;
      FLockRetry         : SmallInt;
      FName              : DBINAME;
      NetDir             : DBIPATH;
      PrivDir            : DBIPATH;
      SystemTables       : TTitanCollection;
      FConfigMode        : LongInt;

      Property LockRetry : SmallInt
        Read  FLockRetry
        Write SetLockRetry;

      Property Name : PChar
        Read  GetName
        Write SetName;

      Property TitanEnvironment : TTitanEnvInfo
        Read  FTitanEnv;  

      Constructor CreateAsSes( P : TObject; Container : TTitanCollection; PName, PNetDir : PChar );
         Override;

      Destructor  Destroy; Override;

      Procedure   SetLocaleInfo;
      Procedure   SetTitanEnv;
        Virtual; Abstract;

      Function    IsBde : Boolean; Virtual;

      Procedure   SetPrivateDir( pszDir : PChar );
      Procedure   SetIntlFlags( OemToAnsi, AnsiToOEM : Boolean );

      Procedure   GetInfo( var s : SesInfo ); Virtual;

      Function    GetDriverDescText : PChar; Virtual;
      Procedure   SetDBType( BeHonest : Boolean; pDbDesc : pDBDesc ); Virtual;

      Procedure   GetDbDescInternal (                       { Get a description of a logical db }
                    pszName       : PChar;                  { Name of logical database }
                    pdbDesc       : pDBDesc;                { Database description }
                    BeHonest      : Boolean
                  ); Virtual;

      Procedure   GetDatabaseDesc (                         { Get a description of a logical db }
                    pszName       : PChar;                  { Name of logical database }
                    pdbDesc       : pDBDesc                 { Database description }
                  ); Virtual;

      Procedure   OpenTableTypesList (                      { Get a list of table types }
                    pszDriverType : PChar;                  { Driver type }
                    var hCur      : hDBICur                 { Returned cursor }
                  ); Virtual;

      Procedure   GetTableTypeDesc (                        { Get Table capabilities }
                    pszDriverType : PChar;                  { Driver type }
                    pszTableType  : PChar;                  { Table type }
                    var tblType   : TBLType                 { Table Capabilities }
                  ); Virtual;

      Procedure   OpenFieldTypesList (                      { Get a list of field types }
                    pszDriverType : PChar;                  { Driver type }
                    pszTblType    : PChar;                  { Table type (Optional) }
                    var hCur      : hDBICur                 { Returned cursor }
                  ); Virtual;

      Procedure   GetFieldTypeDesc (                        { Get Table capabilities }
                    pszDriverType : PChar;                  { Driver type }
                    pszTableType  : PChar;                  { Table type }
                    pszFieldType  : PChar;                  { Field type }
                    var fldType   : FLDType                 { Field Capabilities }
                  ); Virtual;

      Procedure   OpenIndexTypesList (                      { Get a list of index types }
                    pszDriverType : PChar;                  { Driver type }
                    var hCur      : hDBICur                 { Returned cursor }
                  ); Virtual;

      Procedure   OpenLdList (                              { Get a list of Lang Drivers }
                    var hCur : hDBICur                      { Returned cursor }
                  ); Virtual;

      Procedure   OpenDatabaseInternal (                    { Open a database }
                    pdbDesc       : pDBDesc;                { Database description }
                    eOpenMode     : DBIOpenMode;            { Open type }
                    eShareMode    : DBIShareMode;           { Share type }
                    pszPassword   : PChar;                  { Password }
                    iOptFlds      : Word;                   { Number of optional Params }
                    pOptFldDesc   : pFLDDesc;               { Optional Field Descriptors }
                    pOptParams    : Pointer;                { Optional Params }
                    var hDb       : hDBIDb                  { Returned database handle }
                  ); Virtual;

      Procedure   OpenDatabase (                            { Open a database }
                    pszDbName     : PChar;                  { Database name }
                    pszDbType     : PChar;                  { Database type (NULL: Universal) }
                    eOpenMode     : DBIOpenMode;            { Open type }
                    eShareMode    : DBIShareMode;           { Share type }
                    pszPassword   : PChar;                  { Password }
                    iOptFlds      : Word;                   { Number of optional Params }
                    pOptFldDesc   : pFLDDesc;               { Optional Field Descriptors }
                    pOptParams    : Pointer;                { Optional Params }
                    var hDb       : hDBIDb                  { Returnd database handle }
                  ); Virtual;

      Procedure   OpenDriverList (                          { Get a list of driver names }
                    var   hCur          : hDBICur           { Returned cursor }
                  ); Virtual;

      Procedure   GetDriverDesc (                           { Get description for a given type }
                    pszDriverType : PChar;                  { Symbolic name for driver type }
                    var  drvType  : DRVType                 { Driver type description }
                  ); Virtual;

      Procedure   OpenDatabaseList ( var hCur : hDBICur ); Virtual;

      Procedure   CloseDatabase( var hDb : hDBIDb ); Virtual;

      Procedure   UseIdleTime; Virtual;                     { Use Idle time }

      Procedure   GetLdObj (                                { Get language driver }
                    hCursor       : hDBICur;                { Cursor handle }
                    var   pLdObj  : Pointer                 { Returned language driver object }
                  ); Virtual;

      Procedure   GetLdName (                               { Get language driver name from table }
                    pszDriver     : PChar;                  { Driver name }
                    pObjName      : PChar;                  { Name of object, i.e. table name }
                    pLdName       : PChar                   { Returned language driver name }
                  ); Virtual;

      Procedure   GetTableOpenCount (                       {  Get local cursor count }
                    hDb            : hDBIDb;                { Database }
                    pszTableName   : PChar;                 { Table name }
                    pszDriverType  : PChar;                 { Driver type }
                    var iOpenCount : Word                   { returned number of cursors }
                  ); Virtual;

      Procedure   AddPassword (                             { Add a password to current session }
                    pszPassword   : PChar                   { Password }
                  ); Virtual;

      Procedure   DropPassword (                            { Add a password to current session }
                    pszPassword   : PChar                   { Password }
                  ); Virtual;

      Procedure   TranslateRecordStructure (                { Translate a record }
                    pszSrcDriverType : PChar;               { Source driver type }
                    iFlds         : Word;                   { Number of fields }
                    pfldsSrc      : pFLDDesc;               { Array of source fields: logical or physical types }
                    pszDstDriverType : PChar;               { Destination driver type }
                    pszLangDriver : PChar;                  { Language driver for destination }
                    pfldsDst      : pFLDDesc                { Array of dest. fields returned }
                    ;
                    bCreatable    : Bool                    { TRUE -> map to creatable fields only. }
                  ); Virtual; 

      Procedure   OpenFieldXlt (                            { Open translation object }
                    pszSrcTblType : PChar;                  { NULL for Logical }
                    pszSrcLangDrv : PChar;                  { NULL if no tranliteration }
                    pfldSrc       : pFLDDesc;               { source field descriptor }
                    pszDestTblType : PChar;                 { NULL for Logical }
                    pszDstLangDrv : PChar;                  { NULL if no tranliteration }
                    pfldDest      : pFLDDesc;               { Source field descriptor }
                    var bDataLoss : Bool;                   { Set to TRUE, for data loss }
                    var hXlt      : hDBIXlt                 { Returned translate handle }
                  ); Virtual;

      Procedure   TranslateField (                          { Translate a field }
                    hXlt          : hDBIXlt;                { Translation handle }
                    pSrc          : Pointer;
                    pDest         : Pointer                 { Destination field }
                  ); Virtual;

      Procedure   CloseFieldXlt (                           { Close translation object }
                    hXlt          : hDBIXlt                 { Translation handle }
                  ); Virtual;

      Procedure   GetProp (                                 { Get property }
                    iProp         : Longint;                { Property to retrieve }
                    PropValue     : Pointer;                { == NULL, validate iProp for getting }
                    iMaxLen       : Word;                   { Length of buffer pPropValue }
                    var   iLen    : Word                    { Returns required length }
                  ); Override;

      Procedure   SetProp (                                 { Get property }
                    iProp         : Longint;                { Property to retrieve }
                    PropValue     : Longint                 { == NULL, validate iProp for getting }
                  ); Override;

      Procedure   OpenUserList (                            { Get a list of users loggedin }
                    var hUsers : hDBICur                    { Returned cursor on user list }
                  ); Virtual;

      Procedure   NativeToAnsi (                            { Convert from native to Ansi }
                    LdObj         : Pointer;                { Language driver }
                    pAnsiStr      : PChar;                  { Destination buffer (opt) }
                    pNativeStr    : PChar;                  { Source buffer }
                    iLen          : LongInt;                { Length of buffer (opt) }
                    var bDataLoss : Bool                    { Returns TRUE if conversion will loose data (opt) }
                  ); Virtual;

      Procedure   AnsiToNative (                            { Convert from Ansi to native }
                    LdObj         : Pointer;                { Language driver }
                    pNativeStr    : PChar;                  { Destination buffer (opt) }
                    pAnsiStr      : PChar;                  { Source buffer }
                    iLen          : LongInt;                { Length of buffer (opt) }
                    var bDataLoss : Bool                    { Returns TRUE if conversion will loose data (opt) }
                  ); Virtual;

      Procedure   RegisterCallBack (                        { Register a call back fn }
                    hCursor       : hDBICur;                { Cursor (Optional) }
                    ecbType       : CBType;                 { Type of call back }
                    iClientData   : Longint;                { Pass-thru client data }
                    iCbBufLen     : Word;                   { Callback buffer len }
                    CbBuf         : Pointer;                { Pointer to callback buffer }
                    pfCb          : pfDBICallBack           { Call back fn being registered }
                  ); Virtual;

      Procedure   GetCallBack (                             { Register a call back fn }
                    hCursor       : hDBICur;                { Cursor (Optional) }
                    ecbType       : CBType;                 { Type of call back }
                    piClientData  : PLongint;               { Pass-thru client data }
                    piCbBufLen    : PWord;                  { Callback buffer len }
                    ppCbBuf       : Pointer;                { Pointer to callback buffer }
                    var pfCb      : pfDBICallBack           { Call back fn being registered }
                  ); Virtual;

      Procedure   GetNumberFormat (                         { Get current number format }
                    var   fmtNumber     : FMTNumber
                  ); Virtual;

      Procedure   SetNumberFormat (                         { Set current number format }
                    var   fmtNumber     : FMTNumber
                  ); Virtual;

      Procedure   GetIndexTypeDesc (                        { Get Table capabilities }
                    pszDriverType : PChar;                  { Driver type }
                    pszIndexType  : PChar;                  { Index type }
                    var idxType   : idxType                 { Index Capabilities }
                  ); Virtual;

      Procedure   CheckRefresh; Virtual;

      Procedure   GetSysVersion( var s : SysVersion ); Virtual;

      Procedure   GetSysConfig( var s : SysConfig ); Virtual;

      Procedure   GetClientInfo( var s : clientInfo ); Virtual;

      Procedure   LoadDriver ( pszDriverType : PChar ); Virtual;

      Procedure   GetSysInfo( var s : SysInfo ); Virtual;

      Procedure   GetSesInfo( var s : SesInfo ); Virtual;

      Procedure   GetNetUserName (                          { Get network username }
                    pszNetUserName : PChar                  { Returns username }
                  ); Virtual;

      Procedure   AddAlias (                                { Add a new alias }
                    hCfg          : hDBICfg;                { NULL }
                    pszAliasName  : PChar;                  { Alias name }
                    pszDriverType : PChar;                  { Driver type for alias }
                    pszParams     : PChar;                  { Optional parameters }
                    bPersist      : Bool                    { Persistent or session relative }
                  ); Virtual;

      Procedure   DeleteAlias (                             { Delete an alias }
                    hCfg          : hDBICfg;                { NULL }
                    pszAliasName  : PChar                   { Alias name }
                  ); Virtual;

      Procedure   WriteTitanAliasParams( Reg : TRegistry; pszParams : PChar ); Virtual;

      Procedure   AddTitanAlias (                           { Add a new alias }
                    pszAliasName  : PChar;                  { Alias name }
                    pszParams     : PChar                   { Optional parameters }
                  ); Virtual;

      Procedure   DeleteTitanAlias (                        { Delete an alias }
                    pszAliasName  : PChar                   { Alias name }
                  ); Virtual;

      Procedure   OpenCfgInfoList (                         { Open a cursor on "Config" }
                    hCfg          : hDBICfg;                { NULL }
                    eOpenMode     : DBIOpenMode;            { ReadWrite or readonly }
                    eConfigMode   : CFGMode;                { Config mode }
                    pszCfgPath    : PChar;                  { Path }
                    var   hCur    : hDBICur                 { Returned cursor }
                  );

      Procedure   LoadCfgInfoList( hCur : hDBICur ); Virtual;

      Procedure   OpenConfigFile (                          { Open/Create configuration }
                    pszDirPath    : PChar;                  { Directory }
                    bCreate       : Bool;                   { TRUE to create/overwrite }
                    var hCfg      : hDBICfg                 { Handle to config }
                  ); Virtual;

      Procedure   CloseConfigFile (                         { Close the config file }
                    var hCfg      : hDBICfg;                { Handle }
                    bSave         : Bool;                   { To save the changes }
                    bDefault      : Bool                    { To make this file the default }
					;
                    bSaveAs16     : Bool                    { To save as a 16-bit config file }
                  ); Virtual;

      Procedure   CfgSave (                                 { Save current configuration }
                    hCfg          : hDBICfg;                { Config Handle/NULL }
                    pszNewFile    : PChar                   { (Optional): Save as this file }
					;
                    bSaveAs16     : Bool                    { To save as a 16-bit config file }
                  ); Virtual;

      Procedure   CfgBuildPath (                            { Build a path for accessing config. }
                    hCfg          : hDBICfg;                { Config Handle/NULL }
                    pszCategory   : PChar;                  { NULL for root }
                    pszGroup      : PChar;                  { NULL for no group }
                    pszSection    : PChar;                  { NULL fro no section }
                    pszCfgPath    : PChar                   { Returned path }
                  ); Virtual;

      Procedure   CfgPosition (                             { Position the config path }
                    hCfg          : hDBICfg;                { Config Handle/NULL }
                    pszCfgPath    : PChar                   { Path }
                  ); Virtual;

      Procedure   CfgGetNextNode (                          { Get next defined node }
                    hCfg          : hDBICfg;                { Config Handle/NULL }
                    pszNodeName   : PChar                   { Node name (Returned) }
                  ); Virtual;

      Procedure   CfgGetRecord (                            { Get a record }
                    hCfg          : hDBICfg;                { Config Handle/NULL }
                    pszCfgPath    : PChar;                  { Path }
                    var iFields   : Word;                   { Returned nbr of fields }
                    pfldDesc      : pFLDDesc;               { Field descriptors }
                    pRec          : Pointer                 { Field values }
                  ); Virtual;

      Procedure   CfgAddRecord (                            { Add a record }
                    hCfg          : hDBICfg;                { Config Handle/NULL }
                    pszCfgPath    : PChar;                  { Path }
                    iFields       : Word;                   { No of fields }
                    pfldDesc      : pFLDDesc;               { Field descriptors }
                    pRec          : Pointer                 { Data values }
                  ); Virtual;

      Procedure   CfgModifyRecord (                         { Modify a record }
                    hCfg          : hDBICfg;                { Config Handle/NULL }
                    pszCfgPath    : PChar;                  { Path }
                    iFields       : Word;                   { Nbr of fields }
                    pfldDesc      : pFLDDesc;               { Field descriptors }
                    pRec          : Pointer                 { Data values }
                  ); Virtual;

      Procedure   CfgDropRecord (                           { Delete a record }
                    hCfg          : hDBICfg;                { Config Handle/NULL }
                    pszCfgPath    : PChar                   { Path }
                  ); Virtual;

      Procedure   CfgTranslate (                            { Translate configuration string }
                    hCfg          : hDBICfg;                { Config Handle/NULL }
                    pszConfigPath : PChar;                  { configuration path }
                    pszTrans      : PChar;                  { translated path }
                    iFields       : Word;                   { number of fields, 0 if path only }
                    pfldDesc      : pFLDDesc;               { field descriptors, NULL if path only }
                    pRec          : Pointer                 { record buffer, NULL if path only }
                  ); Virtual;

      Procedure   CfgGetHelp (                              { Get help message }
                    hCfg          : hDBICfg;                { Config Handle/NULL }
                    pszConfigPath : PChar;                  { configuration path }
                    pszFldName    : PChar;                  { field name  ( optional ) }
                    pszHelpString : PChar                   { help string ( returned ) }
                  ); Virtual;

      Procedure   CfgMerge (                                { Merge config files }
                    hCfgDest      : hDBICfg;                { Destination Cfg handle/ NULL }
                    hCfgSrc       : hDBICfg;                { Source Cfg handle/ NULL }
                    pszSrcPath    : PChar                   { Source Path / NULL }
                  ); Virtual;
      Procedure   ImportODBC(                               { Import current ODBC drivers and data sources }
                    hCfg          : hDBICfg;                { NULL }
                    bPersist      : Bool                    { Persistent or session relative }
                  ); Virtual;

      Procedure   AddDriver(                                { Add a new driver }
                    hCfg          : hDBICfg;                { NULL }
                    pszDriverName : PChar;                  { Driver name }
                    pszParams     : PChar;                  { Optional parameters }
                    bPersist      : Bool                    { Persistent or session relative }
                  ); Virtual;

      Procedure   DeleteDriver(                             { Delete a driver }
                    hCfg          : hDBICfg;                { NULL }
                    pszDriverName : PChar;                  { Driver name }
                    bSave         : Bool                    { Save config file }
                  ); Virtual;
  end;
  
  TBaseSessionClass = Class of TBaseSession;



Implementation
Uses
  SysUtils,
  Classes,
  BseRgtry,

  BseUtils,
  BseConst,
  BseCache,
  BseDbase,
  BseErrs;


Constructor TBaseSession.CreateAsSes( P : TObject; Container : TTitanCollection;
              PName, PNetDir : PChar );
begin
  Inherited Create( P, Container );

  Databases      := TTitanCollection.Create;
  CfgRecords     := TTitanCollection.Create;
  SystemTables   := TTitanCollection.Create;

  Name := PName;

  If Assigned( PNetDir ) then
  begin
    StrLCopy( @NetDir,  PNetDir, SizeOf( NetDir  ) - 1 );
    StrLCopy( @PrivDir, PNetDir, SizeOf( PrivDir ) - 1 );
  end;

  SetLocaleInfo;
  SetTitanEnv;
end;


Destructor TBaseSession.Destroy;
begin
  Databases.Free;
  CfgRecords.Free;
  SystemTables.Free;
  Inherited Destroy;
end;


Procedure TBaseSession.SetLockRetry( iWait : SmallInt );
begin
  FLockRetry := iWait;
end;


Function TBaseSession.GetName : PChar;
begin
  Result := @FName;
end;


Procedure TBaseSession.SetName( P : PChar );
begin
  if ( P <> NIL ) then
    StrLCopy( @FName, P, DBIMAXNAMELEN );
end;


Procedure TBaseSession.SetLocaleInfo;
begin
end;




Function TBaseSession.IsBde : Boolean;
begin
  Result := FALSE;
end;


Procedure TBaseSession.SetPrivateDir( pszDir : PChar );
begin
  StrLCopy( @PrivDir, pszDir, SizeOf( PrivDir ) - 1 );
end;


Procedure TBaseSession.SetIntlFlags( OemToAnsi, AnsiToOEM : Boolean );
begin
  FIgnoreOEMAnsi := OEMToAnsi;
  FIgnoreAnsiOEM := AnsiToOEM;
end;


Procedure TBaseSession.GetInfo( var s : SesInfo );
var
  i : Integer;
  P : TBaseDatabase;
begin
  MoveZero( s, SizeOf( s ) );
  For i := 0 to Pred( Databases.Count ) do
  begin
    P := Databases.Items[ i ];
    Inc( S.iCursors, P.Tables.Count );
  end;
  With S do
  begin
    iSession := Identifier;                                 { Session id (1..n) }
    StrCopy( szName, Name );                                { Documentary name }
    iDatabases := Databases.Count;                          { Open databases }
    StrCopy( szNetDir,  NetDir  );                          { Net directory location }
    StrCopy( szPrivDir, PrivDir );                          { Current Private directory   }
  end;
end;


Function TBaseSession.GetDriverDescText : PChar;
begin
  Result := BAPI_NAME_OF_THE_WEEK;
end;


Procedure TBaseSession.SetDBType( BeHonest : Boolean; pDbDesc : pDBDesc );
begin
  if not BeHonest then
    With pDbDesc^ do
      StrCopy( @szDbType, STANDARD_DRIVER_DESC   );   { Database type }
end;


Procedure TBaseSession.GetDbDescInternal (                  { Get a description of a logical db }
           pszName       : PChar;                           { Name of logical database }
           pdbDesc       : pDBDesc;                         { Database description }
           BeHonest      : Boolean
         );
var
  Cursor : TBaseTable;
  Curr   : ShortString;
begin
  If HasPath( pszName, TRUE ) then
  begin
    Curr := StrPas( pszName );
    If not FNoDBNameBackSlash then
      Curr := AddBackSlash( Curr );
    MoveZero( pdbDesc^, SizeOf( DBDesc ) );
    With DBDesc( pDbDesc^ ) do
    begin
      StrPCopy( @szName,    'PATH' );                       { Logical name (Or alias) }
      StrPCopy( @szText,    'PATH' );                       { Descriptive text }
      StrPCopy( @szPhyName, Curr );                         { Physical name/path }
      SetDBType( FALSE, pDbDesc );                          { Database type }
    end;
    Exit;
  end;
  OpenDatabaseList( hDBICur( Cursor ) );
  Try
    Try
      Repeat
        Cursor.GetNextRecord( dbiNOLOCK, pdbDesc, NIL );
        If ( StrIComp( pszName, pdbDesc^.szName ) = 0 ) then
        begin
          SetDbType( BeHonest, pDbDesc );
          Break;
        end;
      Until FALSE;
    Except
      on ETitanBoundryError do
        ThrowExceptionMsg( DBIERR_UNKNOWNDB, StrPas( pszName ) );
    end;
  Finally
    Cursor.Free;
  end;
end;


Procedure TBaseSession.GetDatabaseDesc (                    { Get a description of a logical db }
           pszName       : PChar;                           { Name of logical database }
           pdbDesc       : pDBDesc                          { Database description }
         );
begin
  GetDBDescInternal( pszName, pDbDesc, FALSE );
end;


Procedure TBaseSession.OpenTableTypesList (                 { Get a list of table types }
           pszDriverType : PChar;                           { Driver type }
           var hCur      : hDBICur                          { Returned cursor }
         );
begin
  Not_Supported( fnOPENTABLETYPESLIST );
end;


Procedure TBaseSession.GetTableTypeDesc (                   { Get Table capabilities }
           pszDriverType : PChar;                           { Driver type }
           pszTableType  : PChar;                           { Table type }
           var tblType   : TBLType                          { Table Capabilities }
         );
begin
  Not_Supported( fnGETTABLETYPEDESC );
end;


Procedure TBaseSession.OpenFieldTypesList (                 { Get a list of field types }
           pszDriverType : PChar;                           { Driver type }
           pszTblType    : PChar;                           { Table type (Optional) }
           var hCur      : hDBICur                          { Returned cursor }
         );
begin
  Not_Supported( fnOPENFIELDTYPESLIST );
end;


Procedure TBaseSession.GetFieldTypeDesc (                   { Get list of field types }
           pszDriverType : PChar;                           { Driver type }
           pszTableType  : PChar;                           { Table type }
           pszFieldType  : PChar;                           { Field type  (Physical only) }
           var fldType   : FLDType                          { Field type description }
   );
begin
  Not_Supported( fnGETFIELDTYPEDESC );
end;


Procedure TBaseSession.OpenIndexTypesList (                 { Get a list of Index types }
           pszDriverType : PChar;                           { Driver type }
           var hCur      : hDBICur                          { Returned cursor }
         );
begin
  Not_Supported( fnOPENINDEXTYPESLIST );
end;


Procedure TBaseSession.OpenLdList (                         { Get a list of Lang Drivers }
           var hCur : hDBICur                               { Returned cursor }
         );
begin
  Not_Supported( fnOPENLDLIST );
end;


Procedure TBaseSession.OpenDatabaseInternal (               { Open a database }
           pdbDesc       : pDBDesc;                         { Database description }
           eOpenMode     : DBIOpenMode;                     { Open type }
           eShareMode    : DBIShareMode;                    { Share type }
           pszPassword   : PChar;                           { Password }
           iOptFlds      : Word;                            { Number of optional Params }
           pOptFldDesc   : pFLDDesc;                        { Optional Field Descriptors }
           pOptParams    : Pointer;                         { Optional Params }
           var   hDb     : hDBIDb                           { Returned database handle }
         );
begin
  Not_Supported( fnOPENDATABASEINTERNAL );
end;


Procedure TBaseSession.OpenDatabase (                       { Open a database }
           pszDbName     : PChar;                           { Database name }
           pszDbType     : PChar;                           { Database type (NULL: Universal) }
           eOpenMode     : DBIOpenMode;                     { Open type }
           eShareMode    : DBIShareMode;                    { Share type }
           pszPassword   : PChar;                           { Password }
           iOptFlds      : Word;                            { Number of optional Params }
           pOptFldDesc   : pFLDDesc;                        { Optional Field Descriptors }
           pOptParams    : Pointer;                         { Optional Params }
           var hDb       : hDBIDb                           { Returnd database handle }
         );
var
  Desc : DBDesc;

  (*---------------------------------------------------------*)
  (* This new code loads the description record from values  *)
  (* passed as optional.  This is much faster than having to *)
  (* go fetch the database description again. If the values  *)
  (* aren't all there, then the fetch is done anyway.        *)
  (*---------------------------------------------------------*)
  Function ScanOptionalParams : Boolean;
  var
    i    : Word;
    F    : pFLDDesc;
    O    : PChar;
    Hits : Word;
  begin
    Hits := 0;
    MoveZero( Desc, SizeOf( Desc ) );
    StrLCopy( @Desc.szName,   pszDbName,         Pred( SizeOf( DBINAME ) ) );
    StrLCopy( @Desc.szDbType, GetDriverDescText, Pred( SizeOf( DBINAME ) ) );
    if ( iOptFlds > 0 ) then
    begin
      F := pOptFldDesc;
      For i := 0 to Pred( iOptFlds ) do
      begin
        O := PChar( pOptParams );
        Inc( O, F^.iOffset );
        if ( StrIComp( F^.szName, REG_DESCRIPTION ) = 0 ) then
        begin
          StrLCopy( @Desc.szText, O, Pred( SizeOf( FName ) ) );
          Inc( Hits );
        end
        else
          if ( StrIComp( F^.szName, REG_PHYSICALNAME ) = 0 ) then
          begin
            StrLCopy( @Desc.szPhyName, O, Pred( SizeOf( DBIPATH ) ) );
            Inc( Hits );
          end;
        Inc( F );
      end;
    end;
    Result := ( Hits = 2 );
  end;

begin
  ValidateParameter( pszDbName );
  if not ScanOptionalParams then
    GetDbDescInternal( pszDbName, @Desc, TRUE );
  OpenDatabaseInternal( @Desc, eOpenMode, eShareMode, pszPassword, iOptFlds, pOptFldDesc, pOptParams, hDb );
end;


Procedure TBaseSession.OpenDriverList (                     { Get a list of driver names }
           var   hCur          : hDBICur                    { Returned cursor }
         );
begin
  hCur := NIL;
end;


Procedure TBaseSession.GetDriverDesc (                      { Get description for a given type }
            pszDriverType : PChar;                          { Symbolic name for driver type }
            var  drvType  : DRVType                         { Driver type description }
          );
begin
  MoveZero( drvType, SizeOf( drvType ) );
end;


Procedure TBaseSession.OpenDatabaseList ( var hCur : hDBICur );
begin
  hCur := hDBICur( TRegDBListTable.Create( Self, SystemTables, CfgRecords, NIL, @FTitanEnv ) );
  TBaseDBListTable( hCur ).OpenTable;
end;


Procedure TBaseSession.CloseDatabase( var hDb : hDBIDb );
begin
  If Assigned( hDb ) then
  begin
    TBaseDatabase( hDb ).Free;
    hDb := NIL;
  end;
end;


Procedure TBaseSession.UseIdleTime;                         { Use Idle time }
begin
end;


Procedure TBaseSession.GetLdObj (                           { Get language driver }
           hCursor       : hDBICur;                         { Cursor handle }
           var   pLdObj  : Pointer                          { Returned language driver object }
         );
begin
  pLdObj := @FLocale;
end;


Procedure TBaseSession.GetLdName (                          { Get language driver name from table }
           pszDriver     : PChar;                           { Driver name }
           pObjName      : PChar;                           { Name of object, i.e. table name }
           pLdName       : PChar                            { Returned language driver name }
         );
begin
  Not_Used( fnGETLDNAME );
end;


Procedure TBaseSession.GetTableOpenCount (                  {  Get local cursor count }
           hDb            : hDBIDb;                         { Database }
           pszTableName   : PChar;                          { Table name }
           pszDriverType  : PChar;                          { Driver type }
           var iOpenCount : Word                            { returned number of cursors }
         );
Var
  Total : Word;
  I     : Integer;
  P     : TBaseDatabase;
begin
  iOpenCount := 0;
  if Assigned( hDb ) then
  begin
    Total := 0;
    For i := 0 to Pred( Databases.Count ) do
    begin
      P := Databases.Items[ i ];
      P.GetTableOpenCount( pszTableName, pszDriverType, iOpenCount );
      Inc( Total, IOpenCount );
    end;
    iOpenCount := Total;
  end
end;


Procedure TBaseSession.AddPassword (                        { Add a password to current session }
           pszPassword   : PChar                            { Password }
         );
begin
  Not_Supported( fnADDPASSWORD );
end;


Procedure TBaseSession.DropPassword (                       { Drop a password to current session }
           pszPassword   : PChar                            { Password }
         );
begin
  Not_Supported( fnDROPPASSWORD );
end;


Procedure TBaseSession.TranslateRecordStructure (           { Translate a record }
            pszSrcDriverType : PChar;                       { Source driver type }
            iFlds         : Word;                           { Number of fields }
            pfldsSrc      : pFLDDesc;                       { Array of source fields: logical or physical types }
            pszDstDriverType : PChar;                       { Destination driver type }
            pszLangDriver : PChar;                          { Language driver for destination }
            pfldsDst      : pFLDDesc                        { Array of dest. fields returned }
            ;
            bCreatable    : Bool                            { TRUE -> map to creatable fields only. }
          );
begin
  Not_Supported( fnTRANSLATERECORDSTRUCTURE );
end;


Procedure TBaseSession.OpenFieldXlt (                       { Open translation object }
           pszSrcTblType : PChar;                           { NULL for Logical }
           pszSrcLangDrv : PChar;                           { NULL if no tranliteration }
           pfldSrc       : pFLDDesc;                        { source field descriptor }
           pszDestTblType : PChar;                          { NULL for Logical }
           pszDstLangDrv : PChar;                           { NULL if no tranliteration }
           pfldDest      : pFLDDesc;                        { Source field descriptor }
           var bDataLoss : Bool;                            { Set to TRUE, for data loss }
           var hXlt      : hDBIXlt                          { Returned translate handle }
         );
begin
  Not_Supported( fnOPENFIELDXLT );
end;


Procedure TBaseSession.TranslateField (                     { Translate a field }
           hXlt          : hDBIXlt;                         { Translation handle }
           pSrc          : Pointer;                         { Source field }
           pDest         : Pointer                          { Destination field }
         );
begin
  Not_Supported( fnTRANSLATEFIELD );
end;


Procedure TBaseSession.CloseFieldXlt (                      { Close translation object }
           hXlt          : hDBIXlt                          { Translation handle }
         );
begin
  Not_Supported( fnCLOSEFIELDXLT );
end;


Procedure TBaseSession.GetProp (                            { Get property }
           iProp         : Longint;                         { Property to retrieve }
           PropValue     : Pointer;                         { == NULL, validate iProp for getting }
           iMaxLen       : Word;                            { Length of buffer pPropValue }
           var   iLen    : Word                             { Returns required length }
         );
Var
  S : String;
begin
  Case iProp of
    sesNETFILE:
    begin
      GetDir( 0, S );
      iLen := Succ( Length( S ) );
      StrCopy( PropValue, PChar( S ) );
    end;
    sesCfgMode,
    sesCfgMode2:
    begin
      iLen       := SizeOf( Integer );
      Move( FConfigMode, PropValue^, iLen );
    end;
  else
    Inherited GetProp( iProp, PropValue, iMaxLen, iLen );
  end;
end;


Procedure TBaseSession.SetProp (                            { Get property }
           iProp         : Longint;                         { Property to retrieve }
           PropValue     : Longint                          { == NULL, validate iProp for getting }
         );
begin
  Case iProp of
    sesCfgMode
    ,sesCfgMode2
    :
      FConfigMode := PropValue;
  else
    Inherited SetProp( iProp, PropValue );
  end;
end;


Procedure TBaseSession.OpenUserList (                       { Get a list of users loggedin }
           var hUsers : hDBICur                             { Returned cursor on user list }
         );
begin
  Not_Supported( fnOPENUSERLIST );
end;


Procedure TBaseSession.NativeToAnsi (                       { Convert from native to Ansi }
           LdObj         : Pointer;                         { Language driver }
           pAnsiStr      : PChar;                           { Destination buffer (opt) }
           pNativeStr    : PChar;                           { Source buffer }
           iLen          : LongInt;                         { Length of buffer (opt) }
           var bDataLoss : Bool                             { Returns TRUE if conversion will loose data (opt) }
         );
begin
  bDataLoss := FALSE;
  If FIgnoreOEMAnsi then
    Move( pNativeStr^, pAnsiStr^, iLen )
  else
    OemToCharBuff( pNativeStr, pAnsiStr, iLen );
end;


Procedure TBaseSession.AnsiToNative (                       { Convert from Ansi to native }
           LdObj         : Pointer;                         { Language driver }
           pNativeStr    : PChar;                           { Destination buffer (opt) }
           pAnsiStr      : PChar;                           { Source buffer }
           iLen          : LongInt;                         { Length of buffer (opt) }
           var bDataLoss : Bool                             { Returns TRUE if conversion will loose data (opt) }
   );
begin
  bDataLoss := FALSE;
  If FIgnoreAnsiOEM then
    Move( pAnsiStr^, pNativeStr^, iLen )
  else
    CharToOEMBuff( pAnsiStr, pNativeStr, iLen );
end;


Procedure TBaseSession.RegisterCallBack (                   { Register a call back fn }
           hCursor       : hDBICur;                         { Cursor (Optional) }
           ecbType       : CBType;                          { Type of call back }
           iClientData   : Longint;                         { Pass-thru client data }
           iCbBufLen     : Word;                            { Callback buffer len }
           CbBuf         : Pointer;                         { Pointer to callback buffer }
           pfCb          : pfDBICallBack                    { Call back fn being registered }
         );
begin
  if ( hCursor <> NIL ) then
    TBaseTable( hCursor ).RegisterCallBack( ecbType, iClientData, iCbBufLen, CbBuf, pfCb )
  else
    Not_Used( fnREGISTERCALLBACK );
end;


Procedure TBaseSession.GetCallBack (                        { Register a call back fn }
                    hCursor       : hDBICur;                { Cursor (Optional) }
                    ecbType       : CBType;                 { Type of call back }
                    piClientData  : PLongint;               { Pass-thru client data }
                    piCbBufLen    : PWord;                  { Callback buffer len }
                    ppCbBuf       : Pointer;                { Pointer to callback buffer }
                    var pfCb      : pfDBICallBack           { Call back fn being registered }
                  );
begin
  if ( hCursor <> NIL ) then
    TBaseTable( hCursor ).GetCallBack( ecbType,
      piClientData, piCbBufLen, ppCbBuf, pfCb
    )
  else
    Not_Used( fnGETCALLBACK );
end;


Procedure TBaseSession.GetNumberFormat (                    { Get current number format }
           var   fmtNumber     : FMTNumber
         );
begin
  Not_Supported( fnGETNUMBERFORMAT );
end;


Procedure TBaseSession.SetNumberFormat (                    { Set current number format }
           var   fmtNumber     : FMTNumber
         );
begin
  Not_Supported( fnSETNUMBERFORMAT );
end;


Procedure TBaseSession.GetIndexTypeDesc (                   { Get list of Index types }
            pszDriverType : PChar;                          { Driver type }
            pszIndexType  : PChar;                          { Index type }
            var idxType   : idxType                         { Index type description }
          );
begin
  Not_Supported( fnGETINDEXTYPEDESC );
end;


Procedure TBaseSession.CheckRefresh;
begin
end;


Procedure TBaseSession.GetSysVersion( var s : SysVersion );
begin
  MoveZero( s, SizeOf( s ) );
end;


Procedure TBaseSession.GetSysConfig( var s : SysConfig );
begin
  MoveZero( s, SizeOf( s ) );
  With s do
  begin
    bLocalShare:=  TRUE;                                    { If Local files will be shared }
    bNetShare:=    TRUE;                                    { True if connected to network }
  end;
end;


Procedure TBaseSession.GetClientInfo( var s : clientInfo );
begin
  MoveZero( s, SizeOf( s ) );
  With s do
  begin
(*  szName          : DBINAME;                              { Documentary name }*)
    If ( Container <> NIL ) then
      iSessions := Container.Count;                         { Number of FSessions }
    StrCopy( szWorkDir, NetDir );                           { Working directory }
(*  szLang          : DBINAME;                              { System language driver (Client supplied) }*)
  end;
end;


Procedure TBaseSession.LoadDriver (                         { Load a given driver }
            pszDriverType : PChar                           { Driver name }
          );
begin
  ThrowException( DBIERR_DRIVERLIMIT );
end;


Procedure TBaseSession.GetSysInfo( var s : SysInfo );
begin
  MoveZero( s, SizeOf( s ) );
  if ( Container <> NIL ) then
    s.iSessions := Container.Count;                         { Number of FSessions (For all clients) }
end;


Procedure TBaseSession.GetSesInfo( var s : SesInfo );
begin
  GetInfo( s );
  { These fields are not currently in the session object }
  s.iLockWait := FLockWait;                                 { Lock wait time (in seconds) }
end;


Procedure TBaseSession.GetNetUserName (                     { Get network username }
           pszNetUserName : PChar                           { Returns username }
         );
begin
  BseUtils.GetNetUserName( pszNetUserName );
end;


Procedure TBaseSession.DeleteAlias (                        { Add a new alias }
           hCfg          : hDBICfg;                         { NULL }
           pszAliasName  : PChar                            { Alias name }
          );
begin
  Try
    CfgDropRecord( hCfg, pszAliasName );
  Except
    On E:ETitanBoundryError do
      ;
  end;
end;


Procedure TBaseSession.WriteTitanAliasParams( Reg : TRegistry; pszParams : PChar );
{ Parameters are in the format KeyName:"KeyValue"; }
var
  KeyName   : String;
  KeyValue  : String;
  InName    : Boolean;
  InQuotes  : Boolean;

  Procedure Initialize;
  begin
    KeyName   := '';
    KeyValue  := '';
    InName    := TRUE;
    InQuotes  := FALSE;
  end;

  Procedure AddCharacter;
  begin
    If InName then
      KeyName := KeyName + pszParams^
    else
      KeyValue := KeyValue + pszParams^;
  end;

begin
  Initialize;
  While ( pszParams^ <> #0 ) do
  begin
    Case pszParams^ of
      ':' : If InQuotes then
              AddCharacter
            else
              InName := FALSE;
      '"' : begin
              InQuotes := Not InQuotes;
              If Not InQuotes then
              begin
                Reg.WriteString( KeyName, KeyValue );
                Initialize;
              end
              else
                InName := FALSE;
            end;
      ';' : If InQuotes then
              AddCharacter
            else
              Initialize;
      else
        AddCharacter;
    end;
    Inc( pszParams );
  end;
end;


Procedure TBaseSession.AddTitanAlias (                      { Add a new alias }
            pszAliasName  : PChar;                          { Alias name }
            pszParams     : PChar                           { Optional parameters }
          );
Var
  Reg : TRegistry;
  Key : String;
begin
  Reg := TRegistry.Create;
  Reg.RootKey := FTitanEnv.RootKey;
  Try
    Key := FTitanEnv.ClientPath + '\' + REG_ALIASES + '\' + StrPas( pszAliasName );
    If Reg.OpenKey( Key, TRUE ) then
      WriteTitanAliasParams( Reg, pszParams );
  Finally
    Reg.Free;
  end;
end;


Procedure TBaseSession.DeleteTitanAlias (                   { Delete an alias }
            pszAliasName  : PChar                           { Alias name }
          );
Var
  Reg : TRegistry;
  Key : String;
begin
  Reg := TRegistry.Create;
  Reg.RootKey := FTitanEnv.RootKey;
  Try
    Key := FTitanEnv.ClientPath + '\' + REG_ALIASES + '\' + StrPas( pszAliasName );
    If Reg.KeyExists( Key ) then
      Reg.DeleteKey( Key );
  Finally
    Reg.Free;
  end;
end;


Procedure TBaseSession.OpenCfgInfoList (                    { Open a cursor on "Config" }
           hCfg          : hDBICfg;                         { NULL }
           eOpenMode     : DBIOpenMode;                     { ReadWrite or readonly }
           eConfigMode   : CFGMode;                         { Config mode }
           pszCfgPath    : PChar;                           { Path }
           var   hCur    : hDBICur                          { Returned cursor }
         );
Const
  MAXFIELDS = 5;
Var
  Fields : Array[1..MAXFIELDS] of FLDDesc;
  Cfg    : CFGDesc;
begin
  MoveZero( Fields, SizeOf( Fields ) );
  With Fields[ 1 ] do
  begin
    iFldNum   := 1;
    szName    := 'szNodeName';
    iFldType  := fldZString;
    iUnits1   := Pred( SizeOf( Cfg.szNodeName ) );
  end;
  With Fields[ 2 ] do
  begin
    iFldNum   := 2;
    szName    := 'szDescription';
    iFldType  := fldZString;
    iUnits1   := Pred( SizeOf( Cfg.szDescription ) );
  end;
  With Fields[ 3 ] do
  begin
    iFldNum   := 3;
    szName    := 'iDataType';
    iFldType  := fldUINT16;
  end;
  With Fields[ 4 ] do
  begin
    iFldNum   := 4;
    szName    := 'szValue';
    iFldType  := fldZString;
    iUnits1   := Pred( SizeOf( Cfg.szValue ) );
  end;
  With Fields[ 5 ] do
  begin
    iFldNum   := 5;
    szName    := 'bHasSubNodes';
    iFldType  := fldBOOL;
  end;
  hCur := hDBICur( TMemTable.Create( Self, SystemTables, pszCfgPath, MAXFIELDS, 0, @Fields, NIL ) );
  ValidateHandle( hCur );
  LoadCfgInfoList( hCur );
  TBaseTable( hCur ).State := TblNoPos;
end;



Procedure TBaseSession.LoadCfgInfoList( hCur : HDBICur );
Var
  Cfg     : CFGDesc;
  S       : ShortString;
  i       : Integer;
  Values  : TStringList;
  Source  : TRightsRegistry;
  tmp     : Integer;
  DidUser : Boolean;

  Procedure TestForUser;
  begin
    if Not DidUser then
    begin
      MoveZero( Cfg, SizeOf( Cfg ) );
      With Cfg do
      begin
        StrCopy( @szNodeName, szUSERNAME );
        iDataType := fldZSTRING;
      end;
      TBaseTable( hCur ).InsertRecord( dbiNOLOCK, @Cfg );
    end;
  end;

  { This function ensures that the CFG.szValue field is not blown out }
  { by a large string value written into it.                          }
  Procedure SetszValue( Const S : ShortString );
  begin
    StrPCopy( @Cfg.szValue, Copy( S, 1, SizeOf( Cfg.szValue ) - 1 ) );
  end;

begin
  { TableName contains \DATABASES\<Alias>\DB OPEN... }
  S := StrPas( TBaseTable( hCur ).TableName );
  i := Pos( '\DATABASES\', S );
  If ( i > 0 ) then
  begin
    S := Copy( S, 12, 255 );
    i := Pos( '\DB OPEN', S );
    if ( i = 0 ) then
      i := Pos( '\DB INFO', S );
    if ( i <> 0 ) then
      S[ i ] := #0;
    If HasPath( @S[ 0 ], TRUE ) then
    begin
      MoveZero( Cfg, SizeOf( Cfg ) );
      With Cfg do
      begin
        StrPCopy( @szNodeName, 'PATH' );
        SetszValue( S );
      end;
      TBaseTable( hCur ).InsertRecord( dbiNOLOCK, @Cfg );
      TestForUser;
      Exit;
    end;
    Source := TRightsRegistry.Create;
    Try
      ValidatePointer( Source, DBIERR_NOSUCHTABLE );
      Source.RootKey := FTitanEnv.RootKey;
      Source.Rights  := KEY_READ;
      if Source.OpenKey( FTitanEnv.ClientPath + '\' + REG_ALIASES + '\' + S, FALSE ) then
      begin
        Values := TStringList.Create;
        Try
          Source.GetValueNames( Values );
          TBaseTable( hCur ).OpenTable;
          DidUser := FALSE;
          For i := 0 to Pred( Values.Count ) do
          begin
            MoveZero( Cfg, SizeOf( Cfg ) );
            With Cfg do
            begin
              StrPCopy( @szNodeName, Values.Strings[ i ] );
              If not DidUser and ( StrIComp( @szNodeName, 'USER' ) = 0 ) then
              begin
                StrCopy( @szNodeName, szUSERNAME );
                DidUser := TRUE;
              end;
              iDataType := fldZSTRING;
              Case Source.GetDataType( Values[ i ] ) of
                rdString:
                  SetszValue( Source.ReadString( Values[ i ] ) );
                rdInteger:
                  begin
                    tmp := Source.ReadInteger( Values[ i ] );
                    SetszValue( IntToStr( tmp ) );
                  end;
              else
                Continue;
              end;
            end;
            TBaseTable( hCur ).InsertRecord( dbiNOLOCK, @Cfg );
          end;
          TestForUser;
        Finally
          Values.Free;
        end;
      end;
    Finally
      Source.Free;
    end;
  end;
end;



Procedure TBaseSession.AddAlias (                           { Add a new alias }
           hCfg          : hDBICfg;                         { NULL }
           pszAliasName  : PChar;                           { Alias name }
           pszDriverType : PChar;                           { Driver type for alias }
           pszParams     : PChar;                           { Optional parameters }
           bPersist      : Bool                             { Persistent or session relative }
         );
{ Parameters are in the format KeyName:"KeyValue"; }
Const
  MAX_PARAMS = 255;
  MAX_BUFFER = 4095;
var
  KeyName   : String;
  KeyValue  : String;
  InName    : Boolean;
  InQuotes  : Boolean;
  FldDescs  : Array[0..MAX_PARAMS] of FLDDesc;
  Buffer    : Array[0..MAX_BUFFER] of Char;
  BufPtr    : PChar;
  Index     : Integer;

  Procedure Initialize;
  begin
    KeyName   := '';
    KeyValue  := '';
    InName    := TRUE;
    InQuotes  := FALSE;
  end;

  Procedure AddCharacter;
  begin
    If InName then
      KeyName  := KeyName  + pszParams^
    else
      KeyValue := KeyValue + pszParams^;
  end;

begin
  Index  := 0;
  BufPtr := Buffer;
  MoveZero( Buffer, SizeOf( Buffer ) );
  Initialize;
  While ( pszParams^ <> #0 ) do
  begin
    Case pszParams^ of
      ':' : If InQuotes then
              AddCharacter
            else
              InName := FALSE;
      '"' : begin
              InQuotes := Not InQuotes;
              If Not InQuotes then
              begin
                MoveZero( FldDescs[ Index ], SizeOf( FldDesc ) );
                With FldDescs[ Index ] do
                begin
                  iFldNum := Succ( Index );
                  iOffset := BufPtr - Buffer;
                  iLen    := Succ( Length( KeyValue ) );
                  StrLCopy( @szName, PChar( KeyName ), SizeOf( szName ) - 1 );

                  StrCopy( BufPtr, PChar( KeyValue ) );
                  Inc( BufPtr, iLen );
                  Inc( Index );
                end;
                Initialize;
              end
              else
                InName := FALSE;
            end;
      ';' : If InQuotes then
              AddCharacter
            else
              Initialize;
      else
        AddCharacter;
    end;
    Inc( pszParams );
  end;
  KeyName := '\DATABASES\' + StrPas( pszAliasName ) + '\DB INFO';
  CfgAddRecord( hCfg, pChar( KeyName ), Index, @FldDescs, @Buffer );
end;



Procedure TBaseSession.OpenConfigFile (                     { Open/Create configuration }
           pszDirPath    : PChar;                           { Directory }
           bCreate       : Bool;                            { TRUE to create/overwrite }
           var hCfg      : hDBICfg                          { Handle to config }
         );
begin
  Not_Supported( fnOPENCONFIGFILE );
end;


Procedure TBaseSession.CloseConfigFile (                    { Close the config file }
           var hCfg      : hDBICfg;                         { Handle }
           bSave         : Bool;                            { To save the changes }
           bDefault      : Bool                             { To make this file the default }
           ;
           bSaveAs16     : Bool                             { To save as a 16-bit config file }
         );
begin
  Not_Supported( fnCLOSECONFIGFILE );
end;


Procedure TBaseSession.CfgSave (                            { Save current configuration }
           hCfg          : hDBICfg;                         { Config Handle/NULL }
           pszNewFile    : PChar                            { (Optional): Save as this file }
           ;
           bSaveAs16     : Bool                             { To save as a 16-bit config file }
         );
begin
  Not_Used( fnCFGSAVE );
end;


Procedure TBaseSession.CfgBuildPath (                       { Build a path for accessing config. }
           hCfg          : hDBICfg;                         { Config Handle/NULL }
           pszCategory   : PChar;                           { NULL for root }
           pszGroup      : PChar;                           { NULL for no group }
           pszSection    : PChar;                           { NULL for no section }
           pszCfgPath    : PChar                            { Returned path }
         );
begin
  Not_Supported( fnCFGBUILDPATH );
end;


Procedure TBaseSession.CfgPosition (                        { Position the config path }
           hCfg          : hDBICfg;                         { Config Handle/NULL }
           pszCfgPath    : PChar                            { Path }
         );
var
  i : Word;
  P : TBaseCfgRecord;
  S : String;
begin
  if ( CfgRecords.Count > 0 ) then
  begin
    S := StrPas( pszCfgPath );
    For i := 0 to Pred( CfgRecords.Count ) do
    begin
      P := TBaseCfgRecord( CfgRecords.At( i ) );
      if ( P <> NIL ) and ( Pos( S, P.FPath ) > 0 ) then
        Exit;
    end;
  end;
  ThrowEOFException;
end;


Procedure TBaseSession.CfgGetNextNode (                     { Get next defined node }
           hCfg          : hDBICfg;                         { Config Handle/NULL }
           pszNodeName   : PChar                            { Node name (Returned) }
         );
begin
  Not_Supported( fnCFGNEXTNODE );
end;


Procedure TBaseSession.CfgGetRecord (                       { Get a record }
           hCfg          : hDBICfg;                         { Config Handle/NULL }
           pszCfgPath    : PChar;                           { Path }
           var iFields   : Word;                            { Returned nbr of fields }
           pfldDesc      : pFLDDesc;                        { Field descriptors }
           pRec          : Pointer                          { Field values }
         );
var
  i : Word;
  P : TBaseCfgRecord;
  S : String;
begin
  iFields := 0;
  if ( CfgRecords.Count > 0 ) then
  begin
    S := StrPas( pszCfgPath );
    For i := 0 to Pred( CfgRecords.Count ) do
    begin
      P := TBaseCfgRecord( CfgRecords.At( i ) );
      if ( P <> NIL ) then
      begin
        If ( S = P.FPath ) then
        begin
          iFields := P.FFields;
          If ( pfldDesc <> NIL ) then
            Move( P.FFieldDescs^, pfldDesc^, SizeOf( FLDDesc ) * iFields );
          If ( pRec <> NIL ) then
            Move( P.FRec^, pRec^, P.RecordSize );
          Exit;
        end;
      end;
    end;
  end;
  ThrowEOFException;
end;


Procedure TBaseSession.CfgAddRecord (                       { Add a record }
           hCfg          : hDBICfg;                         { Config Handle/NULL }
           pszCfgPath    : PChar;                           { Path }
           iFields       : Word;                            { No of fields }
           pfldDesc      : pFLDDesc;                        { Field descriptors }
           pRec          : Pointer                          { Data values }
         );
begin
  Try
    CfgModifyRecord( hCfg, pszCfgPath, iFields, pfldDesc, pRec );
  Except
    on E:ETitanBoundryError do
      TBaseCfgRecord.Create( Self, CfgRecords, pszCfgPath, iFields, pfldDesc, pRec );
  end;
end;


Procedure TBaseSession.CfgModifyRecord (                    { Modify a record }
           hCfg          : hDBICfg;                         { Config Handle/NULL }
           pszCfgPath    : PChar;                           { Path }
           iFields       : Word;                            { Nbr of fields }
           pfldDesc      : pFLDDesc;                        { Field descriptors }
           pRec          : Pointer                          { Data values }
         );
var
  i : Word;
  P : TBaseCfgRecord;
  S : String;
begin
  if ( CfgRecords.Count > 0 ) then
  begin
    S := StrPas( pszCfgPath );
    For i := 0 to Pred( CfgRecords.Count ) do
    begin
      P := TBaseCfgRecord( CfgRecords.At( i ) );
      if ( P <> NIL ) then
      begin
        If ( S = P.FPath ) then
        begin
          P.SetFields( iFields, pFldDesc, pRec );
          Exit;
        end;
      end;
    end;
  end;
  ThrowEOFException;
end;


Procedure TBaseSession.CfgDropRecord (                      { Delete a record }
           hCfg          : hDBICfg;                         { Config Handle/NULL }
           pszCfgPath    : PChar                            { Path }
         );
var
  i     : Word;
  P     : TBaseCfgRecord;
  S     : String;
  Found : Boolean;
begin
  Found := FALSE;
  S     := StrPas( pszCfgPath );
  if ( CfgRecords.Count > 0 ) then
  begin
    For i := Pred( CfgRecords.Count ) downto 0 do
    begin
      P := TBaseCfgRecord( CfgRecords.At( i ) );
      if ( P <> NIL ) and ( Pos( S, P.FPath ) > 0 ) then
      begin
        P.Free;
        Found := TRUE;
      end;
    end;
  end;
  If Not Found then
    ThrowEOFException;
end;


Procedure TBaseSession.CfgTranslate (                       { Translate configuration string }
           hCfg          : hDBICfg;                         { Config Handle/NULL }
           pszConfigPath : PChar;                           { configuration path }
           pszTrans      : PChar;                           { translated path }
           iFields       : Word;                            { number of fields, 0 if path only }
           pfldDesc      : pFLDDesc;                        { field descriptors, NULL if path only }
           pRec          : Pointer                          { record buffer, NULL if path only }
         );
begin
  Not_Supported( fnCFGTRANSLATE );
end;


Procedure TBaseSession.CfgGetHelp (                         { Get help message }
           hCfg          : hDBICfg;                         { Config Handle/NULL }
           pszConfigPath : PChar;                           { configuration path }
           pszFldName    : PChar;                           { field name  ( optional ) }
           pszHelpString : PChar                            { help string ( returned ) }
         );
begin
  Not_Supported( fnCFGGETHELP );
end;


Procedure TBaseSession.CfgMerge (                           { Merge config files }
           hCfgDest      : hDBICfg;                         { Destination Cfg handle/ NULL }
           hCfgSrc       : hDBICfg;                         { Source Cfg handle/ NULL }
           pszSrcPath    : PChar                            { Source Path / NULL }
         );
begin
  Not_Supported( fnCFGMERGE );
end;

Procedure TBaseSession.ImportODBC(                          { Import current ODBC drivers and data sources }
           hCfg          : hDBICfg;                         { NULL }
           bPersist      : Bool                             { Persistent or session relative }
         );
begin
  Not_Supported( fnIMPORTODBC );
end;

Procedure TBaseSession.AddDriver(                           { Add a new driver }
           hCfg          : hDBICfg;                         { NULL }
           pszDriverName : PChar;                           { Driver name }
           pszParams     : PChar;                           { Optional parameters }
           bPersist      : Bool                             { Persistent or session relative }
         );
begin
  Not_Supported( fnADDDRIVER );
end;

Procedure TBaseSession.DeleteDriver(                        { Delete a driver }
           hCfg          : hDBICfg;                         { NULL }
           pszDriverName : PChar;                           { Driver name }
           bSave         : Bool                             { Save config file }
         );
begin
  Not_Supported( fnDELETEDRIVER );
end;



end.

