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
9 /* INCLUDES *******************************************************************/
13 // File ID number for NPFS bugchecking support
14 #define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_STATESUP)
16 /* FUNCTIONS ******************************************************************/
20 NpCancelListeningQueueIrp(IN PDEVICE_OBJECT DeviceObject
,
23 FsRtlEnterFileSystem();
24 NpAcquireExclusiveVcb();
26 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
28 FsRtlExitFileSystem();
31 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
32 IoCompleteRequest(Irp
, IO_NAMED_PIPE_INCREMENT
);
37 NpSetConnectedPipeState(IN PNP_CCB Ccb
,
38 IN PFILE_OBJECT FileObject
,
41 PLIST_ENTRY NextEntry
;
44 ASSERT(Ccb
->NamedPipeState
== FILE_PIPE_LISTENING_STATE
);
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
;
51 NpSetFileObject(FileObject
, Ccb
, Ccb
->NonPagedCcb
, FALSE
);
53 while (!IsListEmpty(&Ccb
->IrpList
))
55 NextEntry
= RemoveHeadList(&Ccb
->IrpList
);
57 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, Tail
.Overlay
.ListEntry
);
59 if (IoSetCancelRoutine(Irp
, NULL
))
61 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
62 InsertTailList(List
, NextEntry
);
66 InitializeListHead(NextEntry
);
70 return STATUS_SUCCESS
;
75 NpSetDisconnectedPipeState(IN PNP_CCB Ccb
,
79 PNP_NONPAGED_CCB NonPagedCcb
;
81 PLIST_ENTRY NextEntry
;
82 PNP_EVENT_BUFFER EventBuffer
;
84 NonPagedCcb
= Ccb
->NonPagedCcb
;
86 switch (Ccb
->NamedPipeState
)
88 case FILE_PIPE_DISCONNECTED_STATE
:
89 Status
= STATUS_PIPE_DISCONNECTED
;
92 case FILE_PIPE_LISTENING_STATE
:
93 while (!IsListEmpty(&Ccb
->IrpList
))
95 NextEntry
= RemoveHeadList(&Ccb
->IrpList
);
97 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, Tail
.Overlay
.ListEntry
);
99 if (IoSetCancelRoutine(Irp
, NULL
))
101 Irp
->IoStatus
.Status
= STATUS_PIPE_DISCONNECTED
;
102 InsertTailList(List
, NextEntry
);
106 InitializeListHead(NextEntry
);
110 Status
= STATUS_SUCCESS
;
113 case FILE_PIPE_CONNECTED_STATE
:
115 EventBuffer
= NonPagedCcb
->EventBuffer
[FILE_PIPE_CLIENT_END
];
117 while (Ccb
->DataQueue
[FILE_PIPE_INBOUND
].QueueState
!= Empty
)
119 Irp
= NpRemoveDataQueueEntry(&Ccb
->DataQueue
[FILE_PIPE_INBOUND
], FALSE
, List
);
122 Irp
->IoStatus
.Status
= STATUS_PIPE_DISCONNECTED
;
123 InsertTailList(List
, &Irp
->Tail
.Overlay
.ListEntry
);
127 while (Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
].QueueState
!= Empty
)
129 Irp
= NpRemoveDataQueueEntry(&Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
], FALSE
, List
);
132 Irp
->IoStatus
.Status
= STATUS_PIPE_DISCONNECTED
;
133 InsertTailList(List
, &Irp
->Tail
.Overlay
.ListEntry
);
137 if (EventBuffer
) KeSetEvent(EventBuffer
->Event
, IO_NO_INCREMENT
, FALSE
);
139 // drop down on purpose... queue will be empty so flush code is nop
140 ASSERT(Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
].QueueState
== Empty
);
142 case FILE_PIPE_CLOSING_STATE
:
144 EventBuffer
= NonPagedCcb
->EventBuffer
[FILE_PIPE_CLIENT_END
];
146 while (Ccb
->DataQueue
[FILE_PIPE_INBOUND
].QueueState
!= Empty
)
148 Irp
= NpRemoveDataQueueEntry(&Ccb
->DataQueue
[FILE_PIPE_INBOUND
], FALSE
, List
);
151 Irp
->IoStatus
.Status
= STATUS_PIPE_DISCONNECTED
;
152 InsertTailList(List
, &Irp
->Tail
.Overlay
.ListEntry
);
156 ASSERT(Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
].QueueState
== Empty
);
158 NpDeleteEventTableEntry(&NpVcb
->EventTable
, EventBuffer
);
159 NonPagedCcb
->EventBuffer
[FILE_PIPE_CLIENT_END
] = NULL
;
161 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_CLIENT_END
], NULL
, NULL
, FALSE
);
162 Ccb
->FileObject
[FILE_PIPE_CLIENT_END
] = NULL
;
164 NpUninitializeSecurity(Ccb
);
166 if (Ccb
->ClientSession
)
168 ExFreePool(Ccb
->ClientSession
);
169 Ccb
->ClientSession
= NULL
;
172 Status
= STATUS_SUCCESS
;
176 NpBugCheck(Ccb
->NamedPipeState
, 0, 0);
180 Ccb
->NamedPipeState
= FILE_PIPE_DISCONNECTED_STATE
;
186 NpSetListeningPipeState(IN PNP_CCB Ccb
,
192 switch (Ccb
->NamedPipeState
)
194 case FILE_PIPE_DISCONNECTED_STATE
:
196 Status
= NpCancelWaiter(&NpVcb
->WaitQueue
,
200 if (!NT_SUCCESS(Status
)) return Status
;
203 // Drop down on purpose
206 case FILE_PIPE_LISTENING_STATE
:
208 if (Ccb
->CompletionMode
[FILE_PIPE_SERVER_END
] == FILE_PIPE_COMPLETE_OPERATION
)
210 Ccb
->NamedPipeState
= FILE_PIPE_LISTENING_STATE
;
211 return STATUS_PIPE_LISTENING
;
214 IoSetCancelRoutine(Irp
, NpCancelListeningQueueIrp
);
215 if (Irp
->Cancel
&& IoSetCancelRoutine(Irp
, NULL
))
217 return STATUS_CANCELLED
;
220 Ccb
->NamedPipeState
= FILE_PIPE_LISTENING_STATE
;
221 IoMarkIrpPending(Irp
);
222 InsertTailList(&Ccb
->IrpList
, &Irp
->Tail
.Overlay
.ListEntry
);
223 return STATUS_PENDING
;
225 case FILE_PIPE_CONNECTED_STATE
:
226 Status
= STATUS_PIPE_CONNECTED
;
229 case FILE_PIPE_CLOSING_STATE
:
230 Status
= STATUS_PIPE_CLOSING
;
234 NpBugCheck(Ccb
->NamedPipeState
, 0, 0);
243 NpSetClosingPipeState(IN PNP_CCB Ccb
,
245 IN ULONG NamedPipeEnd
,
248 PNP_NONPAGED_CCB NonPagedCcb
;
250 PLIST_ENTRY NextEntry
;
251 PNP_DATA_QUEUE ReadQueue
, WriteQueue
, DataQueue
;
252 PNP_EVENT_BUFFER EventBuffer
;
255 NonPagedCcb
= Ccb
->NonPagedCcb
;
258 switch (Ccb
->NamedPipeState
)
260 case FILE_PIPE_LISTENING_STATE
:
262 ASSERT(NamedPipeEnd
== FILE_PIPE_SERVER_END
);
264 while (!IsListEmpty(&Ccb
->IrpList
))
266 NextEntry
= RemoveHeadList(&Ccb
->IrpList
);
268 ListIrp
= CONTAINING_RECORD(NextEntry
, IRP
, Tail
.Overlay
.ListEntry
);
270 if (IoSetCancelRoutine(ListIrp
, NULL
))
272 ListIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
273 InsertTailList(List
, NextEntry
);
277 InitializeListHead(NextEntry
);
283 case FILE_PIPE_DISCONNECTED_STATE
:
285 ASSERT(NamedPipeEnd
== FILE_PIPE_SERVER_END
);
287 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_SERVER_END
], NULL
, NULL
, TRUE
);
288 Ccb
->FileObject
[FILE_PIPE_SERVER_END
] = NULL
;
290 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_CLIENT_END
], NULL
, NULL
, FALSE
);
291 Ccb
->FileObject
[FILE_PIPE_CLIENT_END
] = NULL
;
293 NpDeleteCcb(Ccb
, List
);
294 if (!Fcb
->CurrentInstances
) NpDeleteFcb(Fcb
, List
);
297 case FILE_PIPE_CLOSING_STATE
:
299 if (NamedPipeEnd
== FILE_PIPE_SERVER_END
)
301 DataQueue
= &Ccb
->DataQueue
[FILE_PIPE_INBOUND
];
305 DataQueue
= &Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
];
308 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_SERVER_END
], NULL
, NULL
, TRUE
);
309 Ccb
->FileObject
[FILE_PIPE_SERVER_END
] = NULL
;
311 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_CLIENT_END
], NULL
, NULL
, FALSE
);
312 Ccb
->FileObject
[FILE_PIPE_CLIENT_END
] = NULL
;
314 while (DataQueue
->QueueState
!= Empty
)
316 ListIrp
= NpRemoveDataQueueEntry(DataQueue
, FALSE
, List
);
319 ListIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
320 InsertTailList(List
, &ListIrp
->Tail
.Overlay
.ListEntry
);
324 NpUninitializeSecurity(Ccb
);
326 if (Ccb
->ClientSession
)
328 ExFreePool(Ccb
->ClientSession
);
329 Ccb
->ClientSession
= NULL
;
332 NpDeleteCcb(Ccb
, List
);
333 if (!Fcb
->CurrentInstances
) NpDeleteFcb(Fcb
, List
);
336 case FILE_PIPE_CONNECTED_STATE
:
338 if (NamedPipeEnd
== FILE_PIPE_SERVER_END
)
340 ReadQueue
= &Ccb
->DataQueue
[FILE_PIPE_INBOUND
];
341 WriteQueue
= &Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
];
343 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_SERVER_END
], NULL
, NULL
, TRUE
);
344 Ccb
->FileObject
[FILE_PIPE_SERVER_END
] = NULL
;
348 ReadQueue
= &Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
];
349 WriteQueue
= &Ccb
->DataQueue
[FILE_PIPE_INBOUND
];
351 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_CLIENT_END
], NULL
, NULL
, FALSE
);
352 Ccb
->FileObject
[FILE_PIPE_CLIENT_END
] = NULL
;
355 EventBuffer
= NonPagedCcb
->EventBuffer
[NamedPipeEnd
];
357 Ccb
->NamedPipeState
= FILE_PIPE_CLOSING_STATE
;
359 while (ReadQueue
->QueueState
!= Empty
)
361 ListIrp
= NpRemoveDataQueueEntry(ReadQueue
, FALSE
, List
);
364 ListIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
365 InsertTailList(List
, &ListIrp
->Tail
.Overlay
.ListEntry
);
369 while (WriteQueue
->QueueState
== ReadEntries
)
371 ListIrp
= NpRemoveDataQueueEntry(WriteQueue
, FALSE
, List
);
374 ListIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
375 InsertTailList(List
, &ListIrp
->Tail
.Overlay
.ListEntry
);
379 if (EventBuffer
) KeSetEvent(EventBuffer
->Event
, IO_NO_INCREMENT
, FALSE
);
383 NpBugCheck(Ccb
->NamedPipeState
, 0, 0);
386 return STATUS_SUCCESS
;