RCDATA und binäre Ressourcen


Ein kleiner Sonderfall ist die RCDATA-Ressource. Ihr Parameter kann beliebige Dateien aufnehmen, es wird also keine Dateityperkennung durchgeführt. Aber zusätzlich hat man die Möglichkeit, binäre Daten direkt in das Ressourcescript einzugeben. So kann man ganze Datenstrukturen direkt in die Ressourcen speichern:

100 RCDATA "somefile.exe"
200 RCDATA
{
  123  // WORD
  456L // LONGWORD
}

Die resultierende Ressourcendatei enthält 2 Ressourcen. Einmal die Datei "somefile.exe", die dann geladen, temporär gespeichert und ausgeführt werden kann.

Die zweite Ressource ist eine binäre Ressource, deren Daten direkt im Script festgelegt wurden. Sie ist 6 Bytes lang (Word + LongWord), wobei die ersten 2 Bytes die Zahl 123 enthalten und die restlichen 4 die Zahl 456. Diese binäre Struktur kann man jetzt direkt in einen Record laden, aber man muss beachten, dass der Ressourcencompiler keinerlei Ausrichtung der Daten übernimmt. Die Deklaration eines solchen Record muss also unbedingt packed sein:

TResRec = packed record
  Val1: Word;
  Val2: LongWord;
end;
PResRec = ^TResRec;


Bei dieser Art, binäre Daten in eine Ressource zu packen, muss man allerdings ein paar Dinge beachten

Bei Strings sollte man zusätzlich bedenken, dass der String als "array of Char" in der Ressource liegt, nicht als PChar und auch nicht als normaler String. Entsprechend muss man die Länge des Strings vorher wissen und ein entsprechend langes Array verwenden. Für Sprachressourcen, deren Strings je nach Sprache verschiedene Längen haben, ist diese Methode also ungeeignet.

RCDATA-Ressourcen lädt man mit den Befehlen FindResource, LoadResource und LockResource. Erstere liefert einen speziellen Resource Location Block zurück, den "LoadResource" dazu verwendet, die Daten zu laden. "LockResource" schließlich hält die Daten im Speicher fest und liefert einen Pointer auf den Datenbereich.

Für unsere Ressource sähe das also folgendermaßen aus:

var
  hMod: hModule;
  hRes: HRSRC
  hData: hGlobal;
  Data: PResRec;
begin
  hMod  := LoadLibrary(PChar(paramstr(0));
  hRes  := FindResource(hMod, MAKEINTRESOURCE(200), RT_RCDATA);
  hData := LoadResource(hMod, hRes);
  Data  := PResRec(LockResource(hData));
{ ... } end;

"Data" zeigt jetzt auf unsere zwei Integer, die wir nun beliebig verwenden können.