![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Безопасен ли вызов в DllMain такой функции [XP]
Егорка © (2012-08-24 16:33:00)Доброго времени суток. Прочитал много страшного про вызовы из DllMain и так и не понял чего там можно, а чего нет.
Меня интересует только ниже приведенный код. При загрузке DLL нужно извлечь из нее ресурс.
Все вместе это выглядет примерно так так:
library MyLib;
uses
Windows;
function ExtractResource(const ResName, FileName: string): Boolean;
var
hNewFile, hResInfo, hResData: THandle;
dwResSize, dwWritten: Cardinal;
PRes: Pointer;
begin
Result := False;
hResInfo := FindResource(hInstance, CharUpper(PChar(ResName)), RT_RCDATA);
if hResInfo = 0 then
Exit;
dwResSize := SizeOfResource(hInstance, hResInfo);
hResData := LoadResource(hInstance, hResInfo);
PRes := LockResource(hResData);
if Assigned(PRes) then
begin
hNewFile := CreateFile(PChar(FileName), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, 0, 0);
if hNewFile <> INVALID_HANDLE_VALUE then
begin
if WriteFile(hNewFile, PRes^, dwResSize, dwWritten, nil) then
Result := dwWritten = dwResSize;
CloseHandle(hNewFile);
end;
end;
end;
function GetLibDir: string;
var
I: Integer;
ModuleName: array[0..MAX_PATH] of Char;
begin
Result := '';
ZeroMemory(@ModuleName, SizeOf(ModuleName));
if GetModuleFileName(hInstance, ModuleName, SizeOf(ModuleName)) > 0 then
begin
for I := High(ModuleName) downto Low(ModuleName) do
if ModuleName[I] = '\' then
begin
Result := Copy(ModuleName, 0, Succ(I));
Break;
end;
end;
end;
var
FileName: string;
begin
FileName := GetLibDir + 'myfilename.ext';
if GetFileAttributes(PChar(FileName)) = DWORD(-1) then
if not ExtractResource('MyResName', FileName) then
MessageBox(0, 'Не удалось извлечь ресурс', nil, MB_ICONERROR);
end;
bems (2012-09-04 00:42:00) [1]
> длл на дельфи не удавалось использовать для загрузки из KnownDLLs
AppInit конечно же
bems (2012-09-03 23:04:00) [2]> А разве загрузчик не выстроит порядок загрузки DLL на основе зависимостей?
Обычно выстраивает правильно, но гарантий никто не даёт. К тому же user-функции внутренне любят делать динамическую загрузку, которая всё ломает
длл на дельфи не удавалось использовать для загрузки из KnownDLLs, если дллка спользовала SysUtils. не помню точно, но кажется дело было в каком-то user-вызове в секции инициализации юнита
Rouse_ (2012-09-03 20:41:00) [3]
> Дмитрий С © (03.09.12 18:04) [14]
> А разве загрузчик не выстроит порядок загрузки DLL на основе
> зависимостей?
Если проект написан на дельфи, то шансов ошибки практически не существует.
Статические линкуемые библиотеки будут подгружены до передачи управления на OP. Правда я уже не помню по какому принципу идет подгрузка но в принципе, если имеешь желание навредить самому себе, то остаются еще TLS каллбэки, во время исполнения которых некоторые "особо продвинутые пакеры" умудряются искать API из еще не подгруженных модулей, не озабачиваясь о их подгрузке и полагаясь что тот-же shell32.dll или еще что-то из com* уже присутствует.
Дмитрий С (2012-09-03 18:04:00) [4]А разве загрузчик не выстроит порядок загрузки DLL на основе зависимостей?
bems (2012-09-03 02:36:00) [5]> Это еще надо умудриться загрузить свою либу раньше user32
в этой ситуации нет ничего невероятного. в msdn обещают только то, что будет доступна kernel32. Это подразумевает доступность ntdll
dllmain остальных модулей может быть еще не вызвана на момент вызова dllmain модуля который их использует
Сергей М. (2012-08-27 09:33:00) [6]
> user32.dll еще может быть не инициализирована
Это еще надо умудриться загрузить свою либу раньше user32
Leonid Troyanovsky (2012-08-25 13:57:00) [7]
> Егорка (24.08.12 16:34) [1]
http://msdn.microsoft.com/en-us/windows/hardware/gg487379.aspx
--
Regards, LVT.
bems (2012-08-25 13:32:00) [8]
> Чтой-то вдруг ?
потому что user32.dll еще может быть не инициализирована
> в DllMain следует остерегаться манипуляций созданием тредов
треды создавать можно, но нельзя ожидать любого события в коде выполнения треда (потому что фактическое выполнение начнется после выхода из DllMain)
Егорка (2012-08-25 00:59:00) [9]Вызов MessageBox не критичен, я его привел для наглядности) Спасибо всем ответившим!
Rouse_ (2012-08-25 00:36:00) [10]Зы, чуть не забыл ответить авторы темы :)
Код нормальный, должен работать, только не привязывай данную бибилотеку статически. На вызове user32 функций лоадер может терминировать процесс.
Rouse_ (2012-08-25 00:31:00) [11]
> в DllMain следует остерегаться манипуляций созданием тредов,
> равно как и иных ОС-объектов
Ненаказуемо © :)
А вот воспользоваться DisableThreadLibraryCalls() желательно.
Ну а TEB в динамике залочить - этож я даже не знаю как постараться нужно с учетом библиотеки . Ну точнее знаю, но стандартные компилеры не позволяют прописывать TLS-callback даже с учетом асм-вставок.
sniknik (2012-08-24 22:44:00) [12]> Чтой-то вдруг ?
из dll? сообщение с ожиданием нажатия... даже при ошибке, я бы не делал.
Сергей М. (2012-08-24 22:07:00) [13]
> MessageBox нельзя
Чтой-то вдруг ?
Сергей М. (2012-08-24 22:06:00) [14]в DllMain следует остерегаться манипуляций созданием тредов, равно как и иных ОС-объектов (например, образов DLL, впервые динамически загружаемых в АП пространство процесса), создание которых претендует на блокировку таблиц PEB и TEB.
bems (2012-08-24 20:49:00) [15]MessageBox нельзя, хоть обычно и работает
Dimka Maslov (2012-08-24 16:46:00) [16]Делать можно, но не нужно.
Егорка (2012-08-24 16:34:00) [17]Вобщем вопрос: можно так делать или нет?