ReactOS 0.4.15-dev-7674-gc0b4db1
readwrite.c
Go to the documentation of this file.
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
14static
15VOID
18{
20 PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
21 PNDISUIO_PACKET_ENTRY PacketEntry;
22
23 /* Release the cancel spin lock */
24 IoReleaseCancelSpinLock(Irp->CancelIrql);
25
26 /* Indicate a 0-byte packet on the queue to cancel the read */
27 PacketEntry = ExAllocatePool(NonPagedPool, sizeof(NDISUIO_PACKET_ENTRY));
28 if (PacketEntry)
29 {
30 PacketEntry->PacketLength = 0;
31
33 &PacketEntry->ListEntry,
34 &AdapterContext->Spinlock);
35
37 }
38}
39
43 PIRP Irp)
44{
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;
53
55
56 if (OpenEntry->WriteOnly)
57 {
58 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
59 Irp->IoStatus.Information = 0;
61
63 }
64
65 /* Make the read cancellable */
66 IoAcquireCancelSpinLock(&OldCancelIrql);
68 if (Irp->Cancel)
69 {
70 IoReleaseCancelSpinLock(OldCancelIrql);
71
72 /* Indicate a 0 byte read */
73 Irp->IoStatus.Status = STATUS_SUCCESS;
74 Irp->IoStatus.Information = 0;
76
77 return STATUS_SUCCESS;
78 }
79 IoReleaseCancelSpinLock(OldCancelIrql);
80
81 while (TRUE)
82 {
83 KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
84
85 /* Check if we have a packet */
86 if (IsListEmpty(&AdapterContext->PacketList))
87 {
88 KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
89
90 /* Wait for a packet (in the context of the calling user thread) */
94 TRUE,
95 NULL);
97 {
98 /* Remove the cancel routine */
99 IoAcquireCancelSpinLock(&OldCancelIrql);
101 IoReleaseCancelSpinLock(OldCancelIrql);
102
103 break;
104 }
105 }
106 else
107 {
108 /* Remove the cancel routine */
109 IoAcquireCancelSpinLock(&OldCancelIrql);
111 IoReleaseCancelSpinLock(OldCancelIrql);
112
113 /* Remove the first packet in the list */
114 ListEntry = RemoveHeadList(&AdapterContext->PacketList);
115 PacketEntry = CONTAINING_RECORD(ListEntry, NDISUIO_PACKET_ENTRY, ListEntry);
116
117 /* Release the adapter lock */
118 KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
119
120 /* And we're done with this loop */
122 break;
123 }
124 }
125
126 /* Check if we got a packet */
127 if (PacketEntry != NULL)
128 {
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;
133
134 /* Copy the packet */
135 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
136 &PacketEntry->PacketData[0],
138
139 /* Free the packet entry */
140 ExFreePool(PacketEntry);
141 }
142 else
143 {
144 /* Something failed */
145 BytesCopied = 0;
146 }
147
148 /* Complete the IRP */
149 Irp->IoStatus.Status = Status;
150 Irp->IoStatus.Information = BytesCopied;
152
153 return Status;
154}
155
157NTAPI
159 PIRP Irp)
160{
162 PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
165 ULONG BytesCopied = 0;
166
168
169 /* Create a packet and buffer descriptor for this user buffer */
170 Packet = CreatePacketFromPoolBuffer(AdapterContext,
171 Irp->AssociatedIrp.SystemBuffer,
172 IrpSp->Parameters.Write.Length);
173 if (Packet)
174 {
175 /* Send it via NDIS */
177 AdapterContext->BindingHandle,
178 Packet);
179
180 /* Wait for the send */
182 {
183 KeWaitForSingleObject(&AdapterContext->AsyncEvent,
184 Executive,
186 FALSE,
187 NULL);
188 Status = AdapterContext->AsyncStatus;
189 }
190
191 /* Check if it succeeded */
193 BytesCopied = IrpSp->Parameters.Write.Length;
194
196 }
197 else
198 {
199 /* No memory */
201 }
202
203 /* Complete the IRP */
204 Irp->IoStatus.Status = Status;
205 Irp->IoStatus.Information = BytesCopied;
207
208 return Status;
209}
LONG NTSTATUS
Definition: precomp.h:26
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
VOID EXPORT NdisSend(OUT PNDIS_STATUS Status, IN NDIS_HANDLE NdisBindingHandle, IN PNDIS_PACKET Packet)
Definition: protocol.c:1272
PDEVICE_OBJECT GlobalDeviceObject
Definition: main.c:14
PNDIS_PACKET CreatePacketFromPoolBuffer(PNDISUIO_ADAPTER_CONTEXT AdapterContext, PVOID Buffer, ULONG BufferSize)
Definition: misc.c:52
VOID CleanupAndFreePacket(PNDIS_PACKET Packet, BOOLEAN FreePool)
Definition: misc.c:83
NTSTATUS NTAPI NduDispatchWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: readwrite.c:158
NTSTATUS NTAPI NduDispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: readwrite.c:42
static VOID NTAPI ReadIrpCancel(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: readwrite.c:17
#define IO_NETWORK_INCREMENT
Definition: tcpip.h:43
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
Status
Definition: gdiplustypes.h:25
PLIST_ENTRY NTAPI ExInterlockedInsertHeadList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY ListEntry, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:114
IoSetCancelRoutine(Irp, CancelRoutine)
#define ASSERT(a)
Definition: mode.c:44
#define NDIS_STATUS_PENDING
Definition: ndis.h:347
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
_In_ UINT _In_ UINT _In_ PNDIS_PACKET _In_ UINT _Out_ PUINT BytesCopied
Definition: ndis.h:3171
#define NDIS_STATUS_SUCCESS
Definition: ndis.h:346
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
int NDIS_STATUS
Definition: ntddndis.h:475
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_SUCCESS
Definition: shellext.h:65
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
Definition: typedefs.h:120
NDIS_STATUS AsyncStatus
Definition: ndisuio.h:22
LIST_ENTRY PacketList
Definition: ndisuio.h:37
KSPIN_LOCK Spinlock
Definition: ndisuio.h:50
NDIS_HANDLE BindingHandle
Definition: ndisuio.h:26
Definition: ndisuio.h:54
BOOLEAN WriteOnly
Definition: ndisuio.h:59
Definition: ndisuio.h:66
UCHAR PacketData[1]
Definition: ndisuio.h:74
LIST_ENTRY ListEntry
Definition: ndisuio.h:71
ULONG PacketLength
Definition: ndisuio.h:68
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ UserRequest
Definition: ketypes.h:421
@ Executive
Definition: ketypes.h:415