2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS User I/O driver
5 * PURPOSE: Handles IRP_MJ_READ and IRP_MJ_WRITE
6 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
17 ReadIrpCancel(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
19 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
20 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= IrpSp
->FileObject
->FsContext
;
21 PNDISUIO_PACKET_ENTRY PacketEntry
;
23 /* Release the cancel spin lock */
24 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
26 /* Indicate a 0-byte packet on the queue to cancel the read */
27 PacketEntry
= ExAllocatePool(NonPagedPool
, sizeof(NDISUIO_PACKET_ENTRY
));
30 PacketEntry
->PacketLength
= 0;
32 ExInterlockedInsertHeadList(&AdapterContext
->PacketList
,
33 &PacketEntry
->ListEntry
,
34 &AdapterContext
->Spinlock
);
36 KeSetEvent(&AdapterContext
->PacketReadEvent
, IO_NO_INCREMENT
, FALSE
);
42 NduDispatchRead(PDEVICE_OBJECT DeviceObject
,
45 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
46 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= IrpSp
->FileObject
->FsContext
;
47 PNDISUIO_OPEN_ENTRY OpenEntry
= IrpSp
->FileObject
->FsContext2
;
48 KIRQL OldIrql
, OldCancelIrql
;
50 PLIST_ENTRY ListEntry
;
51 PNDISUIO_PACKET_ENTRY PacketEntry
= NULL
;
52 ULONG BytesCopied
= 0;
54 ASSERT(DeviceObject
== GlobalDeviceObject
);
56 if (OpenEntry
->WriteOnly
)
58 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
59 Irp
->IoStatus
.Information
= 0;
60 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
62 return STATUS_INVALID_PARAMETER
;
65 /* Make the read cancellable */
66 IoAcquireCancelSpinLock(&OldCancelIrql
);
67 IoSetCancelRoutine(Irp
, ReadIrpCancel
);
70 IoReleaseCancelSpinLock(OldCancelIrql
);
72 /* Indicate a 0 byte read */
73 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
74 Irp
->IoStatus
.Information
= 0;
75 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
77 return STATUS_SUCCESS
;
79 IoReleaseCancelSpinLock(OldCancelIrql
);
83 KeAcquireSpinLock(&AdapterContext
->Spinlock
, &OldIrql
);
85 /* Check if we have a packet */
86 if (IsListEmpty(&AdapterContext
->PacketList
))
88 KeReleaseSpinLock(&AdapterContext
->Spinlock
, OldIrql
);
90 /* Wait for a packet (in the context of the calling user thread) */
91 Status
= KeWaitForSingleObject(&AdapterContext
->PacketReadEvent
,
96 if (Status
!= STATUS_SUCCESS
)
98 /* Remove the cancel routine */
99 IoAcquireCancelSpinLock(&OldCancelIrql
);
100 IoSetCancelRoutine(Irp
, NULL
);
101 IoReleaseCancelSpinLock(OldCancelIrql
);
108 /* Remove the cancel routine */
109 IoAcquireCancelSpinLock(&OldCancelIrql
);
110 IoSetCancelRoutine(Irp
, NULL
);
111 IoReleaseCancelSpinLock(OldCancelIrql
);
113 /* Remove the first packet in the list */
114 ListEntry
= RemoveHeadList(&AdapterContext
->PacketList
);
115 PacketEntry
= CONTAINING_RECORD(ListEntry
, NDISUIO_PACKET_ENTRY
, ListEntry
);
117 /* Release the adapter lock */
118 KeReleaseSpinLock(&AdapterContext
->Spinlock
, OldIrql
);
120 /* And we're done with this loop */
121 Status
= STATUS_SUCCESS
;
126 /* Check if we got a packet */
127 if (PacketEntry
!= NULL
)
129 /* Find the right amount of bytes to copy */
130 BytesCopied
= PacketEntry
->PacketLength
;
131 if (BytesCopied
> IrpSp
->Parameters
.Read
.Length
)
132 BytesCopied
= IrpSp
->Parameters
.Read
.Length
;
134 /* Copy the packet */
135 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
136 &PacketEntry
->PacketData
[0],
139 /* Free the packet entry */
140 ExFreePool(PacketEntry
);
144 /* Something failed */
148 /* Complete the IRP */
149 Irp
->IoStatus
.Status
= Status
;
150 Irp
->IoStatus
.Information
= BytesCopied
;
151 IoCompleteRequest(Irp
, IO_NETWORK_INCREMENT
);
158 NduDispatchWrite(PDEVICE_OBJECT DeviceObject
,
161 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
162 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= IrpSp
->FileObject
->FsContext
;
165 ULONG BytesCopied
= 0;
167 ASSERT(DeviceObject
== GlobalDeviceObject
);
169 /* Create a packet and buffer descriptor for this user buffer */
170 Packet
= CreatePacketFromPoolBuffer(AdapterContext
,
171 Irp
->AssociatedIrp
.SystemBuffer
,
172 IrpSp
->Parameters
.Write
.Length
);
175 /* Send it via NDIS */
177 AdapterContext
->BindingHandle
,
180 /* Wait for the send */
181 if (Status
== NDIS_STATUS_PENDING
)
183 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
188 Status
= AdapterContext
->AsyncStatus
;
191 /* Check if it succeeded */
192 if (Status
== NDIS_STATUS_SUCCESS
)
193 BytesCopied
= IrpSp
->Parameters
.Write
.Length
;
195 CleanupAndFreePacket(Packet
, FALSE
);
200 Status
= STATUS_NO_MEMORY
;
203 /* Complete the IRP */
204 Irp
->IoStatus
.Status
= Status
;
205 Irp
->IoStatus
.Information
= BytesCopied
;
206 IoCompleteRequest(Irp
, IO_NETWORK_INCREMENT
);