* Sync up to trunk head (r65074).
[reactos.git] / drivers / filesystems / npfs / readsup.c
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 */