Developer Links
SUPPORT FORUMS  
SAMPLE CODE & TIDS  
TEST/DEVELOPMENT KIT INFO
 
DEVELOPER LABS  
NOVELL SUPERLAB  
SUPPORT DOCUMENTS  
STRATEGIC/EXECUTIVE ISSUE TRACKING  
SYSOP PROGRAM  
     
Related Links
 
 
 
 
 
Related Links  
 

 
DEVELOPER SUPPORT HOME  

NOVEMBER 1992 VOLUME 4 NUMBER 10


INDEX


MAD'S COLUMN

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


ARTICLES:

Loading NWShell

NWShell can be loaded in two ways:
  1. 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]
  2. 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:
    1. If a full or relative path is specified on the file name, search there only.
    2. 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.
    3. 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.


TECHNICAL INSIGHTS:

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.
  1. Log files created with Btrieve v5.x can be applied to v5.x files with the v6.0 xBROLL utilities (DBROLL, PBROLL, WBROLL).
  2. 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.
  3. 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.
  4. 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.

NIBBLES AND BITS

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:
  1. Register class: invalid hInstance
  2. Register class: windows procedure not exported
  3. 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

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.

FUN & FACTS

(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

CONTACTING NOVELL

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.

ACKNOWLEDGEMENTS

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.