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
, NotificationEvent
, FALSE
);
209 KeInitializeEvent(&ClientCcb
->WriteEvent
, NotificationEvent
, 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
);
260 ExFreePool(ClientCcb
);
261 KeUnlockMutex(&Fcb
->CcbListLock
);
262 Irp
->IoStatus
.Status
= STATUS_OBJECT_PATH_NOT_FOUND
;
263 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
264 return STATUS_OBJECT_PATH_NOT_FOUND
;
269 /* Signal the server thread and remove it from the waiter list */
270 /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
271 NpfsSignalAndRemoveListeningServerInstance(Fcb
, ServerCcb
);
274 else if (IsListEmpty(&Fcb
->ServerCcbListHead
))
276 DPRINT("No server fcb found!\n");
280 ExFreePool(ClientCcb
->Data
);
283 ExFreePool(ClientCcb
);
285 KeUnlockMutex(&Fcb
->CcbListLock
);
286 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
287 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
288 return STATUS_UNSUCCESSFUL
;
292 * Step 4. Add the client CCB to a list and connect it if possible.
295 /* Add the client CCB to the pipe CCB list. */
296 InsertTailList(&Fcb
->ClientCcbListHead
, &ClientCcb
->CcbListEntry
);
298 /* Connect to listening server side */
301 ClientCcb
->OtherSide
= ServerCcb
;
302 ServerCcb
->OtherSide
= ClientCcb
;
303 ClientCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
304 ServerCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
305 KeSetEvent(&ServerCcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
308 KeUnlockMutex(&Fcb
->CcbListLock
);
310 FileObject
->FsContext
= Fcb
;
311 FileObject
->FsContext2
= ClientCcb
;
312 FileObject
->Flags
|= FO_NAMED_PIPE
;
314 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
315 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
317 DPRINT("Success!\n");
319 return STATUS_SUCCESS
;
324 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject
,
327 PEXTENDED_IO_STACK_LOCATION IoStack
;
328 PFILE_OBJECT FileObject
;
329 PNPFS_DEVICE_EXTENSION DeviceExt
;
332 PNAMED_PIPE_CREATE_PARAMETERS Buffer
;
333 BOOLEAN NewPipe
= FALSE
;
335 DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
337 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
338 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
339 FileObject
= IoStack
->FileObject
;
340 DPRINT("FileObject %p\n", FileObject
);
341 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
343 Buffer
= IoStack
->Parameters
.CreatePipe
.Parameters
;
345 Irp
->IoStatus
.Information
= 0;
347 if (!(IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
)) ||
348 (IoStack
->Parameters
.CreatePipe
.ShareAccess
& ~(FILE_SHARE_READ
|FILE_SHARE_WRITE
)))
350 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
351 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
352 return STATUS_INVALID_PARAMETER
;
355 Ccb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_CCB
));
358 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
359 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
360 return STATUS_NO_MEMORY
;
363 Ccb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
364 KeLockMutex(&DeviceExt
->PipeListLock
);
367 * First search for existing Pipe with the same name.
369 Fcb
= NpfsFindPipe(DeviceExt
,
370 &FileObject
->FileName
);
374 * Found Pipe with the same name. Check if we are
377 KeUnlockMutex(&DeviceExt
->PipeListLock
);
379 if (Fcb
->CurrentInstances
>= Fcb
->MaximumInstances
)
381 DPRINT("Out of instances.\n");
383 Irp
->IoStatus
.Status
= STATUS_INSTANCE_NOT_AVAILABLE
;
384 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
385 return STATUS_INSTANCE_NOT_AVAILABLE
;
388 if (Fcb
->MaximumInstances
!= Buffer
->MaximumInstances
||
389 Fcb
->TimeOut
.QuadPart
!= Buffer
->DefaultTimeout
.QuadPart
||
390 Fcb
->PipeType
!= Buffer
->NamedPipeType
)
392 DPRINT("Asked for invalid pipe mode.\n");
394 Irp
->IoStatus
.Status
= STATUS_ACCESS_DENIED
;
395 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
396 return STATUS_ACCESS_DENIED
;
402 Fcb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_FCB
));
405 KeUnlockMutex(&DeviceExt
->PipeListLock
);
407 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
408 Irp
->IoStatus
.Information
= 0;
409 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
410 return STATUS_NO_MEMORY
;
413 Fcb
->PipeName
.Length
= FileObject
->FileName
.Length
;
414 Fcb
->PipeName
.MaximumLength
= Fcb
->PipeName
.Length
+ sizeof(UNICODE_NULL
);
415 Fcb
->PipeName
.Buffer
= ExAllocatePool(NonPagedPool
, Fcb
->PipeName
.MaximumLength
);
416 if (Fcb
->PipeName
.Buffer
== NULL
)
418 KeUnlockMutex(&DeviceExt
->PipeListLock
);
421 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
422 Irp
->IoStatus
.Information
= 0;
423 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
424 return STATUS_NO_MEMORY
;
427 RtlCopyUnicodeString(&Fcb
->PipeName
, &FileObject
->FileName
);
429 InitializeListHead(&Fcb
->ServerCcbListHead
);
430 InitializeListHead(&Fcb
->ClientCcbListHead
);
431 InitializeListHead(&Fcb
->WaiterListHead
);
432 KeInitializeMutex(&Fcb
->CcbListLock
, 0);
434 Fcb
->PipeType
= Buffer
->NamedPipeType
;
435 Fcb
->ServerReadMode
= Buffer
->ReadMode
;
436 /* MSDN documentation reads that clients always start off in byte mode */
437 Fcb
->ClientReadMode
= FILE_PIPE_BYTE_STREAM_MODE
;
439 Fcb
->CompletionMode
= Buffer
->CompletionMode
;
440 switch (IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
))
442 case FILE_SHARE_READ
:
443 Fcb
->PipeConfiguration
= FILE_PIPE_OUTBOUND
;
445 case FILE_SHARE_WRITE
:
446 Fcb
->PipeConfiguration
= FILE_PIPE_INBOUND
;
448 case FILE_SHARE_READ
|FILE_SHARE_WRITE
:
449 Fcb
->PipeConfiguration
= FILE_PIPE_FULL_DUPLEX
;
452 Fcb
->MaximumInstances
= Buffer
->MaximumInstances
;
453 Fcb
->CurrentInstances
= 0;
454 Fcb
->TimeOut
= Buffer
->DefaultTimeout
;
455 if (!(Fcb
->PipeConfiguration
& FILE_PIPE_OUTBOUND
) ||
456 Fcb
->PipeConfiguration
& FILE_PIPE_FULL_DUPLEX
)
458 if (Buffer
->InboundQuota
== 0)
460 Fcb
->InboundQuota
= DeviceExt
->DefaultQuota
;
464 Fcb
->InboundQuota
= PAGE_ROUND_UP(Buffer
->InboundQuota
);
465 if (Fcb
->InboundQuota
< DeviceExt
->MinQuota
)
467 Fcb
->InboundQuota
= DeviceExt
->MinQuota
;
469 else if (Fcb
->InboundQuota
> DeviceExt
->MaxQuota
)
471 Fcb
->InboundQuota
= DeviceExt
->MaxQuota
;
477 Fcb
->InboundQuota
= 0;
480 if (Fcb
->PipeConfiguration
& (FILE_PIPE_FULL_DUPLEX
|FILE_PIPE_OUTBOUND
))
482 if (Buffer
->OutboundQuota
== 0)
484 Fcb
->OutboundQuota
= DeviceExt
->DefaultQuota
;
488 Fcb
->OutboundQuota
= PAGE_ROUND_UP(Buffer
->OutboundQuota
);
489 if (Fcb
->OutboundQuota
< DeviceExt
->MinQuota
)
491 Fcb
->OutboundQuota
= DeviceExt
->MinQuota
;
493 else if (Fcb
->OutboundQuota
> DeviceExt
->MaxQuota
)
495 Fcb
->OutboundQuota
= DeviceExt
->MaxQuota
;
501 Fcb
->OutboundQuota
= 0;
504 InsertTailList(&DeviceExt
->PipeListHead
, &Fcb
->PipeListEntry
);
505 KeUnlockMutex(&DeviceExt
->PipeListLock
);
508 if (Fcb
->InboundQuota
)
510 Ccb
->Data
= ExAllocatePool(PagedPool
, Fcb
->InboundQuota
);
511 if (Ccb
->Data
== NULL
)
517 KeLockMutex(&DeviceExt
->PipeListLock
);
518 RemoveEntryList(&Fcb
->PipeListEntry
);
519 KeUnlockMutex(&DeviceExt
->PipeListLock
);
520 RtlFreeUnicodeString(&Fcb
->PipeName
);
524 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
525 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
526 return STATUS_NO_MEMORY
;
534 Ccb
->ReadPtr
= Ccb
->Data
;
535 Ccb
->WritePtr
= Ccb
->Data
;
536 Ccb
->ReadDataAvailable
= 0;
537 Ccb
->WriteQuotaAvailable
= Fcb
->InboundQuota
;
538 Ccb
->MaxDataLength
= Fcb
->InboundQuota
;
539 InitializeListHead(&Ccb
->ReadRequestListHead
);
540 ExInitializeFastMutex(&Ccb
->DataListLock
);
542 Fcb
->CurrentInstances
++;
545 Ccb
->PipeEnd
= FILE_PIPE_SERVER_END
;
546 Ccb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
547 Ccb
->OtherSide
= NULL
;
549 DPRINT("CCB: %p\n", Ccb
);
551 KeInitializeEvent(&Ccb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
552 KeInitializeEvent(&Ccb
->ReadEvent
, NotificationEvent
, FALSE
);
553 KeInitializeEvent(&Ccb
->WriteEvent
, NotificationEvent
, FALSE
);
555 KeLockMutex(&Fcb
->CcbListLock
);
556 InsertTailList(&Fcb
->ServerCcbListHead
, &Ccb
->CcbListEntry
);
557 KeUnlockMutex(&Fcb
->CcbListLock
);
559 FileObject
->FsContext
= Fcb
;
560 FileObject
->FsContext2
= Ccb
;
561 FileObject
->Flags
|= FO_NAMED_PIPE
;
563 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
564 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
566 DPRINT("Success!\n");
568 return STATUS_SUCCESS
;
573 NpfsCleanup(PDEVICE_OBJECT DeviceObject
,
576 PNPFS_DEVICE_EXTENSION DeviceExt
;
577 PIO_STACK_LOCATION IoStack
;
578 PFILE_OBJECT FileObject
;
579 PNPFS_CCB Ccb
, OtherSide
;
583 DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
585 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
586 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
587 FileObject
= IoStack
->FileObject
;
588 Ccb
= FileObject
->FsContext2
;
592 DPRINT("Success!\n");
593 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
594 Irp
->IoStatus
.Information
= 0;
595 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
596 return STATUS_SUCCESS
;
599 DPRINT("CCB %p\n", Ccb
);
602 DPRINT("Cleaning pipe %wZ\n", &Fcb
->PipeName
);
604 KeLockMutex(&Fcb
->CcbListLock
);
606 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
610 /* FIXME: Clean up existing connections here ?? */
617 if ((Ccb
->PipeState
== FILE_PIPE_CONNECTED_STATE
) && (Ccb
->OtherSide
))
619 OtherSide
= Ccb
->OtherSide
;
620 /* Lock the server first */
623 ExAcquireFastMutex(&Ccb
->DataListLock
);
624 ExAcquireFastMutex(&OtherSide
->DataListLock
);
628 ExAcquireFastMutex(&OtherSide
->DataListLock
);
629 ExAcquireFastMutex(&Ccb
->DataListLock
);
631 OtherSide
->OtherSide
= NULL
;
633 * Signaling the write event. If is possible that an other
634 * thread waits for an empty buffer.
636 KeSetEvent(&OtherSide
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
637 KeSetEvent(&OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
640 ExReleaseFastMutex(&OtherSide
->DataListLock
);
641 ExReleaseFastMutex(&Ccb
->DataListLock
);
645 ExReleaseFastMutex(&Ccb
->DataListLock
);
646 ExReleaseFastMutex(&OtherSide
->DataListLock
);
649 else if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
652 PNPFS_WAITER_ENTRY WaitEntry
= NULL
;
653 BOOLEAN Complete
= FALSE
;
657 Entry
= Ccb
->Fcb
->WaiterListHead
.Flink
;
658 while (Entry
!= &Ccb
->Fcb
->WaiterListHead
)
660 WaitEntry
= CONTAINING_RECORD(Entry
, NPFS_WAITER_ENTRY
, Entry
);
661 if (WaitEntry
->Ccb
== Ccb
)
663 RemoveEntryList(Entry
);
664 tmpIrp
= CONTAINING_RECORD(WaitEntry
, IRP
, Tail
.Overlay
.DriverContext
);
665 IoAcquireCancelSpinLock(&oldIrql
);
668 (void)IoSetCancelRoutine(tmpIrp
, NULL
);
671 IoReleaseCancelSpinLock(oldIrql
);
674 tmpIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
675 tmpIrp
->IoStatus
.Information
= 0;
676 IoCompleteRequest(tmpIrp
, IO_NO_INCREMENT
);
680 Entry
= Entry
->Flink
;
684 Ccb
->PipeState
= FILE_PIPE_CLOSING_STATE
;
686 KeUnlockMutex(&Fcb
->CcbListLock
);
688 ExAcquireFastMutex(&Ccb
->DataListLock
);
691 ExFreePool(Ccb
->Data
);
694 Ccb
->WritePtr
= NULL
;
696 ExReleaseFastMutex(&Ccb
->DataListLock
);
698 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
699 Irp
->IoStatus
.Information
= 0;
700 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
702 DPRINT("Success!\n");
704 return STATUS_SUCCESS
;
708 NpfsClose(PDEVICE_OBJECT DeviceObject
,
711 PNPFS_DEVICE_EXTENSION DeviceExt
;
712 PIO_STACK_LOCATION IoStack
;
713 PFILE_OBJECT FileObject
;
718 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
720 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
721 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
722 FileObject
= IoStack
->FileObject
;
723 Ccb
= FileObject
->FsContext2
;
727 DPRINT("Success!\n");
728 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
729 Irp
->IoStatus
.Information
= 0;
730 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
731 return STATUS_SUCCESS
;
734 DPRINT("CCB %p\n", Ccb
);
737 DPRINT("Closing pipe %wZ\n", &Fcb
->PipeName
);
739 KeLockMutex(&Fcb
->CcbListLock
);
741 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
746 Fcb
->CurrentInstances
--;
753 /* Disconnect the pipes */
756 Ccb
->OtherSide
->OtherSide
= NULL
;
757 Ccb
->OtherSide
= NULL
;
760 ASSERT(Ccb
->PipeState
== FILE_PIPE_CLOSING_STATE
);
762 FileObject
->FsContext2
= NULL
;
764 RemoveEntryList(&Ccb
->CcbListEntry
);
768 KeUnlockMutex(&Fcb
->CcbListLock
);
770 if (IsListEmpty(&Fcb
->ServerCcbListHead
) &&
771 IsListEmpty(&Fcb
->ClientCcbListHead
))
773 RtlFreeUnicodeString(&Fcb
->PipeName
);
774 KeLockMutex(&DeviceExt
->PipeListLock
);
775 RemoveEntryList(&Fcb
->PipeListEntry
);
776 KeUnlockMutex(&DeviceExt
->PipeListLock
);
778 FileObject
->FsContext
= NULL
;
781 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
782 Irp
->IoStatus
.Information
= 0;
783 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
785 DPRINT("Success!\n");
787 return STATUS_SUCCESS
;