*******************************************************
*******************************************************

Professional Development Series
Bullets

February 1992
Volume 4, Number 2

*******************************************************
*******************************************************


*******************************************************
*******************************************************
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
#include <direct.h>
#include <dos.h>

#include <nit.h>
#include <niterror.h>

#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(&regs,&regs,&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
*******************************************************



*******************************************************
*******************************************************
ARTICLES:
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.

25.  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.

26.  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" as well as the
     "parent."

27.  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).

28.  Load SHARE at your workstation if you are opening a local
     file with multiple position blocks.

29.  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.

30.  Using Btrieve transaction processing with American
     Megatrends CNT 286 BIOS v1.3 requires v5.10a or greater
     of Btrieve.

31.  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.

32.  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).

33.  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 <Btrieve filename>
     NUL N <key number> [-O<owner>]

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 <Btrieve filename>
      NUL [-O<owner>]

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 (/* ... */).



*******************************************************
*******************************************************
TECHNICAL INSIGHTS:
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 <os2.h>
#include <stdlib.h>
#include <stdio.h>
#include <process.h>
#include <nwcalls.h>

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
*******************************************************



*******************************************************
*******************************************************
TECHNICAL INSIGHTS:
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.



*******************************************************
*******************************************************
TECHNICAL INSIGHTS:
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;



*******************************************************
*******************************************************
TECHNICAL INSIGHTS:
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.



*******************************************************
*******************************************************
TECHNICAL INSIGHTS:
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.



*******************************************************
*******************************************************
TECHNICAL INSIGHTS:
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.



*******************************************************
*******************************************************
PATCH LISTINGS:
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 & 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



********************************************************
********************************************************
CONTACTING NOVELL AUSTIN
********************************************************
********************************************************

To obtain technical support, call 1-800-NETWARE
(1-800-638-9273), or 1-801-429-5588. Be prepared to give the
support operator your Direct Connect authorization number or
open incident reference number. Technical support questions
may also be sent by FAX to 1-512-794-1775. Novell provides a
wide range of support contracts designed to meet your needs.

If you have purchased a new Novell Development Product, you
are eligible for 30 days of free telephone support. Please be
prepared to give the support operator the product's serial
number.

Many international distributors provide technical support.
Please contact your distributor or local Novell office (see
list at end of this issue) for more information on
international support options.

Software patches may be obtained from the NetWire forum on
CompuServe, or by contacting the Developer Support Group and
specifying the patches you need by product name.

For more information on Novell's Professional Developers'
Program, Novell Database Products, and Direct Connect Support
Contracts, call 1-800-RED-WORD (1-800-733-9673), or
1-512-794-1796, FAX 1-512-794-1770, or contact the nearest
Novell office.

Novell Development Products can be obtained through Novell
Authorized Resellers, or by calling 1-800-RED-WORD
(1-800-733-9673) or 1-512-794-1796.

Software Developer's Kits (SDKs) are available only through
Novell's Professional Developers' Program Call 1-800-RED-WORD
(1-800-733-9673) or 1-512-794-1796.


********************************************************
********************************************************
CURRENT VERSIONS OF NOVELL PRODUCTS
********************************************************
********************************************************

---------------------------------------------------
NetWare
---------------------------------------------------
     NetWare 3.x                             3.11
     NetWare 2.x                             2.2
     NetWare Lite                            1.0
     NetWare for VMS                         2.1
---------------------------------------------------

---------------------------------------------------
NetWare Services
---------------------------------------------------
     NetWare for Macintosh                   3.01
     NetWare NFS                             1.2
     NetWare FTAM                            1.2
     NetWare for SAA                         1.1
     NetWare RMS
     NetWare NNS
---------------------------------------------------

---------------------------------------------------
Communication Toolkits
---------------------------------------------------
     LAN WorkPlace Toolkit for DOS           4.0
---------------------------------------------------

---------------------------------------------------
NetWare System Interfaces
---------------------------------------------------
     NetWare C Interface for DOS             1.2
     NetWare System Calls for DOS            1.0
     NetWare System Interface
          Technical Overview                 1.2

---------------------------------------------------
Software Developer's Kits
---------------------------------------------------
     OS/2 Developer's Kit                    1.3a
     NetWare C Interface for Windows         1.22
     NetWare C Interface for Macintosh       1.3
     NetWare Network Management Toolkit      1.0
     TCPort Developer's Kit                  2.2
     LAN WorkPlace Toolkit for OS/2          2.0
     Network C for NLMs                      2.0b
     NetWare TIRPC                           1.0
     NetWare AppleTalk Interface for NLMs    1.0
     NetWare LU6.2 Toolkit                   1.2
     NetWare 3270 Toolkit                    1.6
---------------------------------------------------

---------------------------------------------------
NetWare RPC
---------------------------------------------------
     NetWare RPC for DOS                     1.1
     NetWare RPC 386                         1.1
---------------------------------------------------

---------------------------------------------------
Compiler Toolkits
---------------------------------------------------
     Network C for DOS                       2.0
---------------------------------------------------

---------------------------------------------------
XQL
---------------------------------------------------
     XQL for DOS                             2.11
     XQL for OS/2                            2.11
---------------------------------------------------

---------------------------------------------------
NetWare SQL
---------------------------------------------------
     NetWare SQL (NLM)                       2.11a
     NetWare SQL (VAP)                       2.11
---------------------------------------------------

---------------------------------------------------
Btrieve
---------------------------------------------------
     NetWare Btrieve (NLM)                   5.15
     NetWare Btrieve (VAP)                   5.15
     Btrieve for DOS                         5.10a
     Btrieve for OS/2                        5.10
     Btrieve for Windows                     5.10
---------------------------------------------------

---------------------------------------------------
Xtrieve PLUS
---------------------------------------------------
     Xtrieve PLUS for DOS                    4.10
     Xtrieve PLUS for OS/2                   4.01
---------------------------------------------------

---------------------------------------------------
Report Executive
---------------------------------------------------
     Report Executive for DOS                4.01a
     Report Executive for OS/2               4.01a
---------------------------------------------------

For a complete list of the Novell product line contact Novell
Austin or your local Novell Authorized dealer.




********************************************************
********************************************************
CURRENT REQUESTER VERSIONS
********************************************************
********************************************************

---------------------------------------------------
NetWare Btrieve v5.15
---------------------------------------------------
     Requester for DOS                       5.16
     Requester for OS/2                      5.17a
     Requester Interface for Windows 3.0     5.16
---------------------------------------------------

---------------------------------------------------
NetWare SQL v2.11
---------------------------------------------------
     Requester for DOS                       2.12a
     Requester for OS/2                      2.11
     Requester Interface for Windows 3.0     2.13
---------------------------------------------------

-----------------------------------------------------
NetWare Shells and Requesters
-----------------------------------------------------
     DOS Shell                               3.22a
     IPX (DOS)                               3.10
     VIPX.386                                1.10
     NetWare Requester for OS/2              1.3
     NETWARE.DRV (Windows)                   1.03.7
     VNETWARE.386 (Windows)                  1.03.2
-----------------------------------------------------


********************************************************
********************************************************
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

********************************************************
********************************************************
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.
********************************************************

Developer Support/Direct Connect:
1-800-SAY-HELP (1-800-729-4357)
Tel. (512) 346-8380
Fax  (512) 794-1775

International Customers please contact your local Novell
authorized dealer or nearest Novell office.

********************************************************
********************************************************

Novell, Inc.
Corporate Headquarters
122 East 1700 South
P.O. Box 5900
Provo, Utah 84606
USA
Tel.  (801) 429-7000

********************************************************

Novell International Operations
& Novell Latin America
890 Ross Drive
Sunnyvale, CA 94089
USA
Tel.  (408) 747-4000
FAX (408) 747-4033

********************************************************

Novell Australia
Level 2
2 Help Street
Chatswood NSW 2067
Australia
Tel.  61 (2) 413-3077
FAX 61 (2) 413-3116

********************************************************

Novell Benelux
Excelsiorlaan 13
1930 Zaventem
Belgium
Tel.  32 (2) 725-02-00
FAX 32 (2) 725-03-11

********************************************************

Novell France
Tour Anjou
33, Quai De Dion-Bouton
92814 Puteaux Cedex
France
Tel.  33 (1) 47.75.09.09
FAX 33 (1) 47.78.94.72

********************************************************

Novell Germany
Willsttter Strasse 13
4000 Dsseldorf 11
Germany
Tel.  49 (211) 5973-0
FAX 49 (211) 5973-250

********************************************************

Novell Hong Kong
12/F New Town Tower
8-18 Pak Hok Ting Street
Shatin, New Territories
Hong Kong
Tel.  852 6012123
FAX 852 6940818

********************************************************

Novell Italy
Via San Vittore 40
20123 Milan
Italy
Tel.  39-2-4801 3554
FAX 39-2-4801 3594

********************************************************

Novell Japan
Toei Mishuku Bldg.3F
1-13-1 Mishuku
Setagaya-ku, Tokyo 154
Japan
Tel.  81 (3) 5481-1161
FAX 81 (3) 5481-1855

********************************************************

Novell Spain
Lexington. S.a.
Paseo Castellana, 141
Planta 18
28046 Madrid
Spain
Tel.  34 (1) 572-0360
FAX 34 (1) 570-7199

********************************************************

Novell Sweden
Kottbyjatan 7
16475 Kista
Sweden
Tel.  46 (8)-7032350
FAX 46 (8)-7039434

********************************************************

Novell Switzerland
Bahnstrasse 102
8105 Regensdorf
Switzerland
Tel.  41 (1) 870-0650
FAX 41 (1) 870-0628

********************************************************

Novell United Kingdom
Avon House, Sweetwell Road
Bracknell, Berkshire
RG12 1HH
United Kingdom
Tel.  44 (344) 860 400
FAX 44 (344) 860 353

********************************************************
********************************************************
********************************************************
********************************************************
********************************************************
********************************************************
********************************************************
********************************************************
********************************************************
{END OF FILE}
