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 *****************************************************************/
22 NpfsDeleteFcb(PNPFS_FCB Fcb
)
24 PNPFS_VCB Vcb
= Fcb
->Vcb
;
26 KeLockMutex(&Vcb
->PipeListLock
);
27 RemoveEntryList(&Fcb
->PipeListEntry
);
28 KeUnlockMutex(&Vcb
->PipeListLock
);
29 RtlFreeUnicodeString(&Fcb
->PipeName
);
30 ExFreePoolWithTag(Fcb
, TAG_NPFS_FCB
);
35 NpfsAllocateCcb(CCB_TYPE Type
, PNPFS_FCB Fcb
)
39 Ccb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(NPFS_CCB
), TAG_NPFS_CCB
);
45 RtlZeroMemory(Ccb
, sizeof(NPFS_CCB
));
50 Ccb
->OtherSide
= NULL
;
57 NpfsReferenceCcb(PNPFS_CCB Ccb
)
59 ASSERT(Ccb
->RefCount
> 0);
60 InterlockedIncrement((PLONG
)&Ccb
->RefCount
);
65 NpfsDereferenceCcb(PNPFS_CCB Ccb
)
67 /* Decrement reference count */
68 ASSERT(Ccb
->RefCount
> 0);
69 if (InterlockedDecrement((PLONG
)&Ccb
->RefCount
) == 0)
71 /* Its zero, delete CCB */
72 ExFreePoolWithTag(Ccb
, TAG_NPFS_CCB
);
78 NpfsCcbSetOtherSide(PNPFS_CCB Ccb
, PNPFS_CCB OtherSide
)
80 /* Dereference old other side */
81 if (Ccb
->OtherSide
) NpfsDereferenceCcb(Ccb
->OtherSide
);
83 /* Reference the new other side */
84 if (OtherSide
) NpfsReferenceCcb(OtherSide
);
87 Ccb
->OtherSide
= OtherSide
;
91 NpfsFindPipe(PNPFS_VCB Vcb
,
92 PUNICODE_STRING PipeName
)
94 PLIST_ENTRY CurrentEntry
;
97 CurrentEntry
= Vcb
->PipeListHead
.Flink
;
98 while (CurrentEntry
!= &Vcb
->PipeListHead
)
100 Fcb
= CONTAINING_RECORD(CurrentEntry
, NPFS_FCB
, PipeListEntry
);
101 if (RtlCompareUnicodeString(PipeName
,
105 DPRINT("<%wZ> = <%wZ>\n", PipeName
, &Fcb
->PipeName
);
109 CurrentEntry
= CurrentEntry
->Flink
;
117 NpfsFindListeningServerInstance(PNPFS_FCB Fcb
)
119 PLIST_ENTRY CurrentEntry
;
120 PNPFS_WAITER_ENTRY Waiter
;
124 CurrentEntry
= Fcb
->WaiterListHead
.Flink
;
125 while (CurrentEntry
!= &Fcb
->WaiterListHead
)
127 Waiter
= CONTAINING_RECORD(CurrentEntry
, NPFS_WAITER_ENTRY
, Entry
);
128 Irp
= CONTAINING_RECORD(Waiter
, IRP
, Tail
.Overlay
.DriverContext
);
129 if (Waiter
->Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
131 DPRINT("Server found! CCB %p\n", Waiter
->Ccb
);
133 IoAcquireCancelSpinLock(&oldIrql
);
136 (void)IoSetCancelRoutine(Irp
, NULL
);
137 IoReleaseCancelSpinLock(oldIrql
);
140 IoReleaseCancelSpinLock(oldIrql
);
143 CurrentEntry
= CurrentEntry
->Flink
;
151 NpfsSignalAndRemoveListeningServerInstance(PNPFS_FCB Fcb
,
154 PLIST_ENTRY CurrentEntry
;
155 PNPFS_WAITER_ENTRY Waiter
;
158 CurrentEntry
= Fcb
->WaiterListHead
.Flink
;
159 while (CurrentEntry
!= &Fcb
->WaiterListHead
)
161 Waiter
= CONTAINING_RECORD(CurrentEntry
, NPFS_WAITER_ENTRY
, Entry
);
162 if (Waiter
->Ccb
== Ccb
)
164 DPRINT("Server found! CCB %p\n", Waiter
->Ccb
);
166 RemoveEntryList(&Waiter
->Entry
);
167 Irp
= CONTAINING_RECORD(Waiter
, IRP
, Tail
.Overlay
.DriverContext
);
168 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
169 Irp
->IoStatus
.Information
= 0;
170 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
173 CurrentEntry
= CurrentEntry
->Flink
;
179 NpfsOpenFileSystem(PNPFS_FCB Fcb
,
180 PFILE_OBJECT FileObject
,
181 PIO_STATUS_BLOCK IoStatus
)
185 DPRINT("NpfsOpenFileSystem()\n");
187 Ccb
= NpfsAllocateCcb(CCB_DEVICE
, Fcb
);
190 IoStatus
->Status
= STATUS_NO_MEMORY
;
194 FileObject
->FsContext
= Fcb
;
195 FileObject
->FsContext2
= Ccb
;
197 IoStatus
->Information
= FILE_OPENED
;
198 IoStatus
->Status
= STATUS_SUCCESS
;
205 NpfsOpenRootDirectory(PNPFS_FCB Fcb
,
206 PFILE_OBJECT FileObject
,
207 PIO_STATUS_BLOCK IoStatus
)
211 DPRINT("NpfsOpenRootDirectory()\n");
213 Ccb
= NpfsAllocateCcb(CCB_DIRECTORY
, Fcb
);
216 IoStatus
->Status
= STATUS_NO_MEMORY
;
220 FileObject
->FsContext
= Fcb
;
221 FileObject
->FsContext2
= Ccb
;
223 IoStatus
->Information
= FILE_OPENED
;
224 IoStatus
->Status
= STATUS_SUCCESS
;
231 NpfsCreate(PDEVICE_OBJECT DeviceObject
,
234 PEXTENDED_IO_STACK_LOCATION IoStack
;
235 PUNICODE_STRING FileName
;
236 PFILE_OBJECT FileObject
;
237 PFILE_OBJECT RelatedFileObject
;
240 PNPFS_CCB ServerCcb
= NULL
;
242 ACCESS_MASK DesiredAccess
;
244 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
245 BOOLEAN SpecialAccess
;
248 DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
250 Vcb
= (PNPFS_VCB
)DeviceObject
->DeviceExtension
;
251 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
252 FileObject
= IoStack
->FileObject
;
253 RelatedFileObject
= FileObject
->RelatedFileObject
;
254 FileName
= &FileObject
->FileName
;
255 DesiredAccess
= IoStack
->Parameters
.CreatePipe
.SecurityContext
->DesiredAccess
;
257 DPRINT("FileObject %p\n", FileObject
);
258 DPRINT("FileName %wZ\n", &FileObject
->FileName
);
260 Irp
->IoStatus
.Information
= 0;
262 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
263 SpecialAccess
= ((DesiredAccess
& SPECIFIC_RIGHTS_ALL
) == FILE_READ_ATTRIBUTES
);
266 DPRINT("NpfsCreate() open client end for special use!\n");
270 DPRINT("FileName->Length: %hu RelatedFileObject: %p\n", FileName
->Length
, RelatedFileObject
);
272 /* Open the file system */
273 if (FileName
->Length
== 0 &&
274 (RelatedFileObject
== NULL
|| ((PNPFS_CCB
)RelatedFileObject
->FsContext2
)->Type
== CCB_DEVICE
))
276 DPRINT("Open the file system\n");
278 NpfsOpenFileSystem(Vcb
->DeviceFcb
,
282 Status
= Irp
->IoStatus
.Status
;
283 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
287 /* Open the root directory */
288 if ((FileName
->Length
== 2 && FileName
->Buffer
[0] == L
'\\' && RelatedFileObject
== NULL
) ||
289 (FileName
->Length
== 0 && ((PNPFS_CCB
)RelatedFileObject
->FsContext2
)->Type
== CCB_DIRECTORY
))
291 DPRINT("Open the root directory\n");
293 NpfsOpenRootDirectory(Vcb
->RootFcb
,
297 Status
= Irp
->IoStatus
.Status
;
298 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
304 * Step 1. Find the pipe we're trying to open.
306 KeLockMutex(&Vcb
->PipeListLock
);
307 Fcb
= NpfsFindPipe(Vcb
, &FileObject
->FileName
);
310 /* Not found, bail out with error. */
311 DPRINT("No pipe found!\n");
312 KeUnlockMutex(&Vcb
->PipeListLock
);
313 Irp
->IoStatus
.Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
314 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
315 return STATUS_OBJECT_NAME_NOT_FOUND
;
318 KeUnlockMutex(&Vcb
->PipeListLock
);
321 * Acquire the lock for CCB lists. From now on no modifications to the
322 * CCB lists are allowed, because it can cause various misconsistencies.
324 KeLockMutex(&Fcb
->CcbListLock
);
327 * Step 2. Create the client CCB.
329 ClientCcb
= NpfsAllocateCcb(CCB_PIPE
, Fcb
);
330 if (ClientCcb
== NULL
)
332 DPRINT("No memory!\n");
333 KeUnlockMutex(&Fcb
->CcbListLock
);
334 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
335 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
336 return STATUS_NO_MEMORY
;
339 ClientCcb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
340 ClientCcb
->PipeEnd
= FILE_PIPE_CLIENT_END
;
341 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
342 ClientCcb
->PipeState
= SpecialAccess
? 0 : FILE_PIPE_DISCONNECTED_STATE
;
344 ClientCcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
346 InitializeListHead(&ClientCcb
->ReadRequestListHead
);
348 DPRINT("CCB: %p\n", ClientCcb
);
350 /* Initialize data list. */
351 if (Fcb
->OutboundQuota
)
353 ClientCcb
->Data
= ExAllocatePoolWithTag(PagedPool
,
356 if (ClientCcb
->Data
== NULL
)
358 DPRINT("No memory!\n");
359 NpfsDereferenceCcb(ClientCcb
);
360 KeUnlockMutex(&Fcb
->CcbListLock
);
361 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
362 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
363 return STATUS_NO_MEMORY
;
368 ClientCcb
->Data
= NULL
;
371 ClientCcb
->ReadPtr
= ClientCcb
->Data
;
372 ClientCcb
->WritePtr
= ClientCcb
->Data
;
373 ClientCcb
->ReadDataAvailable
= 0;
374 ClientCcb
->WriteQuotaAvailable
= Fcb
->OutboundQuota
;
375 ClientCcb
->MaxDataLength
= Fcb
->OutboundQuota
;
376 ExInitializeFastMutex(&ClientCcb
->DataListLock
);
377 KeInitializeEvent(&ClientCcb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
378 KeInitializeEvent(&ClientCcb
->ReadEvent
, NotificationEvent
, FALSE
);
379 KeInitializeEvent(&ClientCcb
->WriteEvent
, NotificationEvent
, FALSE
);
383 * Step 3. Search for listening server CCB.
385 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
390 * WARNING: Point of no return! Once we get the server CCB it's
391 * possible that we completed a wait request and so we have to
392 * complete even this request.
395 ServerCcb
= NpfsFindListeningServerInstance(Fcb
);
396 if (ServerCcb
== NULL
)
398 PLIST_ENTRY CurrentEntry
;
402 * If no waiting server CCB was found then try to pick
403 * one of the listing server CCB on the pipe.
406 CurrentEntry
= Fcb
->ServerCcbListHead
.Flink
;
407 while (CurrentEntry
!= &Fcb
->ServerCcbListHead
)
409 Ccb
= CONTAINING_RECORD(CurrentEntry
, NPFS_CCB
, CcbListEntry
);
410 if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
415 CurrentEntry
= CurrentEntry
->Flink
;
419 * No one is listening to me?! I'm so lonely... :(
422 if (ServerCcb
== NULL
)
424 /* Not found, bail out with error for FILE_OPEN requests. */
425 DPRINT("No listening server CCB found!\n");
428 ExFreePoolWithTag(ClientCcb
->Data
, TAG_NPFS_CCB_DATA
);
431 NpfsDereferenceCcb(ClientCcb
);
432 KeUnlockMutex(&Fcb
->CcbListLock
);
433 Irp
->IoStatus
.Status
= STATUS_OBJECT_PATH_NOT_FOUND
;
434 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
435 return STATUS_OBJECT_PATH_NOT_FOUND
;
440 /* Signal the server thread and remove it from the waiter list */
441 /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
442 NpfsSignalAndRemoveListeningServerInstance(Fcb
, ServerCcb
);
444 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
446 else if (IsListEmpty(&Fcb
->ServerCcbListHead
))
448 DPRINT("No server fcb found!\n");
452 ExFreePoolWithTag(ClientCcb
->Data
, TAG_NPFS_CCB_DATA
);
455 NpfsDereferenceCcb(ClientCcb
);
457 KeUnlockMutex(&Fcb
->CcbListLock
);
458 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
459 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
460 return STATUS_UNSUCCESSFUL
;
465 * Step 4. Add the client CCB to a list and connect it if possible.
468 /* Add the client CCB to the pipe CCB list. */
469 InsertTailList(&Fcb
->ClientCcbListHead
, &ClientCcb
->CcbListEntry
);
471 /* Connect to listening server side */
474 NpfsCcbSetOtherSide(ClientCcb
, ServerCcb
);
475 NpfsCcbSetOtherSide(ServerCcb
, ClientCcb
);
476 ClientCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
477 ServerCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
478 KeSetEvent(&ServerCcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
481 KeUnlockMutex(&Fcb
->CcbListLock
);
483 FileObject
->FsContext
= Fcb
;
484 FileObject
->FsContext2
= ClientCcb
;
485 FileObject
->Flags
|= FO_NAMED_PIPE
;
487 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
488 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
490 DPRINT("Success!\n");
492 return STATUS_SUCCESS
;
497 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject
,
500 PEXTENDED_IO_STACK_LOCATION IoStack
;
501 PFILE_OBJECT FileObject
;
505 PNAMED_PIPE_CREATE_PARAMETERS Buffer
;
506 BOOLEAN NewPipe
= FALSE
;
508 DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
510 Vcb
= (PNPFS_VCB
)DeviceObject
->DeviceExtension
;
511 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
512 FileObject
= IoStack
->FileObject
;
513 DPRINT("FileObject %p\n", FileObject
);
514 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
516 Buffer
= IoStack
->Parameters
.CreatePipe
.Parameters
;
518 Irp
->IoStatus
.Information
= 0;
520 if (!(IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
)) ||
521 (IoStack
->Parameters
.CreatePipe
.ShareAccess
& ~(FILE_SHARE_READ
|FILE_SHARE_WRITE
)))
523 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
524 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
525 return STATUS_INVALID_PARAMETER
;
528 KeLockMutex(&Vcb
->PipeListLock
);
531 * First search for existing Pipe with the same name.
533 Fcb
= NpfsFindPipe(Vcb
, &FileObject
->FileName
);
537 * Found Pipe with the same name. Check if we are
540 KeUnlockMutex(&Vcb
->PipeListLock
);
542 if (Fcb
->CurrentInstances
>= Fcb
->MaximumInstances
)
544 DPRINT("Out of instances.\n");
545 Irp
->IoStatus
.Status
= STATUS_INSTANCE_NOT_AVAILABLE
;
546 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
547 return STATUS_INSTANCE_NOT_AVAILABLE
;
550 if (Fcb
->MaximumInstances
!= Buffer
->MaximumInstances
||
551 Fcb
->TimeOut
.QuadPart
!= Buffer
->DefaultTimeout
.QuadPart
||
552 Fcb
->PipeType
!= Buffer
->NamedPipeType
)
554 DPRINT("Asked for invalid pipe mode.\n");
555 Irp
->IoStatus
.Status
= STATUS_ACCESS_DENIED
;
556 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
557 return STATUS_ACCESS_DENIED
;
563 Fcb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(NPFS_FCB
), TAG_NPFS_FCB
);
566 KeUnlockMutex(&Vcb
->PipeListLock
);
567 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
568 Irp
->IoStatus
.Information
= 0;
569 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
570 return STATUS_NO_MEMORY
;
573 Fcb
->Type
= FCB_PIPE
;
575 Fcb
->PipeName
.Length
= FileObject
->FileName
.Length
;
576 Fcb
->PipeName
.MaximumLength
= Fcb
->PipeName
.Length
+ sizeof(UNICODE_NULL
);
577 Fcb
->PipeName
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
578 Fcb
->PipeName
.MaximumLength
,
580 if (Fcb
->PipeName
.Buffer
== NULL
)
582 KeUnlockMutex(&Vcb
->PipeListLock
);
583 ExFreePoolWithTag(Fcb
, TAG_NPFS_FCB
);
584 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
585 Irp
->IoStatus
.Information
= 0;
586 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
587 return STATUS_NO_MEMORY
;
590 RtlCopyUnicodeString(&Fcb
->PipeName
, &FileObject
->FileName
);
592 InitializeListHead(&Fcb
->ServerCcbListHead
);
593 InitializeListHead(&Fcb
->ClientCcbListHead
);
594 InitializeListHead(&Fcb
->WaiterListHead
);
595 KeInitializeMutex(&Fcb
->CcbListLock
, 0);
597 Fcb
->PipeType
= Buffer
->NamedPipeType
;
598 Fcb
->ServerReadMode
= Buffer
->ReadMode
;
599 /* MSDN documentation reads that clients always start off in byte mode */
600 Fcb
->ClientReadMode
= FILE_PIPE_BYTE_STREAM_MODE
;
602 Fcb
->CompletionMode
= Buffer
->CompletionMode
;
603 switch (IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
))
605 case FILE_SHARE_READ
:
606 Fcb
->PipeConfiguration
= FILE_PIPE_OUTBOUND
;
608 case FILE_SHARE_WRITE
:
609 Fcb
->PipeConfiguration
= FILE_PIPE_INBOUND
;
611 case FILE_SHARE_READ
|FILE_SHARE_WRITE
:
612 Fcb
->PipeConfiguration
= FILE_PIPE_FULL_DUPLEX
;
615 Fcb
->MaximumInstances
= Buffer
->MaximumInstances
;
616 Fcb
->CurrentInstances
= 0;
617 Fcb
->TimeOut
= Buffer
->DefaultTimeout
;
618 if (!(Fcb
->PipeConfiguration
& FILE_PIPE_OUTBOUND
) ||
619 Fcb
->PipeConfiguration
& FILE_PIPE_FULL_DUPLEX
)
621 if (Buffer
->InboundQuota
== 0)
623 Fcb
->InboundQuota
= Vcb
->DefaultQuota
;
627 Fcb
->InboundQuota
= PAGE_ROUND_UP(Buffer
->InboundQuota
);
628 if (Fcb
->InboundQuota
< Vcb
->MinQuota
)
630 Fcb
->InboundQuota
= Vcb
->MinQuota
;
632 else if (Fcb
->InboundQuota
> Vcb
->MaxQuota
)
634 Fcb
->InboundQuota
= Vcb
->MaxQuota
;
640 Fcb
->InboundQuota
= 0;
643 if (Fcb
->PipeConfiguration
& (FILE_PIPE_FULL_DUPLEX
|FILE_PIPE_OUTBOUND
))
645 if (Buffer
->OutboundQuota
== 0)
647 Fcb
->OutboundQuota
= Vcb
->DefaultQuota
;
651 Fcb
->OutboundQuota
= PAGE_ROUND_UP(Buffer
->OutboundQuota
);
652 if (Fcb
->OutboundQuota
< Vcb
->MinQuota
)
654 Fcb
->OutboundQuota
= Vcb
->MinQuota
;
656 else if (Fcb
->OutboundQuota
> Vcb
->MaxQuota
)
658 Fcb
->OutboundQuota
= Vcb
->MaxQuota
;
664 Fcb
->OutboundQuota
= 0;
667 InsertTailList(&Vcb
->PipeListHead
, &Fcb
->PipeListEntry
);
668 KeUnlockMutex(&Vcb
->PipeListLock
);
671 Ccb
= NpfsAllocateCcb(CCB_PIPE
, Fcb
);
679 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
680 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
681 return STATUS_NO_MEMORY
;
684 Ccb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
686 if (Fcb
->InboundQuota
)
688 Ccb
->Data
= ExAllocatePoolWithTag(PagedPool
,
691 if (Ccb
->Data
== NULL
)
693 NpfsDereferenceCcb(Ccb
);
700 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
701 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
702 return STATUS_NO_MEMORY
;
710 Ccb
->ReadPtr
= Ccb
->Data
;
711 Ccb
->WritePtr
= Ccb
->Data
;
712 Ccb
->ReadDataAvailable
= 0;
713 Ccb
->WriteQuotaAvailable
= Fcb
->InboundQuota
;
714 Ccb
->MaxDataLength
= Fcb
->InboundQuota
;
715 InitializeListHead(&Ccb
->ReadRequestListHead
);
716 ExInitializeFastMutex(&Ccb
->DataListLock
);
718 Fcb
->CurrentInstances
++;
721 Ccb
->PipeEnd
= FILE_PIPE_SERVER_END
;
722 Ccb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
724 DPRINT("CCB: %p\n", Ccb
);
726 KeInitializeEvent(&Ccb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
727 KeInitializeEvent(&Ccb
->ReadEvent
, NotificationEvent
, FALSE
);
728 KeInitializeEvent(&Ccb
->WriteEvent
, NotificationEvent
, FALSE
);
730 KeLockMutex(&Fcb
->CcbListLock
);
731 InsertTailList(&Fcb
->ServerCcbListHead
, &Ccb
->CcbListEntry
);
732 KeUnlockMutex(&Fcb
->CcbListLock
);
734 FileObject
->FsContext
= Fcb
;
735 FileObject
->FsContext2
= Ccb
;
736 FileObject
->Flags
|= FO_NAMED_PIPE
;
738 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
739 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
741 DPRINT("Success!\n");
743 return STATUS_SUCCESS
;
748 NpfsCleanup(PDEVICE_OBJECT DeviceObject
,
752 PIO_STACK_LOCATION IoStack
;
753 PFILE_OBJECT FileObject
;
754 PNPFS_CCB Ccb
, OtherSide
;
758 DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
760 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
761 Vcb
= (PNPFS_VCB
)DeviceObject
->DeviceExtension
;
762 FileObject
= IoStack
->FileObject
;
763 Ccb
= FileObject
->FsContext2
;
767 DPRINT("Success!\n");
768 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
769 Irp
->IoStatus
.Information
= 0;
770 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
771 return STATUS_SUCCESS
;
774 if (Ccb
->Type
== CCB_DEVICE
)
776 DPRINT("Cleanup the file system!\n");
777 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
778 Irp
->IoStatus
.Information
= 0;
779 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
780 return STATUS_SUCCESS
;
783 if (Ccb
->Type
== CCB_DIRECTORY
)
785 DPRINT("Cleanup the root directory!\n");
786 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
787 Irp
->IoStatus
.Information
= 0;
788 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
789 return STATUS_SUCCESS
;
792 DPRINT("CCB %p\n", Ccb
);
795 DPRINT("Cleaning pipe %wZ\n", &Fcb
->PipeName
);
797 KeLockMutex(&Fcb
->CcbListLock
);
799 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
803 /* FIXME: Clean up existing connections here ?? */
810 if ((Ccb
->PipeState
== FILE_PIPE_CONNECTED_STATE
) && (Ccb
->OtherSide
))
812 OtherSide
= Ccb
->OtherSide
;
813 ASSERT(OtherSide
->OtherSide
== Ccb
);
815 /* Lock the server first */
818 ExAcquireFastMutex(&Ccb
->DataListLock
);
819 ExAcquireFastMutex(&OtherSide
->DataListLock
);
823 ExAcquireFastMutex(&OtherSide
->DataListLock
);
824 ExAcquireFastMutex(&Ccb
->DataListLock
);
828 NpfsCcbSetOtherSide(OtherSide
, NULL
);
829 NpfsCcbSetOtherSide(Ccb
, NULL
);
832 * Signaling the write event. If is possible that an other
833 * thread waits for an empty buffer.
835 KeSetEvent(&OtherSide
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
836 KeSetEvent(&OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
839 ExReleaseFastMutex(&OtherSide
->DataListLock
);
840 ExReleaseFastMutex(&Ccb
->DataListLock
);
844 ExReleaseFastMutex(&Ccb
->DataListLock
);
845 ExReleaseFastMutex(&OtherSide
->DataListLock
);
848 else if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
851 PNPFS_WAITER_ENTRY WaitEntry
= NULL
;
852 BOOLEAN Complete
= FALSE
;
856 Entry
= Ccb
->Fcb
->WaiterListHead
.Flink
;
857 while (Entry
!= &Ccb
->Fcb
->WaiterListHead
)
859 WaitEntry
= CONTAINING_RECORD(Entry
, NPFS_WAITER_ENTRY
, Entry
);
860 if (WaitEntry
->Ccb
== Ccb
)
862 RemoveEntryList(Entry
);
863 tmpIrp
= CONTAINING_RECORD(WaitEntry
, IRP
, Tail
.Overlay
.DriverContext
);
864 IoAcquireCancelSpinLock(&oldIrql
);
867 (void)IoSetCancelRoutine(tmpIrp
, NULL
);
870 IoReleaseCancelSpinLock(oldIrql
);
873 tmpIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
874 tmpIrp
->IoStatus
.Information
= 0;
875 IoCompleteRequest(tmpIrp
, IO_NO_INCREMENT
);
879 Entry
= Entry
->Flink
;
883 Ccb
->PipeState
= FILE_PIPE_CLOSING_STATE
;
885 KeUnlockMutex(&Fcb
->CcbListLock
);
887 ExAcquireFastMutex(&Ccb
->DataListLock
);
890 ExFreePoolWithTag(Ccb
->Data
, TAG_NPFS_CCB_DATA
);
893 Ccb
->WritePtr
= NULL
;
895 ExReleaseFastMutex(&Ccb
->DataListLock
);
897 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
898 Irp
->IoStatus
.Information
= 0;
899 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
901 DPRINT("Success!\n");
903 return STATUS_SUCCESS
;
907 NpfsClose(PDEVICE_OBJECT DeviceObject
,
910 PIO_STACK_LOCATION IoStack
;
911 PFILE_OBJECT FileObject
;
917 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
919 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
920 Vcb
= (PNPFS_VCB
)DeviceObject
->DeviceExtension
;
921 FileObject
= IoStack
->FileObject
;
922 Ccb
= FileObject
->FsContext2
;
926 DPRINT("Success!\n");
927 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
928 Irp
->IoStatus
.Information
= 0;
929 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
930 return STATUS_SUCCESS
;
933 if (Ccb
->Type
== CCB_DEVICE
)
935 DPRINT("Closing the file system!\n");
937 NpfsDereferenceCcb(Ccb
);
938 FileObject
->FsContext
= NULL
;
939 FileObject
->FsContext2
= NULL
;
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_DIRECTORY
)
949 DPRINT("Closing the root directory!\n");
951 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
!= NULL
)
952 ExFreePoolWithTag(Ccb
->u
.Directory
.SearchPattern
.Buffer
,
955 NpfsDereferenceCcb(Ccb
);
956 FileObject
->FsContext
= NULL
;
957 FileObject
->FsContext2
= NULL
;
959 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
960 Irp
->IoStatus
.Information
= 0;
961 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
962 return STATUS_SUCCESS
;
965 DPRINT("CCB %p\n", Ccb
);
968 DPRINT("Closing pipe %wZ\n", &Fcb
->PipeName
);
970 KeLockMutex(&Fcb
->CcbListLock
);
972 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
977 Fcb
->CurrentInstances
--;
984 /* Disconnect the pipes */
987 /* FIXME: Timo wants it rewritten */
988 /*ASSERT(Ccb->OtherSide->OtherSide == Ccb);*/
989 NpfsCcbSetOtherSide(Ccb
->OtherSide
, NULL
);
990 NpfsCcbSetOtherSide(Ccb
, NULL
);
993 ASSERT(Ccb
->PipeState
== FILE_PIPE_CLOSING_STATE
);
995 FileObject
->FsContext2
= NULL
;
997 RemoveEntryList(&Ccb
->CcbListEntry
);
999 NpfsDereferenceCcb(Ccb
);
1001 KeUnlockMutex(&Fcb
->CcbListLock
);
1003 if (IsListEmpty(&Fcb
->ServerCcbListHead
) &&
1004 IsListEmpty(&Fcb
->ClientCcbListHead
))
1007 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
;