'********* DOSWATCH.BAS

'Copyright (c) 1989 Ethan Winer

'DOSWatch is a TSR program that displays information about the current DOS
'service number at the top of the screen everytime an INT 21H is executed.
'To minimize the amount of memory taken when this program is resident, you
'should link with the STR00512, _NOVAL, and _NOREAD object files as follows:
'
'       LINK /NOE /NOD DOSWATCH STR00512 _NOVAL _NOREAD, , NUL, PDQ
'
'THIS PROGRAM WILL NOT WORK WITHIN THE QUICKBASIC ENVIRONMENT.


DEFINT A-Z
'$INCLUDE: 'PDQDECL.BAS'

DIM Registers AS RegType        'RegType is defined in PDQDECL.BAS

ID$ = "DOSWatch Ver. 1.02"      'ID$ prevents multiple installs

Row = CSRLIN                    'print at the current cursor location
Column = POS(0)
PDQPrint ID$, Row, Column, 7    'print the installation message

DIM Message AS STRING * 66
DIM DOSName AS STRING * 50

Zero$ = CHR$(0)                 'this is faster than CHR$(0) repeatedly
Fifty = 50                      'this is faster to pass to BlockCopy
Row = 1                         'where to print the message details
Colr = 9                        'use bright blue on black for the message
                                '  (9 is bright underlined on mono systems)

Registers.IntNum = &H21         'Registers is a TYPE defined in PDQDECL.BAS
                                'specify trapping Int 21h
PointIntHere Registers          'load Registers with what it needs, and pass
GOTO EndIt                      '  control to the next line at each Int. 21h


'----- the code below receives control with each Interrupt 21h

IntEntry1                       'this is the first mandatory step
IntEntry2 Registers, 0          'and this is the second one

Ticks = 0                       'assume we won't pause to read the display
Service = Registers.AX \ 256    'get the current service number in AH

SELECT CASE Service             'print some useful information
   CASE &HE
      Message$ = "Set disk drive to " + CHR$(Registers.DX + 65)

   CASE &H2C
      Message$ = "Get the DOS time"

   CASE &H30
      Message$ = "Get DOS version"

   CASE &H36
      Message$ = "Get disk free space"

   CASE &H3B
      GOSUB GetDOSName                              'load DOSName$ from DS:DX
      Message$ = "Change directory to " + DOSName$

   CASE &H3C
      GOSUB GetDOSName
      Message$ = "Create file " + DOSName$

   CASE &H3D
      GOSUB GetDOSName
      Message$ = "Open file " + DOSName$

   CASE &H3E
      Message$ = "Close handle " + STR$(Registers.BX)

   CASE &H3F
      Message$ = "Read from handle " + STR$(Registers.BX)

   CASE &H40
      Message$ = "Write to handle " + STR$(Registers.BX)

   CASE &H41
      GOSUB GetDOSName
      Message$ = "Delete file " + DOSName$
  
   CASE &H47
      Message$ = "Get current directory"
  
   CASE &H4B
      GOSUB GetDOSName
      Message$ = "Exec program " + DOSName$
  
   CASE &H4E
      GOSUB GetDOSName
      Message$ = "Find first file that matches " + DOSName$

   CASE &H4F
      Message$ = "Find next matching file"
  
   CASE ELSE
      Message$ = ""

END SELECT

PDQPrint "Service: " + HEX$(Service) + " " + Message$, Row, Row, Colr
IF Ticks THEN Pause Ticks

GotoOldInt Registers            'continue on to the original Int 21h

GetDOSName:                     'load DOSName$ with name pointed to by DS:DX
   BlockCopy Registers.DS, Registers.DX, VARSEG(DOSName$), VARPTR(DOSName$), Fifty
   Zero = INSTR(DOSName$, Zero$)           'find terminating zero byte
   DOSName$ = LEFT$(DOSName$, Zero - 1)    'blank out what remains
   Ticks = 8                               'pause 1/2 second for readability
   RETURN

EndIt:
   EndTSR ID$                              'terminate and stay resident

