Форум: "Система";
Текущий архив: 2003.06.26;
Скачать: [xml.tar.bz2];
ВнизЗапрет всех контекстных меню в системе (ловушка) Найти похожие ветки
← →
_ALEXey_ (2003-04-09 19:03) [0]Здравствуйте, мастера и все, кто читает мой вопрос!
Вот какой вопрос меня интересует:
Есть библиотека, в ней - ловушка, которая должна запрещать показ всех всплывающих меню в системе. Запретить не удалось, а вот при выводе тут же его убрать можно. Код приведен ниже. Но вот незадача! менюшка, появляясь, и, тут же, исчезая, создает некрасивый эффект мерцания. В том-то и вопрос: как от этого избавиться ? Может посоветуете какие-нибудь иные способы решения этой задачи...
library Hooks;
uses
Windows,
Messages;
var
PopupMenuH: THandle;
{$R *.res}
function PopupMenuHook(Code, wParam, lParam: Integer): LResult; stdcall;
var
Param: ^MSG;
begin
Result:= 1;
If Code >= 0
then begin
Param:= Pointer(lParam);
If Code = MSGF_MENU
then SendMessage(Param^.hwnd, WM_CANCELMODE, 0, 0)
else Result:= CallNextHookEx(PopupMenuH, Code, wParam, lParam);
end
else
Result:= CallNextHookEx(PopupMenuH, Code, wParam, lParam);
end;
function SetPopupMenuHook: Boolean;
begin
Result:= True;
PopupMenuH:= SetWindowsHookEx(WH_SYSMSGFILTER, @PopupMenuHook, hInstance, 0);
If PopupMenuH = 0 then
Result:= False;
end;
procedure RemovePopupMenuHook;
begin
UnhookWindowsHookEx(PopupMenuH);
end;
exports
SetPopupMenuHook Name "SetPopupMenuHook",
RemovePopupMenuHook Name "RemovePopupMenuHook";
end.
← →
Almaz (2003-04-11 01:31) [1]Как вам должно быть известно, показ любого всплывающего меню в системе сводится к вызову функции
TrackPopupMenuEx
. Чтобы запретить показ всплывающих меню, необходимо запретить возможность вызова этой функции.
Известно, что данная функция реализуется в системной DLL - user32.dll, поэтому получить адрес точки входа в эту функцию можно следующим образом:
var
Address: Pointer;
...
Address := GetProcAddress(GetModuleHandle("USER32.DLL"), "TrackPopupMenuEx");
А теперь, зная точку входа, необходимо просто записать по этому адресу:
asm
MOV EAX,$0 // Результат выполнения функции всегда будет 0
RET 24 // 24 - это суммарный размер передаваемых через стек параметров
end;
В переводе на машинный код, это будет выглядеть как:
$B8 00 00 00 00 C2 18 00
Обобщая вышесказанное, получаем следующий код, запрещающий вызов TrackPopupMenuEx для отдельного процесса:
function DisablePopupMenu: Boolean;
const
CmdBuffer: array [0..7] of Byte = ($B8, $00, $00, $00, $00, $C2, $18, $00);
var
Address: Pointer;
OldProtect, Protect: DWORD;
begin
Address := GetProcAddress(GetModuleHandle("USER32.DLL"), "TrackPopupMenuEx");
if (Address <> nil) and VirtualProtect(Address, sizeof(CmdBuffer),
PAGE_EXECUTE_READWRITE, @Protect) then
begin
MoveMemory(Address, @CmdBuffer, sizeof(CmdBuffer));
VirtualProtect(Address, sizeof(CmdBuffer), Protect, @Protect)
end;
end;
Но я не зря подчеркнул, что именно для отдельного процесса, т.к. из за изолированности АП, изменения вносимые одной задачей не распроcтраняются на другие :)
Таким образом, чтобы запретить всплывающие меню во всей системе достаточно вызвать эту функцию в АП каждого процесса системы. Для этого достаточно описать эту функцию в DLLEntryPoint в обработчике события DLL_PROCESS_ATTACH глобальной ловушки типа WH_GETMESSAGE.
procedure DLLEntryPoint(dwReason: DWORD);
begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
...
DisablePopuMenu;
end
...
end
end;
p.s. Функцию, отменяющую это запрещение я надеюсь написать не составит труда :)
Удачи.
← →
Vlad Oshin (2003-04-11 08:23) [2]
> Almaz © (11.04.03 01:31)
Вам бы статью по этому поводу написать.
← →
_ALEXey_ (2003-04-11 10:15) [3]Almaz, благодарю за помощь! Честно говоря, я о таком способе не думал. Может подскажете, где можно найти описание всех функций, реализованных в подобных модулях (user32.dll, ...)?!
← →
DVM (2003-04-11 10:33) [4]
> Может подскажете, где можно найти описание всех
> функций, реализованных в подобных модулях (user32.dll, ...)?!
Как где? F1, MSDN, Книжки по WinApi. А вообще то нормальной документации на русском языке нет. Да и на английском, наверное только у Microsoft есть нормальная.
user32.dll, kernel32.dll, gdi.32.dll, shell32.dll - почти по 1000 функций в XP содержат. Это ж какой объем!
← →
Almaz (2003-04-11 23:21) [5]
> Vlad Oshin © (11.04.03 08:23)
> Вам бы статью по этому поводу написать.
Будет время - непременно :)
> _ALEXey_ © (11.04.03 10:15)
> Almaz, благодарю за помощь! Честно говоря, я о таком способе
> не думал. Может подскажете, где можно найти описание всех
> функций, реализованных в подобных модулях (user32.dll, ...)?!
Эти модули - стандартные библиотеки Win32. Полное их описание, как уже было сказано DVM © содержиться в Microsoft Development Network - MSDN ( http://msdn.microsoft.com).
Если просто хотите посмотреть список функций, реализованных в том или ином модуле, то можно воспользоваться утилитойtdump.exe
Кроме того существует очень неплохая книга-справочник по этим функциям, которые кстати именуются WinAPI :) К сожалению, я не помню имени автора, но название книги "Справочник по API функциям Windows 2000".
Удачи.
← →
Нууу (2003-04-12 03:50) [6]>Almaz © (11.04.03 23:21)
>> Vlad Oshin © (11.04.03 08:23)
>> Вам бы статью по этому поводу написать.
>Будет время - непременно :)
Ага! А потом будете тратить весь свой траффик на напоминание ссылки на эту статью! В нынешнее время - мало кто читает статьи (УВЫ).
А посему согласен с Вами. (Будет "лишнее" время - "может быть"). :(((
← →
Song (2003-04-12 09:36) [7]А хуком не получится? WM_CONTEXTMENU, WM_INITPOPUPMENU, WM_ENTERMENULOOP/WM_EXITMENULOOP ...
← →
Morfein (2003-04-12 20:50) [8]Хуком получится, но только не этим... надо ставить хук WH_CBT, отлавливать создание окон и классом "#327**" (вместо звёздочек - цифры, точно не помню, какие) и запрещать их создавать... менюшки исчезают начисто, без перехвата вызовов функций!
← →
NightAngel (2003-04-12 23:11) [9]> Almaz © (11.04.03 01:31)
Пример который Вы привели не будет работать в Win9x, т.к. в системах Win9x некоторые системные библиотеки (kernel32, user32 и др.) загружаются в адресное пространство >2Gb, которое проецируется НА ВСЕ контексты, присутствующие в системе. Это усложняет процесс перехвата их функций, так как содержимое памяти свыше 2Gb НЕ МОЖЕТ БЫТЬ ИЗМЕНЕНО стандартными документированными API функциями.
← →
NightAngel (2003-04-12 23:29) [10]И ещё...
После установки атрибута "writable" на необходимый регион памяти и осуществления записи в него, изменения произойдут ВО ВСЕХ присутствующих контекстах одновременно. Значит, код обработчика должен располагаться по одинаковым адресам ВО ВСЕХ контекстах. Это возможно только если код будет находиться выше 2Gb.
← →
Almaz (2003-04-13 00:20) [11]
> NightAngel (12.04.03 23:11)
> > Almaz © (11.04.03 01:31)
> Пример который Вы привели не будет работать в Win9x, т.к.
> в системах Win9x некоторые системные библиотеки (kernel32,
> user32 и др.) загружаются в адресное пространство >2Gb,
> которое проецируется НА ВСЕ контексты, присутствующие в
> системе. Это усложняет процесс перехвата их функций, так
> как содержимое памяти свыше 2Gb НЕ МОЖЕТ БЫТЬ ИЗМЕНЕНО стандартными
> документированными API функциями.
Согласен, данный пример написан под NT платформы. Для Win9x платформ придется вносить изменения в таблицу импорта модулей процесса, что также не очень сложно.
> NightAngel (12.04.03 23:29)
> И ещё...
> После установки атрибута "writable" на необходимый регион
> памяти и осуществления записи в него, изменения произойдут
> ВО ВСЕХ присутствующих контекстах одновременно. Значит,
> код обработчика должен располагаться по одинаковым адресам
> ВО ВСЕХ контекстах. Это возможно только если код будет находиться
> выше 2Gb.
Речь не идет об ОБРАБОТЧИКЕ речь идет о модификации кода вызываемой функции.
← →
Almaz (2003-04-13 00:32) [12]
> Morfein © (12.04.03 20:50)
> Хуком получится, но только не этим... надо ставить хук WH_CBT,
> отлавливать создание окон и классом "#327**" (вместо звёздочек
> - цифры, точно не помню, какие) и запрещать их создавать...
> менюшки исчезают начисто, без перехвата вызовов функций!
#327 68 :) Согласен - это неплохой вариант.
Удачи.
← →
NightAngel (2003-04-13 01:15) [13]> Almaz © (13.04.03 00:20)
Речь не идет об ОБРАБОТЧИКЕ речь идет о модификации кода
вызываемой функции.
Извиняюсь, ошибся.
Согласен, данный пример написан под NT платформы. Для Win9x платформ придется вносить изменения в таблицу импорта модулей процесса, что также не очень сложно.
Этого делать не обязательно. Можно использовать Ваш пример и под Win9x. Документированный Windows API не предоставляет средств для внесения изменений в память >2Gb, VirtualProtect + WriteProcessMemory завершается неудачно, однако эту проблему можно решить и без написания собственного VxD. Достаточно вызвать VxDCall0 _PageModifyPermissions. VxDCall0 - это ВСЕГДА ПЕРВАЯ экспортируемая Kernel32.dll функция.
← →
_ALEXey_ (2003-04-16 18:21) [14]
> Morfein © (12.04.03 20:50)
> Хуком получится, но только не этим... надо ставить хук WH_CBT,
> отлавливать создание окон и классом "#327**" (вместо звёздочек
> - цифры, точно не помню, какие) и запрещать их создавать...
> менюшки исчезают начисто, без перехвата вызовов функций!
Попробовал так, вот что получилось:
function PopupMenuHook(Code, wParam, lParam: Integer): LResult; stdcall;
var
CBTCrtWnd: ^CBT_CREATEWND;
CrtStrct: ^CREATESTRUCT;
WndClass: PChar;
begin
If Code >= 0
then begin
If Code = HCBT_CREATEWND
then begin
CBTCrtWnd:= Pointer(lParam);
CrtStrct:= Pointer(CBTCrtWnd^.lpcs);
WndClass:= CrtStrct^.lpszClass;
If WndClass = "#32768"
then Result:= 1
else Result:= CallNextHookEx(PopupMenuH, Code, wParam, lParam);
end
else Result:= CallNextHookEx(PopupMenuH, Code, wParam, lParam);
end
else begin
Result:= CallNextHookEx(PopupMenuH, Code, wParam, lParam);
Exit;
end;
end;
Однако, при попытке создания любого окна выдается сообщение:
"Инструкция хххххххх обратилась по адресу хххххххххх ... память не может быть "read""
И при этом исчезает таскбар и виснет Explorer (винда - 2000-я).
Подскажите пожалуйста, где ошибка?
← →
Almaz (2003-04-17 01:24) [15]
> ALEXey_ © (16.04.03 18:21)
Попробуйте так:
function Hook(Code: Integer; ParamW: WPARAM; ParamL: LPARAM): LRESULT; stdcall;
var
Buffer: array [0..7] of Char;
begin
if Code = HCBT_CREATEWND then
begin
GetClassName(ParamW, Buffer, sizeof(Buffer));
if Buffer = "#32768" then
begin
Result := 1;
Exit;
end;
end;
Result := CallNextHookEx(OldHook, Code, ParamW, ParamL);
end;
Удачи.
← →
_ALEXey_ (2003-04-17 17:24) [16]
> Almaz ©
Спасибо! Заработало!
Благодарю всех за помощь!
Правда глюки остались: в Delphi 7, Office XP - меню все равно появляется. Вероятно, у них это устроено по-другому. Я пытался убрать главное меню с помощьюSetMenu
- такая же история: почти во всех окнах убирается, а в Делфи и Офисе - нет! Дескриптор меню = 0, а оно доступно и работает!
← →
Song (2003-04-17 19:38) [17]Вероятно у него другой класс. Посмотри WinSight"ом.
← →
Songoku (2003-04-17 20:34) [18]Коаго интересует тема:
"Система перехвата функций API платформы Win32.
"
Есть очень интересная статья об этом.
А вот собственно и адрес: http://wasm.ru/print.php?article=1021007
p.s. Я даже себе её разпичатал и повечерам кагда не чего делать читаю её!!!
← →
Diamond Cat (2003-04-18 01:30) [19]А можно немного оторвать вас от возвышенных материй
попробуйте прописать нижеследующее NoTrayContextMenu = 1 NoViewContextMenu = 1 (Запретить контекстное меню на трее и Запретить контекстное меню) в реестр, ветка HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion
\Policies\Explorer , и меню перестанут появляться. Это конечно не столь круто как перехват системных функций :о) , но знаетели работает .
удачи
← →
Diamond Cat (2003-04-18 01:39) [20]да, извините, забыл добавить что параметры эти строковые
← →
_ALEXey_ (2003-04-18 07:30) [21]
> А можно немного оторвать вас от возвышенных материй
> попробуйте прописать нижеследующее NoTrayContextMenu = 1
> NoViewContextMenu = 1 (Запретить контекстное меню на трее
> и Запретить контекстное меню) в реестр, ветка HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion
> \Policies\Explorer , и меню перестанут появляться. Это конечно
> не столь круто как перехват системных функций :о) , но знаетели
> работает .
Это работает, безусловно! Но только в проводнике (Explorer), а задача состояла в том, чтобы убрать их изо всех приложений.
← →
Songoku (2003-04-18 10:17) [22]> Almaz ©
Как загрузить 1ую функцию по индексу из Kernel32.dll???(Win9x)
Вопрос такой как отключить только немю каторое выскакивает по нажатию кпопки Start(Пуск) либо WIN_R(WIN_L) ?????
Страницы: 1 вся ветка
Форум: "Система";
Текущий архив: 2003.06.26;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.035 c