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 NpfsFindPipe(PNPFS_VCB Vcb
,
22 PUNICODE_STRING PipeName
)
24 PLIST_ENTRY CurrentEntry
;
27 CurrentEntry
= Vcb
->PipeListHead
.Flink
;
28 while (CurrentEntry
!= &Vcb
->PipeListHead
)
30 Fcb
= CONTAINING_RECORD(CurrentEntry
, NPFS_FCB
, PipeListEntry
);
31 if (RtlCompareUnicodeString(PipeName
,
35 DPRINT("<%wZ> = <%wZ>\n", PipeName
, &Fcb
->PipeName
);
39 CurrentEntry
= CurrentEntry
->Flink
;
47 NpfsFindListeningServerInstance(PNPFS_FCB Fcb
)
49 PLIST_ENTRY CurrentEntry
;
50 PNPFS_WAITER_ENTRY Waiter
;
54 CurrentEntry
= Fcb
->WaiterListHead
.Flink
;
55 while (CurrentEntry
!= &Fcb
->WaiterListHead
)
57 Waiter
= CONTAINING_RECORD(CurrentEntry
, NPFS_WAITER_ENTRY
, Entry
);
58 Irp
= CONTAINING_RECORD(Waiter
, IRP
, Tail
.Overlay
.DriverContext
);
59 if (Waiter
->Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
61 DPRINT("Server found! CCB %p\n", Waiter
->Ccb
);
63 IoAcquireCancelSpinLock(&oldIrql
);
66 (void)IoSetCancelRoutine(Irp
, NULL
);
67 IoReleaseCancelSpinLock(oldIrql
);
70 IoReleaseCancelSpinLock(oldIrql
);
73 CurrentEntry
= CurrentEntry
->Flink
;
81 NpfsSignalAndRemoveListeningServerInstance(PNPFS_FCB Fcb
,
84 PLIST_ENTRY CurrentEntry
;
85 PNPFS_WAITER_ENTRY Waiter
;
88 CurrentEntry
= Fcb
->WaiterListHead
.Flink
;
89 while (CurrentEntry
!= &Fcb
->WaiterListHead
)
91 Waiter
= CONTAINING_RECORD(CurrentEntry
, NPFS_WAITER_ENTRY
, Entry
);
92 if (Waiter
->Ccb
== Ccb
)
94 DPRINT("Server found! CCB %p\n", Waiter
->Ccb
);
96 RemoveEntryList(&Waiter
->Entry
);
97 Irp
= CONTAINING_RECORD(Waiter
, IRP
, Tail
.Overlay
.DriverContext
);
98 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
99 Irp
->IoStatus
.Information
= 0;
100 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
103 CurrentEntry
= CurrentEntry
->Flink
;
109 NpfsOpenFileSystem(PNPFS_FCB Fcb
,
110 PFILE_OBJECT FileObject
,
111 PIO_STATUS_BLOCK IoStatus
)
115 DPRINT("NpfsOpenFileSystem()\n");
117 Ccb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_CCB
));
120 IoStatus
->Status
= STATUS_NO_MEMORY
;
124 RtlZeroMemory(Ccb
, sizeof(NPFS_CCB
));
126 Ccb
->Type
= CCB_DEVICE
;
129 FileObject
->FsContext
= Fcb
;
130 FileObject
->FsContext2
= Ccb
;
132 IoStatus
->Information
= FILE_OPENED
;
133 IoStatus
->Status
= STATUS_SUCCESS
;
140 NpfsOpenRootDirectory(PNPFS_FCB Fcb
,
141 PFILE_OBJECT FileObject
,
142 PIO_STATUS_BLOCK IoStatus
)
146 DPRINT("NpfsOpenRootDirectory()\n");
148 Ccb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_CCB
));
151 IoStatus
->Status
= STATUS_NO_MEMORY
;
155 RtlZeroMemory(Ccb
, sizeof(NPFS_CCB
));
157 Ccb
->Type
= CCB_DIRECTORY
;
160 FileObject
->FsContext
= Fcb
;
161 FileObject
->FsContext2
= Ccb
;
163 IoStatus
->Information
= FILE_OPENED
;
164 IoStatus
->Status
= STATUS_SUCCESS
;
171 NpfsCreate(PDEVICE_OBJECT DeviceObject
,
174 PEXTENDED_IO_STACK_LOCATION IoStack
;
175 PUNICODE_STRING FileName
;
176 PFILE_OBJECT FileObject
;
177 PFILE_OBJECT RelatedFileObject
;
180 PNPFS_CCB ServerCcb
= NULL
;
182 ACCESS_MASK DesiredAccess
;
184 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
185 BOOLEAN SpecialAccess
;
188 DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
190 Vcb
= (PNPFS_VCB
)DeviceObject
->DeviceExtension
;
191 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
192 FileObject
= IoStack
->FileObject
;
193 RelatedFileObject
= FileObject
->RelatedFileObject
;
194 FileName
= &FileObject
->FileName
;
195 DesiredAccess
= IoStack
->Parameters
.CreatePipe
.SecurityContext
->DesiredAccess
;
197 DPRINT("FileObject %p\n", FileObject
);
198 DPRINT("FileName %wZ\n", &FileObject
->FileName
);
200 Irp
->IoStatus
.Information
= 0;
202 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
203 SpecialAccess
= ((DesiredAccess
& SPECIFIC_RIGHTS_ALL
) == FILE_READ_ATTRIBUTES
);
206 DPRINT("NpfsCreate() open client end for special use!\n");
210 DPRINT("FileName->Length: %hu RelatedFileObject: %p\n", FileName
->Length
, RelatedFileObject
);
212 /* Open the file system */
213 if (FileName
->Length
== 0 &&
214 (RelatedFileObject
== NULL
|| ((PNPFS_CCB
)RelatedFileObject
->FsContext2
)->Type
== CCB_DEVICE
))
216 DPRINT("Open the file system\n");
218 NpfsOpenFileSystem(Vcb
->DeviceFcb
,
222 Status
= Irp
->IoStatus
.Status
;
223 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
227 /* Open the root directory */
228 if ((FileName
->Length
== 2 && FileName
->Buffer
[0] == L
'\\' && RelatedFileObject
== NULL
) ||
229 (FileName
->Length
== 0 && ((PNPFS_CCB
)RelatedFileObject
->FsContext2
)->Type
== CCB_DIRECTORY
))
231 DPRINT("Open the root directory\n");
233 NpfsOpenRootDirectory(Vcb
->RootFcb
,
237 Status
= Irp
->IoStatus
.Status
;
238 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
244 * Step 1. Find the pipe we're trying to open.
246 KeLockMutex(&Vcb
->PipeListLock
);
247 Fcb
= NpfsFindPipe(Vcb
,
248 &FileObject
->FileName
);
251 /* Not found, bail out with error. */
252 DPRINT("No pipe found!\n");
253 KeUnlockMutex(&Vcb
->PipeListLock
);
254 Irp
->IoStatus
.Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
255 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
256 return STATUS_OBJECT_NAME_NOT_FOUND
;
259 KeUnlockMutex(&Vcb
->PipeListLock
);
262 * Acquire the lock for CCB lists. From now on no modifications to the
263 * CCB lists are allowed, because it can cause various misconsistencies.
265 KeLockMutex(&Fcb
->CcbListLock
);
268 * Step 2. Create the client CCB.
270 ClientCcb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_CCB
));
271 if (ClientCcb
== NULL
)
273 DPRINT("No memory!\n");
274 KeUnlockMutex(&Fcb
->CcbListLock
);
275 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
276 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
277 return STATUS_NO_MEMORY
;
280 ClientCcb
->Type
= CCB_PIPE
;
281 ClientCcb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
282 ClientCcb
->Fcb
= Fcb
;
283 ClientCcb
->PipeEnd
= FILE_PIPE_CLIENT_END
;
284 ClientCcb
->OtherSide
= NULL
;
285 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
286 ClientCcb
->PipeState
= SpecialAccess
? 0 : FILE_PIPE_DISCONNECTED_STATE
;
288 ClientCcb
->PipeState
= FILE_PIPE_DISCONNECTED_STATE
;
290 InitializeListHead(&ClientCcb
->ReadRequestListHead
);
292 DPRINT("CCB: %p\n", ClientCcb
);
294 /* Initialize data list. */
295 if (Fcb
->OutboundQuota
)
297 ClientCcb
->Data
= ExAllocatePool(PagedPool
, Fcb
->OutboundQuota
);
298 if (ClientCcb
->Data
== NULL
)
300 DPRINT("No memory!\n");
301 ExFreePool(ClientCcb
);
302 KeUnlockMutex(&Fcb
->CcbListLock
);
303 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
304 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
305 return STATUS_NO_MEMORY
;
310 ClientCcb
->Data
= NULL
;
313 ClientCcb
->ReadPtr
= ClientCcb
->Data
;
314 ClientCcb
->WritePtr
= ClientCcb
->Data
;
315 ClientCcb
->ReadDataAvailable
= 0;
316 ClientCcb
->WriteQuotaAvailable
= Fcb
->OutboundQuota
;
317 ClientCcb
->MaxDataLength
= Fcb
->OutboundQuota
;
318 ExInitializeFastMutex(&ClientCcb
->DataListLock
);
319 KeInitializeEvent(&ClientCcb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
320 KeInitializeEvent(&ClientCcb
->ReadEvent
, NotificationEvent
, FALSE
);
321 KeInitializeEvent(&ClientCcb
->WriteEvent
, NotificationEvent
, FALSE
);
325 * Step 3. Search for listening server CCB.
327 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
332 * WARNING: Point of no return! Once we get the server CCB it's
333 * possible that we completed a wait request and so we have to
334 * complete even this request.
337 ServerCcb
= NpfsFindListeningServerInstance(Fcb
);
338 if (ServerCcb
== NULL
)
340 PLIST_ENTRY CurrentEntry
;
344 * If no waiting server CCB was found then try to pick
345 * one of the listing server CCB on the pipe.
348 CurrentEntry
= Fcb
->ServerCcbListHead
.Flink
;
349 while (CurrentEntry
!= &Fcb
->ServerCcbListHead
)
351 Ccb
= CONTAINING_RECORD(CurrentEntry
, NPFS_CCB
, CcbListEntry
);
352 if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
357 CurrentEntry
= CurrentEntry
->Flink
;
361 * No one is listening to me?! I'm so lonely... :(
364 if (ServerCcb
== NULL
)
366 /* Not found, bail out with error for FILE_OPEN requests. */
367 DPRINT("No listening server CCB found!\n");
370 ExFreePool(ClientCcb
->Data
);
373 ExFreePool(ClientCcb
);
374 KeUnlockMutex(&Fcb
->CcbListLock
);
375 Irp
->IoStatus
.Status
= STATUS_OBJECT_PATH_NOT_FOUND
;
376 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
377 return STATUS_OBJECT_PATH_NOT_FOUND
;
382 /* Signal the server thread and remove it from the waiter list */
383 /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
384 NpfsSignalAndRemoveListeningServerInstance(Fcb
, ServerCcb
);
386 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
388 else if (IsListEmpty(&Fcb
->ServerCcbListHead
))
390 DPRINT("No server fcb found!\n");
394 ExFreePool(ClientCcb
->Data
);
397 ExFreePool(ClientCcb
);
399 KeUnlockMutex(&Fcb
->CcbListLock
);
400 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
401 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
402 return STATUS_UNSUCCESSFUL
;
407 * Step 4. Add the client CCB to a list and connect it if possible.
410 /* Add the client CCB to the pipe CCB list. */
411 InsertTailList(&Fcb
->ClientCcbListHead
, &ClientCcb
->CcbListEntry
);
413 /* Connect to listening server side */
416 ClientCcb
->OtherSide
= ServerCcb
;
417 ServerCcb
->OtherSide
= ClientCcb
;
418 ClientCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
419 ServerCcb
->PipeState
= FILE_PIPE_CONNECTED_STATE
;
420 KeSetEvent(&ServerCcb
->ConnectEvent
, IO_NO_INCREMENT
, FALSE
);
423 KeUnlockMutex(&Fcb
->CcbListLock
);
425 FileObject
->FsContext
= Fcb
;
426 FileObject
->FsContext2
= ClientCcb
;
427 FileObject
->Flags
|= FO_NAMED_PIPE
;
429 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
430 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
432 DPRINT("Success!\n");
434 return STATUS_SUCCESS
;
439 NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject
,
442 PEXTENDED_IO_STACK_LOCATION IoStack
;
443 PFILE_OBJECT FileObject
;
447 PNAMED_PIPE_CREATE_PARAMETERS Buffer
;
448 BOOLEAN NewPipe
= FALSE
;
450 DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
452 Vcb
= (PNPFS_VCB
)DeviceObject
->DeviceExtension
;
453 IoStack
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
454 FileObject
= IoStack
->FileObject
;
455 DPRINT("FileObject %p\n", FileObject
);
456 DPRINT("Pipe name %wZ\n", &FileObject
->FileName
);
458 Buffer
= IoStack
->Parameters
.CreatePipe
.Parameters
;
460 Irp
->IoStatus
.Information
= 0;
462 if (!(IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
)) ||
463 (IoStack
->Parameters
.CreatePipe
.ShareAccess
& ~(FILE_SHARE_READ
|FILE_SHARE_WRITE
)))
465 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
466 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
467 return STATUS_INVALID_PARAMETER
;
470 Ccb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_CCB
));
473 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
474 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
475 return STATUS_NO_MEMORY
;
478 Ccb
->Type
= CCB_PIPE
;
479 Ccb
->Thread
= (struct ETHREAD
*)Irp
->Tail
.Overlay
.Thread
;
480 KeLockMutex(&Vcb
->PipeListLock
);
483 * First search for existing Pipe with the same name.
485 Fcb
= NpfsFindPipe(Vcb
,
486 &FileObject
->FileName
);
490 * Found Pipe with the same name. Check if we are
493 KeUnlockMutex(&Vcb
->PipeListLock
);
495 if (Fcb
->CurrentInstances
>= Fcb
->MaximumInstances
)
497 DPRINT("Out of instances.\n");
499 Irp
->IoStatus
.Status
= STATUS_INSTANCE_NOT_AVAILABLE
;
500 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
501 return STATUS_INSTANCE_NOT_AVAILABLE
;
504 if (Fcb
->MaximumInstances
!= Buffer
->MaximumInstances
||
505 Fcb
->TimeOut
.QuadPart
!= Buffer
->DefaultTimeout
.QuadPart
||
506 Fcb
->PipeType
!= Buffer
->NamedPipeType
)
508 DPRINT("Asked for invalid pipe mode.\n");
510 Irp
->IoStatus
.Status
= STATUS_ACCESS_DENIED
;
511 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
512 return STATUS_ACCESS_DENIED
;
518 Fcb
= ExAllocatePool(NonPagedPool
, sizeof(NPFS_FCB
));
521 KeUnlockMutex(&Vcb
->PipeListLock
);
523 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
524 Irp
->IoStatus
.Information
= 0;
525 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
526 return STATUS_NO_MEMORY
;
529 Fcb
->Type
= FCB_PIPE
;
531 Fcb
->PipeName
.Length
= FileObject
->FileName
.Length
;
532 Fcb
->PipeName
.MaximumLength
= Fcb
->PipeName
.Length
+ sizeof(UNICODE_NULL
);
533 Fcb
->PipeName
.Buffer
= ExAllocatePool(NonPagedPool
, Fcb
->PipeName
.MaximumLength
);
534 if (Fcb
->PipeName
.Buffer
== NULL
)
536 KeUnlockMutex(&Vcb
->PipeListLock
);
539 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
540 Irp
->IoStatus
.Information
= 0;
541 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
542 return STATUS_NO_MEMORY
;
545 RtlCopyUnicodeString(&Fcb
->PipeName
, &FileObject
->FileName
);
547 InitializeListHead(&Fcb
->ServerCcbListHead
);
548 InitializeListHead(&Fcb
->ClientCcbListHead
);
549 InitializeListHead(&Fcb
->WaiterListHead
);
550 KeInitializeMutex(&Fcb
->CcbListLock
, 0);
552 Fcb
->PipeType
= Buffer
->NamedPipeType
;
553 Fcb
->ServerReadMode
= Buffer
->ReadMode
;
554 /* MSDN documentation reads that clients always start off in byte mode */
555 Fcb
->ClientReadMode
= FILE_PIPE_BYTE_STREAM_MODE
;
557 Fcb
->CompletionMode
= Buffer
->CompletionMode
;
558 switch (IoStack
->Parameters
.CreatePipe
.ShareAccess
& (FILE_SHARE_READ
|FILE_SHARE_WRITE
))
560 case FILE_SHARE_READ
:
561 Fcb
->PipeConfiguration
= FILE_PIPE_OUTBOUND
;
563 case FILE_SHARE_WRITE
:
564 Fcb
->PipeConfiguration
= FILE_PIPE_INBOUND
;
566 case FILE_SHARE_READ
|FILE_SHARE_WRITE
:
567 Fcb
->PipeConfiguration
= FILE_PIPE_FULL_DUPLEX
;
570 Fcb
->MaximumInstances
= Buffer
->MaximumInstances
;
571 Fcb
->CurrentInstances
= 0;
572 Fcb
->TimeOut
= Buffer
->DefaultTimeout
;
573 if (!(Fcb
->PipeConfiguration
& FILE_PIPE_OUTBOUND
) ||
574 Fcb
->PipeConfiguration
& FILE_PIPE_FULL_DUPLEX
)
576 if (Buffer
->InboundQuota
== 0)
578 Fcb
->InboundQuota
= Vcb
->DefaultQuota
;
582 Fcb
->InboundQuota
= PAGE_ROUND_UP(Buffer
->InboundQuota
);
583 if (Fcb
->InboundQuota
< Vcb
->MinQuota
)
585 Fcb
->InboundQuota
= Vcb
->MinQuota
;
587 else if (Fcb
->InboundQuota
> Vcb
->MaxQuota
)
589 Fcb
->InboundQuota
= Vcb
->MaxQuota
;
595 Fcb
->InboundQuota
= 0;
598 if (Fcb
->PipeConfiguration
& (FILE_PIPE_FULL_DUPLEX
|FILE_PIPE_OUTBOUND
))
600 if (Buffer
->OutboundQuota
== 0)
602 Fcb
->OutboundQuota
= Vcb
->DefaultQuota
;
606 Fcb
->OutboundQuota
= PAGE_ROUND_UP(Buffer
->OutboundQuota
);
607 if (Fcb
->OutboundQuota
< Vcb
->MinQuota
)
609 Fcb
->OutboundQuota
= Vcb
->MinQuota
;
611 else if (Fcb
->OutboundQuota
> Vcb
->MaxQuota
)
613 Fcb
->OutboundQuota
= Vcb
->MaxQuota
;
619 Fcb
->OutboundQuota
= 0;
622 InsertTailList(&Vcb
->PipeListHead
, &Fcb
->PipeListEntry
);
623 KeUnlockMutex(&Vcb
->PipeListLock
);
626 if (Fcb
->InboundQuota
)
628 Ccb
->Data
= ExAllocatePool(PagedPool
, Fcb
->InboundQuota
);
629 if (Ccb
->Data
== NULL
)
635 KeLockMutex(&Vcb
->PipeListLock
);
636 RemoveEntryList(&Fcb
->PipeListEntry
);
637 KeUnlockMutex(&Vcb
->PipeListLock
);
638 RtlFreeUnicodeString(&Fcb
->PipeName
);
642 Irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
643 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
644 return STATUS_NO_MEMORY
;
652 Ccb
->ReadPtr
= Ccb
->Data
;
653 Ccb
->WritePtr
= Ccb
->Data
;
654 Ccb
->ReadDataAvailable
= 0;
655 Ccb
->WriteQuotaAvailable
= Fcb
->InboundQuota
;
656 Ccb
->MaxDataLength
= Fcb
->InboundQuota
;
657 InitializeListHead(&Ccb
->ReadRequestListHead
);
658 ExInitializeFastMutex(&Ccb
->DataListLock
);
660 Fcb
->CurrentInstances
++;
663 Ccb
->PipeEnd
= FILE_PIPE_SERVER_END
;
664 Ccb
->PipeState
= FILE_PIPE_LISTENING_STATE
;
665 Ccb
->OtherSide
= NULL
;
667 DPRINT("CCB: %p\n", Ccb
);
669 KeInitializeEvent(&Ccb
->ConnectEvent
, SynchronizationEvent
, FALSE
);
670 KeInitializeEvent(&Ccb
->ReadEvent
, NotificationEvent
, FALSE
);
671 KeInitializeEvent(&Ccb
->WriteEvent
, NotificationEvent
, FALSE
);
673 KeLockMutex(&Fcb
->CcbListLock
);
674 InsertTailList(&Fcb
->ServerCcbListHead
, &Ccb
->CcbListEntry
);
675 KeUnlockMutex(&Fcb
->CcbListLock
);
677 FileObject
->FsContext
= Fcb
;
678 FileObject
->FsContext2
= Ccb
;
679 FileObject
->Flags
|= FO_NAMED_PIPE
;
681 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
682 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
684 DPRINT("Success!\n");
686 return STATUS_SUCCESS
;
691 NpfsCleanup(PDEVICE_OBJECT DeviceObject
,
695 PIO_STACK_LOCATION IoStack
;
696 PFILE_OBJECT FileObject
;
697 PNPFS_CCB Ccb
, OtherSide
;
701 DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
703 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
704 Vcb
= (PNPFS_VCB
)DeviceObject
->DeviceExtension
;
705 FileObject
= IoStack
->FileObject
;
706 Ccb
= FileObject
->FsContext2
;
710 DPRINT("Success!\n");
711 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
712 Irp
->IoStatus
.Information
= 0;
713 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
714 return STATUS_SUCCESS
;
717 if (Ccb
->Type
== CCB_DEVICE
)
719 DPRINT("Cleanup the file system!\n");
720 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
721 Irp
->IoStatus
.Information
= 0;
722 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
723 return STATUS_SUCCESS
;
726 if (Ccb
->Type
== CCB_DIRECTORY
)
728 DPRINT("Cleanup the root directory!\n");
729 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
730 Irp
->IoStatus
.Information
= 0;
731 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
732 return STATUS_SUCCESS
;
735 DPRINT("CCB %p\n", Ccb
);
738 DPRINT("Cleaning pipe %wZ\n", &Fcb
->PipeName
);
740 KeLockMutex(&Fcb
->CcbListLock
);
742 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
746 /* FIXME: Clean up existing connections here ?? */
753 if ((Ccb
->PipeState
== FILE_PIPE_CONNECTED_STATE
) && (Ccb
->OtherSide
))
755 OtherSide
= Ccb
->OtherSide
;
756 /* Lock the server first */
759 ExAcquireFastMutex(&Ccb
->DataListLock
);
760 ExAcquireFastMutex(&OtherSide
->DataListLock
);
764 ExAcquireFastMutex(&OtherSide
->DataListLock
);
765 ExAcquireFastMutex(&Ccb
->DataListLock
);
767 OtherSide
->OtherSide
= NULL
;
769 * Signaling the write event. If is possible that an other
770 * thread waits for an empty buffer.
772 KeSetEvent(&OtherSide
->ReadEvent
, IO_NO_INCREMENT
, FALSE
);
773 KeSetEvent(&OtherSide
->WriteEvent
, IO_NO_INCREMENT
, FALSE
);
776 ExReleaseFastMutex(&OtherSide
->DataListLock
);
777 ExReleaseFastMutex(&Ccb
->DataListLock
);
781 ExReleaseFastMutex(&Ccb
->DataListLock
);
782 ExReleaseFastMutex(&OtherSide
->DataListLock
);
785 else if (Ccb
->PipeState
== FILE_PIPE_LISTENING_STATE
)
788 PNPFS_WAITER_ENTRY WaitEntry
= NULL
;
789 BOOLEAN Complete
= FALSE
;
793 Entry
= Ccb
->Fcb
->WaiterListHead
.Flink
;
794 while (Entry
!= &Ccb
->Fcb
->WaiterListHead
)
796 WaitEntry
= CONTAINING_RECORD(Entry
, NPFS_WAITER_ENTRY
, Entry
);
797 if (WaitEntry
->Ccb
== Ccb
)
799 RemoveEntryList(Entry
);
800 tmpIrp
= CONTAINING_RECORD(WaitEntry
, IRP
, Tail
.Overlay
.DriverContext
);
801 IoAcquireCancelSpinLock(&oldIrql
);
804 (void)IoSetCancelRoutine(tmpIrp
, NULL
);
807 IoReleaseCancelSpinLock(oldIrql
);
810 tmpIrp
->IoStatus
.Status
= STATUS_PIPE_BROKEN
;
811 tmpIrp
->IoStatus
.Information
= 0;
812 IoCompleteRequest(tmpIrp
, IO_NO_INCREMENT
);
816 Entry
= Entry
->Flink
;
820 Ccb
->PipeState
= FILE_PIPE_CLOSING_STATE
;
822 KeUnlockMutex(&Fcb
->CcbListLock
);
824 ExAcquireFastMutex(&Ccb
->DataListLock
);
827 ExFreePool(Ccb
->Data
);
830 Ccb
->WritePtr
= NULL
;
832 ExReleaseFastMutex(&Ccb
->DataListLock
);
834 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
835 Irp
->IoStatus
.Information
= 0;
836 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
838 DPRINT("Success!\n");
840 return STATUS_SUCCESS
;
844 NpfsClose(PDEVICE_OBJECT DeviceObject
,
847 PIO_STACK_LOCATION IoStack
;
848 PFILE_OBJECT FileObject
;
854 DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject
, Irp
);
856 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
857 Vcb
= (PNPFS_VCB
)DeviceObject
->DeviceExtension
;
858 FileObject
= IoStack
->FileObject
;
859 Ccb
= FileObject
->FsContext2
;
863 DPRINT("Success!\n");
864 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
865 Irp
->IoStatus
.Information
= 0;
866 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
867 return STATUS_SUCCESS
;
870 if (Ccb
->Type
== CCB_DEVICE
)
872 DPRINT("Closing the file system!\n");
875 FileObject
->FsContext
= NULL
;
876 FileObject
->FsContext2
= NULL
;
878 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
879 Irp
->IoStatus
.Information
= 0;
880 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
881 return STATUS_SUCCESS
;
884 if (Ccb
->Type
== CCB_DIRECTORY
)
886 DPRINT("Closing the root directory!\n");
888 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
!= NULL
)
889 ExFreePool(Ccb
->u
.Directory
.SearchPattern
.Buffer
);
892 FileObject
->FsContext
= NULL
;
893 FileObject
->FsContext2
= NULL
;
895 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
896 Irp
->IoStatus
.Information
= 0;
897 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
898 return STATUS_SUCCESS
;
901 DPRINT("CCB %p\n", Ccb
);
904 DPRINT("Closing pipe %wZ\n", &Fcb
->PipeName
);
906 KeLockMutex(&Fcb
->CcbListLock
);
908 Server
= (Ccb
->PipeEnd
== FILE_PIPE_SERVER_END
);
913 Fcb
->CurrentInstances
--;
920 /* Disconnect the pipes */
923 Ccb
->OtherSide
->OtherSide
= NULL
;
924 Ccb
->OtherSide
= NULL
;
927 ASSERT(Ccb
->PipeState
== FILE_PIPE_CLOSING_STATE
);
929 FileObject
->FsContext2
= NULL
;
931 RemoveEntryList(&Ccb
->CcbListEntry
);
935 KeUnlockMutex(&Fcb
->CcbListLock
);
937 if (IsListEmpty(&Fcb
->ServerCcbListHead
) &&
938 IsListEmpty(&Fcb
->ClientCcbListHead
))
940 KeLockMutex(&Vcb
->PipeListLock
);
941 RemoveEntryList(&Fcb
->PipeListEntry
);
942 KeUnlockMutex(&Vcb
->PipeListLock
);
943 RtlFreeUnicodeString(&Fcb
->PipeName
);
945 FileObject
->FsContext
= NULL
;
948 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
949 Irp
->IoStatus
.Information
= 0;
950 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
952 DPRINT("Success!\n");
954 return STATUS_SUCCESS
;