IRP беру от i8042prt.sys, потому что пока тестирую PS/2 клаву. А что в моей процедуре завершения не так?
Llirik Извиняюсь. У меня сейчас нет времени отвечать. Но я не помню, чтобы i8042prt кому-то под собой слал IRP для получения KEYBOARD_INPUT_DATA, а глянуть в исходники нету времени. Он заполняет в собственном обработчике прерывания свою очередь, указатели на которую имеются в его device extension. А потом из этой очереди заполняет KEYBOARD_INPUT_DATA, когда дело дойдёт до его процедуры I8042KeyboardIsrDpc. Насколько я помню, под ним никого нет, кто предоставляет KEYBOARD_INPUT_DATA. Поэтому мне всё ещё непонятно, что Вы там перехватываете. А читать... статьи вполне достаточно, но Вы явно не хотите её читать (иначе знали бы, что перед установкой процедуры завершения нужно вызывать IoCopyCurrentIrpStackLocationToNext). Плюс WDK, разумеется. Исходник драйвера есть в версии WDK 6001.18002.
Llirik Хех... Это шутка такая? Если нет, тогда и разговаривать не о чем. Оба языка необходимы, иначе о драйверах можете забыть. Из DispatchRead только перехватывая сообщения, отправленные к kbdclass. А i8042prt, например, позволяет callback зарегистрировать. Но если Вы читать исходники и WDK не собираетесь, то это не важно. Целиком фильтр я писать за Вас не собираюсь, а одним пинком в нужную сторону здесь не обойтись.
Пожалуйста, переведите мне на ассемблер эти две строчки: Код (Text): connectData = ((PCONNECT_DATA) (irpStack->Parameters.DeviceIoControl.Type3InputBuffer)); DevExt->UpperConnectData = *connectData; во второй я просто не знаю что означает *
l_inc, я тут не много запутался. Пожалуйста, помогите разобраться. не хочет компилироваться такой код: Код (Text): FiDO_DEVICE_EXTENSION STRUCT Self PDEVICE_OBJECT ? PDO PDEVICE_OBJECT ? TopOfStack PDEVICE_OBJECT ? SurpriseRemoved BOOLEAN ? Started BOOLEAN ? Removed BOOLEAN ? struct CONNECT_DATA ClassDeviceObject PDEVICE_OBJECT ? ClassService DWORD ? ENDS PCONNECT_DATA typedef ptr CONNECT_DATA FiDO_DEVICE_EXTENSION ENDS PFiDO_DEVICE_EXTENSION typedef ptr FiDO_DEVICE_EXTENSION ...................................... mov ebx, pDeviceObject assume ebx:ptr DEVICE_OBJECT mov ecx, [ebx].DeviceExtension assume ebx:nothing assume ecx:ptr FiDO_DEVICE_EXTENSION .if [ecx].CONNECT_DATA.ClassService != NULL mov status, STATUS_SHARING_VIOLATION .elseif [edi].Parameters.DeviceIoControl.InputBufferLength < sizeof PCONNECT_DATA mov status, STATUS_INVALID_PARAMETER; .else mov eax, [edi].Parameters.DeviceIoControl.Type3InputBuffer mov [ecx].CONNECT_DATA.ClassDeviceObject, eax mov ebx, (PCONNECT_DATA ptr [eax]).ClassService mov [ecx].CONNECT_DATA.ClassService, ebx mov ebx, [ecx].Self mov (PCONNECT_DATA ptr [eax]).ClassDeviceObject, ebx mov (PCONNECT_DATA ptr [eax]).ClassService, offset KbFilter_ServiceCallback и воощбе он по смыслу хотя бы верный?
Llirik Вообще я не этот callback имел в виду (а тот, который ставится вызовом IOCTL_INTERNAL_I8042_HOOK_KEYBOARD и вызывается из ISR драйвера i8042prt.sys), но если Ваш драйвер грузится до загрузки kbdclass.sys, то перехватывать IOCTL_INTERNAL_KEYBOARD_CONNECT тоже можно. Этот код: Код (Text): mov eax, [edi].Parameters.DeviceIoControl.Type3InputBuffer mov [ecx].CONNECT_DATA.ClassDeviceObject, eax сохранит указатель на стековый буфер драйвера kbdclass.sys, а не на его ClassDeviceObject, как ожидается. Должно быть так: Код (Text): mov eax, [edi].Parameters.DeviceIoControl.Type3InputBuffer mov ebx, (PCONNECT_DATA ptr [eax]).ClassDeviceObject mov [ecx].CONNECT_DATA.ClassDeviceObject, ebx В остальном похоже на правду. С компиляцией вряд ли помогу, т.к. masm не люблю и не пользуюсь.
2Llirik вам нужно к мозгоправу, извините за грубость. Не будет вам счастья, если дрова будете писать только асмом, попомните мои слова. Если не можете освоить С, значит просто не хотите, по каким-то личным причинам. Вы упрямо прете в тоннель на кажущийся свет. Знайте, это не божественный свет, это приближается литерный.
Да. Я просто не хочу тратить своё драгоценное время на изучение Вашего С) Чем больше мне что-то навязывают, тем больше у меня к этому неприязнь. Да и поспешил я с предыдущим постом. сам с этим разобрался) Господа, кто не желает помочь мне , того прошу не беспокоиться и не тратить свое время зря, займитесь лучше чем нибудь полезным, а не написанием оскорблений!
Я написал Callback, но получить скан-код нажатой клавиши я так и не могу. Код (Text): KbFilter_ServiceCallback proc pDeviceObject:PDEVICE_OBJECT, InputDataStart:PKEYBOARD_INPUT_DATA, InputDataEnd:PKEYBOARD_INPUT_DATA, InputDataConsumed:PULONG push ebx mov ebx, InputDataConsumed mov ecx, InputDataStart assume ecx:ptr KEYBOARD_INPUT_DATA .while sdword ptr ebx >= sizeof KEYBOARD_INPUT_DATA movzx eax, [ecx].MakeCode mov ScanCode, eax movzx eax, [ecx].Flags mov KeyFlags, eax add ecx, sizeof KEYBOARD_INPUT_DATA sub ebx, sizeof KEYBOARD_INPUT_DATA .endw pop ebx push InputDataConsumed mov eax, pDeviceObject push InputDataEnd assume eax:ptr DEVICE_OBJECT mov ecx, [eax].DeviceExtension assume eax:nothing assume ecx:ptr FiDO_DEVICE_EXTENSION push InputDataStart push [ecx].ClassDeviceObject call [ecx].ClassService ret KbFilter_ServiceCallback endp Что я делаю не так?
l_inc, спасибо за пинок в нужную сторону) Я написал Callback и теперь получаю данные и от PS/2 и от USB-клавы. А Вы говорили: ) Только мне хотелось разобраться вовсем до конца. Скажите, пожалуйста, зачем две стуктуры KEYBOARD_INPUT_DATA (InputDataStart и InputDataEnd), а не одна? И что за InputDataConsumed?
Llirik Это не две структуры. Это два указателя: на начало массива структур и на конец. А InputDataConsumed указывает на то, сколько структур функция KeyboardClassServiceCallback обработала из буфера, полученного от нижележащего драйвера. В большинстве случаев InputDataConsumed будет равно количествую всех структур в массиве между InputDataStart и InputDataEnd. А в случае USB-клавиатуры в массиве вообще всегда ровно одна структура. Три месяца на один простой фильтр? Причём, когда уже всё разжёвано до такой степени, что необходимо от силы два дня? В общем, сейчас я от своих слов не отказываюсь.
Llirik Во-первых, я сказал, что это количество структур, которые обработает KeyboardClassServiceCallback, а не которые она получит. Во-вторых, само значение InputDataConsumed, разумеется, является указателем на количество структур, а не самим количеством. Это называется передачей параметра по указателю. И в-третьих, значение, на которое указывает указатель InputDataConsumed, (по мне, так проще было вместо сложноподчинённого предложения просто сказать InputDataConsumed, но Вы ведь опять придираться станете) заполняется самой процедурой KeyboardClassServiceCallback, а не вызывающим. Когда KeyboardClassServiceCallback отработает, вызвавший его драйвер на основе полученного от этого callback'а значения, на которое указывает указатель InputDataConsumed, будет решать, что делать с оставшимися необработанными структурами. Хотя в 99,9% случаев необработанных структур не будет.
Вопрос такой. Почему при подмене клавиши "8" на "7" на цифровой панели клавиатуры происходит и подмена клавиш "стрелка вверх" на "Home"? Ведь скан-коды у них разные. Код (Text): KKbFilter_ServiceCallback proc pDeviceObject:PDEVICE_OBJECT, InputDataStart:PKEYBOARD_INPUT_DATA, InputDataEnd:PKEYBOARD_INPUT_DATA, InputDataConsumed:PULONG mov eax, InputDataStart assume eax:ptr KEYBOARD_INPUT_DATA cmp [eax].MakeCode, 0048h jnz lll mov [eax].MakeCode, 0047h lll: assume eax:nothing push InputDataConsumed mov eax, pDeviceObject push InputDataEnd assume eax:ptr DEVICE_OBJECT mov ecx, [eax].DeviceExtension assume eax:nothing assume ecx:ptr FiDO_DEVICE_EXTENSION push InputDataStart push [ecx].ClassDeviceObject call [ecx].ClassService ret KKbFilter_ServiceCallback endp