1 /* $Id: rw.c,v 1.13 2004/05/05 18:30:16 navaraf 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>
13 #include <rosrtl/minmax.h>
19 /* FUNCTIONS *****************************************************************/
22 NpfsRead(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
24 PIO_STACK_LOCATION IoStack
;
25 PFILE_OBJECT FileObject
;
27 PNPFS_DEVICE_EXTENSION DeviceExt
;
38 DPRINT("NpfsRead(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
40 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
41 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
42 FileObject
= IoStack
->FileObject
;
43 Fcb
= FileObject
->FsContext
;
45 ReadFcb
= Fcb
->OtherSide
;
49 DPRINT("Pipe is NOT connected!\n");
50 if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
51 Status
= STATUS_PIPE_LISTENING
;
52 else if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
53 Status
= STATUS_PIPE_DISCONNECTED
;
55 Status
= STATUS_UNSUCCESSFUL
;
60 if (Irp
->MdlAddress
== NULL
)
62 DPRINT("Irp->MdlAddress == NULL\n");
63 Status
= STATUS_UNSUCCESSFUL
;
68 if (ReadFcb
->Data
== NULL
)
70 DPRINT("Pipe is NOT readable!\n");
71 Status
= STATUS_UNSUCCESSFUL
;
77 Status
= STATUS_SUCCESS
;
78 Length
= IoStack
->Parameters
.Read
.Length
;
81 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
82 KeAcquireSpinLock(&ReadFcb
->DataListLock
, &OldIrql
);
85 /* FIXME: check if in blocking mode */
86 if (ReadFcb
->ReadDataAvailable
== 0)
88 KeResetEvent(&Fcb
->Event
);
89 KeSetEvent(&ReadFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
90 KeReleaseSpinLock(&ReadFcb
->DataListLock
, OldIrql
);
93 Status
= STATUS_SUCCESS
;
96 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
98 DPRINT("PipeState: %x\n", Fcb
->PipeState
);
99 Status
= STATUS_PIPE_BROKEN
;
102 /* Wait for ReadEvent to become signaled */
103 DPRINT("Waiting for readable data (%S)\n", Pipe
->PipeName
.Buffer
);
104 Status
= KeWaitForSingleObject(&Fcb
->Event
,
109 DPRINT("Finished waiting (%S)! Status: %x\n", Pipe
->PipeName
.Buffer
, Status
);
110 KeAcquireSpinLock(&ReadFcb
->DataListLock
, &OldIrql
);
113 if (Pipe
->PipeReadMode
== FILE_PIPE_BYTE_STREAM_MODE
)
115 DPRINT("Byte stream mode\n");
116 /* Byte stream mode */
117 while (Length
> 0 && ReadFcb
->ReadDataAvailable
> 0)
119 CopyLength
= RtlRosMin(ReadFcb
->ReadDataAvailable
, Length
);
120 if (ReadFcb
->ReadPtr
+ CopyLength
<= ReadFcb
->Data
+ ReadFcb
->MaxDataLength
)
122 memcpy(Buffer
, ReadFcb
->ReadPtr
, CopyLength
);
123 ReadFcb
->ReadPtr
+= CopyLength
;
124 if (ReadFcb
->ReadPtr
== ReadFcb
->Data
+ ReadFcb
->MaxDataLength
)
126 ReadFcb
->ReadPtr
= ReadFcb
->Data
;
131 TempLength
= ReadFcb
->Data
+ ReadFcb
->MaxDataLength
- ReadFcb
->ReadPtr
;
132 memcpy(Buffer
, ReadFcb
->ReadPtr
, TempLength
);
133 memcpy(Buffer
+ TempLength
, ReadFcb
->Data
, CopyLength
- TempLength
);
134 ReadFcb
->ReadPtr
= ReadFcb
->Data
+ CopyLength
- TempLength
;
137 Buffer
+= CopyLength
;
138 Length
-= CopyLength
;
139 Information
+= CopyLength
;
141 ReadFcb
->ReadDataAvailable
-= CopyLength
;
142 ReadFcb
->WriteQuotaAvailable
+= CopyLength
;
147 KeSetEvent(&ReadFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
153 DPRINT("Message mode\n");
156 if (ReadFcb
->ReadDataAvailable
)
158 /* Truncate the message if the receive buffer is too small */
159 CopyLength
= RtlRosMin(ReadFcb
->ReadDataAvailable
, Length
);
160 memcpy(Buffer
, ReadFcb
->Data
, CopyLength
);
163 DPRINT("Length %d Buffer %x\n",CopyLength
,Buffer
);
165 DbgPrint("------\n");
167 for (X
= 0; X
< CopyLength
; X
++)
168 DbgPrint("%02x ", ((PUCHAR
)Buffer
)[X
]);
170 DbgPrint("------\n");
174 Information
= CopyLength
;
175 ReadFcb
->ReadDataAvailable
= 0;
176 ReadFcb
->WriteQuotaAvailable
= ReadFcb
->MaxDataLength
;
180 KeSetEvent(&ReadFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
185 KeReleaseSpinLock(&ReadFcb
->DataListLock
, OldIrql
);
188 Irp
->IoStatus
.Status
= Status
;
189 Irp
->IoStatus
.Information
= Information
;
191 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
198 NpfsWrite(PDEVICE_OBJECT DeviceObject
,
201 PIO_STACK_LOCATION IoStack
;
202 PFILE_OBJECT FileObject
;
203 PNPFS_FCB Fcb
= NULL
;
204 PNPFS_PIPE Pipe
= NULL
;
206 NTSTATUS Status
= STATUS_SUCCESS
;
214 DPRINT("NpfsWrite()\n");
216 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
217 FileObject
= IoStack
->FileObject
;
218 DPRINT("FileObject %p\n", FileObject
);
219 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
221 Fcb
= FileObject
->FsContext
;
224 Length
= IoStack
->Parameters
.Write
.Length
;
225 Offset
= IoStack
->Parameters
.Write
.ByteOffset
.u
.LowPart
;
228 if (Irp
->MdlAddress
== NULL
)
230 DPRINT("Irp->MdlAddress == NULL\n");
231 Status
= STATUS_UNSUCCESSFUL
;
236 if (Fcb
->OtherSide
== NULL
)
238 DPRINT("Pipe is NOT connected!\n");
239 if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
240 Status
= STATUS_PIPE_LISTENING
;
241 else if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
242 Status
= STATUS_PIPE_DISCONNECTED
;
244 Status
= STATUS_UNSUCCESSFUL
;
249 if (Fcb
->Data
== NULL
)
251 DPRINT("Pipe is NOT writable!\n");
252 Status
= STATUS_UNSUCCESSFUL
;
257 Status
= STATUS_SUCCESS
;
258 Buffer
= MmGetSystemAddressForMdl (Irp
->MdlAddress
);
260 DPRINT("Length %d Buffer %x Offset %x\n",Length
,Buffer
,Offset
);
262 DbgPrint("------\n");
264 for (X
= 0; X
< Length
; X
++)
265 DbgPrint("%02x ", Buffer
[X
]);
267 DbgPrint("------\n");
271 KeAcquireSpinLock(&Fcb
->DataListLock
, &OldIrql
);
274 if (Fcb
->WriteQuotaAvailable
== 0)
276 KeResetEvent(&Fcb
->Event
);
277 KeSetEvent(&Fcb
->OtherSide
->Event
, IO_NO_INCREMENT
, FALSE
);
278 KeReleaseSpinLock(&Fcb
->DataListLock
, OldIrql
);
279 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
281 Status
= STATUS_PIPE_BROKEN
;
284 DPRINT("Waiting for buffer space (%S)\n", Pipe
->PipeName
.Buffer
);
285 Status
= KeWaitForSingleObject(&Fcb
->Event
,
290 DPRINT("Finished waiting (%S)! Status: %x\n", Pipe
->PipeName
.Buffer
, Status
);
291 KeAcquireSpinLock(&Fcb
->DataListLock
, &OldIrql
);
293 if (Pipe
->PipeWriteMode
== FILE_PIPE_BYTE_STREAM_MODE
)
295 DPRINT("Byte stream mode\n");
296 while (Length
> 0 && Fcb
->WriteQuotaAvailable
> 0)
298 CopyLength
= RtlRosMin(Length
, Fcb
->WriteQuotaAvailable
);
299 if (Fcb
->WritePtr
+ CopyLength
<= Fcb
->Data
+ Fcb
->MaxDataLength
)
301 memcpy(Fcb
->WritePtr
, Buffer
, CopyLength
);
302 Fcb
->WritePtr
+= CopyLength
;
303 if (Fcb
->WritePtr
== Fcb
->Data
+ Fcb
->MaxDataLength
)
305 Fcb
->WritePtr
= Fcb
->Data
;
310 TempLength
= Fcb
->Data
+ Fcb
->MaxDataLength
- Fcb
->WritePtr
;
311 memcpy(Fcb
->WritePtr
, Buffer
, TempLength
);
312 memcpy(Fcb
->Data
, Buffer
+ TempLength
, CopyLength
- TempLength
);
313 Fcb
->WritePtr
= Fcb
->Data
+ CopyLength
- TempLength
;
316 Buffer
+= CopyLength
;
317 Length
-= CopyLength
;
318 Information
+= CopyLength
;
320 Fcb
->ReadDataAvailable
+= CopyLength
;
321 Fcb
->WriteQuotaAvailable
-= CopyLength
;
326 KeSetEvent(&Fcb
->OtherSide
->Event
, IO_NO_INCREMENT
, FALSE
);
334 CopyLength
= RtlRosMin(Length
, Fcb
->WriteQuotaAvailable
);
335 memcpy(Fcb
->Data
, Buffer
, CopyLength
);
337 Information
= CopyLength
;
338 Fcb
->ReadDataAvailable
= CopyLength
;
339 Fcb
->WriteQuotaAvailable
= 0;
343 KeSetEvent(&Fcb
->OtherSide
->Event
, IO_NO_INCREMENT
, FALSE
);
348 KeReleaseSpinLock(&Fcb
->DataListLock
, OldIrql
);
351 Irp
->IoStatus
.Status
= Status
;
352 Irp
->IoStatus
.Information
= Information
;
354 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);