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 ******************************************************************/
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");
50 NpfsReadWriteCancelRoutine(IN PDEVICE_OBJECT DeviceObject
,
53 PNPFS_CONTEXT Context
;
54 PNPFS_DEVICE_EXTENSION DeviceExt
;
55 PIO_STACK_LOCATION IoStack
;
57 BOOLEAN Complete
= FALSE
;
59 DPRINT("NpfsReadWriteCancelRoutine(DeviceObject %x, Irp %x)\n", DeviceObject
, Irp
);
61 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
63 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
64 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
65 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
66 Fcb
= IoStack
->FileObject
->FsContext
;
68 KeLockMutex(&DeviceExt
->PipeListLock
);
69 ExAcquireFastMutex(&Fcb
->DataListLock
);
70 switch(IoStack
->MajorFunction
)
73 if (Fcb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
75 /* we are not the first in the list, remove an complete us */
76 RemoveEntryList(&Context
->ListEntry
);
81 KeSetEvent(&Fcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
87 ExReleaseFastMutex(&Fcb
->DataListLock
);
88 KeUnlockMutex(&DeviceExt
->PipeListLock
);
91 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
92 Irp
->IoStatus
.Information
= 0;
93 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
98 NpfsWaiterThread(PVOID InitContext
)
100 PNPFS_THREAD_CONTEXT ThreadContext
= (PNPFS_THREAD_CONTEXT
) InitContext
;
106 BOOLEAN Terminate
= FALSE
;
107 BOOLEAN Cancel
= FALSE
;
108 PIO_STACK_LOCATION IoStack
= NULL
;
109 PNPFS_CONTEXT Context
;
110 PNPFS_CONTEXT NextContext
;
113 KeLockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
117 CurrentCount
= ThreadContext
->Count
;
118 KeUnlockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
123 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
124 Irp
->IoStatus
.Information
= 0;
125 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
129 switch (IoStack
->MajorFunction
)
132 NpfsRead(IoStack
->DeviceObject
, Irp
);
143 Status
= KeWaitForMultipleObjects(CurrentCount
,
144 ThreadContext
->WaitObjectArray
,
150 ThreadContext
->WaitBlockArray
);
151 if (!NT_SUCCESS(Status
))
155 KeLockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
156 Count
= Status
- STATUS_SUCCESS
;
157 ASSERT (Count
< CurrentCount
);
160 Irp
= ThreadContext
->WaitIrpArray
[Count
];
161 ThreadContext
->Count
--;
162 ThreadContext
->DeviceExt
->EmptyWaiterCount
++;
163 ThreadContext
->WaitObjectArray
[Count
] = ThreadContext
->WaitObjectArray
[ThreadContext
->Count
];
164 ThreadContext
->WaitIrpArray
[Count
] = ThreadContext
->WaitIrpArray
[ThreadContext
->Count
];
166 Cancel
= (NULL
== IoSetCancelRoutine(Irp
, NULL
));
167 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
168 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
172 Fcb
= IoStack
->FileObject
->FsContext
;
173 ExAcquireFastMutex(&Fcb
->DataListLock
);
174 RemoveEntryList(&Context
->ListEntry
);
175 switch (IoStack
->MajorFunction
)
178 if (!IsListEmpty(&Fcb
->ReadRequestListHead
))
180 /* put the next request on the wait list */
181 NextContext
= CONTAINING_RECORD(Fcb
->ReadRequestListHead
.Flink
, NPFS_CONTEXT
, ListEntry
);
182 ThreadContext
->WaitObjectArray
[ThreadContext
->Count
] = NextContext
->WaitEvent
;
183 NextIrp
= CONTAINING_RECORD(NextContext
, IRP
, Tail
.Overlay
.DriverContext
);
184 ThreadContext
->WaitIrpArray
[ThreadContext
->Count
] = NextIrp
;
185 ThreadContext
->Count
++;
186 ThreadContext
->DeviceExt
->EmptyWaiterCount
--;
192 ExReleaseFastMutex(&Fcb
->DataListLock
);
197 /* someone has add a new wait request */
200 if (ThreadContext
->Count
== 1 && ThreadContext
->DeviceExt
->EmptyWaiterCount
>= MAXIMUM_WAIT_OBJECTS
)
202 /* it exist an other thread with empty wait slots, we can remove our thread from the list */
203 RemoveEntryList(&ThreadContext
->ListEntry
);
204 ThreadContext
->DeviceExt
->EmptyWaiterCount
-= MAXIMUM_WAIT_OBJECTS
- 1;
208 KeUnlockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
209 ExFreePool(ThreadContext
);
213 NpfsAddWaitingReadWriteRequest(IN PDEVICE_OBJECT DeviceObject
,
216 PLIST_ENTRY ListEntry
;
217 PNPFS_THREAD_CONTEXT ThreadContext
= NULL
;
222 PNPFS_CONTEXT Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
223 PNPFS_DEVICE_EXTENSION DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
225 DPRINT("NpfsAddWaitingReadWriteRequest(DeviceObject %p, Irp %p)\n", DeviceObject
, Irp
);
227 KeLockMutex(&DeviceExt
->PipeListLock
);
229 ListEntry
= DeviceExt
->ThreadListHead
.Flink
;
230 while (ListEntry
!= &DeviceExt
->ThreadListHead
)
232 ThreadContext
= CONTAINING_RECORD(ListEntry
, NPFS_THREAD_CONTEXT
, ListEntry
);
233 if (ThreadContext
->Count
< MAXIMUM_WAIT_OBJECTS
)
237 ListEntry
= ListEntry
->Flink
;
239 if (ListEntry
== &DeviceExt
->ThreadListHead
)
241 ThreadContext
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_THREAD_CONTEXT
));
242 if (ThreadContext
== NULL
)
244 KeUnlockMutex(&DeviceExt
->PipeListLock
);
245 return STATUS_NO_MEMORY
;
247 ThreadContext
->DeviceExt
= DeviceExt
;
248 KeInitializeEvent(&ThreadContext
->Event
, SynchronizationEvent
, FALSE
);
249 ThreadContext
->Count
= 1;
250 ThreadContext
->WaitObjectArray
[0] = &ThreadContext
->Event
;
253 DPRINT("Creating a new system thread for waiting read/write requests\n");
255 Status
= PsCreateSystemThread(&hThread
,
261 (PVOID
)ThreadContext
);
262 if (!NT_SUCCESS(Status
))
264 ExFreePool(ThreadContext
);
265 KeUnlockMutex(&DeviceExt
->PipeListLock
);
268 InsertHeadList(&DeviceExt
->ThreadListHead
, &ThreadContext
->ListEntry
);
269 DeviceExt
->EmptyWaiterCount
+= MAXIMUM_WAIT_OBJECTS
- 1;
271 IoMarkIrpPending(Irp
);
273 IoAcquireCancelSpinLock(&oldIrql
);
276 IoReleaseCancelSpinLock(oldIrql
);
277 Status
= STATUS_CANCELLED
;
281 IoSetCancelRoutine(Irp
, NpfsReadWriteCancelRoutine
);
282 IoReleaseCancelSpinLock(oldIrql
);
283 ThreadContext
->WaitObjectArray
[ThreadContext
->Count
] = Context
->WaitEvent
;
284 ThreadContext
->WaitIrpArray
[ThreadContext
->Count
] = Irp
;
285 ThreadContext
->Count
++;
286 DeviceExt
->EmptyWaiterCount
--;
287 KeSetEvent(&ThreadContext
->Event
, IO_NO_INCREMENT
, FALSE
);
288 Status
= STATUS_SUCCESS
;
290 KeUnlockMutex(&DeviceExt
->PipeListLock
);
295 NpfsRead(IN PDEVICE_OBJECT DeviceObject
,
298 PFILE_OBJECT FileObject
;
300 NTSTATUS OriginalStatus
= STATUS_SUCCESS
;
302 PNPFS_CONTEXT Context
;
308 BOOLEAN IsOriginalRequest
= TRUE
;
311 DPRINT("NpfsRead(DeviceObject %p, Irp %p)\n", DeviceObject
, Irp
);
313 if (Irp
->MdlAddress
== NULL
)
315 DPRINT("Irp->MdlAddress == NULL\n");
316 Status
= STATUS_UNSUCCESSFUL
;
317 Irp
->IoStatus
.Information
= 0;
321 FileObject
= IoGetCurrentIrpStackLocation(Irp
)->FileObject
;
322 Fcb
= FileObject
->FsContext
;
323 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
325 if (Fcb
->Data
== NULL
)
327 DPRINT1("Pipe is NOT readable!\n");
328 Status
= STATUS_UNSUCCESSFUL
;
329 Irp
->IoStatus
.Information
= 0;
333 ExAcquireFastMutex(&Fcb
->DataListLock
);
335 if (IoIsOperationSynchronous(Irp
))
337 InsertTailList(&Fcb
->ReadRequestListHead
, &Context
->ListEntry
);
338 if (Fcb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
340 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
341 Context
->WaitEvent
= &Event
;
342 ExReleaseFastMutex(&Fcb
->DataListLock
);
343 Status
= KeWaitForSingleObject(&Event
,
348 if (!NT_SUCCESS(Status
))
352 ExAcquireFastMutex(&Fcb
->DataListLock
);
354 Irp
->IoStatus
.Information
= 0;
359 if (IsListEmpty(&Fcb
->ReadRequestListHead
) ||
360 Fcb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
362 /* this is a new request */
363 Irp
->IoStatus
.Information
= 0;
364 Context
->WaitEvent
= &Fcb
->ReadEvent
;
365 InsertTailList(&Fcb
->ReadRequestListHead
, &Context
->ListEntry
);
366 if (Fcb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
368 /* there was already a request on the list */
369 IoAcquireCancelSpinLock(&oldIrql
);
372 IoReleaseCancelSpinLock(oldIrql
);
373 RemoveEntryList(&Context
->ListEntry
);
374 ExReleaseFastMutex(&Fcb
->DataListLock
);
375 Status
= STATUS_CANCELLED
;
378 IoSetCancelRoutine(Irp
, NpfsReadWriteCancelRoutine
);
379 IoReleaseCancelSpinLock(oldIrql
);
380 ExReleaseFastMutex(&Fcb
->DataListLock
);
381 IoMarkIrpPending(Irp
);
382 Status
= STATUS_PENDING
;
390 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
391 Information
= Irp
->IoStatus
.Information
;
392 Length
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.Read
.Length
;
393 ASSERT (Information
<= Length
);
394 Buffer
+= Information
;
395 Length
-= Information
;
396 Status
= STATUS_SUCCESS
;
400 if (Fcb
->ReadDataAvailable
== 0)
402 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
404 KeSetEvent(&Fcb
->OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
406 if (Information
> 0 &&
407 (Fcb
->Pipe
->ReadMode
!= FILE_PIPE_BYTE_STREAM_MODE
||
408 Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
))
412 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
414 DPRINT("PipeState: %x\n", Fcb
->PipeState
);
415 Status
= STATUS_PIPE_BROKEN
;
418 ExReleaseFastMutex(&Fcb
->DataListLock
);
419 if (IoIsOperationSynchronous(Irp
))
421 /* Wait for ReadEvent to become signaled */
423 DPRINT("Waiting for readable data (%wZ)\n", &Fcb
->Pipe
->PipeName
);
424 Status
= KeWaitForSingleObject(&Fcb
->ReadEvent
,
429 DPRINT("Finished waiting (%wZ)! Status: %x\n", &Fcb
->Pipe
->PipeName
, Status
);
430 ExAcquireFastMutex(&Fcb
->DataListLock
);
434 PNPFS_CONTEXT Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
436 Context
->WaitEvent
= &Fcb
->ReadEvent
;
437 Status
= NpfsAddWaitingReadWriteRequest(DeviceObject
, Irp
);
439 if (NT_SUCCESS(Status
))
441 Status
= STATUS_PENDING
;
443 ExAcquireFastMutex(&Fcb
->DataListLock
);
447 if (Fcb
->Pipe
->ReadMode
== FILE_PIPE_BYTE_STREAM_MODE
)
449 DPRINT("Byte stream mode\n");
450 /* Byte stream mode */
451 while (Length
> 0 && Fcb
->ReadDataAvailable
> 0)
453 CopyLength
= RtlRosMin(Fcb
->ReadDataAvailable
, Length
);
454 if (Fcb
->ReadPtr
+ CopyLength
<= Fcb
->Data
+ Fcb
->MaxDataLength
)
456 memcpy(Buffer
, Fcb
->ReadPtr
, CopyLength
);
457 Fcb
->ReadPtr
+= CopyLength
;
458 if (Fcb
->ReadPtr
== Fcb
->Data
+ Fcb
->MaxDataLength
)
460 Fcb
->ReadPtr
= Fcb
->Data
;
465 TempLength
= Fcb
->Data
+ Fcb
->MaxDataLength
- Fcb
->ReadPtr
;
466 memcpy(Buffer
, Fcb
->ReadPtr
, TempLength
);
467 memcpy(Buffer
+ TempLength
, Fcb
->Data
, CopyLength
- TempLength
);
468 Fcb
->ReadPtr
= Fcb
->Data
+ CopyLength
- TempLength
;
471 Buffer
+= CopyLength
;
472 Length
-= CopyLength
;
473 Information
+= CopyLength
;
475 Fcb
->ReadDataAvailable
-= CopyLength
;
476 Fcb
->WriteQuotaAvailable
+= CopyLength
;
481 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
483 KeSetEvent(&Fcb
->OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
485 KeResetEvent(&Fcb
->ReadEvent
);
491 DPRINT("Message mode\n");
494 if (Fcb
->ReadDataAvailable
)
496 /* Truncate the message if the receive buffer is too small */
497 CopyLength
= RtlRosMin(Fcb
->ReadDataAvailable
, Length
);
498 memcpy(Buffer
, Fcb
->Data
, CopyLength
);
501 DPRINT("Length %d Buffer %x\n",CopyLength
,Buffer
);
502 HexDump((PUCHAR
)Buffer
, CopyLength
);
505 Information
= CopyLength
;
507 if (Fcb
->ReadDataAvailable
> Length
)
509 memmove(Fcb
->Data
, Fcb
->Data
+ Length
,
510 Fcb
->ReadDataAvailable
- Length
);
511 Fcb
->ReadDataAvailable
-= Length
;
512 Status
= STATUS_MORE_ENTRIES
;
516 KeResetEvent(&Fcb
->ReadEvent
);
517 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
519 KeSetEvent(&Fcb
->OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
521 Fcb
->ReadDataAvailable
= 0;
522 Fcb
->WriteQuotaAvailable
= Fcb
->MaxDataLength
;
532 Irp
->IoStatus
.Information
= Information
;
533 Irp
->IoStatus
.Status
= Status
;
535 if (IoIsOperationSynchronous(Irp
))
537 RemoveEntryList(&Context
->ListEntry
);
538 if (!IsListEmpty(&Fcb
->ReadRequestListHead
))
540 Context
= CONTAINING_RECORD(Fcb
->ReadRequestListHead
.Flink
, NPFS_CONTEXT
, ListEntry
);
541 KeSetEvent(Context
->WaitEvent
, IO_NO_INCREMENT
, FALSE
);
543 ExReleaseFastMutex(&Fcb
->DataListLock
);
544 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
546 DPRINT("NpfsRead done (Status %lx)\n", Status
);
551 if (IsOriginalRequest
)
553 IsOriginalRequest
= FALSE
;
554 OriginalStatus
= Status
;
556 if (Status
== STATUS_PENDING
)
558 ExReleaseFastMutex(&Fcb
->DataListLock
);
559 DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus
);
560 return OriginalStatus
;
562 RemoveEntryList(&Context
->ListEntry
);
563 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
564 if (IsListEmpty(&Fcb
->ReadRequestListHead
))
566 ExReleaseFastMutex(&Fcb
->DataListLock
);
567 DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus
);
568 return OriginalStatus
;
570 Context
= CONTAINING_RECORD(Fcb
->ReadRequestListHead
.Flink
, NPFS_CONTEXT
, ListEntry
);
571 Irp
= CONTAINING_RECORD(Context
, IRP
, Tail
.Overlay
.DriverContext
);
576 Irp
->IoStatus
.Status
= Status
;
578 if (Status
!= STATUS_PENDING
)
580 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
582 DPRINT("NpfsRead done (Status %lx)\n", Status
);
588 NpfsWrite(PDEVICE_OBJECT DeviceObject
,
591 PIO_STACK_LOCATION IoStack
;
592 PFILE_OBJECT FileObject
;
593 PNPFS_FCB Fcb
= NULL
;
595 PNPFS_PIPE Pipe
= NULL
;
597 NTSTATUS Status
= STATUS_SUCCESS
;
604 DPRINT("NpfsWrite()\n");
606 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
607 FileObject
= IoStack
->FileObject
;
608 DPRINT("FileObject %p\n", FileObject
);
609 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
611 Fcb
= FileObject
->FsContext
;
612 ReaderFcb
= Fcb
->OtherSide
;
615 Length
= IoStack
->Parameters
.Write
.Length
;
616 Offset
= IoStack
->Parameters
.Write
.ByteOffset
.u
.LowPart
;
619 if (Irp
->MdlAddress
== NULL
)
621 DPRINT("Irp->MdlAddress == NULL\n");
622 Status
= STATUS_UNSUCCESSFUL
;
627 if (ReaderFcb
== NULL
)
629 DPRINT("Pipe is NOT connected!\n");
630 if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
631 Status
= STATUS_PIPE_LISTENING
;
632 else if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
633 Status
= STATUS_PIPE_DISCONNECTED
;
635 Status
= STATUS_UNSUCCESSFUL
;
640 if (ReaderFcb
->Data
== NULL
)
642 DPRINT("Pipe is NOT writable!\n");
643 Status
= STATUS_UNSUCCESSFUL
;
648 Status
= STATUS_SUCCESS
;
649 Buffer
= MmGetSystemAddressForMdl (Irp
->MdlAddress
);
651 ExAcquireFastMutex(&ReaderFcb
->DataListLock
);
653 DPRINT("Length %d Buffer %x Offset %x\n",Length
,Buffer
,Offset
);
654 HexDump(Buffer
, Length
);
659 if (ReaderFcb
->WriteQuotaAvailable
== 0)
661 KeSetEvent(&ReaderFcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
662 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
664 Status
= STATUS_PIPE_BROKEN
;
665 ExReleaseFastMutex(&ReaderFcb
->DataListLock
);
668 ExReleaseFastMutex(&ReaderFcb
->DataListLock
);
670 DPRINT("Waiting for buffer space (%S)\n", Pipe
->PipeName
.Buffer
);
671 Status
= KeWaitForSingleObject(&Fcb
->WriteEvent
,
676 DPRINT("Finished waiting (%S)! Status: %x\n", Pipe
->PipeName
.Buffer
, Status
);
678 ExAcquireFastMutex(&ReaderFcb
->DataListLock
);
680 * It's possible that the event was signaled because the
681 * other side of pipe was closed.
683 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
685 DPRINT("PipeState: %x\n", Fcb
->PipeState
);
686 Status
= STATUS_PIPE_BROKEN
;
687 ExReleaseFastMutex(&ReaderFcb
->DataListLock
);
692 if (Pipe
->WriteMode
== FILE_PIPE_BYTE_STREAM_MODE
)
694 DPRINT("Byte stream mode\n");
695 while (Length
> 0 && ReaderFcb
->WriteQuotaAvailable
> 0)
697 CopyLength
= RtlRosMin(Length
, ReaderFcb
->WriteQuotaAvailable
);
698 if (ReaderFcb
->WritePtr
+ CopyLength
<= ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
)
700 memcpy(ReaderFcb
->WritePtr
, Buffer
, CopyLength
);
701 ReaderFcb
->WritePtr
+= CopyLength
;
702 if (ReaderFcb
->WritePtr
== ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
)
704 ReaderFcb
->WritePtr
= ReaderFcb
->Data
;
709 TempLength
= ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
- ReaderFcb
->WritePtr
;
710 memcpy(ReaderFcb
->WritePtr
, Buffer
, TempLength
);
711 memcpy(ReaderFcb
->Data
, Buffer
+ TempLength
, CopyLength
- TempLength
);
712 ReaderFcb
->WritePtr
= ReaderFcb
->Data
+ CopyLength
- TempLength
;
715 Buffer
+= CopyLength
;
716 Length
-= CopyLength
;
717 Information
+= CopyLength
;
719 ReaderFcb
->ReadDataAvailable
+= CopyLength
;
720 ReaderFcb
->WriteQuotaAvailable
-= CopyLength
;
725 KeSetEvent(&ReaderFcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
726 KeResetEvent(&Fcb
->WriteEvent
);
732 DPRINT("Message mode\n");
735 CopyLength
= RtlRosMin(Length
, ReaderFcb
->WriteQuotaAvailable
);
736 memcpy(ReaderFcb
->Data
, Buffer
, CopyLength
);
738 Information
= CopyLength
;
739 ReaderFcb
->ReadDataAvailable
= CopyLength
;
740 ReaderFcb
->WriteQuotaAvailable
= 0;
745 KeSetEvent(&ReaderFcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
746 KeResetEvent(&Fcb
->WriteEvent
);
752 ExReleaseFastMutex(&ReaderFcb
->DataListLock
);
755 Irp
->IoStatus
.Status
= Status
;
756 Irp
->IoStatus
.Information
= Information
;
758 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
760 DPRINT("NpfsWrite done (Status %lx)\n", Status
);