1

In a Delphi package, I have a .RC file, with following content:

STRINGTABLE
BEGIN
1000, "First line."
1001, "Second line"
1002, "Last line"
END

The .RC file was included in .dpk source, and the following command is fully functional:

LoadStr(1000) {returns "First line."}

I want to get a complete list of lines in string table. Using EnumResourceNames, it just returns content of default .res file (forms contents, etc). No content of .RC returned using EnumResourceNames.

Here is the code calling EnumResourceNames:

unit uxbResources;

interface

uses
  System.SysUtils, System.Classes, WinApi.Windows;

type
  TxbResources = class
  private
    FItems: TStringList;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Load(const AHandle: THandle);
    property Items: TStringList read FItems;
  end;


implementation

function EnumResNamesProc( module: HMODULE; restype, resname: PChar; list: TStrings): Integer; stdcall;
begin
  if HiWord( Cardinal(resname) ) <> 0 then
    list.add( '  '+resname )
  else
    list.add( format('  #%d',[loword(cardinal(resname))]));
  result := 1;
end;

function StockResourceType( restype: PChar ): string;
const
  restypenames: array [1..22] of string = (
    'RT_CURSOR', //       = MakeIntResource(1);
    'RT_BITMAP', //       = MakeIntResource(2);
    'RT_ICON',   //       = MakeIntResource(3);
    'RT_MENU',   //       = MakeIntResource(4);
    'RT_DIALOG', //       = MakeIntResource(5);
    'RT_STRING', //       = MakeIntResource(6);
    'RT_FONTDIR',//       = MakeIntResource(7);
    'RT_FONT',   //       = MakeIntResource(8);
    'RT_ACCELERATOR',//   = MakeIntResource(9);
    'RT_RCDATA', //       = MakeIntResource(10);
    'RT_MESSAGETABLE',//  = MakeIntResource(11);
    // DIFFERENCE = 11;
    'RT_GROUP_CURSOR',// = MakeIntResource(DWORD(RT_CURSOR + DIFFERENCE));
    'UNKNOWN',        // 13 not used
    'RT_GROUP_ICON',  //   = MakeIntResource(DWORD(RT_ICON + DIFFERENCE));
    'UNKNOWN',        // 15 not used
    'RT_VERSION',     // = MakeIntResource(16);
    'RT_DLGINCLUDE',  // = MakeIntResource(17);
    'UNKNOWN',
    'RT_PLUGPLAY',    // = MakeIntResource(19);
    'RT_VXD',         // = MakeIntResource(20);
    'RT_ANICURSOR',   // = MakeIntResource(21);
    'RT_ANIICON'     // = MakeIntResource(22);
  );
var
  resid: Cardinal absolute restype;
begin
  if resid In [1..22] then
    result := restypenames[resid]
  else
    result := 'UNKNOWN';
end;

function enumResTypesProc( module: HMODULE; restype: PChar; list: TStrings): Integer; stdcall;
var
  s: string;
begin
  if HiWord( cardinal(restype) ) <> 0 then
    s := restype
  else
    s := format('Stock type %d: %s',[LoWord(cardinal(restype)), StockResourcetype( restype )]);
  if (Pos('stringtable', Lowercase(s)) > 0)
  or (Pos('documento', Lowercase(s)) > 0) then
  begin
    sleep(1);
  end;
  list.Add(s);
  EnumResourceNames( module, restype, @enumResNamesProc, Integer(list));
  Result := 1;
end;

constructor TxbResources.Create;
begin
  inherited;
  FItems := TStringList.Create;
end;

destructor TxbResources.Destroy;
begin
  FItems.Free;
  inherited;
end;

procedure TxbResources.Load(const AHandle: THandle);
var
  s: string;
begin
  if not Enumresourcetypes(AHandle, @EnumResTypesProc, Integer(FItems)) then
    SysErrorMessage(GetLastError);
end;

...

with TxbResources.Create do
  Load(LoadPackage('mypackage.bpl');

My question is: How could I get all lines from STRINGTABLE, since I do not know the id?

Thanks

Capslock
  • 59
  • 2
  • 1
    Show us how you are calling EnumResourceNames – Anders Jul 05 '22 at 16:39
  • Probably a duplicate of [this Q&A](https://stackoverflow.com/q/14088057/1889329). – IInspectable Jul 05 '22 at 17:23
  • EnumResourceNames code added. – Capslock Jul 05 '22 at 17:50
  • 1
    Is there a reason why you are using a manual `STRINGTABLE` resource instead of using `ResourceString`s? Let the compiler manage the resources for you. In any case, your checks to detect numeric IDs should be using `IS_INTRESOURCE()` instead of manual casts. And your `Integer()` casts on `EnumResourceTypes()` and `EnumResourceNames()` should be using `LONG_PTR` instead to avoid truncating pointers on 64bit builds. – Remy Lebeau Jul 05 '22 at 17:57
  • 1
    "No content of .RC returned using EnumResourceNames." I suggest you could try to call [GetLastError](https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror) to get extended error information. If IS_INTRESOURCE(lpszType) is TRUE, then lpszType specifies the integer identifier of the given resource type. Otherwise, it is a pointer to a null-terminated string. – Jeaninez - MSFT Jul 06 '22 at 06:22

0 Answers0