home *** CD-ROM | disk | FTP | other *** search
- {$C-}
- {-----------------------------------------------------------------------------}
- { This code has been tested/used on an IBM PC using PC-DOS 2.10 }
- {-----------------------------------------------------------------------------}
-
- { Compiling: This program must be compiled with Turbo pascal to a COM file.
- Select the options, select C, select I and enter 300,
- select A and enter 400. Then select Q and then C. }
-
- { Authors: Lane H. Ferris (Stay Resident/Exit Code)
- Neil J. Rubenking (Directory code and ideas)
- Other Public Gurus on whose shoulders we stand.
-
- { PURPOSE: This code will serve as a template to create other "Stay Resident"
- programs in Turbo Pascal(tm). This code intercepts Int 16,
- displacing original Interrupt 16 Vector to User Interrupt 67.
- During execution of other programs, it can be invoked by the
- special key combination specified by "Our_Char" (in this case
- Alt-F10.)
-
- }
- Program Stay_Resident;
-
- { * * * * * * * CONSTANTS * * * * * * * * * * * * * * * * * * * * * * }
- const
- Our_Char = 113; {this is the scan code for AltF10}
- Ctrl_Home = #119; {Control Home Scan Code }
- Quit_Key = #119;
- Ctrl_End = #117; {Control End Scan Code }
- User_Int = $67; {place to put new interrupt}
- Kybrd_Int = $16; {BIOS keyboard interrupt}
-
- { - - - - - - T Y P E D E C L A R A T I O N S - - - - - - - - - - - - }
- Type
- Regtype = record Ax,Bx,Cx,Dx,Bp,Si,Di,Ds,Es,Flags:integer end;
- HalfRegtype = record Al,Ah,Bl,Bh,Cl,Ch,Dl,Dh:byte end;
- filename_type = string[64];
-
- { - - - - - - - T Y P E D C O N S T A N T S - - - - - - - - - - - - - - -}
- Const
- {regs is defined as a typed constant in order to get it in the code segment}
-
- Regs : regtype = (Ax:0;Bx:0;Cx:0;Dx:0;Bp:0;Si:0;Di:0;Ds:0;Es:0;Flags:0);
-
- OurDseg: integer = 0; {Our Data Segment Value }
- OurSseg: integer = 0; {Our Stack Segment Value }
- DosSseg: integer = 0; {Dos Stack Segment Value }
- Inuse : Boolean = false; {Recursion flag }
- { The following two constants *MUST* remain in the Ip:CS order }
- { because StaySave uses them as a JMP target }
- User_IntIP : integer = 0; {Pointer to Original IP Int value }
- User_IntCs : integer = 0; {Pointer to Original Cs Int value }
-
- { - - - - - - - V A R I A B L E S - - - - - - - - - - - - - - - - - - - - - -}
- Var
- SaveRegs : regtype;
- HalfRegs : halfregtype absolute regs;
- Terminate_flag : boolean ;
- Keychr : char ;
- Old_Xpos,Old_Ypos : integer ;
- x,y : integer ;
-
-
- { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - }
- {$I Nwindo.300} { W i n d o w M a k e r }
- { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - }
- { Check Terminate Keys
- { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - }
- {$I StayXit.320} {Check for Exit to Dos }
-
- {---------------------------------------------------------------------------- }
- { DIRECTORY PROCEDURE }
- { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - }
- Procedure Direct;
-
- Var
- Chd : Char; { command character }
- DirName, OldName : String[40]; { directory name }
- Xcursor : integer ; { cursor postions }
- Ycursor : integer ;
- OK, DONE : Boolean; { logical expressions }
-
- Begin
- KeyChr := #0;
- MkWin(15,5,65,20,Cyan); { make a large window }
- TextColor(White); { set color to white }
-
- Repeat { start main loop }
- DONE:=FALSE; { initiate done }
- ClrScr; { clear window }
-
- { menu options }
- GotoXY(20,1); Write('Options');
- GotoXY(9,2); Write('<M> MAKE A New Directory On B:');
- GotoXY(9,3); Write('<C> CHANGE Directory On B:');
- GotoXY(9,4); Write('<R> RETURN To Root Directory On B:');
- GotoXY(9,5); Write('<S> SHOW Current Directory of B:');
- GotoXY(9,6); Write('<E> EXIT this Utility');
-
- GotoXY(12,8); ClrEol;
- Write('Enter Option Letter: ');
- ReadLn(Chd); { get option number }
-
- If (Chd='M') or (Chd='m') then Begin { make a new directory }
- GetDir(0,OldName); { get current dir in use }
- DirName:=''; { initiate name }
- GotoXY(2,10); Write('New Directory or <CR> to Quit ? ');
- ReadLn(DirName); { get new name }
- If DirName<>'' then Begin { do if not nul }
- DirName:='B:\'+ DirName; { assign to b drive }
- ChDir('B:\'); { root dir in b }
- {$I-} MkDir(DirName) {$I+}; { make directory }
- OK:=(IOresult = 0); { ok = true if not exist }
- GotoXY(12,12);
- If OK then Begin { OK is true }
- ChDir(DirName); { change to new dir on b }
- WriteLn('New Directory Made');
- DONE:=TRUE
- End
- Else Begin { ok = false, dir exists }
- Write('Directory Already Exists'+Chr(7));
- GoToXY(12,13); WriteLn('Press Any Key To Continue');
- Read(Kbd,Chd)
- End; { ik OK }
- ChDir(OldName); { return to original dir }
- End; { if dirname <> '' }
- End; { if chd was M }
-
- If (Chd='C') or (Chd='c') then Begin { change a directory }
- DirName:='';
- GotoXY(2,10); Write('Directory or <CR> to Quit ? ');
- ReadLn(DirName); { get directory }
- If DirName<>'' then Begin { do if not nul }
- GetDir(0,OldName); { get current dir in use }
- ChDir('B:\'); { chg to root dir of b }
- DirName:='B:\'+ DirName; { assign to b drive }
- {$I-} ChDir(DirName) {$I+}; { change dir }
- OK:= (IOresult = 0); { OK = true if dir exists }
- GotoXY(10,12);
- If OK Then Begin { dir is exists }
- WriteLn('Directory Change Made');
- DONE:=TRUE
- End
- Else Begin { dir does not exist }
- Write('Dir Does Not Exist '+Chr(7));
- GotoXY(10,13); Write('Press Any Key To Continue');
- Read(Kbd,Chd)
- End; { if OK }
- ChDir(OldName); { return to old dir }
- End; { if dirname <> '' }
- End; { if chd was C }
-
- If (Chd='R') or (Chd='r') then Begin { change to root dir of b}
- GetDir(0,OldName); { get existing dir }
- Chdir('B:\'); { change to root on B }
- ChDir(OldName); { return to existing dir }
- DONE:=TRUE; { completed }
- End; { if chd was R }
-
- If (Chd='S') or (Chd='s') then Begin { show current dir of b }
- GetDir(2,OldName); { get the dir of b }
- GotoXY(10,12); Write('Directory Is: ',OldName);
- GotoXY(10,13); Write('Press Any Key To Continue');
- Read(Kbd,Chd)
- End; { if chd = S }
-
- If (Chd='E') or (Chd='e') then { exit utility }
- DONE:=TRUE;
-
- Until DONE;
-
- { Make a little Window and hold for }
- { user to give us a goose..or whatever}
- GotoXY(19,19);
- Get_Abs_Cursor(x,y); { Get Absolute Cursor Position }
- MkWin(x,y,x+12,y+3,White); { Put Window at Cursor }
- GotoXY(1,1);
- Write('Press a key . . .');
-
- While (Not Keypressed) do; { Pause until Key pressed }
- While Keypressed do { Get Ctrl-Home maybe }
- Read(Kbd,KeyChr); { Read the users Key }
- RmWin ; { Remove the Window }
- If KeyChr = Quit_Key then { If Terminate Key then }
- Stay_Xit ; { remove ourself from Memory }
- RmWin;
- End; { direct }
-
-
- {----------------------------------------------------------------------------}
- { P R O C E S S I N T E R R U P T }
- { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - }
- Procedure Process_Intr;
-
- { PURPOSE: This procedure replaces the standard keyboard interrupt. If
- anything but <Alt>-F10 is pressed, the key is passed on to the
- standard keyboard interrupt. B*U*T when <Alt>- F10 is pressed,
- this program takes over. The variable InUse is set to TRUE to
- ensure that this code doesn't try to run "on top of itself " AND to
- indicate to the Inline code to save/restore the original interrupt
- regs.
- }
- Begin
- { K e y b o a r d Interrupt o c c u r s here }
- {----------------------------------------------------------------------}
- {$I Staysave.320}
- {----------------------------------------------------------------------}
- { Check the Int 16 request function in Ah reg:
- 0 = read character from Keyboard
- 1 = check character available
- 2 = check shift key values
- }
-
- { HalfRegs.Ah = 0 This is a Character Request because StaySave }
- { doesnt allow an enter here unless it is! }
-
- Intr (User_Int, Regs); { Use the DOS replaced interrupt}
- { Get Key from Keyboard }
- If (Halfregs.Ah = Our_Char) { Separate the tests so code }
- { performs efficiently. }
- then if (not InUse) then { Must be OUR key and not busy }
-
- Begin { Demo }
- InUse := true; { "dont clobber saved stack"}
- { Get current Cursor Position }
- Old_Xpos := WhereX; Old_Ypos := WhereY;
- Direct;
- { Writeln(Lst,'That''s all Folks');{ Test Printer Output if you like }
- GotoXY(Old_Xpos,Old_Ypos); { Put Cursor Back }
- Regs.Ax := $1D00; { Give Dummy Ctrl Scan Code to }
- { interrupted program }
- InUse := false; { ok to restore interrupted stack }
- End; { Demo }
-
- {$I Stayrstr.310} { Return to Caller }
- End ;{Process_Intr}
- {-----------------------------------------------------------------------}
-
- {The main program installs the new interrupt routine and makes it permanently
- resident as the keyboard interrupt. The old keyboard interrupt is addressed
- through #67H, so it can still be used.
-
- The following dos calls are used:
-
- Function 25 - Install interrupt address
- input al = int number,
- ds:dx = address to install
- Function 35 - get interrupt address
- input al = int number
- output es:bx = address in interrupt
- Function 31 - terminate and stay resident
- input dx = size of resident program obtained from the memory
- allocation block at [Cs:0 - $10 + 3]
- Function 49 - Free Allocated Memory
- input Es = Block Segment to free
- Interrupt 20 - Return to invoking process
- }
-
- {-----------M A I N B L O C K---------------------------------------------}
- Begin {**main**}
-
- InUse := false;
- OurDseg:= Dseg; { Save the Data Segment Address for Interrupts }
- OurSseg:= Sseg; { Save our Stack Segment for Interrupts }
-
-
- Terminate_Flag := false ;
-
- {now install the interrupt routine}
-
- SaveRegs.Ax := $35 shl 8 + User_Int;
- Intr($21,SaveRegs); {Check to make sure int not already used}
-
- if SaveRegs.Es <> $00 then
- WriteLn ('Interrupt in use -- can''t install Resident Turbo Code')
- else
- begin
-
- { Initialize Your Progam Here since you wont get control again
- until "Our_Char" is entered from the Keyboard. }
-
- SaveRegs.Ax := $35 shl 8 + Kybrd_Int;
- Intr($21,SaveRegs); {get the address of keyboard interrupt }
-
- SaveRegs.Ax := $25 shl 8 + User_Int;
- SaveRegs.Ds := SaveRegs.Es;
- SaveRegs.Dx := SaveRegs.Bx;
- Intr($21,SaveRegs); { set the user-interrupt address to point
- { to the keyboard interrupt address }
-
- SaveRegs.Ax := $25 shl 8 + Kybrd_Int;
- SaveRegs.Ds := Cseg;
- SaveRegs.Dx := Ofs(Process_Intr);
- Intr ($21,SaveRegs); { set the keyboard interrupt to point to
- "Process-Intr" above}
-
- User_IntIp := MemW[0:User_Int * 4 ]; { Location of User Interrupt Ip }
- User_IntCs := MemW[0:User_Int * 4 +2];{ Location of User Interrupt Cs }
-
- Writeln(' Directory Utility: Press Alt-F10 to Activate');
-
- {now terminate and stay resident}
- { Pass return code of zero }
- SaveRegs.Ax := $31 shl 8 + 0 ; { Terminate and Stay Resident }
- SaveRegs.Dx := MemW [Cseg-1:0003] ; { Prog_Size from Allocation Blk}
- Intr ($21,SaveRegs);
-
- end;
- { END OF RESIDENCY CODE }
- end.
-