2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/fs/np/create.c
5 * PURPOSE: Named pipe filesystem
6 * PROGRAMMER: David Welch <welch@cwcom.net>
9 /* INCLUDES ******************************************************************/
16 /* FUNCTIONS *****************************************************************/
19 NpfsFindPipe(PNPFS_DEVICE_EXTENSION DeviceExt
,
20 PUNICODE_STRING PipeName
)
22 PLIST_ENTRY CurrentEntry
;
25 CurrentEntry
= DeviceExt
->PipeListHead
.Flink
;
26 while (CurrentEntry
!= &DeviceExt
->PipeListHead
)
28 Fcb
= CONTAINING_RECORD(CurrentEntry
, NPFS_FCB
, PipeListEntry
);
29 if (RtlCompareUnicodeString(PipeName
,
33 DPRINT("<%wZ> = <%wZ>\n", PipeName
, &Fcb
->PipeName
);
37 CurrentEntry
= CurrentEntry
->Flink
;
45 NpfsFindListeningServerInstance(PNPFS_FCB Fcb
)
47 PLIST_ENTRY CurrentEntry
;
48 PNPFS_WAITER_ENTRY Waiter
;
52 CurrentEntry
= Fcb
->WaiterListHead
.Flink
;
53 while (CurrentEntry
!= &Fcb
->WaiterListHead
)
55 Waiter
= CONTAINING_RECORD(CurrentEntry
, NPFS_WAITER_ENTRY
, Entry
);
56 Irp
= CONTAINING_RECORD(Waiter
, IRP
, Tail
.Overlay
.DriverContext
);
57 if (Waiter
->Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
59 DPRINT("Server found! CCB %p\n", Waiter
->Ccb
);
61 IoAcquireCancelSpinLock(&oldIrql
);
64 (void)IoSetCancelRoutine(Irp
, NULL
);
65 IoReleaseCancelSpinLock(oldIrql
);
68 IoReleaseCancelSpinLock(oldIrql
);
71 CurrentEntry
= CurrentEntry
->Flink
;
79 NpfsSignalAndRemoveListeningServerInstance(PNPFS_FCB Fcb
,
82 PLIST_ENTRY CurrentEntry
;
83 PNPFS_WAITER_ENTRY Waiter
;
86 CurrentEntry
= Fcb
->WaiterListHead
.Flink
;
87 while (CurrentEntry
!= &Fcb
->WaiterListHead
)
89 Waiter
= CONTAINING_RECORD(CurrentEntry
, NPFS_WAITER_ENTRY
, Entry
);
90 if (Waiter
->Ccb
== Ccb
)
92 DPRINT("Server found! CCB %p\n", Waiter
->Ccb
);
94 RemoveEntryList(&Waiter
->Entry
);
95 Irp
= CONTAINING_RECORD(Waiter
, IRP
, Tail
.Overlay
.DriverContext
);
96 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
97 Irp
->IoStatus
.Information
= 0;
98 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
101 CurrentEntry
= CurrentEntry
->Flink
;
107 NpfsCreate(PDEVICE_OBJECT DeviceObject
,
110 PEXTENDED_IO_STACK_LOCATION IoStack
;
111 PFILE_OBJECT FileObject
;
114 PNPFS_CCB ServerCcb
= NULL
;
115 PNPFS_DEVICE_EXTENSION DeviceExt
;
116 BOOLEAN SpecialAccess
;
117 ACCESS_MASK DesiredAccess
;
119 DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
121 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
122 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
123 FileObject
= IoStack
->FileObject
;
124 DesiredAccess
= IoStack
->Parameters
.CreatePipe
.SecurityContext
->DesiredAccess
;
125 DPRINT("FileObject %p\n", FileObject
);
126 DPRINT("FileName %wZ\n", &FileObject
->FileName
);
128 Irp
->IoStatus
.Information
= 0;
130 SpecialAccess
= ((DesiredAccess
& SPECIFIC_RIGHTS_ALL
) == FILE_READ_ATTRIBUTES
);
133 DPRINT("NpfsCreate() open client end for special use!\n");
137 * Step 1. Find the pipe we're trying to open.
139 KeLockMutex(&DeviceExt
->PipeListLock
);
140 Fcb
= NpfsFindPipe(DeviceExt
,
141 &FileObject
->FileName
);
144 /* Not found, bail out with error. */
145 DPRINT("No pipe found!\n");
146 KeUnlockMutex(&DeviceExt
->PipeListLock
);
147 Irp
->IoStatus
.Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
148 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
149 return STATUS_OBJECT_NAME_NOT_FOUND
;
152 KeUnlockMutex(&DeviceExt
->PipeListLock
);
155 * Acquire the lock for CCB lists. From now on no modifications to the
156 * CCB lists are allowed, because it can cause various misconsistencies.
158 KeLockMutex(&Fcb
->CcbListLock
);
161 * Step 2. Create the client CCB.
163 ClientCcb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_CCB
));
164 if (ClientCcb
== NULL
)
166 DPRINT("No memory!\n");
167 KeUnlockMutex(&Fcb
->CcbListLock
);
168 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
169 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
170 return STATUS_NO_MEMORY
;
173 ClientCcb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
174 ClientCcb
->Fcb
= Fcb
;
175 ClientCcb
->PipeEnd
= FILE_PIPE_CLIENT_END
;
176 ClientCcb
->OtherSide
= NULL
;
177 ClientCcb
->PipeState
= SpecialAccess
? 0 : FILE_PIPE_DISCONNECTED_STATE
;
178 InitializeListHead(&ClientCcb
->ReadRequestListHead
);
180 DPRINT("CCB: %p\n", ClientCcb
);
182 /* Initialize data list. */
183 if (Fcb
->OutboundQuota
)
185 ClientCcb
->Data
= ExAllocatePool(PagedPool
, Fcb
->OutboundQuota
);
186 if (ClientCcb
->Data
== NULL
)
188 DPRINT("No memory!\n");
189 ExFreePool(ClientCcb
);
190 KeUnlockMutex(&Fcb
->CcbListLock
);
191 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
192 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
193 return STATUS_NO_MEMORY
;
198 ClientCcb
->Data
= NULL
;
201 ClientCcb
->ReadPtr
= ClientCcb
->Data
;
202 ClientCcb
->WritePtr
= ClientCcb
->Data
;
203 ClientCcb
->ReadDataAvailable
= 0;
204 ClientCcb
->WriteQuotaAvailable
= Fcb
->OutboundQuota
;
205 ClientCcb
->MaxDataLength
= Fcb
->OutboundQuota
;
206 ExInitializeFastMutex(&ClientCcb
->DataListLock
);
207 KeInitializeEvent(&ClientCcb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
208 KeInitializeEvent(&ClientCcb
->ReadEvent
, SynchronizationEvent
, FALSE
);
209 KeInitializeEvent(&ClientCcb
->WriteEvent
, SynchronizationEvent
, FALSE
);
213 * Step 3. Search for listening server CCB.
219 * WARNING: Point of no return! Once we get the server CCB it's
220 * possible that we completed a wait request and so we have to
221 * complete even this request.
224 ServerCcb
= NpfsFindListeningServerInstance(Fcb
);
225 if (ServerCcb
== NULL
)
227 PLIST_ENTRY CurrentEntry
;
231 * If no waiting server CCB was found then try to pick
232 * one of the listing server CCB on the pipe.
235 CurrentEntry
= Fcb
->ServerCcbListHead
.Flink
;
236 while (CurrentEntry
!= &Fcb
->ServerCcbListHead
)
238 Ccb
= CONTAINING_RECORD(CurrentEntry
, NPFS_CCB
, CcbListEntry
);
239 if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
244 CurrentEntry
= CurrentEntry
->Flink
;
248 * No one is listening to me?! I'm so lonely... :(
251 if (ServerCcb
== NULL
)
253 /* Not found, bail out with error for FILE_OPEN requests. */
254 DPRINT("No listening server CCB found!\n");
257 ExFreePool(ClientCcb
->Data
);
258 ClientCcb
->Data
= NULL
;
260 KeUnlockMutex(&Fcb
->CcbListLock
);
261 Irp
->IoStatus
.Status
= STATUS_OBJECT_PATH_NOT_FOUND
;
262 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
263 return STATUS_OBJECT_PATH_NOT_FOUND
;
268 /* Signal the server thread and remove it from the waiter list */
269 /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
270 NpfsSignalAndRemoveListeningServerInstance(Fcb
, ServerCcb
);
273 else if (IsListEmpty(&Fcb
->ServerCcbListHead
))
275 DPRINT("No server fcb found!\n");
276 KeUnlockMutex(&Fcb
->CcbListLock
);
277 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
278 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
279 return STATUS_UNSUCCESSFUL
;
283 * Step 4. Add the client CCB to a list and connect it if possible.
286 /* Add the client CCB to the pipe CCB list. */
287 InsertTailList(&Fcb
->ClientCcbListHead
, &ClientCcb
->CcbListEntry
);
289 /* Connect to listening server side */
292 ClientCcb
->OtherSide
= ServerCcb
;
293 ServerCcb
->OtherSide
= ClientCcb
;
294 ClientCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
295 ServerCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
296 KeSetEvent(&ServerCcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
299 KeUnlockMutex(&Fcb
->CcbListLock
);
301 FileObject
->FsContext
= Fcb
;
302 FileObject
->FsContext2
= ClientCcb
;
303 FileObject
->Flags
|= FO_NAMED_PIPE
;
305 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
306 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
308 DPRINT("Success!\n");
310 return STATUS_SUCCESS
;
315 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject
,
318 PEXTENDED_IO_STACK_LOCATION IoStack
;
319 PFILE_OBJECT FileObject
;
320 PNPFS_DEVICE_EXTENSION DeviceExt
;
323 PNAMED_PIPE_CREATE_PARAMETERS Buffer
;
324 BOOLEAN NewPipe
= FALSE
;
326 DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
328 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
329 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
330 FileObject
= IoStack
->FileObject
;
331 DPRINT("FileObject %p\n", FileObject
);
332 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
334 Buffer
= IoStack
->Parameters
.CreatePipe
.Parameters
;
336 Irp
->IoStatus
.Information
= 0;
338 if (!(IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
)) ||
339 (IoStack
->Parameters
.CreatePipe
.ShareAccess
& ~(FILE_SHARE_READ
|FILE_SHARE_WRITE
)))
341 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
342 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
343 return STATUS_INVALID_PARAMETER
;
346 Ccb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_CCB
));
349 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
350 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
351 return STATUS_NO_MEMORY
;
354 Ccb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
355 KeLockMutex(&DeviceExt
->PipeListLock
);
358 * First search for existing Pipe with the same name.
360 Fcb
= NpfsFindPipe(DeviceExt
,
361 &FileObject
->FileName
);
365 * Found Pipe with the same name. Check if we are
368 KeUnlockMutex(&DeviceExt
->PipeListLock
);
370 if (Fcb
->CurrentInstances
>= Fcb
->MaximumInstances
)
372 DPRINT("Out of instances.\n");
374 Irp
->IoStatus
.Status
= STATUS_INSTANCE_NOT_AVAILABLE
;
375 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
376 return STATUS_INSTANCE_NOT_AVAILABLE
;
379 if (Fcb
->MaximumInstances
!= Buffer
->MaximumInstances
||
380 Fcb
->TimeOut
.QuadPart
!= Buffer
->DefaultTimeout
.QuadPart
||
381 Fcb
->PipeType
!= Buffer
->NamedPipeType
)
383 DPRINT("Asked for invalid pipe mode.\n");
385 Irp
->IoStatus
.Status
= STATUS_ACCESS_DENIED
;
386 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
387 return STATUS_ACCESS_DENIED
;
393 Fcb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_FCB
));
396 KeUnlockMutex(&DeviceExt
->PipeListLock
);
398 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
399 Irp
->IoStatus
.Information
= 0;
400 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
401 return STATUS_NO_MEMORY
;
404 Fcb
->PipeName
.Length
= FileObject
->FileName
.Length
;
405 Fcb
->PipeName
.MaximumLength
= Fcb
->PipeName
.Length
+ sizeof(UNICODE_NULL
);
406 Fcb
->PipeName
.Buffer
= ExAllocatePool(NonPagedPool
, Fcb
->PipeName
.MaximumLength
);
407 if (Fcb
->PipeName
.Buffer
== NULL
)
409 KeUnlockMutex(&DeviceExt
->PipeListLock
);
412 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
413 Irp
->IoStatus
.Information
= 0;
414 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
415 return STATUS_NO_MEMORY
;
418 RtlCopyUnicodeString(&Fcb
->PipeName
, &FileObject
->FileName
);
420 InitializeListHead(&Fcb
->ServerCcbListHead
);
421 InitializeListHead(&Fcb
->ClientCcbListHead
);
422 InitializeListHead(&Fcb
->WaiterListHead
);
423 KeInitializeMutex(&Fcb
->CcbListLock
, 0);
425 Fcb
->PipeType
= Buffer
->NamedPipeType
;
426 Fcb
->ServerReadMode
= Buffer
->ReadMode
;
427 /* MSDN documentation reads that clients always start off in byte mode */
428 Fcb
->ClientReadMode
= FILE_PIPE_BYTE_STREAM_MODE
;
430 Fcb
->CompletionMode
= Buffer
->CompletionMode
;
431 switch (IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
))
433 case FILE_SHARE_READ
:
434 Fcb
->PipeConfiguration
= FILE_PIPE_OUTBOUND
;
436 case FILE_SHARE_WRITE
:
437 Fcb
->PipeConfiguration
= FILE_PIPE_INBOUND
;
439 case FILE_SHARE_READ
|FILE_SHARE_WRITE
:
440 Fcb
->PipeConfiguration
= FILE_PIPE_FULL_DUPLEX
;
443 Fcb
->MaximumInstances
= Buffer
->MaximumInstances
;
444 Fcb
->CurrentInstances
= 0;
445 Fcb
->TimeOut
= Buffer
->DefaultTimeout
;
446 if (!(Fcb
->PipeConfiguration
& FILE_PIPE_OUTBOUND
) ||
447 Fcb
->PipeConfiguration
& FILE_PIPE_FULL_DUPLEX
)
449 if (Buffer
->InboundQuota
== 0)
451 Fcb
->InboundQuota
= DeviceExt
->DefaultQuota
;
455 Fcb
->InboundQuota
= PAGE_ROUND_UP(Buffer
->InboundQuota
);
456 if (Fcb
->InboundQuota
< DeviceExt
->MinQuota
)
458 Fcb
->InboundQuota
= DeviceExt
->MinQuota
;
460 else if (Fcb
->InboundQuota
> DeviceExt
->MaxQuota
)
462 Fcb
->InboundQuota
= DeviceExt
->MaxQuota
;
468 Fcb
->InboundQuota
= 0;
471 if (Fcb
->PipeConfiguration
& (FILE_PIPE_FULL_DUPLEX
|FILE_PIPE_OUTBOUND
))
473 if (Buffer
->OutboundQuota
== 0)
475 Fcb
->OutboundQuota
= DeviceExt
->DefaultQuota
;
479 Fcb
->OutboundQuota
= PAGE_ROUND_UP(Buffer
->OutboundQuota
);
480 if (Fcb
->OutboundQuota
< DeviceExt
->MinQuota
)
482 Fcb
->OutboundQuota
= DeviceExt
->MinQuota
;
484 else if (Fcb
->OutboundQuota
> DeviceExt
->MaxQuota
)
486 Fcb
->OutboundQuota
= DeviceExt
->MaxQuota
;
492 Fcb
->OutboundQuota
= 0;
495 InsertTailList(&DeviceExt
->PipeListHead
, &Fcb
->PipeListEntry
);
496 KeUnlockMutex(&DeviceExt
->PipeListLock
);
499 if (Fcb
->InboundQuota
)
501 Ccb
->Data
= ExAllocatePool(PagedPool
, Fcb
->InboundQuota
);
502 if (Ccb
->Data
== NULL
)
508 KeLockMutex(&DeviceExt
->PipeListLock
);
509 RemoveEntryList(&Fcb
->PipeListEntry
);
510 KeUnlockMutex(&DeviceExt
->PipeListLock
);
511 RtlFreeUnicodeString(&Fcb
->PipeName
);
515 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
516 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
517 return STATUS_NO_MEMORY
;
525 Ccb
->ReadPtr
= Ccb
->Data
;
526 Ccb
->WritePtr
= Ccb
->Data
;
527 Ccb
->ReadDataAvailable
= 0;
528 Ccb
->WriteQuotaAvailable
= Fcb
->InboundQuota
;
529 Ccb
->MaxDataLength
= Fcb
->InboundQuota
;
530 InitializeListHead(&Ccb
->ReadRequestListHead
);
531 ExInitializeFastMutex(&Ccb
->DataListLock
);
533 Fcb
->CurrentInstances
++;
536 Ccb
->PipeEnd
= FILE_PIPE_SERVER_END
;
537 Ccb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
538 Ccb
->OtherSide
= NULL
;
540 DPRINT("CCB: %p\n", Ccb
);
542 KeInitializeEvent(&Ccb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
543 KeInitializeEvent(&Ccb
->ReadEvent
, SynchronizationEvent
, FALSE
);
544 KeInitializeEvent(&Ccb
->WriteEvent
, SynchronizationEvent
, FALSE
);
546 KeLockMutex(&Fcb
->CcbListLock
);
547 InsertTailList(&Fcb
->ServerCcbListHead
, &Ccb
->CcbListEntry
);
548 KeUnlockMutex(&Fcb
->CcbListLock
);
550 FileObject
->FsContext
= Fcb
;
551 FileObject
->FsContext2
= Ccb
;
552 FileObject
->Flags
|= FO_NAMED_PIPE
;
554 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
555 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
557 DPRINT("Success!\n");
559 return STATUS_SUCCESS
;
564 NpfsCleanup(PDEVICE_OBJECT DeviceObject
,
567 PNPFS_DEVICE_EXTENSION DeviceExt
;
568 PIO_STACK_LOCATION IoStack
;
569 PFILE_OBJECT FileObject
;
570 PNPFS_CCB Ccb
, OtherSide
;
574 DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
576 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
577 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
578 FileObject
= IoStack
->FileObject
;
579 Ccb
= FileObject
->FsContext2
;
583 DPRINT("Success!\n");
584 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
585 Irp
->IoStatus
.Information
= 0;
586 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
587 return STATUS_SUCCESS
;
590 DPRINT("CCB %p\n", Ccb
);
593 DPRINT("Cleaning pipe %wZ\n", &Fcb
->PipeName
);
595 KeLockMutex(&Fcb
->CcbListLock
);
597 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
601 /* FIXME: Clean up existing connections here ?? */
608 if ((Ccb
->PipeState
== FILE_PIPE_CONNECTED_STATE
) && (Ccb
->OtherSide
))
610 OtherSide
= Ccb
->OtherSide
;
611 /* Lock the server first */
614 ExAcquireFastMutex(&Ccb
->DataListLock
);
615 ExAcquireFastMutex(&OtherSide
->DataListLock
);
619 ExAcquireFastMutex(&OtherSide
->DataListLock
);
620 ExAcquireFastMutex(&Ccb
->DataListLock
);
622 //OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
623 OtherSide
->OtherSide
= NULL
;
625 * Signaling the write event. If is possible that an other
626 * thread waits for an empty buffer.
628 KeSetEvent(&OtherSide
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
629 KeSetEvent(&OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
632 ExReleaseFastMutex(&OtherSide
->DataListLock
);
633 ExReleaseFastMutex(&Ccb
->DataListLock
);
637 ExReleaseFastMutex(&Ccb
->DataListLock
);
638 ExReleaseFastMutex(&OtherSide
->DataListLock
);
641 else if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
644 PNPFS_WAITER_ENTRY WaitEntry
= NULL
;
645 BOOLEAN Complete
= FALSE
;
649 Entry
= Ccb
->Fcb
->WaiterListHead
.Flink
;
650 while (Entry
!= &Ccb
->Fcb
->WaiterListHead
)
652 WaitEntry
= CONTAINING_RECORD(Entry
, NPFS_WAITER_ENTRY
, Entry
);
653 if (WaitEntry
->Ccb
== Ccb
)
655 RemoveEntryList(Entry
);
656 tmpIrp
= CONTAINING_RECORD(WaitEntry
, IRP
, Tail
.Overlay
.DriverContext
);
657 IoAcquireCancelSpinLock(&oldIrql
);
660 (void)IoSetCancelRoutine(tmpIrp
, NULL
);
663 IoReleaseCancelSpinLock(oldIrql
);
666 tmpIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
667 tmpIrp
->IoStatus
.Information
= 0;
668 IoCompleteRequest(tmpIrp
, IO_NO_INCREMENT
);
672 Entry
= Entry
->Flink
;
676 Ccb
->PipeState
= FILE_PIPE_CLOSING_STATE
;
678 KeUnlockMutex(&Fcb
->CcbListLock
);
680 ExAcquireFastMutex(&Ccb
->DataListLock
);
683 ExFreePool(Ccb
->Data
);
686 Ccb
->WritePtr
= NULL
;
688 ExReleaseFastMutex(&Ccb
->DataListLock
);
690 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
691 Irp
->IoStatus
.Information
= 0;
692 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
694 DPRINT("Success!\n");
696 return STATUS_SUCCESS
;
700 NpfsClose(PDEVICE_OBJECT DeviceObject
,
703 PNPFS_DEVICE_EXTENSION DeviceExt
;
704 PIO_STACK_LOCATION IoStack
;
705 PFILE_OBJECT FileObject
;
710 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
712 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
713 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
714 FileObject
= IoStack
->FileObject
;
715 Ccb
= FileObject
->FsContext2
;
719 DPRINT("Success!\n");
720 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
721 Irp
->IoStatus
.Information
= 0;
722 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
723 return STATUS_SUCCESS
;
726 DPRINT("CCB %p\n", Ccb
);
729 DPRINT("Closing pipe %wZ\n", &Fcb
->PipeName
);
731 KeLockMutex(&Fcb
->CcbListLock
);
733 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
738 Fcb
->CurrentInstances
--;
745 /* Disconnect the pipes */
746 if (Ccb
->OtherSide
) Ccb
->OtherSide
->OtherSide
= NULL
;
747 if (Ccb
) Ccb
->OtherSide
= NULL
;
749 ASSERT(Ccb
->PipeState
== FILE_PIPE_CLOSING_STATE
);
751 FileObject
->FsContext2
= NULL
;
753 RemoveEntryList(&Ccb
->CcbListEntry
);
757 KeUnlockMutex(&Fcb
->CcbListLock
);
759 if (IsListEmpty(&Fcb
->ServerCcbListHead
) &&
760 IsListEmpty(&Fcb
->ClientCcbListHead
))
762 RtlFreeUnicodeString(&Fcb
->PipeName
);
763 KeLockMutex(&DeviceExt
->PipeListLock
);
764 RemoveEntryList(&Fcb
->PipeListEntry
);
765 KeUnlockMutex(&DeviceExt
->PipeListLock
);
767 FileObject
->FsContext
= NULL
;
770 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
771 Irp
->IoStatus
.Information
= 0;
772 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
774 DPRINT("Success!\n");
776 return STATUS_SUCCESS
;