Существует клавиатуру крюк установлен так:Краша после возвращения из процедуры крюка клавиатуры Windows,
s_hKeyboardHook = ::SetWindowsHookEx(WH_KEYBOARD, KeyboardHookProc, nullptr, ::GetCurrentThreadId());
(Это плагин, который хочет, чтобы перехватывать событие клавиатуры, которые получают отправленный его хозяину (64-разрядную версию), хотя хост не обеспечивает клавиатурные события для своих плагинов обычным способом. У меня нет исходного кода хоста, хотя у меня есть исходный код подключаемого модуля.)
После процедура крючка клавиатуры успешно запускается и возвращается, программа вылетает из строя. Сбой происходит внутри Windows 'ZwCallbackReturn()
, выполняя инструкцию syscall
. Исключением является 0XC0000005
(нарушение прав доступа). Сбой происходит только при нажатии определенной клавиши, которая вызывает определенную логику.
Я застрял диагностировать эту аварию и может реально использовать некоторую помощь. Я уверен, что проблема заключается в этом большом фрагменте кода, который находится в hook proc. У меня возникают проблемы с пониманием того, где произошел сбой, и где в основном разместить точку останова, чтобы выгрузить ее.
Дополнительная информация:
1) Подключаемая процедура действительно очень тяжелая, с большим количеством блокирующего ввода/вывода и использования памяти (она завершается в течение нескольких секунд на быстрой машине) , Возможно, это часть проблемы.
2) Если скомпилирован как 32-бит, стек сразу после аварии выглядит более интересно, но я сомневаюсь, что это можно доверять:
2a71f510() Unknown
[email protected]() Unknown
[email protected]() Unknown
[email protected]() Unknown
[email protected]() Unknown
2a10f24a() Unknown
[email protected]() Unknown
[email protected]() Unknown
[email protected]() Unknown
[email protected]() Unknown
[email protected]() Unknown
AfxInternalPumpMessage() Line 153 C++
AfxWinMain(0x00000000, 0x00000020, 0x00000001, 1638280) Line 47 C++
@[email protected]() Unknown
где верхние 5 строк повторяются много раз.
Вот что я пробовал до сих пор. Я понимаю, что инструкция syscall
не генерирует исключение: регистры выглядят разумно, и я думаю, что стек остался бы таким же, если бы он разбился. Поэтому я думаю, что после того, как эта инструкция инициирует переход в режим ядра, откуда возникла «обратная связь с пользователем» (вызов процедуры hook), ядро продолжает работать нормально. В конце концов он должен вернуть управление обратно в userland - GetMessage()
Я полагаю). По дороге, я думаю, стек поврежден, и программа выйдет из строя. Но, к сожалению, я не могу проинструктировать моего отладчика Visual C++ для разрыва при первой инструкции пользовательского режима, прежде чем поврежден стек. Я попытался установить условные точки останова в TranslateMessage()
и DispatchMessage()
, которые, скорее всего, будут работать сразу после GetMessage()
, но они не срабатывают между последней хорошей инструкцией пользователя и сбоем.
'Крушение происходит только, если нажата конкретная клавиша, которая запускает какую-то определенную логику" - это немного неопределенно, чтобы мы могли различить, что может быть проблемой. –
Если вы отделите всю логику от своего крючка и сразу вернетесь, она все равно сработает? Если нет, вы знаете, где искать. –
Является ли плагин запущенным в том же процессе, что и хост? Если да, я предполагаю, что плагин - это DLL, которая загружается явно. Возможно ли, что DLL плагина разгружается, возможно, в ответ на нажатие клавиши? –