Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Безопасен ли вызов в 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]

Вобщем вопрос: можно так делать или нет?


Наверх

Титульная страница Поиск, карта сайта Написать письмо