xref: /reactos/drivers/filesystems/npfs/write.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/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
NpCommonWrite(IN PFILE_OBJECT FileObject,IN PVOID Buffer,IN ULONG DataSize,IN PETHREAD Thread,IN PIO_STATUS_BLOCK IoStatus,IN PIRP Irp,IN PLIST_ENTRY List)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
NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)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 
_Function_class_(FAST_IO_WRITE)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