4e1f0e9fa3be80967693543ff80ae58a81a7aff2
[reactos.git] / drivers / network / ndisuio / readwrite.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS User I/O driver
4 * FILE: readwrite.c
5 * PURPOSE: Handles IRP_MJ_READ and IRP_MJ_WRITE
6 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
7 */
8
9 #include "ndisuio.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 NTSTATUS
15 NTAPI
16 NduDispatchRead(PDEVICE_OBJECT DeviceObject,
17 PIRP Irp)
18 {
19 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
20 PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
21 KIRQL OldIrql;
22 NTSTATUS Status;
23 PLIST_ENTRY ListEntry;
24 PNDISUIO_PACKET_ENTRY PacketEntry = NULL;
25 ULONG BytesCopied = 0;
26
27 ASSERT(DeviceObject == GlobalDeviceObject);
28
29 while (TRUE)
30 {
31 KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
32
33 /* Check if we have a packet */
34 if (IsListEmpty(&AdapterContext->PacketList))
35 {
36 KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
37
38 /* Wait for a packet (in the context of the calling user thread) */
39 Status = KeWaitForSingleObject(&AdapterContext->PacketReadEvent,
40 UserRequest,
41 UserMode,
42 TRUE,
43 NULL);
44 if (Status != STATUS_SUCCESS)
45 break;
46 }
47 else
48 {
49 /* Remove the first packet in the list */
50 ListEntry = RemoveHeadList(&AdapterContext->PacketList);
51 PacketEntry = CONTAINING_RECORD(ListEntry, NDISUIO_PACKET_ENTRY, ListEntry);
52
53 /* Release the adapter lock */
54 KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
55
56 /* And we're done with this loop */
57 Status = STATUS_SUCCESS;
58 break;
59 }
60 }
61
62 /* Check if we got a packet */
63 if (PacketEntry != NULL)
64 {
65 /* Find the right amount of bytes to copy */
66 BytesCopied = PacketEntry->PacketLength;
67 if (BytesCopied > IrpSp->Parameters.Read.Length)
68 BytesCopied = IrpSp->Parameters.Read.Length;
69
70 /* Copy the packet */
71 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
72 &PacketEntry->PacketBuffer[0],
73 BytesCopied);
74
75 /* Free the packet entry */
76 ExFreePool(PacketEntry);
77 }
78 else
79 {
80 /* Something failed */
81 BytesCopied = 0;
82 }
83
84 /* Complete the IRP */
85 Irp->IoStatus.Status = Status;
86 Irp->IoStatus.Information = BytesCopied;
87 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
88
89 return Status;
90 }
91
92 NTSTATUS
93 NTAPI
94 NduDispatchWrite(PDEVICE_OBJECT DeviceObject,
95 PIRP Irp)
96 {
97 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
98 PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
99 PNDIS_PACKET Packet;
100 NDIS_STATUS Status;
101 ULONG BytesCopied = 0;
102
103 ASSERT(DeviceObject == GlobalDeviceObject);
104
105 /* Create a packet and buffer descriptor for this user buffer */
106 Packet = CreatePacketFromPoolBuffer(Irp->AssociatedIrp.SystemBuffer,
107 IrpSp->Parameters.Write.Length);
108 if (Packet)
109 {
110 /* Send it via NDIS */
111 NdisSend(&Status,
112 AdapterContext->BindingHandle,
113 Packet);
114
115 /* Wait for the send */
116 if (Status == NDIS_STATUS_PENDING)
117 {
118 KeWaitForSingleObject(&AdapterContext->AsyncEvent,
119 Executive,
120 KernelMode,
121 FALSE,
122 NULL);
123 Status = AdapterContext->AsyncStatus;
124 }
125
126 /* Check if it succeeded */
127 if (Status == NDIS_STATUS_SUCCESS)
128 BytesCopied = IrpSp->Parameters.Write.Length;
129
130 CleanupAndFreePacket(Packet);
131 }
132 else
133 {
134 /* No memory */
135 Status = STATUS_NO_MEMORY;
136 }
137
138 /* Complete the IRP */
139 Irp->IoStatus.Status = Status;
140 Irp->IoStatus.Information = BytesCopied;
141 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
142
143 return Status;
144 }