MAY 1992 VOLUME 4 NUMBER 5
INDEX
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 commitment
on a daily basis. If you could only see the plans on my whiteboard....
Happy_Programming!
Mad Poarch
Director
Developer Support/Service
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 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:
- Client application calls API in DAP layer
- DAP API fills in the necessary fields in the DAP request buffer, then passes the data to an
API in the CP layer.
- 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.
- On the server side, IPX passes the incoming request to a buffer set aside by the CP NLM.
- 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.
- 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.
- 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.
- 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.
- 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
#include
#include
#include
#include "h/appl.h"
#include "dap/dapapi.h"
#include
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.
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:
[=]
In this entry, "" is the absolute pathname of the Btrieve file to be logged
without the drive letter (it must begin with a backslash (\) character). "" 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.
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.
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.
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.
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:
- OwnerID is invalid
- LastUpdatedID is invalid
- LastArchivedID is invalid
- 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.
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
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).
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).
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.
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.
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.
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.
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."
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.
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.
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.
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.
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 NDEVREL 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 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.
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
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, 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.
|