home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1996 August / VPR9608A.BIN / del20try / install / data.z / EXEIMAGE.PAS < prev    next >
Pascal/Delphi Source File  |  1996-05-08  |  20KB  |  776 lines

  1. unit ExeImage;
  2.  
  3. interface
  4.  
  5. uses
  6.   TypInfo, Classes, SysUtils, Windows, Graphics, RXTypes;
  7.  
  8. type
  9.  
  10. { Exceptions }
  11.  
  12.   EExeError = class(Exception);
  13.  
  14. { Forward Declarations }
  15.  
  16.   TResourceItem = class;
  17.   TResourceClass = class of TResourceItem;
  18.   TResourceList = class;
  19.  
  20. { TExeImage }
  21.  
  22.   TExeImage = class(TComponent)
  23.   private
  24.     FFileName: string;
  25.     FFileHandle: THandle;
  26.     FFileMapping: THandle;
  27.     FFileBase: Pointer;
  28.     FDosHeader: PIMAGE_DOS_HEADER;
  29.     FNTHeader: PIMAGE_NT_HEADERS;
  30.     FSections: TList;
  31.     FResourceList: TResourceList;
  32.     FIconResources: TResourceItem;
  33.     FCursorResources: TResourceItem;
  34.     FResourceBase: Longint;
  35.     FResourceRVA: Longint;
  36.     function GetResourceList: TResourceList;
  37.     function GetSectionHdr(const SectionName: string;
  38.       var Header: PIMAGE_SECTION_HEADER): Boolean;
  39.   public
  40.     constructor Create(AOwner: TComponent; const AFileName: string);
  41.     destructor Destroy;
  42.     property FileName: string read FFileName;
  43.     property Resources: TResourceList read GetResourceList;
  44.   end;
  45.  
  46. { TResourceItem }
  47.  
  48.   TResourceItem = class(TComponent)
  49.   private
  50.     FList: TResourceList;
  51.     FDirEntry: PIMAGE_RESOURCE_DIRECTORY_ENTRY;
  52.     function DataEntry: PIMAGE_RESOURCE_DATA_ENTRY;
  53.     function FExeImage: TExeImage;
  54.     function FirstChildDirEntry: PIMAGE_RESOURCE_DIRECTORY_ENTRY;
  55.     function GetResourceItem(Index: Integer): TResourceItem;
  56.     function GetResourceType: TResourceType;
  57.   protected
  58.     function GetName: string; virtual;
  59.     function GetResourceList: TResourceList; virtual;
  60.   public
  61.     constructor Create(AOwner: TComponent; ADirEntry: Pointer);
  62.     function IsList: Boolean; virtual;
  63.     function Offset: Integer;
  64.     function Size: Integer;
  65.     function RawData: Pointer;
  66.     function ResTypeStr: string;
  67.     procedure SaveToFile(const FileName: string);
  68.     procedure SaveToStream(Stream: TStream);
  69.     property Items[Index: Integer]: TResourceItem read GetResourceItem; default;
  70.     property List: TResourceList read GetResourceList;
  71.     property Name: string read GetName;
  72.     property ResType: TResourceType read GetResourceType;
  73.   end;
  74.  
  75. { TIconResource }
  76.  
  77.   TIconResource = class(TResourceItem)
  78.   protected
  79.     function GetResourceList: TResourceList; override;
  80.   public
  81.     function IsList: Boolean; override;
  82.   end;
  83.  
  84. { TIconResEntry }
  85.  
  86.   TIconResEntry = class(TResourceItem)
  87.   protected
  88.     FResInfo: PIconResInfo;
  89.     function GetName: string; override;
  90.     procedure AssignTo(Dest: TPersistent); override;
  91.   public
  92.     procedure SaveToStream(Stream: TStream);
  93.   end;
  94.  
  95. { TCursorResource }
  96.  
  97.   TCursorResource = class(TIconResource)
  98.   protected
  99.     function GetResourceList: TResourceList; override;
  100.   end;
  101.  
  102. { TCursorResEntry }
  103.  
  104.   TCursorResEntry = class(TIconResEntry)
  105.   protected
  106.     FResInfo: PCursorResInfo;
  107.     function GetName: string; override;
  108.   end;
  109.  
  110. { TBitmapResource }
  111.  
  112.   TBitMapResource = class(TResourceItem)
  113.   protected
  114.     procedure AssignTo(Dest: TPersistent); override;
  115.   public
  116.     procedure SaveToStream(Stream: TStream);
  117.   end;
  118.  
  119. { TStringResource }
  120.  
  121.   TStringResource = class(TResourceItem)
  122.   protected
  123.     procedure AssignTo(Dest: TPersistent); override;
  124.   end;
  125.  
  126. { TMenuResource }
  127.  
  128.   TMenuResource = class(TResourceItem)
  129.   private
  130.     FNestStr: string;
  131.     FNestLevel: Integer;
  132.     procedure SetNestLevel(Value: Integer);
  133.   protected
  134.     procedure AssignTo(Dest: TPersistent); override;
  135.     property NestLevel: Integer read FNestLevel write SetNestLevel;
  136.     property NestStr: string read FNestStr;
  137.   end;
  138.  
  139. { TResourceList }
  140.  
  141.   TResourceList = class(TComponent)
  142.   protected
  143.     FList: TList;
  144.     FResDir: PIMAGE_RESOURCE_DIRECTORY;
  145.     FExeImage: TExeImage;
  146.     FResType: Integer;
  147.     function List: TList; virtual;
  148.     function GetResourceItem(Index: Integer): TResourceItem;
  149.   public
  150.     constructor Create(AOwner: TComponent; ResDirOfs: Longint;
  151.       AExeImage: TExeImage);
  152.     destructor Destroy; override;
  153.     function Count: Integer;
  154.     property Items[Index: Integer]: TResourceItem read GetResourceItem; default;
  155.   end;
  156.  
  157. { TIconResourceList }
  158.  
  159.   TIconResourceList = class(TResourceList)
  160.   protected
  161.     function List: TList; override;
  162.   end;
  163.  
  164. { TCursorResourceList }
  165.  
  166.   TCursorResourceList = class(TResourceList)
  167.   protected
  168.     function List: TList; override;
  169.   end;
  170.  
  171. implementation
  172.  
  173. { This function maps a resource type to the associated resource class }
  174.  
  175. function GetResourceClass(ResType: Integer): TResourceClass;
  176. const
  177.   TResourceClasses: array[TResourceType] of TResourceClass = (
  178.     TResourceItem,      { rtUnknown0 }
  179.     TCursorResEntry,    { rtCursorEntry }
  180.     TBitmapResource,    { rtBitmap }
  181.     TIconResEntry,      { rtIconEntry }
  182.     TMenuResource,      { rtMenu }
  183.     TResourceItem,      { rtDialog }
  184.     TStringResource,    { rtString }
  185.     TResourceItem,      { rtFontDir }
  186.     TResourceItem,      { rtFont }
  187.     TResourceItem,      { rtAccelerators }
  188.     TResourceItem,      { rtRCData }
  189.     TResourceItem,      { rtMessageTable }
  190.     TCursorResource,    { rtGroupCursor }
  191.     TResourceItem,      { rtUnknown13 }
  192.     TIconResource,      { rtIcon }
  193.     TResourceItem,      { rtUnknown15 }
  194.     TResourceItem);     { rtVersion }
  195. begin
  196.   if (ResType >= Integer(Low(TResourceType))) and
  197.     (ResType <= Integer(High(TResourceType))) then
  198.     Result := TResourceClasses[TResourceType(ResType)] else
  199.     Result := TResourceItem;
  200. end;
  201.  
  202. { Utility Functions }
  203.  
  204. function Min(A, B: Integer): Integer;
  205. begin
  206.   if A < B then Result := A
  207.   else Result := B;
  208. end;
  209.  
  210. { This function checks if an offset is a string name, or a directory }
  211. {Assumes: IMAGE_RESOURCE_NAME_IS_STRING = IMAGE_RESOURCE_DATA_IS_DIRECTORY}
  212.  
  213. function HighBitSet(L: Longint): Boolean;
  214. begin
  215.   Result := (L and IMAGE_RESOURCE_DATA_IS_DIRECTORY) <> 0;
  216. end;
  217.  
  218. function StripHighBit(L: Longint): Longint;
  219. begin
  220.   Result := L and IMAGE_OFFSET_STRIP_HIGH;
  221. end;
  222.  
  223. function StripHighPtr(L: Longint): Pointer;
  224. begin
  225.   Result := Pointer(L and IMAGE_OFFSET_STRIP_HIGH);
  226. end;
  227.  
  228. { This function converts a pointer to a wide char string into a pascal string }
  229.  
  230. function WideCharToStr(WStr: PWChar; Len: Integer): string;
  231. begin
  232.   if Len = 0 then 
  233.     Len := lstrlenw(WStr);
  234.   SetLength(Result, Len);
  235.   WideCharToMultiByte(CP_ACP, 0, WStr, Len, PChar(Result), Len, nil, nil);
  236. end;
  237.  
  238. { Exceptions }
  239.  
  240. procedure ExeError(const ErrMsg: string);
  241. begin
  242.   raise EExeError.Create(ErrMsg);
  243. end;
  244.  
  245. { TExeImage }
  246.  
  247. constructor TExeImage.Create(AOwner: TComponent; const AFileName: string);
  248. begin
  249.   inherited Create(AOwner);
  250.   FFileName := AFileName;
  251.   FFileHandle := CreateFile(PChar(FFileName), GENERIC_READ, FILE_SHARE_READ,
  252.     nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  253.   if FFileHandle = INVALID_HANDLE_VALUE then ExeError('Couldn''t open: '+FFileName);
  254.     FFileMapping := CreateFileMapping(FFileHandle, nil, PAGE_READONLY, 0, 0, nil);
  255.   if FFileMapping = 0 then ExeError('CreateFileMapping failed');
  256.     FFileBase := MapViewOfFile(FFileMapping, FILE_MAP_READ, 0, 0, 0);
  257.   if FFileBase = nil then ExeError('MapViewOfFile failed');
  258.     FDosHeader := PIMAGE_DOS_HEADER(FFileBase);
  259.   if not FDosHeader.e_magic = IMAGE_DOS_SIGNATURE then
  260.     ExeError('unrecognized file format');
  261.   FNTHeader := PIMAGE_NT_HEADERS(Longint(FDosHeader) + FDosHeader.e_lfanew);
  262.   if IsBadReadPtr(FNTHeader, sizeof(IMAGE_NT_HEADERS)) or
  263.      (FNTHeader.Signature <> IMAGE_NT_SIGNATURE) then
  264.     ExeError('Not a PE (WIN32 Executable) file');
  265.  end;
  266.  
  267. destructor TExeImage.Destroy;
  268. begin
  269.   if FFileHandle <> INVALID_HANDLE_VALUE then
  270.   begin
  271.     UnmapViewOfFile(FFileBase);
  272.     CloseHandle(FFileMapping);
  273.     CloseHandle(FFileHandle);
  274.   end;
  275.   inherited Destroy;
  276. end;
  277.  
  278. function TExeImage.GetSectionHdr(const SectionName: string;
  279.   var Header: PIMAGE_SECTION_HEADER): Boolean;
  280. var
  281.   I: Integer;
  282. begin
  283.   Header := PIMAGE_SECTION_HEADER(FNTHeader);
  284.   Inc(PIMAGE_NT_HEADERS(Header));
  285.   Result := True;
  286.   for I := 0 to FNTHeader.FileHeader.NumberOfSections - 1 do
  287.   begin
  288.     if Strlicomp(Header.Name, PChar(SectionName), IMAGE_SIZEOF_SHORT_NAME) = 0 then Exit;
  289.     Inc(Header);
  290.   end;
  291.   Result := False;
  292. end;
  293.  
  294. function TExeImage.GetResourceList: TResourceList;
  295. var
  296.   ResSectHdr: PIMAGE_SECTION_HEADER;
  297. begin
  298.   if not Assigned(FResourceList) then
  299.   begin
  300.     if GetSectionHdr('.rsrc', ResSectHdr) then
  301.     begin
  302.       FResourceBase := ResSectHdr.PointerToRawData + Longint(FDosHeader);
  303.       FResourceRVA := ResSectHdr.VirtualAddress;
  304.       FResourceList := TResourceList.Create(Self, FResourceBase, Self);
  305.     end
  306.     else
  307.       ExeError('No resources in this file.');
  308.   end;
  309.   Result := FResourceList;
  310. end;
  311.  
  312. { TResourceItem }
  313.  
  314. constructor TResourceItem.Create(AOwner: TComponent; ADirEntry: Pointer);
  315. begin
  316.   inherited Create(AOwner);
  317.   FDirEntry := ADirEntry;
  318. end;
  319.  
  320. function TResourceItem.DataEntry: PIMAGE_RESOURCE_DATA_ENTRY;
  321. begin
  322.   Result := PIMAGE_RESOURCE_DATA_ENTRY(FirstChildDirEntry.OffsetToData
  323.     + FExeImage.FResourceBase);
  324. end;
  325.  
  326. function TResourceItem.FirstChildDirEntry: PIMAGE_RESOURCE_DIRECTORY_ENTRY;
  327. begin
  328.   Result := PIMAGE_RESOURCE_DIRECTORY_ENTRY(StripHighBit(FDirEntry.OffsetToData) +
  329.     FExeImage.FResourceBase + SizeOf(IMAGE_RESOURCE_DIRECTORY));
  330. end;
  331.  
  332. function TResourceItem.FExeImage: TExeImage;
  333. begin
  334.   Result := (Owner as TResourceList).FExeImage;
  335. end;
  336.  
  337. function TResourceItem.GetResourceItem(Index: Integer): TResourceItem;
  338. begin
  339.   Result := List[Index];
  340. end;
  341.  
  342. function TResourceItem.GetResourceType: TResourceType;
  343. begin
  344.   Result := TResourceType((Owner as TResourceList).FResType);
  345. end;
  346.  
  347. function TResourceItem.IsList: Boolean;
  348. begin
  349.   Result := HighBitSet(FirstChildDirEntry.OffsetToData);
  350. end;
  351.  
  352. function TResourceItem.GetResourceList: TResourceList;
  353. begin
  354.   if not IsList then ExeError('ResourceItem is not a list');
  355.   if not Assigned(FList) then
  356.     FList := TResourceList.Create(Self, StripHighBit(FDirEntry.OffsetToData) +
  357.       FExeImage.FResourceBase, FExeImage);
  358.   Result := FList;
  359. end;
  360.  
  361. function TResourceItem.GetName: string;
  362. var
  363.   PDirStr: PIMAGE_RESOURCE_DIR_STRING_U;
  364. begin
  365.   { Check for Level1 entries, these are resource types. }
  366.   if (Owner.Owner = FExeImage) and not HighBitSet(FDirEntry.Name) and
  367.     (FDirEntry.Name <= 16) then
  368.   begin
  369.     Result := Copy(GetEnumName(TypeInfo(TResourceType), FDirEntry.Name), 3, 20);
  370.     Exit;
  371.   end;
  372.  
  373.   if HighBitSet(FDirEntry.Name) then
  374.   begin
  375.     PDirStr := PIMAGE_RESOURCE_DIR_STRING_U(StripHighBit(FDirEntry.Name) +
  376.       FExeImage.FResourceBase);
  377.     Result := WideCharToStr(@PDirStr.NameString, PDirStr.Length);
  378.     Exit;
  379.   end;
  380.   Result := Format('%d', [FDirEntry.Name]);
  381. end;
  382.  
  383. function TResourceItem.Offset: Integer;
  384. begin
  385.   if IsList then
  386.     Result := StripHighBit(FDirEntry.OffsetToData)
  387.   else
  388.     Result := DataEntry.OffsetToData;
  389. end;
  390.  
  391. function TResourceItem.RawData: Pointer;
  392. begin
  393.   with FExeImage do
  394.     Result := pointer(FResourceBase - FResourceRVA + DataEntry.OffsetToData);
  395. end;
  396.  
  397. function TResourceItem.ResTypeStr: string;
  398. begin
  399.   Result := Copy(GetEnumName(TypeInfo(TResourceType), Ord(ResType)), 3, 20);
  400. end;
  401.  
  402. procedure TResourceItem.SaveToFile(const FileName: string);
  403. var
  404.   FS: TFileStream;
  405. begin
  406.   FS := TFileStream.Create(FileName, fmCreate);
  407.   try
  408.     Self.SaveToStream(FS);
  409.   finally
  410.     FS.Free;
  411.   end;
  412. end;
  413.  
  414. procedure TResourceItem.SaveToStream(Stream: TStream);
  415. begin
  416.   Stream.Write(RawData^, Size);
  417. end;
  418.  
  419. function TResourceItem.Size: Integer;
  420. begin
  421.   if IsList then
  422.     Result := 0
  423.   else
  424.     Result := DataEntry.Size;
  425. end;
  426.  
  427. { TBitmapResource }
  428.  
  429. procedure TBitmapResource.AssignTo(Dest: TPersistent);
  430. var
  431.   MemStr: TMemoryStream;
  432.   BitMap: TBitMap;
  433. begin
  434.   if (Dest is TPicture) then
  435.   begin
  436.     BitMap := TPicture(Dest).Bitmap;
  437.     MemStr := TMemoryStream.Create;
  438.     try
  439.       SaveToStream(MemStr);
  440.       MemStr.Seek(0,0);
  441.       BitMap.LoadFromStream(MemStr);
  442.     finally
  443.       MemStr.Free;
  444.     end
  445.   end
  446.   else
  447.     inherited AssignTo(Dest);
  448. end;
  449.  
  450. procedure TBitmapResource.SaveToStream(Stream: TStream);
  451. var
  452.   BH: TBitmapFileHeader;
  453. begin
  454.   FillChar(BH, sizeof(BH), #0);
  455.   BH.bfType := $4D42;
  456.   BH.bfSize := Self.Size + SizeOf(BH);
  457.   Stream.Write(BH, SizeOf(BH));
  458.   Stream.Write(RawData^, Self.Size);
  459. end;
  460.  
  461.  
  462. { TIconResource }
  463.  
  464. function TIconResource.GetResourceList: TResourceList;
  465. begin
  466.   if not Assigned(FList) then
  467.     FList := TIconResourceList.Create(Owner, LongInt(RawData), FExeImage);
  468.   Result := FList;
  469. end;
  470.  
  471. function TIconResource.IsList: Boolean;
  472. begin
  473.   Result := True;
  474. end;
  475.  
  476. { TIconResEntry }
  477.  
  478. procedure TIconResEntry.AssignTo(Dest: TPersistent);
  479. var
  480.   hIco: HIcon;
  481. begin
  482.   if Dest is TPicture then
  483.   begin
  484.     hIco := CreateIconFromResource(RawData, Size, (ResType = rtIconEntry), $30000);
  485.     TPicture(Dest).Icon.Handle := hIco;
  486.   end
  487.   else
  488.     inherited AssignTo(Dest);
  489. end;
  490.  
  491. function TIconResEntry.GetName: string;
  492. begin
  493.   if Assigned(FResInfo) then
  494.     with FResInfo^ do
  495.       Result := Format('%d X %d %d Colors', [bWidth, bHeight, bColorCount])
  496.   else
  497.     Result := inherited GetName;
  498. end;
  499.  
  500. procedure TIconResEntry.SaveToStream(Stream: TStream);
  501. begin
  502.   with TIcon.Create do
  503.   try
  504.     Handle := CreateIconFromResource(RawData, Self.Size, (ResType <> rtIcon), $30000);
  505.     SaveToStream(Stream);
  506.   finally
  507.     Free;
  508.   end;
  509. end;
  510.  
  511. { TCursorResource }
  512.  
  513. function TCursorResource.GetResourceList: TResourceList;
  514. begin
  515.   if not Assigned(FList) then
  516.     FList := TCursorResourceList.Create(Owner, LongInt(RawData), FExeImage);
  517.   Result := FList;
  518. end;
  519.  
  520. { TCursorResEntry }
  521.  
  522. function TCursorResEntry.GetName: string;
  523. begin
  524.   if Assigned(FResInfo) then
  525.     with FResInfo^ do
  526.       Result := Format('%d X %d %d Bit(s)', [wWidth, wWidth, wBitCount])
  527.   else
  528.     Result := inherited GetName;
  529. end;
  530.  
  531. { TStringResource }
  532.  
  533. procedure TStringResource.AssignTo(Dest: TPersistent);
  534. var
  535.   P: PWChar;
  536.   ID: Integer;
  537.   Cnt: Integer;
  538.   Len: Word;
  539. begin
  540.   if (Dest is TStrings) then
  541.     with TStrings(Dest) do
  542.     begin
  543.       BeginUpdate;
  544.       try
  545.         Clear;
  546.         P := RawData;
  547.         Cnt := 0;
  548.         while Cnt < StringsPerBlock do
  549.         begin
  550.           Len := Word(P^);
  551.           Inc(P);
  552.           if Len > 0 then
  553.           begin
  554.             ID := ((FDirEntry.Name - 1) shl 4) + Cnt;
  555.             Add(Format('%d,  "%s"', [ID, WideCharToStr(P, Len)]));
  556.             Inc(P, Len);
  557.           end;
  558.           Inc(Cnt);
  559.         end;
  560.       finally
  561.         EndUpdate;
  562.       end;
  563.     end
  564.   else
  565.     inherited AssignTo(Dest);
  566. end;
  567.  
  568. { TMenuResource }
  569.  
  570. procedure TMenuResource.SetNestLevel(Value: Integer);
  571. begin
  572.   FNestLevel := Value;
  573.   SetLength(FNestStr, Value * 2);
  574.   FillChar(FNestStr[1], Value * 2, ' ');
  575. end;
  576.  
  577. procedure TMenuResource.AssignTo(Dest: TPersistent);
  578. var
  579.   IsPopup: Boolean;
  580.   Len: Word;
  581.   MenuData: PWord;
  582.   MenuEnd: PChar;
  583.   MenuText: PWChar;
  584.   MenuID: Word;
  585.   MenuFlags: Word;
  586.   S: string;
  587. begin
  588.   if (Dest is TStrings) then
  589.     with TStrings(Dest) do
  590.     begin
  591.       BeginUpdate;
  592.       try
  593.         Clear;
  594.         MenuData := RawData;
  595.         MenuEnd := PChar(RawData) + Size;
  596.         Inc(MenuData, 2);
  597.         NestLevel := 0;
  598.         while PChar(MenuData) < MenuEnd do
  599.         begin
  600.           MenuFlags := MenuData^;
  601.           Inc(MenuData);
  602.           IsPopup := (MenuFlags and MF_POPUP) = MF_POPUP;
  603.           if not IsPopup then
  604.           begin
  605.             MenuID := MenuData^;
  606.             Inc(MenuData);
  607.           end;
  608.           MenuText := PWChar(MenuData);
  609.           Len := lstrlenw(MenuText);
  610.           if Len = 0 then
  611.             S := 'MENUITEM SEPARATOR'
  612.           else
  613.           begin
  614.             S := WideCharToStr(MenuText, Len);
  615.             if IsPopup then
  616.               S := Format('POPUP "%s"', [S]) else
  617.               S := Format('MENUITEM "%s",  %d', [S, MenuID]);
  618.           end;
  619.           Inc(MenuData, Len + 1);
  620.           Add(NestStr + S);
  621.           if (MenuFlags and MF_END) = MF_END then
  622.           begin
  623.             NestLevel := NestLevel - 1;
  624.             Add(NestStr + 'ENDPOPUP');
  625.           end;
  626.           if IsPopup then
  627.             NestLevel := NestLevel + 1;
  628.         end;
  629.       finally
  630.         EndUpdate;
  631.       end;
  632.     end
  633.   else
  634.     inherited AssignTo(Dest);
  635. end;
  636.  
  637. { TResourceList }
  638.  
  639. constructor TResourceList.Create(AOwner: TComponent; ResDirOfs: Longint;
  640.   AExeImage: TExeImage);
  641. var
  642.   DirEntry: PIMAGE_RESOURCE_DIRECTORY_ENTRY;
  643. begin
  644.   inherited Create(AOwner);
  645.   FExeImage := AExeImage;
  646.   FResDir := Pointer(ResDirOfs);
  647.   if AOwner <> AExeImage then
  648.     if AOwner.Owner.Owner = AExeImage then
  649.     begin
  650.       DirEntry := PIMAGE_RESOURCE_DIRECTORY_ENTRY(FResDir);
  651.       inc(PIMAGE_RESOURCE_DIRECTORY(DirEntry));
  652.       FResType := TResourceItem(Owner).FDirEntry.Name;
  653.     end
  654.     else
  655.       FResType := (AOwner.Owner.Owner as TResourceList).FResType;
  656. end;
  657.  
  658. destructor TResourceList.Destroy;
  659. begin
  660.   inherited Destroy;
  661.   FList.Free;
  662. end;
  663.  
  664. function TResourceList.List: TList;
  665. var
  666.   I: Integer;
  667.   DirEntry: PIMAGE_RESOURCE_DIRECTORY_ENTRY;
  668.   DirCnt: Integer;
  669.   ResItem: TResourceItem;
  670. begin
  671.   if not Assigned(FList) then
  672.   begin
  673.     FList := TList.Create;
  674.     DirEntry := PIMAGE_RESOURCE_DIRECTORY_ENTRY(FResDir);
  675.     inc(PIMAGE_RESOURCE_DIRECTORY(DirEntry));
  676.     DirCnt := FResDir.NumberOfNamedEntries + FResDir.NumberOfIdEntries - 1;
  677.     for I := 0 to DirCnt do
  678.     begin
  679.       { Handle Cursors and Icons specially }
  680.       ResItem := GetResourceClass(FResType).Create(Self, DirEntry);
  681.       if Owner = FExeImage then
  682.         if (TResourceType(DirEntry.Name) in [rtCursorEntry, rtIconEntry]) then
  683.         begin
  684.           if TResourceType(DirEntry.Name) = rtCursorEntry then
  685.             FExeImage.FCursorResources := ResItem else
  686.             FExeImage.FIconResources := ResItem;
  687.           Inc(DirEntry);
  688.           Continue;
  689.         end;
  690.       FList.Add(ResItem);
  691.       Inc(DirEntry);
  692.     end;
  693.   end;
  694.   Result := FList;
  695. end;
  696.  
  697. function TResourceList.Count: Integer;
  698. begin
  699.   Result := List.Count;
  700. end;
  701.  
  702. function TResourceList.GetResourceItem(Index: Integer): TResourceItem;
  703. begin
  704.   Result := List[Index];
  705. end;
  706.  
  707. { TIconResourceList }
  708.  
  709. function TIconResourceList.List: TList;
  710. var
  711.   I,  J, Cnt: Integer;
  712.   ResData: PIconResInfo;
  713.   ResList: TResourceList;
  714.   ResOrd: Integer;
  715.   IconResource: TIconResEntry;
  716. begin
  717.   if not Assigned(FList) then
  718.   begin
  719.     FList := TList.Create;
  720.     Cnt := PIconHeader(FResDir).wCount;
  721.     PChar(ResData) := PChar(FResDir) + SizeOf(TIconHeader);
  722.     ResList := FExeImage.FIconResources.List;
  723.     for I := 0 to Cnt - 1 do
  724.     begin
  725.       ResOrd := ResData.wNameOrdinal;
  726.       for J := 0 to ResList.Count - 1 do
  727.       begin
  728.         if ResOrd = ResList[J].FDirEntry.Name then
  729.         begin
  730.           IconResource := ResList[J] as TIconResEntry;
  731.           IconResource.FResInfo := ResData;
  732.           FList.Add(IconResource);
  733.         end;
  734.       end;
  735.       Inc(ResData);
  736.     end;
  737.   end;
  738.   Result := FList;
  739. end;
  740.  
  741. { TCursorResourceList }
  742.  
  743. function TCursorResourceList.List: TList;
  744. var
  745.   I, J, Cnt: Integer;
  746.   ResData: PCursorResInfo;
  747.   ResList: TResourceList;
  748.   ResOrd: Integer;
  749.   CursorResource: TCursorResEntry;
  750. begin
  751.   if not Assigned(FList) then
  752.   begin
  753.     FList := TList.Create;
  754.     Cnt := PIconHeader(FResDir).wCount;
  755.     PChar(ResData) := PChar(FResDir) + SizeOf(TIconHeader);
  756.     ResList := FExeImage.FCursorResources.List;
  757.     for I := 0 to Cnt - 1 do
  758.     begin
  759.       ResOrd := ResData.wNameOrdinal;
  760.       for J := 0 to ResList.Count - 1 do
  761.       begin
  762.         if ResOrd = ResList[J].FDirEntry.Name then
  763.         begin
  764.           CursorResource := ResList[J] as TCursorResEntry;
  765.           CursorResource.FResInfo := ResData;
  766.           FList.Add(CursorResource);
  767.         end;
  768.       end;
  769.       Inc(ResData);
  770.     end;
  771.   end;
  772.   Result := FList;
  773. end;
  774.  
  775. end.
  776.