-/* $Id: create.c,v 1.6 2001/05/10 23:38:31 ekohl Exp $
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
- * FILE: services/fs/np/create.c
+ * FILE: drivers/fs/np/create.c
* PURPOSE: Named pipe filesystem
* PROGRAMMER: David Welch <welch@cwcom.net>
*/
/* INCLUDES ******************************************************************/
-#include <ddk/ntddk.h>
+#define NDEBUG
+#include <debug.h>
#include "npfs.h"
-//#define NDEBUG
-#include <debug.h>
+/* FUNCTIONS *****************************************************************/
+
+static PNPFS_PIPE
+NpfsFindPipe(PNPFS_DEVICE_EXTENSION DeviceExt,
+ PUNICODE_STRING PipeName)
+{
+ PLIST_ENTRY CurrentEntry;
+ PNPFS_PIPE Pipe;
+ CurrentEntry = DeviceExt->PipeListHead.Flink;
+ while (CurrentEntry != &DeviceExt->PipeListHead)
+ {
+ Pipe = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE, PipeListEntry);
+ if (RtlCompareUnicodeString(PipeName,
+ &Pipe->PipeName,
+ TRUE) == 0)
+ {
+ DPRINT("<%wZ> = <%wZ>\n", PipeName, &Pipe->PipeName);
+ return Pipe;
+ }
-/* GLOBALS *******************************************************************/
+ CurrentEntry = CurrentEntry->Flink;
+ }
+ return NULL;
+}
+
+
+static PNPFS_FCB
+NpfsFindListeningServerInstance(PNPFS_PIPE Pipe)
+{
+ PLIST_ENTRY CurrentEntry;
+ PNPFS_WAITER_ENTRY Waiter;
+ KIRQL oldIrql;
+ PIRP Irp;
+
+ CurrentEntry = Pipe->WaiterListHead.Flink;
+ while (CurrentEntry != &Pipe->WaiterListHead)
+ {
+ Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
+ Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
+ if (Waiter->Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
+ {
+ DPRINT("Server found! Fcb %p\n", Waiter->Fcb);
+
+ IoAcquireCancelSpinLock(&oldIrql);
+ if (!Irp->Cancel)
+ {
+ IoSetCancelRoutine(Irp, NULL);
+ IoReleaseCancelSpinLock(oldIrql);
+ return Waiter->Fcb;
+ }
+ IoReleaseCancelSpinLock(oldIrql);
+ }
+
+ CurrentEntry = CurrentEntry->Flink;
+ }
+
+ return NULL;
+}
+
+
+static VOID
+NpfsSignalAndRemoveListeningServerInstance(PNPFS_PIPE Pipe,
+ PNPFS_FCB Fcb)
+{
+ PLIST_ENTRY CurrentEntry;
+ PNPFS_WAITER_ENTRY Waiter;
+ PIRP Irp;
+
+ CurrentEntry = Pipe->WaiterListHead.Flink;
+ while (CurrentEntry != &Pipe->WaiterListHead)
+ {
+ Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
+ if (Waiter->Fcb == Fcb)
+ {
+ DPRINT("Server found! Fcb %p\n", Waiter->Fcb);
+
+ 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;
+ }
+}
-/* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL
NpfsCreate(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
- PIO_STACK_LOCATION IoStack;
+ PEXTENDED_IO_STACK_LOCATION IoStack;
+ PFILE_OBJECT FileObject;
+ PNPFS_PIPE Pipe;
+ PNPFS_FCB ClientFcb;
+ PNPFS_FCB ServerFcb = NULL;
+ PNPFS_DEVICE_EXTENSION DeviceExt;
+
+ DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
+
+ DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
+ FileObject = IoStack->FileObject;
+ DPRINT("FileObject %p\n", FileObject);
+ DPRINT("FileName %wZ\n", &FileObject->FileName);
+
+ Irp->IoStatus.Information = 0;
+
+ /*
+ * Step 1. Find the pipe we're trying to open.
+ */
+ KeLockMutex(&DeviceExt->PipeListLock);
+ Pipe = NpfsFindPipe(DeviceExt,
+ &FileObject->FileName);
+ if (Pipe == NULL)
+ {
+ /* Not found, bail out with error. */
+ DPRINT("No pipe found!\n");
+ KeUnlockMutex(&DeviceExt->PipeListLock);
+ Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ KeUnlockMutex(&DeviceExt->PipeListLock);
+
+ /*
+ * Acquire the lock for FCB lists. From now on no modifications to the
+ * FCB lists are allowed, because it can cause various misconsistencies.
+ */
+ KeLockMutex(&Pipe->FcbListLock);
+
+ /*
+ * Step 2. Create the client FCB.
+ */
+ ClientFcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
+ if (ClientFcb == NULL)
+ {
+ DPRINT("No memory!\n");
+ KeUnlockMutex(&Pipe->FcbListLock);
+ Irp->IoStatus.Status = STATUS_NO_MEMORY;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_NO_MEMORY;
+ }
+
+ ClientFcb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
+ ClientFcb->Pipe = Pipe;
+ ClientFcb->PipeEnd = FILE_PIPE_CLIENT_END;
+ ClientFcb->OtherSide = NULL;
+ ClientFcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
+ InitializeListHead(&ClientFcb->ReadRequestListHead);
+
+ DPRINT("Fcb: %x\n", ClientFcb);
+
+ /* Initialize data list. */
+ if (Pipe->OutboundQuota)
+ {
+ ClientFcb->Data = ExAllocatePool(PagedPool, Pipe->OutboundQuota);
+ if (ClientFcb->Data == NULL)
+ {
+ DPRINT("No memory!\n");
+ ExFreePool(ClientFcb);
+ KeUnlockMutex(&Pipe->FcbListLock);
+ Irp->IoStatus.Status = STATUS_NO_MEMORY;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_NO_MEMORY;
+ }
+ }
+ else
+ {
+ ClientFcb->Data = NULL;
+ }
+
+ ClientFcb->ReadPtr = ClientFcb->Data;
+ ClientFcb->WritePtr = ClientFcb->Data;
+ ClientFcb->ReadDataAvailable = 0;
+ ClientFcb->WriteQuotaAvailable = Pipe->OutboundQuota;
+ ClientFcb->MaxDataLength = Pipe->OutboundQuota;
+ ExInitializeFastMutex(&ClientFcb->DataListLock);
+ KeInitializeEvent(&ClientFcb->ConnectEvent, SynchronizationEvent, FALSE);
+ KeInitializeEvent(&ClientFcb->ReadEvent, SynchronizationEvent, FALSE);
+ KeInitializeEvent(&ClientFcb->WriteEvent, SynchronizationEvent, FALSE);
+
+
+ /*
+ * Step 3. Search for listening server FCB.
+ */
+
+ /*
+ * WARNING: Point of no return! Once we get the server FCB it's
+ * possible that we completed a wait request and so we have to
+ * complete even this request.
+ */
+
+ ServerFcb = NpfsFindListeningServerInstance(Pipe);
+ if (ServerFcb == NULL)
+ {
+ PLIST_ENTRY CurrentEntry;
+ PNPFS_FCB Fcb;
+
+ /*
+ * If no waiting server FCB was found then try to pick
+ * one of the listing server FCB on the pipe.
+ */
+
+ CurrentEntry = Pipe->ServerFcbListHead.Flink;
+ while (CurrentEntry != &Pipe->ServerFcbListHead)
+ {
+ Fcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, FcbListEntry);
+ if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
+ {
+ ServerFcb = Fcb;
+ break;
+ }
+ CurrentEntry = CurrentEntry->Flink;
+ }
+
+ /*
+ * No one is listening to me?! I'm so lonely... :(
+ */
+
+ if (ServerFcb == NULL)
+ {
+ /* Not found, bail out with error for FILE_OPEN requests. */
+ DPRINT("No listening server fcb found!\n");
+ if (ClientFcb->Data)
+ ExFreePool(ClientFcb->Data);
+ KeUnlockMutex(&Pipe->FcbListLock);
+ Irp->IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_PIPE_NOT_AVAILABLE;
+ }
+ }
+ else
+ {
+ /* Signal the server thread and remove it from the waiter list */
+ /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
+ NpfsSignalAndRemoveListeningServerInstance(Pipe, ServerFcb);
+ }
+
+ /*
+ * Step 4. Add the client FCB to a list and connect it if possible.
+ */
+
+ /* Add the client FCB to the pipe FCB list. */
+ InsertTailList(&Pipe->ClientFcbListHead, &ClientFcb->FcbListEntry);
+
+ /* Connect to listening server side */
+ if (ServerFcb)
+ {
+ ClientFcb->OtherSide = ServerFcb;
+ ServerFcb->OtherSide = ClientFcb;
+ ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
+ ServerFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
+ }
+
+ KeUnlockMutex(&Pipe->FcbListLock);
+
+ FileObject->FsContext = ClientFcb;
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ DPRINT("Success!\n");
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS STDCALL
+NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ PEXTENDED_IO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
- NTSTATUS Status;
+ PNPFS_DEVICE_EXTENSION DeviceExt;
PNPFS_PIPE Pipe;
PNPFS_FCB Fcb;
- PNPFS_PIPE current;
- PLIST_ENTRY current_entry;
- PNPFS_DEVICE_EXTENSION DeviceExt;
- KIRQL oldIrql;
-
- DPRINT1("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
-
+ PNAMED_PIPE_CREATE_PARAMETERS Buffer;
+ BOOLEAN NewPipe = FALSE;
+
+ DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
+
DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
- IoStack = IoGetCurrentIrpStackLocation(Irp);
+ 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;
+
Fcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
if (Fcb == NULL)
{
Irp->IoStatus.Status = STATUS_NO_MEMORY;
- Irp->IoStatus.Information = 0;
-
IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return(STATUS_NO_MEMORY);
+ return STATUS_NO_MEMORY;
}
-
+
+ Fcb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
KeLockMutex(&DeviceExt->PipeListLock);
- current_entry = DeviceExt->PipeListHead.Flink;
- while (current_entry != &DeviceExt->PipeListHead)
+
+ /*
+ * First search for existing Pipe with the same name.
+ */
+ Pipe = NpfsFindPipe(DeviceExt,
+ &FileObject->FileName);
+ if (Pipe != NULL)
{
- current = CONTAINING_RECORD(current_entry,
- NPFS_PIPE,
- PipeListEntry);
-
- if (RtlCompareUnicodeString(&Pipe->PipeName,
- ¤t->PipeName,
- TRUE) == 0)
- {
- break;
- }
-
- current_entry = current_entry->Flink;
+ /*
+ * Found Pipe with the same name. Check if we are
+ * allowed to use it.
+ */
+ KeUnlockMutex(&DeviceExt->PipeListLock);
+
+ if (Pipe->CurrentInstances >= Pipe->MaximumInstances)
+ {
+ DPRINT("Out of instances.\n");
+ ExFreePool(Fcb);
+ Irp->IoStatus.Status = STATUS_PIPE_BUSY;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_PIPE_BUSY;
+ }
+
+ /* FIXME: Check pipe modes also! */
+ if (Pipe->MaximumInstances != Buffer->MaximumInstances ||
+ Pipe->TimeOut.QuadPart != Buffer->DefaultTimeout.QuadPart)
+ {
+ DPRINT("Asked for invalid pipe mode.\n");
+ ExFreePool(Fcb);
+ Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_ACCESS_DENIED;
+ }
}
-
- if (current_entry == &DeviceExt->PipeListHead)
+ else
{
- ExFreePool(Fcb);
- KeUnlockMutex(&DeviceExt->PipeListLock);
-
- Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
- Irp->IoStatus.Information = 0;
-
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return(STATUS_UNSUCCESSFUL);
+ NewPipe = TRUE;
+ Pipe = ExAllocatePool(NonPagedPool, sizeof(NPFS_PIPE));
+ if (Pipe == NULL)
+ {
+ KeUnlockMutex(&DeviceExt->PipeListLock);
+ Irp->IoStatus.Status = STATUS_NO_MEMORY;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_NO_MEMORY;
+ }
+
+ Pipe->PipeName.Length = FileObject->FileName.Length;
+ Pipe->PipeName.MaximumLength = Pipe->PipeName.Length + sizeof(UNICODE_NULL);
+ Pipe->PipeName.Buffer = ExAllocatePool(NonPagedPool, Pipe->PipeName.MaximumLength);
+ if (Pipe->PipeName.Buffer == NULL)
+ {
+ KeUnlockMutex(&DeviceExt->PipeListLock);
+ ExFreePool(Pipe);
+ ExFreePool(Fcb);
+ Irp->IoStatus.Status = STATUS_NO_MEMORY;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_NO_MEMORY;
+ }
+
+ RtlCopyUnicodeString(&Pipe->PipeName, &FileObject->FileName);
+
+ InitializeListHead(&Pipe->ServerFcbListHead);
+ InitializeListHead(&Pipe->ClientFcbListHead);
+ InitializeListHead(&Pipe->WaiterListHead);
+ KeInitializeMutex(&Pipe->FcbListLock, 0);
+
+ Pipe->PipeType = Buffer->NamedPipeType;
+ Pipe->WriteMode = Buffer->ReadMode;
+ Pipe->ReadMode = Buffer->ReadMode;
+ Pipe->CompletionMode = Buffer->CompletionMode;
+ Pipe->PipeConfiguration = IoStack->Parameters.CreatePipe.Options & 0x3;
+ Pipe->MaximumInstances = Buffer->MaximumInstances;
+ Pipe->CurrentInstances = 0;
+ Pipe->TimeOut = Buffer->DefaultTimeout;
+ if (!(IoStack->Parameters.CreatePipe.Options & FILE_PIPE_OUTBOUND) ||
+ IoStack->Parameters.CreatePipe.Options & FILE_PIPE_FULL_DUPLEX)
+ {
+ if (Buffer->InboundQuota == 0)
+ {
+ Pipe->InboundQuota = DeviceExt->DefaultQuota;
+ }
+ else
+ {
+ Pipe->InboundQuota = PAGE_ROUND_UP(Buffer->InboundQuota);
+ if (Pipe->InboundQuota < DeviceExt->MinQuota)
+ {
+ Pipe->InboundQuota = DeviceExt->MinQuota;
+ }
+ else if (Pipe->InboundQuota > DeviceExt->MaxQuota)
+ {
+ Pipe->InboundQuota = DeviceExt->MaxQuota;
+ }
+ }
+ }
+ else
+ {
+ Pipe->InboundQuota = 0;
+ }
+
+ if (IoStack->Parameters.CreatePipe.Options & (FILE_PIPE_FULL_DUPLEX|FILE_PIPE_OUTBOUND))
+ {
+ if (Buffer->OutboundQuota == 0)
+ {
+ Pipe->OutboundQuota = DeviceExt->DefaultQuota;
+ }
+ else
+ {
+ Pipe->OutboundQuota = PAGE_ROUND_UP(Buffer->OutboundQuota);
+ if (Pipe->OutboundQuota < DeviceExt->MinQuota)
+ {
+ Pipe->OutboundQuota = DeviceExt->MinQuota;
+ }
+ else if (Pipe->OutboundQuota > DeviceExt->MaxQuota)
+ {
+ Pipe->OutboundQuota = DeviceExt->MaxQuota;
+ }
+ }
+ }
+ else
+ {
+ Pipe->OutboundQuota = 0;
+ }
+
+ InsertTailList(&DeviceExt->PipeListHead, &Pipe->PipeListEntry);
+ KeUnlockMutex(&DeviceExt->PipeListLock);
+ }
+
+ if (Pipe->InboundQuota)
+ {
+ Fcb->Data = ExAllocatePool(PagedPool, Pipe->InboundQuota);
+ if (Fcb->Data == NULL)
+ {
+ ExFreePool(Fcb);
+
+ if (NewPipe)
+ {
+ KeLockMutex(&DeviceExt->PipeListLock);
+ RemoveEntryList(&Pipe->PipeListEntry);
+ KeUnlockMutex(&DeviceExt->PipeListLock);
+ RtlFreeUnicodeString(&Pipe->PipeName);
+ ExFreePool(Pipe);
+ }
+
+ Irp->IoStatus.Status = STATUS_NO_MEMORY;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_NO_MEMORY;
+ }
+ }
+ else
+ {
+ Fcb->Data = NULL;
}
-
- Pipe = current;
-
- KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql);
- InsertTailList(&Pipe->FcbListHead, &Fcb->FcbListEntry);
- KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql);
- Fcb->WriteModeMessage = FALSE;
- Fcb->ReadModeMessage = FALSE;
- Fcb->NonBlocking = FALSE;
- Fcb->InBufferSize = PAGESIZE;
- Fcb->OutBufferSize = PAGESIZE;
+
+ Fcb->ReadPtr = Fcb->Data;
+ Fcb->WritePtr = Fcb->Data;
+ Fcb->ReadDataAvailable = 0;
+ Fcb->WriteQuotaAvailable = Pipe->InboundQuota;
+ Fcb->MaxDataLength = Pipe->InboundQuota;
+ InitializeListHead(&Fcb->ReadRequestListHead);
+ ExInitializeFastMutex(&Fcb->DataListLock);
+
+ Pipe->CurrentInstances++;
+
Fcb->Pipe = Pipe;
- Fcb->IsServer = FALSE;
+ Fcb->PipeEnd = FILE_PIPE_SERVER_END;
+ Fcb->PipeState = FILE_PIPE_LISTENING_STATE;
Fcb->OtherSide = NULL;
-
- Pipe->ReferenceCount++;
-
- /* search for unconnected server fcb */
-
-
- KeUnlockMutex(&DeviceExt->PipeListLock);
-
+
+ DPRINT("Fcb: %x\n", Fcb);
+
+ KeInitializeEvent(&Fcb->ConnectEvent, SynchronizationEvent, FALSE);
+ KeInitializeEvent(&Fcb->ReadEvent, SynchronizationEvent, FALSE);
+ KeInitializeEvent(&Fcb->WriteEvent, SynchronizationEvent, FALSE);
+
+ KeLockMutex(&Pipe->FcbListLock);
+ InsertTailList(&Pipe->ServerFcbListHead, &Fcb->FcbListEntry);
+ KeUnlockMutex(&Pipe->FcbListLock);
+
FileObject->FsContext = Fcb;
-
- Irp->IoStatus.Status = Status;
- Irp->IoStatus.Information = 0;
-
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return(Status);
+
+ DPRINT("Success!\n");
+
+ return STATUS_SUCCESS;
}
NTSTATUS STDCALL
-NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+NpfsCleanup(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
{
+ PNPFS_DEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
- NTSTATUS Status = STATUS_SUCCESS;
- PNPFS_DEVICE_EXTENSION DeviceExt;
+ PNPFS_FCB Fcb, OtherSide;
PNPFS_PIPE Pipe;
- PNPFS_FCB Fcb;
- KIRQL oldIrql;
- PLIST_ENTRY current_entry;
- PNPFS_PIPE current;
- PIO_PIPE_CREATE_BUFFER Buffer;
-
- DPRINT1("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
-
- DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ BOOLEAN Server;
+
+ DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
+
IoStack = IoGetCurrentIrpStackLocation(Irp);
+ DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
FileObject = IoStack->FileObject;
-
- Buffer = (PIO_PIPE_CREATE_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
-
- Pipe = ExAllocatePool(NonPagedPool, sizeof(NPFS_PIPE));
- if (Pipe == NULL)
- {
- Irp->IoStatus.Status = STATUS_NO_MEMORY;
- Irp->IoStatus.Information = 0;
-
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return(STATUS_NO_MEMORY);
- }
-
- Fcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
+ Fcb = FileObject->FsContext;
+
if (Fcb == NULL)
- {
- ExFreePool(Pipe);
-
- Irp->IoStatus.Status = STATUS_NO_MEMORY;
- Irp->IoStatus.Information = 0;
-
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return(STATUS_NO_MEMORY);
- }
-
- if (RtlCreateUnicodeString(&Pipe->PipeName, FileObject->FileName.Buffer) == 0)
- {
- ExFreePool(Pipe);
- ExFreePool(Fcb);
-
- Irp->IoStatus.Status = STATUS_NO_MEMORY;
- Irp->IoStatus.Information = 0;
-
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ {
+ DPRINT("Success!\n");
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+ }
- return(STATUS_NO_MEMORY);
- }
-
- Pipe->ReferenceCount = 0;
- InitializeListHead(&Pipe->FcbListHead);
- KeInitializeSpinLock(&Pipe->FcbListLock);
-
- Pipe->MaxInstances = Buffer->MaxInstances;
- Pipe->TimeOut = Buffer->TimeOut;
-
- KeLockMutex(&DeviceExt->PipeListLock);
- current_entry = DeviceExt->PipeListHead.Flink;
- while (current_entry != &DeviceExt->PipeListHead)
- {
- current = CONTAINING_RECORD(current_entry,
- NPFS_PIPE,
- PipeListEntry);
-
- if (RtlCompareUnicodeString(&Pipe->PipeName, ¤t->PipeName, TRUE) == 0)
- {
- break;
- }
-
- current_entry = current_entry->Flink;
- }
-
- if (current_entry != &DeviceExt->PipeListHead)
- {
- RtlFreeUnicodeString(&Pipe->PipeName);
- ExFreePool(Pipe);
-
- Pipe = current;
- }
+ DPRINT("Fcb %x\n", Fcb);
+ Pipe = Fcb->Pipe;
+
+ DPRINT("Cleaning pipe %wZ\n", &Pipe->PipeName);
+
+ KeLockMutex(&Pipe->FcbListLock);
+
+ Server = (Fcb->PipeEnd == FILE_PIPE_SERVER_END);
+
+ if (Server)
+ {
+ /* FIXME: Clean up existing connections here ?? */
+ DPRINT("Server\n");
+ }
else
- {
- InsertTailList(&DeviceExt->PipeListHead, &Pipe->PipeListEntry);
- }
- Pipe->ReferenceCount++;
-
- KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql);
- InsertTailList(&Pipe->FcbListHead, &Fcb->FcbListEntry);
- KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql);
-
- Fcb->WriteModeMessage = Buffer->WriteModeMessage;
- Fcb->ReadModeMessage = Buffer->ReadModeMessage;
- Fcb->NonBlocking = Buffer->NonBlocking;
- Fcb->InBufferSize = Buffer->InBufferSize;
- Fcb->OutBufferSize = Buffer->OutBufferSize;
-
- Fcb->Pipe = Pipe;
- Fcb->IsServer = TRUE;
- Fcb->OtherSide = NULL;
-
- KeInitializeEvent(&Fcb->ConnectEvent,
- SynchronizationEvent,
- FALSE);
-
- KeUnlockMutex(&DeviceExt->PipeListLock);
-
- FileObject->FsContext = Fcb;
-
- Irp->IoStatus.Status = Status;
+ {
+ DPRINT("Client\n");
+ }
+ if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
+ {
+ OtherSide = Fcb->OtherSide;
+ /* Lock the server first */
+ if (Server)
+ {
+ ExAcquireFastMutex(&Fcb->DataListLock);
+ ExAcquireFastMutex(&OtherSide->DataListLock);
+ }
+ else
+ {
+ ExAcquireFastMutex(&OtherSide->DataListLock);
+ ExAcquireFastMutex(&Fcb->DataListLock);
+ }
+ OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
+ OtherSide->OtherSide = NULL;
+ /*
+ * 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(&Fcb->DataListLock);
+ ExReleaseFastMutex(&OtherSide->DataListLock);
+ }
+ else
+ {
+ ExReleaseFastMutex(&OtherSide->DataListLock);
+ ExReleaseFastMutex(&Fcb->DataListLock);
+ }
+ }
+ else if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
+ {
+ PLIST_ENTRY Entry;
+ PNPFS_WAITER_ENTRY WaitEntry = NULL;
+ BOOLEAN Complete = FALSE;
+ KIRQL oldIrql;
+ PIRP tmpIrp;
+
+ Entry = Fcb->Pipe->WaiterListHead.Flink;
+ while (Entry != &Fcb->Pipe->WaiterListHead)
+ {
+ WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
+ if (WaitEntry->Fcb == Fcb)
+ {
+ RemoveEntryList(Entry);
+ tmpIrp = CONTAINING_RECORD(WaitEntry, IRP, Tail.Overlay.DriverContext);
+ IoAcquireCancelSpinLock(&oldIrql);
+ if (!tmpIrp->Cancel)
+ {
+ IoSetCancelRoutine(tmpIrp, NULL);
+ Complete = TRUE;
+ }
+ IoReleaseCancelSpinLock(oldIrql);
+ if (Complete)
+ {
+ tmpIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
+ tmpIrp->IoStatus.Information = 0;
+ IoCompleteRequest(tmpIrp, IO_NO_INCREMENT);
+ }
+ break;
+ }
+ Entry = Entry->Flink;
+ }
+
+ }
+ Fcb->PipeState = FILE_PIPE_CLOSING_STATE;
+
+ KeUnlockMutex(&Pipe->FcbListLock);
+
+ ExAcquireFastMutex(&Fcb->DataListLock);
+ if (Fcb->Data)
+ {
+ ExFreePool(Fcb->Data);
+ Fcb->Data = NULL;
+ Fcb->ReadPtr = NULL;
+ Fcb->WritePtr = NULL;
+ }
+ ExReleaseFastMutex(&Fcb->DataListLock);
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
-
IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return(Status);
-}
+ DPRINT("Success!\n");
+
+ return STATUS_SUCCESS;
+}
NTSTATUS STDCALL
NpfsClose(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+ PIRP Irp)
{
PNPFS_DEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
PNPFS_FCB Fcb;
PNPFS_PIPE Pipe;
- KIRQL oldIrql;
+ BOOLEAN Server;
DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
IoStack = IoGetCurrentIrpStackLocation(Irp);
DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
FileObject = IoStack->FileObject;
- Fcb = FileObject->FsContext;
+ Fcb = FileObject->FsContext;
+
+ if (Fcb == NULL)
+ {
+ DPRINT("Success!\n");
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+ }
+
+ DPRINT("Fcb %x\n", Fcb);
Pipe = Fcb->Pipe;
DPRINT("Closing pipe %wZ\n", &Pipe->PipeName);
- KeLockMutex(&DeviceExt->PipeListLock);
+ KeLockMutex(&Pipe->FcbListLock);
+
+ Server = (Fcb->PipeEnd == FILE_PIPE_SERVER_END);
- Pipe->ReferenceCount--;
+ if (Server)
+ {
+ DPRINT("Server\n");
+ Pipe->CurrentInstances--;
+ }
+ else
+ {
+ DPRINT("Client\n");
+ }
+
+ ASSERT (Fcb->PipeState == FILE_PIPE_CLOSING_STATE);
+
+ FileObject->FsContext = NULL;
- KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql);
RemoveEntryList(&Fcb->FcbListEntry);
- KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql);
+
ExFreePool(Fcb);
- FileObject->FsContext = NULL;
- if (Pipe->ReferenceCount == 0)
- {
- RtlFreeUnicodeString(&Pipe->PipeName);
- RemoveEntryList(&Pipe->PipeListEntry);
- ExFreePool(Pipe);
- }
+ KeUnlockMutex(&Pipe->FcbListLock);
- KeUnlockMutex(&DeviceExt->PipeListLock);
+ if (IsListEmpty(&Pipe->ServerFcbListHead) &&
+ IsListEmpty(&Pipe->ClientFcbListHead))
+ {
+ RtlFreeUnicodeString(&Pipe->PipeName);
+ KeLockMutex(&DeviceExt->PipeListLock);
+ RemoveEntryList(&Pipe->PipeListEntry);
+ KeUnlockMutex(&DeviceExt->PipeListLock);
+ ExFreePool(Pipe);
+ }
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
-
IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return(STATUS_SUCCESS);
+
+ DPRINT("Success!\n");
+
+ return STATUS_SUCCESS;
}
/* EOF */