home *** CD-ROM | disk | FTP | other *** search
/ Datatid 1999 #6 / Datatid_1999-06.iso / internet / Tango352Promo / P.SQL / PTKPKG.1 / BTRAPI.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  74.5 KB  |  2,391 lines

  1. /*************************************************************************
  2. **
  3. **  Copyright 1982-1997 Pervasive Software Inc. All Rights Reserved
  4. **
  5. *************************************************************************/
  6. /*************************************************************************
  7.    BTRAPI.C
  8.      This module implements the Btrieve Interface for C/C++ applications
  9.      using MS Windows, Windows 95, Windows NT, OS2, DOS, Extended DOS.  An
  10.      NLM application does not need to compile and link this module.
  11.  
  12.      You must select a target platform switch.  See the prologue inside
  13.      'btrapi.h' for a list of platform switches.
  14.  
  15.      IMPORTANT
  16.      ---------
  17.      Pervasive Software Inc., invites you to modify this file
  18.      if you find it necessary for your particular situation.  However,
  19.      we cannot provide technical support for this module if you
  20.      do modify it.
  21.  
  22. *************************************************************************/
  23. #if !defined(BTI_WIN) && !defined(BTI_OS2) && !defined(BTI_DOS) \
  24. && !defined(BTI_NLM) && !defined(BTI_DOS_32R) && !defined(BTI_DOS_32P) \
  25. && !defined(BTI_DOS_32B) && !defined(BTI_WIN_32) && !defined(BTI_OS2_32)
  26. #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
  27. #endif
  28.  
  29. #include <btrconst.h>
  30. #include <btrapi.h>
  31. #include <string.h>
  32.  
  33. #if defined( BTI_DOS )     || defined( BTI_DOS_32R ) || \
  34.     defined( BTI_DOS_32P ) || defined( BTI_DOS_32B )
  35. #include <dos.h>
  36.  
  37. #define BTR_INTRPT       0x7B                   /* Btrieve interrupt vector */
  38. #define BTR_OFFSET       0x33              /* Btrieve offset within segment */
  39. #define VARIABLE_ID      0x6176    /* id for variable length records - 'va' */
  40. #define PROTECTED_ID     0x6370             /* id for protected call - 'pc' */
  41. #define VERSION_OFFSET   0
  42. #define REVISION_OFFSET  2
  43. #define TYPE_OFFSET      4
  44. #define VERSION_BUF_SIZE 5
  45. #define BTRV_CODE        7
  46. #define TRUE             1
  47. #define FALSE            0
  48.  
  49. typedef unsigned char    BOOLEAN;
  50.  
  51. /* Protected Mode switch parameter block */
  52. typedef struct
  53. {
  54.    BTI_CHAR      sign[ 4 ];
  55.    BTI_ULONG     flags;
  56.    BTI_ULONG     functionCode;
  57.    BTI_LONG      pmSwitchStatus;
  58.    BTI_LONG      dataLength;
  59.    BTI_VOID_PTR  dataPtr;
  60. } pmswParmBlock;
  61. #endif
  62.  
  63. #ifdef __cplusplus
  64. extern "C" {
  65. #endif
  66.  
  67. /***************************************************************************
  68.    PROCESS7B IS IN PMSWITCH, AND IS RESOLVED AT RUN-TIME
  69. ***************************************************************************/
  70. #if defined( BTI_DOS_32R )
  71. typedef struct
  72. {
  73.    char  *Name;
  74.    void  cdecl (*functionPtr) ( pmswParmBlock *bP );
  75. } IMPORTS[];
  76. #define PROCESS7B 75
  77. IMPORTS * _ImportedFunctions_ = 0;
  78. #endif
  79.  
  80. /****************************************************************************
  81.    RQSHELLINIT() Function for MS Windows
  82. ***************************************************************************/
  83. #if defined( BTI_WIN ) || defined( BTI_WIN_32 )
  84. BTI_API RQSHELLINIT( BTI_CHAR_PTR option )
  85. {
  86.    return WBRQSHELLINIT( option );
  87. }
  88. #endif
  89.  
  90. /****************************************************************************
  91.    BTRV() Function for 16-Bit MS Windows or OS2
  92. ***************************************************************************/
  93. #if defined( BTI_WIN ) || defined( BTI_OS2 )
  94. BTI_API BTRV(
  95.            BTI_WORD     operation,
  96.            BTI_VOID_PTR posBlock,
  97.            BTI_VOID_PTR dataBuffer,
  98.            BTI_WORD_PTR dataLength,
  99.            BTI_VOID_PTR keyBuffer,
  100.            BTI_SINT     keyNumber )
  101. {
  102.    BTI_BYTE keyLength = MAX_KEY_SIZE;
  103.    BTI_CHAR ckeynum = (BTI_CHAR)keyNumber;
  104.    return BTRCALL (
  105.              operation,
  106.              posBlock,
  107.              dataBuffer,
  108.              dataLength,
  109.              keyBuffer,
  110.              keyLength,
  111.              ckeynum );
  112. }
  113. #endif
  114.  
  115. /****************************************************************************
  116.    BTRVID() Function for 16-Bit MS Windows or OS2
  117. ***************************************************************************/
  118. #if defined( BTI_WIN ) || defined( BTI_OS2 )
  119. BTI_API BTRVID(
  120.            BTI_WORD       operation,
  121.            BTI_VOID_PTR   posBlock,
  122.            BTI_VOID_PTR   dataBuffer,
  123.            BTI_WORD_PTR   dataLength,
  124.            BTI_VOID_PTR   keyBuffer,
  125.            BTI_SINT       keyNumber,
  126.            BTI_BUFFER_PTR clientID )
  127. {
  128.    BTI_BYTE keyLength = MAX_KEY_SIZE;
  129.    BTI_CHAR ckeynum = (BTI_CHAR)keyNumber;
  130.    return BTRCALLID (
  131.              operation,
  132.              posBlock,
  133.              dataBuffer,
  134.              dataLength,
  135.              keyBuffer,
  136.              keyLength,
  137.              ckeynum,
  138.              clientID );
  139. }
  140. #endif
  141.  
  142. /****************************************************************************
  143.    BTRV() Function for NT, Win32s, or 32-bit OS2
  144. ***************************************************************************/
  145. #if defined( BTI_WIN_32 ) || defined( BTI_OS2_32 )
  146. #if defined( BTI_OS2_32 )
  147. #define BTRCALL BTRCALL32
  148. #endif
  149. BTI_API BTRV(
  150.            BTI_WORD     operation,
  151.            BTI_VOID_PTR posBlock,
  152.            BTI_VOID_PTR dataBuffer,
  153.            BTI_WORD_PTR dataLength,
  154.            BTI_VOID_PTR keyBuffer,
  155.            BTI_SINT     keyNumber )
  156. {
  157.    BTI_BYTE keyLength  = MAX_KEY_SIZE;
  158.    BTI_CHAR ckeynum    = (BTI_CHAR)keyNumber;
  159.    BTI_ULONG dataLen32 = 0;
  160.    BTI_SINT status;
  161.  
  162.    if ( dataLength != NULL )
  163.       dataLen32 = *dataLength;
  164.  
  165.    status = BTRCALL (
  166.               operation,
  167.               posBlock,
  168.               dataBuffer,
  169.               &dataLen32,
  170.               keyBuffer,
  171.               keyLength,
  172.               ckeynum );
  173.  
  174.    if ( dataLength != NULL )
  175.       *dataLength = (BTI_WORD)dataLen32;
  176.  
  177.    return status;
  178. }
  179. #endif
  180.  
  181.  
  182. /****************************************************************************
  183.    BTRVID() Function for NT, Win32s or 32-bit OS2
  184. ***************************************************************************/
  185. #if defined( BTI_WIN_32 ) || defined( BTI_OS2_32 )
  186. #if defined( BTI_OS2_32 )
  187. #define BTRCALLID BTRCALLID32
  188. #endif
  189. BTI_API BTRVID(
  190.            BTI_WORD       operation,
  191.            BTI_VOID_PTR   posBlock,
  192.            BTI_VOID_PTR   dataBuffer,
  193.            BTI_WORD_PTR   dataLength,
  194.            BTI_VOID_PTR   keyBuffer,
  195.            BTI_SINT       keyNumber,
  196.            BTI_BUFFER_PTR clientID )
  197. {
  198.    BTI_BYTE keyLength  = MAX_KEY_SIZE;
  199.    BTI_CHAR ckeynum    = (BTI_CHAR)keyNumber;
  200.    BTI_ULONG dataLen32 = 0;
  201.    BTI_SINT status;
  202.  
  203.    if ( dataLength != NULL )
  204.       dataLen32 = *dataLength;
  205.  
  206.    status = BTRCALLID (
  207.               operation,
  208.               posBlock,
  209.               dataBuffer,
  210.               &dataLen32,
  211.               keyBuffer,
  212.               keyLength,
  213.               ckeynum,
  214.               clientID );
  215.  
  216.    if ( dataLength != NULL )
  217.       *dataLength = (BTI_WORD)dataLen32;
  218.  
  219.    return status;
  220. }
  221. #endif
  222.  
  223.  
  224. /****************************************************************************
  225.    BTRVID() Function for Real Mode DOS ( Btrieve 6.15 or later )
  226. ***************************************************************************/
  227. #if defined( BTI_DOS )
  228. BTI_API BTRVID(
  229.            BTI_WORD       operation,
  230.            BTI_VOID_PTR   posBlock,
  231.            BTI_VOID_PTR   dataBuffer,
  232.            BTI_WORD_PTR   dataLength,
  233.            BTI_VOID_PTR   keyBuffer,
  234.            BTI_SINT       keyNumber,
  235.            BTI_BUFFER_PTR clientID )
  236. {
  237.    /* Microsoft changed function and structure names in 7.x . */
  238.    #if defined( _MSC_VER )
  239.       #if ( _MSC_VER > 600 )
  240.          #define segread _segread
  241.          #define int86x  _int86x
  242.          #define REGS    _REGS
  243.          #define SREGS   _SREGS
  244.       #endif
  245.    #endif
  246.  
  247.    static BOOLEAN btrieveVersionOkay = FALSE;
  248.    BTI_BYTE       versionOffset;
  249.    BTI_BYTE       revisionOffset;
  250.    BTI_BYTE       typeOffset;
  251.    BOOLEAN        done;
  252.    union  REGS    b_regs;
  253.    struct SREGS   b_sregs;
  254.    BTI_SINT       stat = B_NO_ERROR;
  255.    BTI_VOID_PTR   fptr;
  256.    BTI_VOID_PTR   twoPointersPtr;
  257.    pmswParmBlock  newParms;
  258.    BTI_WORD       version;
  259.    BTI_WORD       revision;
  260.  
  261.    struct                     /* structure passed to Btrieve */
  262.    {
  263.       BTI_VOID_PTR   DATA_BUF;                       /* callers data buffer */
  264.       BTI_WORD       BUF_LEN;                      /* length of data buffer */
  265.       BTI_VOID_PTR   POS_BLOCK;                      /* user position block */
  266.       BTI_VOID_PTR   FCB;                                       /* disk FCB */
  267.       BTI_WORD       FUNCTION;                        /* requested function */
  268.       BTI_VOID_PTR   KEY_BUFFER;                       /* user's key buffer */
  269.       BTI_BYTE       KEY_LENGTH;             /* length of user's key buffer */
  270.       BTI_CHAR       KEY_NUMBER;            /* key of reference for request */
  271.       BTI_SINT_PTR   STATUS;                                 /* status word */
  272.       BTI_SINT       XFACE_ID;                       /* language identifier */
  273.     } XDATA;
  274.  
  275.    struct
  276.    {
  277.       BTI_VOID_PTR xdataPtr;
  278.       BTI_VOID_PTR clientIdPtr;
  279.    } twoPointers;
  280.  
  281.    /* Btrieve Parameters for stat call */
  282.    BTI_BYTE posBlockx[ 128 ];
  283.    BTI_BYTE dataBufx[ 255 ];
  284.    BTI_WORD dataLenx;
  285.    BTI_BYTE keyBufx[ 255 ];
  286.    BTI_WORD keyNumx = 0;
  287.  
  288.  
  289.    segread( &b_sregs );
  290.  
  291.    /*=========================================================================
  292.    Check to see that Btrieve has been started.
  293.    =========================================================================*/
  294.    b_regs.x.ax = 0x3500 + BTR_INTRPT;
  295.    int86x( 0x21, &b_regs, &b_regs, &b_sregs );
  296.    if ( b_regs.x.bx != BTR_OFFSET )
  297.       stat = B_RECORD_MANAGER_INACTIVE;
  298.  
  299.    /*=========================================================================
  300.     Check for correct versions of requester and engine.  This check is done
  301.     only once per application.
  302.    =========================================================================*/
  303.    if ( ( stat == B_NO_ERROR ) && ( !btrieveVersionOkay ) )
  304.    {
  305.       versionOffset  = VERSION_OFFSET;
  306.       revisionOffset = REVISION_OFFSET;
  307.       typeOffset     = TYPE_OFFSET;
  308.       done           = FALSE;
  309.       dataLenx       = sizeof( dataBufx );
  310.       stat = BTRV( B_VERSION, posBlockx, &dataBufx, &dataLenx, keyBufx,
  311.                 keyNumx );
  312.       if ( stat == B_NO_ERROR )
  313.       {
  314.          while ( !done )
  315.          {
  316.             version  = (*(BTI_WORD *)&dataBufx[ versionOffset ] );
  317.             revision = (*(BTI_WORD *)&dataBufx[ revisionOffset ] );
  318.             switch( *(BTI_BYTE *)&dataBufx[ typeOffset ] )
  319.             {
  320.                /* Must have requestor version 6.16 or higher. */
  321.                case 'N':
  322.                   if ( ( ( version == 6 ) && ( revision < 16 ) ) ||
  323.                        ( version < 6 ) )
  324.                      {
  325.                         stat = B_INVALID_INTERFACE;
  326.                         done = TRUE;
  327.                      }
  328.                      break;
  329.                /* Must have engine version 6 or higher. */
  330.                case 'D':
  331.                   if ( version < 6 )
  332.                      {
  333.                         stat = B_INVALID_INTERFACE;
  334.                         done = TRUE;
  335.                      }
  336.                      break;
  337.                case 0:
  338.                   done = TRUE;
  339.                   break;
  340.             }
  341.             if ( !done )
  342.             {
  343.                versionOffset  = versionOffset  + VERSION_BUF_SIZE;
  344.                revisionOffset = revisionOffset + VERSION_BUF_SIZE;
  345.                typeOffset     = typeOffset     + VERSION_BUF_SIZE;
  346.                continue;
  347.             }
  348.          }
  349.       }
  350.       else
  351.          stat = B_INVALID_INTERFACE;
  352.    }
  353.  
  354.    if ( stat == B_NO_ERROR )
  355.    {
  356.       /*======================================================================
  357.       Move user parameters to XDATA, the block where Btrieve expects them.
  358.       ======================================================================*/
  359.       XDATA.FUNCTION    = operation;
  360.       XDATA.STATUS      = &stat;
  361.       XDATA.FCB         = posBlock;
  362.       XDATA.POS_BLOCK   = (BTI_BUFFER_PTR)posBlock + 38;
  363.       XDATA.DATA_BUF    = dataBuffer;
  364.       XDATA.BUF_LEN     = *dataLength;
  365.       XDATA.KEY_BUFFER  = keyBuffer;
  366.       XDATA.KEY_LENGTH  = 255;               /* use max since we don't know */
  367.       XDATA.KEY_NUMBER  = (BTI_CHAR)keyNumber;
  368.       XDATA.XFACE_ID    = VARIABLE_ID;
  369.  
  370.       btrieveVersionOkay = TRUE;
  371.       twoPointers.xdataPtr = &XDATA;
  372.       twoPointers.clientIdPtr = clientID;
  373.       twoPointersPtr = &twoPointers;
  374.       *((BTI_LONG_PTR) &(newParms.sign)) = *((BTI_LONG_PTR) "PMSW" );
  375.       newParms.flags = 0;
  376.       newParms.functionCode = BTRV_CODE;
  377.       newParms.dataLength = sizeof( newParms );
  378.       newParms.dataPtr = twoPointersPtr;
  379.  
  380.       /*======================================================================
  381.       Make call to Btrieve.
  382.       ======================================================================*/
  383.       fptr = &newParms;
  384.       b_regs.x.dx = FP_OFF(fptr);
  385.       b_sregs.ds = FP_SEG(fptr);
  386.  
  387.       int86x( BTR_INTRPT, &b_regs, &b_regs, &b_sregs );
  388.       *dataLength = XDATA.BUF_LEN;
  389.    }
  390.    return( stat );
  391. }
  392. #endif
  393.  
  394.  
  395. /***************************************************************************
  396.    BTRV() Function for Real Mode DOS
  397. ***************************************************************************/
  398. #if defined( BTI_DOS )
  399. BTI_API BTRV(
  400.            BTI_WORD     operation,
  401.            BTI_VOID_PTR posBlock,
  402.            BTI_VOID_PTR dataBuffer,
  403.            BTI_WORD_PTR dataLength,
  404.            BTI_VOID_PTR keyBuffer,
  405.            BTI_SINT     keyNumber )
  406. {
  407.    /* Microsoft changed function and structure names in 7.x . */
  408.    #if defined( _MSC_VER )
  409.       #if ( _MSC_VER > 600 )
  410.          #define segread _segread
  411.          #define int86x  _int86x
  412.          #define REGS    _REGS
  413.          #define SREGS   _SREGS
  414.       #endif
  415.    #endif
  416.  
  417.    union REGS b_regs;
  418.    struct SREGS b_sregs;
  419.  
  420.    struct                     /* structure passed to Btrieve */
  421.    {
  422.       BTI_VOID_PTR   DATA_BUF;                       /* callers data buffer */
  423.       BTI_WORD       BUF_LEN;                      /* length of data buffer */
  424.       BTI_VOID_PTR   POS_BLOCK;                      /* user position block */
  425.       BTI_VOID_PTR   FCB;                                       /* disk FCB */
  426.       BTI_WORD       FUNCTION;                        /* requested function */
  427.       BTI_VOID_PTR   KEY_BUFFER;                       /* user's key buffer */
  428.       BTI_BYTE       KEY_LENGTH;             /* length of user's key buffer */
  429.       BTI_CHAR       KEY_NUMBER;            /* key of reference for request */
  430.       BTI_SINT_PTR   STATUS;                                 /* status word */
  431.       BTI_SINT       XFACE_ID;                       /* language identifier */
  432.     } XDATA;
  433.  
  434.    BTI_VOID_PTR fptr;
  435.    BTI_SINT     stat = B_NO_ERROR;
  436.  
  437.    segread( &b_sregs );
  438.  
  439.    /*=========================================================================
  440.    Check to see that Btrieve has been started.
  441.    =========================================================================*/
  442.    b_regs.x.ax = 0x3500 + BTR_INTRPT;
  443.    int86x( 0x21, &b_regs, &b_regs, &b_sregs );
  444.    if ( b_regs.x.bx != BTR_OFFSET )
  445.       stat = B_RECORD_MANAGER_INACTIVE;
  446.  
  447.    /*=========================================================================
  448.    Move user parameters to XDATA, the block where Btrieve expects them.
  449.    =========================================================================*/
  450.    if ( stat == B_NO_ERROR )
  451.    {
  452.       XDATA.FUNCTION    = operation;
  453.       XDATA.STATUS      = &stat;
  454.       XDATA.FCB         = posBlock;
  455.       XDATA.POS_BLOCK   = (BTI_BUFFER_PTR)posBlock + 38;
  456.       XDATA.DATA_BUF    = dataBuffer;
  457.       XDATA.BUF_LEN     = *dataLength;
  458.       XDATA.KEY_BUFFER  = keyBuffer;
  459.       XDATA.KEY_LENGTH  = 255;               /* use max since we don't know */
  460.       XDATA.KEY_NUMBER  = (BTI_CHAR)keyNumber;
  461.       XDATA.XFACE_ID    = VARIABLE_ID;
  462.  
  463.       /*======================================================================
  464.       Make call to Btrieve.
  465.       ======================================================================*/
  466.       fptr = &XDATA;
  467.       b_regs.x.dx = FP_OFF(fptr);    /*parameter block is expected to be in DX */
  468.       b_sregs.ds = FP_SEG(fptr);
  469.  
  470.       int86x( BTR_INTRPT, &b_regs, &b_regs, &b_sregs );
  471.       *dataLength = XDATA.BUF_LEN;
  472.    }
  473.    return( stat );
  474. }
  475. #endif
  476.  
  477.  
  478. /***************************************************************************
  479.    BTRVID() Function for Extended DOS Using Rational + BSTUB.EXE
  480. ***************************************************************************/
  481. #if defined( BTI_DOS_32R )
  482. BTI_API BTRVID(
  483.            BTI_WORD       operation,
  484.            BTI_VOID_PTR   posBlock,
  485.            BTI_VOID_PTR   dataBuffer,
  486.            BTI_WORD_PTR   dataLength,
  487.            BTI_VOID_PTR   keyBuffer,
  488.            BTI_SINT       keyNumber,
  489.            BTI_BUFFER_PTR clientID )
  490. {
  491.  
  492.    BTI_SINT      stat = B_NO_ERROR;
  493.    BTI_VOID_PTR  twoPointersPtr;
  494.    pmswParmBlock newParms;
  495.  
  496.    struct
  497.    {
  498.       BTI_VOID_PTR xdataPtr;
  499.       BTI_VOID_PTR clientIdPtr;
  500.    } twoPointers;
  501.  
  502.    /*=========================================================================
  503.    Check to see that Btrieve has been started.
  504.    =========================================================================*/
  505.    /* bstub code will check for presence of Btrieve; no need to check ver */
  506.  
  507.    /*=========================================================================
  508.    Move user parameters to XDATA, the block where Btrieve expects them.
  509.    =========================================================================*/
  510.    struct                  /* structure passed to Btrieve */
  511.    {
  512.       BTI_VOID_PTR   DATA_BUF;                    /* callers data buffer */
  513.       BTI_WORD       BUF_LEN;                   /* length of data buffer */
  514.       BTI_VOID_PTR   POS_BLOCK;                   /* user position block */
  515.       BTI_VOID_PTR   FCB;                                    /* disk FCB */
  516.       BTI_WORD       FUNCTION;                     /* requested function */
  517.       BTI_VOID_PTR   KEY_BUFFER;                    /* user's key buffer */
  518.       BTI_BYTE       KEY_LENGTH;          /* length of user's key buffer */
  519.       BTI_CHAR       KEY_NUMBER;         /* key of reference for request */
  520.       BTI_SINT_PTR   STATUS;                              /* status word */
  521.       BTI_SINT       XFACE_ID;                    /* language identifier */
  522.     } XDATA;
  523.  
  524.    /*======================================================================
  525.    Move user parameters to XDATA, the block where Btrieve expects them.
  526.    ======================================================================*/
  527.    XDATA.FUNCTION    = operation;
  528.    XDATA.STATUS      = &stat;
  529.    XDATA.FCB         = posBlock;
  530.    XDATA.POS_BLOCK   = (BTI_BUFFER_PTR)posBlock + 38;
  531.    XDATA.DATA_BUF    = dataBuffer;
  532.    XDATA.BUF_LEN     = *dataLength;
  533.    XDATA.KEY_BUFFER  = keyBuffer;
  534.    XDATA.KEY_LENGTH  = 255;               /* use max since we don't know */
  535.    XDATA.KEY_NUMBER  = (BTI_CHAR)keyNumber;
  536.    XDATA.XFACE_ID    = PROTECTED_ID;
  537.  
  538.    /*=========================================================================
  539.    Set up the new parmeter block.
  540.    =========================================================================*/
  541.    twoPointers.xdataPtr = &XDATA;
  542.    twoPointers.clientIdPtr = clientID;
  543.    twoPointersPtr = &twoPointers;
  544.    *((BTI_LONG_PTR) &(newParms.sign)) = *((BTI_LONG_PTR) "PMSW" );
  545.    newParms.flags = 0;
  546.    newParms.functionCode = BTRV_CODE;
  547.    newParms.dataLength = sizeof( newParms );
  548.    newParms.dataPtr = twoPointersPtr;
  549.  
  550.    /*======================================================================
  551.    Make call to Btrieve.
  552.    ======================================================================*/
  553.    (*_ImportedFunctions_)[ PROCESS7B ].functionPtr(
  554.                                                 (pmswParmBlock *)&newParms );
  555.  
  556.    *dataLength = XDATA.BUF_LEN;
  557.    return( stat );
  558. }
  559. #endif
  560.  
  561.  
  562. /***************************************************************************
  563.    BTRV() Function for Extended DOS Using Rational + BSTUB.EXE
  564. ***************************************************************************/
  565. #if defined( BTI_DOS_32R )
  566. BTI_API BTRV(
  567.            BTI_WORD     operation,
  568.            BTI_VOID_PTR posBlock,
  569.            BTI_VOID_PTR dataBuffer,
  570.            BTI_WORD_PTR dataLength,
  571.            BTI_VOID_PTR keyBuffer,
  572.            BTI_SINT     keyNumber )
  573. {
  574.    BTI_SINT      stat = B_NO_ERROR;
  575.  
  576.    /*=========================================================================
  577.    Check to see that Btrieve has been started.
  578.    =========================================================================*/
  579.    /* bstub code will check for presence of Btrieve */
  580.  
  581.    /*=========================================================================
  582.    Move user parameters to XDATA, the block where Btrieve expects them.
  583.    =========================================================================*/
  584.    struct                  /* structure passed to Btrieve */
  585.    {
  586.       BTI_VOID_PTR   DATA_BUF;                    /* callers data buffer */
  587.       BTI_WORD       BUF_LEN;                   /* length of data buffer */
  588.       BTI_VOID_PTR   POS_BLOCK;                   /* user position block */
  589.       BTI_VOID_PTR   FCB;                                    /* disk FCB */
  590.       BTI_WORD       FUNCTION;                     /* requested function */
  591.       BTI_VOID_PTR   KEY_BUFFER;                    /* user's key buffer */
  592.       BTI_BYTE       KEY_LENGTH;          /* length of user's key buffer */
  593.       BTI_CHAR       KEY_NUMBER;         /* key of reference for request */
  594.       BTI_SINT_PTR   STATUS;                              /* status word */
  595.       BTI_SINT       XFACE_ID;                    /* language identifier */
  596.     } XDATA;
  597.  
  598.    /*======================================================================
  599.    Move user parameters to XDATA, the block where Btrieve expects them.
  600.    ======================================================================*/
  601.    XDATA.FUNCTION    = operation;
  602.    XDATA.STATUS      = &stat;
  603.    XDATA.FCB         = posBlock;
  604.    XDATA.POS_BLOCK   = (BTI_BUFFER_PTR)posBlock + 38;
  605.    XDATA.DATA_BUF    = dataBuffer;
  606.    XDATA.BUF_LEN     = *dataLength;
  607.    XDATA.KEY_BUFFER  = keyBuffer;
  608.    XDATA.KEY_LENGTH  = 255;               /* use max since we don't know */
  609.    XDATA.KEY_NUMBER  = (BTI_CHAR)keyNumber;
  610.    XDATA.XFACE_ID    = PROTECTED_ID;
  611.  
  612.    /*======================================================================
  613.    Make call to Btrieve.
  614.    ======================================================================*/
  615.    (*_ImportedFunctions_)[ PROCESS7B ].functionPtr(
  616.                                                 (pmswParmBlock *)&XDATA );
  617.    *dataLength = XDATA.BUF_LEN;
  618.    return( stat );
  619. }
  620. #endif
  621.  
  622.  
  623. /***************************************************************************
  624.    'Borland PowerPack' and 'Phar-Lap TNT 6.0' 32-Bit Interfaces
  625. ***************************************************************************/
  626. #if defined( BTI_DOS_32B ) || defined( BTI_DOS_32P )
  627.  
  628. #define min(a,b)    (((a) < (b)) ? (a) : (b))
  629.  
  630. #if defined( BTI_DOS_32B )
  631. /***************************************************************************
  632. ** Define Far pointer data type (selector:offset32)
  633. **
  634. ** The Borland C 32-bit compiler does not support far pointers.  For this
  635. ** compiler, a FARPTR is defined as a structure which has the same
  636. ** organization in memory as a standard 48-bit far pointer.
  637. **
  638. ** The following macros are used to get and set the selector and offset
  639. ** fields of far pointers, and work both for compilers that directly
  640. ** support far pointers and compilers that don't have far pointer support.
  641. ** The FP_SEL macro returns the 16-bit selector number field
  642. ** of a far pointer.  The FP_OFF macro returns the 32-bit offset
  643. ** field of a far pointer.  The FP_SET macro is used to construct a far
  644. ** pointer from a selector number and offset.  It takes three arguments:
  645. ** the name of the far pointer to be set, an offset, and a selector number.
  646. ** The FP_INCR macro increments the offset field of a far pointer.
  647. ***************************************************************************/
  648.    typedef struct
  649.    {
  650.       BTI_ULONG    Off;
  651.       BTI_WORD    Sel;
  652.    } FARPTR;
  653.  
  654.    #ifndef FP_SEL
  655.       #define FP_SEL(fp) ((fp).Sel)
  656.    #endif
  657.  
  658.    #ifndef FP_OFF
  659.       #define FP_OFF(fp) ((fp).Off)
  660.    #endif
  661.  
  662.    #ifndef FP_SET
  663.       #define FP_SET(fp, off, sel) \
  664.     {\
  665.         (fp).Sel = (BTI_WORD) (sel);\
  666.         (fp).Off = (BTI_ULONG) (off);\
  667.     }
  668.    #endif
  669.  
  670.    #ifndef FP_INCR
  671.       #define FP_INCR(fp, incr) ((fp).Off += (BTI_ULONG) (incr))
  672.    #endif
  673.  
  674.    /*
  675.    ** Include files for Borland Compiler
  676.    */
  677.    #include <windows.h>
  678.  
  679. #else
  680.    /*
  681.    ** Include files for PharLap extender
  682.    */
  683.    #include <i86.h>
  684.    #include <pharlap.h>
  685.  
  686. #endif
  687.  
  688. #include <blobhdr.h>          /* structure definitions for chunk operations */
  689.  
  690. /*
  691. ** Constant definitions
  692. */
  693. #define structoffset(s,m) (unsigned)(((char *)(&((s *)0)->m))-((char *)0))
  694. #define Normalize(x)     ((BTI_ULONG)(x))
  695. #define CLIENT_ID_SIZE 16
  696.  
  697. /*============================================================================
  698. The XDATASTRUCT defines the Btrieve parameter block
  699. ============================================================================*/
  700. typedef struct                /* structure passed to Btrieve */
  701. {
  702.    BTI_ULONG      DATA_BUF;                          /* callers data buffer */
  703.    BTI_WORD       BUF_LEN;                         /* length of data buffer */
  704.    BTI_ULONG      POS_BLOCK;                         /* user position block */
  705.    BTI_ULONG      FCB;                                          /* disk FCB */
  706.    BTI_WORD       FUNCTION;                           /* requested function */
  707.    BTI_ULONG      KEY_BUFFER;                          /* user's key buffer */
  708.    BTI_BYTE       KEY_LENGTH;                /* length of user's key buffer */
  709.    BTI_CHAR       KEY_NUMBER;               /* key of reference for request */
  710.    BTI_ULONG      STATUS;                                    /* status word */
  711.    BTI_SINT       XFACE_ID;                          /* language identifier */
  712. } XDATASTRUCT;
  713.  
  714. /*============================================================================
  715. This structure defines the real mode buffer.  The DATA_BUF parameter is
  716. set up as one byte for reference.  Memory needs to be declared large enough
  717. for data buffers that will be returned.
  718. ============================================================================*/
  719. typedef struct
  720. {
  721.    XDATASTRUCT XDATA;
  722.    BTI_SINT    STATUS;
  723.    BTI_BYTE    POS_BLOCK[128];
  724.    BTI_BYTE    KEY_BUFFER[255];
  725.    BTI_BYTE    DATA_BUF[1];
  726. } RMBUFF;
  727.  
  728.  
  729. /*============================================================================
  730. Prototypes for functions in protected mode interface
  731. =============================================================================*/
  732. BTI_SINT BtrLoaded( void );
  733.  
  734. BTI_VOID CallBTRV(
  735.             BTI_ULONG );
  736.  
  737. BTI_SINT GetRealModeBuffer(
  738.             FARPTR *,
  739.             BTI_ULONG *,
  740.             BTI_ULONG );
  741.  
  742. BTI_SINT SetUpBTRVData(
  743.             FARPTR *,
  744.             BTI_VOID_PTR,
  745.             BTI_VOID_PTR,
  746.             BTI_VOID_PTR );
  747.  
  748. BTI_VOID RetrieveBTRVData(
  749.             FARPTR *,
  750.             BTI_VOID_PTR,
  751.             BTI_VOID_PTR,
  752.             BTI_VOID_PTR );
  753.  
  754. BTI_SINT BlobInputDBlen(
  755.             register XTRACTR *);
  756.  
  757. BTI_SINT ProcessIndirect(
  758.             FARPTR *,
  759.             BTI_VOID_PTR,
  760.             BTI_WORD,
  761.             BTI_SINT,
  762.             BTI_WORD * );
  763.  
  764. BTI_SINT VerifyChunk(
  765.             BTI_VOID_PTR,
  766.             BTI_WORD,
  767.             BTI_VOID_PTR,
  768.             BTI_WORD,
  769.             BTI_WORD,
  770.             BTI_WORD );
  771.  
  772. /*
  773. ** The following function are in assembly language- define with CDECL
  774. */
  775.  
  776. extern BTI_CHAR  cdecl getLowMemByte(
  777.                           BTI_WORD,
  778.                           BTI_ULONG );
  779.  
  780. extern BTI_CHAR  cdecl setLowMemByte(
  781.                           BTI_WORD,
  782.                           BTI_ULONG,
  783.                           BTI_BYTE );
  784.  
  785. extern BTI_WORD  cdecl getLowMemWord(
  786.                           BTI_WORD,
  787.                           BTI_ULONG );
  788.  
  789. extern BTI_WORD  cdecl setLowMemWord(
  790.                           BTI_WORD,
  791.                           BTI_ULONG,
  792.                           BTI_WORD );
  793.  
  794. extern BTI_ULONG cdecl getLowMemLong(
  795.                           BTI_WORD,
  796.                           BTI_ULONG );
  797.  
  798. extern BTI_ULONG cdecl setLowMemLong(
  799.                           BTI_WORD,
  800.                           BTI_ULONG,
  801.                           BTI_ULONG );
  802.  
  803. extern void cdecl copyToLow(
  804.                      unsigned short dst_sel,
  805.                      unsigned dst_offset,
  806.                      void * src,
  807.                      unsigned int size);
  808.  
  809. extern void cdecl copyFromLow(
  810.                      void * dst,
  811.                      unsigned short src_sel,
  812.                      unsigned src_offset,
  813.                      unsigned int size);
  814.  
  815. /*
  816. *****************************************************************************
  817. **
  818. **  Prototype:
  819. **
  820. **      BTI_SINT GetRealModeBuffer(
  821. **                  FARPTR *protectedP,
  822. **                  BTI_ULONG *realAddr,
  823. **                  BTI_ULONG requestedSize )
  824. **
  825. **  Description:
  826. **
  827. **      This function returns a protected mode pointer and a real mode
  828. **      pointer to a block of memory allocated in DOS real memory.
  829. **      This memory is used for the Btrieve parameter block information.
  830. **      When BTI_DOS_32B is defined, this function allocates DOS real
  831. **      memory.  When BTI_DOS_32P is defined, this function uses a
  832. **      DOS buffer that is preallocated by PharLap.
  833. **
  834. **  Preconditions:
  835. **
  836. **      None.
  837. **
  838. **  Parameters:
  839. **
  840. **      *protectedP:        On output, protectedP is the protected mode
  841. **        <output>          pointer to the real memory Btrieve parameter
  842. **                          block.
  843. **
  844. **      *realAddr:          On output, realAddr contains the real mode
  845. **        <output>          pointer the Btrieve parameter block in DOS
  846. **                          real memory.
  847. **
  848. **      requestedSize:      Contains the size of memory to allocate.
  849. **        <input>
  850. **
  851. **
  852. **  Return value:
  853. **
  854. **      B_NO_ERROR          GetRealModeBuffer is successful.
  855. **
  856. **      B_DATALENGTH_ERROR  If BTI_DOS_32B is defined, this status code is
  857. **                          returned if the int386 call fails to allocate
  858. **                          the DOS real memory block.
  859. **
  860. **                          If BTI_DOS_32P is defined, this status is
  861. **                          returned when the requestedSize + dataLength
  862. **                          is smaller than the size of the DOS buffer.
  863. **                          As an enhancement to the interface, a call to
  864. **                          _dx_dosbuf_set could be made to set the
  865. **                          size of the PharLap DOS buffer before the call
  866. **                          to _dx_dosbuf_get instead of relying on the
  867. **                          default buffer size.
  868. **
  869. **
  870. **  Globals:
  871. **
  872. **      None.
  873. **
  874. **  Called Functions:
  875. **
  876. **      BTI_DOS_32B:
  877. **         int386() - Use DPMI services to allocate DOS memory.
  878. **
  879. **      BTI_DOS_32P:
  880. **         _dx_dosbuf_get - PharLap function to return protected mode and
  881. **                          real mode pointers to a DOS buffer that PharLap
  882. **                          maintains.
  883. **
  884. **  Comments:
  885. **
  886. **      None.
  887. **
  888. *****************************************************************************
  889. */
  890. BTI_SINT GetRealModeBuffer(
  891.             FARPTR *protectedP,    /* protected mode pointer to real memory */
  892.             BTI_ULONG *realAddr,        /* real mode pointer to real memory */
  893.             BTI_ULONG requestedSize )         /* size of buffer to allocate */
  894.  
  895. #if defined( BTI_DOS_32B )
  896. {
  897.    /*=========================================================================
  898.    GetRealModeBuffer - Borland Power Pack
  899.    =========================================================================*/
  900.  
  901.    BTI_SINT allocStatus;
  902.  
  903.    union REGS inRegs, outRegs;
  904.  
  905.    /*
  906.    ** Allocate DOS Memory
  907.    ** Interrupt 31h, function 100h
  908.    ** Note: The DPMI server must support version 0.9 or later of the DPMI
  909.    **       specification to support this this function.  An error code
  910.    **       will be returned in the AX register and returned to caller
  911.    **       as B_DATALENGTH_ERROR.
  912.    **
  913.    ** AX = 100h
  914.    ** BX = Number of 16-byte paragraphs to allocate
  915.    **
  916.    ** Returns:
  917.    **
  918.    ** if carry flag is clear
  919.    **    AX = real mode segment base address of allocated block
  920.    **    DX = selector for allocated block
  921.    **
  922.    ** if carry flag is set
  923.    **    AX = error code
  924.    **
  925.    */
  926.    inRegs.x.eax = 0x100;
  927.    inRegs.x.ebx = (requestedSize + 15) / 16;        /* Number of paragraphs */
  928.  
  929.    int386( 0x31, &inRegs, &outRegs );
  930.  
  931.    if ( outRegs.x.cflag )
  932.       allocStatus = B_DATALENGTH_ERROR;
  933.    else
  934.    {
  935.       *realAddr = (outRegs.x.eax << 16) & 0xFFFF0000;
  936.       FP_SET( *protectedP, 0, (BTI_WORD) outRegs.x.edx );
  937.       allocStatus = B_NO_ERROR;
  938.    }
  939.  
  940.    return allocStatus;
  941. }
  942. #else
  943. {
  944.    /*=========================================================================
  945.    GetRealModeBuffer - Phar Lap Extender
  946.    =========================================================================*/
  947.    BTI_SINT stat;                                     /* Return status code */
  948.    BTI_ULONG bufferSize;
  949.  
  950.    /*
  951.    ** Get Information about the DOS Data Buffer
  952.    **
  953.    ** The _dx_dos_buf_get function returns real and protected-mode pointers
  954.    ** to the buffer used to buffer data on MS-DOS and BIOS system calls.  The
  955.    ** size of the buffer is returned in the size parameter.  Note: need to
  956.    ** make this call each time because address of the MS_DOS buffer changes
  957.    ** when anyone calls Load for Debug(_dx_dbg_ld) or the Set DOS Data Buffer
  958.    ** Size(_dx_dosbuf_set).
  959.    */
  960.  
  961.    _dx_dosbuf_get( (FARPTR *) protectedP, realAddr, &bufferSize);
  962.  
  963.    if ( bufferSize < requestedSize )
  964.       stat = B_DATALENGTH_ERROR;
  965.    else
  966.       stat = B_NO_ERROR;
  967.  
  968.    return stat;
  969. }
  970. #endif
  971.  
  972. /*
  973. *****************************************************************************
  974. **
  975. **  Prototype:
  976. **
  977. **      static void FreeRealModeBuffer( BTI_WORD sel )
  978. **
  979. **  Description:
  980. **
  981. **      FreeRealModeBuffer frees the memory allocated by GetRealModeBuffer
  982. **      when BTI_DOS_32B is defined.  For BTI_DOS_32P there is nothing to do.
  983. **
  984. **  Preconditions:
  985. **
  986. **      None.
  987. **
  988. **  Parameters:
  989. **
  990. **      sel:            Protected mode selector of the Real Mode buffer to
  991. **        <input>       free.
  992. **
  993. **
  994. **  Return value:
  995. **
  996. **      None.
  997. **
  998. **
  999. **  Globals:
  1000. **
  1001. **      None.
  1002. **
  1003. **  Called Functions:
  1004. **
  1005. **      int386
  1006. **
  1007. **  Comments:
  1008. **
  1009. **      None.
  1010. **
  1011. *****************************************************************************
  1012. */
  1013. static void FreeRealModeBuffer( BTI_WORD sel )
  1014. {
  1015. #if defined( BTI_DOS_32B )
  1016.    union REGS inRegs, outRegs;
  1017.  
  1018.  
  1019.    inRegs.x.edx = sel;                              /* Selector to be freed */
  1020.    inRegs.x.eax = 0x101;
  1021.  
  1022.    int386( 0x31, &inRegs, &outRegs );
  1023.  
  1024. #else
  1025.  
  1026.    /*
  1027.    ** Phar Lap specific code
  1028.    */
  1029.  
  1030.    /* do nothing */
  1031. #endif
  1032. }
  1033.  
  1034. /*
  1035. *****************************************************************************
  1036. **
  1037. **  Prototype:
  1038. **
  1039. **      BTI_SINT BtrLoaded( )
  1040. **
  1041. **  Description:
  1042. **
  1043. **      This function checks to see if Btrieve is loaded.
  1044. **
  1045. **  Preconditions:
  1046. **
  1047. **      None.
  1048. **
  1049. **  Parameters:
  1050. **
  1051. **      None.
  1052. **
  1053. **  Return value:
  1054. **
  1055. **      B_NO_ERROR                      Btrieve is loaded
  1056. **
  1057. **      B_RECORD_MANAGER_INACTIVE       Btrieve is not loaded.
  1058. **
  1059. **  Globals:
  1060. **
  1061. **      None.
  1062. **
  1063. **  Called Functions:
  1064. **
  1065. **      BTI_DOS_32B             BTI_DOS_32P
  1066. **
  1067. **        int386()              _dx_rmiv_get()
  1068. **
  1069. **
  1070. **  Comments:
  1071. **
  1072. **      None.
  1073. **
  1074. *****************************************************************************
  1075. */
  1076. BTI_SINT BtrLoaded( )
  1077. {
  1078.    BTI_ULONG             btrAddress;
  1079.    BTI_SINT              stat;
  1080.  
  1081. #if defined( BTI_DOS_32B )
  1082.    union REGS            inRegs, outRegs;
  1083.  
  1084.    inRegs.x.eax = 0x200;
  1085.    inRegs.x.ebx = BTR_INTRPT;
  1086.  
  1087.    int386( 0x31, &inRegs, &outRegs );
  1088.    btrAddress = outRegs.x.edx;
  1089.  
  1090.    if (( (BTI_WORD) (((BTI_ULONG)(btrAddress)) & 0xFFFF) ) != BTR_OFFSET )
  1091.       stat = B_RECORD_MANAGER_INACTIVE;
  1092.    else
  1093.       stat = B_NO_ERROR;
  1094.  
  1095.    return ( stat );
  1096. }
  1097. #else
  1098.    /*
  1099.    **   The _dx_rmiv_get routine returns the real-mode interrupt
  1100.    **   vector for interupt 7b
  1101.    */
  1102.  
  1103.    _dx_rmiv_get( BTR_INTRPT, &btrAddress );
  1104.  
  1105.    if (( (BTI_WORD) (((BTI_ULONG)(btrAddress)) & 0xFFFF) ) != BTR_OFFSET )
  1106.       stat = B_RECORD_MANAGER_INACTIVE;
  1107.    else
  1108.       stat = B_NO_ERROR;
  1109.  
  1110.    return (stat);
  1111. }
  1112. #endif
  1113.  
  1114. /*
  1115. *****************************************************************************
  1116. **
  1117. **  Prototype:
  1118. **
  1119. **      BTI_VOID CallBTRV( BTI_ULONG realPtr )
  1120. **
  1121. **  Description:
  1122. **
  1123. **      CallBTRV calls Btrieve using real mode interrupt 7B.
  1124. **
  1125. **  Preconditions:
  1126. **
  1127. **      None.
  1128. **
  1129. **  Parameters:
  1130. **
  1131. **      realPtr:                Real mode pointer to the Btrieve parameter
  1132. **        <input>               block in real memory.
  1133. **
  1134. **
  1135. **  Return value:
  1136. **
  1137. **      None.
  1138. **
  1139. **
  1140. **  Globals:
  1141. **
  1142. **      None.
  1143. **
  1144. **  Called Functions:
  1145. **
  1146. **      BTI_DOS_32B             BTI_DOS_32P
  1147. **
  1148. **        int386()              _dx_real_int()
  1149. **
  1150. **
  1151. **  Comments:
  1152. **
  1153. **      None.
  1154. **
  1155. **
  1156. *****************************************************************************
  1157. */
  1158. BTI_VOID CallBTRV( BTI_ULONG realPtr )
  1159. #if defined( BTI_DOS_32B )
  1160. {
  1161.    /*
  1162.    **   Call Btrieve using Borland Power Pack DOS Extender
  1163.    */
  1164.    union  REGS           b_regs;
  1165.    struct   REALMODEREGS
  1166.    {
  1167.       BTI_ULONG edi;
  1168.       BTI_ULONG esi;
  1169.       BTI_ULONG ebp;
  1170.       BTI_ULONG reserved;
  1171.       BTI_ULONG ebx;
  1172.       BTI_ULONG edx;
  1173.       BTI_ULONG ecx;
  1174.       BTI_ULONG eax;
  1175.       BTI_WORD  CPUflag;
  1176.       BTI_WORD  es;
  1177.       BTI_WORD  ds;
  1178.       BTI_WORD  fs;
  1179.       BTI_WORD  gs;
  1180.       BTI_WORD  ip;
  1181.       BTI_WORD  cs;
  1182.       BTI_WORD  sp;
  1183.       BTI_WORD  ss;
  1184.    } realmodeRegs;
  1185.  
  1186.    b_regs.x.eax = 0x300;
  1187.    b_regs.h.bl  = BTR_INTRPT;
  1188.    b_regs.h.bh  = 0;
  1189.      /* CX = Number of words to copy from protected-mode to real-mode stack */
  1190.    b_regs.x.ecx = 0;
  1191.  
  1192.    /*
  1193.    ** Initialize real mode segment registers for call to Btrieve
  1194.    */
  1195.    memset( &realmodeRegs, 0, sizeof(struct REALMODEREGS) );
  1196.  
  1197.    realmodeRegs.ds  = (BTI_WORD) (realPtr >> 16);  /* Segment of parm block */
  1198.    realmodeRegs.edx = (realPtr << 16);         /* Offset of parameter block */
  1199.  
  1200.    b_regs.x.edi = (BTI_ULONG) &realmodeRegs;
  1201.  
  1202.    int386( 0x31, &b_regs, &b_regs );
  1203. }
  1204. #else
  1205. {
  1206.    /*
  1207.    ** Phar Lap DOS extender specific code
  1208.    */
  1209.    SWI_REGS              b_regs;
  1210.  
  1211.    memset( &b_regs, 0, sizeof( b_regs ) );
  1212.    b_regs.ds  = RP_SEG( realPtr );
  1213.    b_regs.edx = RP_OFF( realPtr );
  1214.  
  1215.    /*
  1216.    **   The _dx_real_int routine issues the 7b interrupt in real mode
  1217.    */
  1218.    _dx_real_int( BTR_INTRPT, &b_regs );
  1219. }
  1220. #endif
  1221.  
  1222.  
  1223. /***************************************************************************
  1224.     BTRVID() Function for Extended DOS Using 'Borland PowerPack' or
  1225.     'Phar-Lap TNT 6.0' DOS Extenders
  1226. ***************************************************************************/
  1227. BTI_API BTRVID(
  1228.            BTI_WORD       operation,
  1229.            BTI_VOID_PTR   posBlock,
  1230.            BTI_VOID_PTR   dataBuffer,
  1231.            BTI_WORD_PTR   dataLength,
  1232.            BTI_VOID_PTR   keyBuffer,
  1233.            BTI_SINT       keyNumber,
  1234.            BTI_BUFFER_PTR clientID )
  1235. {
  1236.    /* Microsoft changed function and structure names in 7.x . */
  1237.    #if defined( _MSC_VER )
  1238.       #if ( _MSC_VER > 600 )
  1239.          #define segread _segread
  1240.          #define int86x  _int86x
  1241.          #define REGS    _REGS
  1242.          #define SREGS   _SREGS
  1243.       #endif
  1244.    #endif
  1245.  
  1246.    typedef struct
  1247.    {
  1248.       BTI_ULONG xdataPtr;
  1249.       BTI_ULONG clientIdPtr;
  1250.    } TWOPTRSTRUCT;
  1251.  
  1252.    typedef struct
  1253.    {
  1254.       pmswParmBlock  newParms;
  1255.       TWOPTRSTRUCT   twoPointers;
  1256.       BTI_BYTE       clientID[CLIENT_ID_SIZE];
  1257.       RMBUFF         btrv;
  1258.    } RMBTRVID;
  1259.  
  1260.    static BOOLEAN btrieveVersionOkay = FALSE;
  1261.    BTI_BYTE       versionOffset;
  1262.    BTI_BYTE       revisionOffset;
  1263.    BTI_BYTE       typeOffset;
  1264.    BOOLEAN        done;
  1265.    BTI_SINT       stat = B_NO_ERROR;
  1266.    BTI_ULONG      bufferSize;
  1267.    FARPTR         protectedP;
  1268.    FARPTR         tmpProtectedP;
  1269.    BTI_ULONG      realPtr;
  1270.  
  1271.  
  1272.    /*
  1273.    **   Btrieve Parameters for stat call
  1274.    */
  1275.    BTI_BYTE posBlockx[ 128 ];
  1276.    BTI_BYTE dataBufx[ 255 ];
  1277.    BTI_WORD dataLenx;
  1278.    BTI_BYTE keyBufx[ 255 ];
  1279.    BTI_WORD keyNumx = 0;
  1280.  
  1281.    /*=========================================================================
  1282.    Check to see that Btrieve has been started.
  1283.    =========================================================================*/
  1284.    stat = BtrLoaded( );
  1285.  
  1286.    /*=========================================================================
  1287.     Check for correct versions of requester and engine.  This check is done
  1288.     only once per application.
  1289.    =========================================================================*/
  1290.    if ( ( stat == B_NO_ERROR ) && ( !btrieveVersionOkay ) )
  1291.    {
  1292.       versionOffset  = VERSION_OFFSET;
  1293.       revisionOffset = REVISION_OFFSET;
  1294.       typeOffset     = TYPE_OFFSET;
  1295.       done           = FALSE;
  1296.       dataLenx       = sizeof( dataBufx );
  1297.       stat = BTRV(
  1298.                 B_VERSION,
  1299.                 posBlockx,
  1300.                 &dataBufx,
  1301.                 &dataLenx,
  1302.                 keyBufx,
  1303.                 keyNumx );
  1304.       if ( stat == B_NO_ERROR )
  1305.       {
  1306.          while ( !done )
  1307.          {
  1308.             switch( *(BTI_BYTE *)&dataBufx[ typeOffset ] )
  1309.             {
  1310.                /* Must have requestor version 6.16 or higher. */
  1311.                case 'N':
  1312.                   if ( ( (*(BTI_WORD *)&dataBufx[ versionOffset ] ) < 6 ) ||
  1313.                          ( ( (*(BTI_WORD *)&dataBufx[ versionOffset ] ) == 6 ) &&
  1314.                          ( (*(BTI_WORD *)&dataBufx[ revisionOffset ] ) < 16 ) ) )
  1315.                   {
  1316.                      stat = B_INVALID_INTERFACE;
  1317.                      done = TRUE;
  1318.                   }
  1319.                   break;
  1320.  
  1321.                /* Must have engine version 6 or higher. */
  1322.                case 'D':
  1323.                   if ( (*(BTI_WORD *)&dataBufx[ versionOffset ] ) < 6 )
  1324.                   {
  1325.                      stat = B_INVALID_INTERFACE;
  1326.                      done = TRUE;
  1327.                   }
  1328.                   break;
  1329.  
  1330.                case 0:
  1331.                   done = TRUE;
  1332.                   break;
  1333.             }
  1334.             if ( !done )
  1335.             {
  1336.                versionOffset  = versionOffset  + VERSION_BUF_SIZE;
  1337.                revisionOffset = revisionOffset + VERSION_BUF_SIZE;
  1338.                typeOffset     = typeOffset     + VERSION_BUF_SIZE;
  1339.                continue;
  1340.             }
  1341.          }
  1342.       }
  1343.       else
  1344.          stat = B_INVALID_INTERFACE;
  1345.    }
  1346.  
  1347.    /*=========================================================================
  1348.    Get pointers to real memory which is used to transfer data on the
  1349.    call to BTRVID
  1350.    =========================================================================*/
  1351.    if ( stat == B_NO_ERROR )
  1352.    {
  1353.       bufferSize = sizeof( RMBTRVID ) + *dataLength;
  1354.       stat = GetRealModeBuffer( &protectedP, &realPtr, bufferSize );
  1355.  
  1356.       if (stat == B_NO_ERROR)
  1357.       {
  1358.          btrieveVersionOkay = TRUE;
  1359.  
  1360.          /*===================================================================
  1361.          Establish pointer links inside real mode buffer.  Note: at first
  1362.          glance you might think to do this only one time.  However, if you are
  1363.          not the only one using the DOS buffer these relations would not be
  1364.          there next time around.
  1365.          ===================================================================*/
  1366.  
  1367.          copyToLow(                                   /* Use PMSW signature */
  1368.             FP_SEL(protectedP),
  1369.             FP_OFF(protectedP) + structoffset( RMBTRVID, newParms.sign ),
  1370.             "PMSW",
  1371.             4 );
  1372.  
  1373.          setLowMemLong(                                      /* Clear flags */
  1374.             FP_SEL(protectedP),
  1375.             FP_OFF(protectedP)
  1376.                + structoffset( RMBTRVID, newParms.flags ),
  1377.             0 );
  1378.  
  1379.          setLowMemLong(                 /* set function code to BTRVID code */
  1380.             FP_SEL(protectedP),
  1381.             FP_OFF(protectedP)
  1382.                + structoffset( RMBTRVID, newParms.functionCode ),
  1383.             BTRV_CODE );
  1384.  
  1385.          setLowMemLong(                             /* clear pmSwitchStatus */
  1386.             FP_SEL(protectedP),
  1387.             FP_OFF(protectedP)
  1388.                + structoffset( RMBTRVID, newParms.pmSwitchStatus ),
  1389.             0 );
  1390.  
  1391.          setLowMemLong(                                  /* set data length */
  1392.             FP_SEL(protectedP),
  1393.             FP_OFF(protectedP)
  1394.                + structoffset( RMBTRVID, newParms.dataLength ),
  1395.             sizeof( pmswParmBlock ) );
  1396.  
  1397.          setLowMemLong(    /* set dataPtr to point to twoPointers structure */
  1398.             FP_SEL(protectedP),
  1399.             FP_OFF(protectedP)
  1400.                + structoffset( RMBTRVID, newParms.dataPtr ),
  1401.             realPtr + structoffset( RMBTRVID, twoPointers ) );
  1402.  
  1403.          setLowMemLong(          /* set xDataPtr to Btrieve parameter block */
  1404.             FP_SEL(protectedP),
  1405.             FP_OFF(protectedP)
  1406.                + structoffset( RMBTRVID, twoPointers.xdataPtr ),
  1407.             realPtr + structoffset( RMBTRVID, btrv.XDATA ) );
  1408.  
  1409.          setLowMemLong(            /* set pointer to clientID in low memory */
  1410.             FP_SEL(protectedP),
  1411.             FP_OFF(protectedP)
  1412.                + structoffset( RMBTRVID, twoPointers.clientIdPtr ),
  1413.             realPtr + structoffset( RMBTRVID, clientID ) );
  1414.  
  1415.          copyToLow(                   /* copy clientID from input parameter */
  1416.             FP_SEL(protectedP),
  1417.             FP_OFF(protectedP) + structoffset( RMBTRVID, clientID ),
  1418.             clientID,
  1419.             CLIENT_ID_SIZE );
  1420.  
  1421.          setLowMemLong(                          /* set data buffer pointer */
  1422.             FP_SEL(protectedP),
  1423.             FP_OFF(protectedP)
  1424.                + structoffset( RMBTRVID, btrv.XDATA.DATA_BUF ),
  1425.             realPtr + structoffset( RMBTRVID, btrv.DATA_BUF ) );
  1426.  
  1427.          setLowMemWord(             /* set data buffer length in parm block */
  1428.             FP_SEL(protectedP),
  1429.             FP_OFF(protectedP)
  1430.                + structoffset( RMBTRVID, btrv.XDATA.BUF_LEN ),
  1431.             *dataLength );
  1432.  
  1433.          setLowMemLong(                                   /* Position block */
  1434.             FP_SEL(protectedP),
  1435.             FP_OFF(protectedP)
  1436.                + structoffset( RMBTRVID, btrv.XDATA.POS_BLOCK ),
  1437.             realPtr + structoffset( RMBTRVID, btrv.POS_BLOCK) + 38 );
  1438.  
  1439.          setLowMemLong(
  1440.             FP_SEL(protectedP),
  1441.             FP_OFF(protectedP)
  1442.                + structoffset( RMBTRVID, btrv.XDATA.FCB ),
  1443.             realPtr + structoffset( RMBTRVID, btrv.POS_BLOCK ) );
  1444.  
  1445.          setLowMemWord(
  1446.             FP_SEL(protectedP),
  1447.             FP_OFF(protectedP)
  1448.                + structoffset( RMBTRVID, btrv.XDATA.FUNCTION ),
  1449.             operation );
  1450.  
  1451.          setLowMemLong(
  1452.             FP_SEL(protectedP),
  1453.             FP_OFF(protectedP)
  1454.                + structoffset( RMBTRVID, btrv.XDATA.KEY_BUFFER ),
  1455.             realPtr + structoffset( RMBTRVID, btrv.KEY_BUFFER) );
  1456.  
  1457.          setLowMemByte(
  1458.             FP_SEL(protectedP),
  1459.             FP_OFF(protectedP)
  1460.                + structoffset( RMBTRVID, btrv.XDATA.KEY_LENGTH ),
  1461.             255 );
  1462.  
  1463.          setLowMemByte(
  1464.             FP_SEL(protectedP),
  1465.             FP_OFF(protectedP)
  1466.                + structoffset( RMBTRVID, btrv.XDATA.KEY_NUMBER ),
  1467.             keyNumber );
  1468.  
  1469.          setLowMemLong(
  1470.             FP_SEL(protectedP),
  1471.             FP_OFF(protectedP)
  1472.                + structoffset( RMBTRVID, btrv.XDATA.STATUS ),
  1473.             realPtr + structoffset( RMBTRVID, btrv.STATUS ) );
  1474.  
  1475.          setLowMemWord(
  1476.             FP_SEL(protectedP),
  1477.             FP_OFF(protectedP)
  1478.                + structoffset( RMBTRVID, btrv.XDATA.XFACE_ID ),
  1479.             VARIABLE_ID );
  1480.  
  1481.          tmpProtectedP = protectedP;
  1482.          FP_INCR(tmpProtectedP, structoffset( RMBTRVID, btrv ));
  1483.          stat = SetUpBTRVData(
  1484.                    &tmpProtectedP,
  1485.                    posBlock,
  1486.                    dataBuffer,
  1487.                    keyBuffer );
  1488.  
  1489.          /*===================================================================
  1490.          Make call to Btrieve.
  1491.          ===================================================================*/
  1492.          if ( stat == B_NO_ERROR )
  1493.          {
  1494.             CallBTRV( realPtr );
  1495.  
  1496.             *dataLength = getLowMemWord(
  1497.                              FP_SEL(protectedP),
  1498.                              FP_OFF(protectedP)
  1499.                                 + structoffset(
  1500.                                      RMBTRVID,
  1501.                                      btrv.XDATA.BUF_LEN ) );
  1502.  
  1503.             stat = getLowMemLong(
  1504.                       FP_SEL(protectedP),
  1505.                       FP_OFF(protectedP)
  1506.                          + structoffset( RMBTRVID, btrv.STATUS ) ) ;
  1507.  
  1508.             /*================================================================
  1509.             Copy data from protected mode back to user's data
  1510.             ================================================================*/
  1511.             RetrieveBTRVData(
  1512.                &tmpProtectedP,
  1513.                posBlock,
  1514.                dataBuffer,
  1515.                keyBuffer );
  1516.          }
  1517.       }
  1518.    }
  1519.  
  1520.    return( stat );
  1521. }
  1522.  
  1523.  
  1524. /***************************************************************************
  1525.     BTRV() Function for Extended DOS Using 'Borland PowerPack' or
  1526.     'Phar-Lap TNT 6.0' DOS Extenders
  1527. ***************************************************************************/
  1528. BTI_API BTRV(
  1529.            BTI_WORD     operation,
  1530.            BTI_VOID_PTR posBlock,
  1531.            BTI_VOID_PTR dataBuffer,
  1532.            BTI_WORD_PTR dataLength,
  1533.            BTI_VOID_PTR keyBuffer,
  1534.            BTI_SINT     keyNumber )
  1535. {
  1536.    /* Microsoft changed function and structure names in post 6.0 versions. */
  1537.    #if defined( _MSC_VER )
  1538.       #if ( _MSC_VER > 600 )
  1539.          #define int386x _int386x
  1540.          #define REGS    _REGS
  1541.       #endif
  1542.    #endif
  1543.  
  1544.    BTI_SINT              stat = B_NO_ERROR;
  1545.    BTI_ULONG             bufferSize;
  1546.    FARPTR                protectedP;
  1547.    BTI_ULONG             realPtr;
  1548.  
  1549.    /*=========================================================================
  1550.    Check to see that Btrieve has been started.
  1551.    =========================================================================*/
  1552.    stat = BtrLoaded( );
  1553.  
  1554.    /*=========================================================================
  1555.    Move user parameters to XDATA, the block where Btrieve expects them.
  1556.    =========================================================================*/
  1557.    if ( stat == B_NO_ERROR )
  1558.    {
  1559.       bufferSize = sizeof( RMBUFF ) + *dataLength;
  1560.       stat = GetRealModeBuffer( &protectedP, &realPtr, bufferSize );
  1561.  
  1562.       if (stat == B_NO_ERROR)
  1563.       {
  1564.          /*===================================================================
  1565.          Establish pointer links inside real mode buffer.  Note: at first
  1566.          glance you might think to do this only one time.  However, if you are
  1567.          not the only one using the DOS buffer these relations would not be
  1568.          there next time around.
  1569.          ===================================================================*/
  1570.  
  1571.          setLowMemLong(
  1572.             FP_SEL(protectedP),
  1573.             FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.POS_BLOCK ),
  1574.             realPtr + structoffset(RMBUFF, POS_BLOCK) + 38 );
  1575.  
  1576.          setLowMemLong(
  1577.             FP_SEL(protectedP),
  1578.             FP_OFF(protectedP) + structoffset(RMBUFF, XDATA.FCB),
  1579.             realPtr + structoffset( RMBUFF, POS_BLOCK ) );
  1580.  
  1581.          setLowMemLong(
  1582.             FP_SEL(protectedP),
  1583.             FP_OFF(protectedP) + structoffset(RMBUFF, XDATA.STATUS),
  1584.             realPtr + structoffset( RMBUFF, STATUS ) );
  1585.  
  1586.          setLowMemLong(
  1587.             FP_SEL(protectedP),
  1588.             FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.KEY_BUFFER ),
  1589.             realPtr + structoffset( RMBUFF, KEY_BUFFER) );
  1590.  
  1591.          setLowMemLong(
  1592.             FP_SEL(protectedP),
  1593.             FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.DATA_BUF ),
  1594.             realPtr + structoffset( RMBUFF, DATA_BUF ) );
  1595.  
  1596.          setLowMemWord(
  1597.             FP_SEL(protectedP),
  1598.             FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.XFACE_ID ),
  1599.             VARIABLE_ID );
  1600.  
  1601.          setLowMemWord(
  1602.             FP_SEL(protectedP),
  1603.             FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.FUNCTION ),
  1604.             operation );
  1605.  
  1606.          setLowMemWord(
  1607.             FP_SEL(protectedP),
  1608.             FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.BUF_LEN ),
  1609.             *dataLength );
  1610.  
  1611.          setLowMemByte(
  1612.             FP_SEL(protectedP),
  1613.             FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.KEY_LENGTH ),
  1614.             255 );
  1615.  
  1616.          setLowMemByte(
  1617.             FP_SEL(protectedP),
  1618.             FP_OFF(protectedP) + structoffset( RMBUFF, XDATA.KEY_NUMBER ),
  1619.             keyNumber );
  1620.  
  1621.          stat = SetUpBTRVData( &protectedP, posBlock, dataBuffer, keyBuffer );
  1622.  
  1623.          /*===================================================================
  1624.          Make call to Btrieve.
  1625.          ===================================================================*/
  1626.          if ( stat == B_NO_ERROR )
  1627.          {
  1628.             CallBTRV( realPtr );
  1629.  
  1630.             *dataLength = getLowMemWord(
  1631.                              FP_SEL(protectedP),
  1632.                              FP_OFF(protectedP)
  1633.                                 + structoffset( RMBUFF, XDATA.BUF_LEN) );
  1634.  
  1635.             stat = getLowMemLong(
  1636.                       FP_SEL(protectedP),
  1637.                       FP_OFF(protectedP)
  1638.                          + structoffset( RMBUFF, STATUS ) );
  1639.  
  1640.             /*================================================================
  1641.             Copy data from protected mode back to user's data
  1642.             ================================================================*/
  1643.             RetrieveBTRVData( &protectedP, posBlock, dataBuffer, keyBuffer );
  1644.          }
  1645.          FreeRealModeBuffer( FP_SEL(protectedP) );
  1646.       }
  1647.    }
  1648.    return( stat );
  1649. }
  1650.  
  1651. /*
  1652. *****************************************************************************
  1653. **
  1654. **  Prototype:
  1655. **
  1656. **      BTI_SINT SetUpBTRVData(
  1657. **                  FARPTR *protectedP,
  1658. **                  BTI_VOID_PTR posBlock,
  1659. **                  BTI_VOID_PTR dataBuffer,
  1660. **                  BTI_VOID_PTR keyBuffer )
  1661. **
  1662. **  Description:
  1663. **
  1664. **      This function copies Btrieve parameter data from the user's
  1665. **      application to the Btrieve parameter block in DOS real memory.
  1666. **      It checks the Btrieve function code and key number parameters
  1667. **      that are already in the parameter block to see if the operation
  1668. **      processes indirect chunk data.  If so, ProcessIndirect() is called
  1669. **      to process the indirect Btrieve chunk data.
  1670. **
  1671. **  Preconditions:
  1672. **
  1673. **      Real Mode Btrieve parameter block is already initialized with
  1674. **      Function code, Key Number, Data buffer length.
  1675. **
  1676. **  Parameters:
  1677. **
  1678. **      *protectedP:    Protected mode pointer to the Btrieve parameter block.
  1679. **       <input/output>
  1680. **
  1681. **      posBlock:       Application's parameter block
  1682. **        <input>
  1683. **
  1684. **      dataBuffer:     Application's data buffer
  1685. **        <input>
  1686. **
  1687. **      keyBuffer:      Application's key buffer
  1688. **        <input>
  1689. **
  1690. **
  1691. **  Return value:
  1692. **
  1693. **      B_NO_ERROR      SetUpBTRVData() is successful.
  1694. **
  1695. **      B_DATA_MESSAGE_TOO_SMALL Chunk cannot fit in the user's data buffer.
  1696. **
  1697. **      B_INVALID_GET_EXPRESSION Chunk data overwrites chunk descriptors.
  1698. **
  1699. **
  1700. **  Globals:
  1701. **
  1702. **      None.
  1703. **
  1704. **  Called Functions:
  1705. **
  1706. **      BlobInputDBlen()
  1707. **      copyToLow()
  1708. **      getLowMemByte()
  1709. **      getLowMemWord()
  1710. **      ProcessIndirect()
  1711. **
  1712. **  Comments:
  1713. **
  1714. **      None.
  1715. **
  1716. *****************************************************************************
  1717. */
  1718. BTI_SINT SetUpBTRVData(
  1719.             FARPTR *protectedP,
  1720.             BTI_VOID_PTR posBlock,
  1721.             BTI_VOID_PTR dataBuffer,
  1722.             BTI_VOID_PTR keyBuffer )
  1723. {
  1724.    BTI_WORD function;
  1725.    BTI_WORD copyLen;
  1726.    BTI_CHAR keyNumber;
  1727.    BTI_WORD stat;
  1728.    BTI_WORD bufLen;
  1729.  
  1730.    function = getLowMemWord(
  1731.                  FP_SEL(*protectedP),
  1732.                  FP_OFF(*protectedP)
  1733.                     + structoffset( RMBUFF, XDATA.FUNCTION) );
  1734.    function = function % S_WAIT_LOCK;
  1735.  
  1736.    copyLen  = getLowMemWord(
  1737.                  FP_SEL(*protectedP),
  1738.                  FP_OFF(*protectedP)
  1739.                     + structoffset( RMBUFF, XDATA.BUF_LEN ) );
  1740.  
  1741.    if (function == B_GET_DIRECT)
  1742.    {
  1743.       keyNumber = getLowMemByte(
  1744.                      FP_SEL(*protectedP),
  1745.                      FP_OFF(*protectedP)
  1746.                         + structoffset( RMBUFF, XDATA.KEY_NUMBER ) );
  1747.  
  1748.       if ( keyNumber == (BTI_CHAR) GET_DRTC_XTRACTOR_KEY )
  1749.       {
  1750.  
  1751.          PUT_XTRACTR *xtr;
  1752.  
  1753.          xtr = (PUT_XTRACTR *)((BTI_BYTE *) dataBuffer + 4);
  1754.          if ( xtr->Signature & INDIRECT_BIT)
  1755.          {
  1756.             bufLen = getLowMemWord(
  1757.                         FP_SEL(*protectedP),
  1758.                         FP_OFF(*protectedP)
  1759.                            + structoffset( RMBUFF, XDATA.BUF_LEN ) );
  1760.  
  1761.             if (stat = ProcessIndirect(
  1762.                           protectedP,
  1763.                           dataBuffer,          /* application's data buffer */
  1764.                           bufLen,
  1765.                           (BTI_SINT) PREPROCESS_BLOBGET,
  1766.                           ©Len))
  1767.             {
  1768.                return (stat);
  1769.             }
  1770.             /*
  1771.             ** Data was already copied in ProcessIndirect, so set
  1772.             ** copyLen to 0
  1773.             */
  1774.             copyLen = 0;
  1775.          }
  1776.          else
  1777.          {               /* Only copy the extractors & the record address. */
  1778.             copyLen = (BTI_WORD) BlobInputDBlen ((XTRACTR *) xtr) + 4;
  1779.          }
  1780.       }
  1781.    }
  1782.  
  1783.    if (function == B_CHUNK_UPDATE)
  1784.    {
  1785.       PUT_XTRACTR *xtr;
  1786.  
  1787.       xtr = (PUT_XTRACTR *)(dataBuffer);
  1788.  
  1789.       if ( xtr->Signature & INDIRECT_BIT)
  1790.       {
  1791.          bufLen = getLowMemWord(
  1792.                      FP_SEL(*protectedP),
  1793.                      FP_OFF(*protectedP)
  1794.                         + structoffset( RMBUFF, XDATA.BUF_LEN ) );
  1795.  
  1796.          if (stat = ProcessIndirect(
  1797.                        protectedP,
  1798.                        dataBuffer,            /* application's data buffer  */
  1799.                        bufLen,
  1800.                        PREPROCESS_BLOBPUT,
  1801.                        ©Len))
  1802.          {
  1803.             return (stat);
  1804.          }
  1805.          /* Data was already copied in ProcessIndirect, so set copyLen to 0 */
  1806.          copyLen = 0;
  1807.       }
  1808.    }
  1809.  
  1810.    copyToLow(
  1811.       FP_SEL(*protectedP),
  1812.       FP_OFF(*protectedP) + structoffset( RMBUFF, POS_BLOCK),
  1813.       posBlock,
  1814.       128 );
  1815.  
  1816.    copyToLow(
  1817.       FP_SEL(*protectedP),
  1818.       FP_OFF(*protectedP) + structoffset( RMBUFF, KEY_BUFFER),
  1819.       keyBuffer,
  1820.       255 );
  1821.  
  1822.    copyToLow(
  1823.       FP_SEL(*protectedP),
  1824.       FP_OFF(*protectedP) + structoffset( RMBUFF, DATA_BUF),
  1825.       dataBuffer,
  1826.       copyLen );
  1827.  
  1828.    return (0);
  1829. }
  1830.  
  1831.  
  1832. /*
  1833. *****************************************************************************
  1834. **
  1835. **  Prototype:
  1836. **
  1837. **      BTI_VOID RetrieveBTRVData(
  1838. **                  FARPTR *protectedP,
  1839. **                  BTI_VOID_PTR posBlock,
  1840. **                  BTI_VOID_PTR dataBuffer,
  1841. **                  BTI_VOID_PTR keyBuffer )
  1842. **
  1843. **  Description:
  1844. **
  1845. **      RetrieveBTRVData() copies data from the Btrieve parameter block
  1846. **      in DOS real memory to the application's data area.  When there
  1847. **      is indirection in the destination of the data, then
  1848. **      RetrieveBTRVData() calls ProcessIndirect() to pull the data out
  1849. **      of the parameter block and place it at the correct address.
  1850. **
  1851. **  Preconditions:
  1852. **
  1853. **      None.
  1854. **
  1855. **  Parameters:
  1856. **
  1857. **      *protectedP:            Protected-mode pointer to the Btrieve
  1858. **        <input>               parameter block which contains data from
  1859. **                              the last Btrieve call.
  1860. **
  1861. **      posBlock:               Application's position block.
  1862. **        <output>
  1863. **
  1864. **      dataBuffer:             Application's data buffer.
  1865. **        <output>
  1866. **
  1867. **      keyBuffer:              Application's data buffer.
  1868. **        <output>
  1869. **
  1870. **
  1871. **  Return value:
  1872. **
  1873. **      B_NO_ERROR               RetrieveBTRVData() is successful.
  1874. **
  1875. **      B_DATA_MESSAGE_TOO_SMALL Chunk cannot fit in the user's data buffer.
  1876. **
  1877. **      B_INVALID_GET_EXPRESSION Chunk data overwrites chunk descriptors.
  1878. **
  1879. **  Globals:
  1880. **
  1881. **      None.
  1882. **
  1883. **  Called Functions:
  1884. **
  1885. **      copyFromLow()
  1886. **      getLowMemWord()
  1887. **      ProcessIndirect()
  1888. **
  1889. **  Comments:
  1890. **
  1891. **      None.
  1892. **
  1893. *****************************************************************************
  1894. */
  1895. BTI_VOID RetrieveBTRVData(
  1896.             FARPTR *protectedP,
  1897.             BTI_VOID_PTR posBlock,
  1898.             BTI_VOID_PTR dataBuffer,
  1899.             BTI_VOID_PTR keyBuffer )
  1900. {
  1901.    BTI_WORD function;
  1902.    BTI_CHAR keyNumber;
  1903.    BTI_WORD bufLen;
  1904.  
  1905.    function = getLowMemWord(
  1906.                  FP_SEL(*protectedP),
  1907.                  FP_OFF(*protectedP)
  1908.                     + structoffset( RMBUFF, XDATA.FUNCTION) );
  1909.    function = function % S_WAIT_LOCK;
  1910.  
  1911.    keyNumber = getLowMemWord(
  1912.                   FP_SEL(*protectedP),
  1913.                   FP_OFF(*protectedP)
  1914.                      + structoffset( RMBUFF, XDATA.KEY_NUMBER));
  1915.  
  1916.    bufLen = getLowMemWord(
  1917.                FP_SEL(*protectedP),
  1918.                FP_OFF(*protectedP)
  1919.                   + structoffset( RMBUFF, XDATA.BUF_LEN ) );
  1920.  
  1921.    if ( (function == B_GET_DIRECT) &&
  1922.         (keyNumber == (BTI_CHAR) GET_DRTC_XTRACTOR_KEY ) &&
  1923.         (((GET_XTRACTR *) dataBuffer)->Signature & INDIRECT_BIT))
  1924.    {
  1925.       BTI_WORD ignoredDataLen;
  1926.  
  1927.       ProcessIndirect(
  1928.          protectedP,
  1929.          dataBuffer,
  1930.          bufLen,
  1931.          POSTPROCESS_BLOBGET,
  1932.          &ignoredDataLen );
  1933.    }
  1934.    else
  1935.    {
  1936.  
  1937.       copyFromLow(
  1938.          dataBuffer,
  1939.          FP_SEL(*protectedP),
  1940.          FP_OFF(*protectedP) + structoffset( RMBUFF, DATA_BUF ),
  1941.          bufLen );
  1942.  
  1943.    }
  1944.  
  1945.    copyFromLow(
  1946.       posBlock,
  1947.       FP_SEL(*protectedP),
  1948.       FP_OFF(*protectedP) + structoffset( RMBUFF, POS_BLOCK ),
  1949.       128 );
  1950.  
  1951.    copyFromLow(
  1952.       keyBuffer,
  1953.       FP_SEL(*protectedP),
  1954.       FP_OFF(*protectedP) + structoffset( RMBUFF, KEY_BUFFER ),
  1955.       255 );
  1956.  
  1957. }
  1958.  
  1959. /*
  1960. *****************************************************************************
  1961. **
  1962. **  Prototype:
  1963. **
  1964. **      BTI_SINT BlobInputDBlen( register XTRACTR * xtractP )
  1965. **
  1966. **  Description:
  1967. **
  1968. **      Returns the size of the Chunk Extractors based on the signature
  1969. **      field.
  1970. **
  1971. **  Preconditions:
  1972. **
  1973. **      None.
  1974. **
  1975. **  Parameters:
  1976. **
  1977. **      xtractP:        Pointer to the chunk extractor.
  1978. **        <input>
  1979. **
  1980. **
  1981. **  Return value:
  1982. **
  1983. **      Returns the number of bytes in the extractor descriptor.
  1984. **
  1985. **  Globals:
  1986. **
  1987. **      None.
  1988. **
  1989. **  Called Functions:
  1990. **
  1991. **      None.
  1992. **
  1993. **  Comments:
  1994. **
  1995. **      None.
  1996. **
  1997. **
  1998. *****************************************************************************
  1999. */
  2000. BTI_SINT BlobInputDBlen( register XTRACTR * xtractP )
  2001. {
  2002.    register BTI_WORD ret;
  2003.  
  2004.    /*
  2005.    ** The size returned is based on the Signature field.
  2006.    */
  2007.    if ( xtractP->Signature & RECTANGLE_BIT )
  2008.    {
  2009.       ret = sizeof (PUT_RECTANGLE);
  2010.    }
  2011.    else
  2012.    {                                               /* Signature & numfields */
  2013.       ret = (xtractP->NumChunks * sizeof(CHUNK)) + (2 * sizeof(BTI_ULONG));
  2014.    }
  2015.    return (ret);
  2016. }
  2017.  
  2018. /*
  2019. *****************************************************************************
  2020. **
  2021. **  Prototype:
  2022. **
  2023. **      BTI_SINT ProcessIndirect(
  2024. **                  FARPTR *protectedP,
  2025. **                  BTI_VOID_PTR usersDataBuf,
  2026. **                  BTI_WORD maxlen,
  2027. **                  BTI_SINT Action,
  2028. **                  BTI_WORD *bytesDone )
  2029. **
  2030. **  Description:
  2031. **
  2032. **      ProcessIndirect() copies data to/from the address of the
  2033. **      application's chunk data.
  2034. **
  2035. **  Preconditions:
  2036. **
  2037. **      None.
  2038. **
  2039. **  Parameters:
  2040. **
  2041. **      *protectedP:            Protected-mode pointer to Btrieve parameter
  2042. **        <input/output>        block (RMBUFF data structure) in DOS real
  2043. **                              memory.
  2044. **
  2045. **      usersDataBuf:           Pointer to application's data buffer.
  2046. **        <input/output>
  2047. **
  2048. **      maxlen:                 Maximum length of application's data buffer.
  2049. **        <input>
  2050. **
  2051. **      Action:                 Type of action to take (See below)
  2052. **        <input>
  2053. **
  2054. **      *bytesDone:             Number of bytes copied.
  2055. **        <input/output>
  2056. **
  2057. **
  2058. **  Action can be one of the following:
  2059. **
  2060. **  PREPROCESS_BLOBGET
  2061. **      Chunk extractor information is copied from the user's data buffer
  2062. **      to the data buffer in the Btrieve parameter block.  The request
  2063. **      type is changed to a direct data request so that we do not
  2064. **      have to mess with pointer conversions between real and protected
  2065. **      mode.  It also makes it easier for us to copy data to/from
  2066. **      real-mode request buffer and user's buffer when request is
  2067. **      pre/post processed.
  2068. **
  2069. **
  2070. **  POSTPROCESS_BLOBGET
  2071. **      Chunk data is copied from the Btrieve parameter block to the
  2072. **      application's address given in the chunk extractor information
  2073. **      (still in the application's data buffer)
  2074. **
  2075. **
  2076. **  PREPROCESS_BLOBPUT
  2077. **
  2078. **      Chunk extractor information is copied from the user's data buffer
  2079. **      to the data buffer in the Btrieve parameter block.  The request
  2080. **      type is changed from indirect to direct so that the application's
  2081. **      data can be copied into the Btrieve parameter block.
  2082. **
  2083. **  Return value:
  2084. **
  2085. **      B_NO_ERROR               Success
  2086. **
  2087. **      B_DATA_MESSAGE_TOO_SMALL Chunk cannot fit in the user's data buffer
  2088. **
  2089. **      B_INVALID_GET_EXPRESSION Chunk data overwrites chunk descriptors
  2090. **
  2091. **
  2092. **  Globals:
  2093. **
  2094. **      None.
  2095. **
  2096. **  Called Functions:
  2097. **
  2098. **      BlobInputDBlen()
  2099. **      copyFromLow()
  2100. **      copyToLow()
  2101. **      getLowMemLong()
  2102. **      setLowMemLong()
  2103. **      VerifyChunk()
  2104. **
  2105. **  Comments:
  2106. **
  2107. **      None.
  2108. **
  2109. *****************************************************************************
  2110. */
  2111. BTI_SINT ProcessIndirect(
  2112.             FARPTR *protectedP,
  2113.             BTI_VOID_PTR usersDataBuf,
  2114.             BTI_WORD maxlen,
  2115.             BTI_SINT Action,
  2116.             BTI_WORD *bytesDone )
  2117. {
  2118.    PUT_XTRACTR   *xtr;
  2119.    PUT_RECTANGLE *rectP;
  2120.    BTI_WORD      protectSize;
  2121.    BTI_WORD      len = 0;                           /* Len of current chunk */
  2122.    BTI_WORD      i, limit;                                       /* Helpers */
  2123.    BTI_WORD      stat = 0;
  2124.    CHUNK         *iP;                        /* Will point to current chunk */
  2125.    BTI_SINT      rectangle;
  2126.    BTI_ULONG     chunkFlag;
  2127.    FARPTR        reqB;
  2128.  
  2129.    reqB = *protectedP;
  2130.  
  2131.    FP_INCR(reqB, structoffset(RMBUFF, DATA_BUF));
  2132.  
  2133.    if ( (Action == PREPROCESS_BLOBGET) || (Action == POSTPROCESS_BLOBGET) )
  2134.    {
  2135.       xtr = (PUT_XTRACTR *)(((BTI_BYTE *) usersDataBuf) + 4);
  2136.    }
  2137.    else
  2138.    {
  2139.       xtr = (PUT_XTRACTR *)usersDataBuf;
  2140.    }
  2141.  
  2142.    rectP = (PUT_RECTANGLE *) xtr;
  2143.      /* protectSize is the size of req. buffer that must not be overwritten */
  2144.    *bytesDone = protectSize = (BTI_WORD) BlobInputDBlen ((XTRACTR *)xtr);
  2145.  
  2146.    rectangle = xtr->Signature & RECTANGLE_BIT;
  2147.    if (rectangle)
  2148.       limit = (BTI_WORD)rectP->NumRows;
  2149.    else
  2150.       limit = (BTI_WORD)xtr->NumChunks;
  2151.  
  2152.    switch (Action)
  2153.    {
  2154.       case PREPROCESS_BLOBGET:
  2155.  
  2156.          *bytesDone += 4;                          /* four byte positioning */
  2157.          /*
  2158.          **    move record positioning information
  2159.          */
  2160.          setLowMemLong(
  2161.             FP_SEL(reqB),
  2162.             FP_OFF(reqB),
  2163.             *((BTI_ULONG *) usersDataBuf) );
  2164.          FP_INCR(reqB,sizeof( BTI_ULONG ));
  2165.  
  2166.                          /* Control flows down to copyToLow() and beyond... */
  2167.  
  2168.       case PREPROCESS_BLOBPUT:
  2169.                                                     /* move over extractors */
  2170.          copyToLow(
  2171.             FP_SEL(reqB),
  2172.             FP_OFF(reqB),
  2173.             xtr,
  2174.             protectSize );
  2175.          /*
  2176.          ** Change the request to a direct data request so that we do not
  2177.          ** have to mess with pointer conversions between real and protectSize
  2178.          ** mode.  It also makes it easier for us to copy data to/from
  2179.          ** real-mode request buffer and user's buffer when request is
  2180.          ** pre/post processed.
  2181.          */
  2182.  
  2183.          chunkFlag = getLowMemLong(
  2184.                         FP_SEL(reqB),
  2185.                         FP_OFF(reqB) );
  2186.          setLowMemLong(
  2187.             FP_SEL(reqB),
  2188.             FP_OFF(reqB),
  2189.             chunkFlag & ~INDIRECT_BIT );
  2190.          FP_INCR(reqB,protectSize);
  2191.  
  2192.          break;
  2193.  
  2194.       case POSTPROCESS_BLOBGET:
  2195.          *bytesDone = 0;
  2196.          break;
  2197.    }
  2198.  
  2199.    if (Action == PREPROCESS_BLOBGET)
  2200.    {
  2201.       /*
  2202.       ** Zero bytesDone so that it can now accumulate the number of bytes
  2203.       ** expected to be returned, looking for status 97.  This is done by
  2204.       ** calling VerifyChunk who also catches attempts to overwrite the
  2205.       ** descriptors with the returned data.
  2206.       */
  2207.       *bytesDone = 0;
  2208.    }
  2209.  
  2210.    /*=========================================================================
  2211.    Tack the chunks together at the end of the request buffer.
  2212.    =========================================================================*/
  2213.    /*
  2214.    ** iP is always initialized and maintained, but not used if chunk type
  2215.    ** is rectangle.
  2216.    */
  2217.    iP = &(xtr->Chunk[0]);
  2218.    for (i = 0; i < limit; i++)          /* limit is the same for both types */
  2219.    {
  2220.       register BTI_BYTE *chunkP;
  2221.  
  2222.       if ( rectangle )
  2223.       {
  2224.          if ( rectP->BytesPerRow & 0xffff0000L )   /* must be 16-bit number */
  2225.             return ( B_INVALID_GET_EXPRESSION );            /* return error */
  2226.          len = (BTI_WORD) rectP->BytesPerRow;
  2227.          chunkP = rectP->dataP + (i * rectP->AppDistanceBetweenRows);
  2228.       }
  2229.       else
  2230.       {
  2231.          chunkP = iP->dataP;
  2232.  
  2233.          if (iP->ChunkLen & 0xffff0000L)           /* must be 16-bit number */
  2234.             return (B_INVALID_GET_EXPRESSION);              /* return error */
  2235.  
  2236.          len = (BTI_WORD) iP->ChunkLen;
  2237.       }
  2238.  
  2239.  
  2240.       /*======================================================================
  2241.       Does the chunk about to be written overlap with the extractors?
  2242.       ======================================================================*/
  2243.       stat = VerifyChunk(
  2244.                 xtr,
  2245.                 protectSize,
  2246.                 chunkP,
  2247.                 len,
  2248.                 *bytesDone,
  2249.                 Action == POSTPROCESS_BLOBGET ? 0xffff : maxlen );
  2250.  
  2251.       if ( stat != B_NO_ERROR )
  2252.       {
  2253.          return ( stat );
  2254.       }
  2255.  
  2256.       if ( *bytesDone >= maxlen )               /* Already consumed buffer? */
  2257.       {
  2258.          return ( B_DATA_MESSAGE_TOO_SMALL );
  2259.       }
  2260.  
  2261.       if ( Action != PREPROCESS_BLOBGET )
  2262.       {
  2263.          switch ( Action )
  2264.          {
  2265.             case POSTPROCESS_BLOBGET:
  2266.                copyFromLow(
  2267.                   chunkP,
  2268.                   FP_SEL(reqB),
  2269.                   FP_OFF(reqB),
  2270.                   min( len, maxlen - *bytesDone ) );
  2271.                break;
  2272.  
  2273.             case PREPROCESS_BLOBPUT:
  2274.                copyToLow(
  2275.                   FP_SEL(reqB),
  2276.                   FP_OFF(reqB),
  2277.                   chunkP,
  2278.                   min( len, maxlen - *bytesDone ) );
  2279.                break;
  2280.          }
  2281.       }
  2282.       FP_INCR(reqB,len);
  2283.       *bytesDone += len;
  2284.       iP++;
  2285.    }
  2286.  
  2287.    return ( B_NO_ERROR );
  2288. }
  2289.  
  2290. /*
  2291. *****************************************************************************
  2292. **
  2293. **  Prototype:
  2294. **
  2295. **      BTI_SINT VerifyChunk(
  2296. **                  BTI_VOID_PTR userDB,
  2297. **                  BTI_WORD bytesToProtect,
  2298. **                  BTI_VOID_PTR ChunkP,
  2299. **                  BTI_WORD ChunkLen,
  2300. **                  BTI_WORD bytesDone,
  2301. **                  BTI_WORD maxlen )
  2302. **
  2303. **  Description:
  2304. **
  2305. **      VerifyChunk makes sure the data will not overwrite the end of the
  2306. **      output buffer.  It also catches attempts to overwrite the
  2307. **      chunk descriptors with the returned data.
  2308. **
  2309. **
  2310. **  Preconditions:
  2311. **
  2312. **      None.
  2313. **
  2314. **  Parameters:
  2315. **
  2316. **      userDB:                 pointer to the user's data buffer.
  2317. **        <input>
  2318. **
  2319. **      bytesToProtect:         Size of request buffer that must not be
  2320. **        <input>               overwritten with returned data.
  2321. **
  2322. **      ChunkP:                 Pointer to the chunk data.
  2323. **        <input>
  2324. **
  2325. **      ChunkLen:
  2326. **        <input>               Length of the chunk data.
  2327. **
  2328. **      bytesDone:              Number of bytes copied so far to user's
  2329. **        <input>               data buffer.
  2330. **
  2331. **      maxlen:                 Maximum length of the user's data buffer.
  2332. **        <input>
  2333. **
  2334. **
  2335. **  Return value:
  2336. **
  2337. **      B_NO_ERROR               Success
  2338. **
  2339. **      B_DATA_MESSAGE_TOO_SMALL Chunk cannot fit in the user's data buffer
  2340. **
  2341. **      B_INVALID_GET_EXPRESSION Chunk data overwrites chunk descriptors
  2342. **
  2343. **  Globals:
  2344. **
  2345. **      None.
  2346. **
  2347. **  Called Functions:
  2348. **
  2349. **      None.
  2350. **
  2351. **  Comments:
  2352. **
  2353. **      None.
  2354. **
  2355. *****************************************************************************
  2356. */
  2357. BTI_SINT VerifyChunk(
  2358.             BTI_VOID_PTR userDB,
  2359.             BTI_WORD bytesToProtect,
  2360.             BTI_VOID_PTR ChunkP,
  2361.             BTI_WORD ChunkLen,
  2362.             BTI_WORD bytesDone,
  2363.             BTI_WORD maxlen )
  2364. {
  2365.    register BTI_ULONG uNorm = Normalize(userDB),
  2366.                       cNorm = Normalize(ChunkP);
  2367.  
  2368.    /*
  2369.    **   Check for buffer overrun
  2370.    */
  2371.    if ((BTI_ULONG)bytesDone + (BTI_ULONG)ChunkLen > maxlen)
  2372.    {
  2373.       return (B_DATA_MESSAGE_TOO_SMALL);
  2374.    }
  2375.    /*
  2376.    **   Check if chunk about to be written overlaps with the extractors
  2377.    */
  2378.    if ((cNorm + ChunkLen < uNorm) || (cNorm >= uNorm + bytesToProtect))
  2379.    {
  2380.       return (0);
  2381.    }
  2382.  
  2383.    return (B_INVALID_GET_EXPRESSION);
  2384. }
  2385. #endif
  2386.  
  2387. #ifdef __cplusplus
  2388. }
  2389. #endif
  2390.  
  2391.