Subversion Repositories autosfx

Rev

Blame | Last modification | View Log | RSS feed

  1. unit ZMCore19;
  2.  
  3. (*
  4.   ZMCore19.pas - event triggering
  5.   TZipMaster19 VCL by Chris Vleghert and Eric W. Engler
  6.   v1.9
  7.   Copyright (C) 2009  Russell Peters
  8.  
  9.  
  10.   This library is free software; you can redistribute it and/or
  11.   modify it under the terms of the GNU Lesser General Public
  12.   License as published by the Free Software Foundation; either
  13.   version 2.1 of the License, or (at your option) any later version.
  14.  
  15.   This library is distributed in the hope that it will be useful,
  16.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18.   Lesser General Public License (licence.txt) for more details.
  19.  
  20.   You should have received a copy of the GNU Lesser General Public
  21.   License along with this library; if not, write to the Free Software
  22.   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  23.  
  24.   contact: problems AT delphizip DOT org
  25.   updates: http://www.delphizip.org
  26.  
  27.   modified 2009-08-19
  28.   --------------------------------------------------------------------------- *)
  29.  
  30. interface
  31.  
  32. // {$DEFINE DEBUG_PROGRESS}
  33.  
  34. uses
  35.   Classes, SysUtils, Controls, Forms, Dialogs,
  36.   ZipMstr19, ZMXcpt19, ZMDelZip19, ZMStructs19, ZMCompat19;
  37.  
  38. const
  39.   zprFile = 0;
  40.   zprArchive = 1;
  41.   zprCopyTemp = 2;
  42.   zprSFX = 3;
  43.   zprHeader = 4;
  44.   zprFinish = 5;
  45.   zprCompressed = 6;
  46.   zprCentral = 7;
  47.   zprChecking = 8;
  48.   zprLoading = 9;
  49.   zprJoining = 10;
  50.   zprSplitting = 11;
  51.   zprWriting = 12;
  52.  
  53. const
  54.   EXT_EXE = '.EXE';
  55.   EXT_EXEL = '.exe';
  56.   EXT_ZIP = '.ZIP';
  57.   EXT_ZIPL = '.zip';
  58.   PRE_INTER = 'ZI$';
  59.   PRE_SFX = 'ZX$';
  60.  
  61. type
  62.   TZLoadOpts = (zloNoLoad, zloFull, zloSilent);
  63.  
  64. type
  65.   TZMVerbosity = (zvOff, zvVerbose, zvTrace);
  66.   TZMEncodingDir = (zedFromInt, zedToInt);
  67.   TZipShowProgress = (zspNone, zspFull, zspExtra);
  68.  
  69.   TZipAllwaysItems = (zaaYesOvrwrt);
  70.   TZipAnswerAlls = set of TZipAllwaysItems;
  71.  
  72. type
  73.   TZipNameType = (zntExternal, zntInternal);
  74.  
  75. type
  76.   TProgDetails = class(TZMProgressDetails)
  77.   private
  78.     fDelta: Int64;
  79.     fInBatch: Boolean;
  80.     fItemCount: Int64;
  81.     fItemName: TZMString;
  82.     fItemNumber: Integer;
  83.     fItemPosition: Int64;
  84.     fItemSize: Int64;
  85.     fProgType: TZMProgressType;
  86.     fTotalPosition: Int64;
  87.     fTotalSize: Int64;
  88.     fWritten: Int64;
  89.   protected
  90.     function GetBytesWritten: Int64; override;
  91.     function GetDelta: Int64; override;
  92.     function GetItemName: TZMString; override;
  93.     function GetItemNumber: Integer; override;
  94.     function GetItemPosition: Int64; override;
  95.     function GetItemSize: Int64; override;
  96.     function GetOrder: TZMProgressType; override;
  97.     function GetTotalCount: Int64; override;
  98.     function GetTotalPosition: Int64; override;
  99.     function GetTotalSize: Int64; override;
  100.   public
  101.     procedure Advance(adv: Int64);
  102.     procedure AdvanceXtra(adv: Cardinal);
  103.     procedure Clear;
  104.     procedure SetCount(Count: Int64);
  105.     procedure SetEnd;
  106.     procedure SetItem(const FName: TZMString; FSize: Int64);
  107.     procedure SetItemXtra(const xmsg: TZMString; FSize: Int64);
  108.     procedure SetSize(FullSize: Int64);
  109.     procedure Written(bytes: Int64);
  110.     property BytesWritten: Int64 read GetBytesWritten write fWritten;
  111.     property InBatch: Boolean Read fInBatch;
  112.     property ItemName: TZMString read GetItemName write fItemName;
  113.     property ItemNumber: Integer read GetItemNumber write fItemNumber;
  114.     property ItemPosition: Int64 read GetItemPosition write fItemPosition;
  115.     property ItemSize: Int64 read GetItemSize write fItemSize;
  116.     property Order: TZMProgressType read GetOrder write fProgType;
  117.     property TotalCount: Int64 read GetTotalCount write fItemCount;
  118.     property TotalPosition: Int64 read GetTotalPosition write fTotalPosition;
  119.     property TotalSize: Int64 read GetTotalSize write fTotalSize;
  120.   end;
  121.  
  122. type
  123.   TZCentralValues = (zcvDirty, zcvEmpty, zcvError, zcvBadStruct, zcvBusy);
  124.   TZCentralStatus = set of TZCentralValues;
  125.  
  126. type
  127.   TZMPipeImp = class(TZMPipe)
  128.   private
  129.     FAttributes: Cardinal;
  130.     FDOSDate: Cardinal;
  131.     FFileName: string;
  132.     FOwnsStream: boolean;
  133.     FSize: Integer;
  134.     FStream: TStream;
  135.   protected
  136.     function GetAttributes: Cardinal; override;
  137.     function GetDOSDate: Cardinal; override;
  138.     function GetFileName: string; override;
  139.     function GetOwnsStream: boolean; override;
  140.     function GetSize: Integer; override;
  141.     function GetStream: TStream; override;
  142.     procedure SetAttributes(const Value: Cardinal); override;
  143.     procedure SetDOSDate(const Value: Cardinal); override;
  144.     procedure SetFileName(const Value: string); override;
  145.     procedure SetOwnsStream(const Value: boolean); override;
  146.     procedure SetSize(const Value: Integer); override;
  147.     procedure SetStream(const Value: TStream); override;
  148.   public
  149.     procedure AfterConstruction; override;
  150.     procedure AssignTo(Dest: TZMPipeImp);
  151.     procedure BeforeDestruction; override;
  152.   end;
  153.  
  154.   TZMPipeListImp = class(TZMPipeList)
  155.   private
  156.     List: TList;
  157.   protected
  158.     function GetCount: Integer; override;
  159.     function GetPipe(Index: Integer): TZMPipe; override;
  160.     procedure SetCount(const Value: Integer); override;
  161.     procedure SetPipe(Index: Integer; const Value: TZMPipe); override;
  162.   public
  163.     function Add(aStream: TStream; const FileName: string; Own: boolean): integer; override;
  164.     procedure AfterConstruction; override;
  165.     procedure AssignTo(Dest: TZMPipeListImp);
  166.     procedure BeforeDestruction; override;
  167.     procedure Clear; override;
  168.     function HasStream(Index: Integer): boolean;
  169.     function KillStream(Index: Integer): boolean;
  170.   end;
  171.  
  172. const
  173.   MAX_PIPE = 9;
  174.  
  175.  
  176. type
  177.   TZMCore = class
  178.   private
  179.     fAnswerAll: TZipAnswerAlls;
  180.     fCancel: Integer;
  181.     fCheckNo: Integer;
  182.     fConfirmErase: Boolean;
  183.     FEncodeAs: TZMEncodingOpts;
  184.     FEncoding_CP: Cardinal;
  185.     fFErrCode: Integer;
  186.     fFileCleanup: TStringList;
  187.     fFSpecArgs: TStrings;
  188.     fFSpecArgsExcl: TStrings;
  189.     fHandle: Cardinal;
  190.     fHowToDelete: TZMDeleteOpts;
  191.     FIgnoreDirOnly: Boolean;
  192.     fKeepFreeOnAllDisks: Cardinal;
  193.     fKeepFreeOnDisk1: Cardinal;
  194.     fMaster: TCustomZipMaster19;
  195.     FMaxVolumeSize: Int64;
  196.     fMinFreeVolumeSize: Integer;
  197.     FNoSkipping: TZMSkipAborts;
  198.     fShowProgress: TZipShowProgress;
  199.     fSniffer: Cardinal;
  200.     fSniffNo: Integer;
  201.     fSpanOptions: TZMSpanOpts;
  202.     fUnattended: Boolean;
  203. {$IFNDEF UNICODE}
  204.     fUseUTF8: Boolean;
  205. {$ENDIF}
  206.     fWinXP: Boolean;
  207.     FWriteOptions: TZMWriteOpts;
  208.     function GetErrMessage: TZMString;
  209.     function GetTotalWritten: Int64;
  210.     procedure SetCancel(Value: Integer);
  211.     procedure SetErrCode(Value: Integer);
  212.     procedure SetProgDetail(const Value: TProgDetails);
  213.     procedure SetTotalWritten(const Value: Int64);
  214.   protected
  215.     FAddOptions: TZMAddOpts;
  216.     fBusy: Boolean;
  217.     fEncoding: TZMEncodingOpts;
  218.     FErrMessage: TZMString;
  219.     fEventErr: String;
  220.     FDllErrCode: Integer;
  221.     fIsDestructing: Boolean;
  222.     fNotMainTask: Boolean;
  223.     fProgDetails: TProgDetails;
  224.     FTempDir: String;
  225.     fVerbosity: TZMVerbosity;
  226.     procedure EncodingChanged(New_Enc: TZMEncodingOpts); virtual; abstract;
  227.     procedure Encoding_CPChanged(New_CP: Cardinal); virtual; abstract;
  228.     // 1 Locate sniffer and get overrides
  229.     function FindSniffer: Cardinal;
  230.     function GetTotalSizeToProcess: Int64;
  231.     procedure ReportToSniffer(err: Integer; const msg: TZMString);
  232.     procedure SetEncoding(const Value: TZMEncodingOpts);
  233.     procedure SetEncoding_CP(const Value: Cardinal); //virtual;
  234.     procedure StartUp; virtual;
  235.     property Sniffer: Cardinal Read fSniffer Write fSniffer;
  236.     property SniffNo: Integer Read fSniffNo Write fSniffNo;
  237.   public
  238.     constructor Create(AMaster: TCustomZipMaster19);
  239.     procedure AddCleanupFile(const fn: String; always: Boolean = False);
  240.     procedure AfterConstruction; override;
  241.     procedure BeforeDestruction; override;
  242.     procedure CheckCancel;
  243.     procedure CleanupFiles(IsError: Boolean);
  244.     procedure Clear; virtual;
  245.     procedure ClearErr;
  246.     procedure Diag(const msg: String);
  247.     procedure Done(Good: boolean = true); virtual;
  248.     function FNMatch(const pattern, spec: TZMString): Boolean;
  249.     function KeepAlive: Boolean;
  250.     procedure Kill; virtual;
  251.     function MakeTempFileName(Prefix, Extension: String): String;
  252.     function NextCheckNo: Integer;
  253.     procedure OnDirUpdate;
  254.     procedure OnNewName(idx: Integer);
  255.     function RemoveFileCleanup(const fn: String): Boolean;
  256.     procedure ReportMessage(err: Integer; const msg: TZMString);
  257.     procedure ReportMessage1(err: Integer; const msg: TZMString);
  258.     procedure ReportMsg(id: Integer; const Args: array of const );
  259.     procedure ReportProgress(ActionCode: TActionCodes; ErrorCode: Integer; msg:
  260.         TZMString; File_Size: Int64);
  261.     function ReportSkipping(const FName: String; err: Integer;
  262.       typ: TZMSkipTypes): Boolean;
  263.     procedure ShowExceptionError(const ZMExcept: Exception);
  264.     procedure ShowMsg(const msg: TZMString; err: Integer; display: Boolean);
  265.     procedure ShowZipFmtMsg(id: Integer; const Args: array of const ;
  266.       display: Boolean);
  267.     procedure ShowZipMessage(Ident: Integer; const UserStr: String);
  268.     procedure ShowZipMsg(Ident: Integer; display: Boolean);
  269.     function ZipFmtLoadStr(id: Integer; const Args: array of const ): TZMString;
  270.     function ZipLoadStr(id: Integer): TZMString;
  271.     function ZipMessageDialog(const title: String; var msg: String;
  272.       context: Integer; btns: TMsgDlgButtons): TModalResult;
  273.     procedure ZipMessageDlg(const msg: String; context: Integer);
  274.     function ZipMessageDlgEx(const title, msg: String; context: Integer;
  275.       btns: TMsgDlgButtons): TModalResult;
  276.     property AddOptions: TZMAddOpts read FAddOptions write FAddOptions;
  277.     property AnswerAll: TZipAnswerAlls Read fAnswerAll Write fAnswerAll;
  278.     property Busy: Boolean Read fBusy Write fBusy;
  279.     property Cancel: Integer Read fCancel Write SetCancel;
  280.     property ConfirmErase
  281.       : Boolean Read fConfirmErase Write fConfirmErase default True;
  282.     property EncodeAs: TZMEncodingOpts read FEncodeAs write FEncodeAs;
  283.     property Encoding: TZMEncodingOpts Read fEncoding Write SetEncoding;
  284.     property ErrCode: Integer Read fFErrCode Write SetErrCode;
  285.     property ErrMessage: TZMString read GetErrMessage write FErrMessage;
  286.     property FSpecArgs: TStrings Read fFSpecArgs Write fFSpecArgs;
  287.     property FSpecArgsExcl: TStrings Read fFSpecArgsExcl Write fFSpecArgsExcl;
  288.     property DllErrCode: Integer read FDllErrCode write FDllErrCode;
  289.     property Encoding_CP: Cardinal read FEncoding_CP write SetEncoding_CP;
  290.     property Handle: Cardinal Read fHandle;
  291.     property HowToDelete: TZMDeleteOpts Read fHowToDelete Write fHowToDelete;
  292.     property IgnoreDirOnly: Boolean read FIgnoreDirOnly;
  293.     property KeepFreeOnAllDisks
  294.       : Cardinal Read fKeepFreeOnAllDisks Write fKeepFreeOnAllDisks;
  295.     property KeepFreeOnDisk1
  296.       : Cardinal Read fKeepFreeOnDisk1 Write fKeepFreeOnDisk1;
  297.     property Master: TCustomZipMaster19 Read fMaster;
  298.     property MaxVolumeSize: Int64 read FMaxVolumeSize write FMaxVolumeSize;
  299.     property MinFreeVolumeSize
  300.       : Integer Read fMinFreeVolumeSize Write fMinFreeVolumeSize;
  301.     property NoSkipping: TZMSkipAborts read FNoSkipping;
  302.     property NotMainTask: Boolean Read fNotMainTask Write fNotMainTask;
  303.     property ProgDetail: TProgDetails Read fProgDetails Write SetProgDetail;
  304.     property ShowProgress
  305.       : TZipShowProgress Read fShowProgress Write fShowProgress;
  306.     property SpanOptions: TZMSpanOpts Read fSpanOptions Write fSpanOptions;
  307.     property TempDir: String read FTempDir write FTempDir;
  308.     property TotalWritten: Int64 read GetTotalWritten write SetTotalWritten;
  309.     property Unattended: Boolean Read fUnattended Write fUnattended;
  310. {$IFNDEF UNICODE}
  311.     property UseUTF8: Boolean read fUseUTF8 write fUseUTF8;
  312. {$ENDIF}
  313.     property Verbosity: TZMVerbosity Read fVerbosity Write fVerbosity;
  314.     property WinXP: Boolean Read fWinXP;
  315.     property WriteOptions: TZMWriteOpts read FWriteOptions write FWriteOptions;
  316.   end;
  317.  
  318. implementation
  319.  
  320. {$INCLUDE '.\ZipVers19.inc'}
  321.  
  322. uses Windows, Messages, ZMUtils19, ZMDlg19, ZMMsg19, ZMCtx19, ZMMsgStr19,
  323.   ZMUTF819, ZMMatch19;
  324.  
  325. const
  326.   SZipMasterSniffer = 'ZipMaster Sniffer';
  327.   STZipSniffer = 'TZipSniffer';
  328.   WM_SNIFF_START = WM_APP + $3F42;
  329.   WM_SNIFF_STOP = WM_APP + $3F44;
  330.   SNIFF_MASK = $FFFFFF;
  331.   RESOURCE_ERROR: String =
  332.     'ZMRes19_???.res is probably not linked to the executable' + #10 +
  333.     'Missing String ID is: %d ';
  334.  
  335.   { TProgDetails }
  336. procedure TProgDetails.Advance(adv: Int64);
  337. begin
  338.   fDelta := adv;
  339.   fTotalPosition := fTotalPosition + adv;
  340.   fItemPosition := fItemPosition + adv;
  341.   fProgType := ProgressUpdate;
  342. end;
  343.  
  344. procedure TProgDetails.AdvanceXtra(adv: Cardinal);
  345. begin
  346.   fDelta := adv;
  347.   Inc(fItemPosition, adv);
  348.   fProgType := ExtraUpdate;
  349. end;
  350.  
  351. procedure TProgDetails.Clear;
  352. begin
  353.   fProgType := EndOfBatch;
  354.   fDelta := 0;
  355.   fItemCount := 0;
  356.   fWritten := 0;
  357.   fTotalSize := 0;
  358.   fTotalPosition := 0;
  359.   fItemSize := 0;
  360.   fItemPosition := 0;
  361.   fItemName := '';
  362.   fItemNumber := 0;
  363. end;
  364.  
  365. function TProgDetails.GetBytesWritten: Int64;
  366. begin
  367.   Result := fWritten;
  368. end;
  369.  
  370. function TProgDetails.GetDelta: Int64;
  371. begin
  372.   Result := fDelta;
  373. end;
  374.  
  375. function TProgDetails.GetItemName: TZMString;
  376. begin
  377.   Result := fItemName;
  378. end;
  379.  
  380. function TProgDetails.GetItemNumber: Integer;
  381. begin
  382.   Result := fItemNumber;
  383. end;
  384.  
  385. function TProgDetails.GetItemPosition: Int64;
  386. begin
  387.   Result := fItemPosition;
  388. end;
  389.  
  390. function TProgDetails.GetItemSize: Int64;
  391. begin
  392.   Result := fItemSize;
  393. end;
  394.  
  395. function TProgDetails.GetOrder: TZMProgressType;
  396. begin
  397.   Result := fProgType;
  398. end;
  399.  
  400. function TProgDetails.GetTotalCount: Int64;
  401. begin
  402.   Result := fItemCount;
  403. end;
  404.  
  405. function TProgDetails.GetTotalPosition: Int64;
  406. begin
  407.   Result := fTotalPosition;
  408. end;
  409.  
  410. function TProgDetails.GetTotalSize: Int64;
  411. begin
  412.   Result := fTotalSize;
  413. end;
  414.  
  415. procedure TProgDetails.SetCount(Count: Int64);
  416. begin
  417.   Clear;
  418.   fItemCount := Count;
  419.   fItemNumber := 0;
  420.   fProgType := TotalFiles2Process;
  421. end;
  422.  
  423. procedure TProgDetails.SetEnd;
  424. begin
  425.   fItemName := '';
  426.   fItemSize := 0;
  427.   fInBatch := False;
  428.   fProgType := EndOfBatch;
  429. end;
  430.  
  431. procedure TProgDetails.SetItem(const FName: TZMString; FSize: Int64);
  432. begin
  433.   Inc(fItemNumber);
  434.   fItemName := FName;
  435.   fItemSize := FSize;
  436.   fItemPosition := 0;
  437.   fProgType := NewFile;
  438. end;
  439.  
  440. procedure TProgDetails.SetItemXtra(const xmsg: TZMString; FSize: Int64);
  441. begin
  442.   fItemName := xmsg;
  443.   fItemSize := FSize;
  444.   fItemPosition := 0;
  445.   fProgType := NewExtra;
  446. end;
  447.  
  448. procedure TProgDetails.SetSize(FullSize: Int64);
  449. begin
  450.   fTotalSize := FullSize;
  451.   fTotalPosition := 0;
  452.   fItemName := '';
  453.   fItemSize := 0;
  454.   fItemPosition := 0;
  455.   fProgType := TotalSize2Process;
  456.   fWritten := 0;
  457.   fInBatch := True; // start of batch
  458. end;
  459.  
  460. procedure TProgDetails.Written(bytes: Int64);
  461. begin
  462.   fWritten := bytes;
  463. end;
  464.  
  465. { TZMCore }
  466. constructor TZMCore.Create(AMaster: TCustomZipMaster19);
  467. begin
  468.   fMaster := AMaster;
  469. end;
  470.  
  471. procedure TZMCore.AddCleanupFile(const fn: String; always: Boolean = False);
  472. var
  473.   f: String;
  474.   obj: TObject;
  475. begin
  476.   f := ExpandFileName(fn); // need full path incase current dir changes
  477.   obj := nil;
  478.   if always then
  479.     obj := TObject(self);
  480.   fFileCleanup.AddObject(f, obj);
  481. end;
  482.  
  483. procedure TZMCore.AfterConstruction;
  484. begin
  485.   inherited;
  486.   fHandle := Application.Handle;
  487.   fProgDetails := TProgDetails.Create;
  488.   fFSpecArgs := TStringList.Create;
  489.   fFSpecArgsExcl := TStringList.Create;
  490.   fFileCleanup := TStringList.Create;
  491.   fHowToDelete := htdAllowUndo;
  492.   fSpanOptions := [];
  493.   FErrMessage := '';
  494.   fFErrCode := -1;
  495.   fVerbosity := zvOff;
  496.   fUnattended := True; // during construction
  497.   fEncoding := zeoAuto;
  498.   FEncodeAs := zeoAuto;
  499.   fVerbosity := zvOff;
  500.   fTempDir := '';
  501.   fNotMainTask := False;
  502.   fWinXP := IsWinXP; // set flag;
  503. end;
  504.  
  505. procedure TZMCore.BeforeDestruction;
  506. begin
  507.   fCancel := DS_Canceled;
  508.   fVerbosity := zvOff;
  509.   FreeAndNil(fFileCleanup);
  510.   FreeAndNil(fProgDetails);
  511.   FreeAndNil(fFSpecArgsExcl);
  512.   FreeAndNil(fFSpecArgs);
  513.   inherited;
  514. end;
  515.  
  516. procedure TZMCore.CheckCancel;
  517. begin
  518.   KeepAlive;
  519.   if fCancel <> 0 then
  520.     raise EZipMaster.CreateResDisp(Cancel, True);
  521. end;
  522.  
  523. procedure TZMCore.CleanupFiles(IsError: Boolean);
  524. var
  525.   AlwaysClean: Boolean;
  526.   fn: String;
  527.   i: Integer;
  528. begin
  529.   if (fFileCleanup.Count > 0) then
  530.   begin
  531.     for i := fFileCleanup.Count - 1 downto 0 do
  532.     begin
  533.       fn := fFileCleanup[i];
  534.       if Length(fn) < 2 then
  535.         continue;
  536.       AlwaysClean := fFileCleanup.Objects[i] <> nil;
  537.       if IsError or AlwaysClean then
  538.       begin
  539.         if CharInSet(fn[Length(fn)], ['/', '\']) then
  540.         begin
  541.           fn := ExcludeTrailingBackslash(fn);
  542.           if DirExists(fn) then
  543.             RemoveDir(fn);
  544.         end
  545.         else
  546.         begin
  547.           if FileExists(fn) then
  548.             SysUtils.DeleteFile(fn);
  549.         end;
  550.       end;
  551.     end;
  552.     fFileCleanup.Clear;
  553.   end;
  554. end;
  555.  
  556. procedure TZMCore.Clear;
  557. begin
  558.   Cancel := 0;
  559.   ClearErr;
  560.   fHowToDelete := htdAllowUndo;
  561.   fUnattended := False;
  562.   fEncoding := zeoAuto;
  563.   FEncodeAs := zeoAuto;
  564.   fVerbosity := zvOff;
  565.   TProgDetails(fProgDetails).Clear;
  566.   fFSpecArgs.Clear;
  567.   fFSpecArgsExcl.Clear;
  568.   fEventErr := '';
  569.   fIsDestructing := False;
  570.   fSpanOptions := [];
  571.   FWriteOptions := [];
  572. end;
  573.  
  574. procedure TZMCore.ClearErr;
  575. begin
  576.   FErrMessage := '';
  577.   fFErrCode := 0;
  578.   FDllErrCode := 0;
  579. end;
  580.  
  581. procedure TZMCore.Diag(const msg: String);
  582. begin
  583.   if Verbosity >= zvVerbose then
  584.     ShowMsg('Trace: ' + msg, 0, False); // quicker
  585. end;
  586.  
  587. procedure TZMCore.Done(Good: boolean = true);
  588. begin
  589.   CleanupFiles(not Good);
  590.   if Sniffer <> 0 then
  591.   begin
  592.     // send finished
  593.     SendMessage(Sniffer, WM_SNIFF_STOP, 0, SniffNo);
  594.     Sniffer := 0;
  595.   end;
  596.   fBusy := False;
  597. end;
  598.  
  599. function TZMCore.FindSniffer: Cardinal;
  600. var
  601.   flgs: Cardinal;
  602.   res: Integer;
  603. begin
  604.   Result := FindWindow(PChar(STZipSniffer), PChar(SZipMasterSniffer));
  605.   if Result <> 0 then
  606.   begin
  607.     res := SendMessage(Result, WM_SNIFF_START, Longint(Handle), Ord(Verbosity));
  608.     if res < 0 then
  609.     begin
  610.       Result := 0; // invalid
  611.       exit;
  612.     end;
  613.     // in range so hopefully valid response
  614.     flgs := Cardinal(res) shr 24;
  615.     if flgs >= 8 then
  616.     begin
  617.       Result := 0; // invalid
  618.       exit;
  619.     end;
  620.     // treat it as valid
  621.     if flgs > 3 then
  622.       Verbosity := TZMVerbosity(flgs and 3); // force it
  623.     SniffNo := res and SNIFF_MASK; // operation number
  624.   end;
  625. end;
  626.  
  627. function TZMCore.FNMatch(const pattern, spec: TZMString): Boolean;
  628. begin
  629. {$IFDEF UNICODE}
  630.   Result := FileNameMatch(pattern, spec);
  631. {$ELSE}
  632.   Result := FileNameMatch(pattern, spec, UseUTF8);
  633. {$ENDIF}
  634. end;
  635.  
  636. (* ? TZMCore.GetErrMessage
  637.   1.73 13 July 2003 RP only return ErrMessage if error
  638. *)
  639. function TZMCore.GetErrMessage: TZMString;
  640. begin
  641.   Result := '';
  642.   if ErrCode <> 0 then
  643.   begin
  644.     Result := FErrMessage;
  645.     if Result = '' then
  646.       Result := ZipLoadStr(ErrCode);
  647.     if Result = '' then
  648.       Result := ZipFmtLoadStr(GE_Unknown, [ErrCode]);
  649.   end;
  650. end;
  651.  
  652. function TZMCore.GetTotalSizeToProcess: Int64;
  653. begin
  654.   Result := TProgDetails(fProgDetails).TotalSize;
  655. end;
  656.  
  657. function TZMCore.GetTotalWritten: Int64;
  658. begin
  659.   Result := ProgDetail.BytesWritten;
  660. end;
  661.  
  662. function TZMCore.KeepAlive: Boolean;
  663. var
  664.   DoStop: Boolean;
  665.   tmpCheckTerminate: TZMCheckTerminateEvent;
  666.   tmpTick: TZMTickEvent;
  667. begin
  668.   Result := Cancel <> 0;
  669.   tmpTick := Master.OnTick;
  670.   if assigned(tmpTick) then
  671.     tmpTick(Master);
  672.   tmpCheckTerminate := Master.OnCheckTerminate;
  673.   if assigned(tmpCheckTerminate) then
  674.   begin
  675.     DoStop := Cancel <> 0;
  676.     tmpCheckTerminate(Master, DoStop);
  677.     if DoStop then
  678.       Cancel := DS_Canceled;
  679.   end
  680.   else if not fNotMainTask then
  681.     Application.ProcessMessages;
  682. end;
  683.  
  684. procedure TZMCore.Kill;
  685. begin
  686.   fCancel := DS_Canceled;
  687. end;
  688.  
  689. (* ? TZMCore.MakeTempFileName
  690.   Make a temporary filename like: C:\...\zipxxxx.zip
  691.   Prefix and extension are default: 'zip' and '.zip'
  692. *)
  693. function TZMCore.MakeTempFileName(Prefix, Extension: String): String;
  694. var
  695.   buf: String;
  696.   len: DWORD;
  697.   tmpDir: String;
  698. begin
  699.   if Prefix = '' then
  700.     Prefix := 'zip';
  701.   if Extension = '' then
  702.     Extension := EXT_ZIPL;
  703.   if Length(fTempDir) = 0 then // Get the system temp dir
  704.   begin
  705.     // 1. The path specified by the TMP environment variable.
  706.     // 2. The path specified by the TEMP environment variable, if TMP is not defined.
  707.     // 3. The current directory, if both TMP and TEMP are not defined.
  708.     len := GetTempPath(0, PChar(tmpDir));
  709.     SetLength(tmpDir, len);
  710.     GetTempPath(len, PChar(tmpDir));
  711.   end
  712.   else // Use Temp dir provided by ZipMaster
  713.   begin
  714.     tmpDir := DelimitPath(fTempDir, True);
  715.   end;
  716.   SetLength(buf, MAX_PATH + 12);
  717.   if GetTempFileName(PChar(tmpDir), PChar(Prefix), 0, PChar(buf)) <> 0 then
  718.   begin
  719.     buf := PChar(buf);
  720.     SysUtils.DeleteFile(buf); // Needed because GetTempFileName creates the file also.
  721.     Result := ChangeFileExt(buf, Extension);
  722.     // And finally change the extension.
  723.   end;
  724. end;
  725.  
  726. function TZMCore.NextCheckNo: Integer;
  727. begin
  728.   Inc(fCheckNo);
  729.   Result := fCheckNo;
  730. end;
  731.  
  732. procedure TZMCore.OnDirUpdate;
  733. begin
  734.   if assigned(Master.OnDirUpdate) then
  735.     Master.OnDirUpdate(Master);
  736. end;
  737.  
  738. procedure TZMCore.OnNewName(idx: Integer);
  739. begin
  740.   if assigned(Master.OnNewName) then
  741.     Master.OnNewName(Master, idx);
  742. end;
  743.  
  744. function TZMCore.RemoveFileCleanup(const fn: String): Boolean;
  745. var
  746.   f: String;
  747.   i: Integer;
  748. begin
  749.   Result := False;
  750.   f := ExpandFileName(fn);
  751.   for i := fFileCleanup.Count - 1 downto 0 do
  752.     if AnsiSameText(fFileCleanup[i], f) then
  753.     begin
  754.       fFileCleanup.Delete(i);
  755.       Result := True;
  756.       break;
  757.     end;
  758. end;
  759.  
  760. procedure TZMCore.ReportMessage(err: Integer; const msg: TZMString);
  761. begin
  762.   if Sniffer <> 0 then
  763.     ReportToSniffer(err, msg);
  764.   ReportMessage1(err, msg);
  765. end;
  766.  
  767. procedure TZMCore.ReportMessage1(err: Integer; const msg: TZMString);
  768. var
  769.   tmpMessage: TZMMessageEvent;
  770. begin
  771.   if (err <> 0) and (ErrCode = 0) then // only catch first
  772.   begin
  773.     if DllErrCode = 0 then
  774.       FDllErrCode := err;
  775.     fFErrCode := err;
  776.     FErrMessage := msg;
  777.   end;
  778.   tmpMessage := Master.OnMessage;
  779.   if assigned(tmpMessage) then
  780.     tmpMessage(Master, err, msg);
  781.   KeepAlive; // process messages or check terminate
  782. end;
  783.  
  784. procedure TZMCore.ReportMsg(id: Integer; const Args: array of const );
  785. var
  786.   msg: TZMString;
  787.   p: Integer;
  788. begin
  789.   msg := ZipFmtLoadStr(id, Args);
  790.   if msg <> '' then
  791.   begin
  792.     p := 0;
  793.     case msg[1] of
  794.       '#':
  795.         p := TM_Trace;
  796.       '!':
  797.         p := TM_Verbose;
  798.     end;
  799.     if p <> 0 then
  800.     begin
  801.       msg := ZipLoadStr(p) + copy(msg, 2, Length(msg) - 1);
  802.     end;
  803.   end;
  804.   ReportMessage(0, msg);
  805. end;
  806.  
  807. (* ? TZMCore.ReportProgress
  808.   1.77.2.0 14 September 2004 - RP fix setting ErrCode caused re-entry
  809.   1.77.2.0 14 September 2004 - RP alter thread support & OnCheckTerminate
  810.   1.77 16 July 2004 - RP preserve last errors ErrMessage
  811.   1.76 24 April 2004 - only handle 'progress' and information
  812. *)
  813. procedure TZMCore.ReportProgress(ActionCode: TActionCodes; ErrorCode: Integer;
  814.     msg: TZMString; File_Size: Int64);
  815. var
  816.   Details: TProgDetails;
  817.   SendDetails: Boolean;
  818.   tmpProgress: TZMProgressEvent;
  819. begin
  820.   if fIsDestructing then
  821.     exit;
  822.   if ActionCode <= zacXProgress then
  823.   begin
  824.     Details := fProgDetails as TProgDetails;
  825.     SendDetails := True;
  826.     case ActionCode of
  827.       zacTick: { 'Tick' Just checking / processing messages }
  828.         begin
  829.           KeepAlive;
  830.           SendDetails := False;
  831.         end;
  832.  
  833.       zacItem: { progress type 1 = StartUp any ZIP operation on a new file }
  834.         Details.SetItem(msg, File_Size);
  835.  
  836.       zacProgress: { progress type 2 = increment bar }
  837.         Details.Advance(File_Size);
  838.  
  839.       zacEndOfBatch: { end of a batch of 1 or more files }
  840.         begin
  841.           if Details.InBatch then
  842.             Details.SetEnd
  843.           else
  844.             SendDetails := False;
  845.         end;
  846.  
  847.       zacCount: { total number of files to process }
  848.         Details.SetCount(File_Size);
  849.  
  850.       zacSize: { total size of all files to be processed }
  851.         Details.SetSize(File_Size);
  852.  
  853.       zacXItem: { progress type 15 = StartUp new extra operation }
  854.         begin
  855.           if ErrorCode < 20 then
  856.             ErrorCode := PR_Progress + ErrorCode;
  857.           msg := ZipLoadStr(ErrorCode);
  858.           Details.SetItemXtra(msg, File_Size);
  859.         end;
  860.  
  861.       zacXProgress: { progress type 16 = increment bar for extra operation }
  862.         Details.AdvanceXtra(File_Size);
  863.     end; { end case }
  864. {$IFDEF DEBUG_PROGRESS}
  865.     if Verbosity >= zvVerbose then
  866.       case ActionCode of
  867.         zacItem:
  868.           Diag(Format('#Item - "%s" %d', [Details.ItemName, Details.ItemSize]));
  869.         zacProgress:
  870.           Diag(Format('#Progress - [inc:%d] ipos:%d isiz:%d, tpos:%d tsiz:%d',
  871.               [File_Size, Details.ItemPosition, Details.ItemSize,
  872.               Details.TotalPosition, Details.TotalSize]));
  873.         zacEndOfBatch:
  874.           if SendDetails then
  875.             Diag('#End Of Batch')
  876.           else
  877.             Diag('#End Of Batch with no batch');
  878.         zacCount:
  879.           Diag(Format('#Count - %d', [Details.TotalCount]));
  880.         zacSize:
  881.           Diag(Format('#Size - %d', [Details.TotalSize]));
  882.         zacXItem:
  883.           Diag(Format('#XItem - %s size = %d', [Details.ItemName, File_Size]));
  884.         zacXProgress:
  885.           Diag(Format('#XProgress - [inc:%d] pos:%d siz:%d',
  886.               [File_Size, Details.ItemPosition, Details.ItemSize]));
  887.       end;
  888. {$ENDIF}
  889.     tmpProgress := Master.OnProgress;
  890.     if SendDetails and (assigned(tmpProgress)) then
  891.       tmpProgress(Master, Details);
  892.   end;
  893.  
  894.   KeepAlive;
  895. end;
  896.  
  897. // returns True if skipping not allowed
  898. function TZMCore.ReportSkipping(const FName: String; err: Integer;
  899.   typ: TZMSkipTypes): Boolean;
  900. var
  901.   ti: Integer;
  902.   tmpMessage: ZipMstr19.TZMMessageEvent;
  903.   tmpSkipped: TZMSkippedEvent;
  904. begin
  905.   Result := False;
  906.   if typ in NoSkipping then
  907.   begin
  908.     if err = 0 then
  909.       err := GE_NoSkipping;
  910.   end;
  911.   ti := err;
  912.   if ti < 0 then
  913.     ti := -ti;
  914.   if (ti <> 0) and (typ in NoSkipping) then
  915.     ti := -ti; // default to abort
  916.   tmpSkipped := Master.OnSkipped;
  917.   if assigned(tmpSkipped) then
  918.     tmpSkipped(Master, FName, typ, ti)
  919.   else if Verbosity >= zvVerbose then
  920.   begin
  921.     tmpMessage := Master.OnMessage;
  922.     if assigned(tmpMessage) then
  923.       tmpMessage(Master, GE_Unknown, ZipFmtLoadStr
  924.           (GE_Skipped, [FName, Ord(typ)]));
  925.   end;
  926.   if ti < 0 then
  927.     Result := True; // Skipping not allowed
  928.   if Sniffer <> 0 then
  929.     ReportToSniffer(0, Format('[Skipped] IN=%d,%d OUT=%d', [err, Ord(typ), Ord
  930.           (Result)]));
  931. end;
  932.  
  933. procedure TZMCore.ReportToSniffer(err: Integer; const msg: TZMString);
  934. var
  935.   aCopyData: TCopyDataStruct;
  936.   msg8: UTF8String;
  937. begin
  938.   if Sniffer = 0 then // should not happen
  939.     exit;
  940.   // always feed Sniffer with UTF8
  941. {$IFDEF UNICODE}
  942.   msg8 := StrToUTF8(msg);
  943. {$ELSE}
  944.   if UseUTF8 then
  945.     msg8 := msg
  946.   else
  947.     msg8 := StrToUTF8(msg);
  948. {$ENDIF}
  949.   aCopyData.dwData := Cardinal(err);
  950.   aCopyData.cbData := (Length(msg8) + 1) * sizeof(AnsiChar);
  951.   aCopyData.lpData := @msg8[1];
  952.   if SendMessage(Sniffer, WM_COPYDATA, SniffNo, Longint(@aCopyData)) = 0 then
  953.     Sniffer := 0; // could not process it -don't try again
  954. end;
  955.  
  956. procedure TZMCore.SetCancel(Value: Integer);
  957. begin
  958.   fCancel := Value;
  959. end;
  960.  
  961. procedure TZMCore.SetEncoding(const Value: TZMEncodingOpts);
  962. begin
  963.   if Encoding <> Value then
  964.   begin
  965.     FEncoding := Value;
  966.     EncodingChanged(Value);
  967.   end;
  968. end;
  969.  
  970. procedure TZMCore.SetEncoding_CP(const Value: Cardinal);
  971. begin
  972.   if Encoding_CP <> Value then
  973.   begin
  974.     FEncoding_CP := Value;
  975.     Encoding_CPChanged(Value);
  976.   end;
  977. end;
  978.  
  979. (* ? TZMCore.SetErrCode
  980.   Some functions return -error - normalise these values
  981. *)
  982. procedure TZMCore.SetErrCode(Value: Integer);
  983. begin
  984.   if Value < 0 then
  985.     fFErrCode := -Value
  986.   else
  987.     fFErrCode := Value;
  988. end;
  989.  
  990. procedure TZMCore.SetProgDetail(const Value: TProgDetails);
  991. begin
  992.   // do not change
  993. end;
  994.  
  995. procedure TZMCore.SetTotalWritten(const Value: Int64);
  996. begin
  997.   ProgDetail.Written(Value);
  998. end;
  999.  
  1000. (* ? TZMCore.ShowExceptionError
  1001.   1.80 strings already formatted
  1002.   // Somewhat different from ShowZipMessage() because the loading of the resource
  1003.   // string is already done in the constructor of the exception class.
  1004. *)
  1005. procedure TZMCore.ShowExceptionError(const ZMExcept: Exception);
  1006. var
  1007.   display: Boolean;
  1008.   msg: String;
  1009.   ResID: Integer;
  1010. begin
  1011.   if ZMExcept is EZMException then
  1012.   begin
  1013.     ResID := EZMException(ZMExcept).ResID;
  1014.     display := EZMException(ZMExcept).DisplayMsg;
  1015. {$IFDEF UNICODE}
  1016.     msg := EZMException(ZMExcept).Message;
  1017. {$ELSE}
  1018.     msg := EZMException(ZMExcept).TheMessage(UseUTF8);
  1019. {$ENDIF}
  1020.   end
  1021.   else
  1022.   begin
  1023.     ResID := GE_ExceptErr;
  1024.     display := True;
  1025.     msg := ZMExcept.Message;
  1026.   end;
  1027.   ShowMsg(msg, ResID, display);
  1028. end;
  1029.  
  1030. procedure TZMCore.ShowMsg(const msg: TZMString; err: Integer; display: Boolean);
  1031. begin
  1032.   FErrMessage := msg;
  1033.   if err < 0 then
  1034.     fFErrCode := -err
  1035.   else
  1036.     fFErrCode := err;
  1037.   if display and (not fUnattended) and (ErrCode <> GE_Abort) and
  1038.     (ErrCode <> DS_Canceled) then
  1039.     ZipMessageDlg(msg, zmtInformation + DHC_ZipMessage);
  1040.  
  1041.   ReportMessage(ErrCode, msg);
  1042. end;
  1043.  
  1044. (* ? TZMCore.ShowZipFmtMsg
  1045.   1.79 added
  1046. *)
  1047. procedure TZMCore.ShowZipFmtMsg(id: Integer; const Args: array of const ;
  1048.   display: Boolean);
  1049. begin
  1050.   if id < 0 then
  1051.     id := -id;
  1052.   ShowMsg(ZipFmtLoadStr(id, Args), id, display);
  1053. end;
  1054.  
  1055. (* ? TZMCore.ShowZipMessage
  1056. *)
  1057. procedure TZMCore.ShowZipMessage(Ident: Integer; const UserStr: String);
  1058. var
  1059.   msg: String;
  1060. begin
  1061.   if Ident < 0 then
  1062.     Ident := -Ident;
  1063.   msg := ZipLoadStr(Ident);
  1064.   if msg = '' then
  1065.     msg := Format(RESOURCE_ERROR, [Ident]);
  1066.   msg := msg + UserStr;
  1067.   ShowMsg(msg, Ident, True);
  1068. end;
  1069.  
  1070. procedure TZMCore.ShowZipMsg(Ident: Integer; display: Boolean);
  1071. var
  1072.   msg: String;
  1073. begin
  1074.   if Ident < 0 then
  1075.     Ident := -Ident;
  1076.   msg := ZipLoadStr(Ident);
  1077.   if msg = '' then
  1078.     msg := Format(RESOURCE_ERROR, [Ident]);
  1079.   ShowMsg(msg, Ident, display);
  1080. end;
  1081.  
  1082. (* ? TZMCore.StartUp
  1083. *)
  1084. procedure TZMCore.StartUp;
  1085. var
  1086.   s: String;
  1087. begin
  1088.   fBusy := True;
  1089.   Cancel := 0;
  1090.   fAnswerAll := [];
  1091.   ClearErr;
  1092. {$IFNDEF UNICODE}
  1093.   fUseUTF8 := Master.UseUTF8;
  1094. {$ENDIF}
  1095.   fHandle := Master.Handle;
  1096.   FAddOptions := Master.AddOptions;
  1097.   fUnattended := Master.Unattended;
  1098.   fConfirmErase := Master.ConfirmErase;
  1099.   fKeepFreeOnAllDisks := Master.KeepFreeOnAllDisks;
  1100.   fKeepFreeOnDisk1 := Master.KeepFreeOnDisk1;
  1101.   if Master.MaxVolumeSizeKb = 0 then
  1102.     FMaxVolumeSize := Master.MaxVolumeSize
  1103.   else
  1104.     FMaxVolumeSize := Master.MaxVolumeSizeKb * 1024;
  1105.   fMinFreeVolumeSize := Master.MinFreeVolumeSize;
  1106.   FNoSkipping := Master.NoSkipping;
  1107.   fSpanOptions := Master.SpanOptions;
  1108.   FWriteOptions := Master.WriteOptions;
  1109.   if Master.Trace then
  1110.     fVerbosity := zvTrace
  1111.   else if Master.Verbose then
  1112.     fVerbosity := zvVerbose
  1113.   else
  1114.     fVerbosity := zvOff;
  1115.   {f}Encoding := Master.Encoding;
  1116.   Encoding_CP := Master.Encoding_CP;
  1117.   FEncodeAs := Master.EncodeAs;
  1118.   fHowToDelete := Master.HowToDelete;
  1119.   TempDir := Master.TempDir;
  1120.   fFSpecArgs.Assign(Master.FSpecArgs);
  1121.   fFSpecArgsExcl.Assign(Master.FSpecArgsExcl);
  1122.   FIgnoreDirOnly := not Master.UseDirOnlyEntries;
  1123.   fNotMainTask := Master.NotMainThread;
  1124.   if GetCurrentThreadID <> MainThreadID then
  1125.     fNotMainTask := True;
  1126.   Sniffer := FindSniffer;
  1127.   if Sniffer <> 0 then
  1128.   begin
  1129.     if Master.Owner <> nil then
  1130.     begin
  1131.       s := Master.Owner.Name;
  1132.       if s <> '' then
  1133.         s := s + '.';
  1134.     end;
  1135.     if Master.Name = '' then
  1136.       s := '<unknown>'
  1137.     else
  1138.       s := s + Master.Name;
  1139.     if fNotMainTask then
  1140.       s := '*' + s;
  1141.     ReportToSniffer(0, 'Starting ' + s);
  1142.   end;
  1143.   fFileCleanup.Clear;
  1144. end;
  1145.  
  1146. function TZMCore.ZipFmtLoadStr(id: Integer; const Args: array of const )
  1147.   : TZMString;
  1148. begin
  1149.   Result := ZipLoadStr(id);
  1150.  
  1151.   if Result <> '' then
  1152.     Result := Format(Result, Args);
  1153. end;
  1154.  
  1155. function TZMCore.ZipLoadStr(id: Integer): TZMString;
  1156. begin
  1157.   Result := LoadZipStr(id);
  1158. {$IFNDEF UNICODE}
  1159.   if (Result <> '') and UseUTF8 then
  1160.     Result := StrToUTF8(Result);
  1161. {$ENDIF}
  1162. end;
  1163.  
  1164. function TZMCore.ZipMessageDialog(const title: String; var msg: String;
  1165.   context: Integer; btns: TMsgDlgButtons): TModalResult;
  1166. var
  1167.   ctx: Integer;
  1168.   dlg: TZipDialogBox;
  1169.   s: String;
  1170.   t: String;
  1171.   tmpZipDialog: TZMDialogEvent;
  1172. begin
  1173.   t := title;
  1174.   if title = '' then
  1175.     t := Application.title;
  1176.   if Verbosity >= zvVerbose then
  1177.     t := Format('%s   (%d)', [t, context and MAX_WORD]);
  1178.   tmpZipDialog := Master.OnZipDialog;
  1179.   if assigned(tmpZipDialog) then
  1180.   begin
  1181.     s := msg;
  1182.     ctx := context;
  1183.     tmpZipDialog(Master, t, s, ctx, btns);
  1184.     if (ctx > 0) and (ctx <= Ord(mrYesToAll)) then
  1185.     begin
  1186.       msg := s;
  1187.       Result := TModalResult(ctx);
  1188.       exit;
  1189.     end;
  1190.   end;
  1191.   dlg := TZipDialogBox.CreateNew2(Application, context);
  1192.   try
  1193.     dlg.Build(t, msg, btns {$IFNDEF UNICODE}, UseUTF8 {$ENDIF});
  1194.     dlg.ShowModal();
  1195.     Result := dlg.ModalResult;
  1196.     if dlg.DlgType = zmtPassword then
  1197.     begin
  1198.       if (Result = mrOk) then
  1199.         msg := dlg.PWrd
  1200.       else
  1201.         msg := '';
  1202.     end;
  1203.   finally
  1204.     FreeAndNil(dlg);
  1205.   end;
  1206. end;
  1207.  
  1208. procedure TZMCore.ZipMessageDlg(const msg: String; context: Integer);
  1209. begin
  1210.   ZipMessageDlgEx('', msg, context, [mbOK]);
  1211. end;
  1212.  
  1213. function TZMCore.ZipMessageDlgEx(const title, msg: String; context: Integer;
  1214.   btns: TMsgDlgButtons): TModalResult;
  1215. var
  1216.   m: String;
  1217. begin
  1218.   m := msg;
  1219.   Result := ZipMessageDialog(title, m, context, btns);
  1220. end;
  1221.  
  1222. procedure TZMPipeImp.AfterConstruction;
  1223. begin
  1224.   inherited;
  1225.   FStream := nil;
  1226.   fSize := 0;
  1227.   fDOSDate := Cardinal(DateTimeToFileDate(now));
  1228.   fAttributes := 0;
  1229. end;
  1230.  
  1231. procedure TZMPipeImp.AssignTo(Dest: TZMPipeImp);
  1232. begin
  1233.   if Dest <> self then
  1234.   begin
  1235.     Dest.Stream := FStream;
  1236.     FStream := nil;
  1237.     Dest.Size := FSize;
  1238.     Dest.DOSDate := fDOSDate;
  1239.     Dest.Attributes := FAttributes;
  1240.     Dest.OwnsStream := FOwnsStream;
  1241.   end;
  1242. end;
  1243.  
  1244. procedure TZMPipeImp.BeforeDestruction;
  1245. begin
  1246.   if OwnsStream and (FStream <> nil) then
  1247.     FStream.Free;
  1248.   inherited;
  1249. end;
  1250.  
  1251. function TZMPipeImp.GetAttributes: Cardinal;
  1252. begin
  1253.   Result := FAttributes;
  1254. end;
  1255.  
  1256. function TZMPipeImp.GetDOSDate: Cardinal;
  1257. begin
  1258.   Result := FDOSDate;
  1259. end;
  1260.  
  1261. function TZMPipeImp.GetFileName: string;
  1262. begin
  1263.   Result := FFileName;
  1264. end;
  1265.  
  1266. function TZMPipeImp.GetOwnsStream: boolean;
  1267. begin
  1268.   Result := FOwnsStream;
  1269. end;
  1270.  
  1271. function TZMPipeImp.GetSize: Integer;
  1272. begin
  1273.   Result := FSize;
  1274. end;
  1275.  
  1276. function TZMPipeImp.GetStream: TStream;
  1277. begin
  1278.   Result := FStream;
  1279. end;
  1280.  
  1281. procedure TZMPipeImp.SetAttributes(const Value: Cardinal);
  1282. begin
  1283.   FAttributes := Value;
  1284. end;
  1285.  
  1286. procedure TZMPipeImp.SetDOSDate(const Value: Cardinal);
  1287. begin
  1288.   FDOSDate := Value;
  1289. end;
  1290.  
  1291. procedure TZMPipeImp.SetFileName(const Value: string);
  1292. begin
  1293.   if FFileName <> Value then
  1294.   begin
  1295.     FFileName := Value;
  1296.   end;
  1297. end;
  1298.  
  1299. procedure TZMPipeImp.SetOwnsStream(const Value: boolean);
  1300. begin
  1301.   FOwnsStream := Value;
  1302. end;
  1303.  
  1304. procedure TZMPipeImp.SetSize(const Value: Integer);
  1305. begin
  1306.   if Value <> FSize then
  1307.   begin
  1308.     if FStream = nil then
  1309.       FSize := 0
  1310.     else
  1311.     begin
  1312.       if Value > FStream.Size then
  1313.         FSize := Integer(FStream.Size)
  1314.       else
  1315.         FSize := Value;
  1316.     end;
  1317.   end;
  1318. end;
  1319.  
  1320. procedure TZMPipeImp.SetStream(const Value: TStream);
  1321. begin
  1322.   if FStream <> Value then
  1323.   begin
  1324.     if Value = nil then
  1325.       FStream.Free;
  1326.     FStream := Value;
  1327.     if Value <> nil then
  1328.     begin
  1329.       FSize := Integer(FStream.Size);
  1330.       FStream.Position := 0;
  1331.     end;
  1332.   end;
  1333. end;
  1334.  
  1335. function TZMPipeListImp.Add(aStream: TStream; const FileName: string; Own:
  1336.     boolean): integer;
  1337. var
  1338.   tmpPipe: TZMPipe;
  1339. begin
  1340.   Result := List.Count;
  1341.   tmpPipe := Pipe[Result];
  1342.   tmpPipe.Stream := aStream;
  1343.   tmpPipe.FileName := FileName;
  1344.   tmpPipe.OwnsStream := Own;
  1345. end;
  1346.  
  1347. procedure TZMPipeListImp.AfterConstruction;
  1348. begin
  1349.   inherited;
  1350.   List := TList.Create;
  1351. end;
  1352.  
  1353. procedure TZMPipeListImp.AssignTo(Dest: TZMPipeListImp);
  1354. var
  1355.   I: Integer;
  1356. begin
  1357.   if (Dest <> nil) and (Dest <> Self) then
  1358.   begin
  1359.     Dest.Clear;
  1360.     for I := 0 to Count - 1 do
  1361.       Dest.List.Add(List[i]);
  1362.     List.Clear;
  1363.   end;
  1364. end;
  1365.  
  1366. procedure TZMPipeListImp.BeforeDestruction;
  1367. begin
  1368.   Clear;
  1369.   List.Free;
  1370.   inherited;
  1371. end;
  1372.  
  1373. procedure TZMPipeListImp.Clear;
  1374. var
  1375.   i: Integer;
  1376.   tmp: TZMPipeImp;
  1377. begin
  1378.   if (List <> nil) and (List.Count > 0) then
  1379.   begin
  1380.     for I := 0 to List.Count - 1 do
  1381.     begin
  1382.      if TObject(List[i]) is TZMPipeImp then
  1383.       begin
  1384.         tmp := TZMPipeImp(List[i]);
  1385.         List[i] := nil;
  1386.         tmp.Free;
  1387.       end;
  1388.     end;
  1389.     List.Clear;
  1390.   end;
  1391. end;
  1392.  
  1393. function TZMPipeListImp.GetCount: Integer;
  1394. begin
  1395.   Result := List.Count;
  1396. end;
  1397.  
  1398. function TZMPipeListImp.GetPipe(Index: Integer): TZMPipe;
  1399. var
  1400.   tmpPipe: TZMPipeImp;
  1401. begin
  1402.   if (Index <0) or (Index > MAX_PIPE) then
  1403.     raise EZipMaster.CreateResFmt(GE_RangeError, [Index, MAX_PIPE]);
  1404.   if Index >= List.Count then
  1405.     List.Count := Index + 1;
  1406.    if not (TObject(List[Index]) is TZMPipeImp) then
  1407.    begin
  1408.      // need a new one
  1409.      tmpPipe := TZMPipeImp.Create;
  1410.      List[Index] := tmpPipe;
  1411.    end;
  1412.    Result := TZMPipeImp(List[Index]);
  1413. end;
  1414.  
  1415. function TZMPipeListImp.HasStream(Index: Integer): boolean;
  1416. begin
  1417.   Result := (Index >= 0) and (Index < count) and (Pipe[Index].Stream <> nil);
  1418. end;
  1419.  
  1420. function TZMPipeListImp.KillStream(Index: Integer): boolean;
  1421. var
  1422.   tmp: TZMPipe;
  1423. begin
  1424.   Result := False;
  1425.   if (Index >= 0) and (Index < count) then
  1426.   begin
  1427.     tmp := Pipe[Index];
  1428.     if tmp.OwnsStream and (tmp.Stream <> nil) then
  1429.       tmp.Stream := nil;
  1430.   end;
  1431. end;
  1432.  
  1433. procedure TZMPipeListImp.SetCount(const Value: Integer);
  1434. var
  1435.   I: Integer;
  1436. begin
  1437.   if (Value <0) or (Value > MAX_PIPE) then
  1438.     raise EZipMaster.CreateResInt(GE_RangeError, Value);
  1439.   if Value > List.Count then
  1440.   begin
  1441.     I := List.Count;
  1442.     while I < Value do
  1443.       List.Add(nil);
  1444.   end;
  1445. end;
  1446.  
  1447. procedure TZMPipeListImp.SetPipe(Index: Integer; const Value: TZMPipe);
  1448. var
  1449.   tmpPipe: TZMPipeImp;
  1450. begin
  1451.   if (Index <0) or (Index > MAX_PIPE) then
  1452.     raise EZipMaster.CreateResInt(GE_RangeError, Index);
  1453.   if Index >= List.Count then
  1454.     List.Count := Index + 1;
  1455.   if not (TObject(List[Index]) is TZMPipeImp) then
  1456.     List[Index] := Value
  1457.   else
  1458.   begin
  1459.     tmpPipe := TZMPipeImp(List[Index]);
  1460.     if Value <> tmpPipe then
  1461.     begin
  1462.       tmpPipe.Free;
  1463.       List[Index] := Value;
  1464.     end;
  1465.   end;
  1466. end;
  1467.  
  1468.  
  1469. end.
  1470.