Subversion Repositories autosfx

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 daniel-mar 1
unit ZMDllOpr19;
2
 
3
(*
4
  ZMDllOpr19.pas - Dll operations and functions
5
    Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht,
6
      Eric W. Engler and Chris Vleghert.
7
 
8
        This file is part of TZipMaster Version 1.9.
9
 
10
    TZipMaster is free software: you can redistribute it and/or modify
11
    it under the terms of the GNU Lesser General Public License as published by
12
    the Free Software Foundation, either version 3 of the License, or
13
    (at your option) any later version.
14
 
15
    TZipMaster 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
18
    GNU Lesser General Public License for more details.
19
 
20
    You should have received a copy of the GNU Lesser General Public License
21
    along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
22
 
23
    contact: problems@delphizip.org (include ZipMaster in the subject).
24
    updates: http://www.delphizip.org
25
    DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
26
 
27
  modified 2010-02-10
28
  --------------------------------------------------------------------------- *)
29
 
30
interface
31
 
32
{$INCLUDE '.\ZipVers19.inc'}
33
 
34
uses
35
  Classes, Windows, Controls, Graphics, Dialogs,
36
  ZMDelZip19, ZipMstr19, ZMCompat19, ZMWrkr19, ZMCore19;
37
 
38
// {$DEFINE ZDEBUG}
39
 
40
type
41
  TZMDLLOpr = class;
42
 
43
  TDZCallback = class
44
  private
45
    fHoldSize: Integer;
46
    PCB: PZCallBackStruct;
47
    function GetActionCode: Integer;
48
    function GetArg1: Cardinal;
49
    function GetArg2: Cardinal;
50
    function GetArg3: Integer;
51
    function GetFile_Size: Int64;
52
    function GetIsZip: Boolean;
53
    function GetMsg: TZMString;
54
    function GetMsg2: TZMString;
55
    function GetOwner: TZMDLLOpr;
56
    function GetWritten: Int64;
57
    procedure SetArg1(const Value: Cardinal);
58
    procedure SetArg2(const Value: Cardinal);
59
    procedure SetArg3(const Value: Integer);
60
    procedure SetFile_Size(const Value: Int64);
61
    procedure SetMsg(const Value: TZMString);
62
  protected
63
    fHeldData: PByte;
64
    fWorker: TZMWorker;
65
    function Assign(ZCallBackRec: PZCallBackStruct): Integer;
66
    function CopyData(dst: PByte; MaxSize: Integer): Boolean;
67
    function HoldData(const src: PByte; size: Cardinal): PByte;
68
    function HoldString(const src: TZMString): PByte;
69
    function GetMsgStr(const msg: PByte): TZMString;
70
    procedure SetComment(const AStr: AnsiString);
71
    procedure SetData(src: PByte; size: Integer);
72
  public
73
    constructor Create(theWorker: TZMWorker);
74
    destructor Destroy; override;
75
    procedure Clear;
76
    property ActionCode: Integer Read GetActionCode;
77
    property Arg1: Cardinal Read GetArg1 Write SetArg1;
78
    property Arg2: Cardinal Read GetArg2 Write SetArg2;
79
    property Arg3: Integer Read GetArg3 Write SetArg3;
80
    property File_Size: Int64 Read GetFile_Size Write SetFile_Size;
81
    property IsZip: Boolean Read GetIsZip;
82
    property msg: TZMString read GetMsg write SetMsg;
83
    property Msg2: TZMString read GetMsg2;
84
    property Owner: TZMDLLOpr Read GetOwner;
85
    property Written: Int64 Read GetWritten;
86
  end;
87
 
88
  // type
89
  TZMDLLOpr = class(TZMWorker)
90
  private
91
    fAddCompLevel: Integer;
92
    fAddStoreSuffixes: TZMAddStoreExts;
93
    fAutoAttr: Cardinal;
94
    fAutoDate: Cardinal;
95
    fCB: TDZCallback;
96
    fDidLoad: Boolean;
97
    fDLLDirectory: string;
98
    fDLLOperKey: Cardinal;
99
    fDLLTargetName: String;
100
    fEncrypt: Boolean;
101
    fExtAddStoreSuffixes: String;
102
    fExtrBaseDir: String;
103
    fExtrOptions: TZMExtrOpts;
104
    fFromDate: TDate;
105
    // 1 data for dll held until next callback or fini
106
    fHeldData: Pointer;
107
    fPassword: String;
108
    FPasswordReqCount: Integer;
109
    FPipes: TZMPipeListImp;
110
    fRootDir: String;
111
    fZipStream: TMemoryStream;
112
    function DLLStreamClose(ZStreamRec: PZStreamRec): Integer;
113
    function DLLStreamCreate(ZStreamRec: PZStreamRec): Integer;
114
    function DLLStreamIdentify(ZStreamRec: PZStreamRec): Integer;
115
    function DllToErrCode(DLL_error: Integer): integer;
116
    procedure DLL_Comment(var Result: Integer);
117
    procedure DLL_CRCError(var Result: Integer);
118
    procedure DLL_Data(var Result: Integer);
119
    procedure DLL_ExtName(var Result: Integer);
120
    procedure DLL_Message(var Result: Integer);
121
    procedure DLL_Overwrite(var Result: Integer);
122
    procedure DLL_Password(var Result: Integer);
123
    procedure DLL_Progress(Action: TActionCodes; var Result: Integer);
124
    procedure DLL_SetAddName(var Result: Integer);
125
    procedure DLL_Skipped(var Result: Integer);
126
    function GetDLL_Build: Integer;
127
    function GetDLL_Load: Boolean;
128
    function GetDLL_Path: string;
129
    procedure GrabPipes;
130
    procedure SetCB(const Value: TDZCallback);
131
    procedure SetDLL_Load(const Value: Boolean);
132
    procedure SetExtAddStoreSuffixes(const Value: String);
133
    procedure SetPipes(const Value: TZMPipeListImp);
134
  protected
135
    fAutoStream: TStream;
136
    function AddStoreExtStr(Options: TZMAddStoreExts): String;
137
    function AllocDLLCommand(const FileName: String): pDLLCommands;
138
    procedure DestroyDLLCmd(var rec: pDLLCommands);
139
    function DLLCallback(ZCallBackRec: PZCallBackStruct): Integer;
140
    function DLLStreamOp(op: TZStreamActions; ZStreamRec: PZStreamRec): Integer;
141
    procedure DLL_Arg(var Result: Integer);
142
    procedure ExtAdd;
143
    procedure ExtExtract;
144
    function SetupUnzCmd(const Value: String): pDLLCommands;
145
    function SetupZipCmd(const Value: String): pDLLCommands;
146
    property DLLTargetName: String read fDLLTargetName write fDLLTargetName;
147
  public
148
    constructor Create(AMaster: TCustomZipMaster19);
149
    procedure AbortDLL;
150
    function Add: Integer;
151
    procedure AddStreamToFile(const FileName: String;
152
      FileDate, FileAttr: Dword);
153
    procedure AddStreamToStream(InStream: TMemoryStream);
154
    procedure AfterConstruction; override;
155
    procedure BeforeDestruction; override;
156
    procedure Clear; override;
157
    procedure Deflate(OutStream, InStream: TStream; Length: Int64; var Method:
158
        TZMDeflates; var crc: Cardinal); override;
159
    function DLL_Version(Load: Boolean): string;
160
    procedure Done(Good: boolean = true); override;
161
    procedure Extract;
162
    procedure ExtractFileToStream(const FileName: String);
163
    procedure ExtractStreamToStream(InStream: TMemoryStream; OutSize: Longword);
164
    function GetAddPassword(var Response: TmsgDlgBtn): String;
165
    function GetExtrPassword(var Response: TmsgDlgBtn): String;
166
    function GetPassword(const DialogCaption, MsgTxt: String; ctx: Integer;
167
      pwb: TmsgDlgButtons; var ResultStr: String): TmsgDlgBtn; overload;
168
    function GetPassword(const DialogCaption, MsgTxt: String;
169
      pwb: TmsgDlgButtons; var ResultStr: String): TmsgDlgBtn; overload;
170
    procedure Kill; override;
171
    procedure StartUp; override;
172
    procedure Undeflate(OutStream, InStream: TStream; Length: Int64; var Method:
173
        tzMDeflates; var crc: Cardinal); override;
174
    property AddCompLevel: Integer Read fAddCompLevel Write fAddCompLevel;
175
    property AddStoreSuffixes
176
      : TZMAddStoreExts Read fAddStoreSuffixes Write fAddStoreSuffixes;
177
    property CB: TDZCallback Read fCB Write SetCB;
178
    property DLLDirectory: string read fDLLDirectory write fDLLDirectory;
179
    property DLL_Build: Integer read GetDLL_Build;
180
    property DLL_Load: Boolean read GetDLL_Load write SetDLL_Load;
181
    property DLL_Path: string read GetDLL_Path;
182
    property Encrypt: Boolean Read fEncrypt Write fEncrypt;
183
    property ExtAddStoreSuffixes: String Read fExtAddStoreSuffixes Write
184
      SetExtAddStoreSuffixes;
185
    property ExtrBaseDir: String Read fExtrBaseDir Write fExtrBaseDir;
186
    property ExtrOptions: TZMExtrOpts Read fExtrOptions Write fExtrOptions;
187
    property FromDate: TDate Read fFromDate Write fFromDate;
188
    property Password: String Read fPassword Write fPassword;
189
    property PasswordReqCount: Integer read FPasswordReqCount write
190
        FPasswordReqCount;
191
    property Pipes: TZMPipeListImp read FPipes write SetPipes;
192
    property RootDir: String Read fRootDir Write fRootDir;
193
    property ZipStream: TMemoryStream Read fZipStream;
194
  end;
195
 
196
implementation
197
 
198
uses
199
  SysUtils, Forms, ZMMsg19, ZMXcpt19, ZMUtils19, ZMMsgStr19, ZMCtx19,
200
  ZMDlg19, ZMZipFile19, ZMCenDir19, ZMDrv19, ZMStructs19, ZMUTF819,
201
  ZMDLLLoad19, ZMIRec19;
202
 
203
(* ? ZCallback
204
  1.76 01 May 2004 RP change return type and value to return flag for exception
205
  1.76 24 April 2004 RP use DLLCallback
206
  1.73 ( 1 June 2003) changed for new callback
207
  { Dennis Passmore (Compuserve: 71640,2464) contributed the idea of passing an
208
  instance handle to the DLL, and, in turn, getting it back from the callback.
209
  This lets us referance variables in the TZMDLLOpr class from within the
210
  callback function.  Way to go Dennis!
211
  Modified by Russell Peters }
212
*)
213
function ZCallback(ZCallBackRec: PZCallBackStruct): Longint; stdcall;
214
begin
215
  Result := CALLBACK_ERROR;
216
  if ZCallBackRec^.Check = ZCallBack_Check then
217
  begin
218
    with TObject(ZCallBackRec^.Caller) as TZMDLLOpr do
219
      Result := DLLCallback(ZCallBackRec);
220
  end;
221
end;
222
 
223
function ZStreamCallback(ZStreamRec: PZStreamRec): Longint; stdcall;
224
var
225
  cnt: Integer;
226
  op: TZStreamActions;
227
  Strm: TStream;
228
begin
229
  Result := CALLBACK_ERROR;
230
  try
231
    if ZStreamRec^.Check = ZStream_Check then
232
    begin
233
      with ZStreamRec^ do
234
      begin
235
        op := TZStreamActions(OpCode);
236
        Result := 0;
237
        case op of
238
          zsaIdentify .. zsaClose:
239
            with TObject(ZStreamRec^.Caller) as TZMDLLOpr do
240
              Result := DLLStreamOp(op, ZStreamRec);
241
          zsaPosition: // reposition
242
            begin
243
{$IFNDEF VERD6up}
244
              if Integer(ArgLL) <> ArgLL then
245
                raise EZipMaster.CreateResDisp(DS_SeekError, true);
246
{$ENDIF}
247
              Strm := TObject(StrmP) as TStream;
248
              ArgLL := Strm.Seek(ArgLL, ArgI);
249
              if ArgLL >= 0 then
250
                Result := CALLBACK_TRUE;
251
            end;
252
          zsaRead: // read
253
            begin
254
              Strm := TObject(StrmP) as TStream;
255
              cnt := ArgI;
256
              if (Strm.Position + cnt) > Strm.size then
257
                cnt := Integer(Strm.size - Strm.Position);
258
              ArgI := Strm.Read(BufP^, cnt);
259
              if ArgI = cnt then
260
                Result := CALLBACK_TRUE;
261
            end;
262
          zsaWrite: // Write
263
            begin
264
              Strm := TObject(StrmP) as TStream;
265
              cnt := ArgI;
266
              ArgI := Strm.Write(BufP^, cnt);
267
              if ArgI = cnt then
268
                Result := CALLBACK_TRUE;
269
            end;
270
        end;
271
      end;
272
    end;
273
  except
274
    on E: Exception do
275
    begin
276
      // clear any exceptions
277
      Result := CALLBACK_ERROR;
278
    end;
279
  end;
280
end;
281
 
282
constructor TZMDLLOpr.Create(AMaster: TCustomZipMaster19);
283
begin
284
  inherited Create(AMaster);
285
end;
286
 
287
procedure TZMDLLOpr.AbortDLL;
288
begin
289
  if fDLLOperKey <> 0 then
290
    _DLL_Abort(self, fDLLOperKey);
291
end;
292
 
293
(* ? TZMDLLOpr.Add
294
*)
295
function TZMDLLOpr.Add: Integer;
296
begin
297
  fAutoStream := nil;
298
  ExtAdd;
299
  Result := ErrCode;
300
end;
301
 
302
(* ? TZMDLLOpr.AddStoreExtStr
303
*)
304
function TZMDLLOpr.AddStoreExtStr(Options: TZMAddStoreExts): String;
305
const
306
  SuffixStrings: array [TZMAddStoreSuffixEnum] of PChar =
307
    ('gif', 'png', 'z', 'zip', 'zoo', 'arc', 'lzh', 'arj', 'taz', 'tgz', 'lha',
308
    'rar', 'ace', 'cab', 'gz', 'gzip', 'jar', 'exe', '', 'jpg', 'jpeg', '7zp',
309
    'mp3', 'wmv', 'wma', 'dvr-ms', 'avi');
310
var
311
  o: TZMAddStoreSuffixEnum;
312
begin
313
  for o := Low(TZMAddStoreSuffixEnum) to High(TZMAddStoreSuffixEnum) do
314
    if (o <> assEXT) and (o in Options) then
315
      Result := Result + '.' + String(SuffixStrings[o]) + ':';
316
  if assEXT in Options then
317
    Result := Result + fExtAddStoreSuffixes;
318
end;
319
 
320
(* ? TZMDLLOpr.AddStreamToFile
321
  // EWE: I think 'FileName' is the name you want to use in the zip file to
322
  // store the contents of the stream under.
323
*)
324
procedure TZMDLLOpr.AddStreamToFile(const FileName: String;
325
  FileDate, FileAttr: Dword);
326
var
327
  FatDate: Word;
328
  FatTime: Word;
329
  fn: String;
330
  ft: TFileTime;
331
  st: TSystemTime;
332
begin
333
  fn := Trim(FileName);
334
  if (Length(FileName) = 0) and (FSpecArgs.Count > 0) then
335
    fn := Trim(FSpecArgs[0]);
336
  if (fn = '') or (ZipStream.size = 0) then
337
  begin
338
    ShowZipMessage(AD_NothingToZip, '');
339
    exit;
340
  end;
341
  if IsWild(fn) then
342
  begin
343
    ShowZipMessage(AD_InvalidName, '');
344
    exit;
345
  end;
346
  FSpecArgs.Clear();
347
 
348
  FSpecArgs.Add('0:' + fn);
349
  if FileDate = 0 then
350
  begin
351
    GetLocalTime(st);
352
    SystemTimeToFileTime(st, ft);
353
    FileTimeToDosDateTime(ft, FatDate, FatTime);
354
    FileDate := (Dword(FatDate) shl 16) + FatTime;
355
  end;
356
  SuccessCnt := 0;
357
  fAutoStream := ZipStream;
358
  fAutoDate := FileDate;
359
  fAutoAttr := FileAttr;
360
  // Add;
361
  ExtAdd;
362
end;
363
 
364
(* ? TZMDLLOpr.AddStreamToStream
365
*)
366
procedure TZMDLLOpr.AddStreamToStream(InStream: TMemoryStream);
367
var
368
  Header: TZM_StreamHeader;
369
  Method: TZMDeflates;
370
begin
371
  SuccessCnt := 0;
372
  if InStream = ZipStream then
373
  begin
374
    ShowZipMessage(AD_InIsOutStream, '');
375
    exit;
376
  end;
377
  if assigned(InStream) and (InStream.size > 0) then
378
  begin
379
    if AddEncrypt in AddOptions then
380
    begin
381
      ShowZipMessage(DS_NoEncrypt, '');
382
      exit;
383
    end;
384
    ZipStream.size := 0;
385
    Method := zmDeflate;
386
    Header.Method := METHOD_DEFLATED;
387
    Header.CRC := 0;
388
    ZipStream.WriteBuffer(Header, SizeOf(Header));
389
    Deflate(ZipStream, InStream, -1, Method, Header.CRC);
390
    if SuccessCnt = 1 then
391
    begin
392
      ZipStream.Position := 0;
393
      if Method <> zmDeflate then
394
        Header.Method := METHOD_STORED; // was stored
395
      ZipStream.WriteBuffer(Header, SizeOf(Header));
396
    end
397
    else
398
      ZipStream.size := 0;
399
  end
400
  else
401
    ShowZipMessage(AD_NothingToZip, '');
402
end;
403
 
404
procedure TZMDLLOpr.AfterConstruction;
405
begin
406
  inherited;
407
  fDLLOperKey := 0;
408
  fHeldData := nil;
409
  fPassword := '';
410
  fPasswordReqCount := 1;
411
  fEncrypt := False;
412
  fAddCompLevel := 9; // dflt to tightest compression
413
  fAddStoreSuffixes := ZMDefAddStoreSuffixes;
414
  fZipStream := TMemoryStream.Create;
415
  fCB := TDZCallback.Create(self);
416
  FPipes := TZMPipeListImp.Create;
417
end;
418
 
419
function TZMDLLOpr.AllocDLLCommand(const FileName: String): pDLLCommands;
420
var
421
  Opts: Cardinal;
422
begin
423
  Result := AllocMem(SizeOf(TDLLCommands));
424
  DLLTargetName := FileName;
425
  ZeroMemory(Result, SizeOf(TDLLCommands));
426
  Result^.fVersion := DELZIPVERSION; // version we expect the DLL to be
427
  Result^.fCaller := self; // point to our VCL instance; returned in Report
428
 
429
  Result^.ZCallbackFunc := ZCallback; // pass addr of function to be called from DLL
430
  Result^.ZStreamFunc := ZStreamCallback;
431
  Result^.fEncodedAs := Ord(Encoding); // how to interpret existing names
432
  Result^.fFromPage := Encoding_CP;
433
 
434
  if Verbosity >= zvTrace then
435
    Result^.fVerbosity := -1
436
  else if Verbosity >= zvVerbose then
437
    Result^.fVerbosity := 1
438
  else
439
    Result^.fVerbosity := 0;
440
  { if tracing, we want verbose also }
441
 
442
  // used for dialogs (like the pwd dialogs)
443
  if Unattended then
444
    Result^.fHandle := 0
445
  else
446
    Result^.fHandle := Handle;
447
  Result^.fSS := nil;
448
 
449
  Opts := DLL_OPT_Quiet; // no DLL error reporting
450
 
451
  Result^.fOptions := Opts;
452
end;
453
 
454
procedure TZMDLLOpr.BeforeDestruction;
455
begin
456
  fIsDestructing := true; // stop callbacks
457
  AbortDLL;
458
  if fHeldData <> nil then
459
    FreeMem(fHeldData); // release held data
460
  FreeAndNil(fZipStream);
461
  FreeAndNil(fCB);
462
  FPipes.Clear;
463
  FreeAndNil(FPipes);
464
  _DLL_Remove(self); // remove from list
465
  inherited;
466
end;
467
 
468
procedure TZMDLLOpr.Clear;
469
begin
470
  fIsDestructing := true; // stop callbacks
471
  AbortDLL;
472
  fIsDestructing := False; // restore callbacks
473
  inherited;
474
  fPassword := '';
475
  fPasswordReqCount := 1;
476
  fEncrypt := False;
477
  fAddCompLevel := 9; // dflt to tightest compression
478
  fAddStoreSuffixes := ZMDefAddStoreSuffixes;
479
  fZipStream.size := 0;
480
  FPipes.Clear;
481
end;
482
 
483
procedure TZMDLLOpr.Deflate(OutStream, InStream: TStream; Length: Int64; var
484
    Method: TZMDeflates; var crc: Cardinal);
485
var
486
  Args: TZSSArgs;
487
  CmdRecP: pDLLCommands;
488
  i: Integer;
489
  ncrypt: boolean;
490
begin
491
  SuccessCnt := 0;
492
  ClearErr;
493
  if not assigned(InStream) then
494
  begin
495
    ShowZipMessage(DS_NoInStream, '');
496
    exit;
497
  end;
498
  if not assigned(OutStream) then
499
  begin
500
    ShowZipMessage(DS_NoOutStream, '');
501
    exit;
502
  end;
503
  if InStream = ZipStream then
504
  begin
505
    ShowZipMessage(AD_InIsOutStream, '');
506
    exit;
507
  end;
508
  CmdRecP := nil;
509
  ncrypt := (Method = zmStoreEncrypt) or (Method = zmDeflateEncrypt);
510
  // We can not do an Unattended Add if we don't have a password.
511
  if Unattended and ncrypt and (Password = '') then
512
  begin
513
    ShowZipMessage(AD_UnattPassword, '');
514
    exit;
515
  end;
516
  if Length < 0 then
517
    Length := InStream.size;
518
  if (Method = zmDeflate) or (Method = zmDeflateEncrypt) then
519
    Args.Method := 8
520
  else
521
    Args.Method := 0;
522
  Args.fSSInput := InStream;
523
  Args.fSSOutput := OutStream;
524
  Args.size := Length;
525
  Args.crc := crc;
526
  if _DLL_Load(self) <= 0 then
527
  begin
528
    ShowZipMessage(LD_NoDLL, DelZipDLL_Name);
529
    exit;
530
  end;
531
  try
532
    if ncrypt then
533
      AddOptions := AddOptions + [addEncrypt]
534
    else
535
      AddOptions := AddOptions - [addEncrypt];
536
    CmdRecP := SetupZipCmd('');
537
    CmdRecP^.fSS := @Args;
538
    fEventErr := ''; // added
539
    { pass in a ptr to parms }
540
    i := _DLL_Exec(self, CmdRecP, fDLLOperKey);
541
  finally
542
    _DLL_Unload(self);
543
    DestroyDLLCmd(CmdRecP);
544
  end;
545
  if i = 1 then
546
  begin // success
547
    SuccessCnt := 1;
548
    if Args.Method = 8 then
549
      Method := zmDeflate
550
    else
551
      Method := zmStore;
552
    crc := Args.crc;
553
  end;
554
end;
555
 
556
procedure TZMDLLOpr.DestroyDLLCmd(var rec: pDLLCommands);
557
begin
558
  if rec <> nil then
559
  begin
560
    FreeMem(rec);
561
    rec := nil;
562
  end;
563
end;
564
 
565
(* ? TZMDLLOpr.DLLCallback
566
*)
567
function TZMDLLOpr.DLLCallback(ZCallBackRec: PZCallBackStruct): Integer;
568
var
569
  Action: TActionCodes;
570
begin
571
  Result := CALLBACK_UNHANDLED; // unhandled //CALLBACK_IGNORED;
572
  if fIsDestructing then // in destructor return
573
  begin
574
    exit;
575
  end;
576
  CB.Assign(ZCallBackRec);
577
  Action := TActionCodes(CB.ActionCode and 63);
578
  try
579
    case Action of
580
      zacMessage:
581
        DLL_Message(Result);
582
      zacItem .. zacXProgress:
583
        DLL_Progress(Action, Result);
584
      zacNewName:
585
        // request for a new path+name just before zipping or extracting
586
        DLL_SetAddName(Result);
587
      zacPassword:
588
        // New or other password needed during Extract()
589
        DLL_Password(Result);
590
      zacCRCError:
591
        // CRC32 error, (default action is extract/test the file)
592
        DLL_CRCError(Result);
593
      zacOverwrite:
594
        // Extract(UnZip) Overwrite ask
595
        DLL_Overwrite(Result);
596
      zacSkipped:
597
        // Extract(UnZip) and Skipped
598
        DLL_Skipped(Result);
599
      zacComment:
600
        // Add(Zip) FileComments.
601
        DLL_Comment(Result);
602
      zacData:
603
        // Set Extra Data
604
        DLL_Data(Result);
605
      zacExtName:
606
        // request for a new path+name just before zipping or extracting
607
        DLL_ExtName(Result);
608
      zacKey:
609
        begin
610
          fDLLOperKey := CB.Arg1;
611
          Result := 0;
612
        end;
613
      zacArg:
614
        DLL_Arg(Result);
615
    else
616
      Result := CALLBACK_IGNORED; // unknown
617
    end; { end case }
618
    if (Action < zacKey) and (Action > zacMessage) then
619
    begin
620
      KeepAlive;
621
    end;
622
    if Cancel <> 0 then
623
    begin
624
      Result := CALLBACK_CANCEL;
625
      if Sniffer <> 0 then
626
        ReportToSniffer(0, '[CANCEL sent]');
627
    end;
628
  except
629
    on E: Exception do
630
    begin
631
      if fEventErr = '' then
632
        // catch first exception only
633
        fEventErr := ' #' + IntToStr(Ord(Action)) + ' "' + E.Message + '"';
634
      Cancel := GE_Except;
635
      Result := CALLBACK_EXCEPTION;
636
      if Sniffer <> 0 then
637
        ReportToSniffer(0, '[CALLBACK Exception sent] ' + fEventErr);
638
    end;
639
  end;
640
end;
641
 
642
function TZMDLLOpr.DLLStreamClose(ZStreamRec: PZStreamRec): Integer;
643
var
644
  IsDone: Boolean;
645
  SNumber: Integer;
646
  Strm: TStream;
647
  tmpOnStream: TZMStreamEvent;
648
  zstats: TZMSStats;
649
begin
650
  zstats.size := 0;
651
  zstats.Date := 0;
652
  zstats.Attrs := 0;
653
  Result := CALLBACK_UNHANDLED;
654
  if TObject(ZStreamRec^.StrmP) is TStream then
655
  begin
656
    Strm := TStream(ZStreamRec^.StrmP);
657
    if Strm = ZipStream then
658
    begin
659
      fAutoStream := nil;
660
      ZStreamRec^.StrmP := nil;
661
      Result := CALLBACK_TRUE;
662
    end
663
    else
664
    begin
665
          IsDone := False;
666
      tmpOnStream := Master.OnStream;
667
      SNumber := ZStreamRec^.Number;
668
      if assigned(tmpOnStream) then
669
      begin
670
        if (Strm <> ZipStream) then
671
        begin
672
          tmpOnStream(Master, zsoClose, SNumber, Strm, zstats, IsDone);
673
          if IsDone then
674
          begin
675
            Result := CALLBACK_TRUE;
676
            ZStreamRec^.StrmP := Strm;
677
          end;
678
        end;
679
      end;
680
    if (not IsDone) and FPipes.HasStream(SNumber) then
681
      begin
682
        FPipes.KillStream(SNumber);
683
        Result := CALLBACK_TRUE;
684
      end;
685
    end;
686
  end;
687
end;
688
 
689
function TZMDLLOpr.DLLStreamCreate(ZStreamRec: PZStreamRec): Integer;
690
var
691
  IsDone: Boolean;
692
  pipe: TZMPipe;
693
  SNumber: Integer;
694
  Strm: TStream;
695
  tmpOnStream: TZMStreamEvent;
696
  zstats: TZMSStats;
697
begin
698
  zstats.size := 0;
699
  zstats.Date := 0;
700
  zstats.Attrs := 0;
701
  Result := CALLBACK_UNHANDLED;
702
  ZStreamRec^.StrmP := nil;
703
  if assigned(fAutoStream) then
704
  begin
705
    Result := CALLBACK_TRUE;
706
    ZStreamRec^.StrmP := fAutoStream;
707
    fAutoStream.Position := 0;
708
  end
709
  else
710
  begin
711
    IsDone := False;
712
    tmpOnStream := Master.OnStream;
713
    SNumber := ZStreamRec^.Number;
714
    if assigned(tmpOnStream) then
715
    begin
716
      IsDone := False;
717
      tmpOnStream(Master, zsoOpen, SNumber, Strm, zstats, IsDone);
718
      if IsDone and assigned(Strm) then
719
      begin
720
        Result := CALLBACK_TRUE;
721
        ZStreamRec^.StrmP := Strm;
722
      end;
723
    end;
724
    if (not IsDone) and FPipes.HasStream(SNumber) then
725
    begin
726
      pipe := FPipes[SNumber];
727
      Result := CALLBACK_TRUE;
728
      ZStreamRec^.StrmP := pipe.Stream;
729
    end;
730
  end;
731
end;
732
 
733
function TZMDLLOpr.DLLStreamIdentify(ZStreamRec: PZStreamRec): Integer;
734
var
735
  IsDone: Boolean;
736
  pipe: TZMPipe;
737
  SNumber: Integer;
738
  Strm: TStream;
739
  tmpOnStream: TZMStreamEvent;
740
  zstats: TZMSStats;
741
begin
742
  zstats.size := 0;
743
  zstats.Date := 0;
744
  zstats.Attrs := 0;
745
  Result := CALLBACK_UNHANDLED;
746
  if assigned(fAutoStream) then
747
  begin
748
    Result := CALLBACK_TRUE;
749
    ZStreamRec^.ArgLL := fAutoStream.size;
750
    ZStreamRec^.ArgD := fAutoDate;
751
    ZStreamRec^.ArgA := fAutoAttr;
752
  end
753
  else
754
  begin
755
      IsDone := False;
756
    tmpOnStream := Master.OnStream;
757
    SNumber := ZStreamRec^.Number;
758
    if assigned(tmpOnStream) then
759
    begin
760
      tmpOnStream(Master, zsoIdentify, SNumber, Strm, zstats, IsDone);
761
      if IsDone then
762
      begin
763
        Result := CALLBACK_TRUE;
764
        ZStreamRec^.ArgLL := zstats.size;
765
        ZStreamRec^.ArgD := zstats.Date;
766
        ZStreamRec^.ArgA := zstats.Attrs;
767
      end;
768
    end;
769
    if (not IsDone) and FPipes.HasStream(SNumber) then
770
    begin
771
      pipe := FPipes[SNumber];
772
      Result := CALLBACK_TRUE;
773
      ZStreamRec^.ArgLL := pipe.size;
774
      ZStreamRec^.ArgD := pipe.DOSDate;
775
      ZStreamRec^.ArgA := pipe.Attributes;
776
    end;
777
  end;
778
end;
779
 
780
// ALL interface structures BYTE ALIGNED
781
(* stream operation arg usage
782
  zacStIdentify,
783
  //      IN BufP = name
784
  IN Number = number
785
  OUT ArgLL = size, ArgD = Date, ArgA = Attrs
786
  zacStCreate,
787
  //      IN BufP = name
788
  IN Number = number
789
  OUT StrmP = stream
790
  zacStClose,
791
  IN Number = number
792
  IN StrmP = stream
793
  OUT StrmP = stream (= NULL)
794
  zacStPosition,
795
  IN Number = number
796
  IN StrmP = stream, ArgLL = offset, ArgI = from
797
  OUT ArgLL = position
798
  zacStRead,
799
  IN Number = number
800
  IN StrmP = stream, BufP = buf, ArgI = count
801
  OUT ArgI = bytes read
802
  zacStWrite
803
  IN Number = number
804
  IN StrmP = stream, BufP = buf, ArgI = count
805
  OUT ArgI = bytes written
806
*)
807
function TZMDLLOpr.DLLStreamOp(op: TZStreamActions; ZStreamRec: PZStreamRec)
808
  : Integer;
809
begin
810
  Result := CALLBACK_UNHANDLED;
811
  case op of
812
    zsaIdentify: // get details for named stream
813
        Result := DLLStreamIdentify(ZStreamRec);
814
    zsaCreate: // Assign a stream
815
        Result := DLLStreamCreate(ZStreamRec);
816
    zsaClose: // defaults to freeing stream if not ZipStream
817
        Result := DLLStreamClose(ZStreamRec);
818
  end;
819
  if Verbosity >= zvVerbose then
820
  begin
821
    Diag(Format('Stream operation %d on %d returns %d',
822
        [Ord(op), ZStreamRec^.Number, Result]));
823
  end;
824
end;
825
 
826
// return proper ErrCode for dll error
827
function TZMDLLOpr.DllToErrCode(DLL_error: Integer): integer;
828
begin
829
  Result := DLL_error and 255;
830
  if Result <> 0 then
831
    Result := DZ_RES_GOOD + Result;
832
  if Result > DZ_ERR_DUPNAME then
833
    Result := DZ_RES_ERROR;
834
end;
835
 
836
(* Arg1 = argument
837
 
838
  1 = password
839
  2 = RootDir
840
  3 = ExtractDir
841
  4 = Zip comment
842
  5 = FSpecArgs      Arg3 = index
843
  6 = FSpecArgsExcl  Arg3 = index
844
*)
845
procedure TZMDLLOpr.DLL_Arg(var Result: Integer);
846
var
847
  Arg: TCBArgs;
848
  idx: Integer;
849
  sr: TZMString;
850
begin
851
  if CB.Arg1 <= Cardinal(Ord( HIGH(TCBArgs))) then
852
  begin
853
    Arg := TCBArgs(CB.Arg1);
854
    idx := CB.Arg3;
855
    sr := '';
856
    if (Arg in [zcbFSpecArgs, zcbFSpecArgsExcl]) and (idx < 0) then
857
      Result := CALLBACK_ERROR
858
    else if Arg = zcbComment then
859
    begin // always Ansi
860
      CB.SetComment(ZipComment);
861
      Result := CALLBACK_TRUE;
862
    end
863
    else
864
    begin
865
      Result := CALLBACK_TRUE;
866
      case Arg of
867
        zcbFilename:
868
          sr := DLLTargetName;
869
        zcbPassword:
870
          sr := Password;
871
        zcbRootDir:
872
          sr := RootDir;
873
        zcbExtractDir:
874
          sr := ExtrBaseDir;
875
        zcbFSpecArgs:
876
          begin
877
            if idx >= FSpecArgs.Count then
878
              Result := CALLBACK_UNHANDLED
879
            else
880
              sr := FSpecArgs[idx];
881
            CB.Arg3 := FSpecArgs.Count;
882
          end;
883
        zcbFSpecArgsExcl:
884
          begin
885
            if idx >= FSpecArgsExcl.Count then
886
              Result := CALLBACK_UNHANDLED
887
            else
888
              sr := FSpecArgsExcl[idx];
889
            CB.Arg3 := FSpecArgsExcl.Count;
890
          end;
891
        zcbSpecials:
892
          sr := AddStoreExtStr(AddStoreSuffixes);
893
        zcbTempPath:
894
          sr := TempDir;
895
      end;
896
      CB.msg := sr;
897
    end;
898
  end
899
  else
900
    Result := CALLBACK_ERROR;
901
end;
902
 
903
procedure TZMDLLOpr.DLL_Comment(var Result: Integer);
904
var
905
  FileComment: TZMString;
906
  IsChanged: Boolean;
907
  ti: Integer;
908
  tmpFileComment: TZMFileCommentEvent;
909
begin
910
  tmpFileComment := Master.OnFileComment;
911
  if assigned(tmpFileComment) then
912
  begin
913
    FileComment := CB.Msg2;
914
    IsChanged := False;
915
    tmpFileComment(Master, CB.msg, FileComment, IsChanged);
916
    if IsChanged then
917
    begin
918
      Result := CALLBACK_TRUE;
919
      ti := Length(FileComment);
920
      if ti > 255 then
921
      begin
922
        ti := 255;
923
        FileComment := Copy(FileComment, 1, 255);
924
      end;
925
      CB.msg := FileComment;
926
      CB.Arg1 := ti;
927
    end;
928
  end;
929
  if (Cancel <> 0) and (Result >= CALLBACK_IGNORED) then
930
    Result := CALLBACK_CANCEL;
931
end;
932
 
933
procedure TZMDLLOpr.DLL_CRCError(var Result: Integer);
934
var
935
  DoExtract: Boolean;
936
  tmpCRC32Error: TZMCRC32ErrorEvent;
937
begin
938
  DoExtract := true;
939
  tmpCRC32Error := Master.OnCRC32Error;
940
  if assigned(tmpCRC32Error) then
941
  begin
942
    tmpCRC32Error(Master, CB.msg, CB.Arg1, CB.Arg2, DoExtract);
943
    if DoExtract then
944
      Result := CALLBACK_TRUE
945
    else
946
      Result := CALLBACK_3;
947
  end;
948
end;
949
 
950
procedure TZMDLLOpr.DLL_Data(var Result: Integer);
951
var
952
  dat: TZMRawBytes;
953
  DataChanged: Boolean;
954
  DatSize: Int64;
955
  IsChanged: Boolean;
956
  LevelChanged: Boolean;
957
  lvl: Integer;
958
  tmpFileExtra: TZMFileExtraEvent;
959
  tmpSetCompLevel: TZMSetCompLevel;
960
  xlen: Integer;
961
begin
962
  tmpFileExtra := Master.OnFileExtra;
963
  tmpSetCompLevel := Master.OnSetCompLevel;
964
  LevelChanged := False;
965
  DataChanged := False;
966
  if assigned(tmpSetCompLevel) then
967
  begin
968
    IsChanged := False;
969
    lvl := Integer(CB.Arg2);
970
    tmpSetCompLevel(Master, CB.msg, lvl, IsChanged);
971
    if IsChanged and (lvl in [0 .. 9]) then
972
    begin
973
      CB.Arg2 := lvl;
974
      LevelChanged := true;
975
    end;
976
  end;
977
  if assigned(tmpFileExtra) then
978
  begin
979
    DatSize := CB.Arg1; // old size
980
    SetLength(dat, DatSize);
981
    if DatSize > 0 then
982
      CB.CopyData(PByte(@dat[1]), DatSize);
983
    IsChanged := False;
984
    tmpFileExtra(Master, CB.msg, dat, IsChanged);
985
    if IsChanged then
986
    begin
987
      DataChanged := true;
988
      xlen := Length(dat);
989
      if xlen > 2047 then // limit
990
        xlen := 2047;
991
      CB.SetData(PByte(@dat[1]), xlen);
992
    end;
993
  end;
994
  if DataChanged then
995
  begin
996
    if LevelChanged then
997
      Result := CALLBACK_3
998
    else
999
      Result := CALLBACK_TRUE;
1000
  end
1001
  else
1002
  begin
1003
    if LevelChanged then
1004
      Result := CALLBACK_2;
1005
  end;
1006
end;
1007
 
1008
procedure TZMDLLOpr.DLL_ExtName(var Result: Integer);
1009
var
1010
  BaseDir: TZMString;
1011
  IsChanged: Boolean;
1012
  msg: TZMString;
1013
  OldFileName: TZMString;
1014
  tmpSetExtName: TZMSetExtNameEvent;
1015
 
1016
  function IsPathOnly(const f: String): Boolean;
1017
  var
1018
    c: Char;
1019
  begin
1020
    Result := False;
1021
    if f <> '' then
1022
    begin
1023
      c := f[Length(f)];
1024
      if (c = PathDelim) or (c = PathDelimAlt) then
1025
        Result := true;
1026
    end;
1027
  end;
1028
 
1029
begin
1030
  tmpSetExtName := Master.OnSetExtName;
1031
  if assigned(tmpSetExtName) then
1032
  begin
1033
    msg := CB.Msg2;
1034
    BaseDir := SetSlashW(msg, psdExternal);
1035
    msg := CB.msg;
1036
    OldFileName := msg;
1037
    IsChanged := False;
1038
    tmpSetExtName(Master, OldFileName, BaseDir, IsChanged);
1039
    if IsChanged and (OldFileName <> msg) and
1040
      (IsPathOnly(OldFileName) = IsPathOnly(msg)) then
1041
    begin
1042
      CB.msg := OldFileName;
1043
      Result := CALLBACK_TRUE;
1044
    end;
1045
  end;
1046
end;
1047
 
1048
procedure TZMDLLOpr.DLL_Message(var Result: Integer);
1049
var
1050
  ECode: Integer;
1051
  Erm: TZMString;
1052
  ErrorCode: Integer;
1053
  EType: Integer;
1054
begin
1055
  Erm := CB.msg;
1056
  ErrorCode := CB.Arg1;
1057
  if (ErrorCode > 0) and (DllErrCode = 0) then
1058
    DllErrCode := ErrorCode;   // remember last error
1059
  ECode := DllToErrCode(ErrorCode);
1060
  EType := ErrorCode and DZM_Type_Mask;
1061
  if (EType >= DZM_Message) and ((ErrorCode and DZM_MessageBit) <> 0) then
1062
    Erm := ZipLoadStr(ECode) + Erm;
1063
  if (ECode <> 0) and (ErrCode = 0) then // W'll always keep the last ErrorCode
1064
  begin
1065
    if (fEventErr <> '') and (ECode = _DZ_ERR_ABORT) then
1066
    begin
1067
      Erm := ZipFmtLoadStr(GE_EventEx, [fEventErr]);
1068
    end;
1069
  end;
1070
  if Sniffer <> 0 then
1071
    ReportToSniffer(ErrorCode, Erm);
1072
  ReportMessage1(ECode, Erm);
1073
end;
1074
 
1075
procedure TZMDLLOpr.DLL_Overwrite(var Result: Integer);
1076
var
1077
  DoOverwrite: Boolean;
1078
  tmpExtractOverwrite: TZMExtractOverwriteEvent;
1079
begin
1080
  tmpExtractOverwrite := Master.OnExtractOverwrite;
1081
  if assigned(tmpExtractOverwrite) then
1082
  begin
1083
    DoOverwrite := CB.Arg1 <> 0;
1084
    tmpExtractOverwrite(Master, CB.msg, CB.Arg3 <> 2, DoOverwrite, CB.Arg2);
1085
    if DoOverwrite then
1086
      Result := CALLBACK_TRUE
1087
    else
1088
      Result := CALLBACK_2;
1089
    if Sniffer <> 0 then
1090
      ReportToSniffer
1091
        (0, Format('[Overwrite] IN=%d,%d OUT=%d', [CB.Arg1, CB.Arg2, Result]));
1092
  end;
1093
end;
1094
 
1095
procedure TZMDLLOpr.DLL_Password(var Result: Integer);
1096
var
1097
  IsZip: Boolean;
1098
  pwd: String;
1099
  Response: TmsgDlgBtn;
1100
  RptCount: Longword;
1101
  tmpPasswordError: TZMPasswordErrorEvent;
1102
begin
1103
  pwd := '';
1104
  RptCount := CB.Arg1;
1105
  Response := mbOK;
1106
  IsZip := CB.IsZip;
1107
  tmpPasswordError := Master.OnPasswordError;
1108
  if assigned(tmpPasswordError) then
1109
  begin
1110
    tmpPasswordError(Master, IsZip, pwd, CB.msg, RptCount, Response);
1111
    if Response <> mbOK then
1112
      pwd := '';
1113
  end
1114
  else if IsZip then
1115
    pwd := GetAddPassword(Response)
1116
  else
1117
    pwd := GetExtrPassword(Response);
1118
 
1119
  if pwd <> '' then
1120
  begin
1121
    CB.msg := pwd;
1122
    Result := CALLBACK_TRUE;
1123
  end
1124
  else
1125
  begin // no password
1126
    RptCount := 0;
1127
    Result := CALLBACK_2;
1128
  end;
1129
  if RptCount > 15 then
1130
    RptCount := 15;
1131
  CB.Arg1 := RptCount;
1132
  if Response = mbCancel then // Cancel
1133
  begin
1134
    Result := CALLBACK_2;
1135
  end
1136
  else if Response = mbNoToAll then // Cancel all
1137
  begin
1138
    Result := CALLBACK_3;
1139
  end
1140
  else if Response = mbAbort then // Abort
1141
  begin
1142
    Cancel := GE_Abort;
1143
    Result := CALLBACK_ABORT;
1144
  end;
1145
end;
1146
 
1147
procedure TZMDLLOpr.DLL_Progress(Action: TActionCodes; var Result: Integer);
1148
var
1149
  ErrorCode: Integer;
1150
  File_Size: Int64;
1151
  M: String;
1152
begin
1153
  ErrorCode := 0;
1154
  File_Size := 0;
1155
  M := '';
1156
  if (Action > zacTick) and (Action <= zacXProgress) then
1157
    File_Size := CB.File_Size;
1158
//    File_Size := Int64(CB.File_Size);
1159
  if (Action = zacItem) or (Action = zacXItem) then
1160
    M := CB.msg;
1161
  case Action of
1162
    zacItem .. zacEndOfBatch:
1163
        ProgDetail.Written(CB.Written);
1164
//        ProgDetail.Written(Int64(CB.Written));
1165
    zacCount:
1166
      File_Size := CB.Arg1;
1167
    zacXItem, zacXProgress:
1168
        ErrorCode := CB.Arg1;
1169
  end;
1170
  ReportProgress(Action, ErrorCode, M, File_Size);
1171
  Result := 0;
1172
end;
1173
 
1174
procedure TZMDLLOpr.DLL_SetAddName(var Result: Integer);
1175
var
1176
  IsChanged: Boolean;
1177
  M: String;
1178
  M2: String;
1179
  OldFileName: TZMString;
1180
  OrigName: TZMString;
1181
  tmpSetAddName: TZMSetAddNameEvent;
1182
begin
1183
  tmpSetAddName := Master.OnSetAddName;
1184
  if assigned(tmpSetAddName) then
1185
  begin
1186
    M := CB.msg; // saves OldFileName
1187
    M2 := CB.Msg2;
1188
    if assigned(tmpSetAddName) then
1189
    begin
1190
      OrigName := SetSlashW(M2, psdExternal);
1191
      OldFileName := M;
1192
      IsChanged := False;
1193
 
1194
      tmpSetAddName(Master, OldFileName, OrigName, IsChanged);
1195
      if IsChanged then
1196
      begin
1197
        CB.msg := OldFileName;
1198
        Result := CALLBACK_TRUE;
1199
      end;
1200
    end;
1201
  end;
1202
end;
1203
 
1204
procedure TZMDLLOpr.DLL_Skipped(var Result: Integer);
1205
var
1206
  ErrorCode: Integer;
1207
  ti: Integer;
1208
begin
1209
  ErrorCode := CB.Arg1; // error
1210
  if ErrorCode < 0 then
1211
    ErrorCode := -ErrorCode;
1212
//  ti := CB.Arg2; // type
1213
  if ErrorCode <> 0 then
1214
    DllErrCode := ErrorCode;
1215
  ti := CB.Arg2; // type
1216
  if ReportSkipping(CB.msg, DllToErrCode(ErrorCode), TZMSkipTypes(pred(ti and MAX_BYTE))) then
1217
    Result := CALLBACK_TRUE;
1218
end;
1219
 
1220
procedure TZMDLLOpr.Done(Good: boolean = true);
1221
begin
1222
  inherited;
1223
  if not Good then
1224
    FPipes.Clear;
1225
end;
1226
 
1227
(* ? TZMDLLOpr.ExtAdd
1228
*)
1229
procedure TZMDLLOpr.ExtAdd;
1230
var
1231
  CmdRecP: pDLLCommands;
1232
  curz: TZMZipFile;
1233
  MultiDisk: Boolean;
1234
  ret: Integer;
1235
  TmpZipName: String;
1236
begin
1237
//  { Make sure we can't get back in here while work is going on }
1238
  SuccessCnt := 0;
1239
  ClearErr;
1240
  CmdRecP := nil;
1241
  MultiDisk := zwoDiskSpan in WriteOptions;
1242
  // We can not do an Unattended Add if we don't have a password.
1243
  if Unattended and (AddEncrypt in AddOptions) and (Password = '') then
1244
    raise EZipMaster.CreateResDisp(AD_UnattPassword, true);
1245
  try
1246
    GrabPipes;
1247
    if ZipFileName = '' then // make sure we have a zip filename
1248
      raise EZipMaster.CreateResDisp(GE_NoZipSpecified, true);
1249
    if (FSpecArgs.Count = 0) then
1250
    begin
1251
      if not((AddFreshen in AddOptions) or (AddUpdate in AddOptions)) then
1252
        raise EZipMaster.CreateResDisp(AD_NothingToZip, true);
1253
      AddOptions := (AddOptions - [AddUpdate]) + [AddFreshen];
1254
      FSpecArgs.Add(WILD_ALL); // do freshen all
1255
    end;
1256
 
1257
    curz := CentralDir.Current;
1258
    if curz.FileName = '' then
1259
      curz.FileName := ZipFileName;
1260
    curz.WorkDrive.HasMedia(False);
1261
    // drive must exist and be changeable
1262
    if Unattended and (not curz.WorkDrive.DriveIsFixed) and MultiDisk then
1263
      raise EZipMaster.CreateResDisp(DS_NoUnattSpan, true);
1264
 
1265
    if (curz.Count = 0) and ((AddFreshen in AddOptions)) then
1266
      raise EZipMaster.CreateResDisp(AD_NothingToZip, true);
1267
 
1268
    // make certain destination can exist
1269
    { We must allow a zipfile to be specified that doesn't already exist,
1270
      so don't check here for existance. }
1271
    if (curz.WorkDrive.DriveIsFixed or not MultiDisk) then
1272
    begin
1273
      if zwoForceDest in WriteOptions then
1274
        ForceDirectory(ExtractFilePath(ZipFileName));
1275
      if not DirExists(ExtractFilePath(ZipFileName)) then
1276
        raise EZipMaster.CreateResStr(AD_NoDestDir, ExtractFilePath(ZipFileName)
1277
          );
1278
    end;
1279
 
1280
    if not IsDestWritable(ZipFileName, MultiDisk) then
1281
      raise EZipMaster.CreateResStr(DS_NotChangeable, ZipFileName);
1282
 
1283
    if _DLL_Load(self) <= 0 then
1284
      exit; // could not load valid dll
1285
    TmpZipName := ZipFileName; // default
1286
    // If we are using disk spanning, first create a temporary file
1287
    if (MultiDisk) then
1288
    begin
1289
      ret := RejoinMVArchive(TmpZipName);
1290
      if ret <> 0 then
1291
      begin
1292
        _DLL_Unload(self);
1293
        raise EZipMaster.CreateResDisp(ErrCode, true);
1294
      end;
1295
    end;
1296
    if not MultiDisk and AnsiSameText(EXT_EXE, ExtractFileExt(ZipFileName))
1297
      and not FileExists(ZipFileName) then
1298
    begin
1299
      { This is the first "add" operation following creation of a new
1300
        .EXE archive.  We need to add the SFX code now, before we add
1301
        the files. }
1302
      ret := NewSFXFile(ZipFileName);
1303
      if ret <> 0 then
1304
        raise EZipMaster.CreateResInt(AD_AutoSFXWrong, AbsErr(ret));
1305
    end;
1306
  except
1307
    on ews: EZipMaster do
1308
    begin
1309
      ShowExceptionError(ews);
1310
      exit;
1311
    end;
1312
    else
1313
      exit;
1314
  end;
1315
  Cancel := 0;
1316
 
1317
  try
1318
    try
1319
      CmdRecP := SetupZipCmd(TmpZipName);
1320
      fEventErr := ''; // added
1321
      { pass in a ptr to parms }
1322
      SuccessCnt := _DLL_Exec(self, CmdRecP, fDLLOperKey);
1323
      fEventErr := ''; // added
1324
      if MultiDisk then
1325
      begin
1326
        if (SuccessCnt < 0) or RecreateMVArchive(TmpZipName,
1327
             (CentralDir.Count > 0) and ((AddFreshen in AddOptions)
1328
              or (AddUpdate in AddOptions))) then
1329
          SysUtils.DeleteFile(TmpZipName);
1330
      end;
1331
    except
1332
      on ews: EZipMaster do
1333
      begin
1334
        if fEventErr <> '' then
1335
          ews.Message := ews.Message + fEventErr;
1336
        ShowExceptionError(ews);
1337
      end
1338
      else
1339
        ShowZipMessage(GE_FatalZip, '');
1340
    end;
1341
  finally
1342
    FSpecArgs.Clear;
1343
    FSpecArgsExcl.Clear;
1344
    FPipes.Clear;
1345
    DestroyDLLCmd(CmdRecP);
1346
  end; { end try finally }
1347
 
1348
  _DLL_Unload(self);
1349
  Cancel := 0;
1350
  // Update the Zip Directory by calling List method
1351
  // for spanned exe avoid swapping to last disk
1352
  if (SuccessCnt > 0) and not IsDetachedSFX(ZipFileName) then
1353
    List
1354
  else
1355
    CentralDir.Current := nil;
1356
end;
1357
 
1358
(* ? TZMDLLOpr.ExtExtract
1359
  *)
1360
procedure TZMDLLOpr.ExtExtract;
1361
var
1362
  CmdRecP: pDLLCommands;
1363
  DLLVers: Integer;
1364
  good: boolean;
1365
  OldPRC: Integer;
1366
  TmpBaseDir: String;
1367
  TmpS: String;
1368
  TmpZipName: String;
1369
begin
1370
  SuccessCnt := 0;
1371
  ClearErr;
1372
  OldPRC := PasswordReqCount;
1373
  DLLVers := 0;
1374
  TmpZipName := '';
1375
  CmdRecP := nil;
1376
  good := True;
1377
  Cancel := 0;
1378
  try
1379
    if (ZipFileName = '') then
1380
      raise EZipMaster.CreateResDisp(GE_NoZipSpecified, true);
1381
    if CentralDir.Count = 0 then
1382
      List; // try again
1383
    if CentralDir.Count = 0 then
1384
    begin
1385
      good := False; // stop from doing anything
1386
      if ErrCode = 0 then // only show once
1387
        raise EZipMaster.CreateResDisp(DS_FileOpen, true);
1388
    end;
1389
    Cancel := 0; // might have been set in List
1390
    if good then
1391
    begin
1392
      TmpBaseDir := '';
1393
      // expand and check ExtrBaseDir
1394
      if (ExtrBaseDir <> '') and not(ExtrTest in ExtrOptions) then
1395
      begin
1396
        TmpBaseDir := ExpandUNCFileName(DelimitPath(ExtrBaseDir, true));
1397
        if ExtrForceDirs in ExtrOptions then
1398
          ForceDirectory(TmpBaseDir);
1399
        if not DirExists(TmpBaseDir) then
1400
          raise EZipMaster.CreateResStr(EX_NoExtrDir, TmpBaseDir);
1401
      end;
1402
 
1403
      TmpZipName := ZipFileName;
1404
 
1405
      // We do a check if we need UnSpanning first, this depends on
1406
      // The number of the disk the EOC record was found on. ( provided by List() )
1407
      // If we have a spanned set consisting of only one disk we don't use ReadSpan().
1408
      if CentralDir.TotalDisks > 1 then
1409
      begin
1410
        if TempDir = '' then
1411
        begin
1412
          SetLength(TmpS, MAX_PATH + 2);
1413
          GetTempPath(MAX_PATH, PChar(TmpS));
1414
          TmpZipName := PChar(TmpS); // convert from NULL terminated
1415
          TmpS := '';
1416
        end;
1417
        TmpZipName := DelimitPath(TempDir, true);
1418
        good := ReadSpan(ZipFileName, TmpZipName, true) = 0;
1419
        // if we returned without an error, TmpZipName contains a real name.
1420
      end;
1421
    end; // if fUnzBusy then
1422
 
1423
    if good then
1424
      DLLVers := _DLL_Load(self);
1425
    if DLLVers > 0 then
1426
      try
1427
        GrabPipes;
1428
        CmdRecP := SetupUnzCmd(TmpZipName);
1429
        fEventErr := ''; // added
1430
        // We have to be carefull doing an unattended Extract when a password is needed
1431
        // for some file in the archive.
1432
        if Unattended and (Password = '') and not assigned
1433
          (Master.OnPasswordError) then
1434
        begin
1435
          PasswordReqCount := 0;
1436
          ReportMsg(EX_UnAttPassword, []);
1437
        end;
1438
        SuccessCnt := _DLL_Exec(self, CmdRecP, fDLLOperKey);
1439
      finally
1440
        _DLL_Unload(self);
1441
        FSpecArgs.Clear;
1442
        FPipes.Clear;
1443
        { If UnSpanned we still have this temporary file hanging around. }
1444
        if CentralDir.TotalDisks > 1 then
1445
          SysUtils.DeleteFile(TmpZipName);
1446
        DestroyDLLCmd(CmdRecP);
1447
 
1448
        if Unattended and (Password = '') and not assigned
1449
          (Master.OnPasswordError) then
1450
          PasswordReqCount := OldPRC;
1451
      end;
1452
  except
1453
    on ews: EZipMaster do
1454
    begin
1455
      if fEventErr <> '' then
1456
        ews.Message := ews.Message + fEventErr;
1457
      ShowExceptionError(ews);
1458
      SuccessCnt := 0;
1459
    end;
1460
  end;
1461
  { no need to call the List method; contents unchanged }
1462
end;
1463
 
1464
procedure TZMDLLOpr.Extract;
1465
begin
1466
  fAutoStream := nil;
1467
  ExtExtract;
1468
end;
1469
 
1470
(* ? TZMDLLOpr.ExtractFileToStream
1471
  1.73 15 July 2003 RA add check on FileName in FSpecArgs + return on busy
1472
  *)
1473
procedure TZMDLLOpr.ExtractFileToStream(const FileName: String);
1474
var
1475
  fn: String;
1476
begin
1477
  fn := Trim(FileName);
1478
  if (Length(FileName) = 0) and (FSpecArgs.Count > 0) then
1479
    fn := Trim(FSpecArgs[0]);
1480
  if (fn = '') or IsWild(fn) then
1481
  begin
1482
    if fn <> '' then
1483
      ShowZipMessage(AD_InvalidName, '')
1484
    else
1485
      ShowZipMessage(AD_NothingToZip, '');
1486
    exit;
1487
  end;
1488
  FSpecArgs.Clear();
1489
  FSpecArgs.Add('0:' + fn);
1490
  SuccessCnt := 0;
1491
  fAutoStream := ZipStream;
1492
  fAutoDate := 0;
1493
  fAutoAttr := 0;
1494
  ZipStream.Clear();
1495
  ExtExtract;
1496
  fAutoStream := nil;
1497
end;
1498
 
1499
(* ? TZMDLLOpr.ExtractStreamToStream
1500
  1.73 14 July 2003 RA initial SuccessCnt
1501
  *)
1502
procedure TZMDLLOpr.ExtractStreamToStream(InStream: TMemoryStream;
1503
  OutSize: Longword);
1504
var
1505
  crc: Cardinal;
1506
  Header: TZM_StreamHeader;
1507
  Method: TZMDeflates;
1508
  realsize: Int64;
1509
begin
1510
  SuccessCnt := 0;
1511
  ZipStream.Clear();
1512
  if not assigned(InStream) then
1513
  begin
1514
    ShowZipMessage(AZ_NothingToDo, '');
1515
    exit;
1516
  end;
1517
  if InStream = ZipStream then
1518
  begin
1519
    ShowZipMessage(AD_InIsOutStream, '');
1520
    exit;
1521
  end;
1522
  realsize := InStream.Size - SizeOf(TZM_StreamHeader);
1523
  if realsize > 0 then
1524
  begin
1525
    InStream.ReadBuffer(Header, SizeOf(TZM_StreamHeader));
1526
    case Header.Method of
1527
      METHOD_DEFLATED or TZMDeflateEncrypt: Method := zmDeflateEncrypt;
1528
      METHOD_DEFLATED: Method := zmDeflate;
1529
      METHOD_STORED: Method := zmStore;
1530
    else
1531
      begin
1532
        ShowZipMessage(DS_Unsupported, '');
1533
        ZipStream.size := 0;
1534
        Exit;
1535
      end;
1536
    end;
1537
    crc := Header.CRC;
1538
    Undeflate(ZipStream, InStream, realsize, Method, crc);
1539
    if SuccessCnt = 1 then
1540
    begin
1541
//      if crc <> crc0 then
1542
      if crc <> Header.CRC then
1543
      begin
1544
        ShowZipMessage(DS_BadCRC, '');
1545
        ZipStream.size := 0;
1546
      end;
1547
    end
1548
    else
1549
      ZipStream.size := 0;
1550
  end;
1551
end;
1552
 
1553
(* ? TZMWorker.GetAddPassword
1554
  1.76 25 May 2004 changed
1555
  1.76 10 May 2004 change loading strings
1556
  *)
1557
function TZMDLLOpr.GetAddPassword(var Response: TmsgDlgBtn): String;
1558
var
1559
  p1: String;
1560
  p2: String;
1561
begin
1562
  p2 := '';
1563
  if Unattended then
1564
    ShowZipMessage(PW_UnatAddPWMiss, '')
1565
  else
1566
  begin
1567
    Response := GetPassword(ZipLoadStr(PW_Caption), ZipLoadStr
1568
        (PW_MessageEnter), DHC_AddPwrd1, mbOkCancel, p1);
1569
    if (Response = mbOK) and (p1 <> '') then
1570
    begin
1571
      Response := GetPassword(ZipLoadStr(PW_Caption), ZipLoadStr
1572
          (PW_MessageConfirm), DHC_AddPWrd2, mbOkCancel, p2);
1573
      if (Response = mbOK) and (p2 <> '') then
1574
        if {Ansi}CompareStr(p1, p2) <> 0 then
1575
        begin
1576
          ShowZipMessage(GE_WrongPassword, '');
1577
          p2 := '';
1578
        end;
1579
    end;
1580
  end;
1581
  Result := p2;
1582
end;
1583
 
1584
function TZMDLLOpr.GetDLL_Build: Integer;
1585
begin
1586
  Result := _DLL_Build;
1587
end;
1588
 
1589
function TZMDLLOpr.GetDLL_Load: Boolean;
1590
begin
1591
  Result := _DLL_Loaded(self);
1592
{$IFDEF ZDEBUG}
1593
  Diag('DLL_Load = ' + IntToStr(Ord(Result)));
1594
{$ENDIF}
1595
end;
1596
 
1597
function TZMDLLOpr.GetDLL_Path: string;
1598
begin
1599
  Result := _DLL_Path;
1600
end;
1601
 
1602
function TZMDLLOpr.DLL_Version(Load: Boolean): string;
1603
begin
1604
  if Load then
1605
    _DLL_Load(self);
1606
  Result := VersStr(_DLL_Build, False);
1607
  if Load then
1608
    _DLL_Unload(self);
1609
end;
1610
 
1611
(* ? TZMWorker.GetExtrPassword
1612
  1.76 25 May 2004 changed
1613
  1.76 10 May 2004 change loading strings
1614
  Same as GetAddPassword, but does NOT verify
1615
  *)
1616
function TZMDLLOpr.GetExtrPassword(var Response: TmsgDlgBtn): String;
1617
begin
1618
  Result := '';
1619
  if Unattended then
1620
    ShowZipMessage(PW_UnatExtPWMiss, '')
1621
  else
1622
    Response := GetPassword(ZipLoadStr(PW_Caption), ZipLoadStr
1623
        (PW_MessageEnter), DHC_ExtrPwrd, [mbOK, mbCancel, mbAll], Result);
1624
end;
1625
 
1626
(* ? TZMWorker.GetPassword
1627
  1.76 25 May 2004 no external GlobalResult
1628
  *)
1629
function TZMDLLOpr.GetPassword(const DialogCaption, MsgTxt: String;
1630
  ctx: Integer; pwb: TmsgDlgButtons; var ResultStr: String): TmsgDlgBtn;
1631
var
1632
  GModalResult: TModalResult;
1633
  msg: String;
1634
begin
1635
  msg := MsgTxt;
1636
  ResultStr := '';
1637
  GModalResult := ZipMessageDialog(DialogCaption, msg, zmtPassword +
1638
      (ctx and MAX_WORD), pwb);
1639
  case GModalResult of
1640
    mrOk:
1641
      begin
1642
        ResultStr := msg;
1643
        Result := mbOK;
1644
      end;
1645
    mrCancel:
1646
      Result := mbCancel;
1647
    mrAll:
1648
      Result := mbNoToAll;
1649
  else
1650
    Result := mbAbort;
1651
  end;
1652
end;
1653
 
1654
function TZMDLLOpr.GetPassword(const DialogCaption, MsgTxt: String;
1655
  pwb: TmsgDlgButtons; var ResultStr: String): TmsgDlgBtn;
1656
begin
1657
  Result := GetPassword(DialogCaption, MsgTxt, DHC_Password, pwb, ResultStr);
1658
end;
1659
 
1660
procedure TZMDLLOpr.GrabPipes;
1661
var
1662
  i: Integer;
1663
  fn: String;
1664
  MasterPipes: TZMPipeListImp;
1665
begin
1666
  MasterPipes := Master.Pipes as TZMPipeListImp;
1667
  MasterPipes.AssignTo(Pipes);
1668
  //  Add names to start of FSpecArgs
1669
  if Pipes.Count > 0 then
1670
  begin
1671
    for I := 0 to Pipes.Count - 1 do
1672
    begin
1673
      fn := Pipes[I].FileName;
1674
      if (fn <> '') and IsInvalidIntName(fn) then
1675
        raise EZipMaster.CreateResDisp(AD_BadFileName, true);
1676
      while (fn <> '') and (fn[1] = '\') do
1677
        fn := Copy(fn, 2, MAX_PATH);
1678
      if fn = '' then
1679
        fn := '#stream' + IntToStr(I) + '#';
1680
      fn := IntToStr(I) + ':' + fn;
1681
      FSpecArgs.Insert(I, fn);
1682
    end;
1683
  end;
1684
end;
1685
 
1686
procedure TZMDLLOpr.Kill;
1687
begin
1688
  fIsDestructing := true; // stop callbacks
1689
  AbortDLL;
1690
  inherited;
1691
end;
1692
 
1693
procedure TZMDLLOpr.SetCB(const Value: TDZCallback);
1694
begin
1695
  if fCB <> Value then
1696
  begin
1697
    fCB := Value;
1698
  end;
1699
end;
1700
 
1701
procedure TZMDLLOpr.SetDLL_Load(const Value: Boolean);
1702
begin
1703
{$IFDEF ZDEBUG}
1704
  Diag('set DLL_Load to ' + IntToStr(Ord(Value)));
1705
{$ENDIF}
1706
  if Value <> fDidLoad then
1707
  begin
1708
    if Value then
1709
    begin
1710
      fDidLoad := _DLL_Load(self) > 0;
1711
    end
1712
    else
1713
    begin
1714
      _DLL_Unload(self);
1715
      fDidLoad := False;
1716
    end;
1717
{$IFDEF ZDEBUG}
1718
    Diag('changed DLL_Load to ' + IntToStr(Ord(Value)));
1719
{$ENDIF}
1720
  end;
1721
end;
1722
 
1723
procedure TZMDLLOpr.SetExtAddStoreSuffixes(const Value: String);
1724
var
1725
  c: Char;
1726
  i: Integer;
1727
  tempStr: String;
1728
begin
1729
  if Value <> '' then
1730
  begin
1731
    c := ':';
1732
    i := 1;
1733
    while i <= Length(Value) do
1734
    begin
1735
      c := Value[i];
1736
      if c <> '.' then
1737
        tempStr := tempStr + '.';
1738
      while (c <> ':') and (i <= Length(Value)) do
1739
      begin
1740
        c := Value[i];
1741
        if (c = ';') or (c = ':') or (c = ',') then
1742
          c := ':';
1743
        tempStr := tempStr + c;
1744
        Inc(i);
1745
      end;
1746
    end;
1747
    if c <> ':' then
1748
      tempStr := tempStr + ':';
1749
    fAddStoreSuffixes := fAddStoreSuffixes + [assEXT];
1750
    fExtAddStoreSuffixes := Lowercase(tempStr);
1751
  end
1752
  else
1753
  begin
1754
    fAddStoreSuffixes := fAddStoreSuffixes - [assEXT];
1755
    fExtAddStoreSuffixes := '';
1756
  end;
1757
end;
1758
 
1759
procedure TZMDLLOpr.SetPipes(const Value: TZMPipeListImp);
1760
begin
1761
//
1762
end;
1763
 
1764
function TZMDLLOpr.SetupUnzCmd(const Value: String): pDLLCommands;
1765
var
1766
  Opts: Cardinal;
1767
begin
1768
  Result := AllocDLLCommand(Value);
1769
  if Result <> nil then
1770
  begin
1771
    Opts := Result^.fOptions;
1772
    if ExtrNTFS in ExtrOptions then
1773
      Opts := Opts or DLL_OPT_NTFSStamps;
1774
    if ExtrDirNames in ExtrOptions then
1775
      Opts := Opts or DLL_OPT_Directories;
1776
    if ExtrOverWrite in ExtrOptions then
1777
      Opts := Opts or DLL_OPT_Overwrite;
1778
    if ExtrUpdate in ExtrOptions then
1779
      Opts := Opts or DLL_OPT_Update
1780
    else if ExtrFreshen in ExtrOptions then
1781
      Opts := Opts or DLL_OPT_Freshen;
1782
    { Update has precedence over freshen }
1783
 
1784
    if ExtrTest in ExtrOptions then
1785
      Opts := Opts or DLL_OPT_OpIsTest
1786
    else
1787
      Opts := Opts or DLL_OPT_OpIsUnz;
1788
 
1789
    Result^.fPwdReqCount := PasswordReqCount;
1790
    Result^.fOptions := Opts;
1791
    Result^.fCheck := DLLCOMMANDCHECK;
1792
  end;
1793
end;
1794
 
1795
function TZMDLLOpr.SetupZipCmd(const Value: String): pDLLCommands;
1796
var
1797
  Opts: Cardinal;
1798
begin
1799
  Result := AllocDLLCommand(Value);
1800
  if Result <> nil then
1801
  begin
1802
    Opts := Result^.fOptions;
1803
    Result^.fEncodedAs := 0; // how to interpret existing names
1804
    if Encoding = zeoOEM then
1805
      Result^.fEncodedAs := Ord(zeoOEM)
1806
    else if Encoding = zeoUTF8 then
1807
      Result^.fEncodedAs := Ord(zeoUTF8);
1808
    Result^.fEncodeAs := Ord(EncodeAs); // how to encode new names
1809
 
1810
    if AddArchiveOnly in AddOptions then
1811
      Opts := Opts or DLL_OPT_ArchiveFilesOnly;
1812
    if AddResetArchive in AddOptions then
1813
      Opts := Opts or DLL_OPT_ResetArchiveBit;
1814
 
1815
    if HowToDelete = htdAllowUndo then
1816
      Opts := Opts or DLL_OPT_HowToMove;
1817
    if AddVersion in AddOptions then
1818
      Opts := Opts or DLL_OPT_Versioning;
1819
    if AddVolume in AddOptions then
1820
      Opts := Opts or DLL_OPT_Volume;
1821
 
1822
    { if True, exclude files earlier than specified date }
1823
    { Date to include files after; only used if fDate=TRUE }
1824
    if AddFromDate in AddOptions then
1825
      Result^.fDate := DateTimeToFileDate(FromDate);
1826
    // Compression level (0 - 9, 0=none and 9=best)
1827
    Result^.fLevel := AddCompLevel;
1828
    if not(AddSafe in AddOptions) then
1829
      Opts := Opts or DLL_OPT_Grow;
1830
    { if True, Allow appending to a zip file (-g) }
1831
    if AddNTFS in AddOptions then
1832
      Opts := Opts or DLL_OPT_NTFSStamps;
1833
 
1834
    // distinguish bet. Add and Delete
1835
    Opts := Opts or DLL_OPT_OpIsZip;
1836
 
1837
    // make zipfile's timestamp same as newest file
1838
    if zwoZipTime in WriteOptions then
1839
      Opts := Opts or DLL_OPT_LatestTime;
1840
 
1841
    if AddMove in AddOptions then
1842
      Opts := Opts or DLL_OPT_Move; // dangerous, beware!
1843
 
1844
    if AddUpdate in AddOptions then
1845
      Opts := Opts or DLL_OPT_Update
1846
    else if AddFreshen in AddOptions then
1847
      Opts := Opts or DLL_OPT_Freshen;
1848
    // { Update has precedence over freshen }
1849
 
1850
    { DLL will prompt for password }
1851
    if AddEncrypt in AddOptions then
1852
      Opts := Opts or DLL_OPT_Encrypt;
1853
    { NOTE: if user wants recursion, then he probably also wants
1854
      AddDirNames, but we won't demand it. }
1855
    if AddRecurseDirs in AddOptions then
1856
      Opts := Opts or DLL_OPT_Recurse;
1857
    if AddHiddenFiles in AddOptions then
1858
      Opts := Opts or DLL_OPT_System;
1859
//    if not(AddSeparateDirs in AddOptions) then
1860
//      Opts := Opts or DLL_OPT_NoDirEntries;
1861
//    if AddNoSeparateDirs in AddOptions then
1862
    if not (AddEmptyDirs in AddOptions) then
1863
      Opts := Opts or DLL_OPT_NoDirEntries;
1864
    { don't store dirnames with filenames }
1865
    if not(AddDirNames in AddOptions) then
1866
      Opts := Opts or DLL_OPT_JunkDir;
1867
 
1868
    Result^.fOptions := Opts;
1869
    Result^.fCheck := DLLCOMMANDCHECK;
1870
  end;
1871
end;
1872
 
1873
procedure TZMDLLOpr.StartUp;
1874
begin
1875
  inherited StartUp;
1876
  fAddCompLevel := Master.AddCompLevel;
1877
  fFromDate := Master.AddFrom;
1878
  fAddStoreSuffixes := Master.AddStoreSuffixes;
1879
  ExtAddStoreSuffixes := Master.ExtAddStoreSuffixes;
1880
  fExtrBaseDir := Master.ExtrBaseDir;
1881
  fExtrOptions := Master.ExtrOptions;
1882
  fPassword := Master.Password;
1883
  fPasswordReqCount := Master.PasswordReqCount;
1884
  fRootDir := Master.RootDir;
1885
end;
1886
 
1887
procedure TZMDLLOpr.Undeflate(OutStream, InStream: TStream; Length: Int64; var
1888
    Method: tzMDeflates; var crc: Cardinal);
1889
var
1890
  Args: TZSSArgs;
1891
  CmdRecP: pDLLCommands;
1892
  i: Integer;
1893
  ncrypt: boolean;
1894
begin
1895
  SuccessCnt := 0;
1896
  ClearErr;
1897
  if not assigned(InStream) then
1898
  begin
1899
    ShowZipMessage(DS_NoInStream, '');
1900
    exit;
1901
  end;
1902
  if not assigned(OutStream) then
1903
  begin
1904
    ShowZipMessage(DS_NoOutStream, '');
1905
    exit;
1906
  end;
1907
  if InStream = ZipStream then
1908
  begin
1909
    ShowZipMessage(AD_InIsOutStream, '');
1910
    exit;
1911
  end;
1912
  ncrypt := (Method = zmStoreEncrypt) or (Method = zmDeflateEncrypt);
1913
  // We can not do an Unattended Add if we don't have a password.
1914
  if Unattended and ncrypt and (Password = '') then
1915
  begin
1916
    ShowZipMessage(EX_UnAttPassword, '');
1917
    exit;
1918
  end;
1919
  if Length < 0 then
1920
    Length := InStream.size;
1921
  CmdRecP := nil;
1922
  if (Method = zmDeflate) or (Method = zmDeflateEncrypt) then
1923
    Args.Method := METHOD_DEFLATED
1924
  else
1925
    Args.Method := METHOD_STORED;
1926
  if ncrypt then
1927
    Args.Method := Args.Method or TZMDeflateEncrypt;//1024;
1928
  Args.fSSInput := InStream;
1929
  Args.fSSOutput := OutStream;
1930
  Args.size := Length;
1931
  Args.crc := crc;
1932
  if _DLL_Load(self) <= 0 then
1933
  begin
1934
    ShowZipMessage(LD_NoDLL, DelZipDLL_Name);
1935
    exit;
1936
  end;
1937
  try
1938
//    fUnzBusy := true;
1939
    Cancel := 0;
1940
    CmdRecP := SetupUnzCmd('<UNDEFLATE>'); // do not localize
1941
    CmdRecP^.fSS := @Args;
1942
    fEventErr := ''; // added
1943
    { pass in a ptr to parms }
1944
    i := _DLL_Exec(self, CmdRecP, fDLLOperKey);
1945
  finally
1946
    _DLL_Unload(self);
1947
    DestroyDLLCmd(CmdRecP);
1948
  end;
1949
  if i = 1 then
1950
  begin // success
1951
    SuccessCnt := 1;
1952
    if Args.Method = METHOD_DEFLATED then
1953
      Method := zmDeflate
1954
    else
1955
      Method := zmStore;
1956
    crc := Args.crc;
1957
  end;
1958
end;
1959
 
1960
constructor TDZCallback.Create(theWorker: TZMWorker);
1961
begin
1962
  fWorker := theWorker;
1963
  PCB := nil;
1964
  fHeldData := nil;
1965
  fHoldSize := 0;
1966
end;
1967
 
1968
destructor TDZCallback.Destroy; // override;
1969
begin
1970
  if fHeldData <> nil then
1971
    FreeMem(fHeldData);
1972
  fHeldData := nil;
1973
end;
1974
 
1975
function TDZCallback.Assign(ZCallBackRec: PZCallBackStruct): Integer;
1976
begin
1977
  PCB := ZCallBackRec;
1978
  if PCB = nil then
1979
    Result := 1
1980
  else
1981
    Result := 0;
1982
end;
1983
 
1984
procedure TDZCallback.Clear;
1985
begin
1986
  if fHeldData <> nil then
1987
    FreeMem(fHeldData);
1988
  fHeldData := nil;
1989
  fHoldSize := 0;
1990
  PCB := nil; // ??
1991
end;
1992
 
1993
function TDZCallback.CopyData(dst: PByte; MaxSize: Integer): Boolean;
1994
var
1995
  sz: Integer;
1996
begin
1997
  Result := False;
1998
  sz := Arg1;
1999
  if sz > MaxSize then
2000
    sz := MaxSize;
2001
  if sz > 0 then
2002
  begin
2003
    move(PCB^.Msg2P^, dst^, sz);
2004
    Result := true;
2005
  end;
2006
end;
2007
 
2008
function TDZCallback.GetActionCode: Integer;
2009
begin
2010
  Result := PCB^.ActionCode;
2011
end;
2012
 
2013
function TDZCallback.GetArg1: Cardinal;
2014
begin
2015
  Result := PCB^.Arg1;
2016
end;
2017
 
2018
function TDZCallback.GetArg2: Cardinal;
2019
begin
2020
  Result := PCB^.Arg2;
2021
end;
2022
 
2023
function TDZCallback.GetArg3: Integer;
2024
begin
2025
  Result := PCB^.Arg3;
2026
end;
2027
 
2028
function TDZCallback.GetFile_Size: Int64;
2029
begin
2030
  Result := PCB^.File_Size;
2031
end;
2032
 
2033
function TDZCallback.GetIsZip: Boolean;
2034
begin
2035
  Result := PCB^.IsOperationZip;
2036
end;
2037
 
2038
function TDZCallback.GetMsg: TZMString;
2039
begin
2040
  Result := GetMsgStr(PCB^.MsgP);
2041
end;
2042
 
2043
function TDZCallback.GetMsg2: TZMString;
2044
begin
2045
  Result := GetMsgStr(PCB^.Msg2P);
2046
end;
2047
 
2048
function TDZCallback.GetMsgStr(const msg: PByte): TZMString;
2049
{$IFNDEF UNICODE}
2050
var
2051
  utemp: UTF8String;
2052
{$ENDIF}
2053
begin
2054
  Result := '';
2055
  if msg <> nil then
2056
  begin
2057
{$IFDEF UNICODE}
2058
    if PCB^.HaveWide <> 0 then
2059
      Result := PWideChar(msg)
2060
    else
2061
      Result := PUTF8ToWideStr(PAnsiChar(msg), -1);
2062
{$ELSE}
2063
    if fWorker.UseUtf8 then
2064
    begin
2065
      if PCB^.HaveWide <> 0 then
2066
        Result := PWideToUTF8(PWideChar(msg), -1)
2067
      else
2068
      begin
2069
        utemp := PAnsiChar(msg);
2070
        Result := StrToUTF8(utemp);
2071
      end;
2072
    end
2073
    else
2074
    begin
2075
      if PCB^.HaveWide <> 0 then
2076
        Result := PWideChar(msg) // will convert wide -> ansi
2077
      else
2078
        Result := PAnsiChar(msg);
2079
    end;
2080
{$ENDIF}
2081
  end;
2082
end;
2083
 
2084
function TDZCallback.GetOwner: TZMDLLOpr;
2085
begin
2086
  Result := TObject(PCB^.Caller) as TZMDLLOpr;
2087
end;
2088
 
2089
function TDZCallback.GetWritten: Int64;
2090
begin
2091
  Result := PCB^.Written;
2092
end;
2093
 
2094
function TDZCallback.HoldData(const src: PByte; size: Cardinal): PByte;
2095
var
2096
  len: Integer;
2097
  p: PByte;
2098
begin
2099
  if src = nil then
2100
  begin
2101
    // free buffer
2102
    FreeMem(fHeldData);
2103
    fHeldData := nil;
2104
    fHoldSize := 0;
2105
    Result := fHeldData;
2106
    exit;
2107
  end;
2108
  if fHeldData = nil then
2109
    fHoldSize := 0;
2110
  len := size + sizeof(Integer);
2111
  if (fHeldData = nil) or (len >= fHoldSize) then
2112
  begin
2113
    if fHeldData <> nil then
2114
      FreeMem(fHeldData);
2115
    fHeldData := nil;
2116
    len := (len or 511) + 1;  // increments of 512
2117
    GetMem(fHeldData, len);
2118
    fHoldSize := len;
2119
  end;
2120
  p := fHeldData;
2121
  if size > 0 then
2122
  begin
2123
    move(src^, fHeldData^, size);
2124
    Inc(p, size);
2125
  end;
2126
  PCardinal(p)^ := 0; // mark end
2127
  Result := fHeldData;
2128
end;
2129
 
2130
function TDZCallback.HoldString(const src: TZMString): PByte;
2131
var
2132
  len: Integer;
2133
begin
2134
  len := Length(src) * sizeof(Char);
2135
  if len > 0 then
2136
    Result := HoldData(PByte(PChar(src)), len)
2137
  else
2138
    Result := HoldData(PByte(@len), 0);  // avoid freeing hold area
2139
end;
2140
 
2141
procedure TDZCallback.SetArg1(const Value: Cardinal);
2142
begin
2143
  PCB^.Arg1 := Value;
2144
end;
2145
 
2146
procedure TDZCallback.SetArg2(const Value: Cardinal);
2147
begin
2148
  PCB^.Arg2 := Value;
2149
end;
2150
 
2151
procedure TDZCallback.SetArg3(const Value: Integer);
2152
begin
2153
  PCB^.Arg3 := Value;
2154
end;
2155
 
2156
procedure TDZCallback.SetComment(const AStr: AnsiString);
2157
begin
2158
  PCB^.HaveWide := 0;
2159
  PCB^.MsgP := HoldData(PByte(PAnsiChar(AStr)), Length(AStr));
2160
  PCB^.Arg1 := Cardinal(Length(AStr));
2161
end;
2162
 
2163
procedure TDZCallback.SetData(src: PByte; size: Integer);
2164
begin
2165
  if size > 2048 then
2166
    size := 2048;
2167
  PCB^.MsgP := HoldData(src, size);
2168
  PCB^.Arg1 := Cardinal(size);
2169
end;
2170
 
2171
procedure TDZCallback.SetFile_Size(const Value: Int64);
2172
begin
2173
  PCB^.File_Size := Value;
2174
end;
2175
 
2176
procedure TDZCallback.SetMsg(const Value: TZMString);
2177
begin
2178
{$IFDEF UNICODE}
2179
  PCB^.HaveWide := 1; // Unicode
2180
{$ELSE}
2181
  if fWorker.UseUtf8 and (ValidUTF8(Value, -1) > 0) then
2182
    PCB^.HaveWide := 2 // UTF8
2183
  else
2184
    PCB^.HaveWide := 0; // Ansi
2185
{$ENDIF}
2186
  PCB^.MsgP := HoldString(Value);
2187
end;
2188
 
2189
end.