Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / drivers / network / afd / afd / event.c
diff --git a/drivers/network/afd/afd/event.c b/drivers/network/afd/afd/event.c
new file mode 100644 (file)
index 0000000..93f5f3d
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * 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 = ExAllocatePool(NonPagedPool, BytesAvailable);
+    if (!ReceiveBuffer)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /*Buffer = (PAFD_BUFFER)ExAllocateFromNPagedLookasideList(
+      &BufferLookasideList);*/
+    Buffer = (PAFD_BUFFER)ExAllocatePool(NonPagedPool, sizeof(AFD_BUFFER));
+    if (!Buffer) {
+        ExFreePool(ReceiveBuffer);
+        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 = ExAllocatePool(NonPagedPool, BytesAvailable);
+    if (!ReceiveBuffer)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /*Buffer = (PAFD_BUFFER)ExAllocateFromNPagedLookasideList(
+      &BufferLookasideList);*/
+    Buffer = (PAFD_BUFFER)ExAllocatePool(NonPagedPool, sizeof(AFD_BUFFER));
+    if (!Buffer) {
+        ExFreePool(ReceiveBuffer);
+        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 */