// Прошу прощения за дубли... случайно закрыл тему... Всем привет. Возникла такая задача: написАть IM NDIS драйвер для того, чтобы получать из приложения сетевые пакеты и передавать "наверх" протоколам, как будто они пришли от сетевухи. Решил переделать PassThru, с NDIS-драйверами ранее дела не имел - изучаю по-ходу.... В обработчике IRP_MJ_DEVICE_CONTROL нужного кода формирую NDIS-пакет, а когда вызываю NdisMIndicateReceivePacket получаю BSOD IRQL_NOT_LESS_THAN_OR_EQUAL. В DDK написано, что "Serialized callers of NdisMIndicateReceivePacket must run at IRQL DISPATCH_LEVEL". Проверил - обработчик вызывается на PASSIVE_LEVEL. Пробовал поднимать IRQL для вызова функции - результат тот же... Знающие, помогите, а.. // сильно ногами не бейте - я еще только учусь 8-)
Неудивительно, что у тебя бсод, если ты сразу же освобождаешь пакет и пул и все ресурсы. Читай внимательно MSDN: Код (Text): A deserialized miniport driver must save the Status member of the out-of-band data block in a local variable before indicating up the packet descriptor. As explained in more detail below, when NdisMIndicateReceivePacket returns, a deserialized miniport driver must check the saved packet Status to determine whether it can immediately reclaim the packet descriptor and the associated buffers. If a serialized miniport driver does not set a packet's Status member to NDIS_STATUS_RESOURCES, the call to NdisMIndicateReceivePacket gives interested protocols exclusive, read-only access to the buffers chained to each packet. The miniport driver regains ownership of the packet descriptor and the associated buffers as follows: If the Status in the out-of-band data block is set to NDIS_STATUS_SUCCESS on return from NdisMIndicateReceivePacket, the miniport driver immediately regains ownership of the packet descriptor and all buffers chained to the packet. It can prepare these descriptors for reuse in subsequent receive indications. If the Status is set to NDIS_STATUS_PENDING on return from NdisMIndicateReceivePacket, the miniport driver regains ownership of the packet descriptor and all buffers chained to the packet when NDIS subsequently calls the miniport driver's MiniportReturnPacket function. It can then prepare these descriptors for reuse in subsequent receive indications.
2 Ms Rem Минуточку... Я ведь установил NDIS_STATUS_RESOURCES. в DDK пишут, что это должно заставить обработчик протокола СКОПИРОВАТЬ пакет в СВОЮ память и прямо написано, что, в этом случае, сразу после вызова NdisMIndicateReceivePacket можно освобождать буферы и пакет... // у меня не просто бсод, а IRQL_NOT_LESS_OR_EQUAL. Вот я и подумал, что проблема именно в IRQL Вот что меня смущает, так это то, что не могу найти, где читал про "если установлен NDIS_STATUS_RESOURCES, то нет необходимости обрабатывать MiniportReturnPacket, п.ч. ответа NDIS_STATUS_PENDING не будет..." то бишь либо SUCCESS либо ошибка... никаких отложенных обработок... И еще не понимаю, что такое "serialized miniport" и "deserialized ..." ... в чем отличия и где это указать/настроить?...
> у меня не просто бсод, а IRQL_NOT_LESS_OR_EQUAL Ну так это значит, что было исключение при обращении к неподкачиваемому пулу (скорее всего к пакету). А была отложеная обработка или нет - это следует определять по наличию NDIS_STATUS_PENDING в выходном пакете. По своему опыту скажу - не все драйвера минипортов/протоколов корректно работают с NDIS_STATUS_RESOURCES. Для начала попробуй не освобожлать пакеты, и посмотри что из этого получиться. Пример рабочего драйвера минипорта смотри в сорцах OpenVpn. Где указать: Код (Text): A deserialized miniport driver must identify itself as such to NDIS during initialization. Its MiniportInitialize function must call NdisMSetAttributesEx with the NDIS_ATTRIBUTES_DESERIALIZE flag set in the AttributeFlags. Отличия читай в мсдн (Deserialized NDIS Miniport Drivers.)
Ms Rem Действительно... убрал освобождение пакетов и буферов - первый раз срабатывает гарантированно Странно... а ведь сам драйвер passthru делает именно так и даже не смотрит статус после вызова - сразу освобождает пакет. Правда он не создает пакет "с нуля"... может дело в атрибутах? А есть где-то рабочие сорцы, где бы пакеты создавались "с нуля" ?
Ms Rem Попробовал не освобождать пакеты - помогло... Есть где-то рабочий пример, в котором создается пакет "с нуля", а не копированием из имеющегося? В ДДК вот чего написано: A deserialized miniport driver must not examine the Status of indicated packets on return of NdisMIndicateReceivePacket. Instead, a deserialized miniport driver must save a packet's Status in a local variable before indicating up the packet descriptor. When NdisMIndicateReceivePacket returns, the miniport driver should check the saved packet Status. If the miniport driver set the packet's Status to NDIS_STATUS_RESOURCES before indicating up the packet descriptor, it should reclaim the packet descriptor immediately after NdisMIndicateReceivePacket returns, preferably by calling its own MiniportReturnPacket function. In this case, NDIS does not call the miniport driver's MiniportReturnPacket function to return the packet descriptor. If the miniport driver set the packet's Status to NDIS_STATUS_SUCCESS before indicating up the packet descriptor, the miniport driver must not reclaim the packet descriptor until NDIS subsequently returns the packet descriptor to the miniport driver's MiniportReturnPacket function. Минипорт у меня deserialized Если я правильно понял, тут написано, что если я указал NDIS_STAUS_RESOURCE, то ДОЛЖЕН после вызова функции освободить (или заюзать по новой) пакет, а соответственно и буферы... Но что-то я видимо делаю не так... может какие атрибуты у нового пакета выставить забываю?
Попробовал указать в статусе NDIS_STATUS_SUCCESS - бсода нет, но не вызывается MiniportReturnPacket и снифер не видит моих пакетов.... Народ! Дайте, пожалуйста, рабочий пример создания сетевого пакета "с нуля"!
Ms Rem Посмотрел сорцы OpenVPN - сначала сделал поиск строки NdisMIndicateReceivePacket, ничего не нашлось и я хотел по-возмущаться хреновым предложением 8-) за что извинияюсь. В tap драйвере намного более элегантный способ решения моей проблемы: Код (Text): ioBuffer = Irp->AssociatedIrp.SystemBuffer; ioBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; pAdapt = pAdaptList; NdisMEthIndicateReceive( pAdapt->MiniportHandle, pAdapt, ioBuffer, ETHERNET_HEADER_SIZE, ioBuffer + ETHERNET_HEADER_SIZE, ioBufferLength - ETHERNET_HEADER_SIZE, ioBufferLength - ETHERNET_HEADER_SIZE ); NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = ioBufferLength;