Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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