delphidelphi-11-alexandria

How to extract strings from RCDATA?


I'm using a RC file with images and strings , like this :

splash RCDATA splash.png
ilogo RCDATA ilogo.png
site RCDATA { "https://www.example.com" }

I then compile this file with BRCC32 and generate a RES file.

I know how to extract the images, using a code like this :

Var
  img: TWICImage;
Begin
  Try
    img := TWICImage.create;
    img.LoadFromResourceName(HInstance, resName);
    im.Picture.Graphic := img;
    Result := true;
  Finally
    img.free;
  End;

But i don't know how to extract the string RCDATA, for instance the 'site' RCDATA ; how can i do this ?


Solution

  • This depends on the encoding of your RCDATA. The low-level approach is to read the bytes and then interpret them explicitly in the encoding you know is right:

    var RS := TResourceStream.Create(HInstance, 'greeting', RT_RCDATA);
    try
      var LData := TBytes(nil);
      SetLength(LData, RS.Size);
      RS.ReadData(LData, RS.Size);
      var LStr := TEncoding.ASCII.GetString(LData);
      ShowMessage(LStr);
    finally
      RS.Free;
    end;
    

    A marginally simpler approach is to use a TStringList, for example:

    var List := TStringList.Create;
    try
      var RS := TResourceStream.Create(HInstance, 'greeting', RT_RCDATA);
      try
        List.LoadFromStream(RS, TEncoding.ASCII);
        ShowMessage(List.Text);
      finally
        RS.Free;
      end;
    finally
      List.Free;
    end;
    

    And a very important off-topic remark:

    Your code

    Var
      img: TWICImage;
    Begin
      Try
        img := TWICImage.create;
        img.LoadFromResourceName(HInstance, resName);
        im.Picture.Graphic := img;
        Result := true;
      Finally
        img.free;
      End;
    

    has a serious bug that can cause memory corruption, at least in some contexts. Specifically, if this is the code of a procedure or function, then img is a local variable of a non-managed type, and so it is not initialized. Hence, initially, img is a "random" pointer. Its value is the native-sized integer that happens to be there in your computer's RAM.

    So if the TWICImage.Create constructor raises an exception (which is very much a possibility), then you'll do img.Free on a random pointer img. Then anything can happen. If you are lucky, you get an access violation almost immediately.

    Always write

    var LFrog := TFrog.Create;
    try
      { use LFrog }
    finally
      LFrog.Free;
    end
    

    and never write

    try
      LFrog := TFrog.Create;
      { use LFrog }
    finally
      LFrog.Free; // wrong!
    end