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_PIPE_BUSY
;
259 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
260 return STATUS_PIPE_BUSY
;
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_PIPE_BUSY
;
372 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
373 return STATUS_PIPE_BUSY
;
376 /* FIXME: Check pipe modes also! */
377 if (Fcb
->MaximumInstances
!= Buffer
->MaximumInstances
||
378 Fcb
->TimeOut
.QuadPart
!= Buffer
->DefaultTimeout
.QuadPart
)
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
->WriteMode
= Buffer
->ReadMode
;
424 Fcb
->ReadMode
= Buffer
->ReadMode
;
425 Fcb
->CompletionMode
= Buffer
->CompletionMode
;
426 switch (IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
))
428 case FILE_SHARE_READ
:
429 Fcb
->PipeConfiguration
= FILE_PIPE_OUTBOUND
;
431 case FILE_SHARE_WRITE
:
432 Fcb
->PipeConfiguration
= FILE_PIPE_INBOUND
;
434 case FILE_SHARE_READ
|FILE_SHARE_WRITE
:
435 Fcb
->PipeConfiguration
= FILE_PIPE_FULL_DUPLEX
;
438 Fcb
->MaximumInstances
= Buffer
->MaximumInstances
;
439 Fcb
->CurrentInstances
= 0;
440 Fcb
->TimeOut
= Buffer
->DefaultTimeout
;
441 if (!(Fcb
->PipeConfiguration
& FILE_PIPE_OUTBOUND
) ||
442 Fcb
->PipeConfiguration
& FILE_PIPE_FULL_DUPLEX
)
444 if (Buffer
->InboundQuota
== 0)
446 Fcb
->InboundQuota
= DeviceExt
->DefaultQuota
;
450 Fcb
->InboundQuota
= PAGE_ROUND_UP(Buffer
->InboundQuota
);
451 if (Fcb
->InboundQuota
< DeviceExt
->MinQuota
)
453 Fcb
->InboundQuota
= DeviceExt
->MinQuota
;
455 else if (Fcb
->InboundQuota
> DeviceExt
->MaxQuota
)
457 Fcb
->InboundQuota
= DeviceExt
->MaxQuota
;
463 Fcb
->InboundQuota
= 0;
466 if (Fcb
->PipeConfiguration
& (FILE_PIPE_FULL_DUPLEX
|FILE_PIPE_OUTBOUND
))
468 if (Buffer
->OutboundQuota
== 0)
470 Fcb
->OutboundQuota
= DeviceExt
->DefaultQuota
;
474 Fcb
->OutboundQuota
= PAGE_ROUND_UP(Buffer
->OutboundQuota
);
475 if (Fcb
->OutboundQuota
< DeviceExt
->MinQuota
)
477 Fcb
->OutboundQuota
= DeviceExt
->MinQuota
;
479 else if (Fcb
->OutboundQuota
> DeviceExt
->MaxQuota
)
481 Fcb
->OutboundQuota
= DeviceExt
->MaxQuota
;
487 Fcb
->OutboundQuota
= 0;
490 InsertTailList(&DeviceExt
->PipeListHead
, &Fcb
->PipeListEntry
);
491 KeUnlockMutex(&DeviceExt
->PipeListLock
);
494 if (Fcb
->InboundQuota
)
496 Ccb
->Data
= ExAllocatePool(PagedPool
, Fcb
->InboundQuota
);
497 if (Ccb
->Data
== NULL
)
503 KeLockMutex(&DeviceExt
->PipeListLock
);
504 RemoveEntryList(&Fcb
->PipeListEntry
);
505 KeUnlockMutex(&DeviceExt
->PipeListLock
);
506 RtlFreeUnicodeString(&Fcb
->PipeName
);
510 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
511 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
512 return STATUS_NO_MEMORY
;
520 Ccb
->ReadPtr
= Ccb
->Data
;
521 Ccb
->WritePtr
= Ccb
->Data
;
522 Ccb
->ReadDataAvailable
= 0;
523 Ccb
->WriteQuotaAvailable
= Fcb
->InboundQuota
;
524 Ccb
->MaxDataLength
= Fcb
->InboundQuota
;
525 InitializeListHead(&Ccb
->ReadRequestListHead
);
526 ExInitializeFastMutex(&Ccb
->DataListLock
);
528 Fcb
->CurrentInstances
++;
531 Ccb
->PipeEnd
= FILE_PIPE_SERVER_END
;
532 Ccb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
533 Ccb
->OtherSide
= NULL
;
535 DPRINT("CCB: %p\n", Ccb
);
537 KeInitializeEvent(&Ccb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
538 KeInitializeEvent(&Ccb
->ReadEvent
, SynchronizationEvent
, FALSE
);
539 KeInitializeEvent(&Ccb
->WriteEvent
, SynchronizationEvent
, FALSE
);
541 KeLockMutex(&Fcb
->CcbListLock
);
542 InsertTailList(&Fcb
->ServerCcbListHead
, &Ccb
->CcbListEntry
);
543 KeUnlockMutex(&Fcb
->CcbListLock
);
545 FileObject
->FsContext
= Fcb
;
546 FileObject
->FsContext2
= Ccb
;
547 FileObject
->Flags
|= FO_NAMED_PIPE
;
549 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
550 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
552 DPRINT("Success!\n");
554 return STATUS_SUCCESS
;
559 NpfsCleanup(PDEVICE_OBJECT DeviceObject
,
562 PNPFS_DEVICE_EXTENSION DeviceExt
;
563 PIO_STACK_LOCATION IoStack
;
564 PFILE_OBJECT FileObject
;
565 PNPFS_CCB Ccb
, OtherSide
;
569 DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
571 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
572 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
573 FileObject
= IoStack
->FileObject
;
574 Ccb
= FileObject
->FsContext2
;
578 DPRINT("Success!\n");
579 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
580 Irp
->IoStatus
.Information
= 0;
581 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
582 return STATUS_SUCCESS
;
585 DPRINT("CCB %p\n", Ccb
);
588 DPRINT("Cleaning pipe %wZ\n", &Fcb
->PipeName
);
590 KeLockMutex(&Fcb
->CcbListLock
);
592 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
596 /* FIXME: Clean up existing connections here ?? */
603 if (Ccb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
605 OtherSide
= Ccb
->OtherSide
;
606 /* Lock the server first */
609 ExAcquireFastMutex(&Ccb
->DataListLock
);
610 ExAcquireFastMutex(&OtherSide
->DataListLock
);
614 ExAcquireFastMutex(&OtherSide
->DataListLock
);
615 ExAcquireFastMutex(&Ccb
->DataListLock
);
617 OtherSide
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
618 OtherSide
->OtherSide
= NULL
;
620 * Signaling the write event. If is possible that an other
621 * thread waits for an empty buffer.
623 KeSetEvent(&OtherSide
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
624 KeSetEvent(&OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
627 ExReleaseFastMutex(&OtherSide
->DataListLock
);
628 ExReleaseFastMutex(&Ccb
->DataListLock
);
632 ExReleaseFastMutex(&Ccb
->DataListLock
);
633 ExReleaseFastMutex(&OtherSide
->DataListLock
);
636 else if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
639 PNPFS_WAITER_ENTRY WaitEntry
= NULL
;
640 BOOLEAN Complete
= FALSE
;
644 Entry
= Ccb
->Fcb
->WaiterListHead
.Flink
;
645 while (Entry
!= &Ccb
->Fcb
->WaiterListHead
)
647 WaitEntry
= CONTAINING_RECORD(Entry
, NPFS_WAITER_ENTRY
, Entry
);
648 if (WaitEntry
->Ccb
== Ccb
)
650 RemoveEntryList(Entry
);
651 tmpIrp
= CONTAINING_RECORD(WaitEntry
, IRP
, Tail
.Overlay
.DriverContext
);
652 IoAcquireCancelSpinLock(&oldIrql
);
655 (void)IoSetCancelRoutine(tmpIrp
, NULL
);
658 IoReleaseCancelSpinLock(oldIrql
);
661 tmpIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
662 tmpIrp
->IoStatus
.Information
= 0;
663 IoCompleteRequest(tmpIrp
, IO_NO_INCREMENT
);
667 Entry
= Entry
->Flink
;
671 Ccb
->PipeState
= FILE_PIPE_CLOSING_STATE
;
673 KeUnlockMutex(&Fcb
->CcbListLock
);
675 ExAcquireFastMutex(&Ccb
->DataListLock
);
678 ExFreePool(Ccb
->Data
);
681 Ccb
->WritePtr
= NULL
;
683 ExReleaseFastMutex(&Ccb
->DataListLock
);
685 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
686 Irp
->IoStatus
.Information
= 0;
687 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
689 DPRINT("Success!\n");
691 return STATUS_SUCCESS
;
695 NpfsClose(PDEVICE_OBJECT DeviceObject
,
698 PNPFS_DEVICE_EXTENSION DeviceExt
;
699 PIO_STACK_LOCATION IoStack
;
700 PFILE_OBJECT FileObject
;
705 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
707 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
708 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
709 FileObject
= IoStack
->FileObject
;
710 Ccb
= FileObject
->FsContext2
;
714 DPRINT("Success!\n");
715 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
716 Irp
->IoStatus
.Information
= 0;
717 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
718 return STATUS_SUCCESS
;
721 DPRINT("CCB %p\n", Ccb
);
724 DPRINT("Closing pipe %wZ\n", &Fcb
->PipeName
);
726 KeLockMutex(&Fcb
->CcbListLock
);
728 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
733 Fcb
->CurrentInstances
--;
740 ASSERT(Ccb
->PipeState
== FILE_PIPE_CLOSING_STATE
);
742 FileObject
->FsContext2
= NULL
;
744 RemoveEntryList(&Ccb
->CcbListEntry
);
748 KeUnlockMutex(&Fcb
->CcbListLock
);
750 if (IsListEmpty(&Fcb
->ServerCcbListHead
) &&
751 IsListEmpty(&Fcb
->ClientCcbListHead
))
753 RtlFreeUnicodeString(&Fcb
->PipeName
);
754 KeLockMutex(&DeviceExt
->PipeListLock
);
755 RemoveEntryList(&Fcb
->PipeListEntry
);
756 KeUnlockMutex(&DeviceExt
->PipeListLock
);
758 FileObject
->FsContext
= NULL
;
761 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
762 Irp
->IoStatus
.Information
= 0;
763 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
765 DPRINT("Success!\n");
767 return STATUS_SUCCESS
;