Освобождение пакета при нормальной передаче.
> NdisDprFreePacket(MyPacket);
> break;
> }
>}
Выбор типа адаптера внизу дает возможность применить для индикации готовности к передаче в случае ошибки стандартного сообщения NDIS. Это происходит в случае специфичных сетей и обрабатывается функциями связанными с этими типами.
>pAdapt->IndicateRcvComplete = TRUE;
>switch (pAdapt->Medium) {
>case NdisMedium802_3:
> NdisMEthIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize);
> break;
>case NdisMedium802_5:
> NdisMTrIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize);
> break;
>case NdisMediumFddi:
> NdisMFddiIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize);
> break;
>default:
Это в случае если тип сети неизвестен.
> ASSERT(0);
> break;
> }
>} while(FALSE);
>return Status;
Выход с статусом завершения.
Некоторое пояснение.
Когда тип адаптера и сети специфичен и отличается от стандарта LAN, нам нужно сообщить о пакете и его отправке соответствующей части сервиса NDIS. Именно в связи с этим и появляется выбор типа адаптера. При получении возможно наличие одновременного запроса на прием пакета с разных адаптеров.
В случае с операцией Send этого не происходит, так как NDIS сама по контексту определяет к какому адаптеру предназначен пакет.
Оставшиеся функции аналогичны по назначению с группой функций минипорта.
Как писать драйвера (часть 5)
Итак, мы возвращаемся к драйверам.
Справедливости ради, стоит отметить, что на сайте эта тема – одна из самых популярных, так что, кому нужны более глубокие знания, может обращаться к нам на форум, там обсуждаются конкретные проблемы.
Сегодня мы поговорим о коммуникации программы с драйвером.
В одной из предыдущих статей описаны были функции типа Filter:
Вот они:
>extern NTSTATUS FilterOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
>extern NTSTATUS FilterClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
>extern NTSTATUS FilterRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
>extern NTSTATUS FilterWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
>extern NTSTATUS FilterIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
В любом драйвере необходима система управления, для указания самому драйверу, какого типа операцию стоит выполнить в текущий момент времени.
Скажем для нашего примера, драйверу фильтра потока данных по сети стоит указывать степень фильтрации, типы портов для перехвата, адреса, запрещенные к обращению и т.п.
Для этого используются вышеназванные функции.
FilterOpen вызывается когда в программе вызвано обращение к драйверу с помощью функции CreateFile
FilterClose – CloseHandle()
FilterRead/FilterWrite – ReadFile/WriteFile
FilterIoControl – DeviceIoControl() соответственно.
Для правильного завершения работы каждой из этих функций – нужно обеспечить передачу в программу необходимых данных.
>NTSTATUS FilterOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
> // инициализация любых управляющих параметров, например структуры управляющих данных
> Irp->IoStatus.Status = NDIS_STATUS_SUCCESS; // Возращаемое значение – ошибка или нормальное. При нормальном завершении – будет передан HANDLE на устройство, в нашем случае на драйвер.
> Irp->IoStatus.Information = 0; // Количество переданных вверх байт – в нашем случае 0 потому как нет передаваемых параметров.
> IoCompleteRequest(Irp, IO_NO_INCREMENT); // Завершение работы.
> return NDIS_STATUS_SUCCESS; // Нормальный код возврата.
>}
Эта форма будет использоваться в том или ином виде в каждой из этих функций.
Точно так же выглядит и функция закрытия:
>NTSTATUS FilterClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
> // Код окончания работы с драйвером.
> Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
> Irp->IoStatus.Information = 0;
> IoCompleteRequest(Irp, IO_NO_INCREMENT);
> return NDIS_STATUS_SUCCESS;
>}
В драйвере можно создать например просто элемент для нашего примера – например, описать глобальную переменную DWORD Port; Ее будем испрользовать для задания номера порта для перехвата.