IPB
ЛогинПароль:

> ВНИМАНИЕ!

Прежде чем задать вопрос, смотрите FAQ.
Рекомендуем загрузить DRKB.

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

3 страниц V < 1 2 3 >  
 Ответить  Открыть новую тему 
> Хук на HCBT_CREATEWND
сообщение
Сообщение #21


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


У меня почти то же самое было, только это работает)) Я понял, надо было в основной программе сразу писать процедуру из exports, без всяких name 'CBTProc'.. Большое спасибо smile.gif Всё чаще, когда у меня какой-то затык, я лезу смотреть созданные мною темы..))

Кстати, чтобы не таскать с собой отдельно dll - только извлекать из ресурсов в нужный момент? Прилинковать как-нибудь нельзя?


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #22


Гость






Цитата
Прилинковать как-нибудь нельзя?
Можно (через Project->Resources->New->User Data, а потом - извлекать через TResourceStream + SaveToFile), но не нужно. Спокойная жизнь надоела? Хочется слышать матюгание антивирусов? smile.gif
 К началу страницы 
+ Ответить 
сообщение
Сообщение #23


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


Простенький ксор перед добавлением в ресурсы, и после извлечения обратная операция - помогают smile.gif И потом такая тишина..)


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #24


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


Ещё вопрос, относительно "обратной связи". Мне в основной программе нужно узнавать, как там дела у ловушки, что она поймала и т.п. Но т.к. я не нашёл приём экспортирования переменных (наверное, этого вообще нельзя делать), то написал функцию, которая возвращает значение переменной. Так:

Function retb:integer;stdcall
begin
result:=b;
end;


Переменная b:integer=0; , описана глобально, когда ловушка что-то ловит - b присваивается число. В основной программе:

function retb:byte; stdcall; external mydlname;


Регистр названий одинаковый. В главной программе в таймере запрашиваю значение retb (интервал 100мс), но оно почему-то всегда равно 0, даже когда точно известно, что ловушка сработала..


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #25


Гость






Цитата
Переменная b:integer=0; , описана глобально, когда ловушка что-то ловит - b присваивается число.
Ага, размечтался smile.gif Вот здесь посмотри, как возвращать данные из DLL в приложение: http://www.mustangpeak.net/hooks.htm (там внизу прилеплен архив с примером, который работает с MMF - Memory Mapped Files). Сегодня вечером поменяю видеоплату на своем компьютере (уже купил наконец-то smile.gif ), тогда будет проще, начнется не теоретический разговор, а практический...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #26


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


blink.gif офигеть, из-за одной переменной столько кода непонятного! Неужели не предусмотрено что-то попроще? (хотя, гугл намекает, что нет). Может, можно описать во входных параметрах SetHook(var b:integer), а потом, в процедуре, присваивать? (да, так не нужно писать программы))

Вообще, самый элегантный метод - использовать txt в качестве посредника) Сработало - создал, принял - удалил..


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #27


Гость






Цитата
Вообще, самый элегантный метод - использовать txt в качестве посредника) Сработало - создал, принял - удалил..
Угу. Если получилось - удалил, ты имеешь в виду? Можно, конечно, и TXT-файлами пользоваться для обмена информацией. Но ты для начала задачу озвучь, что именно нужно тебе получать? Сколько окон было заблокировано? Сколько раз вообще вызывалась ловушка? Что именно? Может, найдем и более красивое решение

P.S. (Показать/Скрыть)
 К началу страницы 
+ Ответить 
сообщение
Сообщение #28


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


Цитата
Сколько окон было заблокировано? Сколько раз вообще вызывалась ловушка?


Устанавливается один раз, в библиотеке массив из 5 элементов с идентефикаторами программ, нужно просто в момент отлова неугодного окна сообщать об этом основной программой, в виде переменной с её (программы) индексом.

Со строками, как мне обещали мануалы, проблем нет. По крайней мере, окна нормально определяются по строкам из массива. А вот текстовик что-то не создаётся, а messagebox появляется только наполовину - звуком, само окошко не показывается)

По-моему, здесь способ с текстовиком самый оптимальный. Именно потому, что я буду проверять в таймере его существование, а существовать он будет только при срабатывании ловушки. А почему может не получиться удалить? Права? У меня туда манифест вшит, для UAC smile.gif

Сообщение отредактировано: Unconnected -


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #29


Гость






Если нужно просто возвращать индекс заблокированного окна, вот тебе еще один способ, навскидку (не тестировал, но явных причин не работать - не вижу, да и получше будет, чем с txt-файлами). У тебя ж хендл твоего окна не меняется после того, как ты хук установил? Вот в SetHook передавай хендл своего окна (главного окна приложения, либо какой-то формы, я не знаю, что там у тебя), а при блокировке приложения ловушкой - PostMessage этому окну, "так мол и так - заблокировано приложение <и информация о нем>", а в оконной функции своего приложения лови эти сообщения и обрабатывай как нужно. Лучше будет, чем с текстовыми файлами, да еще по таймеру заморачиваться. К таймеру бы вообще привязываться не надо.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #30


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


Вот так шлю:

const wm_user=$0400; //в библиотеке эта константа почему-то была undeclared, юнит windows есть

begin
postmessage(whan,$0400+50000,i,0);//+50000 взял, чтоб наверняка попасть в [0xC000 ; 0xFFFF].
end;


Ловлю:

function TForm1.KOLFormMessage(var Msg: tagMSG;
var Rslt: Integer): Boolean;
begin
if msg.message=WM_USER+50000 then begin
//...используем wparam
result:=false; //дальше сообщению хода нет
end;
end;


Так надо? В KOL, кстати, очень удобная система работы с сообщениями, всё в одном обработчике.


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #31


Гость






Цитата
+50000 взял, чтоб наверняка попасть в [0xC000 ; 0xFFFF].
blink.gif Это еще зачем? MSDN явно говорит:
Цитата
Message numbers in the fourth range (0xC000 through 0xFFFF) are defined at run time when an application calls the RegisterWindowMessage function to retrieve a message number for a string. All applications that register the same string can use the associated message number for exchanging messages. The actual message number, however, is not a constant and cannot be assumed to be the same between different sessions.
Ты регистрировал сообщения через RegisterWindowMessage?

Я б на твоем месте все-таки использовал интервал WM_USER .. 0x7FFF, ты же фактически из своей библиотеки посылаешь сообщение своему же приложению, то есть, никаких разночтений возникнуть не должно. Вот если будешь посылать чужому приложению - тогда да, надо договариваться, что это сообщение означает... Посылай

postmessage(whan, WM_USER + 1, i, 0);
 К началу страницы 
+ Ответить 
сообщение
Сообщение #32


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


Очевидное-невероятное, блин! Передаю в sethook хэндл:

procedure SetTheHook(h:hwnd); stdcall;
begin
whan:=h;
if HookHandle = 0 then
begin
HookHandle := SetWindowsHookEx(WH_CBT, @CBTProc, HInstance, 0);
end;
end;


Смотрю в этой процедуре h - всё верно, совпадает с хэндлом формы, параметр был передан. whan (whan:hwnd, описана глобально), соответственно, присвоено значение h. Это если смотреть сразу после присваивания, в Sethook (я смотрел путём вывода в текстовик). Но в процедуре CBTProc почему-то whan всегда равна нулю!!! На локализацию этой фигни я угрохал полдня )) (зато теперь знаю, что прототип функции действительно лучше не менять)). И вот сейчас сижу и думаю, почему глобальная переменная в одном месте нормальная, а в другом - нулевая..
Значение whan в библиотеке ТОЧНО нигде не трогается, уже всё обсмотрел..

Сообщение отредактировано: Unconnected -


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #33


Гость






В общем, если не хочешь потерять еще три дня, и потом все-таки вернуться к тому, что я тебе написал в сообщении №25 - вернись сейчас. ТОЛЬКО MMF гарантируют тебе работу. Память должна быть общей (shared memory). Вот тебе еще один пример: Сайт из гуглокэша (начиная со слов "this is real working example". Проверено, действительно работает). Больше прописные истины повторять не буду. Хочешь экспериментировать - экспериментируй. Как надоест - скажешь.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #34


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


Короче на данный момент я остановился на текстовике. Логика программы предполагает, что если она вообще работает, то текстовик хватит прав создать... Просто из-за одной переменной добавлять (и разбирать) кода столько, сколько наверное во всей программе нет - нерационально как-то, что ли.. Наверное, я ещё вернусь к этой теме, когда будет "рациональней"..

volvo, ещё раз спасибо за советы, без них я бы тут далеко не уехал smile.gif

И всё же как-то странно, зачем нужна возможность создания глобальных переменных в dll, если такие дела с ними..

Сообщение отредактировано: Unconnected -


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #35


Гость






Цитата
Просто из-за одной переменной добавлять (и разбирать) кода столько, сколько наверное во всей программе нет - нерационально как-то, что ли..
blink.gif Смотри, как выглядит DLL с расшаренной памятью:
library myhook;

{ Тут было длинное предупреждение... }

uses
SysUtils, Windows, Messages;

{$R *.res}

type
PHookRec = ^THookRec;
THookRec =
record
AppWindow: HWND;
HookID: HHOOK;
end;

const
MY_MESSAGE = WM_USER + 1;
var
RHookRec: PHookRec = nil;


function GetClName(myWnd: HWND): String;
var
Cl: array[0 .. pred(MAX_PATH)] of char;
begin
GetClassName(myWnd, Cl, MAX_PATH);
result := cl;
end;

function CBTProc(Code: integer; myWParam: WPARAM;
myLParam: LPARAM): LRESULT; stdcall;
begin
if Code < 0 then
begin
Result := CallNextHookEx(RHookRec^.HookID, code, myWParam, myLParam);
exit;
end;

case Code of
HCBT_CREATEWND:
begin
if pos('NOTEPAD', UpperCase(GetClName(myWParam))) > 0 then
begin
PostMessage(RHookRec^.AppWindow, MY_MESSAGE, myWParam, 0);
result := 1; Exit;
end;
end;
end;
result := 0;
end;

procedure SetTheHook(Handle: HWND); stdcall;
begin
RHookRec^.AppWindow := Handle;
RHookRec^.HookID := SetWindowsHookEx(WH_CBT, @CBTProc, HInstance, 0);
end;
procedure DelTheHook; stdcall;
begin
UnhookWindowsHookEx(rHookRec^.HookID);
end;

{$J+}
procedure EntryPointProc(Reason: Integer);
const
hMapObject: THandle = 0;
begin
case reason of
DLL_PROCESS_ATTACH:
begin
hMapObject :=
CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(THookRec), 'volvo_CBT');
rHookRec := MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(THookRec));
end;

DLL_PROCESS_DETACH:
begin
UnMapViewOfFile(rHookRec);
CloseHandle(hMapObject);
end;

DLL_THREAD_ATTACH,
DLL_THREAD_DETACH: ;
end;
end;

exports
SetTheHook, DelTheHook;

begin
DllProc := @EntryPointProc;
EntryPointProc(DLL_PROCESS_ATTACH);
end.

Сколько кода добавлено? 10 строк? smile.gif Если что - вот VCL-ный проект, который ставит хук и получает сообщение о том, что окно было заблокировано (проект с DLL-кой тоже вложен):
Прикрепленный файл  hook_test.zip ( 73.85 килобайт ) Кол-во скачиваний: 269
 К началу страницы 
+ Ответить 
сообщение
Сообщение #36


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


Кажется понял, в библиотеке просто делается указатель на одну общую структуру, и какие-то пассы при инициализации)
Спасибо, сделал по-человечески) Только такой способ кажется не подходит для динамической подгрузки DLL? Делаю так:

type
Tsetthehook = procedure(Handle: HWND);stdcall;
Tdelthehook = procedure;stdcall;

var setthehook:TSetthehook;
delthehook:TDelthehook;
DLLInstance : THandle;

Procedure loadlib;
begin
try
DLLInstance := LoadLibrary(pchar(writepath+mydlname));
if DLLInstance = 0 then killmeplz;
@setthehook := GetProcAddress(DLLInstance, 'SetTheHook');
if @setthehook <> nil then setthehook(form1.form.handle) else killmeplz;
@delthehook := GetProcAddress(DLLInstance, 'DelTheHook');
finally
FreeLibrary(DLLInstance);
end;
end;


, и хэндлы внутри библиотеки опять обращаются в нули...

Сообщение отредактировано: Unconnected -


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #37


Гость






Цитата
Только такой способ кажется не подходит для динамической подгрузки DLL?
Вообще-то DLL-ке все равно, как ее подгружают, хоть загрузкой процесса, хоть LoadLibrary - в любом случае работает ветка DLL_PROCESS_ATTACH. А вот чего ты творишь в программе - непонятно. Ты DLL отключаешь (FreeLibrary) ГДЕ? Сразу после того, как адреса процедур получил? Ну-ну... smile.gif

Добавлено через 5 мин.
P.S. Только что подключил через LoadLibrary:
Procedure loadlib;
begin
DLLInstance := LoadLibrary(DLLname);
if DLLInstance = 0 then ShowMessage('Cannot Load DLL')
else
begin
@setthehook := GetProcAddress(DLLInstance, 'SetTheHook');
@delthehook := GetProcAddress(DLLInstance, 'DelTheHook');
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
loadlib;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
FreeLibrary(DLLInstance);
end;

Работает, зараза smile.gif
 К началу страницы 
+ Ответить 
сообщение
Сообщение #38


Гость






Все-таки решил добавить. Интересная и познавательная информация о написании своих DLL:
Несколько причин, чтобы не делать ничего страшного в своей DllMain
, и по ссылкам оттуда:
DllMain и жизнь до родов
DllMain - страшилка на ночь
Ещё причины, почему не надо делать ничего страшного в DllMain: случайная блокировка
 К началу страницы 
+ Ответить 
сообщение
Сообщение #39


mea culpa
*****

Группа: Пользователи
Сообщений: 1 372
Пол: Мужской
Реальное имя: Николай

Репутация: -  24  +


Цитата
Ты DLL отключаешь (FreeLibrary) ГДЕ?


Блин, ковырялся с дллами - и заснул)
И как я её только не отключаю (-ал) smile.gif Насколько понимаю, после FreeLibrary библиотека должна исчезнуть из памяти, чтобы предоставить возможность удалить саму dll. Но она что-то такой возможности не представляет, даже после завершения программы. Более того, происходит такая странная вещь - dll даёт себя удалить где-то через минуту.. Я сначала думал, что это связано с использованием string, позаменял все string на shortstring (длиннее 255 символов строк нет там), - не помогло.

Читаю Гансмокера. Кажется, затянется - в каждой статье куча перекрестных ссылок) Говорит, использование хуков при блокировке загрузчика ОС приведёт к катастрофе)


--------------------
"Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #40


Гость






Цитата
Насколько понимаю, после FreeLibrary библиотека должна исчезнуть из памяти, чтобы предоставить возможность удалить саму dll. Но она что-то такой возможности не представляет, даже после завершения программы.
Вот ты будешь смеяться, но:
Прикрепленный файл  Unit1.pas ( 1.88 килобайт ) Кол-во скачиваний: 330


прекрасно удаляет ту самую DLL-ку, которая была в прошлом проекте, только теперь она запихана в ресурсы и появляется в папке только при старте программы. После завершения - исчезает (нет, нет, не через минуту - я б столько не прождал smile.gif ). Что-то у тебя DLL не то делает, или ты мудришь с ее загрузкой. Откуда там взялись уже строки?

Цитата
И как я её только не отключаю (-ал)
А не надо ее "как только не отключать". Надо помнить, что каждый LoadLibrary или статическое подключение - это (+1) к счетчику ссылок, а каждое завершение процесса (при статическом подключении) или FreeLibrary - это (-1). До тех пор, пока счетчик этот не станет = 0, DLL выгружена не будет.
 К началу страницы 
+ Ответить 

3 страниц V < 1 2 3 >
 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 23.10.2020 7:03
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name