home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
pascal
/
das_buch
/
tsr
/
chktsr.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-06-04
|
17KB
|
685 lines
PROGRAM ChkTSR;
{$A+,B-,I-,S-,V+}
{$M 4096,2096,2096}
{**************************************
* Autor : Robert Flogaus *
* Datum : 24.4.1993 *
* Sprache: Turbo Pascal ab 5.x *
* oder kompatible *
* Sprachen *
* Übersetzung: tpc chktsr *
* Zweck: 1.) Überprüfung von *
* TSRs auf verbogene *
* Interrupt-Vektoren *
* 2.) Ergänzung der *
* TSR-Dateien *
* mit der Absicht, *
* a.) einen Installationscheck *
* und *
* b.) die leichte Deinstallation *
* zu gewährleisten. *
***************************************}
USES Dos;
TYPE
VectorArray=ARRAY[0..255] OF LONGINT;
Int_ChangeType=ARRAY[0..255] OF BOOLEAN;
LongArray=ARRAY[1..$FFF0] OF CHAR;
CONST
First:BOOLEAN=TRUE;
Termination_Type:WORD=0;
Env_Memory:LONGINT=0;
Program_Memory:LONGINT=0;
Data_Memory:LONGINT=0;
Is_Exe:BOOLEAN=FALSE;
Peculiar_Seg:BOOLEAN=FALSE;
No_Uninstall:BOOLEAN=FALSE;
ErrorFlag:BYTE=0;
ExitCode:BYTE=0;
VAR
f:FILE;
DirInfo:SearchRec;
PrgName:STRING[9];
Str5:STRING[5];
Path,p_1:PathStr;
CmdLine:STRING;
FBlock:^LongArray;
WPtr:^WORD;
Stack_Test:ARRAY[0..8] OF WORD;
Vector_No:ARRAY[1..256] OF BYTE;
FSize,MinAddr,MaxAddr,TempLong:LONGINT;
i,j,Result,tsrpsp_seg,chktsr_space,
TSRProg_space,Writeback_space,
Front_buf_bytes:WORD;
Number_of_vecs:BYTE;
OldCBreak,Extra_Byte,Free_Env,
NoExec:BOOLEAN;
JNChar:CHAR;
OldInt_Ptr,NewInt_Ptr:^VectorArray;
Int_Changed:^Int_ChangeType;
{$L chktsr.obj}
PROCEDURE Keep_Prog;EXTERNAL;
FUNCTION Get_Calc_Start_Progsize:LONGINT;EXTERNAL;
FUNCTION Get_Actual_Start_Progsize:LONGINT;EXTERNAL;
FUNCTION Get_TSRProg_Space:WORD;EXTERNAL;
FUNCTION Get_Int_ChangedAdd:POINTER;EXTERNAL;
FUNCTION Get_TSRProg_Add:POINTER;EXTERNAL;
FUNCTION Get_WriteBack_Space:WORD;EXTERNAL;
FUNCTION Get_WriteBack_Add:POINTER;EXTERNAL;
FUNCTION Mouse_Used:BOOLEAN;EXTERNAL;
FUNCTION Get_Old_FSize:WORD;EXTERNAL;
FUNCTION Get_Old_ChkTSR_Space:WORD;EXTERNAL;
FUNCTION DosGetMem(VAR Ptr:POINTER;Blocksize:WORD):BOOLEAN;EXTERNAL;
FUNCTION ResizeBlock(VAR Ptr:POINTER;Blocksize:WORD):BOOLEAN;EXTERNAL;
PROCEDURE Read_Line(VAR s:STRING;maxlen:BYTE);EXTERNAL;
FUNCTION get_jn:CHAR;EXTERNAL;
PROCEDURE debugexec(prog:PathStr;CmdLine:ComStr);EXTERNAL;
FUNCTION set_exe_data:BOOLEAN;EXTERNAL;
FUNCTION chkconverted_already:BOOLEAN;EXTERNAL;
FUNCTION restore_exe:LONGINT;EXTERNAL;
PROCEDURE adjust_checksum;EXTERNAL;
PROCEDURE patch;EXTERNAL;
FUNCTION ucase(s:STRING):STRING;
VAR
i:BYTE;
BEGIN
FOR i:=1 TO Length(s) DO
s[i]:=UpCase(s[i]);
ucase:=s
END;
PROCEDURE strgwrite(z:STRING);
BEGIN
Write(z)
END;
PROCEDURE terminate_program;
BEGIN
strgwrite(#13#10'CHKTSR beendet.'#13#10);
Halt(0)
END;
PROCEDURE terminate_with_help;
BEGIN
strgwrite('SYNTAX: CHKTSR Programmname'+
' [Parameterliste]'#13#10+
'Zur Wiederherstellung nicht '+
'lauffähiger Programme vorher'+
': SET CHKTSR=NOEXEC'#13#10);
Halt(1)
END;
FUNCTION cvtasciiz(VAR a):STRING;
VAR
i:BYTE;
cstr:STRING;
carr:ARRAY[1..255] OF CHAR ABSOLUTE a;
BEGIN
i:=1;
WHILE (i<=255) AND (carr[i]<>#0)
DO BEGIN
cstr[i]:=carr[i];
Inc(i)
END;
cstr[0]:=Chr(i-1);
cvtasciiz:=cstr
END;
PROCEDURE checkresulth;
BEGIN
IF IOResult<>0 THEN BEGIN
SetCBreak(OldCBreak);
strgwrite(#7'Dateifehler beim '
+'Bearbeiten von ');
strgwrite(cvtasciiz(FileRec(f).Name));
terminate_program
END
END;
FUNCTION hex(num:LONGINT):STRING;
VAR
st:STRING;
rest:BYTE;
BEGIN
IF num<>0 THEN BEGIN
st:='';
WHILE num<>0 DO BEGIN
rest:=num AND 15;
num:=num SHR 4;
IF rest<10 THEN
st:=Chr(rest+48)+st
ELSE
st:=Chr(rest+55)+st
END;
hex:=st+'h'
END
ELSE
hex:='0h'
END;
PROCEDURE do_conversion;
PROCEDURE back2sq1;
BEGIN
Erase(f);
Result:=IOResult;
Assign(f,p_1);
Rename(f,Path);
checkresulth;
SetCBreak(OldCBreak);
strgwrite(#13#10#7'Schreibfehler bei '+
'Datei ');
strgwrite(Path);
terminate_program
END;
BEGIN {do_conversion}
SetCBreak(FALSE);
p_1:=Copy(Path,1,Length(Path)-3)+'BAK';
Assign(f,p_1);
Erase(f);
Result:=IOResult;
IF (Result<>0) AND (Result<>2) THEN
BEGIN
SetCBreak(OldCBreak);
strgwrite(#7'Kann Datei ');
strgwrite(p_1);
strgwrite(' nicht löschen!');
terminate_program
END;
Assign(f,Path);
Rename(f,p_1);
checkresulth;
Assign(f,Path);
ReWrite(f,1);
IF IOResult<>0 THEN
back2sq1
ELSE BEGIN
BlockWrite(f,FBlock^,FSize,Result);
IF (IOResult<>0) OR (FSize>Result)
THEN BEGIN
Close(f);
back2sq1
END
ELSE BEGIN
Close(f);
IF IOResult<>0 THEN back2sq1
END;
SetCBreak(OldCBreak);
strgwrite('Neue Dateigröße ');
Write(FSize);
strgwrite(' (');
strgwrite(hex(FSize));
strgwrite(') Byte'#13#10'Unveränderte'
+' Datei in ');
strgwrite(p_1)
END
END;
PROCEDURE get_limits;
BEGIN
MinAddr:=LONGINT(tsrpsp_seg) SHL 4;
IF Program_Memory>$FFFF THEN
MaxAddr:=MinAddr+$FFFF
ELSE
MaxAddr:=MinAddr+Program_Memory-1
END;
PROCEDURE std_ptr(VAR Ptr:LONGINT);
VAR
normptr:LONGINT;
BEGIN
normptr:=((Ptr AND $FFFF0000) SHR 12)
+(Ptr AND $FFFF);
IF (normptr<MinAddr)
OR (normptr>MaxAddr) THEN
Peculiar_Seg:=TRUE
ELSE
Ptr:=normptr-MinAddr {Ofs zum PSP}
END;
FUNCTION flushnget_jn:CHAR;
BEGIN
strgwrite(' (J/N)? ');
Flush(Output);
flushnget_jn:=get_jn;
END;
BEGIN {main program}
GetCBreak(OldCBreak);
strgwrite(#13#10'CHKTSR 1.0, (C) Robert '+
'Flogaus, 1993'#13#10);
IF ParamCount>0 THEN BEGIN
p_1:=ParamStr(1);
CmdLine:='';
i:=Pos('/',p_1);
IF i>0 THEN BEGIN
j:=Length(p_1)-i+1;
CmdLine:=Copy(p_1,i,j)+' ';
Dec(p_1[0],j)
END;
FOR i:=2 TO ParamCount DO
CmdLine:=CmdLine+ParamStr(i)+' ';
IF Length(CmdLine)>0 THEN
Dec(CmdLine[0]);
IF (Pos('?',p_1)>0) OR
(Pos('*',p_1)>0) THEN
terminate_with_help;
p_1:=ucase(p_1);
IF Length(p_1)>4 THEN
Str5:=Copy(p_1,Length(p_1)-3,4)
ELSE
Str5:=p_1;
IF (Str5<>'.COM') AND (Str5<>'.EXE')
THEN BEGIN
Path:=FSearch(p_1+'.COM',
GetEnv('PATH'));
IF Path='' THEN
Path:=FSearch(p_1+'.EXE',
GetEnv('PATH'))
END
ELSE
Path:=FSearch(p_1,GetEnv('PATH'));
IF Path='' THEN terminate_with_help;
FindFirst(Path,Anyfile,DirInfo);
IF (DirInfo.Attr AND (Hidden+SysFile+
VolumeID+Directory))>0 THEN
terminate_with_help;
New(NewInt_Ptr);
New(OldInt_Ptr);
i:=Length(Path)-4;
j:=i;
WHILE (i>0) AND (Path[i]<>'\') AND
(Path[i]<>':') DO Dec(i);
PrgName:=Copy(Path,i+1,j-i);
IF Length(PrgName)>8 THEN
PrgName[0]:=#8;
Int_Changed:=Get_Int_ChangedAdd;
NoExec:=ucase(GetEnv('CHKTSR'))
='NOEXEC';
IF NOT NoExec
THEN BEGIN
FileMode:=0;
FillChar(Stack_Test,SizeOf(Stack_Test),0);
Assign(f,Path);
Reset(f,1);
checkresulth;
BlockRead(f,Stack_Test,SizeOf(Stack_Test),Result);
checkresulth;
Close(f);
checkresulth;
SetCBreak(FALSE);
SwapVectors;
debugexec(Path,CmdLine);
SwapVectors;
SetCBreak(OldCBreak)
END
ELSE
DosError:=0;
strgwrite(#13#10'Programm ');
strgwrite(Path);
strgwrite(#13#10#13#10);
FillChar(Int_Changed^[$22],3,FALSE);
{INT 22h-24h irrelevant}
Number_of_vecs:=0;
IF ErrorFlag<>0 THEN BEGIN
IF (ErrorFlag AND 1)=1 THEN BEGIN
strgwrite(#7'Nicht residentes '+
'Programm verbog von CHKTSR '+
'verwendete(n) Interrupt(s) 21h, '+
'27h oder 33h. Diese(r) '+
'Interrupt(s) wurde(n) nicht '+
'zurückgesetzt.'#13#10'CHKTSR '+
'sollte resident bleiben. Sind '+
'Sie damit einverstanden');
IF flushnget_jn='J' THEN BEGIN
strgwrite('CHKTSR bleibt '+
'resident.');
Flush(Output);
SwapVectors;
Keep_Prog
END
END
ELSE strgwrite(#7'MCB nicht gefunden.');
strgwrite(#13#10#7'Bitte neu booten!');
terminate_program
END;
IF (Termination_Type<>0) THEN BEGIN
IF (tsrpsp_seg=0) THEN BEGIN
strgwrite(#13#10#7'Fehler bei der '+
'Programmauswertung!');
terminate_program
END;
strgwrite('PSP-Segment: ');
strgwrite(hex(tsrpsp_seg));
strgwrite(#13#10);
FOR i:=0 TO 255 DO
IF Int_Changed^[i] THEN BEGIN
Inc(Number_of_vecs);
Vector_No[Number_of_vecs]:=i;
IF First THEN BEGIN
First:=FALSE;
get_limits;
strgwrite('Interrupt-Vektor '+
' ISR-Adresse'#13#10)
END;
Str5:=hex(NewInt_Ptr^[i] SHR 16);
WriteLn(hex(i):9,' ':11,
Str5:5,':',
hex(NewInt_Ptr^[i] AND $FFFF));
std_ptr(NewInt_Ptr^[i])
END;
strgwrite(#13#10);
IF Mouse_Used THEN BEGIN
strgwrite('Maustreiber umgesetzt!'
+#13#10);
PrgName:=PrgName+#32;
END
END;
IF NOT NoExec THEN
CASE Termination_Type OF
0:
BEGIN
IF DosError=0 THEN BEGIN
strgwrite('Programm normal beendet');
strgwrite(', Exitcode ');
strgwrite(hex(ExitCode))
END
ELSE IF DosError=8 THEN
strgwrite(#7'Speichermangel!')
ELSE
strgwrite(#7'Fehler bei der '+
'Programmausführung.');
strgwrite(#13#10);
END;
$2700:strgwrite('TSR mit INT 27h'#13#10);
ELSE BEGIN
strgwrite('TSR mit Funktion 31h von '+
'INT 21h');
strgwrite(', Exitcode ');
strgwrite(hex(Lo(Termination_Type)));
strgwrite(#13#10)
END
END;
IF Termination_Type<>0 THEN BEGIN
IF Program_Memory<$60 THEN
Program_Memory:=$60;
strgwrite(#13#10'Hauptspeicherbe'+
'darf (resident):');
WriteLn(#13#10'Programm: ',
Program_Memory:6,' (',
hex(Program_Memory):6,
') Byte');
WriteLn('Umgebung: ',
Env_Memory:6,' (',
hex(Env_Memory):6,')',' Byte');
WriteLn(' Daten: ',
Data_Memory:6,' (',
hex(Data_Memory):6,')',
' Byte'#13#10)
END
END
ELSE
terminate_with_help;
IF (DirInfo.Attr AND ReadOnly)=ReadOnly
THEN BEGIN
strgwrite(#7'Datei ist '+
'schreibgeschützt!');
terminate_program
END;
FileMode:=0;
Assign(f,Path);
Reset(f,1);
checkresulth;
FSize:=FileSize(f);
strgwrite('Dateigröße auf Disk '+
'derzeit ');
Write(FSize);
strgwrite(' (');
strgwrite(hex(FSize));
strgwrite(') Byte'#13#10);
TSRProg_space:=Get_TSRProg_Space;
chktsr_space:=TSRProg_space
+Length(PrgName)
+(3*Number_of_vecs)
+3;
Writeback_space:=Get_WriteBack_Space;
IF (FSize+chktsr_space+Writeback_space)
<=$FEF0 THEN BEGIN
IF NOT DosGetMem(POINTER(FBlock),
FSize+chktsr_space
+Writeback_space+255)
THEN BEGIN
strgwrite(#7'Speichermangel!');
terminate_program
END
END
ELSE BEGIN
IF Termination_Type<>0 THEN
strgwrite(#7'Programm zu groß!');
terminate_program
END;
BlockRead(f,FBlock^,FSize,Result);
checkresulth;
IF Result<>FSize THEN BEGIN
strgwrite(#7'Lesefehler!');
terminate_program
END;
Close(f);
checkresulth;
Is_Exe:=(FSize>$1A) AND (((FBlock^[1]='M')
AND (FBlock^[2]='Z')) OR
((FBlock^[1]='Z') AND (FBlock^[2]='M')));
IF Termination_Type<>0 THEN BEGIN
strgwrite('Max. nutzbarer '+
'Speicher (Start): ');
IF (NOT Is_Exe) THEN
strgwrite('ALLES'#13#10)
ELSE BEGIN
TempLong:=Get_Calc_Start_Progsize;
IF TempLong=$FFFFFFFF THEN
strgwrite('ALLES'#13#10)
ELSE
WriteLn(TempLong,' (',
hex(TempLong),
') Byte')
END;
strgwrite('Belegter Speicher'+
' (Start): ');
TempLong:=Get_Actual_Start_Progsize;
WriteLn(TempLong,' (',hex(TempLong),')'+
' Byte')
END;
IF NOT chkconverted_already THEN
BEGIN
IF Termination_Type=0 THEN
terminate_program;
IF Lo(DosVersion)<3 THEN BEGIN
strgwrite(#7'Von diesem Programm '+
'veränderte TSR-Programme'#13#10+
'wären auf ihrem System nicht '+
'lauffähig.');
terminate_program
END;
IF Peculiar_Seg THEN BEGIN
strgwrite(#7'Interruptvektoren auf'+
' Bereiche außerhalb PSP-Segment '+
'umgesetzt.');
terminate_program
END;
IF FSize>62000-TSRProg_space
-(3*Number_of_vecs)
THEN BEGIN
strgwrite(#7'Programm zu groß!');
terminate_program
END;
IF Is_Exe THEN BEGIN
IF NOT set_exe_data THEN BEGIN
strgwrite(#7'.EXE-Datei mit '+
'falscher Länge!');
terminate_program
END;
TSRProg_space:=Get_TSRProg_Space;
Inc(chktsr_space,Get_WriteBack_Space);
IF NOT ResizeBlock(POINTER(FBlock),
FSize+chktsr_space+$100) THEN BEGIN
strgwrite(#7'Speichermangel!');
terminate_program
END
END;
strgwrite('Darf ');
strgwrite(Path);
strgwrite(' geändert werden');
IF flushnget_jn='N' THEN
terminate_program;
strgwrite('Deinstallation ermöglichen');
JNChar:=flushnget_jn;
IF JNChar='J' THEN BEGIN
strgwrite('Befehlszeilenparameter'+
' zur Deinstallation? ');
Flush(Output);
Read_Line(CmdLine,35)
END
ELSE BEGIN
CmdLine:=#13#13;
No_Uninstall:=TRUE
END;
strgwrite('Mehrfachinstallation '+
'unterbinden');
JNChar:=flushnget_jn;
IF No_Uninstall AND (JNChar='N') THEN
terminate_program;
IF Env_Memory=0 THEN
Free_Env:=FALSE
ELSE BEGIN
strgwrite('Benötigt das TSR seine '+
'Programmumgebung');
Free_Env:=(flushnget_jn='N')
END;
Inc(chktsr_space,Length(CmdLine));
Extra_Byte:=Is_Exe AND
(Odd(chktsr_space+FSize));
IF Extra_Byte THEN Inc(chktsr_space);
patch;
IF Is_Exe THEN BEGIN
FillChar(FBlock^[FSize+1],
Front_buf_bytes,0);
i:=FSize+Front_buf_bytes+1;
Move(Get_TSRProg_Add^,FBlock^[i],
TSRProg_space);
Inc(i,TSRProg_space)
END
ELSE BEGIN
IF chktsr_space<FSize THEN
Move(FBlock^,FBlock^[FSize+1],
chktsr_space)
ELSE
Move(FBlock^,
FBlock^[chktsr_space+1],FSize);
Move(Get_TSRProg_Add^,FBlock^,
TSRProg_space);
i:=TSRProg_space+1
END;
Move(PrgName,FBlock^[i],
Length(PrgName)+1);
Inc(i,Length(PrgName)+1);
Move(CmdLine,FBlock^[i],
Length(CmdLine)+1);
Inc(i,Length(CmdLine)+1);
FBlock^[i]:=Chr(Number_of_vecs);
Inc(i);
FOR j:=1 TO Number_of_vecs DO BEGIN
Result:=Vector_No[j];
FBlock^[i]:=Chr(Result);
Move(NewInt_Ptr^[Result],FBlock^[i+1],2);
Inc(i,3)
END;
IF Is_Exe THEN BEGIN
FillChar(FBlock^[i],$210+
BYTE(Extra_Byte),0);
Inc(FSize,chktsr_space);
WPtr:=@FBlock^[3];
i:=FSize AND 511;
IF i=0 THEN i:=512;
WPtr^:=i;
WPtr:=@FBlock^[5];
IF i<>512 THEN
WPtr^:=(FSize SHR 9)+1
ELSE
WPtr^:=FSize SHR 9;
adjust_checksum
END
ELSE BEGIN
Move(Get_WriteBack_Add^,
FBlock^[FSize+chktsr_space+1],
Writeback_space);
Inc(FSize,chktsr_space+
Writeback_space)
END;
do_conversion
END
ELSE BEGIN
IF Is_Exe THEN
FSize:=restore_exe
ELSE BEGIN
IF FSize<=TSRProg_space THEN BEGIN
strgwrite(#7'FEHLER: Datei nicht '+
'zu bearbeiten.');
terminate_program
END;
i:=Get_Old_FSize;
chktsr_space:=Get_Old_ChkTSR_Space;
IF chktsr_space+i+Writeback_space<>
FSize THEN BEGIN
strgwrite(#7'FEHLER: Datei nicht '+
'zu bearbeiten.');
terminate_program
END
END;
strgwrite('Programm ist bereits '
+'konvertiert!'#13#10);
strgwrite('Wollen Sie es wieder in seine'+
' ursprüngliche Form versetzen');
JNChar:=flushnget_jn;
IF JNChar='J' THEN BEGIN
IF NOT Is_Exe THEN BEGIN
IF chktsr_space<i THEN
Move(FBlock^[i+1],FBlock^,
chktsr_space)
ELSE
Move(FBlock^[FSize-i-
Writeback_space+1],
FBlock^,i);
FSize:=i
END;
do_conversion
END
END;
terminate_program
END.