2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/filesystems/npfs/create.c
5 * PURPOSE: Named pipe filesystem
6 * PROGRAMMER: David Welch <welch@cwcom.net>
9 /* INCLUDES ******************************************************************/
16 //#define USING_PROPER_NPFS_WAIT_SEMANTICS
18 /* FUNCTIONS *****************************************************************/
21 NpfsDereferenceFcb(PNPFS_FCB Fcb
)
23 PNPFS_VCB Vcb
= Fcb
->Vcb
;
25 KeLockMutex(&Vcb
->PipeListLock
);
26 if (InterlockedDecrement(&Fcb
->RefCount
) == 0)
28 DPRINT("NpfsDereferenceFcb. Deleting %p\n", Fcb
);
29 RemoveEntryList(&Fcb
->PipeListEntry
);
30 RtlFreeUnicodeString(&Fcb
->PipeName
);
31 ExFreePoolWithTag(Fcb
, TAG_NPFS_FCB
);
33 KeUnlockMutex(&Vcb
->PipeListLock
);
38 NpfsAllocateCcb(CCB_TYPE Type
, PNPFS_FCB Fcb
)
42 Ccb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(NPFS_CCB
), TAG_NPFS_CCB
);
48 RtlZeroMemory(Ccb
, sizeof(NPFS_CCB
));
52 // FIXME: why does this function not reference Fcb?
54 Ccb
->OtherSide
= NULL
;
61 NpfsReferenceCcb(PNPFS_CCB Ccb
)
63 ASSERT(Ccb
->RefCount
> 0);
64 InterlockedIncrement(&Ccb
->RefCount
);
69 NpfsDereferenceCcb(PNPFS_CCB Ccb
)
71 /* Decrement reference count */
72 ASSERT(Ccb
->RefCount
> 0);
73 if (InterlockedDecrement(&Ccb
->RefCount
) == 0)
75 /* Its zero, delete CCB */
76 ExFreePoolWithTag(Ccb
, TAG_NPFS_CCB
);
82 NpfsCcbSetOtherSide(PNPFS_CCB Ccb
, PNPFS_CCB OtherSide
)
84 /* Dereference old other side */
85 if (Ccb
->OtherSide
) NpfsDereferenceCcb(Ccb
->OtherSide
);
87 /* Reference the new other side */
88 if (OtherSide
) NpfsReferenceCcb(OtherSide
);
91 Ccb
->OtherSide
= OtherSide
;
95 NpfsFindPipe(PNPFS_VCB Vcb
,
96 PUNICODE_STRING PipeName
)
98 PLIST_ENTRY CurrentEntry
;
101 CurrentEntry
= Vcb
->PipeListHead
.Flink
;
102 while (CurrentEntry
!= &Vcb
->PipeListHead
)
104 Fcb
= CONTAINING_RECORD(CurrentEntry
, NPFS_FCB
, PipeListEntry
);
105 if (RtlCompareUnicodeString(PipeName
,
109 DPRINT("<%wZ> = <%wZ>\n", PipeName
, &Fcb
->PipeName
);
110 (VOID
)InterlockedIncrement(&Fcb
->RefCount
);
114 CurrentEntry
= CurrentEntry
->Flink
;
122 NpfsFindListeningServerInstance(PNPFS_FCB Fcb
)
124 PLIST_ENTRY CurrentEntry
;
125 PNPFS_WAITER_ENTRY Waiter
;
129 CurrentEntry
= Fcb
->WaiterListHead
.Flink
;
130 while (CurrentEntry
!= &Fcb
->WaiterListHead
)
132 Waiter
= CONTAINING_RECORD(CurrentEntry
, NPFS_WAITER_ENTRY
, Entry
);
133 Irp
= CONTAINING_RECORD(Waiter
, IRP
, Tail
.Overlay
.DriverContext
);
134 if (Waiter
->Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
136 DPRINT("Server found! CCB %p\n", Waiter
->Ccb
);
138 IoAcquireCancelSpinLock(&oldIrql
);
141 if (IoSetCancelRoutine(Irp
, NULL
) != NULL
)
143 IoReleaseCancelSpinLock(oldIrql
);
147 IoReleaseCancelSpinLock(oldIrql
);
150 CurrentEntry
= CurrentEntry
->Flink
;
158 NpfsSignalAndRemoveListeningServerInstance(PNPFS_FCB Fcb
,
161 PLIST_ENTRY CurrentEntry
;
162 PNPFS_WAITER_ENTRY Waiter
;
165 CurrentEntry
= Fcb
->WaiterListHead
.Flink
;
166 while (CurrentEntry
!= &Fcb
->WaiterListHead
)
168 Waiter
= CONTAINING_RECORD(CurrentEntry
, NPFS_WAITER_ENTRY
, Entry
);
169 if (Waiter
->Ccb
== Ccb
)
171 DPRINT("Server found! CCB %p\n", Waiter
->Ccb
);
173 RemoveEntryList(&Waiter
->Entry
);
174 Irp
= CONTAINING_RECORD(Waiter
, IRP
, Tail
.Overlay
.DriverContext
);
175 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
176 Irp
->IoStatus
.Information
= 0;
177 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
180 CurrentEntry
= CurrentEntry
->Flink
;
186 NpfsOpenFileSystem(PNPFS_FCB Fcb
,
187 PFILE_OBJECT FileObject
,
188 PIO_STATUS_BLOCK IoStatus
)
192 DPRINT("NpfsOpenFileSystem()\n");
194 Ccb
= NpfsAllocateCcb(CCB_DEVICE
, Fcb
);
197 IoStatus
->Status
= STATUS_NO_MEMORY
;
201 Ccb
->FileObject
= FileObject
;
203 FileObject
->FsContext
= Fcb
;
204 FileObject
->FsContext2
= Ccb
;
206 IoStatus
->Information
= FILE_OPENED
;
207 IoStatus
->Status
= STATUS_SUCCESS
;
214 NpfsOpenRootDirectory(PNPFS_FCB Fcb
,
215 PFILE_OBJECT FileObject
,
216 PIO_STATUS_BLOCK IoStatus
)
220 DPRINT("NpfsOpenRootDirectory()\n");
222 Ccb
= NpfsAllocateCcb(CCB_DIRECTORY
, Fcb
);
225 IoStatus
->Status
= STATUS_NO_MEMORY
;
229 Ccb
->FileObject
= FileObject
;
231 FileObject
->FsContext
= Fcb
;
232 FileObject
->FsContext2
= Ccb
;
234 IoStatus
->Information
= FILE_OPENED
;
235 IoStatus
->Status
= STATUS_SUCCESS
;
242 NpfsCreate(PDEVICE_OBJECT DeviceObject
,
245 PEXTENDED_IO_STACK_LOCATION IoStack
;
246 PUNICODE_STRING FileName
;
247 PFILE_OBJECT FileObject
;
248 PFILE_OBJECT RelatedFileObject
;
251 PNPFS_CCB ServerCcb
= NULL
;
254 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
255 ACCESS_MASK DesiredAccess
;
256 BOOLEAN SpecialAccess
;
259 DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
261 Vcb
= (PNPFS_VCB
)DeviceObject
->DeviceExtension
;
262 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
263 FileObject
= IoStack
->FileObject
;
264 RelatedFileObject
= FileObject
->RelatedFileObject
;
265 FileName
= &FileObject
->FileName
;
266 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
267 DesiredAccess
= IoStack
->Parameters
.CreatePipe
.SecurityContext
->DesiredAccess
;
270 DPRINT("FileObject %p\n", FileObject
);
271 DPRINT("FileName %wZ\n", &FileObject
->FileName
);
273 Irp
->IoStatus
.Information
= 0;
275 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
276 SpecialAccess
= ((DesiredAccess
& SPECIFIC_RIGHTS_ALL
) == FILE_READ_ATTRIBUTES
);
279 DPRINT("NpfsCreate() open client end for special use!\n");
283 DPRINT("FileName->Length: %hu RelatedFileObject: %p\n", FileName
->Length
, RelatedFileObject
);
285 /* Open the file system */
286 if (FileName
->Length
== 0 &&
287 (RelatedFileObject
== NULL
|| ((PNPFS_CCB
)RelatedFileObject
->FsContext2
)->Type
== CCB_DEVICE
))
289 DPRINT("Open the file system\n");
291 NpfsOpenFileSystem(Vcb
->DeviceFcb
,
295 Status
= Irp
->IoStatus
.Status
;
296 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
300 /* Open the root directory */
301 if ((FileName
->Length
== 2 && FileName
->Buffer
[0] == L
'\\' && RelatedFileObject
== NULL
) ||
302 (FileName
->Length
== 0 && ((PNPFS_CCB
)RelatedFileObject
->FsContext2
)->Type
== CCB_DIRECTORY
))
304 DPRINT("Open the root directory\n");
306 NpfsOpenRootDirectory(Vcb
->RootFcb
,
310 Status
= Irp
->IoStatus
.Status
;
311 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
317 * Step 1. Find the pipe we're trying to open.
319 KeLockMutex(&Vcb
->PipeListLock
);
320 Fcb
= NpfsFindPipe(Vcb
, &FileObject
->FileName
);
323 /* Not found, bail out with error. */
324 DPRINT("No pipe found!\n");
325 KeUnlockMutex(&Vcb
->PipeListLock
);
326 Irp
->IoStatus
.Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
327 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
328 return STATUS_OBJECT_NAME_NOT_FOUND
;
331 KeUnlockMutex(&Vcb
->PipeListLock
);
334 * Acquire the lock for CCB lists. From now on no modifications to the
335 * CCB lists are allowed, because it can cause various misconsistencies.
337 KeLockMutex(&Fcb
->CcbListLock
);
340 * Step 2. Create the client CCB.
342 ClientCcb
= NpfsAllocateCcb(CCB_PIPE
, Fcb
);
343 if (ClientCcb
== NULL
)
345 DPRINT("No memory!\n");
346 KeUnlockMutex(&Fcb
->CcbListLock
);
347 NpfsDereferenceFcb(Fcb
);
348 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
349 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
350 return STATUS_NO_MEMORY
;
353 ClientCcb
->FileObject
= FileObject
;
354 ClientCcb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
355 ClientCcb
->PipeEnd
= FILE_PIPE_CLIENT_END
;
356 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
357 ClientCcb
->PipeState
= SpecialAccess
? 0 : FILE_PIPE_DISCONNECTED_STATE
;
359 ClientCcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
361 InitializeListHead(&ClientCcb
->ReadRequestListHead
);
363 DPRINT("CCB: %p\n", ClientCcb
);
365 /* Initialize data list. */
366 if (Fcb
->OutboundQuota
)
368 ClientCcb
->Data
= ExAllocatePoolWithTag(PagedPool
,
371 if (ClientCcb
->Data
== NULL
)
373 DPRINT("No memory!\n");
374 NpfsDereferenceCcb(ClientCcb
);
375 KeUnlockMutex(&Fcb
->CcbListLock
);
376 NpfsDereferenceFcb(Fcb
);
377 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
378 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
379 return STATUS_NO_MEMORY
;
384 ClientCcb
->Data
= NULL
;
387 ClientCcb
->ReadPtr
= ClientCcb
->Data
;
388 ClientCcb
->WritePtr
= ClientCcb
->Data
;
389 ClientCcb
->ReadDataAvailable
= 0;
390 ClientCcb
->WriteQuotaAvailable
= Fcb
->OutboundQuota
;
391 ClientCcb
->MaxDataLength
= Fcb
->OutboundQuota
;
392 ExInitializeFastMutex(&ClientCcb
->DataListLock
);
393 KeInitializeEvent(&ClientCcb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
394 KeInitializeEvent(&ClientCcb
->ReadEvent
, NotificationEvent
, FALSE
);
395 KeInitializeEvent(&ClientCcb
->WriteEvent
, NotificationEvent
, FALSE
);
399 * Step 3. Search for listening server CCB.
401 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
406 * WARNING: Point of no return! Once we get the server CCB it's
407 * possible that we completed a wait request and so we have to
408 * complete even this request.
411 ServerCcb
= NpfsFindListeningServerInstance(Fcb
);
412 if (ServerCcb
== NULL
)
414 PLIST_ENTRY CurrentEntry
;
418 * If no waiting server CCB was found then try to pick
419 * one of the listing server CCB on the pipe.
422 CurrentEntry
= Fcb
->ServerCcbListHead
.Flink
;
423 while (CurrentEntry
!= &Fcb
->ServerCcbListHead
)
425 Ccb
= CONTAINING_RECORD(CurrentEntry
, NPFS_CCB
, CcbListEntry
);
426 if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
431 CurrentEntry
= CurrentEntry
->Flink
;
435 * No one is listening to me?! I'm so lonely... :(
438 if (ServerCcb
== NULL
)
440 /* Not found, bail out with error for FILE_OPEN requests. */
441 DPRINT("No listening server CCB found!\n");
444 ExFreePoolWithTag(ClientCcb
->Data
, TAG_NPFS_CCB_DATA
);
447 NpfsDereferenceCcb(ClientCcb
);
448 KeUnlockMutex(&Fcb
->CcbListLock
);
449 NpfsDereferenceFcb(Fcb
);
450 Irp
->IoStatus
.Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
451 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
452 return STATUS_OBJECT_NAME_NOT_FOUND
;
457 /* Signal the server thread and remove it from the waiter list */
458 /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
459 NpfsSignalAndRemoveListeningServerInstance(Fcb
, ServerCcb
);
461 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
463 else if (IsListEmpty(&Fcb
->ServerCcbListHead
))
465 DPRINT("No server fcb found!\n");
469 ExFreePoolWithTag(ClientCcb
->Data
, TAG_NPFS_CCB_DATA
);
472 NpfsDereferenceCcb(ClientCcb
);
473 KeUnlockMutex(&Fcb
->CcbListLock
);
474 NpfsDereferenceFcb(Fcb
);
475 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
476 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
477 return STATUS_UNSUCCESSFUL
;
482 * Step 4. Add the client CCB to a list and connect it if possible.
485 /* Add the client CCB to the pipe CCB list. */
486 InsertTailList(&Fcb
->ClientCcbListHead
, &ClientCcb
->CcbListEntry
);
488 /* Connect to listening server side */
491 NpfsCcbSetOtherSide(ClientCcb
, ServerCcb
);
492 NpfsCcbSetOtherSide(ServerCcb
, ClientCcb
);
493 ClientCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
494 ServerCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
495 KeSetEvent(&ServerCcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
498 KeUnlockMutex(&Fcb
->CcbListLock
);
500 FileObject
->FsContext
= Fcb
;
501 FileObject
->FsContext2
= ClientCcb
;
502 FileObject
->Flags
|= FO_NAMED_PIPE
;
504 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
505 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
507 DPRINT("Success!\n");
509 return STATUS_SUCCESS
;
514 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject
,
517 PEXTENDED_IO_STACK_LOCATION IoStack
;
518 PFILE_OBJECT FileObject
;
524 PNAMED_PIPE_CREATE_PARAMETERS Parameters
;
526 DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
528 Vcb
= (PNPFS_VCB
)DeviceObject
->DeviceExtension
;
529 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
530 FileObject
= IoStack
->FileObject
;
531 DPRINT("FileObject %p\n", FileObject
);
532 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
534 Disposition
= (IoStack
->Parameters
.CreatePipe
.Options
>> 24) & 0xFF;
535 ShareAccess
= IoStack
->Parameters
.CreatePipe
.ShareAccess
;
536 Parameters
= IoStack
->Parameters
.CreatePipe
.Parameters
;
538 Irp
->IoStatus
.Information
= 0;
540 if ((Disposition
== FILE_OVERWRITE
) ||
541 (Disposition
== FILE_OVERWRITE_IF
) ||
542 !(ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
)) ||
543 (ShareAccess
& ~(FILE_SHARE_READ
|FILE_SHARE_WRITE
)))
545 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
546 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
547 return STATUS_INVALID_PARAMETER
;
550 KeLockMutex(&Vcb
->PipeListLock
);
553 * First search for existing Pipe with the same name.
555 Fcb
= NpfsFindPipe(Vcb
, &FileObject
->FileName
);
559 * Found Pipe with the same name. Check if we are
562 KeUnlockMutex(&Vcb
->PipeListLock
);
564 if (Fcb
->CurrentInstances
>= Fcb
->MaximumInstances
)
566 DPRINT("Out of instances.\n");
567 NpfsDereferenceFcb(Fcb
);
568 Irp
->IoStatus
.Status
= STATUS_INSTANCE_NOT_AVAILABLE
;
569 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
570 return STATUS_INSTANCE_NOT_AVAILABLE
;
573 if (Disposition
== FILE_CREATE
||
574 Fcb
->MaximumInstances
!= Parameters
->MaximumInstances
||
575 Fcb
->TimeOut
.QuadPart
!= Parameters
->DefaultTimeout
.QuadPart
||
576 Fcb
->PipeType
!= Parameters
->NamedPipeType
)
578 DPRINT("Asked for invalid pipe mode.\n");
579 NpfsDereferenceFcb(Fcb
);
580 Irp
->IoStatus
.Status
= STATUS_ACCESS_DENIED
;
581 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
582 return STATUS_ACCESS_DENIED
;
587 Fcb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(NPFS_FCB
), TAG_NPFS_FCB
);
590 KeUnlockMutex(&Vcb
->PipeListLock
);
591 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
592 Irp
->IoStatus
.Information
= 0;
593 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
594 return STATUS_NO_MEMORY
;
597 Fcb
->Type
= FCB_PIPE
;
600 Fcb
->PipeName
.Length
= FileObject
->FileName
.Length
;
601 Fcb
->PipeName
.MaximumLength
= Fcb
->PipeName
.Length
+ sizeof(UNICODE_NULL
);
602 Fcb
->PipeName
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
603 Fcb
->PipeName
.MaximumLength
,
605 if (Fcb
->PipeName
.Buffer
== NULL
)
607 KeUnlockMutex(&Vcb
->PipeListLock
);
608 ExFreePoolWithTag(Fcb
, TAG_NPFS_FCB
);
609 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
610 Irp
->IoStatus
.Information
= 0;
611 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
612 return STATUS_NO_MEMORY
;
615 RtlCopyUnicodeString(&Fcb
->PipeName
, &FileObject
->FileName
);
617 InitializeListHead(&Fcb
->ServerCcbListHead
);
618 InitializeListHead(&Fcb
->ClientCcbListHead
);
619 InitializeListHead(&Fcb
->WaiterListHead
);
620 KeInitializeMutex(&Fcb
->CcbListLock
, 0);
622 Fcb
->PipeType
= Parameters
->NamedPipeType
;
623 Fcb
->ServerReadMode
= Parameters
->ReadMode
;
624 /* MSDN documentation reads that clients always start off in byte mode */
625 Fcb
->ClientReadMode
= FILE_PIPE_BYTE_STREAM_MODE
;
627 Fcb
->CompletionMode
= Parameters
->CompletionMode
;
628 switch (ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
))
630 case FILE_SHARE_READ
:
631 Fcb
->PipeConfiguration
= FILE_PIPE_OUTBOUND
;
633 case FILE_SHARE_WRITE
:
634 Fcb
->PipeConfiguration
= FILE_PIPE_INBOUND
;
636 case FILE_SHARE_READ
|FILE_SHARE_WRITE
:
637 Fcb
->PipeConfiguration
= FILE_PIPE_FULL_DUPLEX
;
640 Fcb
->MaximumInstances
= Parameters
->MaximumInstances
;
641 Fcb
->CurrentInstances
= 0;
642 Fcb
->TimeOut
= Parameters
->DefaultTimeout
;
643 if (!(Fcb
->PipeConfiguration
& FILE_PIPE_OUTBOUND
) ||
644 Fcb
->PipeConfiguration
& FILE_PIPE_FULL_DUPLEX
)
646 if (Parameters
->InboundQuota
== 0)
648 Fcb
->InboundQuota
= Vcb
->DefaultQuota
;
652 Fcb
->InboundQuota
= PAGE_ROUND_UP(Parameters
->InboundQuota
);
653 if (Fcb
->InboundQuota
< Vcb
->MinQuota
)
655 Fcb
->InboundQuota
= Vcb
->MinQuota
;
657 else if (Fcb
->InboundQuota
> Vcb
->MaxQuota
)
659 Fcb
->InboundQuota
= Vcb
->MaxQuota
;
665 Fcb
->InboundQuota
= 0;
668 if (Fcb
->PipeConfiguration
& (FILE_PIPE_FULL_DUPLEX
|FILE_PIPE_OUTBOUND
))
670 if (Parameters
->OutboundQuota
== 0)
672 Fcb
->OutboundQuota
= Vcb
->DefaultQuota
;
676 Fcb
->OutboundQuota
= PAGE_ROUND_UP(Parameters
->OutboundQuota
);
677 if (Fcb
->OutboundQuota
< Vcb
->MinQuota
)
679 Fcb
->OutboundQuota
= Vcb
->MinQuota
;
681 else if (Fcb
->OutboundQuota
> Vcb
->MaxQuota
)
683 Fcb
->OutboundQuota
= Vcb
->MaxQuota
;
689 Fcb
->OutboundQuota
= 0;
692 InsertTailList(&Vcb
->PipeListHead
, &Fcb
->PipeListEntry
);
693 KeUnlockMutex(&Vcb
->PipeListLock
);
696 Ccb
= NpfsAllocateCcb(CCB_PIPE
, Fcb
);
699 NpfsDereferenceFcb(Fcb
);
700 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
701 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
702 return STATUS_NO_MEMORY
;
705 Ccb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
707 if (Fcb
->InboundQuota
)
709 Ccb
->Data
= ExAllocatePoolWithTag(PagedPool
,
712 if (Ccb
->Data
== NULL
)
714 NpfsDereferenceCcb(Ccb
);
715 NpfsDereferenceFcb(Fcb
);
717 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
718 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
719 return STATUS_NO_MEMORY
;
727 Ccb
->ReadPtr
= Ccb
->Data
;
728 Ccb
->WritePtr
= Ccb
->Data
;
729 Ccb
->ReadDataAvailable
= 0;
730 Ccb
->WriteQuotaAvailable
= Fcb
->InboundQuota
;
731 Ccb
->MaxDataLength
= Fcb
->InboundQuota
;
732 InitializeListHead(&Ccb
->ReadRequestListHead
);
733 ExInitializeFastMutex(&Ccb
->DataListLock
);
735 Fcb
->CurrentInstances
++;
738 Ccb
->FileObject
= FileObject
;
739 Ccb
->PipeEnd
= FILE_PIPE_SERVER_END
;
740 Ccb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
742 DPRINT("CCB: %p\n", Ccb
);
744 KeInitializeEvent(&Ccb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
745 KeInitializeEvent(&Ccb
->ReadEvent
, NotificationEvent
, FALSE
);
746 KeInitializeEvent(&Ccb
->WriteEvent
, NotificationEvent
, FALSE
);
748 KeLockMutex(&Fcb
->CcbListLock
);
749 InsertTailList(&Fcb
->ServerCcbListHead
, &Ccb
->CcbListEntry
);
750 KeUnlockMutex(&Fcb
->CcbListLock
);
752 FileObject
->FsContext
= Fcb
;
753 FileObject
->FsContext2
= Ccb
;
754 FileObject
->Flags
|= FO_NAMED_PIPE
;
756 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
757 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
759 DPRINT("Success!\n");
761 return STATUS_SUCCESS
;
766 NpfsCleanup(PDEVICE_OBJECT DeviceObject
,
770 PIO_STACK_LOCATION IoStack
;
771 PFILE_OBJECT FileObject
;
772 PNPFS_CCB Ccb
, OtherSide
;
776 DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
778 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
779 //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
780 FileObject
= IoStack
->FileObject
;
781 Ccb
= FileObject
->FsContext2
;
785 DPRINT("Success!\n");
786 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
787 Irp
->IoStatus
.Information
= 0;
788 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
789 return STATUS_SUCCESS
;
792 if (Ccb
->Type
== CCB_DEVICE
)
794 DPRINT("Cleanup the file system!\n");
795 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
796 Irp
->IoStatus
.Information
= 0;
797 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
798 return STATUS_SUCCESS
;
801 if (Ccb
->Type
== CCB_DIRECTORY
)
803 DPRINT("Cleanup the root directory!\n");
804 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
805 Irp
->IoStatus
.Information
= 0;
806 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
807 return STATUS_SUCCESS
;
810 DPRINT("CCB %p\n", Ccb
);
813 DPRINT("Cleaning pipe %wZ\n", &Fcb
->PipeName
);
815 KeLockMutex(&Fcb
->CcbListLock
);
817 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
821 /* FIXME: Clean up existing connections here ?? */
828 if ((Ccb
->PipeState
== FILE_PIPE_CONNECTED_STATE
) && (Ccb
->OtherSide
))
830 OtherSide
= Ccb
->OtherSide
;
831 ASSERT(OtherSide
->OtherSide
== Ccb
);
833 /* Lock the server first */
836 ExAcquireFastMutex(&Ccb
->DataListLock
);
837 ExAcquireFastMutex(&OtherSide
->DataListLock
);
841 ExAcquireFastMutex(&OtherSide
->DataListLock
);
842 ExAcquireFastMutex(&Ccb
->DataListLock
);
846 NpfsCcbSetOtherSide(OtherSide
, NULL
);
847 NpfsCcbSetOtherSide(Ccb
, NULL
);
850 * Signaling the write event. If is possible that an other
851 * thread waits for an empty buffer.
853 KeSetEvent(&OtherSide
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
854 KeSetEvent(&OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
857 ExReleaseFastMutex(&OtherSide
->DataListLock
);
858 ExReleaseFastMutex(&Ccb
->DataListLock
);
862 ExReleaseFastMutex(&Ccb
->DataListLock
);
863 ExReleaseFastMutex(&OtherSide
->DataListLock
);
866 else if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
869 PNPFS_WAITER_ENTRY WaitEntry
= NULL
;
870 BOOLEAN Complete
= FALSE
;
874 Entry
= Ccb
->Fcb
->WaiterListHead
.Flink
;
875 while (Entry
!= &Ccb
->Fcb
->WaiterListHead
)
877 WaitEntry
= CONTAINING_RECORD(Entry
, NPFS_WAITER_ENTRY
, Entry
);
878 if (WaitEntry
->Ccb
== Ccb
)
880 RemoveEntryList(Entry
);
881 tmpIrp
= CONTAINING_RECORD(WaitEntry
, IRP
, Tail
.Overlay
.DriverContext
);
882 IoAcquireCancelSpinLock(&oldIrql
);
883 Complete
= (NULL
!= IoSetCancelRoutine(tmpIrp
, NULL
));
884 IoReleaseCancelSpinLock(oldIrql
);
887 tmpIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
888 tmpIrp
->IoStatus
.Information
= 0;
889 IoCompleteRequest(tmpIrp
, IO_NO_INCREMENT
);
893 Entry
= Entry
->Flink
;
897 Ccb
->PipeState
= FILE_PIPE_CLOSING_STATE
;
899 KeUnlockMutex(&Fcb
->CcbListLock
);
901 ExAcquireFastMutex(&Ccb
->DataListLock
);
904 ExFreePoolWithTag(Ccb
->Data
, TAG_NPFS_CCB_DATA
);
907 Ccb
->WritePtr
= NULL
;
909 ExReleaseFastMutex(&Ccb
->DataListLock
);
911 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
912 Irp
->IoStatus
.Information
= 0;
913 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
915 DPRINT("Success!\n");
917 return STATUS_SUCCESS
;
921 NpfsClose(PDEVICE_OBJECT DeviceObject
,
924 PIO_STACK_LOCATION IoStack
;
925 PFILE_OBJECT FileObject
;
931 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
933 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
934 //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
935 FileObject
= IoStack
->FileObject
;
936 Ccb
= FileObject
->FsContext2
;
940 DPRINT("Success!\n");
941 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
942 Irp
->IoStatus
.Information
= 0;
943 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
944 return STATUS_SUCCESS
;
947 if (Ccb
->Type
== CCB_DEVICE
)
949 DPRINT("Closing the file system!\n");
951 NpfsDereferenceCcb(Ccb
);
952 FileObject
->FsContext
= NULL
;
953 FileObject
->FsContext2
= NULL
;
955 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
956 Irp
->IoStatus
.Information
= 0;
957 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
958 return STATUS_SUCCESS
;
961 if (Ccb
->Type
== CCB_DIRECTORY
)
963 DPRINT("Closing the root directory!\n");
965 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
!= NULL
)
966 ExFreePoolWithTag(Ccb
->u
.Directory
.SearchPattern
.Buffer
,
969 NpfsDereferenceCcb(Ccb
);
970 FileObject
->FsContext
= NULL
;
971 FileObject
->FsContext2
= NULL
;
973 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
974 Irp
->IoStatus
.Information
= 0;
975 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
976 return STATUS_SUCCESS
;
979 DPRINT("CCB %p\n", Ccb
);
982 DPRINT("Closing pipe %wZ\n", &Fcb
->PipeName
);
984 KeLockMutex(&Fcb
->CcbListLock
);
986 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
991 Fcb
->CurrentInstances
--;
998 /* Disconnect the pipes */
1001 /* FIXME: Timo wants it rewritten */
1002 /*ASSERT(Ccb->OtherSide->OtherSide == Ccb);*/
1003 NpfsCcbSetOtherSide(Ccb
->OtherSide
, NULL
);
1004 NpfsCcbSetOtherSide(Ccb
, NULL
);
1007 ASSERT(Ccb
->PipeState
== FILE_PIPE_CLOSING_STATE
);
1009 FileObject
->FsContext2
= NULL
;
1011 RemoveEntryList(&Ccb
->CcbListEntry
);
1013 NpfsDereferenceCcb(Ccb
);
1015 KeUnlockMutex(&Fcb
->CcbListLock
);
1017 NpfsDereferenceFcb(Fcb
);
1018 FileObject
->FsContext
= NULL
;
1020 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1021 Irp
->IoStatus
.Information
= 0;
1022 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1024 DPRINT("Success!\n");
1026 return STATUS_SUCCESS
;