mirror of
https://github.com/reactos/reactos.git
synced 2024-07-01 02:10:07 +00:00
324 lines
8.9 KiB
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 */
|