Закнчиваю университет, вместо экзамена преподаватель предложил написать драйвер меняющий маппинг клавиатуры, сам фильтр вполне работоспособен, но при попытке вставить ассемблерный код (беру его из листинга генерируемого компилятором студии, видимо проблема в этом, так как sys беру тот, что выдается ddk build) система валится в bsod. C++ код: Код (Text): KeyData = Irp->AssociatedIrp.SystemBuffer; numKeys = Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA); получаемая вставка: Код (Text): __asm{ ; Line 411 mov edx, DWORD PTR Irp[ebp] mov eax, DWORD PTR [edx+12] mov DWORD PTR KeyData[ebp], eax ; Line 412 mov ecx, DWORD PTR Irp[ebp] mov eax, DWORD PTR [ecx+28] xor edx, edx mov ecx, 12 ; 0000000cH div ecx mov DWORD PTR numKeys[ebp], eax } Полный код функции: Код (Text): NTSTATUS Ctrl2capReadComplete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { PIO_STACK_LOCATION IrpSp; PKEYBOARD_INPUT_DATA KeyData; int numKeys, i; // // Request completed - look at the result. // IrpSp = IoGetCurrentIrpStackLocation( Irp ); if( NT_SUCCESS( Irp->IoStatus.Status ) ) { // // Do caps-lock down and caps-lock up. Note that // just frobbing the MakeCode handles both the up-key // and down-key cases since the up/down information is specified // seperately in the Flags field of the keyboard input data // (0 means key-down, 1 means key-up). // /*KeyData = Irp->AssociatedIrp.SystemBuffer; numKeys = Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);*/ __asm{ ; Line 411 mov edx, DWORD PTR Irp[ebp] mov eax, DWORD PTR [edx+12] mov DWORD PTR KeyData[ebp], eax ; Line 412 mov ecx, DWORD PTR Irp[ebp] mov eax, DWORD PTR [ecx+28] xor edx, edx mov ecx, 12 ; 0000000cH div ecx mov DWORD PTR numKeys[ebp], eax } for( i = 0; i < numKeys; i++ ) { switch (KeyData[i].MakeCode){ case CAPS_LOCK: KeyData[i].MakeCode = LCONTROL; break; case LALT: KeyData[i].MakeCode = CAPS_LOCK; break; case LCONTROL: KeyData[i].MakeCode = LALT; break; case KEY_Q: KeyData[i].MakeCode = KEY_A; break; case KEY_W: KeyData[i].MakeCode = KEY_B; break; case KEY_E: KeyData[i].MakeCode = KEY_C; break; case KEY_R: KeyData[i].MakeCode = KEY_D; break; case KEY_T: KeyData[i].MakeCode = KEY_E; break; case KEY_Y: KeyData[i].MakeCode = KEY_F; break; case KEY_U: KeyData[i].MakeCode = KEY_G; break; case KEY_I: KeyData[i].MakeCode = KEY_H; break; case KEY_O: KeyData[i].MakeCode = KEY_I; break; case KEY_P: KeyData[i].MakeCode = KEY_J; break; case KEY_A: KeyData[i].MakeCode = KEY_K; break; case KEY_S: KeyData[i].MakeCode = KEY_L; break; case KEY_D: KeyData[i].MakeCode = KEY_M; break; case KEY_F: KeyData[i].MakeCode = KEY_N; break; case KEY_G: KeyData[i].MakeCode = KEY_O; break; case KEY_H: KeyData[i].MakeCode = KEY_P; break; case KEY_J: KeyData[i].MakeCode = KEY_Q; break; case KEY_K: KeyData[i].MakeCode = KEY_R; break; case KEY_L: KeyData[i].MakeCode = KEY_S; break; case KEY_Z: KeyData[i].MakeCode = KEY_T; break; case KEY_X: KeyData[i].MakeCode = KEY_U; break; case KEY_C: KeyData[i].MakeCode = KEY_V; break; case KEY_V: KeyData[i].MakeCode = KEY_W; break; case KEY_B: KeyData[i].MakeCode = KEY_X; break; case KEY_N: KeyData[i].MakeCode = KEY_Y; break; case KEY_M: KeyData[i].MakeCode = KEY_Z; break; } } } // // Mark the Irp pending if required // if( Irp->PendingReturned ) { IoMarkIrpPending( Irp ); } return Irp->IoStatus.Status; } Основано на ctrl2cap Марка Руссиновича Помогите пожалуйста, гуру дзена, да будет радостным этот воскресный день =)
эмм, причина в том, что я не знаком с masm, я вообще в основном дотнетом занимаюсь, но партия сказала "нужны вставки на ассемблере", причем не что то конкретное, а просто чтобы были. Вот потому я здесь
Код (Text): __asm{ ; Line 411 [b]mov edx, DWORD PTR Irp[ebp][/b] mov eax, DWORD PTR [edx+12] mov DWORD PTR KeyData[ebp], eax ; Line 412 [b]mov ecx, DWORD PTR Irp[ebp][/b] mov eax, DWORD PTR [ecx+28] xor edx, edx mov ecx, 12 ; 0000000cH div ecx mov DWORD PTR numKeys[ebp], eax } в выделенных строчках регистр ebp указывает не на нужные локальные переменные
точнее IN PIRP Irp это входящий параметр и должно быть вот так Код (Text): ; Line 411 mov edx, DWORD PTR [ebp+12] а PKEYBOARD_INPUT_DATA KeyData локальная переменная и обращение к ней должно выглядеть так Код (Text): ; Line 412 mov edx, DWORD PTR [ebp-8]
defaultplayer, спасибо, а можно немного подробнее? Как получить ассемблерный код при использовании ddk build? (не могу найти то место, где прописываются ключи для cl.exe)
Код (Text): __asm{ ; Line 411 mov edx, DWORD PTR [ebp+12] mov eax, DWORD PTR [edx+12] mov DWORD PTR [ebp-8], eax ; Line 412 mov ecx, DWORD PTR [ebp+12] mov eax, DWORD PTR [ecx+28] xor edx, edx mov ecx, 12 ; 0000000cH div ecx mov DWORD PTR [ebp-16], eax } замени свой код на этот и напиши работает или нет
у меня в папке с проектом создан файл makefile.inc, в нем есть опция CC= , в ней задается имя файла Си компилятора который надо использовать, только предварительно должны быть установлены пути к нему. Потому за ним идет опция CFLAGS= в ней и задаем ключи. Еще есть опция CINC=, в ней задаются пути к файлам включений
defaultplayer не работает, в bsod не валится, просто не перехватывает ввод. makefile.inc у меня нет, вы его сами создавали?
странно, ща попробую у себя запустить под отладкой да, но в принципе он вам ненужен. В общем, когда запускается build.exe он тянет из директории bin (в DDK) файл makefile.def, а тот в зависимости от платформы (а она у вас наверно х86) включает файл i386mk.inc, в котором есть флаг CFLAGS= , и строка в нем выглядит вот так CFLAGS=$(386_FLAGS) $(NT386FLAGS) $(STDFLAGS) $(DBGFLAGS) $(PERFFLAGS) $(USER_C_FLAGS), это и есть группы флагов Си компилера. Так вот все, кроме $(USER_C_FLAGS) задефайнены по умолчанию, а переменная $(USER_C_FLAGS), как видно из названия пользовательская, поэтому нужно батничек создать и определить свои параметры в этой переменной. В общем поизучайте этот файлик ...
куда флаги воткнуть нашел, i386mk.inc лежит в папке bin ddk =) Ща буду курить нубскими методами, как хорошо что все на виртуалбоксе крутится, и винда на нем порезаная, грузится все быстрее чем открывается фотошоп
тут есть возможнось редактировать посты? а то нахожу что-то пока пишу вы постите подсказку, и я тут радостный, что сам нашел, аж стыдно
нет проверил, у меня все работает замечательно DbgPrint выводиты сканкоды. вот часть лога WinDbg Код (Text): f8ea114f cc int 3 kd> g ScanCode: 1c Down Break instruction exception - code 80000003 (first chance) drv!Ctrl2capReadComplete+0x1f: f8ea114f cc int 3 kd> g ScanCode: 1c Up ScanCode: 1d Down ScanCode: 38 Down ScanCode: 1d Up ScanCode: 38 Up Break instruction exception - code 80000003 (first chance) drv!Ctrl2capReadComplete+0x1f:
defaultplayer спасибо, не трудитесь, смог договориться с преподавателем, необходимость во вставках отпала=) Огромное вам спасибо за помощь!
пожалуйста, но у меня все работает и с вставками и без вставок. Единственное только в коде для NT4 есть функция Ctrl2capInit, так вот в ней вызов ZwDisplayString pool крошит, пришлось закоментарить.
не понял причем тут сегментация, но причина падения в следующем: ZwDisplayString->NtDisplayString вызывает HalDisplayString, которая ресетит дисплей функцией HalpBiosDisplayReset и в которой вызывается HalpDisableAllInterrupts которая повышает IRQL до HIGH_LEVEL. Так вот в исходниках HalpBiosDisplayReset есть такие коментари Код (Text): // KIRQL OldIrql; ..... // // This function is only used during a system crash. We don't re- // enable interrupts. // // KeLowerIrql(OldIrql); соответственно IRQL до OldIrql не понижается и при возврате в NtDisplayString, при освобождении non-paged string buffer, идет проверка на IRQL, и если не DISPATCH, то bsod с IRQL_NOT_GREATER_OR_EQUAL.