415 lines
15 KiB
ObjectPascal
415 lines
15 KiB
ObjectPascal
(* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is TurboPower Abbrevia
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* TurboPower Software
|
|
*
|
|
* Portions created by the Initial Developer are Copyright (C) 1997-2002
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* ***** END LICENSE BLOCK ***** *)
|
|
|
|
{*********************************************************}
|
|
{* ABBREVIA: AbFciFdi.pas *}
|
|
{*********************************************************}
|
|
{* ABBREVIA: Cabinet DLL wrapper *}
|
|
{* Based on info from the FCI/FDI Library Description, *}
|
|
{* included in the Microsoft Cabinet SDK *}
|
|
{*********************************************************}
|
|
|
|
unit AbFciFdi;
|
|
|
|
{$I AbDefine.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, AbUtils;
|
|
|
|
const
|
|
CabinetDLL = 'cabinet.dll';
|
|
cpuUnknown = -1;
|
|
cpu80286 = 0;
|
|
cpu80386 = 1;
|
|
cpuDefault = cpuUnknown;
|
|
|
|
|
|
type
|
|
{FDI errors}
|
|
FDIError =
|
|
(FDIError_None, FDIError_Cabinet_Not_Found,
|
|
FDIError_Not_A_Cabinet, FDIError_Unknown_Cabinet_Version,
|
|
FDIError_Corrupt_Cabinet, FDIError_Alloc_Fail,
|
|
FDIError_Bad_Compr_Type, FDIError_MDI_Fail,
|
|
FDIError_Target_File, FDIError_Reserve_Mismatch,
|
|
FDIError_Wrong_Cabinet, FDIError_User_Abort);
|
|
|
|
{FCI errors}
|
|
FCIError =
|
|
(FCIError_NONE, FCIError_Open_SRC,
|
|
FCIError_Read_SRC, FCIError_Alloc_Fail,
|
|
FCIError_Temp_File, FCIError_Bad_Compr_Type,
|
|
FCIError_Cab_File, FCIError_User_Abort,
|
|
FCIERRor_MCI_Fail);
|
|
|
|
{FDI notifications}
|
|
FDINotificationType =
|
|
(FDINT_Cabinet_Info, FDINT_Partial_File,
|
|
FDINT_Copy_File, FDINT_Close_File_Info,
|
|
FDINT_Next_Cabinet, FDINT_Enumerate);
|
|
|
|
{FDI/FCI error structure}
|
|
PCabErrorRecord = ^CabErrorRecord;
|
|
CabErrorRecord = record
|
|
ErrorCode : Integer;
|
|
ErrorType : Integer;
|
|
ErrorPresent : BOOL;
|
|
end;
|
|
|
|
{FDI cabinet information structure}
|
|
PFDICabInfo = ^FDICabInfo;
|
|
FDICabInfo = record
|
|
cbCabinet : Longint;
|
|
cFolders : Word;
|
|
cFiles : Word;
|
|
setID : Word;
|
|
iCabinet : Word;
|
|
fReserve : BOOL;
|
|
hasprev : BOOL;
|
|
hasnext : BOOL;
|
|
end;
|
|
|
|
{FCI cabinet information structure}
|
|
PFCICabInfo = ^FCICabInfo;
|
|
FCICabInfo = record
|
|
cb : Longint;
|
|
cbFolderThresh : Longint;
|
|
cbReserveCFHeader : Integer;
|
|
cbReserveCFFolder : Integer;
|
|
cbReserveCFData : Integer;
|
|
iCab : Integer;
|
|
iDisk : Integer;
|
|
fFailOnIncompressible : Integer;
|
|
setID : Word;
|
|
szDisk : array[0..255] of AnsiChar;
|
|
szCab : array[0..255] of AnsiChar;
|
|
szCabPath : array[0..255] of AnsiChar;
|
|
end;
|
|
|
|
{FDI notification structure}
|
|
PFDINotification = ^FDINotification;
|
|
FDINotification = record
|
|
cb : Longint;
|
|
psz1 : PAnsiChar;
|
|
psz2 : PAnsiChar;
|
|
psz3 : PAnsiChar;
|
|
pv : Pointer;
|
|
hf : PtrInt;
|
|
date : Word;
|
|
time : Word;
|
|
attribs : Word;
|
|
setID : Word;
|
|
iCabinet : Word;
|
|
iFolder : Word;
|
|
fdie : FDIERROR;
|
|
end;
|
|
|
|
{misc defines}
|
|
HFDI = Pointer;
|
|
HFCI = Pointer;
|
|
FARPROC = Pointer;
|
|
|
|
|
|
{== Cabinet DLL routine prototypes ==========================================}
|
|
type
|
|
TFDICreate =
|
|
function (pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose,
|
|
pfnseek : FARPROC; cpuType : Integer; pError : PCabErrorRecord) : HFDI;
|
|
cdecl;
|
|
{----------------------------------------------------------------------------}
|
|
TFDIIsCabinet =
|
|
function(hfdi : HFDI; hf : PtrInt; pfdici : PFDICabInfo) : BOOL;
|
|
cdecl;
|
|
{----------------------------------------------------------------------------}
|
|
TFDICopy =
|
|
function(hfdi : HFDI; pszCabinet, pszCabPath : PAnsiChar;
|
|
flags : Integer; pfnfdin, pfnfdid : FARPROC; Archive : Pointer) : BOOL;
|
|
cdecl;
|
|
{----------------------------------------------------------------------------}
|
|
TFDIDestroy =
|
|
function(hfdi : HFDI) : BOOL;
|
|
cdecl;
|
|
{----------------------------------------------------------------------------}
|
|
TFCICreate =
|
|
function(pError : PCabErrorRecord; pfnfcifp, pfnalloc, pfnfree,
|
|
pfnopen, pfnread, pfnwrite, pfnclose, pfnseek, pfndelete,
|
|
pfnfcigtf : FARPROC; pccab : PFCICabInfo; Archive : Pointer) : HFCI;
|
|
cdecl;
|
|
{----------------------------------------------------------------------------}
|
|
TFCIAddFile =
|
|
function(hfci : HFCI; pszFilePath, pszFileName : PAnsiChar;
|
|
fExecute : BOOL; pfnfcignc, pfnfcis, pfnfcigoi : FARPROC;
|
|
typeCompress : Word) : BOOL;
|
|
cdecl;
|
|
{----------------------------------------------------------------------------}
|
|
TFCIFlushCabinet =
|
|
function(hfci : HFCI; fGetNextCab : BOOL;
|
|
pfnfcignc, pfnfcis : FARPROC) : BOOL;
|
|
cdecl;
|
|
{----------------------------------------------------------------------------}
|
|
TFCIFlushFolder =
|
|
function(hfci : HFCI; pfnfcignc, pfnfcis : FARPROC) : BOOL;
|
|
cdecl;
|
|
{----------------------------------------------------------------------------}
|
|
TFCIDestroy =
|
|
function(hfci : HFCI) : BOOL;
|
|
cdecl;
|
|
|
|
|
|
{== DLL routine wrappers ====================================================}
|
|
function FDICreate(pfnalloc, pfnfree, pfnopen, pfnread,
|
|
pfnwrite, pfnclose, pfnseek : FARPROC;
|
|
cpuType : Integer; pError : PCabErrorRecord) : HFDI;
|
|
{returns an FDI context for opening an existing cabinet}
|
|
{ pfnalloc - heap allocation callback function }
|
|
{ pfnfree - heap deallocation callback function }
|
|
{ pfnopen - open file callback function }
|
|
{ pfnwrite - write file callback function }
|
|
{ pfnclose - close file callback function }
|
|
{ pfnseek - reposition file pointer callback function }
|
|
{ cpuType - -1: unknown, 0: 80286, 1: 80386 }
|
|
{ pError - pointer to error record }
|
|
{----------------------------------------------------------------------------}
|
|
function FDIIsCabinet(hfdi : HFDI; hf : PtrInt;
|
|
pfdici : PFDICabInfo) : BOOL;
|
|
{checks cabinet file for validity}
|
|
{ hfdi - FDI context }
|
|
{ hf - cabinet file handle }
|
|
{ pfdici - pointer to FDI cabinet info structure }
|
|
{----------------------------------------------------------------------------}
|
|
function FDICopy(hfdi : HFDI; pszCabinet, pszCabPath : PAnsiChar;
|
|
flags : Integer; pfnfdin, pfnfdid : FARPROC;
|
|
Archive : Pointer) : BOOL;
|
|
{enumerates every file in the cabinet. The callback function }
|
|
{should indicate whether or not to extract a given file}
|
|
{ hfdi - FDI context }
|
|
{ pszCabinet - cabinet file name }
|
|
{ pszCabPath - cabinet file path }
|
|
{ flags - currently not used }
|
|
{ pfnfdin - FDI notifaction callback function }
|
|
{ pfnfdid - decryption callback (currently not used)}
|
|
{ Archive - the calling TAbCabArchive instance }
|
|
{----------------------------------------------------------------------------}
|
|
function FDIDestroy(hfdi : HFDI) : BOOL;
|
|
{releases FDI context and frees resources}
|
|
{ hfdi - FDI context }
|
|
{----------------------------------------------------------------------------}
|
|
function FCICreate(pError : PCabErrorRecord;
|
|
pfnfcifp, pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose,
|
|
pfnseek, pfndelete, pfnfcigtf : FARPROC;
|
|
pccab : PFCICabInfo; Archive : Pointer) : HFCI;
|
|
{creates a new cabinet file and returns the FCI context}
|
|
{ pError - pointer to error record }
|
|
{ pfnfcifp - callback notification when file has been placed in cabinet }
|
|
{ pfnalloc - callback function to allocate memory }
|
|
{ pfnfree - callback function to free memory }
|
|
{ pfnopen - callback function to open a file }
|
|
{ pfnwrite - callback function to write to a file }
|
|
{ pfnclose - callback function to close a file }
|
|
{ pfnseek - callback function to reposition file pointer }
|
|
{ pfndelete - callback function to delete a file }
|
|
{ pfnfcigtf - callback function to obtain temp filename }
|
|
{ pccab - pointer to FCI cabinet infor structure }
|
|
{ Archive - the calling TAbCabArchive instance }
|
|
{----------------------------------------------------------------------------}
|
|
function FCIAddFile(hfci : HFCI; pszFilePath, pszFileName : PAnsiChar;
|
|
fExecute : BOOL; pfnfcignc, pfnfcis, pfnfcigoi : FARPROC;
|
|
typeCompress : Word) : BOOL;
|
|
{adds a file to the cabinet}
|
|
{ hfci - FCI context }
|
|
{ pszFilePath - full pathname of file being added }
|
|
{ pszFileName - just the file name }
|
|
{ fExecute - flag to indicate if file is executable }
|
|
{ pfnfcignc - callback function to obtain next cabinet info }
|
|
{ pfnfcis - callback function to relay progress }
|
|
{ pfnfcigoi - callback function to open file and get attributes }
|
|
{ typeCompress - compression type to use }
|
|
{----------------------------------------------------------------------------}
|
|
function FCIFlushCabinet(hfci : HFCI; fGetNextCab : BOOL;
|
|
pfnfcignc, pfnfcis : FARPROC) : BOOL;
|
|
{writes current cabinet file out to disk and optionally starts a new one}
|
|
{ hfci - FCI context }
|
|
{ fGetNextCab - flag indicating whether to start a new cabinet }
|
|
{ pfnfcignc - callback function to obtain next cabinet info }
|
|
{ pfnfcis - callback function to relay progress }
|
|
{----------------------------------------------------------------------------}
|
|
function FCIFlushFolder(hfci : HFCI;
|
|
pfnfcignc, pfnfcis : FARPROC) : BOOL;
|
|
{close current compression block and start a new one}
|
|
{ hfci - FCI context }
|
|
{ pfnfcignc - callback function to obtain next cabinet info }
|
|
{ pfnfcis - callback function to relay progress }
|
|
{----------------------------------------------------------------------------}
|
|
function FCIDestroy(hfci : HFCI) : BOOL;
|
|
{releases FCI context and frees resources}
|
|
{ hfdi - FDI context }
|
|
{----------------------------------------------------------------------------}
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
AbExcept;
|
|
|
|
|
|
var
|
|
CabDLLLoaded : Boolean;
|
|
CabDLLHandle : THandle;
|
|
FDICreateProc : TFDICreate;
|
|
FDIIsCabinetProc : TFDIIsCabinet;
|
|
FDICopyProc : TFDICopy;
|
|
FDIDestroyProc : TFDIDestroy;
|
|
FCICreateProc : TFCICreate;
|
|
FCIAddFileProc : TFCIAddFile;
|
|
FCIFlushCabinetProc : TFCIFlushCabinet;
|
|
FCIFlushFolderProc : TFCIFlushFolder;
|
|
FCIDestroyProc : TFCIDestroy;
|
|
|
|
|
|
{============================================================================}
|
|
procedure LoadCabinetDLL;
|
|
begin
|
|
if CabDllLoaded then
|
|
Exit;
|
|
CabDllHandle := LoadLibrary(CabinetDLL);
|
|
if (CabDllHandle = 0) then
|
|
raise EAbNoCabinetDLL.Create;
|
|
@FDICreateProc := GetProcAddress(CabDllHandle, 'FDICreate');
|
|
@FDIIsCabinetProc := GetProcAddress(CabDllHandle, 'FDIIsCabinet');
|
|
@FDICopyProc := GetProcAddress(CabDllHandle, 'FDICopy');
|
|
@FDIDestroyProc := GetProcAddress(CabDllHandle, 'FDIDestroy');
|
|
@FCICreateProc := GetProcAddress(CabDllHandle, 'FCICreate');
|
|
@FCIAddFileProc := GetProcAddress(CabDllHandle, 'FCIAddFile');
|
|
@FCIFlushCabinetProc := GetProcAddress(CabDllHandle, 'FCIFlushCabinet');
|
|
@FCIFlushFolderProc := GetProcAddress(CabDllHandle, 'FCIFlushFolder');
|
|
@FCIDestroyProc := GetProcAddress(CabDllHandle, 'FCIDestroy');
|
|
CabDllLoaded := True;
|
|
end;
|
|
{----------------------------------------------------------------------------}
|
|
function FDICreate(pfnalloc, pfnfree, pfnopen, pfnread,
|
|
pfnwrite, pfnclose, pfnseek : FARPROC;
|
|
cpuType : Integer; pError : PCabErrorRecord) : HFDI;
|
|
begin
|
|
LoadCabinetDLL;
|
|
if Assigned(FDICreateProc) then
|
|
Result := FDICreateProc(pfnalloc, pfnfree, pfnopen, pfnread,
|
|
pfnwrite, pfnclose, pfnseek, cpuType, pError)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
{----------------------------------------------------------------------------}
|
|
function FDIIsCabinet(hfdi : HFDI; hf : PtrInt;
|
|
pfdici : PFDICabInfo) : BOOL;
|
|
begin
|
|
LoadCabinetDLL;
|
|
if Assigned(FDIIsCabinetProc) then
|
|
Result := FDIIsCabinetProc(hfdi, hf, pfdici)
|
|
else
|
|
Result := False;
|
|
end;
|
|
{----------------------------------------------------------------------------}
|
|
function FDICopy(hfdi : HFDI; pszCabinet, pszCabPath : PAnsiChar;
|
|
flags : Integer; pfnfdin, pfnfdid : FARPROC;
|
|
Archive : Pointer) : BOOL;
|
|
begin
|
|
LoadCabinetDLL;
|
|
if Assigned(FDICopyProc) then
|
|
Result := FDICopyProc(hfdi, pszCabinet, pszCabPath, flags,
|
|
pfnfdin, pfnfdid, Archive)
|
|
else
|
|
Result := False;
|
|
end;
|
|
{----------------------------------------------------------------------------}
|
|
function FDIDestroy(hfdi : HFDI) : BOOL;
|
|
begin
|
|
LoadCabinetDLL;
|
|
if Assigned(FDIDestroyProc) then
|
|
Result := FDIDestroyProc(hfdi)
|
|
else
|
|
Result := False;
|
|
end;
|
|
{----------------------------------------------------------------------------}
|
|
function FCICreate(pError : PCabErrorRecord;
|
|
pfnfcifp, pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose,
|
|
pfnseek, pfndelete, pfnfcigtf : FARPROC;
|
|
pccab : PFCICabInfo; Archive : Pointer) : HFCI;
|
|
begin
|
|
LoadCabinetDLL;
|
|
if Assigned(FCICreateProc) then
|
|
Result := FCICreateProc(pError, pfnfcifp, pfnalloc, pfnfree, pfnopen,
|
|
pfnread, pfnwrite, pfnclose, pfnseek, pfndelete, pfnfcigtf,
|
|
pccab, Archive)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
{----------------------------------------------------------------------------}
|
|
function FCIAddFile(hfci : HFCI; pszFilePath, pszFileName : PAnsiChar;
|
|
fExecute : BOOL; pfnfcignc, pfnfcis, pfnfcigoi : FARPROC;
|
|
typeCompress : Word) : BOOL;
|
|
begin
|
|
LoadCabinetDLL;
|
|
if Assigned(FCIAddFileProc) then
|
|
Result := FCIAddFileProc(hfci, pszFilePath, pszFileName,
|
|
fExecute, pfnfcignc, pfnfcis, pfnfcigoi, typeCompress)
|
|
else
|
|
Result := False;
|
|
end;
|
|
{----------------------------------------------------------------------------}
|
|
function FCIFlushCabinet(hfci : HFCI; fGetNextCab : BOOL;
|
|
pfnfcignc, pfnfcis : FARPROC) : BOOL;
|
|
begin
|
|
LoadCabinetDLL;
|
|
if Assigned(FCIFlushCabinetProc) then
|
|
Result := FCIFlushCabinetProc(hfci, fGetNextCab, pfnfcignc, pfnfcis)
|
|
else
|
|
Result := False;
|
|
end;
|
|
{----------------------------------------------------------------------------}
|
|
function FCIFlushFolder(hfci : HFCI;
|
|
pfnfcignc, pfnfcis : FARPROC) : BOOL;
|
|
begin
|
|
LoadCabinetDLL;
|
|
if Assigned(FCIFlushFolderProc) then
|
|
Result := FCIFlushFolderProc(hfci, pfnfcignc, pfnfcis)
|
|
else
|
|
Result := False;
|
|
end;
|
|
{----------------------------------------------------------------------------}
|
|
function FCIDestroy(hfci : HFCI) : BOOL;
|
|
begin
|
|
LoadCabinetDLL;
|
|
if Assigned(FCIDestroyProc) then
|
|
Result := FCIDestroyProc(hfci)
|
|
else
|
|
Result := False;
|
|
end;
|
|
{----------------------------------------------------------------------------}
|
|
initialization
|
|
CabDllLoaded := False;
|
|
|
|
end.
|