reactos/drivers/network/afd/afd/event.c

324 lines
8.9 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: afd/event.c
* PURPOSE: TDI event handlers
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <afd.h>
NTSTATUS AfdEventError(
IN PVOID TdiEventContext,
IN NTSTATUS Status)
{
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
return STATUS_SUCCESS;
}
NTSTATUS AfdEventDisconnect(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN LONG DisconnectDataLength,
IN PVOID DisconnectData,
IN LONG DisconnectInformationLength,
IN PVOID DisconnectInformation,
IN ULONG DisconnectFlags)
{
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
return STATUS_SUCCESS;
}
NTSTATUS AfdEventReceive(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN ULONG ReceiveFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG *BytesTaken,
IN PVOID Tsdu,
OUT PIRP *IoRequestPacket)
{
PAFDFCB FCB = (PAFDFCB)TdiEventContext;
PVOID ReceiveBuffer;
PAFD_BUFFER Buffer;
KIRQL OldIrql;
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
AFD_DbgPrint(MID_TRACE, ("Receiving (%d) bytes on socket\n",
BytesAvailable));
ReceiveBuffer = ExAllocatePoolWithTag(NonPagedPool,
BytesAvailable,
TAG_AFD_DATA_BUFFER);
if (!ReceiveBuffer)
return STATUS_INSUFFICIENT_RESOURCES;
/*Buffer = (PAFD_BUFFER)ExAllocateFromNPagedLookasideList(
&BufferLookasideList);*/
Buffer = (PAFD_BUFFER)ExAllocatePoolWithTag(NonPagedPool,
sizeof(AFD_BUFFER),
TAG_AFD_DATA_BUFFER);
if (!Buffer) {
ExFreePoolWithTag(ReceiveBuffer, TAG_AFD_DATA_BUFFER);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Copy the data to a local buffer */
RtlCopyMemory(ReceiveBuffer, Tsdu, BytesAvailable);
Buffer->Buffer.len = BytesAvailable;
Buffer->Buffer.buf = ReceiveBuffer;
Buffer->Offset = 0;
KeAcquireSpinLock(&FCB->ReceiveQueueLock, &OldIrql);
InsertTailList( &FCB->ReceiveQueue, &Buffer->ListEntry );
TryToSatisfyRecvRequest( FCB, TRUE );
KeReleaseSpinLock(&FCB->ReceiveQueueLock, OldIrql);
*BytesTaken = BytesAvailable;
AFD_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return STATUS_SUCCESS;
}
TDI_STATUS ClientEventReceiveExpedited(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN ULONG ReceiveFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG *BytesTaken,
IN PVOID Tsdu,
OUT PIRP *IoRequestPacket)
{
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
return STATUS_SUCCESS;
}
NTSTATUS ClientEventChainedReceive(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN ULONG ReceiveFlags,
IN ULONG ReceiveLength,
IN ULONG StartingOffset,
IN PMDL Tsdu,
IN PVOID TsduDescriptor)
{
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
return STATUS_SUCCESS;
}
NTSTATUS AfdEventReceiveDatagramHandler(
IN PVOID TdiEventContext,
IN LONG SourceAddressLength,
IN PVOID SourceAddress,
IN LONG OptionsLength,
IN PVOID Options,
IN ULONG ReceiveDatagramFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG *BytesTaken,
IN PVOID Tsdu,
OUT PIRP *IoRequestPacket)
{
PAFDFCB FCB = (PAFDFCB)TdiEventContext;
PAFD_READ_REQUEST ReadRequest;
PVOID ReceiveBuffer;
PAFD_BUFFER Buffer;
PLIST_ENTRY Entry;
NTSTATUS Status;
KIRQL OldIrql;
ULONG Count;
BOOLEAN CompleteIrp;
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
AFD_DbgPrint(MID_TRACE, ("Receiving (%d) bytes from (0x%X).\n",
BytesAvailable, *(PULONG)SourceAddress));
ReceiveBuffer = ExAllocatePoolWithTag(NonPagedPool,
BytesAvailable,
TAG_AFD_DATA_BUFFER);
if (!ReceiveBuffer)
return STATUS_INSUFFICIENT_RESOURCES;
/*Buffer = (PAFD_BUFFER)ExAllocateFromNPagedLookasideList(
&BufferLookasideList);*/
Buffer = (PAFD_BUFFER)ExAllocatePoolWithTag(NonPagedPool,
sizeof(AFD_BUFFER),
TAG_AFD_DATA_BUFFER);
if (!Buffer) {
ExFreePoolWithTag(ReceiveBuffer, TAG_AFD_DATA_BUFFER);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Copy the data to a local buffer */
RtlCopyMemory(ReceiveBuffer, Tsdu, BytesAvailable);
Buffer->Buffer.len = BytesAvailable;
Buffer->Buffer.buf = ReceiveBuffer;
Buffer->Offset = 0;
ExInterlockedInsertTailList(&FCB->ReceiveQueue,
&Buffer->ListEntry,
&FCB->ReceiveQueueLock);
KeAcquireSpinLock(&FCB->ReceiveQueueLock, &OldIrql);
if (CompleteIrp = !IsListEmpty(&FCB->ReadRequestQueue)) {
AFD_DbgPrint(MAX_TRACE, ("Satisfying read request.\n"));
Entry = RemoveHeadList(&FCB->ReceiveQueue);
ReadRequest = CONTAINING_RECORD(Entry, AFD_READ_REQUEST, ListEntry);
Status = FillWSABuffers(FCB,
ReadRequest->RecvFromRequest->Buffers,
ReadRequest->RecvFromRequest->BufferCount,
&Count,
FALSE); /* Packet oriented */
ReadRequest->RecvFromReply->NumberOfBytesRecvd = Count;
ReadRequest->RecvFromReply->Status = NO_ERROR;
ReadRequest->Irp->IoStatus.Information = 0;
ReadRequest->Irp->IoStatus.Status = Status;
}
KeReleaseSpinLock(&FCB->ReceiveQueueLock, OldIrql);
if (CompleteIrp) {
AFD_DbgPrint(MAX_TRACE, ("Completing IRP at (0x%X).\n", ReadRequest->Irp));
IoCompleteRequest(ReadRequest->Irp, IO_NETWORK_INCREMENT);
*BytesTaken = BytesAvailable;
}
AFD_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return STATUS_SUCCESS;
}
NTSTATUS AfdRegisterEventHandlers(
PAFDFCB FCB)
{
NTSTATUS Status;
assert(FCB->TdiAddressObject);
/* Report errors for all types of sockets */
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_ERROR,
(PVOID)AfdEventError,
(PVOID)FCB);
if (!NT_SUCCESS(Status)) { return Status; }
switch (FCB->SocketType) {
case SOCK_STREAM:
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_DISCONNECT,
(PVOID)AfdEventDisconnect,
(PVOID)FCB);
if (!NT_SUCCESS(Status)) { return Status; }
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_RECEIVE,
(PVOID)AfdEventReceive,
(PVOID)FCB);
if (!NT_SUCCESS(Status)) { return Status; }
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_RECEIVE_EXPEDITED,
(PVOID)ClientEventReceiveExpedited,
(PVOID)FCB);
if (!NT_SUCCESS(Status)) { return Status; }
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_CHAINED_RECEIVE,
(PVOID)ClientEventChainedReceive,
(PVOID)FCB);
if (!NT_SUCCESS(Status)) { return Status; }
break;
case SOCK_DGRAM:
case SOCK_RAW:
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_RECEIVE_DATAGRAM,
(PVOID)AfdEventReceiveDatagramHandler,
(PVOID)FCB);
if (!NT_SUCCESS(Status)) { return Status; }
}
return STATUS_SUCCESS;
}
NTSTATUS AfdDeregisterEventHandlers(
PAFDFCB FCB)
{
NTSTATUS Status;
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_ERROR,
NULL,
NULL);
if (!NT_SUCCESS(Status)) { return Status; }
switch (FCB->SocketType) {
case SOCK_STREAM:
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_DISCONNECT,
NULL,
NULL);
if (!NT_SUCCESS(Status)) { return Status; }
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_RECEIVE,
NULL,
NULL);
if (!NT_SUCCESS(Status)) { return Status; }
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_RECEIVE_EXPEDITED,
NULL,
NULL);
if (!NT_SUCCESS(Status)) { return Status; }
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_CHAINED_RECEIVE,
NULL,
NULL);
if (!NT_SUCCESS(Status)) { return Status; }
break;
case SOCK_DGRAM:
case SOCK_RAW:
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_RECEIVE_DATAGRAM,
NULL,
NULL);
if (!NT_SUCCESS(Status)) { return Status; }
}
return STATUS_SUCCESS;
}
/* EOF */