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>
10 /* INCLUDES ******************************************************************/
12 #include <ddk/ntddk.h>
19 /* FUNCTIONS *****************************************************************/
21 static inline PNPFS_PIPE_DATA
22 NpfsAllocatePipeData(PVOID Data,
25 PNPFS_PIPE_DATA PipeData;
27 PipeData = ExAllocateFromNPagedLookasideList(&NpfsPipeDataLookasideList);
33 PipeData->Data = Data;
34 PipeData->Size = Size;
41 static inline PNPFS_PIPE_DATA
42 NpfsInitializePipeData(
46 PNPFS_PIPE_DATA PipeData;
49 Buffer = ExAllocatePool(NonPagedPool, Size);
55 RtlMoveMemory(Buffer, Data, Size);
57 PipeData = NpfsAllocatePipeData(Buffer, Size);
68 NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
70 PIO_STACK_LOCATION IoStack;
71 PFILE_OBJECT FileObject;
73 PNPFS_DEVICE_EXTENSION DeviceExt;
76 PLIST_ENTRY CurrentEntry;
77 PNPFS_PIPE_DATA Current;
86 DPRINT("NpfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
88 DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
89 IoStack = IoGetCurrentIrpStackLocation(Irp);
90 FileObject = IoStack->FileObject;
91 Fcb = FileObject->FsContext;
93 ReadFcb = Fcb->OtherSide;
97 DPRINT("Pipe is NOT connected!\n");
98 Status = STATUS_UNSUCCESSFUL;
103 if (Irp->MdlAddress == NULL)
105 DPRINT("Irp->MdlAddress == NULL\n");
106 Status = STATUS_UNSUCCESSFUL;
111 Status = STATUS_SUCCESS;
112 Length = IoStack->Parameters.Read.Length;
115 Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
116 DPRINT("Length %d Buffer %x\n",Length,Buffer);
118 KeAcquireSpinLock(&ReadFcb->DataListLock, &OldIrql);
121 /* FIXME: check if in blocking mode */
122 if (IsListEmpty(&ReadFcb->DataListHead))
124 KeResetEvent(&Fcb->ReadEvent);
125 KeReleaseSpinLock(&ReadFcb->DataListLock, OldIrql);
128 Status = STATUS_SUCCESS;
131 if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
133 Status = STATUS_PIPE_BROKEN;
136 /* Wait for ReadEvent to become signaled */
137 DPRINT("Waiting for readable data (%S)\n", Pipe->PipeName.Buffer);
138 Status = KeWaitForSingleObject(&Fcb->ReadEvent,
143 DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status);
144 KeAcquireSpinLock(&ReadFcb->DataListLock, &OldIrql);
147 if (Pipe->PipeReadMode == FILE_PIPE_BYTE_STREAM_MODE)
149 DPRINT("Byte stream mode\n");
151 /* Byte stream mode */
153 while (Length > 0 && !IsListEmpty(&ReadFcb->DataListHead))
155 CurrentEntry = RemoveHeadList(&ReadFcb->DataListHead);
156 Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry);
158 DPRINT("Took pipe data at %p off the queue\n", Current);
160 CopyLength = RtlMin(Current->Size, Length);
161 RtlCopyMemory(Buffer,
162 ((PVOID)((PVOID)Current->Data + Current->Offset)),
164 Buffer += CopyLength;
165 Length -= CopyLength;
166 Information += CopyLength;
168 /* Update the data buffer */
169 Current->Offset += CopyLength;
170 Current->Size -= CopyLength;
171 if (Current->Size == 0)
173 NpfsFreePipeData(Current);
178 if (CurrentEntry && Current->Size > 0)
180 DPRINT("Putting pipe data at %p back in queue\n", Current);
182 /* The caller's buffer could not contain the complete message,
183 so put it back on the queue */
184 InsertHeadList(&ReadFcb->DataListHead, &Current->ListEntry);
194 DPRINT("Message mode\n");
197 if (!IsListEmpty(&ReadFcb->DataListHead))
199 CurrentEntry = RemoveHeadList(&ReadFcb->DataListHead);
200 Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry);
202 DPRINT("Took pipe data at %p off the queue\n", Current);
204 /* Truncate the message if the receive buffer is too small */
205 CopyLength = RtlMin(Current->Size, Length);
206 RtlCopyMemory(Buffer, Current->Data, CopyLength);
207 Information = CopyLength;
209 Current->Offset += CopyLength;
210 NpfsFreePipeData(Current);
218 /* reset ReaderEvent */
219 KeReleaseSpinLock(&ReadFcb->DataListLock, OldIrql);
223 Irp->IoStatus.Status = Status;
224 Irp->IoStatus.Information = Information;
226 IoCompleteRequest(Irp, IO_NO_INCREMENT);
233 NpfsWrite(PDEVICE_OBJECT DeviceObject,
236 PIO_STACK_LOCATION IoStack;
237 PFILE_OBJECT FileObject;
238 PNPFS_FCB Fcb = NULL;
239 PNPFS_PIPE Pipe = NULL;
241 NTSTATUS Status = STATUS_SUCCESS;
245 PNPFS_PIPE_DATA PipeData;
247 DPRINT("NpfsWrite()\n");
249 IoStack = IoGetCurrentIrpStackLocation(Irp);
250 FileObject = IoStack->FileObject;
251 DPRINT("FileObject %p\n", FileObject);
252 DPRINT("Pipe name %wZ\n", &FileObject->FileName);
254 Fcb = FileObject->FsContext;
257 Length = IoStack->Parameters.Write.Length;
258 Offset = IoStack->Parameters.Write.ByteOffset.u.LowPart;
260 if (Irp->MdlAddress == NULL)
262 DbgPrint ("Irp->MdlAddress == NULL\n");
263 Status = STATUS_UNSUCCESSFUL;
268 if (Fcb->OtherSide == NULL)
270 DPRINT("Pipe is NOT connected!\n");
271 Status = STATUS_UNSUCCESSFUL;
276 Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress);
277 DPRINT("Length %d Buffer %x Offset %x\n",Length,Buffer,Offset);
279 PipeData = NpfsInitializePipeData(Buffer, Length);
282 DPRINT("Attaching pipe data at %p (%d bytes)\n", PipeData, Length);
284 KeAcquireSpinLock(&Fcb->DataListLock, &OldIrql);
285 InsertTailList(&Fcb->DataListHead, &PipeData->ListEntry);
287 /* signal the readers ReadEvent */
288 KeSetEvent(&Fcb->OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
290 KeReleaseSpinLock(&Fcb->DataListLock, OldIrql);
296 Status = STATUS_INSUFFICIENT_RESOURCES;
300 Irp->IoStatus.Status = Status;
301 Irp->IoStatus.Information = Length;
303 IoCompleteRequest(Irp, IO_NO_INCREMENT);