FEBRUARY 1992 VOLUME 4 NUMBER 2
INDEX
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
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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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
- 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.)
- 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.
- 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.
- 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.
- When using Microsoft Basic v7.x, use versions of the Btrieve interface
(BC7RBTRV.OBJ) dated November 26, 1990 or later.
- 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.)
- 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.
- If you need to run Btrieve files on large (255+ MB) mirrored drives, use NetWare SFT
v2.15c or greater.
- 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.
- 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.
- 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."
- 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).
- Load SHARE at your workstation if you are opening a local file with multiple position
blocks.
- 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.
- Using Btrieve transaction processing with American Megatrends CNT 286 BIOS v1.3
requires v5.10a or greater of Btrieve.
- 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.
- 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).
- 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).
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.
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.
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.
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 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.
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
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.
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.
|