*/
If you have a PH account, you can customize your PH profile.
*/

View \CHIEFLZ.PAS

ChiefLZ LZ77 Compression

Submitted By: Unknown
Rating: starstar (Rate It)


{
   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);