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");
256 ExFreePool(ClientCcb
->Data
);
257 KeUnlockMutex(&Fcb
->CcbListLock
);
258 Irp
->IoStatus
.Status
= STATUS_OBJECT_PATH_NOT_FOUND
;
259 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
260 return STATUS_OBJECT_PATH_NOT_FOUND
;
265 /* Signal the server thread and remove it from the waiter list */
266 /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
267 NpfsSignalAndRemoveListeningServerInstance(Fcb
, ServerCcb
);
270 else if (IsListEmpty(&Fcb
->ServerCcbListHead
))
272 DPRINT("No server fcb found!\n");
273 KeUnlockMutex(&Fcb
->CcbListLock
);
274 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
275 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
276 return STATUS_UNSUCCESSFUL
;
280 * Step 4. Add the client CCB to a list and connect it if possible.
283 /* Add the client CCB to the pipe CCB list. */
284 InsertTailList(&Fcb
->ClientCcbListHead
, &ClientCcb
->CcbListEntry
);
286 /* Connect to listening server side */
289 ClientCcb
->OtherSide
= ServerCcb
;
290 ServerCcb
->OtherSide
= ClientCcb
;
291 ClientCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
292 ServerCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
293 KeSetEvent(&ServerCcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
296 KeUnlockMutex(&Fcb
->CcbListLock
);
298 FileObject
->FsContext
= Fcb
;
299 FileObject
->FsContext2
= ClientCcb
;
300 FileObject
->Flags
|= FO_NAMED_PIPE
;
302 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
303 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
305 DPRINT("Success!\n");
307 return STATUS_SUCCESS
;
312 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject
,
315 PEXTENDED_IO_STACK_LOCATION IoStack
;
316 PFILE_OBJECT FileObject
;
317 PNPFS_DEVICE_EXTENSION DeviceExt
;
320 PNAMED_PIPE_CREATE_PARAMETERS Buffer
;
321 BOOLEAN NewPipe
= FALSE
;
323 DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
325 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
326 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
327 FileObject
= IoStack
->FileObject
;
328 DPRINT("FileObject %p\n", FileObject
);
329 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
331 Buffer
= IoStack
->Parameters
.CreatePipe
.Parameters
;
333 Irp
->IoStatus
.Information
= 0;
335 if (!(IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
)) ||
336 (IoStack
->Parameters
.CreatePipe
.ShareAccess
& ~(FILE_SHARE_READ
|FILE_SHARE_WRITE
)))
338 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
339 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
340 return STATUS_INVALID_PARAMETER
;
343 Ccb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_CCB
));
346 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
347 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
348 return STATUS_NO_MEMORY
;
351 Ccb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
352 KeLockMutex(&DeviceExt
->PipeListLock
);
355 * First search for existing Pipe with the same name.
357 Fcb
= NpfsFindPipe(DeviceExt
,
358 &FileObject
->FileName
);
362 * Found Pipe with the same name. Check if we are
365 KeUnlockMutex(&DeviceExt
->PipeListLock
);
367 if (Fcb
->CurrentInstances
>= Fcb
->MaximumInstances
)
369 DPRINT("Out of instances.\n");
371 Irp
->IoStatus
.Status
= STATUS_INSTANCE_NOT_AVAILABLE
;
372 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
373 return STATUS_INSTANCE_NOT_AVAILABLE
;
376 if (Fcb
->MaximumInstances
!= Buffer
->MaximumInstances
||
377 Fcb
->TimeOut
.QuadPart
!= Buffer
->DefaultTimeout
.QuadPart
||
378 Fcb
->PipeType
!= Buffer
->NamedPipeType
)
380 DPRINT("Asked for invalid pipe mode.\n");
382 Irp
->IoStatus
.Status
= STATUS_ACCESS_DENIED
;
383 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
384 return STATUS_ACCESS_DENIED
;
390 Fcb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_FCB
));
393 KeUnlockMutex(&DeviceExt
->PipeListLock
);
395 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
396 Irp
->IoStatus
.Information
= 0;
397 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
398 return STATUS_NO_MEMORY
;
401 Fcb
->PipeName
.Length
= FileObject
->FileName
.Length
;
402 Fcb
->PipeName
.MaximumLength
= Fcb
->PipeName
.Length
+ sizeof(UNICODE_NULL
);
403 Fcb
->PipeName
.Buffer
= ExAllocatePool(NonPagedPool
, Fcb
->PipeName
.MaximumLength
);
404 if (Fcb
->PipeName
.Buffer
== NULL
)
406 KeUnlockMutex(&DeviceExt
->PipeListLock
);
409 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
410 Irp
->IoStatus
.Information
= 0;
411 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
412 return STATUS_NO_MEMORY
;
415 RtlCopyUnicodeString(&Fcb
->PipeName
, &FileObject
->FileName
);
417 InitializeListHead(&Fcb
->ServerCcbListHead
);
418 InitializeListHead(&Fcb
->ClientCcbListHead
);
419 InitializeListHead(&Fcb
->WaiterListHead
);
420 KeInitializeMutex(&Fcb
->CcbListLock
, 0);
422 Fcb
->PipeType
= Buffer
->NamedPipeType
;
423 Fcb
->ServerReadMode
= Buffer
->ReadMode
;
424 /* MSDN documentation reads that clients always start off in byte mode */
425 Fcb
->ClientReadMode
= FILE_PIPE_BYTE_STREAM_MODE
;
427 Fcb
->CompletionMode
= Buffer
->CompletionMode
;
428 switch (IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
))
430 case FILE_SHARE_READ
:
431 Fcb
->PipeConfiguration
= FILE_PIPE_OUTBOUND
;
433 case FILE_SHARE_WRITE
:
434 Fcb
->PipeConfiguration
= FILE_PIPE_INBOUND
;
436 case FILE_SHARE_READ
|FILE_SHARE_WRITE
:
437 Fcb
->PipeConfiguration
= FILE_PIPE_FULL_DUPLEX
;
440 Fcb
->MaximumInstances
= Buffer
->MaximumInstances
;
441 Fcb
->CurrentInstances
= 0;
442 Fcb
->TimeOut
= Buffer
->DefaultTimeout
;
443 if (!(Fcb
->PipeConfiguration
& FILE_PIPE_OUTBOUND
) ||
444 Fcb
->PipeConfiguration
& FILE_PIPE_FULL_DUPLEX
)
446 if (Buffer
->InboundQuota
== 0)
448 Fcb
->InboundQuota
= DeviceExt
->DefaultQuota
;
452 Fcb
->InboundQuota
= PAGE_ROUND_UP(Buffer
->InboundQuota
);
453 if (Fcb
->InboundQuota
< DeviceExt
->MinQuota
)
455 Fcb
->InboundQuota
= DeviceExt
->MinQuota
;
457 else if (Fcb
->InboundQuota
> DeviceExt
->MaxQuota
)
459 Fcb
->InboundQuota
= DeviceExt
->MaxQuota
;
465 Fcb
->InboundQuota
= 0;
468 if (Fcb
->PipeConfiguration
& (FILE_PIPE_FULL_DUPLEX
|FILE_PIPE_OUTBOUND
))
470 if (Buffer
->OutboundQuota
== 0)
472 Fcb
->OutboundQuota
= DeviceExt
->DefaultQuota
;
476 Fcb
->OutboundQuota
= PAGE_ROUND_UP(Buffer
->OutboundQuota
);
477 if (Fcb
->OutboundQuota
< DeviceExt
->MinQuota
)
479 Fcb
->OutboundQuota
= DeviceExt
->MinQuota
;
481 else if (Fcb
->OutboundQuota
> DeviceExt
->MaxQuota
)
483 Fcb
->OutboundQuota
= DeviceExt
->MaxQuota
;
489 Fcb
->OutboundQuota
= 0;
492 InsertTailList(&DeviceExt
->PipeListHead
, &Fcb
->PipeListEntry
);
493 KeUnlockMutex(&DeviceExt
->PipeListLock
);
496 if (Fcb
->InboundQuota
)
498 Ccb
->Data
= ExAllocatePool(PagedPool
, Fcb
->InboundQuota
);
499 if (Ccb
->Data
== NULL
)
505 KeLockMutex(&DeviceExt
->PipeListLock
);
506 RemoveEntryList(&Fcb
->PipeListEntry
);
507 KeUnlockMutex(&DeviceExt
->PipeListLock
);
508 RtlFreeUnicodeString(&Fcb
->PipeName
);
512 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
513 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
514 return STATUS_NO_MEMORY
;
522 Ccb
->ReadPtr
= Ccb
->Data
;
523 Ccb
->WritePtr
= Ccb
->Data
;
524 Ccb
->ReadDataAvailable
= 0;
525 Ccb
->WriteQuotaAvailable
= Fcb
->InboundQuota
;
526 Ccb
->MaxDataLength
= Fcb
->InboundQuota
;
527 InitializeListHead(&Ccb
->ReadRequestListHead
);
528 ExInitializeFastMutex(&Ccb
->DataListLock
);
530 Fcb
->CurrentInstances
++;
533 Ccb
->PipeEnd
= FILE_PIPE_SERVER_END
;
534 Ccb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
535 Ccb
->OtherSide
= NULL
;
537 DPRINT("CCB: %p\n", Ccb
);
539 KeInitializeEvent(&Ccb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
540 KeInitializeEvent(&Ccb
->ReadEvent
, SynchronizationEvent
, FALSE
);
541 KeInitializeEvent(&Ccb
->WriteEvent
, SynchronizationEvent
, FALSE
);
543 KeLockMutex(&Fcb
->CcbListLock
);
544 InsertTailList(&Fcb
->ServerCcbListHead
, &Ccb
->CcbListEntry
);
545 KeUnlockMutex(&Fcb
->CcbListLock
);
547 FileObject
->FsContext
= Fcb
;
548 FileObject
->FsContext2
= Ccb
;
549 FileObject
->Flags
|= FO_NAMED_PIPE
;
551 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
552 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
554 DPRINT("Success!\n");
556 return STATUS_SUCCESS
;
561 NpfsCleanup(PDEVICE_OBJECT DeviceObject
,
564 PNPFS_DEVICE_EXTENSION DeviceExt
;
565 PIO_STACK_LOCATION IoStack
;
566 PFILE_OBJECT FileObject
;
567 PNPFS_CCB Ccb
, OtherSide
;
571 DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
573 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
574 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
575 FileObject
= IoStack
->FileObject
;
576 Ccb
= FileObject
->FsContext2
;
580 DPRINT("Success!\n");
581 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
582 Irp
->IoStatus
.Information
= 0;
583 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
584 return STATUS_SUCCESS
;
587 DPRINT("CCB %p\n", Ccb
);
590 DPRINT("Cleaning pipe %wZ\n", &Fcb
->PipeName
);
592 KeLockMutex(&Fcb
->CcbListLock
);
594 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
598 /* FIXME: Clean up existing connections here ?? */
605 if (Ccb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
607 OtherSide
= Ccb
->OtherSide
;
608 /* Lock the server first */
611 ExAcquireFastMutex(&Ccb
->DataListLock
);
612 ExAcquireFastMutex(&OtherSide
->DataListLock
);
616 ExAcquireFastMutex(&OtherSide
->DataListLock
);
617 ExAcquireFastMutex(&Ccb
->DataListLock
);
619 OtherSide
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
620 OtherSide
->OtherSide
= NULL
;
622 * Signaling the write event. If is possible that an other
623 * thread waits for an empty buffer.
625 KeSetEvent(&OtherSide
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
626 KeSetEvent(&OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
629 ExReleaseFastMutex(&OtherSide
->DataListLock
);
630 ExReleaseFastMutex(&Ccb
->DataListLock
);
634 ExReleaseFastMutex(&Ccb
->DataListLock
);
635 ExReleaseFastMutex(&OtherSide
->DataListLock
);
638 else if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
641 PNPFS_WAITER_ENTRY WaitEntry
= NULL
;
642 BOOLEAN Complete
= FALSE
;
646 Entry
= Ccb
->Fcb
->WaiterListHead
.Flink
;
647 while (Entry
!= &Ccb
->Fcb
->WaiterListHead
)
649 WaitEntry
= CONTAINING_RECORD(Entry
, NPFS_WAITER_ENTRY
, Entry
);
650 if (WaitEntry
->Ccb
== Ccb
)
652 RemoveEntryList(Entry
);
653 tmpIrp
= CONTAINING_RECORD(WaitEntry
, IRP
, Tail
.Overlay
.DriverContext
);
654 IoAcquireCancelSpinLock(&oldIrql
);
657 (void)IoSetCancelRoutine(tmpIrp
, NULL
);
660 IoReleaseCancelSpinLock(oldIrql
);
663 tmpIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
664 tmpIrp
->IoStatus
.Information
= 0;
665 IoCompleteRequest(tmpIrp
, IO_NO_INCREMENT
);
669 Entry
= Entry
->Flink
;
673 Ccb
->PipeState
= FILE_PIPE_CLOSING_STATE
;
675 KeUnlockMutex(&Fcb
->CcbListLock
);
677 ExAcquireFastMutex(&Ccb
->DataListLock
);
680 ExFreePool(Ccb
->Data
);
683 Ccb
->WritePtr
= NULL
;
685 ExReleaseFastMutex(&Ccb
->DataListLock
);
687 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
688 Irp
->IoStatus
.Information
= 0;
689 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
691 DPRINT("Success!\n");
693 return STATUS_SUCCESS
;
697 NpfsClose(PDEVICE_OBJECT DeviceObject
,
700 PNPFS_DEVICE_EXTENSION DeviceExt
;
701 PIO_STACK_LOCATION IoStack
;
702 PFILE_OBJECT FileObject
;
707 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
709 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
710 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
711 FileObject
= IoStack
->FileObject
;
712 Ccb
= FileObject
->FsContext2
;
716 DPRINT("Success!\n");
717 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
718 Irp
->IoStatus
.Information
= 0;
719 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
720 return STATUS_SUCCESS
;
723 DPRINT("CCB %p\n", Ccb
);
726 DPRINT("Closing pipe %wZ\n", &Fcb
->PipeName
);
728 KeLockMutex(&Fcb
->CcbListLock
);
730 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
735 Fcb
->CurrentInstances
--;
742 /* Disconnect the pipes */
743 if (Ccb
->OtherSide
) Ccb
->OtherSide
->OtherSide
= NULL
;
744 if (Ccb
) Ccb
->OtherSide
= NULL
;
746 ASSERT(Ccb
->PipeState
== FILE_PIPE_CLOSING_STATE
);
748 FileObject
->FsContext2
= NULL
;
750 RemoveEntryList(&Ccb
->CcbListEntry
);
754 KeUnlockMutex(&Fcb
->CcbListLock
);
756 if (IsListEmpty(&Fcb
->ServerCcbListHead
) &&
757 IsListEmpty(&Fcb
->ClientCcbListHead
))
759 RtlFreeUnicodeString(&Fcb
->PipeName
);
760 KeLockMutex(&DeviceExt
->PipeListLock
);
761 RemoveEntryList(&Fcb
->PipeListEntry
);
762 KeUnlockMutex(&DeviceExt
->PipeListLock
);
764 FileObject
->FsContext
= NULL
;
767 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
768 Irp
->IoStatus
.Information
= 0;
769 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
771 DPRINT("Success!\n");
773 return STATUS_SUCCESS
;