NOVEMBER 1992 VOLUME 4 NUMBER 10
INDEX
Hello and welcome to the November 1992 issue of Bullets!
Ahh, November. How does one piece together the wide range of events this month?
Veterans/Armistice Day, Election Day, Comdex Week and Thanksgiving round out the special
days in my scheduler.
People in the United States are quite fond of Thanksgiving. Eating a lot of turkey to recognize
the hardships of our forefathers is a popular multi-meal festivity. And yes, history books today
very clearly inform us that the pilgrims ate more than just turkey with the original inhabitants. I
believe some people now say they ate quail.
There's more to November than turkey. It's a time to think and give thanks.
It's easy to look back and be thankful for past deeds. Looking ahead is a bit trickier. Currently,
I'm particularly grateful that I no longer have to man the booth at the five-day Comdex
tradeshow.
One hundred years from now, I wonder who will be the person or group that the computer
industry will be thanking for their contributions and achievements? Maybe it's you -in which
case, thanks in advance.
Happy Thanks_Programming!
Mad Poarch
Director
Developer Support/Service
Loading NWShell
NWShell can be loaded in two ways:
- Place NWShell in the server SYS: SYSTEM directory, or any path specified in
the server's SEARCH path. Then, from the NetWare 3.x console type:
:LOAD NWSHELL [USERNAME]
- From an NCF file -for example, the server's AUTOEXEC.NCF file.
If a user name is specified, NWShell attempts to login as that user during the initialization phase.
If user name is not specified, NWShell attempts to login as SUPERVISOR. NWShell prompts
for any required password.
Immediately following an initial login, NWShell searches the user account's SYS:MAIL
directory for a script file called LOGIN.NWS (see the section on NWShell configuration for
more information on LOGIN.NWS). If found, NWShell executes the script. If LOGIN.NWS is
not found, NWShell maps drive numbers 0: and 9: as follows: Drive 0: is always mapped to the
root directory of volume SYS: If the SUPERVISOR account was used, drive 9: is mapped to
SYS:SYSTEM, otherwise, drive 9: is set to SYS:PUBLIC. Drive 0: becomes the default drive at
the beginning of the session.
You can load multiple copies of NWShell on a given server. Each copy will have its own drive
mappings and server login(s). You might use this feature to create test scripts that exercise the
functionality of an NLM. For example, the initial copy of NWShell executes a driver script that
spawns an alternate copy of NWShell which loads and unloads a target NLM to exercise all of its
command line parameters. At the same time, the initial copy of NWShell might be placing a load
test on the server by copying files from one location to another.
Using NWShell's Features
Normally, after loading NWShell, one or more drives are mapped to the SYS volume of
the local server. Navigating in this environment is similar to getting around the DOS
environment; commands like "CD" to change the current working directory and "COPY" to copy
files are identical to their DOS counterparts (see Figure 1 for a list of NWShell commands).
Several NetWare command line utilities are also implemented in NWShell, such as "LOGIN"
and "MAP." The syntaxes for NWShell's internal commands map closely to the commands they
mimic, so using NWShell is very straight-forward for developers who know DOS.
FIGURE 1: NSWhell Commands
ABORT BREAK CALL CAPTURE CD CDD
CHDIR CLRENV CLS CONSOLE CONTINUE COPY
DEL DF DIR DUMP ECHO ELIF
ELSE ENDIF ERASE EXEC EXIST EXIT
FLAG FINDFIRST FINDNEXT IF LIST LOAD
LOGIN LOGOUT LOWER MAP MD MKDIR
MODE MSG PAUSE PRINT PSET RD
READLINE REM REN RETURN RMDIR SALVAGE
SAY MODE SET[ENV] STDERR STDOUT STDPRN
STOP SYSTEM TRACE TYPE UPPER USERLIST
VER WEND WHEREIS WHILE WHOAMI YNPROMPT
End of Figure 1
In addition to built-in commands, NWShell offers a script language with several
enhancements over the DOS batch language. Using script files, one can create sophisticated
automated operations, especially useful for NLM testing purposes. Script files are discussed in
detail later.
Executing NWShell Commands
Whenever you enter a command on the command line, NWShell compares the command
against a list of internal commands. Then:
- If a match is found, the corresponding procedure is called to process the
command. Arguments are passed to the procedure. For example, if you enter the command
"COPY *.NLM SYS:SYSTEM," the "COPY" keyword produces a match against an internal
command, and the "COPY" procedure is invoked with the arguments "*.NLM" and
"SYS:SYSTEM."
- Beginning with v3.11b, if the command does not match the internal command list,
NWShell attempts to load an NLM or execute a script file whose name matches the supplied
argument. As with the internal procedure, any arguments are passed on to the executed NLM or
script file. NWShell searches for NLMs and script files using the following logic:
- If a full or relative path is specified on the file name, search there only.
- Otherwise, search the current directory, then each directory specified in the NWShell
"include" file, NWSINCL. Search for files in this order: .NLM, .LAN, .DSK, .NAM, .NWS.
- If Step 2 fails, try to load an NLM using the server's search path (SEARCH command).
If NWShell detects that an NLM is on a remote server and LOAD REMOTE MODULE
MODE is enabled, it copies the NLM to a temporary directory on the local server and then loads
it. The file is copied to SYS:SYSTEM /NWSHELL/NLMTEMP.
Other common operations include logging in/mapping drives to remote NetWare 2.x and 3.x
servers and queuing print jobs to a NetWare Print Queue.
Logging In to Remote Servers
Logging in to a remote server allows you to perform operations on a remote server, just
like under DOS. Copying files to/from the remote server, listing directories, manipulating files,
etc, can be performed just as if the server were local. One use of this feature might be the remote
update of a software program when a new version is received. You could write a script file to
perform a login to all NetWare servers that need a copy of the utility, and then copy the update to
each one. You could also use this feature to update a group of utilities. The update could be
applied to the server where NWShell resides, then a script file could systematically apply the
update to other NetWare servers.
Compared to using a DOS workstation to apply the same update, using NWShell cuts network
traffic in half. Files are only transferred across the network once rather than twice (once for
reading and once for writing).
When developing NLMs, the ability to login to a remote server is especially useful, since it
allows you to transfer updated versions of your NLM from the development server to the test
server. NWShell v3.11b provides this feature transparently by copying the remote NLM to a
local server, then automatically executing it.
NWShell Environment Variables
Other features offered by NWShell include the support of an environment with both global
and local variables, and built-in system variables containing many items useful for script
development. The NWShell environment also supports line preprocessing, a feature important to
the creation of more sophisticated script files.
The concept of the NWShell environment is inherited from DOS, with a few enhancements.
At this time, the environment is mainly useful for script development, since you cannot pass the
environment between NLMs. An environment variable consists of a name and a value.
To create an environment variable, use one of the following commands: "SETENV," "SET" or
"PSET." The commands "SETENV" and "SET" create a global variable that remains until the
definition is explicitly removed by redefining it to a null string. "PSET" is used to create a local
variable that can be accessed only in the script where it is created and is automatically removed
when the script terminates. Local variables are passed to a called script. Finally, there are two
special environment variables, NWSINCL and PROMPT. (See "Custom Configurations" for a
complete description of these variables.) The following statement creates a global variable called
TEMP:
SET TEMP=SYS:TEMP
Once the variable is set, it is extracted by placing the variable name between caret "^" symbols.
For example:
ECHO Value of TEMP is ^temp^
would produces the output:
Value of TEMP is SYS:TEMP
(See "NWShell Script Files" for more examples using environment variables.)
You can use system variables for many different purposes, from obtaining context information
regarding current session parameters to returning values from many of the internal commands.
Figure 2 contains the complete list of NWShell system parameters.
FIGURE 2: NWShell's built-in system variables
Variable Definition
ampm AM if in morning, PM if in afternoon
cdir current directory without volume
cdrive current drive letter
cpath current default path
cretc return code from last CALL command
cserver current server
cuser current user
cvol current volume
date current system date (mm/dd/yy)
day current weekday, long version (e.g., Monday)
dow current week day (number 0-6, 0 = Sunday)
doy current day of year (1-366)
eretc return code from last EXEC command
ffile findfirst and findnext matching filespec
filename filename of currently executing script
fname findfirst and findnext matching filename only
fpath findfirst and findnext matching pathname only
locdate current locale system date
loctime current locale system time
maildir mail directory of current user
month current month, long version. (e.g., February)
newline carriage return/line feed
readline result of last READLINE command
sday current weekday, short version (e.g., Mon.)
smonth current month, short version (e.g., Feb.)
sretc return code from last MAP command
time current system time (hh:mm:ss)
week current week number (0-51)
year current year with century
ynvar result of last YNPROMPT command
End of Figure 2
Extracting the value of a system variable is like extracting environment variables, except
the variable name is placed between plus "+" signs. For example, if user JANET is logged into
server SPOT, the command:
ECHO +cuser+ is logged into +cserver+
would produce the output:
JANET is logged into SPOT
Line Preprocessing
To fully utilize both environment and system variables within scripts, you must
understand how NWShell performs line preprocessing. By default, NWShell only performs
"single scan preprocessing;" that is, each line is scanned only once and all variables are expanded
during that single pass. With this type of processing, variables should fully evaluate after a single
pass to obtain the desired results. For example, consider the following environment definitions:
set argument=test
set newfile=%^argument%^
After execution of the preceding statements, the variables "ARGUMENT" and "NEWFILE"
would be defined. "ARGUMENT" would be equated to the string "test," and "NEWFILE" would
be equated to the string "^argument^." (The percent sign (%) is used to embed the caret symbol.)
The following NWShell command illustrates a problem which can occur with single scan
processing:
exec myprog ^newfile^
This line would expand to:
exec myprog ^argument^
instead of:
exec myprog test
NWShell v3.11b allows you to specify the number of passes to be made during the line
preprocessing phase. Be careful to avoid other caveats that can occur when you specify multiple
passes during preprocessing, like attempting to define an environment variable whose value is
another variable. Multiscanning can cause the initial definition to be fully evaluated, producing
undesirable results.
In some cases, only a partial value of either an environment or system variable is desired. To
support substring parsing, NWShell allows you to specify two optional parameters when
accessing a variable: "SKIP" and "KEEP." To parse a substring, use the format:
^SKIP.KEEPvariablename^
For example, assume the definition:
set VERSION=1.21
The following example demonstrates substring parsing:
echo ^0.1version^ displays "1"
echo ^2.2version^ displays "21"
You can apply this feature to system variables as well.
Expression Support
NWShell supports expressions with the commands "IF," "ELIF" and "WHILE." Figure 3
shows a valid NWShell expression.
FIGURE 3: Valid NWShell expression
expr := subexpr [ subexpr [...] ]
subexpr := operand1 operator operand2
logical operator := "&& ||"
operand := any string
operator := "==, !=, <=, >=, <, >, FILE, DIR, CONNECTION"
End of Figure 3
The operands can be any string, but they may not contain embedded white space
(characters from the set {space, newline, tab}). Comparisons are performed lexicographically, so
be careful when doing numerical comparisons. The logical operators "&&" for logical AND and
"||" for logical OR associate left to right, and evaluation stops as soon as truth or falsehood is
determined. Figure 4 contains a list of NWShell operators.
FIGURE 4: NWShell Operators
Operator Description
__________________________________________________________________
== Equality operator
!= Inequality operator
<= Less than or equal relational operator
>= Greater than or equal relational operator
< Less than relational
> Greater than relational
FILE Test for existence or non-existence of file.
Operand2 must be "EXISTS" for testing existence,
and "NOTEXI" for testing non-existence
DIR Test for existence or non-existence of subdirectory.
Like FILE, Op2 must be either "EXISTS" or "NOTEXI"
CONNECTION Test for a current login to a server. Op2 must
be either "EXISTS" or "NOTEXI"
NLM Test to see if NLM is currently loaded
__________________________________________________________________
End of Figure 4
NWShell Script Files
NWShell's features can be combined to create very powerful script files. NWShell's
built-in script language offers many capabilities you can use to create sophisticated NLM testing
suites. You can write automated tests to exercise various features of an NLM that otherwise
might undergo more limited testing.
For example, NWShell's entire regression test was built using the script language. Each feature of
the NLM is subjected to many different types of scenarios which could occur during normal
operations. The "COPY" command undergoes very rigorous testing procedures during its
regression test. As many combinations of the file copies as possible are tested to ensure the
stability of the command with each version of the NLM. Also, when an error is found, a
corresponding test is added to the script file to help ensure that a similar error does not reappear
later.
Building a test suite for an NLM that exercises various features depends on the type of NLM
being tested. A LAN driver developer, for example, could create a script file which repeatedly
loads and unloads an NLM, perhaps with different parameters, to ensure the driver is capable of
responding correctly. In addition, other NLMs which test functionality of various features could
be written and incorporated into the test suite to ensure that the NLM works as expected.
You can also write script files that simply place a load on the server to test how an NLM reacts in
such an environment. Since NWShell can be loaded multiple times, a main script might simply
spawn other instances of NWShell, which in turn would run different scripts designed to test a
given NLM.
Debugging Script Files
Of course, writing script files is like writing programs; some debugging is usually
required. NWShell offers several features explicitly for the purpose of debugging script files.
For the script debugging phase, three modes are available:
- DEBUG STATEMENTS
- TRACE STATEMENTS
- SINGLE STEP SCRIPTS
In DEBUG STATEMENTS mode, NWShell displays each input line in two forms, raw
and processed. The raw display shows the input line as it was read from the file, and the
processed display shows the line after it has been preprocessed (i.e. after environment and system
variables have been expanded). DEBUG STATEMENTS mode helps show how NWShell line
preprocessing works.
The TRACE STATEMENTS mode is identical to the DOS ECHO ON feature. It displays each
line as it is executed. Lines are displayed in processed mode, as apposed to raw mode. NWShell
supports the ECHO ON feature for compatibility with DOS.
SINGLE STEP SCRIPTS mode is the most useful debugging mode. In this mode, NWShell
prompts for a keystroke between each line in a script file. As with all debugging modes, you can
turn the feature on and off dynamically anywhere in a script file. Do not forget to set ECHO ON
or turn TRACE STATEMENTS on or you might think that NWShell is locked up if no screen
output is occurring!
Another debugging feature, the "DUMP" command, displays all global and local variable
information in addition to the current script parameters. Script parameters are prefixed with a
"P," local environment strings are prefixed with an "L," and globals are prefixed with a "G."
Example Script Files
Figure 5 contains a script which will view all files matching a supplied file specification,
using the LIST command. Notice that a parameter can be passed to supply the file specification,
but if none is supplied, the user is prompted for one via the READLINE command.
FIGURE 5: Script to view all files matching a file spec
if "%1" == ""
readline Enter filespec:
if "+readline+" == ""
say No file specified!
stop
endif
pset spec=+readline+
else
pset spec=%1
endif
findfirst ^spec^
if "+ffile+" == ""
say File not found.
stop
endif
while "+ffile+" != ""
if +ffile+ dir exists
continue
endif
list +ffile+
findnext
wend
return 0
End of Figure 5
Figure 6 contains an example script which logs in to a remote server and maps a drive to
it. The script is semi-intelligent, since it detects if a login already exists before trying a new one.
If a login is attempted to a server to which you are logged in, NWShell will log out first, deleting
all previously mapped drives to that server. By detecting existing connections, previous
mappings can be preserved. If no drive parameter is specified, drive 7: is mapped to SYS: on the
new server by default.
FIGURE 6: Generic login to server script
if "%1" == ""
say usage: +filename+ SERVER
[DriveNumber]
return 1
endif
redir stdall nul
pset server=%1
pset drive=%2
upper server
if ^server^ connection notexi
# login only if not already
# logged in
login ^server^/+CUSER+
else
stdout Already logged in to
^server^!
endif
#
pset srvol=^server^/SYS:
#
if "^drive^" != ""
map ^drive^:=^srvol^ ^drive^:
else
map 7:=^srvol^
7:
endif
if +sretc+ != 0
stdout Error mapping to ^srvol^
elif "^drive^" != ""
stdout Drive ^drive^: = ^srvol^
else
stdout Drive 7: = ^srvol^
endif
if ^server^ != +cserver+
stdout Could not login to
^server^
endif
unredir
return
End of Figure 6
Custom Configurations
Many developers customize NWShell to create an environment that suits their particular
development needs, just as they would in the DOS environment. In DOS, a command prompt
which displays relevant context information is normally set, along with various environment
variables which are used by different processes and/or batch files. Several features in NWShell
exist specifically for customizing how context is relayed, where it searches for scripts and NLMs,
and certain behavior defaults when a given type of event occurs, just to name a few. To begin
with, consider two special environment variables used by NWShell: PROMPT and NWSINCL.
NWShell's default prompt is the familiar "d:/path>." NWShell uses this style of prompt if no
PROMPT variable is defined. In DOS, this style path would be created using a statement like:
SET PROMPT=$P$G
To customize a prompt, use any of NWShell's internal system variables, as well as user-defined
environment variables. For example, you can create a prompt that displays the current server and
user on the first line, then displays the familiar console colon prompt on the second by use of a
command line like:
SET PROMPT=%+NEWLINE%+[%+CSERVER%+/%+CUSER%+]%+NEWLINE%+:
'%' imbeds the "+" in the PROMPT environment variable. When you imbed the "+" in the
prompt string, NWShell evaluates the line each time the prompt is displayed. After executing the
above command, the PROMPT variable would be:
PROMPT=+NEWLINE+[+CSERVER+/+CUSER+]+NEWLINE+:
NWShell evaluates each line as it is entered, including the expansion of variables. Therefore, if
the "+" is not embedded, the values of the "CSERVER" and "CUSER" variables would be
expanded when the SET command is processed, rather than when the PROMPT is displayed.
Assuming that the current server is WISHBONE and the current user is John, the PROMPT
environment variable without the "+" would have the following value after the line was executed:
PROMPT=\r\nWISHBONE/JOHN\r\n:
This value would lead to misleading context information when the default server and/or user
changed, since we have made the PROMPT value a constant!
If user "Kirk" were currently logged in to server "ENTERPRISE," NWShell would display
the following command prompt:
ENTERPRISE/KIRK
:
With this type of prompt, anytime you change the current server or user context (either implicitly
by changing drives or explicitly by changing the current working directory) the prompt reflects
accurate context. Both system and environment variables can be used in a prompt statement, so
you can create a very flexible prompt that can relay all relevant context information.
NLM/Script Search Directories
If you give a non-internal command name, NWShell tries to load it as an NLM or execute
it as a batch file. Unless you specify an absolute path, NWShell first looks in the default
directory, then it searches each directory specified in the NWSINCL environment variable.
Multiple directories can be specified by separating each with a semicolon (;). You can set the
NWSINCL variable with a command like:
SET NWSINCL=TEST386/SYS:NWS;
RDSERVER/SYS:SCRIPTS
Specifying the server name on each path is necessary if you will be using any of the remote
facilities built into the shell.
The MODE command
The MODE command configures internal controls such as how many statements can be executed
in a script and which logical port print jobs are sent to. The complete list is shown in Figure 7.
FIGURE 7: NWShell MODE Commands
EXEC IGNORE MODE
EXECUTION MODE
MAX STMT COUNT
DEFAULT LOCAL PORT
DEBUG STATEMENTS
TRACE STATEMENTS
SINGLE STEP SCRIPTS
PREPROCESS SCAN COUNT
PAUSE ON FULL SCREEN
SCREEN SWITCH BACK
LOAD REMOTE MODULE
INHERIT CONTEXT
PUSH
POP
End of Figure 7
- Use EXEC IGNORE MODE to specify whether to abort script processing
if no NLM can be found.
- EXECUTION MODE sets the NLM execution mode. Currently, two modes are
supported: "Wait" and "NoWait." When "Wait" mode is in effect, NWShell waits until a
spawned NLM terminates before continuing. "NoWait" mode, the default, returns immediately
after spawning the NLM. The most common use of "Wait" mode is to temporarily suspend
processing of a script file until a secondary NLM completes.
- Use MAX STMT COUNT to set the maximum number of statements that can be
executed during processing of script files. It defaults to 1000.
- Use DEFAULT LOCAL PORT to set the port number that is used for spooling print jobs
with the PRINT command. It defaults to 1.
- Use DEBUG STATEMENTS to display debugging information while line processing is
occurring. This is very useful for debugging scripts.
- Use TRACE STATEMENTS to echo statements. This command is similar to the DOS
ECHO ON command.
- Set SINGLE STEP SCRIPTS to "ON" to prompt for a keystroke during execution of
script files after each line is executed.
- Use PREPROCESS SCAN COUNT to specify the number of times that NWShell will
scan an input line to expand macros. By default, this is done only once.
- Use PAUSE ON FULL SCREEN to specify whether NWShell will pause on the
USERLIST and WHOAMI commands if the screen is full.
- Use SCREEN SWITCH BACK to specify whether NWShell will switch back to its
screen when a spawned NLM terminates. This only works when execution mode is set to "Wait."
- Use LOAD REMOTE MODULE to specify whether NWShell will load NLMs from
remote servers.
- Use INHERIT CONTEXT to pass the current user login and current working directory to
the NLM spawned when using the EXEC or LOAD commands.
- Use PUSH to save current mode settings in a static variable (which prevents them from
being nested). All settings are saved except the Default Load Screen.
- Use POP to restore the previous MODE settings saved when the PUSH command was
executed.
Custom login scripts
NWShell script files provide a natural method to perform custom setup automatically.
Creating a custom login script provides the same benefits with NWShell as it does with the
normal LOGIN.EXE utility. Just like its counterpart, the LOGIN.NWS file is a good place to
perform initial logins, drive mappings and environment setup. It is recommended that you at
least set the NWSINCL environment variable to point to the location of your script files. This
location will be searched if an attempt to locate a script in the default directory fails, much like
the DOS PATH is searched for .BAT files. You may also want to set the PROMPT environment
variable to customize your command prompt.
The NWShell NLM is included with the Network C for NLMs SDK, which is available to
members of Novell's Professional Developers' Program. NWShell can also be downloaded from
Novell's NDEVREL forum on NetWire. For more information on the Network C for NLMs
SDK, NetWire and Novell's Professional Developers' Program, see "Contacting Novell," at the
end of this issue.
SPX APIs & the ES Register (NetWare C Interface for DOS v1.2)
Using the Microsoft C compilers (v5.1 and up) with the NetWare C Interface for DOS
SPX APIs in the SMALL and MEDIUM model can cause memory overwrites. This occurs due
to assumptions by the NetWare C interface for DOS about the contents of the ES register. The
SPX APIs assume that the ES register contains the same value as the DS register.
The example shown in Figure 8 forces this condition to be false (it forces ES DS) and can cause
memory overwrites and system crashes.
FIGURE 8: Example that forces ES DS condition
int _far *dummy = NULL; /* set pointer to NULL (0:0) */
int ivar;
:
:
ivar = *dummy; /* forces ES:SI to the pointer value */
SPX /* call any SPX function using ECB's */
End of Figure 8
In the example, the assignment of "*dummy" to "ivar" forces ES:SI to be loaded with the
value 0000.0000, resulting in a memory overwrite (starting at 0000.0000) inside the SPX
functions.
To remedy the situation, set ES = DS in the SMALL and MEDIUM models immediately before
calling SPX functions.
ATTACH.C Does Not Reorder Internet Addresses (NetWare C Interface for DOS v1.2)
When applications terminate, Automatic EOJ (End of Job) operations are not occurring
when the AttachToFileServer API in ATTACH.C has been used to create the attachment to the
file server. This situation becomes apparent when applications terminate without closing their
files.
Normally, the NetWare shell generates an EOJ API and closes the files for the workstation. The
shell generates EOJs based on the network addresses stored in the shell connection table. These
addresses must be ordered from lowest to highest network address using the order number field
in the shell connection table. The current version of ATTACH.C does not order the network
addresses and the open files are not being closed.
To make sure that EOJ commands are issued on application termination, contact the Developer
Support Group and request the latest (fixed) version of ATTACH.C source code.
TRUSTEE.NLM & Event Registration (Network C for NLMs v2.0(d))
TRUSTEE.NLM, an NLM in /NOVX /EVENTS/TRUSTEE, does not close its local
semaphore if an error occurs during event registration. Use an atexit() routine to register the
unload code instead of the AtUnload API, and replace the open semaphore code (on line 119)
with the four lines in Figure 9.
FIGURE 9: Necessary changes to TRUSTEE.NLM
Existing code (Line 119):
semaphoreHandle = OpenLocalSemaphore( 0 );
Replacement code:
if( (semaphoreHandle = OpenLocalSemaphore( 0 )) == -1 ){
cP("Error opening a local semaphore!\n");
return 1;
}
End of Figure 9
Declaring DLL Routines in Visual Basic (Microsoft Visual Basic)
Most DLL routines are written in C. Developers using Visual Basic have to translate the
syntax of a typical API routine into a Visual Basic DECLARE statement. Doing this requires
some knowledge of how arguments are passed in both C and Visual Basic. The following
information is helpful in determining how to set up DECLARE statements in the Global Module
of a Visual Basic application.
In C, numeric arguments are usually passed by Value; a copy of the value of the argument is
passed to the routine. Sometimes C arguments are pointers, and these arguments are said to be
passed by reference. Passing an argument by reference allows the called routine to modify the
argument and return it to the calling routine. C strings (null terminated strings) and arrays are
always passed by reference.
By default, Visual Basic passes all of its arguments by reference. In effect, when arguments are
passed to a Visual Basic procedure, they are actually passed as "far" (32 bit) pointers to those
values. To pass arguments to a C routine expecting arguments to be passed by value, you have to
use the ByVal keyword with the argument in the Declaration statement.
To complicate matters, Visual Basic strings do not use the same format as C strings. Visual Basic
uses the ByVal keyword to mean, "pass a C string by reference," when it is used with a string
argument in a Declare statement. The table in Figure 10 describes how selected arguments in an
API call should be passed.
FIGURE 10: Visual Basic arguments and appropriate declarations
Argument Declaration
__________________________________________________________________
A standard C string (LPSTR, char far *) ByVal S$
A Visual Basic String (see note) S$
An integer (WORD, HANDLE, int) ByVal I%
A pointer to an integer (LPINT, int far *) I%,
A long (DWORD, unsigned long) ByVal L&
A pointer to a long
(LPDWORD, LPLONG, DWORD far *) L&
A standard C array (A[]) Base type of Array
A Visual Basic array A()
A structure (user-defined TYPE) S As Struct
__________________________________________________________________
End of Figure 10
Never pass a Visual Basic string or array to a DLL routine unless the DLL was written
specifically for use with Visual Basic. Visual Basic strings and arrays are represented in memory
by descriptors, not pointers. These descriptors are useless to DLL routines that were not written
with Visual Basic in mind.
Visual Basic also allows arguments to be passed AS ANY. The AS ANY declaration tells Visual
Basic not to do any type checking for that argument. The developer can pass the function any
parameter, as long as it is what the function is expecting. If not, the application can terminate
with a UAE (Unrecoverable Application Error). If an argument is declared AS ANY, the call
must specify how the argument will be passed to the calling function. To do this, use the ByVal
keyword for strings and for arguments that should be passed by value, and omit ByVal keyword
for arguments that should be passed by reference.
For example, using Btrieve, if the key buffer parameter must be passed differently depending on
the operation that is to be performed, you would declare the Key Buffer parameter AS ANY in
the Global Module and set up the Btrieve call as shown in Figure 11.
FIGURE 11: Visual Basic Key Buffer declaration and Btrieve call
'Global Module
Declare Function btrcall Lib "wbtrcall.dll" (ByVal Op%,
ByVal Pb$,
Db As Any,
DL As Integer,
Kb As Any,
ByVal Kl%,
ByVal Kn%) As Integer
'Open File
OPEN%=0
PosBlk$=space$(128)
FileName$ = "f:\data\file.btr "
DL%=Len(DataBuf)
KLen% = Len(FileName$)
Status% = btrcall(OPEN%,
PosBlk$,
DataBuf,
DL%,
ByVal FileName$,
KLen%,
0)
End of Figure 11
Notice that the key buffer parameter (FileName$) is specified to be passed by Value.
Later in the code, if you wanted to pass a user-defined type for the key buffer on a GET EQUAL
operation, you would pass the structure by name for the key buffer as shown in Figure 12.
FIGURE 12: Passing structure by name
'Global Module
Type DateStruct
Day As String * 1
Month As String * 1
Year As Integer
End Type
Global Birthdate As DateStruct
'Main Module
'Get Equal
GE%=5
DLen% = Len(DataBuf)
Birthdate.Day = Chr$(3)
Birthdate.Month=Chr$(6)
Birthdate.Year=1966
KbLen% = Len(Birthdate)
KeyNum% = 1
Status% = btrcall(GE%,
PosBlk$,
DataBuf,
DLen%,
Birthdate,
KbLen%,
KeyNum%)
End of Figure 12
Btrieve v6.0 Page Size & NetWare v3.11 (NetWare Btrieve (NLM) v6.0)
If the page size of a Btrieve data file is not evenly divisible into 4096 (is NOT 512, 1024,
2048 or 4096), the file may become corrupted. The NetWare v3.11 patch, ASNCRDFX.NLM
(Async Read Fix), fixes this problem. This patch is available on NetWire (NOVLIB,
311PT9.ZIP).
Date Masks in Xtrieve PLUS Reports (Xtrieve PLUS for DOS v4.10)
Currently, there is no way to place a mask on the date that is printed as a result of the
"@date text" directive in an Xtrieve PLUS report. The date will always print using the mask
mm/dd/yy. As a workaround, add a user-defined date field to the view, and specify CURRENT
as its definition. This field will always have the current date, and when placing this field on the
report, the user will be prompted to specify a mask.
Assembler Errors for SPXESR.ASM (NetWare C Interface for Windows v1.22)
When assembling SPXESR.ASM with CMACROS.INC v5.02 in Large model, the
message, "Error A2024:Segment parameter has changed," is returned for the createSeg macro.
This error is returned when the assembler uses simplified segment directives that set the
following default segments and types for the Large model .CODE directive:
DIRECTIVE NAME ALIGN COMBINE CLASS
SPXESR.ASM contains the macro:
createSeg SPXESR_TEXT,
CODE1,
BYTE,
PUBLIC,
CODE
When assembled, the error message mentioned above is returned because the alignment is
defined as a BYTE instead of a WORD. To prevent this error, replace the BYTE definition with
a WORD definition.
Rolling-Forward with Btrieve v5.x & v6.0 (NetWare Btrieve v6.0)
Log files created with Btrieve v5.x can only be rolled-forward with Btrieve v6.0 under
certain circumstances. The following list describes each possibility.
- Log files created with Btrieve v5.x can be applied to v5.x files with the v6.0
xBROLL utilities (DBROLL, PBROLL, WBROLL).
- Log files created with Btrieve v6.0 are not compatible with the v5.x roll-forward utilities
(BROLLFWD and WBROLL 5.x) and cannot be used with the 5.x utilities.
- If a single log file contains entries that were created by both Btrieve v5.x and Btrieve v6.0
(using the xBROLL v6.0 utilities), if the first entry was created by Btrieve v5.x, only the v5.x
entries in the log file will be applied. If the first entry in the log file is created by Btrieve v6.0,
the xBROLL v6.0 utilities will only apply to the v6.0 entries.
- If a log file is created with Btrieve v5.x, the changes in the log file can be applied to a
Btrieve file with the xBROLL utilities multiple times. If a log file is created by Btrieve v6.0,
(even if the data file is a v5.x format file), once xBROLL is used to apply the changes to a
Btrieve file, the entries in the log file are marked as "used" and cannot be applied again to a data
file using xBROLL.
Fast Answers to Common Questions
BTRIEVE
Tip If a Btrieve file is opened from a workstation running Brequest v6.0, this
connection cannot be reset from a workstation running Brequest v5.16. However, if a file is
opened from a workstation running Brequest v5.16, its connection can be reset from a
workstation running Brequest v5.16 or v6.0.
With BTRIEVE.NLM v6.0, a successful Btrieve operation (status = 0) that accesses the
NLM must be performed from a workstation before that station can remotely reset the other
station. With BTRIEVE.NLM v5.15, the reset is not dependent on the success (status !=0) of the
call. If a Btrieve file is opened with Brequest v6.0 and needs to be reset remotely, run Brequest
v6.0 on the remote workstation. Before the reset operation, make a successful call to
BTRIEVE.NLM to establish a connection.
Q - I have just upgraded to NetWare v3.11 and the NetWare Btrieve NLM v5.15, and
Btrieve is running slower than expected. What should I do?
A - A combination of factors can result in slow performance after upgrading to the
NetWare Btrieve NLM v5.15 and NetWare v3.11:
- Btrieve page sizes are set to 1024 bytes and 512 bytes
- Workstations are using IPX v2.15
- During the installation process, disk block size was set to a size other than the default 4k
block size
Individually, each of these factors can cause minor Btrieve performance degradation. A
combination of factors affects performance more noticeably. To improve performance, rebuild
the Btrieve files with a page size of 4096 bytes, upgrade IPX to v3.10, and recreate volumes with
a 4K block size.
NETWARE SQL
Q - How many users can access NetWare SQL through the DAL Server NLM?
A - The number of users accessing NetWare SQL v3.0 through the DAL Server NLM
is limited to 200, even when using the 250-user version of NetWare SQL v3.0. This restriction is
related to a limitation in the current version of the AppleTalk NLM (200 users).
Q - When I try to run an embedded SQL application that was compiled with
WATCOM v8.5, my application hangs. Why does this happen?
A - When you use the WATCOM compiler v8.5 to compile embedded SQL source
code, NetWare SQL v3.0 uses the /FPI switch by default. This switch is for use with a math
co-processor. If your workstation does not have a math coprocessor, using this switch may hang
the embedded SQL application at runtime. If your workstation does not have a math coprocessor,
use the /FPC switch to compile the embedded SQL source code, instead of the /FPI switch.
Tip If the file ID for a file changes, all stored statements pertaining to that file are
invalidated. A file ID can change if the definition of the file is dropped and re-added to the
dictionary. NetWare SQL returns a status 204 (Table is not defined in the dictionary) when you
try to recall a stored statement that has an invalid file ID.
XTRIEVE PLUS
Q - Xtrieve PLUS v4.11 returns the error "No Views in Dictionary," when I try to
recall a view. What should I do?
A - Xtrieve PLUS v4.11 can return this error if NSREQ is loaded with the /d:
parameter set too low. To ensure that views are recalled properly, load NSREQ with a larger /d:
parameter.
NETWARE SYSTEM CALLS FOR DOS
Q - Where is the documentation for Close File And Abort Queue Job?
A - Some system calls refer to the functions Close File And Abort Queue Job,
however, this function does not exist. The functions that should be used are the DOS close API
(3Eh) and the Remove Job From Queue API (E3h 6Ah).
Q - How can you tell whether you are on a local DOS device, or on a redirected
network device?
A - Use the DOS call, Int 21H function 44, subfunction 0D, to detect if you are on a
redirected device. This test should work for all NetWare platforms, including NetWare Lite.
Tip The Set Spool Flags call (E0h(02h)) (used to set the form number) fails while
sending a job to a print queue. This failure can be verified through PCONSOLE. The form
number remains set to zero. Set Spool Flags fails to set the form number with the NetWare shell
v3.26, but performs properly under v3.22. Currently, the only workaround is to use version 3.22
of the shell or use set default capture flags.
NETWARE C INTERFACE FOR WINDOWS
Q - Under Windows v3.1 and with the debug version of the kernel, the Netware C for
Windows internal API, IPXYield(), returns the following warning messages:
- Register class: invalid hInstance
- Register class: windows procedure not exported
- Create Window: null instance handle
What should I do?
A - IPXYield() still functions correctly. Currently, however, there is no way to stop
these warning messages.
Novell Education is now offering several new and updated 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
- This new course provides a general overview of NetWare Btrieve v6.x and its new
features. It covers file structures, indexing, data integrity, record and file locking, caching,
operating modes, segmented keys, backward compatibility and utilities.
- 905: Programming with Btrieve
- This course has been enhanced to cover all Btrieve operations & environments, including
COBOL. It provides a complete introduction to Novell's server-based record manager. 50% of
class time is spent in programming workshops. Working knowledge of C, BASIC, Pascal, or
COBOL required. Prerequisite: 904: Btrieve: An Overview
- 907: Xtrieve PLUS
- This course has been updated to include new features introduced with NetWare SQL v3.0.
It teaches developers to use Xtrieve PLUS as a Btrieve or NetWare SQL programming utility.
Trains users of Btrieve- or NetWare SQL-based database applications to work effectively with
this menu driven utility.
- 911: NetWare Database Administrator
- This new course gives a complete, hands-on look at installing and configuring NetWare
SQL and NetWare Btrieve. It covers the basics of ANSI Standard Structured Query Language
(SQL), focusing on NetWare SQL and key database features like security, referential integrity
(RI), database design, data normalization and performance.
- 912: Programming with NetWare SQL
- This new course is designed for developers and experienced network and database
administrators who will be developing NetWare SQL applications or enhancing existing Btrieve
applications with NetWare SQL. It provides an in-depth look at the functionality of NetWare
SQL and discusses optimizing database systems for development of efficient applications using
Novell database tools.
- 930: Developing NetWare Loadable Modules (NLMs)
- This course introduces C programmers to server-based application development in the
32-bit NetWare 3.x environment. It covers basic concepts for writing server-based C applications
that access the NetWare 3.x C library (CLib). Requires working knowledge of the C language.
- 940: NetWare Programming: Basic Services
- This new lab-oriented class (40 percent lab work) introduces NetWare programming
concepts. It covers topics such as bindery services, file system services, print services, queue
management, connection and file-server services, and accounting and synchronization services.
This class requires knowledge of the C programming language.
- 945: NetWare Programming: Protocol Support
- This new class covers protocol support features. It also discusses network programming
concepts and techniques for developing client-side applications, including Service Advertising
Protocol (SAP) IPX/SPX, diagnostics, NetBIOS, TLI, and Named Pipes. This class requires
strong knowledge of the C programming language.
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. Customers outside of the US
should call 1-801-429-5508. For information on availability, location, and prices of classes
outside of the US, contact your local Novell office.
(Developer Trivia)
1. To which layer(s) of the OSI model does IPX belong?
A. Session/Transport
B. Network/Transport
C. Network
2. How many zeros are there in one decillion ?
A. 15
B. 27
C. 33
3. What is the maximum file size for a Netware 3.11 file?
A. 400 MB
B. 800 MB
C. 4 GB
4. What key sequence invokes the Microsoft Windows kernel debugger?
A. Ctrl-Alt-SysReq
B. Shift-Shift-Alt-Esc
C. Ctrl-Alt-Del
5. To take advantage of Btrieve v6.0's new Continuous Operations feature, all files must be
rebuilt to v6.0 format.
A. True
B. False
6. With Btrieve v6.0, you can rebuild Btrieve files using BSETUP.NLM.
A. True
B. False
7. With NetWare SQL requesters, which function is processed locally by NSREQ.EXE and
passed to the file server by NSREQS.EXE?
A. xMask
B. xConvert
C. XQLMask
D. XQLConvert
E. All of the above
8. With the NetWare SQL security, a user may belong to _____ group(s) in addition to the
Public Group.
A. one
B. three
C. five
Fun & Facts Answers
1. B
2. C
3. C
4. A
5. B
6. A
7. E
8. A
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 Humphries
Design: Creative Services, Provo
Contributors: Gaurang Amin,
Linda Anderson,
Vitek Boruvka,
Laura Heater,
Ken Lowrie,
Sudz Khawaja,
Diane Klinetob,
Clint McVey,
Chris Ojeda,
Paige Parker,
Mike Shoemaker,
Aslam Tejani,
Brenda Wallace
Special thanks to the Developer Support, Development, Developer Relations, Product Marketing,
and Marketing Communications staff who contributed time and valuable input.
Novell, the N design, NetWare, Btrieve, XQL, LAN WorkPlace and
LANalyzer are registered trademarks; NetWare Loadable Module (NLM),
NetWare Global Messaging, 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 MHS, NetWare
Asynchronous Communication Services (NACS), NetWare Management
System, Professional Development Series, NetWare 3270 LAN
Workstation, LANtern and Xtrieve PLUS are trademarks; and NetWire
and Professional Developers' Program are service marks of Novell,
Inc. OS/2, and AS/400 are registered trademarks, and NetBIOS and
SAA are trademarks of International Business Machines Corporation.
Microsoft is a registered trademark, and Windows is a trademark of
Microsoft Corporation. Macintosh and AppleTalk are registered
trademarks of Apple Computer, Inc. CompuServe is a registered
trademark of CompuServe Corporation. NFS is a registered trademark
of Sun Microsystems, Inc.
(c) 1992 Novell, Inc. All rights reserved.
|