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 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 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 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