Thread: Compiling C in Visual Studio 2005

  1. #1
    Registered User
    Join Date
    Jun 2005
    Posts
    20

    Compiling C in Visual Studio 2005

    Hello,
    I am looking to upgrade my programs from Microsoft C version 6 to Visual Studio 2005 and am trying to compile the btrieve program btrapi.c.

    Unfortunately I get these errors:

    c:\dev\c\btitypes.h(145) : error C2143: syntax error : missing '{' before '*'
    c:\dev\c\btitypes.h(146 ) : error C2143: syntax error : missing '{' before '*'
    c:\dev\c\btitypes.h(147) : error C2143: syntax error : missing '{' before '*'
    c:\dev\c\btitypes.h(148 ) : error C2143: syntax error : missing '{' before '*'
    c:\dev\c\btitypes.h(149) : error C2143: syntax error : missing '{' before '*'
    c:\dev\c\btitypes.h(150) : error C2143: syntax error : missing '{' before '*'
    c:\dev\c\btitypes.h(151) : error C2143: syntax error : missing '{' before '*'
    c:\dev\c\btitypes.h(152) : error C2143: syntax error : missing '{' before '*'
    c:\dev\c\btitypes.h(153) : error C2143: syntax error : missing '{' before '*'
    c:\dev\c\btrapi.h(179) : error C2061: syntax error : identifier 'BTRV'
    c:\dev\c\btrapi.h(179) : error C2059: syntax error : ';'
    c:\dev\c\btrapi.h(180) : error C2059: syntax error : 'type'
    c:\dev\c\btrapi.h(187) : error C2061: syntax error : identifier 'BTRVID'
    c:\dev\c\btrapi.h(187) : error C2059: syntax error : ';'
    c:\dev\c\btrapi.h(188 ) : error C2059: syntax error : 'type'
    c:\dev\c\btrapi.c(63) : error C2061: syntax error : identifier 'BTI_VOID_PTR'
    c:\dev\c\btrapi.c(64) : error C2059: syntax error : '}'
    c:\dev\c\btrapi.c(235) : error C2061: syntax error : identifier 'BTRVID'
    c:\dev\c\btrapi.c(235) : error C2059: syntax error : ';'
    c:\dev\c\btrapi.c(236) : error C2059: syntax error : 'type'
    c:\dev\c\btrapi.c(405) : error C2061: syntax error : identifier 'BTRV'
    c:\dev\c\btrapi.c(405) : error C2059: syntax error : ';'
    c:\dev\c\btrapi.c(406) : error C2059: syntax error : 'type'

    I think the first errors are something to do with pointers.

    The Build Log showed this under Command LIne:
    Creating temporary file "c:\dev\Debug\RSP00000436002804.rsp" with contents
    [
    /Od /I "C:\dev\c" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc80.pdb" /W3 /c /Wp64 /ZI /TC .\c\btrapi.c
    ]
    Creating command line "cl.exe @c:\dev\Debug\RSP00000436002804.rsp /nologo /errorReport: prompt"

    Any help gratefully received!

    Thanks,
    Bob

    BTITYPES.H
    Code:
    #ifndef _BTITYPES_H_INCLUDED
    /*************************************************************************
    **
    **  Copyright 1982-2008 Pervasive Software Inc. All Rights Reserved
    **
    *************************************************************************/
    /*************************************************************************
       BTITYPES.H
         This module contains platform-independent data types used by the
         Btrieve and Scalable SQL C/C++ Interface for MS Windows, OS2, DOS,
         Extended DOS, NetWare NLM, Windows 9x/Me, MS Windows NT/2000, and UNIX.
    
         You must define one of the following to your compiler in order to
         compile for a particular platform:
    
            BTI_DOS     - DOS Real Mode                           16-bit Apps
            BTI_DOS_32R - Extended DOS with Rational + bstub.exe  32-bit Apps
            BTI_DOS_32P - Extended DOS with Phar Lap 6.0          32-bit Apps
            BTI_DOS_32B - Extended DOS with Borland PowerPack     32-bit Apps
            BTI_DOS_16B - Extended DOS with Borland PowerPack     16-bit Apps
            BTI_WIN     - MS WINDOWS                              16-bit Apps
            BTI_WIN_32  - Windows NT and Windows 95               32-bit Apps
            BTI_WIN_64  - 64-bit Windows                          64-bit Apps
            BTI_OS2     - OS2                                     16-bit Apps
            BTI_OS2_32  - OS2                                     32-bit Apps
            BTI_NLM     - NetWare NLM                             32-bit Apps
            BTI_SQL     - For 32-Bit OS2 SSQL Apps
            BTI_SOL     - Solaris                                 32-bit Apps
            BTI_HPUX    - HP Unix
            BTI_AIX     - IBM Aix
            BTI_IRIX    - Irix
            BTI_DEC_UNIX  - DEC Unix
            BTI_LINUX   - Linux                                   32-bit Apps
            BTI_LINUX_64 - 64-bit Linux                           64-bit Apps
    
    
         If you do not specify one of the above switches to your compiler,
         an error directive in btitypes.h will halt the compilation.
    *************************************************************************/
    #if !defined(BTI_WIN)     && !defined(BTI_OS2)     && !defined(BTI_DOS) && \
        !defined(BTI_NLM)     && !defined(BTI_DOS_32R) && !defined(BTI_DOS_32P) && \
        !defined(BTI_DOS_32B) && !defined(BTI_WIN_32)  && !defined(BTI_OS2_32) && \
        !defined(BTI_DOS_16B) && !defined(BTI_SOL)     && !defined(BTI_HPUX) && \
        !defined(BTI_AIX)     && !defined(BTI_IRIX)    && !defined(BTI_DEC_UNIX) && \
        !defined(BTI_LINUX)   && !defined(BTI_WIN_64)  && !defined(BTI_LINUX_64)
    #error You must define one of the following: BTI_WIN, BTI_OS2, BTI_DOS, BTI_NLM, BTI_DOS_32R, BTI_DOS_32P, BTI_DOS_32B, BTI_WIN_32, BTI_OS2_32, BTI_DOS_16B, BTI_SOL, BTI_HPUX, BTI_AIX, BTI_IRIX, BTI_DEC_UNIX, BTI_LINUX, BTI_LINUX_64
    #endif
    
       /* ONLY FOR NLM APPS THAT PASS PARAMETERS IN REGISTERS */
       #if defined (__WATCOMC__) && defined (BTI_NLM)
          /***********************************************************************
             Declare one of the  following cdecl pragmas IF AND ONLY IF your
             NLM application is using register-based parameter-passing.  Most
             users will not have to modify this file.
          ***********************************************************************/
          /********************* WATCOM Compiler Version <= 8.5 ******************
           #define USING_REGISTERS
           #pragma aux cdecl "*" parm caller []\
                   value struct float struct routine [eax]\
                   modify [eax ecx edx fs gs 8087];
          ***********************************************************************/
          /********************* WATCOM Compiler Version >= 9.01 *****************
          #define USING_REGISTERS
          #pragma aux cdecl "*" parm caller []\
                  modify [eax ecx edx gs 8087];
          ***********************************************************************/
       #endif
    
      /* Platform-Dependent Definitions for BTI_FAR and BTI_PASCAL */
       #if defined(BTI_WIN)
          #define BTI_FAR       far
          #define BTI_PASCAL    pascal
       #endif
    
       #if defined(BTI_WIN_32) || defined(BTI_WIN_64)
         #include <windows.h>
         #define BTI_FAR
         #define BTI_PASCAL APIENTRY
       #endif
    
       #if defined(BTI_NLM) || defined(BTI_DOS_32R) || defined(BTI_DOS_32P)
          #define BTI_FAR
          #define BTI_PASCAL
       #endif
    
       #if defined(BTI_DOS_32B)
          #define BTI_FAR
          #define BTI_PASCAL pascal
       #endif
    
       #if defined(BTI_DOS_16B)
          #define BTI_FAR       far
          #define BTI_PASCAL    pascal
       #endif
    
       #if defined(BTI_OS2)
          #define BTI_FAR       far
          #define BTI_PASCAL    pascal
       #endif
    
       #if defined(BTI_DOS)
          #define BTI_FAR       far
          #define BTI_PASCAL
       #endif
    
     #if defined(BTI_OS2_32)
          #define BTI_FAR
          #define BTI_PASCAL    pascal
          #define INCL_BASE
          /* #include <os2.h> */
       #endif
    
       #if defined( BTI_OS2 ) || defined( BTI_OS2_32 )
       typedef unsigned short int BTI_SIZE;
       #else
       #include <stdlib.h>
       typedef size_t BTI_SIZE;
       #endif
    
       #define DDFAPICALLTYPE WINAPI
       #if defined(BTI_SOL) || defined(BTI_HPUX) || defined(BTI_AIX) || \
           defined(BTI_IRIX) || defined(BTI_DEC_UNIX) || defined(BTI_LINUX) || \
           defined(BTI_LINUX_64)
          #define BTI_FAR
          #define BTI_PASCAL
          #define WINAPI
       #endif
    
       #if !defined(BTI_LINUX_64)
       typedef long                  BTI_LONG;
       typedef unsigned long         BTI_ULONG;
       #else
       typedef int                   BTI_LONG;
       typedef unsigned int          BTI_ULONG;
       #endif
    
    
       /* Platform-Independent Data Types */
       typedef short int             BTI_SINT;
       typedef unsigned short        BTI_WORD;
       typedef int                   BTI_INT;
       typedef char                  BTI_CHAR;
       typedef unsigned char         BTI_BYTE;
       typedef void                  BTI_VOID;
       typedef BTI_CHAR     BTI_FAR* BTI_CHAR_PTR;   <<<< line 145 >>>>
       typedef BTI_BYTE     BTI_FAR* BTI_BUFFER_PTR;
       typedef BTI_SINT     BTI_FAR* BTI_SINT_PTR;
       typedef BTI_INT      BTI_FAR* BTI_INT_PTR;
       typedef BTI_WORD     BTI_FAR* BTI_WORD_PTR;
       typedef BTI_LONG     BTI_FAR* BTI_LONG_PTR;
       typedef BTI_ULONG    BTI_FAR* BTI_ULONG_PTR;
       typedef BTI_VOID     BTI_FAR* BTI_VOID_PTR;
       typedef BTI_SIZE     BTI_FAR* BTI_SIZE_PTR;
    
       #if defined (BTI_WIN_64)
       typedef signed __int64        BTI_LONGLONG;
       typedef signed __int64*       BTI_LONGLONG_PTR;
       #elif defined (BTI_LINUX_64)
       typedef long        BTI_LONGLONG;
       typedef long*       BTI_LONGLONG_PTR;
       #endif
    
       #if defined(BTI_WIN_64) || defined(BTI_LINUX_64)
       typedef BTI_LONGLONG          BTI_PTR_CAST;
       #else
       typedef BTI_LONG              BTI_PTR_CAST;
       #endif
    
       /***********************************************************************
          Currently, OS2 32-bit Scalable SQL applications must be passed to a
          16-bit entry point.   BTI_SQL is temporary until there is a 32-bit
          entry point for Scalable SQL applications on OS2.
       ************************************************************************/
       #if defined( BTI_OS2_32 ) && defined( BTI_SQL )
       #include <os2def.h>
       #if defined( __BORLANDC__ )
       #define BTI_CHAR_PTR    BTI_CHAR  FAR16PTR
       #define BTI_BUFFER_PTR  BTI_BYTE  FAR16PTR
       #define BTI_SINT_PTR    BTI_SINT  FAR16PTR
       #define BTI_INT_PTR     BTI_INT   FAR16PTR
       #define BTI_WORD_PTR    BTI_WORD  FAR16PTR
       #define BTI_LONG_PTR    BTI_LONG  FAR16PTR
       #define BTI_ULONG_PTR   BTI_ULONG FAR16PTR
       #define BTI_VOID_PTR    BTI_VOID  FAR16PTR
       #define BTI_SIZE_PTR    BTI_SIZE  FAR16PTR
       #else   /* IBM Visual Age Compiler, others */
       #define BTI_CHAR_PTR    BTI_CHAR  * _Seg16
       #define BTI_BUFFER_PTR  BTI_BYTE  * _Seg16
       #define BTI_SINT_PTR    BTI_SINT  * _Seg16
       #define BTI_INT_PTR     BTI_INT   * _Seg16
       #define BTI_WORD_PTR    BTI_WORD  * _Seg16
       #define BTI_LONG_PTR    BTI_LONG  * _Seg16
       #define BTI_ULONG_PTR   BTI_ULONG * _Seg16
       #define BTI_VOID_PTR    BTI_VOID  * _Seg16
       #define BTI_SIZE_PTR    BTI_SIZE  * _Seg16
       #endif
       #endif
    
       #if defined(USING_REGISTERS)
       #define BTI_API extern BTI_SINT BTI_FAR BTI_PASCAL cdecl
       #endif
    
       #if !defined(USING_REGISTERS)  && !defined( BTI_OS2_32 ) && \
           !defined( BTI_WIN_32 ) && !defined( BTI_WIN_64 )
       #define BTI_API extern BTI_SINT BTI_FAR BTI_PASCAL
       #endif
    
       #if defined( BTI_OS2_32 )
       #if defined( BTI_SQL )
       #define BTI_API BTI_SINT APIENTRY16
       #else
       #define BTI_API BTI_SINT APIENTRY
       #endif
       #endif
    
       #if defined( BTI_WIN_32 ) || defined( BTI_WIN_64 )
       #include <windef.h>
       #define BTI_API extern BTI_SINT BTI_FAR WINAPI
       #endif
    
       /* Callback Functions Data Types for MS Windows Applications */
       #ifndef SWIG
       #if defined(BTI_WIN) || defined(BTI_WIN_32) || defined(BTI_WIN_64)
    
       typedef struct
       {
          BTI_WORD iSessionID;
       } NWSQL_YIELD_T;
    
       typedef struct
       {
          BTI_WORD  iOpCode;
          BTI_BYTE  bClientIDlastFour[ 4 ];
       } BTRV_YIELD_T;
    
       typedef struct
       {
          BTI_WORD type;
          BTI_WORD size;
          union
          {
              NWSQL_YIELD_T sYield;
              BTRV_YIELD_T  bYield;
          } u;
       } BTI_CB_INFO_T;
    
       typedef BTI_SINT ( BTI_FAR BTI_PASCAL *BTI_CB_FUNC_PTR_T ) (
                                            BTI_CB_INFO_T BTI_FAR *bCallbackInfo,
                                            BTI_VOID_PTR           bUserData );
    
       #endif
       #endif /* SWIG */
    
    #define _BTITYPES_H_INCLUDED
    #endif
    BTRAPI.H
    Code:
    #ifndef _BTRAPI_H_INCLUDED
    /*************************************************************************
    **
    **  Copyright 1982-2008 Pervasive Software Inc. All Rights Reserved
    **
    *************************************************************************/
    /***************************************************************************
     BTRAPI.H
        This file contains prototypes for the DOS, Extended DOS, MS Windows,
        MS Windows NT, MS Windows 95, OS2, NLM, and Unix Btrieve call.   The
        calling application may be C or C++.
    
        You must define one of the following to your compiler in order to
        compile for a particular platform:
    
            BTI_DOS     - DOS                                     16-bit Apps
            BTI_DOS_32R - Extended DOS with Rational + bstub.exe  32-bit Apps
            BTI_DOS_32P - Extended DOS with Phar Lap 6.0          32-bit Apps
            BTI_DOS_32B - Extended DOS with Borland PowerPack     32-bit Apps
            BTI_DOS_16B - Extended DOS with Borland PowerPack     16-bit Apps
            BTI_WIN     - MS WINDOWS                              16-bit Apps
            BTI_WIN_32  - Windows NT and Windows 95               32-bit Apps
            BTI_WIN_64  - 64-bit Windows                          64-bit Apps
            BTI_OS2     - OS2                                     16-bit Apps
            BTI_OS2_32  - OS2                                     32-bit Apps
            BTI_NLM     - NetWare NLM                             32-bit Apps
            BTI_SQL     - For 32-Bit OS2 SSQL Apps
            BTI_SOL     - Solaris                                 32-bit Apps
            BTI_HPUX    - HP Unix
            BTI_AIX     - IBM Aix
            BTI_IRIX    - Irix
            BTI_DEC_UNIX  - DEC Unix
            BTI_LINUX   - Linux
            BTI_LINUX_64   - 64-bit Linux        
    
        If you do not specify one of the above switches to your compiler,
        an error directive will halt the compilation.
    
        Modules are:
          btrapi.c     - compile and link with all apps except NLMs
          btrsamp.c    - sample program which can be compiled for any platform
          btitypes.h   - platform-independent data types
          blobhdr.h    - used by apps which use BTI_DOS_32B or BTI_DOS_32P
          btrapi.h     - included by all apps
          btrconst.h   - Btrieve constants
          bmemcopy.obj - used by apps which use BTI_DOS_32B or BTI_DOS_32P
          w3btrv7.lib  - used by 32-bit apps; versions are provided for
                         Microsoft Visual C++ apps ("COFF" format) and
                         Borland, Watcom, and other compilers ( see NT note
                         below )
          w64btrv7.lib  - used by 64-bit apps; versions are provided for
                         Microsoft Visual C++ apps 
    
        Except for DOS or Extended DOS, the Btrieve application developer will
        also need either an import library or linker import statements to
        identify the imported Btrieve functions to the linker.  The imported
        functions are:
    
          MS Windows
          ----------
          W1BTRV7.LIB  - WBTRVINIT, WBRQSHELLINIT, WBTRVSTOP, BTRCALL,
                         BTRCALLID, BTRCALLBACK, RQSHELLINIT
          NT and WIN95
          -------------
          W3BTRV7.LIB - WBTRVINIT, WBRQSHELLINIT, WBTRVSTOP, BTRCALL,
                        BTRCALLID, BTRCALLBACK, RQSHELLINIT ( see NT note below )
    
    
          64-bit Windows
          -------------
          W64BTRV7.LIB - WBTRVINIT, WBRQSHELLINIT, WBTRVSTOP, BTRCALL,
                         BTRCALLID, BTRCALLBACK, RQSHELLINIT 
    
          OS2
          ---
          O3BTRV7.LIB - BTRVINIT,  BRQSHELLINIT,  BTRVSTOP,  BTRCALL
    
          NLM
          ---
          Use linker import statements - btrv, btrvID
    
          Unix
          -------
          RDA - Tbd
    
        You will need to compile and link 'btrapi.c' if you call any of
        the following functions from the indicated platforms:
              BTRV .......... MS Windows, OS2, DOS
              BTRVID ........ MS Windows, OS2, DOS
              RQSHELLINIT ... MS Windows
    
        For 32-Bit DOS Rational Applications Using Bstub
        ------------------------------------------------
        If you are using the Rational Systems DOS Extender, DOS4G.EXE, along
        with BSTUB.EXE, you will need to define the plaform switch,
        BTI_DOS_32R to your compiler.  You also must link your application
        using the Rational linker, GLU.EXE.  You MUST have a '.def' file
        similar to the following which is used to create a 32-bit btrsamp.exe:
    
             btrsamp.def
             -----------
                LIBRARY btrsamp.dll
                DATA NONSHARED
                EXPORTS
                   __ImportedFunctions_
    
        The module, btrapi.c, requires '__ImportedFunctions_' as shown in
        the above btrsamp.def.  This allows btrapi.c to call a function
        in Btrieve without using int386.
    
        Depending on your compiler's naming conventions, you may need to
        add a leading underscore to '_ImportedFunctions' at 3 locations in
        btrapi.c.  For example, when you compile with WATCOM using register-based
        parameter-passing, no change to '_ImportedFunctions' is needed.  But
        if you compile using stack-based parameter-passing, you will need to
        change '_ImportedFunctions' to '__ImportedFunctions' in btrapi.c.  We
        could have added compiler predefined macros to btrapi.c to handle
        this naming problem for you, except we were not assured of the
        predefined macros being present in all cases.
    
        The following is the GLU '.lnk' file for sqlsamp.exe using WATCOM
        libraries:
    
              btrsamp.lnk
              -----------
                btrsamp.obj
                btrapi.obj
                -format lin -stack 40000 -dbg -stub bstub.exe
                e(btrsamp)
                m(btrsamp)
                dos32wc.lib
                clib3r.lib
                math3r.lib
                math387r.lib
                emu387.lib
    
        You invoke GLU.EXE as follows:
    
                glu -deffile btrsamp.def @btrsamp.lnk
    
    
        For 32-Bit Borland PowerPack and Phar Lap DOS Applications
        -----------------------------------------------------------
        You must link 'bmemcopy.obj' with your application.
    
       For 32-Bit NT, Win95, and Win32s Applications
       ---------------------------------------------
       - If using WATCOM, you must use version 10.5 or later.  Earlier versions
         do not understand the format of the import library, w3btrv7.lib.
    
       - If you are using a compiler that complains that w3btrv7.lib has
         an invalid format, you will need to get a version of that compiler that
         understands the 'coff' format used by Microsoft Visual C++.
    
    
    ***************************************************************************/
    #if !defined(BTI_WIN)     && !defined(BTI_OS2)     && !defined(BTI_DOS) && \
        !defined(BTI_NLM)     && !defined(BTI_DOS_32R) && !defined(BTI_DOS_32P) && \
        !defined(BTI_DOS_32B) && !defined(BTI_WIN_32)  && !defined(BTI_OS2_32) && \
        !defined(BTI_DOS_16B) && !defined(BTI_SOL)     && !defined(BTI_HPUX) && \
        !defined(BTI_AIX)     && !defined(BTI_IRIX)    && !defined(BTI_DEC_UNIX) && \
        !defined(BTI_LINUX)   && !defined(BTI_WIN_64)  && !defined(BTI_LINUX_64)
    #error You must define one of the following: BTI_WIN, BTI_OS2, BTI_DOS, BTI_NLM, BTI_DOS_32R, BTI_DOS_32P, BTI_DOS_32B, BTI_WIN_32, BTI_OS2_32, BTI_DOS_16B, BTI_SOL, BTI_HPUX, BTI_AIX, BTI_IRIX, BTI_DEC_UNIX, BTI_LINUX, BTI_WIN_64, BTI_LINUX_64
    #endif
    
    #include "btitypes.h"
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    /***************************************************************************
       PLATFORM-INDEPENDENT FUNCTIONS
         These APIs are the same on all platforms for which they have
         an implementation.  We recommend that you use only these two
         functions with Btrieve 6.x client components, and then issue the
         B_STOP operation prior to exiting your application.
    ****************************************************************************/
    BTI_API BTRV(                                   <<<< line 179 >>>>
               BTI_WORD     operation,
               BTI_VOID_PTR posBlock,
               BTI_VOID_PTR dataBuffer,
               BTI_WORD_PTR dataLength,
               BTI_VOID_PTR keyBuffer,
               BTI_SINT     keyNumber );
    
    BTI_API BTRVID(
               BTI_WORD       operation,
               BTI_VOID_PTR   posBlock,
               BTI_VOID_PTR   dataBuffer,
               BTI_WORD_PTR   dataLength,
               BTI_VOID_PTR   keyBuffer,
               BTI_SINT       keyNumber,
               BTI_BUFFER_PTR clientID );
    
    /***************************************************************************
       PLATFORM-SPECIFIC FUNCTIONS
          These APIs are specific to the indicated platform.  With the
          exception of BTRCALLBACK, we recommend that you use either
          BTRV or BTRVID, shown above.  Slight performance gains can be
          achieved by using BTRCALL or BTRCALLID.
    ****************************************************************************/
    #if defined( BTI_NLM )
    BTI_API btrv(
               BTI_WORD     operation,
               BTI_VOID_PTR posBlock,
               BTI_VOID_PTR dataBuffer,
               BTI_WORD_PTR dataLength,
               BTI_VOID_PTR keyBuffer,
               BTI_SINT     keyNumber );
    #define BTRV( a, b, c, d, e, f )  btrv( a, b, c, d, e, f )
    
    BTI_API btrvID(
               BTI_WORD       operation,
               BTI_VOID_PTR   posBlock,
               BTI_VOID_PTR   dataBuffer,
               BTI_WORD_PTR   dataLength,
               BTI_VOID_PTR   keyBuffer,
               BTI_SINT       keyNumber,
               BTI_BUFFER_PTR clientID );
    #define BTRVID( a, b, c, d, e, f, g )  btrvID( a, b, c, d, e, f, g )
    #endif
    
    #if defined( BTI_WIN ) || defined( BTI_OS2 )
    BTI_API BTRCALL(
               BTI_WORD     operation,
               BTI_VOID_PTR posBlock,
               BTI_VOID_PTR dataBuffer,
               BTI_WORD_PTR dataLength,
               BTI_VOID_PTR keyBuffer,
               BTI_BYTE     keyLength,
               BTI_CHAR     ckeynum );
    
    BTI_API BTRCALLID(
               BTI_WORD       operation,
               BTI_VOID_PTR   posBlock,
               BTI_VOID_PTR   dataBuffer,
               BTI_WORD_PTR   dataLength,
               BTI_VOID_PTR   keyBuffer,
               BTI_BYTE       keyLength,
               BTI_CHAR       ckeynum,
               BTI_BUFFER_PTR clientID );
    #endif
    
    #if defined( BTI_WIN_32) || defined( BTI_OS2_32 ) || defined( BTI_SOL ) || \
        defined( BTI_HPUX) || defined( BTI_AIX ) || defined( BTI_IRIX ) || \
        defined( BTI_DEC_UNIX) || defined(BTI_LINUX) || defined ( BTI_WIN_64) || \
        defined( BTI_LINUX_64)
    #if defined( BTI_OS2_32 )
    #define BTRCALL   BTRCALL32
    #define BTRCALLID BTRCALLID32
    #endif
    BTI_API BTRCALL(
               BTI_WORD      operation,
               BTI_VOID_PTR  posBlock,
               BTI_VOID_PTR  dataBuffer,
               BTI_ULONG_PTR dataLength,
               BTI_VOID_PTR  keyBuffer,
               BTI_BYTE      keyLength,
               BTI_CHAR      ckeynum );
    
    BTI_API BTRCALLID(
               BTI_WORD       operation,
               BTI_VOID_PTR   posBlock,
               BTI_VOID_PTR   dataBuffer,
               BTI_ULONG_PTR  dataLength,
               BTI_VOID_PTR   keyBuffer,
               BTI_BYTE       keyLength,
               BTI_CHAR       ckeynum,
               BTI_BUFFER_PTR clientID );
    #endif
    
    #if defined( BTI_WIN ) || defined( BTI_WIN_32 ) || defined( BTI_WIN_64 )
    BTI_API BTRCallback(
               BTI_WORD                   iAction,
               BTI_WORD                   iOption,
               BTI_CB_FUNC_PTR_T          fCallBackFunction,
               BTI_CB_FUNC_PTR_T BTI_FAR *fPreviousCallBackFunction,
               BTI_VOID_PTR               bUserData,
               BTI_VOID_PTR BTI_FAR      *bPreviousUserData,
               BTI_BUFFER_PTR             bClientID );
    #endif
    
    
    /***************************************************************************
       HISTORICAL FUNCTIONS
          These APIs were needed prior to Btrieve 6.x client
          components.  Older applications may still call these functions,
          and the newer Btrieve client components will do the appropriate
          thing, depending on the platform.  New applications using the
          newer client components do NOT have to call these functions.
    ****************************************************************************/
    #if defined( BTI_WIN ) || defined( BTI_WIN_32 )
    #define BTRVINIT WBTRVINIT
    #define BTRVSTOP WBTRVSTOP
    BTI_API WBTRVINIT( BTI_CHAR_PTR option );
    BTI_API WBRQSHELLINIT( BTI_CHAR_PTR option );
    BTI_API WBTRVSTOP( BTI_VOID );
    BTI_API RQSHELLINIT( BTI_CHAR_PTR options );
    #endif
    
    #if defined( BTI_OS2 )
    BTI_API BTRVINIT( BTI_CHAR_PTR options );
    BTI_API BTRVSTOP( BTI_VOID );
    BTI_API BRQSHELLINIT( BTI_VOID );
    #endif
    
    #if defined( BTI_OS2_32 )
    BTI_API BTRVINIT32( BTI_CHAR_PTR options );
    BTI_API BTRVSTOP32( BTI_VOID );
    BTI_API BRQSHELLINIT32( BTI_VOID );
    #endif
    
    #ifdef __cplusplus
    }
    #endif
    
    #define _BTRAPI_H_INCLUDED
    #endif
    BTRAPI.C
    Code:
    #define BTI_DOS
    /*************************************************************************
    **
    **  Copyright 1982-2007 Pervasive Software Inc. All Rights Reserved
    **
    *************************************************************************/
    /*************************************************************************
       BTRAPI.C
         This module implements the Btrieve Interface for C/C++ applications
         using MS Windows, Windows 9x/Me, Windows NT/2000, OS2, DOS, Extended DOS, 
         and 64-bit versions of Windows.
         An NLM application does not need to compile and link this module.
    
         You must select a target platform switch.  See the prologue inside
         'btrapi.h' for a list of platform switches.
    
         IMPORTANT
         ---------
         Pervasive Software Inc., invites you to modify this file
         if you find it necessary for your particular situation.  However,
         we cannot provide technical support for this module if you
         do modify it.
    
    *************************************************************************/
    
    #if !defined(BTI_WIN) && !defined(BTI_OS2) && !defined(BTI_DOS) \
    && !defined(BTI_NLM) && !defined(BTI_DOS_32R) && !defined(BTI_DOS_32P) \
    && !defined(BTI_DOS_32B) && !defined(BTI_WIN_32) && !defined(BTI_OS2_32) \
    && !defined(BTI_WIN_64) && !defined(BTI_LINUX) && !defined(BTI_LINUX_64)
    #error You must define one of the following: BTI_WIN, BTI_OS2, BTI_DOS, BTI_NLM, BTI_DOS_32R, BTI_DOS_32P, BTI_DOS_32B, BTI_WIN_32, BTI_OS2_32, BTI_WIN_64, BTI_LINUX, BTI_LINUX_64
    #endif
    
    #include <btrconst.h>
    #include <btrapi.h>
    #include <string.h>
    
    #if defined( BTI_DOS )     || defined( BTI_DOS_32R ) || \
        defined( BTI_DOS_32P ) || defined( BTI_DOS_32B )
    #include <dos.h>
    
    #define BTR_INTRPT       0x7B       /* Btrieve interrupt vector */
    #define BTR_OFFSET       0x33       /* Btrieve offset within segment */
    #define VARIABLE_ID      0x6176     /* id for variable length records - 'va' */
    #define PROTECTED_ID     0x6370     /* id for protected call - 'pc' */
    #define VERSION_OFFSET   0
    #define REVISION_OFFSET  2
    #define TYPE_OFFSET      4
    #define VERSION_BUF_SIZE 5
    #define BTRV_CODE        7
    #define TRUE             1
    #define FALSE            0
    
    typedef unsigned char    BOOLEAN;
    
    /* Protected Mode switch parameter block */
    typedef struct
    {
       BTI_CHAR      sign[ 4 ];
       BTI_ULONG     flags;
       BTI_ULONG     functionCode;
       BTI_LONG      pmSwitchStatus;
       BTI_LONG      dataLength;
       BTI_VOID_PTR  dataPtr;                 <<<< line 63 >>>>
    } pmswParmBlock;
    #endif /* BTI_DOS || BTI_DOS_32R || BTI_DOS_32P || BTI_DOS_32B */
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    /***************************************************************************
       PROCESS7B IS IN PMSWITCH, AND IS RESOLVED AT RUN-TIME
    ***************************************************************************/
    #if defined( BTI_DOS_32R )
    typedef struct
    {
       char  *Name;
       void  cdecl (*functionPtr) ( pmswParmBlock *bP );
    } IMPORTS[];
    #define PROCESS7B 75
    IMPORTS * _ImportedFunctions_ = 0;
    #endif /* BTI_DOS_32R */
    
    /****************************************************************************
       RQSHELLINIT() Function for MS Windows
    ***************************************************************************/
    #if defined( BTI_WIN ) || defined( BTI_WIN_32 )
    BTI_API RQSHELLINIT( BTI_CHAR_PTR option )
    {
       return WBRQSHELLINIT( option );
    }
    #endif
    
    /****************************************************************************
       BTRV() Function for 16-Bit MS Windows or OS2
    ***************************************************************************/
    #if defined( BTI_WIN ) || defined( BTI_OS2 )
    BTI_API BTRV(
               BTI_WORD     operation,
               BTI_VOID_PTR posBlock,
               BTI_VOID_PTR dataBuffer,
               BTI_WORD_PTR dataLength,
               BTI_VOID_PTR keyBuffer,
               BTI_SINT     keyNumber )
    {
       BTI_BYTE keyLength = MAX_KEY_SIZE;
       BTI_CHAR ckeynum = (BTI_CHAR)keyNumber;
       return BTRCALL (
                 operation,
                 posBlock,
                 dataBuffer,
                 dataLength,
                 keyBuffer,
                 keyLength,
                 ckeynum );
    }
    #endif /* BTI_WIN || BTI_OS2 */
    
    /****************************************************************************
       BTRVID() Function for 16-Bit MS Windows or OS2
    ***************************************************************************/
    #if defined( BTI_WIN ) || defined( BTI_OS2 )
    BTI_API BTRVID(
               BTI_WORD       operation,
               BTI_VOID_PTR   posBlock,
               BTI_VOID_PTR   dataBuffer,
               BTI_WORD_PTR   dataLength,
               BTI_VOID_PTR   keyBuffer,
               BTI_SINT       keyNumber,
               BTI_BUFFER_PTR clientID )
    {
       BTI_BYTE keyLength = MAX_KEY_SIZE;
       BTI_CHAR ckeynum = (BTI_CHAR)keyNumber;
       return BTRCALLID (
                 operation,
                 posBlock,
                 dataBuffer,
                 dataLength,
                 keyBuffer,
                 keyLength,
                 ckeynum,
                 clientID );
    }
    #endif /* BTI_WIN || BTI_OS2 */
    
    /****************************************************************************
       BTRV() Function for Win9x/Me, NT/2000, Win32s, or 32-bit OS2
    ***************************************************************************/
    #if defined(BTI_WIN_32) || defined(BTI_OS2_32) || defined (BTI_WIN_64) || \
        defined(BTI_LINUX) || defined(BTI_LINUX_64)
       #if defined( BTI_OS2_32 )
          #define BTRCALL BTRCALL32
       #endif
    BTI_API BTRV(
               BTI_WORD     operation,
               BTI_VOID_PTR posBlock,
               BTI_VOID_PTR dataBuffer,
               BTI_WORD_PTR dataLength,
               BTI_VOID_PTR keyBuffer,
               BTI_SINT     keyNumber )
    {
       BTI_BYTE keyLength  = MAX_KEY_SIZE;
       BTI_CHAR ckeynum    = (BTI_CHAR)keyNumber;
       BTI_ULONG dataLen32 = 0;
       BTI_SINT status;
    
       if ( dataLength != NULL )
          dataLen32 = *dataLength;
    
       status = BTRCALL (
                  operation,
                  posBlock,
                  dataBuffer,
                  &dataLen32,
                  keyBuffer,
                  keyLength,
                  ckeynum );
    
       if ( dataLength != NULL )
          *dataLength = (BTI_WORD)dataLen32;
    
       return status;
    }
    
    #endif /* BTI_WIN32 || BTI_OS2_32 || BTI_WIN64 || BTI_LINUX || BTI_LINUX_64 */
    
    
    /****************************************************************************
       BTRVID() Function for Win9x/Me, NT/2000, Win32s, or 32-bit OS2
    ***************************************************************************/
    #if defined(BTI_WIN_32) || defined(BTI_OS2_32) || defined (BTI_WIN_64) || \
        defined(BTI_LINUX) || defined(BTI_LINUX_64)
       #if defined( BTI_OS2_32 )
          #define BTRCALLID BTRCALLID32
       #endif
    BTI_API BTRVID(
               BTI_WORD       operation,
               BTI_VOID_PTR   posBlock,
               BTI_VOID_PTR   dataBuffer,
               BTI_WORD_PTR   dataLength,
               BTI_VOID_PTR   keyBuffer,
               BTI_SINT       keyNumber,
               BTI_BUFFER_PTR clientID )
    {
       BTI_BYTE keyLength  = MAX_KEY_SIZE;
       BTI_CHAR ckeynum    = (BTI_CHAR)keyNumber;
       BTI_ULONG dataLen32 = 0;
       BTI_SINT status;
    
       if ( dataLength != NULL )
          dataLen32 = *dataLength;
    
       status = BTRCALLID (
                  operation,
                  posBlock,
                  dataBuffer,
                  &dataLen32,
                  keyBuffer,
                  keyLength,
                  ckeynum,
                  clientID );
    
       if ( dataLength != NULL )
          *dataLength = (BTI_WORD)dataLen32;
    
       return status;
    }
    
    #endif /* BTI_WIN32 || BTI_OS2_32 || BTI_WIN64 || BTI_LINUX || BTI_LINUX_64 */
    
    /****************************************************************************
       BTRVID() Function for Real Mode DOS ( Btrieve 6.15 or later )
    ***************************************************************************/
    #if defined( BTI_DOS )
    BTI_API BTRVID(                                                   <<<< line 235 >>>>
               BTI_WORD       operation,
               BTI_VOID_PTR   posBlock,
               BTI_VOID_PTR   dataBuffer,
               BTI_WORD_PTR   dataLength,
               BTI_VOID_PTR   keyBuffer,
               BTI_SINT       keyNumber,
               BTI_BUFFER_PTR clientID )
    {
       /* Microsoft changed function and structure names in 7.x . */
       #if defined( _MSC_VER )
          #if ( _MSC_VER > 600 )
             #define segread _segread
             #define int86x  _int86x
             #define REGS    _REGS
             #define SREGS   _SREGS
          #endif
       #endif
    
       static BOOLEAN btrieveVersionOkay = FALSE;
       BTI_BYTE       versionOffset;
       BTI_BYTE       revisionOffset;
       BTI_BYTE       typeOffset;
       BOOLEAN        done;
       union  REGS    b_regs;
       struct SREGS   b_sregs;
       BTI_SINT       stat = B_NO_ERROR;
       BTI_VOID_PTR   fptr;
       BTI_VOID_PTR   twoPointersPtr;
       pmswParmBlock  newParms;
       BTI_WORD       version;
       BTI_WORD       revision;
    
       struct   /* structure passed to Btrieve */
       {
          BTI_VOID_PTR   DATA_BUF;          /* callers data buffer */
          BTI_WORD       BUF_LEN;           /* length of data buffer */
          BTI_VOID_PTR   POS_BLOCK;         /* user position block */
          BTI_VOID_PTR   FCB;               /* disk FCB */
          BTI_WORD       FUNCTION;          /* requested function */
          BTI_VOID_PTR   KEY_BUFFER;        /* user's key buffer */
          BTI_BYTE       KEY_LENGTH;        /* length of user's key buffer */
          BTI_CHAR       KEY_NUMBER;        /* key of reference for request */
          BTI_SINT_PTR   STATUS;            /* status word */
          BTI_SINT       XFACE_ID;          /* language identifier */
        } XDATA;
    
       struct
       {
          BTI_VOID_PTR xdataPtr;
          BTI_VOID_PTR clientIdPtr;
       } twoPointers;
    
       /* Btrieve Parameters for stat call */
       BTI_BYTE posBlockx[ 128 ];
       BTI_BYTE dataBufx[ 255 ];
       BTI_WORD dataLenx;
       BTI_BYTE keyBufx[ 255 ];
       BTI_WORD keyNumx = 0;
    
    
       segread( &b_sregs );
    
       /*=========================================================================
       Check to see that Btrieve has been started.
       =========================================================================*/
       b_regs.x.ax = 0x3500 + BTR_INTRPT;
       int86x( 0x21, &b_regs, &b_regs, &b_sregs );
       if ( b_regs.x.bx != BTR_OFFSET )
          stat = B_RECORD_MANAGER_INACTIVE;
    
       /*=========================================================================
        Check for correct versions of requester and engine.  This check is done
        only once per application.
       =========================================================================*/
       if ( ( stat == B_NO_ERROR ) && ( !btrieveVersionOkay ) )
       {
          versionOffset  = VERSION_OFFSET;
          revisionOffset = REVISION_OFFSET;
          typeOffset     = TYPE_OFFSET;
          done           = FALSE;
          dataLenx       = sizeof( dataBufx );
          stat = BTRV( B_VERSION, posBlockx, &dataBufx, &dataLenx, keyBufx,
                    keyNumx );
          if ( stat == B_NO_ERROR )
          {
             while ( !done )
             {
                version  = (*(BTI_WORD *)&dataBufx[ versionOffset ] );
                revision = (*(BTI_WORD *)&dataBufx[ revisionOffset ] );
                switch( *(BTI_BYTE *)&dataBufx[ typeOffset ] )
                {
                   /* Must have requestor version 6.16 or higher. */
                   case 'N':
                      if ( ( ( version == 6 ) && ( revision < 16 ) ) ||
                           ( version < 6 ) )
                         {
                            stat = B_INVALID_INTERFACE;
                            done = TRUE;
                         }
                         break;
                   /* Must have engine version 6 or higher. */
                   case 'D':
                      if ( version < 6 )
                         {
                            stat = B_INVALID_INTERFACE;
                            done = TRUE;
                         }
                         break;
                   case 0:
                      done = TRUE;
                      break;
                }
                if ( !done )
                {
                   versionOffset  = versionOffset  + VERSION_BUF_SIZE;
                   revisionOffset = revisionOffset + VERSION_BUF_SIZE;
                   typeOffset     = typeOffset     + VERSION_BUF_SIZE;
                   continue;
                }
             }
          }
          else
             stat = B_INVALID_INTERFACE;
       }
    
       if ( stat == B_NO_ERROR )
       {
          /*======================================================================
          Move user parameters to XDATA, the block where Btrieve expects them.
          ======================================================================*/
          XDATA.FUNCTION    = operation;
          XDATA.STATUS      = &stat;
          XDATA.FCB         = posBlock;
          XDATA.POS_BLOCK   = (BTI_BUFFER_PTR)posBlock + 38;
          XDATA.DATA_BUF    = dataBuffer;
          XDATA.BUF_LEN     = *dataLength;
          XDATA.KEY_BUFFER  = keyBuffer;
          XDATA.KEY_LENGTH  = 255;               /* use max since we don't know */
          XDATA.KEY_NUMBER  = (BTI_CHAR)keyNumber;
          XDATA.XFACE_ID    = VARIABLE_ID;
    
          btrieveVersionOkay = TRUE;
          twoPointers.xdataPtr = &XDATA;
          twoPointers.clientIdPtr = clientID;
          twoPointersPtr = &twoPointers;
          *((BTI_LONG_PTR) &(newParms.sign)) = *((BTI_LONG_PTR) "PMSW" );
          newParms.flags = 0;
          newParms.functionCode = BTRV_CODE;
          newParms.dataLength = sizeof( newParms );
          newParms.dataPtr = twoPointersPtr;
    
          /*======================================================================
          Make call to Btrieve.
          ======================================================================*/
          fptr = &newParms;
          b_regs.x.dx = FP_OFF(fptr);
          b_sregs.ds = FP_SEG(fptr);
    
          int86x( BTR_INTRPT, &b_regs, &b_regs, &b_sregs );
          *dataLength = XDATA.BUF_LEN;
       }
       return( stat );
    }
    #endif /* BTI_DOS */
    
    /***************************************************************************
       BTRV() Function for Real Mode DOS
    ***************************************************************************/
    #if defined( BTI_DOS )
    BTI_API BTRV(                                          <<<< line 405 >>>>
               BTI_WORD     operation,
               BTI_VOID_PTR posBlock,
               BTI_VOID_PTR dataBuffer,
               BTI_WORD_PTR dataLength,
               BTI_VOID_PTR keyBuffer,
               BTI_SINT     keyNumber )
    {
       /* Microsoft changed function and structure names in 7.x . */
       #if defined( _MSC_VER )
          #if ( _MSC_VER > 600 )
             #define segread _segread
             #define int86x  _int86x
             #define REGS    _REGS
             #define SREGS   _SREGS
          #endif
       #endif
    
       union REGS b_regs;
       struct SREGS b_sregs;
    
       struct       /* structure passed to Btrieve */
       {
          BTI_VOID_PTR   DATA_BUF;          /* callers data buffer */
          BTI_WORD       BUF_LEN;           /* length of data buffer */
          BTI_VOID_PTR   POS_BLOCK;         /* user position block */
          BTI_VOID_PTR   FCB;               /* disk FCB */
          BTI_WORD       FUNCTION;          /* requested function */
          BTI_VOID_PTR   KEY_BUFFER;        /* user's key buffer */
          BTI_BYTE       KEY_LENGTH;        /* length of user's key buffer */
          BTI_CHAR       KEY_NUMBER;        /* key of reference for request */
          BTI_SINT_PTR   STATUS;            /* status word */
          BTI_SINT       XFACE_ID;          /* language identifier */
        } XDATA;
    
       BTI_VOID_PTR fptr;
       BTI_SINT     stat = B_NO_ERROR;
    
       segread( &b_sregs );
    
       /*=========================================================================
       Check to see that Btrieve has been started.
       =========================================================================*/
       b_regs.x.ax = 0x3500 + BTR_INTRPT;
       int86x( 0x21, &b_regs, &b_regs, &b_sregs );
       if ( b_regs.x.bx != BTR_OFFSET )
          stat = B_RECORD_MANAGER_INACTIVE;
    
       /*=========================================================================
       Move user parameters to XDATA, the block where Btrieve expects them.
       =========================================================================*/
       if ( stat == B_NO_ERROR )
       {
          XDATA.FUNCTION    = operation;
          XDATA.STATUS      = &stat;
          XDATA.FCB         = posBlock;
          XDATA.POS_BLOCK   = (BTI_BUFFER_PTR)posBlock + 38;
          XDATA.DATA_BUF    = dataBuffer;
          XDATA.BUF_LEN     = *dataLength;
          XDATA.KEY_BUFFER  = keyBuffer;
          XDATA.KEY_LENGTH  = 255;               /* use max since we don't know */
          XDATA.KEY_NUMBER  = (BTI_CHAR)keyNumber;
          XDATA.XFACE_ID    = VARIABLE_ID;
    
          /*======================================================================
          Make call to Btrieve.
          ======================================================================*/
          fptr = &XDATA;
          b_regs.x.dx = FP_OFF(fptr);    /*parameter block is expected to be in DX */
          b_sregs.ds = FP_SEG(fptr);
    
          int86x( BTR_INTRPT, &b_regs, &b_regs, &b_sregs );
          *dataLength = XDATA.BUF_LEN;
       }
       return( stat );
    }
    #endif /* BTI_DOS */
    
    /***************************************************************************
       BTRVID() Function for Extended DOS Using Rational + BSTUB.EXE
    ***************************************************************************/
    #if defined( BTI_DOS_32R )
    BTI_API BTRVID(
               BTI_WORD       operation,
               BTI_VOID_PTR   posBlock,
               BTI_VOID_PTR   dataBuffer,
               BTI_WORD_PTR   dataLength,
               BTI_VOID_PTR   keyBuffer,
               BTI_SINT       keyNumber,
               BTI_BUFFER_PTR clientID )
    {
    
       BTI_SINT      stat = B_NO_ERROR;
       BTI_VOID_PTR  twoPointersPtr;
       pmswParmBlock newParms;
    
       struct
       {
          BTI_VOID_PTR xdataPtr;
          BTI_VOID_PTR clientIdPtr;
       } twoPointers;
    
       /*=========================================================================
       Check to see that Btrieve has been started.
       =========================================================================*/
       /* bstub code will check for presence of Btrieve; no need to check ver */
    
       /*=========================================================================
       Move user parameters to XDATA, the block where Btrieve expects them.
       =========================================================================*/
       struct       /* structure passed to Btrieve */
       {
          BTI_VOID_PTR   DATA_BUF;          /* callers data buffer */
          BTI_WORD       BUF_LEN;           /* length of data buffer */
          BTI_VOID_PTR   POS_BLOCK;         /* user position block */
          BTI_VOID_PTR   FCB;               /* disk FCB */
          BTI_WORD       FUNCTION;          /* requested function */
          BTI_VOID_PTR   KEY_BUFFER;        /* user's key buffer */
          BTI_BYTE       KEY_LENGTH;        /* length of user's key buffer */
          BTI_CHAR       KEY_NUMBER;        /* key of reference for request */
          BTI_SINT_PTR   STATUS;            /* status word */
          BTI_SINT       XFACE_ID;          /* language identifier */
        } XDATA;
    
       /*======================================================================
       Move user parameters to XDATA, the block where Btrieve expects them.
       ======================================================================*/
       XDATA.FUNCTION    = operation;
       XDATA.STATUS      = &stat;
       XDATA.FCB         = posBlock;
       XDATA.POS_BLOCK   = (BTI_BUFFER_PTR)posBlock + 38;
       XDATA.DATA_BUF    = dataBuffer;
       XDATA.BUF_LEN     = *dataLength;
       XDATA.KEY_BUFFER  = keyBuffer;
       XDATA.KEY_LENGTH  = 255;               /* use max since we don't know */
       XDATA.KEY_NUMBER  = (BTI_CHAR)keyNumber;
       XDATA.XFACE_ID    = PROTECTED_ID;
    
       /*=========================================================================
       Set up the new parmeter block.
       =========================================================================*/
       twoPointers.xdataPtr = &XDATA;
       twoPointers.clientIdPtr = clientID;
       twoPointersPtr = &twoPointers;
       *((BTI_LONG_PTR) &(newParms.sign)) = *((BTI_LONG_PTR) "PMSW" );
       newParms.flags = 0;
       newParms.functionCode = BTRV_CODE;
       newParms.dataLength = sizeof( newParms );
       newParms.dataPtr = twoPointersPtr;
    
       /*======================================================================
       Make call to Btrieve.
       ======================================================================*/
       (*_ImportedFunctions_)[ PROCESS7B ].functionPtr(
                                                    (pmswParmBlock *)&newParms );
    
       *dataLength = XDATA.BUF_LEN;
       return( stat );
    }
    #endif /* BTI_DOS_32R */
    
    /***************************************************************************
       BTRV() Function for Extended DOS Using Rational + BSTUB.EXE
    ***************************************************************************/
    #if defined( BTI_DOS_32R )
    BTI_API BTRV(
               BTI_WORD     operation,
               BTI_VOID_PTR posBlock,
               BTI_VOID_PTR dataBuffer,
               BTI_WORD_PTR dataLength,
               BTI_VOID_PTR keyBuffer,
               BTI_SINT     keyNumber )
    {
       BTI_SINT      stat = B_NO_ERROR;
    
       /*=========================================================================
       Check to see that Btrieve has been started.
       =========================================================================*/
       /* bstub code will check for presence of Btrieve */
    
       /*=========================================================================
       Move user parameters to XDATA, the block where Btrieve expects them.
       =========================================================================*/
       struct       /* structure passed to Btrieve */
       {
          BTI_VOID_PTR   DATA_BUF;          /* callers data buffer */
          BTI_WORD       BUF_LEN;           /* length of data buffer */
          BTI_VOID_PTR   POS_BLOCK;         /* user position block */
          BTI_VOID_PTR   FCB;               /* disk FCB */
          BTI_WORD       FUNCTION;          /* requested function */
          BTI_VOID_PTR   KEY_BUFFER;        /* user's key buffer */
          BTI_BYTE       KEY_LENGTH;        /* length of user's key buffer */
          BTI_CHAR       KEY_NUMBER;        /* key of reference for request */
          BTI_SINT_PTR   STATUS;            /* status word */
          BTI_SINT       XFACE_ID;          /* language identifier */
        } XDATA;
    
       /*======================================================================
       Move user parameters to XDATA, the block where Btrieve expects them.
       ======================================================================*/
       XDATA.FUNCTION    = operation;
       XDATA.STATUS      = &stat;
       XDATA.FCB         = posBlock;
       XDATA.POS_BLOCK   = (BTI_BUFFER_PTR)posBlock + 38;
       XDATA.DATA_BUF    = dataBuffer;
       XDATA.BUF_LEN     = *dataLength;
       XDATA.KEY_BUFFER  = keyBuffer;
       XDATA.KEY_LENGTH  = 255;               /* use max since we don't know */
       XDATA.KEY_NUMBER  = (BTI_CHAR)keyNumber;
       XDATA.XFACE_ID    = PROTECTED_ID;
    
       /*======================================================================
       Make call to Btrieve.
       ======================================================================*/
       (*_ImportedFunctions_)[ PROCESS7B ].functionPtr(
                                                    (pmswParmBlock *)&XDATA );
       *dataLength = XDATA.BUF_LEN;
       return( stat );
    }
    #endif /* BTI_DOS_32R */
    
    /***************************************************************************
       'Borland PowerPack' and 'Phar-Lap TNT 6.0' 32-Bit Interfaces
    ***************************************************************************/
    #if defined( BTI_DOS_32B ) || defined( BTI_DOS_32P )
    
    #define min(a,b)    (((a) < (b)) ? (a) : (b))
    
    #if defined( BTI_DOS_32B )
    /***************************************************************************
    ** Define Far pointer data type (selector:offset32)
    **
    ** The Borland C 32-bit compiler does not support far pointers.  For this
    ** compiler, a FARPTR is defined as a structure which has the same
    ** organization in memory as a standard 48-bit far pointer.
    **
    ** The following macros are used to get and set the selector and offset
    ** fields of far pointers, and work both for compilers that directly
    ** support far pointers and compilers that don't have far pointer support.
    ** The FP_SEL macro returns the 16-bit selector number field
    ** of a far pointer.  The FP_OFF macro returns the 32-bit offset
    ** field of a far pointer.  The FP_SET macro is used to construct a far
    ** pointer from a selector number and offset.  It takes three arguments:
    ** the name of the far pointer to be set, an offset, and a selector number.
    ** The FP_INCR macro increments the offset field of a far pointer.
    ***************************************************************************/
       typedef struct
       {
          BTI_ULONG Off;
          BTI_WORD  Sel;
       } FARPTR;
    
       #ifndef FP_SEL
          #define FP_SEL(fp) ((fp).Sel)
       #endif
    
       #ifndef FP_OFF
          #define FP_OFF(fp) ((fp).Off)
       #endif
    
       #ifndef FP_SET
          #define FP_SET(fp, off, sel) \
        {\
            (fp).Sel = (BTI_WORD) (sel);\
            (fp).Off = (BTI_ULONG) (off);\
        }
       #endif
    
       #ifndef FP_INCR
          #define FP_INCR(fp, incr) ((fp).Off += (BTI_ULONG) (incr))
       #endif
    
       /*
       ** Include files for Borland Compiler
       */
       #include <windows.h>
    
    #else /* BTI_DOS_32B */
       /*
       ** Include files for PharLap extender
       */
       #include <i86.h>
       #include <pharlap.h>
    
    #endif /* BTI_DOS_32B */
    
    #include <blobhdr.h>          /* structure definitions for chunk operations */
    
    /*
    ** Constant definitions
    */
    #define structoffset(s,m) (unsigned)(((char *)(&((s *)0)->m))-((char *)0))
    #define Normalize(x)     ((BTI_ULONG)(x))
    #define CLIENT_ID_SIZE 16
    
    /*============================================================================
    The XDATASTRUCT defines the Btrieve parameter block
    ============================================================================*/
    typedef struct          /* structure passed to Btrieve */
    {
       BTI_ULONG      DATA_BUF;         /* callers data buffer */
       BTI_WORD       BUF_LEN;          /* length of data buffer */
       BTI_ULONG      POS_BLOCK;        /* user position block */
       BTI_ULONG      FCB;              /* disk FCB */
       BTI_WORD       FUNCTION;         /* requested function */
       BTI_ULONG      KEY_BUFFER;       /* user's key buffer */
       BTI_BYTE       KEY_LENGTH;       /* length of user's key buffer */
       BTI_CHAR       KEY_NUMBER;       /* key of reference for request */
       BTI_ULONG      STATUS;           /* status word */
       BTI_SINT       XFACE_ID;         /* language identifier */
    } XDATASTRUCT;
    
    /*============================================================================
    This structure defines the real mode buffer.  The DATA_BUF parameter is
    set up as one byte for reference.  Memory needs to be declared large enough
    for data buffers that will be returned.
    ============================================================================*/
    typedef struct
    {
       XDATASTRUCT XDATA;
       BTI_SINT    STATUS;
       BTI_BYTE    POS_BLOCK[128];
       BTI_BYTE    KEY_BUFFER[255];
       BTI_BYTE    DATA_BUF[1];
    } RMBUFF;
    
    
    /*============================================================================
    Prototypes for functions in protected mode interface
    =============================================================================*/
    BTI_SINT BtrLoaded( void );
    
    BTI_VOID CallBTRV(
                BTI_ULONG );
    
    BTI_SINT GetRealModeBuffer(
                FARPTR *,
                BTI_ULONG *,
                BTI_ULONG );
    
    BTI_SINT SetUpBTRVData(
                FARPTR *,
                BTI_VOID_PTR,
                BTI_VOID_PTR,
                BTI_VOID_PTR );
    
    BTI_VOID RetrieveBTRVData(
                FARPTR *,
                BTI_VOID_PTR,
                BTI_VOID_PTR,
                BTI_VOID_PTR );
    
    BTI_SINT BlobInputDBlen(
                register XTRACTR *);
    
    BTI_SINT ProcessIndirect(
                FARPTR *,
                BTI_VOID_PTR,
                BTI_WORD,
                BTI_SINT,
                BTI_WORD * );
    
    BTI_SINT VerifyChunk(
                BTI_VOID_PTR,
                BTI_WORD,
                BTI_VOID_PTR,
                BTI_WORD,
                BTI_WORD,
                BTI_WORD );
    
    /*
    ** The following function are in assembly language- define with CDECL
    */
    
    extern BTI_CHAR  cdecl getLowMemByte(
                              BTI_WORD,
                              BTI_ULONG );
    
    extern BTI_CHAR  cdecl setLowMemByte(
                              BTI_WORD,
                              BTI_ULONG,
                              BTI_BYTE );
    
    extern BTI_WORD  cdecl getLowMemWord(
                              BTI_WORD,
                              BTI_ULONG );
    
    extern BTI_WORD  cdecl setLowMemWord(
                              BTI_WORD,
                              BTI_ULONG,
                              BTI_WORD );
    
    extern BTI_ULONG cdecl getLowMemLong(
                              BTI_WORD,
                              BTI_ULONG );
    
    extern BTI_ULONG cdecl setLowMemLong(
                              BTI_WORD,
                              BTI_ULONG,
                              BTI_ULONG );
    
    extern void cdecl copyToLow(
                         unsigned short dst_sel,
                         unsigned dst_offset,
                         void * src,
                         unsigned int size);
    
    extern void cdecl copyFromLow(
                         void * dst,
                         unsigned short src_sel,
                         unsigned src_offset,
                         unsigned int size);
    
    /*
    *****************************************************************************
    **
    **  Prototype:
    **
    **      BTI_SINT GetRealModeBuffer(
    **                  FARPTR *protectedP,
    **                  BTI_ULONG *realAddr,
    **                  BTI_ULONG requestedSize )
    **
    **  Description:
    **
    **      This function returns a protected mode pointer and a real mode
    **      pointer to a block of memory allocated in DOS real memory.
    **      This memory is used for the Btrieve parameter block information.
    **      When BTI_DOS_32B is defined, this function allocates DOS real
    **      memory.  When BTI_DOS_32P is defined, this function uses a
    **      DOS buffer that is preallocated by PharLap.
    **
    **  Preconditions:
    **
    **      None.
    **
    **  Parameters:
    **
    **      *protectedP:        On output, protectedP is the protected mode
    **        <output>          pointer to the real memory Btrieve parameter
    **                          block.
    **
    **      *realAddr:          On output, realAddr contains the real mode
    **        <output>          pointer the Btrieve parameter block in DOS
    **                          real memory.
    **
    **      requestedSize:      Contains the size of memory to allocate.
    **        <input>
    **
    **
    **  Return value:
    **
    **      B_NO_ERROR          GetRealModeBuffer is successful.
    **
    **      B_DATALENGTH_ERROR  If BTI_DOS_32B is defined, this status code is
    **                          returned if the int386 call fails to allocate
    **                          the DOS real memory block.
    **
    **                          If BTI_DOS_32P is defined, this status is
    **                          returned when the requestedSize + dataLength
    **                          is smaller than the size of the DOS buffer.
    **                          As an enhancement to the interface, a call to
    **                          _dx_dosbuf_set could be made to set the
    **                          size of the PharLap DOS buffer before the call
    **                          to _dx_dosbuf_get instead of relying on the
    **                          default buffer size.
    **
    **
    **  Globals:
    **
    **      None.
    **
    **  Called Functions:
    **
    **      BTI_DOS_32B:
    **         int386() - Use DPMI services to allocate DOS memory.
    **
    **      BTI_DOS_32P:
    **         _dx_dosbuf_get - PharLap function to return protected mode and
    **                          real mode pointers to a DOS buffer that PharLap
    **                          maintains.
    **
    **  Comments:
    **
    **      None.
    **
    *****************************************************************************
    */
    BTI_SINT GetRealModeBuffer(
                FARPTR *protectedP,         /* protected mode pointer to real memory */
                BTI_ULONG *realAddr,        /* real mode pointer to real memory */
                BTI_ULONG requestedSize )   /* size of buffer to allocate */
    
    #if defined( BTI_DOS_32B )
    {
       /*=========================================================================
       GetRealModeBuffer - Borland Power Pack
       =========================================================================*/
    
       BTI_SINT allocStatus;
    
       union REGS inRegs, outRegs;
    
       /*
       ** Allocate DOS Memory
       ** Interrupt 31h, function 100h
       ** Note: The DPMI server must support version 0.9 or later of the DPMI
       **       specification to support this this function.  An error code
       **       will be returned in the AX register and returned to caller
       **       as B_DATALENGTH_ERROR.
       **
       ** AX = 100h
       ** BX = Number of 16-byte paragraphs to allocate
       **
       ** Returns:
       **
       ** if carry flag is clear
       **    AX = real mode segment base address of allocated block
       **    DX = selector for allocated block
       **
       ** if carry flag is set
       **    AX = error code
       **
       */
       inRegs.x.eax = 0x100;
       inRegs.x.ebx = (requestedSize + 15) / 16;        /* Number of paragraphs */
    
       int386( 0x31, &inRegs, &outRegs );
    
       if ( outRegs.x.cflag )
          allocStatus = B_DATALENGTH_ERROR;
       else
       {
          *realAddr = (outRegs.x.eax << 16) & 0xFFFF0000;
          FP_SET( *protectedP, 0, (BTI_WORD) outRegs.x.edx );
          allocStatus = B_NO_ERROR;
       }
    
       return allocStatus;
    }
    #else /* BTI_DOS_32B */
    {
       /*=========================================================================
       GetRealModeBuffer - Phar Lap Extender
       =========================================================================*/
       BTI_SINT stat;                                     /* Return status code */
       BTI_ULONG bufferSize;
    
       /*
       ** Get Information about the DOS Data Buffer
       **
       ** The _dx_dos_buf_get function returns real and protected-mode pointers
       ** to the buffer used to buffer data on MS-DOS and BIOS system calls.  The
       ** size of the buffer is returned in the size parameter.  Note: need to
       ** make this call each time because address of the MS_DOS buffer changes
       ** when anyone calls Load for Debug(_dx_dbg_ld) or the Set DOS Data Buffer
       ** Size(_dx_dosbuf_set).
       */
    
       _dx_dosbuf_get( (FARPTR *) protectedP, realAddr, &bufferSize);
    
       if ( bufferSize < requestedSize )
          stat = B_DATALENGTH_ERROR;
       else
          stat = B_NO_ERROR;
    
       return stat;
    }
    #endif /* BTI_DOS_32B */
    
    /*
    *****************************************************************************
    **
    **  Prototype:
    **
    **      static void FreeRealModeBuffer( BTI_WORD sel )
    **
    **  Description:
    **
    **      FreeRealModeBuffer frees the memory allocated by GetRealModeBuffer
    **      when BTI_DOS_32B is defined.  For BTI_DOS_32P there is nothing to do.
    **
    **  Preconditions:
    **
    **      None.
    **
    **  Parameters:
    **
    **      sel:            Protected mode selector of the Real Mode buffer to
    **        <input>       free.
    **
    **
    **  Return value:
    **
    **      None.
    **
    **
    **  Globals:
    **
    **      None.
    **
    **  Called Functions:
    **
    **      int386
    **
    **  Comments:
    **
    **      None.
    **
    *****************************************************************************
    */
    static void FreeRealModeBuffer( BTI_WORD sel )
    {
    #if defined( BTI_DOS_32B )
       union REGS inRegs, outRegs;
    
    
       inRegs.x.edx = sel;          /* Selector to be freed */
       inRegs.x.eax = 0x101;
    
       int386( 0x31, &inRegs, &outRegs );
    
    #else /* BTI_DOS_32B */
    
       /*
       ** Phar Lap specific code
       */
    
       /* do nothing */
    #endif /* BTI_DOS_32B */
    }
    
    /*
    *****************************************************************************
    **
    **  Prototype:
    **
    **      BTI_SINT BtrLoaded( )
    **
    **  Description:
    **
    **      This function checks to see if Btrieve is loaded.
    **
    **  Preconditions:
    **
    **      None.
    **
    **  Parameters:
    **
    **      None.
    **
    **  Return value:
    **
    **      B_NO_ERROR                      Btrieve is loaded
    **
    **      B_RECORD_MANAGER_INACTIVE       Btrieve is not loaded.
    **
    **  Globals:
    **
    **      None.
    **
    **  Called Functions:
    **
    **      BTI_DOS_32B             BTI_DOS_32P
    **
    **        int386()              _dx_rmiv_get()
    **
    **
    **  Comments:
    **
    **      None.
    **
    *****************************************************************************
    */
    BTI_SINT BtrLoaded( )
    {
       BTI_ULONG             btrAddress;
       BTI_SINT              stat;
    
    #if defined( BTI_DOS_32B )
       union REGS            inRegs, outRegs;
    
       inRegs.x.eax = 0x200;
       inRegs.x.ebx = BTR_INTRPT;
    
       int386( 0x31, &inRegs, &outRegs );
       btrAddress = outRegs.x.edx;
    
       if (( (BTI_WORD) (((BTI_ULONG)(btrAddress)) & 0xFFFF) ) != BTR_OFFSET )
          stat = B_RECORD_MANAGER_INACTIVE;
       else
          stat = B_NO_ERROR;
    
       return ( stat );
    }
    #else /* BTI_DOS_32B */
       /*
       **   The _dx_rmiv_get routine returns the real-mode interrupt
       **   vector for interupt 7b
       */
    
       _dx_rmiv_get( BTR_INTRPT, &btrAddress );
    
       if (( (BTI_WORD) (((BTI_ULONG)(btrAddress)) & 0xFFFF) ) != BTR_OFFSET )
          stat = B_RECORD_MANAGER_INACTIVE;
       else
          stat = B_NO_ERROR;
    
       return (stat);
    }
    #endif /* BTI_DOS_32B */
    
    /*
    *****************************************************************************
    **
    **  Prototype:
    **
    **      BTI_VOID CallBTRV( BTI_ULONG realPtr )
    **
    **  Description:
    **
    **      CallBTRV calls Btrieve using real mode interrupt 7B.
    **
    **  Preconditions:
    **
    **      None.
    **
    **  Parameters:
    **
    **      realPtr:                Real mode pointer to the Btrieve parameter
    **        <input>               block in real memory.
    **
    **
    **  Return value:
    **
    **      None.
    **
    **
    **  Globals:
    **
    **      None.
    **
    **  Called Functions:
    **
    **      BTI_DOS_32B             BTI_DOS_32P
    **
    **        int386()              _dx_real_int()
    **
    **
    **  Comments:
    **
    **      None.
    **
    **
    *****************************************************************************
    */
    BTI_VOID CallBTRV( BTI_ULONG realPtr )
    #if defined( BTI_DOS_32B )
    {
       /*
       **   Call Btrieve using Borland Power Pack DOS Extender
       */
       union  REGS           b_regs;
       struct   REALMODEREGS
       {
          BTI_ULONG edi;
          BTI_ULONG esi;
          BTI_ULONG ebp;
          BTI_ULONG reserved;
          BTI_ULONG ebx;
          BTI_ULONG edx;
          BTI_ULONG ecx;
          BTI_ULONG eax;
          BTI_WORD  CPUflag;
          BTI_WORD  es;
          BTI_WORD  ds;
          BTI_WORD  fs;
          BTI_WORD  gs;
          BTI_WORD  ip;
          BTI_WORD  cs;
          BTI_WORD  sp;
          BTI_WORD  ss;
       } realmodeRegs;
    
       b_regs.x.eax = 0x300;
       b_regs.h.bl  = BTR_INTRPT;
       b_regs.h.bh  = 0;
         /* CX = Number of words to copy from protected-mode to real-mode stack */
       b_regs.x.ecx = 0;
    
       /*
       ** Initialize real mode segment registers for call to Btrieve
       */
       memset( &realmodeRegs, 0, sizeof(struct REALMODEREGS) );
    
       realmodeRegs.ds  = (BTI_WORD) (realPtr >> 16);  /* Segment of parm block */
       realmodeRegs.edx = (realPtr << 16);         /* Offset of parameter block */
    
       b_regs.x.edi = (BTI_ULONG) &realmodeRegs;
    
       int386( 0x31, &b_regs, &b_regs );
    }
    #else /* BTI_DOS_32B */
    {
       /*
       ** Phar Lap DOS extender specific code
       */
       SWI_REGS              b_regs;
    
       memset( &b_regs, 0, sizeof( b_regs ) );
       b_regs.ds  = RP_SEG( realPtr );
       b_regs.edx = RP_OFF( realPtr );
    
       /*
       **   The _dx_real_int routine issues the 7b interrupt in real mode
       */
       _dx_real_int( BTR_INTRPT, &b_regs );
    }
    #endif /* BTI_DOS_32B */
    
    /***************************************************************************
        BTRVID() Function for Extended DOS Using 'Borland PowerPack' or
        'Phar-Lap TNT 6.0' DOS Extenders
    ***************************************************************************/
    BTI_API BTRVID(
               BTI_WORD       operation,
               BTI_VOID_PTR   posBlock,
               BTI_VOID_PTR   dataBuffer,
               BTI_WORD_PTR   dataLength,
               BTI_VOID_PTR   keyBuffer,
               BTI_SINT       keyNumber,
               BTI_BUFFER_PTR clientID )
    {
       /* Microsoft changed function and structure names in 7.x . */
       #if defined( _MSC_VER )
          #if ( _MSC_VER > 600 )
             #define segread _segread
             #define int86x  _int86x
             #define REGS    _REGS
             #define SREGS   _SREGS
          #endif
       #endif
    
       typedef struct
       {
          BTI_ULONG xdataPtr;
          BTI_ULONG clientIdPtr;
       } TWOPTRSTRUCT;
    
       typedef struct
       {
          pmswParmBlock  newParms;
          TWOPTRSTRUCT   twoPointers;
          BTI_BYTE       clientID[CLIENT_ID_SIZE];
          RMBUFF         btrv;
       } RMBTRVID;
    
       static BOOLEAN btrieveVersionOkay = FALSE;
       BTI_BYTE       versionOffset;
       BTI_BYTE       revisionOffset;
       BTI_BYTE       typeOffset;
       BOOLEAN        done;
       BTI_SINT       stat = B_NO_ERROR;
       BTI_ULONG      bufferSize;
       FARPTR         protectedP;
       FARPTR         tmpProtectedP;
       BTI_ULONG      realPtr;
    
    
       /*
       **   Btrieve Parameters for stat call
       */
       BTI_BYTE posBlockx[ 128 ];
       BTI_BYTE dataBufx[ 255 ];
       BTI_WORD dataLenx;
       BTI_BYTE keyBufx[ 255 ];
       BTI_WORD keyNumx = 0;
    
       /*=========================================================================
       Check to see that Btrieve has been started.
       =========================================================================*/
       stat = BtrLoaded( );
    
       /*=========================================================================
        Check for correct versions of requester and engine.  This check is done
        only once per application.
       =========================================================================*/
       if ( ( stat == B_NO_ERROR ) && ( !btrieveVersionOkay ) )
       {
          versionOffset  = VERSION_OFFSET;
          revisionOffset = REVISION_OFFSET;
          typeOffset     = TYPE_OFFSET;
          done           = FALSE;
          dataLenx       = sizeof( dataBufx );
          stat = BTRV(
                    B_VERSION,
                    posBlockx,
                    &dataBufx,
                    &dataLenx,
                    keyBufx,
                    keyNumx );
          if ( stat == B_NO_ERROR )
          {
             while ( !done )
             {
                switch( *(BTI_BYTE *)&dataBufx[ typeOffset ] )
                {
                   /* Must have requestor version 6.16 or higher. */
                   case 'N':
                      if ( ( (*(BTI_WORD *)&dataBufx[ versionOffset ] ) < 6 ) ||
                             ( ( (*(BTI_WORD *)&dataBufx[ versionOffset ] ) == 6 ) &&
                             ( (*(BTI_WORD *)&dataBufx[ revisionOffset ] ) < 16 ) ) )
                      {
                         stat = B_INVALID_INTERFACE;
                         done = TRUE;
                      }
                      break;
    
                   /* Must have engine version 6 or higher. */
                   case 'D':
                      if ( (*(BTI_WORD *)&dataBufx[ versionOffset ] ) < 6 )
                      {
                         stat = B_INVALID_INTERFACE;
                         done = TRUE;
                      }
                      break;
    
                   case 0:
                      done = TRUE;
                      break;
                }
                if ( !done )
                {
                   versionOffset  = versionOffset  + VERSION_BUF_SIZE;
                   revisionOffset = revisionOffset + VERSION_BUF_SIZE;
                   typeOffset     = typeOffset     + VERSION_BUF_SIZE;
                   continue;
                }
             }
          }
          else
             stat = B_INVALID_INTERFACE;
       }
    
       /*=========================================================================
       Get pointers to real memory which is used to transfer data on the
       call to BTRVID
       =========================================================================*/
       if ( stat == B_NO_ERROR )
       {
          bufferSize = sizeof( RMBTRVID ) + *dataLength;
          stat = GetRealModeBuffer( &protectedP, &realPtr, bufferSize );
    
          if (stat == B_NO_ERROR)
          {
             btrieveVersionOkay = TRUE;
    
             /*===================================================================
             Establish pointer links inside real mode buffer.  Note: at first
             glance you might think to do this only one time.  However, if you are
             not the only one using the DOS buffer these relations would not be
             there next time around.
             ===================================================================*/
    
             copyToLow(                                   /* Use PMSW signature */
                FP_SEL(protectedP),
                FP_OFF(protectedP) + structoffset( RMBTRVID, newParms.sign ),
                "PMSW",
                4 );
    
             setLowMemLong(                                      /* Clear flags */
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, newParms.flags ),
                0 );
    
             setLowMemLong(                 /* set function code to BTRVID code */
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, newParms.functionCode ),
                BTRV_CODE );
    
             setLowMemLong(                             /* clear pmSwitchStatus */
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, newParms.pmSwitchStatus ),
                0 );
    
             setLowMemLong(                                  /* set data length */
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, newParms.dataLength ),
                sizeof( pmswParmBlock ) );
    
             setLowMemLong(    /* set dataPtr to point to twoPointers structure */
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, newParms.dataPtr ),
                realPtr + structoffset( RMBTRVID, twoPointers ) );
    
             setLowMemLong(          /* set xDataPtr to Btrieve parameter block */
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, twoPointers.xdataPtr ),
                realPtr + structoffset( RMBTRVID, btrv.XDATA ) );
    
             setLowMemLong(            /* set pointer to clientID in low memory */
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, twoPointers.clientIdPtr ),
                realPtr + structoffset( RMBTRVID, clientID ) );
    
             copyToLow(                   /* copy clientID from input parameter */
                FP_SEL(protectedP),
                FP_OFF(protectedP) + structoffset( RMBTRVID, clientID ),
                clientID,
                CLIENT_ID_SIZE );
    
             setLowMemLong(                          /* set data buffer pointer */
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, btrv.XDATA.DATA_BUF ),
                realPtr + structoffset( RMBTRVID, btrv.DATA_BUF ) );
    
             setLowMemWord(             /* set data buffer length in parm block */
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, btrv.XDATA.BUF_LEN ),
                *dataLength );
    
             setLowMemLong(                                   /* Position block */
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, btrv.XDATA.POS_BLOCK ),
                realPtr + structoffset( RMBTRVID, btrv.POS_BLOCK) + 38 );
    
             setLowMemLong(
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, btrv.XDATA.FCB ),
                realPtr + structoffset( RMBTRVID, btrv.POS_BLOCK ) );
    
             setLowMemWord(
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, btrv.XDATA.FUNCTION ),
                operation );
    
             setLowMemLong(
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, btrv.XDATA.KEY_BUFFER ),
                realPtr + structoffset( RMBTRVID, btrv.KEY_BUFFER) );
    
             setLowMemByte(
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, btrv.XDATA.KEY_LENGTH ),
                255 );
    
             setLowMemByte(
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, btrv.XDATA.KEY_NUMBER ),
                keyNumber );
    
             setLowMemLong(
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, btrv.XDATA.STATUS ),
                realPtr + structoffset( RMBTRVID, btrv.STATUS ) );
    
             setLowMemWord(
                FP_SEL(protectedP),
                FP_OFF(protectedP)
                   + structoffset( RMBTRVID, btrv.XDATA.XFACE_ID ),
                VARIABLE_ID );
    
             tmpProtectedP = protectedP;
             FP_INCR(tmpProtectedP, structoffset( RMBTRVID, btrv ));
             stat = SetUpBTRVData(
                       &tmpProtectedP,
                       posBlock,
                       dataBuffer,
                       keyBuffer );
    
             /*===================================================================
             Make call to Btrieve.
             ===================================================================*/
             if ( stat == B_NO_ERROR )
             {
                CallBTRV( realPtr );
    
                *dataLength = getLowMemWord(
                                 FP_SEL(protectedP),
                                 FP_OFF(protectedP)
                                    + structoffset(
                                         RMBTRVID,
                                         btrv.XDATA.BUF_LEN ) );
    
                stat = getLowMemLong(
                          FP_SEL(protectedP),
                          FP_OFF(protectedP)
                             + structoffset( RMBTRVID, btrv.STATUS ) ) ;
    
                /*================================================================
                Copy data from protected mode back to user's data
                ================================================================*/
                RetrieveBTRVData(
                   &tmpProtectedP,
                   posBlock,
                   dataBuffer,
                   keyBuffer );
             }
          }
       }
    
       return( stat );
    }
    
    /***************************************************************************
        BTRV() Function for Extended DOS Using 'Borland PowerPack' or
        'Phar-Lap TNT 6.0' DOS Extenders
    ***************************************************************************/
    BTI_API BTRV(
               BTI_WORD     operation,
               BTI_VOID_PTR posBlock,
               BTI_VOID_PTR dataBuffer,
               BTI_WORD_PTR dataLength,
               BTI_VOID_PTR keyBuffer,
               BTI_SINT     keyNumber )
    {
       /* Microsoft changed function and structure names in post 6.0 versions. */
       #if defined( _MSC_VER )
          #if ( _MSC_VER > 600 )
             #define int386x _int386x
             #define REGS    _REGS
          #endif
       #endif
    
       BTI_SINT              stat = B_NO_ERROR;
       BTI_ULONG             bufferSize;
       FARPTR                protectedP;
       BTI_ULONG             realPtr;
    
       /*=========================================================================
       Check to see that Btrieve has been started.
       =========================================================================*/
       stat = BtrLoaded( );
    
       /*=========================================================================
       Move user parameters to XDATA, the block where Btrieve expects them.
       =========================================================================*/
       if ( stat == B_NO_ERROR )
       {
          bufferSize = sizeof( RMBUFF ) + *dataLength;
          stat = GetRealModeBuffer( &protectedP, &realPtr, bufferSize );
    
          if (stat == B_NO_ERROR)
          {
             /*===================================================================
             Establish pointer links inside real mode buffer.  Note: at first
             glance you might think to do this only one time.  However, if you are
             not the only one using the DOS buffer these relations would not be
             there next time around.
             ===================================================================*/
    
             setLowMemLong(
                FP_SEL(protectedP),
                FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.POS_BLOCK ),
                realPtr + structoffset(RMBUFF, POS_BLOCK) + 38 );
    
             setLowMemLong(
                FP_SEL(protectedP),
                FP_OFF(protectedP) + structoffset(RMBUFF, XDATA.FCB),
                realPtr + structoffset( RMBUFF, POS_BLOCK ) );
    
             setLowMemLong(
                FP_SEL(protectedP),
                FP_OFF(protectedP) + structoffset(RMBUFF, XDATA.STATUS),
                realPtr + structoffset( RMBUFF, STATUS ) );
    
             setLowMemLong(
                FP_SEL(protectedP),
                FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.KEY_BUFFER ),
                realPtr + structoffset( RMBUFF, KEY_BUFFER) );
    
             setLowMemLong(
                FP_SEL(protectedP),
                FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.DATA_BUF ),
                realPtr + structoffset( RMBUFF, DATA_BUF ) );
    
             setLowMemWord(
                FP_SEL(protectedP),
                FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.XFACE_ID ),
                VARIABLE_ID );
    
             setLowMemWord(
                FP_SEL(protectedP),
                FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.FUNCTION ),
                operation );
    
             setLowMemWord(
                FP_SEL(protectedP),
                FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.BUF_LEN ),
                *dataLength );
    
             setLowMemByte(
                FP_SEL(protectedP),
                FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.KEY_LENGTH ),
                255 );
    
             setLowMemByte(
                FP_SEL(protectedP),
                FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.KEY_NUMBER ),
                keyNumber );
    
             stat = SetUpBTRVData( &protectedP, posBlock, dataBuffer, keyBuffer );
    
             /*===================================================================
             Make call to Btrieve.
             ===================================================================*/
             if ( stat == B_NO_ERROR )
             {
                CallBTRV( realPtr );
    
                *dataLength = getLowMemWord(
                                 FP_SEL(protectedP),
                                 FP_OFF(protectedP)
                                    + structoffset( RMBUFF, XDATA.BUF_LEN) );
    
                stat = getLowMemLong(
                          FP_SEL(protectedP),
                          FP_OFF(protectedP)
                             + structoffset( RMBUFF, STATUS ) );
    
                /*================================================================
                Copy data from protected mode back to user's data
                ================================================================*/
                RetrieveBTRVData( &protectedP, posBlock, dataBuffer, keyBuffer );
             }
             FreeRealModeBuffer( FP_SEL(protectedP) );
          }
       }
       return( stat );
    }
    
    /*
    *****************************************************************************
    **
    **  Prototype:
    **
    **      BTI_SINT SetUpBTRVData(
    **                  FARPTR *protectedP,
    **                  BTI_VOID_PTR posBlock,
    **                  BTI_VOID_PTR dataBuffer,
    **                  BTI_VOID_PTR keyBuffer )
    **
    **  Description:
    **
    **      This function copies Btrieve parameter data from the user's
    **      application to the Btrieve parameter block in DOS real memory.
    **      It checks the Btrieve function code and key number parameters
    **      that are already in the parameter block to see if the operation
    **      processes indirect chunk data.  If so, ProcessIndirect() is called
    **      to process the indirect Btrieve chunk data.
    **
    **  Preconditions:
    **
    **      Real Mode Btrieve parameter block is already initialized with
    **      Function code, Key Number, Data buffer length.
    **
    **  Parameters:
    **
    **      *protectedP:    Protected mode pointer to the Btrieve parameter block.
    **       <input/output>
    **
    **      posBlock:       Application's parameter block
    **        <input>
    **
    **      dataBuffer:     Application's data buffer
    **        <input>
    **
    **      keyBuffer:      Application's key buffer
    **        <input>
    **
    **
    **  Return value:
    **
    **      B_NO_ERROR      SetUpBTRVData() is successful.
    **
    **      B_DATA_MESSAGE_TOO_SMALL Chunk cannot fit in the user's data buffer.
    **
    **      B_INVALID_GET_EXPRESSION Chunk data overwrites chunk descriptors.
    **
    **
    **  Globals:
    **
    **      None.
    **
    **  Called Functions:
    **
    **      BlobInputDBlen()
    **      copyToLow()
    **      getLowMemByte()
    **      getLowMemWord()
    **      ProcessIndirect()
    **
    **  Comments:
    **
    **      None.
    **
    *****************************************************************************
    */
    BTI_SINT SetUpBTRVData(
                FARPTR *protectedP,
                BTI_VOID_PTR posBlock,
                BTI_VOID_PTR dataBuffer,
                BTI_VOID_PTR keyBuffer )
    {
       BTI_WORD function;
       BTI_WORD copyLen;
       BTI_CHAR keyNumber;
       BTI_WORD stat;
       BTI_WORD bufLen;
    
       function = getLowMemWord(
                     FP_SEL(*protectedP),
                     FP_OFF(*protectedP)
                        + structoffset( RMBUFF, XDATA.FUNCTION) );
       function = function % S_WAIT_LOCK;
    
       copyLen  = getLowMemWord(
                     FP_SEL(*protectedP),
                     FP_OFF(*protectedP)
                        + structoffset( RMBUFF, XDATA.BUF_LEN ) );
    
       if (function == B_GET_DIRECT)
       {
          keyNumber = getLowMemByte(
                         FP_SEL(*protectedP),
                         FP_OFF(*protectedP)
                            + structoffset( RMBUFF, XDATA.KEY_NUMBER ) );
    
          if ( keyNumber == (BTI_CHAR) GET_DRTC_XTRACTOR_KEY )
          {
    
             PUT_XTRACTR *xtr;
    
             xtr = (PUT_XTRACTR *)((BTI_BYTE *) dataBuffer + 4);
             if ( xtr->Signature & INDIRECT_BIT)
             {
                bufLen = getLowMemWord(
                            FP_SEL(*protectedP),
                            FP_OFF(*protectedP)
                               + structoffset( RMBUFF, XDATA.BUF_LEN ) );
    
                if (stat = ProcessIndirect(
                              protectedP,
                              dataBuffer,          /* application's data buffer */
                              bufLen,
                              (BTI_SINT) PREPROCESS_BLOBGET,
                              &copyLen))
                {
                   return (stat);
                }
                /*
                ** Data was already copied in ProcessIndirect, so set
                ** copyLen to 0
                */
                copyLen = 0;
             }
             else
             {               /* Only copy the extractors & the record address. */
                copyLen = (BTI_WORD) BlobInputDBlen ((XTRACTR *) xtr) + 4;
             }
          }
       }
    
       if (function == B_CHUNK_UPDATE)
       {
          PUT_XTRACTR *xtr;
    
          xtr = (PUT_XTRACTR *)(dataBuffer);
    
          if ( xtr->Signature & INDIRECT_BIT)
          {
             bufLen = getLowMemWord(
                         FP_SEL(*protectedP),
                         FP_OFF(*protectedP)
                            + structoffset( RMBUFF, XDATA.BUF_LEN ) );
    
             if (stat = ProcessIndirect(
                           protectedP,
                           dataBuffer,            /* application's data buffer  */
                           bufLen,
                           PREPROCESS_BLOBPUT,
                           &copyLen))
             {
                return (stat);
             }
             /* Data was already copied in ProcessIndirect, so set copyLen to 0 */
             copyLen = 0;
          }
       }
    
       copyToLow(
          FP_SEL(*protectedP),
          FP_OFF(*protectedP) + structoffset( RMBUFF, POS_BLOCK),
          posBlock,
          128 );
    
       copyToLow(
          FP_SEL(*protectedP),
          FP_OFF(*protectedP) + structoffset( RMBUFF, KEY_BUFFER),
          keyBuffer,
          255 );
    
       copyToLow(
          FP_SEL(*protectedP),
          FP_OFF(*protectedP) + structoffset( RMBUFF, DATA_BUF),
          dataBuffer,
          copyLen );
    
       return (0);
    }
    
    
    /*
    *****************************************************************************
    **
    **  Prototype:
    **
    **      BTI_VOID RetrieveBTRVData(
    **                  FARPTR *protectedP,
    **                  BTI_VOID_PTR posBlock,
    **                  BTI_VOID_PTR dataBuffer,
    **                  BTI_VOID_PTR keyBuffer )
    **
    **  Description:
    **
    **      RetrieveBTRVData() copies data from the Btrieve parameter block
    **      in DOS real memory to the application's data area.  When there
    **      is indirection in the destination of the data, then
    **      RetrieveBTRVData() calls ProcessIndirect() to pull the data out
    **      of the parameter block and place it at the correct address.
    **
    **  Preconditions:
    **
    **      None.
    **
    **  Parameters:
    **
    **      *protectedP:            Protected-mode pointer to the Btrieve
    **        <input>               parameter block which contains data from
    **                              the last Btrieve call.
    **
    **      posBlock:               Application's position block.
    **        <output>
    **
    **      dataBuffer:             Application's data buffer.
    **        <output>
    **
    **      keyBuffer:              Application's data buffer.
    **        <output>
    **
    **
    **  Return value:
    **
    **      B_NO_ERROR               RetrieveBTRVData() is successful.
    **
    **      B_DATA_MESSAGE_TOO_SMALL Chunk cannot fit in the user's data buffer.
    **
    **      B_INVALID_GET_EXPRESSION Chunk data overwrites chunk descriptors.
    **
    **  Globals:
    **
    **      None.
    **
    **  Called Functions:
    **
    **      copyFromLow()
    **      getLowMemWord()
    **      ProcessIndirect()
    **
    **  Comments:
    **
    **      None.
    **
    *****************************************************************************
    */
    BTI_VOID RetrieveBTRVData(
                FARPTR *protectedP,
                BTI_VOID_PTR posBlock,
                BTI_VOID_PTR dataBuffer,
                BTI_VOID_PTR keyBuffer )
    {
       BTI_WORD function;
       BTI_CHAR keyNumber;
       BTI_WORD bufLen;
    
       function = getLowMemWord(
                     FP_SEL(*protectedP),
                     FP_OFF(*protectedP)
                        + structoffset( RMBUFF, XDATA.FUNCTION) );
       function = function % S_WAIT_LOCK;
    
       keyNumber = getLowMemWord(
                      FP_SEL(*protectedP),
                      FP_OFF(*protectedP)
                         + structoffset( RMBUFF, XDATA.KEY_NUMBER));
    
       bufLen = getLowMemWord(
                   FP_SEL(*protectedP),
                   FP_OFF(*protectedP)
                      + structoffset( RMBUFF, XDATA.BUF_LEN ) );
    
       if ( (function == B_GET_DIRECT) &&
            (keyNumber == (BTI_CHAR) GET_DRTC_XTRACTOR_KEY ) &&
            (((GET_XTRACTR *) dataBuffer)->Signature & INDIRECT_BIT))
       {
          BTI_WORD ignoredDataLen;
    
          ProcessIndirect(
             protectedP,
             dataBuffer,
             bufLen,
             POSTPROCESS_BLOBGET,
             &ignoredDataLen );
       }
       else
       {
    
          copyFromLow(
             dataBuffer,
             FP_SEL(*protectedP),
             FP_OFF(*protectedP) + structoffset( RMBUFF, DATA_BUF ),
             bufLen );
    
       }
    
       copyFromLow(
          posBlock,
          FP_SEL(*protectedP),
          FP_OFF(*protectedP) + structoffset( RMBUFF, POS_BLOCK ),
          128 );
    
       copyFromLow(
          keyBuffer,
          FP_SEL(*protectedP),
          FP_OFF(*protectedP) + structoffset( RMBUFF, KEY_BUFFER ),
          255 );
    
    }
    
    /*
    *****************************************************************************
    **
    **  Prototype:
    **
    **      BTI_SINT BlobInputDBlen( register XTRACTR * xtractP )
    **
    **  Description:
    **
    **      Returns the size of the Chunk Extractors based on the signature
    **      field.
    **
    **  Preconditions:
    **
    **      None.
    **
    **  Parameters:
    **
    **      xtractP:        Pointer to the chunk extractor.
    **        <input>
    **
    **
    **  Return value:
    **
    **      Returns the number of bytes in the extractor descriptor.
    **
    **  Globals:
    **
    **      None.
    **
    **  Called Functions:
    **
    **      None.
    **
    **  Comments:
    **
    **      None.
    **
    **
    *****************************************************************************
    */
    BTI_SINT BlobInputDBlen( register XTRACTR * xtractP )
    {
       register BTI_WORD ret;
    
       /*
       ** The size returned is based on the Signature field.
       */
       if ( xtractP->Signature & RECTANGLE_BIT )
       {
          ret = sizeof (PUT_RECTANGLE);
       }
       else
       {                                               /* Signature & numfields */
          ret = (xtractP->NumChunks * sizeof(CHUNK)) + (2 * sizeof(BTI_ULONG));
       }
       return (ret);
    }
    
    /*
    *****************************************************************************
    **
    **  Prototype:
    **
    **      BTI_SINT ProcessIndirect(
    **                  FARPTR *protectedP,
    **                  BTI_VOID_PTR usersDataBuf,
    **                  BTI_WORD maxlen,
    **                  BTI_SINT Action,
    **                  BTI_WORD *bytesDone )
    **
    **  Description:
    **
    **      ProcessIndirect() copies data to/from the address of the
    **      application's chunk data.
    **
    **  Preconditions:
    **
    **      None.
    **
    **  Parameters:
    **
    **      *protectedP:            Protected-mode pointer to Btrieve parameter
    **        <input/output>        block (RMBUFF data structure) in DOS real
    **                              memory.
    **
    **      usersDataBuf:           Pointer to application's data buffer.
    **        <input/output>
    **
    **      maxlen:                 Maximum length of application's data buffer.
    **        <input>
    **
    **      Action:                 Type of action to take (See below)
    **        <input>
    **
    **      *bytesDone:             Number of bytes copied.
    **        <input/output>
    **
    **
    **  Action can be one of the following:
    **
    **  PREPROCESS_BLOBGET
    **      Chunk extractor information is copied from the user's data buffer
    **      to the data buffer in the Btrieve parameter block.  The request
    **      type is changed to a direct data request so that we do not
    **      have to mess with pointer conversions between real and protected
    **      mode.  It also makes it easier for us to copy data to/from
    **      real-mode request buffer and user's buffer when request is
    **      pre/post processed.
    **
    **
    **  POSTPROCESS_BLOBGET
    **      Chunk data is copied from the Btrieve parameter block to the
    **      application's address given in the chunk extractor information
    **      (still in the application's data buffer)
    **
    **
    **  PREPROCESS_BLOBPUT
    **
    **      Chunk extractor information is copied from the user's data buffer
    **      to the data buffer in the Btrieve parameter block.  The request
    **      type is changed from indirect to direct so that the application's
    **      data can be copied into the Btrieve parameter block.
    **
    **  Return value:
    **
    **      B_NO_ERROR               Success
    **
    **      B_DATA_MESSAGE_TOO_SMALL Chunk cannot fit in the user's data buffer
    **
    **      B_INVALID_GET_EXPRESSION Chunk data overwrites chunk descriptors
    **
    **
    **  Globals:
    **
    **      None.
    **
    **  Called Functions:
    **
    **      BlobInputDBlen()
    **      copyFromLow()
    **      copyToLow()
    **      getLowMemLong()
    **      setLowMemLong()
    **      VerifyChunk()
    **
    **  Comments:
    **
    **      None.
    **
    *****************************************************************************
    */
    BTI_SINT ProcessIndirect(
                FARPTR *protectedP,
                BTI_VOID_PTR usersDataBuf,
                BTI_WORD maxlen,
                BTI_SINT Action,
                BTI_WORD *bytesDone )
    {
       PUT_XTRACTR   *xtr;
       PUT_RECTANGLE *rectP;
       BTI_WORD      protectSize;
       BTI_WORD      len = 0;                           /* Len of current chunk */
       BTI_WORD      i, limit;                                       /* Helpers */
       BTI_WORD      stat = 0;
       CHUNK         *iP;                        /* Will point to current chunk */
       BTI_SINT      rectangle;
       BTI_ULONG     chunkFlag;
       FARPTR        reqB;
    
       reqB = *protectedP;
    
       FP_INCR(reqB, structoffset(RMBUFF, DATA_BUF));
    
       if ( (Action == PREPROCESS_BLOBGET) || (Action == POSTPROCESS_BLOBGET) )
       {
          xtr = (PUT_XTRACTR *)(((BTI_BYTE *) usersDataBuf) + 4);
       }
       else
       {
          xtr = (PUT_XTRACTR *)usersDataBuf;
       }
    
       rectP = (PUT_RECTANGLE *) xtr;
         /* protectSize is the size of req. buffer that must not be overwritten */
       *bytesDone = protectSize = (BTI_WORD) BlobInputDBlen ((XTRACTR *)xtr);
    
       rectangle = xtr->Signature & RECTANGLE_BIT;
       if (rectangle)
          limit = (BTI_WORD)rectP->NumRows;
       else
          limit = (BTI_WORD)xtr->NumChunks;
    
       switch (Action)
       {
          case PREPROCESS_BLOBGET:
    
             *bytesDone += 4;                          /* four byte positioning */
             /*
             **    move record positioning information
             */
             setLowMemLong(
                FP_SEL(reqB),
                FP_OFF(reqB),
                *((BTI_ULONG *) usersDataBuf) );
             FP_INCR(reqB,sizeof( BTI_ULONG ));
    
                             /* Control flows down to copyToLow() and beyond... */
    
          case PREPROCESS_BLOBPUT:
                                                        /* move over extractors */
             copyToLow(
                FP_SEL(reqB),
                FP_OFF(reqB),
                xtr,
                protectSize );
             /*
             ** Change the request to a direct data request so that we do not
             ** have to mess with pointer conversions between real and protectSize
             ** mode.  It also makes it easier for us to copy data to/from
             ** real-mode request buffer and user's buffer when request is
             ** pre/post processed.
             */
    
             chunkFlag = getLowMemLong(
                            FP_SEL(reqB),
                            FP_OFF(reqB) );
             setLowMemLong(
                FP_SEL(reqB),
                FP_OFF(reqB),
                chunkFlag & ~INDIRECT_BIT );
             FP_INCR(reqB,protectSize);
    
             break;
    
          case POSTPROCESS_BLOBGET:
             *bytesDone = 0;
             break;
       }
    
       if (Action == PREPROCESS_BLOBGET)
       {
          /*
          ** Zero bytesDone so that it can now accumulate the number of bytes
          ** expected to be returned, looking for status 97.  This is done by
          ** calling VerifyChunk who also catches attempts to overwrite the
          ** descriptors with the returned data.
          */
          *bytesDone = 0;
       }
    
       /*=========================================================================
       Tack the chunks together at the end of the request buffer.
       =========================================================================*/
       /*
       ** iP is always initialized and maintained, but not used if chunk type
       ** is rectangle.
       */
       iP = &(xtr->Chunk[0]);
       for (i = 0; i < limit; i++)          /* limit is the same for both types */
       {
          register BTI_BYTE *chunkP;
    
          if ( rectangle )
          {
             if ( rectP->BytesPerRow & 0xffff0000L )   /* must be 16-bit number */
                return ( B_INVALID_GET_EXPRESSION );            /* return error */
             len = (BTI_WORD) rectP->BytesPerRow;
             chunkP = rectP->dataP + (i * rectP->AppDistanceBetweenRows);
          }
          else
          {
             chunkP = iP->dataP;
    
             if (iP->ChunkLen & 0xffff0000L)           /* must be 16-bit number */
                return (B_INVALID_GET_EXPRESSION);              /* return error */
    
             len = (BTI_WORD) iP->ChunkLen;
          }
    
    
          /*======================================================================
          Does the chunk about to be written overlap with the extractors?
          ======================================================================*/
          stat = VerifyChunk(
                    xtr,
                    protectSize,
                    chunkP,
                    len,
                    *bytesDone,
                    Action == POSTPROCESS_BLOBGET ? 0xffff : maxlen );
    
          if ( stat != B_NO_ERROR )
          {
             return ( stat );
          }
    
          if ( *bytesDone >= maxlen )               /* Already consumed buffer? */
          {
             return ( B_DATA_MESSAGE_TOO_SMALL );
          }
    
          if ( Action != PREPROCESS_BLOBGET )
          {
             switch ( Action )
             {
                case POSTPROCESS_BLOBGET:
                   copyFromLow(
                      chunkP,
                      FP_SEL(reqB),
                      FP_OFF(reqB),
                      min( len, maxlen - *bytesDone ) );
                   break;
    
                case PREPROCESS_BLOBPUT:
                   copyToLow(
                      FP_SEL(reqB),
                      FP_OFF(reqB),
                      chunkP,
                      min( len, maxlen - *bytesDone ) );
                   break;
             }
          }
          FP_INCR(reqB,len);
          *bytesDone += len;
          iP++;
       }
    
       return ( B_NO_ERROR );
    }
    
    /*
    *****************************************************************************
    **
    **  Prototype:
    **
    **      BTI_SINT VerifyChunk(
    **                  BTI_VOID_PTR userDB,
    **                  BTI_WORD bytesToProtect,
    **                  BTI_VOID_PTR ChunkP,
    **                  BTI_WORD ChunkLen,
    **                  BTI_WORD bytesDone,
    **                  BTI_WORD maxlen )
    **
    **  Description:
    **
    **      VerifyChunk makes sure the data will not overwrite the end of the
    **      output buffer.  It also catches attempts to overwrite the
    **      chunk descriptors with the returned data.
    **
    **
    **  Preconditions:
    **
    **      None.
    **
    **  Parameters:
    **
    **      userDB:                 pointer to the user's data buffer.
    **        <input>
    **
    **      bytesToProtect:         Size of request buffer that must not be
    **        <input>               overwritten with returned data.
    **
    **      ChunkP:                 Pointer to the chunk data.
    **        <input>
    **
    **      ChunkLen:
    **        <input>               Length of the chunk data.
    **
    **      bytesDone:              Number of bytes copied so far to user's
    **        <input>               data buffer.
    **
    **      maxlen:                 Maximum length of the user's data buffer.
    **        <input>
    **
    **
    **  Return value:
    **
    **      B_NO_ERROR               Success
    **
    **      B_DATA_MESSAGE_TOO_SMALL Chunk cannot fit in the user's data buffer
    **
    **      B_INVALID_GET_EXPRESSION Chunk data overwrites chunk descriptors
    **
    **  Globals:
    **
    **      None.
    **
    **  Called Functions:
    **
    **      None.
    **
    **  Comments:
    **
    **      None.
    **
    *****************************************************************************
    */
    BTI_SINT VerifyChunk(
                BTI_VOID_PTR userDB,
                BTI_WORD bytesToProtect,
                BTI_VOID_PTR ChunkP,
                BTI_WORD ChunkLen,
                BTI_WORD bytesDone,
                BTI_WORD maxlen )
    {
       register BTI_ULONG uNorm = Normalize(userDB),
                          cNorm = Normalize(ChunkP);
    
       /*
       **   Check for buffer overrun
       */
       if ((BTI_ULONG)bytesDone + (BTI_ULONG)ChunkLen > maxlen)
       {
          return (B_DATA_MESSAGE_TOO_SMALL);
       }
       /*
       **   Check if chunk about to be written overlaps with the extractors
       */
       if ((cNorm + ChunkLen < uNorm) || (cNorm >= uNorm + bytesToProtect))
       {
          return (0);
       }
    
       return (B_INVALID_GET_EXPRESSION);
    }
    #endif /* BTI_DOS_32B || BTI_DOS_32P */
    
    #ifdef __cplusplus
    }
    #endif

  2. #2
    Registered User slingerland3g's Avatar
    Join Date
    Jan 2008
    Location
    Seattle
    Posts
    603
    That just looks strange to me:

    typedef BTI_CHAR BTI_FAR* BTI_CHAR_PTR;

    What is your intent of this typedef and the others?

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    20
    It looks strange to me too! Especially as I'm not a strong C programmer.

    The bulk of the program is as written by pervasive, I've only ever added the BTI_DOS switch on the first line.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    20
    We managed to compile the sample program, btrsamp.c, by following these instructions http://ww1.pervasive.com/library/doc...g_tut-8-2.html and defining the BTI_WIN_32 switch in the PDB, so case closed.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. LDAP Query
    By Travoiz in forum C++ Programming
    Replies: 0
    Last Post: 08-13-2009, 02:58 PM
  2. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  3. C++ std routines
    By siavoshkc in forum C++ Programming
    Replies: 33
    Last Post: 07-28-2006, 12:13 AM
  4. load gif into program
    By willc0de4food in forum Windows Programming
    Replies: 14
    Last Post: 01-11-2006, 10:43 AM
  5. Learning OpenGL
    By HQSneaker in forum C++ Programming
    Replies: 7
    Last Post: 08-06-2004, 08:57 AM