Recently I stumbled into a question asking how to embed array of bytes into an application using resource. I found this question is interesting because that way you can alter the array content without actually hacking the body of executable. We don't need to hack because Windows provides a way to safely modify content of a resource.

This tutorial will show you how to embed an array of bytes to an executable using resource.

Windows Resource

This time I will not dig deeper about Windows Resource. Please read this Wikipedia page to learn more about it. Simply said resouces are a collection of read-only (to the executable) data.

Please take the read-only part with a grain of salt, because there are ways to modify resources. But not easily done inside the executable that contains or uses the resource(s).

Embedding Array of Bytes Through Resource

Obviously we do this by creating a resource and then embed the resource into our Delphi application. The steps are:

Write the array to a resource script

Compile the resource script

Include the compiled resource file into Delphi source code

Let's learn by doing. Let's say that we have array of bytes that in Delphi code defined like this.

const
MyArray: array[1..4] of byte = (10, 20, 30, 40);

And we want to embed this array not in plain simple Delphi code, but through resource.

1. Write the Array to Resource Script

In resource script, a resource is defined basically using 3 fields.

The resource's name or id

The resource's type

Content of the resource

In our case, let's use MyArray for the resource name, and RCDATA as the type, and of course 10, 20, 30, 40 for the content. But how do we write this down?

A visit to MSDN page that explains RCDATA resource type reveals interesting information and also a very helpful example. However now we hit our first problem. Because there is no direct way to store one byte value with resource command. The easier options are.

Cast the array of bytes content into ansi string. Remember that each member/char in ansi string is actually a byte.

Combine each two bytes into one word, then use one way specify integer values in the resource script.

The first option looks the easiest. And we actually can define the "numeric" value of a character in a string using escape character of "\" followed by the numeric value in octal format. Let's choose this option.

Using the first option, our array resource entry would be:

MyArray RCDATA
{
"\12\24\36\50"
}

Let's save the resource script as "test.rc" in our project directory. Note that the .rc extension is not actually required. Just a convention, a "clue".

2. Compile the Resource Script

Now we need to compile the resource script to get the resource in binary form. Delphi installation usually already has a resource compiler named brcc32.exe. It usually already in the system path, making it available to be called from anywhere in command prompt. Calling "brcc32.exe" bare would yield more information like shown below.

After executing brcc32, you will get new file named test.res in the same folder as test.rc. This is the compiled binary resource. Time to embed it to our Delphi application.

Include the Compiled Resource into Delphi Source Code

Embedding the .res is easy in Delphi. In our case, you just have add either one the following lines somewhere in any file used by your Delpi project.

{$R test.res}

or

{$RESOURCE test.res}

And that's it! Each time you compile the project, the resource will automatically be embedded to the executable. Next section will show how to read the array.

Reading the Embedded Array

Now that we have successfully embed (or at least we thought so ;P ) the array through resource, we need a way to read it. Fortunately for us, VCL already has a class for reading resource content into stream. It's [URL=http://docwiki.embarcadero.com/Libraries/XE2/en/System.Classes.TResourceStream]TResourceStream[/I]. With it, we can treat a resource like we treat any other TStream instance.

Let's say we want to read MyArray and show the content as string inside a TMemo which named Memo1. The following codes will suffice.

See that the values are exactly what we have embedded? So that is the proof that our method is working properly. Please check the attached test.rc (inside the zip file) to see implementation of the other option.