3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: drivers/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 VOID
HexDump(PUCHAR Buffer
, ULONG Length
)
26 const char Hex
[] = "0123456789ABCDEF";
29 DbgPrint("---------------\n");
31 for (i
= 0; i
< ROUND_UP(Length
, 16); i
+= 16)
33 memset(Line
, ' ', 64);
36 for (j
= 0; j
< 16 && j
+ i
< Length
; j
++)
39 Line
[3*j
+ 0] = Hex
[ch
>> 4];
40 Line
[3*j
+ 1] = Hex
[ch
& 0x0f];
41 Line
[48 + j
] = isprint(ch
) ? ch
: '.';
43 DbgPrint("%s\n", Line
);
45 DbgPrint("---------------\n");
51 NpfsRead(PDEVICE_OBJECT DeviceObject
,
54 PIO_STACK_LOCATION IoStack
;
55 PFILE_OBJECT FileObject
;
57 PNPFS_DEVICE_EXTENSION DeviceExt
;
68 DPRINT("NpfsRead(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
70 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
71 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
72 FileObject
= IoStack
->FileObject
;
73 Fcb
= FileObject
->FsContext
;
75 WriterFcb
= Fcb
->OtherSide
;
77 if (Irp
->MdlAddress
== NULL
)
79 DPRINT("Irp->MdlAddress == NULL\n");
80 Status
= STATUS_UNSUCCESSFUL
;
85 if (Fcb
->Data
== NULL
)
87 DPRINT("Pipe is NOT readable!\n");
88 Status
= STATUS_UNSUCCESSFUL
;
93 Status
= STATUS_SUCCESS
;
94 Length
= IoStack
->Parameters
.Read
.Length
;
97 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
98 KeAcquireSpinLock(&Fcb
->DataListLock
, &OldIrql
);
101 /* FIXME: check if in blocking mode */
102 if (Fcb
->ReadDataAvailable
== 0)
104 KeResetEvent(&Fcb
->Event
);
105 KeSetEvent(&WriterFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
106 KeReleaseSpinLock(&Fcb
->DataListLock
, OldIrql
);
109 Status
= STATUS_SUCCESS
;
113 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
115 DPRINT("PipeState: %x\n", Fcb
->PipeState
);
116 Status
= STATUS_PIPE_BROKEN
;
120 /* Wait for ReadEvent to become signaled */
121 DPRINT("Waiting for readable data (%S)\n", Pipe
->PipeName
.Buffer
);
122 Status
= KeWaitForSingleObject(&Fcb
->Event
,
127 DPRINT("Finished waiting (%S)! Status: %x\n", Pipe
->PipeName
.Buffer
, Status
);
129 KeAcquireSpinLock(&Fcb
->DataListLock
, &OldIrql
);
132 if (Pipe
->ReadMode
== FILE_PIPE_BYTE_STREAM_MODE
)
134 DPRINT("Byte stream mode\n");
135 /* Byte stream mode */
136 while (Length
> 0 && Fcb
->ReadDataAvailable
> 0)
138 CopyLength
= RtlRosMin(Fcb
->ReadDataAvailable
, Length
);
139 if (Fcb
->ReadPtr
+ CopyLength
<= Fcb
->Data
+ Fcb
->MaxDataLength
)
141 memcpy(Buffer
, Fcb
->ReadPtr
, CopyLength
);
142 Fcb
->ReadPtr
+= CopyLength
;
143 if (Fcb
->ReadPtr
== Fcb
->Data
+ Fcb
->MaxDataLength
)
145 Fcb
->ReadPtr
= Fcb
->Data
;
150 TempLength
= Fcb
->Data
+ Fcb
->MaxDataLength
- Fcb
->ReadPtr
;
151 memcpy(Buffer
, Fcb
->ReadPtr
, TempLength
);
152 memcpy(Buffer
+ TempLength
, Fcb
->Data
, CopyLength
- TempLength
);
153 Fcb
->ReadPtr
= Fcb
->Data
+ CopyLength
- TempLength
;
156 Buffer
+= CopyLength
;
157 Length
-= CopyLength
;
158 Information
+= CopyLength
;
160 Fcb
->ReadDataAvailable
-= CopyLength
;
161 Fcb
->WriteQuotaAvailable
+= CopyLength
;
166 KeSetEvent(&WriterFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
172 DPRINT("Message mode\n");
175 if (Fcb
->ReadDataAvailable
)
177 /* Truncate the message if the receive buffer is too small */
178 CopyLength
= RtlRosMin(Fcb
->ReadDataAvailable
, Length
);
179 memcpy(Buffer
, Fcb
->Data
, CopyLength
);
182 DPRINT("Length %d Buffer %x\n",CopyLength
,Buffer
);
183 HexDump((PUCHAR
)Buffer
, CopyLength
);
186 Information
= CopyLength
;
187 Fcb
->ReadDataAvailable
= 0;
188 Fcb
->WriteQuotaAvailable
= Fcb
->MaxDataLength
;
193 KeSetEvent(&WriterFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
199 KeReleaseSpinLock(&Fcb
->DataListLock
, OldIrql
);
202 Irp
->IoStatus
.Status
= Status
;
203 Irp
->IoStatus
.Information
= Information
;
205 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
207 DPRINT("NpfsRead done (Status %lx)\n", Status
);
214 NpfsWrite(PDEVICE_OBJECT DeviceObject
,
217 PIO_STACK_LOCATION IoStack
;
218 PFILE_OBJECT FileObject
;
219 PNPFS_FCB Fcb
= NULL
;
221 PNPFS_PIPE Pipe
= NULL
;
223 NTSTATUS Status
= STATUS_SUCCESS
;
231 DPRINT("NpfsWrite()\n");
233 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
234 FileObject
= IoStack
->FileObject
;
235 DPRINT("FileObject %p\n", FileObject
);
236 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
238 Fcb
= FileObject
->FsContext
;
239 ReaderFcb
= Fcb
->OtherSide
;
242 Length
= IoStack
->Parameters
.Write
.Length
;
243 Offset
= IoStack
->Parameters
.Write
.ByteOffset
.u
.LowPart
;
246 if (Irp
->MdlAddress
== NULL
)
248 DPRINT("Irp->MdlAddress == NULL\n");
249 Status
= STATUS_UNSUCCESSFUL
;
254 if (ReaderFcb
== NULL
)
256 DPRINT("Pipe is NOT connected!\n");
257 if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
258 Status
= STATUS_PIPE_LISTENING
;
259 else if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
260 Status
= STATUS_PIPE_DISCONNECTED
;
262 Status
= STATUS_UNSUCCESSFUL
;
267 if (ReaderFcb
->Data
== NULL
)
269 DPRINT("Pipe is NOT writable!\n");
270 Status
= STATUS_UNSUCCESSFUL
;
275 Status
= STATUS_SUCCESS
;
276 Buffer
= MmGetSystemAddressForMdl (Irp
->MdlAddress
);
278 KeAcquireSpinLock(&ReaderFcb
->DataListLock
, &OldIrql
);
280 DPRINT("Length %d Buffer %x Offset %x\n",Length
,Buffer
,Offset
);
281 HexDump(Buffer
, Length
);
286 if (ReaderFcb
->WriteQuotaAvailable
== 0)
288 KeResetEvent(&Fcb
->Event
);
289 KeSetEvent(&ReaderFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
290 KeReleaseSpinLock(&ReaderFcb
->DataListLock
, OldIrql
);
291 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
293 Status
= STATUS_PIPE_BROKEN
;
297 DPRINT("Waiting for buffer space (%S)\n", Pipe
->PipeName
.Buffer
);
298 Status
= KeWaitForSingleObject(&Fcb
->Event
,
303 DPRINT("Finished waiting (%S)! Status: %x\n", Pipe
->PipeName
.Buffer
, Status
);
306 * It's possible that the event was signaled because the
307 * other side of pipe was closed.
309 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
311 DPRINT("PipeState: %x\n", Fcb
->PipeState
);
312 Status
= STATUS_PIPE_BROKEN
;
315 KeAcquireSpinLock(&ReaderFcb
->DataListLock
, &OldIrql
);
318 if (Pipe
->WriteMode
== FILE_PIPE_BYTE_STREAM_MODE
)
320 DPRINT("Byte stream mode\n");
321 while (Length
> 0 && ReaderFcb
->WriteQuotaAvailable
> 0)
323 CopyLength
= RtlRosMin(Length
, ReaderFcb
->WriteQuotaAvailable
);
324 if (ReaderFcb
->WritePtr
+ CopyLength
<= ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
)
326 memcpy(ReaderFcb
->WritePtr
, Buffer
, CopyLength
);
327 ReaderFcb
->WritePtr
+= CopyLength
;
328 if (ReaderFcb
->WritePtr
== ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
)
330 ReaderFcb
->WritePtr
= ReaderFcb
->Data
;
335 TempLength
= ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
- ReaderFcb
->WritePtr
;
336 memcpy(ReaderFcb
->WritePtr
, Buffer
, TempLength
);
337 memcpy(ReaderFcb
->Data
, Buffer
+ TempLength
, CopyLength
- TempLength
);
338 ReaderFcb
->WritePtr
= ReaderFcb
->Data
+ CopyLength
- TempLength
;
341 Buffer
+= CopyLength
;
342 Length
-= CopyLength
;
343 Information
+= CopyLength
;
345 ReaderFcb
->ReadDataAvailable
+= CopyLength
;
346 ReaderFcb
->WriteQuotaAvailable
-= CopyLength
;
351 KeSetEvent(&ReaderFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
357 DPRINT("Message mode\n");
360 CopyLength
= RtlRosMin(Length
, ReaderFcb
->WriteQuotaAvailable
);
361 memcpy(ReaderFcb
->Data
, Buffer
, CopyLength
);
363 Information
= CopyLength
;
364 ReaderFcb
->ReadDataAvailable
= CopyLength
;
365 ReaderFcb
->WriteQuotaAvailable
= 0;
370 KeSetEvent(&ReaderFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
376 KeReleaseSpinLock(&ReaderFcb
->DataListLock
, OldIrql
);
379 Irp
->IoStatus
.Status
= Status
;
380 Irp
->IoStatus
.Information
= Information
;
382 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
384 DPRINT("NpfsWrite done (Status %lx)\n", Status
);