Виртуальная библиотека Delphi
- Название:Виртуальная библиотека Delphi
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Виртуальная библиотека Delphi краткое содержание
Виртуальная библиотека Delphi - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
end;
end;
{//// TestBuiltInStrRes ////}
RESOURCESTRING
sMsgHello = 'ЯВЕРТЫяверты';
sMsgBye = 'явертыЯВЕРТЫ';
procedure TestBuiltInStrRes;
{ load strings from resources via Delphi`s Linker }
begin
i_MsgBox( 'built-in string resources:', sMsgHello+#13+sMsgBye );
end;
{//////////////////////////////////////////////}
type
tFH_Method = procedure( AFHandle:tHandle );
{ `AFHandle` must be a handle of instance of image (of memory-map)
of a PE-file (EXE or DLL) }
procedure i_Call_FH_Method( AProc:tFH_Method );
{ it is wrapper to load and free a instance of binary
file with resource; also it calls to "AProc()" with
given instance-handle }
const
cLibName = 'PROJ_L.DLL';
var
qFHandle : tHandle;
begin
qFHandle := Windows.LoadLibrary(
pChar(ExtractFilePath(ParamStr(0))+cLibName) );
if qFHandle=0 then
i_MsgBox( 'Error loading library',
Format('Code# %xh',[Windows.GetLastError]) )
else
try AProc( qFHandle );
finally Windows.FreeLibrary( qFHandle );
end;
end;
{//// TestBinRes_WinAPI ////}
procedure TestBinRes_WinAPI( AFHandle:tHandle );
{ loading binary resource via usual windows-API }
var
qResH,
qResInfoH : tHandle;
begin
qResInfoH := Windows.FindResourceEx( AFHandle , RT_RCDATA, 'RC1', 0 );
qResH := Windows.LoadResource( AFHandle, qResInfoH );
try i_MsgBox( 'binary resource (Win API):',
pChar(Windows.LockResource(qResH)) );
finally Windows.FreeResource( qResH );
end;
end;
{//// TestBinRes_VCLStream ////}
procedure TestBinRes_VCLStream( AFHandle:tHandle );
{ loading binary resource via VCL`s stream }
var
qResStream : tResourceStream;
begin
qResStream := tResourceStream.Create( AFHandle, 'RC1', RT_RCDATA );
try i_MsgBox( 'binary resource (VCL stream):',
pChar(qResStream.Memory) );
finally qResStream.Free;
end;
end;
{//// TestStrRes_WinAPI ////}
procedure TestStrRes_WinAPI( AFHandle:tHandle );
{ loading string resource via usual windows-API }
const
cBufSize = 512;
var
qBuf : array[0..1,0..cBufSize-1]of Char;
begin
Windows.LoadStringA( AFHandle, 1000, qBuf[0], cBufSize );
Windows.LoadStringA( AFHandle, 1001, qBuf[1], cBufSize );
i_MsgBox( 'string resources (Win API):',
StrPas(qBuf[0])+#13+StrPas(qBuf[1]) );
end;
BEGIN
TestSList;
TestBuiltInStrRes;
i_Call_FH_Method( TestBinRes_WinAPI );
i_Call_FH_Method( TestBinRes_VCLStream );
i_Call_FH_Method( TestStrRes_WinAPI );
END.
Замечания:
• Rесурсы частично вынесены во внешнюю DLL только для демонстрации, поскольку большинство вопросов в конференции подразумевает именно такое их использование.
• Если ресурсы слинкованы не в отдельную DLL, а в исполняемый файл проекта, в параметре AFHandle надо везде передавать `0` или значение переменной System.HInstance.
• Вместо функции Windows.FindResource() я предпочитаю FindResourceEx() с лишним явным параметром — `LanguageId`. Дело в том, что первая не всегда находит ресурсы, сделанные борландовскими компиляторами — семантика LanguageId по умолчанию определена MS не совсем однозначно.
• Для однозначности, я явно указал имя функции Windows.LoadStringA(). В NT работает еще функция LoadStringW(), которая возвращает строки UNICODE. В Win95 LoadStringW() возвращает код ошибки `not implemented`.
Внутренний формат ресурсов Windows
В каталоге DELPHI\DEMOS\RESXPLOR есть пример работы с ресурсами Windows на самом `фундаментальном` уровне — непосредствено с форматом PE COFF (Portable Executable Common Object File Format) для Win32. Данный раздел написан, в основном, для тех, кто захочет разобраться в этом стандартном примере Delphi.
Сами по себе ресурсы — индексированный набор данных с записями переменной длины. Чтобы конкретную запись ресурса можно было найти, у нее есть один из двух идентификаторов — имя (строка символов UNICODE) или целое число. Целыми числами идентифицируются, например, каталоги стандартных типов ресурсов и строки в таблицах. Большинство записей ресурсов стандартных типов идентифицируются именами. Практически, в именах ресурсов разумно использовать только подмножетсво стандартных символов ASCII (коды от 0 до 255). Описание стандартных типов ресурсов Windows можно посмотреть в on-line help`е любой IDE C или Delphi. Любопытно, что способ идентификации ресурса ( целое число или ссылка на имя ) специфицирован, скорее, не на уровне стандарта, а на уровне принятых соглашений. Для поиска ресурса мы, в общем случае, задаем три параметра:
• Тип — один из стандартных кодов типа ресурса. В вызовах API это может быть либо адресом строки, содержащей одно из стандартных имен, либо — одна из констант RT_xxx из DELPHI\SOURCE\RTL\WIN\WINDOWS.PAS.
• Идентификатор. В зависимости от типа ресурса, это может быть целое число или имя.
• Язык ресурса. Кодируется целым числом.
Формат ресурсов PE COFF ориентирован чтобы:
– максимально быстро находить нужный ресурс по указаным трем параметрам,
– расположить ресурсы достаточно компактно,
– переносить скомпилированные ресурсы между процессорами с разными правилами адресации.
Далее используется термин RVA (relative virtual address), я его поясню. Все адреса в защищенных многозадачных системах (не только на x286..586) обычно делаются `виртуальными`: То есть, пользовательское приложение не должно иметь шанс узнать что-либо о физических адресах — иначе оно теоретически может разрушить любую защиту операционной системы. В Windows строгой защиты в этом смысле нет, но есть еще одна причина `виртуальности` адресов — динамическая загрузка/выгрузка данных из ОЗУ на диск для организации виртуальной памяти. Процессор аппаратно, `на лету`, транслирует виртуальные адреся в физические по таблицам, созданным ядром операционной системы.
Теперь о слове `relative`. Операционной системе, по большому счету, без разницы, какой именно виртуальный адрес дать первому байту образа исполняемого файла в ОЗУ. А линкеру и самой программе, в ряде случаев, удобнее работать с конкретным значением. Оно называется `ImageBase`; линкер записывает его в заголовке PE-файла. По техническим причинам, оно не может быть произвольным для Windows-программ. В Delphi есть директива `{$ImageBase …}`. Так вот, RVA объекта – это его смещение относительно значения `ImageBase`. Обычный адрес объекта (он, кстати, тоже виртуальный) есть сумма значений глобальной переменной `ImageBase` и `RVA` данного объекта.
В тексте использована ассемблерная мнемоника: `DD` и `DW` (Define Double и Define Word), что означает, соответственно, 32– и 16-разрядное слово. Символ `|` означает `или`, `либо`.
Описание формата ресурсов в MS PE COFF.
Я делаю сокращенное изложение фрагмента документации PE COFF. Я полагаю, этого более-менее достаточно, чтобы разобраться, при желании, с текстом примера Delphi. Файл PE.TXT (author Micheal J. O'Leary) взят из документации Microsoft C. Он же входит в MS Software Developers Kit (SDK) и в комплект поставки большинства компиляторов C для Win32. Если Вам интересно положение корневого каталога ресурсов в заголовке PE COFF или более подробный формат заголовка – можно смотреть исходные тексты проекта проекта RSEXPLOR или, разумеется, сам первоисточник — PE.TXT
Ресурсы индексированы как многоуровневое двоичное дерево. Технологически возможно 2**31 уровней, но в Windows стандартно используются только три: первый — TYPE (тип), далее — NAME (имя), далее — LANGUAGE (язык). Ресурсы должны быть отсортированы по определенным правилам – для ускорения поиска.
Читать дальшеИнтервал:
Закладка: