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 ******************************************************************/
18 /* FUNCTIONS *****************************************************************/
21 VOID
HexDump(PUCHAR Buffer
, ULONG Length
)
25 const char Hex
[] = "0123456789ABCDEF";
28 DbgPrint("---------------\n");
30 for (i
= 0; i
< Length
; i
+= 16)
32 memset(Line
, ' ', 64);
35 for (j
= 0; j
< 16 && j
+ i
< Length
; j
++)
38 Line
[3*j
+ 0] = Hex
[ch
>> 4];
39 Line
[3*j
+ 1] = Hex
[ch
& 0x0f];
40 Line
[48 + j
] = isprint(ch
) ? ch
: '.';
42 DbgPrint("%s\n", Line
);
44 DbgPrint("---------------\n");
49 NpfsReadWriteCancelRoutine(IN PDEVICE_OBJECT DeviceObject
,
52 PNPFS_CONTEXT Context
;
53 PNPFS_DEVICE_EXTENSION DeviceExt
;
54 PIO_STACK_LOCATION IoStack
;
56 BOOLEAN Complete
= FALSE
;
58 DPRINT("NpfsReadWriteCancelRoutine(DeviceObject %x, Irp %x)\n", DeviceObject
, Irp
);
60 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
62 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
63 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
64 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
65 Fcb
= IoStack
->FileObject
->FsContext
;
67 KeLockMutex(&DeviceExt
->PipeListLock
);
68 ExAcquireFastMutex(&Fcb
->DataListLock
);
69 switch(IoStack
->MajorFunction
)
72 if (Fcb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
74 /* we are not the first in the list, remove an complete us */
75 RemoveEntryList(&Context
->ListEntry
);
80 KeSetEvent(&Fcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
86 ExReleaseFastMutex(&Fcb
->DataListLock
);
87 KeUnlockMutex(&DeviceExt
->PipeListLock
);
90 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
91 Irp
->IoStatus
.Information
= 0;
92 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
97 NpfsWaiterThread(PVOID InitContext
)
99 PNPFS_THREAD_CONTEXT ThreadContext
= (PNPFS_THREAD_CONTEXT
) InitContext
;
105 BOOLEAN Terminate
= FALSE
;
106 BOOLEAN Cancel
= FALSE
;
107 PIO_STACK_LOCATION IoStack
= NULL
;
108 PNPFS_CONTEXT Context
;
109 PNPFS_CONTEXT NextContext
;
112 KeLockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
116 CurrentCount
= ThreadContext
->Count
;
117 KeUnlockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
122 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
123 Irp
->IoStatus
.Information
= 0;
124 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
128 switch (IoStack
->MajorFunction
)
131 NpfsRead(IoStack
->DeviceObject
, Irp
);
142 Status
= KeWaitForMultipleObjects(CurrentCount
,
143 ThreadContext
->WaitObjectArray
,
149 ThreadContext
->WaitBlockArray
);
150 if (!NT_SUCCESS(Status
))
154 KeLockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
155 Count
= Status
- STATUS_SUCCESS
;
156 ASSERT (Count
< CurrentCount
);
159 Irp
= ThreadContext
->WaitIrpArray
[Count
];
160 ThreadContext
->Count
--;
161 ThreadContext
->DeviceExt
->EmptyWaiterCount
++;
162 ThreadContext
->WaitObjectArray
[Count
] = ThreadContext
->WaitObjectArray
[ThreadContext
->Count
];
163 ThreadContext
->WaitIrpArray
[Count
] = ThreadContext
->WaitIrpArray
[ThreadContext
->Count
];
165 Cancel
= (NULL
== IoSetCancelRoutine(Irp
, NULL
));
166 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
167 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
171 Fcb
= IoStack
->FileObject
->FsContext
;
172 ExAcquireFastMutex(&Fcb
->DataListLock
);
173 RemoveEntryList(&Context
->ListEntry
);
174 switch (IoStack
->MajorFunction
)
177 if (!IsListEmpty(&Fcb
->ReadRequestListHead
))
179 /* put the next request on the wait list */
180 NextContext
= CONTAINING_RECORD(Fcb
->ReadRequestListHead
.Flink
, NPFS_CONTEXT
, ListEntry
);
181 ThreadContext
->WaitObjectArray
[ThreadContext
->Count
] = NextContext
->WaitEvent
;
182 NextIrp
= CONTAINING_RECORD(NextContext
, IRP
, Tail
.Overlay
.DriverContext
);
183 ThreadContext
->WaitIrpArray
[ThreadContext
->Count
] = NextIrp
;
184 ThreadContext
->Count
++;
185 ThreadContext
->DeviceExt
->EmptyWaiterCount
--;
187 KeUnlockMutex(&ThreadContext
->DeviceExt
->PipeListLock
);
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 ExFreePool(ThreadContext
);
212 NpfsAddWaitingReadWriteRequest(IN PDEVICE_OBJECT DeviceObject
,
215 PLIST_ENTRY ListEntry
;
216 PNPFS_THREAD_CONTEXT ThreadContext
= NULL
;
221 PNPFS_CONTEXT Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
222 PNPFS_DEVICE_EXTENSION DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
224 DPRINT("NpfsAddWaitingReadWriteRequest(DeviceObject %p, Irp %p)\n", DeviceObject
, Irp
);
226 KeLockMutex(&DeviceExt
->PipeListLock
);
228 ListEntry
= DeviceExt
->ThreadListHead
.Flink
;
229 while (ListEntry
!= &DeviceExt
->ThreadListHead
)
231 ThreadContext
= CONTAINING_RECORD(ListEntry
, NPFS_THREAD_CONTEXT
, ListEntry
);
232 if (ThreadContext
->Count
< MAXIMUM_WAIT_OBJECTS
)
236 ListEntry
= ListEntry
->Flink
;
238 if (ListEntry
== &DeviceExt
->ThreadListHead
)
240 ThreadContext
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_THREAD_CONTEXT
));
241 if (ThreadContext
== NULL
)
243 KeUnlockMutex(&DeviceExt
->PipeListLock
);
244 return STATUS_NO_MEMORY
;
246 ThreadContext
->DeviceExt
= DeviceExt
;
247 KeInitializeEvent(&ThreadContext
->Event
, SynchronizationEvent
, FALSE
);
248 ThreadContext
->Count
= 1;
249 ThreadContext
->WaitObjectArray
[0] = &ThreadContext
->Event
;
252 DPRINT("Creating a new system thread for waiting read/write requests\n");
254 Status
= PsCreateSystemThread(&hThread
,
260 (PVOID
)ThreadContext
);
261 if (!NT_SUCCESS(Status
))
263 ExFreePool(ThreadContext
);
264 KeUnlockMutex(&DeviceExt
->PipeListLock
);
267 InsertHeadList(&DeviceExt
->ThreadListHead
, &ThreadContext
->ListEntry
);
268 DeviceExt
->EmptyWaiterCount
+= MAXIMUM_WAIT_OBJECTS
- 1;
270 IoMarkIrpPending(Irp
);
272 IoAcquireCancelSpinLock(&oldIrql
);
275 IoReleaseCancelSpinLock(oldIrql
);
276 Status
= STATUS_CANCELLED
;
280 IoSetCancelRoutine(Irp
, NpfsReadWriteCancelRoutine
);
281 IoReleaseCancelSpinLock(oldIrql
);
282 ThreadContext
->WaitObjectArray
[ThreadContext
->Count
] = Context
->WaitEvent
;
283 ThreadContext
->WaitIrpArray
[ThreadContext
->Count
] = Irp
;
284 ThreadContext
->Count
++;
285 DeviceExt
->EmptyWaiterCount
--;
286 KeSetEvent(&ThreadContext
->Event
, IO_NO_INCREMENT
, FALSE
);
287 Status
= STATUS_SUCCESS
;
289 KeUnlockMutex(&DeviceExt
->PipeListLock
);
294 NpfsRead(IN PDEVICE_OBJECT DeviceObject
,
297 PFILE_OBJECT FileObject
;
299 NTSTATUS OriginalStatus
= STATUS_SUCCESS
;
301 PNPFS_CONTEXT Context
;
307 BOOLEAN IsOriginalRequest
= TRUE
;
310 DPRINT("NpfsRead(DeviceObject %p, Irp %p)\n", DeviceObject
, Irp
);
312 if (Irp
->MdlAddress
== NULL
)
314 DPRINT("Irp->MdlAddress == NULL\n");
315 Status
= STATUS_UNSUCCESSFUL
;
316 Irp
->IoStatus
.Information
= 0;
320 FileObject
= IoGetCurrentIrpStackLocation(Irp
)->FileObject
;
321 Fcb
= FileObject
->FsContext
;
322 Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
324 if (Fcb
->Data
== NULL
)
326 DPRINT1("Pipe is NOT readable!\n");
327 Status
= STATUS_UNSUCCESSFUL
;
328 Irp
->IoStatus
.Information
= 0;
332 ExAcquireFastMutex(&Fcb
->DataListLock
);
334 if (IoIsOperationSynchronous(Irp
))
336 InsertTailList(&Fcb
->ReadRequestListHead
, &Context
->ListEntry
);
337 if (Fcb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
339 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
340 Context
->WaitEvent
= &Event
;
341 ExReleaseFastMutex(&Fcb
->DataListLock
);
342 Status
= KeWaitForSingleObject(&Event
,
347 if (!NT_SUCCESS(Status
))
351 ExAcquireFastMutex(&Fcb
->DataListLock
);
353 Irp
->IoStatus
.Information
= 0;
358 if (IsListEmpty(&Fcb
->ReadRequestListHead
) ||
359 Fcb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
361 /* this is a new request */
362 Irp
->IoStatus
.Information
= 0;
363 Context
->WaitEvent
= &Fcb
->ReadEvent
;
364 InsertTailList(&Fcb
->ReadRequestListHead
, &Context
->ListEntry
);
365 if (Fcb
->ReadRequestListHead
.Flink
!= &Context
->ListEntry
)
367 /* there was already a request on the list */
368 IoAcquireCancelSpinLock(&oldIrql
);
371 IoReleaseCancelSpinLock(oldIrql
);
372 RemoveEntryList(&Context
->ListEntry
);
373 ExReleaseFastMutex(&Fcb
->DataListLock
);
374 Status
= STATUS_CANCELLED
;
377 IoSetCancelRoutine(Irp
, NpfsReadWriteCancelRoutine
);
378 IoReleaseCancelSpinLock(oldIrql
);
379 ExReleaseFastMutex(&Fcb
->DataListLock
);
380 IoMarkIrpPending(Irp
);
381 Status
= STATUS_PENDING
;
389 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
390 Information
= Irp
->IoStatus
.Information
;
391 Length
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.Read
.Length
;
392 ASSERT (Information
<= Length
);
393 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ Information
);
394 Length
-= Information
;
395 Status
= STATUS_SUCCESS
;
399 if (Fcb
->ReadDataAvailable
== 0)
401 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
403 DPRINT("PipeState: %x\n", Fcb
->PipeState
);
404 if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
405 Status
= STATUS_PIPE_LISTENING
;
407 Status
= STATUS_PIPE_DISCONNECTED
;
411 ASSERT(Fcb
->OtherSide
!= NULL
);
412 KeSetEvent(&Fcb
->OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
414 if (Information
> 0 &&
415 Fcb
->Pipe
->ReadMode
!= FILE_PIPE_BYTE_STREAM_MODE
)
420 ExReleaseFastMutex(&Fcb
->DataListLock
);
421 if (IoIsOperationSynchronous(Irp
))
423 /* Wait for ReadEvent to become signaled */
425 DPRINT("Waiting for readable data (%wZ)\n", &Fcb
->Pipe
->PipeName
);
426 Status
= KeWaitForSingleObject(&Fcb
->ReadEvent
,
431 DPRINT("Finished waiting (%wZ)! Status: %x\n", &Fcb
->Pipe
->PipeName
, Status
);
432 ExAcquireFastMutex(&Fcb
->DataListLock
);
436 PNPFS_CONTEXT Context
= (PNPFS_CONTEXT
)&Irp
->Tail
.Overlay
.DriverContext
;
438 Context
->WaitEvent
= &Fcb
->ReadEvent
;
439 Status
= NpfsAddWaitingReadWriteRequest(DeviceObject
, Irp
);
441 if (NT_SUCCESS(Status
))
443 Status
= STATUS_PENDING
;
445 ExAcquireFastMutex(&Fcb
->DataListLock
);
449 if (Fcb
->Pipe
->ReadMode
== FILE_PIPE_BYTE_STREAM_MODE
)
451 DPRINT("Byte stream mode\n");
452 /* Byte stream mode */
453 while (Length
> 0 && Fcb
->ReadDataAvailable
> 0)
455 CopyLength
= min(Fcb
->ReadDataAvailable
, Length
);
456 if ((ULONG_PTR
)Fcb
->ReadPtr
+ CopyLength
<= (ULONG_PTR
)Fcb
->Data
+ Fcb
->MaxDataLength
)
458 memcpy(Buffer
, Fcb
->ReadPtr
, CopyLength
);
459 Fcb
->ReadPtr
= (PVOID
)((ULONG_PTR
)Fcb
->ReadPtr
+ CopyLength
);
460 if (Fcb
->ReadPtr
== (PVOID
)((ULONG_PTR
)Fcb
->Data
+ Fcb
->MaxDataLength
))
462 Fcb
->ReadPtr
= Fcb
->Data
;
467 TempLength
= (ULONG
)((ULONG_PTR
)Fcb
->Data
+ Fcb
->MaxDataLength
- (ULONG_PTR
)Fcb
->ReadPtr
);
468 memcpy(Buffer
, Fcb
->ReadPtr
, TempLength
);
469 memcpy((PVOID
)((ULONG_PTR
)Buffer
+ TempLength
), Fcb
->Data
, CopyLength
- TempLength
);
470 Fcb
->ReadPtr
= (PVOID
)((ULONG_PTR
)Fcb
->Data
+ CopyLength
- TempLength
);
473 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ CopyLength
);
474 Length
-= CopyLength
;
475 Information
+= CopyLength
;
477 Fcb
->ReadDataAvailable
-= CopyLength
;
478 Fcb
->WriteQuotaAvailable
+= CopyLength
;
483 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
485 KeSetEvent(&Fcb
->OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
487 KeResetEvent(&Fcb
->ReadEvent
);
493 DPRINT("Message mode\n");
496 if (Fcb
->ReadDataAvailable
)
498 /* Truncate the message if the receive buffer is too small */
499 CopyLength
= min(Fcb
->ReadDataAvailable
, Length
);
500 memcpy(Buffer
, Fcb
->Data
, CopyLength
);
503 DPRINT("Length %d Buffer %x\n",CopyLength
,Buffer
);
504 HexDump((PUCHAR
)Buffer
, CopyLength
);
507 Information
= CopyLength
;
509 if (Fcb
->ReadDataAvailable
> Length
)
511 memmove(Fcb
->Data
, (PVOID
)((ULONG_PTR
)Fcb
->Data
+ Length
),
512 Fcb
->ReadDataAvailable
- Length
);
513 Fcb
->ReadDataAvailable
-= Length
;
514 Status
= STATUS_MORE_ENTRIES
;
518 KeResetEvent(&Fcb
->ReadEvent
);
519 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
521 KeSetEvent(&Fcb
->OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
523 Fcb
->ReadDataAvailable
= 0;
524 Fcb
->WriteQuotaAvailable
= Fcb
->MaxDataLength
;
534 Irp
->IoStatus
.Information
= Information
;
535 Irp
->IoStatus
.Status
= Status
;
537 if (IoIsOperationSynchronous(Irp
))
539 RemoveEntryList(&Context
->ListEntry
);
540 if (!IsListEmpty(&Fcb
->ReadRequestListHead
))
542 Context
= CONTAINING_RECORD(Fcb
->ReadRequestListHead
.Flink
, NPFS_CONTEXT
, ListEntry
);
543 KeSetEvent(Context
->WaitEvent
, IO_NO_INCREMENT
, FALSE
);
545 ExReleaseFastMutex(&Fcb
->DataListLock
);
546 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
548 DPRINT("NpfsRead done (Status %lx)\n", Status
);
553 if (IsOriginalRequest
)
555 IsOriginalRequest
= FALSE
;
556 OriginalStatus
= Status
;
558 if (Status
== STATUS_PENDING
)
560 ExReleaseFastMutex(&Fcb
->DataListLock
);
561 DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus
);
562 return OriginalStatus
;
564 RemoveEntryList(&Context
->ListEntry
);
565 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
566 if (IsListEmpty(&Fcb
->ReadRequestListHead
))
568 ExReleaseFastMutex(&Fcb
->DataListLock
);
569 DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus
);
570 return OriginalStatus
;
572 Context
= CONTAINING_RECORD(Fcb
->ReadRequestListHead
.Flink
, NPFS_CONTEXT
, ListEntry
);
573 Irp
= CONTAINING_RECORD(Context
, IRP
, Tail
.Overlay
.DriverContext
);
578 Irp
->IoStatus
.Status
= Status
;
580 if (Status
!= STATUS_PENDING
)
582 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
584 DPRINT("NpfsRead done (Status %lx)\n", Status
);
590 NpfsWrite(PDEVICE_OBJECT DeviceObject
,
593 PIO_STACK_LOCATION IoStack
;
594 PFILE_OBJECT FileObject
;
595 PNPFS_FCB Fcb
= NULL
;
597 PNPFS_PIPE Pipe
= NULL
;
599 NTSTATUS Status
= STATUS_SUCCESS
;
606 DPRINT("NpfsWrite()\n");
608 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
609 FileObject
= IoStack
->FileObject
;
610 DPRINT("FileObject %p\n", FileObject
);
611 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
613 Fcb
= FileObject
->FsContext
;
614 ReaderFcb
= Fcb
->OtherSide
;
617 Length
= IoStack
->Parameters
.Write
.Length
;
618 Offset
= IoStack
->Parameters
.Write
.ByteOffset
.u
.LowPart
;
621 if (Irp
->MdlAddress
== NULL
)
623 DPRINT("Irp->MdlAddress == NULL\n");
624 Status
= STATUS_UNSUCCESSFUL
;
629 if (ReaderFcb
== NULL
)
631 DPRINT("Pipe is NOT connected!\n");
632 if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
633 Status
= STATUS_PIPE_LISTENING
;
634 else if (Fcb
->PipeState
== FILE_PIPE_DISCONNECTED_STATE
)
635 Status
= STATUS_PIPE_DISCONNECTED
;
637 Status
= STATUS_UNSUCCESSFUL
;
642 if (ReaderFcb
->Data
== NULL
)
644 DPRINT("Pipe is NOT writable!\n");
645 Status
= STATUS_UNSUCCESSFUL
;
650 Status
= STATUS_SUCCESS
;
651 Buffer
= MmGetSystemAddressForMdl (Irp
->MdlAddress
);
653 ExAcquireFastMutex(&ReaderFcb
->DataListLock
);
655 DPRINT("Length %d Buffer %x Offset %x\n",Length
,Buffer
,Offset
);
656 HexDump(Buffer
, Length
);
661 if (ReaderFcb
->WriteQuotaAvailable
== 0)
663 KeSetEvent(&ReaderFcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
664 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
666 Status
= STATUS_PIPE_BROKEN
;
667 ExReleaseFastMutex(&ReaderFcb
->DataListLock
);
670 ExReleaseFastMutex(&ReaderFcb
->DataListLock
);
672 DPRINT("Waiting for buffer space (%S)\n", Pipe
->PipeName
.Buffer
);
673 Status
= KeWaitForSingleObject(&Fcb
->WriteEvent
,
678 DPRINT("Finished waiting (%S)! Status: %x\n", Pipe
->PipeName
.Buffer
, Status
);
680 ExAcquireFastMutex(&ReaderFcb
->DataListLock
);
682 * It's possible that the event was signaled because the
683 * other side of pipe was closed.
685 if (Fcb
->PipeState
!= FILE_PIPE_CONNECTED_STATE
)
687 DPRINT("PipeState: %x\n", Fcb
->PipeState
);
688 Status
= STATUS_PIPE_BROKEN
;
689 ExReleaseFastMutex(&ReaderFcb
->DataListLock
);
694 if (Pipe
->WriteMode
== FILE_PIPE_BYTE_STREAM_MODE
)
696 DPRINT("Byte stream mode\n");
697 while (Length
> 0 && ReaderFcb
->WriteQuotaAvailable
> 0)
699 CopyLength
= min(Length
, ReaderFcb
->WriteQuotaAvailable
);
700 if ((ULONG_PTR
)ReaderFcb
->WritePtr
+ CopyLength
<= (ULONG_PTR
)ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
)
702 memcpy(ReaderFcb
->WritePtr
, Buffer
, CopyLength
);
703 ReaderFcb
->WritePtr
= (PVOID
)((ULONG_PTR
)ReaderFcb
->WritePtr
+ CopyLength
);
704 if ((ULONG_PTR
)ReaderFcb
->WritePtr
== (ULONG_PTR
)ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
)
706 ReaderFcb
->WritePtr
= ReaderFcb
->Data
;
711 TempLength
= (ULONG
)((ULONG_PTR
)ReaderFcb
->Data
+ ReaderFcb
->MaxDataLength
- (ULONG_PTR
)ReaderFcb
->WritePtr
);
712 memcpy(ReaderFcb
->WritePtr
, Buffer
, TempLength
);
713 memcpy(ReaderFcb
->Data
, Buffer
+ TempLength
, CopyLength
- TempLength
);
714 ReaderFcb
->WritePtr
= (PVOID
)((ULONG_PTR
)ReaderFcb
->Data
+ CopyLength
- TempLength
);
717 Buffer
+= CopyLength
;
718 Length
-= CopyLength
;
719 Information
+= CopyLength
;
721 ReaderFcb
->ReadDataAvailable
+= CopyLength
;
722 ReaderFcb
->WriteQuotaAvailable
-= CopyLength
;
727 KeSetEvent(&ReaderFcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
728 KeResetEvent(&Fcb
->WriteEvent
);
734 DPRINT("Message mode\n");
737 CopyLength
= min(Length
, ReaderFcb
->WriteQuotaAvailable
);
738 memcpy(ReaderFcb
->Data
, Buffer
, CopyLength
);
740 Information
= CopyLength
;
741 ReaderFcb
->ReadDataAvailable
= CopyLength
;
742 ReaderFcb
->WriteQuotaAvailable
= 0;
747 KeSetEvent(&ReaderFcb
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
748 KeResetEvent(&Fcb
->WriteEvent
);
754 ExReleaseFastMutex(&ReaderFcb
->DataListLock
);
757 Irp
->IoStatus
.Status
= Status
;
758 Irp
->IoStatus
.Information
= Information
;
760 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
762 DPRINT("NpfsWrite done (Status %lx)\n", Status
);