Читать «Виртуальная библиотека Delphi» онлайн - страница 60

Unknown

Ресурсы индексированы как многоуровневое двоичное дерево. Технологически возможно 2**31 уровней, но в Windows стандартно используются только три: первый — TYPE (тип), далее — NAME (имя), далее — LANGUAGE (язык). Ресурсы должны быть отсортированы по определенным правилам – для ускорения поиска.

Типичное расположение ресурсов в файле: сначала лежит `RESOURCE DIRECTORY` (каталог/каталоги ресурсов), затем – `RESOURCE DATA` (собственно данные ресурсов).

Каталог ресурсов довольно похож, по структуре, на каталоги дисков. Он содержит записи (`DIR ENTRIES` – см. далее), которые указывают либо на ресурсы, либо на другие каталоги (точнее – подкаталоги) ресурсов. В отличие от дисков, сами данные не разносятся по кластерам, а наоборот – их стараются плотнее прижать друг к другу, поскольку никто не собирается вставлять туда дополнительные данные после сборки (линковки) исполняемого файла.

Каталог ресурсов начинается с заголовка (четыре 32-битных слова):

DD RESOURCE FLAGS

DD TIME/DATE STAMP

DW MAJOR VERSION, DW MINOR VERSION

DW # NAME ENTRY,  DW # ID ENTRY

декларация в RXTypes.Pas:

IMAGE_RESOURCE_DIRECTORY = packed record

  Characteristics : DWORD;

  TimeDateStamp   : DWORD;

  MajorVersion    : WORD;

  MinorVersion    : WORD;

  NumberOfNamedEntries : WORD;

  NumberOfIdEntries : WORD;

end;

Здесь важны два поля: `# NAME ENTRY` — число точек входа, имеющих имена, и `# ID ENTRY` — число точек входа, имеющих вместо имен целочисленные идентификаторы.

За заголовком следует массив из записей `RESOURCE DIR ENTRIES` (точек входа каталога). Там лежат `# NAME ENTRY`+ `# ID ENTRY` записей типа `DIR ENTRY`. Формат записи `DIR ENTRY` — два 32-битных слова:

DD NAME RVA       | INTEGER ID

DD DATA ENTRY RVA | SUBDIR RVA

декларация в RXTypes.Pas:

IMAGE_RESOURCE_DIRECTORY_ENTRY = packed record

  Name: DWORD; // Or ID: Word (Union)

  OffsetToData: DWORD;

end;

Первое поле содержит либо `NAME RVA` — адрес строки (UNICODE) с именем, либо — `INTEGER ID` – целочисленный идентификатор. `INTEGER ID` может быть, например, одним из стандартных кодов типа ресурса или заданным пользователем кодом строки в таблице строк.

Самый старший бит второго поля (31-й бит) называется `Escape-флагом`. Если он установлен в `1`, считается что данная `DIR ENTRY` — ссылка на другой подкаталог ресурсов. Если сброшен в `0` — данная запись ссылка на данные ресурса. Понятно, при вычислении адреса этот бит всегда должен считаться `0`.

Строка, на которую указывает `NAME RVA`, очень похожа на паскалевскую short-string, только вместо байтов она состоит из 16-битные слов. Самое первое слово – длина строки, за ним лежат 16-битные символы UNICODE. Физически линкер кладет эти строки переменной длиины между каталогами и собственно данными ресурсов.