Developer Links
SUPPORT FORUMS  
SAMPLE CODE & TIDS  
TEST/DEVELOPMENT KIT INFO
 
DEVELOPER LABS  
NOVELL SUPERLAB  
SUPPORT DOCUMENTS  
STRATEGIC/EXECUTIVE ISSUE TRACKING  
SYSOP PROGRAM  
     
Related Links
 
 
 
 
 
Related Links  
 

 
DEVELOPER SUPPORT HOME  

FEBRUARY 1992 VOLUME 4 NUMBER 2


INDEX


MAD'S COLUMN

Hello and welcome to the February 1992 issue of Bullets!

A few years ago, the idea of having a new federal holiday in February was an exciting one to me, that is, until I discovered it was "Presidents Day" and not "Precedents Day." Presidents are inaugurated in January and not all are born in February, so why celebrate "Presidents Day" in February? Yes, I know that George and Abe were born in February, but what about all the other presidents and those yet to come?

If it were actually "Precedents Day," it could be a day when everyone would set an example or precedent. Everyone could define a way to make his or her products, division, company, or industry better. Maybe our engineers thought it was Precedents Day when they laid the plans for NetWare SQL v3.0. Announced this week at NetWorld Boston, NetWare SQL v3.0 sets the standard for declarative relational database access. The next issue of Bullets will feature a special section on this exciting new database system.

Until then, I'll set a precedent and include a rare, personal note in Bullets. Nancy Woodward has decided to leave Novell to pursue other interests and take on new challenges. Her style and knack for setting precedents brought Btrieve to the PC world ten years ago and contributed generously to the success of our industry and of Novell. Adios and thank you, Nancy!

Happy_Programming!

Mad Poarch
Director
Developer Support/Service


ARTICLES:

Saving & Restoring Drive Mappings

Many programming situations require you to save drive mappings and later restore the mappings to their original state. You may need to save and restore drive mappings when recovering critical applications after a connection is lost, with all the drive mappings for that server. This procedure also may be necessary for special processing requiring an application to login to a server that already has an active connection, which will cause the respective drives for that server to be cleared as well. This article describes how to use the APIs supplied with the NetWare C Interface for DOS v1.2 to save and restore all drives to which a node is currently mapped.

Saving Mappings

Required APIs:
  • GetDriveInformation,
  • GetFileServerName,
  • SetPreferredConnectionID,
  • GetDirectoryHandle
Required functions:
  • C library call to obtain environment variables
The simplest approach is to obtain drive information for all mapped drives (drives 0-25, or 0-31 when temporary drives are to be included). Use the GetDriveInformation API to determine a drive handle, connection ID, and drive letter for each drive number. All mapped drives, including search drives, will return a valid drive handle. This includes local drives mapped to network drives.

Search mappings require special handling. They are simply drives that compose the PATH environment variable. Local search drive mappings, such as a mapping to a hard disk drive, are treated differently than network search drives because they are not associated with a directory handle. They are put as full paths into the PATH variable.

Using the connection ID returned by the GetDriveInformation API, obtain the server name and the directory path for each drive handle using GetFileServerName API and GetDirectoryHandle APIs, respectively. You must call SetPreferredConnectionID API before obtaining the directory path for each server.

To determine which drives are search drives, parse the PATH environment variable. This will also permit you to determine local search drive mappings. The GetSearchDriveVector API only returns network specific search drives and does not consider any local search drive mappings, so you must use the PATH variable instead.

Since the PATH environment variable dictates the search order of the search drives, it can be parsed easily. Each drive letter and its corresponding path must be saved. For local search drives, the entire drive and path must be saved from the PATH environment variable.

After retaining information about the drives and paths in a control structure, you are ready for the recovery process. Figure 1 contains an example of a control structure. With critical errors such as losing a connection to a file server, you should deallocate the directory handles for that file server. This discards control information for the disabled server.

FIGURE 1: Example Control Structure

struct {
       BYTE searchVector[17]; /* indexes in struct below point
                              ** at the specified drive or path

                              ** making up the PATH variable */
       struct {
               char path[255];  /* server name:vol\full path */
               int  search;     /* marks search drive */
               BYTE drivType;    /* local, permanent or temp*/
               WORD connectionID; /* connID of server for drv*/
                } drive[31];      /* index respective to drive
                                  ** letters A-Z + temps */
        }

END of FIGURE 1

Restoring Mappings

Required APIs:
  • MapDrive
  • PutEnvironmentVariable
You can restore original drive mappings using the MapDrive API. Set the parameters for the API as follows:
  • search flag = DRIVE_ADD
  • search drive order number = 0
To restore the search drives, you must build a new PATH environment variable and place it in the ROOT environment using the PutEnvironmentVariable API. The PATH environment variable is built using the search drive order designated in the control structure. Drive letters are placed in the PATH variable followed by a colon, period, and semicolon (:.;). The paths of all local search mappings, followed by a semicolon, are also placed in the PATH environment variable in their corresponding order.

If you want to change the environment your application is currently using, modify the PATH environment variable in the new environment. Use the 'C' library call "putenv" provided with the WATCOM C and Microsoft C compilers.

Saving Mapped Roots

  • Additional APIs Required: ParsePath
In additional to normal mapped drives, mapped root drives require some special handling. To determine if a drive is a mapped root drive, use the ParsePath API to obtain the path for the drive. If the drive is a mapped root drive, the ParsePath API will return a path that does not include the mapped root portion. Using the GetDirectoryPath API will return the full path, including the mapped root portion. If you compare these two paths and they do not match, you have found a mapped root drive.

Comparing the results of these two APIs also allows you to determine which portion of the path is the rooted portion and which part is the path off of the root. The ParsePath API has already returned the path off the root. To identify the rooted portion, find the position in the full path where the paths match. The part preceding the matching portion is the mapped root.

Restoring Mapped Roots

Additional C library functions:
  • _dos_getdrive
  • _dos_setdrive
  • chdir
To restore a mapped root drive, you must use a new function: the MapRoot API. This API uses Interrupt 21h with the following register settings:
     AX = 0xE905
     BX = drive no. (A = 1, B = 2, etc.)
     DS = segment for the path
     DX = offset for the path
Restore mapped root drives by calling the above API with a drive number and the path. In many cases, a path off the root also must be specified, so set the mapping to this full path, keeping the root intact. To do this, move to the specified drive, and change directories with the remaining portion of the path.

Figure 2 (see end of this article) contains a C code example of each of the procedures described in this article. A full-length, version of this program, MAPIT.ZIP, can be downloaded from NetWire. MAPIT.ZIP is currently stored in NOVLIB LIB 1. After March 13, 1992, it will be moved to LIB 14.

If you have additional questions on using the NetWare C Interface for DOS to save and restore drive mappings, or if you need technical assistance, contact the Developer Support Group. (See "Contacting Novell Austin," at the end of this issue.)

FIGURE 2: Example Save & Restore Procedures

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 

#define NOTMAPPED       255
#define LOCAL           128
#define MAXMAPPINGS      32
#define MAXSEARCHDRIVES  16
#define SEARCHDRIVE       1
#define ENDMARKER      0xFF

/* Mapping Control Structure */

struct {
   BYTE vector[MAXSEARCHDRIVES]; /* search drv order */
   struct {
      char path[255];
      BYTE search;         /* marks whether search drive */
      BYTE dtype;          /* drive type */
      BYTE rootEnd;        /* path[rootEnd] = end of root*/
      WORD connID;         /* server connection */
      } drive[MAXMAPPINGS];
   }  maps;

int   cCode;
BYTE  drivenum, dirhandlenum, sflags;
WORD  connID, defaultConnID;
char  dirPath[255], thePath[255], tmpPath[255];
char  serverName[48], volume[48];

/*********************************************************/

void SaveDriveMappings()
{
  int drv, I;
  char *pntr, *pntr2, *tpntr, tchr;

  for (drv = 0; drv < MAXMAPPINGS; drv++) {
    maps.drive[drv].dtype = NOTMAPPED;
    maps.drive[drv].rootEnd = 0;

    cCode = GetDriveInformation((BYTE)drv,
            &maps.drive[drv].connID, &dirhandlenum);
    if (cCode == LOCAL) {
      maps.drive[drv].dtype = (BYTE)LOCAL;
      maps.drive[drv].connID = 0;
      } /* if */

    if (dirhandlenum) {
      GetFileServerName(maps.drive[drv].connID,
                  maps.drive[drv].path);
      if (connID != maps.drive[drv].connID) {
        connID = maps.drive[drv].connID;
        SetPreferredConnectionID(maps.drive[drv].connID);
        } /* if */

      if (GetDirectoryPath(dirhandlenum,dirPath) == 0) {
        maps.drive[drv].dtype = (BYTE)cCode;
        strcat(maps.drive[drv].path,"\\");
        strcat(maps.drive[drv].path,dirPath);

          /* Check if MAP ROOT */

        sprintf(thePath,"%c:",drv + 'A');
        ParsePath(thePath, serverName, volume, tmpPath);

          /* rid of trailing '\' */

        if (tmpPath[0]) tmpPath[strlen(tmpPath) - 1] = NULL;

        if (strcmp(tmpPath,(strchr(dirPath,':') + 1))) {

          maps.drive[drv].rootEnd =
            (BYTE)(strstr(maps.drive[drv].path,tmpPath) -
             maps.drive[drv].path );

            /* force NULL into end of root */

          I = maps.drive[drv].rootEnd - 1;
          maps.drive[drv].path[I] = NULL;
          } /* if */
        } /* if */
      } /* if */
    } /* for */

    /* get search order from PATH environment variable */
  strcpy(thePath,strupr(getenv("PATH")));

  if (thePath[0] != NULL) {
    drv = 0;
    pntr = thePath;

    while (drv < MAXSEARCHDRIVES && (pntr = strchr(pntr,':'))
) {
      tpntr = pntr;
      if (*(pntr + 1) == '.') {
        maps.vector[drv] = *(pntr - 1) - 'A';
        maps.drive[maps.vector[drv]].search = SEARCHDRIVE;
        drv++;
        }
      else {
        for (I = 0; (maps.drive[I].dtype != NOTMAPPED) &&
                    (I < MAXMAPPINGS); I++);

        if (I < MAXMAPPINGS) {
        if ((pntr2 = strchr(pntr,';')) == NULL)
        pntr2 = strchr(pntr, '\0');

          if (pntr2) {
            tchr = *pntr2;
            *pntr2 = '\0';
            pntr ;
            maps.vector[drv] = (BYTE)I;
            maps.drive[I].dtype = 1;
            maps.drive[I].search = SEARCHDRIVE;
            strcpy(maps.drive[I].path,pntr);
            if (tchr != NULL) *pntr2 = '|';
            drv++;
            } /* if */
          } /* if */
        } /* else */

      if (drv <= MAXSEARCHDRIVES)
        maps.vector[drv] = ENDMARKER;

      *tpntr = ' ';        /* STEP over current ':' */
      } /* while */
    }
} /* SaveDriveMappings */

/*********************************************************/

int MapRoot(int drv, char far *rpath)
{
  union  REGS   regs;
  struct  SREGS  sregs;

  regs.x.ax = 0xE905;
  regs.x.bx = drv + 1;
  regs.x.dx = FP_OFF(rpath);
  sregs.ds  = FP_SEG(rpath);

  intdosx(®s,®s,&sregs);
  return(regs.h.al);
}  /* MapRoot */

/*********************************************************/

void ResetDriveMappings()
{
  int drv, sdrv, dummy, rt;
  char drvl, *pntr;

  for (drv = 0; drv < MAXMAPPINGS; drv++) {
    if (maps.drive[drv].connID) {
        /* if MAPped ROOT, set root & path */

      if (rt = maps.drive[drv].rootEnd) {
        SetPreferredConnectionID(maps.drive[drv].connID);
        cCode = MapRoot(drv,
                       (char far *)maps.drive[drv].path);
        if (cCode)  {
          printf("\nError MapRoot: %d",cCode);
          exit(1);
          }

          /* change to path off of root */
        if (maps.drive[drv].path[rt] != NULL) {
          _dos_getdrive(&sdrv);
          _dos_setdrive(drv, &dummy);
          chdir(&maps.drive[drv].path[rt]);
          _dos_setdrive(sdrv, &sdrv);
          } /* if */
        } /* if */
      else {
        drvl = (char)(drv + 'A');
        if (cCode = MapDrive(maps.drive[drv].connID,
                  NO_BASE_DRIVE,maps.drive[drv].path,
                  DRIVE_ADD, 0, &drvl)) {
          printf("\nError MapDrive: %d",cCode);
          exit(1);
          } /* if */
        } /* else */
      } /* if */
    } /* for */

    /* make the PATH string */

  pntr = thePath;
  for (drv = 0; (maps.vector[drv] != ENDMARKER) &&
            (drv < MAXSEARCHDRIVES); drv++) {
    if (maps.vector[drv] < MAXMAPPINGS) {
      if (maps.drive[maps.vector[drv]].connID) {
        sprintf(pntr,"%c:.;",
              (char)(maps.vector[drv] + 'A'));
        pntr += 4;
        }
      else {  /* local mapping */
        strcpy(pntr,maps.drive[maps.vector[drv]].path);
        if (pntr = strchr(pntr,NULL)) {
          *pntr++ = ';';
          *pntr = NULL;
          }
        } /* else */
      } /* if */
    } /* for */

  PutEnvironmentVariable( "PATH", thePath );
} /* ResetDriveMappings */

END of FIGURE 2

Preventing & Analyzing Btrieve Status 2s

Btrieve status 2s (I/O Error) can be caused by many conditions and can signal problems in any part of your environment. At a fundamental level, status 2 indicates that Btrieve is unable to perform the specified I/O against a designated Btrieve file. I/O errors can be the result of a problem with the Btrieve call parameters, file structure, hardware, system configuration, security rights, memory or any combination of factors.

To diagnose the cause, begin by examining the Btrieve function call that returned the status 2. Is the call returning the status 2 a read operation or a write operation? Do consecutive read and write operations also return status 2s. Did the status 2 suddenly appear on a long-running application?

Next, consider other possible causes. Is the status 2 returned if you move the file to another machine or a different directory or is it a problem with the file? If the file is on a server, can you access it from another workstation?

Status 2s do not always indicate that a Btrieve file is damaged. This article discusses methods for preventing and analyzing problems with your development environment or application that can lead to status 2s.

Preventing Status 2s

If your application receives status 2s, do not immediately assume the worst. Start by examining the following list of do's and don'ts.
  1. Stay up-to-date on patches for your Novell database products. If the patches do not fix the problem, they may change the symptoms of the problem and provide a clearer understanding of the cause. Patches are available at no charge either through Novell's NetWire forum on CompuServe, or by contacting Novell Austin (see end of this issue for details). Apply patches first because your problem may already have been fixed.
  2. Btrieve files must be flagged NON-SHARABLE to NetWare . Btrieve should be a file's only user. In this configuration, Btrieve controls access to the file from multiple applications and preserves file consistency. The NON-SHARABLE flag prevents different versions of Btrieve from accessing a file simultaneously. For example, you cannot use Btrieve for DOS and NetWare Btrieve (NLM or VAP) on the same file concurrently. The NON-SHARABLE flag also prevents you from making backups of your file while Btrieve has the file open.
  3. Certain hardware and shell problems can trigger Btrieve status messages. If your application suddenly starts receiving unusual status messages:
    • Make sure all hardware is certified by Novell for your version of NetWare. If you have doubts, please contact Developer Support.
    • Check for hardware failure by running your application on another server or workstation, or from another directory. Experiment with substituting hardware and network cards.
    • Install the newest drivers and shells. Check for patches to the drivers, shells, or network OS.
  4. Some viruses can generate status 2s. For example, virus 1704 sends erroneous hardware errors to your application. Check all disks and hard drives for viruses regularly.
  5. If your computer has expanded memory and you are experiencing problems, try loading Btrieve for DOS with the "/e" parameter. This parameter keeps Btrieve data buffers out of expanded memory, which may be necessary if another application uses that memory without restoring pointers properly.
  6. Make sure position blocks retain physical integrity throughout your application. Check where the position block is defined and what variables are defined immediately before it. Identify when, where, and how those variables are accessed to make sure the position block is not overwritten.
  7. Make sure each Btrieve file has only one pre-image file. Multiple pre-image files for a Btrieve file can invalidate file rollback operations.
    • If users redirect pre-image files to another directory with the Btrieve "/i" parameter, all users of a Btrieve file must direct their pre-image files to the same directory.
    • With versions of Btrieve prior to v5.00, do not use NetWare search mappings to find Btrieve files. If multiple users with different mappings access the same file, a separate pre-image file may be created in each users current directory.
  8. Make sure each pre-image file is associated with only one Btrieve file. Btrieve names the pre-image file with the same name as the Btrieve file with a .PRE extension. Two files named EMPLOYEE.DAT and EMPLOYEE.VAC would have the same pre-image filename, EMPLOYEE.PRE.
  9. You may have run out of disk space for your Btrieve write operation. Normally, this will return a status 18 (Disk Full), but Btrieve may return a status 2 under some circumstances.
  10. Be certain that enough disk space is available for your pre-image file. Status 2s may be returned on a write operation if you do not have enough disk space for the pre-image file. This point is especially important if you use Btrieve transactions. Within a transaction, each write operation adds pages to the pre-image file, and these pages are not deleted until an End Transaction or Abort Transaction operation is performed.
  11. You must assign users the necessary NetWare security rights for all accessed files, including transaction and pre-image files. The rights required for normal, accelerated, or exclusive mode access are READ, WRITE, and CREATE.
  12. With NetWare v2.10, v3.10 or greater, flagging files "transactional" and using Btrieve for DOS may result in status 2s if multiple workstations access the same files, TTS is active, and Btrieve files are flagged "transactional." TTS locks every page it accesses, including the Btrieve file header page. If another workstation tries to access a file that is currently active with TTS, Btrieve detects a lock on the header page. Since the lock is not a Btrieve lock, status 2 is returned.
  13. Do not attempt to directly access the extended portion of a Btrieve file. You can only access the original portion of an extended Btrieve file. For example, if you have a file called STUFF.DAT and you extend it to a file called STUFF2.DAT (using operation 16), and then try to access STUFF2.DAT directly, Btrieve will return a status 2.
  14. On NetWare v2.x, if the number of communication buffers currently in use are at or near maximum, BSERVER.VAP may be logged out. Subsequent Btrieve calls will return status 2. To avoid this situation, increase the number of communication buffers. On NetWare v2.2, the maximum is 1000 and the default is 150. To increase the number to 250, type the following in the SYS:SYSTEM directory:
         dconfig net$os buffers:250
    
  15. If you apply patches to Btrieve, with DEBUG.COM, give the Btrieve .EXE file another extension (e.g., ren BTRIEVE.EXE BTRIEVE.PAT). After you apply the patches, rename it back to the .EXE extension. If you do not rename Btrieve while using DEBUG.COM on it, that copy of Btrieve will return status 2 on any files it accesses. (Batch files for Btrieve v5.10 and above no longer use DEBUG.COM, so this is not a concern for current versions.)
  16. Within a transaction, if you initiate an Abort Transaction with a single-record, no-wait lock (operation code 221), the next time the file is accessed, a status 14 (Pre-Image Open Error) is returned. You will not be able to open the file in any mode after this; the file must be recreated. Novell engineers are currently working to resolve this situation.
  17. If you use the "/o" (Override Criti-cal Errors) load parameter when loading Btrieve for DOS, Btrieve translates OS critical errors like "Drive not ready" to Btrieve status codes. Do not use this load parameter unless your application handles OS critical errors correctly.
  18. If you are using single-user Btrieve, do not open a file with more than one position block. Doing so will violate integrity checks, and may lead to status 2s. If a file resides on a network drive, only allow one user to access it at a time.
  19. When using Microsoft Basic v7.x, use versions of the Btrieve interface (BC7RBTRV.OBJ) dated November 26, 1990 or later.
  20. Using BTRIEVE.NLM v5.11, if one station reads a file while another workstation simultaneously opens the file in a transaction, Btrieve returns a status 2 to the reading station. The operation is successful when retried. This situation does not occur with NetWare Btrieve (NLM) v5.15. (See Bullets, June/July 1991.)
  21. Older versions of NETx.COM (v3.02 and v3.20) contain known problems. Get the newest version from Novell's NetWire forum (NOVLIB, LIB 5, DOSUP4.ZIP) or from Novell Developer Support.
  22. If you need to run Btrieve files on large (255+ MB) mirrored drives, use NetWare SFT v2.15c or greater.
  23. If you use NCOPY.EXE v2.2 or 3.10 to make a copy of a Btrieve file with the characteristics listed below, the duplicate file will be larger by exactly 65K.
    • The Btrieve file was created specifying pre-allocation.
    • The last 1K of the file were zeros.
    • The file was .5 MB or larger.
    • Btrieve v4.10 or greater will return status 2s when accessing the file.
    24. An MSDOS v4.01 bug causes status 2s when a Btrieve file's size is with-in 512 bytes of a 32 MB boundary and the file is expanded (See Bullets, October 1991). Microsoft has a patch for this bug that can be applied to MSDOS.SYS or IBMDOS.COM. To obtain the patch, call Microsoft at 900-896-9000 or 206-646-5108.
  24. Using NetWare v2.12, NetWare Btrieve v4.11, and Btrieve transactions, status 2s may be returned on an Insert operation. This situation has been corrected in current versions of NetWare Btrieve and NetWare 2.x.
  25. Design your applications so that static subprograms do not use stale position blocks to access files. If a "child" process remains in memory after returning control to the "parent" process and then the "parent" closes a file, that file is closed for the "child" a6s well as the "parent."
  26. If you are using a LANtastic network, or any other network that uses SHARE for managing file and record locks, load SHARE.EXE only at the server. (For the exception to this rule, see #28).
  27. Load SHARE at your workstation if you are opening a local file with multiple position blocks.
  28. If you use a CVIS network with Btrieve for DOS v5.00 and above, opening a file with multiple position blocks may return a status 2.
  29. Using Btrieve transaction processing with American Megatrends CNT 286 BIOS v1.3 requires v5.10a or greater of Btrieve.
  30. Btrieve for DOS v5.10a may return erroneous error messages when you run it on an AT&T Stargroup network. This problem is being investigated.
  31. On NetWare v3.10, apply READFIX.NLM and CACHEFIX.NLM. These patches prevent some causes of status 2s and 52s. Both patches can be downloaded from Novell's NetWire forum (READFX.ZIP, NOVLIB, LIB 7; CACHFX.ZIP, NOVLIB, LIB 4).
  32. Changing NetWare directory rights on a directory where a Btrieve file is being accessed causes status 2s.

Verifying File Integrity

BUTIL provides an easy way to determine if a file is damaged. Perform a BUTIL SAVE on all keys in the file. This operation traverses and validates the specified key path and reports any errors. It can write the records from your Btrieve file to an ASCII file in key order. If you don't want to consume disk space, use the command below to report errors to the screen without creating a text file:
BUTIL -SAVE 

NUL N  [-O]
To verify data page links, perform a BUTIL RECOVER operation on the file. BUTIL RECOVER is not specific to a key path, so you only need to run it once. BUTIL RECOVER can also write records to an ASCII file. If you do not to need this feature, perform the recovery with the following command:
BUTIL -RECOVER 

NUL [-O]
If these utilities run successfully your Btrieve file is probably intact. If you determine that your status 2 indicates a damaged Btrieve file, replace the file with a backup or rebuild the file using Btrieve or a Btrieve utility. To rebuild the file, use BUTIL CREATE to create an empty duplicate of the file that may be damaged. Then, use BUTIL LOAD to insert the records from the BUTIL RECOVER or SAVE ASCII file into the duplicate file you just created.

Determining why and when file corruption occured is the next step. Keep a log of affected files, and the times and dates when you detect corruption, and what code modules were running on each workstation. When performed at regular intervals, these operations can help establish when corruption occurs, and provide insight into the cause of the problem.

BUTIL.EXE (or, with Btrieve for Windows, BTRTOOLS.EXE) is only available with the Btrieve Developer's Kit. (Server-based BUTIL.NLM is a faster version of BUTIL.EXE.) A third party utility, BCLEAN.EXE, can recover files that are severely damaged. Both BUTIL and BCLEAN can be obtained from the Developer Support Group or downloaded from Novell's NetWire library forum, NOVLIB.

With proper development environment configuration and application design, status 2s can be prevented in most cases. This article includes the most common preventable causes of status 2s and provides you with a productive first step in the event that your files are damaged. If you have additional questions about Btrieve status 2s, or if you require technical assistance, please contact the Developer Support Group at Novell Austin (see "Contacting Novell Austin," at the end of this issue).


TECHNICAL INSIGHTS:

Compiling NMPIPE.H (NetWare OS/2 SDK v1.30a)

In the NetWare OS/2 SDK, compil-ing the DOS client version of the file, NMPIPE.H, results in compiling errors. A simple modification to NMPIPE.H will, however, correct the situation and allow the file compile correctly.

On lines 65, 69, 71, and 74 of this file, a semicolon has been erroneously placed after the #define statement. A comment follows the semicolon. Replace the semicolon with comment delimiters (/* ... */).

Checking if NetWare Requester for OS/2 is Loaded (NetWare Requester for OS/2 v1.3)

For developers that are familar with the OS/2 programming environment, writing applications that are NetWare-Aware usually involves determining whether or not the NetWare OS/2 Requester is running and, if so, what version is running. The NetWare OS/2 Requester is loaded from the CONFIG.SYS file at boot time and allows access to a NetWare file server from an OS/2 workstation. The code in Figure 3 shows one way to check to see if the requester is loaded from inside your source code.

FIGURE 3: Program to check if OS/2 Requester is loaded

#define INCL_DOS
#include 
#include 
#include 
#include 
#include 

void main()
{
  HFILE    deviceHandle;
  USHORT   action;
  int      ccode;

  if ( ccode = DosOpen("NWREQ$", &deviceHandle,
                       &action, 0L, 0, 0x01, 0x60C0, 0L) )
     printf("Requester loaded....NOT!!!");
  else{
     printf("Yes, Requester is loaded");
     DosClose(deviceHandle);  // close device handle to be
safe
  }
}

END of FIGURE 3
The code example in Figure 3 uses the DosOpen call from the files, OS2.H and OS2.LIB. IPX$, SPX$, NetBIOS$ and even Named Pipes (NAMPIPE$) device drivers can also be checked for existance. With a minor modification, the above code can be changed to determine which version of the OS/2 Requester is running. For example, the code segment in Figure 4 uses a NetWare OS/2 SDK call, NWGetRequesterVersion, and includes the prorotype for the function in NWCALLS.H.

FIGURE 4: Modification to check for requester version

void main()
{
  HFILE    deviceHandle;
  USHORT   action;
  int      ccode;
  BYTE     majorVersion, minorVersion, revision;
  char     device[80];

  if ( ccode = DosOpen("NWREQ$", &deviceHandle, &action,
                       0L, 0, 0x01, 0x60C0, 0L) )
     printf("Requester loaded.....NOT!!");
  else{
     NWGetRequesterVersion( &majorVersion,
                            &minorVersion,
                            &revision );
     printf("NetWare OS/2 Requester v%d.%d
         Rev. %c.",majorVersion,minorVersion,revision + 'A');
     DosClose(deviceHandle);
                  // close the device handle after opening
  }
}

END of FIGURE 4

Using Local and Requester DLLs (Btrieve for Windows v5.10)

With Btrieve Windows applications which access both local and server-based Btrieve files, after a local file has been accessed, any subsequent Btrieve operation to a server-based file will use the local Dynamic Link Library (DLL) instead of the Btrieve for Windows Requester DLL. To verify that this situation has occured in your application, use the BTRTOOLS Version command. The Version command should display both the local and requester DLL versions before running the application. After the application accesses a local Btrieve file, suspend the application, reload BTRTOOLS, and run Version again. If the Requester version is not displayed, your application is only accessing the local DLL.

This situation can only be detected when another Btrieve application accesses the same file via BREQUEST and returns a status 85 (File in Use) or 94 (Permission Error). To ensure that your Btrieve Windows application calls both DLLs properly, edit the local DLL with DEBUG.COM. Find the line in the code containing "WBTRCALL" and edit the hexidecimal bytes to read "WBTRLOCL." With this modification, the local DLL must always be used in combination with the Requester DLL.

WATCOM C386 Patches (Network C for NLMs SDK v2.0b)

WATCOM currently offers four patch levels for C386 v8.5. The patches can be obtained from WATCOM's bulletin board service at 519-884-2103. README.DOC files provided with each patch level identify the purpose of each patch. In order to create protected mode DOS applications which call Btrieve or the NetWare APIs, you must install all four patch levels.

Also, WATCOM started treating the _argc parameter differently between the release of patch levels C and D for the WATCOM v8.5 compiler. To ensure proper linking operations, define _argc as a global variable. For example:

int  _argc;

LPTCaptureFlag (NetWare C Interface DOS v1.2)

With the NetWare Print Services, if you call the SetCapturePrintQueue API to a new print server, the shell responds as if you are capturing to a new queue on the original print server.

To avoid this situation, set CAPTURE_FLAGS.LPTCaptureFlag to zero before calling the SetCapturePrintQueue API. This flag instucts the shell to ignore the previous queue setting since you are no longer capturing.

Use the CAPTURE_FLAGS structure for both Get and Set flags functions. Do not use SET_CAPTURE_FLAGS for the Set functions.

Critical Errors while Capturing (NetWare System Calls for DOS v1.0)

Even after installing your own critical error handler, the following message may still appear on your screen:
     Network Error on Server ANY-SERVER:
     Error receiving from network.
     Abort, Retry?
This message appears when you are printing to a captured LPT port when a network connection is lost (e.g., when the cable to the NIC is unplugged).

With v3.22 and below of the DOS shell, a critical error occuring within print capturing is considered "network critical" and is not passed to the standard critical error handler. Currently, there is no workaround.

Xtrieve PLUS and Unique Field Names (Xtrieve PLUS v4.x)

When you define or reorganize a file, Xtrieve PLUS will not allow you to give two fields the same name in the same case. If you attempt to do so, you will receive the error message, "Name Already Exists."

Xtrieve PLUS's error checking will not detect fields with the same name if they are entered in a different case. For example, you may enter fields named "Field" and "FIELD." However, when you store a definition with these fields using the "Finished Create" or "Finished Don't Create" command, Xtrieve PLUS will return a status 259 ("Error inserting new dictionary file definition").

In any given file definition, all field names should always be unique, regardless of case.


PATCH LISTINGS:

Btrieve for DOS v5.10 Patches (For patches 1 - 114, see earlier issues of Bullets.)

Patches can be downloaded from NetWire, or obtained from the Developer Support Group at no charge. (See "Contacting Novell Austin" at then end of this issue).

115. Btrieve (DOS, Windows, OS/2) If Btrieve is configured with no compression buffer (/u parameter), or with a one that is too small, Step operations incorrectly return a status 54 (Variable Page Error) instead of the correct status, 58 (Compression Buffer Too Short). This patch returns the proper status.

NetWare Btrieve (VAP, NLM) v5.15 Patches (For patches 1 - 43 & 45 - 46, see earlier issues of Bullets)

44. (BTRIEVE.NLM v5.15) If a file opened in normal mode is used inside a transaction, another workstation can not open this file in read-only mode within a transaction. The Open operation returns a status 85 (File in Use). This patch ensures that the open operation is successful.

47. (BTRIEVE.NLM v5.15) In very special situations, performing a Delete (4) operation results either in a status 2 (I/O error) or loss of a key from the B-tree. This patch prevents key loss and ensures file integrity.

48. (BTRIEVE.NLM v5.15) This patch ensures that Btrieve's logging feature functions properly. Without the patch, the logging feature can be disabled on some servers.

49. (BTRIEVE.NLM v5.15) While opening a file with a page size bigger than 1024 Kb that requires recovery from the pre-image file, a status 52 may be returned if any other file has been opened. This patch corrects the situation and adds new logic to Btrieve that helps control the size of the pre-image file.


NIBBLES AND BITS

Fast Answers to Common Questions

General Questions

Q - Where on NetWire can I find Novell's database patches?

A - Database patch files are initially uploaded to Novell's NetWire forum in NOVLIB, Library 1. Thirty days after they are uploaded, patch files are permanently moved to NOVLIB, Library 7.

Network C for NLMs

Q - When I use the Synchronize option in my NLM linker definition file, why does the console hang after I load my NLM?

A - You forgot to call the function SynchronizeStart from your NLM. This function will restart the console process after it has loaded an NLM with this option.

NetWare C Interface for DOS

Q - Why does the link error message "Unresolved External" appear for each NetWare API function when linking under Turbo C in the desktop environment?

A - In this environment, a project file must be used to compile and link. The project file must contain at least the source file name and the model specific NetWare API library file name.

NetWare C Interface for Windows

Q - A client process runs Windows and the message, "Can Not Find NETWARE.DLL," is returned. What does this message mean?

A - It means that Windows can not find the NETWARE.DRV file in the current search mapping. NETWARE.DRV and NETWARE.DLL are the same. Microsoft refers to the file as NETWARE.DLL and Novell calls it NETWARE.DRV. NETWARE.DRV is a DLL.

Btrieve

Q - If my application runs twenty-four hours a day, how can I perform a backup?

A - If a user has a file open through Btrieve, no other applications or users can open that file until Btrieve closes it. For the same reason, operating system "copy" commands will not work. Use Btrieve to copy the file, either through BUTIL operations or your own application. With BUTIL, use BUTIL CLONE to create a backup file, and then BUTIL COPY to copy records from the old file to the new one. The ability to back up continuously running files is a planned enhancement for future versions of NetWare Btrieve.

Q - Do I need to load Brequest if I want to access the Btrieve NLM from the Windows environment?

A - Yes. The DOS requester (BREQUEST.EXE) is loaded first, and then Windows is loaded. Once a Windows application is running, the first Windows call to Btrieve loads the Btrieve Requester Interface for Windows (WBTRCALL.DLL).

Q - What does the "Total" column in the BUTIL -STAT indicate?

A - "Total" gives you the number of UNIQUE values for each key. This column should not be confused with the "Total Records" column, which includes all records, not just unique values.

Xtrieve PLUS

Q - Why don't all of the command files I created with Xtrieve PLUS v4.01a work with v4.10?

A - Additional or different options on v4.10 menus prevent some command files from executing as they did in v4.01a. Use XCFP to rebuild these command files.


TECHNICAL DEVELOPMENT CONFERENCES

Novell's 8th Annual Technical Development Conference

As a reminder, the 8th annual Technical Development Conference is scheduled for March 23 27 on the University of Utah campus in Salt Lake City, Utah. This year's conference will include courses designed for all Novell partners and customers. To receive more information about the Novell's Technical Development Conference, call 1-800-858-8379 or 801-429-5878 today.

Novell's International Technical Development Conference

Novell's International Technical Development Conference will be held April 27 through April 29, 1992 in Frankfurt, Germany. The conference will be held in conjunction with the NetWorld Europe 1992 tradeshow.

This year's conference is expanded with courses for all Novell partners and customers. Whether you are a software developer, consultant, system integrator, Certified NetWare Engineer (CNE), Certified NetWare Instructor (CNI) or support provider, this conference offers valuable training for you.

To receive more information about the largest computer network development conference in the world, FAX your name, address and telephone number to 801-429-5775 or contact your local Novell Office.


NOVELL EDUCATION

Novell Education offers classes for many of the Development Products including Btrieve, XQL /NetWare SQL , Xtrieve PLUS and the NetWare Client APIs. These classes are designed to introduce participants to the powerful features of Novell's development tools, database products, and services. Nearly 50% of class time is devoted to hands-on activities.
  • 901 - Programming with NetWare: Client APIs
    Mar. 16-18 Austin, TX
    Apr. 8-10 Washington, DC
  • 905 - Programming with Btrieve
    Feb. 11-13 Chicago, IL
  • 906 - Programming with Btrieve: Advanced Features
    Mar. 10-12 Chicago, IL
  • 907 - Xtrieve PLUS
    Mar. 17-18 Washington, DC
  • 910 - Programming with XQL
    Feb. 18-20 Austin, TX
    Apr. 14-16 Chicago, IL
  • 920 - Programming with Network: Communication Services
    Feb. 19-20 Dallas, TX
    Mar. 19-20 Austin, TX
    Apr. 13-14 Washington, DC
  • 930 - Developing NetWare Loadable Modules (NLMs)
    Feb. 11-13 Austin, TX
    Mar. 10-12 Austin, TX
    Apr. 14-16 Austin, TX
To register or obtain information on pricing, location and course content for classes held in the US, call 1-800-233-3382, 1-801-429-5508 or 1-800-NET-WARE. International customers should call 1-801-537-8850. All courses are subject to cancellation or rescheduling within two weeks of the scheduled date, depending on enrollment.

For information on availability, location, and prices of international classes, contact your local Novell office.


FUN & FACTS

Test your "developing" skills with the various Professional Development Series products by taking our Fun & Facts quiz. Have fun and good luck! (See end of this issue for answers.)
1.   What password should be used by an NLM to login a user if the NLM does not
know the password of the user?

A.  NULL
B.  NO_PASSWORD
C.  LOGIN_WITHOUT_PASSWORD
2.   The Btrieve for OS/2 DLL can be called by multiple processes as well as by multiple
threads without the use of semaphores.

A.  True
B.  False
3.   What console command can be used to set the time zone on a NetWare v3.11 server to
Eastern Standard time five hours earlier than Greenwhich Mean Time.

A.  SET TIME = EASTERN + 5
B.  SET TIMEZONE = EST5
C.  SET SERVER TIME = EASTERN - 5GMT
4.   What is the Btrieve operation code for a Get Previous operation with a multiple, NoWait
lock?

A.  107
B.  207
C.  307
D.  407
5.   What is the maximum packet size of an IPX packet in the standard mode of Windows?

A.  512 bytes
B.  576 bytes
C.  534 bytes
D.  1024 bytes
6.   In Xtrieve PLUS, what parameter tells Xtrieve PLUS not to write anything to the screen?

A.  /d
B.  /m
C.  /s
D.  /k
7.   While loading an NLM, what command line parameter can be used to redirect the output
to a file?

A.  >filename
B.  >>pathname
C.  (CLIB_OPT)/>filename
8.   What is the maximum record length that BUTIL v5.10 can handle?

A.  32K
B.  10K
C.  50K
9.   What XQL keywords allow you to use the system date and time in expressions?

A.  DATE and TIME
B.  CURDATE and CURTIME
C.  SYSDATE and SYSTIME
10.  What keyword can be used in the link file of an NLM that would cause the console
command process to go to sleep?

A.  OPTION SYNCHRONIZE
B.  OPTION SLEEP
C.  OPTION CONSOLE
11.  How can you substantially increase the performance of a Btrieve Windows application
when retrieving or inserting records?

A.  By closing all other files
B.  By performing the operations in a transaction
C.  By using Btrieve's extended operations
FUN & FACTS ANSWERS
1.   C
2.   A
3.   B
4.   D
5.   A
6.    A
7.   C
8.   A
9.   B
10.  A
11.  C

CONTACTING NOVELL

Developer Support

Developers in the U.S. and Canada may contact Novell Developer Support via telephone, fax, BBS or electronic mail via CompuServe, MHS or the Internet.

Voice

For both presales and postsales support, call Novell Developer Support between 8:00 a.m. and 5:00 p.m. Mountain Time at 1-801-429-5588. Many calls to Novell Developer Support are passed to a software support engineer immediately. Calls to Novell Developer Support generally will be acknowledged or answered within four hours.

Fax

If you prefer, you may contact Novell Developer Support via fax at 1-801-429-2990. Faxed questions are acknowledged or answered within 24 hours.

Developer BBS

If you do not have access to either CompuServe or the Internet, send test cases to our BBS. Set your communication software to N-8-1 and call 1-801-429-5836.

E-mail: CompuServe

Post your messages in the appropriate section addressed to Novell at 76701,171. These messages will receive a response within 24 hours.

E-mail: MHS

You may direct your questions and comments to Novell Developer Support via Novell's Message Handling Service E-mail facility. Address your messages to devsup@novell. These messages will receive a response within 24 hours.

E-mail: Internet (SMTP)

An alternative method of contacting Novell Developer Support is through the Internet E-mail system. Send your messages to devsup@novell.com. These messages will receive a response within 24 hours.

NetWire on CompuServe

Novell's NetWire forum is open to all registered CompuServe subscribers. Through the NDEVSUP forum, professional developers writing applications with Novell development tools can gain access to information specific to Novell development. Support, patches, periodicals and product information, as well as information on all of the programs and services provided for Novell developers are accessible through this forum. Post your messages in the appropriate section addressed to Novell at 76701,171. Technical questions will be acknowledged or answered by Novell Developer Support within 24 hours.

Novell Products and SDKs

Novell products on the "Currently Shipping Developer Products" list (see page 15 of this issue), including the Red Box Products, are available to Novell Professional Developer's Program members. Call 1-800-RED-WORD (1-800-733-9673) or 1-303-894-4135 to order these products or to receive additional information. To order other Red Box Products not listed, contact your local Novell office or Novell Authorized Reseller.

DeveloperNet Labs

For information on DeveloperNet Labs development tools, education classes and product certification, in the U.S. and Canada call 1-800-453-1267 ext. 5544 or 1-801-429-5544, or call your local Novell office (see back cover of this issue).

Novell Developer Relations

Novell Professional Developers or those wishing to become members may contact Novell Developer Relations via telephone, fax, or electronic mail via Compuserve, MHS or the Internet.

Voice

For general information or questions on Novell Developer Relations programs, in the U.S. or Canada call 1-800-RED-WORD (1-800-733-9673). All others call 1-801-429-5281.

Fax

If you prefer, you may contact Novell Developer Relations via fax at 1-801-429-7207.

NetWire on CompuServe

Novell's NetWire forum is open to all registered Compuserve subscribers. Through the NDEVREL forum, Novell Professional Developer's Program-related issues or general questions may be posted. Through the NDEVINFO forum, customers who do not have products may post pre-sales product information questions on all Novell SDKs.

E-mail: MHS or Internet (SMTP)

You may direct your questions and comments to Novell Developer Relations via Novell's Message Handling Service E-mail facility. Address your messages to devprog@novell.com. Use the same address when going through the Internet E-mail system.

ACKNOWLEDGEMENTS

Publisher: Mad Poarch
Editor: Kirk R. Humphries
Design: Creative Services, Provo

Contributing Authors:
Linda Anderson, Vitek Boruvka, David Harris, Sudz Khawaja, Ken Lowrie, Clint McVey, Mike Shoemaker, Glenn Stephens, Aslam Tejani, Maggie Walczynski

Special thanks to the Developer Support, Development, Developer Relations, Product Marketing, and Marketing Communications staff who contributed time and valuable input.

Novell, NetWare, Btrieve, XQL and LAN WorkPlace are registered trademarks, NetWare System Calls for DOS, NetWare Loadable Module (NLM), NetWare SQL, NetWare Btrieve, Xtrieve PLUS, NetWare C Interface for DOS, NetWare System Interface Technical Overview, NetWare RPC, NetWare RPC 386, TCPort, TTS, NetWare LU6.2, Report Executive, and Professional Development Series (PDS) are trademarks, and Professional Developers' Forum (PDF), NetWire, Direct Connect and Professional Developers' Program (PDP) are servicemarks of Novell, Inc. Apple, Macintosh and AppleTalk are registered trademarks of Apple Computer, Inc. CompuServe is registered trademark of CompuServe Corporation. Microsoft is a registered trademark, and Windows is a trademark of Microsoft, Inc. IBM and OS/2 are registered trademarks, and SAA is a trademark of International Business Machines Corporation. Sun Microsystems and NFS are registered trademarks of Sun Microsystems, Inc. WATCOM is a trademark of WATCOM Systems, Inc.

Professional Development Series Bullets (c) 1992 Novell, Inc. All rights reserved.