Посмотрел пример, находящийся в src\input\kbfiltr\sys
Я правильно понимаю, мне необходимо в драйвере создать объект PDO клавиатуры, зарегистрировать GUID клавиатуры? и уже с ней общаться.
Только не пойму, какая функция для этого используется?
в контексте драйвера объявляются структуры, как я понял, которые мне и нужны
// Write function from within KbFilter_IsrHook
//
IN PI8042_ISR_WRITE_PORT IsrWritePort;
//
// Queue the current packet (ie the one passed into KbFilter_IsrHook)
//
IN PI8042_QUEUE_PACKET QueueKeyboardPacket;
//
// Context for IsrWritePort, QueueKeyboardPacket
//
IN PVOID CallContext;
Далее мне нужно создать еще одну очередь управления запросами на запись в клавиатуру
// Create a new queue to handle IOCTLs that will be forwarded to us from
// the rawPDO.
//
WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig,
WdfIoQueueDispatchParallel);
//
// Framework by default creates non-power managed queues for
// filter drivers.
//
ioQueueConfig.EvtIoDeviceControl = KbFilter_EvtIoDeviceControlFromRawPdo;
и наконец в обработчике этой callback-функции написать что-то наподобие этого?
// Attach this driver to the initialization and byte processing of the
// i8042 (ie PS/2) keyboard. This is only necessary if you want to do PS/2
// specific functions, otherwise hooking the CONNECT_DATA is sufficient
//
case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD:
DebugPrint(("hook keyboard received!\n"));
//
// Get the input buffer from the request
// (Parameters.DeviceIoControl.Type3InputBuffer)
//
status = WdfRequestRetrieveInputBuffer(Request,
sizeof(INTERNAL_I8042_HOOK_KEYBOARD),
&hookKeyboard,
&length);
if(!NT_SUCCESS(status)){
DebugPrint(("WdfRequestRetrieveInputBuffer failed %x\n", status));
break;
}
ASSERT(length == InputBufferLength);
//
// Enter our own initialization routine and record any Init routine
// that may be above us. Repeat for the isr hook
//
devExt->UpperContext = hookKeyboard->Context;
//
// replace old Context with our own
//
hookKeyboard->Context = (PVOID) devExt;
if (hookKeyboard->InitializationRoutine) {
devExt->UpperInitializationRoutine =
hookKeyboard->InitializationRoutine;
}
hookKeyboard->InitializationRoutine =
(PI8042_KEYBOARD_INITIALIZATION_ROUTINE)
KbFilter_InitializationRoutine;
if (hookKeyboard->IsrRoutine) {
devExt->UpperIsrHook = hookKeyboard->IsrRoutine;
}
hookKeyboard->IsrRoutine = (PI8042_KEYBOARD_ISR) KbFilter_IsrHook;
//
// Store all of the other important stuff
//
devExt->IsrWritePort = hookKeyboard->IsrWritePort;
devExt->QueueKeyboardPacket = hookKeyboard->QueueKeyboardPacket;
devExt->CallContext = hookKeyboard->CallContext;
status = STATUS_SUCCESS;
break;
потому что IOCTL_INTERNAL_I8042_HOOK_KEYBOARD перехватывает прерывания, идущие клавиатуре
Но как-то не понятно, а где собственно изменение данных?
Callback-функции, которые присваиваются в этой части кода очень интересные - они перенаправляют запрос вниз по стеку драйверов, или нет? Например функция, которая вызывается в начале прерывания клавиатуры
BOOLEAN
KbFilter_IsrHook(
PVOID IsrContext,
PKEYBOARD_INPUT_DATA CurrentInput,
POUTPUT_PACKET CurrentOutput,
UCHAR StatusByte,
PUCHAR DataByte,
PBOOLEAN ContinueProcessing,
PKEYBOARD_SCAN_STATE ScanState
)
/*++
Routine Description:
This routine gets called at the beginning of processing of the kb interrupt.
i8042prt specific code, if you are writing a packet only filter driver, you
can remove this function
Arguments:
DeviceObject - Our context passed during IOCTL_INTERNAL_I8042_HOOK_KEYBOARD
CurrentInput - Current input packet being formulated by processing all the
interrupts
CurrentOutput - Current list of bytes being written to the keyboard or the
i8042 port.
StatusByte - Byte read from I/O port 60 when the interrupt occurred
DataByte - Byte read from I/O port 64 when the interrupt occurred.
This value can be modified and i8042prt will use this value
if ContinueProcessing is TRUE
ContinueProcessing - If TRUE, i8042prt will proceed with normal processing of
the interrupt. If FALSE, i8042prt will return from the
interrupt after this function returns. Also, if FALSE,
it is this functions responsibilityt to report the input
packet via the function provided in the hook IOCTL or via
queueing a DPC within this driver and calling the
service callback function acquired from the connect IOCTL
Return Value:
Status is returned.
--*/
{
PDEVICE_EXTENSION devExt;
BOOLEAN retVal = TRUE;
devExt = (PDEVICE_EXTENSION)IsrContext;
if (devExt->UpperIsrHook) {
retVal = (*devExt->UpperIsrHook) (
devExt->UpperContext,
CurrentInput,
CurrentOutput,
StatusByte,
DataByte,
ContinueProcessing,
ScanState
);
if (!retVal || !(*ContinueProcessing)) {
return retVal;
}
}
*ContinueProcessing = TRUE;
return retVal;
}
Помогите, пожалуйста, разобраться, как всё-таки сэмулировать нажатие кнопки на клавиатуре