1 /* $Id: rw.c,v 1.5 2001/11/20 20:34:29 ekohl Exp $
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 *****************************************************************/
22 NpfsFreePipeData(PNPFS_PIPE_DATA PipeData
)
26 ExFreePool(PipeData
->Data
);
29 ExFreeToNPagedLookasideList(&NpfsPipeDataLookasideList
, PipeData
);
33 static inline PNPFS_PIPE_DATA
34 NpfsAllocatePipeData(PVOID Data
,
37 PNPFS_PIPE_DATA PipeData
;
39 PipeData
= ExAllocateFromNPagedLookasideList(&NpfsPipeDataLookasideList
);
45 PipeData
->Data
= Data
;
46 PipeData
->Size
= Size
;
53 static inline PNPFS_PIPE_DATA
54 NpfsInitializePipeData(
58 PNPFS_PIPE_DATA PipeData
;
61 Buffer
= ExAllocatePool(NonPagedPool
, Size
);
67 RtlMoveMemory(Buffer
, Data
, Size
);
69 PipeData
= NpfsAllocatePipeData(Buffer
, Size
);
80 NpfsRead(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
82 PIO_STACK_LOCATION IoStack
;
83 PFILE_OBJECT FileObject
;
85 PNPFS_DEVICE_EXTENSION DeviceExt
;
88 PLIST_ENTRY CurrentEntry
;
89 PNPFS_PIPE_DATA Current
;
97 BOOLEAN DataListEmpty
;
99 DPRINT("NpfsRead(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
101 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
102 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
103 FileObject
= IoStack
->FileObject
;
104 Fcb
= FileObject
->FsContext
;
106 ReadFcb
= Fcb
->OtherSide
;
110 DPRINT("Pipe is NOT connected!\n");
111 Status
= STATUS_UNSUCCESSFUL
;
116 if (Irp
->MdlAddress
== NULL
)
118 DPRINT("Irp->MdlAddress == NULL\n");
119 Status
= STATUS_UNSUCCESSFUL
;
124 Status
= STATUS_SUCCESS
;
125 Length
= IoStack
->Parameters
.Read
.Length
;
127 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
128 DPRINT("Length %d Buffer %x\n",Length
,Buffer
);
130 KeAcquireSpinLock(&ReadFcb
->DataListLock
, &OldIrql
);
131 DataListEmpty
= IsListEmpty(&ReadFcb
->DataListHead
);
132 KeReleaseSpinLock(&ReadFcb
->DataListLock
, OldIrql
);
134 /* FIXME: check if in blocking mode */
135 if (DataListEmpty
== TRUE
)
137 /* Wait for ReadEvent to become signaled */
138 DPRINT("Waiting for readable data\n");
139 Status
= KeWaitForSingleObject(&Fcb
->ReadEvent
,
144 DPRINT("Finished waiting! Status: %x\n", Status
);
147 KeAcquireSpinLock(&ReadFcb
->DataListLock
, &OldIrql
);
149 if (Pipe
->PipeReadMode
& FILE_PIPE_BYTE_STREAM_MODE
)
151 DPRINT("Byte stream mode\n");
153 /* Byte stream mode */
155 CurrentEntry
= ReadFcb
->DataListHead
.Flink
;
156 while ((Length
> 0) && (CurrentEntry
= RemoveHeadList(&ReadFcb
->DataListHead
)))
158 Current
= CONTAINING_RECORD(CurrentEntry
, NPFS_PIPE_DATA
, ListEntry
);
160 DPRINT("Took pipe data at %p off the queue\n", Current
);
162 CopyLength
= RtlMin(Current
->Size
, Length
);
163 RtlCopyMemory(Buffer
,
164 ((PVOID
)((ULONG_PTR
)Current
->Data
+ Current
->Offset
)),
166 Buffer
+= CopyLength
;
167 Length
-= CopyLength
;
168 Information
+= CopyLength
;
170 /* Update the data buffer */
171 Current
->Offset
+= CopyLength
;
172 Current
->Size
-= CopyLength
;
174 CurrentEntry
= CurrentEntry
->Flink
;
177 if ((CurrentEntry
!= &ReadFcb
->DataListHead
) && (Current
->Offset
!= Current
->Size
))
179 DPRINT("Putting pipe data at %p back in queue\n", Current
);
181 /* The caller's buffer could not contain the complete message,
182 so put it back on the queue */
183 InsertHeadList(&ReadFcb
->DataListHead
, &Current
->ListEntry
);
188 DPRINT("Message mode\n");
191 CurrentEntry
= ReadFcb
->DataListHead
.Flink
;
192 if (CurrentEntry
= RemoveHeadList(&ReadFcb
->DataListHead
))
194 Current
= CONTAINING_RECORD(CurrentEntry
, NPFS_PIPE_DATA
, ListEntry
);
196 DPRINT("Took pipe data at %p off the queue\n", Current
);
198 /* Truncate the message if the receive buffer is too small */
199 CopyLength
= RtlMin(Current
->Size
, Length
);
200 RtlCopyMemory(Buffer
, Current
->Data
, CopyLength
);
201 Information
= CopyLength
;
203 Current
->Offset
+= CopyLength
;
205 CurrentEntry
= CurrentEntry
->Flink
;
209 KeReleaseSpinLock(&ReadFcb
->DataListLock
, OldIrql
);
211 /* reset ReaderEvent */
212 KeResetEvent(&Fcb
->ReadEvent
);
215 Irp
->IoStatus
.Status
= Status
;
216 Irp
->IoStatus
.Information
= Information
;
218 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
225 NpfsWrite(PDEVICE_OBJECT DeviceObject
,
228 PIO_STACK_LOCATION IoStack
;
229 PFILE_OBJECT FileObject
;
230 PNPFS_FCB Fcb
= NULL
;
231 PNPFS_PIPE Pipe
= NULL
;
233 NTSTATUS Status
= STATUS_SUCCESS
;
237 PNPFS_PIPE_DATA PipeData
;
239 DPRINT("NpfsWrite()\n");
241 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
242 FileObject
= IoStack
->FileObject
;
243 DPRINT("FileObject %p\n", FileObject
);
244 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
246 Fcb
= FileObject
->FsContext
;
249 Length
= IoStack
->Parameters
.Write
.Length
;
250 Offset
= IoStack
->Parameters
.Write
.ByteOffset
.u
.LowPart
;
252 if (Irp
->MdlAddress
== NULL
)
254 DbgPrint ("Irp->MdlAddress == NULL\n");
255 Status
= STATUS_UNSUCCESSFUL
;
260 if (Fcb
->OtherSide
== NULL
)
262 DPRINT("Pipe is NOT connected!\n");
263 Status
= STATUS_UNSUCCESSFUL
;
268 Buffer
= MmGetSystemAddressForMdl (Irp
->MdlAddress
);
269 DPRINT("Length %d Buffer %x Offset %x\n",Length
,Buffer
,Offset
);
271 PipeData
= NpfsInitializePipeData(Buffer
, Length
);
274 DPRINT("Attaching pipe data at %p (%d bytes)\n", PipeData
, Length
);
276 KeAcquireSpinLock(&Fcb
->DataListLock
, &OldIrql
);
277 InsertTailList(&Fcb
->DataListHead
, &PipeData
->ListEntry
);
278 KeReleaseSpinLock(&Fcb
->DataListLock
, OldIrql
);
280 /* signal the readers ReadEvent */
281 KeSetEvent(&Fcb
->OtherSide
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
286 Status
= STATUS_INSUFFICIENT_RESOURCES
;
290 Irp
->IoStatus
.Status
= Status
;
291 Irp
->IoStatus
.Information
= Length
;
293 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);