2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/fs/np/rw.c
5 * PURPOSE: Named pipe filesystem
6 * PROGRAMMER: David Welch <welch@cwcom.net>
9 /* INCLUDES ******************************************************************/
16 /* FUNCTIONS *****************************************************************/
19 VOID
HexDump(PUCHAR Buffer
, ULONG Length
)
23 const char Hex
[] = "0123456789ABCDEF";
26 DbgPrint("---------------\n");
28 for (i
= 0; i
< Length
; i
+= 16)
30 memset(Line
, ' ', 64);
33 for (j
= 0; j
< 16 && j
+ i
< Length
; j
++)
36 Line
[3*j
+ 0] = Hex
[ch
>> 4];
37 Line
[3*j
+ 1] = Hex
[ch
& 0x0f];
38 Line
[48 + j
] = isprint(ch
) ? ch
: '.';
40 DbgPrint("%s\n", Line
);
42 DbgPrint("---------------\n");
46 static DRIVER_CANCEL NpfsReadWriteCancelRoutine
;
48 NpfsReadWriteCancelRoutine(IN PDEVICE_OBJECT DeviceObject
,
51 PNPFS_CONTEXT Context
;
52 PNPFS_DEVICE_EXTENSION DeviceExt
;
53 PIO_STACK_LOCATION IoStack
;
55 BOOLEAN Complete
= FALSE
;
57 DPRINT("NpfsReadWriteCancelRoutine(DeviceObject %p, Irp %p)\n", DeviceObject
, Irp
);
59 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
61 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
62 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
63 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
64 Ccb
= IoStack
->FileObject
->FsContext2
;
66 KeLockMutex(&DeviceExt
->PipeListLock
);
67 ExAcquireFastMutex(&Ccb
->DataListLock
);
68 switch(IoStack
->MajorFunction
)
71 if (Ccb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
73 /* we are not the first in the list, remove an complete us */
74 RemoveEntryList(&Context
->ListEntry
);
79 KeSetEvent(&Ccb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
85 ExReleaseFastMutex(&Ccb
->DataListLock
);
86 KeUnlockMutex(&DeviceExt
->PipeListLock
);
89 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
90 Irp
->IoStatus
.Information
= 0;
91 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
96 NpfsWaiterThread(PVOID InitContext
)
98 PNPFS_THREAD_CONTEXT ThreadContext
= (PNPFS_THREAD_CONTEXT
) InitContext
;
104 BOOLEAN Terminate
= FALSE
;
105 BOOLEAN Cancel
= FALSE
;
106 PIO_STACK_LOCATION IoStack
= NULL
;
107 PNPFS_CONTEXT Context
;
108 PNPFS_CONTEXT NextContext
;
111 KeLockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
115 CurrentCount
= ThreadContext
->Count
;
116 KeUnlockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
121 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
122 Irp
->IoStatus
.Information
= 0;
123 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
127 switch (IoStack
->MajorFunction
)
130 NpfsRead(IoStack
->DeviceObject
, Irp
);
141 Status
= KeWaitForMultipleObjects(CurrentCount
,
142 ThreadContext
->WaitObjectArray
,
148 ThreadContext
->WaitBlockArray
);
149 if (!NT_SUCCESS(Status
))
153 KeLockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
154 Count
= Status
- STATUS_SUCCESS
;
155 ASSERT (Count
< CurrentCount
);
158 Irp
= ThreadContext
->WaitIrpArray
[Count
];
159 ThreadContext
->Count
--;
160 ThreadContext
->DeviceExt
->EmptyWaiterCount
++;
161 ThreadContext
->WaitObjectArray
[Count
] = ThreadContext
->WaitObjectArray
[ThreadContext
->Count
];
162 ThreadContext
->WaitIrpArray
[Count
] = ThreadContext
->WaitIrpArray
[ThreadContext
->Count
];
164 Cancel
= (NULL
== IoSetCancelRoutine(Irp
, NULL
));
165 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
166 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
170 Ccb
= IoStack
->FileObject
->FsContext2
;
171 ExAcquireFastMutex(&Ccb
->DataListLock
);
172 RemoveEntryList(&Context
->ListEntry
);
173 switch (IoStack
->MajorFunction
)
176 if (!IsListEmpty(&Ccb
->ReadRequestListHead
))
178 /* put the next request on the wait list */
179 NextContext
= CONTAINING_RECORD(Ccb
->ReadRequestListHead
.Flink
, NPFS_CONTEXT
, ListEntry
);
180 ThreadContext
->WaitObjectArray
[ThreadContext
->Count
] = NextContext
->WaitEvent
;
181 NextIrp
= CONTAINING_RECORD(NextContext
, IRP
, Tail
.Overlay
.DriverContext
);
182 ThreadContext
->WaitIrpArray
[ThreadContext
->Count
] = NextIrp
;
183 ThreadContext
->Count
++;
184 ThreadContext
->DeviceExt
->EmptyWaiterCount
--;
190 ExReleaseFastMutex(&Ccb
->DataListLock
);
195 /* someone has add a new wait request */
198 if (ThreadContext
->Count
== 1 && ThreadContext
->DeviceExt
->EmptyWaiterCount
>= MAXIMUM_WAIT_OBJECTS
)
200 /* it exist an other thread with empty wait slots, we can remove our thread from the list */
201 RemoveEntryList(&ThreadContext
->ListEntry
);
202 ThreadContext
->DeviceExt
->EmptyWaiterCount
-= MAXIMUM_WAIT_OBJECTS
- 1;
206 ExFreePool(ThreadContext
);
210 NpfsAddWaitingReadWriteRequest(IN PDEVICE_OBJECT DeviceObject
,
213 PLIST_ENTRY ListEntry
;
214 PNPFS_THREAD_CONTEXT ThreadContext
= NULL
;
219 PNPFS_CONTEXT Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
220 PNPFS_DEVICE_EXTENSION DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
222 DPRINT("NpfsAddWaitingReadWriteRequest(DeviceObject %p, Irp %p)\n", DeviceObject
, Irp
);
224 KeLockMutex(&DeviceExt
->PipeListLock
);
226 ListEntry
= DeviceExt
->ThreadListHead
.Flink
;
227 while (ListEntry
!= &DeviceExt
->ThreadListHead
)
229 ThreadContext
= CONTAINING_RECORD(ListEntry
, NPFS_THREAD_CONTEXT
, ListEntry
);
230 if (ThreadContext
->Count
< MAXIMUM_WAIT_OBJECTS
)
234 ListEntry
= ListEntry
->Flink
;
236 if (ListEntry
== &DeviceExt
->ThreadListHead
)
238 ThreadContext
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_THREAD_CONTEXT
));
239 if (ThreadContext
== NULL
)
241 KeUnlockMutex(&DeviceExt
->PipeListLock
);
242 return STATUS_NO_MEMORY
;
244 ThreadContext
->DeviceExt
= DeviceExt
;
245 KeInitializeEvent(&ThreadContext
->Event
, SynchronizationEvent
, FALSE
);
246 ThreadContext
->Count
= 1;
247 ThreadContext
->WaitObjectArray
[0] = &ThreadContext
->Event
;
250 DPRINT("Creating a new system thread for waiting read/write requests\n");
252 Status
= PsCreateSystemThread(&hThread
,
258 (PVOID
)ThreadContext
);
259 if (!NT_SUCCESS(Status
))
261 ExFreePool(ThreadContext
);
262 KeUnlockMutex(&DeviceExt
->PipeListLock
);
265 InsertHeadList(&DeviceExt
->ThreadListHead
, &ThreadContext
->ListEntry
);
266 DeviceExt
->EmptyWaiterCount
+= MAXIMUM_WAIT_OBJECTS
- 1;
268 IoMarkIrpPending(Irp
);
270 IoAcquireCancelSpinLock(&oldIrql
);
273 IoReleaseCancelSpinLock(oldIrql
);
274 Status
= STATUS_CANCELLED
;
278 (void)IoSetCancelRoutine(Irp
, NpfsReadWriteCancelRoutine
);
279 IoReleaseCancelSpinLock(oldIrql
);
280 ThreadContext
->WaitObjectArray
[ThreadContext
->Count
] = Context
->WaitEvent
;
281 ThreadContext
->WaitIrpArray
[ThreadContext
->Count
] = Irp
;
282 ThreadContext
->Count
++;
283 DeviceExt
->EmptyWaiterCount
--;
284 KeSetEvent(&ThreadContext
->Event
, IO_NO_INCREMENT
, FALSE
);
285 Status
= STATUS_SUCCESS
;
287 KeUnlockMutex(&DeviceExt
->PipeListLock
);
292 NpfsRead(IN PDEVICE_OBJECT DeviceObject
,
295 PFILE_OBJECT FileObject
;
297 NTSTATUS OriginalStatus
= STATUS_SUCCESS
;
299 PNPFS_CONTEXT Context
;
302 ULONG Information
= 0;
305 BOOLEAN IsOriginalRequest
= TRUE
;
308 DPRINT("NpfsRead(DeviceObject %p, Irp %p)\n", DeviceObject
, Irp
);
310 if (Irp
->MdlAddress
== NULL
)
312 DPRINT("Irp->MdlAddress == NULL\n");
313 Status
= STATUS_UNSUCCESSFUL
;
314 Irp
->IoStatus
.Information
= 0;
318 FileObject
= IoGetCurrentIrpStackLocation(Irp
)->FileObject
;
319 Ccb
= FileObject
->FsContext2
;
320 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
322 if (Ccb
->OtherSide
== NULL
)
324 DPRINT("Pipe is NOT connected!\n");
325 if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
326 Status
= STATUS_PIPE_LISTENING
;
327 else if (Ccb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
328 Status
= STATUS_PIPE_DISCONNECTED
;
330 Status
= STATUS_UNSUCCESSFUL
;
331 Irp
->IoStatus
.Information
= 0;
335 if (Ccb
->Data
== NULL
)
337 DPRINT1("Pipe is NOT readable!\n");
338 Status
= STATUS_UNSUCCESSFUL
;
339 Irp
->IoStatus
.Information
= 0;
343 ExAcquireFastMutex(&Ccb
->DataListLock
);
345 if (IoIsOperationSynchronous(Irp
))
347 InsertTailList(&Ccb
->ReadRequestListHead
, &Context
->ListEntry
);
348 if (Ccb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
350 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
351 Context
->WaitEvent
= &Event
;
352 ExReleaseFastMutex(&Ccb
->DataListLock
);
353 Status
= KeWaitForSingleObject(&Event
,
358 if (!NT_SUCCESS(Status
))
362 ExAcquireFastMutex(&Ccb
->DataListLock
);
364 Irp
->IoStatus
.Information
= 0;
369 if (IsListEmpty(&Ccb
->ReadRequestListHead
) ||
370 Ccb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
372 /* this is a new request */
373 Irp
->IoStatus
.Information
= 0;
374 Context
->WaitEvent
= &Ccb
->ReadEvent
;
375 InsertTailList(&Ccb
->ReadRequestListHead
, &Context
->ListEntry
);
376 if (Ccb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
378 /* there was already a request on the list */
379 IoAcquireCancelSpinLock(&oldIrql
);
382 IoReleaseCancelSpinLock(oldIrql
);
383 RemoveEntryList(&Context
->ListEntry
);
384 ExReleaseFastMutex(&Ccb
->DataListLock
);
385 Status
= STATUS_CANCELLED
;
388 (void)IoSetCancelRoutine(Irp
, NpfsReadWriteCancelRoutine
);
389 IoReleaseCancelSpinLock(oldIrql
);
390 ExReleaseFastMutex(&Ccb
->DataListLock
);
391 IoMarkIrpPending(Irp
);
392 Status
= STATUS_PENDING
;
400 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
401 Information
= Irp
->IoStatus
.Information
;
402 Length
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.Read
.Length
;
403 ASSERT (Information
<= Length
);
404 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ Information
);
405 Length
-= Information
;
406 Status
= STATUS_SUCCESS
;
410 if (Ccb
->ReadDataAvailable
== 0)
412 if (Ccb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
414 ASSERT(Ccb
->OtherSide
!= NULL
);
415 KeSetEvent(&Ccb
->OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
417 if (Information
> 0 &&
418 (Ccb
->Fcb
->ReadMode
!= FILE_PIPE_BYTE_STREAM_MODE
||
419 Ccb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
))
423 if (Ccb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
425 DPRINT("PipeState: %x\n", Ccb
->PipeState
);
426 Status
= STATUS_PIPE_BROKEN
;
429 ExReleaseFastMutex(&Ccb
->DataListLock
);
430 if (IoIsOperationSynchronous(Irp
))
432 /* Wait for ReadEvent to become signaled */
434 DPRINT("Waiting for readable data (%wZ)\n", &Ccb
->Fcb
->PipeName
);
435 Status
= KeWaitForSingleObject(&Ccb
->ReadEvent
,
440 DPRINT("Finished waiting (%wZ)! Status: %x\n", &Ccb
->Fcb
->PipeName
, Status
);
441 ExAcquireFastMutex(&Ccb
->DataListLock
);
445 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
447 Context
->WaitEvent
= &Ccb
->ReadEvent
;
448 Status
= NpfsAddWaitingReadWriteRequest(DeviceObject
, Irp
);
450 if (NT_SUCCESS(Status
))
452 Status
= STATUS_PENDING
;
454 ExAcquireFastMutex(&Ccb
->DataListLock
);
458 ASSERT(IoGetCurrentIrpStackLocation(Irp
)->FileObject
!= NULL
);
459 if (Ccb
->Fcb
->ReadMode
== FILE_PIPE_BYTE_STREAM_MODE
)
461 DPRINT("Byte stream mode\n");
462 /* Byte stream mode */
463 while (Length
> 0 && Ccb
->ReadDataAvailable
> 0)
465 CopyLength
= min(Ccb
->ReadDataAvailable
, Length
);
466 if ((ULONG_PTR
)Ccb
->ReadPtr
+ CopyLength
<= (ULONG_PTR
)Ccb
->Data
+ Ccb
->MaxDataLength
)
468 memcpy(Buffer
, Ccb
->ReadPtr
, CopyLength
);
469 Ccb
->ReadPtr
= (PVOID
)((ULONG_PTR
)Ccb
->ReadPtr
+ CopyLength
);
470 if (Ccb
->ReadPtr
== (PVOID
)((ULONG_PTR
)Ccb
->Data
+ Ccb
->MaxDataLength
))
472 Ccb
->ReadPtr
= Ccb
->Data
;
477 TempLength
= (ULONG
)((ULONG_PTR
)Ccb
->Data
+ Ccb
->MaxDataLength
- (ULONG_PTR
)Ccb
->ReadPtr
);
478 memcpy(Buffer
, Ccb
->ReadPtr
, TempLength
);
479 memcpy((PVOID
)((ULONG_PTR
)Buffer
+ TempLength
), Ccb
->Data
, CopyLength
- TempLength
);
480 Ccb
->ReadPtr
= (PVOID
)((ULONG_PTR
)Ccb
->Data
+ CopyLength
- TempLength
);
483 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ CopyLength
);
484 Length
-= CopyLength
;
485 Information
+= CopyLength
;
487 Ccb
->ReadDataAvailable
-= CopyLength
;
488 Ccb
->WriteQuotaAvailable
+= CopyLength
;
493 if (Ccb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
495 KeSetEvent(&Ccb
->OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
497 KeResetEvent(&Ccb
->ReadEvent
);
503 DPRINT("Message mode\n");
506 if (Ccb
->ReadDataAvailable
)
508 /* Truncate the message if the receive buffer is too small */
509 CopyLength
= min(Ccb
->ReadDataAvailable
, Length
);
510 memcpy(Buffer
, Ccb
->Data
, CopyLength
);
513 DPRINT("Length %d Buffer %x\n",CopyLength
,Buffer
);
514 HexDump((PUCHAR
)Buffer
, CopyLength
);
517 Information
= CopyLength
;
519 if (Ccb
->ReadDataAvailable
> Length
)
521 memmove(Ccb
->Data
, (PVOID
)((ULONG_PTR
)Ccb
->Data
+ Length
),
522 Ccb
->ReadDataAvailable
- Length
);
523 Ccb
->ReadDataAvailable
-= Length
;
524 Status
= STATUS_MORE_ENTRIES
;
528 KeResetEvent(&Ccb
->ReadEvent
);
529 if (Ccb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
531 KeSetEvent(&Ccb
->OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
533 Ccb
->ReadDataAvailable
= 0;
534 Ccb
->WriteQuotaAvailable
= Ccb
->MaxDataLength
;
544 Irp
->IoStatus
.Information
= Information
;
545 Irp
->IoStatus
.Status
= Status
;
547 ASSERT(IoGetCurrentIrpStackLocation(Irp
)->FileObject
!= NULL
);
549 if (IoIsOperationSynchronous(Irp
))
551 RemoveEntryList(&Context
->ListEntry
);
552 if (!IsListEmpty(&Ccb
->ReadRequestListHead
))
554 Context
= CONTAINING_RECORD(Ccb
->ReadRequestListHead
.Flink
, NPFS_CONTEXT
, ListEntry
);
555 KeSetEvent(Context
->WaitEvent
, IO_NO_INCREMENT
, FALSE
);
557 ExReleaseFastMutex(&Ccb
->DataListLock
);
558 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
560 DPRINT("NpfsRead done (Status %lx)\n", Status
);
565 if (IsOriginalRequest
)
567 IsOriginalRequest
= FALSE
;
568 OriginalStatus
= Status
;
570 if (Status
== STATUS_PENDING
)
572 ExReleaseFastMutex(&Ccb
->DataListLock
);
573 DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus
);
574 return OriginalStatus
;
576 RemoveEntryList(&Context
->ListEntry
);
577 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
578 if (IsListEmpty(&Ccb
->ReadRequestListHead
))
580 ExReleaseFastMutex(&Ccb
->DataListLock
);
581 DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus
);
582 return OriginalStatus
;
584 Context
= CONTAINING_RECORD(Ccb
->ReadRequestListHead
.Flink
, NPFS_CONTEXT
, ListEntry
);
585 Irp
= CONTAINING_RECORD(Context
, IRP
, Tail
.Overlay
.DriverContext
);
590 Irp
->IoStatus
.Status
= Status
;
592 if (Status
!= STATUS_PENDING
)
594 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
596 DPRINT("NpfsRead done (Status %lx)\n", Status
);
602 NpfsWrite(PDEVICE_OBJECT DeviceObject
,
605 PIO_STACK_LOCATION IoStack
;
606 PFILE_OBJECT FileObject
;
607 PNPFS_FCB Fcb
= NULL
;
608 PNPFS_CCB Ccb
= NULL
;
611 NTSTATUS Status
= STATUS_SUCCESS
;
618 DPRINT("NpfsWrite()\n");
620 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
621 FileObject
= IoStack
->FileObject
;
622 DPRINT("FileObject %p\n", FileObject
);
623 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
625 Ccb
= FileObject
->FsContext2
;
626 ReaderCcb
= Ccb
->OtherSide
;
629 Length
= IoStack
->Parameters
.Write
.Length
;
630 Offset
= IoStack
->Parameters
.Write
.ByteOffset
.u
.LowPart
;
633 if (Irp
->MdlAddress
== NULL
)
635 DPRINT("Irp->MdlAddress == NULL\n");
636 Status
= STATUS_UNSUCCESSFUL
;
641 if (ReaderCcb
== NULL
)
643 DPRINT("Pipe is NOT connected!\n");
644 if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
645 Status
= STATUS_PIPE_LISTENING
;
646 else if (Ccb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
647 Status
= STATUS_PIPE_DISCONNECTED
;
649 Status
= STATUS_UNSUCCESSFUL
;
654 if (ReaderCcb
->Data
== NULL
)
656 DPRINT("Pipe is NOT writable!\n");
657 Status
= STATUS_UNSUCCESSFUL
;
662 Status
= STATUS_SUCCESS
;
663 Buffer
= MmGetSystemAddressForMdl (Irp
->MdlAddress
);
665 ExAcquireFastMutex(&ReaderCcb
->DataListLock
);
667 DPRINT("Length %d Buffer %x Offset %x\n",Length
,Buffer
,Offset
);
668 HexDump(Buffer
, Length
);
673 if (ReaderCcb
->WriteQuotaAvailable
== 0)
675 KeSetEvent(&ReaderCcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
676 if (Ccb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
678 Status
= STATUS_PIPE_BROKEN
;
679 ExReleaseFastMutex(&ReaderCcb
->DataListLock
);
682 ExReleaseFastMutex(&ReaderCcb
->DataListLock
);
684 DPRINT("Waiting for buffer space (%S)\n", Fcb
->PipeName
.Buffer
);
685 Status
= KeWaitForSingleObject(&Ccb
->WriteEvent
,
690 DPRINT("Finished waiting (%S)! Status: %x\n", Fcb
->PipeName
.Buffer
, Status
);
693 * It's possible that the event was signaled because the
694 * other side of pipe was closed.
696 if (Ccb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
698 DPRINT("PipeState: %x\n", Ccb
->PipeState
);
699 Status
= STATUS_PIPE_BROKEN
;
700 // ExReleaseFastMutex(&ReaderCcb->DataListLock);
704 ExAcquireFastMutex(&ReaderCcb
->DataListLock
);
707 if (Fcb
->WriteMode
== FILE_PIPE_BYTE_STREAM_MODE
)
709 DPRINT("Byte stream mode\n");
710 while (Length
> 0 && ReaderCcb
->WriteQuotaAvailable
> 0)
712 CopyLength
= min(Length
, ReaderCcb
->WriteQuotaAvailable
);
713 if ((ULONG_PTR
)ReaderCcb
->WritePtr
+ CopyLength
<= (ULONG_PTR
)ReaderCcb
->Data
+ ReaderCcb
->MaxDataLength
)
715 memcpy(ReaderCcb
->WritePtr
, Buffer
, CopyLength
);
716 ReaderCcb
->WritePtr
= (PVOID
)((ULONG_PTR
)ReaderCcb
->WritePtr
+ CopyLength
);
717 if ((ULONG_PTR
)ReaderCcb
->WritePtr
== (ULONG_PTR
)ReaderCcb
->Data
+ ReaderCcb
->MaxDataLength
)
719 ReaderCcb
->WritePtr
= ReaderCcb
->Data
;
724 TempLength
= (ULONG
)((ULONG_PTR
)ReaderCcb
->Data
+ ReaderCcb
->MaxDataLength
- (ULONG_PTR
)ReaderCcb
->WritePtr
);
725 memcpy(ReaderCcb
->WritePtr
, Buffer
, TempLength
);
726 memcpy(ReaderCcb
->Data
, Buffer
+ TempLength
, CopyLength
- TempLength
);
727 ReaderCcb
->WritePtr
= (PVOID
)((ULONG_PTR
)ReaderCcb
->Data
+ CopyLength
- TempLength
);
730 Buffer
+= CopyLength
;
731 Length
-= CopyLength
;
732 Information
+= CopyLength
;
734 ReaderCcb
->ReadDataAvailable
+= CopyLength
;
735 ReaderCcb
->WriteQuotaAvailable
-= CopyLength
;
740 KeSetEvent(&ReaderCcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
741 KeResetEvent(&Ccb
->WriteEvent
);
747 DPRINT("Message mode\n");
750 CopyLength
= min(Length
, ReaderCcb
->WriteQuotaAvailable
);
751 memcpy(ReaderCcb
->Data
, Buffer
, CopyLength
);
753 Information
= CopyLength
;
754 ReaderCcb
->ReadDataAvailable
= CopyLength
;
755 ReaderCcb
->WriteQuotaAvailable
= 0;
760 KeSetEvent(&ReaderCcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
761 KeResetEvent(&Ccb
->WriteEvent
);
767 ExReleaseFastMutex(&ReaderCcb
->DataListLock
);
770 Irp
->IoStatus
.Status
= Status
;
771 Irp
->IoStatus
.Information
= Information
;
773 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
775 DPRINT("NpfsWrite done (Status %lx)\n", Status
);