2005-09-04 21:44:02 +00:00
|
|
|
/*
|
2007-04-18 01:25:28 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* FILE: drivers/fs/np/create.c
|
|
|
|
* PURPOSE: Named pipe filesystem
|
|
|
|
* PROGRAMMER: David Welch <welch@cwcom.net>
|
|
|
|
*/
|
1999-11-24 11:51:55 +00:00
|
|
|
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
|
2007-04-18 01:51:27 +00:00
|
|
|
#include "npfs.h"
|
|
|
|
|
2001-10-21 18:58:32 +00:00
|
|
|
#define NDEBUG
|
2001-05-01 11:09:01 +00:00
|
|
|
#include <debug.h>
|
1999-11-24 11:51:55 +00:00
|
|
|
|
2010-11-21 23:15:11 +00:00
|
|
|
//#define USING_PROPER_NPFS_WAIT_SEMANTICS
|
|
|
|
|
1999-11-24 11:51:55 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2011-07-06 18:14:42 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
NpfsDeleteFcb(PNPFS_FCB Fcb)
|
|
|
|
{
|
|
|
|
PNPFS_VCB Vcb = Fcb->Vcb;
|
|
|
|
|
|
|
|
KeLockMutex(&Vcb->PipeListLock);
|
|
|
|
RemoveEntryList(&Fcb->PipeListEntry);
|
|
|
|
KeUnlockMutex(&Vcb->PipeListLock);
|
|
|
|
RtlFreeUnicodeString(&Fcb->PipeName);
|
|
|
|
ExFreePoolWithTag(Fcb, TAG_NPFS_FCB);
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
PNPFS_CCB
|
|
|
|
NpfsAllocateCcb(CCB_TYPE Type, PNPFS_FCB Fcb)
|
|
|
|
{
|
|
|
|
PNPFS_CCB Ccb;
|
|
|
|
|
|
|
|
Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_CCB), TAG_NPFS_CCB);
|
|
|
|
if (!Ccb)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlZeroMemory(Ccb, sizeof(NPFS_CCB));
|
|
|
|
|
|
|
|
Ccb->RefCount = 1;
|
|
|
|
Ccb->Type = Type;
|
|
|
|
Ccb->Fcb = Fcb;
|
|
|
|
Ccb->OtherSide = NULL;
|
|
|
|
|
|
|
|
return Ccb;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
NpfsReferenceCcb(PNPFS_CCB Ccb)
|
|
|
|
{
|
|
|
|
ASSERT(Ccb->RefCount > 0);
|
|
|
|
InterlockedIncrement((PLONG)&Ccb->RefCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
NpfsDereferenceCcb(PNPFS_CCB Ccb)
|
|
|
|
{
|
|
|
|
/* Decrement reference count */
|
|
|
|
ASSERT(Ccb->RefCount > 0);
|
|
|
|
if (InterlockedDecrement((PLONG)&Ccb->RefCount) == 0)
|
|
|
|
{
|
|
|
|
/* Its zero, delete CCB */
|
|
|
|
ExFreePoolWithTag(Ccb, TAG_NPFS_CCB);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
NpfsCcbSetOtherSide(PNPFS_CCB Ccb, PNPFS_CCB OtherSide)
|
|
|
|
{
|
|
|
|
/* Dereference old other side */
|
|
|
|
if (Ccb->OtherSide) NpfsDereferenceCcb(Ccb->OtherSide);
|
|
|
|
|
|
|
|
/* Reference the new other side */
|
|
|
|
if (OtherSide) NpfsReferenceCcb(OtherSide);
|
|
|
|
|
|
|
|
/* Set new value */
|
|
|
|
Ccb->OtherSide = OtherSide;
|
|
|
|
}
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
PNPFS_FCB
|
|
|
|
NpfsFindPipe(PNPFS_VCB Vcb,
|
2009-02-08 09:04:42 +00:00
|
|
|
PUNICODE_STRING PipeName)
|
2004-10-11 12:37:04 +00:00
|
|
|
{
|
2009-02-08 09:04:42 +00:00
|
|
|
PLIST_ENTRY CurrentEntry;
|
|
|
|
PNPFS_FCB Fcb;
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
CurrentEntry = Vcb->PipeListHead.Flink;
|
|
|
|
while (CurrentEntry != &Vcb->PipeListHead)
|
2009-02-08 09:04:42 +00:00
|
|
|
{
|
|
|
|
Fcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, PipeListEntry);
|
|
|
|
if (RtlCompareUnicodeString(PipeName,
|
|
|
|
&Fcb->PipeName,
|
|
|
|
TRUE) == 0)
|
|
|
|
{
|
|
|
|
DPRINT("<%wZ> = <%wZ>\n", PipeName, &Fcb->PipeName);
|
|
|
|
return Fcb;
|
|
|
|
}
|
|
|
|
|
|
|
|
CurrentEntry = CurrentEntry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2004-10-11 12:37:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-07 19:56:32 +00:00
|
|
|
static PNPFS_CCB
|
2006-05-21 13:19:10 +00:00
|
|
|
NpfsFindListeningServerInstance(PNPFS_FCB Fcb)
|
2004-10-11 12:37:04 +00:00
|
|
|
{
|
2009-02-08 09:04:42 +00:00
|
|
|
PLIST_ENTRY CurrentEntry;
|
|
|
|
PNPFS_WAITER_ENTRY Waiter;
|
|
|
|
KIRQL oldIrql;
|
|
|
|
PIRP Irp;
|
|
|
|
|
|
|
|
CurrentEntry = Fcb->WaiterListHead.Flink;
|
|
|
|
while (CurrentEntry != &Fcb->WaiterListHead)
|
|
|
|
{
|
|
|
|
Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
|
|
|
|
Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
|
|
|
|
if (Waiter->Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
|
|
|
|
{
|
|
|
|
DPRINT("Server found! CCB %p\n", Waiter->Ccb);
|
|
|
|
|
|
|
|
IoAcquireCancelSpinLock(&oldIrql);
|
|
|
|
if (!Irp->Cancel)
|
|
|
|
{
|
2011-11-07 00:52:32 +00:00
|
|
|
if (IoSetCancelRoutine(Irp, NULL) != NULL)
|
|
|
|
{
|
|
|
|
IoReleaseCancelSpinLock(oldIrql);
|
|
|
|
return Waiter->Ccb;
|
|
|
|
}
|
2009-02-08 09:04:42 +00:00
|
|
|
}
|
|
|
|
IoReleaseCancelSpinLock(oldIrql);
|
|
|
|
}
|
|
|
|
|
|
|
|
CurrentEntry = CurrentEntry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2004-10-11 12:37:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-05 12:08:50 +00:00
|
|
|
static VOID
|
2006-05-21 13:19:10 +00:00
|
|
|
NpfsSignalAndRemoveListeningServerInstance(PNPFS_FCB Fcb,
|
2009-02-08 09:04:42 +00:00
|
|
|
PNPFS_CCB Ccb)
|
2005-03-05 12:08:50 +00:00
|
|
|
{
|
2009-02-08 09:04:42 +00:00
|
|
|
PLIST_ENTRY CurrentEntry;
|
|
|
|
PNPFS_WAITER_ENTRY Waiter;
|
|
|
|
PIRP Irp;
|
|
|
|
|
|
|
|
CurrentEntry = Fcb->WaiterListHead.Flink;
|
|
|
|
while (CurrentEntry != &Fcb->WaiterListHead)
|
|
|
|
{
|
|
|
|
Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
|
|
|
|
if (Waiter->Ccb == Ccb)
|
|
|
|
{
|
|
|
|
DPRINT("Server found! CCB %p\n", Waiter->Ccb);
|
|
|
|
|
|
|
|
RemoveEntryList(&Waiter->Entry);
|
|
|
|
Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
CurrentEntry = CurrentEntry->Flink;
|
|
|
|
}
|
2005-03-05 12:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-22 23:08:11 +00:00
|
|
|
static VOID
|
|
|
|
NpfsOpenFileSystem(PNPFS_FCB Fcb,
|
|
|
|
PFILE_OBJECT FileObject,
|
|
|
|
PIO_STATUS_BLOCK IoStatus)
|
|
|
|
{
|
|
|
|
PNPFS_CCB Ccb;
|
|
|
|
|
|
|
|
DPRINT("NpfsOpenFileSystem()\n");
|
|
|
|
|
2011-07-06 18:14:42 +00:00
|
|
|
Ccb = NpfsAllocateCcb(CCB_DEVICE, Fcb);
|
2010-11-22 23:08:11 +00:00
|
|
|
if (Ccb == NULL)
|
|
|
|
{
|
|
|
|
IoStatus->Status = STATUS_NO_MEMORY;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-11-06 18:47:51 +00:00
|
|
|
Ccb->FileObject = FileObject;
|
|
|
|
|
2010-11-22 23:08:11 +00:00
|
|
|
FileObject->FsContext = Fcb;
|
|
|
|
FileObject->FsContext2 = Ccb;
|
|
|
|
|
|
|
|
IoStatus->Information = FILE_OPENED;
|
|
|
|
IoStatus->Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
static VOID
|
|
|
|
NpfsOpenRootDirectory(PNPFS_FCB Fcb,
|
|
|
|
PFILE_OBJECT FileObject,
|
|
|
|
PIO_STATUS_BLOCK IoStatus)
|
|
|
|
{
|
|
|
|
PNPFS_CCB Ccb;
|
|
|
|
|
|
|
|
DPRINT("NpfsOpenRootDirectory()\n");
|
|
|
|
|
2011-07-06 18:14:42 +00:00
|
|
|
Ccb = NpfsAllocateCcb(CCB_DIRECTORY, Fcb);
|
2010-11-19 22:42:53 +00:00
|
|
|
if (Ccb == NULL)
|
|
|
|
{
|
|
|
|
IoStatus->Status = STATUS_NO_MEMORY;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-11-06 18:47:51 +00:00
|
|
|
Ccb->FileObject = FileObject;
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
FileObject->FsContext = Fcb;
|
|
|
|
FileObject->FsContext2 = Ccb;
|
|
|
|
|
|
|
|
IoStatus->Information = FILE_OPENED;
|
|
|
|
IoStatus->Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-29 20:14:45 +00:00
|
|
|
NTSTATUS NTAPI
|
2004-12-23 23:58:44 +00:00
|
|
|
NpfsCreate(PDEVICE_OBJECT DeviceObject,
|
2009-02-08 09:04:42 +00:00
|
|
|
PIRP Irp)
|
1999-11-24 11:51:55 +00:00
|
|
|
{
|
2009-02-08 09:04:42 +00:00
|
|
|
PEXTENDED_IO_STACK_LOCATION IoStack;
|
2010-11-19 22:42:53 +00:00
|
|
|
PUNICODE_STRING FileName;
|
2009-02-08 09:04:42 +00:00
|
|
|
PFILE_OBJECT FileObject;
|
2010-11-19 22:42:53 +00:00
|
|
|
PFILE_OBJECT RelatedFileObject;
|
2009-02-08 09:04:42 +00:00
|
|
|
PNPFS_FCB Fcb;
|
|
|
|
PNPFS_CCB ClientCcb;
|
|
|
|
PNPFS_CCB ServerCcb = NULL;
|
2010-11-19 22:42:53 +00:00
|
|
|
PNPFS_VCB Vcb;
|
2009-02-08 09:04:42 +00:00
|
|
|
ACCESS_MASK DesiredAccess;
|
2010-11-19 22:42:53 +00:00
|
|
|
NTSTATUS Status;
|
2010-11-21 23:15:11 +00:00
|
|
|
#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
|
|
|
|
BOOLEAN SpecialAccess;
|
|
|
|
#endif
|
2009-02-08 09:04:42 +00:00
|
|
|
|
|
|
|
DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
|
2009-02-08 09:04:42 +00:00
|
|
|
IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
FileObject = IoStack->FileObject;
|
2010-11-19 22:42:53 +00:00
|
|
|
RelatedFileObject = FileObject->RelatedFileObject;
|
|
|
|
FileName = &FileObject->FileName;
|
2009-02-08 09:04:42 +00:00
|
|
|
DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
|
2010-11-19 22:42:53 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
DPRINT("FileObject %p\n", FileObject);
|
|
|
|
DPRINT("FileName %wZ\n", &FileObject->FileName);
|
|
|
|
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
|
2010-11-21 23:15:11 +00:00
|
|
|
#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
|
|
|
|
SpecialAccess = ((DesiredAccess & SPECIFIC_RIGHTS_ALL) == FILE_READ_ATTRIBUTES);
|
|
|
|
if (SpecialAccess)
|
|
|
|
{
|
|
|
|
DPRINT("NpfsCreate() open client end for special use!\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-11-22 23:08:11 +00:00
|
|
|
DPRINT("FileName->Length: %hu RelatedFileObject: %p\n", FileName->Length, RelatedFileObject);
|
|
|
|
|
|
|
|
/* Open the file system */
|
|
|
|
if (FileName->Length == 0 &&
|
|
|
|
(RelatedFileObject == NULL || ((PNPFS_CCB)RelatedFileObject->FsContext2)->Type == CCB_DEVICE))
|
|
|
|
{
|
|
|
|
DPRINT("Open the file system\n");
|
|
|
|
|
|
|
|
NpfsOpenFileSystem(Vcb->DeviceFcb,
|
|
|
|
FileObject,
|
|
|
|
&Irp->IoStatus);
|
|
|
|
|
|
|
|
Status = Irp->IoStatus.Status;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Open the root directory */
|
2010-12-07 20:16:45 +00:00
|
|
|
if ((FileName->Length == 2 && FileName->Buffer[0] == L'\\' && RelatedFileObject == NULL) ||
|
|
|
|
(FileName->Length == 0 && ((PNPFS_CCB)RelatedFileObject->FsContext2)->Type == CCB_DIRECTORY))
|
2009-02-08 09:04:42 +00:00
|
|
|
{
|
2010-11-19 22:42:53 +00:00
|
|
|
DPRINT("Open the root directory\n");
|
|
|
|
|
|
|
|
NpfsOpenRootDirectory(Vcb->RootFcb,
|
|
|
|
FileObject,
|
|
|
|
&Irp->IoStatus);
|
|
|
|
|
|
|
|
Status = Irp->IoStatus.Status;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
2009-02-08 09:04:42 +00:00
|
|
|
}
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
/*
|
|
|
|
* Step 1. Find the pipe we're trying to open.
|
|
|
|
*/
|
2010-11-19 22:42:53 +00:00
|
|
|
KeLockMutex(&Vcb->PipeListLock);
|
2011-07-06 18:14:42 +00:00
|
|
|
Fcb = NpfsFindPipe(Vcb, &FileObject->FileName);
|
2009-02-08 09:04:42 +00:00
|
|
|
if (Fcb == NULL)
|
|
|
|
{
|
|
|
|
/* Not found, bail out with error. */
|
|
|
|
DPRINT("No pipe found!\n");
|
2010-11-19 22:42:53 +00:00
|
|
|
KeUnlockMutex(&Vcb->PipeListLock);
|
2009-02-08 09:04:42 +00:00
|
|
|
Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
KeUnlockMutex(&Vcb->PipeListLock);
|
2009-02-08 09:04:42 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Acquire the lock for CCB lists. From now on no modifications to the
|
|
|
|
* CCB lists are allowed, because it can cause various misconsistencies.
|
|
|
|
*/
|
|
|
|
KeLockMutex(&Fcb->CcbListLock);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Step 2. Create the client CCB.
|
|
|
|
*/
|
2011-07-06 18:14:42 +00:00
|
|
|
ClientCcb = NpfsAllocateCcb(CCB_PIPE, Fcb);
|
2009-02-08 09:04:42 +00:00
|
|
|
if (ClientCcb == NULL)
|
|
|
|
{
|
|
|
|
DPRINT("No memory!\n");
|
|
|
|
KeUnlockMutex(&Fcb->CcbListLock);
|
|
|
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
2011-11-06 18:47:51 +00:00
|
|
|
ClientCcb->FileObject = FileObject;
|
2009-02-08 09:04:42 +00:00
|
|
|
ClientCcb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
|
|
|
|
ClientCcb->PipeEnd = FILE_PIPE_CLIENT_END;
|
2010-11-21 23:15:11 +00:00
|
|
|
#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
|
|
|
|
ClientCcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE;
|
|
|
|
#else
|
2010-11-19 22:42:53 +00:00
|
|
|
ClientCcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
|
2010-11-21 23:15:11 +00:00
|
|
|
#endif
|
2009-02-08 09:04:42 +00:00
|
|
|
InitializeListHead(&ClientCcb->ReadRequestListHead);
|
|
|
|
|
|
|
|
DPRINT("CCB: %p\n", ClientCcb);
|
|
|
|
|
|
|
|
/* Initialize data list. */
|
|
|
|
if (Fcb->OutboundQuota)
|
|
|
|
{
|
2011-07-06 18:14:42 +00:00
|
|
|
ClientCcb->Data = ExAllocatePoolWithTag(PagedPool,
|
|
|
|
Fcb->OutboundQuota,
|
|
|
|
TAG_NPFS_CCB_DATA);
|
2009-02-08 09:04:42 +00:00
|
|
|
if (ClientCcb->Data == NULL)
|
|
|
|
{
|
|
|
|
DPRINT("No memory!\n");
|
2011-07-06 18:14:42 +00:00
|
|
|
NpfsDereferenceCcb(ClientCcb);
|
2009-02-08 09:04:42 +00:00
|
|
|
KeUnlockMutex(&Fcb->CcbListLock);
|
|
|
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ClientCcb->Data = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClientCcb->ReadPtr = ClientCcb->Data;
|
|
|
|
ClientCcb->WritePtr = ClientCcb->Data;
|
|
|
|
ClientCcb->ReadDataAvailable = 0;
|
|
|
|
ClientCcb->WriteQuotaAvailable = Fcb->OutboundQuota;
|
|
|
|
ClientCcb->MaxDataLength = Fcb->OutboundQuota;
|
|
|
|
ExInitializeFastMutex(&ClientCcb->DataListLock);
|
|
|
|
KeInitializeEvent(&ClientCcb->ConnectEvent, SynchronizationEvent, FALSE);
|
2010-05-27 23:52:32 +00:00
|
|
|
KeInitializeEvent(&ClientCcb->ReadEvent, NotificationEvent, FALSE);
|
|
|
|
KeInitializeEvent(&ClientCcb->WriteEvent, NotificationEvent, FALSE);
|
2009-02-08 09:04:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Step 3. Search for listening server CCB.
|
|
|
|
*/
|
2010-11-21 23:15:11 +00:00
|
|
|
#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
|
2009-02-08 09:04:42 +00:00
|
|
|
if (!SpecialAccess)
|
|
|
|
{
|
2010-11-21 23:15:11 +00:00
|
|
|
#endif
|
2009-02-08 09:04:42 +00:00
|
|
|
/*
|
|
|
|
* WARNING: Point of no return! Once we get the server CCB it's
|
|
|
|
* possible that we completed a wait request and so we have to
|
|
|
|
* complete even this request.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ServerCcb = NpfsFindListeningServerInstance(Fcb);
|
|
|
|
if (ServerCcb == NULL)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY CurrentEntry;
|
|
|
|
PNPFS_CCB Ccb;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If no waiting server CCB was found then try to pick
|
|
|
|
* one of the listing server CCB on the pipe.
|
|
|
|
*/
|
|
|
|
|
|
|
|
CurrentEntry = Fcb->ServerCcbListHead.Flink;
|
|
|
|
while (CurrentEntry != &Fcb->ServerCcbListHead)
|
|
|
|
{
|
|
|
|
Ccb = CONTAINING_RECORD(CurrentEntry, NPFS_CCB, CcbListEntry);
|
|
|
|
if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
|
|
|
|
{
|
|
|
|
ServerCcb = Ccb;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
CurrentEntry = CurrentEntry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No one is listening to me?! I'm so lonely... :(
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (ServerCcb == NULL)
|
|
|
|
{
|
|
|
|
/* Not found, bail out with error for FILE_OPEN requests. */
|
|
|
|
DPRINT("No listening server CCB found!\n");
|
|
|
|
if (ClientCcb->Data)
|
2009-02-08 09:20:11 +00:00
|
|
|
{
|
2011-07-06 18:14:42 +00:00
|
|
|
ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA);
|
2009-02-08 09:20:11 +00:00
|
|
|
}
|
2010-06-01 10:57:26 +00:00
|
|
|
|
2011-07-06 18:14:42 +00:00
|
|
|
NpfsDereferenceCcb(ClientCcb);
|
2009-02-08 09:04:42 +00:00
|
|
|
KeUnlockMutex(&Fcb->CcbListLock);
|
|
|
|
Irp->IoStatus.Status = STATUS_OBJECT_PATH_NOT_FOUND;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_OBJECT_PATH_NOT_FOUND;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Signal the server thread and remove it from the waiter list */
|
|
|
|
/* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
|
|
|
|
NpfsSignalAndRemoveListeningServerInstance(Fcb, ServerCcb);
|
|
|
|
}
|
2010-11-21 23:15:11 +00:00
|
|
|
#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
|
2009-02-08 09:04:42 +00:00
|
|
|
}
|
|
|
|
else if (IsListEmpty(&Fcb->ServerCcbListHead))
|
|
|
|
{
|
|
|
|
DPRINT("No server fcb found!\n");
|
2010-06-01 10:57:26 +00:00
|
|
|
|
|
|
|
if (ClientCcb->Data)
|
|
|
|
{
|
2011-07-06 18:14:42 +00:00
|
|
|
ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA);
|
2010-06-01 10:57:26 +00:00
|
|
|
}
|
|
|
|
|
2011-07-06 18:14:42 +00:00
|
|
|
NpfsDereferenceCcb(ClientCcb);
|
2010-06-01 10:57:26 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
KeUnlockMutex(&Fcb->CcbListLock);
|
|
|
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2010-11-21 23:15:11 +00:00
|
|
|
#endif
|
2009-02-08 09:04:42 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Step 4. Add the client CCB to a list and connect it if possible.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Add the client CCB to the pipe CCB list. */
|
|
|
|
InsertTailList(&Fcb->ClientCcbListHead, &ClientCcb->CcbListEntry);
|
|
|
|
|
|
|
|
/* Connect to listening server side */
|
|
|
|
if (ServerCcb)
|
|
|
|
{
|
2011-07-06 18:14:42 +00:00
|
|
|
NpfsCcbSetOtherSide(ClientCcb, ServerCcb);
|
|
|
|
NpfsCcbSetOtherSide(ServerCcb, ClientCcb);
|
2009-02-08 09:04:42 +00:00
|
|
|
ClientCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
|
|
|
|
ServerCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
|
|
|
|
KeSetEvent(&ServerCcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
KeUnlockMutex(&Fcb->CcbListLock);
|
|
|
|
|
|
|
|
FileObject->FsContext = Fcb;
|
|
|
|
FileObject->FsContext2 = ClientCcb;
|
|
|
|
FileObject->Flags |= FO_NAMED_PIPE;
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
|
|
|
DPRINT("Success!\n");
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
2000-03-26 22:00:10 +00:00
|
|
|
}
|
|
|
|
|
2001-05-10 23:38:31 +00:00
|
|
|
|
2008-11-29 20:14:45 +00:00
|
|
|
NTSTATUS NTAPI
|
2001-05-01 11:09:01 +00:00
|
|
|
NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
|
2009-02-08 09:04:42 +00:00
|
|
|
PIRP Irp)
|
2000-03-26 22:00:10 +00:00
|
|
|
{
|
2009-02-08 09:04:42 +00:00
|
|
|
PEXTENDED_IO_STACK_LOCATION IoStack;
|
|
|
|
PFILE_OBJECT FileObject;
|
2010-11-19 22:42:53 +00:00
|
|
|
PNPFS_VCB Vcb;
|
2009-02-08 09:04:42 +00:00
|
|
|
PNPFS_FCB Fcb;
|
|
|
|
PNPFS_CCB Ccb;
|
|
|
|
PNAMED_PIPE_CREATE_PARAMETERS Buffer;
|
|
|
|
BOOLEAN NewPipe = FALSE;
|
|
|
|
|
|
|
|
DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
|
2009-02-08 09:04:42 +00:00
|
|
|
IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
FileObject = IoStack->FileObject;
|
|
|
|
DPRINT("FileObject %p\n", FileObject);
|
|
|
|
DPRINT("Pipe name %wZ\n", &FileObject->FileName);
|
|
|
|
|
|
|
|
Buffer = IoStack->Parameters.CreatePipe.Parameters;
|
|
|
|
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
|
|
|
|
if (!(IoStack->Parameters.CreatePipe.ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE)) ||
|
|
|
|
(IoStack->Parameters.CreatePipe.ShareAccess & ~(FILE_SHARE_READ|FILE_SHARE_WRITE)))
|
|
|
|
{
|
|
|
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
KeLockMutex(&Vcb->PipeListLock);
|
2009-02-08 09:04:42 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* First search for existing Pipe with the same name.
|
|
|
|
*/
|
2011-07-06 18:14:42 +00:00
|
|
|
Fcb = NpfsFindPipe(Vcb, &FileObject->FileName);
|
2009-02-08 09:04:42 +00:00
|
|
|
if (Fcb != NULL)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Found Pipe with the same name. Check if we are
|
|
|
|
* allowed to use it.
|
|
|
|
*/
|
2010-11-19 22:42:53 +00:00
|
|
|
KeUnlockMutex(&Vcb->PipeListLock);
|
2009-02-08 09:04:42 +00:00
|
|
|
|
|
|
|
if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
|
|
|
|
{
|
|
|
|
DPRINT("Out of instances.\n");
|
|
|
|
Irp->IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_INSTANCE_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Fcb->MaximumInstances != Buffer->MaximumInstances ||
|
|
|
|
Fcb->TimeOut.QuadPart != Buffer->DefaultTimeout.QuadPart ||
|
|
|
|
Fcb->PipeType != Buffer->NamedPipeType)
|
|
|
|
{
|
|
|
|
DPRINT("Asked for invalid pipe mode.\n");
|
|
|
|
Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_ACCESS_DENIED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NewPipe = TRUE;
|
2011-07-06 18:14:42 +00:00
|
|
|
Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_FCB), TAG_NPFS_FCB);
|
2009-02-08 09:04:42 +00:00
|
|
|
if (Fcb == NULL)
|
|
|
|
{
|
2010-11-19 22:42:53 +00:00
|
|
|
KeUnlockMutex(&Vcb->PipeListLock);
|
2009-02-08 09:04:42 +00:00
|
|
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
Fcb->Type = FCB_PIPE;
|
|
|
|
Fcb->Vcb = Vcb;
|
2009-02-08 09:04:42 +00:00
|
|
|
Fcb->PipeName.Length = FileObject->FileName.Length;
|
|
|
|
Fcb->PipeName.MaximumLength = Fcb->PipeName.Length + sizeof(UNICODE_NULL);
|
2011-07-06 18:14:42 +00:00
|
|
|
Fcb->PipeName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
Fcb->PipeName.MaximumLength,
|
|
|
|
TAG_NPFS_NAMEBLOCK);
|
2009-02-08 09:04:42 +00:00
|
|
|
if (Fcb->PipeName.Buffer == NULL)
|
|
|
|
{
|
2010-11-19 22:42:53 +00:00
|
|
|
KeUnlockMutex(&Vcb->PipeListLock);
|
2011-07-06 18:14:42 +00:00
|
|
|
ExFreePoolWithTag(Fcb, TAG_NPFS_FCB);
|
2009-02-08 09:04:42 +00:00
|
|
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlCopyUnicodeString(&Fcb->PipeName, &FileObject->FileName);
|
|
|
|
|
|
|
|
InitializeListHead(&Fcb->ServerCcbListHead);
|
|
|
|
InitializeListHead(&Fcb->ClientCcbListHead);
|
|
|
|
InitializeListHead(&Fcb->WaiterListHead);
|
|
|
|
KeInitializeMutex(&Fcb->CcbListLock, 0);
|
|
|
|
|
|
|
|
Fcb->PipeType = Buffer->NamedPipeType;
|
|
|
|
Fcb->ServerReadMode = Buffer->ReadMode;
|
|
|
|
/* MSDN documentation reads that clients always start off in byte mode */
|
|
|
|
Fcb->ClientReadMode = FILE_PIPE_BYTE_STREAM_MODE;
|
|
|
|
|
|
|
|
Fcb->CompletionMode = Buffer->CompletionMode;
|
|
|
|
switch (IoStack->Parameters.CreatePipe.ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE))
|
|
|
|
{
|
|
|
|
case FILE_SHARE_READ:
|
|
|
|
Fcb->PipeConfiguration = FILE_PIPE_OUTBOUND;
|
|
|
|
break;
|
|
|
|
case FILE_SHARE_WRITE:
|
|
|
|
Fcb->PipeConfiguration = FILE_PIPE_INBOUND;
|
|
|
|
break;
|
|
|
|
case FILE_SHARE_READ|FILE_SHARE_WRITE:
|
|
|
|
Fcb->PipeConfiguration = FILE_PIPE_FULL_DUPLEX;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Fcb->MaximumInstances = Buffer->MaximumInstances;
|
|
|
|
Fcb->CurrentInstances = 0;
|
|
|
|
Fcb->TimeOut = Buffer->DefaultTimeout;
|
|
|
|
if (!(Fcb->PipeConfiguration & FILE_PIPE_OUTBOUND) ||
|
|
|
|
Fcb->PipeConfiguration & FILE_PIPE_FULL_DUPLEX)
|
|
|
|
{
|
|
|
|
if (Buffer->InboundQuota == 0)
|
|
|
|
{
|
2010-11-19 22:42:53 +00:00
|
|
|
Fcb->InboundQuota = Vcb->DefaultQuota;
|
2009-02-08 09:04:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Fcb->InboundQuota = PAGE_ROUND_UP(Buffer->InboundQuota);
|
2010-11-19 22:42:53 +00:00
|
|
|
if (Fcb->InboundQuota < Vcb->MinQuota)
|
2009-02-08 09:04:42 +00:00
|
|
|
{
|
2010-11-19 22:42:53 +00:00
|
|
|
Fcb->InboundQuota = Vcb->MinQuota;
|
2009-02-08 09:04:42 +00:00
|
|
|
}
|
2010-11-19 22:42:53 +00:00
|
|
|
else if (Fcb->InboundQuota > Vcb->MaxQuota)
|
2009-02-08 09:04:42 +00:00
|
|
|
{
|
2010-11-19 22:42:53 +00:00
|
|
|
Fcb->InboundQuota = Vcb->MaxQuota;
|
2009-02-08 09:04:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Fcb->InboundQuota = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Fcb->PipeConfiguration & (FILE_PIPE_FULL_DUPLEX|FILE_PIPE_OUTBOUND))
|
|
|
|
{
|
|
|
|
if (Buffer->OutboundQuota == 0)
|
|
|
|
{
|
2010-11-19 22:42:53 +00:00
|
|
|
Fcb->OutboundQuota = Vcb->DefaultQuota;
|
2009-02-08 09:04:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Fcb->OutboundQuota = PAGE_ROUND_UP(Buffer->OutboundQuota);
|
2010-11-19 22:42:53 +00:00
|
|
|
if (Fcb->OutboundQuota < Vcb->MinQuota)
|
2009-02-08 09:04:42 +00:00
|
|
|
{
|
2010-11-19 22:42:53 +00:00
|
|
|
Fcb->OutboundQuota = Vcb->MinQuota;
|
2009-02-08 09:04:42 +00:00
|
|
|
}
|
2010-11-19 22:42:53 +00:00
|
|
|
else if (Fcb->OutboundQuota > Vcb->MaxQuota)
|
2009-02-08 09:04:42 +00:00
|
|
|
{
|
2010-11-19 22:42:53 +00:00
|
|
|
Fcb->OutboundQuota = Vcb->MaxQuota;
|
2009-02-08 09:04:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Fcb->OutboundQuota = 0;
|
|
|
|
}
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
InsertTailList(&Vcb->PipeListHead, &Fcb->PipeListEntry);
|
|
|
|
KeUnlockMutex(&Vcb->PipeListLock);
|
2009-02-08 09:04:42 +00:00
|
|
|
}
|
|
|
|
|
2011-07-06 18:14:42 +00:00
|
|
|
Ccb = NpfsAllocateCcb(CCB_PIPE, Fcb);
|
|
|
|
if (Ccb == NULL)
|
|
|
|
{
|
|
|
|
if (NewPipe)
|
|
|
|
{
|
|
|
|
NpfsDeleteFcb(Fcb);
|
|
|
|
}
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ccb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
|
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
if (Fcb->InboundQuota)
|
|
|
|
{
|
2011-07-06 18:14:42 +00:00
|
|
|
Ccb->Data = ExAllocatePoolWithTag(PagedPool,
|
|
|
|
Fcb->InboundQuota,
|
|
|
|
TAG_NPFS_CCB_DATA);
|
2009-02-08 09:04:42 +00:00
|
|
|
if (Ccb->Data == NULL)
|
|
|
|
{
|
2011-07-06 18:14:42 +00:00
|
|
|
NpfsDereferenceCcb(Ccb);
|
2009-02-08 09:04:42 +00:00
|
|
|
|
|
|
|
if (NewPipe)
|
|
|
|
{
|
2011-07-06 18:14:42 +00:00
|
|
|
NpfsDeleteFcb(Fcb);
|
2009-02-08 09:04:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Ccb->Data = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ccb->ReadPtr = Ccb->Data;
|
|
|
|
Ccb->WritePtr = Ccb->Data;
|
|
|
|
Ccb->ReadDataAvailable = 0;
|
|
|
|
Ccb->WriteQuotaAvailable = Fcb->InboundQuota;
|
|
|
|
Ccb->MaxDataLength = Fcb->InboundQuota;
|
|
|
|
InitializeListHead(&Ccb->ReadRequestListHead);
|
|
|
|
ExInitializeFastMutex(&Ccb->DataListLock);
|
|
|
|
|
|
|
|
Fcb->CurrentInstances++;
|
|
|
|
|
|
|
|
Ccb->Fcb = Fcb;
|
2011-11-06 18:47:51 +00:00
|
|
|
Ccb->FileObject = FileObject;
|
2009-02-08 09:04:42 +00:00
|
|
|
Ccb->PipeEnd = FILE_PIPE_SERVER_END;
|
|
|
|
Ccb->PipeState = FILE_PIPE_LISTENING_STATE;
|
|
|
|
|
|
|
|
DPRINT("CCB: %p\n", Ccb);
|
|
|
|
|
|
|
|
KeInitializeEvent(&Ccb->ConnectEvent, SynchronizationEvent, FALSE);
|
2010-05-27 23:52:32 +00:00
|
|
|
KeInitializeEvent(&Ccb->ReadEvent, NotificationEvent, FALSE);
|
|
|
|
KeInitializeEvent(&Ccb->WriteEvent, NotificationEvent, FALSE);
|
2009-02-08 09:04:42 +00:00
|
|
|
|
|
|
|
KeLockMutex(&Fcb->CcbListLock);
|
|
|
|
InsertTailList(&Fcb->ServerCcbListHead, &Ccb->CcbListEntry);
|
|
|
|
KeUnlockMutex(&Fcb->CcbListLock);
|
|
|
|
|
|
|
|
FileObject->FsContext = Fcb;
|
|
|
|
FileObject->FsContext2 = Ccb;
|
|
|
|
FileObject->Flags |= FO_NAMED_PIPE;
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
|
|
|
DPRINT("Success!\n");
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
1999-11-24 11:51:55 +00:00
|
|
|
}
|
1999-12-04 20:58:45 +00:00
|
|
|
|
|
|
|
|
2008-11-29 20:14:45 +00:00
|
|
|
NTSTATUS NTAPI
|
2005-03-25 13:40:33 +00:00
|
|
|
NpfsCleanup(PDEVICE_OBJECT DeviceObject,
|
2009-02-08 09:04:42 +00:00
|
|
|
PIRP Irp)
|
2001-05-01 11:09:01 +00:00
|
|
|
{
|
2011-09-11 15:39:19 +00:00
|
|
|
//PNPFS_VCB Vcb;
|
2009-02-08 09:04:42 +00:00
|
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
PFILE_OBJECT FileObject;
|
|
|
|
PNPFS_CCB Ccb, OtherSide;
|
|
|
|
PNPFS_FCB Fcb;
|
|
|
|
BOOLEAN Server;
|
|
|
|
|
|
|
|
DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
|
|
|
|
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
2011-09-11 15:39:19 +00:00
|
|
|
//Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
|
2009-02-08 09:04:42 +00:00
|
|
|
FileObject = IoStack->FileObject;
|
|
|
|
Ccb = FileObject->FsContext2;
|
|
|
|
|
|
|
|
if (Ccb == NULL)
|
|
|
|
{
|
|
|
|
DPRINT("Success!\n");
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-11-22 23:08:11 +00:00
|
|
|
if (Ccb->Type == CCB_DEVICE)
|
|
|
|
{
|
|
|
|
DPRINT("Cleanup the file system!\n");
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
if (Ccb->Type == CCB_DIRECTORY)
|
|
|
|
{
|
|
|
|
DPRINT("Cleanup the root directory!\n");
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
DPRINT("CCB %p\n", Ccb);
|
|
|
|
Fcb = Ccb->Fcb;
|
|
|
|
|
|
|
|
DPRINT("Cleaning pipe %wZ\n", &Fcb->PipeName);
|
|
|
|
|
|
|
|
KeLockMutex(&Fcb->CcbListLock);
|
|
|
|
|
|
|
|
Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END);
|
|
|
|
|
|
|
|
if (Server)
|
|
|
|
{
|
|
|
|
/* FIXME: Clean up existing connections here ?? */
|
|
|
|
DPRINT("Server\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT("Client\n");
|
|
|
|
}
|
2009-03-29 11:15:10 +00:00
|
|
|
if ((Ccb->PipeState == FILE_PIPE_CONNECTED_STATE) && (Ccb->OtherSide))
|
2009-02-08 09:04:42 +00:00
|
|
|
{
|
|
|
|
OtherSide = Ccb->OtherSide;
|
2011-07-06 18:14:42 +00:00
|
|
|
ASSERT(OtherSide->OtherSide == Ccb);
|
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
/* Lock the server first */
|
|
|
|
if (Server)
|
|
|
|
{
|
|
|
|
ExAcquireFastMutex(&Ccb->DataListLock);
|
|
|
|
ExAcquireFastMutex(&OtherSide->DataListLock);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ExAcquireFastMutex(&OtherSide->DataListLock);
|
|
|
|
ExAcquireFastMutex(&Ccb->DataListLock);
|
|
|
|
}
|
2011-07-06 18:14:42 +00:00
|
|
|
|
|
|
|
/* Unlink FCBs */
|
|
|
|
NpfsCcbSetOtherSide(OtherSide, NULL);
|
|
|
|
NpfsCcbSetOtherSide(Ccb, NULL);
|
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
/*
|
|
|
|
* Signaling the write event. If is possible that an other
|
|
|
|
* thread waits for an empty buffer.
|
|
|
|
*/
|
|
|
|
KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
|
|
|
|
KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
|
|
|
|
if (Server)
|
|
|
|
{
|
|
|
|
ExReleaseFastMutex(&OtherSide->DataListLock);
|
|
|
|
ExReleaseFastMutex(&Ccb->DataListLock);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ExReleaseFastMutex(&Ccb->DataListLock);
|
|
|
|
ExReleaseFastMutex(&OtherSide->DataListLock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
PNPFS_WAITER_ENTRY WaitEntry = NULL;
|
|
|
|
BOOLEAN Complete = FALSE;
|
|
|
|
KIRQL oldIrql;
|
|
|
|
PIRP tmpIrp;
|
|
|
|
|
|
|
|
Entry = Ccb->Fcb->WaiterListHead.Flink;
|
|
|
|
while (Entry != &Ccb->Fcb->WaiterListHead)
|
|
|
|
{
|
|
|
|
WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
|
|
|
|
if (WaitEntry->Ccb == Ccb)
|
|
|
|
{
|
|
|
|
RemoveEntryList(Entry);
|
|
|
|
tmpIrp = CONTAINING_RECORD(WaitEntry, IRP, Tail.Overlay.DriverContext);
|
|
|
|
IoAcquireCancelSpinLock(&oldIrql);
|
2011-11-07 00:52:32 +00:00
|
|
|
Complete = (NULL != IoSetCancelRoutine(tmpIrp, NULL));
|
2009-02-08 09:04:42 +00:00
|
|
|
IoReleaseCancelSpinLock(oldIrql);
|
|
|
|
if (Complete)
|
|
|
|
{
|
|
|
|
tmpIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
|
|
|
|
tmpIrp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(tmpIrp, IO_NO_INCREMENT);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Entry = Entry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
Ccb->PipeState = FILE_PIPE_CLOSING_STATE;
|
|
|
|
|
|
|
|
KeUnlockMutex(&Fcb->CcbListLock);
|
|
|
|
|
|
|
|
ExAcquireFastMutex(&Ccb->DataListLock);
|
|
|
|
if (Ccb->Data)
|
|
|
|
{
|
2011-07-06 18:14:42 +00:00
|
|
|
ExFreePoolWithTag(Ccb->Data, TAG_NPFS_CCB_DATA);
|
2009-02-08 09:04:42 +00:00
|
|
|
Ccb->Data = NULL;
|
|
|
|
Ccb->ReadPtr = NULL;
|
|
|
|
Ccb->WritePtr = NULL;
|
|
|
|
}
|
|
|
|
ExReleaseFastMutex(&Ccb->DataListLock);
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
|
|
|
DPRINT("Success!\n");
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
2005-03-25 13:40:33 +00:00
|
|
|
}
|
|
|
|
|
2008-11-29 20:14:45 +00:00
|
|
|
NTSTATUS NTAPI
|
2005-03-25 13:40:33 +00:00
|
|
|
NpfsClose(PDEVICE_OBJECT DeviceObject,
|
2009-02-08 09:04:42 +00:00
|
|
|
PIRP Irp)
|
2005-03-25 13:40:33 +00:00
|
|
|
{
|
2009-02-08 09:04:42 +00:00
|
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
PFILE_OBJECT FileObject;
|
2011-09-11 15:39:19 +00:00
|
|
|
//PNPFS_VCB Vcb;
|
2009-02-08 09:04:42 +00:00
|
|
|
PNPFS_FCB Fcb;
|
|
|
|
PNPFS_CCB Ccb;
|
|
|
|
BOOLEAN Server;
|
2005-03-25 13:40:33 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
|
2005-03-25 13:40:33 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
2011-09-11 15:39:19 +00:00
|
|
|
//Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
|
2009-02-08 09:04:42 +00:00
|
|
|
FileObject = IoStack->FileObject;
|
|
|
|
Ccb = FileObject->FsContext2;
|
2005-03-25 13:40:33 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
if (Ccb == NULL)
|
|
|
|
{
|
|
|
|
DPRINT("Success!\n");
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2005-03-25 13:40:33 +00:00
|
|
|
|
2010-11-22 23:08:11 +00:00
|
|
|
if (Ccb->Type == CCB_DEVICE)
|
|
|
|
{
|
|
|
|
DPRINT("Closing the file system!\n");
|
|
|
|
|
2011-07-06 18:14:42 +00:00
|
|
|
NpfsDereferenceCcb(Ccb);
|
2010-11-22 23:08:11 +00:00
|
|
|
FileObject->FsContext = NULL;
|
|
|
|
FileObject->FsContext2 = NULL;
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-11-19 22:42:53 +00:00
|
|
|
if (Ccb->Type == CCB_DIRECTORY)
|
|
|
|
{
|
|
|
|
DPRINT("Closing the root directory!\n");
|
|
|
|
|
2011-01-01 12:40:24 +00:00
|
|
|
if (Ccb->u.Directory.SearchPattern.Buffer != NULL)
|
2011-07-06 18:14:42 +00:00
|
|
|
ExFreePoolWithTag(Ccb->u.Directory.SearchPattern.Buffer,
|
|
|
|
TAG_NPFS_NAMEBLOCK);
|
2011-01-01 12:40:24 +00:00
|
|
|
|
2011-07-06 18:14:42 +00:00
|
|
|
NpfsDereferenceCcb(Ccb);
|
2010-11-19 22:42:53 +00:00
|
|
|
FileObject->FsContext = NULL;
|
|
|
|
FileObject->FsContext2 = NULL;
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
DPRINT("CCB %p\n", Ccb);
|
|
|
|
Fcb = Ccb->Fcb;
|
2005-03-25 13:40:33 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
DPRINT("Closing pipe %wZ\n", &Fcb->PipeName);
|
2005-03-25 13:40:33 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
KeLockMutex(&Fcb->CcbListLock);
|
2005-03-25 13:40:33 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END);
|
2005-03-25 13:40:33 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
if (Server)
|
|
|
|
{
|
|
|
|
DPRINT("Server\n");
|
|
|
|
Fcb->CurrentInstances--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT("Client\n");
|
|
|
|
}
|
2005-03-25 13:40:33 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
/* Disconnect the pipes */
|
2010-05-27 00:26:34 +00:00
|
|
|
if (Ccb->OtherSide)
|
|
|
|
{
|
2011-07-12 22:33:53 +00:00
|
|
|
/* FIXME: Timo wants it rewritten */
|
|
|
|
/*ASSERT(Ccb->OtherSide->OtherSide == Ccb);*/
|
2011-07-06 18:14:42 +00:00
|
|
|
NpfsCcbSetOtherSide(Ccb->OtherSide, NULL);
|
|
|
|
NpfsCcbSetOtherSide(Ccb, NULL);
|
2010-05-27 00:26:34 +00:00
|
|
|
}
|
2009-01-16 19:30:55 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
ASSERT(Ccb->PipeState == FILE_PIPE_CLOSING_STATE);
|
2005-03-25 13:40:33 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
FileObject->FsContext2 = NULL;
|
2005-03-25 13:40:33 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
RemoveEntryList(&Ccb->CcbListEntry);
|
2005-03-25 13:40:33 +00:00
|
|
|
|
2011-07-06 18:14:42 +00:00
|
|
|
NpfsDereferenceCcb(Ccb);
|
2004-05-05 18:30:16 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
KeUnlockMutex(&Fcb->CcbListLock);
|
2004-05-05 18:30:16 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
if (IsListEmpty(&Fcb->ServerCcbListHead) &&
|
|
|
|
IsListEmpty(&Fcb->ClientCcbListHead))
|
|
|
|
{
|
2011-07-06 18:14:42 +00:00
|
|
|
NpfsDeleteFcb(Fcb);
|
2009-02-08 09:04:42 +00:00
|
|
|
FileObject->FsContext = NULL;
|
|
|
|
}
|
2001-10-20 15:30:07 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
2001-10-20 15:30:07 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
DPRINT("Success!\n");
|
2005-01-02 12:02:42 +00:00
|
|
|
|
2009-02-08 09:04:42 +00:00
|
|
|
return STATUS_SUCCESS;
|
2001-05-01 11:09:01 +00:00
|
|
|
}
|
|
|
|
|
1999-12-04 20:58:45 +00:00
|
|
|
/* EOF */
|