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)
16 ReadIrpCancel(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
18 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= IrpSp
->FileObject
->FsContext
;
19 PNDISUIO_PACKET_ENTRY PacketEntry
;
21 /* Release the cancel spin lock */
22 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
24 /* Indicate a 0-byte packet on the queue to cancel the read */
25 PacketEntry
= ExAllocatePool(PagedPool
, sizeof(NDISUIO_PACKET_ENTRY
));
28 PacketEntry
->PacketLength
= 0;
30 ExInterlockedInsertHeadList(&AdapterContext
->PacketList
,
31 &PacketEntry
->ListEntry
,
32 &AdapterContext
->Spinlock
);
34 KeSetEvent(&AdapterContext
->PacketReadEvent
, IO_NO_INCREMENT
, FALSE
);
40 NduDispatchRead(PDEVICE_OBJECT DeviceObject
,
43 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
44 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= IrpSp
->FileObject
->FsContext
;
45 PNDISUIO_OPEN_ENTRY OpenEntry
= IrpSp
->FileObject
->FsContext2
;
46 KIRQL OldIrql
, OldCancelIrql
;
48 PLIST_ENTRY ListEntry
;
49 PNDISUIO_PACKET_ENTRY PacketEntry
= NULL
;
50 ULONG BytesCopied
= 0;
52 ASSERT(DeviceObject
== GlobalDeviceObject
);
54 if (OpenEntry
->WriteOnly
)
56 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
57 Irp
->IoStatus
.Information
= 0;
58 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
60 return STATUS_INVALID_PARAMETER
;
63 /* Make the read cancellable */
64 IoAcquireCancelSpinLock(&OldCancelIrql
);
65 IoSetCancelRoutine(Irp
, ReadIrpCancel
);
68 IoReleaseCancelSpinLock(OldCancelIrql
);
70 /* Indicate a 0 byte read */
71 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
72 Irp
->IoStatus
.Information
= 0;
73 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
75 return STATUS_SUCCESS
;
77 IoReleaseCancelSpinLock(OldCancelIrql
);
81 KeAcquireSpinLock(&AdapterContext
->Spinlock
, &OldIrql
);
83 /* Check if we have a packet */
84 if (IsListEmpty(&AdapterContext
->PacketList
))
86 KeReleaseSpinLock(&AdapterContext
->Spinlock
, OldIrql
);
88 /* Wait for a packet (in the context of the calling user thread) */
89 Status
= KeWaitForSingleObject(&AdapterContext
->PacketReadEvent
,
94 if (Status
!= STATUS_SUCCESS
)
96 /* Remove the cancel routine */
97 IoAcquireCancelSpinLock(&OldCancelIrql
);
98 IoSetCancelRoutine(Irp
, NULL
);
99 IoReleaseCancelSpinLock(OldCancelIrql
);
106 /* Remove the cancel routine */
107 IoAcquireCancelSpinLock(&OldCancelIrql
);
108 IoSetCancelRoutine(Irp
, NULL
);
109 IoReleaseCancelSpinLock(OldCancelIrql
);
111 /* Remove the first packet in the list */
112 ListEntry
= RemoveHeadList(&AdapterContext
->PacketList
);
113 PacketEntry
= CONTAINING_RECORD(ListEntry
, NDISUIO_PACKET_ENTRY
, ListEntry
);
115 /* Release the adapter lock */
116 KeReleaseSpinLock(&AdapterContext
->Spinlock
, OldIrql
);
118 /* And we're done with this loop */
119 Status
= STATUS_SUCCESS
;
124 /* Check if we got a packet */
125 if (PacketEntry
!= NULL
)
127 /* Find the right amount of bytes to copy */
128 BytesCopied
= PacketEntry
->PacketLength
;
129 if (BytesCopied
> IrpSp
->Parameters
.Read
.Length
)
130 BytesCopied
= IrpSp
->Parameters
.Read
.Length
;
132 /* Copy the packet */
133 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
134 &PacketEntry
->PacketBuffer
[0],
137 /* Free the packet entry */
138 ExFreePool(PacketEntry
);
142 /* Something failed */
146 /* Complete the IRP */
147 Irp
->IoStatus
.Status
= Status
;
148 Irp
->IoStatus
.Information
= BytesCopied
;
149 IoCompleteRequest(Irp
, IO_NETWORK_INCREMENT
);
156 NduDispatchWrite(PDEVICE_OBJECT DeviceObject
,
159 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
160 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= IrpSp
->FileObject
->FsContext
;
163 ULONG BytesCopied
= 0;
165 ASSERT(DeviceObject
== GlobalDeviceObject
);
167 /* Create a packet and buffer descriptor for this user buffer */
168 Packet
= CreatePacketFromPoolBuffer(Irp
->AssociatedIrp
.SystemBuffer
,
169 IrpSp
->Parameters
.Write
.Length
);
172 /* Send it via NDIS */
174 AdapterContext
->BindingHandle
,
177 /* Wait for the send */
178 if (Status
== NDIS_STATUS_PENDING
)
180 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
185 Status
= AdapterContext
->AsyncStatus
;
188 /* Check if it succeeded */
189 if (Status
== NDIS_STATUS_SUCCESS
)
190 BytesCopied
= IrpSp
->Parameters
.Write
.Length
;
192 CleanupAndFreePacket(Packet
);
197 Status
= STATUS_NO_MEMORY
;
200 /* Complete the IRP */
201 Irp
->IoStatus
.Status
= Status
;
202 Irp
->IoStatus
.Information
= BytesCopied
;
203 IoCompleteRequest(Irp
, IO_NETWORK_INCREMENT
);