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