Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2005.03.27;
Скачать: [xml.tar.bz2];

Вниз

Опять Hook DLL :)   Найти похожие ветки 

 
Goorus ©   (2005-02-12 12:50) [0]

Пишу компонент, для перехвата событий клавиатуры и мыши. Хотел избавиться от SendMessage при получении сообщения, но ничего не получилось :(
Если вызывать RunHook, то сообщения перехватываются до тех пор, пока приложение активно, если оно теряет фокус, то AppProcKeybrd больше не вызывается, даже если фокус вернуть.
В прнципе, выриант RunHook2 работает нормально, но просто не хотелось бы лишний раз отсылать сообщение.

Вот код библиотеки:

library HookLibrary;

uses
 Windows, Messages;

const
 MMFName = "g_HookMs";

type

 TObjHookProc = procedure(WParam: WParam; LParam: LParam)of object;

 TGlobalData = record
   shKeybrd: HWnd;  // дескриптор ловушки клавы
   shMouse : HWnd;  // ловушки мыши

   shKeybrd2: HWnd;

   AppWnd: HWnd;
 end;
 PGlobalData = ^TGlobalData;

var
 AppProcKeybrd: TObjHookProc;
 AppProcMouse : TObjHookProc;

 InWorking: Boolean = False;
 Runing: Boolean = False;

 MMFHandle: THandle;

 GlobalData: PGlobalData;

function SysMsgKeybrdProc(code: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
begin
 with GlobalData^ do
 if (code = HC_ACTION) and (not InWorking) then
 try
   InWorking := True;
   AppProcKeybrd(WParam, LParam);
 finally
   Result := CallNextHookEx(shKeybrd, Code, wParam, LParam);
   InWorking := False;
 end
 else
   Result := CallNextHookEx(shKeybrd, Code, wParam, LParam);
end;

function SysMsgKeybrdProc2(code: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
begin
 with GlobalData^ do
 if (code = HC_ACTION) and (not InWorking) then
 try
   InWorking := True;
   SendMessage(AppWnd, WH_KEYBOARD, wParam, LParam);
 finally
   Result := CallNextHookEx(shKeybrd2, Code, wParam, LParam);
   InWorking := False;
 end
 else
   Result := CallNextHookEx(shKeybrd2, Code, wParam, LParam);
end;

function SysMsgMouseProc(code: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
begin
 with GlobalData^ do
 if (code = HC_ACTION) and (not InWorking) then
 try
   InWorking := True;
   AppProcMouse(WParam, LParam);
 finally
   Result := CallNextHookEx(shMouse, Code, wParam, LParam);
   InWorking := False;
 end
 else
   Result := CallNextHookEx(shMouse, Code, wParam, LParam);
end;

function RunHook(OnKeybrd, OnMouse: TObjHookProc): Boolean; export; stdcall;
begin
 Result := False;
 with GlobalData^ do
 if not Runing then
 try
   AppProcKeybrd := OnKeybrd;
   AppProcMouse := OnMouse;
   if not(Assigned(OnKeybrd) or Assigned(OnMouse)) then Exit;

   if Assigned(OnKeybrd) then
     shKeybrd := SetWindowsHookEx(WH_KEYBOARD, @SysMsgKeybrdProc, hInstance, 0);

   if Assigned(OnMouse) then
     shMouse := SetWindowsHookEx(WH_MOUSE, @SysMsgMouseProc, hInstance, 0);

   Result := True;
   Runing := True;
 except

 end;
end;

function RunHook2(OnKeybrd: HWnd): Boolean; export; stdcall;
begin
 Result := False;
 with GlobalData^ do
 if not Runing then
 try
   AppWnd := OnKeybrd;

   shKeybrd2 := SetWindowsHookEx(WH_KEYBOARD, @SysMsgKeybrdProc2, hInstance, 0);

   Result := True;
   Runing := True;
 except

 end;
end;

procedure StopHook(); export; stdcall;
begin
 with GlobalData^ do
 try
   UnHookWindowsHookEx(shKeybrd);
   UnHookWindowsHookEx(shMouse);
   UnHookWindowsHookEx(shKeybrd2);
 finally
   shKeybrd := 0;
   shMouse := 0;
   shKeybrd2 := 0;
 end;
 Runing := False;
end;

procedure OpenGlobalData;
begin
 // получаем объект файлового отображения
 MMFHandle := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE,
   0, SizeOf(TGlobalData), MMFName
 );
 if MMFHandle = 0 then
 begin
   MessageBox(0, "Невозможно создать FileMapping", "Сообщение из HookLib.dll", 0);
   Exit;
 end;
 // отображаем глобальные данные на АП вызывающего процесса и
 // получаем указатель на начало выделенного пространства
 GlobalData := MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0,
   SizeOf(TGlobalData)
 );
 if GlobalData = nil then
 begin
   CloseHandle(MMFHandle);
   MessageBox(0, "Невозможно создать MapViewOfFile", "Сообщение из HookLib.dll", 0);
   Exit;
 end;
end;

procedure CloseGlobalData;
begin
 UnmapViewOfFile(GlobalData);
 CloseHandle(MMFHandle);
end;

procedure DLLEntryPoint(dwReason: DWord); stdcall;
begin
 case dwReason of
   DLL_PROCESS_ATTACH: OpenGlobalData;
   DLL_PROCESS_DETACH: begin
     if Runing then StopHook;
     CloseGlobalData;
   end;
 end;
end;

exports RunHook;
exports RunHook2;
exports StopHook;

begin
 DLLProc := @DLLEntryPoint;
 // вызываем назначенную процедуру для отражения
 // факта присоединения данной библиотеки к процессу
 DLLEntryPoint(DLL_PROCESS_ATTACH);
end.


 
GuAV ©   (2005-02-12 15:38) [1]


>   SendMessage(AppWnd, WH_KEYBOARD, wParam, LParam);

WH_KEYBOARD = WM_DESTROY. очень интересное совпадение.
см. справку по WM_USER


> procedure DLLEntryPoint(dwReason: DWord); stdcall;


А почему не safecall ?


>   AppProcKeybrd := OnKeybrd;
>    AppProcMouse := OnMouse;


Ну во первых метод по сути пара указателей - на код и на экземпляр объекта. Угадай, какой из них будет валидным в чужом АП.

И кстати зачем этот трюк с GlobalData ?

Следует не тупо коприрвать пример а разобраться в этом прежде чем применят хуки.


 
Goorus ©   (2005-02-12 18:00) [2]

> А почему не safecall ?
Работает - не трогай! Золотое правило :)

На счёт трюка с GlobalData, опыты показали, что shKeybrd
(shMouse, shKeybrd2) должны находиться именно там, иначе не работает.

> WH_KEYBOARD = WM_DESTROY
Это не имеет значения, у меня свой обработчик.

Про метод я понимаю, только не понимаю, почему он перестаёт быть валидным когда приложение перестаёт быть активным. Ведь DLL подключена к моему приложению.
Или, когда фокус получает другое приложения, DLL начинает пытаться вызвать эти методы у него? Сам не верю в то, что сказал :)


 
Piter ©   (2005-02-12 18:03) [3]

Goorus ©   (12.02.05 18:00) [2]
> А почему не safecall ?
Работает - не трогай!


а-а-а-а... я сейчас сползу со стула...


 
GuAV ©   (2005-02-12 20:15) [4]


> На счёт трюка с GlobalData, опыты показали, что
>shKeybrd
> (shMouse, shKeybrd2) должны находиться именно там,
> иначе не работает.


Жаль. Следует всё же понять почему shKeybrd, shMouse, shKeybrd2 должны быть именно там. Здесь лежит одна из причин

> почему он перестаёт быть валидным когда приложение
> перестаёт быть активным


Другая причина - здесь.

> DLL начинает пытаться вызвать эти методы у него?



> Ведь DLL подключена к моему приложению.

Нет. Точнее не только.


> Работает - не трогай! Золотое правило :)

Жаль. А я хотел помочь...


> Это не имеет значения, у меня свой обработчик.

Ну и что. Выпенреж может стоить геморроя.

Читай
http://www.delphimaster.ru/articles/hooks/index.html


 
Grief ©   (2005-02-12 23:14) [5]

скопируй другой пример :)
например, мой - посылает мессаи события мыши и клавы сразу:
library Catcher;

uses Messages, Windows;

type
 PGlobalDLLData = ^TGlobalDLLData;
 TGlobalDLLData = record
   KeyBoardHook: HWND;
   MouseHook: HWND;
 end;

var
 GlobalData: PGlobalDLLData;
 MMFHandle: THandle;
 WM_MouseHook, WM_KeyboardHook: Cardinal;

function MouseProc(Code: Integer; WParam: Word; LParam: Longint): Longint; stdcall;
begin
 if Code = HC_Action then PostMessage(HWND_Broadcast, WM_MouseHook, WParam, LParam);
 MouseProc := CallNextHookEx(GlobalData^.MouseHook, Code, WParam, LParam);
end;

function KeyboardProc(Code: Integer; WParam: Word; LParam: Longint): Longint; stdcall;
begin
 if Code = HC_Action then PostMessage(HWND_Broadcast, WM_KeyboardHook, WParam, LParam);
 KeyboardProc := CallNextHookEx(GlobalData^.KeyBoardHook, Code, WParam, LParam);
end;

procedure Hook(Switch: Boolean); export; stdcall;
begin
 if Switch = True then begin
   GlobalData^.MouseHook := SetWindowsHookEx(WH_Mouse, @MouseProc, HInstance, 0);
   if GlobalData^.MouseHook = 0 then
     MessageBox(0, "Не удается установить ловушку для мыши!", "Критическая ошибка", MB_IconError);
   GlobalData^.KeyboardHook := SetWindowsHookEx(WH_Keyboard, @KeyboardProc, HInstance, 0);
   if GlobalData^.KeyBoardHook = 0 then
     MessageBox(0, "Не удается установить ловушку для клавиатуры!", "Критическая ошибка", MB_IconError);
 end
 else begin
   if UnhookWindowsHookEx(GlobalData^.KeyBoardHook) = False then
     MessageBox(0, "Не удается снять ловушку для клавиатуры!", "Критическая ошибка", MB_IconError);
   if UnhookWindowsHookEx(GlobalData^.MouseHook) = False then
     MessageBox(0, "Не удается снять ловушку для мыши!", "Критическая ошибка", MB_IconError);
 end;
end;

procedure OpenGlobalData;
begin
 WM_KeyboardHook := RegisterWindowMessage("WM_KeyboardHook");
 WM_MouseHook := RegisterWindowMessage("WM_MouseHook");
 MMFHandle := CreateFileMapping(Invalid_Handle_Value, nil, PAGE_ReadWrite, 0, SizeOf(TGlobalDLLData), "MyMMF");
 if MMFHandle = 0 then
   MessageBox(0, "Can""t create FileMapping", "Message from Exampel2/Process2", 0);
 GlobalData := MapViewOfFile(MMFHandle, File_Map_All_Access, 0, 0, SizeOf(TGlobalDLLData));
 if GlobalData = nil then
   begin
     CloseHandle(MMFHandle);
     MessageBox(0, "Can""t make MapViewOfFile", "Кртитическая ошибка", 0);
   end;
end;

procedure CloseGlobalData;
begin
 UnmapViewOfFile(GlobalData);
 CloseHandle(MMFHandle);
end;

procedure DLLEntryPoint(dwReason: DWord); stdcall;
begin
 case dwReason of
   DLL_Process_Attach: OpenGlobalData;
   DLL_Process_Detach: CloseGlobalData;
 end;
end;

exports Hook;

begin
 DLLProc:= @DLLEntryPoint;
 DLLEntryPoint(DLL_Process_Attach);
end.



 
GuAV ©   (2005-02-13 00:04) [6]


>скопируй другой пример :)
> например, мой

LOL


 
Goorus ©   (2005-02-13 04:48) [7]

>> Grief
Видишь ли, PostMessage я бы тоже не хотел использовать :)

>> GuAV
Помогите, очень прошу. Вы указываете на причины ошибки, а я не понимаю её сути.
> А почему не safecall ?
Зачем? Насколько я понимаю, safecall отличается от stdcall только тем, что берёт весь код в структуру try..except end, и в случае ошибки результатом выполнения функции будет S_EXCEPT. Разве нет?


 
GuAV ©   (2005-02-13 13:13) [8]

Не нужно ни safecall ни stdcall. В справке (DllProc + F1) дано объявление без указания модели. Т.е. использована register. Почему оно работает, вопрос конечно интересный. С вызовом DLL_PROCESS_ATTACH вопросов нет - как описали так и вызвали из begin..end. Что касается DLL_PROCESS_DETACH = 0, то этот параметр читается из стека, где он тоже оказывается равным 0 и "деформация" стека похоже не сказывается на выгрузке (по крайней мере сообщений об ошибках нет). Однако не факт что с выгрузкой никогда не будет проблем, а кроме того есть ещё и DLL_THREAD_ATTACH/DETACH.

Суть такова. SetWindowsHookEx(... , 0); устанавливает глобальный хук, который работает во всех потоках текущего десктопа. Следовательно эта dll загружается многими процессами. Если dll загруженна разными процессами, у каждой из них свои данные (и, возможно, код, если он будет отличатся). Инициализация происходит при загрузке каждым из процессов, соотв финализация при выгрузке каждым из процессов.

Т.е. для того чтобы какие либо переменные имели одинаковые значения во всех экземплярах dll и изменяли их при изменении в одном из экземпляров, следует возпользоваться каким либо механизмом обмеа данных между процессами, в данном случае MMF. Так, при назначении AppWnd из RunHook2, экземпляры dll загруженные позже уже получат это значение (если бы были уже загруженные в них бы тоже поменялось), что касается AppProcKeybrd, то изменение значения в экзепляре, загруженном для выполнения RunHook никак не отразится на других - в них останется неназначенный метод (глоб. переменные инициализируются нулями).

Помещение AppProcKeybrd в TGlobalData, однако, не решит проблемы. Дело в том что поскольку dll загруженна другим процессом, эти самые указатели на код и на даные будут разрешены в контексте того процесса. Что при этом поучится - неизвестно, хотя вероятно AV в большинстве случаев.

Почему методы всё же работают в своём процессе - для него используется копия загруженная для выполнения RunHook2. Почему перестают работать - там видимо  библиотека подключается динамически (через вызовы loadlibrary(ex)/freelibarary), и она выгружается и вновь загружается.

Способ решения - передавать сообщения, а методы запускать только в своём компоненте. Я подозреваю что он наследник TComponent поэтому в нём следует самому создать окно для приёма сообщений. (Рекомендую воспользовать AllocateHWND, в оконном методе можно делать Dispatch, а можно просто case). Или, создать поток для приёма сообщений.


 
GuAV ©   (2005-02-13 13:20) [9]

GuAV ©   (13.02.05 13:13) [8]
Или, создать поток для приёма сообщений.


С потоком я конечно погорячился. Не следует создавать поток, который будет только спать и синхронизироваться.


 
GuAV ©   (2005-02-13 14:33) [10]

Да, ещё, про


> function RunHook2(OnKeybrd: HWnd): Boolean; export;
>stdcall;
>begin
> Result := False;
> with GlobalData^ do
> if not Runing then
> try
>   AppWnd := OnKeybrd;
>
>    shKeybrd2 := SetWindowsHookEx(WH_KEYBOARD,
>@SysMsgKeybrdProc2, hInstance, 0);
>
>   Result := True;
>   Runing := True;
> except
>
> end;
> end;


Такая конструкция не потокобезопасна. Т.е. если из двух приложений будут почти одновременно вызваны RunHook, то оба вызова состоятся, причём возможно shKeybrd будет соответствовать хуку одного, а shMouse  - другого, а установленны быть все четыре. Поэтому лучше использовать такую конструкцию

 if InterlockedCompareExchange(Pointer(Running),
   Pointer(True), Pointer(False)) <> Pointer(False) then
 try
   ...
 except
   Runing := Fasle;
 end;


Кстати except здесь IMHO не нужен. Если SetWindowsHookEx не удасться, то исключения не будет, просто он вернёт 0 (кроме случаев типа AV, stack overflow). Достаточно проверять shKeybrd <> 0.


 
Goorus ©   (2005-02-13 16:02) [11]

Большое спасибо :) Буду использовать SendMessage.

Ещё вопрос: тогда получается, что несколько приложений одноверменно не смогут пользоваться этой библиотекой? Ведь все они будут использовать один временный файл, в котором будут записаны данные последней запущенной библиотеки. Прийдётся имя файла брать что-то вида
MMFName + IntToStr(hInstance)


 
GuAV ©   (2005-02-13 16:47) [12]

Goorus ©   (13.02.05 16:02) [11]
Ещё вопрос: тогда получается, что несколько приложений одноверменно не смогут пользоваться этой библиотекой?

Верно.

Goorus ©   (13.02.05 16:02) [11]
временный файл

Это не файл, а проекция файла. В данном случае проекция page file, т.е. просто область памяти, "поддерживаемая" page file.

Goorus ©   (13.02.05 16:02) [11]
MMFName + IntToStr(hInstance)

Нет. Нужно брать что-то действительно уникальное. ProcessId или ThreadId подойдут.
hInstance для ехе практически всегда = ImageBase = $00400000, для Dll в лучшем случае равно ImageBase, в общем - что угодно.

Причём помимо разделения по приложениям ещё следует учесть возможность двух и более копий компонента в одном приложении. Если такую возможность нужно предусмотреть, то следует создать только одно окно на всю библиотеку, из которого вызывать обработчики, назначенные в каждом из экземпляров компонента (придётся обеспечить учёт экземпляров компонента во внутреннем списке TComponentList).


 
GuAV ©   (2005-02-13 16:57) [13]

GuAV ©   (13.02.05 16:47) [12]
ProcessId или ThreadId подойдут.


Хотя и это не совсем верно. Исключается возможность использовать библиотеку в ехе и dll независимо. Наиболее правильным думаю будет
GetModuleFileName с параметром hInstance (не 0, а именно SysInit.HInstance)


 
GuAV ©   (2005-02-13 17:08) [14]

GuAV ©   (13.02.05 16:57) [13]
GetModuleFileName с параметром hInstance (не 0, а именно SysInit.HInstance)


Причём SysInit.HInstance должнен быть взят из кода модуля компонента, а не dll. Т.е. выходит что его нужно передать как параметр RunHook.


 
Goorus ©   (2005-02-13 17:21) [15]

Спасибо ещё раз.


 
GuAV ©   (2005-02-13 22:35) [16]

Блин, я туплю..
Самый уникальный идентификатор, чтобы прибавить к MMFName - это AppWnd !


 
Piter ©   (2005-02-14 01:03) [17]

GuAV ©   (13.02.05 22:35) [16]
Самый уникальный идентификатор, чтобы прибавить к MMFName - это AppWnd !


а чем он уникальнее, например, ID процесса или потока?
И нет никакой гарантии, что кто-то не прибавит AppWnd твоего процесса.

Так что 100% уникальность гарантировать нельзя, ясное дело.


 
Goorus ©   (2005-02-14 03:11) [18]

Это мелкий вопрос, в принципе, имя файла никого не волнует, так что можно брать AppWnd + Random + GetTickCount, придумаю что-нибудь.


 
GuAV ©   (2005-02-14 08:34) [19]

Piter ©   (14.02.05 1:03) [17]
а чем он уникальнее, например, ID процесса или потока?


Тем что в случае использования компонента в нескольких dll без BwRTP он будет один и тот же.

Piter ©   (14.02.05 1:03) [17]
И нет никакой гарантии, что кто-то не прибавит AppWnd твоего процесса.

???


 
GuAV ©   (2005-02-14 08:47) [20]

Хотя... отставить. Ничего со случайным идентификатором не выйдет, тк. он должен совпасть для dll загруженных данным процессам во все процессы. Придётся наверное в GlobalData массив создавать.


 
Goorus ©   (2005-02-14 17:54) [21]

Я опять чего-то не понял. Разве GlobalData в различных приложения будет различна? Сейчас сделал так:

library HookLibrary;

uses
 Windows, Dialogs,
 Messages,
 ghlbTypes in "..\ghlbTypes.pas";

const
 MMFName_ = "HookMsg";

var

 InWorking: Boolean = False;
 Runing: Boolean = False;

 MMFName: String;
 MMFHandle: THandle;

 GlobalData: PGlobalData;

function IntToStr(const X: Int64): String;
begin
 Str(X, Result);
end;

function SysMsgKeybrdProc(code: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
begin
 if not Assigned(GlobalData) then
   ShowMessage("not Assigned")
 else
 with GlobalData^ do
 if (code = HC_ACTION) and (not InWorking) then
 try
   InWorking := True;
   SendMessage(AppWnd, GMH_KEYBOARD, wParam, LParam);
 finally
   Result := CallNextHookEx(shKeybrd, Code, wParam, LParam);
   InWorking := False;
 end
 else
   Result := CallNextHookEx(shKeybrd, Code, wParam, LParam);
end;

function SysMsgMouseProc(code: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
begin
 with GlobalData^ do
 if (code = HC_ACTION) and (not InWorking) then
 try
   InWorking := True;
   msgMouse := TMouseHookStruct( Pointer(LParam)^ );
   SendMessage(AppWnd, GMH_MOUSE, wParam, LParam);
 finally
   Result := CallNextHookEx(shMouse, Code, wParam, LParam);
   InWorking := False;
 end
 else
   Result := CallNextHookEx(shMouse, Code, wParam, LParam);
end;

procedure OpenGlobalData;
begin
 if MMFName = "" then Exit;
 if Assigned(GlobalData) then Exit;
 // получаем объект файлового отображения
 MMFHandle := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE,
   0, SizeOf(TGlobalData), PChar(MMFName)
 );
 if MMFHandle = 0 then
 begin
   MessageBox(0, "Невозможно создать FileMapping", "Сообщение из HookLib.dll", 0);
   Exit;
 end;
 // отображаем глобальные данные на АП вызывающего процесса и
 // получаем указатель на начало выделенного пространства
 GlobalData := MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0,
   SizeOf(TGlobalData)
 );
 if GlobalData = nil then
 begin
   CloseHandle(MMFHandle);
   MessageBox(0, "Невозможно создать MapViewOfFile", "Сообщение из HookLib.dll", 0);
   Exit;
 end;
end;

function RunHook(AAppWnd: HWnd): PGlobalData; export; stdcall;
begin
 Result := nil;

 if not Runing then
 begin
   // создаём уникальное имя
   MMFName :=
     MMFName_ + "-" + IntToStr(GetCurrentProcessId) +
     "-" + IntToStr(GetCurrentThreadId) + "-" + IntToStr(AAppWnd) +
     "-" + IntToStr(GetTickCount) + "-" + IntToStr( Random(MaxInt) )
   ;

   OpenGlobalData;

   with GlobalData^ do
   begin
     AppWnd := AAppWnd;

     shKeybrd := SetWindowsHookEx(WH_KEYBOARD, @SysMsgKeybrdProc, hInstance, 0);
     shMouse := SetWindowsHookEx(WH_MOUSE, @SysMsgMouseProc, hInstance, 0);
   end;

   Result := GlobalData;
   Runing := True;
 end;
end;

procedure StopHook(); export; stdcall;
begin
 with GlobalData^ do
 try
   UnHookWindowsHookEx(shKeybrd);
   UnHookWindowsHookEx(shMouse);
 finally
   shKeybrd := 0;
   shMouse := 0;
 end;
 Runing := False;
end;

procedure CloseGlobalData;
begin
 if Assigned(GlobalData) then
 begin
   UnmapViewOfFile(GlobalData);
   CloseHandle(MMFHandle);
 end;
end;

procedure DLLEntryPoint(dwReason: DWord); register;
begin
 case dwReason of
//    DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH: OpenGlobalData;
   DLL_PROCESS_DETACH: begin
     if Runing then StopHook;
     CloseGlobalData;
   end;
 end;
end;

exports RunHook;
exports StopHook;

begin
 Randomize;
 DLLProc := @DLLEntryPoint;
end.

Если я нажимаю клавишу на клавиатуре в другом приложении, сообщение "not Assigned" появляется.. Но почему? Ведь GlobalData ссылается на MapViewOfFile, а оно ведь не привязано к приложению?

В ghlbTypes:

type

 TGlobalData = record
   shKeybrd: HWnd;  // дескриптор ловушки клавы
   shMouse : HWnd;  // ловушки мыши

   AppWnd: HWnd;
   // данные хука
   msgMouse: TMouseHookStruct;
 end;
 PGlobalData = ^TGlobalData;

var
 GMH_KEYBOARD: Cardinal;
 GMH_MOUSE: Cardinal;
...


 
GuAV ©   (2005-02-14 19:12) [22]

Goorus ©   (14.02.05 17:54) [21]
  // создаём уникальное имя
  MMFName :=
    MMFName_ + "-" + IntToStr(GetCurrentProcessId) +
    "-" + IntToStr(GetCurrentThreadId) + "-" + IntToStr(AAppWnd) +
    "-" + IntToStr(GetTickCount) + "-" + IntToStr( Random(MaxInt) )
  ;


Так не получится.... немного раньше в [20] об этом написал. Если нужно несколько копий, придётся массив внутри globaldata  делать...


 
Goorus ©   (2005-02-15 03:53) [23]

Тесты показали.. :)
DLL подключается к другому приложению, когда в нём происходит отлавливаемое событие, при этом MMFName = "", а GlobalData = nil.
То есть все переменные сбрасываются.. Точнее библиотека заново загружается и подключается к этому рпиложению. Но тогда получается, что библиотека никак не сможет узнать к какому же приложению она на самом деле подключена, т.е. создать библиотеку, которую можно использовать сразу в нескольких приложениях невозможно?!
Даже если создать в GlobalData массив, DLL не будет знать, к какому элементу обращаться... индекс ведь опять нужно хранить вне библиотеки, где он опять же будет переписан другой ДЛЛ...


 
Digitman ©   (2005-02-15 08:40) [24]


> DLL подключается к другому приложению, когда в нём происходит
> отлавливаемое событие


точнее сказать, DLL загружается в АП целевого процесса


> при этом MMFName = "", а GlobalData = nil
> То есть все переменные сбрасываются


сколько будет этих целевых процессов, столько будет и экземпляров данных DLL


> библиотека никак не сможет узнать к какому же приложению
> она на самом деле подключена


почему не может ? может !
см. GetModuleHandle + GetModuleFileName



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2005.03.27;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.56 MB
Время: 0.042 c
6-1106804477
ТехникПТО
2005-01-27 08:41
2005.03.27
Copy в WebBrowsere


3-1109060114
Term
2005-02-22 11:15
2005.03.27
Как открыть OLE документ из BLOB-поля


1-1110882991
ksu
2005-03-15 13:36
2005.03.27
Мигающий текст в StringGrid


3-1109799582
PalladinA
2005-03-03 00:39
2005.03.27
Как из программы изменить путь к БД, прописанный в BDE?


3-1109679828
Valeriya
2005-03-01 15:23
2005.03.27
Drop table





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский