{
CHIEFLZ UNIT/DLL, by Dr A Olowofoyeku (the African Chief);
internet: [[Email Removed]]
http://ourworld.compuserve.com/homepages/African_Chief/chief.htm
Version 1.00.
USES the original LZSSUNIT source, as amended by the Chief,
and Chris J Rankin. Ported to Win32 (Delphi 2.0) by Chris Rankin.
// -----------------------------------------------------------//
* 16-bit ASM functions converted to 32-bit ASM by Chris J Rankin
* Win32 (Delphi 2.0) code: added by Chris J Rankin
Package assembled together: 5th September 1996.
The routines in this package are already being used in some famous
programs!
}
{----------------------------------------------------------------------}
{to compile to a DLL in Delphi you need to rename this with the
extension .DPR}
{$I LZDefine.inc} {// defines various things, including "aDLL" //}
{$ifDef aDLL}
Library ChiefLZ;
Uses
{$ifdef Win32}
ShareMem, // Because the library exports functions that have
// long-string results/parameters, we need to use
// the ShareMem unit. All apps that use this library
// *must also use ShareMem* - Put DelphiMM.dll on the
// Path too ...
Windows,
LZSS32,
LZ_Const,
LZ_DLL,
{$else Win32}
LZSS16,
{$ifdef Windows}
{$ifdef DPMI}
WinAPI,
{$else DPMI}
WinProcs,
{$endif DPMI}
{$endif Windows}
{$endif Win32}
{$ifDef Delphi}
SysUtils,
{$else Delphi}
WinDos,
Strings,
{$endif Delphi}
ChfTypes,
ChfUtils;
{$else aDLL}
Unit ChiefLZ;
{$endif aDLL}
{------------------------------------------------------------}
{$ifNDef aDLL}
interface
uses
{$ifdef Delphi}
SysUtils,
{$endif}
ChfTypes;
{$endif aDLL}
Const ChiefLZVersionNumber = 100; { version 1.00 }
{$ifdef Win32} Var
{$else} Const
{$endif} MyLZMarker:Char = '~'; {last char in filenames created automatically}
{////////////////////////////////////////////////////}
{////////////////////////////////////////////////////}
{////////////////////////////////////////////////////}
{Pascal object encapsulating the functionality of
this unit - CANNOT BE EXPORTED BY DLL}
{////////////////////////////////////////////////////}
{////////////////////////////////////////////////////}
{$ifndef aDLL}
Type
LZObj={$ifdef Delphi}Class{$else Delphi}Object{$Endif Delphi}
Constructor {$ifdef Delphi} Create
{$else} Init
{$endif}(Const InfName, OutFName:String);
{you can init with source and target file names,
or with blanks - so set the source and target file names
later
}
Destructor {$ifdef Delphi} Destroy; override
{$else} Done; virtual
{$endif};
{$ifndef Delphi}
Procedure SetInputName(Const aName: String);
{set source file name; absolutely necessary}
Procedure SetOutputName(Const aName: String);
{set target file name = if empty, then a default one
will be used}
Procedure SetReportProc(const aProc: TLZReportProc);
{point to procedure to report progress}
Procedure SetQuestionProc(const aProc: TLZQuestionFunc);
{point to function to ask question if the target file exists
already - if nothing is set, then existing target files will
be overwritten automatically}
{$endif}
Function Compress: Longint; virtual;
{compress the source file >> target file }
Function Decompress: Longint; virtual;
{decompress the source file >> target file}
private
{$ifdef Delphi}
FQuestionProc: TLZQuestionFunc;
FReportProc : TLZReportProc;
fInputName,
fOutputName : StrType;
function GetIsInited: boolean;
public
property QuestionProc: TLZQuestionFunc read FQuestionProc
write FQuestionProc;
property ReportProc: TLZReportProc read FReportProc
write FReportProc;
property IsInited: boolean read GetIsInited;
property InputName: StrType read FInputName write FInputName;
property OutputName: StrType read FOutputName write FOutputName;
{$else Delphi}
IsInited : boolean;
QuestionProc: TLZQuestionFunc;
ReportProc : TLZReportProc;
InputName,
OutputName : StrType;
{$endif Delphi}
End{LZOBJ};
{$endif aDLL}
{////////////////////////////////////////////////////}
{////////////////////////////////////////////////////}
{exported INTERFACE functions}
{$ifNDef aDLL}
Function LZCompress(const {$ifdef Win32} Source, Dest: string
{$else} aSource, aDest: PChar
{$endif};
LZQuestion: TLZQuestionFunc;
aProc: TLZReportProc):LongInt;
{ This Function is used for compression.
Source = Source file name
Dest = target file name
LZQuestion = procedural type to ask for overwrite permission
aProc = procedural type to return progress information
}
Function LZDecompress({$ifdef Win32} Source, Dest: string
{$else} const aSource, aDest: PChar
{$endif};
LZQuestion: TLZQuestionFunc;
aProc: TLZReportProc):LongInt;
{ This functione is used for decompression.
Source = Source file name
Dest = target file name
LZQuestion = procedural type to ask for overwrite permission
aProc = procedural type to return progress information
}
Function IsChiefLZFile(const fName: {$ifdef Win32} string
{$else} PChar
{$endif} ): boolean;
{is this an LZ file compressed with this unit?}
Function LZArchive(const fSpec, ArchName: {$ifdef Win32} string
{$else} PChar
{$endif};
LZRecurseDirs: TLZRecurse;
aProc: TLZReportProc): LongInt;
{archive all the files matching "fSpec" into archive "ArchName";
fSpec = a filespec (e.g., "*.PAS", or a filename containing a list
of files to be archived - in which case, use "/F=<listfilename>" as
the fSpec.
LZRecurseDirs = whether to recurse into subdirectories for matching
files
}
Function LZDearchive(ArchName: {$ifdef Win32} string
{$else} PChar
{$endif};
{$ifdef Win32} DefDir: string
{$else} const aDefDir: PChar
{$endif};
LZQuestion: TLZQuestionFunc;
aProc: TLZReportProc;
aRename: TLZRenameFunc): LongInt;
{De-Arc a ChiefLZ archive}
Function IsChiefLZArchive(const fName: {$ifdef Win32} string
{$else} PChar
{$endif} ): boolean;
{is this an LZ archive file compressed with this unit?}
Function GetChiefLZFileName{$ifdef Win32}(const fName: string): string;
{$else} (fName, Dest: PChar): boolean;
{$endif}
{if LZ file, then return name (in dest, if not Win32) - else return
fname (in dest, if not Win32) }
Function GetChiefLZFileSize(fName: {$ifdef Win32} string
{$else} PChar
{$endif}): LongInt;
{if LZ file then return uncompressed size - else
return actual filesize. On error, Win32 throws exception; Win16 returns -1 }
function GetChiefLZArchiveInfo(const ArchName: {$ifdef Win32} string
{$else Win32} PChar
{$endif Win32};
var Header: TChiefLZArchiveHeader): boolean;
{ if LZ-Archive then this function returns True, with the header info
in Header. Otherwise the function returns False }
Function GetChiefLZArchiveSize(const ArchName: {$ifdef Win32} string
{$else Win32} PChar
{$endif Win32}): LongInt;
{$ifdef aDLL} {$ifdef Win32} stdcall
{$else Win32} export
{$endif Win32};
{$endif aDLL}
{ If ArchName is LZArchive, returns sum of uncompressed file-sizes in archive.
If not LZArchive then returns size of file ArchName }
Function LZCompressEx(const {$ifdef Win32} Name: string
{$else} aName: PChar
{$endif};
ReplaceQuestion: TLZQuestionFunc;
aProc: TLZReportProc): LongInt;
{compress the file aName, and use the filename,
with the last character replaced by a '~' as the output file
If target file exists, and autoreplace=false then the
function exits and returns -100 else the target file
will be overwritten
}
Function LZDecompressEx({$ifdef Win32} Name: string
{$else} aName: PChar
{$endif};
ReplaceQuestion: TLZQuestionFunc;
aProc: TLZReportProc): LongInt;
{decompress the file aName, obtaining the output name from
the header automatically
If target file exists, and autoreplace=false then the
function exits and returns -100 else the target file
will be overwritten
}
function GetFullLZName(Const X : TChiefLZArchiveHeader;
Index: Integer): String;
{for internal use}
{$endif aDLL}
{////////////////////////////////////////////////////}
{$ifNDef aDLL}
implementation
uses
ChfUtils,
{$ifdef Win32}
LZSS32, Windows, LZ_Const
{$else Win32}
LZSS16, { All 16-bit code }
{$ifdef Windows}
WinProcs { Win16 }
{$ifndef Delphi}
,WinDos, Strings { TPW / BPW }
{$endif Delphi}
{$else Windows}
Dos, Strings { TP / BP }
{$endif Windows}
{$endif Win32};
{$endif aDLL}
{$ifdef Win32}
{
These constants taken from SysUtils.inc ...
}
{$ifdef Ver90}
const SInOutError = 65416;
const SFileNotFound = 65417;
const SEndOfFile = 65421;
{$else Ver90}
These constants may have changed; Check SysUtils.inc ... or scan
the String Resource Table from 0-65535 looking for keywords ...
{$endif Ver90}
{$endif Win32}
const ChiefLZSig = 'aChiefM#';
const NulFileDate = 2162688; { 01/01/1980 12:00a }
{////////////////////////////////////////////////////}
{//// my header to identify LZ file///}
Type
PLZHeader = ^TLZHeader;
TLZHeader = Packed Record
fName: TLZFileStr; {filename}
uSize: LongInt; {uncompressed size}
cSize: LongInt; {compressed size}
fTime: LongInt; {time/date stamp}
Version: TLZVerStr;
Signature: String[8]; {the identification header}
end;
Type
TLZBigFileRec= packed Record
{is it a directory}
IsBigDir: Boolean;
{its directory ID}
BigDirID: Word;
{its parent directory ID}
BigParentDir: Word;
{is it compressed?}
BigCompressed: Boolean;
{any version information?}
BigFileVersion: TLZVerStr;
{compressed sizes}
BigSizes: LongInt;
{uncompressed sizes}
uBigSizes:LongInt;
{date/time stamps}
BigTimes: LongInt;
{file names}
BigNames: TLZPathStr
end;
PLZArchiveFiles = ^TLZArchiveFiles;
TLZArchiveFiles = Array[1..MaxChiefLZArchiveSize] of TLZBigFileRec;
Const
MySigStr = #4+^M+'ChfLZ'+#5#6#8;
MyLZSignature :String[Length(MySigStr)]= MySigStr;
Const
CopyBufSize=32000;
Type
PBufType=^TBufType;
TBufType=array[1..CopyBufSize] of byte;
{////////////////////////////////////////////////////}
Type {don't want to use collections because of other versions of TPascal}
PLZDirArray=^TLZDirArray;
TLZDirArray = array[0..MaxChiefLZDirectories] of {$ifdef Win32} string
{$else Win32} PString
{$endif Win32};
{////////////////////////////////////////////////////}
Var
buf : PBufType;
jR : PLZArchiveFiles;
jR2 : PChiefLZArchiveHeader;
{
This global variable contains a long-string field in Delphi 2; it must
therefore be initialised if ChiefLZ is to be made into a DLL ...
(This is a problem with Delphi v2.00 - v2.01 seems to have fixed this)
}
BlankRec: TLZReportRec {$ifdef Win32} = () {$endif Win32};
{/////////////////////////////////////////////////////////}
var aRead, aWrite: Longint;
var LZReportProc: TLZReportProc {$ifdef Win32} = nil {$endif Win32};
{
This global variable ensures that MyReadProc() calls LZReportProc()
only during compression, and that MyWriteProc() calls LZReportProc()
only during decompression. This is done by setting Decompressing
to the appropriate value immediately before calling LZEncode() or
LZDecode().
}
var Decompressing: Boolean;
{/////////////////////////////////////////////////////////}
var InFile, OutFile: file;
{/////////////////////////////////////////////////////////}
{$ifdef Win32}
{
These are Win32-specific functions that cannot be moved into the more
general ChfUtils due to their dependance on types defined in ChfTypes
}
function GetTempChiefFileName: string;
var
RetBuf: PChar;
begin
GetMem(RetBuf, MAX_PATH);
try
if (GetTempPath(MAX_PATH, RetBuf) = 0) or
(GetTempFileName(RetBuf,'CHF',0,RetBuf) = 0) then
RaiseError(EChiefLZError,SNoTempFileName);
SetString(Result,RetBuf,StrLen(RetBuf))
finally
FreeMem(RetBuf, MAX_PATH)
end
end;
function GetFoundFileName(const Search: TSearchRec): string;
begin
if Length(Search.Name) >= SizeOf(TLZFileStr) then
Result := string(Search.FindData.cAlternateFileName)
else
Result := Search.Name // Take long filename (if short enough)
end; // else take short filename
{$else Win32}
function GetTempChiefFileName(const FName: PChar): boolean; assembler;
asm
{
Create a temporary file- FName must specify a path + '\', with enough
room afterwards to append 12 characters.
}
PUSH DS
LDS DX, FName
MOV AH, $5A
MOV CX, faArchive
{$ifdef Windows}
CALL DOS3Call
{$else Windows}
INT $21
{$endif Windows}
POP DS
JC @Fail
{
The file handle refers to an OPEN file; close it so we can open it
the Pascal way ...
}
MOV BX, AX
MOV AH, $3E
{$ifdef Windows}
CALL DOS3Call
{$else Windows}
INT $21
{$endif Windows}
{
Return True if successful, False otherwise ...
}
@Fail:
{$ifdef Delphi}
DB $0F, $93, $C0 (* setnc al *)
{$else Delphi}
MOV AL, False
JC @End
INC AX
@End:
{$endif Delphi}
end;
{$endif Win32}
{/////////////////////////////////////////////////////////}
{///// is this an LZ compressed file using this unit? ////}
Function IsMyLZFile(Var InFile:file; Var f:TLZHeader):boolean;
var
OldPos: LongInt;
NumRead: Integer;
begin
OldPos := FilePos(InFile);
Seek(InFile,0);
BlockRead(InFile, f, SizeOf(f), NumRead);
IsMyLZFile := (NumRead = SizeOf(f))
and (Length(f.FName) <> 0)
and (f.Signature = ChiefLZSig);
Seek(InFile,OldPos)
end;
{/////////////////////////////////////////////////////////}
{////: normal file copy if not LZ file}
const LZ_UNKNOWN_LENGTH = -1;
type TReporting = (doReportOnRead, doReportOnWrite);
Function MyFCopy(var InFile, OutFile: file;
const CopyLength: LongInt;
const doReport: TReporting): LongInt;
{$ifndef Win32} far; {$endif}
Var
p: PBufType;
{
Turn the enumerated type doReport into a Boolean:
doReportOnRead -> False
doReportOnWrite -> True
Decompression routines will call MyFCopy() using doReportOnWrite,
whereas Compression routines will call using doReportOnRead
}
var
ReportingOnWrite: Boolean absolute doReport;
{$ifdef Win32}
NumRead:integer;
BRead: integer;
{$else}
BRead: word;
NumRead:word;
NumWrit:word;
{$endif}
{$ifndef Delphi}
Result: LongInt;
{$endif}
begin
{$IFDEF Debug}
if CopyLength < LZ_UNKNOWN_LENGTH then
{$ifdef Win32}
raise EChiefLZDebug.Create('Negative copy-length passed to MyFCopy')
at AddrOfCaller
{$else Win32}
RunErrorMessageAt('Negative copy-length passed to MyFCopy',
AddrOfCaller)
{$endif Win32};
{$ENDIF}
Result := 0;
New(p);
{$ifdef Win32}
try {finally}
{$else Win32}
if p = nil then
begin
{$ifndef Delphi}
MyFCopy := 0;
{$endif}
Exit { ERROR !!! Failed Memory Allocation! }
end;
{$endif Win32}
repeat
if CopyLength <> LZ_UNKNOWN_LENGTH then
BRead := Min(CopyLength-Result, SizeOf(p^))
else
BRead := SizeOf(p^);
BlockRead(InFile, p^, BRead, NumRead);
{compressing - return number of bytes read}
if Assigned(LZReportProc) and not ReportingOnWrite then
LZReportProc(BlankRec, NumRead);
{
If CopyLength <> LZ_UNKNOWN_LENGTH, we know how many bytes we EXPECT
to be able to read from this file. If BRead <> NumRead, then the
file must be corrupt ...
}
{$ifdef Win32}
if (CopyLength <> LZ_UNKNOWN_LENGTH) and (BRead <> NumRead) then
RaiseIOError(SEndOfFile,100); { Will exit via `finally...end' }
{$endif}
{
This is the EOF condition for when we DON'T know how long the copy is ...
}
if NumRead = 0 then
break;
{
Without the NumWrit parameter, BlockWrite will cause an IO-Error if the disc
doesn't have room for SizeOf(p) bytes. This is good in Win32, as an exception
will then be raised.
}
BlockWrite(OutFile,p^,NumRead {$ifndef Win32}, NumWrit {$endif});
{
If Win32 version gets this far, then all NumRead chars must have
been written ...
}
inc(Result, {$ifdef Win32} NumRead {$else} NumWrit {$endif});
{de-compressing - return number of bytes written}
if Assigned(LZReportProc) and ReportingOnWrite then
LZReportProc(BlankRec, {$ifdef Win32} NumRead {$else} NumWrit {$endif})
until {$ifndef Win32} (NumWrit<>NumRead) or {$endif}
( (CopyLength <> LZ_UNKNOWN_LENGTH) and
(Result >= CopyLength) );
{$ifndef Delphi}
MyFCopy := Result;
{$endif}
{$ifdef Win32}
finally
{$endif}
Dispose(p);
{$ifdef Win32}
end;
{$endif}
end;
{/////////////////////////////////////////////////////////}
Function MyReadProc(var ReadBuf): TLZSSWord; {$ifndef Win32} far; {$endif}
{to read from files}
{$ifndef Delphi}
var
Result: TLZSSWord;
{$endif}
Begin
BlockRead(InFile, ReadBuf, LZRWBufSize, Result);
Inc(aRead, Result);
{compressing - return bytes read}
if Assigned(LZReportProc) and not Decompressing then
LZReportProc(BlankRec, Result);
{$ifndef Delphi}
MyReadProc := Result
{$endif}
End; { MyReadProc }
{/////////////////////////////////////////////////////////}
Function MyWriteProc(var WriteBuf; Count: TLZSSWord): TLZSSWord;
{$ifndef Win32} far; {$endif Win32}
{$ifndef Delphi}
var
Result: TLZSSWord;
{$endif}
{to write to files}
Begin
BlockWrite(OutFile, WriteBuf, Count, Result);
Inc(aWrite, Result);
{de-compressing - return bytes written}
if Assigned(LZReportProc) and Decompressing then
LZReportProc(BlankRec, Result);
{$ifndef Delphi}
MyWriteProc := Result
{$endif}
End; { MyWriteProc }
{/////////////////////////////////////////////////////////}
Function GetDirIndex(aDir: TLZPathStr; Const DirList: PLZDirArray;
Const Max: TLZSSWord): LongInt;
{find the index of a directory within an array}
Var
i: TLZSSWord;
begin
{$ifndef Win32}
aDir := UpperCase(aDir);
{$endif Win32}
for i := 0 to Max do
if {$ifdef Win32} AnsiCompareText(aDir, DirList^[i]) = 0
{$else Win32} aDir = DirList^[i]^
{$endif Win32} then
begin
GetDirIndex := i;
Exit
end;
GetDirIndex := -1
end;
{/////////////////////////////////////////////////////////}
function CreatePath(Path: TLZPathStr): Integer;
{Iteratively create a directory path}
var
i: Integer;
NewDir: TLZPathStr;
{$ifndef Delphi}
{$ifdef Windows}
P: array[0..79] of Char;
{$endif Windows}
Result: Integer;
{$endif Delphi}
begin
{$ifdef Delphi}
Path := ExpandFileName(Path);
{$else Delphi}
{$ifdef Windows}
FileExpand(P, Str2PChar(Path));
Path := StrPas(p);
{$else Windows}
Path := FExpand(Path);
{$endif Windows}
{$endif Delphi}
i := 3;
Result := 0;
repeat
repeat
Inc(i)
until (i > Length(Path)) or (Path[i] = '\');
NewDir := Copy(Path,1,i-1);
if not DirectoryExists(NewDir) then
begin
MkDir(NewDir); { Win32 throws an exception and exits... }
{$ifndef Win32} { We shall catch and handle this }
If IOResult <> 0 then { exception in the calling function. }
begin
CreatePath := -1;
Exit
end;
{$endif Win32}
Inc(Result)
end
until i > Length(Path);
{$ifndef Delphi}
CreatePath := Result;
{$endif}
end;
{/////////////////////////////////////////////////////////}
function GetFullLZName(const X: TChiefLZArchiveHeader;
Index: Integer): string;
{$ifdef aDLL} {$ifdef Win32} stdcall
{$else Win32} export
{$endif Win32}; {$endif aDLL}
{$ifndef Delphi}
var
Result: string;
{$endif}
begin
Result := '';
repeat
with X.Files[Index] do
begin
Result := Names + '\' + Result;
if not IsDir then
Index := DirID
else
Index := ParentDir
end
until Index = 0;
{$ifdef Win32}
SetLength(Result, Pred(Length(Result)));
{$else Win32}
Dec(Result[0]);
{$endif Win32}
{$ifndef Delphi}
GetFullLZName := Result;
{$endif Delphi}
end;
Function GetFileVersion({$ifdef Win32} Const
{$endif} fName: String): TLZVerStr;
{$ifndef DPMI}
{$ifdef TPW}
Var
Result: TLZVerStr;
{$endif TPW}
{$endif DPMI}
Begin
{$ifdef DPMI}
GetFileVersion := '0'
{$else DPMI}
{$ifdef Windows}
{$ifdef Win32}
Result := FileVersionInfo(fName, 'FileVersion');
{$else Win32}
Result := FileVersionInfo(Str2PChar(fName), 'FileVersion');
{$endif Win32}
if Length(Result) = 0 then
GetFileVersion := '0'
{$ifndef Delphi}
else
GetFileVersion := Result
{$endif Delphi}
{$else Windows}
GetFileVersion := '0'
{$endif Windows}
{$endif DPMI}
End;
{/////////////////////////////////////////////////////////}
function GetLZMarkedName(const FName: string): string;
var
i: Integer;
Ext: TLZExtStr;
begin
Ext := ExtractFileExt(FName);
i := Length(Ext);
if i < 2 then { Ext is either '' or '.' }
Ext := '.' + MyLZMarker
else
Ext[i] := MyLZMarker;
GetLZMarkedName := ChangeFileExt(FName, Ext)
end;
{/////////////////////////////////////////////////////////}
{/////////////////////////////////////////////////////////}
{
These are the LZ functions exported from the unit
}
{/////////////////////////////////////////////////////////}
{/////////////////////////////////////////////////////////}
Function IsChiefLZArchive(const fName: {$ifdef Win32} string
{$else} PChar
{$endif} ):boolean;
{$ifdef aDLL} {$ifdef Win32} stdcall
{$else Win32} export
{$endif Win32};
{$endif aDLL}
Var
f:file;
NumRead: TLZSSWord;
{$ifndef Win32}
OldFMode: byte;
{$endif}
Hed : TLZArchiveHeader;
Begin
IsChiefLZArchive := False;
if {$ifdef Win32} Length(fName)
{$else} StrLen(fName)
{$endif} = 0 then
Exit;
{$ifdef Win32}
AssignFile(f, fName);
FileMode := fmOpenRead; { Win32 only allows 0 <= FileMode <= 2 }
{$I-} { However, share access is FILE_SHARE_READ }
Reset(f, 1);
{$I+}
if IOResult = 0 then
begin
BlockRead(f, Hed, SizeOf(Hed), NumRead); // No IO-Error; uses NumRead
CloseFile(f);
IsChiefLZArchive := (NumRead = SizeOf(Hed)) and
(Hed.Signature = MyLZSignature) and
(Hed.Count <> 0)
// If haven't read SizeOf(Hed) bytes, CAN'T be LZ Archive
end
{$else}
Assign(f, StrPas(fName));
OldFMode := FileMode;
{
Open file: we need Read-access, don't need Write-access and *INSIST*
that no one else can write to it (i.e. corrupt it) until we're done.
}
FileMode := (fmOpenRead or fmShareDenyWrite);
Reset(f,1);
FileMode := OldFMode;
if IOResult = 0 then
begin
BlockRead(f, Hed, SizeOf(Hed), NumRead);
Close(f);
IsChiefLZArchive := (NumRead = SizeOf(Hed)) and
(Hed.Signature = MyLZSignature) and
(Hed.Count <> 0)
end
{$endif}
end;
{/////////////////////////////////////////////////////////}
{$ifdef Win32}
Function GetChiefLZFileName(const fName: string): string;
{$ifdef aDLL} stdcall; {$endif aDLL}
var
f: file;
h: TLZHeader;
begin
AssignFile(f, fName);
FileMode := fmOpenRead; { Win32 only allows 0 <= FileMode <= 2 }
Reset(f,1); { However, share access is FILE_SHARE_READ }
try
if IsMyLZFile(f,h) then
SetString(Result, PChar(@h.fName[1]), Length(h.fName))
else
Result := fName
finally
CloseFile(f)
end
end;
{$else}
Function GetChiefLZFileName(fName, Dest:PChar):boolean;
{$ifdef aDLL} export; {$endif aDLL}
Var
h:TLZHeader;
f:file;
{$ifndef Delphi}
Result:boolean;
{$endif}
OldFMode:byte;
Begin
GetChiefLZFileName := false;
StrCopy(Dest, fName); {return filename}
Assign(f, StrPas(fName));
OldFMode := FileMode;
{
Open file: we need Read-access, don't need Write access, and *INSIST*
that no one else can write to it (i.e. corrupt it) until we're done.
}
FileMode := (fmOpenRead or fmShareDenyWrite);
Reset(f,1);
FileMode := OldFMode;
if IOResult=0 then
begin
Result := IsMyLZfile(f,h);
Close(f); { Reset() OK, so Close() must succeed }
{$ifndef Delphi}
GetChiefLZFileName := Result;
{$endif Delphi}
if Result then
StrPCopy(Dest, h.fName);
end
end;
{$endif}
{/////////////////////////////////////////////////////////}
{/////////////////////////////////////////////////////////}
Function GetChiefLZFileSize(fName: {$ifdef Win32} string
{$else} PChar
{$endif}):LongInt;
{$ifdef aDLL} {$ifdef Win32} stdcall
{$else Win32} export
{$endif Win32};
{$endif aDLL}
Var
h:TLZHeader;
f:file;
{$ifndef Win32}
OldFMode:byte;
{$endif}
Begin
{$ifdef Win32}
AssignFile(f,fName);
FileMode := fmOpenRead; { Win32 only allows 0 <= FileMode <= 2 }
Reset(f,1); { However, share access is FILE_SHARE_READ }
try
if IsMyLZFile(f,h) then
Result := h.uSize
else
Result := FileSize(f)
finally
CloseFile(f)
end;
{$else}
GetChiefLZFileSize := -1{error};
Assign(f, StrPas(fName));
OldFMode := FileMode;
{
Open file: we need Read-access, don't need Write-access and *INSIST*
that no one else can write to it (i.e. corrupt it) until we're done.
}
FileMode := (fmOpenRead or fmShareDenyWrite);
Reset(f,1);
FileMode := OldFMode;
if IOResult=0 then
begin
if IsMyLZFile(f,h) then
GetChiefLZFileSize := h.uSize {uncompressed size}
else
GetChiefLZFileSize := FileSize(f); {actual size}
Close(f); { Reset() OK, so Close() cannot fail }
end;
{$endif}
end;
{/////////////////////////////////////////////////////////}
function GetChiefLZArchiveInfo(const ArchName: {$ifdef Win32} string
{$else Win32} PChar
{$endif Win32};
var Header: TChiefLZArchiveHeader): boolean;
{$ifdef aDLL} {$ifdef Win32} stdcall
{$else Win32} export
{$endif Win32};
{$endif aDLL}
var
f : file;
Hed : TLZArchiveHeader;
{$ifndef Win32}
OldFMode: byte;
{$endif Win32}
begin
{$ifdef Win32}
Result := IsChiefLZArchive(ArchName);
if Result then
begin
AssignFile(f,ArchName);