Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Система";
Текущий архив: 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
1-45973
DKalinin
2002-11-03 16:23
2002.11.14
почему ToolButton при задании ему свойства Action становится недо


14-46132
AL2002
2002-10-24 19:17
2002.11.14
100%-ый плагиат?


3-45732
123000
2002-10-23 17:41
2002.11.14
Сортировка


1-45963
Whippi
2002-11-04 11:19
2002.11.14
HTTP сервер


1-45811
DD
2002-11-04 03:09
2002.11.14
Подскажите, как обработать нажатие правой клавиши мышки





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский