Будьте добры, подскажите, ПОЖАЛУЙСТА, где находятся скан-коды клавиш перед вызовом функции KeyboardClassRead?
Llirik Обычно нигде они не находятся... я бы сказал, что в голове пользователя, но обычно он не в курсе кодов клавиш. При вызове KeyboardClassRead возвращается STATUS_PENDING и IRP продолжает висеть до нажатия клавиши. После нажатия клавиши (пропуская генерацию и обработку прерывания и добавление обработчика в очередь DPC) либо kbdhid.sys либо i8042prt.sys уже на уровне DPC вызывает KeyboardClassServiceCallback, передавая ей указатель на структуру KEYBOARD_INPUT_DATA, которую KeyboardClassServiceCallback копирует в висящий IRP, после чего завершает его.
Llirik Фильтр — классический метод. Смысла приводить ссылку на известную статью нет, т.к. Вы её уже читали. По проблемам фильтра USB-клавиатуры подсказать не могу, т.к. не пробовал.
А я пробовал, не подключается к стеку USB-клавы. мало того. что делать если клавиатуры 2 или больше? к стеку каждой подключаться? замучаешься. вот я и ищу более универсальное решение
А это относится ко всем фильтрам, прописанным в параметре UpperFilters ключа HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E96B-E325-11CE-BFC1-08002BE10318} ?
Llirik В процитированном посте нет ни одного слова о фильтрах. К фильтрам ничего из сказанного не относится. Речь шла только о функциях драйвера класса kbdclass.sys.
почему же тогда это не работает? Код (Text): FiDO_DispatchRead proc uses esi edi ebx pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP .if gggfSpy mov esi, pIrp assume esi:ptr _IRP .if [esi].IoStatus.Status == STATUS_SUCCESS mov edi, [esi].AssociatedIrp.SystemBuffer assume edi:ptr KEYBOARD_INPUT_DATA mov ebx, [esi].IoStatus.Information .while sdword ptr ebx >= sizeof KEYBOARD_INPUT_DATA ;.if [edi].MakeCode == 48h ;.IF [edi].Flags == 1 ;.if KeyFlags == FALSE ;and KeyFlags, TRUE ;.else mov [edi].MakeCode, 48h ;and KeyFlags, FALSE ;.endif ;.endif ;.endif add edi, sizeof KEYBOARD_INPUT_DATA sub ebx, sizeof KEYBOARD_INPUT_DATA .endw assume edi:nothing .endif .if [esi].PendingReturned IoMarkIrpPending esi .endif assume esi:nothing mov eax, STATUS_SUCCESS .endif invoke FiDO_DispatchPassThrough, pDeviceObject, pIrp ret FiDO_DispatchRead endp
Llirik Наверное, по тем же причинам, по которым работает всё остальное, о чём я не говорил в том посте.
Llirik Честно говоря, я тоже. Вы приводите мой пост в качестве аргумента за работоспособность куска кода из драйвера-фильтра, о которых в посте и речь не шла. Ну скажите, что в посте нету о том, что Солнце светит, а оно светит, и... о ужас... о землетрясении в Японии, а оно ведь было! В общем, проверять статус IRP ещё до того, как его кто-либо мог обработать, бессмысленно. И даже если управление зайдёт внутрь первого условия, то установленный MakeCode всё равно будет перезаписан в момент завершения IRP процедурой KeyboardClassServiceCallback. Короче говоря, всё, что делает Ваш FiDO_DispatchRead, — это передаёт IRP дальше по стеку (и то только в случае, если FiDO_DispatchPassThrough не был так же грязно испохаблен).
Llirik Вы статью, видимо, не очень-то внимательно читали. Там всё описано до мелочей. В приходящий IRP устанавливается процедура завершения, а потом уже IRP переправляется дальше в драйвер kbdclass.sys. И вот когда kbdclass.sys захочет завершить этот IRP... да ну что я буду статью перепечатывать. Читайте.
Llirik Ага. Вместо этого Вы рассчитываете на мой высокоточный хрустальный шар. И что же за IRP вы обрабатываете? Тот, который шлёт kbdhid.sys нижележащим драйверам из KbdHid_StartRead? Если да, сути это не меняет: нужно ставить свою процедуру завершения и ждать, пока hidclass.sys вызовет IopfCompleteRequest.
l_inc, так? Код (Text): ReadComplete proc uses esi edi ebx pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP, pContext:PVOID mov esi, pIrp assume esi:ptr _IRP .if [esi].IoStatus.Status == STATUS_SUCCESS mov edi, [esi].AssociatedIrp.SystemBuffer assume edi:ptr KEYBOARD_INPUT_DATA mov ebx, [esi].IoStatus.Information .while sdword ptr ebx >= sizeof KEYBOARD_INPUT_DATA movzx eax, [edi].MakeCode mov ScanCode, eax movzx eax, [edi].Flags mov KeyFlags, eax add edi, sizeof KEYBOARD_INPUT_DATA sub ebx, sizeof KEYBOARD_INPUT_DATA .endw assume edi:nothing ; inc fScanCode .endif .if [esi].PendingReturned IoMarkIrpPending esi .endif assume esi:nothing lock dec g_dwPendingRequests call SetValueKey2 mov eax, STATUS_SUCCESS ret ReadComplete endp ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: FiDO_DispatchRead proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP ; .if gggfSpy lock inc g_dwPendingRequests IoSetCompletionRoutine pIrp, ReadComplete, NULL, TRUE, TRUE, TRUE ;;; and gggfSpy, FALSE ;.endif push pIrp push pDeviceObject call FiDO_DispatchPassThrough ret FiDO_DispatchRead endp Тоже неполучается(
Мой фильтр прописан в параметре UpperFilters ключа HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E96B-E325-11CE-BFC1-08002BE10318}
Llirik Да-да. Я понял, что ответ мне, но вопрос скорее не ко мне. Я не в курсе того, что происходит в реестре (пусть кто-нибудь другой отвечает ). В глаза бросается, что процедура завершения неверно устанавливается (следующий драйвер получит в стеке IRP ерунду), но вполне вероятно, что это далеко не единственная проблема.