[NPFS_NEW]: Add file header info.
[reactos.git] / reactos / drivers / filesystems / npfs_new / statesup.c
1 /*
2 * PROJECT: ReactOS Named Pipe FileSystem
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/filesystems/npfs/statesup.c
5 * PURPOSE: Pipes State Support
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "npfs.h"
12
13 /* FUNCTIONS ******************************************************************/
14
15 VOID
16 NTAPI
17 NpCancelListeningQueueIrp(IN PDEVICE_OBJECT DeviceObject,
18 IN PIRP Irp)
19 {
20 FsRtlEnterFileSystem();
21 NpAcquireExclusiveVcb();
22
23 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
24
25 FsRtlExitFileSystem();
26 NpReleaseVcb();
27
28 Irp->IoStatus.Status = STATUS_CANCELLED;
29 IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
30 }
31
32 NTSTATUS
33 NTAPI
34 NpSetConnectedPipeState(IN PNP_CCB Ccb,
35 IN PFILE_OBJECT FileObject,
36 IN PLIST_ENTRY List)
37 {
38 PLIST_ENTRY NextEntry;
39 PIRP Irp;
40
41 ASSERT(Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE);
42
43 Ccb->ReadMode[FILE_PIPE_CLIENT_END] = FILE_PIPE_BYTE_STREAM_MODE;
44 Ccb->CompletionMode[FILE_PIPE_CLIENT_END] = FILE_PIPE_QUEUE_OPERATION;
45 Ccb->NamedPipeState = FILE_PIPE_CONNECTED_STATE;
46 Ccb->FileObject[FILE_PIPE_CLIENT_END] = FileObject;
47
48 NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, FALSE);
49
50 while (!IsListEmpty(&Ccb->IrpList))
51 {
52 NextEntry = RemoveHeadList(&Ccb->IrpList);
53
54 Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
55
56 if (IoSetCancelRoutine(Irp, NULL))
57 {
58 Irp->IoStatus.Status = STATUS_SUCCESS;
59 InsertTailList(List, NextEntry);
60 }
61 else
62 {
63 InitializeListHead(NextEntry);
64 }
65 }
66
67 return STATUS_SUCCESS;
68 }
69
70 NTSTATUS
71 NTAPI
72 NpSetDisconnectedPipeState(IN PNP_CCB Ccb,
73 IN PLIST_ENTRY List)
74 {
75 PIRP Irp;
76 PNP_NONPAGED_CCB NonPagedCcb;
77 NTSTATUS Status;
78 PLIST_ENTRY NextEntry;
79 PNP_EVENT_BUFFER EventBuffer;
80
81 NonPagedCcb = Ccb->NonPagedCcb;
82
83 switch (Ccb->NamedPipeState)
84 {
85 case FILE_PIPE_DISCONNECTED_STATE:
86 Status = STATUS_PIPE_DISCONNECTED;
87 break;
88
89 case FILE_PIPE_LISTENING_STATE:
90 while (!IsListEmpty(&Ccb->IrpList))
91 {
92 NextEntry = RemoveHeadList(&Ccb->IrpList);
93
94 Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
95
96 if (IoSetCancelRoutine(Irp, NULL))
97 {
98 Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
99 InsertTailList(List, NextEntry);
100 }
101 else
102 {
103 InitializeListHead(NextEntry);
104 }
105 }
106
107 Status = STATUS_SUCCESS;
108 break;
109
110 case FILE_PIPE_CONNECTED_STATE:
111
112 EventBuffer = NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END];
113
114 while (Ccb->DataQueue[FILE_PIPE_INBOUND].QueueState != Empty)
115 {
116 Irp = NpRemoveDataQueueEntry(&Ccb->DataQueue[FILE_PIPE_INBOUND], FALSE, List);
117 if (Irp)
118 {
119 Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
120 InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
121 }
122 }
123
124 while (Ccb->DataQueue[FILE_PIPE_OUTBOUND].QueueState != Empty)
125 {
126 Irp = NpRemoveDataQueueEntry(&Ccb->DataQueue[FILE_PIPE_OUTBOUND], FALSE, List);
127 if (Irp)
128 {
129 Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
130 InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
131 }
132 }
133
134 if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
135
136 // drop down on purpose... queue will be empty so flush code is nop
137 ASSERT(Ccb->DataQueue[FILE_PIPE_OUTBOUND].QueueState == Empty);
138
139 case FILE_PIPE_CLOSING_STATE:
140
141 EventBuffer = NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END];
142
143 while (Ccb->DataQueue[FILE_PIPE_INBOUND].QueueState != Empty)
144 {
145 Irp = NpRemoveDataQueueEntry(&Ccb->DataQueue[FILE_PIPE_INBOUND], FALSE, List);
146 if (Irp)
147 {
148 Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
149 InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
150 }
151 }
152
153 ASSERT(Ccb->DataQueue[FILE_PIPE_OUTBOUND].QueueState == Empty);
154
155 NpDeleteEventTableEntry(&NpVcb->EventTable, EventBuffer);
156 NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END] = NULL;
157
158 NpSetFileObject(Ccb->FileObject[FILE_PIPE_CLIENT_END], NULL, NULL, FALSE);
159 Ccb->FileObject[FILE_PIPE_CLIENT_END] = NULL;
160
161 NpUninitializeSecurity(Ccb);
162
163 if (Ccb->ClientSession)
164 {
165 ExFreePool(Ccb->ClientSession);
166 Ccb->ClientSession = NULL;
167 }
168
169 Status = STATUS_SUCCESS;
170 break;
171
172 default:
173 KeBugCheckEx(NPFS_FILE_SYSTEM, 0x1603DD, Ccb->NamedPipeState, 0, 0);
174 break;
175 }
176
177 Ccb->NamedPipeState = FILE_PIPE_DISCONNECTED_STATE;
178 return Status;
179 }
180
181 NTSTATUS
182 NTAPI
183 NpSetListeningPipeState(IN PNP_CCB Ccb,
184 IN PIRP Irp,
185 IN PLIST_ENTRY List)
186 {
187 NTSTATUS Status;
188
189 switch (Ccb->NamedPipeState)
190 {
191 case FILE_PIPE_DISCONNECTED_STATE:
192
193 Status = NpCancelWaiter(&NpVcb->WaitQueue,
194 &Ccb->Fcb->FullName,
195 STATUS_SUCCESS,
196 List);
197 if (!NT_SUCCESS(Status)) return Status;
198
199 //
200 // Drop down on purpose
201 //
202
203 case FILE_PIPE_LISTENING_STATE:
204
205 if (Ccb->CompletionMode[FILE_PIPE_SERVER_END] == FILE_PIPE_COMPLETE_OPERATION)
206 {
207 Ccb->NamedPipeState = FILE_PIPE_LISTENING_STATE;
208 return STATUS_PIPE_LISTENING;
209 }
210
211 IoSetCancelRoutine(Irp, NpCancelListeningQueueIrp);
212 if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
213 {
214 return STATUS_CANCELLED;
215 }
216
217 Ccb->NamedPipeState = FILE_PIPE_LISTENING_STATE;
218 IoMarkIrpPending(Irp);
219 InsertTailList(&Ccb->IrpList, &Irp->Tail.Overlay.ListEntry);
220 return STATUS_PENDING;
221
222 case FILE_PIPE_CONNECTED_STATE:
223 Status = STATUS_PIPE_CONNECTED;
224 break;
225
226 case FILE_PIPE_CLOSING_STATE:
227 Status = STATUS_PIPE_CLOSING;
228 break;
229
230 default:
231 KeBugCheckEx(NPFS_FILE_SYSTEM, 0x160133, Ccb->NamedPipeState, 0, 0);
232 break;
233 }
234
235 return Status;
236 }
237
238 NTSTATUS
239 NTAPI
240 NpSetClosingPipeState(IN PNP_CCB Ccb,
241 IN PIRP Irp,
242 IN ULONG NamedPipeEnd,
243 IN PLIST_ENTRY List)
244 {
245 PNP_NONPAGED_CCB NonPagedCcb;
246 PNP_FCB Fcb;
247 PLIST_ENTRY NextEntry;
248 PNP_DATA_QUEUE ReadQueue, WriteQueue, DataQueue;
249 PNP_EVENT_BUFFER EventBuffer;
250 PIRP ListIrp;
251
252 NonPagedCcb = Ccb->NonPagedCcb;
253 Fcb = Ccb->Fcb;
254
255 switch (Ccb->NamedPipeState)
256 {
257 case FILE_PIPE_LISTENING_STATE:
258
259 ASSERT(NamedPipeEnd == FILE_PIPE_SERVER_END);
260
261 while (!IsListEmpty(&Ccb->IrpList))
262 {
263 NextEntry = RemoveHeadList(&Ccb->IrpList);
264
265 ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
266
267 if (IoSetCancelRoutine(ListIrp, NULL))
268 {
269 ListIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
270 InsertTailList(List, NextEntry);
271 }
272 else
273 {
274 InitializeListHead(NextEntry);
275 }
276 }
277
278 // Drop on purpose
279
280 case FILE_PIPE_DISCONNECTED_STATE:
281
282 ASSERT(NamedPipeEnd == FILE_PIPE_SERVER_END);
283
284 NpSetFileObject(Ccb->FileObject[FILE_PIPE_SERVER_END], NULL, NULL, TRUE);
285 Ccb->FileObject[FILE_PIPE_SERVER_END] = NULL;
286
287 NpSetFileObject(Ccb->FileObject[FILE_PIPE_CLIENT_END], NULL, NULL, FALSE);
288 Ccb->FileObject[FILE_PIPE_CLIENT_END] = NULL;
289
290 NpDeleteCcb(Ccb, List);
291 if (!Fcb->CurrentInstances) NpDeleteFcb(Fcb, List);
292 break;
293
294 case FILE_PIPE_CLOSING_STATE:
295
296 if (NamedPipeEnd == FILE_PIPE_SERVER_END)
297 {
298 DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
299 }
300 else
301 {
302 DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
303 }
304
305 NpSetFileObject(Ccb->FileObject[FILE_PIPE_SERVER_END], NULL, NULL, TRUE);
306 Ccb->FileObject[FILE_PIPE_SERVER_END] = NULL;
307
308 NpSetFileObject(Ccb->FileObject[FILE_PIPE_CLIENT_END], NULL, NULL, FALSE);
309 Ccb->FileObject[FILE_PIPE_CLIENT_END] = NULL;
310
311 while (DataQueue->QueueState != Empty)
312 {
313 ListIrp = NpRemoveDataQueueEntry(DataQueue, FALSE, List);
314 if (ListIrp)
315 {
316 ListIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
317 InsertTailList(List, &ListIrp->Tail.Overlay.ListEntry);
318 }
319 }
320
321 NpUninitializeSecurity(Ccb);
322
323 if (Ccb->ClientSession)
324 {
325 ExFreePool(Ccb->ClientSession);
326 Ccb->ClientSession = NULL;
327 }
328
329 NpDeleteCcb(Ccb, List);
330 if (!Fcb->CurrentInstances) NpDeleteFcb(Fcb, List);
331 break;
332
333 case FILE_PIPE_CONNECTED_STATE:
334
335 if (NamedPipeEnd == FILE_PIPE_SERVER_END)
336 {
337 ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
338 WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
339
340 NpSetFileObject(Ccb->FileObject[FILE_PIPE_SERVER_END], NULL, NULL, TRUE);
341 Ccb->FileObject[FILE_PIPE_SERVER_END] = NULL;
342 }
343 else
344 {
345 ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
346 WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
347
348 NpSetFileObject(Ccb->FileObject[FILE_PIPE_CLIENT_END], NULL, NULL, FALSE);
349 Ccb->FileObject[FILE_PIPE_CLIENT_END] = NULL;
350 }
351
352 EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd];
353
354 Ccb->NamedPipeState = FILE_PIPE_CLOSING_STATE;
355
356 while (ReadQueue->QueueState != Empty)
357 {
358 ListIrp = NpRemoveDataQueueEntry(ReadQueue, FALSE, List);
359 if (ListIrp)
360 {
361 ListIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
362 InsertTailList(List, &ListIrp->Tail.Overlay.ListEntry);
363 }
364 }
365
366 while (WriteQueue->QueueState == ReadEntries)
367 {
368 ListIrp = NpRemoveDataQueueEntry(WriteQueue, FALSE, List);
369 if (ListIrp)
370 {
371 ListIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
372 InsertTailList(List, &ListIrp->Tail.Overlay.ListEntry);
373 }
374 }
375
376 if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
377 break;
378
379 default:
380 KeBugCheckEx(NPFS_FILE_SYSTEM, 0x1602F9, Ccb->NamedPipeState, 0, 0);
381 break;
382 }
383 return STATUS_SUCCESS;
384 }
385
386 /* EOF */