ReactOS  0.4.13-dev-73-gcfe54aa
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 
14 static
15 VOID
16 NTAPI
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 
32  ExInterlockedInsertHeadList(&AdapterContext->PacketList,
33  &PacketEntry->ListEntry,
34  &AdapterContext->Spinlock);
35 
36  KeSetEvent(&AdapterContext->PacketReadEvent, IO_NO_INCREMENT, FALSE);
37  }
38 }
39 
41 NTAPI
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;
52  ULONG BytesCopied = 0;
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) */
91  Status = KeWaitForSingleObject(&AdapterContext->PacketReadEvent,
93  UserMode,
94  TRUE,
95  NULL);
96  if (Status != STATUS_SUCCESS)
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],
137  BytesCopied);
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 
156 NTSTATUS
157 NTAPI
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 */
176  NdisSend(&Status,
177  AdapterContext->BindingHandle,
178  Packet);
179 
180  /* Wait for the send */
182  {
183  KeWaitForSingleObject(&AdapterContext->AsyncEvent,
184  Executive,
185  KernelMode,
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 }
Definition: ndisuio.h:65
NTSTATUS NTAPI NduDispatchWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: readwrite.c:158
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1530
#define NDIS_STATUS_PENDING
Definition: ndis.h:347
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
KSPIN_LOCK Spinlock
Definition: ndisuio.h:50
VOID CleanupAndFreePacket(PNDIS_PACKET Packet, BOOLEAN FreePool)
Definition: misc.c:83
IoSetCancelRoutine(Irp, CancelRoutine)
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
int NDIS_STATUS
Definition: ntddndis.h:380
UCHAR KIRQL
Definition: env_spec_w32.h:591
PLIST_ENTRY NTAPI ExInterlockedInsertHeadList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY ListEntry, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:114
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
VOID EXPORT NdisSend(OUT PNDIS_STATUS Status, IN NDIS_HANDLE NdisBindingHandle, IN PNDIS_PACKET Packet)
Definition: protocol.c:1270
Definition: ndisuio.h:53
_In_ UINT _In_ UINT _In_ PNDIS_PACKET _In_ UINT _Out_ PUINT BytesCopied
Definition: ndis.h:3149
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
UCHAR PacketData[1]
Definition: ndisuio.h:74
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define IO_NETWORK_INCREMENT
Definition: tcpip.h:43
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
NDIS_STATUS AsyncStatus
Definition: ndisuio.h:22
PNDIS_PACKET CreatePacketFromPoolBuffer(PNDISUIO_ADAPTER_CONTEXT AdapterContext, PVOID Buffer, ULONG BufferSize)
Definition: misc.c:52
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define NDIS_STATUS_SUCCESS
Definition: ndis.h:346
PDEVICE_OBJECT GlobalDeviceObject
Definition: main.c:14
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
Definition: typedefs.h:117
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
Status
Definition: gdiplustypes.h:24
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_OBJECT FileObject
Definition: iotypes.h:2812
NDIS_HANDLE BindingHandle
Definition: ndisuio.h:26
BOOLEAN WriteOnly
Definition: ndisuio.h:59
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
NTSTATUS NTAPI NduDispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: readwrite.c:42
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
static VOID NTAPI ReadIrpCancel(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: readwrite.c:17
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:565
ULONG PacketLength
Definition: ndisuio.h:68
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
return STATUS_SUCCESS
Definition: btrfs.c:2725
LIST_ENTRY PacketList
Definition: ndisuio.h:37
LIST_ENTRY ListEntry
Definition: ndisuio.h:71
#define ExFreePool(addr)
Definition: env_spec_w32.h:352