*********************************************
*********************************************
Professional Development Series
B  U  L  L  E  T  S
*********************************************
May 1992
Volume 4, Number 5
*********************************************
*********************************************


*********************************************
*********************************************
MAD'S COLUMN
*********************************************
*********************************************

Hello and welcome to the May 1992 issue of Bullets!

I hope that the information provided in "NLMs: From 'Hello
World' to World-Class Computing" over the last two months has
assisted you in writing your own NLMs and distributed
applications.

In talking with a wide variety of folks during the past two
months, I have discovered that developers and their managers
do not always agree about NLM development. In general, I have
found that current NLM developers:

*    feel that the present SDK has come a long way in a short
     time and contains highly useful, stable, well-documented
     and supported API sets.

*    believe that the NetWare v3.11 APIs and tools are good
     -and that those which will be included in the NetWare
     v3.2 SDK are "very good" to "screaming" (i.e.,
     "excellent").

On the other hand, many managers:

*    are not aware that Novell has developer APIs available
     or feel that NLMs are very difficult to understand and
     write.

*    feel that Novell is not committed to its developers and
     programs.

Whether these managers' opinions are the result of
misinformation or a simple lack of information, I do not know
I'll leave that for you to decide. I can say that Novell is
more committed to developers today than it was last year.
And, we are strengthening that committment on a daily basis.
If you could only see the plans on my whiteboard....

Happy_Programming!

Mad Poarch
Director
Developer Support/Service



*********************************************
*********************************************
ARTICLES:
NLMs: From "Hello World" to World-Class Computing
(Part II)
*********************************************
*********************************************

In the April 1992 issue of Bullets, "NLMs: From 'Hello World'
to World-Class Computing (Part I)" discussed the similarities
between building NetWare Loadable Modules (NLMs) and building
applications for other environments. The article examined the
APIs available in the NLM environment, and discussed issues
like thread synchronization and using NetWare APIs. Part I
also investigated the design and function of the
communication protocol (CP) layer of a distributed
application and examined the CP implementation in the
distributed application example, DAX, that is available on
NetWire (NOVLIB forum, LIB 1, DAXn.ZIP, where "n" is the
version).

This month, Part II will explore the three remaining software
components of a distributed application: the distributed
application protocol (DAP), and the client and server
portions of the distributed application. As before, this
article will include an in-depth discussion of how these
layers are implemented in the DAX example, and how you can
customize this example program for use in your own
distributed application. Regardless of the server or client
operating system platforms, the issues and techniques
discussed in this article can be applied to developing any
distributed application.


Distributed Application Protocol

The DAP layer implements the protocol used by the client and
server parts of a distributed application. In this case,
protocol is the structure of messages exchanged between the
two applications. Novell's NetWare Core Protocol (NCP) is one
example of a distributed application protocol. NCP is the
protocol NetWare clients use to communicate with a NetWare
file server. For example, when a DOS client application wants
to open a file on a NetWare volume, it issues DOS interrupt
21 function 3D. The NetWare shell, NETX.COM, intercepts the
request, builds an NCP request packet, and sends it to the
server. The request contains information such as the filename
that the application wants to open and the mode in which to
open the file. The server receives the NCP, opens the file,
and sends a reply packet back to the requesting workstation.
The reply packet contains a return code and, if the open was
successful, a file handle that the workstation uses on
subsequent requests to read or write the file.

Some messages exchanged between the client and server are
standard for almost any distributed application, while others
are unique to a specific application. Requests for allocating
and deallocating sessions with a server application will
appear in almost any distributed application. The remaining
messages are usually unique to a specific application.
Regardless of the message type, each message that the
distributed application supports is implemented essentially
the same way.

In the same way that the CP protocol layer hides the details
of a given communication protocol from the DAP, the DAP
conceals the details of the distributed application protocol
from the application itself. The client application uses
several APIs in the DAP layer to communicate with the server
application. This modular design allows you to replace the
the DAP Layer with minimum difficulty, simplifying the
creation of new distributed applications.


The DAX Implementation of DAP

Having discussed the DAP Layer in general terms, it is time
to examine how this layer is implemented in the DAX example.
Distributed applications handle the overall flow of a request
and reply in the following manner:

1.   Client application calls API in DAP layer

2.   DAP API fills in the necessary fields in the DAP request
buffer, then passes the data to an API in the CP layer.

3.   CP API fills in the necessary fields in the CP request
buffer, builds a protocol packet conforming to the underlying
communication protocol (in this case, IPX) then calls an API
in IPX to transmit the request.

4.   On the server side, IPX passes the incoming request to
a buffer set aside by the CP NLM.

5.   A thread in the CP NLM looks at the data in the CP
header, performs a few authentication details, then calls an
API in the DAP layer to queue the request. Note that only the
DAP related data is given to the DAP API, the CP header is
stripped off by the CP layer.

6.   A thread in the DAP NLM identifies the request type,
calls an API to service the request, then calls another API
to queue the reply.

7.   The sending thread in the DAP NLM unlinks the reply from
the send queue, then passes the data to an API in the CP
layer.

8.   The CP API fills in the necessary fields in the CP reply
buffer, builds a protocol packet, then calls an IPX API to
transmit the reply.
9.   The client CP layer receives the reply, strips the CP
header information, and passes the DAP data to the DAP layer.
The DAP layer extracts the results, and returns them to the
client application.

Part I of this article discussed the advantages of designing
a distributed application with four software layers:

*    Communication protocol
*    Distributed application protocol
*    Client application
*    Server application

This design enables you to maintain a very modular program.
In some situations, however, you may want embed the server
application within the DAP layer. When the server code for
each request is minimal, combining it with the DAP layer
simplifies the design and reduces the overhead involved with
synchronizing error conditions across multiple layers of a
software application. For example, when the CP layer detects
a failed session, it must clean up resources in use by that
session, and then notify the DAP layer to do the same. If the
server application is completely isolated from the DAP layer,
it must be notified to release resources being used by the
failed session too. Of course, similar logic must be in place
to handle clean up when an error is detected in the server
application. It must notify the DAP Layer, which must clean
up and then notify the CP Layer.

Most of the requests supported by the DAX example were
implemented with a single line of code. Because of this, it
was possible to embed the server application within the DAP
software layer. This design allows you to customize the
application to your specific needs quickly and painlessly.


DAX Source Directories

The DAX example comes with a number of source directories.
Take a moment to look at the layout of these source
directories:

*    DAP - Common source and headers
*    DAP/DAPE - Engine code & headers
*    DAP/DAPA - Client code & headers
*    DAP/DAPA/DOS - MakeFile for DOS client
*    DAP/DAPA/NLM - MakeFile for NLM client

The DAP directory contains header files and source files
common to both the client and server components of the
distributed application, including the source code for the
messages that the protocol supports and the error message
routine. In addition, the header file, CONFIG.H, is stored
here. this file defines constants that determine various
configuration defaults for this layer and contains seven
configuration parameters for the DAP layer.

The first configuration parameter, DAPMAXDATA, defines the
maximum packet size of any single packet within the DAP layer
(i.e., the maximum size of a message, be it reply or request)
that can be exchanged between the two applications.

The next three constants are specific to the server
application. INCDATAAREA identifies whether or not the server
application's data structure is defined inside the DAP
structure. In DAX, since the server application logic is
embedded in the DAP layer, INCDATAAREA is set to TRUE.
DEFMAXSESSIONS sets the default maximum number of clients the
server application can support. Finally, DAPSTATISTICS
defines whether the logic for enabling statistical
information will be included in the build. When DAPSTATISTICS
is set to TRUE, the DAP spawns a thread of execution that
continuously updates various statistical data on the main
screen of the server application.

The final three constants are used during the build of the
client software. DEFRETRYCOUNT specifies the number of times
the DAP layer should resend a request to the server
application before giving up. DEFRESPONSEDELAY stipulates how
many tenths of a second to wait between each resend of the
message. DEFSEQUENCENUMBER is the sequence number assigned to
the first packet exchanged between the client and server.

Also included in the DAP directory is the header file, DAP.H.
This file contains declarations and constants used by both
the client and server portions of the DAP layer. The first
items of interest in DAP.H are the protocol packet types
supported by the DAX example.

Two of these protocol packet types, DAPALLOCATESESSION and
DAPDEALLOCATESESSION, are used by nearly any distributed
application. When you customize this example for your own
application, these two protocol packet types will probably be
the only two you reuse. The remaining seven are specific to
DAX.

DAP.H also contains the packet layout structures for the DAP
layer. The type declarations are shown below:

..typedef struct {
....UINT32    packetType;
....UINT32    sequence;
....UINT32    sessionID;
....UINT32    timesTried;
....UINT32    requestCode;
....UINT8     data[DAPMAXDATA];
  }DAPRequest;

..typedef struct {
....UINT32    packetType;
....UINT32    sequence;
....UINT32    returnCode;
....UINT8     data[DAPMAXDATA];
....UINT32    dummy[2];
  }DAPReply;

The DAPRequest structure defines the layout of a request that
the client application sends to the server application.
DAPReply defines the layout of the data returned by the
server application in response to a DAPRequest.

"packetType" tells the DAP layer what type of message is
being transmitted. Future versions of DAX supporting
broadcasting and bidirectional messaging will use this field
to identify what type of message has been received.

"sequence" contains the sequence number of a given request.
This value is set by the client when a request is made of the
server. The server copies the sequence number from the
request packet over to the reply packet. The client
(application) uses this value to ensure that the reply
received was in response to the request generated.

The "sessionID" is assigned by the DAP layer on the server
side when the client performs an "allocate session" request.
For the "allocate session" request, this value should be
zero.

"timesTried" informs the server side when it has been
necessary to resend a request and is used for statistical
purposes only.

"requestCode" is the protocol packet number (i.e.
DAPALLOCATESESSION).

"data" contains the information necessary for a given
protocol packet, and is usually unique for each protocol
packet type. Of course, each protocol packet has one format
for the "data" on the request, and another for the reply.

"returnCode" is the return code of the protocol request and
is only valid if the request is processed by the server.

Finally, the DAP.H header file contains the structure layouts
for a structure called DAPDATA, used on both the client and
server side to track a given session in the DAP layer. These
structures are not transmitted across the network; they are
used locally to maintain the session. On the client side, the
DAPInitialize API returns a pointer to one of these
structures whenever a session is established. All subsequent
calls to the DAP layer use this pointer as a parameter. This
design allows you to use these APIs in a multithreaded
environment, such as the NLM implementation of the client
application. The client application does not modify this
structure; in fact, it knows nothing about the contents of
the structure. Only the APIs in the DAP layer of the client
software can "see" the elements of this structure.

Figure 1 shows the layout of the client DAPDATA structure.
Items of interest in the client DAPDATA structure include
"CPid," the handle returned by the CP layer when a session is
established with the server. "CPid" is passed on subsequent
calls to the CP layer, much like the DAPDATA structure
pointer is passed into the DAP layer. In addition, the DAP
layer knows nothing about the "CPid" variable, it just passes
it to the APIs in the CP layer. (See Part I of this article
for a discussion of this structure). Finally, both a
DAPRequest and DAPReply structure are declared within the
client's DAPDATA structure.

*********************************************
Figure 1: Layout of the Client DAPDATA Structure

typedef struct  {
        void    *CPid;         // data for CP layer
        UINT32  sessionID;     // ID between client &
                                  server DAP Layer
        UINT16  retryCount;    // retry count for session
        UINT16  responseDelay; // units to wait for a reply
        UINT16  timesTried;    // #times sent duplicate msg
        UINT16  sendFailed;    // #times actual send failed
        char    serverName[48];
        UINT32  nextSequence;  // next sequence # to use
        DAPRequest  dapRequest;
        DAPReply    dapReply;
}DAPDATA;

End of Figure 1
*********************************************

The server DAPDATA structure is different from that of the
client. Figure 2 shows the layout of the server application's
DAPDATA structure. The linked list pointers "next" and "prev"
are used to queue up requests. When the client sends in a
request, the DAP layer queues this structure to a linked list
for processing by a separate thread. These pointers are also
used for queueing up this structure for an outgoing message.
"CPid" is obtained from the CP layer when a new session is
established between the client and server. The DAP layer uses
this ID when sending replies to the client. "DAPState" is
used to provide state information for this client. It is used
to control the flow of the structure between the multiple
threads of execution. Once again, memory for both a
DAPRequest and DAPReply structure is reserved here, providing
temporary storage for incoming and outgoing requests.

*********************************************
Figure 2: Layout of the Server DAPDATA Structure

typedef struct  _dd{
        struct _dd  *prev;    // pointer to previous link
        struct _dd  *next;    // pointer to next one in link
        UINT32      CPid;     // client ID for CP layer
        UINT32      DAPState;
        UINT32      DAPFlags;
        DAPRequest  dapRequest;
        DAPReply    dapReply;
    #if INCDATAAREA
        struct{
        SINT32      lastResult;
        SINT32      mailBox001;
        }applData;
    #else
        void        *applData;
    #endif
}DAPDATA;

End of Figure 2
*********************************************


Server implementation

The server implementation of the DAP layer is depicted in
Figure 3. Incoming messages are given to the DAP layer using
an API defined by the DAP layer during initialization.
Requests are queued via DAPEnqueueRequest, processed by the
DAPServiceRequestQueue thread of execution, and then queued
for sending back to the client by DAPServiceReplyQueue. The
server application itself is implemented within the Request
1 through Request n functions.

*********************************************
Figure 3: Server implementation of the DAP layer
 __________              __________         _________
| Service  |  Requests  |          |       | From    |
| Request  |<-----------| Enqueue  |<------| CP      |
| Queue    |            | Request  |       | Layer   |
|__________|            |__________|       |_________|
        |
      __V_________ ____________ _______________
     |            |            |               |
 ____V_____   _____V____   _____V____       ____V_____
|          | | De-      | |          |     |          |
| Allocate | | Allocate | | Request  | *** | Request  |
| Session  | | Session  | |    1     |     |    n     |
|__________| |__________| |__________|     |__________|
     |            |            |               |
     V____________V____________V_______________V
        |
 _______V__              __________         _________
|          |  Replies   | Service  |       | To      |
| Enqueue  |----------->| Reply    |------>| CP      |
| Reply    |            | Queue    |       | Layer   |
|__________|            |__________|       |_________|

End of Figure 3
*********************************************


The Client Application

Having implemented the underlying CP layer, DAP layer, and
server application, a client application is all that is
required to complete the distributed application. When you
browse the code provided for the client applications that
come with DAX, you will immediately see that the details of
communicating with the server application are entirely hidden
from the client application. Once the CP and DAP layers are
written, you can use  and reuse them with only slight
modifications.

This article includes a final example of the minimum
requirements for a client application. The example program,
named ADD, is displayed in Figure 4.

*********************************************
Figure 4: Example program ADD

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include "h/appl.h"
#include "dap/dapapi.h"

#include <nxt.h>

static  DAPDATA *dd;

atexitproc()
{
   if( dd ){
      DAPDeAllocateSession(dd);
      DAPDeInitialize(dd);
   }
}

main(int argc, char *argv[])
{
   int     rc;
   long    x,y,z;

   if( argc == 3 ){
      x = atol(argv[1]);
      y = atol(argv[2]);
   }
   else{
      printf("usage: ADD op1 op2\n");
      exit(1);
   }
   atexit(atexitproc);
   if( (dd = DAPInitialize(SERVERNAME,
                           SERVERTYPE)) == NULL ){
      printf("Could not initialize DAP\n");
      exit(1);
   }
   printf("Initialized okay...\n");
   if( (rc = DAPAllocateSession(dd)) != NULL ){
      printf("Allocate Session failed '%s'",
      DAPTranslateReturnCode(rc));
   }
   printf("Attached to server '%s'\n",SERVERNAME);
   if( (rc = DAPAddOperands(dd,x,y,&z)) != NULL ){
      if( DAP_CRITICAL_ERROR(rc) ){
          printf("\n\n\t%s. rc = %d\n",
                 DAPTranslateReturnCode(rc),rc);
          DAPDisplaySessionData(dd);
          exit(1);
      }
      else{
          printf("\n%s\n", DAPTranslateReturnCode(rc));
      }
   }
   printf("%ld + %ld = %ld\n",x,y,z);
   if( (rc = DAPDeAllocateSession(dd)) != NULL ){
      printf("\n\n\t%s. rc = %d\n",
             DAPTranslateReturnCode(rc),rc);
   }
   DAPDeInitialize(dd);
   dd = NULL;
   return 0;
}

End of Figure 4
*********************************************

ADD takes two arguments for an addition operation, attaches
to the application server, sends a request, and prints the
results. This application uses only five DAP API calls:

*    DAPInitialize()
*    DAPAllocateSession()
*    DAPAddOperands()
*    DAPDeAllocateSession()
*    DAPDeInitialize()

The first two and last two APIs will be present in any client
application which utilizes the services provided by the DAX
server application. The function of each specific client
application will determine which other APIs you must
incorporate. As shown in Figure 4, the example client
application makes no API calls to the CP layer. The client
application is not aware of how its requests are communicated
to the server application and there is no need for it to
know.

Using the DAX example program as a prototype or point of
departure, you should be able to create your own distributed
applications. The NetWare 3.x environment offers a full set
of APIs for application programmers: an ANSI-compliant
runtime library, an execution thread API, synchronization
APIs, POSIX APIs, NetWare APIs, and other platform specific
APIs. For more information on the Network C for NLMs software
developer's kit, contact Novell's Professional Developers'
Program at 1-800-RED-WORD (1-800-733-9673), or
1-512-794-1796.

*********************************************
ADDITIONAL READING

NetWare Application Notes - March 1992,
   "LookUp: Implementing a Multiplatform, Multiprotocol
    Application."

Bullets, August 1991, "Network ComputingThe New Phase"
Bullets, January 1991, "Programming with CLib:
                        Graceful Exits"
Bullets, July 1990,   "The Big Picture"
*********************************************



*********************************************
*********************************************
TECHNICAL INSIGHTS:
Using BROLLFWD with Btrieve for DOS
(Btrieve for DOS v5.10)
*********************************************
*********************************************

The Btrieve for DOS Installation and Operation Manual
discusses how to log Btrieve files to another volume on the
server. However, it does not describe how to log a Btrieve
file to another physical hard drive or mapped drive.

To log a Btrieve file to another physical drive, make an
entry in the BLOG.CFG file in the following format:

  <Btrieve filename> [=<logname>]

In this entry, "<Btrieve filename>" is the absolute pathname
of the Btrieve file to be logged without the drive letter (it
must begin with a backslash (\) character). "<logname>" is
the absolute pathname to the associated log file including
the drive letter.

For example, if a Btrieve file called TEST.BTR resides on the
server in the F:\DATA directory and the log file is located
on a local hard drive (Drive C:\BTR\LOG\TEST.LOG), the entry
in the BLOG.CFG file should be:

\DATA\TEST.BTR =C:\BTRIEVE\LOG\TEST.LOG

This information applies to Btrieve for DOS only. With
NetWare Btrieve, do not specify a drive letter for either the
Btrieve filename or the logfile.



*********************************************
*********************************************
TECHNICAL INSIGHTS:
Borland C++ & Btrieve
(Btrieve for Windows v5.10)
*********************************************
*********************************************

Name Mangling is an attribute of the Borland C++ compiler
which allows multiple definitions of functions within an
application. Name mangling is documented in Chapter One of
the Borland C++ Programmer's Guide, v2.0.

This attribute is not compatible with the WBTRINTF.C file
supplied with Btrieve for Windows v5.10. When you link a
program, unresolved externals can appear and the linker may
return "unresolved external btrv()" errors. The linker will
also return all functions defined in the C file in lower case
(Btrieve for Windows prototypes and functions do not contain
a lower case "btrv()"). This situation occurs because the C
file is compiled as a C++ file and consequently the compiler
applies name mangling to the BTRV function and every other
function defined.

To disable the name mangling attribute, set a compiler
directive to treat functions as regular C functions if files
are being compiled as C++ files by default. The directive is:

  #ifdef __cplusplus
  extern "C" {
  endif

  #ifdef __cplusplus
  }
  endif

With this directive in place, functions between the two
statements will be treated as standard C functions and name
mangling will not be performed. Function prototypes can be
defined in a series of include files which can be placed
between the compiler directives. For example, WBTRV.H could
be included between the directives and then the function BTRV
would not be mangled by the compiler. There are many ways to
implement this directive, but the compiler will mangle
function definitions if you do not use some implementation.



*********************************************
*********************************************
TECHNICAL INSIGHTS:
VIPX.386 & IPXSendPacket
(NetWare System Calls for DOS v1.0)
*********************************************
*********************************************

When using IPX via the NetWare System Calls for DOS in a
Windows DOS box, VIPX.386 v1.11 does not update the AL
register when ECBs are successfully posted with
IPXSendPacket(). Instead, VIPX.386 updates the AL register
when errors occur. If the AL register is not cleared before
making the IPXSendPacket call, garbage in this register may
be interpreted as an error condition. To avoid this
situation, clear the AL register before making the
IPXSendPacket call.



*********************************************
*********************************************
TECHNICAL INSIGHTS:
Preferred ConnectionID in Windows Applications
(NetWare C for Windows v1.22)
*********************************************
*********************************************

Under Windows, a workstation's preferred ConnectionID
variable can be reset to zero even though the application has
previously called SetPreferredConnectionID() and set it to a
ConnectionID other than zero. When an application calls
SetPreferredConnectionID() and then waits before sending a
request to the server, other Windows applications can change
the PreferredConnectionID in the interim. To avoid this
situation, call SetPreferredConnectionID() before each
request to the server.



*********************************************
*********************************************
TECHNICAL INSIGHTS:
Network C for NLMs Documentation Updates
(Network C for NLMs v2.0b)
*********************************************
*********************************************

ChangeDirectoryEntry()

The ChangeDirectoryEntry API returns an error code 1 if any
of the following conditions occur:

1. OwnerID is invalid
2. LastUpdatedID is invalid
3. LastArchivedID is invalid
4. maximumSpace is invalid, i.e. less than -1 or equal to
0x7FFFFFFF

The Network C for NLMs documentation will be updated to
include this information in the next revision.


FEGetOriginatingNameSpace()

The documentation for the CLib API FEGetOriginatingNameSpace
does not describe the return values of the different name
spaces. The function returns:

0 for DOS
1 for Macintosh
2 for NFS
3 for FTAM
4 for OS/2

These values are mentioned in the documentation for the
GetNameSpaceName() function.



*********************************************
*********************************************
TECHNICAL INSIGHTS:
Converting Decimals to Binary Strings
(Btrieve (all versions))
*********************************************
*********************************************

When developing Btrieve applications in Microsoft BASIC, you
may need to perform BIT manipulations occasionally. For
example, you might need to extract file information from the
return data buffer on a Btrieve STAT operation.

The BASIC code segment shown in Figure 5 demonstrates how to
build a string of binary information from a decimal number.
You can then parse this string to extract the appropriate bit
information.

*********************************************
Figure 5: Converting decimal no. to string of binary info

Bin$=""                            'Initialize the string

  INPUT"Decimal number = ";Decimal 'obtain the decimal number

 FOR i = 14 TO 0 STEP -1           'Positive numbers only
   pow2 = 2^i
   IF Decimal >= pow2 THEN
      Decimal = Decimal - pow2
      Bin$ = Bin$ + "1"
   ELSE
      Bin$ = Bin$ + "0"
   END IF
NEXT i
PRINT"Binary String = ";Bin$

End of Figure 5
*********************************************



*********************************************
*********************************************
TECHNICAL INSIGHTS:
New Patches for HLLAPI v2.2.f.11
(3270 Tools for DOS v1.5)
*********************************************
*********************************************

A new HLLAPI patch file, HLLAPI.ZIP, fixes the following
problems:

*    The Pause function was calculating wait time
     inaccurately.
*    The Find Field Length function returned a invalid field
     length for row 24 of the presentation space (PS).
*    The Find Field Position returned an invalid field
     position for offset 1.

HLLAPI.ZIP can be downloaded from Novell's CompuServe forum,
NetWire (NOVLIB forum, LIB 9).



*********************************************
*********************************************
TECHNICAL INSIGHTS:
Sessions and NetWare SQL v3.0
(NetWare SQL v3.0)
*********************************************
*********************************************

NetWare SQL 3.0 is priced and sold by number of available
sessions. Novell will offer 250-, 100-, 50-, 20-, 10-, and
5-session versions. This system is similar to the NetWare
stratification but there is one major difference: NetWare is
user-count stratified and NetWare SQL v3.0 is session-count
stratified.

With 250-user NetWare, 250 workstations can be logged into
the system simultaneously. There are 250 connections
available on the server. Consequently, Windows and OS/2
workstations can run multiple NetWare applications from a
single workstation, and each application only counts as a
single connection.

With NetWare SQL v3.0, session-count does not necessarily
equate to NetWare user-count. With 250-session NetWare SQL,
it is possible to use all 250 sessions without having 250
workstations logged into NetWare. In Windows and OS/2, every
application that makes a connection to NetWare SQL is
considered a session. So, if there were 10 Windows NetWare
SQL applications running on 25 Windows workstations, all
available NetWare SQL sessions would be used, even though
there would be only 25 NetWare connections.

The Btrieve NLM v6.x (included with NetWare SQL v3.0) is also
session-count stratified, although the limit is based on the
sessions parameter configured in the setup utility (maximum
= 250 sessions).



*********************************************
*********************************************
TECHNICAL INSIGHTS:
Running Brequest in an OS/2 DOS Box
(NetWare Btrieve (NLM) v5.1x)
*********************************************
*********************************************

BREQUEST.EXE will not run in an OS/2 DOS box on OS/2 v1.3
because of incompatibilities between the SPX APIs in the DOS
box and OS/2. If you run DOSBOX.EXE with BREQUEST.EXE, the
error "IPXOpenSocket Failed" will be returned. This problem
cannot be corrected in v1.3 of the NetWare OS/2 requester.



*********************************************
*********************************************
TECHNICAL INSIGHTS:
New API in CLib PATCH311
(Network C for NLMs V2.0b)
*********************************************
*********************************************

PATCH311 includes a new CLib API called
SpxListenForConnectedPacket. This API allows you to post an
ECB on a specific SPX session. The prototype is:

int SpxListenForConnectedPacket(
        unsigned short socket,
        SPX_ECB *ECBp,
        unsigned short connection);

where "socket" is the open socket (0 if specified in ECB),
"ECBp" is a pointer to the listen ECB and "connection" is the
SPX connection number assigned when the connection was
established. You should also add this API to your import
symbol list, or add it to the CLIB.IMP file.



*********************************************
*********************************************
TECHNICAL INSIGHTS:
SetCapturePrintQueue() System Call
(NetWare System Calls for DOS v1.0)
*********************************************
*********************************************

The documentation of SetCapturePrintQueue(), B8h (06h),
instructs you to pass the first(low) word of the Queue ID in
the BX register and the second (high) word in the CX
register.

However, if these are reversed and the high word is passed in
BX and the low word is passed in CX, the function returns
successfully but it does not work; no error codes will be
returned, the target print queue will not be set, and
capturing will fail.



*********************************************
*********************************************
TECHNICAL INSIGHTS:
Btrieve for Windows Load Parameters
(Btrieve for Windows v5.10)
*********************************************
*********************************************

With the local requester, WBTRCALL.DLL, every Windows session
can specify different Btrieve load parameters if each
application calls the WBTRVINIT function. This call allows
you to pass a string containing the Btrieve load parameters,
and should be the first Btrieve call made by your
application.

If you do not use the WBTRVINIT call, then the load
parameters specified in the "[btrieve]" section of WIN.INI
will be used. If there is no "[btrieve]" section in WIN.INI,
the local requester is loaded with default parameter values.

When you use WBTRCALL.DLL, the Btrieve load parameters are
essentially "global" since they can only be specified in the
"[brequestDPMI]" section of the WIN.INI file. The
WBRQSHELLINIT call is not currently implemented to initialize
the WBTRCALL.DLL requester from within an application.



*********************************************
*********************************************
TECHNICAL INSIGHTS:
NetWare Lite & ODI Cards Correction
(NetWare Lite v1.0)
*********************************************
*********************************************

In the April 1992 issue of Bullets, "NetWare Lite & ODI
Approved Cards" (Technical Insights) incorrectly stated that,
"A network card driver suitable for other NetWare networks
will not work with NetWare Lite unless it is an ODI version
of the driver." In fact, NetWare Lite will work with both ODI
and IPX-based LAN drivers. If you choose to use ODI, you
should contact the card manufacturer to see if an ODI driver
is available for the card. If not, you must install another
network card which has an ODI driver."



*********************************************
*********************************************
TECHNICAL INSIGHTS:
Determining if NASI is Loaded
(NASI v3.0)
*********************************************
*********************************************

To determine whether or not the NetWare Asychronous Services
Interface (NASI.EXE) TSR is loaded, follow the procedure
listed below.

*    Since NASI uses interrupt 6Bh, view the contents of the
     two words at offset 1ACh.
*    Go to the segment and offset plus three bytes
     (SEG:OFFSET+3) listed in the two-word entry.
*    Compare the value of the next four bytes with the value,
     NCSI.
*    If the values match, NASI is  loaded.



*********************************************
*********************************************
TECHNICAL INSIGHTS:
Function Incorrectly Sets "errno"
(Network C for NLMs v2.0b)
*********************************************
*********************************************

When you attempt to create a directory that already exists,
the mkdir function correctly returns an error [-1] but
incorrectly sets "errno" to ENOENT (1-No such file or
directory). It should actually be set to EACCES (6-Permission
Denied). There is currently no workaround for this situation.



*********************************************
*********************************************
TECHNICAL INSIGHTS:
Register Passing with Microsoft C v6.0
(NetWare C Interface for DOS v1.2)
*********************************************
*********************************************

Microsoft C v6.0 contains a new command line parameter, /Gr,
which specifies that functions will pass parameters in
registers. If you use this parameter, none of the NetWare C
Interface for DOS functions will be resolved at link time.
Microsoft does not export these symbols with an underscore
before the function name when you use register-passing.

To resolve these functions at link time, you must perform the
following two steps:

*    Include stddef.h before nit.h.
*    Add the "cdecl pragma" before each of the NetWare C
     Interface for DOS functions that you are going to use.

These steps will ensure that symbols are exported with the
underscore before the function name and the parameters will
be pushed on the stack.



*********************************************
*********************************************
TECHNICAL INSIGHTS:
Calling CLib Functions from an AES Process
(Network C for NLMs v2.0b)
*********************************************
*********************************************

Before an AES process calls a CLib function, the
ThreadGroupID must be set to the ThreadGroupID of any CLib
NLM; the most obvious choice is the NLM which scheduled the
AES process. The ThreadGroupID can be added as an element of
the AES structure that is passed to the AES function.

The AES function should set the ThreadGroupID (saving the
current ThreadGroupID), make the CLib calls, then before
exiting the AES process, set the ThreadGroupID to the value
when the process was invoked. This information applies to
both SLEEP and NO SLEEP AES processes. However, with NO SLEEP
AES processes, there is one additional restriction: the AES
process may not call any CLib blocking functions.



*********************************************
*********************************************
NIBBLES & BITS
Fast answers to common questions
*********************************************
*********************************************


Network C for NLMs

TIP  In the March 1992 issue of Bullets, "Nibbles & Bits"
     incorrectly stated  that, at high speeds, "the COMX
     driver does not guarantee that all characters will be
     received, because it disables interrupts for too long."
     In fact, it is the LAN and disk drivers (not the COM
     driver) which disable interrupts for too long. Bullets
     was, however, correct to suggest using a driver like the
     ARTIC driver and the WNIM driver because they have their
     own CPU on board and, for that reason, are more reliable
     at high speeds.

Q:   Where can I find PATCH311.NLM ?

A:   You can download PATCH311.NLM from NetWire (NOVLIB, LIB
     4, PAT311.ZIP). This file is also available in the
     NOVDEV forum (LIB 7, filename: PCL311.ZIP). This file
     contains the debugging information as well a DOC file
     that lists each included patch.

Q:   If I use a ScheduleSleepAESProcessEvent and call
     localtime(), when I unload my NLM, I get a resource
     warning that I have not freed 104 bytes (or a multiple
     of 104 bytes) of short term memory. What should I do?

A:   Running localtime() in this context allocates memory
     that the NLM cannot free because the localtime structure
     pointer is saved as part of the AES thread, rather than
     one of your NLM's threads. CLib cannot detect the
     allocated memory and therefore does not free it. For the
     same reason, you should not call asctime(), ctime(),
     gmtime(), strtok(), rand(), and srand() in an AES
     thread.


Xtrieve PLUS

Q:   How can I configure Xtrieve PLUS v4.10 so that it does
     not use the new printer support, but instead works like
     Xtrieve PLUS v4.01a?

A:   In the Configure menu, choose the "Switches" option.
     Then set the "Printers" option to "NO." If you wish, you
     can save this configuration to make it effective every
     time you load Xtrieve PLUS v4.10.

Q:   How can I print an Xtrieve PLUS v4.10 report with
     different size letters and different fonts on a Hewlett
     Packard LaserJet printer?

A:   If you set Configure/Switches /Printers to "NO," you can
     add a new entry under Configure/Print /Attributes. There
     will be three columns: attribute name, start sequence,
     and stop sequence. Refer to the HP LaserJet Printer
     Manual, and type the escape sequences for the fonts and
     sizes you wish to use. Before printing the report,
     remember to select all desired attributes from the
     Report/Attributes menu.


Btrieve

Q:   When I program with Btrieve, why does Btrieve return a
     status 22 if I perform a Stat operation, even though I
     have allocated the maximum number of key spec buffers
     (24)?

A:   Your file may be using an alternate collating sequence,
     which requires you to allocate an additional 265 bytes
     in the data buffer that you send to the Stat operation.
     Nine bytes are for the name of the alternate collating
     sequence and 256 are for the actual sequence.

Q:   When I perform a Get Next Extended operation, Btrieve
     returns a status 62. What does this mean?

A:   Status 62 often indicates an error in one of the values
     in the descriptor or extractor (i.e. your data buffer).
     To check for this error, make sure the first two bytes
     of the data buffer contain the exact length of the data
     buffer you are sending to the Get Next Extended
     operation. The Data Buffer Length parameter in the call
     to Btrieve does not have to be the exact length of the
     data buffer, but if it is longer , any variable defined
     after the data buffer will be overwritten.


NetWare for SAA

Q:   Can UNIX or OS/2 clients access an IBM host via Netware
     for SAA?

A:   Yes. The latest release, Netware for SAA v1.2, includes
     support for UNIX and OS/2 clients through third-party
     software. CLEO Communications has announced a version of
     3270LINKIX software that works with Netware for SAA and
     provides 3270 terminal emulation for UNIX clients. Wall
     Data's RumbaPM client software now takes full advantage
     of NetWare for SAA to provide OS/2 users with IBM host
     connectivity.


VIPX.386

TIP  To determine if VIPX.386, the NetWare driver for
     Windows, is loaded into memory, issue an INTF2 call with
     the value 1684h in the AX register and 0200h in the BX
     register. The function name is WindGetDeviceApiPoint().
     If the return code in ES:DI register is 0, VIPX.386 is
     not loaded. Otherwise, VIPX.386 is loaded.


NetWare C Interface for Windows

TIP  If you are using the NetWare C Interface for Windows SDK
     v1.22, and need to have full compatibility with Windows
     3.1, use the current version, v1.30. You can obtain the
     upgrade to v1.3 by calling 1-800-RED-WORD.



*********************************************
*********************************************
NOVELL EDUCATION
*********************************************
*********************************************

Novell Education offers classes for many of the Database &
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 NetWare
services. Nearly 50% of class time is devoted to hands-on
activities.

901 - Programming with NetWare Client APIs

     June 10-12          Sunnyvale, CA
     Aug. 12-14          Washington, DC

905 - Programming with Btrieve

     Aug. 12-14          Sunnyvale, CA

906 - Programming with Btrieve: Advanced Features

     June 16-18          Austin, TX

907 - Xtrieve PLUS

     July 14-15          Dallas, TX

910 - Programming with XQL

     June 9-11      Austin, TX

920 - Programming with Network     Communication Services

     June 15-16          Sunnyvale, CA
     Aug. 17-18          Washington, DC

930 - Developing NetWare Loadable Modules (NLMs)

     July 15-17          Washington, DC

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-429-5508. 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 the end of this section for
answers.)

1.   With Novell's Network C for NLMs SDK, how do you set the
     break-point when you get a message on the console saying
     "Module did not release [X] resources" and "Resource :
     Small Memory Allocations" while unloading your NLM?

     A.   'b=malloc-4b+[dmalloc-7]'
     B.   'b=malloc-3d+[dmalloc-5]'
     C.   'b=malloc-4d+[dmalloc-9]'

2.   With the LAN WorkPlace Toolkit for DOS v4.01, what is
     the link interface driver which, instead of interpreting
     received packets, simply copies identification
     information from the packet into a receive ECB and
     passes the ECB to the link support layer (LSL)?

     A.   NLID (Novell Link Interface Driver)
     B.   MLID (Multiple Link Interface Driver)

3.   OS/2 workstations can boot from NetWare server using
     what program?

     A.   RIPL (Remote Initial Program Load)
     B.   OS2RPL (OS/2 Remote Program Load)
     C.   OS2INIT (OS/2 Initialize)

4.   NetWare NFS is implemented as a family of different
     remote procedure calls. How many different calls are
     there?

     A.   23
     B.   18
     C.   15
     D.   14

5.   In NetWare C Interface for Windows, what function
     releases the resources allocated by NWIPXSPX.DLL?

     A.   IPXDeinit()
     B.   SPXDeinit()
     C.   IPXSPXDeinit()
     D.   IPXDeinitialize()

6.   What status code does Btrieve return when you attempt to
     perform an INVALID OPERATION?

     A.   62
     B.   48
     C.   27
     D.   1

7.   What Btrieve operation is valid in the v5.10 DOS and VAP
     versions, but not the NLM version?

     A.   Reset (28)
     B.   Extend (16)
     C.   Insert Extended (40)

8.   What is the pre-defined function key in Xtrieve PLUS to
     display the Help screen?

     A.   F1
     B.   F2
     C.   F7
     D.   F10

9.   In Xtrieve PLUS, what is the maximum length of a user
     password?

     A.   8
     B.   12
     C.   14

10.  What BROLLFWD command line option is used for automatic
     recovery of all files on a volume?

     A.   /v
     B.   /r
     C.   /a

*********************************************
FUN & FACTS ANSWERS
1.   C
2.   B
3.   A
4.   B
5.   C
6.   D
7.   B
8.   A
9.   A
10.  C
*********************************************



*********************************************
*********************************************
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                             n/a
     NetWare NNS                             n/a

Communication Toolkits

     LAN WorkPlace Toolkit for DOS           4.01

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                    2.0
     NetWare C Interface for Windows         1.22
     NetWare C Interface for Macintosh       1.3
     NetWare Network Management Toolkit      1.0
     LAN WorkPlace Toolkit for OS/2          2.0
     Network C for NLMs                      2.0 c
     NetWare TIRPC for DOS and NLMs          1.0
     NetWare AppleTalk Interface for NLMs    1.0
     NetWare for SAA LU6.2 Tools             1.2
     NetWare 3270 Tools                      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



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

Novell Database and 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.

For more information on Novell's Professional Developers'
Program, Novell Development 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.



*********************************************
*********************************************
ACKNOWLEDGEMENTS
*********************************************
*********************************************

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

Contributing authors:
          Linda Anderson
          Michael Eisa
          David Harris
          Laura Heater
          Sudz Khawaja
          Ken Lowrie
          Rudy McNeese
          Clint McVey
          Chris Ojeda
          Paige Parker
          Bill Prentice
          Randy Reddy
          Mike Shoemaker
          John E. Stewart
          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.

(c) 1992 Novell, Inc. All rights reserved.

*********************************************
Novell, the N design, 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,
NetWare LU6.2, Report Executive, and Professional Development
Series (PDS) are trademarks, and 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.
*********************************************

Developer Support/Direct Connect:
1-800-NETWARE (1-800-638-9273)
Tel. (801) 429-5588
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
China Resources Bldg.
Room 4601-5, 46th Floor
26 Harbour Rd.
Wanchai, Hong Kong
Tel.  852 8272223
FAX   852 8276555

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

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
Paseo Castellana, 40 bis
28046 Madrid
Spain
Tel.  34 (1) 577-4941
FAX   34 (1) 577-9053

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

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

*********************************************
Professional Development Series
B  U  L  L  E  T  S
MAY 1992
END OF FILE
*********************************************

