Возвращаемый статус.
PNDIS_PACKET MyPacket;
Наш пакет – пока только указатель.
PRSVD Rsvd;
Резервный указатель.
PVOID MediaSpecificInfo = NULL;
Тип адаптера с которым будем работать.
ULONG MediaSpecificInfoSize = 0;
Размер типа адаптера.
ASSERT (pAdapt->pSecondaryAdapt);
pAdapt = pAdapt->pSecondaryAdapt;
Проверка наличия второго сетевого адаптера. Вверху я говорил, что его наличие необходимо предусматривать.
if (IsIMDeviceStateOn (pAdapt) == FALSE) {
return NDIS_STATUS_FAILURE;
}
Проверка наличия и состояния.
NdisAllocatePacket(&Status, &MyPacket, pAdapt->SendPacketPoolHandle);
Выделение места под размер полученного пакета (Pool) данных.
if (Status == NDIS_STATUS_SUCCESS) {
PNDIS_PACKET_EXTENSION Old, New;
Rsvd = (PRSVD)(MyPacket->ProtocolReserved);
Rsvd->OriginalPkt = Packet;
MyPacket->Private.Flags = Flags;
MyPacket->Private.Head = Packet->Private.Head;
MyPacket->Private.Tail = Packet->Private.Tail;
Собственно копирование всей служебной информации
NdisSetPacketFlags(MyPacket, NDIS_FLAGS_DONT_LOOPBACK);
Установка ее в наш внутренний буфер.
NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket), NDIS_OOB_DATA_FROM_PACKET(Packet), sizeof(NDIS_PACKET_OOB_DATA));
Перенос данных в сам пакет.
NdisIMCopySendPerPacketInfo(MyPacket, Packet);
Копирование служебных данных по пересылке пакета.
Копирование данных о типе адаптера, куда пересылать данные.
NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet, &MediaSpecificInfo, &MediaSpecificInfoSize);
if (MediaSpecificInfo || MediaSpecificInfoSize) {
NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket, MediaSpecificInfo, MediaSpecificInfoSize);
}
Собственно пересылка имеющихся данных в NDIS, что вызовет нормальное прохождение пакета далее по цепочке драйверов.
NdisSend(&Status, pAdapt->BindingHandle, MyPacket);
if (Status != NDIS_STATUS_PENDING) {
NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
NdisFreePacket(MyPacket);
}
Если нет задержки на отсылке освободить пакет.
} else {
Это говорит об отсутствии пакета в системе – ничего не надо делать.
}
return(Status);
Возврат значения SUCCESS или код ошибки.
Стоит остановиться еще на одном моменте. Когда система ответила, что посылка данных закончена кодом задержки пакета – NDIS_STATUS_PENDING.
В этом случае мы пакет не освободим, блокировав таким образом всю систему NDIS по пересылке данных. Такое случается при посылке по медленной сети большого числа пакетов.
Как нам освободить пакет? Система предусматривает такое и при освобождении ресурса после освобождению пакета вызовет функцию из группы протокола PtSendComplete. Смена на протокольную группу вызвана тем, что система получит сообщение от низлежащего драйвера, что вызывает обращение именно к этой группе.
В данной функции, код которой идет следом мы увидим параметры в которых нам передадут контекст операции Send и адаптера, в результате чего мы получим возможность вызвать функцию NdisMSendComplete после NdisDprFreePacket и освободить NDIS для передачи нам следующих пакетов.
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
PNDIS_PACKET Pkt;
PRSVD Rsvd;
pAdapt = pAdapt->pPrimaryAdapt;
Rsvd =(PRSVD)(Packet->ProtocolReserved);
Pkt = Rsvd->OriginalPkt;
NdisIMCopySendCompletePerPacketInfo(Pkt, Packet);
NdisDprFreePacket(Packet);
NdisMSendComplete(pAdapt->MiniportHandle, Pkt, Status);
Протокольные функции несколько отличаются от функций минипорта, но имеют схожую функциональную нагрузку, обратную функциям минипорта по направлению передачи пакетов.
PtOpenAdapterComplete
PtCloseAdapterComplete
PtBindAdapter
PtUnbindAdapter
Функции работы с адаптером – в нашем случае адаптером является драйвер модема или сетевой карты. Адаптер соответственно при запуске надо открыть и при окончании работы – закрыть. При обращении к нему привязать (bind) адаптер, захватить ресурс. В конце работы – освободить.
PtResetComplete
Абсолютно пустая функция – она должна быть но мы сюда не приходим.
PtRequestComplete
Функция вызываемая из PtPnPNetEventSetPower.
PtStatus
Функция отвечающая за проверку статуса нижестоящего адаптера, вернее статуса взаимодействия с ним нашего уровня.
PtStatusComplete
Завершение в случае невозможности быстрого ответа, примерно как и в случае MPSend.
PtSendComplete
Описана в секции минипорт
PtTransferDataComplete
PtReceive
PtReceiveComplete
PtReceivePacket
Функции работы с данными – аналогичны функциям минипорта. Одну из функций мы уже разбирали. Функции остальных – чуть позже.
PtUnload
Функция заведующая выгрузкой драйвера при выходе.
Читать дальше