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 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
106 KeSetEvent(&WriterFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
108 KeReleaseSpinLock(&Fcb
->DataListLock
, OldIrql
);
111 Status
= STATUS_SUCCESS
;
115 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
117 DPRINT("PipeState: %x\n", Fcb
->PipeState
);
118 Status
= STATUS_PIPE_BROKEN
;
122 /* Wait for ReadEvent to become signaled */
123 DPRINT("Waiting for readable data (%S)\n", Pipe
->PipeName
.Buffer
);
124 Status
= KeWaitForSingleObject(&Fcb
->Event
,
129 DPRINT("Finished waiting (%S)! Status: %x\n", Pipe
->PipeName
.Buffer
, Status
);
131 KeAcquireSpinLock(&Fcb
->DataListLock
, &OldIrql
);
134 if (Pipe
->ReadMode
== FILE_PIPE_BYTE_STREAM_MODE
)
136 DPRINT("Byte stream mode\n");
137 /* Byte stream mode */
138 while (Length
> 0 && Fcb
->ReadDataAvailable
> 0)
140 CopyLength
= RtlRosMin(Fcb
->ReadDataAvailable
, Length
);
141 if (Fcb
->ReadPtr
+ CopyLength
<= Fcb
->Data
+ Fcb
->MaxDataLength
)
143 memcpy(Buffer
, Fcb
->ReadPtr
, CopyLength
);
144 Fcb
->ReadPtr
+= CopyLength
;
145 if (Fcb
->ReadPtr
== Fcb
->Data
+ Fcb
->MaxDataLength
)
147 Fcb
->ReadPtr
= Fcb
->Data
;
152 TempLength
= Fcb
->Data
+ Fcb
->MaxDataLength
- Fcb
->ReadPtr
;
153 memcpy(Buffer
, Fcb
->ReadPtr
, TempLength
);
154 memcpy(Buffer
+ TempLength
, Fcb
->Data
, CopyLength
- TempLength
);
155 Fcb
->ReadPtr
= Fcb
->Data
+ CopyLength
- TempLength
;
158 Buffer
+= CopyLength
;
159 Length
-= CopyLength
;
160 Information
+= CopyLength
;
162 Fcb
->ReadDataAvailable
-= CopyLength
;
163 Fcb
->WriteQuotaAvailable
+= CopyLength
;
168 KeSetEvent(&WriterFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
169 KeResetEvent(&Fcb
->Event
);
175 DPRINT("Message mode\n");
178 if (Fcb
->ReadDataAvailable
)
180 /* Truncate the message if the receive buffer is too small */
181 CopyLength
= RtlRosMin(Fcb
->ReadDataAvailable
, Length
);
182 memcpy(Buffer
, Fcb
->Data
, CopyLength
);
185 DPRINT("Length %d Buffer %x\n",CopyLength
,Buffer
);
186 HexDump((PUCHAR
)Buffer
, CopyLength
);
189 Information
= CopyLength
;
191 if (Fcb
->ReadDataAvailable
> Length
)
193 memmove(Fcb
->Data
, Fcb
->Data
+ Length
,
194 Fcb
->ReadDataAvailable
- Length
);
195 Fcb
->ReadDataAvailable
-= Length
;
196 Status
= STATUS_MORE_ENTRIES
;
200 Fcb
->ReadDataAvailable
= 0;
201 Fcb
->WriteQuotaAvailable
= Fcb
->MaxDataLength
;
207 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
209 KeSetEvent(&WriterFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
211 KeResetEvent(&Fcb
->Event
);
217 KeReleaseSpinLock(&Fcb
->DataListLock
, OldIrql
);
220 Irp
->IoStatus
.Status
= Status
;
221 Irp
->IoStatus
.Information
= Information
;
223 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
225 DPRINT("NpfsRead done (Status %lx)\n", Status
);
232 NpfsWrite(PDEVICE_OBJECT DeviceObject
,
235 PIO_STACK_LOCATION IoStack
;
236 PFILE_OBJECT FileObject
;
237 PNPFS_FCB Fcb
= NULL
;
239 PNPFS_PIPE Pipe
= NULL
;
241 NTSTATUS Status
= STATUS_SUCCESS
;
249 DPRINT("NpfsWrite()\n");
251 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
252 FileObject
= IoStack
->FileObject
;
253 DPRINT("FileObject %p\n", FileObject
);
254 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
256 Fcb
= FileObject
->FsContext
;
257 ReaderFcb
= Fcb
->OtherSide
;
260 Length
= IoStack
->Parameters
.Write
.Length
;
261 Offset
= IoStack
->Parameters
.Write
.ByteOffset
.u
.LowPart
;
264 if (Irp
->MdlAddress
== NULL
)
266 DPRINT("Irp->MdlAddress == NULL\n");
267 Status
= STATUS_UNSUCCESSFUL
;
272 if (ReaderFcb
== NULL
)
274 DPRINT("Pipe is NOT connected!\n");
275 if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
276 Status
= STATUS_PIPE_LISTENING
;
277 else if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
278 Status
= STATUS_PIPE_DISCONNECTED
;
280 Status
= STATUS_UNSUCCESSFUL
;
285 if (ReaderFcb
->Data
== NULL
)
287 DPRINT("Pipe is NOT writable!\n");
288 Status
= STATUS_UNSUCCESSFUL
;
293 Status
= STATUS_SUCCESS
;
294 Buffer
= MmGetSystemAddressForMdl (Irp
->MdlAddress
);
296 KeAcquireSpinLock(&ReaderFcb
->DataListLock
, &OldIrql
);
298 DPRINT("Length %d Buffer %x Offset %x\n",Length
,Buffer
,Offset
);
299 HexDump(Buffer
, Length
);
304 if (ReaderFcb
->WriteQuotaAvailable
== 0)
306 KeSetEvent(&ReaderFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
307 KeReleaseSpinLock(&ReaderFcb
->DataListLock
, OldIrql
);
308 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
310 Status
= STATUS_PIPE_BROKEN
;
314 DPRINT("Waiting for buffer space (%S)\n", Pipe
->PipeName
.Buffer
);
315 Status
= KeWaitForSingleObject(&Fcb
->Event
,
320 DPRINT("Finished waiting (%S)! Status: %x\n", Pipe
->PipeName
.Buffer
, Status
);
323 * It's possible that the event was signaled because the
324 * other side of pipe was closed.
326 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
328 DPRINT("PipeState: %x\n", Fcb
->PipeState
);
329 Status
= STATUS_PIPE_BROKEN
;
332 KeAcquireSpinLock(&ReaderFcb
->DataListLock
, &OldIrql
);
335 if (Pipe
->WriteMode
== FILE_PIPE_BYTE_STREAM_MODE
)
337 DPRINT("Byte stream mode\n");
338 while (Length
> 0 && ReaderFcb
->WriteQuotaAvailable
> 0)
340 CopyLength
= RtlRosMin(Length
, ReaderFcb
->WriteQuotaAvailable
);
341 if (ReaderFcb
->WritePtr
+ CopyLength
<= ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
)
343 memcpy(ReaderFcb
->WritePtr
, Buffer
, CopyLength
);
344 ReaderFcb
->WritePtr
+= CopyLength
;
345 if (ReaderFcb
->WritePtr
== ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
)
347 ReaderFcb
->WritePtr
= ReaderFcb
->Data
;
352 TempLength
= ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
- ReaderFcb
->WritePtr
;
353 memcpy(ReaderFcb
->WritePtr
, Buffer
, TempLength
);
354 memcpy(ReaderFcb
->Data
, Buffer
+ TempLength
, CopyLength
- TempLength
);
355 ReaderFcb
->WritePtr
= ReaderFcb
->Data
+ CopyLength
- TempLength
;
358 Buffer
+= CopyLength
;
359 Length
-= CopyLength
;
360 Information
+= CopyLength
;
362 ReaderFcb
->ReadDataAvailable
+= CopyLength
;
363 ReaderFcb
->WriteQuotaAvailable
-= CopyLength
;
368 KeSetEvent(&ReaderFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
369 KeResetEvent(&Fcb
->Event
);
375 DPRINT("Message mode\n");
378 CopyLength
= RtlRosMin(Length
, ReaderFcb
->WriteQuotaAvailable
);
379 memcpy(ReaderFcb
->Data
, Buffer
, CopyLength
);
381 Information
= CopyLength
;
382 ReaderFcb
->ReadDataAvailable
= CopyLength
;
383 ReaderFcb
->WriteQuotaAvailable
= 0;
388 KeSetEvent(&ReaderFcb
->Event
, IO_NO_INCREMENT
, FALSE
);
389 KeResetEvent(&Fcb
->Event
);
395 KeReleaseSpinLock(&ReaderFcb
->DataListLock
, OldIrql
);
398 Irp
->IoStatus
.Status
= Status
;
399 Irp
->IoStatus
.Information
= Information
;
401 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
403 DPRINT("NpfsWrite done (Status %lx)\n", Status
);