1
by ximion
|
1
|
(* ***** BEGIN LICENSE BLOCK *****
|
2
|
* Version: MPL 1.1
|
3
|
*
|
4
|
* The contents of this file are subject to the Mozilla Public License Version
|
5
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
6
|
* the License. You may obtain a copy of the License at
|
7
|
* http://www.mozilla.org/MPL/
|
8
|
*
|
9
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
10
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
11
|
* for the specific language governing rights and limitations under the
|
12
|
* License.
|
13
|
*
|
14
|
* The Original Code is TurboPower Abbrevia
|
15
|
*
|
16
|
* The Initial Developer of the Original Code is
|
17
|
* TurboPower Software
|
18
|
*
|
19
|
* Portions created by the Initial Developer are Copyright (C) 1997-2002
|
20
|
* the Initial Developer. All Rights Reserved.
|
21
|
*
|
22
|
* Contributor(s):
|
23
|
*
|
24
|
* ***** END LICENSE BLOCK ***** *)
|
25
|
|
26
|
{*********************************************************}
|
27
|
{* ABBREVIA: AbFciFdi.pas 3.05 *}
|
28
|
{*********************************************************}
|
29
|
{* ABBREVIA: Cabinet DLL wrapper *}
|
30
|
{* Based on info from the FCI/FDI Library Description, *}
|
31
|
{* included in the Microsoft Cabinet SDK *}
|
32
|
{*********************************************************}
|
33
|
|
34
|
unit AbFciFdi;
|
35
|
|
36
|
{$mode delphi}
|
37
|
|
38
|
interface
|
39
|
|
40
|
uses
|
41
|
typesarchive, //!! MVC for BOOL
|
42
|
dynlibs, // loadlibrary
|
43
|
{$ifdef mswindows}
|
44
|
Windows,
|
45
|
{$endif}
|
46
|
SysUtils, Classes;
|
47
|
|
48
|
const
|
49
|
CabinetDLL = 'cabinet.dll';
|
50
|
cpuUnknown = -1;
|
51
|
cpu80286 = 0;
|
52
|
cpu80386 = 1;
|
53
|
cpuDefault = cpuUnknown;
|
54
|
|
55
|
|
56
|
type
|
57
|
{FDI errors}
|
58
|
FDIError =
|
59
|
(FDIError_None, FDIError_Cabinet_Not_Found,
|
60
|
FDIError_Not_A_Cabinet, FDIError_Unknown_Cabinet_Version,
|
61
|
FDIError_Corrupt_Cabinet, FDIError_Alloc_Fail,
|
62
|
FDIError_Bad_Compr_Type, FDIError_MDI_Fail,
|
63
|
FDIError_Target_File, FDIError_Reserve_Mismatch,
|
64
|
FDIError_Wrong_Cabinet, FDIError_User_Abort);
|
65
|
|
66
|
{FCI errors}
|
67
|
FCIError =
|
68
|
(FCIError_NONE, FCIError_Open_SRC,
|
69
|
FCIError_Read_SRC, FCIError_Alloc_Fail,
|
70
|
FCIError_Temp_File, FCIError_Bad_Compr_Type,
|
71
|
FCIError_Cab_File, FCIError_User_Abort,
|
72
|
FCIERRor_MCI_Fail);
|
73
|
|
74
|
{FDI notifications}
|
75
|
FDINotificationType =
|
76
|
(FDINT_Cabinet_Info, FDINT_Partial_File,
|
77
|
FDINT_Copy_File, FDINT_Close_File_Info,
|
78
|
FDINT_Next_Cabinet, FDINT_Enumerate);
|
79
|
|
80
|
{FDI/FCI error structure}
|
81
|
PCabErrorRecord = ^CabErrorRecord;
|
82
|
CabErrorRecord = record
|
83
|
ErrorCode : Integer;
|
84
|
ErrorType : Integer;
|
85
|
ErrorPresent : Boolean;
|
86
|
end;
|
87
|
|
88
|
{FDI cabinet information structure}
|
89
|
PFDICabInfo = ^FDICabInfo;
|
90
|
FDICabInfo = record
|
91
|
cbCabinet : Longint;
|
92
|
cFolders : Word;
|
93
|
cFiles : Word;
|
94
|
setID : Word;
|
95
|
iCabinet : Word;
|
96
|
fReserve : BOOL;
|
97
|
hasprev : BOOL;
|
98
|
hasnext : BOOL;
|
99
|
end;
|
100
|
|
101
|
{FCI cabinet information structure}
|
102
|
PFCICabInfo = ^FCICabInfo;
|
103
|
FCICabInfo = record
|
104
|
cb : Longint;
|
105
|
cbFolderThresh : Longint;
|
106
|
cbReserveCFHeader : Integer;
|
107
|
cbReserveCFFolder : Integer;
|
108
|
cbReserveCFData : Integer;
|
109
|
iCab : Integer;
|
110
|
iDisk : Integer;
|
111
|
fFailOnIncompressible : Integer;
|
112
|
setID : Word;
|
113
|
szDisk : array[0..255] of Char;
|
114
|
szCab : array[0..255] of Char;
|
115
|
szCabPath : array[0..255] of Char;
|
116
|
end;
|
117
|
|
118
|
{FDI notification structure}
|
119
|
PFDINotification = ^FDINotification;
|
120
|
FDINotification = record
|
121
|
cb : Longint;
|
122
|
psz1 : PChar;
|
123
|
psz2 : PChar;
|
124
|
psz3 : PChar;
|
125
|
pv : Pointer;
|
126
|
hf : Integer;
|
127
|
date : Word;
|
128
|
time : Word;
|
129
|
attribs : Word;
|
130
|
setID : Word;
|
131
|
iCabinet : Word;
|
132
|
iFolder : Word;
|
133
|
fdie : FDIERROR;
|
134
|
end;
|
135
|
|
136
|
{misc defines}
|
137
|
HFDI = Pointer;
|
138
|
HFCI = Pointer;
|
139
|
FARPROC = Pointer;
|
140
|
|
141
|
|
142
|
{== Cabinet DLL routine prototypes ==========================================}
|
143
|
type
|
144
|
TFDICreate =
|
145
|
function (pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose,
|
146
|
pfnseek : FARPROC; cpuType : Integer; pError : PCabErrorRecord) : HFDI;
|
147
|
cdecl;
|
148
|
{----------------------------------------------------------------------------}
|
149
|
TFDIIsCabinet =
|
150
|
function(hfdi : HFDI; hf : Integer; pfdici : PFDICabInfo) : Boolean;
|
151
|
cdecl;
|
152
|
{----------------------------------------------------------------------------}
|
153
|
TFDICopy =
|
154
|
function(hfdi : HFDI; pszCabinet, pszCabPath : PChar;
|
155
|
flags : Integer; pfnfdin, pfnfdid : FARPROC; Archive : Pointer) : Boolean;
|
156
|
cdecl;
|
157
|
{----------------------------------------------------------------------------}
|
158
|
TFDIDestroy =
|
159
|
function(hfdi : HFDI) : Boolean;
|
160
|
cdecl;
|
161
|
{----------------------------------------------------------------------------}
|
162
|
TFCICreate =
|
163
|
function(pError : PCabErrorRecord; pfnfcifp, pfnalloc, pfnfree,
|
164
|
pfnopen, pfnread, pfnwrite, pfnclose, pfnseek, pfndelete,
|
165
|
pfnfcigtf : FARPROC; pccab : PFCICabInfo; Archive : Pointer) : HFCI;
|
166
|
cdecl;
|
167
|
{----------------------------------------------------------------------------}
|
168
|
TFCIAddFile =
|
169
|
function(hfci : HFCI; pszFilePath, pszFileName : PChar;
|
170
|
fExecute : Boolean; pfnfcignc, pfnfcis, pfnfcigoi : FARPROC;
|
171
|
typeCompress : Word) : Boolean;
|
172
|
cdecl;
|
173
|
{----------------------------------------------------------------------------}
|
174
|
TFCIFlushCabinet =
|
175
|
function(hfci : HFCI; fGetNextCab : Boolean;
|
176
|
pfnfcignc, pfnfcis : FARPROC) : Boolean;
|
177
|
cdecl;
|
178
|
{----------------------------------------------------------------------------}
|
179
|
TFCIFlushFolder =
|
180
|
function(hfci : HFCI; pfnfcignc, pfnfcis : FARPROC) : Boolean;
|
181
|
cdecl;
|
182
|
{----------------------------------------------------------------------------}
|
183
|
TFCIDestroy =
|
184
|
function(hfci : HFCI) : Boolean;
|
185
|
cdecl;
|
186
|
|
187
|
|
188
|
{== DLL routine wrappers ====================================================}
|
189
|
function FDICreate(pfnalloc, pfnfree, pfnopen, pfnread,
|
190
|
pfnwrite, pfnclose, pfnseek : FARPROC;
|
191
|
cpuType : Integer; pError : PCabErrorRecord) : HFDI;
|
192
|
{returns an FDI context for opening an existing cabinet}
|
193
|
{ pfnalloc - heap allocation callback function }
|
194
|
{ pfnfree - heap deallocation callback function }
|
195
|
{ pfnopen - open file callback function }
|
196
|
{ pfnwrite - write file callback function }
|
197
|
{ pfnclose - close file callback function }
|
198
|
{ pfnseek - reposition file pointer callback function }
|
199
|
{ cpuType - -1: unknown, 0: 80286, 1: 80386 }
|
200
|
{ pError - pointer to error record }
|
201
|
{----------------------------------------------------------------------------}
|
202
|
function FDIIsCabinet(hfdi : HFDI; hf : Integer;
|
203
|
pfdici : PFDICabInfo) : Boolean;
|
204
|
{checks cabinet file for validity}
|
205
|
{ hfdi - FDI context }
|
206
|
{ hf - cabinet file handle }
|
207
|
{ pfdici - pointer to FDI cabinet info structure }
|
208
|
{----------------------------------------------------------------------------}
|
209
|
function FDICopy(hfdi : HFDI; pszCabinet, pszCabPath : PChar;
|
210
|
flags : Integer; pfnfdin, pfnfdid : FARPROC;
|
211
|
Archive : Pointer) : Boolean;
|
212
|
{enumerates every file in the cabinet. The callback function}
|
213
|
{should indicate whether or not to extract a given file}
|
214
|
{ hfdi - FDI context }
|
215
|
{ pszCabinet - cabinet file name }
|
216
|
{ pszCabPath - cabinet file path }
|
217
|
{ flags - currently not used }
|
218
|
{ pfnfdin - FDI notifaction callback function }
|
219
|
{ pfnfdid - decryption callback (currently not used)}
|
220
|
{ Archive - the calling TAbCabArchive instance }
|
221
|
{----------------------------------------------------------------------------}
|
222
|
function FDIDestroy(hfdi : HFDI) : Boolean;
|
223
|
{releases FDI context and frees resources}
|
224
|
{ hfdi - FDI context }
|
225
|
{----------------------------------------------------------------------------}
|
226
|
function FCICreate(pError : PCabErrorRecord;
|
227
|
pfnfcifp, pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose,
|
228
|
pfnseek, pfndelete, pfnfcigtf : FARPROC;
|
229
|
pccab : PFCICabInfo; Archive : Pointer) : HFCI;
|
230
|
{creates a new cabinet file and returns the FCI context}
|
231
|
{ pError - pointer to error record }
|
232
|
{ pfnfcifp - callback notification when file has been placed in cabinet }
|
233
|
{ pfnalloc - callback function to allocate memory }
|
234
|
{ pfnfree - callback function to free memory }
|
235
|
{ pfnopen - callback function to open a file }
|
236
|
{ pfnwrite - callback function to write to a file }
|
237
|
{ pfnclose - callback function to close a file }
|
238
|
{ pfnseek - callback function to reposition file pointer }
|
239
|
{ pfndelete - callback function to delete a file }
|
240
|
{ pfnfcigtf - callback function to obtain temp filename }
|
241
|
{ pccab - pointer to FCI cabinet infor structure }
|
242
|
{ Archive - the calling TAbCabArchive instance }
|
243
|
{----------------------------------------------------------------------------}
|
244
|
function FCIAddFile(hfci : HFCI; pszFilePath, pszFileName : PChar;
|
245
|
fExecute : Boolean; pfnfcignc, pfnfcis, pfnfcigoi : FARPROC;
|
246
|
typeCompress : Word) : Boolean;
|
247
|
{adds a file to the cabinet}
|
248
|
{ hfci - FCI context }
|
249
|
{ pszFilePath - full pathname of file being added }
|
250
|
{ pszFileName - just the file name }
|
251
|
{ fExecute - flag to indicate if file is executable }
|
252
|
{ pfnfcignc - callback function to obtain next cabinet info }
|
253
|
{ pfnfcis - callback function to relay progress }
|
254
|
{ pfnfcigoi - callback function to open file and get attributes }
|
255
|
{ typeCompress - compression type to use }
|
256
|
{----------------------------------------------------------------------------}
|
257
|
function FCIFlushCabinet(hfci : HFCI; fGetNextCab : Boolean;
|
258
|
pfnfcignc, pfnfcis : FARPROC) : Boolean;
|
259
|
{writes current cabinet file out to disk and optionally starts a new one}
|
260
|
{ hfci - FCI context }
|
261
|
{ fGetNextCab - flag indicating whether to start a new cabinet }
|
262
|
{ pfnfcignc - callback function to obtain next cabinet info }
|
263
|
{ pfnfcis - callback function to relay progress }
|
264
|
{----------------------------------------------------------------------------}
|
265
|
function FCIFlushFolder(hfci : HFCI;
|
266
|
pfnfcignc, pfnfcis : FARPROC) : Boolean;
|
267
|
{close current compression block and start a new one}
|
268
|
{ hfci - FCI context }
|
269
|
{ pfnfcignc - callback function to obtain next cabinet info }
|
270
|
{ pfnfcis - callback function to relay progress }
|
271
|
{----------------------------------------------------------------------------}
|
272
|
function FCIDestroy(hfci : HFCI) : Boolean;
|
273
|
{releases FCI context and frees resources}
|
274
|
{ hfdi - FDI context }
|
275
|
{----------------------------------------------------------------------------}
|
276
|
|
277
|
|
278
|
implementation
|
279
|
|
280
|
uses
|
281
|
AbExcept,
|
282
|
AbConst;
|
283
|
|
284
|
|
285
|
var
|
286
|
CabDLLLoaded : Boolean;
|
287
|
CabDLLHandle : THandle;
|
288
|
FDICreateProc : TFDICreate;
|
289
|
FDIIsCabinetProc : TFDIIsCabinet;
|
290
|
FDICopyProc : TFDICopy;
|
291
|
FDIDestroyProc : TFDIDestroy;
|
292
|
FCICreateProc : TFCICreate;
|
293
|
FCIAddFileProc : TFCIAddFile;
|
294
|
FCIFlushCabinetProc : TFCIFlushCabinet;
|
295
|
FCIFlushFolderProc : TFCIFlushFolder;
|
296
|
FCIDestroyProc : TFCIDestroy;
|
297
|
|
298
|
|
299
|
{============================================================================}
|
300
|
procedure LoadCabinetDLL;
|
301
|
begin
|
302
|
if CabDllLoaded then
|
303
|
Exit;
|
304
|
// CabDllHandle := LoadLibrary(CabinetDLL);
|
305
|
if (CabDllHandle = 0) then
|
306
|
raise EAbNoCabinetDLL.Create;
|
307
|
{$ifdef MSWINDOWS}
|
308
|
@FDICreateProc := GetProcAddress(CabDllHandle, 'FDICreate');
|
309
|
@FDIIsCabinetProc := GetProcAddress(CabDllHandle, 'FDIIsCabinet');
|
310
|
@FDICopyProc := GetProcAddress(CabDllHandle, 'FDICopy');
|
311
|
@FDIDestroyProc := GetProcAddress(CabDllHandle, 'FDIDestroy');
|
312
|
@FCICreateProc := GetProcAddress(CabDllHandle, 'FCICreate');
|
313
|
@FCIAddFileProc := GetProcAddress(CabDllHandle, 'FCIAddFile');
|
314
|
@FCIFlushCabinetProc := GetProcAddress(CabDllHandle, 'FCIFlushCabinet');
|
315
|
@FCIFlushFolderProc := GetProcAddress(CabDllHandle, 'FCIFlushFolder');
|
316
|
@FCIDestroyProc := GetProcAddress(CabDllHandle, 'FCIDestroy');
|
317
|
CabDllLoaded := True;
|
318
|
{$endif}
|
319
|
end;
|
320
|
{----------------------------------------------------------------------------}
|
321
|
function FDICreate(pfnalloc, pfnfree, pfnopen, pfnread,
|
322
|
pfnwrite, pfnclose, pfnseek : FARPROC;
|
323
|
cpuType : Integer; pError : PCabErrorRecord) : HFDI;
|
324
|
begin
|
325
|
LoadCabinetDLL;
|
326
|
if Assigned(FDICreateProc) then
|
327
|
Result := FDICreateProc(pfnalloc, pfnfree, pfnopen, pfnread,
|
328
|
pfnwrite, pfnclose, pfnseek, cpuType, pError)
|
329
|
else
|
330
|
Result := nil;
|
331
|
end;
|
332
|
{----------------------------------------------------------------------------}
|
333
|
function FDIIsCabinet(hfdi : HFDI; hf : Integer;
|
334
|
pfdici : PFDICabInfo) : Boolean;
|
335
|
begin
|
336
|
LoadCabinetDLL;
|
337
|
if Assigned(FDIIsCabinetProc) then
|
338
|
Result := FDIIsCabinetProc(hfdi, hf, pfdici)
|
339
|
else
|
340
|
Result := False;
|
341
|
end;
|
342
|
{----------------------------------------------------------------------------}
|
343
|
function FDICopy(hfdi : HFDI; pszCabinet, pszCabPath : PChar;
|
344
|
flags : Integer; pfnfdin, pfnfdid : FARPROC;
|
345
|
Archive : Pointer) : Boolean;
|
346
|
begin
|
347
|
LoadCabinetDLL;
|
348
|
if Assigned(FDICopyProc) then
|
349
|
Result := FDICopyProc(hfdi, pszCabinet, pszCabPath, flags,
|
350
|
pfnfdin, pfnfdid, Archive)
|
351
|
else
|
352
|
Result := False;
|
353
|
end;
|
354
|
{----------------------------------------------------------------------------}
|
355
|
function FDIDestroy(hfdi : HFDI) : Boolean;
|
356
|
begin
|
357
|
LoadCabinetDLL;
|
358
|
if Assigned(FDIDestroyProc) then
|
359
|
Result := FDIDestroyProc(hfdi)
|
360
|
else
|
361
|
Result := False;
|
362
|
end;
|
363
|
{----------------------------------------------------------------------------}
|
364
|
function FCICreate(pError : PCabErrorRecord;
|
365
|
pfnfcifp, pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose,
|
366
|
pfnseek, pfndelete, pfnfcigtf : FARPROC;
|
367
|
pccab : PFCICabInfo; Archive : Pointer) : HFCI;
|
368
|
begin
|
369
|
LoadCabinetDLL;
|
370
|
if Assigned(FCICreateProc) then
|
371
|
Result := FCICreateProc(pError, pfnfcifp, pfnalloc, pfnfree, pfnopen,
|
372
|
pfnread, pfnwrite, pfnclose, pfnseek, pfndelete, pfnfcigtf,
|
373
|
pccab, Archive)
|
374
|
else
|
375
|
Result := nil;
|
376
|
end;
|
377
|
{----------------------------------------------------------------------------}
|
378
|
function FCIAddFile(hfci : HFCI; pszFilePath, pszFileName : PChar;
|
379
|
fExecute : Boolean; pfnfcignc, pfnfcis, pfnfcigoi : FARPROC;
|
380
|
typeCompress : Word) : Boolean;
|
381
|
begin
|
382
|
LoadCabinetDLL;
|
383
|
if Assigned(FCIAddFileProc) then
|
384
|
Result := FCIAddFileProc(hfci, pszFilePath, pszFileName,
|
385
|
fExecute, pfnfcignc, pfnfcis, pfnfcigoi, typeCompress)
|
386
|
else
|
387
|
Result := False;
|
388
|
end;
|
389
|
{----------------------------------------------------------------------------}
|
390
|
function FCIFlushCabinet(hfci : HFCI; fGetNextCab : Boolean;
|
391
|
pfnfcignc, pfnfcis : FARPROC) : Boolean;
|
392
|
begin
|
393
|
LoadCabinetDLL;
|
394
|
if Assigned(FCIFlushCabinetProc) then
|
395
|
Result := FCIFlushCabinetProc(hfci, fGetNextCab, pfnfcignc, pfnfcis)
|
396
|
else
|
397
|
Result := False;
|
398
|
end;
|
399
|
{----------------------------------------------------------------------------}
|
400
|
function FCIFlushFolder(hfci : HFCI;
|
401
|
pfnfcignc, pfnfcis : FARPROC) : Boolean;
|
402
|
begin
|
403
|
LoadCabinetDLL;
|
404
|
if Assigned(FCIFlushFolderProc) then
|
405
|
Result := FCIFlushFolderProc(hfci, pfnfcignc, pfnfcis)
|
406
|
else
|
407
|
Result := False;
|
408
|
end;
|
409
|
{----------------------------------------------------------------------------}
|
410
|
function FCIDestroy(hfci : HFCI) : Boolean;
|
411
|
begin
|
412
|
LoadCabinetDLL;
|
413
|
if Assigned(FCIDestroyProc) then
|
414
|
Result := FCIDestroyProc(hfci)
|
415
|
else
|
416
|
Result := False;
|
417
|
end;
|
418
|
{----------------------------------------------------------------------------}
|
419
|
initialization
|
420
|
CabDllLoaded := False;
|
421
|
|
422
|
end.
|