21882b34c7e6ce75db996e36747ede753101a327
[reactos.git] / reactos / drivers / fs / np / rw.c
1 /* $Id: rw.c,v 1.4 2001/10/21 18:58:32 chorns Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/fs/np/rw.c
6 * PURPOSE: Named pipe filesystem
7 * PROGRAMMER: David Welch <welch@cwcom.net>
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ddk/ntddk.h>
13 #include "npfs.h"
14
15 #define NDEBUG
16 #include <debug.h>
17
18
19 /* FUNCTIONS *****************************************************************/
20
21 static inline VOID NpfsFreePipeData(
22 PNPFS_PIPE_DATA PipeData)
23 {
24 if (PipeData->Data)
25 {
26 ExFreePool(PipeData->Data);
27 }
28
29 ExFreeToNPagedLookasideList(&NpfsPipeDataLookasideList, PipeData);
30 }
31
32
33 static inline PNPFS_PIPE_DATA
34 NpfsAllocatePipeData(
35 PVOID Data,
36 ULONG Size)
37 {
38 PNPFS_PIPE_DATA PipeData;
39
40 PipeData = ExAllocateFromNPagedLookasideList(&NpfsPipeDataLookasideList);
41 if (!PipeData)
42 {
43 return NULL;
44 }
45
46 PipeData->Data = Data;
47 PipeData->Size = Size;
48 PipeData->Offset = 0;
49
50 return PipeData;
51 }
52
53
54 static inline PNPFS_PIPE_DATA
55 NpfsInitializePipeData(
56 PVOID Data,
57 ULONG Size)
58 {
59 PNPFS_PIPE_DATA PipeData;
60 PVOID Buffer;
61
62 Buffer = ExAllocatePool(NonPagedPool, Size);
63 if (!Buffer)
64 {
65 return NULL;
66 }
67
68 RtlMoveMemory(Buffer, Data, Size);
69
70 PipeData = NpfsAllocatePipeData(Buffer, Size);
71 if (!PipeData)
72 {
73 ExFreePool(Buffer);
74 }
75
76 return PipeData;
77 }
78
79
80 NTSTATUS STDCALL
81 NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
82 {
83 PIO_STACK_LOCATION IoStack;
84 PFILE_OBJECT FileObject;
85 NTSTATUS Status;
86 PNPFS_DEVICE_EXTENSION DeviceExt;
87 PWSTR PipeName;
88 KIRQL OldIrql;
89 PLIST_ENTRY CurrentEntry;
90 PNPFS_PIPE_DATA Current;
91 ULONG Information;
92 PNPFS_FCB Fcb;
93 PNPFS_PIPE Pipe;
94 ULONG Length;
95 PVOID Buffer;
96 ULONG CopyLength;
97
98 DPRINT("NpfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
99
100 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
101 IoStack = IoGetCurrentIrpStackLocation(Irp);
102 FileObject = IoStack->FileObject;
103 Fcb = FileObject->FsContext;
104 Pipe = Fcb->Pipe;
105 Status = STATUS_SUCCESS;
106 Length = IoStack->Parameters.Read.Length;
107
108 DPRINT("Irp->MdlAddress %p\n", Irp->MdlAddress);
109
110 Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
111 KeAcquireSpinLock(&Pipe->ServerDataListLock, &OldIrql);
112
113 if (Pipe->PipeReadMode & FILE_PIPE_BYTE_STREAM_MODE)
114 {
115 DPRINT("Byte stream mode\n");
116
117 /* Byte stream mode */
118 Information = 0;
119 CurrentEntry = Pipe->ServerDataListHead.Flink;
120 while ((Length > 0) && (CurrentEntry = RemoveHeadList(&Pipe->ServerDataListHead)))
121 {
122 Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry);
123
124 DPRINT("Took pipe data at %p off the queue\n", Current);
125
126 CopyLength = RtlMin(Current->Size, Length);
127 RtlCopyMemory(Buffer,
128 ((PVOID)((ULONG_PTR)Current->Data + Current->Offset)),
129 CopyLength);
130 Buffer += CopyLength;
131 Length -= CopyLength;
132 Information += CopyLength;
133
134 /* Update the data buffer */
135 Current->Offset += CopyLength;
136 Current->Size -= CopyLength;
137
138 CurrentEntry = CurrentEntry->Flink;
139 }
140
141 if ((CurrentEntry != &Pipe->ServerDataListHead) && (Current->Offset != Current->Size))
142 {
143 DPRINT("Putting pipe data at %p back in queue\n", Current);
144
145 /* The caller's buffer could not contain the complete message,
146 so put it back on the queue */
147 InsertHeadList(&Pipe->ServerDataListHead, &Current->ListEntry);
148 }
149 }
150 else
151 {
152 DPRINT("Message mode\n");
153
154 /* Message mode */
155 CurrentEntry = Pipe->ServerDataListHead.Flink;
156 if (CurrentEntry = RemoveHeadList(&Pipe->ServerDataListHead))
157 {
158 Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry);
159
160 DPRINT("Took pipe data at %p off the queue\n", Current);
161
162 /* Truncate the message if the receive buffer is too small */
163 CopyLength = RtlMin(Current->Size, Length);
164 RtlCopyMemory(Buffer, Current->Data, CopyLength);
165 Information = CopyLength;
166
167 Current->Offset += CopyLength;
168
169 CurrentEntry = CurrentEntry->Flink;
170 }
171 }
172
173 KeReleaseSpinLock(&Pipe->ServerDataListLock, OldIrql);
174
175 Irp->IoStatus.Status = Status;
176 Irp->IoStatus.Information = Information;
177
178 IoCompleteRequest(Irp, IO_NO_INCREMENT);
179
180 return(Status);
181 }
182
183
184 NTSTATUS STDCALL
185 NpfsWrite(PDEVICE_OBJECT DeviceObject,
186 PIRP Irp)
187 {
188 PIO_STACK_LOCATION IoStack;
189 PFILE_OBJECT FileObject;
190 PNPFS_FCB Fcb = NULL;
191 PNPFS_PIPE Pipe = NULL;
192 PUCHAR Buffer;
193 NTSTATUS Status = STATUS_SUCCESS;
194 ULONG Length;
195 ULONG Offset;
196 KIRQL OldIrql;
197 PNPFS_PIPE_DATA PipeData;
198
199 DPRINT("NpfsWrite()\n");
200
201 IoStack = IoGetCurrentIrpStackLocation(Irp);
202 FileObject = IoStack->FileObject;
203 DPRINT("FileObject %p\n", FileObject);
204 DPRINT("Pipe name %wZ\n", &FileObject->FileName);
205
206 Fcb = FileObject->FsContext;
207 Pipe = Fcb->Pipe;
208
209 Length = IoStack->Parameters.Write.Length;
210 Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress);
211 Offset = IoStack->Parameters.Write.ByteOffset.u.LowPart;
212
213 PipeData = NpfsInitializePipeData(Buffer, Length);
214 if (PipeData)
215 {
216 DPRINT("Attaching pipe data at %p (%d bytes)\n", PipeData, Length);
217
218 KeAcquireSpinLock(&Pipe->ServerDataListLock, &OldIrql);
219
220 InsertTailList(&Pipe->ServerDataListHead, &PipeData->ListEntry);
221
222 KeReleaseSpinLock(&Pipe->ServerDataListLock, OldIrql);
223 }
224 else
225 {
226 Length = 0;
227 Status = STATUS_INSUFFICIENT_RESOURCES;
228 }
229
230 Irp->IoStatus.Status = Status;
231 Irp->IoStatus.Information = Length;
232
233 IoCompleteRequest(Irp, IO_NO_INCREMENT);
234
235 return(Status);
236 }
237
238 /* EOF */