home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
i
/
isres.zip
/
ISRES.DOC
< prev
next >
Wrap
Text File
|
1990-01-19
|
6KB
|
140 lines
ISRES - Routines to determine if a program is already resident
--------------------------------------------------------------
Brian Foley
TurboPower Software
1/90
Version 1.0
Released to the public domain
Overview
----------------------------------------------------------------------------
The main purpose of ISRES is to provide a facility for non-resident programs
similar to TPTSR/OPTSR's standard module interface. That is, it provides
routines that allow a program to determine if it is being loaded for a
second time. The typical use for ISRES is in a program that allows other
programs to be executed, and needs to prevent the user from loading a second
copy of the same program. The supplied example program, RESTEST, illustrates
the use of ISRES in such a case.
A secondary use of ISRES is to provide a communication channel between
programs. When you call ISRES's Install routine, you can specify a pointer
to a data structure or routine that might be of interest to other programs.
This hook can be used to allow other programs access to a program's data, by
passing Install the address of that data. Or it can be used to allow other
programs to call a special routine, by passing Install the address of that
routine.
When using the hook for the latter purpose, keep in mind that the routine in
question must either 1) be compiled FAR or 2) be of type interrupt. If the
routine is *not* of type interrupt, it cannot refer to any data stored in
the data segment unless it sets up the DS register first. Practically
speaking, this means that the routine must be written in assembly language.
If the procedure *is* of type interrupt, the DS register will be set up
automatically, so the routine may refer to global data.
If you plan to use this hook to store the address of a procedure of type
interrupt, we suggest that you read about the standard module interface in
OPTSR (see Object Professional manual) or TPTSR (see Turbo Professional
manual). The technique you would need to employ, described there, basically
involves using ISRES's IsLoaded routine to retrieve the address of the
procedure, and OPINT/TPINT's EmulateInt to call it.
ISRES and TPTSR/OPTSR/OPSWAP
----------------------------------------------------------------------------
The technique used by ISRES to track down other programs is essentially
identical to that used by OPTSR, OPSWAP (also part of Object Professional),
and TPTSR. Consequently, you can use ISRES to locate a TSR that has called
InstallModule and, conversely, a TSR can use either ModuleInstalled or
ModulePtrByName to locate a non-resident program that uses ISRES. For
example, a program using ISRES could locate SMACS by executing the statement
SmacsIsLoaded := IsLoaded('SUPER MACS', P);
If SMACS is found, P will contain the address of SMAC'ss command entry
routine. Similarly, if a non-resident program using ISRES had executed the
statement
InstallModule('MYPROG', @MyData);
then a TSR could obtain the address of MyData by executing
const
MyProgName : string[6] = 'MYPROG';
var
MyProgIfc : IfcPtr;
MyDataPtr : Pointer;
begin
...
MyProgIfc := ModulePtrByName(MyProgName);
if MyProgIfc = nil then
{MYPROG not found}
else
MyDataPtr := MyProgIfc^.CmdEntryPtr;
...
end.
The important distinction to keep in mind here is that the pointer returned
by IsLoaded (if IsLoaded is True) is identical to the address passed to
Install (ISRES) or InstallModule (TPTSR/OPTSR/OPSWAP1). The pointer returned
by ModulePtrByName is the address of an IfcRecord (a record structure
defined by TPTSR/OPTSR/OPSWAP1). To obtain the address of a TSR's command
entry routine or a non-resident program's UserHook, you must look at the
CmdEntryPtr field in the IfcRecord.
ISRES and OPEXEC/EXECSWAP
----------------------------------------------------------------------------
ISRES is designed to allow it to be used in conjunction with the OPEXEC unit
in Object Professional, as well as the earlier EXECSWAP unit available on
CompuServe and elsewhere. That is, all of its data is stored in its code
segment, not in the data segment or on the heap. To use the two units (ISRES
and OPEXEC/EXECSWAP) together successfully, however, you must be certain
that ISRES appears *after* the other unit in the main program's USES list.
This insures that all of ISRES's code will remain resident in memory after
the bulk of the program has been swapped to disk or EMS.
Interfaced Declarations and Routines
----------------------------------------------------------------------------
ISRES interfaces the following types and routines:
type
ProgramName = string[8];
Name of a program to be installed. Note the limit of 8 characters.
procedure Install(Name : ProgramName; UserHook : Pointer);
Adds the specified program to a linked list of installed programs.
UserHook, if not nil, should point to a procedure or data structure of
potential interest to other programs. Does nothing if Name is empty.
function IsLoaded(Name : String; var UserHook : Pointer) : Boolean;
This routine searches the linked list of installed programs looking for
Name. If the program is found, IsLoaded will return True, and UserHook
will contain the pointer that was passed to Install when the program went
resident. The search is case-sensitive: 'MyProg' is not the same as
'MYPROG'. Note that Name may be longer than 8 characters: this allows
IsLoaded to locate TSRs written with TPTSR, OPTSR, or OPSWAP.
procedure Uninstall;
Removes the current program, if already installed, from the linked list of
installed programs.
procedure Init16;
Install ISRES's INT $16 handler. This routine is called automatically when
the program begins, and normally does not need to be called thereafter. It
should be called only if Restore16 has previously been called.
procedure Restore16;
Restore the INT $16 vector grabbed by Init16. This routine is called
automatically when the program ends, and normally does not need to be
called directly. It is interfaced only to allow the INT $16 vector to be
given back temporarily. It can be regrabbed by calling Init16.