home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 16 / 16.iso / w / w048 / 2.ddi / MSSRC.ARC / INVOKE.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1987-12-21  |  6.6 KB  |  250 lines

  1. {                            INVOKE.PAS
  2.                                MS 4.0
  3.                 Copyright (c) 1985, 87 by Borland International, Inc.         }
  4.  
  5. {$I-}
  6. {$R-}
  7. {$V-}
  8. {$S-}
  9. {$D-}
  10.  
  11. unit Invoke;
  12.   {-Compress the Turbo heap and run a DOS command}
  13.  
  14. interface
  15.  
  16. uses
  17.   Crt,
  18.   Dos;
  19.  
  20. function ExecShrink(Command : string) : Integer;
  21.   {-Run any DOS command. Call with command='' for a new shell}
  22.   { Return codes:
  23.            0 : Success
  24.           -1 : Insufficient memory to store free list
  25.           -2 : DOS setblock error before EXEC call
  26.           -3 : DOS setblock error after EXEC call  -- critical error
  27.           -4 : Insufficient memory to run DOS command
  28.         else   a DOS error code
  29.     }
  30.  
  31.   {==========================================================================}
  32.  
  33. implementation
  34.  
  35. const
  36.   MinDOSspace = 20000;       {Minimum bytes for DOS shell to run}
  37.  
  38. var
  39.   PathName, CommandTail : string[127];
  40.   TopOfHeap : Pointer;       {value of HeapEnd when program began}
  41.  
  42.   function HeapEnd : Pointer;
  43.     {-Return the last available location for the heap}
  44.  
  45.   begin                      {HeapEnd}
  46.     if Ofs(FreePtr^) = 0 then
  47.       {Free list is empty}
  48.       HeapEnd := Ptr(Seg(FreePtr^)+$1000, 0)
  49.     else
  50.       HeapEnd := Ptr(Seg(FreePtr^)+Ofs(FreePtr^) shr 4, Ofs(FreePtr^) and $F);
  51.   end;                       {HeapEnd}
  52.  
  53.   function PtrDiff(HighPt, LowPt : Pointer) : LongInt;
  54.     {-Return the number of bytes between point A^ and point B^}
  55.   type
  56.     SegOfs = record
  57.                O, S : Word;
  58.              end;
  59.   var
  60.     High : SegOfs absolute HighPt;
  61.     Low : SegOfs absolute LowPt;
  62.     HighVal, LowVal : LongInt;
  63.  
  64.   begin                      {PtrDiff}
  65.     HighVal := LongInt(High.S) shl 4+LongInt(High.O);
  66.     LowVal := LongInt(Low.S) shl 4+LongInt(Low.O);
  67.     PtrDiff := HighVal-LowVal;
  68.   end;                       {PtrDiff}
  69.  
  70.   function SetBlock(Paras : Integer) : Boolean;
  71.     {-Free up some memory above this program for a DOS shell}
  72.   var
  73.     regs : registers;
  74.  
  75.   begin                      {SetBlock}
  76.     with regs do begin
  77.       Ah := $4A;
  78.       ES := PrefixSeg;
  79.       Bx := Paras;
  80.       MsDos(regs);
  81.       SetBlock := not Odd(Flags);
  82.     end;
  83.   end;                       {SetBlock}
  84.  
  85.   function GetEnvStr(SearchString : string) : string;
  86.     {-Return the environment variable value}
  87.   type
  88.     Env = array[0..32767] of Char;
  89.   var
  90.     EPtr : ^Env;
  91.     EStr : string[255];
  92.     Done : Boolean;
  93.     SearchLen, I : Integer;
  94.  
  95.   begin                      {GetEnvStr}
  96.     GetEnvStr := '';
  97.     if SearchString = '' then
  98.       Exit;
  99.  
  100.     EPtr := Ptr(MemW[PrefixSeg:$2C], 0);
  101.     I := 0;
  102.     SearchString := SearchString+'=';
  103.     SearchLen := Length(SearchString);
  104.     Done := False;
  105.     EStr := '';
  106.     repeat
  107.       if EPtr^[I] = #0 then begin
  108.         if EPtr^[Succ(I)] = #0 then begin
  109.           Done := True;
  110.           if SearchString = '==' then begin
  111.             EStr := '';
  112.             I := I+4;
  113.             while EPtr^[I] <> #0 do begin
  114.               EStr := EStr+EPtr^[I];
  115.               Inc(I);
  116.             end;
  117.             GetEnvStr := EStr;
  118.           end;
  119.         end;
  120.         if Copy(EStr, 1, SearchLen) = SearchString then begin
  121.           GetEnvStr := Copy(EStr, Succ(SearchLen), 255);
  122.           Done := True;
  123.         end;
  124.         EStr := '';
  125.       end
  126.       else
  127.         EStr := EStr+EPtr^[I];
  128.       Inc(I);
  129.     until Done;
  130.   end;                       {GetEnvStr}
  131.  
  132.   function ExecShrink(Command : string) : Integer;
  133.     {-Run any DOS command. Call with command='' for a new shell}
  134.   label
  135.     ExitPoint;
  136.   var
  137.     C : Char;
  138.     OldHeapEnd,
  139.     NewHeapEnd : Pointer;
  140.     BytesAllocated,
  141.     FreeListSize,
  142.     ParasToKeep,
  143.     ParasWeHave,
  144.     ParasForDos : Word;
  145.  
  146.   begin                      {ExecShrink}
  147.  
  148.     {Calculate number of bytes to save}
  149.     FreeListSize := PtrDiff(TopOfHeap, HeapEnd);
  150.     BytesAllocated := 0;
  151.  
  152.     {If enough space available, use stack to store the free list}
  153.     if FreeListSize+1000 < SPtr then
  154.       NewHeapEnd := Ptr(SSeg, 0)
  155.  
  156.     else begin
  157.  
  158.       {Check for sufficient memory}
  159.       if MaxAvail < FreeListSize then begin
  160.         {Insufficient memory to store free list}
  161.         ExecShrink := -1;
  162.         Exit;
  163.       end;
  164.  
  165.       {Allocate memory for copy of free list}
  166.       BytesAllocated := FreeListSize;
  167.       if BytesAllocated > 0 then
  168.         GetMem(NewHeapEnd, BytesAllocated);
  169.  
  170.       {Recalculate the size of the free list}
  171.       FreeListSize := Word(PtrDiff(TopOfHeap, HeapEnd));
  172.     end;
  173.  
  174.     {Save the current pointer to the end of the free list}
  175.     OldHeapEnd := HeapEnd;
  176.  
  177.     {Current DOS memory allocation read from memory control block}
  178.     ParasWeHave := MemW[Pred(PrefixSeg):3];
  179.  
  180.     {Calculate amount of memory to give up}
  181.     ParasForDos := Pred(PtrDiff(TopOfHeap, HeapPtr) shr 4);
  182.  
  183.     {Calculate amount of memory to keep while in shell}
  184.     ParasToKeep := ParasWeHave-ParasForDos;
  185.  
  186.     {See if enough memory to run DOS}
  187.     if (ParasForDos > 0) and (ParasForDos < (MinDOSspace shr 4)) then begin
  188.       ExecShrink := -4;
  189.       goto ExitPoint;
  190.     end;
  191.  
  192.     {Copy the free list to a safe location}
  193.     Move(OldHeapEnd^, NewHeapEnd^, FreeListSize);
  194.  
  195.     {Deallocate memory for DOS}
  196.     if not SetBlock(ParasToKeep) then begin
  197.       ExecShrink := -2;
  198.       goto ExitPoint;
  199.     end;
  200.  
  201.     {get parameters for Execute}
  202.     PathName := GetEnvStr('COMSPEC');
  203.     if Command = '' then
  204.       CommandTail := ''
  205.     else
  206.       CommandTail := '/C '+Command;
  207.  
  208.     {Clear physical screen}
  209.     ClrScr;
  210.  
  211.     {Show status info if entering DOS shell}
  212.     if Command = '' then begin
  213.       WriteLn('Approximate memory available: ', (ParasForDos-240) shr 6, 'K');
  214.       WriteLn('Type EXIT to return to program...');
  215.     end;
  216.  
  217.     {Call Turbo's EXEC function}
  218.     Exec(PathName, CommandTail);
  219.  
  220.     {Reallocate memory from DOS}
  221.     if not SetBlock(ParasWeHave) then begin
  222.       ExecShrink := -3;
  223.       goto ExitPoint;
  224.     end;
  225.  
  226.     {Put free list back where it was}
  227.     Move(NewHeapEnd^, OldHeapEnd^, FreeListSize);
  228.  
  229.     {If not in shell allow time to see result}
  230.     if (Command <> '') or (doserror <> 0) then begin
  231.       Write(^M^J'Press any key to continue...');
  232.       C := ReadKey;
  233.     end;
  234.  
  235.     {If we get to here, our function result is in DosError}
  236.     ExecShrink := doserror;
  237.  
  238. ExitPoint:
  239.  
  240.     {Deallocate any dynamic memory used}
  241.     if BytesAllocated <> 0 then
  242.       FreeMem(NewHeapEnd, BytesAllocated);
  243.  
  244.   end;                       {ExecShrink}
  245.  
  246. begin
  247.   {Save top of heap for later}
  248.   TopOfHeap := HeapEnd;
  249. end.
  250.