xref: /reactos/drivers/filesystems/npfs/read.c (revision c2c66aff)
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