Драйвер нижнего фильтра КМДФ

Я пишу драйвер фильтра и хочу подключить фильтр к нескольким физическим клавиатурам в системе. Если я прикреплю фильтр к первой клавиатуре «\Device\KeyboardClass0», он будет работать нормально, но не для другой. Ошибка IoAttachDevice для "\Device\KeyboardClass1". То же самое с другим классом. Я подключил 3 физические клавиатуры.

status = IoAttachDevice(gkbdDevice, &TargetDevice, &((PDEVICE_EXTENSION)gkbdDevice->DeviceExtension)->kbdDevice);

Кто-нибудь может помочь?


person makurisan    schedule 11.01.2018    source источник
comment
Можно ли привязать фильтр клавиатуры сразу ко всем клавиатурам?   -  person makurisan    schedule 11.01.2018
comment
вы даже не говорите, какие status возвращаются вам IoAttachDevice. во многих случаях IoAttachDevice может выйти из строя из-за флага DO_EXCLUSIVE на устройстве, когда оно уже открыто. нужно использовать IoCreateFile с параметрами IO_ATTACH_DEVICE + IoAttachDeviceToDeviceStackSafe. и сомневаюсь, что вы используете действительно драйвер kmdf   -  person RbMm    schedule 11.01.2018
comment
Перед вызовом IoAttachDevice я вызываю status = IoGetDeviceObjectPointer(&devName, FILE_ALL_ACCESS, &pFileObject, &(pLBKdev)); Эта функция также не работает с возвратом 0.   -  person makurisan    schedule 11.01.2018
comment
IoGetDeviObjectPointer возвращается со статусом STATUS_SHARING_VIOLATION на второй или третьей клавиатуре. Почему это?   -  person makurisan    schedule 11.01.2018
comment
именно потому, что я написал - используйте IoCreateFile с IO_ATTACH_DEVICE опциями   -  person RbMm    schedule 11.01.2018
comment
и вы никогда не должны использовать жестко заданные \Device\KeyboardClassX имена для открытых устройств. нужно открыть нижнее устройство по имени интерфейса - IoRegisterPlugPlayNotification с EventCategoryDeviceInterfaceChange на GUID_CLASS_KEYBOARD . и получил имя устройства на GUID_DEVICE_INTERFACE_ARRIVAL   -  person RbMm    schedule 11.01.2018
comment
Благодарю. Мне непонятно. Я беру IoCreateFile так, но как использовать результат в IoAttachDevice HANDLE hFile; OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, Notification-›SymbolicLinkName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK iosb; status = IoCreateFile(&hFile, SYNCHRONIZE, &oa, &iosb, 0, 0, FILE_SHARE_VALID_FLAGS, FILE_OPEN, 0, 0, 0, CreateFileTypeNone, 0, IO_ATTACH_DEVICE);   -  person makurisan    schedule 11.01.2018
comment
вам нужно использовать IoAttachDeviceToDeviceStackSafe, возвращенный дескриптор файла, который вам нужно преобразовать в файловый объект (ObReferenceObjectByHandle), а затем в устройство - IoGetRelatedDevice . и используйте имя интерфейса вместо \Device\KeyboardClassX   -  person RbMm    schedule 11.01.2018
comment
Теперь я получаю: RtlInitUnicodeString(&devName, LHID\\VID_046A&PID_010D&MI_00\\7&48EAABC&0&0000); ОБРАБАТЫВАТЬ hFile; OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &devName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK iosb; status = IoCreateFile(&hFile, SYNCHRONIZE, &oa, &iosb, 0, 0, FILE_SHARE_VALID_FLAGS, FILE_OPEN, 0, 0, 0, CreateFileTypeNone, 0, IO_ATTACH_DEVICE); CreateAndAttachDevice, IoCreateFile не удалось вызвать: 0xc000003b   -  person makurisan    schedule 11.01.2018
comment
откуда у тебя "HID\\VID_046A&PID_010D&MI_00\\7&48EAABC&0&0000" ? ты жестко это запрограммировал? конечно должна быть ошибка STATUS_OBJECT_PATH_SYNTAX_BAD - правильно - вам нужна ссылка на интерфейс от обратного вызова IoRegisterPlugPlayNotification   -  person RbMm    schedule 11.01.2018
comment
Да, я вижу, но в данный момент я не хочу писать IoRegisterPlugPlayNot... Если мы решим написать драйвер, мы реализуем его с помощью kdmf 2. Я видел в примерах, что это лучший способ. А пока я хочу добавить его жестко запрограммированным. Вы сказали имя интерфейса. Как называется клавиатура?   -  person makurisan    schedule 11.01.2018
comment
что-то вроде \\??\\HID\\VID_046A&PID_010D&MI_00\\7&48EAABC&0&0000 должно быть - вы забыли корневую папку \??\   -  person RbMm    schedule 11.01.2018


Ответы (2)


С помощью следующего кода я теперь могу открыть вторую клавиатуру, но...

    /*
* Form the Device Name and symbolic name
*/
RtlInitUnicodeString(&devNameFlt, L"\\Device\\KeyboardClass0");
RtlInitUnicodeString(&devName, L"\\Device\\MultikeyboardCnt");

status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION),
    &devName,
    FILE_DEVICE_KEYBOARD,
    SYNCHRONIZE,
    FALSE,
    &pDevObj);

if (!NT_SUCCESS(status))
{
    DbgPrint("%s, IoCreateDevice failed:0x%0x\n", __FUNCTION__, status);
    return status;
}

HANDLE hFile;
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, 0, OBJ_CASE_INSENSITIVE };
oa.ObjectName = &devNameFlt;

IO_STATUS_BLOCK iosb;
status = IoCreateFile(&hFile, SYNCHRONIZE, &oa, &iosb, 0, 0, FILE_SHARE_VALID_FLAGS, FILE_OPEN,
    0, 0, 0, CreateFileTypeNone, 0, IO_ATTACH_DEVICE);
if (!NT_SUCCESS(status))
{
    DbgPrint("%s, IoCreateFile failed to call:0x%0x\n", __FUNCTION__, status);
    return status;
}

/* Get File Object */
PFILE_OBJECT LocalFileObject;
status = ObReferenceObjectByHandle(hFile,
                                   0,
                                   *IoFileObjectType,
                                   KernelMode,
                                   (PVOID*)&LocalFileObject,
                                   NULL);

pLBKdev = IoGetRelatedDeviceObject(LocalFileObject);
DbgPrint("%s at IoCreateFile ok\n", __FUNCTION__);
ObReferenceObject(pLBKdev);

/*
* Retrieve device extension pointer from device object
*/
pDevExt = (PDEVICE_EXTENSION)pLBKdev->DeviceExtension;

status = IoAttachDeviceToDeviceStackSafe(pDevObj, pLBKdev, &pDevExt->kbdDevice);
if (status != STATUS_SUCCESS) {
    DbgPrint("IoGetDeviceObjectPointer failed with error = 0x%0x\n", status);
    goto cleanup_failure;
}

pDevObj->Flags |= DO_BUFFERED_IO;
pDevObj->Flags &= ~DO_DEVICE_INITIALIZING;

/*
* Create the symbolic link name, this is not mandatory
* but can be helpful for user mode apps to communicate
*/
status = IoCreateSymbolicLink(&symLinkNameFlt, &devNameFlt);
if (!NT_SUCCESS(status)) {
    // if it fails now, must delete Device object
    DbgPrint("IoCreateSymbolicLink failed with error = 0x%0x\n", status);
    goto cleanup_failure;
}

но подпрограмма DispatchRead падает, если я набираю клавишу на клавиатуре.

person makurisan    schedule 12.01.2018
comment
Проблема в том, что в функции DispatchRead при вызове IoCallDriver(pDevExt-›kbdDevice, Irp); указатель pDevExt->kbdDevice равен NULL. Почему это, потому что это работало раньше. - person makurisan; 12.01.2018

Попробуйте выполнить IoAttachDeviceToDeviceStackSafe() после DO_BUFFERED_IO и ~DO_DEVICE_INITIALIZING.

pDevObj->Flags |= DO_BUFFERED_IO;
pDevObj->Flags &= ~DO_DEVICE_INITIALIZING;

status = IoAttachDeviceToDeviceStackSafe(pDevObj, pLBKdev, &pDevExt->kbdDevice);
if (status != STATUS_SUCCESS) {
    DbgPrint("IoGetDeviceObjectPointer failed with error = 0x%0x\n", status);
    goto cleanup_failure;
}
person Stryker2k2    schedule 24.07.2020