Index: create.c =================================================================== --- create.c (revision 56946) +++ create.c (working copy) @@ -19,15 +19,41 @@ static VOID -NpfsDeleteFcb(PNPFS_FCB Fcb) +NpfsReferenceFcb(PNPFS_FCB Fcb) { +#if 0//DBG Mutexes can be acquired recursively :( + /* Assert that we hold the PipeListLock */ + NTSTATUS Status; + LARGE_INTEGER Timeout; + Timeout.QuadPart = 0; + + Status = KeWaitForSingleObject(&Fcb->Vcb->PipeListLock, + Executive, + KernelMode, + FALSE, + &Timeout); + ASSERT(Status == STATUS_TIMEOUT); + if (Status != STATUS_TIMEOUT) + KeReleaseMutex(&Fcb->Vcb->PipeListLock, FALSE); +#endif + (VOID)InterlockedIncrement(&Fcb->RefCount); +} + +VOID +NpfsDereferenceFcb(PNPFS_FCB Fcb) +{ PNPFS_VCB Vcb = Fcb->Vcb; KeLockMutex(&Vcb->PipeListLock); - RemoveEntryList(&Fcb->PipeListEntry); + DPRINT1("NpfsDereferenceFcb. %p Count=%ld\n", Fcb, Fcb->RefCount); + if (InterlockedDecrement(&Fcb->RefCount) == 0) + { + DPRINT1("NpfsDereferenceFcb. Deleting %p\n", Fcb); + RemoveEntryList(&Fcb->PipeListEntry); + RtlFreeUnicodeString(&Fcb->PipeName); + ExFreePoolWithTag(Fcb, TAG_NPFS_FCB); + } KeUnlockMutex(&Vcb->PipeListLock); - RtlFreeUnicodeString(&Fcb->PipeName); - ExFreePoolWithTag(Fcb, TAG_NPFS_FCB); } static @@ -103,6 +129,7 @@ TRUE) == 0) { DPRINT("<%wZ> = <%wZ>\n", PipeName, &Fcb->PipeName); + NpfsReferenceFcb(Fcb); return Fcb; } @@ -337,6 +364,7 @@ { DPRINT("No memory!\n"); KeUnlockMutex(&Fcb->CcbListLock); + NpfsDereferenceFcb(Fcb); Irp->IoStatus.Status = STATUS_NO_MEMORY; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NO_MEMORY; @@ -365,6 +393,7 @@ DPRINT("No memory!\n"); NpfsDereferenceCcb(ClientCcb); KeUnlockMutex(&Fcb->CcbListLock); + NpfsDereferenceFcb(Fcb); Irp->IoStatus.Status = STATUS_NO_MEMORY; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NO_MEMORY; @@ -437,6 +466,7 @@ NpfsDereferenceCcb(ClientCcb); KeUnlockMutex(&Fcb->CcbListLock); + NpfsDereferenceFcb(Fcb); Irp->IoStatus.Status = STATUS_OBJECT_PATH_NOT_FOUND; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_OBJECT_PATH_NOT_FOUND; @@ -460,8 +490,8 @@ } NpfsDereferenceCcb(ClientCcb); - KeUnlockMutex(&Fcb->CcbListLock); + NpfsDereferenceFcb(Fcb); Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; @@ -549,6 +579,7 @@ if (Fcb->CurrentInstances >= Fcb->MaximumInstances) { DPRINT("Out of instances.\n"); + NpfsDereferenceFcb(Fcb); Irp->IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INSTANCE_NOT_AVAILABLE; @@ -559,6 +590,7 @@ Fcb->PipeType != Buffer->NamedPipeType) { DPRINT("Asked for invalid pipe mode.\n"); + NpfsDereferenceFcb(Fcb); Irp->IoStatus.Status = STATUS_ACCESS_DENIED; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_ACCESS_DENIED; @@ -576,6 +608,7 @@ IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NO_MEMORY; } + DPRINT1("NpfsCreateNamedPipe. Creating FCB %p\n", Fcb); Fcb->Type = FCB_PIPE; Fcb->Vcb = Vcb; @@ -600,6 +633,7 @@ InitializeListHead(&Fcb->ClientCcbListHead); InitializeListHead(&Fcb->WaiterListHead); KeInitializeMutex(&Fcb->CcbListLock, 0); + Fcb->RefCount = 1; Fcb->PipeType = Buffer->NamedPipeType; Fcb->ServerReadMode = Buffer->ReadMode; @@ -678,11 +712,7 @@ Ccb = NpfsAllocateCcb(CCB_PIPE, Fcb); if (Ccb == NULL) { - if (NewPipe) - { - NpfsDeleteFcb(Fcb); - } - + NpfsDereferenceFcb(Fcb); Irp->IoStatus.Status = STATUS_NO_MEMORY; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NO_MEMORY; @@ -698,12 +728,8 @@ if (Ccb->Data == NULL) { NpfsDereferenceCcb(Ccb); + NpfsDereferenceFcb(Fcb); - if (NewPipe) - { - NpfsDeleteFcb(Fcb); - } - Irp->IoStatus.Status = STATUS_NO_MEMORY; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NO_MEMORY; @@ -1004,12 +1030,8 @@ KeUnlockMutex(&Fcb->CcbListLock); - if (IsListEmpty(&Fcb->ServerCcbListHead) && - IsListEmpty(&Fcb->ClientCcbListHead)) - { - NpfsDeleteFcb(Fcb); - FileObject->FsContext = NULL; - } + NpfsDereferenceFcb(Fcb); + FileObject->FsContext = NULL; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; @@ -1020,4 +1042,6 @@ return STATUS_SUCCESS; } +//#include "debugpool.c" + /* EOF */ Index: dirctl.c =================================================================== --- dirctl.c (revision 56946) +++ dirctl.c (working copy) @@ -144,6 +144,7 @@ PipeIndex = 0; Vcb = Ccb->Fcb->Vcb; + KeLockMutex(&Vcb->PipeListLock); CurrentEntry = Vcb->PipeListHead.Flink; while (CurrentEntry != &Vcb->PipeListHead && Status == STATUS_SUCCESS) @@ -252,11 +253,17 @@ /* Leave, if there is no space left in the buffer */ if (Status == STATUS_BUFFER_OVERFLOW) + { + KeUnlockMutex(&Vcb->PipeListLock); return Status; + } /* Leave, if we should return only one entry */ if (Stack->Flags & SL_RETURN_SINGLE_ENTRY) + { + KeUnlockMutex(&Vcb->PipeListLock); return STATUS_SUCCESS; + } /* Store the current offset for the next round */ LastOffset = CurrentOffset; @@ -270,6 +277,7 @@ CurrentEntry = CurrentEntry->Flink; } + KeUnlockMutex(&Vcb->PipeListLock); /* Return STATUS_NO_MORE_FILES if no matching pipe name was found */ if (CurrentOffset == 0) Index: fsctrl.c =================================================================== --- fsctrl.c (revision 56946) +++ fsctrl.c (working copy) @@ -375,7 +375,7 @@ { /* found a listening server CCB */ DPRINT("Listening server CCB found -- connecting\n"); - + NpfsDereferenceFcb(Fcb); return STATUS_SUCCESS; } @@ -402,11 +402,12 @@ /* Wait forever */ TimeOut = NULL; } + NpfsDereferenceFcb(Fcb); Status = KeWaitForSingleObject(&Ccb->ConnectEvent, UserRequest, Irp->RequestorMode, - (Ccb->FileObject->Flags & FO_ALERTABLE_IO), + (Ccb->FileObject->Flags & FO_ALERTABLE_IO) != 0, TimeOut); if ((Status == STATUS_USER_APC) || (Status == STATUS_KERNEL_APC) || (Status == STATUS_ALERTED)) Status = STATUS_CANCELLED; @@ -507,7 +508,7 @@ { /* found a listening server CCB */ DPRINT("Listening server CCB found -- connecting\n"); - + NpfsDereferenceFcb(Fcb); return STATUS_SUCCESS; } @@ -521,6 +522,7 @@ TimeOut = WaitPipe->Timeout; else TimeOut = Fcb->TimeOut; + NpfsDereferenceFcb(Fcb); /* Wait for one */ Status = KeWaitForSingleObject(&Ccb->ConnectEvent, Index: npfs.c =================================================================== --- npfs.c (revision 56946) +++ npfs.c (working copy) @@ -89,12 +89,14 @@ Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_FCB), TAG_NPFS_FCB); Fcb->Type = FCB_DEVICE; Fcb->Vcb = Vcb; + Fcb->RefCount = 1; Vcb->DeviceFcb = Fcb; /* Create the root directory FCB */ Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_FCB), TAG_NPFS_FCB); Fcb->Type = FCB_DIRECTORY; Fcb->Vcb = Vcb; + Fcb->RefCount = 1; Vcb->RootFcb = Fcb; return STATUS_SUCCESS; Index: npfs.h =================================================================== --- npfs.h (revision 56946) +++ npfs.h (working copy) @@ -53,6 +53,7 @@ PNPFS_VCB Vcb; UNICODE_STRING PipeName; LIST_ENTRY PipeListEntry; + volatile LONG RefCount; KMUTEX CcbListLock; LIST_ENTRY ServerCcbListHead; LIST_ENTRY ClientCcbListHead; @@ -83,9 +84,9 @@ LIST_ENTRY CcbListEntry; CCB_TYPE Type; PNPFS_FCB Fcb; - - PFILE_OBJECT FileObject; + PFILE_OBJECT FileObject; + struct _NPFS_CCB* OtherSide; struct ETHREAD *Thread; KEVENT ConnectEvent; @@ -190,6 +191,9 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath); +VOID +NpfsDereferenceFcb(PNPFS_FCB Fcb); + PNPFS_FCB NpfsFindPipe(PNPFS_VCB Vcb, PUNICODE_STRING PipeName); @@ -202,4 +206,6 @@ NpfsGetCcb(PFILE_OBJECT FileObject, PNPFS_CCB *Ccb); +//#include "debugpool.h" + #endif /* __DRIVERS_FS_NP_NPFS_H */ Index: rw.c =================================================================== --- rw.c (revision 56946) +++ rw.c (working copy) @@ -826,13 +826,13 @@ KeSetEvent(&ReaderCcb->ReadEvent, IO_NO_INCREMENT, FALSE); ExReleaseFastMutex(&ReaderCcb->DataListLock); - DPRINT("Write Waiting for buffer space (%S)\n", Fcb->PipeName.Buffer); + DPRINT("Write Waiting for buffer space (%wZ)\n", &Fcb->PipeName); Status = KeWaitForSingleObject(&Ccb->WriteEvent, UserRequest, Irp->RequestorMode, - (FileObject->Flags & FO_ALERTABLE_IO), + (FileObject->Flags & FO_ALERTABLE_IO) != 0, NULL); - DPRINT("Write Finished waiting (%S)! Status: %x\n", Fcb->PipeName.Buffer, Status); + DPRINT("Write Finished waiting (%wZ)! Status: %lx\n", &Fcb->PipeName, Status); if ((Status == STATUS_USER_APC) || (Status == STATUS_KERNEL_APC) || (Status == STATUS_ALERTED)) {