Доброе утро! В аттаче то, что у меня получилось при анализе minidump. Это без символьного файла ntoskrnl. ОС у меня без сервис-паков.
Ну да, таки я не ошибся. У тебя ж в pdx->pLowerDevice просто 0! Код (Text): FAULTING_IP: nt!IofCallDriver+24 804ec046 8b7108 mov esi,[<font color="red]ecx</font><!--color-->+0x8] TRAP_FRAME: f3a00b98 -- (.trap fffffffff3a00b98) ErrCode = 00000000 eax=00000004 ebx=81b0c650 ecx=<font color="red]00000000</font><!--color--> edx=81a07c28 esi=81b0c6c0 edi=81928288 eip=804ec046 esp=f3a00c0c ebp=f3a00c24 iopl=0 nv up ei ng nz na po nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010286 SoftICE с faults on должен легко отлавливать такое. Ты вообще-то отладчиком пользуешься? ЗЫ: Мыло в течение дня гляну.
Код, который в мыло упал посмотрел - всё ясно. Извиняюсь за грубость, но, похоже, налицо явный разрыв желаний и возможностей. Так выпьем же за то, чтобы наши желания, всегда совпадали... Кхм... Пардон Причина ошибки проста - попытка отправить IRP не туда куда следует. У тебя есть один CDO (Control Device Object) (их можно и несколько понаделать, но как правило не за чем) и от одного до бесконечности FiDO (Filter Device Object). Заявления типа "я точно знаю, что устройство будет одно" не хиляют, т.к. нельзя этого знать. Код не должен писАться в расчете только на одно устройство. CDO ты создаешь в DriverEntry. Через некоторое время будет вызвана AddDevice, где ты создаешь FiDO и сажаешь его в стек. Указатель на CDO сохраняется в глобальной переменной. Указатель на лежащий под FiDO девайс - в DEVICE_EXTENSION этого FiDO. По ходу дела AddDevice может вызываться ещё сколь угодно много раз, если будут обнаружены другие устройства, а может и нет, но расчитывать надо именно на худшее. И каждый раз AddDevice создает новый FiDO и сажает его в новый стек. Драйвер будет получать запросы к CDO и ко всем FiDO. Влетать они будут в одну и ту же процедуру диспетченизации. Единственная возможность отличить среди запросов запрос к CDO - это сравнить входящий указатель на девайс с запомненный указателем на CDO. Если это запрос к CDO, то следует его обработка и завершение, т.к. передавать его некому. А если запрос пришёл не к CDO, значит он к одному из фильтров. Т.к. FiDO сами помнят кто под ними в своих DEVICE_EXTENSION, то если бы мы просто форвардили IRP, то делали бы так: Код (Text): NTSTATUS FilterDispatch ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PDEVICE_EXTENSION pdex = (PDEVICE_EXTENSION) pDeviceObject->DeviceExtension; PDEVICE_OBJECT pTargetDO = pdex->pLowerDO; . . . } Когда к твоему CDO приходит ответ от юзера, ты достаешь IRP из очереди, но указатель на Target Device достаешь из DEVICE_EXTENSION, принадлежащего CDO. Т.к. CDO никогда не сажался в стек, то и pdex->pLowerDO = NULL (система обнуляет весь DEVICE_EXTENSION при создании объекта). Здесь сразу несколько ошибок. CDO.DEVICE_EXTENSION и FiDO.DEVICE_EXTENSION вообще должны быть разными структурами и у CDO.DEVICE_EXTENSION не должно быть члена pLowerDO по определению. Если бы ты всё сделал правильно то заметил бы ошибку ещё на этапе компиляции. В твоём случае указатель на Target Device можно достать только из самого IRP. Т.к. ты поставил его в очередь, когда он попал в твой FiDO, то в текущем IO_STACK_LOCATION.DeviceObject будет указатель на этот самый FiDO. Т.о. можно сделать так: Код (Text): PIRP pIrp = PopIrp(); pIoStack = IoGetCurrentIrpStackLocation( pIrp ); PDEVICE_OBJECT pFiDO = pIoStack->DeviceObject; PDEVICE_EXTENSION_FIDO pdex = (PDEVICE_EXTENSION_FIDO) pFiDO->DeviceExtension; PDEVICE_OBJECT pTargetDO = pdex->pLowerDO; IoSkipCurrentIrpStackLocation( pIrp ); status = IoCallDriver( pTargetDO, pIrp ); К сожалению, в ДДК действительно нет 100% подходящего драйвера, но есть многие с подобным функционалом. Например toaster имеет практически 90% нужного кода (кроме опроса пользователя). Но операции с очередью отложенных IRP все есть. Есть даже возобновление обработки IRP достанных из очереди (см. ToasterProcessQueuedRequests). Также там есть необходимый код для реализации отмены IRP, а она по-любому понадобится. Что ты будешь делать с поставлнными в очередь IRP, если приложение пославшее их, например упадет? Когда система начнет принудительно закрывать все открытые упавшей прогой хендлы, ты получишь IRP_MJ_CLEANUP и должен будешь отменить все IRP ассоциированные с соответствующим файловым объектом. ЗЫ: Прочти внимательно 15-ую часть моего цикла по дровам. Мыло тоже посмотри.
Спасибо, Four-F! Насчет желаний и возможностей. Я не раз писал про то, что только начал разбираться в разработке драйверов и никогда не говорил, что все мне понятно, только я не знаю того, того и того. Я прекрасно понимаю, что те вопросы, которые я задавал, являются базовыми (может быть, даже наивными), но они очень помогли мне Это мой первый проект. Почему сразу довольно сложный. Я думаю, так интереснее изучать новую технологию. Так как количество задач, которые необходимо решить для написания всей задумки очень велико, приходится узнавать практически все (например, тот же опрос пользователя, etc.). Еще раз подчеркну, что я благодарен Вам за Вашу помощь и поддержку, а также за здоровую (в смысле, хорошую) критику.
Я как раз и имел ввиду, что велика дистанция между "мой первый проект" и "довольно сложный". Это похвально, но вообще говоря, не верно. Нужна хоть какая-то база, а то опереться совсем не на что.