home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / das_buch / tsr / chktsr.pas < prev    next >
Pascal/Delphi Source File  |  1993-06-04  |  17KB  |  685 lines

  1. PROGRAM ChkTSR;
  2.  
  3. {$A+,B-,I-,S-,V+}
  4. {$M 4096,2096,2096}
  5.  
  6. {**************************************
  7. *        Autor : Robert Flogaus       *
  8. *        Datum : 24.4.1993            *
  9. *       Sprache: Turbo Pascal ab 5.x  *
  10. *                oder kompatible      *
  11. *                Sprachen             *
  12. *   Übersetzung: tpc chktsr           *
  13. *         Zweck: 1.) Überprüfung von  *
  14. *                TSRs auf verbogene   *
  15. *                Interrupt-Vektoren   *
  16. *                2.) Ergänzung der    *
  17. *                TSR-Dateien          *
  18. *                mit der Absicht,     *
  19. *      a.) einen Installationscheck   *
  20. *                und                  *
  21. *      b.) die leichte Deinstallation *
  22. *                zu gewährleisten.    *
  23. ***************************************}
  24.  
  25.  
  26. USES Dos;
  27.  
  28. TYPE
  29.   VectorArray=ARRAY[0..255] OF LONGINT;
  30.   Int_ChangeType=ARRAY[0..255] OF BOOLEAN;
  31.   LongArray=ARRAY[1..$FFF0] OF CHAR;
  32. CONST
  33.   First:BOOLEAN=TRUE;
  34.   Termination_Type:WORD=0;
  35.   Env_Memory:LONGINT=0;
  36.   Program_Memory:LONGINT=0;
  37.   Data_Memory:LONGINT=0;
  38.   Is_Exe:BOOLEAN=FALSE;
  39.   Peculiar_Seg:BOOLEAN=FALSE;
  40.   No_Uninstall:BOOLEAN=FALSE;
  41.   ErrorFlag:BYTE=0;
  42.   ExitCode:BYTE=0;
  43.  
  44. VAR
  45.   f:FILE;
  46.   DirInfo:SearchRec;
  47.   PrgName:STRING[9];
  48.   Str5:STRING[5];
  49.   Path,p_1:PathStr;
  50.   CmdLine:STRING;
  51.   FBlock:^LongArray;
  52.   WPtr:^WORD;
  53.   Stack_Test:ARRAY[0..8] OF WORD;
  54.   Vector_No:ARRAY[1..256] OF BYTE;
  55.   FSize,MinAddr,MaxAddr,TempLong:LONGINT;
  56.   i,j,Result,tsrpsp_seg,chktsr_space,
  57.   TSRProg_space,Writeback_space,
  58.   Front_buf_bytes:WORD;
  59.   Number_of_vecs:BYTE;
  60.   OldCBreak,Extra_Byte,Free_Env,
  61.   NoExec:BOOLEAN;
  62.   JNChar:CHAR;
  63.   OldInt_Ptr,NewInt_Ptr:^VectorArray;
  64.   Int_Changed:^Int_ChangeType;
  65.  
  66.  
  67. {$L chktsr.obj}
  68. PROCEDURE Keep_Prog;EXTERNAL;
  69. FUNCTION Get_Calc_Start_Progsize:LONGINT;EXTERNAL;
  70. FUNCTION Get_Actual_Start_Progsize:LONGINT;EXTERNAL;
  71. FUNCTION Get_TSRProg_Space:WORD;EXTERNAL;
  72. FUNCTION Get_Int_ChangedAdd:POINTER;EXTERNAL;
  73. FUNCTION Get_TSRProg_Add:POINTER;EXTERNAL;
  74. FUNCTION Get_WriteBack_Space:WORD;EXTERNAL;
  75. FUNCTION Get_WriteBack_Add:POINTER;EXTERNAL;
  76. FUNCTION Mouse_Used:BOOLEAN;EXTERNAL;
  77. FUNCTION Get_Old_FSize:WORD;EXTERNAL;
  78. FUNCTION Get_Old_ChkTSR_Space:WORD;EXTERNAL;
  79. FUNCTION DosGetMem(VAR Ptr:POINTER;Blocksize:WORD):BOOLEAN;EXTERNAL;
  80. FUNCTION ResizeBlock(VAR Ptr:POINTER;Blocksize:WORD):BOOLEAN;EXTERNAL;
  81. PROCEDURE Read_Line(VAR s:STRING;maxlen:BYTE);EXTERNAL;
  82. FUNCTION get_jn:CHAR;EXTERNAL;
  83. PROCEDURE debugexec(prog:PathStr;CmdLine:ComStr);EXTERNAL;
  84. FUNCTION set_exe_data:BOOLEAN;EXTERNAL;
  85. FUNCTION chkconverted_already:BOOLEAN;EXTERNAL;
  86. FUNCTION restore_exe:LONGINT;EXTERNAL;
  87. PROCEDURE adjust_checksum;EXTERNAL;
  88. PROCEDURE patch;EXTERNAL;
  89.  
  90. FUNCTION ucase(s:STRING):STRING;
  91.  
  92. VAR
  93.   i:BYTE;
  94.  
  95. BEGIN
  96.   FOR i:=1 TO Length(s) DO
  97.     s[i]:=UpCase(s[i]);
  98.   ucase:=s
  99. END;
  100.  
  101. PROCEDURE strgwrite(z:STRING);
  102.  
  103. BEGIN
  104.   Write(z)
  105. END;
  106.  
  107. PROCEDURE terminate_program;
  108.  
  109. BEGIN
  110.   strgwrite(#13#10'CHKTSR beendet.'#13#10);
  111.   Halt(0)
  112. END;
  113.  
  114. PROCEDURE terminate_with_help;
  115.  
  116. BEGIN
  117.   strgwrite('SYNTAX: CHKTSR Programmname'+
  118.             ' [Parameterliste]'#13#10+
  119.             'Zur Wiederherstellung nicht '+
  120.             'lauffähiger Programme vorher'+
  121.             ': SET CHKTSR=NOEXEC'#13#10);
  122.   Halt(1)
  123. END;
  124.  
  125. FUNCTION cvtasciiz(VAR a):STRING;
  126.  
  127. VAR
  128.   i:BYTE;
  129.   cstr:STRING;
  130.   carr:ARRAY[1..255] OF CHAR ABSOLUTE a;
  131.  
  132. BEGIN
  133.   i:=1;
  134.   WHILE (i<=255) AND (carr[i]<>#0)
  135.   DO BEGIN
  136.     cstr[i]:=carr[i];
  137.     Inc(i)
  138.   END;
  139.   cstr[0]:=Chr(i-1);
  140.   cvtasciiz:=cstr
  141. END;
  142.  
  143. PROCEDURE checkresulth;
  144.  
  145. BEGIN
  146.   IF IOResult<>0 THEN BEGIN
  147.     SetCBreak(OldCBreak);
  148.     strgwrite(#7'Dateifehler beim '
  149.               +'Bearbeiten von ');
  150.     strgwrite(cvtasciiz(FileRec(f).Name));
  151.     terminate_program
  152.   END
  153. END;
  154.  
  155. FUNCTION hex(num:LONGINT):STRING;
  156.  
  157. VAR
  158.   st:STRING;
  159.   rest:BYTE;
  160.  
  161. BEGIN
  162.   IF num<>0 THEN BEGIN
  163.     st:='';
  164.     WHILE num<>0 DO BEGIN
  165.       rest:=num AND 15;
  166.       num:=num SHR 4;
  167.       IF rest<10 THEN
  168.         st:=Chr(rest+48)+st
  169.       ELSE
  170.         st:=Chr(rest+55)+st
  171.     END;
  172.     hex:=st+'h'
  173.   END
  174.   ELSE
  175.     hex:='0h'
  176. END;
  177.  
  178. PROCEDURE do_conversion;
  179.  
  180. PROCEDURE back2sq1;
  181.  
  182. BEGIN
  183.   Erase(f);
  184.   Result:=IOResult;
  185.   Assign(f,p_1);
  186.   Rename(f,Path);
  187.   checkresulth;
  188.   SetCBreak(OldCBreak);
  189.   strgwrite(#13#10#7'Schreibfehler bei '+
  190.             'Datei ');
  191.   strgwrite(Path);
  192.   terminate_program
  193. END;
  194.  
  195. BEGIN {do_conversion}
  196.   SetCBreak(FALSE);
  197.   p_1:=Copy(Path,1,Length(Path)-3)+'BAK';
  198.   Assign(f,p_1);
  199.   Erase(f);
  200.   Result:=IOResult;
  201.   IF (Result<>0) AND (Result<>2) THEN
  202.   BEGIN
  203.     SetCBreak(OldCBreak);
  204.     strgwrite(#7'Kann Datei ');
  205.     strgwrite(p_1);
  206.     strgwrite(' nicht löschen!');
  207.     terminate_program
  208.   END;
  209.   Assign(f,Path);
  210.   Rename(f,p_1);
  211.   checkresulth;
  212.   Assign(f,Path);
  213.   ReWrite(f,1);
  214.   IF IOResult<>0 THEN
  215.     back2sq1
  216.   ELSE BEGIN
  217.     BlockWrite(f,FBlock^,FSize,Result);
  218.     IF (IOResult<>0) OR (FSize>Result)
  219.     THEN BEGIN
  220.       Close(f);
  221.       back2sq1
  222.     END
  223.     ELSE BEGIN
  224.       Close(f);
  225.       IF IOResult<>0 THEN back2sq1
  226.     END;
  227.     SetCBreak(OldCBreak);
  228.     strgwrite('Neue Dateigröße ');
  229.     Write(FSize);
  230.     strgwrite(' (');
  231.     strgwrite(hex(FSize));
  232.     strgwrite(') Byte'#13#10'Unveränderte'
  233.               +' Datei in ');
  234.     strgwrite(p_1)
  235.   END
  236. END;
  237.  
  238. PROCEDURE get_limits;
  239.  
  240. BEGIN
  241.   MinAddr:=LONGINT(tsrpsp_seg) SHL 4;
  242.   IF Program_Memory>$FFFF THEN
  243.     MaxAddr:=MinAddr+$FFFF
  244.   ELSE
  245.     MaxAddr:=MinAddr+Program_Memory-1
  246. END;
  247.  
  248. PROCEDURE std_ptr(VAR Ptr:LONGINT);
  249.  
  250. VAR
  251.   normptr:LONGINT;
  252.  
  253. BEGIN
  254.   normptr:=((Ptr AND $FFFF0000) SHR 12)
  255.            +(Ptr AND $FFFF);
  256.   IF (normptr<MinAddr)
  257.      OR (normptr>MaxAddr) THEN
  258.     Peculiar_Seg:=TRUE
  259.   ELSE
  260.     Ptr:=normptr-MinAddr {Ofs zum PSP}
  261. END;
  262.  
  263. FUNCTION flushnget_jn:CHAR;
  264. BEGIN
  265.   strgwrite(' (J/N)? ');
  266.   Flush(Output);
  267.   flushnget_jn:=get_jn;
  268. END;
  269.  
  270. BEGIN  {main program}
  271. GetCBreak(OldCBreak);
  272. strgwrite(#13#10'CHKTSR 1.0, (C) Robert '+
  273.           'Flogaus, 1993'#13#10);
  274. IF ParamCount>0 THEN BEGIN
  275.   p_1:=ParamStr(1);
  276.   CmdLine:='';
  277.   i:=Pos('/',p_1);
  278.   IF i>0 THEN BEGIN
  279.     j:=Length(p_1)-i+1;
  280.     CmdLine:=Copy(p_1,i,j)+' ';
  281.     Dec(p_1[0],j)
  282.   END;
  283.   FOR i:=2 TO ParamCount DO
  284.     CmdLine:=CmdLine+ParamStr(i)+' ';
  285.   IF Length(CmdLine)>0 THEN
  286.     Dec(CmdLine[0]);
  287.   IF (Pos('?',p_1)>0) OR
  288.      (Pos('*',p_1)>0) THEN
  289.      terminate_with_help;
  290.   p_1:=ucase(p_1);
  291.   IF Length(p_1)>4 THEN
  292.     Str5:=Copy(p_1,Length(p_1)-3,4)
  293.   ELSE
  294.     Str5:=p_1;
  295.   IF (Str5<>'.COM') AND (Str5<>'.EXE')
  296.   THEN BEGIN
  297.     Path:=FSearch(p_1+'.COM',
  298.                   GetEnv('PATH'));
  299.     IF Path='' THEN
  300.       Path:=FSearch(p_1+'.EXE',
  301.                     GetEnv('PATH'))
  302.   END
  303.   ELSE
  304.     Path:=FSearch(p_1,GetEnv('PATH'));
  305.   IF Path='' THEN terminate_with_help;
  306.   FindFirst(Path,Anyfile,DirInfo);
  307.   IF (DirInfo.Attr AND (Hidden+SysFile+
  308.       VolumeID+Directory))>0 THEN
  309.     terminate_with_help;
  310.   New(NewInt_Ptr);
  311.   New(OldInt_Ptr);
  312.   i:=Length(Path)-4;
  313.   j:=i;
  314.   WHILE (i>0) AND (Path[i]<>'\') AND
  315.               (Path[i]<>':') DO Dec(i);
  316.   PrgName:=Copy(Path,i+1,j-i);
  317.   IF Length(PrgName)>8 THEN
  318.     PrgName[0]:=#8;
  319.   Int_Changed:=Get_Int_ChangedAdd;
  320.   NoExec:=ucase(GetEnv('CHKTSR'))
  321.                 ='NOEXEC';
  322.  
  323.   IF NOT NoExec
  324.   THEN BEGIN
  325.     FileMode:=0;
  326.     FillChar(Stack_Test,SizeOf(Stack_Test),0);
  327.     Assign(f,Path);
  328.     Reset(f,1);
  329.     checkresulth;
  330.     BlockRead(f,Stack_Test,SizeOf(Stack_Test),Result);
  331.     checkresulth;
  332.     Close(f);
  333.     checkresulth;
  334.     SetCBreak(FALSE);
  335.     SwapVectors;
  336.     debugexec(Path,CmdLine);
  337.     SwapVectors;
  338.     SetCBreak(OldCBreak)
  339.   END
  340.   ELSE
  341.     DosError:=0;
  342.   strgwrite(#13#10'Programm ');
  343.   strgwrite(Path);
  344.   strgwrite(#13#10#13#10);
  345.   FillChar(Int_Changed^[$22],3,FALSE);
  346.   {INT 22h-24h irrelevant}
  347.   Number_of_vecs:=0;
  348.   IF ErrorFlag<>0 THEN BEGIN
  349.     IF (ErrorFlag AND 1)=1 THEN BEGIN
  350.       strgwrite(#7'Nicht residentes '+
  351.       'Programm verbog von CHKTSR '+
  352.       'verwendete(n) Interrupt(s) 21h, '+
  353.       '27h oder 33h. Diese(r) '+
  354.       'Interrupt(s) wurde(n) nicht '+
  355.       'zurückgesetzt.'#13#10'CHKTSR '+
  356.       'sollte resident bleiben. Sind '+
  357.       'Sie damit einverstanden');
  358.       IF flushnget_jn='J' THEN BEGIN
  359.         strgwrite('CHKTSR bleibt '+
  360.                   'resident.');
  361.         Flush(Output);
  362.         SwapVectors;
  363.         Keep_Prog
  364.       END
  365.     END
  366.     ELSE strgwrite(#7'MCB nicht gefunden.');
  367.     strgwrite(#13#10#7'Bitte neu booten!');
  368.     terminate_program
  369.   END;
  370.   IF (Termination_Type<>0) THEN BEGIN
  371.     IF (tsrpsp_seg=0) THEN BEGIN
  372.       strgwrite(#13#10#7'Fehler bei der '+
  373.                 'Programmauswertung!');
  374.       terminate_program
  375.     END;
  376.     strgwrite('PSP-Segment: ');
  377.     strgwrite(hex(tsrpsp_seg));
  378.     strgwrite(#13#10);
  379.     FOR i:=0 TO 255 DO
  380.       IF Int_Changed^[i] THEN BEGIN
  381.         Inc(Number_of_vecs);
  382.         Vector_No[Number_of_vecs]:=i;
  383.         IF First THEN BEGIN
  384.           First:=FALSE;
  385.           get_limits;
  386.           strgwrite('Interrupt-Vektor '+
  387.                   '   ISR-Adresse'#13#10)
  388.         END;
  389.         Str5:=hex(NewInt_Ptr^[i] SHR 16);
  390.         WriteLn(hex(i):9,' ':11,
  391.         Str5:5,':',
  392.         hex(NewInt_Ptr^[i] AND $FFFF));
  393.         std_ptr(NewInt_Ptr^[i])
  394.       END;
  395.     strgwrite(#13#10);
  396.     IF Mouse_Used THEN BEGIN
  397.       strgwrite('Maustreiber umgesetzt!'
  398.                  +#13#10);
  399.       PrgName:=PrgName+#32;
  400.     END
  401.   END;
  402.   IF NOT NoExec THEN
  403.   CASE Termination_Type OF
  404.   0:
  405.   BEGIN
  406.   IF DosError=0 THEN BEGIN
  407.     strgwrite('Programm normal beendet');
  408.     strgwrite(', Exitcode ');
  409.     strgwrite(hex(ExitCode))
  410.   END
  411.   ELSE IF DosError=8 THEN
  412.     strgwrite(#7'Speichermangel!')
  413.   ELSE
  414.     strgwrite(#7'Fehler bei der '+
  415.             'Programmausführung.');
  416.   strgwrite(#13#10);
  417.   END;
  418.   $2700:strgwrite('TSR mit INT 27h'#13#10);
  419.   ELSE BEGIN
  420.     strgwrite('TSR mit Funktion 31h von '+
  421.               'INT 21h');
  422.     strgwrite(', Exitcode ');
  423.     strgwrite(hex(Lo(Termination_Type)));
  424.     strgwrite(#13#10)
  425.   END
  426.   END;
  427.   IF Termination_Type<>0 THEN BEGIN
  428.     IF Program_Memory<$60 THEN
  429.       Program_Memory:=$60;
  430.     strgwrite(#13#10'Hauptspeicherbe'+
  431.               'darf (resident):');
  432.     WriteLn(#13#10'Programm: ',
  433.             Program_Memory:6,' (',
  434.             hex(Program_Memory):6,
  435.             ') Byte');
  436.     WriteLn('Umgebung: ',
  437.             Env_Memory:6,' (',
  438.            hex(Env_Memory):6,')',' Byte');
  439.     WriteLn('   Daten: ',
  440.             Data_Memory:6,' (',
  441.             hex(Data_Memory):6,')',
  442.                 ' Byte'#13#10)
  443.   END
  444. END
  445. ELSE
  446.   terminate_with_help;
  447.  
  448.  
  449. IF (DirInfo.Attr AND ReadOnly)=ReadOnly
  450. THEN BEGIN
  451.   strgwrite(#7'Datei ist '+
  452.             'schreibgeschützt!');
  453.   terminate_program
  454. END;
  455. FileMode:=0;
  456. Assign(f,Path);
  457. Reset(f,1);
  458. checkresulth;
  459. FSize:=FileSize(f);
  460. strgwrite('Dateigröße auf Disk '+
  461.           'derzeit ');
  462. Write(FSize);
  463. strgwrite(' (');
  464. strgwrite(hex(FSize));
  465. strgwrite(') Byte'#13#10);
  466. TSRProg_space:=Get_TSRProg_Space;
  467. chktsr_space:=TSRProg_space
  468.               +Length(PrgName)
  469.               +(3*Number_of_vecs)
  470.               +3;
  471. Writeback_space:=Get_WriteBack_Space;
  472. IF (FSize+chktsr_space+Writeback_space)
  473.                      <=$FEF0 THEN BEGIN
  474.   IF NOT DosGetMem(POINTER(FBlock),
  475.                    FSize+chktsr_space
  476.                    +Writeback_space+255)
  477.     THEN BEGIN
  478.       strgwrite(#7'Speichermangel!');
  479.       terminate_program
  480.     END
  481. END
  482. ELSE BEGIN
  483.   IF Termination_Type<>0 THEN
  484.     strgwrite(#7'Programm zu groß!');
  485.   terminate_program
  486. END;
  487. BlockRead(f,FBlock^,FSize,Result);
  488. checkresulth;
  489. IF Result<>FSize THEN BEGIN
  490.   strgwrite(#7'Lesefehler!');
  491.   terminate_program
  492. END;
  493. Close(f);
  494. checkresulth;
  495. Is_Exe:=(FSize>$1A) AND (((FBlock^[1]='M')
  496.    AND (FBlock^[2]='Z')) OR
  497.    ((FBlock^[1]='Z') AND (FBlock^[2]='M')));
  498. IF Termination_Type<>0 THEN BEGIN
  499.   strgwrite('Max. nutzbarer '+
  500.               'Speicher (Start): ');
  501.   IF (NOT Is_Exe) THEN
  502.     strgwrite('ALLES'#13#10)
  503.   ELSE BEGIN
  504.     TempLong:=Get_Calc_Start_Progsize;
  505.     IF TempLong=$FFFFFFFF THEN
  506.       strgwrite('ALLES'#13#10)
  507.     ELSE
  508.       WriteLn(TempLong,' (',
  509.               hex(TempLong),
  510.               ') Byte')
  511.   END;
  512.   strgwrite('Belegter Speicher'+
  513.             ' (Start): ');
  514.   TempLong:=Get_Actual_Start_Progsize;
  515.   WriteLn(TempLong,' (',hex(TempLong),')'+
  516.           ' Byte')
  517. END;
  518. IF NOT chkconverted_already THEN
  519. BEGIN
  520.   IF Termination_Type=0 THEN
  521.     terminate_program;
  522.   IF Lo(DosVersion)<3 THEN BEGIN
  523.     strgwrite(#7'Von diesem Programm '+
  524.     'veränderte TSR-Programme'#13#10+
  525.     'wären auf ihrem System nicht '+
  526.     'lauffähig.');
  527.     terminate_program
  528.   END;
  529.   IF Peculiar_Seg THEN BEGIN
  530.     strgwrite(#7'Interruptvektoren auf'+
  531.     ' Bereiche außerhalb PSP-Segment '+
  532.     'umgesetzt.');
  533.     terminate_program
  534.   END;
  535.   IF FSize>62000-TSRProg_space
  536.            -(3*Number_of_vecs)
  537.   THEN BEGIN
  538.     strgwrite(#7'Programm zu groß!');
  539.     terminate_program
  540.   END;
  541.   IF Is_Exe THEN BEGIN
  542.     IF NOT set_exe_data THEN BEGIN
  543.        strgwrite(#7'.EXE-Datei mit '+
  544.                  'falscher Länge!');
  545.        terminate_program
  546.      END;
  547.      TSRProg_space:=Get_TSRProg_Space;
  548.      Inc(chktsr_space,Get_WriteBack_Space);
  549.      IF NOT ResizeBlock(POINTER(FBlock),
  550.      FSize+chktsr_space+$100) THEN BEGIN
  551.        strgwrite(#7'Speichermangel!');
  552.        terminate_program
  553.      END
  554.   END;
  555.   strgwrite('Darf ');
  556.   strgwrite(Path);
  557.   strgwrite(' geändert werden');
  558.   IF flushnget_jn='N' THEN
  559.     terminate_program;
  560.   strgwrite('Deinstallation ermöglichen');
  561.   JNChar:=flushnget_jn;
  562.   IF JNChar='J' THEN BEGIN
  563.       strgwrite('Befehlszeilenparameter'+
  564.                 ' zur Deinstallation? ');
  565.       Flush(Output);
  566.       Read_Line(CmdLine,35)
  567.   END
  568.   ELSE BEGIN
  569.     CmdLine:=#13#13;
  570.     No_Uninstall:=TRUE
  571.   END;
  572.   strgwrite('Mehrfachinstallation '+
  573.             'unterbinden');
  574.   JNChar:=flushnget_jn;
  575.   IF No_Uninstall AND (JNChar='N') THEN
  576.     terminate_program;
  577.   IF Env_Memory=0 THEN
  578.     Free_Env:=FALSE
  579.   ELSE BEGIN
  580.     strgwrite('Benötigt das TSR seine '+
  581.               'Programmumgebung');
  582.     Free_Env:=(flushnget_jn='N')
  583.   END;
  584.   Inc(chktsr_space,Length(CmdLine));
  585.   Extra_Byte:=Is_Exe AND
  586.             (Odd(chktsr_space+FSize));
  587.   IF Extra_Byte THEN Inc(chktsr_space);
  588.   patch;
  589.   IF Is_Exe THEN BEGIN
  590.     FillChar(FBlock^[FSize+1],
  591.              Front_buf_bytes,0);
  592.     i:=FSize+Front_buf_bytes+1;
  593.     Move(Get_TSRProg_Add^,FBlock^[i],
  594.          TSRProg_space);
  595.     Inc(i,TSRProg_space)
  596.   END
  597.   ELSE BEGIN
  598.     IF chktsr_space<FSize THEN
  599.       Move(FBlock^,FBlock^[FSize+1],
  600.            chktsr_space)
  601.     ELSE
  602.       Move(FBlock^,
  603.            FBlock^[chktsr_space+1],FSize);
  604.     Move(Get_TSRProg_Add^,FBlock^,
  605.          TSRProg_space);
  606.     i:=TSRProg_space+1
  607.   END;
  608.   Move(PrgName,FBlock^[i],
  609.        Length(PrgName)+1);
  610.   Inc(i,Length(PrgName)+1);
  611.   Move(CmdLine,FBlock^[i],
  612.        Length(CmdLine)+1);
  613.   Inc(i,Length(CmdLine)+1);
  614.   FBlock^[i]:=Chr(Number_of_vecs);
  615.   Inc(i);
  616.   FOR j:=1 TO Number_of_vecs DO BEGIN
  617.     Result:=Vector_No[j];
  618.     FBlock^[i]:=Chr(Result);
  619.     Move(NewInt_Ptr^[Result],FBlock^[i+1],2);
  620.     Inc(i,3)
  621.   END;
  622.   IF Is_Exe THEN BEGIN
  623.     FillChar(FBlock^[i],$210+
  624.              BYTE(Extra_Byte),0);
  625.     Inc(FSize,chktsr_space);
  626.     WPtr:=@FBlock^[3];
  627.     i:=FSize AND 511;
  628.     IF i=0 THEN i:=512;
  629.     WPtr^:=i;
  630.     WPtr:=@FBlock^[5];
  631.     IF i<>512 THEN
  632.       WPtr^:=(FSize SHR 9)+1
  633.     ELSE
  634.       WPtr^:=FSize SHR 9;
  635.     adjust_checksum
  636.   END
  637.   ELSE BEGIN
  638.     Move(Get_WriteBack_Add^,
  639.          FBlock^[FSize+chktsr_space+1],
  640.          Writeback_space);
  641.     Inc(FSize,chktsr_space+
  642.         Writeback_space)
  643.   END;
  644.   do_conversion
  645. END
  646. ELSE BEGIN
  647.   IF Is_Exe THEN
  648.     FSize:=restore_exe
  649.   ELSE BEGIN
  650.     IF FSize<=TSRProg_space THEN BEGIN
  651.       strgwrite(#7'FEHLER: Datei nicht '+
  652.                 'zu bearbeiten.');
  653.       terminate_program
  654.     END;
  655.     i:=Get_Old_FSize;
  656.     chktsr_space:=Get_Old_ChkTSR_Space;
  657.     IF chktsr_space+i+Writeback_space<>
  658.        FSize THEN BEGIN
  659.       strgwrite(#7'FEHLER: Datei nicht '+
  660.                 'zu bearbeiten.');
  661.       terminate_program
  662.     END
  663.   END;
  664.   strgwrite('Programm ist bereits '
  665.             +'konvertiert!'#13#10);
  666.   strgwrite('Wollen Sie es wieder in seine'+
  667.            ' ursprüngliche Form versetzen');
  668.   JNChar:=flushnget_jn;
  669.   IF JNChar='J' THEN BEGIN
  670.     IF NOT Is_Exe THEN BEGIN
  671.       IF chktsr_space<i THEN
  672.         Move(FBlock^[i+1],FBlock^,
  673.              chktsr_space)
  674.       ELSE
  675.         Move(FBlock^[FSize-i-
  676.              Writeback_space+1],
  677.             FBlock^,i);
  678.       FSize:=i
  679.     END;
  680.     do_conversion
  681.   END
  682. END;
  683. terminate_program
  684. END.
  685.