xref: /reactos/drivers/filesystems/npfs/readsup.c (revision b09b5584)
1 /*
2  * PROJECT:     ReactOS Named Pipe FileSystem
3  * LICENSE:     BSD - See COPYING.ARM in the top level directory
4  * FILE:        drivers/filesystems/npfs/readsup.c
5  * PURPOSE:     Pipes Reading Support
6  * PROGRAMMERS: ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "npfs.h"
12 
13 // File ID number for NPFS bugchecking support
14 #define NPFS_BUGCHECK_FILE_ID   (NPFS_BUGCHECK_READSUP)
15 
16 /* FUNCTIONS ******************************************************************/
17 
18 IO_STATUS_BLOCK
19 NTAPI
20 NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue,
21                 IN BOOLEAN Peek,
22                 IN BOOLEAN ReadOverflowOperation,
23                 IN PVOID Buffer,
24                 IN ULONG BufferSize,
25                 IN ULONG Mode,
26                 IN PNP_CCB Ccb,
27                 IN PLIST_ENTRY List)
28 {
29     PNP_DATA_QUEUE_ENTRY DataEntry, TempDataEntry;
30     PVOID DataBuffer;
31     ULONG DataSize, DataLength, TotalBytesCopied, RemainingSize, Offset;
32     PIRP Irp;
33     IO_STATUS_BLOCK IoStatus;
34     BOOLEAN CompleteWrites = FALSE;
35     PAGED_CODE();
36 
37     if (ReadOverflowOperation) Peek = TRUE;
38 
39     RemainingSize = BufferSize;
40     IoStatus.Status = STATUS_SUCCESS;
41     TotalBytesCopied = 0;
42 
43     if (Peek)
44     {
45         DataEntry = CONTAINING_RECORD(DataQueue->Queue.Flink,
46                                       NP_DATA_QUEUE_ENTRY,
47                                       QueueEntry);
48     }
49     else
50     {
51         DataEntry = CONTAINING_RECORD(NpGetNextRealDataQueueEntry(DataQueue, List),
52                                       NP_DATA_QUEUE_ENTRY,
53                                       QueueEntry);
54     }
55 
56     while ((&DataEntry->QueueEntry != &DataQueue->Queue) && (RemainingSize))
57     {
58         if (!Peek ||
59             DataEntry->DataEntryType == Buffered ||
60             DataEntry->DataEntryType == Unbuffered)
61         {
62             if (DataEntry->DataEntryType == Unbuffered)
63             {
64                 DataBuffer = DataEntry->Irp->AssociatedIrp.SystemBuffer;
65             }
66             else
67             {
68                 DataBuffer = &DataEntry[1];
69             }
70 
71             DataSize = DataEntry->DataSize;
72             Offset = DataSize;
73 
74             if (&DataEntry->QueueEntry == DataQueue->Queue.Flink)
75             {
76                 Offset -= DataQueue->ByteOffset;
77             }
78 
79             DataLength = Offset;
80             if (DataLength >= RemainingSize) DataLength = RemainingSize;
81 
82             _SEH2_TRY
83             {
84                 RtlCopyMemory((PVOID)((ULONG_PTR)Buffer + BufferSize - RemainingSize),
85                               (PVOID)((ULONG_PTR)DataBuffer + DataSize - Offset),
86                               DataLength);
87             }
88             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
89             {
90                 ASSERT(FALSE);
91             }
92             _SEH2_END;
93 
94 
95             RemainingSize -= DataLength;
96             Offset -= DataLength;
97             TotalBytesCopied += DataLength;
98 
99             if (!Peek)
100             {
101                 DataEntry->QuotaInEntry -= DataLength;
102                 DataQueue->QuotaUsed -= DataLength;
103                 DataQueue->ByteOffset += DataLength;
104                 CompleteWrites = TRUE;
105             }
106 
107             NpCopyClientContext(Ccb, DataEntry);
108 
109             if ((Offset) || (ReadOverflowOperation && !TotalBytesCopied))
110             {
111                 if (Mode == FILE_PIPE_MESSAGE_MODE)
112                 {
113                     IoStatus.Status = STATUS_BUFFER_OVERFLOW;
114                     break;
115                 }
116             }
117             else
118             {
119                 if (!Peek || ReadOverflowOperation)
120                 {
121                     if (ReadOverflowOperation)
122                     {
123                         TempDataEntry = CONTAINING_RECORD(NpGetNextRealDataQueueEntry(DataQueue, List),
124                                                           NP_DATA_QUEUE_ENTRY,
125                                                           QueueEntry);
126                         ASSERT(TempDataEntry == DataEntry);
127                     }
128 
129                     Irp = NpRemoveDataQueueEntry(DataQueue, TRUE, List);
130                     if (Irp)
131                     {
132                         Irp->IoStatus.Information = DataSize;
133                         Irp->IoStatus.Status = STATUS_SUCCESS;
134                         InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
135                     }
136                 }
137 
138                 if (Mode == FILE_PIPE_MESSAGE_MODE)
139                 {
140                     IoStatus.Status = STATUS_SUCCESS;
141                     break;
142                 }
143 
144                 ASSERT(!ReadOverflowOperation);
145             }
146         }
147 
148         if (Peek)
149         {
150             DataEntry = CONTAINING_RECORD(DataEntry->QueueEntry.Flink,
151                                           NP_DATA_QUEUE_ENTRY,
152                                           QueueEntry);
153         }
154         else
155         {
156             DataEntry = CONTAINING_RECORD(NpGetNextRealDataQueueEntry(DataQueue, List),
157                                           NP_DATA_QUEUE_ENTRY,
158                                           QueueEntry);
159         }
160     }
161 
162     IoStatus.Information = TotalBytesCopied;
163     if (CompleteWrites) NpCompleteStalledWrites(DataQueue, List);
164     return IoStatus;
165 }
166 
167 /* EOF */
168