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