www.pudn.com > HgzVip1.2_code.rar > IconLibrary.pas


//             ____                 __    _ __ 
//            /  _/________  ____  / /   (_) /_  _________ ________  __ 
//            / // ___/ __ \/ __ \/ /   / / __ \/ ___/ __ `/ ___/ / / / 
//          _/ // /__/ /_/ / / / / /___/ / /_/ / /  / /_/ / /  / /_/ / 
//         /___/\___/\____/_/ /_/_____/_/_.___/_/   \__,_/_/   \__, / 
//                                                            /____/ 
 
(******************************************************************************* 
* IconTools 1.5                                                                * 
*                                                                              * 
* This file is part of the IconTools class library                             * 
*                                                                              * 
******************************************************************************** 
*                                                                              * 
* If you find bugs, has ideas for missing featurs, feel free to contact me     * 
*                           jpstotz@gmx.de                                     * 
*                                                                              * 
* The latest version of TShelltree can be found at:                            * 
*     http://members.tripod.com/~JPStotz/IconTools/IconTools.html              * 
******************************************************************************** 
* Date last modified:   May 12, 1999                                           * 
*******************************************************************************) 
 
unit IconLibrary; 
 
interface 
 
{.$Define Overseer} 
 
{$IfDEF Overseer} 
  {$DEFINE Writer16} 
{$EndIf} 
 
uses 
{$IfDEF Overseer} 
  udbg, 
{$EndIf} 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
  IconTools, IconTypes, ShellAPI; 
 
(********************************************************************) 
(**                      TIconLibrary declaration                  **) 
(********************************************************************) 
 
type 
  TIconLibrary = class 
  private 
    FFilename : String; 
  protected 
    FIcons : TStringList; 
  public 
    constructor Create; virtual; 
    destructor Destroy; override; 
 
    procedure LoadFromFile(Filename : String); 
    procedure SaveToFile(Filename : String); 
 
    property Icons : TStringList read FIcons; 
    property Filename : String read FFilename; 
  end; 
 
(********************************************************************) 
(**                TICLReader abstract declaration                 **) 
(********************************************************************) 
 
type 
  TICLReader = class 
  private 
  protected 
    FFilename : String; 
    FIcons : TStringList; 
  public 
    constructor Create(Filename : String); virtual; 
    destructor Destroy; override; 
    function Execute : Boolean; virtual; abstract; 
    property Icons : TStringList read FIcons; 
  end; 
 
(********************************************************************) 
(**                    T32BitReader declaration                    **) 
(********************************************************************) 
 
type 
  T32BitReader = class(TICLReader) 
  private 
  protected 
    Instance : THandle; 
    FreeLib  : Boolean; 
    procedure IconResFound(ResName : PChar); 
  public 
    constructor Create(Filename : String); override; 
    function Execute : Boolean; override; 
    destructor Destroy; override; 
  end; 
 
(********************************************************************) 
(**                     TICL32Icon declaration                     **) 
(********************************************************************) 
 
type 
  TICL32Icon = class(TResourceIcon) 
  private 
 
  protected 
    FIconData : TMemoryStream; 
    procedure BufferIconData; 
    procedure LoadIconResInfos(Stream : TStream;Var Valid : Boolean;Var Count : Word); override; 
    function  GetHIcon(Index : Word) : HIcon; override; 
  public 
    procedure WriteIconDataToStream(Stream : TStream;Index : Integer); override; 
    destructor Destroy; override; 
  end; 
 
(********************************************************************) 
(**                    T16BitReader declaration                    **) 
(********************************************************************) 
 
type 
  T16BitReader = class(TICLReader) 
  private 
    FStream : TStream; 
    FAlignShift         : Word; 
    FWin16Offset        : Word; 
    FResourceTableStart : DWord; 
    FNamestableStart    : DWord; 
    FIconCount          : Word; 
    FGroupIconCount     : Word; 
    FICLName            : String; 
    FIconsRes           : PNameRecArray; 
    FGroupIconsRes      : PNameRecArray; 
  protected 
    procedure ReadFileHeader; 
    procedure ReadResourceTable; 
    procedure ReadTypeInfo; 
    procedure ReadResourceNames; 
  public 
    constructor Create(AFilename : String); override; 
    destructor Destroy; override; 
    function Execute : Boolean; override; 
    function GetResourceIndex(ID : Word;GroupIcon : Boolean) : Integer; 
    procedure ReadResource(Index : Word;GroupIcon : Boolean;Stream : TStream;Var ResName : String); 
    property IconCount : Word read FGroupIconCount; 
  end; 
 
(********************************************************************) 
(**                    T16BitWriter declaration                    **) 
(********************************************************************) 
 
type 
  T16BitWriter = class 
  private 
    FShiftAlignOffs : DWord; 
    FNamesTableOffs : DWord; 
    FOfs_Icons  : PDWordArray; 
    FOfs_GIcons : PDWordArray; 
    FIcons      : Integer; 
    FIconLib    : TIconLibrary; 
    FAlignShift : Word; 
    FStream : TMemoryStream; 
    Null    : ARRAY[1..256] OF Char; 
  protected 
    procedure WriteShiftAlign; 
    procedure UpdateTableEntry(EntryPos : DWord;StartOffset,EndOffset : DWord); 
    procedure WriteHeader; 
    procedure WriteResTable; 
    procedure WriteNameTable; 
    procedure WriteIconData; 
    procedure Align; 
    property Stream : TMemoryStream read FStream; 
  public 
    constructor Create(AIconLib : TIconLibrary); 
    destructor Destroy; override; 
    procedure SaveToFile(Filename : String); 
    property IconLib : TIconLibrary read FIconLib; 
  end; 
 
(********************************************************************) 
(**                      TICL16Icon declaration                    **) 
(********************************************************************) 
 
type 
  TICL16Icon = class(TMultiIcon) 
  private 
    FResName : String; 
    FICLReader : T16BitReader; 
    function GeTICL16IconResInfo(Index : Word) : TFileIconResInfo; 
  protected 
    Icons : TMemoryStream; 
    function GetHIcon(Index : Word) : HIcon; override; 
    function GetIconSize(Index : Word) : TSize; override; 
    procedure LoadIconResInfos(Stream : TStream;Var Valid : Boolean;Var Count : Word);override; 
    function GetIconResInfo(Index : Word) : TIconResInfo; override; 
  public 
    procedure WriteIconDataToStream(Stream : TStream;Index : Integer); override; 
    constructor ICLCreate(ICLReader : T16BitReader;Index : Word); 
    destructor Destroy; override; 
    property ResName : String read FResName; 
    property ICLIconResInfo[Index : Word] : TFileIconResInfo read GeTICL16IconResInfo; 
  end; 
 
implementation 
 
{$R-} 
 
type 
  EICLReadError  = class (Exception); 
  EICLWriteError = class (Exception); 
 
const 
  IMAGE_DOS_SIGNATURE    = $5A4D;       { MZ } 
  IMAGE_IM_SIGNATURE     = $4D49;       { IM } 
  IMAGE_OS2_SIGNATURE    = $454E;       { NE } 
  IMAGE_W32_SIGNATURE    = $4550;       { PE } 
  IMAGE_NAMETABLE_ICL  : ARRAY[0..3] OF Char = 'ICL'+#0; 
 
  E_R_InvWin16Offs    = 'Invalid Windows 16 Offset'; 
  E_R_InvWin16Header  = 'Invalid Windows 16 Header'; 
  E_R_NotValid16Bit   = 'Not a valid ICL File'; 
  E_R_NoResources     = 'No Resources in file'; 
  E_R_NoNamesTable    = 'Names Table not found'; 
  E_R_IconResNotFound = 'Icon Resource Not Found'; 
  E_R_ResTableError   = 'ResourceTable has an Error'; 
  E_W_NoIcons         = 'Unable to write Iconlibrary with no icons'; 
  E_W_TooManyIcons    = 'Iconlibraries with more than 32767 are not possible'; 
 
procedure ICLReadError(const ErrMsg: string); 
begin 
  raise EICLReadError.Create(ErrMsg); 
end; 
 
procedure ICLWriteError(const ErrMsg: string); 
begin 
  raise EICLReadError.Create(ErrMsg); 
end; 
 
function IsValidLib(Filename : String;Var Is32Bit : Boolean) : Boolean; 
Var 
  F : TFileStream; 
  Sig : Word; 
begin 
  Result:=False; 
  F:=TFileStream.Create(Filename,fmOpenRead or fmShareDenyWrite); 
  With F DO 
  try 
    Read(Sig,SizeOf(Sig)); 
    IF (Sig <>IMAGE_DOS_SIGNATURE) Then exit; 
    Seek($3C,soFromBeginning); 
    Read(Sig,SizeOf(Sig)); 
    Seek(Sig,soFromBeginning); 
    Read(Sig,SizeOf(Sig)); 
    Result:=(Sig = IMAGE_W32_SIGNATURE) OR (Sig = IMAGE_OS2_SIGNATURE); 
    Is32Bit:=(Sig = IMAGE_W32_SIGNATURE); 
  finally 
    F.Free; 
  end; 
end; 
 
(********************************************************************) 
(**                  TIconLibrary implementation                   **) 
(********************************************************************) 
 
constructor TIconLibrary.Create; 
begin 
  FIcons := TStringList.Create; 
end; 
 
destructor TIconLibrary.Destroy; 
Var 
  I : Integer; 
begin 
  FOR I:=1 TO Icons.Count Do TMultiIcon(Icons.Objects[I-1]).Free; 
  FIcons.Free; 
end; 
 
procedure TIconLibrary.LoadFromFile(Filename : String); 
Var 
  LoadedIcons,IconCount : Integer; 
  Is32Bit : Boolean; 
  Reader : TICLReader; 
begin 
  LoadedIcons:=0; 
  IconCount:=ExtractIcon(HInstance,PChar(Filename),dword(-1)); 
  IF (IconCount=0) Then exit; 
  IF NOT IsValidLib(Filename,Is32Bit) Then exit; 
  FFilename:=Filename; 
  IF NOT Is32Bit Then 
    Reader:=T16BitReader.Create(Filename) 
  else 
    Reader:=T32BitReader.Create(Filename); 
  try 
    IF Reader.Execute Then begin 
      LoadedIcons:=Reader.Icons.Count; 
      Icons.Assign(Reader.Icons); 
    end; 
  finally 
    Reader.Free; 
  end; 
  IF LoadedIcons<>IconCount Then begin 
    beep; 
  end;   
end; 
 
procedure TIconLibrary.SaveToFile(Filename : String); 
Var 
  ICLFile  : T16BitWriter; 
begin 
  IF Icons.Count=0 Then ICLWriteError(E_W_NoIcons); 
  IF Icons.Count>=$8000 Then ICLWriteError(E_W_TooManyIcons); 
  ICLFile:=T16BitWriter.Create(self); 
  try 
    ICLFile.SaveToFile(Filename); 
  finally 
    ICLFile.Free; 
  end; 
end; 
 
(********************************************************************) 
(**                  TICLReader implementation                     **) 
(********************************************************************) 
 
constructor TICLReader.Create(Filename : String); 
begin 
  FIcons:=TStringList.Create; 
  FFilename:=Filename; 
end; 
 
destructor TICLReader.Destroy; 
begin 
  IF Assigned(FIcons) Then FIcons.free; 
  inherited; 
end; 
 
(********************************************************************) 
(**                 T32BitReader implementation                    **) 
(********************************************************************) 
 
function EnumResNameProc(hModule : THandle;lpszType,lpszName : PChar;lParam : lParam) : Bool; stdcall; 
begin 
  Result:=True; 
  T32BitReader(lParam).IconResFound(lpszName); 
end; 
 
constructor T32BitReader.Create(Filename : String); 
begin 
  inherited; 
  FreeLib:=False; 
  Instance:=0; 
end; 
 
function T32BitReader.Execute : Boolean; 
begin 
  Result:=False; 
  try 
    Instance:= windows.LoadLibraryEx(PChar(FFilename), 0, LOAD_LIBRARY_AS_DATAFILE); 
  finally 
  end; 
  IF Instance=0 then exit; 
  FreeLib:=True; 
  Result:=True; 
  EnumResourcenames(Instance,RT_GROUP_ICON,@EnumResNameProc,Integer(self)); 
end; 
 
procedure T32BitReader.IconResFound(ResName : PChar); 
Var 
  Ico : TICL32Icon; 
  IsID : Boolean; 
  RName : String; 
begin 
  IsID:=IsBadStringPtr(ResName,63); 
  IF IsID Then begin 
    Ico:=TICL32Icon.CreateFromID(Instance,Loword(Integer(ResName))); 
    RName:=InttoStr(Integer(Resname)); 
  end else begin 
    Ico:=TICL32Icon.Create(Instance,Strpas(ResName)); 
    Rname:=Strpas(ResName); 
  end; 
  FIcons.AddObject(RName,Ico); 
end; 
 
destructor T32BitReader.Destroy; 
begin 
  inherited; 
  IF FreeLib Then FreeLibrary(Instance); 
end; 
 
(********************************************************************) 
(**                   TICL32Icon implementation                    **) 
(********************************************************************) 
 
procedure TICL32Icon.BufferIconData; 
Var 
  I : Integer; 
  RStream : TResourceStream; 
  SPos : DWord; 
begin 
  FIconData:=TMemoryStream.Create; 
  With FIconData DO begin 
    Clear; 
    Seek(IconCount*SizeOf(DWord),soFromBeginning); 
    FOR I:=1 TO IconCount DO 
      With PResourceIconDirList(IconDirList)^[I-1] do begin 
        RStream:=TResourceStream.CreateFromID(Instance,ID,RT_ICON); 
        try 
          SPos:=Position; 
          Position:=SizeOf(DWord)*(I-1); 
          Write(SPos,SizeOf(DWord)); 
          Position:=SPos; 
          ResInfo.BytesInRes:=RStream.Size; 
          CopyFrom(RStream,RStream.Size); 
        finally 
          RStream.Free; 
        end; 
      end; 
  end; 
end; 
 
function TICL32Icon.GetHIcon(Index : Word) : HIcon; 
Var 
  DW : DWord; 
begin 
  Result:=0; 
  IF Index>=IconCount Then exit; 
  IF IconHandleList^[Index]=0 Then begin 
    with ResourceIconResInfo[Index] do begin 
      FIconData.Position:=Index*SizeOf(DWord); 
      FIcondata.Read(DW,SizeOf(DWord)); 
      FIconData.Position:=DW; 
      Result:=CreateIconFromStream(FIconData,ResInfo.BytesInRes,ResInfo); 
      IconHandleList^[Index]:=Result; 
    end; 
  end else 
    Result:=IconHandleList^[Index]; 
end; 
 
procedure TICL32Icon.WriteIconDataToStream(Stream : TStream;Index : Integer); 
Var 
  DW : DWord; 
begin 
  IF Index>=IconCount Then exit; 
  with ResourceIconResInfo[Index] do begin 
    FIconData.Position:=Index*SizeOf(DWord); 
    FIcondata.Read(DW,SizeOf(DWord)); 
    FIconData.Position:=DW; 
    Stream.CopyFrom(FIconData,ResInfo.BytesInRes); 
  end; 
end; 
 
procedure TICL32Icon.LoadIconResInfos(Stream : TStream;Var Valid : Boolean;Var Count : Word); 
begin 
  inherited; 
  BufferIconData; 
end; 
 
destructor TICL32Icon.Destroy; 
begin 
  IF Assigned(FIconData) Then FIconData.Free; 
  inherited; 
end; 
 
(********************************************************************) 
(**                  T16BitReader implementation                   **) 
(********************************************************************) 
 
function T16BitReader.GetResourceIndex(ID : Word;GroupIcon : Boolean) : Integer; 
Var 
  Res : PNameRecArray; 
  I,IMax : Integer; 
begin 
  Result:=-1; 
  IF GroupIcon Then begin 
    Res:=FGroupIconsRes; 
    IMax:=FGroupIconCount; 
  end else begin 
    Res:=FIconsRes; 
    IMax:=FIconCount; 
  end; 
  I:=0; 
  While (I=0 Then exit; 
  ICLReadError(E_R_IconResNotFound); 
end; 
 
 
procedure T16BitReader.ReadResource(Index : Word;GroupIcon : Boolean; 
          Stream : TStream;Var ResName : String); 
Var 
  Namerec : TNameRec; 
  ResStartPos : Longint; 
  ResLength   : Longint; 
begin 
  IF GroupIcon Then NameRec:=FGroupIconsRes^[Index] 
    else NameRec:=FIconsRes^[Index]; 
  ResName:=Format('%s %0.3d',[FICLName,Index+1]); 
  ResStartPos:=NameRec.rnOffset shl FAlignShift; 
  ResLength  :=NameRec.rnLength shl FAlignShift; 
  FStream.Position:=ResStartPos; 
  Stream.CopyFrom(FStream,ResLength); 
end; 
 
constructor T16BitReader.Create(AFilename : String); 
begin 
  inherited; 
  FStream:=TFileStream.Create(AFilename,fmOpenRead or fmShareDenyWrite); 
  FStream.Position:=0; 
  FICLName:=ExtractFilename(AFilename); 
  Delete(FICLName,Length(FICLName)-Length(ExtractFileExt(FICLname))+1,30); 
end; 
 
destructor T16BitReader.Destroy; 
begin 
  FStream.Free; 
  inherited; 
end; 
 
function T16BitReader.Execute : Boolean; 
Var 
  ICLIcon : TICL16Icon; 
  I,L : Integer; 
  S : String; 
  NameOfList : Boolean; 
  SL : TStringList; 
begin 
  try 
    FIconsRes:=nil; 
    FGroupIconsRes:=nil; 
    FIcons.Clear; 
    ReadFileHeader; 
    ReadResourceTable; 
    SL:=TStringList.Create; 
    try 
      L:=FGroupIconCount; 
      NameOfList:=(FIcons.Count=FGroupIconCount); 
      FOR I:=1 TO L DO begin 
        ICLIcon:=TICL16Icon.ICLCreate(self,I-1); 
        IF NameOfList Then 
          S:=FIcons.Strings[I-1] 
        else 
          S:=ICLIcon.ResName; 
        SL.AddObject(S,ICLIcon); 
      end; 
      FIcons.Assign(SL); 
    finally 
      SL.Free; 
    end;   
  except 
    Result:=False; 
    exit; 
  end; 
  Result:=True; 
end; 
 
procedure T16BitReader.ReadFileHeader; 
Var 
  DosSignature     : Word; 
  Win16Signature   : Word; 
  ResTableOffset   : Word; 
  NamesTableOffset : Word; 
begin 
  With FStream DO begin 
    Read(DosSignature,SizeOf(DosSignature)); 
    IF (DosSignature<>IMAGE_DOS_SIGNATURE) Then ICLReadError(E_R_NotValid16Bit); 
    Seek($3C,soFromBeginning); 
    Read(FWin16Offset,SizeOf(Word)); 
    IF (FWin16Offset<$3C) Then ICLReadError(E_R_InvWin16Offs); 
    Seek(FWin16Offset,soFromBeginning); 
    Read(Win16Signature,SizeOf(Win16Signature)); 
    IF (Win16Signature<>IMAGE_OS2_SIGNATURE) Then ICLReadError(E_R_InvWin16Header); 
    Seek($22,soFromCurrent); 
    Read(ResTableOffset,SizeOf(Word)); 
    IF (ResTableOffset=0) Then ICLReadError(E_R_NoResources); 
    FResourceTableStart:=ResTableOffset+FWin16Offset; 
    Read(NamesTableOffset,SizeOf(NamesTableOffset)); 
    IF (NamesTableOffset=0) Then ICLReadError(E_R_NoNamesTable); 
    FNamesTableStart:=NamesTableOffset+FWin16Offset; 
  end; 
end; 
 
procedure T16BitReader.ReadResourceTable; 
Var 
  EndTypes : Word; 
begin 
  with FStream DO begin 
    Seek(FResourceTableStart,soFromBeginning); 
    Read(FAlignShift,SizeOf(Word)); 
    Read(EndTypes,SizeOf(Word)); 
    While (Endtypes>0) DO begin 
      Seek(-SizeOf(Word),sofromCurrent); 
      ReadTypeInfo; 
      Read(EndTypes,SizeOf(Word)); 
    end; 
    IF (FGroupIconsRes=nil) OR (FIconsRes=nil) Then ICLReadError(E_R_ResTableError); 
    ReadResourceNames; 
  end; 
end; 
 
procedure T16BitReader.ReadResourceNames; 
Var 
  NameLen : byte; 
  S : String; 
begin 
  With FStream DO begin 
    Read(NameLen,SizeOf(NameLen)); 
    While (NameLen>0) DO begin 
      SetString(S,nil,NameLen); 
      Read(Pointer(S)^,NameLen); 
      IF NOT ((FIcons.Count=0) AND (CompareStr(S,StrPas(IMAGE_NAMETABLE_ICL))=0)) Then 
        FIcons.Add(S); 
      Read(NameLen,SizeOf(NameLen)); 
    end; 
  end; 
end; 
 
procedure T16BitReader.ReadTypeInfo; 
Var 
  TypeInfo : TTypeRec; 
  I : Integer; 
  TypeRead : Boolean; 
begin 
  With FStream DO begin 
    Read(TypeInfo,SizeOf(TypeInfo)); 
    With TypeInfo DO begin 
      I:=SizeOf(TNameRec)*rtResourceCount; 
      TypeRead:=false; 
      IF (rtTypeID or $8000 = rtTypeID) Then begin 
        IF (Lo(rtTypeID)=Word(RT_ICON))       Then begin 
          FIconCount:=rtResourceCount; 
          GetMem(FIconsRes,I); 
          Read(FIconsRes^,I); 
          TypeRead:=True; 
        end; 
        IF (Lo(rtTypeID)=Word(RT_GROUP_ICON)) Then begin 
          FGroupIconCount:=rtResourceCount; 
          GetMem(FGroupIconsRes,I); 
          Read(FGroupIconsRes^,I); 
          TypeRead:=True; 
        end; 
      end; 
    end; 
    IF NOT TypeRead Then Seek(I,soFromCurrent); 
  end; 
end; 
 
(********************************************************************) 
(**                  T16BitWriter implementation                   **) 
(********************************************************************) 
 
constructor T16BitWriter.Create(AIconLib : TIconLibrary); 
Var 
  I : Integer; 
begin 
  {$IFDEF Writer16} Debugger.Enterproc('Constructor Create');{$ENDIF} 
  FIconLib:=AIconLib; 
  FIcons:=0; 
  FStream:=TMemoryStream.Create; 
  FOR I:=1 TO IconLib.Icons.Count DO 
    INC(FIcons,TMultiIcon(IconLib.Icons.Objects[I-1]).IconCount); 
  FAlignShift:=1; 
  GetMem(FOfs_Icons,FIcons*SizeOf(DWord)); 
  GetMem(FOfs_GIcons,IconLib.Icons.Count*SizeOf(DWord)); 
  FillChar(Null,SizeOf(Null),#0); 
  {$IFDEF Writer16} Debugger.Leaveproc('Constructor Create');{$ENDIF} 
end; 
 
procedure T16BitWriter.WriteShiftAlign; 
Var 
  I,J : Integer; 
  Ico : TMultiIcon; 
  IconDataSize : DWord; 
  SavedPos : Cardinal; 
begin 
  {$IFDEF Writer16} Debugger.Enterproc('WriteShiftAlign');{$ENDIF} 
  IconDataSize:=Stream.Position; 
  FOR I:=1 TO IconLib.Icons.Count DO begin 
    Ico:=TMultiIcon(IconLib.Icons.Objects[I-1]); 
    INC(FIcons,Ico.IconCount); 
    INC(IconDataSize,SizeOf(TIconHeader)); 
    FOR J:=1 TO Ico.IconCount DO begin 
      INC(IconDataSize,SizeOf(TResourceIconResInfo)); 
      INC(IconDataSize,Ico.IconResInfo[J-1].BytesInRes); 
    end; 
  end; 
  FAlignShift:=0; 
  While ((MaxWord shl FAlignShift) Operating System = Windows 
    Write(W,SizeOf(W)); 
    Write(Null,7); 
    W:=$3; // 3Eh -> expected Windows version number 
    Write(W,1); 
  end; 
  {$IFDEF Writer16} Debugger.Leaveproc('WriteHeader');{$ENDIF} 
end; 
 
procedure T16BitWriter.WriteResTable; 
var 
  W : Word; 
  DW : DWord; 
  I : Integer; 
  NameInfo : TNameRec; 
begin 
  {$IFDEF Writer16} Debugger.Enterproc('WriteResTable');{$ENDIF} 
  DW:=0; 
  W:=0; 
  With Stream DO begin 
    FShiftAlignOffs:=Position; 
    Write(W,SizeOf(W)); // rscAlignShift written later; 
    W:=$800E; 
    Write(W,SizeOf(W)); //rt_GroupIcon TypeInfo 
    W:=IconLib.Icons.Count; 
    Write(W,SizeOf(W)); //ResourceCount rt_GroupIcon 
    Write(DW,SizeOf(DW)); 
    FillChar(NameInfo,SizeOf(NameInfo),#0); 
    NameInfo.rnFlags:=$1C30; 
    NameInfo.rnOffset:=$FF; 
    NameInfo.rnLength:=$FF00; 
  {$IFDEF Writer16} Debugger.Enterproc('Loop 1');{$ENDIF} 
    FOR I:=1 TO IconLib.Icons.Count DO begin 
      NameInfo.rnID:=I or $8000; 
      FOfs_GIcons^[I-1]:=Position; 
      Write(NameInfo,SizeOf(NameInfo)); 
    end; 
  {$IFDEF Writer16} Debugger.Leaveproc('Loop 1');{$ENDIF} 
    W:=$8003; 
    Write(W,SizeOf(W)); //rt_Icon TypeInfo 
    W:=FIcons; 
    Write(W,SizeOf(W)); //ResourceCount rt_GroupIcon 
    Write(DW,SizeOf(DW)); 
  {$IFDEF Writer16} Debugger.Enterproc('Loop 2');{$ENDIF} 
    FOR I:=1 TO FIcons DO begin 
      NameInfo.rnID:=I or $8000; 
      FOfs_Icons^[I-1]:=Position; 
      Write(NameInfo,SizeOf(NameInfo)); 
    end; 
  {$IFDEF Writer16} Debugger.Leaveproc('Loop 2');{$ENDIF} 
    W:=0; 
    Write(W,SizeOf(W)); 
  end; 
  {$IFDEF Writer16} Debugger.Leaveproc('WriteResTable');{$ENDIF} 
end; 
 
procedure T16BitWriter.WriteNameTable; 
Var 
  B : byte; 
  I : Integer; 
  S : String; 
  Pos : Integer; 
  W : Word; 
begin 
  {$IFDEF Writer16} Debugger.Enterproc('WriteNameTable');{$ENDIF} 
  With Stream DO begin 
    Pos:=Position; 
    Position:=FNamesTableOffs; 
    W:=Pos-$80; 
    Write(W,SizeOf(Word)); 
    Position:=Pos; 
    B:=3; 
    Write(B,SizeOf(B)); 
    Write(IMAGE_NAMETABLE_ICL,3); 
    FOR I:=1 TO IconLib.Icons.Count DO begin 
      S:=IconLib.Icons.Strings[I-1]; 
      B:=Length(S); 
      Write(B,SizeOf(B)); 
      Write(Pointer(S)^,B) 
    end; 
    B:=0; 
    Write(B,SizeOf(B)); 
  end; 
  {$IFDEF Writer16} Debugger.Leaveproc('WriteNameTable');{$ENDIF} 
end; 
 
procedure T16BitWriter.Align; 
Var 
  C : Integer; 
begin 
  With Stream DO begin 
    C:=(Position shr FAlignShift); 
    IF (C shl FAlignShift)=Position Then exit; 
    INC(C); 
    C:=(C shl FAlignShift)-Position; 
    IF C>SizeOf(Null) Then begin 
      While (C>SizeOf(Null)) DO begin 
        Write(Null,SizeOf(Null)); 
        DEC(C,SizeOf(Null)); 
      end; 
    end; 
    Write(Null,C) 
  end; 
end; 
 
procedure T16BitWriter.WriteIconData; 
Var 
  IID : Word; 
  I,J : Integer; 
  Ico : TMultiIcon; 
  Header : TIconHeader; 
  ResInfo : TResourceIconResInfo; 
  SOffset,EOffset : DWord; 
  W : Word; 
begin 
  {$IFDEF Writer16} Debugger.Enterproc('WriteIconData');{$ENDIF} 
  Header.wReserved:=0; 
  Header.wType:=1; 
  IID:=1; 
  Align; 
  With Stream DO begin 
    FOR I:=1 TO IconLib.Icons.Count DO begin 
      SOffset:=Position; 
      Ico:=TMultiIcon(IconLib.Icons.Objects[I-1]); 
      Header.wCount:=Ico.IconCount; 
      Write(Header,SizeOf(Header)); 
      FOR J:=1 TO Header.wCount DO begin 
        ResInfo.ResInfo:=Ico.IconResInfo[J-1]; 
        ResInfo.ID:=IID; 
        Write(ResInfo,SizeOf(ResInfo)); 
        INC(IID); 
      end; 
      Align; 
      EOffset:=Position; 
      UpdateTableEntry(FOfs_GIcons^[I-1],SOffset,EOffset); 
    end; 
    IID:=1; 
    FOR I:=1 TO IconLib.Icons.Count DO begin 
      Ico:=TMultiIcon(IconLib.Icons.Objects[I-1]); 
      FOR J:=1 TO Ico.IconCount DO begin 
        SOffset:=Position; 
        Ico.WriteIconDataToStream(Stream,J-1); 
        Align; 
        EOffset:=Position; 
        UpdateTableEntry(FOfs_Icons^[IID-1],SOffset,EOffset); 
        INC(IID); 
      end; 
    end; 
    W:=0; 
    Write(W,SizeOf(W)); 
  end; 
  {$IFDEF Writer16} Debugger.Leaveproc('WriteIconData');{$ENDIF} 
end; 
 
procedure T16BitWriter.UpdateTableEntry(EntryPos : DWord;StartOffset,EndOffset : DWord); 
Var 
  OldPos : cardinal; 
  W : Word; 
begin 
  With Stream DO begin 
    OldPos:=Position; 
    try 
      Position:=EntryPos; 
      W:=StartOffset shr FAlignShift; 
      Write(W,SizeOf(Word)); 
      W:=(EndOffset-StartOffset) shr FAlignShift; 
      Write(W,SizeOf(Word)); 
    finally 
      Position:=OldPos; 
    end; 
  end; 
end; 
 
(********************************************************************) 
(**                    TICL16Icon implementation                   **) 
(********************************************************************) 
 
constructor TICL16Icon.ICLCreate(ICLReader : T16BitReader;Index : Word); 
Var 
  GroupIcon : TMemoryStream; 
begin 
  FICLReader:=ICLReader; 
  CreateDefaults; 
  Icons:=TMemoryStream.Create; 
  GroupIcon:=TMemoryStream.Create; 
  try 
    ICLReader.ReadResource(Index,True,GroupIcon,FResname); 
    GroupIcon.Position:=0; 
    InitHeaders(GroupIcon); 
  finally 
    GroupIcon.Free; 
  end; 
end; 
 
destructor TICL16Icon.Destroy; 
begin 
  Icons.free; 
  inherited; 
end; 
 
function TICL16Icon.GeTICL16IconResInfo(Index : Word) : TFileIconResInfo; 
begin 
  IF Index>=IconCount Then exit; 
  Result:=PFileIconDirList(IconDirList)^[Index]; 
end; 
 
function TICL16Icon.GetHIcon(Index : Word) : HIcon; 
begin 
  Result:=0; 
  IF Index>=IconCount Then exit; 
  IF IconHandleList^[Index]=0 Then begin 
    with ICLIconResInfo[Index] do begin 
      Icons.Position:=dwImageOffset; 
      Result:=CreateIconFromStream(Icons,ResInfo.BytesInres,ResInfo); 
      IconHandleList^[Index]:=Result; 
    end; 
  end else 
    Result:=IconHandleList^[Index]; 
end; 
 
function TICL16Icon.GetIconSize(Index : Word) : TSize; 
begin 
  with IconResInfo[Index] do begin 
    Result.cx:=Width; 
    Result.cy:=Height; 
  end; 
end; 
 
procedure TICL16Icon.LoadIconResInfos(Stream : TStream;Var Valid : Boolean;Var Count : Word); 
Var 
  I,ID          : Word; 
  StartHeader : TIconHeader; 
  TmpDirListLen  : Integer; 
  TmpIconDirList : PResourceIconDirList; 
  S : String; 
begin 
  With Stream DO begin 
    Read(StartHeader,sizeOf(StartHeader)); 
    Valid:=((StartHeader.wReserved=0) AND (StartHeader.wType=1)); 
    IF NOT Valid Then exit; 
    Count:=StartHeader.wCount; 
    TmpDirListLen:=Count*SizeOf(TResourceIconResInfo); 
    DirListLen   :=Count*SizeOf(TFileIconResInfo); 
    HandleListLen:=Count*SizeOf(HIcon); 
    TmpIconDirList:=AllocMem(TmpDirListlen); 
    IconDirList   :=AllocMem(DirListlen); 
    IconHandleList:=AllocMem(HandleListlen); 
    FOR I:=1 TO IconCount DO IconHandleList^[I-1]:=0; 
    ReadBuffer(TmpIconDirList^,TmpDirListLen); 
  end; 
  FOR I:=1 TO IconCount DO begin 
    PFileIconDirList(IconDirList)^[I-1].ResInfo:=TmpIconDirList^[I-1].ResInfo; 
    PFileIconDirList(IconDirList)^[I-1].dwImageOffset:=Icons.Position; 
    ID:=FICLReader.GetResourceIndex(TmpIconDirList^[I-1].ID,False); 
    IF ID>=0 Then FICLReader.ReadResource(ID,False,Icons,S); 
  end; 
end; 
 
function TICL16Icon.GetIconResInfo(Index : Word) : TIconResInfo; 
begin 
  IF Index>=IconCount Then exit; 
  Result:=PFileIconDirList(IconDirList)^[Index].ResInfo; 
end; 
 
procedure TICL16Icon.WriteIconDataToStream(Stream : TStream;Index : Integer); 
begin 
  IF Index>=IconCount Then exit; 
  with ICLIconResInfo[Index] do begin 
    Icons.Position:=dwImageOffset; 
    Stream.CopyFrom(Icons,ResInfo.BytesInres); 
  end; 
end; 
 
initialization 
{$IfDEF Overseer} 
  Debugger.Clear; 
{$EndIf} 
end.