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 Pipe
= CONTAINING_RECORD(CurrentEntry
, NPFS_PIPE
, PipeListEntry
);
29 if (RtlCompareUnicodeString(PipeName
,
33 DPRINT("<%wZ> = <%wZ>\n", PipeName
, &Pipe
->PipeName
);
37 CurrentEntry
= CurrentEntry
->Flink
;
45 NpfsFindListeningServerInstance(PNPFS_PIPE Pipe
)
47 PLIST_ENTRY CurrentEntry
;
48 PNPFS_WAITER_ENTRY Waiter
;
52 CurrentEntry
= Pipe
->WaiterListHead
.Flink
;
53 while (CurrentEntry
!= &Pipe
->WaiterListHead
)
55 Waiter
= CONTAINING_RECORD(CurrentEntry
, NPFS_WAITER_ENTRY
, Entry
);
56 Irp
= CONTAINING_RECORD(Waiter
, IRP
, Tail
.Overlay
.DriverContext
);
57 if (Waiter
->Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
59 DPRINT("Server found! Fcb %p\n", Waiter
->Fcb
);
61 IoAcquireCancelSpinLock(&oldIrql
);
64 IoSetCancelRoutine(Irp
, NULL
);
65 IoReleaseCancelSpinLock(oldIrql
);
68 IoReleaseCancelSpinLock(oldIrql
);
71 CurrentEntry
= CurrentEntry
->Flink
;
79 NpfsSignalAndRemoveListeningServerInstance(PNPFS_PIPE Pipe
,
82 PLIST_ENTRY CurrentEntry
;
83 PNPFS_WAITER_ENTRY Waiter
;
86 CurrentEntry
= Pipe
->WaiterListHead
.Flink
;
87 while (CurrentEntry
!= &Pipe
->WaiterListHead
)
89 Waiter
= CONTAINING_RECORD(CurrentEntry
, NPFS_WAITER_ENTRY
, Entry
);
90 if (Waiter
->Fcb
== Fcb
)
92 DPRINT("Server found! Fcb %p\n", Waiter
->Fcb
);
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_FCB ServerFcb
= 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 Pipe
= 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 FCB lists. From now on no modifications to the
156 * FCB lists are allowed, because it can cause various misconsistencies.
158 KeLockMutex(&Pipe
->FcbListLock
);
161 * Step 2. Create the client FCB.
163 ClientFcb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_FCB
));
164 if (ClientFcb
== NULL
)
166 DPRINT("No memory!\n");
167 KeUnlockMutex(&Pipe
->FcbListLock
);
168 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
169 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
170 return STATUS_NO_MEMORY
;
173 ClientFcb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
174 ClientFcb
->Pipe
= Pipe
;
175 ClientFcb
->PipeEnd
= FILE_PIPE_CLIENT_END
;
176 ClientFcb
->OtherSide
= NULL
;
177 ClientFcb
->PipeState
= SpecialAccess
? 0 : FILE_PIPE_DISCONNECTED_STATE
;
178 InitializeListHead(&ClientFcb
->ReadRequestListHead
);
180 DPRINT("Fcb: %x\n", ClientFcb
);
182 /* Initialize data list. */
183 if (Pipe
->OutboundQuota
)
185 ClientFcb
->Data
= ExAllocatePool(PagedPool
, Pipe
->OutboundQuota
);
186 if (ClientFcb
->Data
== NULL
)
188 DPRINT("No memory!\n");
189 ExFreePool(ClientFcb
);
190 KeUnlockMutex(&Pipe
->FcbListLock
);
191 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
192 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
193 return STATUS_NO_MEMORY
;
198 ClientFcb
->Data
= NULL
;
201 ClientFcb
->ReadPtr
= ClientFcb
->Data
;
202 ClientFcb
->WritePtr
= ClientFcb
->Data
;
203 ClientFcb
->ReadDataAvailable
= 0;
204 ClientFcb
->WriteQuotaAvailable
= Pipe
->OutboundQuota
;
205 ClientFcb
->MaxDataLength
= Pipe
->OutboundQuota
;
206 ExInitializeFastMutex(&ClientFcb
->DataListLock
);
207 KeInitializeEvent(&ClientFcb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
208 KeInitializeEvent(&ClientFcb
->ReadEvent
, SynchronizationEvent
, FALSE
);
209 KeInitializeEvent(&ClientFcb
->WriteEvent
, SynchronizationEvent
, FALSE
);
213 * Step 3. Search for listening server FCB.
219 * WARNING: Point of no return! Once we get the server FCB it's
220 * possible that we completed a wait request and so we have to
221 * complete even this request.
224 ServerFcb
= NpfsFindListeningServerInstance(Pipe
);
225 if (ServerFcb
== NULL
)
227 PLIST_ENTRY CurrentEntry
;
231 * If no waiting server FCB was found then try to pick
232 * one of the listing server FCB on the pipe.
235 CurrentEntry
= Pipe
->ServerFcbListHead
.Flink
;
236 while (CurrentEntry
!= &Pipe
->ServerFcbListHead
)
238 Fcb
= CONTAINING_RECORD(CurrentEntry
, NPFS_FCB
, FcbListEntry
);
239 if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
244 CurrentEntry
= CurrentEntry
->Flink
;
248 * No one is listening to me?! I'm so lonely... :(
251 if (ServerFcb
== NULL
)
253 /* Not found, bail out with error for FILE_OPEN requests. */
254 DPRINT("No listening server fcb found!\n");
256 ExFreePool(ClientFcb
->Data
);
257 KeUnlockMutex(&Pipe
->FcbListLock
);
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(Pipe
, ServerFcb
);
270 else if (IsListEmpty(&Pipe
->ServerFcbListHead
))
272 DPRINT("No server fcb found!\n");
273 KeUnlockMutex(&Pipe
->FcbListLock
);
274 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
275 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
276 return STATUS_UNSUCCESSFUL
;
280 * Step 4. Add the client FCB to a list and connect it if possible.
283 /* Add the client FCB to the pipe FCB list. */
284 InsertTailList(&Pipe
->ClientFcbListHead
, &ClientFcb
->FcbListEntry
);
286 /* Connect to listening server side */
289 ClientFcb
->OtherSide
= ServerFcb
;
290 ServerFcb
->OtherSide
= ClientFcb
;
291 ClientFcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
292 ServerFcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
295 KeUnlockMutex(&Pipe
->FcbListLock
);
297 FileObject
->FsContext
= ClientFcb
;
299 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
300 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
302 DPRINT("Success!\n");
304 return STATUS_SUCCESS
;
309 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject
,
312 PEXTENDED_IO_STACK_LOCATION IoStack
;
313 PFILE_OBJECT FileObject
;
314 PNPFS_DEVICE_EXTENSION DeviceExt
;
317 PNAMED_PIPE_CREATE_PARAMETERS Buffer
;
318 BOOLEAN NewPipe
= FALSE
;
320 DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
322 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
323 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
324 FileObject
= IoStack
->FileObject
;
325 DPRINT("FileObject %p\n", FileObject
);
326 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
328 Buffer
= IoStack
->Parameters
.CreatePipe
.Parameters
;
330 Irp
->IoStatus
.Information
= 0;
332 if (!(IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
)) ||
333 (IoStack
->Parameters
.CreatePipe
.ShareAccess
& ~(FILE_SHARE_READ
|FILE_SHARE_WRITE
)))
335 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
336 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
337 return STATUS_INVALID_PARAMETER
;
340 Fcb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_FCB
));
343 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
344 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
345 return STATUS_NO_MEMORY
;
348 Fcb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
349 KeLockMutex(&DeviceExt
->PipeListLock
);
352 * First search for existing Pipe with the same name.
354 Pipe
= NpfsFindPipe(DeviceExt
,
355 &FileObject
->FileName
);
359 * Found Pipe with the same name. Check if we are
362 KeUnlockMutex(&DeviceExt
->PipeListLock
);
364 if (Pipe
->CurrentInstances
>= Pipe
->MaximumInstances
)
366 DPRINT("Out of instances.\n");
368 Irp
->IoStatus
.Status
= STATUS_PIPE_BUSY
;
369 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
370 return STATUS_PIPE_BUSY
;
373 /* FIXME: Check pipe modes also! */
374 if (Pipe
->MaximumInstances
!= Buffer
->MaximumInstances
||
375 Pipe
->TimeOut
.QuadPart
!= Buffer
->DefaultTimeout
.QuadPart
)
377 DPRINT("Asked for invalid pipe mode.\n");
379 Irp
->IoStatus
.Status
= STATUS_ACCESS_DENIED
;
380 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
381 return STATUS_ACCESS_DENIED
;
387 Pipe
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_PIPE
));
390 KeUnlockMutex(&DeviceExt
->PipeListLock
);
391 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
392 Irp
->IoStatus
.Information
= 0;
393 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
394 return STATUS_NO_MEMORY
;
397 Pipe
->PipeName
.Length
= FileObject
->FileName
.Length
;
398 Pipe
->PipeName
.MaximumLength
= Pipe
->PipeName
.Length
+ sizeof(UNICODE_NULL
);
399 Pipe
->PipeName
.Buffer
= ExAllocatePool(NonPagedPool
, Pipe
->PipeName
.MaximumLength
);
400 if (Pipe
->PipeName
.Buffer
== NULL
)
402 KeUnlockMutex(&DeviceExt
->PipeListLock
);
405 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
406 Irp
->IoStatus
.Information
= 0;
407 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
408 return STATUS_NO_MEMORY
;
411 RtlCopyUnicodeString(&Pipe
->PipeName
, &FileObject
->FileName
);
413 InitializeListHead(&Pipe
->ServerFcbListHead
);
414 InitializeListHead(&Pipe
->ClientFcbListHead
);
415 InitializeListHead(&Pipe
->WaiterListHead
);
416 KeInitializeMutex(&Pipe
->FcbListLock
, 0);
418 Pipe
->PipeType
= Buffer
->NamedPipeType
;
419 Pipe
->WriteMode
= Buffer
->ReadMode
;
420 Pipe
->ReadMode
= Buffer
->ReadMode
;
421 Pipe
->CompletionMode
= Buffer
->CompletionMode
;
422 switch (IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
))
424 case FILE_SHARE_READ
:
425 Pipe
->PipeConfiguration
= FILE_PIPE_OUTBOUND
;
427 case FILE_SHARE_WRITE
:
428 Pipe
->PipeConfiguration
= FILE_PIPE_INBOUND
;
430 case FILE_SHARE_READ
|FILE_SHARE_WRITE
:
431 Pipe
->PipeConfiguration
= FILE_PIPE_FULL_DUPLEX
;
434 Pipe
->MaximumInstances
= Buffer
->MaximumInstances
;
435 Pipe
->CurrentInstances
= 0;
436 Pipe
->TimeOut
= Buffer
->DefaultTimeout
;
437 if (!(Pipe
->PipeConfiguration
& FILE_PIPE_OUTBOUND
) ||
438 Pipe
->PipeConfiguration
& FILE_PIPE_FULL_DUPLEX
)
440 if (Buffer
->InboundQuota
== 0)
442 Pipe
->InboundQuota
= DeviceExt
->DefaultQuota
;
446 Pipe
->InboundQuota
= PAGE_ROUND_UP(Buffer
->InboundQuota
);
447 if (Pipe
->InboundQuota
< DeviceExt
->MinQuota
)
449 Pipe
->InboundQuota
= DeviceExt
->MinQuota
;
451 else if (Pipe
->InboundQuota
> DeviceExt
->MaxQuota
)
453 Pipe
->InboundQuota
= DeviceExt
->MaxQuota
;
459 Pipe
->InboundQuota
= 0;
462 if (Pipe
->PipeConfiguration
& (FILE_PIPE_FULL_DUPLEX
|FILE_PIPE_OUTBOUND
))
464 if (Buffer
->OutboundQuota
== 0)
466 Pipe
->OutboundQuota
= DeviceExt
->DefaultQuota
;
470 Pipe
->OutboundQuota
= PAGE_ROUND_UP(Buffer
->OutboundQuota
);
471 if (Pipe
->OutboundQuota
< DeviceExt
->MinQuota
)
473 Pipe
->OutboundQuota
= DeviceExt
->MinQuota
;
475 else if (Pipe
->OutboundQuota
> DeviceExt
->MaxQuota
)
477 Pipe
->OutboundQuota
= DeviceExt
->MaxQuota
;
483 Pipe
->OutboundQuota
= 0;
486 InsertTailList(&DeviceExt
->PipeListHead
, &Pipe
->PipeListEntry
);
487 KeUnlockMutex(&DeviceExt
->PipeListLock
);
490 if (Pipe
->InboundQuota
)
492 Fcb
->Data
= ExAllocatePool(PagedPool
, Pipe
->InboundQuota
);
493 if (Fcb
->Data
== NULL
)
499 KeLockMutex(&DeviceExt
->PipeListLock
);
500 RemoveEntryList(&Pipe
->PipeListEntry
);
501 KeUnlockMutex(&DeviceExt
->PipeListLock
);
502 RtlFreeUnicodeString(&Pipe
->PipeName
);
506 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
507 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
508 return STATUS_NO_MEMORY
;
516 Fcb
->ReadPtr
= Fcb
->Data
;
517 Fcb
->WritePtr
= Fcb
->Data
;
518 Fcb
->ReadDataAvailable
= 0;
519 Fcb
->WriteQuotaAvailable
= Pipe
->InboundQuota
;
520 Fcb
->MaxDataLength
= Pipe
->InboundQuota
;
521 InitializeListHead(&Fcb
->ReadRequestListHead
);
522 ExInitializeFastMutex(&Fcb
->DataListLock
);
524 Pipe
->CurrentInstances
++;
527 Fcb
->PipeEnd
= FILE_PIPE_SERVER_END
;
528 Fcb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
529 Fcb
->OtherSide
= NULL
;
531 DPRINT("Fcb: %x\n", Fcb
);
533 KeInitializeEvent(&Fcb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
534 KeInitializeEvent(&Fcb
->ReadEvent
, SynchronizationEvent
, FALSE
);
535 KeInitializeEvent(&Fcb
->WriteEvent
, SynchronizationEvent
, FALSE
);
537 KeLockMutex(&Pipe
->FcbListLock
);
538 InsertTailList(&Pipe
->ServerFcbListHead
, &Fcb
->FcbListEntry
);
539 KeUnlockMutex(&Pipe
->FcbListLock
);
541 FileObject
->FsContext
= Fcb
;
543 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
544 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
546 DPRINT("Success!\n");
548 return STATUS_SUCCESS
;
553 NpfsCleanup(PDEVICE_OBJECT DeviceObject
,
556 PNPFS_DEVICE_EXTENSION DeviceExt
;
557 PIO_STACK_LOCATION IoStack
;
558 PFILE_OBJECT FileObject
;
559 PNPFS_FCB Fcb
, OtherSide
;
563 DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
565 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
566 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
567 FileObject
= IoStack
->FileObject
;
568 Fcb
= FileObject
->FsContext
;
572 DPRINT("Success!\n");
573 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
574 Irp
->IoStatus
.Information
= 0;
575 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
576 return STATUS_SUCCESS
;
579 DPRINT("Fcb %x\n", Fcb
);
582 DPRINT("Cleaning pipe %wZ\n", &Pipe
->PipeName
);
584 KeLockMutex(&Pipe
->FcbListLock
);
586 Server
= (Fcb
->PipeEnd
== FILE_PIPE_SERVER_END
);
590 /* FIXME: Clean up existing connections here ?? */
597 if (Fcb
->PipeState
== FILE_PIPE_CONNECTED_STATE
)
599 OtherSide
= Fcb
->OtherSide
;
600 /* Lock the server first */
603 ExAcquireFastMutex(&Fcb
->DataListLock
);
604 ExAcquireFastMutex(&OtherSide
->DataListLock
);
608 ExAcquireFastMutex(&OtherSide
->DataListLock
);
609 ExAcquireFastMutex(&Fcb
->DataListLock
);
611 OtherSide
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
612 OtherSide
->OtherSide
= NULL
;
614 * Signaling the write event. If is possible that an other
615 * thread waits for an empty buffer.
617 KeSetEvent(&OtherSide
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
618 KeSetEvent(&OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
621 ExReleaseFastMutex(&OtherSide
->DataListLock
);
622 ExReleaseFastMutex(&Fcb
->DataListLock
);
626 ExReleaseFastMutex(&Fcb
->DataListLock
);
627 ExReleaseFastMutex(&OtherSide
->DataListLock
);
630 else if (Fcb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
633 PNPFS_WAITER_ENTRY WaitEntry
= NULL
;
634 BOOLEAN Complete
= FALSE
;
638 Entry
= Fcb
->Pipe
->WaiterListHead
.Flink
;
639 while (Entry
!= &Fcb
->Pipe
->WaiterListHead
)
641 WaitEntry
= CONTAINING_RECORD(Entry
, NPFS_WAITER_ENTRY
, Entry
);
642 if (WaitEntry
->Fcb
== Fcb
)
644 RemoveEntryList(Entry
);
645 tmpIrp
= CONTAINING_RECORD(WaitEntry
, IRP
, Tail
.Overlay
.DriverContext
);
646 IoAcquireCancelSpinLock(&oldIrql
);
649 IoSetCancelRoutine(tmpIrp
, NULL
);
652 IoReleaseCancelSpinLock(oldIrql
);
655 tmpIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
656 tmpIrp
->IoStatus
.Information
= 0;
657 IoCompleteRequest(tmpIrp
, IO_NO_INCREMENT
);
661 Entry
= Entry
->Flink
;
665 Fcb
->PipeState
= FILE_PIPE_CLOSING_STATE
;
667 KeUnlockMutex(&Pipe
->FcbListLock
);
669 ExAcquireFastMutex(&Fcb
->DataListLock
);
672 ExFreePool(Fcb
->Data
);
675 Fcb
->WritePtr
= NULL
;
677 ExReleaseFastMutex(&Fcb
->DataListLock
);
679 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
680 Irp
->IoStatus
.Information
= 0;
681 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
683 DPRINT("Success!\n");
685 return STATUS_SUCCESS
;
689 NpfsClose(PDEVICE_OBJECT DeviceObject
,
692 PNPFS_DEVICE_EXTENSION DeviceExt
;
693 PIO_STACK_LOCATION IoStack
;
694 PFILE_OBJECT FileObject
;
699 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
701 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
702 DeviceExt
= (PNPFS_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
703 FileObject
= IoStack
->FileObject
;
704 Fcb
= FileObject
->FsContext
;
708 DPRINT("Success!\n");
709 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
710 Irp
->IoStatus
.Information
= 0;
711 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
712 return STATUS_SUCCESS
;
715 DPRINT("Fcb %x\n", Fcb
);
718 DPRINT("Closing pipe %wZ\n", &Pipe
->PipeName
);
720 KeLockMutex(&Pipe
->FcbListLock
);
722 Server
= (Fcb
->PipeEnd
== FILE_PIPE_SERVER_END
);
727 Pipe
->CurrentInstances
--;
734 ASSERT (Fcb
->PipeState
== FILE_PIPE_CLOSING_STATE
);
736 FileObject
->FsContext
= NULL
;
738 RemoveEntryList(&Fcb
->FcbListEntry
);
742 KeUnlockMutex(&Pipe
->FcbListLock
);
744 if (IsListEmpty(&Pipe
->ServerFcbListHead
) &&
745 IsListEmpty(&Pipe
->ClientFcbListHead
))
747 RtlFreeUnicodeString(&Pipe
->PipeName
);
748 KeLockMutex(&DeviceExt
->PipeListLock
);
749 RemoveEntryList(&Pipe
->PipeListEntry
);
750 KeUnlockMutex(&DeviceExt
->PipeListLock
);
754 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
755 Irp
->IoStatus
.Information
= 0;
756 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
758 DPRINT("Success!\n");
760 return STATUS_SUCCESS
;