> developer support home

JULY 1992 VOLUME 4 NUMBER 7


INDEX


MAD'S COLUMN

Hello and welcome to the July 1992 issue of Bullets!

I am never sure what to expect at computer conferences. Last month, two potentially different conferences were held: Novell's BrainShare/Japan and Microsoft's NT Developers Conference. The audiences and their expectations could have been quite different. I wondered what would the attendees be looking for and what messages would be delivered.

I was surprised to discover that the developers, their needs and their wishes were not that different. One of the keynote speakers at Brainshare reminisced about a conference he attended during the mid-1980's. At that conference, he said developers wanted three things: performance, stability and consistency. (I am surprised that, back then, it wasn't performance, performance and performance.) He said these are still the basic developer needs.

If he is correct, what does this say about the past decade? Have we been unsuccessful?

I think we have been successful in fulfilling some basic programming requirements and, while the computer industry continues to change as rapidly as ever, we are constantly working to meet the others. It is a very positive development to see the companies at these conferences asking their customers what their specific needs are. This trend can only help to "accelerate the growth of the network computing industry" in the next decade.

Happy_Programming!

Mad Poarch
Director
Developer Support/Service


ARTICLES:

Keeping Your Database in Sync

NetWare SQL v3.0 is the latest version of Novell's relational data access system developed specifically as a NetWare Loadable Module (NLM) for the NetWare v3.11 platform. NetWare SQL v3.0 offers Named Database support, page-level transactions (cursor stability), continuous operations during backups, and referential integrity (RI), which ensures that cross references between tables are always valid. This article will familiarize you with RI, NetWare SQL 3.0's implementation of it and how to install RI to keep your database in sync.

NetWare SQL's Implementation of Referential Integrity

Keeping a database in sync requires two types of data integrity: physical and logical. NetWare v3.11 works with NetWare Btrieve v6.0, a server-based version of the Btrieve record manager included as a component of NetWare SQL v3.0, to provide the physical data integrity with their automatic recovery functions. NetWare SQL v3.0 provides logical data integrity through two mechanisms: transaction control and RI.

NetWare SQL's transaction control utilizes the transaction and record-locking capabilities of NetWare Btrieve. In NetWare SQL v3.0, RI is initially established by the system administrator or application developer, and once established, it is transparent to any application development.

RI ensures that, when a field or group of fields in one table reference a field or group of fields in another table, any changes made to these fields are synchronized. A set of rules, referred to as referential constraints, define the relationships between tables. Several definitions are useful in understanding RI:

  • A primary key is a field or group of fields whose collective key value uniquely identifies each record in a table. Primary keys are implemented as unique, non-null indexes.
  • A foreign key is a field or group of fields that reference a primary key in the same or a different table. A foreign key cannot contain null values.
  • A parent table is a table containing a primary key referenced by a foreign key.
  • A dependent table is a table containing a foreign key that references a primary key in the same or a different table. A dependent table can contain multiple foreign keys.
  • A dependent row is a record in a dependent table whose foreign key value matches a primary key value in the referenced parent table.
  • A self-referencing table is a table which is its own parent table; in other words, it contains a foreign key that references its primary key.
  • A cycle is a reference path in which the parent table is its own descendant.
Every foreign key value in a dependent table must have a matching primary key value in the referenced parent table. Consequently, an attempt to insert a record with an unmatched foreign key value into a dependent table will fail. Similarly, an attempt to delete a record in a parent table to which a foreign key currently refers may fail, depending on how the foreign key is defined.

Managing an invoice tracking system is one example of a task in which RI is useful. Suppose that customer information is contained in one table and invoice information for each customer is kept in a second table. If a customer is deleted from the database while the customer had an outstanding invoice, the database would be logically corrupted because an invoice would exist for a customer that does not exist. If you used RI on this database, you could establish constraints to prevent customer information from being deleted if invoices exist.

Btrieve fully enforces all referential constraints defined by NetWare SQL. This prevents both Btrieve and NetWare SQL applications from compromising integrity constraints when modifying data. To implement RI, two new files have been added to the NetWare SQL system (which only exist if referential constraints have been defined via NetWare SQL). A file called RELATE.DDF is located with the rest of the dictionary files and contains the relationships between the primary and foreign keys in the tables. In addition, the SYS:\SYSTEM directory contains the file, DBNAMES.CFG, which is created when you define a Named Database.

DBNAMES.CFG contains the descriptive name of the database and the location of the dictionary files associated with that database. Named Database support is a new feature of NetWare SQL v3.0 that allows you to define a name for a database, and associate a dictionary path and datafile paths with that name. You can then use this name to access the database. A Named Database is required to set up RI and, by default, RI is enabled when you define a new Named Database.

When you define a referential constraint for a field in a given table, information is added to the physical Btrieve file to indicate that the file has RI constraints. Included in this information is the SQL database name and the SQL table name. NetWare Btrieve uses this information to look up the location of the dictionary files in DBNAMES.CFG, and then to check the relationships in RELATE.DDF. Based on the information in RELATE.DDF, NetWare Btrieve may access other Btrieve files involved in the relationship to verify data prior to performing the modification to the Btrieve file. As a result, NetWare Btrieve is opening more than just the file being modified. This can be seen using the NetWare SQL Monitor Utility (NDBMON.NLM), and should also be taken into account when configuring the maximum number of open files in the NetWare SQL Setup Utility (NDBSETUP.NLM).

Establishing RI

Establishing RI with NetWare SQL v3.0 is very easy. There are a few simple guidelines for defining referential constraints.
  • The database must be defined as a "Named Database" using the NDBSETUP utility.
  • All of the files in the database must reside on a single server; they can, however, be split across multiple volumes on that server.
  • Data paths defined in the dictionary cannot contain drive letters. Paths must be simple file names or relative paths.
  • If security is enabled on the database, a user must have the References right on a table to define referential constraints on the database.
  • SQL statements are used to define referential constraints. Referential constraints can not be defined using the primitives.
  • RI can be defined on both new and existing databases. All files need to be in the NetWare Btrieve v6.0 file format. For existing databases, files can be rebuilt to the new format using the BREBUILD utility.
  • Referential constraints are easy to define by using either the "CREATE TABLE" or "ALTER TABLE" SQL statement. These statements are used to define primary and foreign keys. The "ALTER TABLE" statement can also be used to remove referential constraints. These statements can be executed from one of the interactive utilities provided with NetWare SQL v3.0 (SQLScope or XQLI), or can be executed from an application using SQL-Level function calls. Figure 1 shows how to define RI with SQL statements.
FIGURE 1: Defining RI using SQL Statements
CREATE TABLE CUSTOMER
USING 'CUST.BTR'
(    PRIMARY KEY (ID),
IDINT(2),
NAME   CHAR(20),
ADDR   CHAR(20),
CITY   CHAR(10),
STATE  CHAR(2),
ZIP    CHAR(10))
WITH INDEX (ID UNIQUE)

ALTER TABLE INVOICE
ADD FOREIGN KEY custID (CUSTID)
REFERENCES CUSTOMER
ON DELETE RESTRICT

END of FIGURE 1
The "WITH INDEX" clause on the create table statement is optional, since NetWare SQL will automatically create the first index according to the field(s) specified as the primary key. Also notice that a "delete rule" is specified for deleting records in the INVOICE table.

With NetWare SQL, there are rules to Insert, Update and Delete foreign keys.

  • The Insert rule is RESTRICT. This means that for each foreign key in the record being inserted, the foreign key value must have an equivalent primary key value in the parent table.
  • The Update rule is RESTRICT. This means that a foreign key value must be updated to a new value that has an equivalent primary key value in the parent table.
  • The Delete rule can be either RESTRICT or CASCADE. If you specify RESTRICT as the delete rule, when you attempt to delete a record from the parent table, NetWare SQL first checks to see if a foreign key exists in any of the dependent tables before it allows the delete. For example, in Figure 2, the EMPLOYEE table has a foreign key, DeptID, which references the DeptID field from the DEPARTMENT table. If you try to delete an DeptID from the DEPARTMENT table which is referenced by a matching ID in the EMPLOYEE table, the delete will fail.
FIGURE 2: NetWare SQL CASCADE and RESTRICT delete rules

 DEPARTMENT table
            
   DeptID    <    RESTRICT      
                                 

                             

                             

               EMPLOYEE table
                                                         
  >   Employee      Employee      Employee     Dept  
         ID           Name        Location      ID   
                                                         


                       CASCADE                      

                                               

                                               

                             PROJECTS table    
                                                         
       Project    Project      Project      Employee  
         ID        Name      Description       ID     
                                                          


END of FIGURE 2
If you specify CASCADE as the delete rule, when you attempt to delete a record from the parent table, NetWare SQL will check to see if a matching foreign key value exists in any of the dependent tables. In Figure 2, the EMPLOYEE table has a primary key, EmployeeID, which is referenced by the EmployeeID field in the PROJECTS table. With the CASCADE delete rule, if you delete an EmployeeID from the EMPLOYEE table, NetWare SQL will delete all dependent rows from the PROJECTS table as well. If all descendants of a primary key have CASCADE as the delete rule, NetWare SQL will delete all dependent rows on a reference path to the original parent table.

When specifying the delete rule for a given foreign key, use the following guidelines:

  • The delete rule for a self-referencing table must be cascade.
  • A cycle with two or more tables cannot be delete-connected to itself. This means that the delete rule for at least two of the dependent tables in the cycle must be restrict.
  • Delete rules from multiple paths (dependent tables that reference the same parent table) must be the same.

Installing RI on a New Database

To setup RI on a new database, use the following steps:
  • Create a dictionary
  • Establish a database name for the dictionary with the NDBSETUP utility. You may wish to disable RI for the database until you have finished defining your constraints.
  • Design your database
    1. Decide how many tables the database will contain, what fields will be in each of the tables, and how the tables' fields relate to each other.
    2. Decide what fields need referential constraints and what the delete rules will be for the foreign keys; this step is sometimes easier if it is done graphically as in the diagram in Figure 2.
  • Define your tables and your referential constraints to the dictionary. Referential constraints can be added when tables are created, or after the tables have been created.
  • Enable RI for the database through NDBSETUP and populate the tables. These two steps can be interchanged depending on how you plan to populate your tables. If you are loading data into your tables from some type of sequential file, you may want to do this without enabling RI. Then, after you have added all the data, you can use the RIUTIL utility to check the consistency of your existing data, based on the referential constraints defined. If you are adding new data into a new system, you may want to enable RI from the start to ensure that all new data complies with the defined constraints.

Installing RI on an Existing Database

Before setting up referential constraints on an existing database, check with the application vendor or developer to make sure the restraints you install will not interfere with the applications. Some applications might allow null values for fields you wish to define as a primary or foreign key, or might perform inserts on dependent tables with no matching primary key values. In these cases, RI will cause new status codes to be returned which the application is not expecting. If the vendor or developer indicates that RI will not interfere with the application, follow these steps to install RI.
  • Convert all files created with version of Btrieve before v6.0, including the dictionary files, to the NetWare Btrieve v6.0 file format using BREBUILD.
  • Establish a database name for the dictionary with NDBSETUP. You may wish to disable RI until you finish defining your constraints.
  • Plan your referential constraints based on the existing indexes, or add new indexes as necessary to implement the constraint that you want. Again, this process may be easier if it is done graphically as in Figure 2.
  • Define your referential constraints to the dictionary using the ALTER TABLE statement.
  • Use the RIUTIL utility to check the consistency of your existing data based on the referential constraints that have been defined.
  • Make any necessary modifications to your data so that it conforms to the referential constraints defined. This can be done manually, or by using the RIUTIL -CHECK utility. RIUTIL -CHECK has an option that will remove any records that violate the RI constraints.
  • Once the RIUTIL utility reports that the database is "in sync," enable RI using NDBSETUP.
NetWare SQL v3.0 has been released only for the NetWare v3.11 environment as a NetWare v3.11 NLM. For additional product information, please contact 1-800-RED-WORD (1-800-733-9673) or 1-512-794-1796. For technical and developer support questions regarding any released Novell products, please call 1-800-NETWARE (1-800-638-9273) or 801-429-5588.

TECHNICAL INSIGHTS:

New ReturnVersion API for DLLs (NetWare C Interface for Windows v1.3)

The function, GetDLLVersion( ), was not exported or supported by the NetWare C Interface for Windows v1.3. However, Figure 3 contains an API, ReturnVersion( ). which, when placed directly into applications or an OBJ file, returns DLL version information.

FIGURE 3: Replacement for GetDLLVersion API

extern void ReturnVersion( BYTE far *majorVersion,
  BYTE far *minorVersion,
  BYTE far *revisionLevel,
  BYTE far *betaReleaseLevel );
   :

void GetDLLVersionInfo( char far *DLLName,
    BYTE far *majorVersion,
    BYTE far *minorVersion,
    BYTE far *revisionLevel,
    BYTE far *betaReleaseLevel )
{
   HANDLE hDriver;
   static FARPROC   lpfnReturnVersion;
   hDriver = LoadLibrary( DLLName );
   lpfnReturnVersion = GetProcAddress( hDriver, "ReturnVersion" );
   if ( lpfnReturnVersion != NULL )
 ( *lpfnReturnVersion )( (BYTE far *)&majorVersion,
(BYTE far *)&minorVersion,
(BYTE far *)&revisionLevel,
(BYTE far *)&betaReleaseLevel );
   if( lpfnReturnVersion == NULL ) {
 majorVersion = 0;
 minorVersion = 0;
 revisionLevel = 0;
 betaReleaseLevel = 0;
 }
} /* GetDLLVersionInfo */

/* Usage example */
   :
   static char DLLName[20] = "NWIPXSPX.DLL";
   BYTE majorVersion;
   BYTE minorVersion;
   BYTE revisionLevel;
   BYTE betaReleaseLevel;
   :
   GetDLLVersionInfo(DLLName, (BYTE far *)&majorVersion,
(BYTE far *)&minorVersion,
(BYTE far *)&revisionLevel,
(BYTE far *)&betaReleaseLevel );

END of FIGURE 3

IPX Function Calls in a WEP Fail (NetWare C Interface for Windows v1.3)

DLLs can use a Windows Exit Procedure (WEP) that is executed before unloading the DLL from memory. When the WEP procedure is called, your data or code segments may no longer be valid. For example, calling an IPX/SPX function where one of the parameters is an ECB will result in an invalid memory reference.

Instead of cleaning up IPX/SPX resources in a WEP procedure, you should write a function for clients to call to clean up resources before exiting. Novell's IPXSPX.DLL is an example of this design. This DLL exports a function called IPXSPXDeinit that clients call to clean up resources.

TTS & Pre-Imaging (NetWare Btrieve (NLM) v5.15)

If TTS is disabled at the server and the Btrieve data files to be accessed with the NetWare Btrieve v5.15 are flagged "transactional" (T), Btrieve will return a status 15 (Pre-image I/O Error) on all updates (Insert, Update and Delete operations) to the data files between Begin Transaction (19) and End Transaction (20) operations.

The status 15 is not returned when:

  • The update is performed outside of a Btrieve transaction
  • Before the update is performed inside of a Btrieve transaction, a successful update has occurred outside of a transaction with the current instance of Brequest. This case is reinitialized once Brequest is unloaded and loaded again on the workstation.
In all cases, even when the status 15 is not returned, no pre-imaging is performed if TTS is not enabled at the server.

If Btrieve data files are flagged transactional, TTS must be enabled at the server for pre-imaging to be performed. When TTS is disabled, flag all Btrieve files non-transactional (-T).

How To Get NetWare SQL v3.0 (NetWare SQL (NLM) v3.0)

New customers can obtain NetWare SQL v3.0 through an authorized Novell reseller. Registered users of NetWare SQL v2.x can upgrade to any user count of NetWare SQL v3.0. Registered users of XQL v2.x can only upgrade to the NetWare SQL Developer's Kit v3.0.
  • To upgrade a copy of NetWare SQL v2.x or XQL v2.x, customers should contact their local Novell resellers.
  • Customers in the U.S. and Canada may also order upgrades by calling Novell After Market Products (AMP) at 1-800-346-7177. Novell resellers are now able to furnish NetWare SQL v3.0 upgrades through the NetWare upgrade program.

Windows, TBMI, VIPX.386, & DOS Applications (NetWare Btrieve v5.x)

Within Windows, running Brequest and a DOS application in a DOS box requires different setups depending on which version of Windows you use and whether or not you run Windows in standard mode or enhanced mode.
  • If you run Windows v3.0 in standard mode, load TBMI.COM before starting Windows. In the DOS box, load TASKID.COM, BREQUEST.EXE, and the DOS application (in that order). TBMI.COM and TASKID.COM are currently available on Novell's CompuServe forum, NetWiresm (NOVLIB, LIB 1 or 5, WINUP6.ZIP).
  • If you run Windows v3.1 in standard mode, load TBMI2.COM before starting Windows. In the DOS box, load BREQUEST.EXE and then the DOS application. TBMI2.COM is provided with Windows v3.1.
  • If you run either Windows v3.0 or v3.1 in enhanced mode, then you should use VIPX.386. Modify the SYSTEM.INI file under the [386Enh] header by adding the line: "network=VIPX.386."
After starting Windows, load BREQUEST.EXE in the DOS box, and then load the DOS application. Use the VIPX.386 that is included in WINUP6.ZIP on NetWire. Do not use the version included with Windows v3.0.
  • If a Windows application (not DOS) requires BREQUEST.EXE, then load BREQUEST.EXE before you start Windows.

Pre-imaging in NetWare Btrieve v6.0 (NetWare Btrieve (NLM) v6.0)

NetWare Btrieve v6.0 creates a pre-image file when writing to a Btrieve file created with an earlier version of Btrieve. However, the format of this pre-image file is different from the format of a pre-image file created by earlier versions of Btrieve. Earlier versions of Btrieve cannot accurately interpret a pre-image file created by NetWare Btrieve v6.0 and vice versa.

If you need to interchange the Btrieve engine that will be accessing the pre-v6.0 Btrieve file, all pre-image files must be cleaned up prior to swapping engines. Use the following procedure to clean up these pre-image files:

  1. Check to see if a .PRE file exists for any Btrieve files
  2. If a .PRE file exists with a pre-v6.0 version of Btrieve:
    • open the Btrieve file in Exclusive mode
    • perform a Get First operation
    • perform an Update operation
    • close the Btrieve file (this should cause the .PRE file to be deleted)
  3. Switch engines
Remember that a Btrieve file can not be accessed simultaneously with a client Btrieve engine and the NetWare Btrieve server-based engine. This procedure should be used if it is necessary to swap between a pre-v6.x client engine and a v6.x server engine.

Novell Database Products & Case-Insensitivity (NetWare SQL (NLM) all versions)

With Btrieve, if a string, lstring or zstring key is created with the alternate collating sequence, UPPER.ALT, the case of the data in the key is ignored when performing a search on that key. For example, if a record is inserted with the key value "test," this record can be retrieved by performing a Get Equal operation with a Key Buffer parameter containing the value "TEST," "Test," "test" or any other combination of upper and lower case letters.

In addition, if two records are inserted with the values "test" and "TEST," they are considered duplicate key values. Get Equal on any case representation of "test" will always return the first record entered. When scanning the key values for this key, it may appear that Btrieve is not sorting the values properly, since "test" will be returned before "TEST" if the records were inserted in that order.

Case searches work differently with NetWare SQL. There is a CASE key-word which indicates that a field or index should be treated as case-insensitive (i.e. upper and lower case letters will be treated the same). There are two situations to consider. The CASE keyword can be specified for any string, lstring or zstring field in the dictionary and/or for any string, lstring or zstring index. For a case-insensitive field, restrictions are evaluated regardless of case. So, a record containing a Name field with the value "John" will be returned when a restriction of "Name = 'JOHN'" is specified. If CASE is not specified for a field, only exact matches with the value in the restriction will be returned, regardless of whether or not there is a case-insensitive index specified for this field.

For a case-insensitive index, the case of the data is ignored when sorting the data. Specifying that an index is case-insensitive causes Btrieve to create and maintain that key using the UPPER.ALT alternate collating sequence.

Figure 4 contains an example that demonstrates the different types of fields. Notice that the Name1 index is case-insensitive, but the Name2 index is case-sensitive.

FIGURE 4: CASE sensitivity and field types

CREATE TABLE Test USING "TEST.DAT"
  (Name1 CHAR(10) CASE, Name2 CHAR(10)) WITH INDEX (Name1 CASE, Name2)

INSERT INTO Test
  VALUES("John", "Doe")  VALUES("jane", "doe")  VALUES("JOHN", "BROWN")

  SELECT * FROM Test     SELECT * FROM Test     SELECT * FROM Test
  WHERE Name1 = "john"   WHERE Name2 = "Doe"    ORDER BY Name1


     Name1     Name2    Name1      Name2     Name1     Name2
---------------------------------------------------------------
John      Doe       John      Doe       jane      doe
JOHN      BROWN                         John      Doe
                                        JOHN      BROWN

END of FIGURE 4
When using Xtrieve PLUS v4.1x to create tables, case-insensitivity for a field is specified by selecting "No" for the "Case?" option for a string, lstring or zstring field on the field definition screen. When the cursor is in the "Case?" column, the help text at the bottom of the screen reads "Specify Case-sensitivity when used in view restrictions?"

Case-insensitivity for indexes is also specified by selecting "No" at the "Case" prompt on the index definition screen. When the Case selection box appears, the help text reads "Treat upper and lower case letters differently in sort?" Answering "No" to this question implies case-insensitivity. Figure 5 contains the Xtrieve PLUS definition for the table Test described above.

FIGURE 5: Example Xtrieve PLUS definition table

FIELD DEFINITIONS
----------------------------------------------------------------
Position   Key    Name    Type     Size    Dec   Delimiter   Case
----------------------------------------------------------------
   1        *     Name1   String    10                        No
  11        *     Name2   String    10                        Yes


INDEX DEFINITIONS
----------------------------------------------------------------
Key   Name     Field     Type     Dups   Mod   Case   Asc   Total
----------------------------------------------------------------
 0             Name1     String   Yes    No    No     Yes    0
 1             Name2     String   Yes    No    Yes    Yes    0

END of FIGURE 5
A confusing situation might occur if a field is defined as case-insensitive and that field is also an index, but the index is defined as the opposite: case-sensitive. Usually, a case-insensitive field implies that case is ignored on restrictions. However, if an index exists, NetWare SQL/Xtrieve PLUS will use that index to optimize the search. If the index is not defined with case-insensitivity (thus Btrieve is NOT using UPPER.ALT for this index), the optimized search will only find exact matches, and the restriction will only find exact matches. In this situation, the case-insensitivity of the field is overridden by the case-sensitive index. Therefore, if a case-insensitive field is also part of an index, that index should also be defined as case-insensitive.

Record Locking In Embedded SQL (NetWare SQL (NLM) all versions)

Record locking is not part of the industry standard for embedded SQL, so NetWare SQL's implementation of embedded SQL does not support it. Guaranteed access is only available through the use of transactions. In fact, by default, transaction processing is automatically enabled, causing all embedded SQL calls to be performed within NetWare SQL transactions.

Record locking is supported by both the Relational Primitive and SQL-Level functions, which can also be used to develop NetWare SQL applications.

Lotus Configuration for DataLens Driver (NetWare SQL (NLM) v3.0)

If a drive letter and path are used in the LOTUS.BCF file to specify the location of the Datalens Driver for NetWare SQL (NLM) v3.0, and this location is not the Lotus directory or the current working directory, the driver will not be found.

Always place the Datalens Driver (LTSNWSQL.DLD or LTSNWSQL.DLL) in the Lotus directory or in the current working directory.

NetWare Btrieve v6.0 & Patch311.NLM (NetWare Btrieve (NLM) v6.0)

When using BTRIEVE.NLM v6.0 with NetWare v3.11, make sure that PATCH311.NLM (the patch file for the version of CLIB.NLM released with NetWare v3.11) is in the SYS:\SYSTEM directory before you attempt to load BTRIEVE.NLM, regardless of which version of CLIB.NLM the networkuses. BTRIEVE.NLM v6.0 always attempts to automatically load this patch file. PATCH311.NLM will only load if the released CLIB.NLM is running. If the system uses a newer version of CLIB.NLM, PATCH311.NLM will detect it and do nothing. As long as the Btrieve NLM can locate the patch file, it will load whether PATCH311.NLM successfully loads or not.

Using Brequest in Multiple Desqview Sessions (NetWare Btrieve (NLM) v5.x)

With Desqview v2.40, if you have multiple sessions running Btrieve applications using the NetWare Btrieve requester (BREQUEST.EXE), Btrieve may return a status 79 (Programming Error). The Desqview v2.40 configuration option, "Network Buffers," can be increased to resolve this status code.

From a Desqview window, run the program DVSETUP. Then, select the advanced setup procedure. From the advanced menu, select the Network option. One of the network options is called "Network Buffers." The default for this parameter is 8. Raising this value to 16 will usually resolve the status 79.

Is TBMI/TBMI2 Loaded? (NetWare C Interface for Windows v1.x)

You can determine if TBMI/TBMI2 is loaded by using the interrupt INT 2Fh with 7A10h in AX with DX initialized to zero. The version will be returned in DX (Major version in DH, minor version in DL). The values in these registers will be zero if TBMI/TBMI2 is not installed. Using IPX/SPXInitialize can serve the same purpose by indicating that IPX could not be initialized (error 240 or 0xF0).

If you use the INT 2Fh method, remember that TBMI/TBMI2 are TSRs and run in REAL mode. If you run a Windows application which needs to check on TBMI, use DPMI to simulate the REAL mode interrupt.

Error Using Turbo Pascal Interface for NetWare SQL NetWare SQL (NLM) v3.0

The Turbo Pascal interface included with NetWare SQL (NLM) v3.0 lets you specify whether the application will use SQL-level functions, primitive functions, or both. To choose one type of function or both, "comment out" one or both of the following lines, which appear at the top of the interface file NWSQLINT.PAS:
{$DEFINE NWSQL_RELATIONAL_PRIMITIVES}

{$DEFINE NWSQL_SQL_FUNCTIONS}
If the second $DEFINE line (for the SQL-level functions) is "commented out," this indicates that only the primitive calls will be included and the interface cannot be compiled into a Turbo Pascal Unit. The compiler will return an error 59 (Undefined Forward).

Two of the prototypes defined in the miscellaneous section of this interface should be moved into the SQL-level prototype section:

  • PROCEDURE SQLLevelCall;
  • FUNCTION SQLManagerLoaded : BOOLEAN;

Passing Parameters with XQLP & Visual Basic (NetWare SQL (NLM) v3.0)

To pass Visual Basic strings "by reference," the function declaration section must specify "ByVal" on any string parameter. According to the Microsoft Visual Basic Programmer's Guide (1991) (pg. 382, "Calling DLL Routines with Specific Data Types"), the routines in most DLLs expect standard C strings which end in a null character. If a DLL routine expects a C string as an argument, declare the argument as a string with the "ByVal" keyword. When used with a string argument, "ByVal" tells Visual Basic to pass the string as a C string ending with a null character.

The "ByVal" clause tells Visual Basic to pass the string address by value (not by reference), instead of just passing the string itself. So, if the XQLP documentation requires a string parameter to be passed by reference, the Visual Basic Function Declaration needs to specify "ByVal." If XQLP requires the string by value, the Visual Basic function declaration needs to specify "as String" or "as VarName$."

Integers work just the opposite. If XQLP requires the integer by value, the Visual Basic function declaration must specify "ByVal." If XQLP requires the integer by reference, the Visual Basic function declaration needs to specify "as Integer" or "as VarName%." If XQLP requires a structure, which is generally the data buffer, Visual Basic stores "TypeDefs" in a different area than strings, and as such, it gets handled the same way as integers with respect to the "ByVal" clause in the Function Declaration.

Status 2001 with WBTRCALL (NetWare Btrieve (NLM) v5.15)

With the Windows Btrieve requester, WBTRCALL.DLL v5.17a (date: 6-28-91), Btrieve returns a status 2001 (Insufficient Memory) on any Btrieve call issued after a WBTRVSTOP call. The status 2001 only occurs within a single task or program. If an application that makes Btrieve calls is running and that application, or any other application calls WBTRVSTOP, the NetWare Btrieve NLM will return a status 2001 on each successive Btrieve call in all Btrieve applications that are running until the applications are restarted.

This situation has been resolved in the version of WBTRCALL.DLL (NetWare Btrieve v6.0) that ships with NetWare SQL (NLM) v3.0. If you use the v6.0 WBTRCALL.DLL, you also need WBTRVRES.DLL (also included with NetWare Btrieve v6.0).

IPXODI Options Affect SPX & Diagnostics (NetWare C Interface for DOS v1.2)

IPXODI allows certain options to be specified when it is loaded that affect what protocol support is installed. Specifically, the D option tells IPXODI NOT to load Diagnostics support. The A option tells IPXODI not to load Diagnostics support or SPX support. If diagnostics support is not loaded, BeginDiagnostics() will return 0xFE (254). If SPX support is not loaded, SPXInitialize() will return a zero.

Retrieving NetWare Volume Serial Numbers (NetWare System Calls for DOS v1.0)

Beginning with DOS v4.x, volume serial numbers were introduced. This information could usually be retrieved from the DOS BOOT sector. Under NetWare volumes, there is no DOS BOOT sector.

You can use an undocumented DOS function to retrieve volume serial numbers: INT 21h, function 69h. The example code in Figure 6 shows how you can retrieve data from drive I.

FIGURE 6: Retrieving NetWare Volume Serial Numbers

union REGS inRegs, outRegs;
struct SREGS segRegs;

struct MID {
WORD midInfoLevel;
LONG midVolumeSerialNumber;
BYTE midVolumeLabel[11];
BYTE midFileSystemType[8];
  } MidInfo;

far *pMidInfo;

void main (void)
{

   memset (&MidInfo, 0, sizeof (MidInfo));

   pMidInfo = (int *)&MidInfo;

   segread (&segRegs);
   inRegs.h.ah = 0x69;
   inRegs.h.al = 0x00;
   inRegs.h.bh = 0x08; /* drive letter to target */
   segRegs.ds =  FP_SEG (pMidInfo);
   inRegs.x.dx = FP_OFF (pMidInfo);

   int86x (0x21, &inRegs, &outRegs, &segRegs);
printf ("\nSerial Number: %lx", MidInfo.midVolumeLabel,
 MidInfo.midVolumeSerialNumber);
} /* main */

END of FIGURE 6

NIBBLES AND BITS

Fast Answers to Common Questions

NetWare C Interface for Windows

Q - What drivers do I need to develop and run Windows v3.1 applications?

A - The current driver requirements for developing and running Windows v3.1 applications are:

  1. the versions of VNETWARE.386, NETWARE.DRV, and VIPX.386 supplied with Windows v3.1.
  2. the DLLs supplied with the NetWare C Interface for Windows v1.3 (not the drivers mentioned in the '\DRVRS' directory).
  3. for Standard mode, the version of TBMI2.COM supplied with the NetWare C Interface for Windows v1.3.

NetWare C Interface for DOS

Q - I have a TSR which manages IPX/SPX communications to other nodes. I do not have to login to NetWare, so I only load IPX.COM. When I unload my TSR, the SHORT_LIVED socket I opened remains open. Are SHORT_LIVED sockets supposed to remain open upon program termination?

A - When a program terminates, the NetWare shell (e.g., NETX) closes Sockets opened as SHORT_LIVED. However, if the shell is not loaded, all sockets are treated like LONG_LIVED_SOCKETS. In this case, call IpxCloseSocket () before terminating the program.

NetWare & OS/2

Q - When will the NetWare OS/2 v2.0 requester be available?

A - The OS/2 v2.0 requester is available now from 1-800-UPDATE1. The price includes documentation. Members of the Professional Developers' Program (PDP), can also obtain the requester from the NDEVREL forum on NetWire. (Remember to unzip the file with the /d option.)

Q - Can 32-bit OS/2 v2.0 applications call the 16-bit Novell libraries?

A - Yes, but a thunk is required. A thunk is the procedure of telling a 32-bit function to handle a 16-bit API call.

NetWare for SAA LU6.2 Tools

Q - When I recompile the NLM example, CPIS.C, that is supplied with NetWare for SAA LU6.2 Tools (Feb. release) with the WATCOM v8.0 compiler, the example will not run correctly. What should I do?

A - This situation occurs with v8.x (and above) of the WATCOM compiler, which has been updated to define "far." In the NLM environment, the normal definition of "far" causes "far" pointers to be 48-bit (not 32-bit) and will not work with NetWare Lu6.2. For usable "far" pointer definitions, delete lines 40 through 42 of the header file CPIC_NET.H and insert the following four lines:

#ifdef far
   #undef far

#endif

#define far

Btrieve

Q - With NetWare Btrieve v6.0, when I perform an Insert (2) operation, NetWare Btrieve inserts for a while, then it returns a status 84 (Record in Use). What should I do?

A - Your application should retry if it receives a status 84. In this case, NetWare Btrieve is locking the key page for a brief moment and at this time another user is trying to access it.

Q - After I create a Btrieve file with an alternate collating sequence, is the alternate collating sequence file (the file that contained the new collating sequence) still required?

A - No. Btrieve stores the new collating sequence within the Btrieve file.

Q - If you create a supplemental index and then close the Btrieve file, does the supplemental index disappear from the file?

A - No, the supplemental index remains in the file until you perform a Drop Supplemental Index operation.

NetWare SQL (NLM) v3.0

Q - When I received NetWare SQL v3.0, I was surprised to find a NetWare Btrieve v5.15 diskette in the package. Why was this diskette included?

A - The NetWare Btrieve (NLM) v5.15 diskette is always shipped with NetWare v3.11, and since NetWare SQL v3.0 (20+ user) packages include a copy of NetWare Runtime, they also include a NetWare Btrieve (NLM) v5.15 diskette. This should not be used on the NetWare Runtime server; you should use the NetWare SQL v3.0 install utility to load NetWare Btrieve v6.0.

Q - Does NetWare SQL (NLM) v3.0 support Lotus 1-2-3 for Windows at this time?

A - No, there is currently no interface for Lotus 1-2-3 for Windows.

Xtrieve PLUS for DOS v4.10

Q - If I install Xtrieve PLUS for DOS v4.10 on a network, will the license agreement be violated if more than one person uses it?

A - No. Xtrieve PLUS 4.10 is licensed per server. Everyone who has access to the server where Xtrieve PLUS resides can use it without violating the license.


NOVELL EDUCATION

Novell Education is now offering several new and updated courses for developers who use Novell's development and database tools, including Btrieve, Xtrieve PLUS, and the NetWare Client APIs.
904: Btrieve: An Overview
This new course provides a general overview of Btrieve and its new features. Covers file structures, indexing, data integrity, record and file locking, caching, operating modes, segmented keys, backward compatibility and utilities.

Aug. 11 Sunnyvale, CA
Sept. 15 Chicago, IL

905: Programming with Btrieve
This course has been enhanced to cover all Btrieve operations & environments, including COBOL. 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

Aug. 12-14 Sunnyvale, CA
Sept. 16-18 Chicago, IL

907: Xtrieve PLUS
This course has been updated to include new features introduced with NetWare SQL v3.0. Teaches application 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.

Sept. 22-23 Austin, TX

930: Developing NetWare Loadable Modules (NLMs)
This course introduces C programmers to server-based application development in the 32-bit NetWare 3.x environment. 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.

Sept. 15-17 Austin, TX

940: NetWare Client Programming: NWCALLS
This new lab-oriented course (40% lab work) introduces network programming concepts and topics like bindery services, file system services, print services, queue management, connection and file server services and accounting and synchronization services. Requires knowledge of the C programming language.

Sept. 22-24 Provo, UT
Oct. 13-15 Chicago, IL

945: NetWare Client Programming: Protocol Support
This new course covers Protocol Support features. Covers network programming concepts and techniques for developing client-side applications, including SAP, IPX/SPX, diagnostics, NetBIOS emulation, TLI, & Named Pipes. Requires strong knowledge of C programming language.

Sept. 15-17 Austin, TX
Oct. 20-21 Sunnyvale, CA

To register or obtain information on pricing, location and course content for classes held in the US, call 1-800-233-3382, 1-801-429-5508 or 1-800-NETWARE. International customers should call 1-801-429-5508. For information on availability, location, and prices of international classes, contact your local Novell office.

FUN & FACTS

Test your "developing" skills by taking our Fun & Facts quiz. Have fun and good luck! (See the end of this section for answers.)
1.   Which of the following statements is true of BREBUILD.NLM?

A.   It allows you to redirect the file to another server

B.   It keeps a copy of the file in 5.x format

C.   It preserves the owner name after the conversion
2.   How many NLMs work together to provide communication services to the NetWare
v3.11 operating system?

A.   8

B.   7

C.   6
3.   What Btrieve data type does not exist in Xtrieve PLUS?

A.   Bit

B.   Unsigned Binary

C.   Money
4.   What module standardizes and manages the primary details of interfacing ODI multi-link
interface drivers to the LSL and the NetWare operating system?

A.   MSM.NLM

B.   HSM.NLM

C.   TSM.NLM
5.   What DDF file contains information about referential integrity constraints?

A.   VIEW.DDF

B.   FILE.DDF

C.   RELATE.DDF
6.   What NLM allows you to use connection encapsulating IPX packets within IP packets?

A.   SNMP.NLM

B.   TCPIP.NLM

C.   IPTUNNEL.NLM
7.   How do you initialize Btrieve for OS/2 (client-only version) within an application?

A.   Cannot be initialized through an application

B.   Use function BTRVINIT(char *)

C.   Use function WBTRINIT(char *)
8.   Name the socket number for the Diagnostic Packet

A.   0x454

B.   0x455

C.   0x456
9.   What console command is used to address memory above 16 MB on EISA computers ?

A.   None

B.   Register Memory

C.   Auto Register Memory Above 16 Meg
FUN & FACTS ANSWERS
1.   C
2.   A
3.   B
4.   A
5.   C
6.   C
7.   B
8.   C
9.   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.

Novell Labs

For information on Novell Labs development tools, education classes and product certification, in the U.S. and Canada call 1-800-453-1267 ext. 5544 or 1-801-429-5544, or call your local Novell office (see back cover of this issue).

Novell Developer Relations

Novell Professional Developers or those wishing to become members may contact Novell Developer Relations via telephone, fax, or electronic mail via Compuserve, MHS or the Internet.

Voice

For general information or questions on Novell Developer Relations programs, in the U.S. or Canada call 1-800-RED-WORD (1-800-733-9673). All others call 1-801-429-5281.

Fax

If you prefer, you may contact Novell Developer Relations via fax at 1-801-429-7207.

NetWire on CompuServe

Novell's NetWire forum is open to all registered Compuserve subscribers. Through the NDEVREL forum, Novell Professional Developer's Program-related issues or general questions may be posted. Through the NDEVINFO forum, customers who do not have products may post pre-sales product information questions on all Novell SDKs.

E-mail: MHS or Internet (SMTP)

You may direct your questions and comments to Novell Developer Relations via Novell's Message Handling Service E-mail facility. Address your messages to devprog@novell.com. Use the same address when going through the Internet E-mail system.

ACKNOWLEDGEMENTS

Publisher: Mad Poarch
Editor: Kirk R. Humphries
Design: Creative Services, Provo

Contributors: Gaurang Amin, Linda Anderson, Vitek Boruvka, Irit Diaz, Neda Eslami, Kumar Gaddam, David Harris, Sudz Khawaja, Ken Lowrie, Diane Klinetob, Nancy Kromar, Rudy McNeese, Chris Ojeda, Paige Parker, Jose Pruneda, Randy Reddy, Glenn Stephens, Brenda Wallace

Special thanks to the Developer Support, Development, Developer Relations, Product Marketing, and Marketing Communications staff who contributed time and valuable input.

(c) 1992 Novell, Inc. All rights reserved.

Novell, the N design, NetWare, Btrieve, XQL and LAN WorkPlace are registered trademarks, NetWare Lite, NetWare System Calls for DOS, NetWare Loadable Module (NLM), NetWare SQL, NetWare Btrieve, Xtrieve PLUS, NetWare C Interface for DOS, NetWare System Interface Technical Overview, NetWare RPC, NetWare RPC 386, NetWare LU6.2, Report Executive, and Professional Development Series (PDS) are trademarks, and NetWire and Professional Developers' Program (PDP) are servicemarks of Novell, Inc. Apple, Macintosh and AppleTalk are registered trademarks of Apple Computer, Inc. CompuServe is registered trademark of CompuServe Corporation. Microsoft is a registered trademark, and Windows and Visual Basic are trademarks of Microsoft, Inc. IBM and OS/2 are registered trademarks, and NetBIOS and SAA are trademarks of International Business Machines Corporation. Sun Microsystems and NFS are registered trademarks of Sun Microsystems, Inc. WATCOM is a trademark of WATCOM Systems, Inc.