.ad 8
.bm 8
.fm 4
.bt $Copyright by   Software AG, 1993$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $NME$Project Distributed Database System$vos11c$
.tt 2 $$$
.tt 3 $R.Roedling$XPARAM Functions$1997-04-28$
***********************************************************
.nf


    ========== licence begin LGPL
    Copyright (C) 2002 SAP AG

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    ========== licence end

.fo
.nf
.sp
Module  : XPARAM_Functions
=========
.sp
Purpose :
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :

.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :

.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :

.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : M. Oezgen
.sp
.cp 3
Created : 12.3.92
.sp
.cp 3
Version :
.sp
.cp 3
Release :  6.2 	 Date : 1997-04-28
.br
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:

.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:

.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:

.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
/*PRETTY*/
//
//  MODULE - XPARAM Functions ( Common Part )
//


//
//  INCLUDE FILES
//


//
//  DEFINES
//

#define MOD__       "VOS11CC : "
#define MF__        MOD__"UNDEFINED"

#define         XP_PAGE_SIZE ( sizeof( XP_KEY_TYPE ) + sizeof( XP_VALUE_REC ) )
#define PREV            0
#define ACT             1
#define NEXT            2

#if defined(_WIN32)
 #define FILE_EXISTED   1
 #define FILE_CREATED   2
#endif

#define MAX_OPEN_PARAMS    3
#define NUM_START_PARAMS 200
#define NUM_NEW_PARAMS    50

typedef struct  xp_data_struc
  {
    PATHNAME szXParamFile;
    HFILE hXParamFile ;
    char *Xparams ;
    ULONG ulActParam ;
    ULONG ulLastParam ;
    ULONG ulMaxParams ;
    BOOLEAN fFileIsNew ;
  } XP_DATA_STRUC ;

static XP_DATA_STRUC  XpData [ MAX_OPEN_PARAMS ] ;

//
//  MACROS
//
#ifdef DEBUG
static char _TmpStr[500 + 1]

#define _PToC( _Str, _Len)
            (sql47c_ptoc( _TmpStr, _Str, min(_Len, 500)), _TmpStr)
#endif

//
//  LOCAL TYPE AND STRUCT DEFINITIONS
//


//
//  EXTERNAL VARIABLES
//


//
//  EXPORTED VARIABLES
//


//
//  LOCAL VARIABLES
//


//
//  LOCAL FUNCTION PROTOTYPES
//

static XP_HFILE GetFreeXparamStrucSlot ( VOID ) ;

static VOID     InitXParam      (   PSZ             pszDBRootPath,
                                    SQL_DBNAME      acXParamDBName,
                                    PATHNAME        acXParamFile        );

static VOID     PutXParam       (   LONG            lXParamFileID,
                                    XP_KEY_TYPEC    acXParamKeyC,
                                    XP_KEY_TYPE     acXParamKey,
                                    XP_PVALUE_REC   prcXParamValue,
                                    ERRORTEXT       acErrorText,
                                    XP_PRETURNCODE  pucXParamReturnCode );

static VOID     GetXParam       (   LONG            lXParamFileID,
                                    XP_KEY_TYPEC    acXParamKeyC,
                                    XP_KEY_TYPE     acXParamKey,
                                    XP_PVALUE_REC   prcXParamValue,
                                    ERRORTEXT       acErrorText,
                                    XP_PRETURNCODE  pucXParamReturnCode );

static VOID     NextXParam      (   LONG            lXParamFileID,
                                    XP_KEY_TYPEC    acXParamKeyC,
                                    XP_KEY_TYPE     acXParamKey,
                                    XP_PVALUE_REC   prcXParamValue,
                                    ERRORTEXT       acErrorText,
                                    XP_PRETURNCODE  pucXParamReturnCode );

static VOID     DeleteXParam    (   LONG            lXParamFileID,
                                    XP_KEY_TYPEC    acXParamKeyC,
                                    ERRORTEXT       acErrorText,
                                    XP_PRETURNCODE  pucXParamReturnCode );

static VOID     WriteXParamPage (   LONG            lXParamFileID,
                                    XP_KEY_TYPEC    acXParamKeyC,
                                    XP_PVALUE_REC   prcXParamValue,
                                    ERRORTEXT       acErrorText,
                                    XP_PRETURNCODE  pucXParamReturnCode );

static VOID     ReadXParamPage  (   LONG            lXParamFileID,
                                    XP_KEY_TYPE     acXParamKey,
                                    XP_PVALUE_REC   prcXParamValue,
                                    PULONG          pulReadBytes,
                                    ERRORTEXT       acErrorText,
                                    XP_PRETURNCODE  pucXParamReturnCode );

static VOID     FindXParamKey   (   LONG            lXParamFileID,
                                    XP_KEY_TYPEC    acXParamKeyC,
                                    UINT            unPrevActNext,
                                    PBOOLEAN        pbFound,
                                    ERRORTEXT       acErrorText,
                                    XP_PRETURNCODE  pucXParamReturnCode );

static VOID     OpenXParamFile  (   XP_PHFILE       plXParamFd,
                                    ERRORTEXT       acErrorText,
                                    PBOOLEAN        pbOk,
                                    PSZ             pszXParamFile,
                                    tsp_int1        OpenMode            );

static VOID     CloseXParamFile (   LONG            lXParamFileID,
                                    BOOLEAN         fFlush,
                                    ERRORTEXT       acErrorText,
                                    PBOOLEAN        pbOk                );

static BOOLEAN  SetFilePtrBeg   (   LONG            lXParamFileID ,
                                    ERRORTEXT       acErrorText,
                                    XP_PRETURNCODE  pucXParamReturnCode );

static VOID    ReadAllParams    (   LONG            lXParamFileID ,
                                    ERRORTEXT       acErrorText,
                                    XP_PRETURNCODE  pucXParamReturnCode );

static BOOLEAN ReallocParams    (   LONG            lXParamFileID ,
                                    LONG            NumNewParams ) ;

//
// ========================== GLOBAL FUNCTIONS ================================
//


VOID    sql11c_OpenXParam   (   PSZ         pszDBRootPath,
                                SQL_DBNAME  acServerDB,
                                XP_PHFILE   plXParamFd,
                                ERRORTEXT   acErrorText,
                                tsp_int1    OpenMode,
                                PBOOLEAN    pbOk            )
{
    #undef  MF__
    #define MF__ MOD__"sql11c_OpenXParam"


    PATHNAME    acXParamFile;

    DBGIN;

    // initialize outgoing parms
    *pbOk = TRUE;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));


    // open xparam file
    InitXParam ( pszDBRootPath, acServerDB, acXParamFile );

    OpenXParamFile ( plXParamFd, acErrorText, pbOk, acXParamFile, OpenMode );

    DBGOUT;
}


/*------------------------------*/

VOID    sql11c_CloseXParam  (   XP_HFILE    lXParamFd,
                                BOOLEAN     fFlush,
                                ERRORTEXT   acErrorText,
                                PBOOLEAN    pbOk            )
{
    #undef  MF__
    #define MF__ MOD__"sql11c_CloseXParam"


    DBGIN;

    // initialize outgoing parms
    *pbOk = TRUE;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));


    // close XPARAM file
    CloseXParamFile (( HFILE ) lXParamFd, fFlush, acErrorText, pbOk );

    DBGOUT;
}


/*------------------------------*/

VOID    sql11c_FsizeXParam  (   PSZ         pszDBRootPath,
                                SQL_DBNAME  acServerDB,
                                tsp_int4    *Fsize,
                                ERRORTEXT   acErrorText,
                                PBOOLEAN    pbOk         )
{
    #undef  MF__
    #define MF__ MOD__"sql11c_OpenXParam"


    PATHNAME    acXParamFile;
    LONG Attl ;
    ULONG FSizeLow, FSizeHigh ;
    APIRET rc ;

    DBGIN;

    InitXParam ( pszDBRootPath, acServerDB, acXParamFile );
    rc = sql44c_get_file_info ( acXParamFile, &Attl, &FSizeLow, &FSizeHigh ) ;
    *pbOk = rc == NO_ERROR ;
    if ( *pbOk )
      *Fsize = FSizeLow ;
    else
      {
        MSGCD (( ERR_ACCESS_XPARAM_FILE, rc ));
        sql46c_build_error_string ( acErrorText, ERRMSG_ACCESS_XPARAM_FILE, rc);
      }

    DBGOUT;
}

/*==========================================================================*/

XP_HFILE        sql11c_InitXparamStruc ( char     *XparamData,
                                         tsp_int4  XparamSize)
{
  XP_HFILE  lXParamFd = GetFreeXparamStrucSlot () ;

  if ( lXParamFd >= 0 )
    {
      XpData [ lXParamFd ].fFileIsNew  = FALSE ;
      XpData [ lXParamFd ].szXParamFile[0]  = '\0' ;
      XpData [ lXParamFd ].ulActParam  = 0 ;
      XpData [ lXParamFd ].ulMaxParams = XparamSize/XP_PAGE_SIZE + 1 ;
      XpData [ lXParamFd ].ulLastParam = XpData[ lXParamFd ].ulMaxParams ;
      XpData [ lXParamFd ].Xparams     = XparamData ;
      XpData [ lXParamFd ].hXParamFile = ( HFILE ) XparamData ; /* unused ! */
    }
  return ( lXParamFd ) ;
}

/*==========================================================================*/

VOID   sql11c_FreeXparamStruc ( XP_HFILE lXParamFd )
{
  XpData [ lXParamFd ].ulActParam    = 0 ;
  XpData [ lXParamFd ].ulLastParam   = 0 ;
  XpData [ lXParamFd ].ulMaxParams   = 0 ;
  XpData [ lXParamFd ].Xparams       = ( char *) NULL ;
  XpData [ lXParamFd ].hXParamFile   = ( HFILE ) NULL ;
}


/*------------------------------*/


VOID    sql11c_RenameXParam (   XP_HFILE        lXParamFd,
                                XP_KEY_TYPEC    acXParamOldKeyC,
                                XP_KEY_TYPEC    acXParamNewKeyC,
                                ERRORTEXT       acErrorText,
                                XP_PRETURNCODE  pucXParamReturnCode )

{
    #undef  MF__
    #define MF__ MOD__"sql11c_RenameXParam"

        BOOLEAN                 bFound;
        XP_KEY_TYPE             xp_key ;
        XP_VALUE_REC            xp_value ;


    DBGIN;

    // initialize outgoing parms
    *pucXParamReturnCode = XP_OK;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));

    // point to the beginning of the file
    DBG3 (( MF__, "lXParamFd = %ld", lXParamFd ));


    // look for the appropriate entries
    // identified by  xp key
    // check xuser key for blanks
    // if blank do nothing
    if ( BLANKS_ONLY ( acXParamOldKeyC ) || BLANKS_ONLY ( acXParamNewKeyC ) )
      {
        *pucXParamReturnCode = XP_NOT_OK;

        DBG1 (( MF__, ERRMSG_BLANK_XP_KEY ));
        MSGD (( ERR_BLANK_XP_KEY ));
        sql46c_build_error_string ( acErrorText, ERRMSG_BLANK_XP_KEY, 0 );

        DBGOUT;

        return;
      }

    FindXParamKey ( lXParamFd, acXParamNewKeyC, ACT,
                    &bFound, acErrorText, pucXParamReturnCode );

    if ( bFound )
      {
        *pucXParamReturnCode = XP_NOT_OK;

        sql46c_build_error_string ( acErrorText, "Parameter already in use!", 0 );
        DBGOUT;
        return;
      }

        if ( !SetFilePtrBeg ( lXParamFd, acErrorText, pucXParamReturnCode ) )
           return;

        sql47c_ctop ( xp_key , acXParamOldKeyC, sizeof ( XP_KEY_TYPE ));
	sql11c_GetXParam ( lXParamFd , xp_key,
                           &xp_value , acErrorText, pucXParamReturnCode ) ;

        if ( *pucXParamReturnCode == XP_OK )
	{
          if ( !SetFilePtrBeg ( lXParamFd, acErrorText, pucXParamReturnCode ) )
             return;

          FindXParamKey ( lXParamFd, acXParamOldKeyC, ACT,
                          &bFound, acErrorText, pucXParamReturnCode );

          sql47c_ctop ( xp_key , acXParamNewKeyC, sizeof ( XP_KEY_TYPE ));

          WriteXParamPage ( lXParamFd, xp_key, &xp_value,
                            acErrorText, pucXParamReturnCode ) ;

        }
}

/*------------------------------*/


VOID    sql11c_PutXParam    (   XP_HFILE        lXParamFd,
                                XP_KEY_TYPE     acXParamKey,
                                XP_PVALUE_REC   prcXParamValue,
                                ERRORTEXT       acErrorText,
                                XP_PRETURNCODE  pucXParamReturnCode )
{
    #undef  MF__
    #define MF__ MOD__"sql11c_PutXParam"


    XP_KEY_TYPEC    acXParamKeyc;


    DBGIN;

    // initialize outgoing parms
    *pucXParamReturnCode = XP_OK;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));


    // point to the beginning of the file
    DBG3 (( MF__, "lXParamFd = %ld", lXParamFd ));

    if ( !SetFilePtrBeg ( lXParamFd, acErrorText, pucXParamReturnCode ) )
        return;

    // convert pascal string to c string
    sql47c_ptoc ( acXParamKeyc, acXParamKey, sizeof ( XP_KEY_TYPE ));

    DBG3(( MF__, "acXParamKeyc = %s", acXParamKeyc ));


    // put param page into XPARAM file
    PutXParam (( HFILE ) lXParamFd, acXParamKeyc, acXParamKey,
                prcXParamValue, acErrorText, pucXParamReturnCode );

    DBGOUT;
}



/*------------------------------*/


VOID    sql11c_GetXParam    (   XP_HFILE        lXParamFd,
                                XP_KEY_TYPE     acXParamKey,
                                XP_PVALUE_REC   prcXParamValue,
                                ERRORTEXT       acErrorText,
                                XP_PRETURNCODE  pucXParamReturnCode )
{
    #undef  MF__
    #define MF__ MOD__"sql11c_GetXParam"


    XP_KEY_TYPEC    acXParamKeyc;

    DBGIN;

    // initialize outgoing parms
    *pucXParamReturnCode = XP_OK;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));


    // point to the beginning of the file
    if ( !SetFilePtrBeg ( lXParamFd, acErrorText, pucXParamReturnCode ) )
        return;

    // convert pascal string to c string

    sql47c_ptoc ( acXParamKeyc, acXParamKey, sizeof ( XP_KEY_TYPE ));

    DBG3(( MF__, "acXParamKeyc = %s", acXParamKeyc ));


    // get xparam page

    GetXParam (( HFILE ) lXParamFd, acXParamKeyc, acXParamKey,
                prcXParamValue, acErrorText, pucXParamReturnCode );

    DBGOUT;
}


/*------------------------------*/

void    sql11c_SeqNextXParam ( XP_HFILE        lXParamFd,
                               XP_KEY_TYPE     acXParamKey,
                               XP_PVALUE_REC   prcXParamValue,
                               ERRORTEXT       acErrorText,
                               XP_PRETURNCODE  pucXParamReturnCode )

{
    do {
         ReadXParamPage ( ( HFILE ) lXParamFd, acXParamKey, prcXParamValue,
                          NULL, acErrorText, pucXParamReturnCode );
       }
   while ( !( memcmp ( XP_DEL_KEY, acXParamKey, sizeof ( XP_KEY_TYPE )))
          && ( *pucXParamReturnCode == XP_OK ));

  return ;
}


/*------------------------------*/


VOID    sql11c_GetNextXParam    (   XP_HFILE        lXParamFd,
                                    XP_KEY_TYPE     acXParamKey,
                                    XP_KEY_TYPE     acXParamNextKey,
                                    XP_PVALUE_REC   prcXParamValue,
                                    ERRORTEXT       acErrorText,
                                    XP_PRETURNCODE  pucXParamReturnCode )
{
    #undef  MF__
    #define MF__ MOD__"sql11c_GetNextXParam"


    XP_KEY_TYPE     acXParamKeyTmp;
    XP_KEY_TYPEC    acXParamKeyc;

    DBGIN;

    // initialize outgoing parms
    *pucXParamReturnCode = XP_OK;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));
    memcpy ( acXParamKeyTmp, acXParamKey, sizeof ( XP_KEY_TYPE ));


    // point to the beginning of the file
    if ( !SetFilePtrBeg ( lXParamFd, acErrorText, pucXParamReturnCode ) )
      return;

    // convert pascal string to c string
    sql47c_ptoc ( acXParamKeyc, acXParamKey, sizeof ( XP_KEY_TYPE ));

    DBG3(( MF__, "acXParamKeyc = %s", acXParamKeyc ));


    // get xparam page
    NextXParam (( HFILE ) lXParamFd, acXParamKeyc, acXParamKeyTmp,
                 prcXParamValue, acErrorText, pucXParamReturnCode );

    memcpy ( acXParamNextKey, acXParamKeyTmp, sizeof ( XP_KEY_TYPE ));

    DBG3(( MF__, "acXParamKey     = %s",
                  _PToC ( acXParamKey, sizeof ( XP_KEY_TYPE ) )));
    DBG3(( MF__, "acXParamNextKey = %s",
                  _PToC ( acXParamNextKey, sizeof ( XP_KEY_TYPE ))));

    DBGOUT;
}


/*------------------------------*/


VOID    sql11c_DeleteXParam (   XP_HFILE        lXParamFd,
                                XP_KEY_TYPE     acXParamKey,
                                ERRORTEXT       acErrorText,
                                XP_PRETURNCODE  pucXParamReturnCode )
{
    #undef  MF__
    #define MF__ MOD__"sql11c_DeleteXParam"

    XP_KEY_TYPEC    acXParamKeyC;

    DBGIN;

    // initialize outgoing parms
    *pucXParamReturnCode = XP_OK;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));


    // point to the beginning of the file
    if ( !SetFilePtrBeg ( lXParamFd, acErrorText, pucXParamReturnCode ) )
      return;

    // convert pascal string to c string
    sql47c_ptoc ( acXParamKeyC, acXParamKey, sizeof ( XP_KEY_TYPE ));

    DBG3 (( MF__, "acXParamKeyC = %s", acXParamKeyC ));


    // delete xparam page
    DeleteXParam (( HFILE ) lXParamFd, acXParamKeyC,
                  acErrorText, pucXParamReturnCode );

    DBGOUT;
}

/*------------------------------*/

VOID    sql11c_SeqBinReadXParam ( XP_HFILE        lXParamFd,
                                  char           *buf ,
                                  ULONG           ulBytesToRead ,
	                          ULONG          *pulBytesRead,
                                  ERRORTEXT       acErrorText,
                                  XP_PRETURNCODE  pucXParamReturnCode )

{
  APIRET rc = READ_FILE ( XpData [ lXParamFd ] . hXParamFile ,
                          buf, ulBytesToRead , pulBytesRead );

  if ( rc )
    { DBG1 (( MF__, ERRMSG_READ_ERROR ));
      MSGCD (( ERR_READ_ERROR ));
      sql46c_build_error_string ( acErrorText, ERRMSG_READ_ERROR, 0 );
      *pucXParamReturnCode = XP_NOT_OK;
    }
  else
  if ( *pulBytesRead < ulBytesToRead )
    { *pucXParamReturnCode = XP_EOF;
      DBG1 (( MF__, ERRMSG_EOF_REACHED ));
      sql46c_build_error_string ( acErrorText, ERRMSG_EOF_REACHED, 0 );
    }
  else
    *pucXParamReturnCode = XP_OK;

  return  ;
}

/*------------------------------*/

VOID    sql11c_SeqBinWriteXParam ( XP_HFILE        lXParamFd,
                                   char           *buf ,
                                   ULONG           ulBytesToWrite ,
	                           ULONG          *pulBytesWritten,
                                   ERRORTEXT       acErrorText,
                                   XP_PRETURNCODE  pucXParamReturnCode )

{
  APIRET rc = WRITE_FILE ( XpData [ lXParamFd ] . hXParamFile ,
                           buf, ulBytesToWrite , pulBytesWritten );

  if ( rc || *pulBytesWritten != ulBytesToWrite )
    {
      *pucXParamReturnCode = XP_NOT_OK;
      DBG1 (( MF__, ERRMSG_WRITE_ERROR ));
      MSGCD (( ERR_WRITE_ERROR ));
      sql46c_build_error_string ( acErrorText, ERRMSG_EOF_REACHED, 0 );
    }
  else
    { *pucXParamReturnCode = XP_OK;
      XpData[lXParamFd].ulLastParam = XpData[lXParamFd].ulActParam =
                                      ulBytesToWrite / XP_PAGE_SIZE ;
    }

  return  ;
}

//
// ========================== LOCAL FUNCTIONS =================================
//

static XP_HFILE       GetFreeXparamStrucSlot ( VOID )

{
    XP_HFILE        lXParamFileID ;
    for ( lXParamFileID = 0; lXParamFileID < MAX_OPEN_PARAMS &&
          XpData[ lXParamFileID ].hXParamFile != (HFILE ) NULL ;
          lXParamFileID++ )
       {;}

    if ( XpData [ lXParamFileID ]. hXParamFile != (HFILE )NULL )
        lXParamFileID = -1 ;

    return ( lXParamFileID ) ;
}

/*------------------------------*/

static VOID InitXParam  (   PSZ         pszDBRootPath,
                            SQL_DBNAME  acXParamDBName,
                            PATHNAME    acXParamFile        )
{
    #undef  MF__
    #define MF__ MOD__"InitXParam"
    PSZ         pszConfigPath;
    SQL_DBNAMEC acXParamDBNameC;
    ULONG       ulLen;


    DBGIN;

    DBG3(( MF__, "acXParamDBName = %s",
                  _PToC ( acXParamDBName, sizeof ( SQL_DBNAME ) )));

    // clear acXParamFile ( name of the xparam file )
    memset ( acXParamFile, ' ', sizeof ( PATHNAME ));


    // convert pascal string to c string and truncate database name
    sql47c_ptoc ( acXParamDBNameC, acXParamDBName, sizeof ( SQL_DBNAME ));

    // truncate database name
    acXParamDBNameC[8] = '\0';

    DBG3 (( MF__, "acXParamDBNameC = %s", acXParamDBNameC ));


    sql01c_get_config_path ( &pszConfigPath );

    if (( strlen ( pszConfigPath )  +
          strlen ( acXParamDBNameC ) + 1 ) > sizeof ( PATHNAME )) {
        DBG1 (( MF__, "path too long for PARAM file" ));
        MSGCD (( ERR_PATH_TOO_LONG_FOR_XPF ));
        DBGOUT;
        return;
    }

    strcpy ( acXParamFile, pszConfigPath );
    ulLen = strlen(acXParamFile);
    if ( acXParamFile[ ulLen - 1 ] != '\\' )
     {
     acXParamFile[ ulLen ]     = '\\';
     acXParamFile[ ulLen + 1 ] = '\0';
     }

    strcat ( acXParamFile, acXParamDBNameC );

    DBG3 (( MF__, "acXParamFile ( no trace ) = %s", acXParamFile ));

#ifdef  TRACE
    DBG3 (( MF__, "acXParamDBNameC ( trace ) = %s", acXParamDBNameC ));

    memset ( acXParamFile, ' ', sizeof ( PATHNAME ));
    strcpy ( acXParamFile, acXParamDBNameC );

#endif  // TRACE

    DBG3 (( MF__, "acXParamDBNameC = %s", acXParamDBNameC ));
    DBG3 (( MF__, "acXParamFile = %s", acXParamFile ));

    DBGOUT;

}



/*------------------------------*/


static VOID PutXParam   (   LONG            lXParamFileID,
                            XP_KEY_TYPEC    acXParamKeyC,
                            XP_KEY_TYPE     acXParamKey,
                            XP_PVALUE_REC   prcXParamValue,
                            ERRORTEXT       acErrorText,
                            XP_PRETURNCODE  pucXParamReturnCode )
{
    #undef  MF__
    #define MF__ MOD__"PutXParam"

    BOOLEAN         bFound;

    DBGIN;

    DBG3 (( MF__, "acXParamKey = %s",
                   _PToC ( acXParamKey, sizeof ( XP_KEY_TYPE ) )));

#ifdef  DEBUG
    if ( prcXParamValue -> xp_value_t == XP_INT2_TYPE )
        DBG3 (( MF__, "prcXParamValue -> xp_int2 = %d",
                       prcXParamValue -> xp_type.xp_int2 ));

    if ( prcXParamValue -> xp_value_t == XP_INT4_TYPE )
        DBG3 (( MF__, "prcXParamValue -> xp_int4 = %ld",
                       prcXParamValue -> xp_type.xp_int4 ));

    if ( prcXParamValue -> xp_value_t == XP_C8_TYPE )
        DBG3 (( MF__, "prcXParamValue -> xp_c8 = %s",
                _PToC ( prcXParamValue -> xp_type.xp_c8,
                              sizeof ( prcXParamValue -> xp_type.xp_c8 ) )));

    if ( prcXParamValue -> xp_value_t == XP_C18_TYPE )
        DBG3 (( MF__, "prcXParamValue -> xp_c18 = %s",
                _PToC ( prcXParamValue -> xp_type.xp_c18,
                              sizeof ( prcXParamValue -> xp_type.xp_c18 ) )));

    if ( prcXParamValue -> xp_value_t == XP_C24_TYPE )
        DBG3 (( MF__, "prcXParamValue -> xp_c24 = %s",
                _PToC ( prcXParamValue -> xp_type.xp_c24,
                              sizeof ( prcXParamValue -> xp_type.xp_c24 ) )));

    if ( prcXParamValue -> xp_value_t == XP_C40_TYPE )
        DBG3 (( MF__, "prcXParamValue -> xp_c40 = %.40s",
                _PToC ( prcXParamValue -> xp_type.xp_c40,
                              sizeof (prcXParamValue -> xp_type.xp_c40) )));

    if ( prcXParamValue -> xp_value_t == XP_C64_TYPE )
        DBG3 (( MF__, "prcXParamValue -> xp_c64 = %s",
                _PToC ( prcXParamValue -> xp_type.xp_c64,
                              sizeof (prcXParamValue -> xp_type.xp_c64) )));

    if ( prcXParamValue -> xp_value_t == XP_CRYPT_TYPE )
        DBG3 (( MF__, "prcXParamValue -> xp_crypt", 0 ));
#endif  // DEBUG


    // initialize outgoing parms
    *pucXParamReturnCode = XP_OK;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));


    // look for the appropriate entries
    // identified by  xp key
    // check xparam key for blanks
    // if blank do nothing
    if ( BLANKS_ONLY ( acXParamKeyC )) {
        *pucXParamReturnCode = XP_NOT_OK;

        DBG1 (( MF__, ERRMSG_BLANK_XP_KEY ));
        MSGD (( ERR_BLANK_XP_KEY ));
        sql46c_build_error_string ( acErrorText, ERRMSG_BLANK_XP_KEY, 0 );

        DBGOUT;

        return;
    }


    // search for specified xparam key
    // and put the parameters into the
    // xparam file
    FindXParamKey ( lXParamFileID, acXParamKeyC, ACT,
                    &bFound, acErrorText, pucXParamReturnCode );

    if ( *pucXParamReturnCode == XP_NOT_OK ) {
        DBGOUT;

        return;
    }
    else {
        if ( bFound == TRUE ) {
            WriteXParamPage ( lXParamFileID,
                              acXParamKey, prcXParamValue,
                              acErrorText, pucXParamReturnCode );
        }
        else {
            // look for free space
            // in xparam file
            // point to the beginning of the file
            if ( !SetFilePtrBeg (lXParamFileID, acErrorText, pucXParamReturnCode))
              return;

            sql47c_ptoc ( acXParamKeyC, XP_DEL_KEY, sizeof ( XP_KEY_TYPE ));

            DBG3 (( MF__, "acXParamKeyC (delete key) = %s", acXParamKeyC ));

            FindXParamKey ( lXParamFileID, acXParamKeyC, ACT,
                            &bFound, acErrorText, pucXParamReturnCode );

            if ( *pucXParamReturnCode == XP_NOT_OK ) {
                DBGOUT;

                return;
            }


            // write xparam parameters
            WriteXParamPage ( lXParamFileID,
                              acXParamKey, prcXParamValue,
                              acErrorText, pucXParamReturnCode );
        }
    }

    DBGOUT;
}



/*------------------------------*/


static VOID GetXParam   (   LONG            lXParamFileID,
                            XP_KEY_TYPEC    acXParamKeyC,
                            XP_KEY_TYPE     acXParamKey,
                            XP_PVALUE_REC   prcXParamValue,
                            ERRORTEXT       acErrorText,
                            XP_PRETURNCODE  pucXParamReturnCode )
{
    #undef  MF__
    #define MF__ MOD__"GetXParam"


    BOOLEAN bFound;


    DBGIN;

    // initialize outgoing parms
    *pucXParamReturnCode = XP_OK;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));


    // look for the appropriate entries
    // identified by acXParamKey
    // check acXParamKey for blanks
    // it is prohibited to be clear
    if ( BLANKS_ONLY ( acXParamKeyC )) {
        *pucXParamReturnCode = XP_NOT_OK;

        DBG1 (( MF__, ERRMSG_BLANK_XP_KEY ));
        MSGD (( ERR_BLANK_XP_KEY ));
        sql46c_build_error_string ( acErrorText, ERRMSG_BLANK_XP_KEY, 0 );

        DBGOUT;

        return;
    }


    // search for specified xparam
    // key and get them
    FindXParamKey ( lXParamFileID, acXParamKeyC, ACT,
                    &bFound, acErrorText, pucXParamReturnCode );

    DBG3 (( MF__, "bFound ( FindXParamKey ) = %f", bFound ));

    if ( *pucXParamReturnCode == XP_NOT_OK ) {
        DBGOUT;

        return;
    }
    else {
        if ( bFound ) {
            // take over xparam information
            ReadXParamPage ( lXParamFileID, acXParamKey, prcXParamValue,
                             NULL, acErrorText, pucXParamReturnCode );

            // xp_eof not valid ( RTE spec )
            if ( *pucXParamReturnCode == XP_EOF ) {
                *pucXParamReturnCode = XP_KEY_NOT_FOUND;

                DBG1 (( MF__, ERRMSG_KEY_NOT_FOUND ));
                sql46c_build_error_string ( acErrorText, ERRMSG_KEY_NOT_FOUND, 0 );
            }
        }
        else {
            // no key found
            *pucXParamReturnCode = XP_KEY_NOT_FOUND;

            DBG1 (( MF__, ERRMSG_KEY_NOT_FOUND ));
            sql46c_build_error_string ( acErrorText, ERRMSG_KEY_NOT_FOUND, 0 );
        }
    }

    DBGOUT;

}



/*------------------------------*/


static VOID NextXParam  (   LONG            lXParamFileID,
                            XP_KEY_TYPEC    acXParamKeyC,
                            XP_KEY_TYPE     acXParamKey,
                            XP_PVALUE_REC   prcXParamValue,
                            ERRORTEXT       acErrorText,
                            XP_PRETURNCODE  pucXParamReturnCode )
{
    #undef  MF__
    #define MF__ MOD__"NextXParam"


    BOOLEAN bFound;


    DBGIN;

    // initialize outgoing parms
    *pucXParamReturnCode = XP_OK;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));


    // look for the appropriate entries
    // identified by acXParamKey
    // check acXParamKey for blanks
    // if blank acXParamKey return first
    // xparam entry
    if ( BLANKS_ONLY ( acXParamKeyC )) {
        // read xparam header and
        // take over xparam infomation
        // read until you have found a
        // key which is not equal
        // to xp_del_key
        ReadXParamPage ( lXParamFileID, acXParamKey, prcXParamValue,
                         NULL, acErrorText, pucXParamReturnCode );

        do {
            ReadXParamPage ( lXParamFileID, acXParamKey, prcXParamValue,
                             NULL, acErrorText, pucXParamReturnCode );
        } while ( !( memcmp ( XP_DEL_KEY,
                              acXParamKey,
                              sizeof ( XP_KEY_TYPE )))
                  && ( *pucXParamReturnCode == XP_OK ));

        DBGOUT;

        return;
    }


    // search for specified xparam
    // key and get them
    FindXParamKey ( lXParamFileID, acXParamKeyC, NEXT,
                    &bFound, acErrorText, pucXParamReturnCode );
    if ( *pucXParamReturnCode == XP_NOT_OK ) {
        DBGOUT;

        return;
    }
    else {
        if ( bFound ) {
            // take over xparam infomation
            // read until you have found a
            // key which is not equal
            // to xp_del_key
            do {
                ReadXParamPage ( lXParamFileID, acXParamKey, prcXParamValue,
                                 NULL, acErrorText, pucXParamReturnCode );
            } while (( memcmp ( XP_DEL_KEY,
                                acXParamKey,
                                sizeof ( XP_KEY_TYPE )) == 0 ) &&
                     ( *pucXParamReturnCode != XP_EOF ));
        }
        else {
            // no key found
            *pucXParamReturnCode = XP_KEY_NOT_FOUND;

            DBG1 (( MF__, ERRMSG_KEY_NOT_FOUND ));
            sql46c_build_error_string ( acErrorText, ERRMSG_KEY_NOT_FOUND, 0 );
        }
    }

    DBGOUT;

}


/*------------------------------*/


static VOID DeleteXParam    (   LONG            lXParamFileID,
                                XP_KEY_TYPEC    acXParamKeyC,
                                ERRORTEXT       acErrorText,
                                XP_PRETURNCODE  pucXParamReturnCode )
{
    #undef  MF__
    #define MF__ MOD__"DeleteXParam"


    BOOLEAN         bFound;
    XP_VALUE_REC    rcXParamValue;


    DBGIN;

    // initialize outgoing parms
    *pucXParamReturnCode  = XP_OK;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));


    // check xuser key for blanks
    // if blank do nothing
    if ( BLANKS_ONLY ( acXParamKeyC )) {
        *pucXParamReturnCode = XP_NOT_OK;

        DBG1 (( MF__, ERRMSG_BLANK_XP_KEY ));
        MSGD (( ERR_BLANK_XP_KEY ));
        sql46c_build_error_string ( acErrorText, ERRMSG_BLANK_XP_KEY, 0 );

        DBGOUT;

        return;
    }


    // search for specified xparam key
    // and put the xp_del_key into the
    // xparam file

    FindXParamKey ( lXParamFileID, acXParamKeyC, ACT,
                    &bFound, acErrorText, pucXParamReturnCode );

    if ( *pucXParamReturnCode == XP_NOT_OK ) {
        DBGOUT;

        return;
    }
    else {
        if ( bFound ) {
            // take over xparam infomation
            WriteXParamPage ( lXParamFileID,
                              XP_DEL_KEY, &rcXParamValue,
                              acErrorText, pucXParamReturnCode );
        }
        else {
            // no key found
            *pucXParamReturnCode = XP_KEY_NOT_FOUND;

            DBG1 (( MF__, ERRMSG_KEY_NOT_FOUND ));
            sql46c_build_error_string ( acErrorText, ERRMSG_KEY_NOT_FOUND, 0 );
        }
    }

    DBGOUT;

}



/*------------------------------*/


static VOID WriteXParamPage (   LONG            lXParamFileID,
                                XP_KEY_TYPEC    acXParamKeyC,
                                XP_PVALUE_REC   prcXParamValue,
                                ERRORTEXT       acErrorText,
                                XP_PRETURNCODE  pucXParamReturnCode )
{
    #undef  MF__
    #define MF__ MOD__"WriteXParamPage"


    char            Buf [ XP_PAGE_SIZE ] ;


    DBGIN;

    DBG3 (( MF__, "acXParamKeyC = %s", acXParamKeyC ));
    DBG3 (( MF__, "prcXParamValue -> xp_c64   = %s",
            _PToC ( prcXParamValue -> xp_type.xp_c64,
                          sizeof(prcXParamValue -> xp_type.xp_c64) )));


    // initialize return parameter
    *pucXParamReturnCode = XP_OK;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));


    // write key and value

    memcpy ( Buf, acXParamKeyC, sizeof ( XP_KEY_TYPE ) ) ;
    memcpy ( Buf + sizeof ( XP_KEY_TYPE ) , (char *) prcXParamValue,
                                       sizeof ( XP_VALUE_REC ) ) ;

    if ( XpData [ lXParamFileID ] . Xparams )
      {
        if ( XpData[ lXParamFileID ].ulActParam >=
             XpData[ lXParamFileID ].ulMaxParams )
          { if ( !ReallocParams ( lXParamFileID , NUM_NEW_PARAMS ) )
              { *pucXParamReturnCode = XP_NOT_OK;
	        return ;
	      }
	  }

        memcpy ( XpData[ lXParamFileID ].Xparams +
                 XpData[ lXParamFileID ].ulActParam * XP_PAGE_SIZE,
                 Buf, XP_PAGE_SIZE ) ;

        XpData[ lXParamFileID ].ulActParam ++ ;
        if ( XpData[ lXParamFileID ].ulActParam >
                                       XpData[ lXParamFileID ].ulLastParam )
           XpData[ lXParamFileID ].ulLastParam =
                                     XpData[ lXParamFileID ].ulActParam ;
      }
    else
      {
        ULONG           ulBytesWritten;
        APIRET          rc = NO_ERROR;
        rc = WRITE_FILE ( XpData [ lXParamFileID ] . hXParamFile ,
                          Buf, XP_PAGE_SIZE, &ulBytesWritten );
        if ( rc ) {
            *pucXParamReturnCode = XP_NOT_OK;

            DBG1 (( MF__, "ERROR[%d]:"ERRMSG_CANNOT_WRITE_XP_KEY, rc ));
            MSGCD (( ERR_CANNOT_WRITE_XP_KEY, rc ));
            sql46c_build_error_string ( acErrorText,
                                        ERRMSG_CANNOT_WRITE_XP_KEY, rc );

            DBGOUT;

            return;
        }

        if ( ulBytesWritten != XP_PAGE_SIZE ) {
            *pucXParamReturnCode = XP_NOT_OK;

            DBG1 (( MF__, ERRMSG_WRITE_ERROR ));
            MSGCD (( ERR_WRITE_ERROR ));
            sql46c_build_error_string ( acErrorText, ERRMSG_WRITE_ERROR, 0 );

            DBGOUT;

            return;
        }
    }

    DBGOUT;
}



/*------------------------------*/


static VOID ReadXParamPage (    LONG            lXParamFileID,
                                XP_KEY_TYPE     acXParamKey,
                                XP_PVALUE_REC   prcXParamValue,
                                PULONG          pulReadBytes,
                                ERRORTEXT       acErrorText,
                                XP_PRETURNCODE  pucXParamReturnCode )
{
    #undef  MF__
    #define MF__ MOD__"ReadXParamPage"


    ULONG           ulReadBytes;
    APIRET          rc = NO_ERROR;
    char            Buf [ XP_PAGE_SIZE ], *pBuf ;


    DBGIN;

    // initialize return parameter
    *pucXParamReturnCode = XP_OK;

    if ( pulReadBytes )
        *pulReadBytes = 0;

    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));


    if ( XpData [ lXParamFileID ] . Xparams )
      { if ( XpData [ lXParamFileID ] . ulActParam ==
             XpData [ lXParamFileID ] . ulLastParam )
          ulReadBytes = 0 ;
        else
          { ulReadBytes = XP_PAGE_SIZE ;
            pBuf = XpData [ lXParamFileID ] . Xparams +
                   XpData [ lXParamFileID ] . ulActParam * XP_PAGE_SIZE ;
            (XpData [ lXParamFileID ] . ulActParam)++ ;
          }
      }
    else
    // read key
      {  pBuf = Buf ;
         rc = READ_FILE ( XpData [ lXParamFileID ] . hXParamFile ,
                          pBuf, XP_PAGE_SIZE , &ulReadBytes );


        DBG3 (( MF__, "ulReadBytes ( acXParamKeyC ) = %ld", ulReadBytes ));

        if ( rc )
          { *pucXParamReturnCode = XP_NOT_OK;
            DBG1 (( MF__, "ERROR[%d]:"ERRMSG_CANNOT_READ_XP_KEY, rc ));
            MSGCD (( ERR_CANNOT_READ_XP_KEY, rc ));
            sql46c_build_error_string ( acErrorText,
                                        ERRMSG_CANNOT_READ_XP_KEY, rc );

            if ( pulReadBytes )
              *pulReadBytes = ulReadBytes;

            DBGOUT;
            return;
          }
      }

      if ( ulReadBytes == 0 )
        { *pucXParamReturnCode = XP_EOF;

          DBG1 (( MF__, ERRMSG_EOF_REACHED ));
          sql46c_build_error_string ( acErrorText, ERRMSG_EOF_REACHED, 0 );
          if ( pulReadBytes )
            *pulReadBytes = ulReadBytes;

          DBGOUT;
          return;
        }

    if ( ulReadBytes != XP_PAGE_SIZE )
      { *pucXParamReturnCode = XP_NOT_OK;

        DBG1 (( MF__, ERRMSG_READ_ERROR ));
        MSGCD (( ERR_READ_ERROR ));
        sql46c_build_error_string ( acErrorText, ERRMSG_READ_ERROR, 0 );

        if ( pulReadBytes )
          *pulReadBytes = ulReadBytes;

        DBGOUT;
        return;
      }

    DBG3 (( MF__, "acXParamKey = %s",
                   _PToC ( acXParamKey, sizeof ( XP_KEY_TYPE ) )));

    memcpy ( (char *) acXParamKey, pBuf, sizeof ( XP_KEY_TYPE ) ) ;
    memcpy ( (char *) prcXParamValue, pBuf + sizeof ( XP_KEY_TYPE ) ,
                                   sizeof ( XP_VALUE_REC ) ) ;

    if ( pulReadBytes )
        *pulReadBytes = ulReadBytes;

    DBGOUT;
}



/*------------------------------*/


static VOID FindXParamKey   (   LONG            lXParamFileID,
                                XP_KEY_TYPEC    acXParamKeyC,
                                UINT            unPrevActNext,
                                PBOOLEAN        pbFound,
                                ERRORTEXT       acErrorText,
                                XP_PRETURNCODE  pucXParamReturnCode )
{
    #undef  MF__
    #define MF__ MOD__"FindXParamKey"


    ULONG           ulPosition;
    ULONG           ulReadBytes;
    LONG            lPageCount;
    LONG            lOffset;
    XP_KEY_TYPE     acXParamKeyTmp;
    XP_VALUE_REC    rcXParamValueTmp;
    APIRET          rc = NO_ERROR;
    XP_KEY_TYPE     acXParamKey;


    DBGIN;

    DBG3 (( MF__, "acXParamKeyC = %s", acXParamKeyC ));
    DBG3 (( MF__, "unPrevActNext = %d", unPrevActNext ));


    // initialize return vars
    *pucXParamReturnCode = XP_OK;
    *pbFound             = FALSE;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));

    sql47c_ctop ( acXParamKey, acXParamKeyC, sizeof ( XP_KEY_TYPE ));

    // compare paramkeys
    do {
        // read actual acXParamKey and covert it to c string
        ReadXParamPage ( lXParamFileID, acXParamKeyTmp, &rcXParamValueTmp,
                         &ulReadBytes, acErrorText, pucXParamReturnCode );

        DBG3 (( MF__, "ulReadBytes = %ld", ulReadBytes ));
        DBG3 (( MF__, "acXParamKeyTmp = >>%s<<",
                _PToC ( acXParamKeyTmp, sizeof ( XP_KEY_TYPE ) )));
        DBG3 (( MF__, "acXParamKeyC = >>%s<<", acXParamKeyC ));
        DBG3 (( MF__, "sizeof (XP_KEY_TYPE) = %d", sizeof ( XP_KEY_TYPE )));

        if ( memcmp ( acXParamKey, acXParamKeyTmp,
                      sizeof ( XP_KEY_TYPE )) == 0 ) {
            *pbFound = TRUE;
            DBG3 (( MF__, "found key" ));
           }

    } while (( ulReadBytes > 0 ) && ( *pbFound == FALSE ));


    // EOF
    //if ( ulReadBytes == 0 )
    //    bEOF = TRUE;

    // now you are at the right position to read the
    // next xparam page
    //if (( nPrevActNext == NEXT ) && ( *pbFound == TRUE )) {
    //    // do nothing
    //}


    // put the file pointer at the beginning
    // of the actual xparam page
    if (( unPrevActNext == ACT ) && ( *pbFound == TRUE )) {
        // point to act pos :
        //  1. determine actual posiotion
        //  2. determine new position
        //  3. point to new position

        if ( XpData [ lXParamFileID ] . Xparams )
          (XpData [ lXParamFileID ] . ulActParam)-- ;
        else
          { rc = SET_FILE_PTR ( XpData [ lXParamFileID ] . hXParamFile ,
                                0, FILE_CURRENT, &ulPosition, NULL );

            if ( rc )
              { *pucXParamReturnCode = XP_NOT_OK;

                DBG1 (( MF__, "ERROR[%d]:"ERRMSG_CANNOT_FIND_ACT_ENTRY, rc ));
                MSGCD (( ERR_CANNOT_FIND_ACT_ENTRY, rc ));
                sql46c_build_error_string ( acErrorText,
                                            ERRMSG_CANNOT_FIND_ACT_ENTRY, rc );
                DBGOUT;
                return;
              }
            else
              { DBG3 (( MF__, "ulPosition ( 1.) = %ld", ulPosition ));
                lPageCount = ulPosition / XP_PAGE_SIZE ;
                DBG3 (( MF__, "lPageCount = %ld", lPageCount ));

                if ( lPageCount < 2 )
                  lPageCount = 2;                  // bTOF = TRUE;

                lOffset = ( lPageCount - 1 ) * XP_PAGE_SIZE ;
                DBG3 (( MF__, "lOffset = %ld", lOffset ));

                rc = SET_FILE_PTR ( XpData [ lXParamFileID ] . hXParamFile ,
                                    lOffset, FILE_BEGIN, &ulPosition, NULL );
                if ( rc )
                  { *pucXParamReturnCode = XP_NOT_OK;
                    DBG1 (( MF__, "ERROR[%d]:"ERRMSG_CANNOT_FIND_ACT_ENTRY,
                            rc ));
                    MSGCD (( ERR_CANNOT_FIND_ACT_ENTRY, rc ));
                    sql46c_build_error_string ( acErrorText,
                                             ERRMSG_CANNOT_FIND_ACT_ENTRY,rc );
                    DBGOUT;
                    return;
                  }
                DBG3 (( MF__, "ulPosition ( 2.) = %ld", ulPosition ));
            }
        }
    }

    // set pucXParamReturnCode
    if ( *pbFound == FALSE ) {
        *pucXParamReturnCode = XP_KEY_NOT_FOUND;

        DBG1 (( MF__, ERRMSG_CANNOT_FIND_ACT_ENTRY ));
        sql46c_build_error_string ( acErrorText, ERRMSG_KEY_NOT_FOUND, 0 );
    }

    //DBG3 (( MF__, "bEOF = %f", bEOF ));
    //DBG3 (( MF__, "bTOF = %f", bTOF ));
    DBG3 (( MF__, "*pbFound = %f", *pbFound ));

    DBGOUT;
}



/*------------------------------*/


static VOID OpenXParamFile  (   XP_PHFILE   plXParamFd,
                                ERRORTEXT   acErrorText,
                                PBOOLEAN    pbOk,
                                PSZ         pszXParamFile,
                                tsp_int1    OpenMode       )
{
    #undef  MF__
    #define MF__ MOD__"OpenXParamFile"


    HFILE           hXParamFile;
    PATHNAME        szPhysXParamFileName;
    ULONG           ulActionTaken;
    XP_VALUE_REC    rcXParamHeaderValue;
    XP_RETURNCODE   ucXParamReturnCode;
    APIRET          rc = NO_ERROR;
    ULONG           lXParamFileID;
    BOOLEAN         bCreate = ( OpenMode & XP_CREATE ) == XP_CREATE ;
    BOOLEAN         bOverwr = bCreate && (OpenMode & XP_OPEN_BIN) ==XP_OPEN_BIN;


    DBGIN;

    // initialize return vars
    *pbOk       = TRUE;
    *plXParamFd = UNDEF;
    memset (( char* ) acErrorText, ' ', sizeof ( ERRORTEXT ));

    DBG3 (( MF__, "Open xparam file: %s", pszXParamFile ));

    lXParamFileID = GetFreeXparamStrucSlot () ;

    if ( lXParamFileID < 0 )
      {
        *pbOk = FALSE;
        return ;
      }

    XpData[ lXParamFileID ].ulActParam  = 0 ;
    XpData[ lXParamFileID ].Xparams    = (char *)NULL ;
    strcpy ( XpData [ lXParamFileID ].szXParamFile, pszXParamFile )  ;

    sql44c_subst_log_parts ( szPhysXParamFileName, pszXParamFile ) ;

    // open or create xparm file
    #if defined(_WIN32)
      if ( bCreate ) {
          hXParamFile = (HFILE)CreateFile(szPhysXParamFileName,
                                          GENERIC_READ | GENERIC_WRITE,
                                          FILE_SHARE_READ,
                                          NULL,
                                bOverwr ? CREATE_ALWAYS : CREATE_NEW ,
                                          FILE_ATTRIBUTE_NORMAL |
                                          FILE_FLAG_WRITE_THROUGH,
                                          NULL);
          ulActionTaken = FILE_CREATED;
      }
      if (!bCreate || hXParamFile==(HFILE)INVALID_HANDLE_VALUE) {
          hXParamFile = (HFILE)CreateFile(szPhysXParamFileName,
                                          GENERIC_READ | GENERIC_WRITE,
                                          FILE_SHARE_READ,
                                          NULL,
                                          OPEN_EXISTING,
                                          FILE_ATTRIBUTE_NORMAL  |
                                          FILE_FLAG_WRITE_THROUGH ,
                                          NULL);
          ulActionTaken = FILE_EXISTED;
      }
      if (hXParamFile==(HFILE)INVALID_HANDLE_VALUE) rc = GetLastError();
      else rc = NO_ERROR;
    #else
      if ( bCreate ) {
        rc = DosOpen ( szPhysXParamFileName,
                       &hXParamFile,
                       &ulActionTaken,
                       0,                   //1781L,
                       FILE_NORMAL,
             bOverwr ? OPEN_ACTION_CREATE_IF_NEW    |
                       OPEN_ACTION_REPLACE_IF_EXISTS
                     : OPEN_ACTION_CREATE_IF_NEW    |
                       OPEN_ACTION_OPEN_IF_EXISTS,
                       OPEN_FLAGS_WRITE_THROUGH     | // Open mode of the file
                       OPEN_FLAGS_FAIL_ON_ERROR     |
                       OPEN_SHARE_DENYWRITE         |
                       OPEN_ACCESS_READWRITE,
                       NOEABUF );                     // No extended attributes
      }
      else {
        rc = DosOpen ( szPhysXParamFileName,
                       &hXParamFile,
                       &ulActionTaken,
                       0,                   //1781L,
                       FILE_NORMAL,
                       OPEN_ACTION_OPEN_IF_EXISTS   |
                       OPEN_ACTION_FAIL_IF_NEW,
                       OPEN_FLAGS_WRITE_THROUGH     | // Open mode of the file
                       OPEN_FLAGS_FAIL_ON_ERROR     |
                       OPEN_SHARE_DENYWRITE         |
                       OPEN_ACCESS_READWRITE,
                       NOEABUF );                     // No extended attributes
      }
    #endif
    if ( rc ) {
        DBG1 (( MF__, "ERROR[%d]:"ERRMSG_ACCESS_XPARAM_FILE, rc ));
        MSGCD (( ERR_ACCESS_XPARAM_FILE, rc ));
        sql46c_build_error_string ( acErrorText, ERRMSG_ACCESS_XPARAM_FILE, rc );
        *pbOk = FALSE;

        DBGOUT;

        return;
    }
    else {

        XpData [ lXParamFileID ] . hXParamFile = hXParamFile;
        XpData[ lXParamFileID ].fFileIsNew = ulActionTaken != FILE_EXISTED ;

        if ( OpenMode & XP_OPEN_REC )
          {
            if ( ulActionTaken == FILE_EXISTED )
              { LONG Attl ;
                ULONG FSizeLow, FSizeHigh ;
                if ( sql44c_get_file_info ( szPhysXParamFileName, &Attl,
                                            &FSizeLow, &FSizeHigh ) == NO_ERROR)
                   XpData [ lXParamFileID ].ulMaxParams =
                                             FSizeLow / XP_PAGE_SIZE + 1;
               }
            else
              XpData[ lXParamFileID ].ulMaxParams = NUM_START_PARAMS ;

            rc = ALLOC_MEM ( (PPVOID) & (XpData [ lXParamFileID ].Xparams),
                        XP_PAGE_SIZE * XpData [ lXParamFileID ].ulMaxParams );

            if ( rc != NO_ERROR )
              XpData [ lXParamFileID ].Xparams = NULL ;

            switch ( ulActionTaken ) {
                case FILE_EXISTED:
                    DBG3 (( MF__, "Open xparam file read/write" ));
                    ReadAllParams ( lXParamFileID, acErrorText,
                                    &ucXParamReturnCode );
                    if ( ucXParamReturnCode != XP_OK )
                      { BOOLEAN  fDummy ;
                        *pbOk = FALSE;
                        CloseXParamFile ( lXParamFileID , FALSE,
                                          acErrorText, &fDummy ) ;
                        DBGOUT;
                        return;
                      }
                    break ;

                case FILE_CREATED:
                    // install first entry :
                    // 1. write xp header
                    rcXParamHeaderValue.xp_value_t  = XP_INT4_TYPE;
                    rcXParamHeaderValue.xp_type.xp_int4 = 1781;

                    WriteXParamPage ( lXParamFileID,
                                      XP_HEADER_0,
                                      &rcXParamHeaderValue,
                                      acErrorText,
                                      &ucXParamReturnCode );

                    if ( ucXParamReturnCode != XP_OK ) {
                        BOOLEAN  fDummy ;
                        DBG1 (( MF__, ERRMSG_CANNOT_WRITE_XP_FILE ));
                        MSGD (( ERR_CANNOT_WRITE_XP_FILE ));
                        *pbOk = FALSE;

                        CloseXParamFile ( lXParamFileID , FALSE,
                                          acErrorText, &fDummy ) ;
                        DBGOUT;
                        return;
                    }

                    DBG3 (( MF__, "XParam file was created" ));
                    break ;

                default:
                    DBG1 (( MF__, ERRMSG_UNDEFINED_OPEN_MODE ));
                    MSGCD (( ERR_UNDEFINED_OPEN_MODE ));
                    sql46c_build_error_string ( acErrorText,
                                                ERRMSG_UNDEFINED_OPEN_MODE, 0 );
                    *pbOk = FALSE;

                    DBGOUT;
                    return;
            }
        }
      else
        {
          XpData [ lXParamFileID ].ulMaxParams = 0 ;
          XpData [ lXParamFileID ].Xparams = NULL ;
        }

      *plXParamFd = lXParamFileID;

      DBGOUT;
      return;
    }
}


/*------------------------------*/


static VOID CloseXParamFile (   LONG        lXParamFileID ,
                                BOOLEAN     fFlush,
                                ERRORTEXT   acErrorText,
                                PBOOLEAN    pbOk            )
{
    #undef  MF__
    #define MF__ MOD__"CloseXParamFile"


    DBGIN;

    *pbOk = lXParamFileID > -1 && lXParamFileID < MAX_OPEN_PARAMS ;
    if ( *pbOk )
      { if ( fFlush && XpData [ lXParamFileID ] . Xparams != ( char *) NULL
                    && XpData [ lXParamFileID ] .ulLastParam > 1 )
          { ULONG           ulFilePtr;
            APIRET          rc ;
            rc = SET_FILE_PTR ( XpData [ lXParamFileID ] . hXParamFile ,
                                0, FILE_BEGIN, &ulFilePtr, NULL);
            *pbOk = rc == NO_ERROR ;

            if ( *pbOk )
              { ULONG           ulBytesToWrite, ulBytesWritten, i, j ;

                for ( j=i=0; i< XpData [ lXParamFileID ] . ulLastParam ; i++ )
                  { char *act_param =XpData[ lXParamFileID ].Xparams
                                    + XP_PAGE_SIZE*i ;
                    if ( memcmp ( XP_DEL_KEY, act_param, sizeof(XP_KEY_TYPE) ))
                      { if ( i != j )
                          memcpy (XpData[ lXParamFileID ].Xparams +
                                  XP_PAGE_SIZE*j,
                                  act_param, XP_PAGE_SIZE ) ;
                         j++ ;
                       }
                    }
                XpData [ lXParamFileID ] .ulLastParam = j ;

                ulBytesToWrite = XpData [ lXParamFileID ] .ulLastParam
                                       * XP_PAGE_SIZE;
                rc = WRITE_FILE ( XpData [ lXParamFileID ] . hXParamFile ,
                                  XpData [ lXParamFileID ] . Xparams,
                                  ulBytesToWrite, &ulBytesWritten );
                if ( rc )
                  {
                    *pbOk = FALSE;
                    DBG1 (( MF__, "ERROR[%d]:"ERRMSG_CANNOT_WRITE_XP_KEY, rc ));
                    MSGCD (( ERR_CANNOT_WRITE_XP_KEY, rc ));
                    sql46c_build_error_string ( acErrorText,
                                                ERRMSG_CANNOT_WRITE_XP_KEY, rc);
                  }
                else
                if ( ulBytesWritten != ulBytesToWrite ||
                     !SetEndOfFile ( (HANDLE )XpData[ lXParamFileID ] . hXParamFile ) )
                  {
                    *pbOk = FALSE;
                    DBG1 (( MF__, ERRMSG_WRITE_ERROR ));
                    MSGCD (( ERR_WRITE_ERROR ));
                    sql46c_build_error_string ( acErrorText,
                                                ERRMSG_WRITE_ERROR, 0 );
                  }

              }
            else
              { DBG1 (( MF__, "ERROR[%d]:"ERRMSG_CANNOT_FIND_START_POINT, rc ));
                MSGCD (( ERR_CANNOT_FIND_START_POINT, rc ));
                sql46c_build_error_string ( acErrorText,
                                            ERRMSG_CANNOT_FIND_START_POINT, rc);

              }
          }
		/* ***** close XPARAN file ***** */

        CLOSE_FILE ( XpData [ lXParamFileID ] . hXParamFile );
        if ( XpData [ lXParamFileID ] .ulLastParam <= 1 &&
             XpData [ lXParamFileID ] .fFileIsNew )
           unlink ( XpData [ lXParamFileID ] . szXParamFile )  ;

        if ( XpData [ lXParamFileID ] . Xparams != ( char *) NULL )
          FREE_MEM ( (PVOID)XpData [ lXParamFileID ] . Xparams);
        memset ( &XpData [ lXParamFileID ] , 0, sizeof ( XP_DATA_STRUC )) ;
        DBG3 (( MF__, "XPARAM file closed" ));
    }
    DBGOUT;
}

/*------------------------------*/


static BOOLEAN  SetFilePtrBeg (   LONG            lXParamFileID,
                                  ERRORTEXT       acErrorText,
                                  XP_PRETURNCODE  pucXParamReturnCode )
{
    ULONG           ulFilePtr;
    APIRET          rc = NO_ERROR;

    if ( XpData [ lXParamFileID ] . Xparams )
      XpData [ lXParamFileID ] . ulActParam = 0 ;
    else
      { rc = SET_FILE_PTR ( XpData [ lXParamFileID ] . hXParamFile ,
                            0, FILE_BEGIN, &ulFilePtr, NULL);

        if ( rc ) {
            *pucXParamReturnCode = XP_NOT_OK;

            DBG1 (( MF__, "ERROR[%d]:"ERRMSG_CANNOT_FIND_START_POINT, rc ));
            MSGCD (( ERR_CANNOT_FIND_START_POINT, rc ));
            sql46c_build_error_string ( acErrorText,
                                        ERRMSG_CANNOT_FIND_START_POINT, rc );

            DBGOUT;
        }
    }
  return ( rc == NO_ERROR ) ;
}


/*==========================================================================*/

static VOID    ReadAllParams ( LONG            lXParamFileID ,
                               ERRORTEXT       acErrorText,
                               XP_PRETURNCODE  pucXParamReturnCode )
{

  int rc = NO_ERROR ;
  ULONG           ulReadBytes;

  *pucXParamReturnCode = XP_OK;
  if ( XpData [ lXParamFileID ].Xparams )
    {
    rc = READ_FILE ( XpData [ lXParamFileID ] . hXParamFile ,
                     XpData [ lXParamFileID ] . Xparams ,
                     XpData [ lXParamFileID ] . ulMaxParams * XP_PAGE_SIZE ,
                     &ulReadBytes );

    DBG3 (( MF__, "ulReadBytes ( acXParamKeyC ) = %ld", ulReadBytes ));

    if ( !rc ) {
      if ( ulReadBytes > 0 )
        { XpData [ lXParamFileID ] . ulLastParam = ulReadBytes / XP_PAGE_SIZE ;
          DBG3 (( MF__, "ulReadBytes %ld, ulLastParam = %ld",
                         ulReadBytes , XpData [ lXParamFileID ].ulLastParam ));
        }
      else
        { DBG1 (( MF__, ERRMSG_READ_ERROR ));
          MSGCD (( ERR_READ_ERROR ));
          sql46c_build_error_string ( acErrorText, ERRMSG_READ_ERROR, 0 );
          *pucXParamReturnCode = XP_NOT_OK;
        }
     }
   }
   return  ;
}

/*==========================================================================*/

static BOOLEAN ReallocParams ( LONG            lXParamFileID ,
                               LONG            NumNewParams )
{
  char *Buf ;
  APIRET  rc = ALLOC_MEM ( (PPVOID) & Buf, XP_PAGE_SIZE *
                       (XpData [ lXParamFileID ].ulMaxParams + NumNewParams)) ;

  if ( rc == NO_ERROR )
    { memcpy (Buf, XpData [ lXParamFileID ].Xparams,
              XP_PAGE_SIZE * XpData [ lXParamFileID ].ulMaxParams );

      FREE_MEM ( (PVOID)XpData [ lXParamFileID ] . Xparams);
      XpData [ lXParamFileID ] . Xparams = Buf ;
      XpData [ lXParamFileID ] . ulMaxParams += NumNewParams;
    }

  return ( rc == NO_ERROR ) ;
}

//
// =============================== END ========================================
//
.CM *-END-* code ----------------------------------------
.SP 2
***********************************************************
.PA
