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

> ВНИМАНИЕ!

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

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

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


mea culpa
*****

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

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


Привет всем smile.gif

Надо поставить хук на создание окон. Нашел (и слегка модифицировал) такой код:

var HookHandle: hHook;

function CBTProc(Code: integer; WParam: word; LParam: Integer): Longint; stdcall;
type PCBT_CREATEWND=^CBT_CREATEWND;
var s: pchar;
z: PCBT_CREATEWND;
ok: Integer;
s2:string;
i:byte;
begin
if Code<0 then begin
Result := CallNextHookEx(HookHandle, code, WParam, LParam);
exit;
end;
case Code of
HCBT_CREATEWND: begin
z:=PCBT_CREATEWND(LParam);
s:=z.lpcs.lpszName;
if s<>nil then begin
s2:='';
for i:=1 to length(s) do begin
s2:=s2+s^;
inc(s);
end;
if pos('Блокнот',s2)>0 then begin
Result:=1;
exit;
end;
end;
end;
end;
Result := 0;
end;

begin
HookHandle := SetWindowsHookEx(WH_CBT, @CBTProc, HInstance, 0);
end;


Я сделал перевод из pchar в string, до этого там была какая-то жутко тупая проверка, которая почему-то работала. Этот код, как я понял, распространяется только на моё приложение. hookhandle>=0.

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


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


Гость






Хм. Интересно, куда подевались все вопросительные знаки? smile.gif Ты хоть один видишь? Я почему-то нет. Вопрос-то в чем?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


mea culpa
*****

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

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


В том, что код не работает как надо ) (по идее, при открытии блокнота блокнот не должен открыться).

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


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


Гость






Цитата
по идее, при открытии блокнота блокнот не должен открыться
С чего бы это? Заголовок окна Блокнота создается при обработке WM_CREATE, а хук твой срабатывает до того, как Блокноту будет выслано сообщение WM_CREATE. Пользуйся WH_SHELL-ом, а не WH_CBT.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


mea culpa
*****

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

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


Нуу.. я изменил code на WH_Shell, этого достаточно? Пока всё равно не ловит.


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


Гость






Цитата
этого достаточно?
Нет, конечно. Но меня посетила шальная мысль: а чего бы тебе в твоем предыдущем коде не проверять результат GetClassName? Класс окна блокнота известен: "Notepad" (и менять его, вроде, MS не собирается). Попробуй. Вот эта информация должна быть известна уже ДО отсылки приложению WM_CREATE, класс-то уже создан...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


mea culpa
*****

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

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


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

Пошукал в msdn, кажется надо так примерно:

function CBTProc(Code: integer; WParam: word; LParam: Integer): Longint; stdcall;
type PCBT_CREATEWND=^CBT_CREATEWND;
var s: pchar;
s2:string;
i:byte;
z: PCBT_CREATEWND;
begin
if Code<0 then begin
Result := CallNextHookEx(HookHandle, code, WParam, LParam);
exit;
end;
case code of
HSHELL_WINDOWCREATED: begin
z:=PCBT_CREATEWND(HSHELL_LANGUAGE); //hshell_language по мсдн должен возвращать хэндл окна
s:=z.lpcs.lpszName;
if s<>nil then begin
s2:='';
for i:=1 to length(s) do begin
s2:=s2+s^;
inc(s);
end;
if pos('Блокнот',s2)>0 then begin
Result:=1;
exit;
end;
end;
end;
end;
Result := 0;
end;

begin
HookHandle := SetWindowsHookEx(WH_SHELL, @CBTProc, HInstance, 0);
end.


Так примерно надо?..

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


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


Гость






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

Цитата
Так примерно надо?..

Цитата
hshell_language по мсдн должен возвращать хэндл окна
Чего-чего он должен возвращать? Все, что в MSDN сказано - это то, что при Code = HSHELL_WINDOWCREATED, параметр wParam будет содержать хэндл окна. Получить по известному хэндлу заголовок сможешь? smile.gif Получишь заголовок, посмотри, содержится ли в нем "Блокнот", и если да - то убивай окно, потому как WH_SHELL не может отменить создание, окно уже было создано. Отменить создание через Result = ненулевое_значение можно, когда ты перехватываешь HCBT_CREATEWND. Но тогда тебе нельзя работать с заголовком окна, он еще не создан smile.gif Выбирай...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


mea culpa
*****

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

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


Цитата
Отменить создание через Result = ненулевое_значение можно, когда ты перехватываешь HCBT_CREATEWND. Но тогда тебе нельзя работать с заголовком окна, он еще не создан


Я бы выбрал перехватывать HCBT_CREATEWND. В оригинале функция хорошо справлялась с завершением диалогов открытия. Но, раз хэндла нет, что мы в том случае можем получить, pid процесса?


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


Гость






Что значит, нет Хэндла? Я где-то тебе сказал про то ,что нет хэндла? Я сказал, что на момент перехвата HCBT_CREATEWND тебе не гарантируется наличие заголовка окна. Хэндл есть всегда, он содержится в wParam:

Цитата
Code
HCBT_CREATEWND
wParam
Specifies the handle to the new window.
lParam
Specifies a long pointer to a CBT_CREATEWND structure containing initialization parameters for the window. The parameters include the coordinates and dimensions of the window. By changing these parameters, a CBTProc hook procedure can set the initial size and position of the window.


И что тебе это дало? Что будешь делать с хэндлом? Как определишь, что это именно блокнот, а не IE, скажем?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


mea culpa
*****

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

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


А у меня есть хитроумная функция, которая выдаст путь к файлу по хэндлу smile.gif

uses tlhelp32;
Function HandtoPath(H: HWND): String;
Var
Pid:Cardinal;
M: TModuleEntry32;
HSnapshot: THandle;
Begin
Result:='';
GetWindowThreadProcessId(H,@Pid);
HSnapshot:=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,Pid);
If HSnapshot=-1 Then Exit;
M.DwSize:=SizeOf(TModuleEntry32);
If Module32First(HSnapshot,M) Then Result:=M.SzExePath;
CloseHandle(HSnapshot);
End;


Приблизительно получится понять, что запустилось..

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


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


Гость






Цитата(Unconnected @ 14.09.2010 15:09) *
универсальность нужна..
и
Цитата(Unconnected @ 14.09.2010 17:27) *
Приблизительно получится понять, что запустилось..
это взаимоисключающие параграфы. Вот возьму я, скопирую notepad.exe в другую папку под именем SuperPuper.exe, и где будет твоя универсальность, когда эта программа запускаться будет? Там же, где и твоя хитроумная функция приблизительно smile.gif Не надо делать сложным то, что можно сделать просто. Имя класса окна вычисляется элементарно, для этого достаточно написать простенькую утилитку, и запустить один раз то приложение, которое будешь потом запрещать. Все, после этого никакие ухищрения с копированием EXE-файлов уже не проходят, приложение бракуется на другом уровне.

Дело, конечно, твое, только ты ж потом опять придешь, когда выяснится, что программа не работает как нужно, и вместо того, чтоб переписать как надо, будешь опять наворачивать на своего монстра еще и еще кода.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


mea culpa
*****

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

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


И правда, по классу лучше определять.. что-то я не подумал) Тогда так:

function getclname(wnd:hwnd):string;
var
Cl:array[0..pred(MAX_PATH)] of char;
begin
GetClassName(wnd,cl,MAX_PATH);
result:=cl;
end;

function CBTProc(Code: integer; WParam: word; LParam: Integer): Longint; stdcall;
begin
if Code<0 then begin
Result := CallNextHookEx(HookHandle, code, WParam, LParam);
exit;
end;
case Code of
HCBT_CREATEWND: begin
showmessage(getclname(wparam));
end;
end;
Result := 0;
end;

begin
HookHandle := SetWindowsHookEx(WH_CBT, @CBTProc, HInstance, 0);
end;


Укоротил донельзя, а всё равно не того.


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


Гость






Можешь прикрепить весь проект?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


mea culpa
*****

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

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


Он на "любимом" KOL... smile.gif Надо? Но ловушка точно ставится, я проверял, проходит куча сообщений через неё.

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

added: сейчас воткнул функцию в обычный проект D2007 - то же самое.

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


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


Гость






Цитата
а всё равно не того
Ну, поскольку Дельфи у меня под рукой нет, и не будет до конца недели (ну полетел у меня компьютер, где были установлены Дельфи и Билдер, да и все остальное - тоже, сейчас я на старой машине, почти пустой, из программного обеспечения - только FF + FPC /который, как выяснилось, даже DLLProc не знает, блин, поделка для первокурсников, пишущих консольные сортировалки, а не язык dry.gif ДЛЛ оформить нормально - и то не получается /), написать рабочий код не могу, а исходников не для KOL у тебя нет - буду доканывать тебя теоретическими вопросами. Ты ловишь HCBT_CREATEWND? А что, ShowMessage окно не создает по-твоему? У тебя ж зависнет все на фиг, это единственное, чего ты добьешься...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #17


mea culpa
*****

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

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


Цитата
ДЛЛ оформить нормально - и то не получается


Какое ценное лирическое отступление! Так значит, надо именно в dll хук оформлять? Просто я помню делал глобальный хук на клаву, там это было необязательно...


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


Гость






Хм... Надо было все-таки исходники попросить у тебя... smile.gif
Цитата
HCBT_CREATEWND

Windows вызывает хук WH_CBT с этим при создании окна. Когда хук установлен как локальный, это окно должно создаваться потоком, на который установлен хук. Хук WH_CBT вызывается до того, как Windows пошлет новому окну сообщения WM_GETMINMAXINFO, WM_NCCREATE, или WM_CREATE. Таким образом, фильтрующая функция может запретить создание окна, вернув TRUE.
DLL, конечно нужна...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #19


mea culpa
*****

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

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


Ту би контин, блин.. Короче, такая dll:

library project1;

uses
sysutils,windows;

{$R *.res}
var hookhandle:HHook;

function getclname(wnd:hwnd):string;
var
Cl:array[0..pred(MAX_PATH)] of char;
begin
GetClassName(wnd,cl,MAX_PATH);
result:=cl;
end;

function CBTProc(Code: integer; WParam: word; LParam: Integer): Longint; stdcall;
begin
if Code<0 then begin
Result := CallNextHookEx(HookHandle, code, WParam, LParam);
exit;
end;
case Code of
HCBT_CREATEWND:begin
if pos('NOTEPAD',uppercase(getclname(wparam)))>0 then begin
result:=1;
exit;
end;
end;
end;
Result := 0;
end;

procedure LocalExitProc; far;
begin
if HookHandle<>0 then begin
UnhookWindowsHookEx(HookHandle);
end;
end;

exports CBTProc;
begin
end.



Подключаю пока самым простым образом:

function hoks(Code: integer; WParam: word; LParam: Integer): Longint; stdcall; external 'project1.dll' name 'CBTProc';
// также пробовал с таким прототипом: procedure hoks()

...

Procedure sethook;
begin
HookHandle := SetWindowsHookEx(WH_CBT, @hoks, HInstance, 0);
end;



Так надо?..


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


Гость






Заставил ты меня все-таки написать работающий хук на FPC smile.gif ...
Вот DLL-ка:
{$mode delphi}

Library Proj;

uses
SysUtils, Windows;

var
HookHandle: HHook;

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(HookHandle, code, myWParam, myLParam);
exit;
end;

case Code of
HCBT_CREATEWND:
begin
if pos('NOTEPAD', UpperCase(GetClName(myWParam))) > 0 then
begin
result := 1; exit;
end;
end;
end;

result := 0;
end;


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

procedure DelTheHook; stdcall;
begin
if HookHandle<>0 then
begin
UnhookWindowsHookEx(HookHandle);
end;
end;

exports
SetTheHook, DelTheHook;

end.


Вот так вызывается (это чистый WinAPI)

const
DLLName = 'proj.dll';

procedure SetTheHook; stdcall; external DLLname;
procedure DelTheHook; stdcall; external DLLname;

// ...

begin // Основной блок программы
if not WinRegister then begin
MessageBox(0, 'Register failed', nil, mb_Ok);
Exit;
end;
hWindow := WinCreate;
if longint(hWindow) = 0 then begin
MessageBox(0, 'WinCreate failed', nil, mb_Ok);
Exit;
end;

SetTheHook;

while GetMessage(@AMessage, 0, 0, 0) do begin
TranslateMessage(AMessage);
DispatchMessage(AMessage);
end;

DelTheHook;
Halt(AMessage.wParam);
end.



Любые приложения запускаются, кроме Notepad-а...
 К началу страницы 
+ Ответить 

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

 





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