Это код обработчика IRP_MJ_READ с драйвера mouclass. Почему сдесь нет обращения к нижелижащему драйверу(в стэке)? Я вижу здесь что пакет додаеться в очередь необработаных сообщений через IoMarkIrpPending. Обясните, пожалуста, как это работает и где же всетаки пакет обрабатываеться. Код (Text): NTSTATUS MouseClassRead( IN PDEVICE_OBJECT Device, IN PIRP Irp ) { NTSTATUS status; PIO_STACK_LOCATION irpSp; PDEVICE_EXTENSION deviceExtension; MouPrint((2,"MOUCLASS-MouseClassRead: enter\n")); irpSp = IoGetCurrentIrpStackLocation(Irp); deviceExtension = (PDEVICE_EXTENSION) Device->DeviceExtension; if (irpSp->Parameters.Read.Length == 0) { status = STATUS_SUCCESS; } else if (irpSp->Parameters.Read.Length % sizeof(MOUSE_INPUT_DATA)) { status = STATUS_BUFFER_TOO_SMALL; } else if (IS_TRUSTED_FILE_FOR_READ (irpSp->FileObject)) { deviceExtension = (PDEVICE_EXTENSION) Device->DeviceExtension; status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp); if (NT_SUCCESS (status)) { status = STATUS_PENDING; } } else { status = STATUS_PRIVILEGE_NOT_HELD; } Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; if (status == STATUS_PENDING) { IoMarkIrpPending(Irp); IoStartPacket(Device, Irp, (PULONG)NULL, MouseClassCancel); } else { IoCompleteRequest(Irp, IO_NO_INCREMENT); } MouPrint((2,"MOUCLASS-MouseClassRead: exit\n")); return(status); }
<font color="gray][ wish3</font><!--color--><font color="gray]: Обясните, пожалуста, как это работает и где же всетаки пакет обрабатываеться. ]</font><!--color--> В ДДК в разделе "Mouclass Driver Reference" очень многое объясняется. Схема такая: Mouclass общается с функциональным драйвером посредством callback'а, коий регистрируется функцией MouseClassServiceCallback. Когда происходит мышиное событие функциональный драйвер зовёт колбэк драйвера Mouclass, а тот заполняет свою внутреннюю очередь данными о событии. Когда к Mouclass приходит IRP_MJ_READ, он достает инфу из этой очереди и завершает IRP. Кстати, Kbdclass работает точно так же.
Перечитывал и Mouclass, и много чего, но так не нашел выход из своей проблемы. В написании драйверов я новичок, а хочеться дописать этот и ити дальше. Вобщем вот код обработки чтения, мне нужно подставлять свои даные IoCompletionRoutine не подходит. При перезагрузке с установленым драйвером я получаю только пикание. Помогите последний раз, очень прошу. Что я не так делаю?? Код (Text): NTSTATUS MouDrv_Read ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION devExt; PMOUSE_INPUT_DATA MouseData; PIO_STACK_LOCATION currentIrpStack; PIRP newIrp; IO_STATUS_BLOCK iosb; ULONG bytesToMove; // #if DBG DbgPrint("MouseDrv: Read started."); #endif devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; currentIrpStack = IoGetCurrentIrpStackLocation(Irp); bytesToMove = currentIrpStack->Parameters.Read.Length; Irp->IoStatus.Information = 0; if (currentIrpStack->Parameters.Read.Length == 0) { Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } else if (currentIrpStack->Parameters.Read.Length % sizeof(MOUSE_INPUT_DATA)) { Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_BUFFER_TOO_SMALL; }; KeStallExecutionProcessor(40); MouseData = Irp->AssociatedIrp.SystemBuffer; MouseData->Flags |= MOUSE_MOVE_RELATIVE; MouseData->LastX = 1; MouseData->LastY = 1; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA); currentIrpStack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA); IoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_SUCCESS; } Что я хочу сделать. Когда вы нажимаете на колесико, то появляется, рисунок в виде кольца на мониторе и теперь если мышу потянуть вниз и остановить, то страница начнет потихоньку прокручиваться и т.д. Я такое такое хочу сделать с обычным перемещением курсора, тоесть потянул мышу вниз, остановил и курсор потихонечку пополз вниз. Идея мне кажеться светлой, если напишу, то обязательно выложу исходники.
Почти всё правильно, окромя: <font color="red]currentIrpStack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA);</font><!--color--> Эта строчка не нужна и вредна. <font color="gray][ wish3</font><!--color--><font color="gray]: получаю только пикание ]</font><!--color--> Поток RIT постоянно шлет IRP_MJ_READ в клавиатурный и мышиный стеки. Ты завершаешь IRP с интервалом в ~40 микросекунд тут же получаешь новый IRP. Т.е. RIT пытается опросить состояние мыши ~25000 раз в секунду! Т.к. у него довольно высокий приоритет - 19, то система только этим и занимается. А пищит, наверное из-за переполнения буфера клавиатуры, т.к. RIT не успевает забирать клавиатурные события. Вобщем, чтоб тебе с этим поиграться, вот код, который двигает мышь по диагонали вниз-вправо с интервалом 1 сек. Мышь при этом блокируется, т.к. Mouclass не получает IRP_MJ_READ. Когда наиграешься, сбрось g_bDo и всё должно заработать как обычно, при условии, что в DeviceExtension->TopDevice адрес нижестоящего драйвера. Код я не проверял - возможно, где-то чуть накосячил. Ну а для того, чтобы реализовать твою идею, код будет гораздо сложнее. Кстати, по-моему, это можно и без драйвера сделать, но как я не знаю, а думать некогда. Код (Text): BOOL g_bDo = TRUE; NTSTATUS MouDrv_Read ( IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp ) { NTSTATUS status; PIO_STACK_LOCATION pIrpStack; LARGE_INTEGER liInterval; PMOUSE_INPUT_DATA pmd; // _asm int 3 if ( g_bDo ) { pIrpStack = IoGetCurrentIrpStackLocation( pIrp ); if ( pIrpStack->Parameters.Read.Length >= sizeof(MOUSE_INPUT_DATA) ) { #define DELAY_ONE_MICROSECOND (-10) #define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000) #define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000) liInterval.QuadPart = DELAY_ONE_SECOND; KeDelayExecutionThread( KernelMode, FALSE, &liInterval ); pmd = pIrp->AssociatedIrp.SystemBuffer; pmd->Flags = MOUSE_MOVE_RELATIVE; pmd->LastX = 1; pmd->LastY = 1; pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = sizeof( MOUSE_INPUT_DATA ); } else { pIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; pIrp->IoStatus.Information = 0; } status = pIrp->IoStatus.Status; IoCompleteRequest( pIrp, IO_NO_INCREMENT ); return status; } else { IoSkipCurrentIrpStackLocation( pIrp ); return IoCallDriver( ((PDEVICE_EXTENSION) DeviceObject->DeviceExtension)->TopDevice, pIrp ); } }
Большое спасибо за код! Главное, теперь я знаю, что действую в нужном направлении. ...к сожелению при загрузке опять одно пикание, только с унтервалом в одна секунда...я думаю что поток RIT хочет еще какието даные в структуре MOUSE_INPUT_DATA увидеть.. ...В любом случее сейчас постараюсь освоить SoftIce, о ее командах я уже читал по H, .. сейчас ламаю голову как сбилдить драйвер с исходниками и загрузить его в SoftIce. Неподскажите??
Дебугить драйвер айсом научился, но есть проблемы: 1. В коде дравера делаю KdBreakPoint(); ... занимаемся отладкой ... не хотим больше заниматься отладкой i3here off рухаем мышой, тогда исполниться KdBreakPoint() и система сразу вырубуеться 2. Как увидить исходный драйвера код в айсе.
<font color="gray][ wish3</font><!--color--><font color="gray]: тогда исполниться KdBreakPoint() и система сразу вырубуеться ]</font><!--color--> Естественно. Пока у тебя стояло i3here on или i3here drv SoftICE отлавливает третье прерывание, которое и генерит функция KdBreakPoint. Когда ты выключил i3here, ловить int3 стало некому. И система показывает BSOD, но у тебя стоит галка Свойства системы -> Загрузка и восстановление -> Выполнить автоматическую перезагрузку. Убери её и тогда вместо ребута увидишь голубой экран. В таких случаях я делаю так. В коде драйвера пишешь стороку. _asm int 3 Это тоже самое, что и KdBreakPoint, но намного удобнее. Это однобайтовая инструкция с кодом CCh. В айсе будешь трапаться прямо за этой строкой. Если трапаться больше не надо, нужно просто заменить CC (int3) на 90 (инструкция nop). Если ты не перемещался по коду, то просто набери eb eip-1 и увидишь в окне дампа CC, замени его на 90. Кстати, я подозреваю, что ты пользуешься "Checked Build Environment", но работаешь в релизной версии системы. Если это так, то очень плохо. <font color="gray][ wish3</font><!--color--><font color="gray]: Как увидить исходный драйвера код в айсе. ]</font><!--color--> Запусти SoftICE Symbol Loader. Перетащи к нему на окошко свой драйвер. Рядом с драйвером должен лежать .pdb - айс транслирует его в .nms. Если всё ОК, то увидишь код. Я помню, очень радовался, когда в айсе исходник увидел, прямо со всем комментариями Только учти, что айс иногда может показать неверную строку, т.е. стоишь на одной, а он показывает, что на следующей и т.п. Переключаться между исходником, дизасмом и смесью оных можно по команде src. <font color="gray][ wish3</font><!--color--><font color="gray]: к сожелению при загрузке опять одно пикание ]</font><!--color--> Мышиный стек разрешает не-Pnp драйвера. Если ты постоянно ребутишься, так ты много не накодишь. Сделай legacy драйвер. В аттаче слегка модифицированный пример из 16 части. По правому щелчку 20 раз дергает курсор по диагонали - код аналогичен, вышеприведенному сишному. Изменения помечены "BAD CODE". Драйвер загружается/выгружается динамически без проблем, но для usb мышей не работает - подробности в статье, если не читал. Уфф...
Спасибо за помощь. Если в системе есть две мыши, то как в реестре сделать записи, чтобы PnP-менеджер грузил мой фильтр только в стэк одной из них? Например, есть: SYSTEM\CurrentControlSet\Control\Class\{4D36E96F-E325-11CE-BFC1-08002B E10318} ....\0000\DriverDesc == PS/2-совместимая мышь ....\0001\DriverDesc == Microsoft USB IntelliMouse оптическая мышь Я перепробовал самые разные комбинации параметров UpperFilters, но ничего не добился. Возможно ли такое сделать?
Эта ветка реестра для всех устройств класса "мышь". В параметре UpperFilters определяются так называемые "Upper-level class filter drivers". Сам mouclass тоже является "Upper-level class filter driver". В общем виде стек может выглядеть так: Upper-level class filter driver Upper-level device filter driver Function driver Lower-level class filter driver Lower-level device filter driver Bus filter driver Bus driver Для того, чтобы поставить фильтр на конкретную мышь нужен "Upper-level device filter driver", но тогда он окажется под mouclass и должен будет работать по другим правилам. См. пример DDK\src\input\moufiltr. Вобщем я не знаю, можно ли заставить систему воткнуть "Upper-level class filter driver" в конкретный стек. Если узнаешь, расскажи. Но я бы не парился. Пусть твой фильтр болтается в обоих стеках, а девайсы различай по HardwareId.
Four-F Это так.((( Почему плохо? В плане, что я не смогу вкусностей отладочной винды заюзать, или в плане, что мне надо перейти в "Free Build Environment"?
Драйвер оказывается заточенным под отладочную версию системы. Некоторые функции могут быть к этому чувствительны. К тому же, "в плане вкусностей отладочной винды", это мало что дает. Разве что IoInitializeRemoveLock, IoAcquireRemoveLock, IoReleaseRemoveLock... Можно накатить только дебужные ntoskrnl и hal. В ДДК даже есть раздел "Installing Just the Checked Operating System and HAL"