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