JULY 1993 VOLUME 5 NUMBER 7
INDEX
Hello and welcome to the July 1993 issue of Bullets!
Last March when I was discussing "March Madness," we left off with a word from our sponsor.
The NBA finals were nearing, the Indy-500 was pending and baseball's All-Star game was way
in the future.
Now, four months later, it was North Carolina over Michigan, the Bulls over the Suns, and Ricky
Mears and the American League came up winners. Time flies.
Now it's time for the 1993 Olympic Festival to begin. Each non-Olympic year, a different
US city hosts this showcase for American athletes. Over 4,200 participants, 12,000 volunteers
and 1,000 journalists at 22 different geographic locations will combine efforts in going for the
gold.
The July 23rd - August 1st activities in San Antonio will not only showcase human athletic
skills and robustness but those of NetWare's SFT III as well. Each host city has the responsibility
for designing and implementing its own technological solution. This is the first festival where
PC- based hardware and software will provide the entire computing solution!
Novell is proud to be a contributor to the Olympic Festival and we hope we win "our gold
medal" as well, and maintain our championship status. In each event, I'd like to congratulate all
of the athletes in advance. Who knows--their second career may be writing NetWare programs.
Happy_Programming!
Mad Poarch
Director
Developer Support/Service
Writing a Network Resource Manager with the MacIPX SDK
Novell's MacIPX Software Developers Kit v1.0.1 is a quantum leap toward providing full
Macintosh integration into NetWare. In addition to making the IPX/SPX transport protocol
available to the Mac, the MacIPX SDK includes a well- documented set of APIs that allows you
to access this protocol when developing cross-platform NetWare client applications.
The Macintosh is a logical target for a utility like the Network Resource Manager, since it
offers an intuitive user interface and efficient multiprocessing. The Resource Manager allows a
network administrator to manage workstation configuration throughout the network. This article
examines using NetWare Diagnostic Services and the MacIPX SDK to create a Network
Resource Manager for the Macintosh.
NetWare Diagnostic Services are built into the device drivers that support the IPX/SPX
transport protocol. Examples of diagnostic functionality include the ability to identify all
internetwork nodes and their software components, to query these nodes for statistical
information, and to perform point-to-point tests such as timing studies. Diagnostic APIs, which
automatically perform the packet formation and data retrieval for these services, are included
with the NetWare Client SDK and the NetWare C Interface products for DOS, Windows and
OS/2. To use these services in a similar manner on the Mac, the first step is to create a set of
Diagnostic APIs using the MacIPX SDK.
The Mac Diagnostics make use of both the IPX and SPX support provided in the MacIPX
SDK. The IPX-based APIs are used to query the network for nodes (responders) or target a
particular node and request that it listen for an SPX connection. The SPX-based APIs are used to
establish and maintain a diagnostic connection with a particular responder and query its
componentry. MacIPX also includes a set of SAP (Service Advertising Protocol) APIs, but they
are not used here.
Resource Manager Design
The design of the Network Resource Manager application centers on the type of
information that is available from the diagnostic services. The design is expandable to
incorporate additional responder data as well. The Manager takes advantage of the intuitive
interface and aesthetic presentation built into the Macintosh operating system. It is menu driven;
it allows the user to acquire information on an ad hoc basis, rather than search through reams of
undesired data. In addition, the Manager presents its information in dialog boxes with controls
that allow the user to zoom in on a particular node or component.
The Manager's design allows administrators to spontaneously query the network for
information from respondent nodes through the use of the Target Broadcast menu option. Given
the list of responders, you can then select a particular node (using the Target Node menu option,
or by selecting it from the responders list) and continue to query it for the information he seeks.
Target Node establishes a diagnostic session with the specific respondent. Subsequent selections
from the Diagnostics menu address that particular responder until another Target is chosen or the
application is terminated.
Available Information from NetWare Diagnostic Services
The NetWare Diagnostic APIs can be divided into five categories:
- IPX/SPX Component Functions
- Driver Component Functions
- Shell Component Functions
- Bridge Component Functions
- Environment Support
IPX/SPX Component Functions return version, statistical and timing information for any
target node. Statistical information includes success/failure counts in requests and transmissions.
Diagnostics can determine transmission efficiency with the timing and packet count functions.
The Driver Component Functions retrieve the configuration and statistics for the shell or
bridge drivers. Another API returns the bridge driver status. Shell and Bridge Component
functions deliver specific information about the component software, including tables and
addresses. Diagnostic's environment support determines available components at a node, either
through specific targeting or broadcasting a configuration request.
Target Machines
There are currently two ways to determine the node to address with the Network Resource
Manager: either through direct entry of the node's full IPX address (network:node) or by
selecting the address from a list of respondents to the target broadcast. Use of the 10-byte
hexadecimal address is an "unMac-like way" to identify a network object. You can use an
alternate method, however, since there are several ways to handle identity on the Macintosh
platform.
Converts from other platforms might expect a discussion on the use of the NetWare Bindery
at this point, since it is a straightforward way to obtain names and other connection information
about network objects. A Bindery lookup by object type equal to OT_USER returns a list of
valid user names. You could then query the file server for connection information about the user
object to target a workstation by address. Unfortunately, full support for the Bindery APIs isn't
available with MacIPX. While the SDK does include a bindery lookup API,
MacIPXScanBinderyObject() establishes a temporary connection to the server and does not
match its security to the requesting workstation. This temporary connection has attached security
and cannot look up user objects.
Other devices on the network available to the Mac workstation can query the Bindery for
user information. The "Future Enhancements" section of this article explains the solution that a
future version of the Resource Manager will use. Presently, the operator must know the IPX
address of the targets, possibly through the use of the "USERLIST /a" utility. The Resource
Manager uses this address in its call BeginDiagnostics() to receive a diagnostic connection ID
and a component list for the respondent.
BeginDiagnostics() consists of two functional parts: First, it opens a temporary socket and
issues an IPX request to the diagnostic socket on the target machine. The target machine
responds back with an SPX socket number on which to establish a connection and a list of
components present on that machine. BeginDiagnostics() then establishes an SPX connection
with the target on its requested socket and returns the connection ID to the caller for use with
future diagnostic calls. EndDiagnostics() terminates this connection.
IssueConfigRequest() is a new diagnostic API created to add functionality to the Network
Resource Manager. It is not available with other platform specific SDKs, but is documented in
the NetWare System Interface Technical Overview. With MacIPX, IssueConfigRequest() is
implemented with a series of IPXSend() and IPXReceive() calls. It takes advantage of the
exclusion list feature in the request broadcast and builds a list of unique respondent nodes and
components. The limit of 80 addresses in the exclusion list implies a maximum number of
respondents returned with this API.
Unlike other diagnostic APIs, IssueConfigRequest() uses an Event Service Routine to
receive the incoming packets instead of querying the OS queue head or Event Control Block
(ECB) status fields. This may be a more efficient means of receiving large quantities of packets
in a short time period. The Network Resource Manager makes use of IssueConfigRequest() in
the Target Broadcast menu option.
Network Area Information
The broadcast option of the Manager can determine what kinds of resources are available
on the network by sorting the respondents into groups by type. Previous discussions have
centered on broadcasting for workstation respondents. You could just as easily use the broadcast
method to list available bridges. With this information, the Network Resource Manager
determines the layout of the network in terms of segments and routes.
Two processes implement the "ad hoc" responder access: you can select a target through a
list of respondent nodes using the Target Broadcast menu option. The other choice gives users a
more global view of the network with the Topology Window. From this window, you can select
a target network to query, or select a target node within that network segment. The Target
Topology menu option sorts the responses by network and continues the exclusion list process
for each network segment until the maximum number of responses is reached.
Additional Node Data
To add to the functionality of the Network Resource Manager, the basic design is
expanded to query nodes for additional data using a method similar to diagnostics. This design
could allow the Network Resource Manager to determine third-party software versions and
system hardware configurations, as well. Obviously collecting of this type information is
platform-dependent.
Interrupts are available to DOS (and Windows) applications that return hardware setup
information like drive type(s), monitors, and total and available memory. Operating system APIs
duplicate this functionality on OS/2 machines and Macintoshes. You might collect setup data
from a node by installing a system that mimics diagnostic responder functionality. For example,
on a DOS machine, you could create a TSR (terminate and stay resident program) that opens a
known socket upon initialization and sleeps until it receives a request for configuration (from the
Mac requester) on that socket. It then collects the hardware configuration information and replies
back. A TSR would work for both DOS and Windows environments. OS/2 would use a daemon
and the Mac an INIT, but the concept is the same.
Adding this type of functionality greatly expands the usability of the Network Resource
Manager. At first, this project seems very complex. However, it is really only three program
shells that share communications functionality. This type of application development is a perfect
candidate for the NetWare Client SDK (DOS, Windows and OS/2) and for the MacIPX SDK for
the Macintosh INIT.
Programming with MacIPX
The Network Resource Manager uses the diagnostic APIs in the NetWare C Interface for
DOS as a basis for diagnostic services on the Mac. This method reveals many technical issues
common to cross platform NetWare development and specific to DOS-to-Mac porting.
Fortunately, the design of the diagnostic APIs on the DOS side is very uniform. Definitions,
compiler options and advice to programmers resolve many of the issues.
Except for the APIs from the environment category (BeginDiagnostics(),
IssueConfigurationRequest(), etc.), most APIs follow a particular pattern in execution. The
process is to:
- Set up an SPX packet containing the diagnostic request
- Issue an SPX send
- Wait for a response
- Copy response data into its structure
- Return a success code.
The primary functions for handling this process are SendSPXPacket() and
GetDiagnosticResponse(). SendSPXPacket() accepts as parameters the diagnostic connection ID,
the request buffer and the request buffer size. GetDiagnosticResponse() is similar except that it
uses two buffers and two size parameters. The first buffer is the response data from the transport
of the request, (i.e., whether the request was valid, accepted and replied to); the second buffer
contains the data itself. Figure 1 lists excerpts from the source for these two functions; they
contain several items particular to developing with MacIPX.
FIGURE 1: Source excerpts for SendSPXPacket( ) & GetDiagnosticResponse( )
static int SendSPXPacket(WORD connectionID,
BYTE *buffer1, WORD size1)
{
int ccode, returnCode;
SPX_SESSION CSB;
SPX_HEADER requestHeader;
SPX_ECB requestECB;
memset((char *)&requestHeader,0,sizeof(SPX_HEADER));
memset((char *)&requestECB,0,sizeof(SPX_ECB));
ccode = SpxGetConnectionStatus(connectionID, &CSB);
if ( !ccode )
{
requestHeader.connectionCtl = 0x00;
requestHeader.dataStreamType = 0x00;
requestECB.ESRAddress = 0;
requestECB.fragCount = 2;
requestECB.fragList[0].fragAddress = &requestHeader;
requestECB.fragList[0].fragSize = sizeof(requestHeader);
requestECB.fragList[1].fragAddress = buffer1;
requestECB.fragList[1].fragSize = size1;
SpxSendSequencedPacket(connectionID,&requestECB);
while ( requestECB.status == ST_SENDPACKET && !CheckTerm() )
IpxRelinquishControl();
if ( requestECB.status == 0x3000 && !exitProgram )
returnCode = NO_ERRORS;
else
returnCode = COULD_NOT_SEND_REQUEST;
}
else
returnCode = BAD_CONNECTION_ID;
return returnCode;
} // END - SendSPXPacket
static int GetDiagnosticResponse(WORD connectionID, BYTE *buffer1,
WORD size1, BYTE *buffer2, WORD size2)
{
int foundECB = FALSE;
int returnCode = RECEIVED_REPLY_IN_ERROR;
SPX_ECB *comeBack;
SPX_HEADER *replyHeader;
BYTE *replyPtr;
while ( !foundECB )
{
// wait for there to be a packet in the queue
while ( !diagQueue.qHead && !exitProgram )
{
IpxRelinquishControl();
CheckTerm();
// might want to put a time out in here
}
// we have one, get it and check it
comeBack = (SPX_ECB *)diagQueue.qHead;
Dequeue((QElemPtr)comeBack,&diagQueue);
replyHeader = (SPX_HEADER *)comeBack->fragList[0].fragAddress;
replyPtr = comeBack->fragList[1].fragAddress;
if ( replyHeader->destConnectID == connectionID )
{
if ( comeBack->status == 0x3000 )
{
returnCode = NO_ERRORS;
memcpy(buffer1,replyPtr,size1);
memcpy(buffer2,replyPtr+size1,size2);
}
else
returnCode = RECEIVED_REPLY_IN_ERROR;
foundECB = TRUE;
} // END - if this was our packet
} // END - while !found
if ( exitProgram )
return DX_ABORTED;
SpxListenForConnectionPacket(connectionID,comeBack);
return returnCode;
} // END - GetDiagnosticResponse
END of FIGURE 1
Porting Issues
Differences in definitions may cause problems for those familiar with programming in the
DOS environment or porting applications from DOS to Macintosh. These include definitions for
structures, return codes, and formal parameters, as well as the inclusion and exclusion of certain
APIs.
The ECB is the structure whose fields contain information necessary to send IPX or SPX
packets; it is used in almost every IPX/SPX API. The ECB structure member names and
functionality vary across the client platforms. The DOS structure, for example, contains an inUse
field and a completionCode field; inUse indicates what is happening to the ECB while in use by
the transport, and completionCode is the ECB function result. MacIPX combines the functions of
these two fields into the status field.
The Mac ECB contains a number of new fields that are not available on other platforms. The
MacOSQueue field is a OS defined variable type that can be used to link incoming ECBs for
future processing. The savedA5 field gives the application's ESR (Event Service Routine, an
interrupt process used to handle incoming ECBs) access to global data.
It is always a good practice to check the API return codes and ECB completion codes.
Defining codes in header files to account for the difference between the environments prevents
conflict when developing across platforms. For example, a returnCode of 0 (zero) usually means
that an API call is successful. On DOS platforms, 0 also implies a successful IPX or SPX
request. DOS completionCodes are one-byte (e.g., 0xFC for event canceled). On the Mac, ECB
status fields are two bytes long. This field is set to 0x0000 for a successful IPX request and to
0x3000 for a successful SPX request. In the event of failures, codes similar to DOS failures are
in the low order byte (i.e., a canceled event will contain 0x90FC in the ECB status field).
As stated previously, using #define statements in your header files accounts for most of these
differences without having to make modifications to the code. The Resource Manager uses an
include file, DIAG.H, which incorporates these definitions.
"Timer tick" is another conditional definition in DIAG.H. IPXScheduleIPXEvent() expects a
tick equal to 1/60 of a second, based on the vertical retrace interval built into the video circuitry.
Under DOS, a tick is approximately 1/18 of a second, so defined to maintain compatibility with
the time circuit design of the original IBMPC. Since the Macintosh uses a different architecture,
you may expect such a difference in a hardware-specific definition. Some MacIPX APIs return
ticks values in terms of 1/18 seconds (e.g., IPXGetLocalTarget()). These functions usually return
time values from requests made to IBM-compatible machines.
The DOS Diagnostic Services use some APIs that are not included with the MacIPX SDK.
One missing API is IPXGetIntervalMarker(), which is sometimes used to check for "time out."
On the Mac, a good replacement is to use the clock() ANSI C function or the TickCount() OS
API. Figure 2 compares the use of these functions.
FIGURE 2: Comparison of IPXGetIntervalMarker() & clock()
DOS Method:
startTicks = IPXGetIntervalMarker();
while( IPXRecvECB.inUseFlag )
{
IPXRelinquishControl();
endTicks = IPXGetIntervalMarker();
if( endTicks - startTicks > 72 )
break;
}
...
Macintosh Method:
startTicks = clock();
while ( !recvQueue.qHead )
{
IpxRelinquishControl();
endTicks = clock();
if ( endTicks - startTicks > 72 )
{
ErrorCode = REMOTE_TIMEOUT;
break;
}
}
...
END of FIGURE 2
Another missing API is IPXScheduleSpecialEvent(), a specialized form of
IPXScheduleIPXEvent() that does not require an open socket to act upon. In DOS, the special
event API triggers a timer for the timing functions. The Manager code uses the clock() function,
but IPXScheduleIPXEvent() could also have been used with a temporary socket.
Mac Advantages & Caveats
Programming with the MacIPX SDK offers some definite benefits. For example, the use
of the Macintosh OS object, MacOSQueue, inside the ECBs is useful for testing if packets have
been received or to check packet order. There is one disadvantage that is particularly evident
when using MacIPX to communicate with a non-Mac target: DOS machines return information
in structures with members aligned on odd-byte boundaries, but Mac compilers do not offer
options to handle packing structures.
Packed structures are used throughout NetWare since they increase transmission efficiency
by eliminating pad data on the wire. Think C and the Macintosh Programmer's Workshop
(MPW) do not support packed structures and will align any non-byte member on a word
boundary. Thus, if you create your structures to duplicate those defined in the NetWare System
Interface Technical Overview, you may discover that the information returned in packets, when
overlaid on this structure, becomes unrecognizable.
There are a couple of ways to resolve this dilemma. The first method requires you to code
your structure access in Assembly language. For a lighter approach, you could use a method
similar to the one shown in Figure 3.
FIGURE 3: Macintosh packed data structure method
From DIAG.H
#define getShort(a) (*(unsigned short *)a)
#define getLong(a) (*(unsigned long *)a)
#define getPtr(a) (*(unsigned long *)a)
#define getStruct(a,t) (*(t *)a)
typedef struct StructAllResp {
BYTE completionCode; // PAD
// long intervalMarker;
BYTE intervalMarker[4];
} AllResponseData;
#define SIZE_AllResponseData 5
typedef struct StructAddressTable {
BYTE serverUsed;
BYTE orderNumber;
BYTE serverNetwork[4];
BYTE serverNode[6];
WORD serverSocket;
WORD receivedTimeOut;
BYTE immediateNode[6];
BYTE sequenceNumber;
BYTE connectionNumber;
BYTE connectionOK; // PAD
// WORD maximumTimeOut;
BYTE maximumTimeOut[2];
BYTE reserved[5];
} AddressTableStruct;
#define SIZE_AddressTableStruct 32
END of FIGURE 3
In instances where the next structure member is of even size and should start on an
odd-byte boundary, the member is defined as an array of BYTES, which the Think compiler will
not pad, and then cast into the appropriate type when accessed for data. Macintoshes will allow
this approach since, unlike DOS machines, there is no reverse-byte ordering with which to
contend. Figure 3 also contains the macros used to access these members; for example,
getShort() retrieves a short integer from a two-byte member.
DOS programmers frequently check for incoming packets by testing the ECBs that have
been posted for listens to see if they are still in use. Typically, this looks like a program loop
through all of the posted ECBs (in Diagnostics there are four) with an if() test and a break. With
Macs, there is a much cleaner way: as part of the program initialization, declare a Qhdr structure
as a global variable, and assign a pointer to this structure in each ECB. When packets arrive,
MacIPX will enqueue them on this OS queue. Then, to check for a packet, test the QHdr element
that points to the head of the list to see if any ECBs have come back. For cross platform
portability, you may still use the ECB.inUse method, if desired. Figure 4 compares the two
methods.
FIGURE 4: Comparing use of ECB field and OS Queue
Checking ECB.inUse:
int ECBPtr;
int returnCode;
for (ECBPtr=0; ECBPtrfragList[0].fragAddress;
if ( replyHeader->destConnectID == connectionID )
returnCode = TRUE;
}
END of FIGURE 4
Future Enhancements
The Resource Manager is a useful utility in its present form, and it thoroughly exercises
the diagnostic services. However, there is still room for improvement: the Resource Manager
could be enhanced to make use of other areas of IPX/SPX transport service and overall
useability. A few enhancements on both the requester side and the respondent side have already
been mentioned and are summarized briefly here. Look for Part Two of this article in a future
issue of Bullets, which will discuss adding this functionality using the NLM SDK and the
NetWare Client SDK.
Server Support
Additional server, or requester, support can include the ability to target respondents with a
network object name rather than an IPX address. As documented earlier, MacIPX cannot lookup
user objects in the bindery (though the NetWare C Interface for Macintosh provides this
functionality), MacIPX does contain full SPX support, however, and can use SPX to
communicate with other server applications that have access to user objects.
Object name lookup capability will be added to v2.0 of the Resource Manager through the
use of an NLM. The basic design is as follows: The NLM will load and advertise on a private
socket. When the Manager needs to find the available responders, it will issue a Service Query
through the SAP API QueryServices() to find the NLM. It will then send a bindery lookup
request to the NLM via SPX, which will in turn return a list of connected objects and their IPX
address. The Network Manager will display this list of object names (rather than the list of
addresses) at the Target Broadcast menu option. The administrator will select a user, and the
program will use its corresponding IPX address to initiate a diagnostic session.
Client Support
Version 2.0 of the Resource Manager will include enhanced responder functionality.
Network administrators may want to determine more information about a particular workstation
than just its connectivity components. Using the same methodology as the diagnostic support,
you can query a target for its hardware configuration and even its storage contents through the
use of responder applications resident on each machine.
The Diagnostics menu option will query these expanded responders. If the expanded
responder is not installed for that target, the menu option will be "grayed out" and unavailable.
Behind the scenes, the requester will issue a DiagHardwareConfig() request on a well known
socket to the desired target. No response will signify that the responder is not present.
The expanded responders will have slightly different architectures based on the machine type
on which they are resident. Machines running the DOS and Windows operating systems will use
TSRs that will load as part of the startup process and open a well known socket upon which to
receive SPX DiagHardwareConfig() requests. The same functionality will apply to OS/2
machines and other Macs except that they will use daemons and INITs, which require different
application generation techniques.
When the expanded responders receive a request on their socket they will issue the
appropriate OS APIs (OS/2 and Macs) or interrupts (DOS) to gather the available information
and send it back in sequenced SPX packets to the requester.
The MacIPX SDK provides comprehensive support of the IPX/SPX transport protocol on
NetWare. It is easy to use for both the experienced Mac programmer and novice alike. The
documentation provides sufficient information on the transport concepts so that you could
readily use this tool to begin your NetWare programming experience.
IPX and SPX are the building blocks for NetWare-compatible applications. This article has
discussed using this protocol to add significant functionality to Mac applications by writing
diagnostic APIs using MacIPX. You can write your own using these techniques, or if you prefer,
the source code for the APIs is available in the file MACDIAG.SIT. The Resource Manager is
contained in MACNRM.SIT. Both files are available on Novell's NDEVREL CompuServe
forum (section 9) and Applelink (Support, 3rd Parties). These files are provided as is and thus are
not supported by Novell. If you have questions on using the MacIPX SDK, contact Novell
Developer Support.
NLM SDK v3.0: New Features for NLM Developers
In July, Novell began shipping the NLM SDK v3.0. The article discusses new features
available in this SDK.
Support for NetWare 3.x and 4.x
This SDK provides the tools necessary for developing both NetWare 3.x and 4.x NLMs.
Previously, Novell offered the Network C for NLMs SDK for developing NetWare 3.x NLMs,
and the NLM SDK for NetWare 4.0 for developing 4.x NLMs.
AppleTalk SDK for NLMs Added
With this release of the NLM SDK, the NetWare 4.0 Interface for AppleTalk for NLMs
SDK has been incorporated into the NLM SDK. This interface allows you to create NLMs that
communicate with an AppleTalk client, such as a Mac. This SDK provides a full set of interfaces
that allow you to access these AppleTalk protocols:
- AppleTalk Data Stream Protocol (ADSP)
- AppleTalk Echo Protocol (AEP)
- AppleTalk Session Protocol (ASP)
- AppleTalk Transaction Protocol (ATP)
- Datagram Delivery Protocol (DDP)
- Name Binding Protocol (NBP)
- Printer Access Protocol (PAP)
- Zone Information Protocol (ZIP)
This SDK enables NLMs developers to access the AppleTalk protocol stack using either
TLI or native NetWare AppleTalk C function calls. In the AppleTalk protocol stack, TLI
provides access to DDP and ADSP. Through a single procedural interface (TLI), NLMs can
access multiple protocols, such as AppleTalk, TCP/IP, and IPX/SPX. To develop applications
using the NetWare 4.0 Interface for AppleTalk for NLMs SDK you must have NetWare 4.0 and
NetWare for Macintosh 4.0.
WATCOM C/386 v9.01 & C/C++32 v9.5 Compiler Support
Beginning with the NLM SDK v3.0, support is provided for WATCOM 386 v8.5 through v9.5
compilers (the compiler is not included). Support is now provided for C++ NLM development
using the WATCOM C/C++32 compiler.
NDebug Source Level Debugger Added
NDebug provides the ability to do source level debugging, similar to WATCOM's VIDEO
debugger. NDebug supports both local and remote debugging. (Source code must be placed on
the DOS partition of the debug server when performing NLM hosted (local) debugging.) The
NDebug utilities that extract debug information from the load modules do not support the
WATCOM v9.5 compiler at this time.
NLM SDK Install Utility Updated
The Install utility has undergone three major changes. First, the utility now uses an ASCII
file INSTALL.LST. This file contains the information needed by the Install utility to identify the
various subsystems and file specifications that need to be installed.
Second, the /NovellNet switch has been changed to simply /NetWare. This switch is used to
install the SDK from a network directory conforming to the SDK staging area. The switch could
install the SDK directly from a network directory structure such as:
/PATH/1 - contents of disk 1
/PATH/2 - contents of disk 2
/PATH/n - contents of disk n
Third, MAKEINIT has undergone several changes:
- It now includes $(appletlk), a new macro that supports the AppleTalk APIs in a
manner similar to how other API subsets are handled.
- The $(startup) macro is undefined if the WATCOM tools v9.5 are detected.
- The OS/2 tool support has been withdrawn, but will be added in a subsequent release.
- Depending on which compiler version is installed, the real mode/protected mode macro
definitions are different.
If the Install utility is unable to detect the compiler version, the values defined for the
macros $(watdrive) and $(wat386loc) will be incorrect. In this case, you should edit the
MAKEINIT file to reflect the correct values for these macros before attempting to rebuild
examples or projects using MAKEFILE's created by QMK386.
For more information on the NLM SDK v3.0, contact Novell Developer Support at
1-800-NETWARE (1-800-638-9273) or 1-801-429-5588. You must be a member of the
Professional Developers' Program to purchase the NLM SDK v3.0.
Using WATCOM's C/C++32 Compiler to Create NLMs
In June, WATCOM began shipping their C/C++32 v9.5 compiler, which includes support
for NetWare 3.x and 4.x platforms. This article discusses some development issues you may
encounter using the new compiler.
Using the New Compiler Without Utilizing C++ Features
You may be one of the developers who simply upgrades to the latest tool offering from
WATCOM, but do not need to use the C++ features. In this case, you can create NLMs that rely
entirely on the CLIB Runtime Library NLM and use the tools the same way as before.
However, be aware that if the NLM SDK Install utility detects the WATCOM C/C++32 9.5
compiler, it will install under the assumption that you are using the WATCOM static library
(which is required for C++ NLM development). Specifically, it will define the $(startup) macro
to expand to nothing, which will cause the linker to get the $(startup) code from WATCOM's
CLIB3S. If you need to use the WATCOM v9.5 compiler under the same environment that you
had with the WATCOM v9.01 compiler, you need to perform one of the following two steps:
- Install the NLM SDK v3.0 in a location other than where the WATCOM
C/C++32 compiler was installed. The NLM Install utility will prompt you for the WATCOM
compiler version. Choose WATCOM C/386 instead of WATCOM C/C++32. Also, be sure to
correct the path specifications for $(watdrive) and $(wat386loc) in MAKEINIT.
OR
- Before running the NLM SDK Install utility, rename the NOVH subdirectory (created by
the WATCOM Installation utility) to "WATNOVH", and the Novell header files will be copied
into the NOVH subdirectory. Define the $(startup) macro to point to the PRELUDE.OBJ file
supplied by Novell (in the NOVI directory). This file will be copied to the NOVI directory
regardless of the compiler version detected.
You may also want to prevent accidental linking of the CLIB3S.LIB file by adding the
"option nod" linker directive to any link files or you can use the "/zl" compiler switch to prevent
the compiler from putting default library names into the object modules. This step is not
required, but it might prevent you from accidentally linking the CLIB3S.LIB file.
In addition, do not use the "/BT" switch with WCC386, or the compiler will place a reference to
__WATCOM_prelude in the object, which will cause errors during the link phase (unless of
course the undefsok option is specified).
Using the New Compiler Utilizing C++ Features
If you need C++ for your NLMs, you will need to do the following:
- Link in CLIB3S.LIB. It provides the base support necessary for the C++ class
libraries.
- Use the System NetWare option of WLINK. This option will ensure that the correct
libraries are linked into your load module. Do not use the PRELUDE.OBJ provided by Novell or
the C++ support will not work.
Using the WATCOM Compile & Link Utility to Create NLMs
Now you can use WATCOM's compile and link command-line utility to create NLMs.
Assuming your path specifies the binary directories, and the INCLUDE and WATCOM
environment variables have been set, the command to compile and link the "Hello World" C
example program is:
WCL386 /BT=NetWare /L=NetWare HELLO.C
The "/BT" (Build Target) switch is used by WCC386 to establish the default compiler switches
required to build NLMs. Specifically, it establishes the following defaults for WCC386:
/3s Use stack-based parameter passing
/ms Use the small memory model (required so CS: overrides are used when
referencing constants, stored in code segment.)
Also, "/BT" causes WCC386 to generate a reference to __WATCOM_Prelude, to ensure that
WATCOM's version of PRELUDE.OBJ is used. Thus, if you choose not to use the WATCOM
static libraries, do not use the "/BT" switch with WCC386.
The "/L" switch instructs WLINK to use the System NetWare defaults, which specifies items like
linking with the proper WATCOM static libraries.
You can also set INC386 (or INCLUDE) and LIB386 to specify search locations for the
WATCOM tools; however, LIB386 won't help the linker find the NOVI path, thus import files
would require full path specifications. QMK386 uses full path specifications currently, along
with INC386 and LIB386, but the next version (v2.20) will set the INCLUDE and WATCOM
environment variables.
IMPORTANT: If you use "/ms" to force the code generator to include CS: overrides when
accessing constants in the code segment, be aware of the following issue. One side-effect that
occurs when using "/ms" is that the code generated for a large sparse case statement will put the
contents of CS into ES in order to do a table scan to find the matching case label. If a hardware
interrupt occurs during this time, and code is executed that assumes ES == DS, a fault may
occur. The only workaround at present (verified thru WATCOM Engineering) is to use "/ot"
("optimize for time") which produces a large jump table for the sparse case statement, instead of
a lookup table. This method appears to work, but may not be the optimal solution for all
developers.
Using the WATCOM CLIB3S.LIB
In order to create a C++ NLM, you must use the WATCOM static library CLIB3S.LIB in
addition to any other specific C++ class libraries, also provided by WATCOM. Without these
libraries, C++ features are not available to NLM developers. WATCOM requires some additional
instance data in the thread package and CLIB3S.LIB handles allocating and releasing these
resources without any intervention from the NLM developer.
To clean up all the resources allocated by the static library, WATCOM registers an atexit()
routine during startup. Therefore, only 31 additional atexit() routines may be registered by NLM
developers when using the static libraries. In addition, if an NLM aborts via the abort() API some
resources will not be cleaned up, including local semaphones which will result in a server abend.
(WATCOM offers a fix that will remedy the abort() problem by not using system
semaphores. See "Patch for NetWare Developers" below for details.)
Only Protected-Mode Compiler & Linker Tools Available
Previous versions of the WATCOM C compiler provided both real mode and protected mode
versions of the compiler and linker tools. However, WATCOM C/C++32 v9.5 only provides
protected mode versions of these tools. Note that WCC386P.EXE and WLINKP.EXE are still
included in the BIN directory. These tools are simply stub utilities which spawn WCC386 and
WLINK respectively.
Source-Level Debugging for NetWare 4.0 Available
As with prior versions of the compiler, WATCOM includes full source-level debugging
support with their latest toolkit. New with v9.5 of the compiler is support for source-level
debugging on NetWare. All source-level debugging is performed remotely, via serial, parallel, or
network (SPX) communications.
NLM Headers and Imports
WATCOM now ships the Novell NLM Header and Import files, allowing developers to
build NLMs without the requirement for the Novell NLM SDK. However, since no API
documentation or other value-added tools are provided, any serious NLM development still
requires the purchase of the NLM SDK.
There are a few differences between the WATCOM NLM headers and the Novell NLM headers.
The most notable difference is the standard C FILE structure. In order to provide support for
implementing C++ I/O support for NLMs, WATCOM required a substantial number of changes
be made to the FILE structure. Novell was unable to incorporate all of these changes into the
current CLIB implementation on NetWare 3.x and 4.x, so WATCOM created a static library
which sits on top of the CLIB Runtime Library NLMs.
If you choose to build NLMs that do not rely on CLIB3S, be sure to install Novell's NLM header
files from the NLM SDK.
Patch for NetWare Developers
Novell added the AppleTalk API support header files and import file after WATCOM had
created the master diskettes for the WATCOM C/C++32 compiler. In addition, there are several
known bugs with v9.5 that are fixed in a patch offered to NetWare developers:
- You cannot debug multi-threaded NLMs.
- beginthread() has a race condition that could cause memory problems.
- You cannot restart or kill an NLM in the debugger because CLIB3S uses semaphores.
The debugger uses _exit() to kill the NLM but this does not free semaphores.
- The export statement in the linker does not work.
- CLIB3S keeps pointers to memory and semaphores in its file structures. If a thread from
another NLM is the cause of the memory allocation, this memory is attributed to that NLM, not
the one keeping the static pointer.
The patch for NetWare developers is available on CompuServe on Novell's NDEVREL
forum (Library 1, WAT95P.ZIP). It can be downloaded from WATCOM's BBS service at
1-519-884-2103.
For more information on the NLM SDK v3.0 which includes support for the WATCOM
C/C++32 compiler, contact Novell at 1- 800-NETWARE (1-800-638-9273) or 1-801-429-5588.
You must be a member of the Professional Developers' Program to purchase the NLM SDK v3.0.
Novell Announces AppWare
In June, Novell announced AppWare, a new layer of software that leverages today's
popular operating systems, development tools, and applications.
Developers who create network applications must deal with the growing number of operating
systems, development APIs, computing standards, and development toolkits available today.
AppWare hides these complexities from developers by providing them with one uniform set of
APIs for accessing different operating systems, graphical user interfaces (GUIs), and network
services. In the AppWare environment, developers can write the application code once and run
the application on different operating systems and networks.
AppWare: What Problems Does It Address?
On average, one major new operating system or service API is delivered to developers
every 45 days. This rapid pace makes it virtually impossible for application developers to keep
up with emerging technologies. Resource constraints force developers to choose among the
available alternatives. Often developers can only afford to focus on one platform or operating
system, limiting the markets and users that their products can address. AppWare provides
solutions for the following problems:
- Multiple Networking Models - application developers are currently faced with an
unprecedented need for network access and functionality. Developers must contend with a
variety of network models to deliver the services and data their users require.
- Multiple Desktop Platforms - Developers must learn all the details of the desktop
platforms on which their applications run. For example, if a developer had to write a million
lines of C code to create an application for MS-Windows, that developer would likely have to
rewrite that code for each platform on which the application will run such as Macintosh, Unix, or
OS/2.
- Inefficiency of Network Application Development Tools - Traditional application
development required writing code from scratch using third generation languages (3GLs) such as
C or C++. Typically, this method of application development is used by horizontal application
vendors who work on multi-million dollar projects that can take years to complete. Corporate
and vertical software developers, however, can no longer afford to create applications using this
method. The industry has reached a point where developers are demanding more effective tools
than are available today.
The AppWare Solution
AppWare is not an operating system or an application. AppWare is a new layer of
software that provides two components of technology that address the problems created by
multiple networking models and multiple desktop platforms: the AppWare Foundation and the
AppWare Bus.
The AppWare Foundation insulates programmers from the growing complexities of multiple
operating systems, GUIs, and networks. AppWare does not replace existing operations systems,
GUIs, and network services; rather it leverages, unifies, and improves them.
The second AppWare component, the AppWare Bus, is a software engine that provides
large-grained, interchangeable software modules that corporate and vertical developers can use
and reuse to quickly construct new network applications, without having to write code. These
software components, called AppWare Loadable Modules (ALMs), provide access to the
functionality provided by both local operating systems and network services.
The AppWare Bus and ALMs are the software equivalent of the PC mother board and
interchangeable plug-in cards. When ALMs are plugged into the AppWare Bus, their
functionality becomes rapidly accessible for building new applications, and third parties can
offer their technology in the form of new ALMs. Business application developers will be able to
create new applications quickly and easily by linking different ALMs.
Developers will use one set of APIs to build ALMs. Applications written on top of the AppWare
Foundations API set are simply recompiled to run on DOS, MS Windows, Windows NT, OS/2,
UnixWare, and the Macintosh desktops, as well as NetWare and UnixWare servers.
Novell intends to work with developers, development vendors, operating system suppliers, and
other third parties to make AppWare a standard for network application development. Novell has
already created basic and network ALMs, and is actively working with a number of ISVs to
provide additional ALMs. For example, Cheyenne Software is creating ALMs for imaging and
document management. Various third parties have already built ALMs for accessing Oracle and
Sybase databases.
AppWare will remain open and extendible and will incorporate important development and
interface standards. Therefore, AppWare will be welcomed into companies that want to protect
themselves from the vagaries of proprietary system components.
Visual AppBuilder: 5GL Application Development Tool
Visual AppBuilder provides a 5GL-level development environment, and is tightly
integrated into the AppWare environment. Visual AppBuilder allows applications to be
constructed by selecting and manipulating on-screen icons that represent different ALMs.
Developers use on-screen links to create application logic, thereby providing for rapid
development of network applications.
Visual AppBuilder is designed for programmers unfamiliar with the details of 3GL development.
The range of applications developers can create is limited only by the range of ALMs provided
by Novell and third parties. Visual AppBuilder is ideal for corporate and vertical business
application developers.
For example, consider a developer who wants to provide an easy-to-use automated telephone
directory system for a global corporation. The directory information is stored in an Oracle
database, and the users of this program are non-technical so it should have a slick multimedia
front end. In addition, the available hardware offers automatic answer and dialing through the
telephony services on the network.
Using a 3GL tool, such an application might take years to complete. With Visual AppBuilder, a
developer would simply use on-screen graphic icons to connect the Oracle database ALM, the
multimedia ALMs, and the telephony ALM to create the new application. By avoiding traditional
line-by-line hand coding, the application could be created quickly. Also, since it is built on the
AppWare foundation, the application could be quickly ported to any common operating system
or network.
Integration with Other Third-Party Development Tools
For procedural developers, ALMs can be built using 3GLs and the AppWare Foundation.
ALMs can be created with almost any compiler including Microsoft, Borland, Symantec,
LightSpeed, SABER, GNU, and MPW compiler. Debugger support includes Multiscope,
CodeView, and SADE debuggers.
For Additional Information
More information on AppWare is available through the Novell Developer Relations
Automated Fax System. Call 1-512-794-1799 and request document 2900 (AppWare press
release). To order white papers on AppWare, Visual AppBuilder, and AppWare Architecture,
request document 2905 (AppWare white paper order form).
Novell Announces Vertical Application Developer Services
To provide the technical and marketing assistance required by vertical application
developers, Novell offers the Vertical Application Developer Services. Membership is reserved
for developers writing or providing industry-specific applications and solutions to the various
vertical markets, such as finance, legal, manufacturing, retail, and others.
Vertical application developers gain access to these services through a fee-based subscription. In
addition, Vertical Developer Services subscribers get all the same benefits that member of the
Novell Professional Developers' Program and the Univel Developers' Programs receive.
Technical Assistance
Novell Vertical Application Developer Services offers the following technical assistance
for your development efforts in the vertical marketplace:
- One Year License to the NetWare Operating System - with each annual
subscription, members receive a free one- year subscription to the NetWare or UnixWare OS of
their choice.
- Priority Developer Support - receive priority access to high-level support without going
through the basic channels.
- NDEVREL - a forum on CompuServe that allows vertical developers to share
information privately and communicate with Novell and Univel staff.
- BrainShare Conference - receive a 10% discount.
- Ongoing Information Updates - receive a technical newsletter, as well as mailings and
updates specific to their industry or market.
- API Special Interest Group - participate in the Novell Compass Program, a roundtable
format in which developers and Novell engineers discuss future API direction.
- Developer Services Advisory Council - join Novell staff and other vertical developers to
periodically discuss vertical industry application challenges.
- Development Technology Lab - the Novell Developer Relations Technologies
Engineering Lab is available to subscribers needing one-on-one engineering assistance.
- DeveloperNet Labs Certification - subscribers receive a 15% discount.
Marketing Support
- Directory Listings - gain product exposure through the Yes, It Runs With NetWare
Resource Guide; the Yes, It Runs With UnixWare Resource Guide, and the NetWire
CompuServe forum.
- Sales Leads & Assistance - Corporate-sponsored events and the resulting leads can be
sent to subscribers as appropriate. Controlled mailing list access to the Novell reseller channel is
granted on a case-by-case basis, and the NetWare Users International (NUI) mailing list is
available.
- Evaluation Copies - Subscribers can send evaluation or demo copies of their applications
to Novell field sales offices for valuable application input.
Sign Up Now
Complete a subscription form and return it with your $495 annual subscription fee to
Novell Vertical Application Developer Services. Subscription forms are available through
Novell's Automated Fax System at 1-512-794-1799, and in the Developer Program Information
section on the main NetWire menu on CompuServe.
New Releases of Novell Development Tools
NetWare for SAA Tools v1.0
Description:
Incorporates the functionality of NetWare 3270 Tools, NetWare for SAA LU6.2 Tools, &
NetWare Open NetView SDK (which lets you build apps that send alerts to the IBM NetView
console and respond to RUNCMDs from the NetView console).
Products Replaced:
- NetWare 3270 Tools v2.0
- NetWare for SAA LU6.2 Tools v1.4
- NetWare Open NetView SDK v1.0
Upgrade Path?
No, but existing customers with replaced products will continue to receive individual product
updates.
Available: Now
Part Number: 884-000081-001
LAN WorkShop v1.1a
Description:
Incorporates the functionality of the LAN WorkPlace Toolkits for DOS, Windows, OS/2 and
Macintosh, as well as NetWare TIRPC for DOS, Windows and NLMs Toolkits.
Products Replaced:
- LAN WorkPlace for DOS Toolkit v4.1
- LAN WorkPlace for OS/2 Toolkit v3.0
- LAN WorkPlace for MAC Toolkit v1.3
- NetWare TIRPC for DOS, Windows & NLMs Toolkit v1.3
Upgrade Path?
Yes, all owners of replaced products will be updated with the LAN WorkShop v1.1a.
Available: Now
Part Number: 884-000061-002
NLM SDK v3.0
Description:
Provides the tools needed for developing NetWare 3.x and 4.x NLMs, as well as NLMs that can
communicate with an AppleTalk client.
Products Replaced:
- Network C for NLMs
- NLM SDK for NetWare 4.0
- NetWare 4.0 Interface for AppleTalk for NLMs SDK
- NetWare 3.x Interface for NLMs SDK
Upgrade Path?
Yes, all owners of replaced products will be updated with the NLM SDK v3.0.
Available: Now
Part Number:884-000090-001
NetWare Client SDK v1.0e
Description:
Provides a single interface for writing DOS, DR-DOS, OS/2, and Microsoft Windows
applications that directly access the core services of NetWare 2.x, 3.x & 4.x via a comprehensive
library of client APIs.
Products Replaced:
- NetWare System Calls for DOS
- NetWare C Interface for DOS
- NetWare C Interface for Windows
- NetWare OS/2 Developer's Kit
Upgrade Path?
If you purchased product before Sept. 12, 1993, you can purchase at a discount with proof of
purchase. If you purchased products after 9/12/93, new product is free until 8/30/93.
Available: Now
Part Number: 884-000031-006
Using Microsoft Access with Btrieve (Btrieve for Windows v5.10)
This Technical Insight describes the most common issues Btrieve users encounter while
using Microsoft Access to access Btrieve data files.
The Data Dictionary
Microsoft Access can access (read or modify) a Btrieve file only through that file's data
dictionary. A data dictionary is a set of files that define fields for each record of a Btrieve file. To
produce the data dictionary files (DDFs) for a Btrieve file, you must know the starting offset,
length, and type of each portion of a file's records that corresponds to a field. You can then use
NetWare SQL, Xtrieve PLUS, or a similar product to define the DDFs for that Btrieve file.
Access cannot create DDFs for a Btrieve file.
File Owner Names
Access opens DDFs with the Novell default DDF owner name; therefore, if security is
defined on a set of DDFs, Access cannot read the DDFs. In this situation, Access returns the
error Couldn't Decrypt File.
If a Btrieve file has an owner name, but does not require you to specify the name in order to
read the file (level 1 or 3), Access does not prompt you for the owner name. Although Access
can read the data from the file, attempting to edit the file's data causes Access to return the
following error: "Couldn't update; database is read-only."
If a Btrieve file has an owner name, and that file requires that you specify the owner name in
order to read or modify the file (level 0 or 2), Access prompts you for the owner name. If you are
using Btrieve v5.x, Access opens the file for normal use after you specify the owner name.
However, if you are using Btrieve v6.x, Access cannot open the file even after you specify the
owner name. Instead, it returns the error, "Couldn't Decrypt File." This error occurs because
Btrieve v6.x requires that the data buffer length be set to the length of the owner name plus the
null terminator on an Open operation. Access sets the data buffer length only to the length of the
owner name.
Tables and the Btrieve File Format
Access can create a Btrieve file and define it to a set of DDFs that have been previously
defined by Xtrieve PLUS, NetWare SQL, or a similar application. Access refers to this action as
exporting a table in Btrieve format.
When exporting a table in Btrieve format, Access always adds the four-byte integer field
"M_I_C_R_O_S_O_F_T" as the first field of the table. Access also makes this field the only
index in the table.
Access translates its own data types into specific Btrieve data types when it exports a table in
Btrieve format. The list in Figure 5 shows the data types that result when Access exports data to
a Btrieve DDF file.
FIGURE 5: Resulting data types when Microsoft Access exports data to a Btrieve
DDF file
Access Data Type DDF Data Type
Text string
Number float
Date/Time date
Currency money
Counter integer
Yes/No logical
Memo note
OLE Object lvar
END of FIGURE 5
You can use Access to read a Btrieve file's format from one set of DDFs and then export
the table for that Btrieve file to another set of DDFs. You can also use Access to join, query, or
update the tables for Btrieve files that are defined in different sets of DDFs.
Access allows you to join Btrieve-based tables to tables that use other formats (such as Access,
Paradox, or dBASE IV). However, you cannot export data from such a joined view or restricted
query to a Btrieve file. You can export only single unrestricted tables to Btrieve format.
Transaction Processing
Access operations occur mainly inside transactions; therefore, you must configure Btrieve
for transaction processing.
Btrieve for Windows
WBTRCALL.DLL, the Btrieve for Windows DLL, is no longer packaged with Access.
You can purchase this DLL from Novell in the Btrieve for Windows Developer's Kit. The
Requester version of this DLL is available from CompuServe in the NOVLIB forum (Library 7,
BTRREQ.ZIP). You can use this Requester with Access to access Btrieve files that reside on a
NetWare v2.x, v3.x, or v4.0 server running the Btrieve engine. For information about how to
install the Btrieve engine packaged with your version of NetWare, see the Btrieve Installation
and Operation manual included in the NetWare documentation.
Access returns error -5001 if you are using the Btrieve v6.x Requester and WBTRVRES.DLL is
not available in your path. Access also returns error -5001 whenever it receives a Btrieve status
code that it has not been programmed to handle. Most of these Btrieve status codes are greater
than 90.
Access can also return the error Disk or Network Error. This error occurs if Access tries to read a
Btrieve file's associated DDFs using a pre-v6.x version of WBTRCALL.DLL, but the DDFs
have been created by Xtrieve PLUS, NetWare SQL, or other application that used Btrieve v6.x to
create those DDFs. This error resembles Btrieve Status Code 2, which Btrieve returns when an
application attempts to access a v6.x-formatted file with a client (v5.x) engine. To solve this
problem, either run the Btrieve v6.x NLM with the v6.x version of BREQUEST or
WBTRCALL.DLL, or make sure all files accessed with the client WBTRCALL.DLL are stored
in v5.x format.
AdvertiseService() & QueryService() Socket Numbers (NetWare Client SDK v1.00d)
AdvertiseService() in the NetWare Client SDK, advertises successfully, but the socket
number is swapped. This situation does not occur with the NetWare C Interface for DOS or the
NetWare C Interface for Windows.
You must use NWWordSwap() on the socket, which is returned by QueryService() or
BinderyScan(), prior to its direct use in ECBs or other APIs.
Calling Btrieve from 32-bit Applications (Btrieve for OS/2 v5.10)
The current Btrieve for OS/2 engine, v5.10, is a 16-bit DLL. In order to access this DLL
from a 32-bit OS/2 application, the Btrieve entry points have to be "thunked." Some aspects of
this process depend on which compiler you use. Figure 6 illustrates the process when using
Borland's 32-bit OS/2 compiler. Figure 7 demonstrates the process for IBM's C-Set/2 OS/2
compiler.
FIGURE 6: "Thunking" Btrieve entry points with Borland's 32-bit OS/2 compiler
#include
#include
#include
#define FPSZ char __far16 * /* Far pointer to null-terminated string */
#define FPUSHORT USHORT __far16 * /* Far pointer to unsigned short */
extern USHORT __far16 __pascal BRQSHELLINIT (FPSZ);
extern USHORT __far16 __pascal BTRVINIT (FPSZ);
extern USHORT __far16 __pascal BTRVSTOP (void);
extern USHORT __far16 __pascal BTRCALL (USHORT, FPSZ, FPSZ,
FPUSHORT, FPSZ, BYTE,
CHAR);
USHORT BTRV (USHORT, PSZ, PSZ, PUSHORT, PSZ, SHORT);
void main() {
.
.
.
}
/* Borland C++ interface to the Btrieve OS/2 dynamic link
library */
USHORT BTRV (USHORT operation, PSZ posblock, PSZ databuf,
PUSHORT datalen, PSZ keybuf, SHORT keynum)
{
BYTE keylen = 255;
CHAR ckeynum = keynum;
return (BTRCALL (operation, posblock, databuf, datalen,
keybuf, keylen, ckeynum));
}
END of FIGURE 6
FIGURE 7: "Thunking" Btrieve entry points with the C-Set/2 32-bit OS/2 compiler
#include
#include
#include
extern USHORT _Far16 _Pascal BTRCALL (USHORT, PSZ, PSZ,
PUSHORT, PSZ, BYTE,
CHAR);
extern USHORT _Far16 _Pascal BTRVINIT (PSZ);
extern USHORT _Far16 _Pascal BTRVSTOP (void);
extern USHORT _Far16 _Pascal BRQSHELLINIT (PSZ);
USHORT BTRV(USHORT, PSZ, PSZ, PUSHORT, PSZ, SHORT);
main() {
.
.
.
}
/* IBM C-Set/2 interface to Btrieve OS/2 DLL */
USHORT BTRV (USHORT operation, PSZ posblock, PSZ databuf,
SHORT datalen, PSZ keybuf, SHORT keynum)
{
BYTE keylen = 255;
CHAR ckeynum = keynum;
return (BTRCALL (operation, posblock, databuf, datalen,
keybuf, keylen, ckeynum));
}
END of FIGURE 7
Loader Cannot Find Symbol (NLM SDK for NetWare 4.0 v1.00b)
When an NLM compiled with NITERROR.H is loaded on a Netware 3.11 file server, the
loader cannot find the symbol __get__NWErrno_ptr. With the NLM SDK for Netware 4.0,
NITERROR.H defines NetWareErrno as
#define NetwareErrno *__get_NWErrno_ptr()
However, this symbol is not found in CLIB.NLM v.3.11d, so the loader returns an error message.
This symbol is actually located in CLIB.NLM v.4.0.
To make the NLM load under CLIB.NLM v.311d, either compile the NLM with the version of
NITERROR.H provided with the Network C for NLMs v.2.0e, or modify the NITERROR.H file
from the NLM SDK for Netware 4.0 as shown below.
#define NetwareErrno __get_NWErrno()
The symbol, __get_NWErrno(), is found in both the CLIB.NLM v.3.11d and v.4.0. The only
difference between __get_NWErrno() and __get_NWErrno_ptr() is that the latter will let you set
NetwareErrno to a value in addition to returning its value whereas __get_NWErrno() only returns
the value of NWErrno.
Defining UPPER.ALT ACS with Microsoft PDS BASIC v7.x (Btrieve (all versions))
Using PDS BASIC 7.X, if you want to define an alternate collating sequence to a
particular key, then in the Btrieve Create operation, you must allocate 265 bytes at the end of the
File Specification structure after all of the file and key specifications variables. The code segment
in Figure 8 demonstrates one method for performing this allocation.
FIGURE 8: Defining UPPER.ALT alternate collating sequence with PDS BASIC
v7.x
DEFINT A-Z
REM **** GLOBAL CONSTANTS
Const BCreate = 14
Const BString = 0
Const Duplicates = 1
Const Modifiable = 2
Const Sequence = 32
Const ExtendedType = 256
TYPE KeySpec
KeyPos AS INTEGER
KeyLen AS INTEGER
KeyFlags AS INTEGER
KeyTot AS LONG
KeyType AS STRING * 1
Reserved AS STRING * 5
END TYPE
TYPE FileSpec
RecLen AS INTEGER
PageSize AS INTEGER
IndxCnt AS INTEGER
NotUsed AS STRING * 4
FileFlags AS INTEGER
Reserved AS STRING * 2
Allocation AS INTEGER
KeyBuf AS KeySpec
AltColSeq AS STRING * 265
END TYPE
DIM FileBuf AS FileSpec
FileName$ = "SAMPLE.BTR "
PosBlk$ = SPACE$(128)
REM ************* SET UP FILE SPECS *************
FileBuf.RecLen = 20
FileBuf.PageSize = 1024
FileBuf.IndxCnt = 1
FileBuf.FileFlags = 0
REM ************* SET UP KEY SPECS ***************
FileBuf.KeyBuf(0).KeyPos = 1
FileBuf.KeyBuf(0).KeyLen = 20
FileBuf.KeyBuf(0).KeyFlags = ExtendedType + Modifiable + Duplicates + Sequence
FileBuf.KeyBuf(0).KeyType = MKI$(BString)
REM **** COPY 265 BYTES OF UPPER.ALT TO STRUCTURE VARIABLE
OPEN "UPPER.ALT" FOR BINARY AS #1 LEN = 265
GET #1,1,FileBuf.AltColSeq
CLOSE #1
BufLen = LEN(FileBuf)
CALL BTRVFAR(BCreate, STATUS, PosBlk$, VARPTR(FileBuf),
VARSEG(FileBuf), BufLen, FileName$, 0)
IF STATUS <> 0 THEN
PRINT"Error Creating File. Status = ";STATUS%;"
Press a key to continue"
DO
LOOP WHILE INKEY$=""
END
ELSE
PRINT"File SAMPLE.BTR Created Successfully!"
END IF
END
END of FIGURE 8
Directory Services & Stack Sizes (NetWare Client SDK v1.00d)
Some Directory Services (DS) functions require up to 6K of stack space. This requirement
can cause stack overflows if enough space has not been reserved.
Make sure the stack size is increased when making DS calls. At least an 8K stack is
recommended. The stack size may need to be increased if DS calls using RSA encryption are
used. Stack size can be increased as a linker option with Microsoft C. The following line is
required in the source file when compiling with Borland tools:
unsigned _stklen = 8192;
xFetch Option 5 Documentation Error (NetWare SQL (NLM) 3.00)
The NetWare SQL Relational Primitive xFetch(), option 5, is used to retrieve the record
positions of previously fetched records. The NetWare SQL Application Programming Interface
manual that comes with the NetWare SQL Developer's Kit v3.00 has a documentation error
concerning this option.
According to the manual, when fetching record positions, the lRecordCount parameter should be
set to zero. If this is done, xFetch() will return a successful status, but no positions will be
returned in the data buffer. To retrieve the position, specify the lRecordCount parameter to be the
number of records fetched on the previous xFetch() call.
Truncation of String Type Fields (NetWare SQL (NLM) v3.x)
If a table has a field of type "string" that is 25 characters long and it contains only 20
characters of data and you want to reduce the field size to 20 characters, the following statement
must be issued using XQL v2.11:
ALTER TABLE MODIFY char (20).
The statement is successful with XQL v2.11, but NetWare SQL v3.x returns the following status:
Status 850: Data value cannot be converted to new data type
This statement is illegal in NetWare SQL v3.x because it will not truncate a "string" type field in
this situation. You should first change all of the strings in the database to fit within the new field
size. For example:
UPDATE TABLE1 SET FIELD1 = LEFT(FIELD1, 20)
Then, call NetWare SQL to modify the size of the fields with the ALTER TABLE statement.
BTRIEVE.NLM & ELRDFX.NLM (NetWare Btrieve (NLM) v5.15)
NetWare v3.11 server performance degrades severely or hangs during heavy read/write
Btrieve operations. This issue has been resolved with the NetWare patch, ELRDFX.NLM. This
patch was previously provided in the NetWare v3.11 patch kit (311PTx), but has been removed
to call attention to the fact that if VREPAIR is run while this patch is loaded, data corruption can
result. The patch is now available on NetWire in the NSD area (ELRDFX.ZIP).
There is also a third-party companion NLM called ELRDCK.NLM that can be found in
NOVLIB, LIB16, in the file ELRDCK.ZIP. If this NLM is loaded, it will issue a warning and
sound a beep if there is an attempt to run VREPAIR with ELRDFX loaded.
Improving Disk I/O Speed (Network C for NLMs v2.0(e))
NetWare's "elevator seeking" design optimizes file I/O. For this optimization to work
properly, reads and writes must be cached at the server so they can be handled in an orderly
manner.
NetWare provides additional functions to NLMs that allow them to handle I/O more
immediately, but while these functions provide greater optimization for an application, they can
interrupt NetWare's "elevator seeking," thus degrading performance of other applications
performing file I/O. These functions are discussed below:
- Using FEsopen(), with the "write through" bit set, along with AsyncRead() and
qwrite() will improve disk I/O performance. The call to AsyncRead() returns a pointer to cache
where the retrieved data is located. This pointer is passed to qwrite() to write back to the same
cache. I/O speed increases because the application does not have to allocate its own read and
write buffers. Data can be flushed to disk using FEFlush().
- Direct File System (DFS) allows a developer to manipulate data directory on the disk.
DFS is not built in to NetWare v3.x, but is inherent in NetWare v4.x. DFS bypasses cache as
well as NetWare's "elevator seeking" method for writing to disk. You should only use DFS when
the NLM engine is solely responsible for servicing any files that it accesses.
- According to the documentation, qwrite() is faster than write(). qwrite() is faster because
it does not check buffer lengths or syntax like write(). The performance gain is minimal,
however.
- The call to gwrite() allows multiple buffers to be written while write() only handles one
buffer. The only other difference between these two calls is that gwrite() does not return until all
buffers are written.
Constants for GetPhysicalDiskStats() (NetWare C Interface for DOS v1.20)
According to the documentation, constants for the driveType field in the structure
PHYS_DISK_STATS should be defined in NIT.H. However, the constants are not found in
NIT.H or any other include files.
Constants for this field are defined as:
PDT_XT 1
PDT_AT 2
PDT_SCSI 3
PDT_COPROCESSOR 4
PDT_PS2MFM 5
PDT_PS2ESDI 6
PDT_CT_SBIC 7
Field & Table Names in Upper Case (NetWare SQL (NLM) v3.00x)
NetWare SQL (NLM) v3.00 returns field and table names in capital letters if SQL-Level
functions like XQLDescribe are used. This situation can interfere with an application written
under v2.11 if the application expects field or table names to be case-sensitive, particularly if the
it is performing string comparisons.
If you explicitly type field names in a select statement, the names returned by XQLDescribe will
be exactly as you typed them in the SQL statement. However, when you type "*" for the field
list, if the view contains more than on file, NetWare SQL returns the heading in the format,
"filename.fieldname." NetWare SQL v3.0 pulls the filename from an internal structure
containing the original file/view/alias name as typed in the SELECT statement.
With all fields selected, NetWare SQL must read the dictionary to get field names. If the
filename in the SELECT is in a different case than the field in the dictionary, you would end up
with names like "patients.FIRST^NAME" or "PATIENTS.First^Name." So, NetWare SQL
converts the names to uppercase to make the file and field names consistent. When there is only
one file in the view, NetWare SQL still converts the field name to upper case to make it
consistent with the way "*" works with multiple files in the FROM clause.
If you have an alias or view name in the FROM clause (and more than one file in the FROM
clause), NetWare SQL v3.0 returns "alias.fieldname" while NetWare SQL v2.11 returns
"file.fieldname." For example, with the statement:
SELECT * FROM patients a, appointments b
where a.id = b.id
NetWare SQL v2.11 returns the names as:
Patients.ID Patients.First^Name Patients.Middle^Name
...
NetWare SQL v3.0 returns the names as:
A.ID A.FIRST^NAME A.MIDDLE^NAME ...
If names must be returned in a particular case, enter each field in the SELECT statement the way
you would like to see it returned by XQLDescribe. Also, the Primitive level functions such as
xDDFile and xDDField will not return the names in capital letters. They will be returned exactly
as they were entered into the data dictionary, since these primitive-level functions read the
dictionary directly.
Set Directory Operation Fails To Change Drive Btrieve for DOS v5.10a
After a Btrieve Set Directory (17) operation is issued to change the current drive and
directory, the current directory is left unchanged.
The Set Directory (17) operation is documented as having the ability to change the current drive
and directory at the same time in one call. With all 5.x versions of client Btrieve and all versions
of NetWare Btrieve through v6.10, Set Directory does not function as documented. If you
attempt to change the drive and directory to a drive and directory other than the current one, a
status 0 (Successful) is returned, but the current drive and directory will be left unchanged. The
operation functions correctly if there is no attempt to change the current drive, but only the
current directory.
To change the current drive and directory with the Set Directory operation, you must call the
operation twice. First, issue the function only specifying the DRIVE:. Doing so will change the
current drive to the drive specified on the call. Then, issue the Set Directory operation once again
specifying the desired path.
Illegal UNION in CREATE VIEW Statement (NetWare SQL (NLM) v3.00x)
When a UNION statement is implemented with a CREATE VIEW statement, only the
records from the first SELECT statement are returned. This situationwas originally reported as a
bug.
Actually, the use of a UNION statement with a CREATE VIEW statement is illegal for the SQL
standard. An error message will be implemented which corresponds to this situation.
API Requires Larger Buffer (Network C for NLMs v2.0 (e))
FEMapVolumeAndDirectory() is passed a buffer in which it returns the NetWare-style
path. In addition to returning the path in this buffer, however, it also returns a second copy 500
bytes beyond the beginning of the buffer. If the buffer is not large enough to hold both of these
copies memory corruption will occur.
CLIB v3.11 places the second copy approximately 240 bytes after the first; CLIB v3.11d puts the
second copy 500 bytes after the first. To ensure that no corruption occurs, add at least 500 bytes
to your buffer size. For example, if you are expecting the returned path to be no larger than 100
bytes allocate at least a 600-byte buffer for the path.
Running NetBIOS in a DOS Session with OS/2 (NetWare OS/2 SDK v2.0)
You cannot run the DOS NetBIOS emulator in a DOS session under OS/2 when you have
loaded the OS/2 NetBIOS emulator. You can use the DOS NetBIOS TSR from a private DOS
box if OS/2 NetBIOS is not loaded. Conversely, the OS/2 NetBIOS is fully functional, but
unavailable to DOS sessions.
You may use IBM's virtual NetBIOS for DOS simultaneously with Novell's NetBIOS for OS/2 if
you install NTS/2 from IBM to support multiple protocol stacks. Doing so will alter your
CONFIG.SYS file to use IBM's landd, lanpdd and lanvpp devices files, which will remap the
NetBIOS calls to the OS/2 NetBIOS daemon.
Fast Answers to Common Questions
AppWare
Q - Where can I get information on AppWare?
A - Call 1-800-NETWARE (1-800-638-9273) or 1-801-429-5588 and choose the
option for Novell's Automated Fax System (AFS). Then, request document #2900. This
document is approximately 20 pages long.
MacIPX SDK
Q - When I call SpxTerminateConnection() all I have to do is check the ECB status
and make sure the status was successful. Do I have to actually set up the Macintosh queue and
look at the packet?
A - Yes, you could check for a successful status, but it is safer to make sure the status
is no longer ST_SENDPACKET. If the remote end crashed just before you sent the terminate
packet, the terminate packet probably would never be sent successfully (i.e., it would not get
"ACKed"). MacIPX would try to retransmit it a number of times, then abort the connection. In
this case, the ECB will indicate that the connection was aborted. By checking that the status is
not ST_SENDPACKET, you know that either the packet was "ACKed," or that MacIPX aborted
the connection.
This function is asynchronous, so you cannot use a "stack" ECB. It must be allocated, or it
must be a global function.
NetWare
Q - Do I need to make any changes to my application to run it under NetWare SFT
III?
A - No, everything is taken care of at the SFT level. Even if the primary server goes
down, the SPX connection will still be valid.
Q - How can I identify the actual file server on which a queue resides under NetWare
Name Services?
A - The DOMAIN QUEUE OBJECT has a property called Q_FILE_SERVER that
contains the name of the server that the real queue is on.
NetWare Client SDK
Q - Where can I find the latest version of the DOS workstation files, including the
DOS Requester?
A - These files are located on CompuServe in the NOVFILES forum, DOS\Windows
Client area. The name of the files to be downloaded are:
- WSDOS1.EXE
- WSWIN1.EXE
- WSDRV1.EXE
NetWare Btrieve (NLM)
Q - After selecting a Named Database to backup, the following error messages were
returned:
Error: File not found for database
Error: Btrieve status 0 reading FILE.DDF dictionary file for database
Error: Status 88 received on Btrieve End Continuous Operations.
Why did this occur and what should I do?
A - The NetWare SBACKUP utility uses both NetWare SQL v3.00 and NetWare
Btrieve v6.00. Basically, a status 88 will occur if there is anything wrong with the Btrieve files.
In this case, a file that was associated with the Named Database was not in the directory that the
utility was trying to backup.
This status will also be returned if the files selected for backup were already in Continuous
Operations. The SBACKUP utility will itself do a Continuous Operations on all the files
associated with the Named Database. Thus, the utility will not be able to perform the backup.
The simple solution is to ensure that all files are in the proper location specified in the
Named Database. The other solution is to ensure that the files are not in Continuous Operations
when using the SBACKUP utility.
Btrieve for Windows
Q - Are there any third-Party ODBC drivers for Btrieve for Windows?
A - Q+E Software (formally Pioneer Software) has a product called ODBC Pack 1.0.
This product currently includes 11 drivers for various database engines, including Btrieve. Q+E
technical support said that the Btrieve file must be in NetWare SQL format. In other words, it
requires .DDF files. The product also includes a utility to build the .DDF files if you do not have
them.
NetWare SQL (NLM)
Q - NetWare SQL v3.00 returns a status 2103 (NetWare SQL not active on the
requested server) when I load NetWare SQL on the server. Why?
A - NetWare SQL v3.00 will return a status 2103 when the maximum number of
configured SPX sessions is reached. Load NDBSETUP and set the 'Maximum Number of SPX
Clients' option to a higher value.
Q - How do I run SQLSCOPE from an OS/2-Windows session?
A - Setup a Private DOS box and log in to the network from that DOS box. Then,
load NSREQ, make sure that WXQLCALL.DLL is in the path, and run WINOS2 SQLSCOPE.
The above procedure can be used for any Windows-based NetWare SQL v3.0 application.
Available Novell Developer Education Courses
Novell Developer Education offers several courses for developers who use Novell's
development & database tools, including NetWare SQL, Btrieve, Xtrieve PLUS, and the
NetWare Client APIs.
904 - Btrieve: An Overview
905 - Programming with Btrieve
907 - Xtrieve PLUS
911 - NetWare Database Administrator
912 - Programming with NetWare SQL
930 - Developing NetWare Loadable Modules (NLMs)
940 - NetWare Programming: Basic Services
945 - NetWare Programming: Protocol Support
To obtain information on pricing, location, scheduling, and course content for classes held in the
US, call 1-800-233-3382, 1-801-429-5508 or 1-800-NETWARE. For information on classes
outside of the US, contact your local Novell office.
The latest NetWare drivers, example code for NetWare API development tools, OS/2 requester
patches, and patches for Novell's database products are available on Novell's NetWire forum on
CompuServe. Back issues of Bullets and developer FYIs are also available (NOVLIB, library
11). New information is first stored in NOVLIB library 1, and moved to library 7 after a period
of 30 days. If you do not have access to CompuServe, request these files from Novell's
Developer Support Group at 1-800-NETWARE (1-800-638-9273) or 1-801-429- 5588.
When calling, be ready to provide a shipping address, disk preference (5.25", 3.5", HD, or DD)
and, if you prefer overnight delivery, your company's Federal Express account number. If you do
not provide a Fed Ex account number, the patch disk will be sent to you via regular mail.
Novell Professional Developers' Program members can obtain updated NetWare API SDK
components from Novell's NDEVREL forum on CompuServe. For more information on Novell
developer programs contact Novell at 1-800-NETWARE (1-800-638-9273) or 1-801-429-5588.
Novell's Developer Relations Automated Fax System
A document describing available patches and other files and their location on CompuServe
is available through Novell Developer Relations Automated Fax System (AFS). This system can
provide you other useful information as well. To use the AFS, call 1-800-RED-WORD
(1-800-733-9673) or 512- 794-1796 from a touchtone phone. Then, choose the option for the
Automated Fax System, select the documents you wish to receive, and supply your fax number
(the fax number to which you want the document(s) sent). Document #7805 describes the
patches. Document #1 lists all other documents available through the Automated Fax System. Up
to five documents can be requested per call.
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
Feature Articles: Ken Lowrie, Holly Roff, Vicki L. Smith
Contributors: Gaurang Amin, Linda Anderson, Vitek Boruvka, Ralph Ellis, Steve Iribarne,
Sadruddin Khawaja, Rudy McNeese, Clint McVey, Chris Ojeda, Paige Parker, Matt
Pinsonneault, Raj Perubhatla, Mike Shoemaker, Nancy Sneary, Michael A. Spano, Aslam Tejani,
Howard C. Thamm, and Brenda Wallace Special thanks to the Developer Support, Development,
Developer Relations, Product Marketing, and Marketing Communications staff who contributed
time and valuable input.
(c) 1993 Novell, Inc. All rights reserved.
Novell, the N design, NetWare, Btrieve, XQL, LAN WorkPlace, NetWare Name Services and
LANalyzer are registered trademarks; NetWare Loadable Module, NLM, NetWare Global
Messaging, Global MHS, NetWare MHS, NetWare System Calls for DOS, NetWare Runtime,
NetWare SQL, NetWare Btrieve, NetWare C Interface for DOS, NetWare System Interface
Technical Overview, NetWare RPC, NetWare RPC 386, NetWare LU6.2, Report Executive,
NetWare Asynchronous Communication Services (NACS), NetWare Asynchronous Services
Interface (NASI), NetWare Management System, NetWare 3270 LAN Workstation, NetWare
SFT III, Xtrieve PLUS, DeveloperNet Labs, IPX, and MacIPX are trademarks; and NetWire and
Professional Developers' Program are service marks of Novell, Inc. IBM and OS/2 are registered
trademarks, and NetBIOS and SAA are trademarks of International Business Machines
Corporation. Microsoft and CodeView are registered trademarks, and Windows, Windows NT,
Microsoft QuickBasic and Visual Basic are trademarks of Microsoft Corporation. Apple,
AppleLink, AppleTalk, Macintosh, and Macintosh Programmers Workshop (MPW) are
registered trademarks of Apple Computer, Inc. CompuServe is a registered trademark of
CompuServe Corporation. Sun Microsystems and NFS are registered trademarks; and TI-RPC is
a trademark of Sun Microsystems, Inc. UNIX is a trademark of UNIX Systems Laboratories, Inc.
in the USA and other countries. UNIX Systems Laboratories is a wholly-owned subsidiary of
Novell, Inc. Univel and UnixWare are trademarks of Univel, Inc. Paradox is a registered
trademark of Borland International. dBASE IV is a registered trademark of Ashton- Tate
Corporation. WATCOM and WATCOM C are registered trademarks of WATCOM Systems,
Inc. Sybase is a registered trademark of Sybase, Inc. Oracle is a registered trademark of Oracle
Corporation.
 |
|
|
 |