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");
47 NpfsReadWriteCancelRoutine(IN PDEVICE_OBJECT DeviceObject
,
50 PNPFS_CONTEXT Context
;
51 PNPFS_DEVICE_EXTENSION DeviceExt
;
52 PIO_STACK_LOCATION IoStack
;
54 BOOLEAN Complete
= FALSE
;
56 DPRINT("NpfsReadWriteCancelRoutine(DeviceObject %x, Irp %x)\n", DeviceObject
, Irp
);
58 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
60 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
61 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
62 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
63 Fcb
= IoStack
->FileObject
->FsContext
;
65 KeLockMutex(&DeviceExt
->PipeListLock
);
66 ExAcquireFastMutex(&Fcb
->DataListLock
);
67 switch(IoStack
->MajorFunction
)
70 if (Fcb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
72 /* we are not the first in the list, remove an complete us */
73 RemoveEntryList(&Context
->ListEntry
);
78 KeSetEvent(&Fcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
84 ExReleaseFastMutex(&Fcb
->DataListLock
);
85 KeUnlockMutex(&DeviceExt
->PipeListLock
);
88 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
89 Irp
->IoStatus
.Information
= 0;
90 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
95 NpfsWaiterThread(PVOID InitContext
)
97 PNPFS_THREAD_CONTEXT ThreadContext
= (PNPFS_THREAD_CONTEXT
) InitContext
;
103 BOOLEAN Terminate
= FALSE
;
104 BOOLEAN Cancel
= FALSE
;
105 PIO_STACK_LOCATION IoStack
= NULL
;
106 PNPFS_CONTEXT Context
;
107 PNPFS_CONTEXT NextContext
;
110 KeLockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
114 CurrentCount
= ThreadContext
->Count
;
115 KeUnlockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
120 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
121 Irp
->IoStatus
.Information
= 0;
122 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
126 switch (IoStack
->MajorFunction
)
129 NpfsRead(IoStack
->DeviceObject
, Irp
);
140 Status
= KeWaitForMultipleObjects(CurrentCount
,
141 ThreadContext
->WaitObjectArray
,
147 ThreadContext
->WaitBlockArray
);
148 if (!NT_SUCCESS(Status
))
152 KeLockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
153 Count
= Status
- STATUS_SUCCESS
;
154 ASSERT (Count
< CurrentCount
);
157 Irp
= ThreadContext
->WaitIrpArray
[Count
];
158 ThreadContext
->Count
--;
159 ThreadContext
->DeviceExt
->EmptyWaiterCount
++;
160 ThreadContext
->WaitObjectArray
[Count
] = ThreadContext
->WaitObjectArray
[ThreadContext
->Count
];
161 ThreadContext
->WaitIrpArray
[Count
] = ThreadContext
->WaitIrpArray
[ThreadContext
->Count
];
163 Cancel
= (NULL
== IoSetCancelRoutine(Irp
, NULL
));
164 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
165 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
169 Fcb
= IoStack
->FileObject
->FsContext
;
170 ExAcquireFastMutex(&Fcb
->DataListLock
);
171 RemoveEntryList(&Context
->ListEntry
);
172 switch (IoStack
->MajorFunction
)
175 if (!IsListEmpty(&Fcb
->ReadRequestListHead
))
177 /* put the next request on the wait list */
178 NextContext
= CONTAINING_RECORD(Fcb
->ReadRequestListHead
.Flink
, NPFS_CONTEXT
, ListEntry
);
179 ThreadContext
->WaitObjectArray
[ThreadContext
->Count
] = NextContext
->WaitEvent
;
180 NextIrp
= CONTAINING_RECORD(NextContext
, IRP
, Tail
.Overlay
.DriverContext
);
181 ThreadContext
->WaitIrpArray
[ThreadContext
->Count
] = NextIrp
;
182 ThreadContext
->Count
++;
183 ThreadContext
->DeviceExt
->EmptyWaiterCount
--;
185 KeUnlockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
190 ExReleaseFastMutex(&Fcb
->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 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
;
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 Fcb
= FileObject
->FsContext
;
320 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
322 if (Fcb
->Data
== NULL
)
324 DPRINT1("Pipe is NOT readable!\n");
325 Status
= STATUS_UNSUCCESSFUL
;
326 Irp
->IoStatus
.Information
= 0;
330 ExAcquireFastMutex(&Fcb
->DataListLock
);
332 if (IoIsOperationSynchronous(Irp
))
334 InsertTailList(&Fcb
->ReadRequestListHead
, &Context
->ListEntry
);
335 if (Fcb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
337 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
338 Context
->WaitEvent
= &Event
;
339 ExReleaseFastMutex(&Fcb
->DataListLock
);
340 Status
= KeWaitForSingleObject(&Event
,
345 if (!NT_SUCCESS(Status
))
349 ExAcquireFastMutex(&Fcb
->DataListLock
);
351 Irp
->IoStatus
.Information
= 0;
356 if (IsListEmpty(&Fcb
->ReadRequestListHead
) ||
357 Fcb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
359 /* this is a new request */
360 Irp
->IoStatus
.Information
= 0;
361 Context
->WaitEvent
= &Fcb
->ReadEvent
;
362 InsertTailList(&Fcb
->ReadRequestListHead
, &Context
->ListEntry
);
363 if (Fcb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
365 /* there was already a request on the list */
366 IoAcquireCancelSpinLock(&oldIrql
);
369 IoReleaseCancelSpinLock(oldIrql
);
370 RemoveEntryList(&Context
->ListEntry
);
371 ExReleaseFastMutex(&Fcb
->DataListLock
);
372 Status
= STATUS_CANCELLED
;
375 IoSetCancelRoutine(Irp
, NpfsReadWriteCancelRoutine
);
376 IoReleaseCancelSpinLock(oldIrql
);
377 ExReleaseFastMutex(&Fcb
->DataListLock
);
378 IoMarkIrpPending(Irp
);
379 Status
= STATUS_PENDING
;
387 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
388 Information
= Irp
->IoStatus
.Information
;
389 Length
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.Read
.Length
;
390 ASSERT (Information
<= Length
);
391 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ Information
);
392 Length
-= Information
;
393 Status
= STATUS_SUCCESS
;
397 if (Fcb
->ReadDataAvailable
== 0)
399 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
401 ASSERT(Fcb
->OtherSide
!= NULL
);
402 KeSetEvent(&Fcb
->OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
404 if (Information
> 0 &&
405 (Fcb
->Pipe
->ReadMode
!= FILE_PIPE_BYTE_STREAM_MODE
||
406 Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
))
410 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
412 DPRINT("PipeState: %x\n", Fcb
->PipeState
);
413 Status
= STATUS_PIPE_BROKEN
;
416 ExReleaseFastMutex(&Fcb
->DataListLock
);
417 if (IoIsOperationSynchronous(Irp
))
419 /* Wait for ReadEvent to become signaled */
421 DPRINT("Waiting for readable data (%wZ)\n", &Fcb
->Pipe
->PipeName
);
422 Status
= KeWaitForSingleObject(&Fcb
->ReadEvent
,
427 DPRINT("Finished waiting (%wZ)! Status: %x\n", &Fcb
->Pipe
->PipeName
, Status
);
428 ExAcquireFastMutex(&Fcb
->DataListLock
);
432 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
434 Context
->WaitEvent
= &Fcb
->ReadEvent
;
435 Status
= NpfsAddWaitingReadWriteRequest(DeviceObject
, Irp
);
437 if (NT_SUCCESS(Status
))
439 Status
= STATUS_PENDING
;
441 ExAcquireFastMutex(&Fcb
->DataListLock
);
445 ASSERT(IoGetCurrentIrpStackLocation(Irp
)->FileObject
!= NULL
);
446 if (Fcb
->Pipe
->ReadMode
== FILE_PIPE_BYTE_STREAM_MODE
)
448 DPRINT("Byte stream mode\n");
449 /* Byte stream mode */
450 while (Length
> 0 && Fcb
->ReadDataAvailable
> 0)
452 CopyLength
= min(Fcb
->ReadDataAvailable
, Length
);
453 if ((ULONG_PTR
)Fcb
->ReadPtr
+ CopyLength
<= (ULONG_PTR
)Fcb
->Data
+ Fcb
->MaxDataLength
)
455 memcpy(Buffer
, Fcb
->ReadPtr
, CopyLength
);
456 Fcb
->ReadPtr
= (PVOID
)((ULONG_PTR
)Fcb
->ReadPtr
+ CopyLength
);
457 if (Fcb
->ReadPtr
== (PVOID
)((ULONG_PTR
)Fcb
->Data
+ Fcb
->MaxDataLength
))
459 Fcb
->ReadPtr
= Fcb
->Data
;
464 TempLength
= (ULONG
)((ULONG_PTR
)Fcb
->Data
+ Fcb
->MaxDataLength
- (ULONG_PTR
)Fcb
->ReadPtr
);
465 memcpy(Buffer
, Fcb
->ReadPtr
, TempLength
);
466 memcpy((PVOID
)((ULONG_PTR
)Buffer
+ TempLength
), Fcb
->Data
, CopyLength
- TempLength
);
467 Fcb
->ReadPtr
= (PVOID
)((ULONG_PTR
)Fcb
->Data
+ CopyLength
- TempLength
);
470 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ CopyLength
);
471 Length
-= CopyLength
;
472 Information
+= CopyLength
;
474 Fcb
->ReadDataAvailable
-= CopyLength
;
475 Fcb
->WriteQuotaAvailable
+= CopyLength
;
480 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
482 KeSetEvent(&Fcb
->OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
484 KeResetEvent(&Fcb
->ReadEvent
);
490 DPRINT("Message mode\n");
493 if (Fcb
->ReadDataAvailable
)
495 /* Truncate the message if the receive buffer is too small */
496 CopyLength
= min(Fcb
->ReadDataAvailable
, Length
);
497 memcpy(Buffer
, Fcb
->Data
, CopyLength
);
500 DPRINT("Length %d Buffer %x\n",CopyLength
,Buffer
);
501 HexDump((PUCHAR
)Buffer
, CopyLength
);
504 Information
= CopyLength
;
506 if (Fcb
->ReadDataAvailable
> Length
)
508 memmove(Fcb
->Data
, (PVOID
)((ULONG_PTR
)Fcb
->Data
+ Length
),
509 Fcb
->ReadDataAvailable
- Length
);
510 Fcb
->ReadDataAvailable
-= Length
;
511 Status
= STATUS_MORE_ENTRIES
;
515 KeResetEvent(&Fcb
->ReadEvent
);
516 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
518 KeSetEvent(&Fcb
->OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
520 Fcb
->ReadDataAvailable
= 0;
521 Fcb
->WriteQuotaAvailable
= Fcb
->MaxDataLength
;
531 Irp
->IoStatus
.Information
= Information
;
532 Irp
->IoStatus
.Status
= Status
;
534 ASSERT(IoGetCurrentIrpStackLocation(Irp
)->FileObject
!= NULL
);
536 if (IoIsOperationSynchronous(Irp
))
538 RemoveEntryList(&Context
->ListEntry
);
539 if (!IsListEmpty(&Fcb
->ReadRequestListHead
))
541 Context
= CONTAINING_RECORD(Fcb
->ReadRequestListHead
.Flink
, NPFS_CONTEXT
, ListEntry
);
542 KeSetEvent(Context
->WaitEvent
, IO_NO_INCREMENT
, FALSE
);
544 ExReleaseFastMutex(&Fcb
->DataListLock
);
545 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
547 DPRINT("NpfsRead done (Status %lx)\n", Status
);
552 if (IsOriginalRequest
)
554 IsOriginalRequest
= FALSE
;
555 OriginalStatus
= Status
;
557 if (Status
== STATUS_PENDING
)
559 ExReleaseFastMutex(&Fcb
->DataListLock
);
560 DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus
);
561 return OriginalStatus
;
563 RemoveEntryList(&Context
->ListEntry
);
564 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
565 if (IsListEmpty(&Fcb
->ReadRequestListHead
))
567 ExReleaseFastMutex(&Fcb
->DataListLock
);
568 DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus
);
569 return OriginalStatus
;
571 Context
= CONTAINING_RECORD(Fcb
->ReadRequestListHead
.Flink
, NPFS_CONTEXT
, ListEntry
);
572 Irp
= CONTAINING_RECORD(Context
, IRP
, Tail
.Overlay
.DriverContext
);
577 Irp
->IoStatus
.Status
= Status
;
579 if (Status
!= STATUS_PENDING
)
581 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
583 DPRINT("NpfsRead done (Status %lx)\n", Status
);
589 NpfsWrite(PDEVICE_OBJECT DeviceObject
,
592 PIO_STACK_LOCATION IoStack
;
593 PFILE_OBJECT FileObject
;
594 PNPFS_FCB Fcb
= NULL
;
596 PNPFS_PIPE Pipe
= NULL
;
598 NTSTATUS Status
= STATUS_SUCCESS
;
605 DPRINT("NpfsWrite()\n");
607 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
608 FileObject
= IoStack
->FileObject
;
609 DPRINT("FileObject %p\n", FileObject
);
610 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
612 Fcb
= FileObject
->FsContext
;
613 ReaderFcb
= Fcb
->OtherSide
;
616 Length
= IoStack
->Parameters
.Write
.Length
;
617 Offset
= IoStack
->Parameters
.Write
.ByteOffset
.u
.LowPart
;
620 if (Irp
->MdlAddress
== NULL
)
622 DPRINT("Irp->MdlAddress == NULL\n");
623 Status
= STATUS_UNSUCCESSFUL
;
628 if (ReaderFcb
== NULL
)
630 DPRINT("Pipe is NOT connected!\n");
631 if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
632 Status
= STATUS_PIPE_LISTENING
;
633 else if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
634 Status
= STATUS_PIPE_DISCONNECTED
;
636 Status
= STATUS_UNSUCCESSFUL
;
641 if (ReaderFcb
->Data
== NULL
)
643 DPRINT("Pipe is NOT writable!\n");
644 Status
= STATUS_UNSUCCESSFUL
;
649 Status
= STATUS_SUCCESS
;
650 Buffer
= MmGetSystemAddressForMdl (Irp
->MdlAddress
);
652 ExAcquireFastMutex(&ReaderFcb
->DataListLock
);
654 DPRINT("Length %d Buffer %x Offset %x\n",Length
,Buffer
,Offset
);
655 HexDump(Buffer
, Length
);
660 if (ReaderFcb
->WriteQuotaAvailable
== 0)
662 KeSetEvent(&ReaderFcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
663 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
665 Status
= STATUS_PIPE_BROKEN
;
666 ExReleaseFastMutex(&ReaderFcb
->DataListLock
);
669 ExReleaseFastMutex(&ReaderFcb
->DataListLock
);
671 DPRINT("Waiting for buffer space (%S)\n", Pipe
->PipeName
.Buffer
);
672 Status
= KeWaitForSingleObject(&Fcb
->WriteEvent
,
677 DPRINT("Finished waiting (%S)! Status: %x\n", Pipe
->PipeName
.Buffer
, Status
);
679 ExAcquireFastMutex(&ReaderFcb
->DataListLock
);
681 * It's possible that the event was signaled because the
682 * other side of pipe was closed.
684 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
686 DPRINT("PipeState: %x\n", Fcb
->PipeState
);
687 Status
= STATUS_PIPE_BROKEN
;
688 ExReleaseFastMutex(&ReaderFcb
->DataListLock
);
693 if (Pipe
->WriteMode
== FILE_PIPE_BYTE_STREAM_MODE
)
695 DPRINT("Byte stream mode\n");
696 while (Length
> 0 && ReaderFcb
->WriteQuotaAvailable
> 0)
698 CopyLength
= min(Length
, ReaderFcb
->WriteQuotaAvailable
);
699 if ((ULONG_PTR
)ReaderFcb
->WritePtr
+ CopyLength
<= (ULONG_PTR
)ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
)
701 memcpy(ReaderFcb
->WritePtr
, Buffer
, CopyLength
);
702 ReaderFcb
->WritePtr
= (PVOID
)((ULONG_PTR
)ReaderFcb
->WritePtr
+ CopyLength
);
703 if ((ULONG_PTR
)ReaderFcb
->WritePtr
== (ULONG_PTR
)ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
)
705 ReaderFcb
->WritePtr
= ReaderFcb
->Data
;
710 TempLength
= (ULONG
)((ULONG_PTR
)ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
- (ULONG_PTR
)ReaderFcb
->WritePtr
);
711 memcpy(ReaderFcb
->WritePtr
, Buffer
, TempLength
);
712 memcpy(ReaderFcb
->Data
, Buffer
+ TempLength
, CopyLength
- TempLength
);
713 ReaderFcb
->WritePtr
= (PVOID
)((ULONG_PTR
)ReaderFcb
->Data
+ CopyLength
- TempLength
);
716 Buffer
+= CopyLength
;
717 Length
-= CopyLength
;
718 Information
+= CopyLength
;
720 ReaderFcb
->ReadDataAvailable
+= CopyLength
;
721 ReaderFcb
->WriteQuotaAvailable
-= CopyLength
;
726 KeSetEvent(&ReaderFcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
727 KeResetEvent(&Fcb
->WriteEvent
);
733 DPRINT("Message mode\n");
736 CopyLength
= min(Length
, ReaderFcb
->WriteQuotaAvailable
);
737 memcpy(ReaderFcb
->Data
, Buffer
, CopyLength
);
739 Information
= CopyLength
;
740 ReaderFcb
->ReadDataAvailable
= CopyLength
;
741 ReaderFcb
->WriteQuotaAvailable
= 0;
746 KeSetEvent(&ReaderFcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
747 KeResetEvent(&Fcb
->WriteEvent
);
753 ExReleaseFastMutex(&ReaderFcb
->DataListLock
);
756 Irp
->IoStatus
.Status
= Status
;
757 Irp
->IoStatus
.Information
= Information
;
759 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
761 DPRINT("NpfsWrite done (Status %lx)\n", Status
);