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 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
25 FsRtlEnterFileSystem();
26 NpAcquireExclusiveVcb();
28 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
30 FsRtlExitFileSystem();
33 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
34 IoCompleteRequest(Irp
, IO_NAMED_PIPE_INCREMENT
);
39 NpSetConnectedPipeState(IN PNP_CCB Ccb
,
40 IN PFILE_OBJECT FileObject
,
43 PLIST_ENTRY NextEntry
;
46 ASSERT(Ccb
->NamedPipeState
== FILE_PIPE_LISTENING_STATE
);
48 Ccb
->ReadMode
[FILE_PIPE_CLIENT_END
] = FILE_PIPE_BYTE_STREAM_MODE
;
49 Ccb
->CompletionMode
[FILE_PIPE_CLIENT_END
] = FILE_PIPE_QUEUE_OPERATION
;
50 Ccb
->NamedPipeState
= FILE_PIPE_CONNECTED_STATE
;
51 Ccb
->FileObject
[FILE_PIPE_CLIENT_END
] = FileObject
;
53 NpSetFileObject(FileObject
, Ccb
, Ccb
->NonPagedCcb
, FALSE
);
55 while (!IsListEmpty(&Ccb
->IrpList
))
57 NextEntry
= RemoveHeadList(&Ccb
->IrpList
);
59 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, Tail
.Overlay
.ListEntry
);
61 if (IoSetCancelRoutine(Irp
, NULL
))
63 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
64 InsertTailList(List
, NextEntry
);
68 InitializeListHead(NextEntry
);
72 return STATUS_SUCCESS
;
77 NpSetDisconnectedPipeState(IN PNP_CCB Ccb
,
81 PNP_NONPAGED_CCB NonPagedCcb
;
83 PLIST_ENTRY NextEntry
;
84 PNP_EVENT_BUFFER EventBuffer
;
86 NonPagedCcb
= Ccb
->NonPagedCcb
;
88 switch (Ccb
->NamedPipeState
)
90 case FILE_PIPE_DISCONNECTED_STATE
:
91 Status
= STATUS_PIPE_DISCONNECTED
;
94 case FILE_PIPE_LISTENING_STATE
:
95 while (!IsListEmpty(&Ccb
->IrpList
))
97 NextEntry
= RemoveHeadList(&Ccb
->IrpList
);
99 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, Tail
.Overlay
.ListEntry
);
101 if (IoSetCancelRoutine(Irp
, NULL
))
103 Irp
->IoStatus
.Status
= STATUS_PIPE_DISCONNECTED
;
104 InsertTailList(List
, NextEntry
);
108 InitializeListHead(NextEntry
);
112 Status
= STATUS_SUCCESS
;
115 case FILE_PIPE_CONNECTED_STATE
:
117 EventBuffer
= NonPagedCcb
->EventBuffer
[FILE_PIPE_CLIENT_END
];
119 while (Ccb
->DataQueue
[FILE_PIPE_INBOUND
].QueueState
!= Empty
)
121 Irp
= NpRemoveDataQueueEntry(&Ccb
->DataQueue
[FILE_PIPE_INBOUND
], FALSE
, List
);
124 Irp
->IoStatus
.Status
= STATUS_PIPE_DISCONNECTED
;
125 InsertTailList(List
, &Irp
->Tail
.Overlay
.ListEntry
);
129 while (Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
].QueueState
!= Empty
)
131 Irp
= NpRemoveDataQueueEntry(&Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
], FALSE
, List
);
134 Irp
->IoStatus
.Status
= STATUS_PIPE_DISCONNECTED
;
135 InsertTailList(List
, &Irp
->Tail
.Overlay
.ListEntry
);
139 if (EventBuffer
) KeSetEvent(EventBuffer
->Event
, IO_NO_INCREMENT
, FALSE
);
141 // drop down on purpose... queue will be empty so flush code is nop
142 ASSERT(Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
].QueueState
== Empty
);
144 case FILE_PIPE_CLOSING_STATE
:
146 EventBuffer
= NonPagedCcb
->EventBuffer
[FILE_PIPE_CLIENT_END
];
148 while (Ccb
->DataQueue
[FILE_PIPE_INBOUND
].QueueState
!= Empty
)
150 Irp
= NpRemoveDataQueueEntry(&Ccb
->DataQueue
[FILE_PIPE_INBOUND
], FALSE
, List
);
153 Irp
->IoStatus
.Status
= STATUS_PIPE_DISCONNECTED
;
154 InsertTailList(List
, &Irp
->Tail
.Overlay
.ListEntry
);
158 ASSERT(Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
].QueueState
== Empty
);
160 NpDeleteEventTableEntry(&NpVcb
->EventTable
, EventBuffer
);
161 NonPagedCcb
->EventBuffer
[FILE_PIPE_CLIENT_END
] = NULL
;
163 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_CLIENT_END
], NULL
, NULL
, FALSE
);
164 Ccb
->FileObject
[FILE_PIPE_CLIENT_END
] = NULL
;
166 NpUninitializeSecurity(Ccb
);
168 if (Ccb
->ClientSession
)
170 ExFreePool(Ccb
->ClientSession
);
171 Ccb
->ClientSession
= NULL
;
174 Status
= STATUS_SUCCESS
;
178 NpBugCheck(Ccb
->NamedPipeState
, 0, 0);
182 Ccb
->NamedPipeState
= FILE_PIPE_DISCONNECTED_STATE
;
188 NpSetListeningPipeState(IN PNP_CCB Ccb
,
194 switch (Ccb
->NamedPipeState
)
196 case FILE_PIPE_DISCONNECTED_STATE
:
198 Status
= NpCancelWaiter(&NpVcb
->WaitQueue
,
202 if (!NT_SUCCESS(Status
)) return Status
;
205 // Drop down on purpose
208 case FILE_PIPE_LISTENING_STATE
:
210 if (Ccb
->CompletionMode
[FILE_PIPE_SERVER_END
] == FILE_PIPE_COMPLETE_OPERATION
)
212 Ccb
->NamedPipeState
= FILE_PIPE_LISTENING_STATE
;
213 return STATUS_PIPE_LISTENING
;
216 IoSetCancelRoutine(Irp
, NpCancelListeningQueueIrp
);
217 if (Irp
->Cancel
&& IoSetCancelRoutine(Irp
, NULL
))
219 return STATUS_CANCELLED
;
222 Ccb
->NamedPipeState
= FILE_PIPE_LISTENING_STATE
;
223 IoMarkIrpPending(Irp
);
224 InsertTailList(&Ccb
->IrpList
, &Irp
->Tail
.Overlay
.ListEntry
);
225 return STATUS_PENDING
;
227 case FILE_PIPE_CONNECTED_STATE
:
228 Status
= STATUS_PIPE_CONNECTED
;
231 case FILE_PIPE_CLOSING_STATE
:
232 Status
= STATUS_PIPE_CLOSING
;
236 NpBugCheck(Ccb
->NamedPipeState
, 0, 0);
245 NpSetClosingPipeState(IN PNP_CCB Ccb
,
247 IN ULONG NamedPipeEnd
,
250 PNP_NONPAGED_CCB NonPagedCcb
;
252 PLIST_ENTRY NextEntry
;
253 PNP_DATA_QUEUE ReadQueue
, WriteQueue
, DataQueue
;
254 PNP_EVENT_BUFFER EventBuffer
;
257 NonPagedCcb
= Ccb
->NonPagedCcb
;
260 switch (Ccb
->NamedPipeState
)
262 case FILE_PIPE_LISTENING_STATE
:
264 ASSERT(NamedPipeEnd
== FILE_PIPE_SERVER_END
);
266 while (!IsListEmpty(&Ccb
->IrpList
))
268 NextEntry
= RemoveHeadList(&Ccb
->IrpList
);
270 ListIrp
= CONTAINING_RECORD(NextEntry
, IRP
, Tail
.Overlay
.ListEntry
);
272 if (IoSetCancelRoutine(ListIrp
, NULL
))
274 ListIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
275 InsertTailList(List
, NextEntry
);
279 InitializeListHead(NextEntry
);
285 case FILE_PIPE_DISCONNECTED_STATE
:
287 ASSERT(NamedPipeEnd
== FILE_PIPE_SERVER_END
);
289 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_SERVER_END
], NULL
, NULL
, TRUE
);
290 Ccb
->FileObject
[FILE_PIPE_SERVER_END
] = NULL
;
292 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_CLIENT_END
], NULL
, NULL
, FALSE
);
293 Ccb
->FileObject
[FILE_PIPE_CLIENT_END
] = NULL
;
295 NpDeleteCcb(Ccb
, List
);
296 if (!Fcb
->CurrentInstances
) NpDeleteFcb(Fcb
, List
);
299 case FILE_PIPE_CLOSING_STATE
:
301 if (NamedPipeEnd
== FILE_PIPE_SERVER_END
)
303 DataQueue
= &Ccb
->DataQueue
[FILE_PIPE_INBOUND
];
307 DataQueue
= &Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
];
310 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_SERVER_END
], NULL
, NULL
, TRUE
);
311 Ccb
->FileObject
[FILE_PIPE_SERVER_END
] = NULL
;
313 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_CLIENT_END
], NULL
, NULL
, FALSE
);
314 Ccb
->FileObject
[FILE_PIPE_CLIENT_END
] = NULL
;
316 while (DataQueue
->QueueState
!= Empty
)
318 ListIrp
= NpRemoveDataQueueEntry(DataQueue
, FALSE
, List
);
321 ListIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
322 InsertTailList(List
, &ListIrp
->Tail
.Overlay
.ListEntry
);
326 NpUninitializeSecurity(Ccb
);
328 if (Ccb
->ClientSession
)
330 ExFreePool(Ccb
->ClientSession
);
331 Ccb
->ClientSession
= NULL
;
334 NpDeleteCcb(Ccb
, List
);
335 if (!Fcb
->CurrentInstances
) NpDeleteFcb(Fcb
, List
);
338 case FILE_PIPE_CONNECTED_STATE
:
340 if (NamedPipeEnd
== FILE_PIPE_SERVER_END
)
342 ReadQueue
= &Ccb
->DataQueue
[FILE_PIPE_INBOUND
];
343 WriteQueue
= &Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
];
345 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_SERVER_END
], NULL
, NULL
, TRUE
);
346 Ccb
->FileObject
[FILE_PIPE_SERVER_END
] = NULL
;
350 ReadQueue
= &Ccb
->DataQueue
[FILE_PIPE_OUTBOUND
];
351 WriteQueue
= &Ccb
->DataQueue
[FILE_PIPE_INBOUND
];
353 NpSetFileObject(Ccb
->FileObject
[FILE_PIPE_CLIENT_END
], NULL
, NULL
, FALSE
);
354 Ccb
->FileObject
[FILE_PIPE_CLIENT_END
] = NULL
;
357 EventBuffer
= NonPagedCcb
->EventBuffer
[NamedPipeEnd
];
359 Ccb
->NamedPipeState
= FILE_PIPE_CLOSING_STATE
;
361 while (ReadQueue
->QueueState
!= Empty
)
363 ListIrp
= NpRemoveDataQueueEntry(ReadQueue
, FALSE
, List
);
366 ListIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
367 InsertTailList(List
, &ListIrp
->Tail
.Overlay
.ListEntry
);
371 while (WriteQueue
->QueueState
== ReadEntries
)
373 ListIrp
= NpRemoveDataQueueEntry(WriteQueue
, FALSE
, List
);
376 ListIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
377 InsertTailList(List
, &ListIrp
->Tail
.Overlay
.ListEntry
);
381 if (EventBuffer
) KeSetEvent(EventBuffer
->Event
, IO_NO_INCREMENT
, FALSE
);
385 NpBugCheck(Ccb
->NamedPipeState
, 0, 0);
388 return STATUS_SUCCESS
;