Sync with trunk r63647.
[reactos.git] / drivers / filesystems / npfs / write.c
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 */