Форум: "Система";
Текущий архив: 2002.11.14;
Скачать: [xml.tar.bz2];
Вниз
Доступ к 3-му параметру DllEntryPoint() Найти похожие ветки
← →
Digitman (2002-09-12 08:21) [0]BOOL WINAPI DllEntryPoint(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved // reserved
);
lpvReserved
Specifies further aspects of DLL initialization and cleanup.
If fdwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic loads and non-NULL for static loads.
If fdwReason is DLL_PROCESS_DETACH, lpvReserved is NULL if DllEntryPoint has been called by using FreeLibrary and non-NULL if DllEntryPoint has been called during process termination.
Оч простой вопрос :
Каким образом, не меняя контекст system.pas и sysinit.pas, получить доступ по чтению к параметру lpvReserved в момент, когда код инициализации/деинициализации DLL (генерируемой средствами Делфи) получает управление ?
Интересны простые и изящные идеи, обеспечивающие надежное решение задачи для указанных ОС и версий Делфи.
← →
Ученик (2002-09-12 08:55) [1]Есть подозрение, что DllProc нужно присвоить адрес процедуры
procedure MyDLLProcEx(Reason: Integer; Reserved: Integer);
begin
end;
В Delphi 6 переменная называется
{ DllProcEx passes the Reserved param provided by WinNT on DLL load & exit }
DllProcEx: TDLLProcEx absolute DllProc;
Для Delphi 5 переменной нет, но возможно будет работать для DllProc, к сожалению проверить не могу.
← →
Digitman (2002-09-12 09:19) [2]>Ученик
Не будет это работать в D5.
@@noTLSproc:
{ Call any DllProc }
MOV EDX,[ESP+4]
TEST EDX,EDX
JE @@noDllProc
MOV EAX,[EBP+12]
CALL EDX
А как это реализовано в D6 ?
Приведи, пожалуйста, полный код _StartLib, у меня нет под руеой Д6
← →
Ученик (2002-09-12 09:24) [3]procedure _InitLib;
asm
{ -> EAX Inittable }
{ [EBP+8] Hinst }
{ [EBP+12] Reason }
{ [EBP+16] Resvd }
MOV EDX,offset Module
CMP dword ptr [EBP+12],DLL_PROCESS_ATTACH
JNE @@notInit
PUSH EAX
PUSH EDX
MOV ModuleIsLib,1
MOV ECX,[EBP+8]
MOV HInstance,ECX
MOV [EDX].TLibModule.Instance,ECX
MOV [EDX].TLibModule.CodeInstance,0
MOV [EDX].TLibModule.DataInstance,0
CALL InitializeModule
POP EDX
POP EAX
@@notInit:
PUSH DllProc
MOV ECX,offset TlsProc
CALL _StartLib
end;
procedure _StartLib;
asm
{ -> EAX InitTable }
{ EDX Module }
{ ECX InitTLS }
{ [ESP+4] DllProc }
{ [EBP+8] HInst }
{ [EBP+12] Reason }
{ Push some desperately needed registers }
PUSH ECX
PUSH ESI
PUSH EDI
{ Save the current init context into the stackframe of our caller }
MOV ESI,offset InitContext
LEA EDI,[EBP- (type TExcFrame) - (type TInitContext)]
MOV ECX,(type TInitContext)/4
REP MOVSD
{ Setup the current InitContext }
POP InitContext.DLLSaveEDI
POP InitContext.DLLSaveESI
MOV InitContext.DLLSaveEBP,EBP
MOV InitContext.DLLSaveEBX,EBX
MOV InitContext.InitTable,EAX
MOV InitContext.Module,EDX
LEA ECX,[EBP- (type TExcFrame) - (type TInitContext)]
MOV InitContext.OuterContext,ECX
XOR ECX,ECX
CMP dword ptr [EBP+12],0
JNE @@notShutDown
MOV ECX,[EAX].PackageInfoTable.UnitCount
@@notShutDown:
MOV InitContext.InitCount,ECX
MOV EAX, offset RaiseException
MOV RaiseExceptionProc, EAX
MOV EAX, offset RTLUnwind
MOV RTLUnwindProc, EAX
CALL SetExceptionHandler
MOV EAX,[EBP+12]
INC EAX
MOV InitContext.DLLInitState,AL
DEC EAX
{ Init any needed TLS }
POP ECX
MOV EDX,[ECX]
MOV InitContext.ExitProcessTLS,EDX
JE @@skipTLSproc
CMP AL,3 // DLL_THREAD_DETACH
JGE @@skipTLSproc // call ExitThreadTLS proc after DLLProc
CALL dword ptr [ECX+EAX*4]
@@skipTLSproc:
{ Call any DllProc }
PUSH ECX
MOV ECX,[ESP+8]
TEST ECX,ECX
JE @@noDllProc
MOV EAX,[EBP+12]
MOV EDX,[EBP+16]
CALL ECX
@@noDllProc:
POP ECX
MOV EAX, [EBP+12]
CMP AL,3 // DLL_THREAD_DETACH
JL @@afterDLLproc // don"t free TLS on process shutdown
CALL dword ptr [ECX+EAX*4]
@@afterDLLProc:
{ Set IsLibrary if there was no exe yet }
CMP MainInstance,0
JNE @@haveExe
MOV IsLibrary,1
FNSTCW Default8087CW // save host exe"s FPU preferences
@@haveExe:
MOV EAX,[EBP+12]
DEC EAX
JNE _Halt0
CALL InitUnits
RET 4
end;
← →
Игорь Шевченко (2002-09-12 10:20) [4]IMHO, анализируя код, похоже, что переданные параметры передаются в DLLProc без изменения, как в D5, так и в D6
← →
Digitman (2002-09-12 11:11) [5]>Игорь Шевченко
да вот не получается, Игорь, как ты имеешь честь скромно предполагать)
Вот смотри - явно же видна разница :
D5:
@@noTLSproc:
{ Call any DllProc }
MOV EDX,[ESP+4]
TEST EDX,EDX
JE @@noDllProc
MOV EAX,[EBP+12] //Reason - как положено : 1-м параметром в EAX
CALL EDX // 2-й параметр д.б. в EDX, а этот РОН использован для иной цели - как CALL-диспетчер
D6:
{ Call any DllProc }
PUSH ECX
MOV ECX,[ESP+8]
TEST ECX,ECX
JE @@noDllProc
MOV EAX,[EBP+12] //Reason - 1-м параметром в EAX
MOV EDX,[EBP+16] //Reserved - 2-м параметром в EDX
CALL ECX //порядок ! оба параметра доступны в теле DLLProc
← →
Игорь Шевченко (2002-09-12 11:14) [6]Digitman © (12.09.02 11:11)
Извиняюсь, не углядел, что вызываемая по DLLProc процедура имеет fastcall calling convention.
Спасибо за науку :-)
С уважением,
← →
Ученик (2002-09-12 11:17) [7]>Digitman ©
Из стэка уже достали ?
← →
Digitman (2002-09-12 11:31) [8]быть бы уверенным, что и в полсед.версиях смещение будет равно +16 - нет проблем, конечно, достать из стека ...
← →
Ученик (2002-09-12 11:43) [9]В последних версиях $IFDEF VERXXX и DllProcEx
← →
Digitman (2002-09-12 14:08) [10]Господа, будьте любезны, проверьте этот код у себя :
type
PDllEntryPointFrame = ^TDllEntryPointFrame;
TDllEntryPointFrame = packed record
hModule: THandle; // DLL module handle
dwReason: DWord; // reason for calling DLLEntryPoint function of DLL
bStatic: LongBool; // TRUE if DLL is loading/unloading satically, FALSE - dinamically
end;
function IsStaticDLLCall: Boolean;
asm
mov edx, [hInstance]
mov eax, ebp
@@nextframe:
cmp [eax + $08].TDllEntryPointFrame.hModule, edx
je @@found
mov eax, [eax]
jmp @@nextframe
@@found:
mov eax, [eax + $08].TDllEntryPointFrame.bStatic
end;
результат вызова ф-ции контекстом исполняемого внутри DLL кода показывает, как было осуществлено обращение к DLL из хост-процесса для загрузки/выгрузки - статически или динамически
код вроде бы устойчиво работает (в D5) и в dpr дельфийской библиотеки и в разделах initialization/finalization любого из ее модулей
хотелось бы проверить это в Д6/Д7
← →
Ученик (2002-09-12 14:25) [11]Delphi 7, Windows 2000, не работает (AV), статическая загрузка DLL
← →
Ученик (2002-09-12 14:29) [12]Сорри, не туда вставил, все работает
← →
Ученик (2002-09-12 14:48) [13]Шутка
procedure Test(I1, I2, I3, I4 : Integer);
begin
if IsStaticDLLCall then
MessageBox(0, "Static", "Info", MB_OK)
else
MessageBox(0, "Dynamic", "Info", MB_OK)
end;
begin
Test(HInstance, HInstance, HInstance, HInstance)
end.
← →
Digitman (2002-09-12 15:14) [14]>Ученик
А в разделах init/final - тоже работает ? Или не пробовал ?
← →
Ученик (2002-09-12 15:22) [15]>Digitman © (12.09.02 15:14)
При динамической работает в секциях init/final
При статической похоже final не вызывается
← →
Digitman (2002-09-12 15:29) [16]>Ученик
>>При статической похоже final не вызывается
быть того не может)
ну да ладно, это уже не столь важно..
главное, что стековые манипуляции (в интересующем меня плане) оказываются идентичными в модулях system и sysinit начиная с D5 и вплоть до D7.
Благодарю за помощь и содействие !
← →
Ученик (2002-09-12 15:56) [17]>Digitman © (12.09.02 15:29)
initialization
if IsLibrary then begin
if IsStaticDLLCall then
MessageBox(0, "I Static", "Info", MB_OK)
else
MessageBox(0, "I Dynamic", "Info", MB_OK)
end
finalization
if IsLibrary then begin
if IsStaticDLLCall then
MessageBox(0, "F Static", "Info", MB_OK)
else
MessageBox(0, "F Dynamic", "Info", MB_OK)
end
end
FreeLibrary(LoadLibrary("DllTest.dll"));
Два сообщения
function ExportString : PChar; stdcall; external "DllTest.dll";
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(ExportString)
end
Одно сообщение на загрузке,
Может конечно вызывается, но окно не показывается, интересно почему.
← →
Ученик (2002-09-12 16:10) [18]>Ученик © (12.09.02 15:56)
Диагноз верен, сообщения в файл выводятся, с MessageBox непонятки
← →
Digitman (2002-09-12 16:57) [19]>Ученик
ShowMessage() в модуле Dialogs требует как миниму наличия невыгруженного и не деинициализированного еще модуля USER32.DLL в АП хост-процесса. И вполне возможно, что при стат. деинициализации/выгрузке системой модулей, загруженных ранее статически, модуль USER32.DLL деинициализируется системой несколько раньше обращения к нему со стороны кода в Dialogs, поэтому окно не выводится, а потенциальнеые ошибки обращения к USER32 мягко "гасятся" системой : на кой черт, спрашивается, ей чего-то сообщать юзеру, если процесс завершен и приложение все равно выгружается вместе со всеми "потрохами" ?
Хотя ... предположение (о порядке деинициализации/выгрузке взаимозависимых модулей) проверить, конечно, следовало бы ...
← →
Ученик (2002-09-12 17:08) [20]>Digitman © (12.09.02 16:57)
Здесь Windows.MessageBox, но скорее всего действительно вывод гасится, хотя почему бы не сообщать об Exception-ах, которые происходят при выгрузке
← →
Digitman (2002-09-12 17:27) [21]> Ученик
Если не лень, оттрассируй пошагово неработающий MessageBox() в данной ситуации - мне тоже интересно...
← →
Игорь Шевченко (2002-09-12 17:27) [22]Digitman © (12.09.02 16:57)
Ученик © (12.09.02 17:08)
Есть список InitializationOrderList в PEB^.LoaderData - там можно посмотреть, кто в какой последовательности инициализировался. Выгрузка происходит в обратном порядке (IMHO).
Но я сомневаюсь, что user32 деинициализируется раньше, чем клиентская DLL.
С уважением,
← →
Digitman (2002-09-12 17:41) [23]>Игорь Шевченко
Я тоже сомневаюсь. Но, тем не менее, факт остается фактом и , значит, причина в чем-то другом. Без трассировки это сложно сказать
← →
Ученик (2002-09-12 18:39) [24]Попробовал MessageBox(0, "F Static", "Info", MB_OK + MB_SERVICE_NOTIFICATION); сообщение в этом случае показывается
← →
Digitman (2002-09-12 18:58) [25]Отсюда - вывод : предположение неверно.
значит, что-то в Dialogs ...
← →
Ученик (2002-09-12 19:09) [26]>Digitman © (12.09.02 18:58)
Здесь нет Dialogs, ShowMessage, и так далее :-), сообщения выводятся средствами Windows API,
только если указан MB_SERVICE_NOTIFICATION, оно показывается по другому, почему не показывается в первом случае так и не понятно.
← →
paul_shmakov (2002-09-13 14:46) [27]лучше OutputDebugString для таких вещей использовать
← →
msts (2002-09-13 16:34) [28]У меня сообщение показывается
только без обработки ввода - прорисовывается и сразу закрывается
видимо процесс выгрузки независим от GUI и пока он незавершен
то сообщение видимо а как только достигнул определенной стадии
(например библиотека какая то выгружается) исчезает
заметно когда много BPL-ек используется (в данном случае штук 30)
Страницы: 1 вся ветка
Форум: "Система";
Текущий архив: 2002.11.14;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.009 c