Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Система";
Текущий архив: 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.026 c
1-84270
Project111
2003-06-14 11:21
2003.06.26
Version info


7-84786
_ALEXey_
2003-04-09 19:03
2003.06.26
Запрет всех контекстных меню в системе (ловушка)


1-84345
Кен
2003-06-09 05:37
2003.06.26
Что изменить в Дельфи, чтобы она сохраняла формы в dfm-файлы


3-83966
Yakudza
2003-05-29 15:40
2003.06.26
Перезагрузка ячейки в DBGrid


14-84564
Sheng
2003-06-07 21:43
2003.06.26
Поисковик для Винампа





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