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 //#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
));
53 Ccb
->OtherSide
= NULL
;
60 NpfsReferenceCcb(PNPFS_CCB Ccb
)
62 ASSERT(Ccb
->RefCount
> 0);
63 InterlockedIncrement((PLONG
)&Ccb
->RefCount
);
68 NpfsDereferenceCcb(PNPFS_CCB Ccb
)
70 /* Decrement reference count */
71 ASSERT(Ccb
->RefCount
> 0);
72 if (InterlockedDecrement((PLONG
)&Ccb
->RefCount
) == 0)
74 /* Its zero, delete CCB */
75 ExFreePoolWithTag(Ccb
, TAG_NPFS_CCB
);
81 NpfsCcbSetOtherSide(PNPFS_CCB Ccb
, PNPFS_CCB OtherSide
)
83 /* Dereference old other side */
84 if (Ccb
->OtherSide
) NpfsDereferenceCcb(Ccb
->OtherSide
);
86 /* Reference the new other side */
87 if (OtherSide
) NpfsReferenceCcb(OtherSide
);
90 Ccb
->OtherSide
= OtherSide
;
94 NpfsFindPipe(PNPFS_VCB Vcb
,
95 PUNICODE_STRING PipeName
)
97 PLIST_ENTRY CurrentEntry
;
100 CurrentEntry
= Vcb
->PipeListHead
.Flink
;
101 while (CurrentEntry
!= &Vcb
->PipeListHead
)
103 Fcb
= CONTAINING_RECORD(CurrentEntry
, NPFS_FCB
, PipeListEntry
);
104 if (RtlCompareUnicodeString(PipeName
,
108 DPRINT("<%wZ> = <%wZ>\n", PipeName
, &Fcb
->PipeName
);
109 (VOID
)InterlockedIncrement(&Fcb
->RefCount
);
113 CurrentEntry
= CurrentEntry
->Flink
;
121 NpfsFindListeningServerInstance(PNPFS_FCB Fcb
)
123 PLIST_ENTRY CurrentEntry
;
124 PNPFS_WAITER_ENTRY Waiter
;
128 CurrentEntry
= Fcb
->WaiterListHead
.Flink
;
129 while (CurrentEntry
!= &Fcb
->WaiterListHead
)
131 Waiter
= CONTAINING_RECORD(CurrentEntry
, NPFS_WAITER_ENTRY
, Entry
);
132 Irp
= CONTAINING_RECORD(Waiter
, IRP
, Tail
.Overlay
.DriverContext
);
133 if (Waiter
->Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
135 DPRINT("Server found! CCB %p\n", Waiter
->Ccb
);
137 IoAcquireCancelSpinLock(&oldIrql
);
140 if (IoSetCancelRoutine(Irp
, NULL
) != NULL
)
142 IoReleaseCancelSpinLock(oldIrql
);
146 IoReleaseCancelSpinLock(oldIrql
);
149 CurrentEntry
= CurrentEntry
->Flink
;
157 NpfsSignalAndRemoveListeningServerInstance(PNPFS_FCB Fcb
,
160 PLIST_ENTRY CurrentEntry
;
161 PNPFS_WAITER_ENTRY Waiter
;
164 CurrentEntry
= Fcb
->WaiterListHead
.Flink
;
165 while (CurrentEntry
!= &Fcb
->WaiterListHead
)
167 Waiter
= CONTAINING_RECORD(CurrentEntry
, NPFS_WAITER_ENTRY
, Entry
);
168 if (Waiter
->Ccb
== Ccb
)
170 DPRINT("Server found! CCB %p\n", Waiter
->Ccb
);
172 RemoveEntryList(&Waiter
->Entry
);
173 Irp
= CONTAINING_RECORD(Waiter
, IRP
, Tail
.Overlay
.DriverContext
);
174 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
175 Irp
->IoStatus
.Information
= 0;
176 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
179 CurrentEntry
= CurrentEntry
->Flink
;
185 NpfsOpenFileSystem(PNPFS_FCB Fcb
,
186 PFILE_OBJECT FileObject
,
187 PIO_STATUS_BLOCK IoStatus
)
191 DPRINT("NpfsOpenFileSystem()\n");
193 Ccb
= NpfsAllocateCcb(CCB_DEVICE
, Fcb
);
196 IoStatus
->Status
= STATUS_NO_MEMORY
;
200 Ccb
->FileObject
= FileObject
;
202 FileObject
->FsContext
= Fcb
;
203 FileObject
->FsContext2
= Ccb
;
205 IoStatus
->Information
= FILE_OPENED
;
206 IoStatus
->Status
= STATUS_SUCCESS
;
213 NpfsOpenRootDirectory(PNPFS_FCB Fcb
,
214 PFILE_OBJECT FileObject
,
215 PIO_STATUS_BLOCK IoStatus
)
219 DPRINT("NpfsOpenRootDirectory()\n");
221 Ccb
= NpfsAllocateCcb(CCB_DIRECTORY
, Fcb
);
224 IoStatus
->Status
= STATUS_NO_MEMORY
;
228 Ccb
->FileObject
= FileObject
;
230 FileObject
->FsContext
= Fcb
;
231 FileObject
->FsContext2
= Ccb
;
233 IoStatus
->Information
= FILE_OPENED
;
234 IoStatus
->Status
= STATUS_SUCCESS
;
241 NpfsCreate(PDEVICE_OBJECT DeviceObject
,
244 PEXTENDED_IO_STACK_LOCATION IoStack
;
245 PUNICODE_STRING FileName
;
246 PFILE_OBJECT FileObject
;
247 PFILE_OBJECT RelatedFileObject
;
250 PNPFS_CCB ServerCcb
= NULL
;
252 ACCESS_MASK DesiredAccess
;
254 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
255 BOOLEAN SpecialAccess
;
258 DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
260 Vcb
= (PNPFS_VCB
)DeviceObject
->DeviceExtension
;
261 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
262 FileObject
= IoStack
->FileObject
;
263 RelatedFileObject
= FileObject
->RelatedFileObject
;
264 FileName
= &FileObject
->FileName
;
265 DesiredAccess
= IoStack
->Parameters
.CreatePipe
.SecurityContext
->DesiredAccess
;
267 DPRINT("FileObject %p\n", FileObject
);
268 DPRINT("FileName %wZ\n", &FileObject
->FileName
);
270 Irp
->IoStatus
.Information
= 0;
272 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
273 SpecialAccess
= ((DesiredAccess
& SPECIFIC_RIGHTS_ALL
) == FILE_READ_ATTRIBUTES
);
276 DPRINT("NpfsCreate() open client end for special use!\n");
280 DPRINT("FileName->Length: %hu RelatedFileObject: %p\n", FileName
->Length
, RelatedFileObject
);
282 /* Open the file system */
283 if (FileName
->Length
== 0 &&
284 (RelatedFileObject
== NULL
|| ((PNPFS_CCB
)RelatedFileObject
->FsContext2
)->Type
== CCB_DEVICE
))
286 DPRINT("Open the file system\n");
288 NpfsOpenFileSystem(Vcb
->DeviceFcb
,
292 Status
= Irp
->IoStatus
.Status
;
293 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
297 /* Open the root directory */
298 if ((FileName
->Length
== 2 && FileName
->Buffer
[0] == L
'\\' && RelatedFileObject
== NULL
) ||
299 (FileName
->Length
== 0 && ((PNPFS_CCB
)RelatedFileObject
->FsContext2
)->Type
== CCB_DIRECTORY
))
301 DPRINT("Open the root directory\n");
303 NpfsOpenRootDirectory(Vcb
->RootFcb
,
307 Status
= Irp
->IoStatus
.Status
;
308 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
314 * Step 1. Find the pipe we're trying to open.
316 KeLockMutex(&Vcb
->PipeListLock
);
317 Fcb
= NpfsFindPipe(Vcb
, &FileObject
->FileName
);
320 /* Not found, bail out with error. */
321 DPRINT("No pipe found!\n");
322 KeUnlockMutex(&Vcb
->PipeListLock
);
323 Irp
->IoStatus
.Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
324 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
325 return STATUS_OBJECT_NAME_NOT_FOUND
;
328 KeUnlockMutex(&Vcb
->PipeListLock
);
331 * Acquire the lock for CCB lists. From now on no modifications to the
332 * CCB lists are allowed, because it can cause various misconsistencies.
334 KeLockMutex(&Fcb
->CcbListLock
);
337 * Step 2. Create the client CCB.
339 ClientCcb
= NpfsAllocateCcb(CCB_PIPE
, Fcb
);
340 if (ClientCcb
== NULL
)
342 DPRINT("No memory!\n");
343 KeUnlockMutex(&Fcb
->CcbListLock
);
344 NpfsDereferenceFcb(Fcb
);
345 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
346 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
347 return STATUS_NO_MEMORY
;
350 ClientCcb
->FileObject
= FileObject
;
351 ClientCcb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
352 ClientCcb
->PipeEnd
= FILE_PIPE_CLIENT_END
;
353 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
354 ClientCcb
->PipeState
= SpecialAccess
? 0 : FILE_PIPE_DISCONNECTED_STATE
;
356 ClientCcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
358 InitializeListHead(&ClientCcb
->ReadRequestListHead
);
360 DPRINT("CCB: %p\n", ClientCcb
);
362 /* Initialize data list. */
363 if (Fcb
->OutboundQuota
)
365 ClientCcb
->Data
= ExAllocatePoolWithTag(PagedPool
,
368 if (ClientCcb
->Data
== NULL
)
370 DPRINT("No memory!\n");
371 NpfsDereferenceCcb(ClientCcb
);
372 KeUnlockMutex(&Fcb
->CcbListLock
);
373 NpfsDereferenceFcb(Fcb
);
374 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
375 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
376 return STATUS_NO_MEMORY
;
381 ClientCcb
->Data
= NULL
;
384 ClientCcb
->ReadPtr
= ClientCcb
->Data
;
385 ClientCcb
->WritePtr
= ClientCcb
->Data
;
386 ClientCcb
->ReadDataAvailable
= 0;
387 ClientCcb
->WriteQuotaAvailable
= Fcb
->OutboundQuota
;
388 ClientCcb
->MaxDataLength
= Fcb
->OutboundQuota
;
389 ExInitializeFastMutex(&ClientCcb
->DataListLock
);
390 KeInitializeEvent(&ClientCcb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
391 KeInitializeEvent(&ClientCcb
->ReadEvent
, NotificationEvent
, FALSE
);
392 KeInitializeEvent(&ClientCcb
->WriteEvent
, NotificationEvent
, FALSE
);
396 * Step 3. Search for listening server CCB.
398 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
403 * WARNING: Point of no return! Once we get the server CCB it's
404 * possible that we completed a wait request and so we have to
405 * complete even this request.
408 ServerCcb
= NpfsFindListeningServerInstance(Fcb
);
409 if (ServerCcb
== NULL
)
411 PLIST_ENTRY CurrentEntry
;
415 * If no waiting server CCB was found then try to pick
416 * one of the listing server CCB on the pipe.
419 CurrentEntry
= Fcb
->ServerCcbListHead
.Flink
;
420 while (CurrentEntry
!= &Fcb
->ServerCcbListHead
)
422 Ccb
= CONTAINING_RECORD(CurrentEntry
, NPFS_CCB
, CcbListEntry
);
423 if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
428 CurrentEntry
= CurrentEntry
->Flink
;
432 * No one is listening to me?! I'm so lonely... :(
435 if (ServerCcb
== NULL
)
437 /* Not found, bail out with error for FILE_OPEN requests. */
438 DPRINT("No listening server CCB found!\n");
441 ExFreePoolWithTag(ClientCcb
->Data
, TAG_NPFS_CCB_DATA
);
444 NpfsDereferenceCcb(ClientCcb
);
445 KeUnlockMutex(&Fcb
->CcbListLock
);
446 NpfsDereferenceFcb(Fcb
);
447 Irp
->IoStatus
.Status
= STATUS_OBJECT_PATH_NOT_FOUND
;
448 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
449 return STATUS_OBJECT_PATH_NOT_FOUND
;
454 /* Signal the server thread and remove it from the waiter list */
455 /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
456 NpfsSignalAndRemoveListeningServerInstance(Fcb
, ServerCcb
);
458 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
460 else if (IsListEmpty(&Fcb
->ServerCcbListHead
))
462 DPRINT("No server fcb found!\n");
466 ExFreePoolWithTag(ClientCcb
->Data
, TAG_NPFS_CCB_DATA
);
469 NpfsDereferenceCcb(ClientCcb
);
470 KeUnlockMutex(&Fcb
->CcbListLock
);
471 NpfsDereferenceFcb(Fcb
);
472 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
473 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
474 return STATUS_UNSUCCESSFUL
;
479 * Step 4. Add the client CCB to a list and connect it if possible.
482 /* Add the client CCB to the pipe CCB list. */
483 InsertTailList(&Fcb
->ClientCcbListHead
, &ClientCcb
->CcbListEntry
);
485 /* Connect to listening server side */
488 NpfsCcbSetOtherSide(ClientCcb
, ServerCcb
);
489 NpfsCcbSetOtherSide(ServerCcb
, ClientCcb
);
490 ClientCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
491 ServerCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
492 KeSetEvent(&ServerCcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
495 KeUnlockMutex(&Fcb
->CcbListLock
);
497 FileObject
->FsContext
= Fcb
;
498 FileObject
->FsContext2
= ClientCcb
;
499 FileObject
->Flags
|= FO_NAMED_PIPE
;
501 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
502 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
504 DPRINT("Success!\n");
506 return STATUS_SUCCESS
;
511 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject
,
514 PEXTENDED_IO_STACK_LOCATION IoStack
;
515 PFILE_OBJECT FileObject
;
519 PNAMED_PIPE_CREATE_PARAMETERS Buffer
;
521 DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
523 Vcb
= (PNPFS_VCB
)DeviceObject
->DeviceExtension
;
524 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
525 FileObject
= IoStack
->FileObject
;
526 DPRINT("FileObject %p\n", FileObject
);
527 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
529 Buffer
= IoStack
->Parameters
.CreatePipe
.Parameters
;
531 Irp
->IoStatus
.Information
= 0;
533 if (!(IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
)) ||
534 (IoStack
->Parameters
.CreatePipe
.ShareAccess
& ~(FILE_SHARE_READ
|FILE_SHARE_WRITE
)))
536 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
537 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
538 return STATUS_INVALID_PARAMETER
;
541 KeLockMutex(&Vcb
->PipeListLock
);
544 * First search for existing Pipe with the same name.
546 Fcb
= NpfsFindPipe(Vcb
, &FileObject
->FileName
);
550 * Found Pipe with the same name. Check if we are
553 KeUnlockMutex(&Vcb
->PipeListLock
);
555 if (Fcb
->CurrentInstances
>= Fcb
->MaximumInstances
)
557 DPRINT("Out of instances.\n");
558 NpfsDereferenceFcb(Fcb
);
559 Irp
->IoStatus
.Status
= STATUS_INSTANCE_NOT_AVAILABLE
;
560 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
561 return STATUS_INSTANCE_NOT_AVAILABLE
;
564 if (Fcb
->MaximumInstances
!= Buffer
->MaximumInstances
||
565 Fcb
->TimeOut
.QuadPart
!= Buffer
->DefaultTimeout
.QuadPart
||
566 Fcb
->PipeType
!= Buffer
->NamedPipeType
)
568 DPRINT("Asked for invalid pipe mode.\n");
569 NpfsDereferenceFcb(Fcb
);
570 Irp
->IoStatus
.Status
= STATUS_ACCESS_DENIED
;
571 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
572 return STATUS_ACCESS_DENIED
;
577 Fcb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(NPFS_FCB
), TAG_NPFS_FCB
);
580 KeUnlockMutex(&Vcb
->PipeListLock
);
581 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
582 Irp
->IoStatus
.Information
= 0;
583 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
584 return STATUS_NO_MEMORY
;
587 Fcb
->Type
= FCB_PIPE
;
590 Fcb
->PipeName
.Length
= FileObject
->FileName
.Length
;
591 Fcb
->PipeName
.MaximumLength
= Fcb
->PipeName
.Length
+ sizeof(UNICODE_NULL
);
592 Fcb
->PipeName
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
593 Fcb
->PipeName
.MaximumLength
,
595 if (Fcb
->PipeName
.Buffer
== NULL
)
597 KeUnlockMutex(&Vcb
->PipeListLock
);
598 ExFreePoolWithTag(Fcb
, TAG_NPFS_FCB
);
599 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
600 Irp
->IoStatus
.Information
= 0;
601 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
602 return STATUS_NO_MEMORY
;
605 RtlCopyUnicodeString(&Fcb
->PipeName
, &FileObject
->FileName
);
607 InitializeListHead(&Fcb
->ServerCcbListHead
);
608 InitializeListHead(&Fcb
->ClientCcbListHead
);
609 InitializeListHead(&Fcb
->WaiterListHead
);
610 KeInitializeMutex(&Fcb
->CcbListLock
, 0);
612 Fcb
->PipeType
= Buffer
->NamedPipeType
;
613 Fcb
->ServerReadMode
= Buffer
->ReadMode
;
614 /* MSDN documentation reads that clients always start off in byte mode */
615 Fcb
->ClientReadMode
= FILE_PIPE_BYTE_STREAM_MODE
;
617 Fcb
->CompletionMode
= Buffer
->CompletionMode
;
618 switch (IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
))
620 case FILE_SHARE_READ
:
621 Fcb
->PipeConfiguration
= FILE_PIPE_OUTBOUND
;
623 case FILE_SHARE_WRITE
:
624 Fcb
->PipeConfiguration
= FILE_PIPE_INBOUND
;
626 case FILE_SHARE_READ
|FILE_SHARE_WRITE
:
627 Fcb
->PipeConfiguration
= FILE_PIPE_FULL_DUPLEX
;
630 Fcb
->MaximumInstances
= Buffer
->MaximumInstances
;
631 Fcb
->CurrentInstances
= 0;
632 Fcb
->TimeOut
= Buffer
->DefaultTimeout
;
633 if (!(Fcb
->PipeConfiguration
& FILE_PIPE_OUTBOUND
) ||
634 Fcb
->PipeConfiguration
& FILE_PIPE_FULL_DUPLEX
)
636 if (Buffer
->InboundQuota
== 0)
638 Fcb
->InboundQuota
= Vcb
->DefaultQuota
;
642 Fcb
->InboundQuota
= PAGE_ROUND_UP(Buffer
->InboundQuota
);
643 if (Fcb
->InboundQuota
< Vcb
->MinQuota
)
645 Fcb
->InboundQuota
= Vcb
->MinQuota
;
647 else if (Fcb
->InboundQuota
> Vcb
->MaxQuota
)
649 Fcb
->InboundQuota
= Vcb
->MaxQuota
;
655 Fcb
->InboundQuota
= 0;
658 if (Fcb
->PipeConfiguration
& (FILE_PIPE_FULL_DUPLEX
|FILE_PIPE_OUTBOUND
))
660 if (Buffer
->OutboundQuota
== 0)
662 Fcb
->OutboundQuota
= Vcb
->DefaultQuota
;
666 Fcb
->OutboundQuota
= PAGE_ROUND_UP(Buffer
->OutboundQuota
);
667 if (Fcb
->OutboundQuota
< Vcb
->MinQuota
)
669 Fcb
->OutboundQuota
= Vcb
->MinQuota
;
671 else if (Fcb
->OutboundQuota
> Vcb
->MaxQuota
)
673 Fcb
->OutboundQuota
= Vcb
->MaxQuota
;
679 Fcb
->OutboundQuota
= 0;
682 InsertTailList(&Vcb
->PipeListHead
, &Fcb
->PipeListEntry
);
683 KeUnlockMutex(&Vcb
->PipeListLock
);
686 Ccb
= NpfsAllocateCcb(CCB_PIPE
, Fcb
);
689 NpfsDereferenceFcb(Fcb
);
690 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
691 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
692 return STATUS_NO_MEMORY
;
695 Ccb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
697 if (Fcb
->InboundQuota
)
699 Ccb
->Data
= ExAllocatePoolWithTag(PagedPool
,
702 if (Ccb
->Data
== NULL
)
704 NpfsDereferenceCcb(Ccb
);
705 NpfsDereferenceFcb(Fcb
);
707 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
708 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
709 return STATUS_NO_MEMORY
;
717 Ccb
->ReadPtr
= Ccb
->Data
;
718 Ccb
->WritePtr
= Ccb
->Data
;
719 Ccb
->ReadDataAvailable
= 0;
720 Ccb
->WriteQuotaAvailable
= Fcb
->InboundQuota
;
721 Ccb
->MaxDataLength
= Fcb
->InboundQuota
;
722 InitializeListHead(&Ccb
->ReadRequestListHead
);
723 ExInitializeFastMutex(&Ccb
->DataListLock
);
725 Fcb
->CurrentInstances
++;
728 Ccb
->FileObject
= FileObject
;
729 Ccb
->PipeEnd
= FILE_PIPE_SERVER_END
;
730 Ccb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
732 DPRINT("CCB: %p\n", Ccb
);
734 KeInitializeEvent(&Ccb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
735 KeInitializeEvent(&Ccb
->ReadEvent
, NotificationEvent
, FALSE
);
736 KeInitializeEvent(&Ccb
->WriteEvent
, NotificationEvent
, FALSE
);
738 KeLockMutex(&Fcb
->CcbListLock
);
739 InsertTailList(&Fcb
->ServerCcbListHead
, &Ccb
->CcbListEntry
);
740 KeUnlockMutex(&Fcb
->CcbListLock
);
742 FileObject
->FsContext
= Fcb
;
743 FileObject
->FsContext2
= Ccb
;
744 FileObject
->Flags
|= FO_NAMED_PIPE
;
746 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
747 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
749 DPRINT("Success!\n");
751 return STATUS_SUCCESS
;
756 NpfsCleanup(PDEVICE_OBJECT DeviceObject
,
760 PIO_STACK_LOCATION IoStack
;
761 PFILE_OBJECT FileObject
;
762 PNPFS_CCB Ccb
, OtherSide
;
766 DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
768 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
769 //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
770 FileObject
= IoStack
->FileObject
;
771 Ccb
= FileObject
->FsContext2
;
775 DPRINT("Success!\n");
776 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
777 Irp
->IoStatus
.Information
= 0;
778 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
779 return STATUS_SUCCESS
;
782 if (Ccb
->Type
== CCB_DEVICE
)
784 DPRINT("Cleanup the file system!\n");
785 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
786 Irp
->IoStatus
.Information
= 0;
787 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
788 return STATUS_SUCCESS
;
791 if (Ccb
->Type
== CCB_DIRECTORY
)
793 DPRINT("Cleanup the root directory!\n");
794 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
795 Irp
->IoStatus
.Information
= 0;
796 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
797 return STATUS_SUCCESS
;
800 DPRINT("CCB %p\n", Ccb
);
803 DPRINT("Cleaning pipe %wZ\n", &Fcb
->PipeName
);
805 KeLockMutex(&Fcb
->CcbListLock
);
807 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
811 /* FIXME: Clean up existing connections here ?? */
818 if ((Ccb
->PipeState
== FILE_PIPE_CONNECTED_STATE
) && (Ccb
->OtherSide
))
820 OtherSide
= Ccb
->OtherSide
;
821 ASSERT(OtherSide
->OtherSide
== Ccb
);
823 /* Lock the server first */
826 ExAcquireFastMutex(&Ccb
->DataListLock
);
827 ExAcquireFastMutex(&OtherSide
->DataListLock
);
831 ExAcquireFastMutex(&OtherSide
->DataListLock
);
832 ExAcquireFastMutex(&Ccb
->DataListLock
);
836 NpfsCcbSetOtherSide(OtherSide
, NULL
);
837 NpfsCcbSetOtherSide(Ccb
, NULL
);
840 * Signaling the write event. If is possible that an other
841 * thread waits for an empty buffer.
843 KeSetEvent(&OtherSide
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
844 KeSetEvent(&OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
847 ExReleaseFastMutex(&OtherSide
->DataListLock
);
848 ExReleaseFastMutex(&Ccb
->DataListLock
);
852 ExReleaseFastMutex(&Ccb
->DataListLock
);
853 ExReleaseFastMutex(&OtherSide
->DataListLock
);
856 else if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
859 PNPFS_WAITER_ENTRY WaitEntry
= NULL
;
860 BOOLEAN Complete
= FALSE
;
864 Entry
= Ccb
->Fcb
->WaiterListHead
.Flink
;
865 while (Entry
!= &Ccb
->Fcb
->WaiterListHead
)
867 WaitEntry
= CONTAINING_RECORD(Entry
, NPFS_WAITER_ENTRY
, Entry
);
868 if (WaitEntry
->Ccb
== Ccb
)
870 RemoveEntryList(Entry
);
871 tmpIrp
= CONTAINING_RECORD(WaitEntry
, IRP
, Tail
.Overlay
.DriverContext
);
872 IoAcquireCancelSpinLock(&oldIrql
);
873 Complete
= (NULL
!= IoSetCancelRoutine(tmpIrp
, NULL
));
874 IoReleaseCancelSpinLock(oldIrql
);
877 tmpIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
878 tmpIrp
->IoStatus
.Information
= 0;
879 IoCompleteRequest(tmpIrp
, IO_NO_INCREMENT
);
883 Entry
= Entry
->Flink
;
887 Ccb
->PipeState
= FILE_PIPE_CLOSING_STATE
;
889 KeUnlockMutex(&Fcb
->CcbListLock
);
891 ExAcquireFastMutex(&Ccb
->DataListLock
);
894 ExFreePoolWithTag(Ccb
->Data
, TAG_NPFS_CCB_DATA
);
897 Ccb
->WritePtr
= NULL
;
899 ExReleaseFastMutex(&Ccb
->DataListLock
);
901 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
902 Irp
->IoStatus
.Information
= 0;
903 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
905 DPRINT("Success!\n");
907 return STATUS_SUCCESS
;
911 NpfsClose(PDEVICE_OBJECT DeviceObject
,
914 PIO_STACK_LOCATION IoStack
;
915 PFILE_OBJECT FileObject
;
921 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
923 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
924 //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
925 FileObject
= IoStack
->FileObject
;
926 Ccb
= FileObject
->FsContext2
;
930 DPRINT("Success!\n");
931 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
932 Irp
->IoStatus
.Information
= 0;
933 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
934 return STATUS_SUCCESS
;
937 if (Ccb
->Type
== CCB_DEVICE
)
939 DPRINT("Closing the file system!\n");
941 NpfsDereferenceCcb(Ccb
);
942 FileObject
->FsContext
= NULL
;
943 FileObject
->FsContext2
= NULL
;
945 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
946 Irp
->IoStatus
.Information
= 0;
947 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
948 return STATUS_SUCCESS
;
951 if (Ccb
->Type
== CCB_DIRECTORY
)
953 DPRINT("Closing the root directory!\n");
955 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
!= NULL
)
956 ExFreePoolWithTag(Ccb
->u
.Directory
.SearchPattern
.Buffer
,
959 NpfsDereferenceCcb(Ccb
);
960 FileObject
->FsContext
= NULL
;
961 FileObject
->FsContext2
= NULL
;
963 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
964 Irp
->IoStatus
.Information
= 0;
965 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
966 return STATUS_SUCCESS
;
969 DPRINT("CCB %p\n", Ccb
);
972 DPRINT("Closing pipe %wZ\n", &Fcb
->PipeName
);
974 KeLockMutex(&Fcb
->CcbListLock
);
976 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
981 Fcb
->CurrentInstances
--;
988 /* Disconnect the pipes */
991 /* FIXME: Timo wants it rewritten */
992 /*ASSERT(Ccb->OtherSide->OtherSide == Ccb);*/
993 NpfsCcbSetOtherSide(Ccb
->OtherSide
, NULL
);
994 NpfsCcbSetOtherSide(Ccb
, NULL
);
997 ASSERT(Ccb
->PipeState
== FILE_PIPE_CLOSING_STATE
);
999 FileObject
->FsContext2
= NULL
;
1001 RemoveEntryList(&Ccb
->CcbListEntry
);
1003 NpfsDereferenceCcb(Ccb
);
1005 KeUnlockMutex(&Fcb
->CcbListLock
);
1007 NpfsDereferenceFcb(Fcb
);
1008 FileObject
->FsContext
= NULL
;
1010 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1011 Irp
->IoStatus
.Information
= 0;
1012 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1014 DPRINT("Success!\n");
1016 return STATUS_SUCCESS
;