FEBRUARY 1994 VOLUME 6 NUMBER 2
INDEX
The NLM Developer's Troubleshooting Checklist for NetWare 4.x
NetWare 4.x is being widely adopted by businesses interested in enterprise-wide
networking solutions. In response, many developers have started writing a 4.x NetWare Loadable
Modules (NLMs) or porting existing NetWare 3.x NLMs to the NetWare 4.x platform.
From conversations with these developers, Novell Developer Support has found that the
majority of NLMs written for NetWare 3.x simply load and run under NetWare 4.x. However, in
some cases, aspects of the NetWare 4.x environment require you to modify your NLMs. This
article presents the most common of these special cases in a format designed for quick reference,
and assumes the reader is familiar with the NetWare 3.x NLM environment.
New Memory Checking Features
The NetWare v3.12 and v4.01 debug versions of CLIB (CLIBDEB.NLM) include
additional messages to help you locate un-freed resources. Many developers find these messages
helpful. For documentation on this feature, look in the file, README.NOV, in the NLM SDK
v3.0.
WATCOM Compiler v9.5 Patches
If you use WATCOM's v9.5 compiler and write in C++, be sure to obtain all patches and
install them before you begin your development effort. To obtain the latest patches (levels A and
B), contact WATCOM at 1-519-886-3700 (or on their BBS at (519) 884-2103).
Switches Required Under Domain
Currently under NetWare v4.01, the code segment of an NLM running in the
OS_PROTECTED domain is flagged "execute only." If you use certain WATCOM switches, the
compiler will attempt to read the code segment. Doing so causes the OS_PROTECTED domain
to be quarantined. Always remember:
- Use the "/ms" switch when compiling with WATCOM to run under Domain.
Using "/ms" forces the code generator to include CS: overrides when accessing constants
in the code segment. 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 by 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 seems to work, but may not be the optimal solution for all NLM
developers.
- Do not use the "/zc" option that places literal strings in the code segment.
Stack Sizes
Under NetWare 4.x, a CLIB thread requires a minimum stack size of 8KB. If you specify
a smaller stack size, it will automatically be increased to 8KB. However, if you allocate the space
yourself and pass that pointer as well as the size to BeginThread(), an error will return indicating
the thread could not start because the stack size is too small. You have to increase this to 8,202
bytes (8KB plus overhead).
Exit Routines
NetWare 4.x has additional memory protection. Once memory is freed, it no longer
belongs to your NLM, so accessing this resource after it has been freed can cause problems.
Because the memory protection was less stringent under NetWare v3.1x, some functions worked
in exit routines with NetWare 3.x that really should not have be allowed.
Exit routines include those registered with atexit() and atunload(). If you attempt to clean up
or close resources that are at the thread group level, you need to do this clean up in a signal
routine or within the thread before it ends. Activities requiring this procedure include closing
files and destroying screens.
File Monitoring Hooks
The file monitoring hook is a new feature in NetWare 4.x that allows you to hook a file
operation before or after the actual operation occurs. If, while in the monitoring thread, you wish
to change context to a thread group other than the thread that resistered the hook, you must set
the context specifier, set the hook, and then clear the specifier.
To alter the thread context, use the functions SetThreadContextSpecifier() and
GetThreadContextSpecifier(). Then, when the thread starts, change to the correct thread group
(see Figure 2). If you can operate under the thread group that registered the hook, CLIB will set
up this context for you.
FIGURE 2: File system monitor hook example
:
:
BYTE in_use = 0;
int mainThreadGroupID;
main()
{
mainThreadGroupID = GetThreadGroupID ();
:
: "wrap" monitor hook call for context specification
:
SetThreadContextSpecifier(GetThreadID(),NO_CONTEXT);
ccode = NWAddFSMonitorHook(FSHOOK_PRE_OPENFILE, openFileCallBackFunc,
&preOpenFileHandle);
SetThreadContextSpecifier(GetThreadID(),USE_CURRENT_CONTEXT);
}
int openFileCallBackFunc(OpenFileCallBackStruct *ofcbs)
{
static int cnt = 0;
int ccode = 0, interruptedThreadGroupID;
char user[48];
WORD objType;
long objID;
BYTE loginTime[7];
LONG pc;
BYTE ps[255];
BYTE volName[16];
interruptedThreadGroupID = SetThreadGroupID (mainThreadGroupID);
ccode = GetConnectionInformation(ofcbs->connection, user, &objType,
&objID, loginTime);
:
:
// dump out info. to a 'log file' within the call back routines.
if (!in_use) {
int f_handle;
in_use = 1;
f_handle = open ("SYS:LOG\\OPENS.LOG", O_CREAT|O_RDWR);
if (f_handle !=-1){
Printf("open(pre) request.conn=%d.user=%s", ofcbs,
user->connection);
close (f_handle);
}
in_use = 0;
}
:
:
errorOut:
SetThreadGroupID (interruptedThreadGroupID);
return ccode;
}
END of FIGURE 2
Forcing NetWare 4.x NLMs to Stay Loaded
With NetWare 3.x NLMs, to prevent an NLM from unloading, you had to register the
check() function and force an ungetch() of a "N" to the console at the correct time. This process
is much simpler under NetWare 4.x. Two 4.x APIs called SetNLMDontUnloadFlag() and
ClearNLMDontUnloadFlag() change a flag in the NLM header that prevents the NLM from
being unloaded at the console.
Thread Management
The NetWare 4.x OS kernel design has changed. Kernel processes for polling, scheduling,
and idling have been replaced with a more dynamic process management paradigm. Processes
are now considered threads, and the kernel can now use multiple "run queues" to ensure fair
treatment of all system processes. One facility to execute fair treatment is handicapping threads.
- You can specify Temporary and Permanent Handicaps of Threads.
Developers use the NetWare Internal Debugger to analyze NLMs if they trigger an abend or
"lock up." When you invoke the debugger, a ".p" command checks the different processes
currently allocated. In one recurring scenario for new NetWare 4.x developers, the server seems
to "hang," and the developer invokes the debugger. One of the processes dedicated to handle
screen I/O is listed under "Processes not on the run queue" and the reason is listed as
"handicapped wait." "Handicapped wait" is a new NetWare 4.x state that a process or thread
enters, either implicitly or explicitly, when the process is delayed for whatever reason.
Handicaps come in two varieties: temporary and permanent. A process can become
temporarily handicapped if you call ThreadSwitchWithDelay(). This call reschedules the thread
to be placed on the RunList after a specified number of context switches have taken place.
The number of switches in each temporary handicap is a specifiable parameter inside
NetWare ( see NetWare NLM Library Reference Volume II, Edition 1.1,
"ThreadSwitchWithDelay," p. 1415).
A process can become permanently handicapped in two ways. Calling SetThreadHandicap()
sets an explicit permanent handicap by setting the number of context switches a thread is
permanently handicapped before being rescheduled (see NetWare NLM Library Reference
Volume II, edition 1.1, "SetThreadHandicap()," p. 1225).
Under NetWare 4.x, the kernel also is able to permanently handicap a process if
necessary. (This would be an implicit handicap from the programmer's point of view.) If a
particular NLM does not yield frequently enough, a handicap can be placed on the thread's
Process Control Block (PCB) by the operating system. This handicap prevents the thread from
rescheduling itself immediately.
For example, if a handicap of 100 is placed on a thread, 100 other processes will run and
yield before that thread is rescheduled on the RunList (see NetWare 4.0 Architecture, Rev. 6.0,
May 1993, "Temporarily Handicapping a Thread," "Permanently Handicapping a Thread," p.
Kernel-5).
- The kernel executes threads in a specific order.
Interrupts are handled first, followed by worker, then threads, then permanently handicapped
threads, then temporarily handicapped threads. When none of the above want to run, except
temporarily handicapped threads, low priority threads can run (see NetWare 4.0 Architecture,
Rev. 6.0, May 1993, "3.2 Six Priority Levels," page Kernel-4).
- The new kernel no longer has to schedule work.
When a thread has to be run, the kernel runs the work directly. Because of this new
paradigm, the number of thread switches is minimized, making it very inexpensive for the
running process to yield control to check if other processes want to run (see NetWare 4.0
Architecture, Rev. 6.0, May, 1993, "3.5 Implications," p. Kernel-12).
Using Handles with NetWare 4.x
With NetWare 4.x, new definitions were introduced for old NLM concepts like handles.
Under NetWare 3.x, for example, the word "handles" was used to describe access to screens, TLI
endpoints, semaphores, and files. Since handles were usually associated with files under
NetWare 3.x, this concept was accepted. Under NetWare 4.x, however, the concept of handles
has changed. Listed below are six ways this change affects developers.
- CreateScreen() from a 3.x NLM requires a DestroyScreen() under NetWare 4.x.
NLMs developed under NetWare 3.x that access the System Console screen will receive
messages from NetWare v4.01 regarding unreleased memory resources when the NLM
terminates. This problem becomes apparent in NetWare v4.01, since CreateScreen() now returns
a screen handle to each screen for each NLM calling CreateScreen(). Simply call
DestroyScreen() before terminating the NLM to remove the unreleased memory resources
warning message.
- Under NetWare 4.x, accessing another NLM's screens requires a new procedure.
Under NetWare 3.x, you can access another NLM's screens by calling ScanScreens() and
GetScreenInfo(). The screen handle returned from GetScreenInfo() can then be used since the
handle is unique.
Under NetWare 4.x, this procedure does not work because the screen handle is unique only
to its NLM. You must access another NLM's screens in a different way. Call ScanScreens() to
retrieve all screen IDs. Then, pass the screen ID (typecast to char *) to CreateScreen() as the first
parameter to obtain a screen handle to that screen.
- OpenSemaphore() returns a 0 handle.
In versions of NetWare before 4.x, many developers checked for a zero semaphore handle as
an error condition. In NetWare 4.x, a zero semaphore handle is considered a valid handle.
- t_open() does not return a unique number.
Prior to NetWare 4.x, t_open() returned a handle that was actually a pointer, so it was unique
across all NLMs. Under NetWare 4.x, file opens return handles, much like handles under DOS.
Since t_open() used the CLIB open() call internally to gain access to the streams, it now returns a
handle. This handle is unique only to the NLM that called open(), so the handle plus the NLM ID
is unique across all NLMs under NetWare 4.x.
- I/O Redirection is supported for NetWare 4.x only.
I/O Redirection on first-level files and file handles is supported only for NetWare 4.x (dup
and dup2). Redirection of second-level files is supported for all NetWare versions (Stream I/O
Services).
- The maximum number of file handles that can be open at once for NetWare 4.x is 1700.
NWSNut Development
The NLM SDK v3.0 gives you the ability to create NLMs with the Novell NetWare NLM
look and feel utilizing the NWSNut APIs. The NDEMO example included in the SDK
demonstrates the basic capabilities of NWSNut. Following are some of the issues developers
have encountered when developing with NWSNut. If you are developing with NWSNut, there
are several precautions you should keep in mind:
- Always call NWSInitializeNUT() for each CLIB screen/NUT handle pair.
NWSInitializeNUT() creates the NWSNUT screen with a header and a NUTInfo structure
containing NWSNUT data. This structure allows NWSNUT to monitor of NWSNut for each
NLM that may be using NWSNUT services concurrently.
- Always call NWSRestoreNUT() for each CLIB screen/NUT handle pair.
You must notify NWSNUT when you are through using the NWSNUT resources. Then
NWSNUT can free memory allocated on your behalf and prevent later memory accesses that
may be invalid once your NLM is unloaded.
- Default messages must be linked into your NLM.
NWSNut requires you to link default messages into your NLM. These messages are
normally created using the Message Tools included with the SDK. The NLMLink linker supplied
by Novell and WATCON's WLink v9.5 linker support the linking of message files.
- There are two known problems with NWSNut and related utilities.
The NWSNUT import file causes errors to be generated at link time if you use it unmodified.
Add commas to all entries missing trailing commas in the import file to rectify this problem.
Also, the MSGLIB utility which ships with the SDK requires an updated version of the
IBM$RUN.OVL file. This file is available on CompuServe in the NDEVREL forum (Section 7,
IBMRUN.ZIP).
- NWSNut NLMs will run on the NetWare 3.x platform as long as you are also running the
AFTER311 compatibility module.
Directory Services & NetWare 4.x
NetWare Directory Services (DS) is Novell's implementation of enterprise-wide network
access and replaces the older server-centric bindery. The primary purpose of the Directory is to
provide dynamic name-to-address mapping between objects and addresses. NLM development of
Directory-Aware applications is very similiar to client Directory Services application
development. When developing to Directory Services, always remember:
- You should define NWNLM before including DS header files.
Defining NWNLM before including the Directory Services header files ensures that the
compiler's preprocessor will process the header files correctly for the NLM environment.
- NWDSMapNameToID() is required with QMS and DS.
The NWDSMapNameToID() function is required when working with Queue Management
Services (QMS) and Directory Services. When used against the Host Server of the queue, this
function returns an object ID of the queue, queue server, queue user, or queue operator. One
important note: the ID returned is only valid for the duration of Directory Services login.
- Directory Services examples are available from Novell.
Using NetWare Directory Service is really not as difficult as you may have been led to
believe. Novell Developer Support now has examples for creating user objects, accessing QMS,
as well as many other Directory-Aware services.
Though by no means all-inclusive, this information will save you time and energy as you
continue your development in the NetWare 4.x NLM platform. If you have additional questions
about NetWare 4.x, NLM development, or porting 3.x NLMs to the 4.x environment, please
contact Novell Developer Support at 1-800-NETWARE (1-800-638-9273) or 1-801-429-5588.
Introduction to the NetWare Btrieve RECPLAY Utility
Novell's Btrieve Developer's Kits contain tools such as BUTIL and BTRTOOLS to make
Btrieve application development a smoother process. Additional tools and toolsets are also
available to developers and network administrators through Novell Developer Support and
Novell's NOVLIB forum on CompuServe (Library 7, BTOOLS.EXE) for troubleshooting
Btrieve applications. This article provides an introduction to one of these toolsets, RECPLAY.
RECPLAY gives developers and system administrators a specialized set of tools for
troubleshooting NetWare Btrieve v6.x applications. Specifically, RECPLAY allows you to:
- Isolate Btrieve or NetWare SQL problems by looking at the sequence of Btrieve
operations that take place before the failure.
- Isolate network and hardware related issues by replaying the history file on a different file
server or network.
- Resolve timing related problems and facilitate testing and debugging by replaying the
history file.
- Isolate performance issues by recording the start and end time of every operation. This
allows the user to recognize which Btrieve operations take longer to execute.
RECPLAY contains four separate tools:
- BRECORD.NLM
- DUMPTR.EXE
- CRDUMP.EXE
- BREPLAY.NLM
This article provides a general description of each tool in the RECPLAY toolset and how
they can be used together. Specific details on the various options available for each tool are
documented in a text file that is supplied with the RECPLAY toolset.
General Usage
In some environments, it is useful to see what Btrieve calls are being made by an
application. For example, NetWare SQL users may wish to find out which Btrieve calls are made
as a result of running a particular SQL statement. To record Btrieve calls for viewing:
- Load BRECORD at the file server.
- Run the application.
- Unload BRECORD.
- Run the DUMPTR utility on a DOS workstation.
For debugging purposes, it may be helpful to record Btrieve calls and then replay the calls
on the same or a different server. To do this:
- Load BRECORD at the file server.
- Run the application.
- Unload BRECORD.
- Run DUMPTR to create a script file out of the history file that was created by
BRECORD. You may make modifications to the script file if you wish.
- Run CRDUMP to convert the script file to a binary file. This step is unnecessary if you
did not make any changes to the script file created in step 4.
- Load BREPLAY and specify the binary file from either:
- Step 5, if you have made changes to the script file, or
- Step 1, if you simply want to replay exactly what your application did.
Tool Usage: BRECORD.NLM
BRECORD.NLM records all Btrieve calls into a history file. Any workstation executable
or other NLM can make these calls. BRECORD.NLM can be configured to only record the calls
for specific Btrieve files or all files.
BRECORD.NLM creates the history file immediately after you load it. However, it will be 0
(zero) bytes in size until BRECORD is unloaded. This history file is stored in binary format and
can be viewed with the DUMPTR utility.
BTRIEVE.NLM v6.x must be loaded before you can run BRECORD.NLM.
The following command will record all Btrieve operations made to a file called
PATIENT.DTA located in SYS:\DATA into a binary file called BREC.DMP in the same
directory. Btrieve will create BREC.DMP or overwrite it if it already exists in SYS:\DATA.
LOAD BRECORD /f=sys:\data\brec.dmp
/n=sys:\data\patient.dta
Tool Usage: DUMPTR.EXE
DUMPTR.EXE is a DOS workstation utility that displays readable output from the history
file to the screen. You can redirect this output to a file using the DOS redirection operator.
DUMPTR.EXE also creates a script file which can be edited and formatted back to a new history
file.
As an example, the command below will read the binary file BREC.DMP created by
BRECORD.NLM and display all the Btrieve operations that were recorded, including the key
and data buffer of each call. The resulting output will be redirected to the BREC.TXT file.
DUMPTR /f=\data\brec.dmp /k
/s >brec.txt
Figure 3 shows an example of the output created by the previous DUMPTR command.
The Btrieve operation being performed is shown in the "opcode" column, and the resulting status
of this operation is listed in the "stat" column (0 indicates that the Open operation was
successful). The "cursor ID" represents a handle to a file for operations that access a file (i.e.,
Open or Get Equal). This column will be blank for non-file operations such as Version or Reset.
The cursor ID specified on the Open is used to identify the file on subsequent operations. For
example, if you see a Get Equal on cursor ID 2, you will know it is reading the PATIENT.DTA
file.
FIGURE 3: Example output file format redirected to BREC.TXT
System
opCode stat cursor client ID key start t. end time exec.t.
ID number (0.1 ms)
------------------------------------------------------------------------
Open 0 2 0200400a 0 24 63 39
key buffer:41 55 53 2d 54 45 4b 33-31 31 2f 53 59 53 3a 44 SERVER10/SYS:...
41 54 41 2f 50 41 54 49-45 4e 54 2e 44 41 54 00 DATA/PATIENT....
data buffer:00 00 00 00 00 00 00 00-00 56 00 da 84 56 00 00 .........V...V..
00 57 00 84 20 00 00 00-00 00 00 00 00 00 00 00 .W..............
00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
END of FIGURE 3
The "client ID" references the user who made the Btrieve call. All calls from the same
user will have the same client ID. The "key number" column will show the key number used on
the call, or will be blank for operations that do not use a key number.
The system times ("start t.," "end time," and "exec.t.") represent the system start time, end
time, and execution time for that operation. In the example in Figure 3, the Open operation took
3.9 milliseconds.
The key buffer and data buffer information shows what is being sent in to Btrieve for the
particular call. The buffers are shown both in hex and in ASCII. Again, these parameters will
only show when appropriate. For example, the key buffer is required for an Open, Get Equal, Get
Next, Create, etc. The data buffer is required for an Open, Get Next Extended, Get Direct, etc.
You can also enter a command to create a script file. The following command generates as
scriptfile called, SCRIPT.TXT, and dumps the Btrieve operations recorded by BRECORD.NLM
from BREC.DMP to this text file.
DUMPTR /f=\data\brec.dmp
/r=script.txt
Tool Usage: CRDUMP.EXE
CRDUMP.EXE is a DOS workstation utility that formats a script file to a binary file.
Script files created with DUMPTR.EXE can be edited for troubleshooting purposes and
reformatted in binary format using CRDUMP.EXE. This binary file can be used by
BREPLAY.NLM to re-execute all of the operations.
The following example command converts the script file, SCRIPT.TXT, created by the
DUMPTR utility with the /r option, into a binary file that can be used by BREPLAY.NLM.
CRDUMP script.txt brec.fil
Tool Usage: BREPLAY.NLM
BREPLAY.NLM executes Btrieve calls previously recorded by BRECORD.NLM. To run
BREPLAY.NLM, BTRIEVE.NLM v6.x must be loaded.
The following example command replays every operation that has been previously recorded
by BRECORD.NLM or created from a script file with CRDUMP.EXE. It also writes a status
report to a list file named BRECLST.OUT after every 200 operations are played.
LOAD BREPLAY /f=sys:\data\brec.dmp /p=200 /l=sys:\data\breclst.out
RECPLAY is an in-house utility made available to developers and network
administrators as a courtesy. This utility is provided as is and it is not an official Novell product.
Novell is not responsible for maintaining or enhancing this product.
For more information on this toolset, contact Novell at 1-800-NETWARE (1-800-638-9273)
or 1-801-429-5588.
t_event() is Not Supported (NetWare Client SDK 1.0e)
The prototype for the function t_event() is contained in the TIUSER.H file, but this
function is not supported. For this reason, t_event() is not documented and this function should
not be used.
The prototype for this function will be removed from the header file in future releases of the
NetWare Client SDK.
NWSetAuditingIdentityFails with Error 0x97 (NLM SDK 3.0)
The call to NWSetAuditingIdentity() fails with the error, 0x97
(ERR_AUDITING_NOT_ENABLED) even though the user has enabled auditing for Directory
Services via AUDITCON.
The AUDITCON utility must be used to initiate auditing server events. To enable auditing
on a volume from the AUDITCON main menu, select "Available Audit Options". Then, in
sequence, choose:
- Auditing Configuration
- Audit By Event
- Audit By Server Events
- NLM Add User ID Record
Changes must be saved before the NLM function will work. On page 53, the NetWare
Using NetWare Services for NLMs v1.1 manual notes:
"For Auditing to begin adding records from your NLM, the AUDITCON option "NLM Add
Audit Record" has to be enabled. For details, see the section "Server Events" in the chapter on
Auditing in NetWare 4.0 OS Architecture."
The NetWare 4.0 OS Architecture manual (Chapter 8, page Auditing-9) also describes
Auditing Options for Volumes and Servers. It does not men-tion needing to enable auditing for
setting an identity.
UC Option on Btrieve Extended Operations (Btrieve v5.x and v6.x)
Btrieve v5.1x and above now support the UC option on the Get Next Extended (36) and
Get Previous Extended (37) operations. This option tells Btrieve to begin searching for records
that match the provided filter (if defined) with the current record instead of the Next/Previous
record. The application still must establish positioning with a Get First (12), Get Equal (5) or
some other operation before using this option in the extended call.
UC functionality is automatically provided in the 5.15 and 6.x versions of the NetWare
Btrieve NLM. All other current versions of Btrieve must be patched in order for the UC option to
be functional, including:
- NetWare Btrieve VAP (BSERVER.VAP v5.15),
- Btrieve for DOS (BTRIEVE.EXE v5.10a)
- Btrieve for MS Windows (WBTRCALL.DLL v5.10)
- Btrieve for OS/2 (BTRCALLS.DLL v5.10)
Patches for these versions of Btrieve are available in Novell's NOVLIB forum on
CompuServe (Library 7, BTR515.EXE or BTR510.EXE depending on the version of Btrieve
being used). You can also obtain these patch files from Novell Developer Support (see
"Contacting Novell" at the end of this issue).
The UC functionality is also available with the Step Next Extended (38) and Step Previous
Extended (39) operations, but only with the Btrieve NLM (v5.15 and all 6.x versions). The UC
option can not be used on the Extended Step operations when using the client versions of Btrieve
or the Btrieve VAP. Any attempt to do so will return a successful status code, but no records will
be returned in the data buffer.
Documentation for MSGLIB Missing (NLM SDK 3.0)
The NLM Development and Tools Overview discusses the messaging services in Chapter
14. All of the components of messaging are described except for MSGLIB. This oversight has
been reported and will be corrected as soon as possible.
UMSG_GET_SEL_NEXT and List Component (AppWare Foundation for Windows 1.70)
With a multiple selection list instance for which multiple line items are selected, if you
would like to retrieve all selected items, you must:
- Get the index of the very first selection using the USMG_GET_SEL message
- Use the index of the first selection as "param1" in a UMSG_GET_SEL_NEXT message
to obtain the next messages.
However, only the index of the current selection is returned. This situation occurs because
the index passed in for the UMSG_GET_SEL_NEXT should be one greater than the index of the
current selection. To receive the index of the next selection in a List instance using the
UMSG_GET_SEL_NEXT message, the index of the current selection you pass in "param1"
should be incremented by one as shown in Figure 4.
FIGURE 4: Incrementing the index of current selection by one
/* _lNid is the nid of the list instance */
/* fNdx and nNdx are nint32 variables */
if ((fNdx = UMsgSend( &Access, _lNid,
UMSG_GET_SEL, N_NULL, N_NULL)) != UMSG_LOC_NONE){
UMsgSend( &Access, _lNid, UMSG_GET_DATA,
fNdx, (UMsgParam)(pnstr) line);
fNdx++; /* Increment the current selection index */
while ((fNdx = UMsgSend( &Access, _lNid,
UMSG_GET_SEL_NEXT, (nparam) fNdx,
NMakePtrParam (&nNdx)))
!= UMSG_LOC_NONE){
UMsgSend( &Access, _lNid, UMSG_GET_DATA,
nNdx, (UMsgParam)(pnstr) line);
fNdx = nNdx; /* assign the index of the next selection */
fNdx++; /* Increment the current selection index
to get the next selection */
} /* End of the while loop */
} /* End of the if condition */
END of FIGURE 4
Calling Netware SQL APIs from NLMs (NetWare SQL v3.00)
Two files are required to call NetWare SQL APIs from an NLM: NWSQLNIF.H and
NWSQLAPI.IMP. Make sure to use the appropriate cdecl statement in the NWSQLNIF.H file.
Two different cdecl statements are commented in the header file. One statement is for the
WATCOM v9.01 (or higher) Compiler and the other is for versions of the WATCOM Compiler
before v9.01.
Insert the appropriate cdecl statement at the top of the NWSQLNIF.H file. Also make sure to
replace the cdecl statement in the NWTYPES.H file with the one used in the NWSQLNIF.H file.
The NWTYPES.H file is located in the NOVH directory of either the WATCOM Compiler or
the NLM SDK v3.0. The NWSQLAPI.IMP file must be imported into the .LNK file of the
application.
QueryServices() Returns Status 1 (NetWare Client SDK 1.0e)
Using NWIPXSPX.DLL (dated 11-2-93) from the NetWare Client SDK v1.0e, a call to
QueryServices() from a MS Windows application will fail with a status 1, when it should
succeed and return a status 0.
Novell is aware of the problem and is working on a solution. Currently, the workaround is to
use the version of NWIPXSPX.DLL that is dated 5-18-93 from the NetWare Client SDK v1.0d.
NetWare OS/2 Requester Produces Status 95 (NetWare Btrieve (NLM) v6.10)
NETX must be loaded and the LOGIN process must be executed in every Private DOS
session. Even though the MAP command may display drive mappings, those resources actually
are not available to the DOS session. Use the LOGIN command to allocate resources to the DOS
box. Otherwise, a Btrieve status 95 (Session No Longer Valid) may be returned if you use a
Private DOS box with OS/2 v2.1 and the NetWare OS/2 requester v2.01.
When using Private DOS sessions with the 2.01 version of the NetWare OS/2 requester and
the Btrieve OS/2 requester v6.1x, always verify that NETX is loaded and that the LOGIN
procedure described above has been followed.
Erroneous Status 82s and 2s (Btrieve for DOS 5.10a)
When a user attempts to read a Btrieve file that is being modified, the file may actually be
busy. This situation may result in the read operation receiving incomplete data, causing an
erroneous status 82 (Lost Position) or status 2 (I/O Error).
Currently, there is no solution for the client Btrieve engines, except to retry the operation.
The status messages are in error and disappear when the write operation completes. The status
messages result from a timing window problem.
No erroneous status is returned when using transactions. Also, this situation does not exist
with the Btrieve NLM or VAP, since only one engine handles the writes and reads for all users.
MS AppStudio and .VBX Custom Controls (AppWare Foundation for Windows 1.70)
When you attempt to use an AppWare Foundation .VBX on a dialog box, Microsoft
AppStudio returns the following error:
"Cannot drop VB controls in non-MFC dialogs."
When creating a new resource in AppStudio, AppStudio presents a dialog box that
permits you to select the current resource type. The resource type defined in AppStudio must be
a Microsoft Foundation Class (MFC) Resource Script.
To prevent this error, select "Resource Script" from the list box and select the "Use
Microsoft Foundation Classes" checkbox. Doing so automatically adds another include file,
AFXRES.H (provided with MS Visual C++), to your resource file.
Establishing Multiple Btrieve Sessions Triggers Status 91 (NetWare Btrieve (NLM) v6.10)
Versions of NetWare Btrieve prior to v6.10c may return a status 91 (Server Error) if many
users attempt to establish a session simultaneously.
NetWare Btrieve returns this status because BSPXCOM.NLM has posted only one
Listen-For-Connection Event Control Block (ECB). BSPXCOM.NLM v6.10b, which is included
with NetWare Btrieve v6.10c, now posts five Listen-For-Connection ECBs for establishing
sessions with workstations.
NetWare Btrieve v6.10c is available for downloading from Novell's NOVLIB forum on
CompuServe (Library 7, BTR61.EXE), or from Novell Developer Support.
:
Bindery Access Levels & NetWare 4.01 (NetWare Client SDK v1.0x)
NWGetBinderyAccessLevel() always returns 0x33 (Supervisor Access Level) for the
access level on a NetWare 4.01 server. This situation does not occur on NetWare 3.11 or
NetWare 4.0.
To ensure that the proper bindery access levels are returned, apply the Directory Service
updates for NetWare 4.01. The patches are available on Novell's NOVLIB forum on
CompuServe (Library 1, DSPAT.EXE).
NLM Optimization and WATCOM v9.5 (NLM SDK v3.0)
An NLM compiled for optimization under WATCOM v9.5a generates a call __STOSB
when the code contains a loop in which an array is initialized to the same value. WLINK then
returns an error with the undefined symbol, __STOSB. This symbol is not in CLIB.IMP or CLIB
NLM.
This situation has been tested with CLIB v3.12, CLIB v4.01b, and WATCOM v9.5a
with the compile options, "/ms /w4 /s /zp1 /3s /oax." The problem does not occur under
WATCOM v9.01e because optimization is handled differently.
For example, if your source code contains the following segment:
int i;
for (i=0; i<12;i++)
internet[i]=0;
WDISASM generates the information in Figure 5 under WATCOM v9.5a.
FIGURE 5: Assembly code generated by WDISASM (WATCOM v9.5a)
0000 53 InitUserId push ebx
0001 8b 5c 24 10 mov ebx,+10H[esp]
0005 b9 0c 00 00 00 mov ecx,0000000cH
000a 89 d8 mov eax,ebx
000c 31 d2 xor edx,edx
000e e8 00 00 00 00 call __STOSB
0013 8b 44 24 08 mov eax,+8H[esp]
0017 66 89 43 0c mov +0cH[ebx],ax
001b 8b 44 24 0c mov eax,+0cH[esp]
001f 66 89 43 0e mov +0eH[ebx],ax
0023 5b pop ebx
0024 c3 ret
END of FIGURE 5
WATCOM v9.01e would generate the information in Figure 6 (with a different function
name, same "for" loop).
FIGURE 6: Assembly code generated by WDISASM (WATCOM v9.01e)
0000 57 my_printf push edi
0001 55 push ebp
0002 89 e5 mov ebp,esp
0004 81 ec 04 04 00 00 sub esp,00000404H
000a 8d bd fc fb ff ff lea edi,-404H[ebp]
0010 b9 03 00 00 00 mov ecx,00000003H
0015 8c da mov dx,ds
0017 31 c0 xor eax,eax
0019 06 push es
001a 8e c2 mov es,dx
001c f2 ab repne stosd
001e 07 pop es
END of FIGURE 6
WATCOM prefers that their static link libraries be used for producing NLMs with
WATCOM v9.5a, rather than using the CLIB.NLM entry points. __STOSB is defined in these
libraries.
In the old method of using CLIB.NLM for all the entry points, WATCOM recommends that
you extract the module STOS from the static library and link it as an ordinary object module. If
using NLMLINK, you have no choice but to link the STOS module, since NLMLINK does not
understand the libraries at all.
Alternately, using WLINK you may be able to leave __STOSB in the library and use both
modules, but in that case you must place the static library at the end of the library path. Using
WLINK may include more library functions than desired, so you need to experiment to
determine the side effects. WLINK users could also extract the module and link it in.
Editable List Instances (AppWare Foundation for Windows 1.70)
In the AppWare Foundation, Editable List Instances and Edit Text Instances are associated
through a Instance Relation (for more details, see the documentation on "Instances"). When
filtering messages for a Editable List Instance and an associated Edit Text Instance, the messages
are directed to the List Instance first. Thus, the order in which you process messages is of critical
importance.
List Instance filters are handled first, followed by the Edit Text filters. Be careful when
filtering for the same messages as this may affect program flow or data.
Allocating Memory for ALM Development (ALM SDK v1.0)
The recommended memory requirement to do quick AppWare Loadable Module (ALM)
debugging and testing is about 6MB to 8MB. Anything less will affect MS Windows
performance and interfere with debugging. With less memory allocated, unpredictable crashes
may occur while debugging ALMs. If these symptoms are seen, examine both the available TPA
and the amount of total memory (including Windows Virtual Memory) and try any of the
following:
- Use virtual memory (performance will drop dramatically). Enabling 32-bit disk
access (if appropriate for your disk) will help minimize this performance drop. As always, be
careful when creating a permanent swap file on a compressed drive. The exception to this rule is
when using Novell DOS 7 and its included Stacker drivers, which handle compressed permanent
swap files correctly.
- Remove Visual AppBuilder from the ALM debugging environment. Do this by creating
an application, then running the created application.
- Remove any unnecessary MS Windows programs (e.g., Clock, Notepad). The exception
to this rule might be a system load monitor or a memory monitor.
- Remove any disk caches using extended or expanded memory. (Again, performance will
drop.)
- Add more memory or move to a machine with more memory.
WINDOW Objects & "Opened" Signal (Visual AppBuilder for Windows v1.0)
If a Window object is configured to be Initially Visible (using the Initially Visible button
in the Edit Window dialog), the object's "Opened" Signal is never raised. This situation is
counter-intuitive if you hook a function chain to a Window Object on the signal "Opened," as the
signal is never raised with this condition. As a workaround, make your Window Object Not
Initially Visible and hook a function chain to the Application Object, which opens the Window
Object.to generate the desired signal.
Fast Answers to Common Questions
Visual AppBuilder for Windows
Tip: The List :: Clear List function does not clear a list. Until this is corrected,
assign an empty list to the filled list as a workaround.
Tip: Once the Text Object style option Editable has been unchecked, the
Vertical Scrollbar option is dimmed and its check box is disabled. To have a non-editable text
object with a vertical scroll bar, select the Vertical Scrollbar option before unchecking the
Editable option.
AppWare Foundation for Macintosh
Q - What versions of Macintosh Programmer's Workshop (MPW) C can you use with the
AppWare Foundation for Macintosh v1.70 ?
A - You can use either MPW C v3.2.4, or MPW C v3.3b1.
NetWare Client SDK
Q - Can I distribute the NetWare Client SDK DLLs with my application?
A - You may legally distribute the NetWare Client SDK DLLs with your application
provided that you have signed and returned the Derivative Software License Agreement to
Novell.
Q - I obtained the Client API for Assembly documentation and it said to look for
APIASMnn.EXE up on CompuServe for the latest documentation updates but it wasn't there!
Where is it?
A - This file is now available on CompuServe in NOVLIB library 7. The filename is
APIASM.EXE.
Q - How do I change the default context for a workstation under Directory Services?
A - Use NWSetDefaultNameContext(), instead of NWDSSetContext(). The context
established by NWDSSetContext() is only valid for the duration of your application.
Tip: The NetWare Client API for Assembly documents assembly system calls.
Making these calls from MS Windows is neither documented nor supported. Customers writing
MS Windows applications should use the C functions as documented in the NetWare
Programmer's Guide for C.
Tip: Novell has released a quarterly update to the NetWare Client SDK v1.0d
bringing the latest revision to v1.0e. This update can be obtained from Novell's NDEVREL
forum on CompuServe, Library 6, in the following files:
CLINEW.TXT - Description of files
CLIWIN.ZIP - MS Windows updates
CLIOS2.ZIP - OS/2 updates
CLIDMC.ZIP - DOS Microsoft C updates
CLIDBC.ZIP - DOS Borland C updates
CLIINC.ZIP - Include file updates
Only members of the Professional Developer's Program may access Library 6. If you are
a member, but your account has not been enabled for access to library 6, send a message to
account 76711,111 requesting access.
Tip: The NetWare Client SDK v1.0e is fully compatible with the Borland C++
v4.0 compiler. Although Borland's new compiler will create 32-bit code, since it does not create
an EZ-OMF object, it currently will not support NLM development.
Q - What is the breakdown of field information returned by
NWGetDirSpaceLimitList() in the 512-byte returnBuff?
A - The returnBuff parameter breaks down as shown in Figure 7. There is no
predefined structure for the returnBuff parameter.
FIGURE 7: Field breakdown for NWGetDirSpaceLimitList() returnBuff
Offset Field # Bytes Remarks
----------------------------------------------------------------------
0 numberOfEntries 1 Number of entries returned. An
entry consists of the next three
fields: Level, Maximum, Current
1 Level 1 Distance from the directory to
the root.
2 Max 4 Maximum amount of space assigned
to a directory.
6 Current 4 Amount of space assigned to a
directory minus the amount of
space used by a directory and
its subdirectories.
10 Level 1 <- These 3 fields
11 Max 4 <- repeat numberOfEntries
15 Current 4 <- times. (up to 512 bytes)
*
*
*
etc.
END of FIGURE 7
Q - I need to connect to an SCO UNIX machine and the server advertise can
take up to two seconds to respond to my query. I rewrote QueryServices() to wait up to two
seconds, but I'd prefer to stick with the true Client SDK libraries. Is there any other way to adjust
the "time-out" value on the NetWare Client SDK QueryServices() call?
A - QueryServices() has a built-in "time-out" value. Issue the query services call, then
loop until a response or a predetermined "time-out" occurs. This predetermined "time-out" is
hard-coded, so you must modify the code to wait for a longer period of time.
NLM SDK
Q - Can I use Borland C++ v4.0 for NLM development?
A - No. Borland C++ v4.0 will not produce the Phar Lap Easy-OMF format object
files that are required by NLMLINK to generate an NLM.
Q - When my NLM calls LoginToFileServer() against a remote server, the call returns
status 5. What is this status and what should I do about it?
A - Status 5 is an NetWare Core Protocol (NCP) error code indicating a broadcast
error. The likely reason for LoginToFileServer() to return this code is if the "Reply To Get
Nearest Server" parameter is set to OFF for the server. It will take the server longer to locate
other servers on the network with this parameter set to OFF, and if an NLM tries to login to an
unknown remote server, the login may "time out" before the remote server is found.
Status 5 generally is returned only when the server has just been started or when you have
just run "RESET ROUTER" on the console. It does not seem to occur if "Reply to Get Nearest
Server" is left with its default setting of ON.
Q - The NLM SDK v3.0 documents GetScreenInfo() and briefly mentions that it
replaces the MapScreenIDToHandle() and that I should not use the latter. However, since
GetScreenInfo() does not work with CLIB v3.11d and v3.11e (the currently available versions),
it seems that I have to use MapScreenIDToHandle(). How do I use this call?
A - Here is the prototype for using MapScreenIDToHandle():
extern int MapScreenIDToHandle(
int __screenID,
char *__name,
LONG *__attrib );
Q - When writing an NLM, how do you respond to queries? Does another
process take control of socket 0x0452, or is that taken care of for you in NLMs and VAPs?
A - You do not have to respond to queries as an advertising NLM. The file server you
are running on is a router, so it will respond for your advertising NLM. (The same holds true for
VAPs as well.)
In general, when running on a client or a server, you only have to make the call to
AdvertiseService() at the beginning of your application. Once you have invoked that function,
your application should not have to deal with any queries or broadcasting every minute.
AdvertiseService() will take care of all SAP duties in the background.
NetWare for OS/2
Tip: Under OS/2 2.1 running the NetWare requester 2.01, there may be
instances when you receive the following error message:
Application could not demand-load segment NETAPI.number.
This message indicates that the application is trying to make a LAN Manager-specific call,
which in turn tries to "demand-load" the DLL for Lan Manager and produces the error. These
LAN Manager-specific calls are not supported by the requester. To avoid this situation, make
sure that all APIs are not referencing specific DLLs outside of their environment.
Hello and welcome to the February 1994 issue of Novell Professional Developer
Bullets.
By now, many of you have read the press release regarding Novell's plans for its database
product line. To briefly recap: on January 26, Novell announced a Memorandum of
Understanding (MOU) to transfer ownership of the database products to Btrieve Technologies
Inc. (BTI). This is a very positive statement of direction by both Novell and BTI concerning this
product line and database developers.
The definitive agreement will be reached within the next eight weeks. (The press release and
a Q & A fact sheet is available on Novell's Automated Fax System: dial 1-800-NetWare, choose
option #1, choose option #1 again, and request document #5007.) All registered users and
developers will receive a letter of notification when the agreement is finalized.
Meanwhile, because this is an MOU and not a definitive agreement, it's "business as usual"
here at Novell. "Business as usual," of course, means that developer support, pre-sales product
information and sales for the database products are still being handled through Novell's
1-800-NETWARE telephone number. I know that many of you have called BTI asking for these
services, and it has delayed your responses because your calls must then be forwarded to Novell
for completion.
If you do have questions specific to Btrieve Technologies Inc. please call 1-800-287-4383
(1-800-BTRIEVE). Thank you in advance for your cooperation and...
Happy_Programming!
Mad Poarch
Director
Developer Support/Services
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, & 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.
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.
Novell Labs
For information on Novell 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.
|