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

Вниз

Передать хенда программы в DLL?   Найти похожие ветки 

 
NetKnight   (2003-10-10 02:22) [0]

Вообщем есть такая прога:


program winctrls;

uses
Messages, Windows, SysUtils;

var
Message:TMsg;
ProcAddr,MAP:Pointer;
DLL:HINST;
sPath:string;
Handle,MapHandle:THandle;

begin
sPath:=ExtractFilePath(ParamStr(0))+"keyhook.dll";
DLL:=LoadLibrary(PChar(sPath));
ProcAddr:=GetProcAddress(DLL,PChar("KeyboardProc"));
Handle:=GetCurrentProcess;
MapHandle:=CreateFileMapping($ffffffff,nil,PAGE_READWRITE, 0, 64000, PChar("AppHandle"));
MAP:=MapViewOfFile(MapHandle,FILE_MAP_WRITE,0,0,64000);
StrPCopy(MAP,PChar(@Handle));
FlushViewOfFile(Map,64000);
UnMapViewOfFile(Map);
SetWindowsHookEx(WH_KEYBOARD,ProcAddr,DLL,0);
While GetMessage (Message, 0, 0, 0) do
begin
TranslateMessage (Message);
DispatchMessage (Message);
end;
Halt(Message.wParam);
end.


И вот такая DLL c функцией обработки клавиатурных сообщений:

library keyhook;

uses
Messages, Windows, SysUtils;

{$R *.res}

function KeyboardProc(Code:integer;wParam:WPARAM;lParam:LPARAM):LRESULT; stdcall;
var msg:string;
MAP:Pointer;
MapHandle,AppHandle:THandle;
begin
MapHandle:=OpenFileMapping(FILE_MAP_READ, true, PChar("AppHandle"));
Map := MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 64000);
AppHandle:=Cardinal(PChar(MAP));
msg:=inttostr(AppHandle);
Result:=0;
if (lParam<0) then
begin
if (lParam=KF_ALTDOWN) then MessageBox(0,PChar("ALT PRESSED"),PChar("ALT ALERT!"),0);
case wParam of
VK_SPACE:
begin
MessageBox(0,PChar(msg),PChar("HOOK ALERT!"),0);
end;
end;
end;
end;

exports
KeyboardProc;

begin
end.


Ясен пень, что программа не дописана, но суть я думаю ясна. Нужно перехватывать ВСЕ сообщения клавиатуры. Вроде как всё работает, но когда через FileMapping передаётся хендл, то он почему-то получается в ДЛЛ не такой, как отправляет его программа. Как можно передать хендл тут? Или можно ли это всё в одном файле сделать? у меня не получалось.. :(


 
Digitman   (2003-10-10 09:09) [1]

для начала вместо
StrPCopy(MAP,PChar(@Handle));
напиши
PInteger(MAP)^ := Handle

а вместо
AppHandle:=Cardinal(PChar(MAP));
напиши
AppHandle:=THandle(PInteger(MAP)^);

а вообще несуразиц в твоем коде немало

1. Каков смысл передавать в хук-ДЛЛ псевдохэндл процесса, устанавливающего хук ? Ну получил ты его, предположим ...Как ты собираешься его далее в теле хук-ДЛЛ использовать ?

2. Зачем всякий раз при исполнении тела процедуры KeyboardProc() создавать FileMap-объект ? Достаточно сделать это 1 раз в ходе инициализации хук-ДЛЛ


 
NetKnight   (2003-10-10 13:24) [2]

Вообщем смысл в том, что нужно по определённому сообщению клавиатуры завершить программу, а для этого нужен хендал, чтоб выполнить closehandle.
Или есть способы проще?


 
Digitman   (2003-10-10 14:29) [3]

с closehandle() брось затею.
не будет это работать в том примитивном виде, как ты себе представляешь

процесс, устанавливающий хук, может, например, создать объект синхронизации типа event.

после создания event"а устанавливается собственно хук и далее в цикле выполняется MsgWaitForMultipleObjects(), чтобы реагировать на оконные сообщения и одновременно ждать срабатывания eventa.

хук-DLL при инициализации получает хэндл event"а по заранее оговоренному его имени.

процедура KeyboardProc() при обнаружении нужного клав.сообщения "сигналит" event"ом, сигнал "ловится" приложением, это - условие выхода из цикла ожидания, следом за которым хук снимается и приложение можно завершать банальным Application.Terminate


 
NetKnight   (2003-10-10 16:24) [4]

Digitman
А может мьютекс создать и как он пропадает, рубить программу? :)

Кстати Application в консольном режиме не сущевствует. Она только в оконных прогах есть. Тут можно только убить процесс.
Или я в юниксах пересидел? :)


 
Ketmar   (2003-10-10 16:32) [5]

>NetKnight © (10.10.03 16:24) [4]
ты прав. нету. если не создать руками %-) но, тем не менее, можно создать поток, который будет получать сообщения (есть такая фича). и ждать сообщения WM_USER_I_MUST_DIE %-)


 
Digitman   (2003-10-10 16:33) [6]


> А может мьютекс создать


а какая разница ? мьютекс - тоже объект синхронизации


> Кстати Application в консольном режиме не сущевствует


потому что объект TApplication никто не создавал.
создай - будет существовать.


> Тут можно только убить процесс.


чушь.


 
nikkie   (2003-10-10 16:37) [7]

передавать надо не хендл, а id. и лучше не процесса, а потока. тогда можно будет отправлять сообщения через PostThreadMessage. а иначе не очень понятно зачем цикл выборки сообщений написан.


 
NetKnight   (2003-10-11 20:52) [8]

А можно поточнее объяенить, как это должно работать? Что-то не очень понятно..


 
nikkie   (2003-10-11 21:58) [9]

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

1. передавать не хендл, а id потока, получаемого с помощью
GetCurrentThreadId

2. прервать цикл выборки сообщений в программе можно, послав WM_QUIT:
PostThreadMessage(ThreadId, WM_QUIT, 0, 0)

3. поскольку в программе никаких окон не создается, то смысла в TranslateMessage/DispatchMessage нет. вреда, впрочем, тоже.

4. ну и учти то, что тебе Digitman написал про передачу данных и FileMapping.


 
NetKnight   (2003-10-13 15:50) [10]

Так, вообщем до PostThreadMessage вроде всё правильно работает, но вот как теперь программа должна поймать это сообщение?


 
Digitman   (2003-10-13 16:07) [11]


> NetKnight


см. GetMessage(), PeekMessage(), MsgWaitForMultipleObjects()


 
NetKnight   (2003-10-17 14:04) [12]

Что-то в MSDN"е я не совсем понял, как это делается...

Вообщем вот так отсылаю сообщение из dll о том, что нужно вырубаться:

PostThreadMessage(id,WM_QUIT,0,0);

id - это переменная, которая получена приложением функцией GetCurrentThreadId и отправленная в dll.

Но вот как поймать это сообщение? Может кто-нить пример напишет, как это делается. Что-то я не догоняю.

Пробовал так:

While GetMessage (Message, 0, 0, 0) do
begin
if Message.message=WM_QUIT then exit;
end;

А как пользоваться MsgWaitForMultipleObjects() я не догнал, пример нужен :(


 
Digitman   (2003-10-17 14:11) [13]


> Пробовал так:
>
> While GetMessage (Message, 0, 0, 0) do
> begin
> if Message.message=WM_QUIT then exit;
> end;


в случае получения сообщения WM_QUIT строчка в теле цикла никогда не выполнится , ибо при получении данного сообщения ф-ция GetMessage() вернет False, по факту чего оператор WHILE благополучно закруглит исполнение цикла, и управление перейдет на строчку, следующую за оператором end


 
NetKnight   (2003-10-17 14:23) [14]

Digitman,
Но за циклом программа делает Unhook и кончается, следовательно она должна завершить выполнение. Но этого не происходит.. :(

Вот что следует далее:

While GetMessage (Message, 0, 0, 0) do
begin
if Message.message=WM_QUIT then halt;
end;
UnhookWindowsHookEx(hk);
Halt(Message.wParam);
end.


 
Digitman   (2003-10-17 14:54) [15]


> Но этого не происходит


я не понял - UnhookWindowsHookEx(hk) выполняется или нет ? Ты брейкпойнт ставил на эту строчку, ловил останов на ней ?


 
NetKnight   (2003-10-17 15:26) [16]

Всё разобрался! :)
У меня каким-то образом переданный ProcessId не соответстовал реальному.. Поправил, теперь вё заработало....
Пока GetLastError не просмотрел, бился головой о стену :)


 
Digitman   (2003-10-17 16:27) [17]


> Пока GetLastError не просмотрел, бился головой о стену :)


что ж мешало ? амбиции ?))



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

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

Наверх





Память: 0.49 MB
Время: 0.008 c
1-36748
Sacred
2003-12-02 01:12
2003.12.12
Противоположность Application.Run?


7-36868
--olg-
2003-10-03 09:53
2003.12.12
Управление притером через WinSpool (WinXP)


3-36561
BlackCat
2003-11-20 09:46
2003.12.12
Борьба с Ado


1-36718
konstantinov
2003-12-02 00:44
2003.12.12
Оптимизация кода


3-36519
Nick-From
2003-11-19 19:55
2003.12.12
Обработка исключения - Нет прав на выполнение действия





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