Creating the Wrapper DLL

Four steps are involved in creating the wrapper DLL:

  1. Determine which functions to wrap.
  2. Map Btrieve import functions to export functions in the DLL.
  3. Implement the Btrieve functions.
  4. Link the application to the wrapper DLL.

Determining Which Functions to Wrap

The wrapper DLL must cover all the functions that the base application imports from the Btrieve library Wbtrv32.dll. Use a binary file dumping utility to list the functions imported from the various external link libraries and referenced by the application. In Microsoft Visual C++, the equivalent of the dumping utility is called Dumpbin.exe.

Use DUMPBIN /IMPORTS application_file_name to obtain the list of imported symbols for Wbtrv32.dll. In the following sample output, the function symbols in Btrvapp.exe imported from Wbtrv32.dll are ordinals 3, 2, and 1:

DUMPBIN /IMPORTS BTRVAPP.EXE
Microsoft (R) COFF Binary File Dumper Version 4.20.6164
Copyright (C) Microsoft Corp 1992-1997. All rights reserved.

Dump of file BTRVAPP.EXE
File Type: EXECUTABLE IMAGE
        Section contains the following Imports:
           wbtrv32.dll
              Ordinal     3
              Ordinal     2
              Ordinal     1

  

Use DUMPBIN /EXPORTS DLL_file_name to obtain the list of exported symbols for the DLL in question. The symbols appear in the name column of the table whose headings are “ordinal,” “hint,” and “name.” In the example, these correspond to BTRCALL, BTRCALLID, and WBRQSHELLINIT.

DUMPBIN /EXPORTS WBTRV32.DLL
Microsoft (R) COFF Binary File Dumper Version 4.20.6164
Copyright (C) Microsoft Corp 1992-1997. All rights reserved.

Dump of file wbtrv32.dll
File Type: DLL
        Section contains the following Exports for wbtrv32.dll
                  0 characteristics
           31D30571 time date stamp Thu Jun 27 15:04:33 1996
               0.00 version
                  1 ordinal base
                 10 number of functions
                 10 number of names

            ordinal hint   name

                  1    0   BTRCALL  (000014EC)
                 8    1   BTRCALLBACK  (00003799)fs
                 2    2   BTRCALLID  (00001561)
                 9    3   DBUGetInfo  (00008600)
                10    4   DBUSetInfo  (000089E8)
                 3    5   WBRQSHELLINIT  (00002090)
                 4    6   WBSHELLINIT  (00002A6A)
                 7    7   WBTRVIDSTOP  (00001812)
                 5    8   WBTRVINIT  (00002A4F)
                 6    9   WBTRVSTOP  (000017D2)

  

The information presented in these output excerpts is used to create the definition file for the wrapper DLL. You need to implement only the exported functions from Wbtrv32.dll that are used by the base application in the wrapper DLL. This eliminates the need to implement exported functions that are never used by the base application.

Mapping Functions in a DEF File

After you have identified the Btrieve import functions and symbols in the base application as well as the exported symbols for the DLL, map these import functions to export functions in the wrapper DLL by using a definition file for the wrapper DLL.

Create a DEF file that contains an EXPORTS section with the names of the functions listed in the name column of the DUMPBIN output. The exact import/export combination varies depending on what Btrieve functionality is used in the application.

Implementing the Btrieve Functions
Within the Wrapper

The next step is to develop the basic framework within the wrapper so that all of the Btrieve operations are implemented properly. Most of the Btrieve operations are performed by using the BTRCALL and BTRCALLID functions. Their equivalent functions within the wrapper must be designed to address the operations used by the base applications. Each of these functions has all of the data necessary to perform the operations by using the input parameters it receives.

The following code fragment shows how the B_GET_EQUAL operation is handled by the BTRCALL function within Mybtrv32.dll:

DllExport int __stdcall BTRCALL (BTI_WORD operation, BTI_VOID_PTR posBlock, 
     BTI_VOID_PTR dataBuffer, BTI_ULONG_PTR dataLen32,
       BTI_VOID_PTR keyBuffer, BTI_BYTE keyLength, BTI_CHAR ckeynum)
{
SQLRETURN rc;    // Btrieve operation return code

/*Perform tasks based on operation used in the calling application */
switch(operation){ 

case B_GET_EQUAL:    
// Get the first Title-Publisher record that matches the search
// criteria
if (!strcmp(posBlock, "titlepub.btr")){//Are we accessing title-publisher info
rc = GetTitlePublisher(henv1, hdbc1, hstmt, B_GET_EQUAL, ckeynum,keyBuffer);
if (rc != B_NO_ERROR)
        return rc;

//Copy title-publisher data to titlepub record structure tpRec
memcpy(dataBuffer, &tpRec, sizeof(tpRec));
}
else {    // Accessing sales info
rc=GetSales(henv1, hdbc2, hstmt2, B_GET_EQUAL, keyBuffer);
    if (rc != B_NO_ERROR)
return rc;

//Copy sales data to sales record structure salesRec
memcpy(dataBuffer, &salesRec, sizeof(salesRec));
}    
break;

  

The most important parameters are the posBlock, operation, dataBuffer, keyBuffer, and ckeynum parameters. The posBlock parameter is described in “Addressing the Btrieve posBlock Handle,” later in this chapter. The operation parameter designates what operation is to be performed. The contents of the dataBuffer, keyBuffer, and ckeynum parameters depend on the operation being performed. You must use these parameters in the same way they would be used if the function was being processed by Btrieve.

The posBlock parameter in the preceding code fragment determines the target SQL Server table. After the target has been determined, a function is called to retrieve the first data record that matches the keyBuffer and ckeynum values from the appropriate SQL Server cursor.

The same methodology is used throughout the wrapper DLL. This illustration shows the wrapper DLL concept.

The base application, Btrvapp.exe, requests the title and publisher information for TitleID “BU1032.” While the wrapper DLL processes this request, the Btrieve application calls the Btrieve function BTRCALL to get the next record from the Titlepub.btr file. The wrapper DLL mimics BTRCALL but accesses SQL Server data instead. It examines the opcode parameter and then performs the appropriate ODBC and Transact-SQL operations to satisfy the request. In this example, the wrapper DLL retrieves the record for TitleID “BU1032” from the titlepub table in the database. The wrapper DLL returns the retrieved data to the base Btrieve application by using the record data buffer passed as part of the original BTRCALL function call.

Accessing the Wrapper DLL in the Base Application

After the wrapper DLL has been created, the original application must reference the wrapper DLL instead of the Btrieve DLL. Link the application with the wrapper DLL and ODBC library files (LIB) rather than with the Btrieve library file. You do not have to recompile the base code. The base application will access SQL Server and not the Btrieve microkernel.