[comp.os.msdos.programmer] How can a TSR detect if it has been installed?

sorrow@oak.circa.ufl.edu (06/23/91)

I have written a  TSR that takes over the command line input for INT21H, in
other words an INT21H replacement.

How can it prevent itself from being re-installed?  I know programs such as
NORTON SI will show you who "owns" an interrupt, and my program comes up 
as the owner.  If there was a way to see if the owner was NOT DOS (i.e. another
program, such as a TSR, owned it) and to not install itself in that case, I
would like to know.

Thanks,

Brian
/*
Brian Hook -- MS-DOS Programmer for Contract
-----------------------------------------------------------------
"Seamus, that's my dog...I saw her today at the reception...sorry, sixTEEN
inches....better save the women and children first...but this one goes to 11!
..anymore of that plutonium nyborg?....there can be only ONE!....like a 
finger pointing to the moon....ease the seat back...one day closer to death
*/

resnicks@netcom.COM (Steve Resnick) (06/23/91)

In article <0094A83A.9AE8E1A0@MAPLE.CIRCA.UFL.EDU> sorrow@oak.circa.ufl.edu writes:
>I have written a  TSR that takes over the command line input for INT21H, in
>other words an INT21H replacement.
>
>How can it prevent itself from being re-installed?  I know programs such as
>NORTON SI will show you who "owns" an interrupt, and my program comes up 
>as the owner.  If there was a way to see if the owner was NOT DOS (i.e. another
>program, such as a TSR, owned it) and to not install itself in that case, I
>would like to know.
The way I have handled this, when using an interrupt vector which may
already be used by some other utility/tsr/system function is to
grab a few bytes in the CS of the ISR as a "signature", then when installing
my TSR, look at that segment address and the specific offset. If my signature
is there, I know my TSR has been installed, otherwise it's not and I can
install it....



Hope this helps....
Steve

-- 
-------------------------------------------------------------------------------
        resnicks@netcom.com, steve@camphq, IFNA:        1:143/105.0, 
                 co moderator for comp.binaries.os2
 Real life: Steve Resnick. Chief Software Architect, Process Scientific, Inc
 Flames, grammar and spelling errors >/dev/null
 The Asylum OS/2 BBS - (408)263-8017 12/2400,8,1 - Running Maximus CBCS 1.2
-------------------------------------------------------------------------------

jesse@gumby.Altos.COM (Jesse Chisholm AAC-RjesseD) (06/24/91)

resnicks@netcom.COM (Steve Resnick) writes:
| In article <0094A83A.9AE8E1A0@MAPLE.CIRCA.UFL.EDU> sorrow@oak.circa.ufl.edu writes:
| >I have written a  TSR that takes over the command line input for INT21H, in
| >other words an INT21H replacement.
| >
| >How can it prevent itself from being re-installed?  I know programs such as
| >NORTON SI will show you who "owns" an interrupt, and my program comes up 
| >as the owner.  If there was a way to see if the owner was NOT DOS (i.e. another
| >program, such as a TSR, owned it) and to not install itself in that case, I
| >would like to know.
| The way I have handled this, when using an interrupt vector which may
| already be used by some other utility/tsr/system function is to
| grab a few bytes in the CS of the ISR as a "signature", then when installing
| my TSR, look at that segment address and the specific offset. If my signature
| is there, I know my TSR has been installed, otherwise it's not and I can
| install it....

Many TSRs chain their interrupt and so it might be installed but no longer
be the first in the chain.  A way of checking for the signature you mention
that gets around this is to check at that offset for ALL segments from 0000
up to your current CS.  when you find the signature if the segment is not
equal to the current CS, then your TSR has been installed before and is still
in memory.  If the first time you find the signature is in your current
CS segment, then your TSR has not yet been installed.  Go for it.

-jesse
-- 
/* jesse@altos86.altos.com  jesse@gumby.altos.com  1-408-432-6200 */
main(){int i;for(i=6;--i;){printf("%c",97^((i>4)*43)|((i&2)?18:(i<5)
<<2));}printf(" ");for(i=9;--i;){printf("%c",((104^(i>7)*43^((i==5)*
24))|(((i&1)&(i<6))*3)|(i==6)|((i<4)*4))^((i==1)*2));}printf("\n");}

pshuang@athena.mit.edu (Ping-Shun Huang) (06/24/91)

In article <0094A83A.9AE8E1A0@MAPLE.CIRCA.UFL.EDU> sorrow@oak.circa.ufl.edu writes:

 > If there was a way to see if the owner was NOT DOS (i.e. another
 > program, such as a TSR, owned it) and to not install itself in that
 > case, I would like to know.

I think there are two fairly common ways to do it.

(1) Grab a completely unused interrupt/service and have your TSR return
identification codes when that interrupt/service is called: e.g.
Interrupt $21, AX=$FEED is probably unused, your TSR could grab it and
return non-trivial data in the registers, BX=$DEAF and CX=$BEAD and
DX=$FEED, the combination of which is unlikely to be accidentally
duplicated by another program.  Your TSR's installation routine can then
check before continuing.  Problem with this method: potential (although
darn unlikely) conflicts with other TSR's if by chance two programmer
decide on the same interrupt/service and ID codes.

(2) In your program, make sure somehow that near your ISR (interrupt
service routine) you place some identifying text string.  This is not
trivial to do, except in assembler, because your compiler is permitted
to move things like constant strings from one place to another, so
having the string adjacent to the routine in your source code does not
guarantee anything.  If you can do this, the installation routine would
need to do a search on memory locations near to where the interrupt
points.  Problem: if another program hooks the interrupt between the
previous installation of the TSR and now, you're scrod; in this case, if
someone loads CED after your INT21H program, the pointer now points into
CED code and not yours, and you have no easy way of tracing back the
interrupt chain since you don't know for sure where CED stored the old
copy of the Int $21 pointer.

--
Above text where applicable is (c) Copyleft 1991, all rights deserved by:
UNIX:/etc/ping instantiated (Ping Huang) [INTERNET: pshuang@athena.mit.edu]

ralf+@cs.cmu.edu (Ralf Brown) (06/24/91)

In article <4944@gumby.Altos.COM> jesse@gumby.Altos.COM (Jesse Chisholm AAC-RjesseD) writes:
}Many TSRs chain their interrupt and so it might be installed but no longer
}be the first in the chain.  A way of checking for the signature you mention
}that gets around this is to check at that offset for ALL segments from 0000
}up to your current CS.  when you find the signature if the segment is not
}equal to the current CS, then your TSR has been installed before and is still
}in memory.  If the first time you find the signature is in your current
}CS segment, then your TSR has not yet been installed.  Go for it.

That will fail on an increasing number of machines, because more and more
people are loading things high (particularly now that DOS5 is out).  The
only acceptably reliable method for determining prior installation is to
reserve a call for an installation check.  Not 100% foolproof, either, but
it can be made arbitrarily reliable by returning a pointer to a signature
string--the longer the string, the less likelihood of a clash.

-- 
{backbone}!cs.cmu.edu!ralf  ARPA: RALF@CS.CMU.EDU   FIDO: Ralf Brown 1:129/53
BITnet: RALF%CS.CMU.EDU@CARNEGIE   AT&Tnet: (412)268-3053 (school)   FAX: ask
DISCLAIMER?  Did  | It isn't what we don't know that gives us trouble, it's
I claim something?| what we know that ain't so.  --Will Rogers

kooijman@duteca.et.tudelft.nl (Richard Kooijman) (06/24/91)

jesse@gumby.Altos.COM (Jesse Chisholm AAC-RjesseD) writes:
>| >How can it prevent itself from being re-installed?  I know programs such as
>| >NORTON SI will show you who "owns" an interrupt, and my program comes up 
>| >as the owner.  If there was a way to see if the owner was NOT DOS (i.e. another

>Many TSRs chain their interrupt and so it might be installed but no longer
>be the first in the chain.  A way of checking for the signature you mention
>that gets around this is to check at that offset for ALL segments from 0000
>up to your current CS.  when you find the signature if the segment is not
>equal to the current CS, then your TSR has been installed before and is still
>in memory.  If the first time you find the signature is in your current
>CS segment, then your TSR has not yet been installed.  Go for it.

One problem with this solution: you can find the signature in your disk
buffers or disk cache. To avoid this you must look for a garbled signature.
So, say the ID string is "clock tsr v1.1", then you can change this
at run-time in "CLOCK TSR V1.1" and look for this string when your TSR is
started.
This solution works flawlessly (although the whole concept is ugly, due
to the lack of standardisation in the TSR world) and has been used by
many programmers (professionels too).


Richard.

-- 
Richard Kooijman                 |           (__)
Delft University of Technology   |           (oo)   -------------------------
Dept. Electrical Engineering     |    /-------\/ - | Don't have a Bart, man! |
Section Computerarchitecture     |   / |     ||     -------------------------
Neural Network Group             |  *  ||----||
Room 10.04                       |     ^^    ^^
kooijman@duteca.et.tudelft.nl    | The Simpsons' cow

mlord@bwdls58.bnr.ca (Mark Lord) (06/26/91)

In article <1991Jun24.083508.6970@donau.et.tudelft.nl> kooijman@duteca.et.tudelft.nl (Richard Kooijman) writes:
<jesse@gumby.Altos.COM (Jesse Chisholm AAC-RjesseD) writes:
<>| >How can it prevent itself from being re-installed?  I know programs such as
<
<>Many TSRs chain their interrupt and so it might be installed but no longer
<>be the first in the chain.  A way of checking for the signature you mention
<>that gets around this is to check at that offset for ALL segments from 0000

... various kludges from the dark ages omitted ...

Hey guys!  Ain't this what the "multiplex" interrupt was designed for ??

Check it out.

-ml

phil@ux1.cso.uiuc.edu (Phil Howard KA9WGN) (06/27/91)

resnicks@netcom.COM (Steve Resnick) writes:

>>I have written a  TSR that takes over the command line input for INT21H, in
>>other words an INT21H replacement.
>>
>>How can it prevent itself from being re-installed?  I know programs such as
>>NORTON SI will show you who "owns" an interrupt, and my program comes up 
>>as the owner.  If there was a way to see if the owner was NOT DOS (i.e. anothe
>>program, such as a TSR, owned it) and to not install itself in that case, I
>>would like to know.
>The way I have handled this, when using an interrupt vector which may
>already be used by some other utility/tsr/system function is to
>grab a few bytes in the CS of the ISR as a "signature", then when installing
>my TSR, look at that segment address and the specific offset. If my signature
>is there, I know my TSR has been installed, otherwise it's not and I can
>install it....

How can you differentiate between some other TSR owning it and DOS owning it?
-- 
 /***************************************************************************\
/ Phil Howard -- KA9WGN -- phil@ux1.cso.uiuc.edu   |  Guns don't aim guns at  \
\ Lietuva laisva -- Brivu Latviju -- Eesti vabaks  |  people; CRIMINALS do!!  /
 \***************************************************************************/

xsession@McRCIM.McGill.EDU (X session) (06/27/91)

Use int 2fh

quoting Ping-Shun Huang:

(1) Grab a completely unused interrupt/service and have your TSR return
identification codes when that interrupt/service is called: e.g.
Interrupt $21, AX=$FEED is probably unused, your TSR could grab it and
return non-trivial data in the registers, BX=$DEAF and CX=$BEAD and
DX=$FEED, the combination of which is unlikely to be accidentally
duplicated by another program.  Your TSR's installation routine can then
check before continuing.  Problem with this method: potential (although
darn unlikely) conflicts with other TSR's if by chance two programmer
decide on the same interrupt/service and ID codes.


But use AH=2fh  (I hope I got it right) instead DOS uses this one 
especially for this purpose  (print graftabl append etc.)
I might be able to find which program use which code, if I find it I'll 
post it.
I always use anything above 80h and it seems to work.

Hope this helps

                        grtnx  Martijn

                               nykerk@mcrcim.mcgill.ca