1 /*
2 * PROJECT: ReactOS Named Pipe FileSystem
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/filesystems/npfs/read.c
5 * PURPOSE: Pipes Reading
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_READ)
15
16 /* GLOBALS ********************************************************************/
17
18 LONG NpSlowReadCalls;
19 ULONG NpFastReadTrue;
20 ULONG NpFastReadFalse;
21
22 /* FUNCTIONS ******************************************************************/
23
24 BOOLEAN
25 NTAPI
NpCommonRead(IN PFILE_OBJECT FileObject,IN PVOID Buffer,IN ULONG BufferSize,OUT PIO_STATUS_BLOCK IoStatus,IN PIRP Irp,IN PLIST_ENTRY List)26 NpCommonRead(IN PFILE_OBJECT FileObject,
27 IN PVOID Buffer,
28 IN ULONG BufferSize,
29 OUT PIO_STATUS_BLOCK IoStatus,
30 IN PIRP Irp,
31 IN PLIST_ENTRY List)
32 {
33 NODE_TYPE_CODE NodeType;
34 PNP_DATA_QUEUE ReadQueue;
35 PNP_EVENT_BUFFER EventBuffer;
36 NTSTATUS Status;
37 ULONG NamedPipeEnd;
38 PNP_CCB Ccb;
39 PNP_NONPAGED_CCB NonPagedCcb;
40 BOOLEAN ReadOk;
41 PAGED_CODE();
42
43 IoStatus->Information = 0;
44 NodeType = NpDecodeFileObject(FileObject, NULL, &Ccb, &NamedPipeEnd);
45
46 if (!NodeType)
47 {
48 IoStatus->Status = STATUS_PIPE_DISCONNECTED;
49 return TRUE;
50 }
51
52 if (NodeType != NPFS_NTC_CCB)
53 {
54 IoStatus->Status = STATUS_INVALID_PARAMETER;
55 return TRUE;
56 }
57
58 NonPagedCcb = Ccb->NonPagedCcb;
59 ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE);
60
61 if (Ccb->NamedPipeState == FILE_PIPE_DISCONNECTED_STATE || Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE)
62 {
63 IoStatus->Status = Ccb->NamedPipeState != FILE_PIPE_DISCONNECTED_STATE ? STATUS_PIPE_LISTENING : STATUS_PIPE_DISCONNECTED;
64 ReadOk = TRUE;
65 goto Quickie;
66 }
67
68 ASSERT((Ccb->NamedPipeState == FILE_PIPE_CONNECTED_STATE) || (Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE));
69
70 if ((NamedPipeEnd == FILE_PIPE_SERVER_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_OUTBOUND) ||
71 (NamedPipeEnd == FILE_PIPE_CLIENT_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_INBOUND))
72 {
73 IoStatus->Status = STATUS_INVALID_PARAMETER;
74 ReadOk = TRUE;
75 goto Quickie;
76 }
77
78 if (NamedPipeEnd == FILE_PIPE_SERVER_END)
79 {
80 ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
81 }
82 else
83 {
84 ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
85 }
86
87 EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd];
88
89 if (ReadQueue->QueueState == WriteEntries)
90 {
91 *IoStatus = NpReadDataQueue(ReadQueue,
92 FALSE,
93 FALSE,
94 Buffer,
95 BufferSize,
96 Ccb->ReadMode[NamedPipeEnd],
97 Ccb,
98 List);
99 if (!NT_SUCCESS(IoStatus->Status))
100 {
101 ReadOk = TRUE;
102 goto Quickie;
103 }
104
105 ReadOk = TRUE;
106 if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
107 goto Quickie;
108 }
109
110 if (Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE)
111 {
112 IoStatus->Status = STATUS_PIPE_BROKEN;
113 ReadOk = TRUE;
114 if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
115 goto Quickie;
116 }
117
118 if (Ccb->CompletionMode[NamedPipeEnd] == FILE_PIPE_COMPLETE_OPERATION)
119 {
120 IoStatus->Status = STATUS_PIPE_EMPTY;
121 ReadOk = TRUE;
122 if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
123 goto Quickie;
124 }
125
126 if (!Irp)
127 {
128 ReadOk = FALSE;
129 goto Quickie;
130 }
131
132 Status = NpAddDataQueueEntry(NamedPipeEnd,
133 Ccb,
134 ReadQueue,
135 ReadEntries,
136 Buffered,
137 BufferSize,
138 Irp,
139 NULL,
140 0);
141 IoStatus->Status = Status;
142 if (!NT_SUCCESS(Status))
143 {
144 ReadOk = FALSE;
145 }
146 else
147 {
148 ReadOk = TRUE;
149 if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
150 }
151
152 Quickie:
153 ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
154 return ReadOk;
155 }
156
157 NTSTATUS
158 NTAPI
NpFsdRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)159 NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
160 IN PIRP Irp)
161 {
162 PIO_STACK_LOCATION IoStack;
163 IO_STATUS_BLOCK IoStatus;
164 LIST_ENTRY DeferredList;
165 PAGED_CODE();
166 NpSlowReadCalls++;
167
168 InitializeListHead(&DeferredList);
169 IoStack = IoGetCurrentIrpStackLocation(Irp);
170
171 FsRtlEnterFileSystem();
172 NpAcquireSharedVcb();
173
174 NpCommonRead(IoStack->FileObject,
175 Irp->UserBuffer,
176 IoStack->Parameters.Read.Length,
177 &IoStatus,
178 Irp,
179 &DeferredList);
180
181 NpReleaseVcb();
182 NpCompleteDeferredIrps(&DeferredList);
183 FsRtlExitFileSystem();
184
185 if (IoStatus.Status != STATUS_PENDING)
186 {
187 Irp->IoStatus.Information = IoStatus.Information;
188 Irp->IoStatus.Status = IoStatus.Status;
189 IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
190 }
191
192 return IoStatus.Status;
193 }
194
195
_Function_class_(FAST_IO_READ)196 _Function_class_(FAST_IO_READ)
197 _IRQL_requires_same_
198 BOOLEAN
199 NTAPI
200 NpFastRead(
201 _In_ PFILE_OBJECT FileObject,
202 _In_ PLARGE_INTEGER FileOffset,
203 _In_ ULONG Length,
204 _In_ BOOLEAN Wait,
205 _In_ ULONG LockKey,
206 _Out_ PVOID Buffer,
207 _Out_ PIO_STATUS_BLOCK IoStatus,
208 _In_ PDEVICE_OBJECT DeviceObject)
209 {
210 LIST_ENTRY DeferredList;
211 BOOLEAN Result;
212 PAGED_CODE();
213
214 InitializeListHead(&DeferredList);
215
216 FsRtlEnterFileSystem();
217 NpAcquireSharedVcb();
218
219 Result = NpCommonRead(FileObject,
220 Buffer,
221 Length,
222 IoStatus,
223 NULL,
224 &DeferredList);
225 if (Result)
226 ++NpFastReadTrue;
227 else
228 ++NpFastReadFalse;
229
230 NpReleaseVcb();
231 NpCompleteDeferredIrps(&DeferredList);
232 FsRtlExitFileSystem();
233
234 return Result;
235 }
236
237 /* EOF */
238