пример должен хоть как то жить, подготовлю и кину в ближайшее время, ото там хрен ногу сломит. А вот насчет HOOKов батенька вы ошибаетесь, это вам не Реестр перехватывать типа { RealRegOpenKey = SYSCALL( ZwOpenKey ); SYSCALL( ZwOpenKey ) = (PVOID) HookRegOpenKey; } Траблы в понимании как происходит захват порта и передача наверх прилажению, я делаю: DriverEntry { IoCreateDevice //мой девайс ZwCreateFile(\device\serial0..7) если успешно { IoGetRelatedDeviceObject IoCreateDevice IoAttachDeviceByPointer } } Далее как и где хранить данные по захваченным портам чтобы передать их наверх, думаю так: При захвате IRP девайса порта надо сделать его копию и послать пакет своему родному DeviceObject, (как это сделать?, использовать системную очередь или придется стряпать свою?), далее свой уже обрабатывает IOCTL_MY_CTL1..2 которая возвращает данные об этом пакете наружу, если данных нет, тоды STATUS_PENDING типа ждемс. Как отловить обработанные нижним драйвером пакеты, которые идут к приложению, ну что то типа снизу вверх, например при асинхроннном IRP_MJ_CLOSE (обработанные потом хрен знает где в случайнои контексте). Можа я все запутанно изложил, но в том что у меня тама в исходниках еще запутанней. Заранее благодарен. P.S. на вопрос "драйвера то писать умеешь, или нет?" умел бы писать не спрашивал бы, затем сюда и залез, за хорошим советом, а не за всякой херней.
Пояснения: ZwCreateFile(\device\serial0..7) если успешно { IoGetRelatedDeviceObject IoCreateDevice IoAttachDeviceByPointer } Это цикл. например при асинхроннном IRP_MJ_CLOSE, неудачный пример,лучше IRP_MJ_READ
[ relikt: <font color="indigo]Далее как и где хранить данные по захваченным портам чтобы передать их наверх, думаю так: При захвате IRP девайса порта надо сделать его копию и послать пакет своему родному DeviceObject, (как это сделать?</font><!--color--> ] Скорее всего полная копия IRP тебе не нужна, а нужны только пересылаемые данные. Поэтому выделяешь кусок памяти нужного размера, копируешь туда содержимое буфера и добавляешь к себе с список (односвязный, двусвязный или как-нить ещё можно организовать). Всё это копится пока твой клиент не захочет получить эти данные. Когда захочет, то через DeviceIoControl или ReadFile сбрасываешь ему сколько влезет его буфер. Ну там синхронизируешь и всё такое. [ relikt: <font color="indigo]Как отловить обработанные нижним драйвером пакеты, которые идут к приложению</font><!--color--> ] IoSetCompletionRoutine ЗЫ: Я заканчиваю первую часть статьи по фильтрации IRP. В начале следующей недели, надеюсь, будет лежать на сайте. Основная теория этого дела там будет.
Спасибо, я уже разобрался, двухсвязанным списком собирать, и наверх проге. Вопрос: Правильно ли я думаю что когда например происходит ReadFile и драйвер порта ответит STATUS_PENDING, далее когда начнется обработка пакета например по прерыванию, прежде чем дойдет обработка пакета до порта, пакет снова попойдет сначало к фильтру. если так тогда нету смысла в IoSetCompletionRoutine 1. STATUS_PENDING 2. STATUS_SUCCESS Типа: MyDispatch(...) { ... satus = IoCallDriver(..); if (status == STATUS_SUCCESS) { ... ExInterlockedPushEntrySList(..);//в список данные ZwDeviceIoControlFile(IOCTL_MYCTL_SET_TO_LIST);//для старта асинхронной обработки возвращеня данных внешней проге, т.к. в StartIo уже может непопасть (Busy), а внешняя прога будет тогда висеть на событии, прерываний то у меня нет. нечто вроде уведомления моему девайсу что типа можно обрабатывать юзерский запрос на получение если он есть. } } [ЗЫ: Я заканчиваю первую часть статьи по фильтрации IRP. В начале следующей недели, надеюсь, будет лежать на сайте. Основная теория этого дела там будет.] Эх нанедельку бы пораньше. Было бы легче. Спасибо за ответы.
Я мало что понял, но если ты повесил фильтр, то когда IRP идет вниз по стеку девайсов к тебе он попадет в любом случае, а вот когда он будет завершаться, то не поподет. А чтобы его опять перехватить на обратном пути как раз и надо IoSetCompletionRoutine. Это если конечно тебя интересуют результаты обработки IRP. STATUS_PENDING, в данном случае, ничего не меняет. Если ты не ставил CompletionRoutine, то какой бы код ни вернул нижестоящий драйвер IRP ты больше не увидишь.
Я так понял что когда внешняя прога делает readfile(..,overlapped) а в очереди порта пока еще пусто, то IRP попадет мне тока один раз, а драйвер порта потом когда нибудь считает данные из буфера порта и отправит во нешнюю прогу и я несмогу увидеть что он там прочитал, чтобы это увидеть я должен буду работать через IoSetCompletionRoutine. Но я взял дамп PORTMON.SYS,(он находится в ресурснике PORTMON.EXE, Русинович.) и посмотрел импортируемые функции, все есть, вот тока как раз IoSetCompletionRoutine нету. Дамп: []
[ relikt: <font color="indigo] все есть, вот тока как раз IoSetCompletionRoutine нету.</font><!--color--> ] И не удивительно. IoSetCompletionRoutine - это не функция, а макрос! Код (Text): .text:00013098 loc_13098: .text:00013098 mov eax, [ebp+Irp] .text:0001309B mov ecx, [ebp+var_8] .text:0001309E mov eax, [eax+60h] ; IoGetCurrentIrpStackLocation // IoSetCompletionRoutine .text:000130A1 mov dword ptr [eax-8], offset IoCompletion .text:000130A8 sub eax, 24h ; sizeof(IO_STACK_LOCATION) .text:000130AB mov [eax+20h], ecx .text:000130AE mov byte ptr [eax+3], 0E0h ; SL_INVOKE_ON_CANCEL | .text:000130AE ; SL_INVOKE_ON_SUCCESS | .text:000130AE ; SL_INVOKE_ON_ERROR .text:000130B2 jmp short loc_130CC .text:000130B4 ; --------------------------------------------------------------------- .text:000130B4 .text:000130B4 loc_130B4: .text:000130B4 .text:000130B4 mov eax, [ebp+Irp] .text:000130B7 mov eax, [eax+60h] ; IoGetCurrentIrpStackLocation // IoSetCompletionRoutine .text:000130BA and dword ptr [eax-4], 0 .text:000130BE sub eax, 24h ; sizeof(IO_STACK_LOCATION) .text:000130C1 and byte ptr [eax+3], 0 .text:000130C5 mov dword ptr [eax+1Ch], offset IoCompletion .text:000130CC .text:000130CC loc_130CC: .text:000130CC mov dl, [ebp+arg_3] ; NewIrql .text:000130CF mov ecx, esi ; SpinLock .text:000130D1 call ds:KfReleaseSpinLock .text:000130D7 mov eax, [ebp+var_14] .text:000130DA mov edx, [ebp+Irp] ; Irp .text:000130DD mov ecx, [eax+0Ch] ; DeviceObject .text:000130E0 call ds:IofCallDriver
может кто подскажет? Как установить и запустить драйвер фильтр программно. не LegacyDriver, класс {4D36E978-E325-11CE-BFC1-08002BE10318},PNP0501. Смотрел примеры установки: ... OpenSCManager(...); ... CreateService(...); ... OpenService(...); ... StartService(...); Получается что таким образом можно установить тока LegacyDriver. Спасибо за советы.
Вот еще траблы.. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\LEGACY_ххх(\0000 \Control) застряла эта запись в реестре, немогу удалить.....
Ага, нашел что то, буду разбиратся, литературы на этот счет вообще мало.., спасибо. Вообще в реестр можно и ручками запихать настройки, а вот стартануть, и остановить. Правда в DDK, нашел пример INSTALL как с INF грузить. Может так и проще, но хочется все в идеале, и не пладить кучу файлов.
[ relikt: <font color="indigo]застряла эта запись в реестре, немогу удалить.....</font><!--color--> ] Если под w2k, то запусти "диспетчер устройств", в меню ставь галки "Устройства по подключению" и "Показать скрытые устройства". Ищи в дереве устройство и удаляй. Если под ХР+, то там только запущенные устройства видны. Тогда запускай regedit с какими-то там ключами (здесь мелькало несколько раз, я их не помню). Я обычно regedit через cmdasuser пущаю. 392592980__cmdasuser.rar
relikt Такая же проблема! Плохо представляю как привязаться к COM-порту! дошол до DriverEntry { IoCreateDevice } Остальное, пока как в тумане, с С ваще не дружу! но кое как разбираюсь.... Если, не всё забыто, подскажи, плз, поподробнее как справился?