/*
-* COPYRIGHT: See COPYING in the top level directory
-* PROJECT: ReactOS kernel
-* FILE: drivers/filesystems/npfs/create.c
-* PURPOSE: Named pipe filesystem
-* PROGRAMMER: David Welch <welch@cwcom.net>
-*/
+ * PROJECT: ReactOS Named Pipe FileSystem
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: drivers/filesystems/npfs/create.c
+ * PURPOSE: Pipes Creation
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
-/* INCLUDES ******************************************************************/
+/* INCLUDES *******************************************************************/
#include "npfs.h"
-#define NDEBUG
-#include <debug.h>
+// File ID number for NPFS bugchecking support
+#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_CREATE)
-//#define USING_PROPER_NPFS_WAIT_SEMANTICS
-
-/* FUNCTIONS *****************************************************************/
+/* FUNCTIONS ******************************************************************/
VOID
-NpfsDereferenceFcb(PNPFS_FCB Fcb)
+NTAPI
+NpCheckForNotify(IN PNP_DCB Dcb,
+ IN BOOLEAN SecondList,
+ IN PLIST_ENTRY List)
{
- PNPFS_VCB Vcb = Fcb->Vcb;
-
- KeLockMutex(&Vcb->PipeListLock);
- if (InterlockedDecrement(&Fcb->RefCount) == 0)
- {
- DPRINT("NpfsDereferenceFcb. Deleting %p\n", Fcb);
- RemoveEntryList(&Fcb->PipeListEntry);
- RtlFreeUnicodeString(&Fcb->PipeName);
- ExFreePoolWithTag(Fcb, TAG_NPFS_FCB);
- }
- KeUnlockMutex(&Vcb->PipeListLock);
-}
-
-static
-PNPFS_CCB
-NpfsAllocateCcb(CCB_TYPE Type, PNPFS_FCB Fcb)
-{
- PNPFS_CCB Ccb;
+ PLIST_ENTRY NextEntry, ListHead;
+ PIRP Irp;
+ ULONG i;
+ PAGED_CODE();
- Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_CCB), TAG_NPFS_CCB);
- if (!Ccb)
+ ListHead = &Dcb->NotifyList;
+ for (i = 0; i < 2; i++)
{
- return NULL;
- }
-
- RtlZeroMemory(Ccb, sizeof(NPFS_CCB));
+ ASSERT(IsListEmpty(ListHead));
+ while (!IsListEmpty(ListHead))
+ {
+ NextEntry = RemoveHeadList(ListHead);
- Ccb->RefCount = 1;
- Ccb->Type = Type;
- // FIXME: why does this function not reference Fcb?
- Ccb->Fcb = Fcb;
- Ccb->OtherSide = NULL;
+ Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
- return Ccb;
-}
-
-static
-VOID
-NpfsReferenceCcb(PNPFS_CCB Ccb)
-{
- ASSERT(Ccb->RefCount > 0);
- InterlockedIncrement(&Ccb->RefCount);
-}
+ if (IoSetCancelRoutine(Irp, NULL))
+ {
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ InsertTailList(List, NextEntry);
+ }
+ else
+ {
+ InitializeListHead(NextEntry);
+ }
+ }
-static
-VOID
-NpfsDereferenceCcb(PNPFS_CCB Ccb)
-{
- /* Decrement reference count */
- ASSERT(Ccb->RefCount > 0);
- if (InterlockedDecrement(&Ccb->RefCount) == 0)
- {
- /* Its zero, delete CCB */
- ExFreePoolWithTag(Ccb, TAG_NPFS_CCB);
+ if (!SecondList) break;
+ ListHead = &Dcb->NotifyList2;
}
}
-static
-VOID
-NpfsCcbSetOtherSide(PNPFS_CCB Ccb, PNPFS_CCB OtherSide)
+IO_STATUS_BLOCK
+NTAPI
+NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject,
+ IN ACCESS_MASK DesiredAccess)
{
- /* Dereference old other side */
- if (Ccb->OtherSide) NpfsDereferenceCcb(Ccb->OtherSide);
+ IO_STATUS_BLOCK Status;
+ PAGED_CODE();
+ TRACE("Entered\n");
- /* Reference the new other side */
- if (OtherSide) NpfsReferenceCcb(OtherSide);
+ NpSetFileObject(FileObject, NpVcb, NULL, FALSE);
+ ++NpVcb->ReferenceCount;
- /* Set new value */
- Ccb->OtherSide = OtherSide;
+ Status.Information = FILE_OPENED;
+ Status.Status = STATUS_SUCCESS;
+ TRACE("Leaving, Status.Status = %lx\n", Status.Status);
+ return Status;
}
-PNPFS_FCB
-NpfsFindPipe(PNPFS_VCB Vcb,
- PUNICODE_STRING PipeName)
+IO_STATUS_BLOCK
+NTAPI
+NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb,
+ IN PFILE_OBJECT FileObject,
+ IN ACCESS_MASK DesiredAccess,
+ IN PLIST_ENTRY List)
{
- PLIST_ENTRY CurrentEntry;
- PNPFS_FCB Fcb;
+ IO_STATUS_BLOCK IoStatus;
+ PNP_ROOT_DCB_FCB Ccb;
+ PAGED_CODE();
+ TRACE("Entered\n");
- CurrentEntry = Vcb->PipeListHead.Flink;
- while (CurrentEntry != &Vcb->PipeListHead)
+ IoStatus.Status = NpCreateRootDcbCcb(&Ccb);
+ if (NT_SUCCESS(IoStatus.Status))
{
- Fcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, PipeListEntry);
- if (RtlCompareUnicodeString(PipeName,
- &Fcb->PipeName,
- TRUE) == 0)
- {
- DPRINT("<%wZ> = <%wZ>\n", PipeName, &Fcb->PipeName);
- (VOID)InterlockedIncrement(&Fcb->RefCount);
- return Fcb;
- }
+ NpSetFileObject(FileObject, Dcb, Ccb, FALSE);
+ ++Dcb->CurrentInstances;
- CurrentEntry = CurrentEntry->Flink;
+ IoStatus.Information = FILE_OPENED;
+ IoStatus.Status = STATUS_SUCCESS;
}
-
- return NULL;
-}
-
-
-static PNPFS_CCB
-NpfsFindListeningServerInstance(PNPFS_FCB Fcb)
-{
- PLIST_ENTRY CurrentEntry;
- PNPFS_WAITER_ENTRY Waiter;
- KIRQL oldIrql;
- PIRP Irp;
-
- CurrentEntry = Fcb->WaiterListHead.Flink;
- while (CurrentEntry != &Fcb->WaiterListHead)
+ else
{
- 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)
- {
- if (IoSetCancelRoutine(Irp, NULL) != NULL)
- {
- IoReleaseCancelSpinLock(oldIrql);
- return Waiter->Ccb;
- }
- }
- IoReleaseCancelSpinLock(oldIrql);
- }
-
- CurrentEntry = CurrentEntry->Flink;
+ IoStatus.Information = 0;
}
- return NULL;
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ return IoStatus;
}
-
-static VOID
-NpfsSignalAndRemoveListeningServerInstance(PNPFS_FCB Fcb,
- PNPFS_CCB Ccb)
+IO_STATUS_BLOCK
+NTAPI
+NpCreateClientEnd(IN PNP_FCB Fcb,
+ IN PFILE_OBJECT FileObject,
+ IN ACCESS_MASK DesiredAccess,
+ IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
+ IN PACCESS_STATE AccessState,
+ IN KPROCESSOR_MODE PreviousMode,
+ IN PETHREAD Thread,
+ IN PLIST_ENTRY List)
{
- 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);
+ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
+ BOOLEAN AccessGranted;
+ ACCESS_MASK GrantedAccess;
+ PPRIVILEGE_SET Privileges;
+ UNICODE_STRING ObjectTypeName;
+ IO_STATUS_BLOCK IoStatus;
+ USHORT NamedPipeConfiguration;
+ PLIST_ENTRY NextEntry, ListHead;
+ PNP_CCB Ccb = NULL;
+ TRACE("Entered\n");
- 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;
- }
-}
+ IoStatus.Information = 0;
+ Privileges = NULL;
+ NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
-static VOID
-NpfsOpenFileSystem(PNPFS_FCB Fcb,
- PFILE_OBJECT FileObject,
- PIO_STATUS_BLOCK IoStatus)
-{
- PNPFS_CCB Ccb;
+ SubjectSecurityContext = &AccessState->SubjectSecurityContext;
+ SeLockSubjectContext(SubjectSecurityContext);
- DPRINT("NpfsOpenFileSystem()\n");
+ AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
+ SubjectSecurityContext,
+ TRUE,
+ DesiredAccess & ~4,
+ 0,
+ &Privileges,
+ IoGetFileObjectGenericMapping(),
+ PreviousMode,
+ &GrantedAccess,
+ &IoStatus.Status);
- Ccb = NpfsAllocateCcb(CCB_DEVICE, Fcb);
- if (Ccb == NULL)
+ if (Privileges)
{
- IoStatus->Status = STATUS_NO_MEMORY;
- return;
+ SeAppendPrivileges(AccessState, Privileges);
+ SeFreePrivileges(Privileges);
}
- Ccb->FileObject = FileObject;
-
- FileObject->FsContext = Fcb;
- FileObject->FsContext2 = Ccb;
+ if (AccessGranted)
+ {
+ AccessState->PreviouslyGrantedAccess |= GrantedAccess;
+ AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
+ }
- IoStatus->Information = FILE_OPENED;
- IoStatus->Status = STATUS_SUCCESS;
+ ObjectTypeName.Buffer = L"NamedPipe";
+ ObjectTypeName.Length = 18;
+ SeOpenObjectAuditAlarm(&ObjectTypeName,
+ NULL,
+ &FileObject->FileName,
+ Fcb->SecurityDescriptor,
+ AccessState,
+ FALSE,
+ AccessGranted,
+ PreviousMode,
+ &AccessState->GenerateOnClose);
+ SeUnlockSubjectContext(SubjectSecurityContext);
+ if (!AccessGranted) return IoStatus;
- return;
-}
+ if (((GrantedAccess & FILE_READ_DATA) && (NamedPipeConfiguration == FILE_PIPE_INBOUND)) ||
+ ((GrantedAccess & FILE_WRITE_DATA) && (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)))
+ {
+ IoStatus.Status = STATUS_ACCESS_DENIED;
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ return IoStatus;
+ }
+ if (!(GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA))) SecurityQos = NULL;
-static VOID
-NpfsOpenRootDirectory(PNPFS_FCB Fcb,
- PFILE_OBJECT FileObject,
- PIO_STATUS_BLOCK IoStatus)
-{
- PNPFS_CCB Ccb;
+ ListHead = &Fcb->CcbList;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry);
+ if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break;
- DPRINT("NpfsOpenRootDirectory()\n");
+ NextEntry = NextEntry->Flink;
+ }
- Ccb = NpfsAllocateCcb(CCB_DIRECTORY, Fcb);
- if (Ccb == NULL)
+ if (NextEntry == ListHead)
{
- IoStatus->Status = STATUS_NO_MEMORY;
- return;
+ IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE;
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ return IoStatus;
}
- Ccb->FileObject = FileObject;
+ IoStatus.Status = NpInitializeSecurity(Ccb, SecurityQos, Thread);
+ if (!NT_SUCCESS(IoStatus.Status)) return IoStatus;
- FileObject->FsContext = Fcb;
- FileObject->FsContext2 = Ccb;
+ IoStatus.Status = NpSetConnectedPipeState(Ccb, FileObject, List);
+ if (!NT_SUCCESS(IoStatus.Status))
+ {
+ NpUninitializeSecurity(Ccb);
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ return IoStatus;
+ }
- IoStatus->Information = FILE_OPENED;
- IoStatus->Status = STATUS_SUCCESS;
+ Ccb->ClientSession = NULL;
+ Ccb->Process = IoThreadToProcess(Thread);
- return;
+ IoStatus.Information = FILE_OPENED;
+ IoStatus.Status = STATUS_SUCCESS;
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ return IoStatus;
}
-
-NTSTATUS NTAPI
-NpfsCreate(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+NTSTATUS
+NTAPI
+NpTranslateAlias(
+ PUNICODE_STRING PipeName)
{
- PEXTENDED_IO_STACK_LOCATION IoStack;
- PUNICODE_STRING FileName;
- PFILE_OBJECT FileObject;
- PFILE_OBJECT RelatedFileObject;
- PNPFS_FCB Fcb;
- PNPFS_CCB ClientCcb;
- PNPFS_CCB ServerCcb = NULL;
- PNPFS_VCB Vcb;
+ WCHAR UpcaseBuffer[MAX_INDEXED_LENGTH + 1];
+ UNICODE_STRING UpcaseString;
+ ULONG Length;
+ PNPFS_ALIAS CurrentAlias;
NTSTATUS Status;
-#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
- ACCESS_MASK DesiredAccess;
- BOOLEAN SpecialAccess;
-#endif
+ BOOLEAN BufferAllocated, BackSlash;
+ LONG Result;
+ PAGED_CODE();
- DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
-
- Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
- IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
- FileObject = IoStack->FileObject;
- RelatedFileObject = FileObject->RelatedFileObject;
- FileName = &FileObject->FileName;
-#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
- DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
-#endif
-
- DPRINT("FileObject %p\n", FileObject);
- DPRINT("FileName %wZ\n", &FileObject->FileName);
-
- Irp->IoStatus.Information = 0;
-
-#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
- SpecialAccess = ((DesiredAccess & SPECIFIC_RIGHTS_ALL) == FILE_READ_ATTRIBUTES);
- if (SpecialAccess)
+ /* Get the pipe name length and check for empty string */
+ Length = PipeName->Length;
+ if (Length == 0)
{
- DPRINT("NpfsCreate() open client end for special use!\n");
+ return STATUS_SUCCESS;
}
-#endif
-
- 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))
+ /* Check if the name starts with a path separator */
+ BackSlash = (PipeName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR);
+ if (BackSlash)
{
- DPRINT("Open the file system\n");
-
- NpfsOpenFileSystem(Vcb->DeviceFcb,
- FileObject,
- &Irp->IoStatus);
-
- Status = Irp->IoStatus.Status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return Status;
+ /* We are only interested in the part after the backslash */
+ Length -= sizeof(WCHAR);
}
- /* Open the root directory */
- if ((FileName->Length == 2 && FileName->Buffer[0] == L'\\' && RelatedFileObject == NULL) ||
- (FileName->Length == 0 && ((PNPFS_CCB)RelatedFileObject->FsContext2)->Type == CCB_DIRECTORY))
+ /* Check if the length is within our indexed list bounds */
+ if ((Length >= MIN_INDEXED_LENGTH * sizeof(WCHAR)) &&
+ (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR)))
{
- DPRINT("Open the root directory\n");
-
- NpfsOpenRootDirectory(Vcb->RootFcb,
- FileObject,
- &Irp->IoStatus);
-
- Status = Irp->IoStatus.Status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return Status;
+ /* Length is within bounds, use the list by length */
+ CurrentAlias = NpAliasListByLength[(Length / sizeof(WCHAR)) - MIN_INDEXED_LENGTH];
}
-
-
- /*
- * Step 1. Find the pipe we're trying to open.
- */
- KeLockMutex(&Vcb->PipeListLock);
- Fcb = NpfsFindPipe(Vcb, &FileObject->FileName);
- if (Fcb == NULL)
+ else
{
- /* Not found, bail out with error. */
- DPRINT("No pipe found!\n");
- KeUnlockMutex(&Vcb->PipeListLock);
- Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_OBJECT_NAME_NOT_FOUND;
- }
-
- KeUnlockMutex(&Vcb->PipeListLock);
+ /* We use the generic list, search for an entry of the right size */
+ CurrentAlias = NpAliasList;
+ while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length != Length))
+ {
+ /* Check if we went past the desired length */
+ if (CurrentAlias->Name.Length > Length)
+ {
+ /* In this case there is no matching alias, return success */
+ return STATUS_SUCCESS;
+ }
- /*
- * 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);
+ /* Go to the next alias in the list */
+ CurrentAlias = CurrentAlias->Next;
+ }
+ }
- /*
- * Step 2. Create the client CCB.
- */
- ClientCcb = NpfsAllocateCcb(CCB_PIPE, Fcb);
- if (ClientCcb == NULL)
+ /* Did we find any alias? */
+ if (CurrentAlias == NULL)
{
- DPRINT("No memory!\n");
- KeUnlockMutex(&Fcb->CcbListLock);
- NpfsDereferenceFcb(Fcb);
- Irp->IoStatus.Status = STATUS_NO_MEMORY;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_NO_MEMORY;
+ /* Nothing found, no matching alias */
+ return STATUS_SUCCESS;
}
- ClientCcb->FileObject = FileObject;
- ClientCcb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
- ClientCcb->PipeEnd = FILE_PIPE_CLIENT_END;
-#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
- ClientCcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE;
-#else
- ClientCcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
-#endif
- InitializeListHead(&ClientCcb->ReadRequestListHead);
-
- DPRINT("CCB: %p\n", ClientCcb);
+ /* Check whether we can use our stack buffer */
+ if (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR))
+ {
+ /* Initialize the upcased string */
+ UpcaseString.Buffer = UpcaseBuffer;
+ UpcaseString.MaximumLength = sizeof(UpcaseBuffer);
- /* Initialize data list. */
- if (Fcb->OutboundQuota)
+ /* Upcase the pipe name */
+ Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, FALSE);
+ NT_ASSERT(NT_SUCCESS(Status));
+ BufferAllocated = FALSE;
+ }
+ else
{
- ClientCcb->Data = ExAllocatePoolWithTag(PagedPool,
- Fcb->OutboundQuota,
- TAG_NPFS_CCB_DATA);
- if (ClientCcb->Data == NULL)
+ /* Upcase the pipe name, allocate the string buffer */
+ Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, TRUE);
+ if (!NT_SUCCESS(Status))
{
- 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;
+ return Status;
}
+
+ BufferAllocated = TRUE;
}
- else
+
+ /* Did the original name start with a backslash? */
+ if (BackSlash)
{
- ClientCcb->Data = NULL;
+ /* Skip it for the comparison */
+ UpcaseString.Buffer++;
+ UpcaseString.Length -= sizeof(WCHAR);
}
- 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);
- KeInitializeEvent(&ClientCcb->ReadEvent, NotificationEvent, FALSE);
- KeInitializeEvent(&ClientCcb->WriteEvent, NotificationEvent, FALSE);
+ /* Make sure the length matches the "raw" length */
+ NT_ASSERT(UpcaseString.Length == Length);
+ NT_ASSERT(CurrentAlias->Name.Length == Length);
-
- /*
- * Step 3. Search for listening server CCB.
- */
-#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
- if (!SpecialAccess)
+ /* Loop while we have aliases */
+ do
{
-#endif
- /*
- * 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)
+ /* Compare the names and check if they match */
+ Result = NpCompareAliasNames(&UpcaseString, &CurrentAlias->Name);
+ if (Result == 0)
{
- 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;
- }
+ /* The names match, use the target name */
+ *PipeName = *CurrentAlias->TargetName;
- /*
- * No one is listening to me?! I'm so lonely... :(
- */
-
- if (ServerCcb == NULL)
+ /* Did the original name start with a backslash? */
+ if (!BackSlash)
{
- /* Not found, bail out with error for FILE_OPEN requests. */
- DPRINT("No listening server CCB found!\n");
- if (ClientCcb->Data)
- {
- ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA);
- }
-
- NpfsDereferenceCcb(ClientCcb);
- KeUnlockMutex(&Fcb->CcbListLock);
- NpfsDereferenceFcb(Fcb);
- Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_OBJECT_NAME_NOT_FOUND;
+ /* It didn't, so skip it in the target name as well */
+ PipeName->Buffer++;
+ PipeName->Length -= sizeof(WCHAR);
}
+ break;
}
- else
- {
- /* Signal the server thread and remove it from the waiter list */
- /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
- NpfsSignalAndRemoveListeningServerInstance(Fcb, ServerCcb);
- }
-#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
- }
- else if (IsListEmpty(&Fcb->ServerCcbListHead))
- {
- DPRINT("No server fcb found!\n");
- if (ClientCcb->Data)
+ /* Check if we went past all string candidates */
+ if (Result < 0)
{
- ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA);
+ /* Nothing found, we're done */
+ break;
}
- NpfsDereferenceCcb(ClientCcb);
- KeUnlockMutex(&Fcb->CcbListLock);
- NpfsDereferenceFcb(Fcb);
- Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_UNSUCCESSFUL;
- }
-#endif
-
- /*
- * Step 4. Add the client CCB to a list and connect it if possible.
- */
+ /* Go to the next alias */
+ CurrentAlias = CurrentAlias->Next;
- /* Add the client CCB to the pipe CCB list. */
- InsertTailList(&Fcb->ClientCcbListHead, &ClientCcb->CcbListEntry);
+ /* Keep looping while we have aliases of the right length */
+ } while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length == Length));
- /* Connect to listening server side */
- if (ServerCcb)
+ /* Did we allocate a buffer? */
+ if (BufferAllocated)
{
- NpfsCcbSetOtherSide(ClientCcb, ServerCcb);
- NpfsCcbSetOtherSide(ServerCcb, ClientCcb);
- ClientCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
- ServerCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
- KeSetEvent(&ServerCcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
+ /* Free the allocated buffer */
+ ASSERT(UpcaseString.Buffer != UpcaseBuffer);
+ RtlFreeUnicodeString(&UpcaseString);
}
- 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;
}
-
-NTSTATUS NTAPI
-NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+NTSTATUS
+NTAPI
+NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
- PEXTENDED_IO_STACK_LOCATION IoStack;
+ IO_STATUS_BLOCK IoStatus;
+ PIO_STACK_LOCATION IoStack;
+ UNICODE_STRING FileName;
PFILE_OBJECT FileObject;
- PNPFS_VCB Vcb;
- PNPFS_FCB Fcb;
- PNPFS_CCB Ccb;
- PNAMED_PIPE_CREATE_PARAMETERS Buffer;
-
- DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
+ PFILE_OBJECT RelatedFileObject;
+ NODE_TYPE_CODE Type;
+ PNP_CCB Ccb;
+ PNP_FCB Fcb;
+ PNP_DCB Dcb;
+ ACCESS_MASK DesiredAccess;
+ LIST_ENTRY DeferredList;
+ UNICODE_STRING Prefix;
+ TRACE("Entered\n");
- Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
- IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
+ InitializeListHead(&DeferredList);
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
FileObject = IoStack->FileObject;
- DPRINT("FileObject %p\n", FileObject);
- DPRINT("Pipe name %wZ\n", &FileObject->FileName);
+ RelatedFileObject = FileObject->RelatedFileObject;
+ FileName = FileObject->FileName;
+ DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
- Buffer = IoStack->Parameters.CreatePipe.Parameters;
+ IoStatus.Information = 0;
- Irp->IoStatus.Information = 0;
+ FsRtlEnterFileSystem();
+ NpAcquireExclusiveVcb();
- if (!(IoStack->Parameters.CreatePipe.ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE)) ||
- (IoStack->Parameters.CreatePipe.ShareAccess & ~(FILE_SHARE_READ|FILE_SHARE_WRITE)))
+ if (RelatedFileObject)
{
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_INVALID_PARAMETER;
+ Type = NpDecodeFileObject(RelatedFileObject, (PVOID*)&Fcb, &Ccb, FALSE);
}
-
- KeLockMutex(&Vcb->PipeListLock);
-
- /*
- * First search for existing Pipe with the same name.
- */
- Fcb = NpfsFindPipe(Vcb, &FileObject->FileName);
- if (Fcb != NULL)
+ else
{
- /*
- * Found Pipe with the same name. Check if we are
- * allowed to use it.
- */
- KeUnlockMutex(&Vcb->PipeListLock);
-
- 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;
- }
+ Type = 0;
+ Fcb = NULL;
+ Ccb = NULL;
+ }
- if (Fcb->MaximumInstances != Buffer->MaximumInstances ||
- Fcb->TimeOut.QuadPart != Buffer->DefaultTimeout.QuadPart ||
- Fcb->PipeType != Buffer->NamedPipeType)
+ if (FileName.Length)
+ {
+ if ((FileName.Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) &&
+ (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
+ !(RelatedFileObject))
{
- DPRINT("Asked for invalid pipe mode.\n");
- NpfsDereferenceFcb(Fcb);
- Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_ACCESS_DENIED;
+ IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
+ FileObject,
+ DesiredAccess,
+ &DeferredList);
+ goto Quickie;
}
}
- else
+ else if (!(RelatedFileObject) || (Type == NPFS_NTC_VCB))
{
- Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_FCB), TAG_NPFS_FCB);
- if (Fcb == NULL)
- {
- KeUnlockMutex(&Vcb->PipeListLock);
- Irp->IoStatus.Status = STATUS_NO_MEMORY;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_NO_MEMORY;
- }
-
- Fcb->Type = FCB_PIPE;
- Fcb->Vcb = Vcb;
- Fcb->RefCount = 1;
- Fcb->PipeName.Length = FileObject->FileName.Length;
- Fcb->PipeName.MaximumLength = Fcb->PipeName.Length + sizeof(UNICODE_NULL);
- Fcb->PipeName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
- Fcb->PipeName.MaximumLength,
- TAG_NPFS_NAMEBLOCK);
- if (Fcb->PipeName.Buffer == NULL)
- {
- KeUnlockMutex(&Vcb->PipeListLock);
- ExFreePoolWithTag(Fcb, TAG_NPFS_FCB);
- 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);
+ IoStatus = NpOpenNamedPipeFileSystem(FileObject,
+ DesiredAccess);
+ goto Quickie;
+ }
+ else if (Type == NPFS_NTC_ROOT_DCB)
+ {
+ IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
+ FileObject,
+ DesiredAccess,
+ &DeferredList);
+ goto Quickie;
+ }
- 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;
+ IoStatus.Status = NpTranslateAlias(&FileName);
+ if (!NT_SUCCESS(IoStatus.Status)) goto Quickie;
- 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 (RelatedFileObject)
+ {
+ if (Type == NPFS_NTC_ROOT_DCB)
{
- if (Buffer->InboundQuota == 0)
+ Dcb = (PNP_DCB)Ccb;
+ IoStatus.Status = NpFindRelativePrefix(Dcb,
+ &FileName,
+ 1,
+ &Prefix,
+ &Fcb);
+ if (!NT_SUCCESS(IoStatus.Status))
{
- Fcb->InboundQuota = Vcb->DefaultQuota;
- }
- else
- {
- Fcb->InboundQuota = PAGE_ROUND_UP(Buffer->InboundQuota);
- if (Fcb->InboundQuota < Vcb->MinQuota)
- {
- Fcb->InboundQuota = Vcb->MinQuota;
- }
- else if (Fcb->InboundQuota > Vcb->MaxQuota)
- {
- Fcb->InboundQuota = Vcb->MaxQuota;
- }
+ goto Quickie;
}
}
- else
+ else if ((Type != NPFS_NTC_CCB) || (FileName.Length))
{
- Fcb->InboundQuota = 0;
+ IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
+ goto Quickie;
}
-
- if (Fcb->PipeConfiguration & (FILE_PIPE_FULL_DUPLEX|FILE_PIPE_OUTBOUND))
+ else
{
- if (Buffer->OutboundQuota == 0)
- {
- Fcb->OutboundQuota = Vcb->DefaultQuota;
- }
- else
- {
- Fcb->OutboundQuota = PAGE_ROUND_UP(Buffer->OutboundQuota);
- if (Fcb->OutboundQuota < Vcb->MinQuota)
- {
- Fcb->OutboundQuota = Vcb->MinQuota;
- }
- else if (Fcb->OutboundQuota > Vcb->MaxQuota)
- {
- Fcb->OutboundQuota = Vcb->MaxQuota;
- }
- }
+ Prefix.Length = 0;
}
- else
+ }
+ else
+ {
+ if ((FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR)) ||
+ (FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
{
- Fcb->OutboundQuota = 0;
+ IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
+ goto Quickie;
}
- InsertTailList(&Vcb->PipeListHead, &Fcb->PipeListEntry);
- KeUnlockMutex(&Vcb->PipeListLock);
+ Fcb = NpFindPrefix(&FileName, 1, &Prefix);
}
- Ccb = NpfsAllocateCcb(CCB_PIPE, Fcb);
- if (Ccb == NULL)
+ if (Prefix.Length)
{
- NpfsDereferenceFcb(Fcb);
- Irp->IoStatus.Status = STATUS_NO_MEMORY;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_NO_MEMORY;
+ IoStatus.Status = Fcb->NodeType != NPFS_NTC_FCB ?
+ STATUS_OBJECT_NAME_NOT_FOUND :
+ STATUS_OBJECT_NAME_INVALID;
+ goto Quickie;
}
- Ccb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
-
- if (Fcb->InboundQuota)
+ if (Fcb->NodeType != NPFS_NTC_FCB)
{
- Ccb->Data = ExAllocatePoolWithTag(PagedPool,
- Fcb->InboundQuota,
- TAG_NPFS_CCB_DATA);
- if (Ccb->Data == NULL)
- {
- NpfsDereferenceCcb(Ccb);
- NpfsDereferenceFcb(Fcb);
-
- Irp->IoStatus.Status = STATUS_NO_MEMORY;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_NO_MEMORY;
- }
+ IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
+ goto Quickie;
}
- else
+
+ if (!Fcb->ServerOpenCount)
{
- Ccb->Data = NULL;
+ IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ goto Quickie;
}
- 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);
+ IoStatus = NpCreateClientEnd(Fcb,
+ FileObject,
+ DesiredAccess,
+ IoStack->Parameters.CreatePipe.
+ SecurityContext->SecurityQos,
+ IoStack->Parameters.CreatePipe.
+ SecurityContext->AccessState,
+ IoStack->Flags &
+ SL_FORCE_ACCESS_CHECK ?
+ UserMode : Irp->RequestorMode,
+ Irp->Tail.Overlay.Thread,
+ &DeferredList);
- Fcb->CurrentInstances++;
+Quickie:
+ NpReleaseVcb();
+ NpCompleteDeferredIrps(&DeferredList);
+ FsRtlExitFileSystem();
- Ccb->Fcb = Fcb;
- Ccb->FileObject = FileObject;
- Ccb->PipeEnd = FILE_PIPE_SERVER_END;
- Ccb->PipeState = FILE_PIPE_LISTENING_STATE;
+ Irp->IoStatus = IoStatus;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ return IoStatus.Status;
+}
- DPRINT("CCB: %p\n", Ccb);
+IO_STATUS_BLOCK
+NTAPI
+NpCreateExistingNamedPipe(IN PNP_FCB Fcb,
+ IN PFILE_OBJECT FileObject,
+ IN ACCESS_MASK DesiredAccess,
+ IN PACCESS_STATE AccessState,
+ IN KPROCESSOR_MODE PreviousMode,
+ IN ULONG Disposition,
+ IN ULONG ShareAccess,
+ IN PNAMED_PIPE_CREATE_PARAMETERS Parameters,
+ IN PEPROCESS Process,
+ OUT PLIST_ENTRY List)
+{
+ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
+ IO_STATUS_BLOCK IoStatus;
+ UNICODE_STRING ObjectTypeName;
+ ACCESS_MASK GrantedAccess;
+ PNP_CCB Ccb;
+ PPRIVILEGE_SET Privileges;
+ USHORT NamedPipeConfiguration, CheckShareAccess;
+ BOOLEAN AccessGranted;
+ PAGED_CODE();
+ TRACE("Entered\n");
- KeInitializeEvent(&Ccb->ConnectEvent, SynchronizationEvent, FALSE);
- KeInitializeEvent(&Ccb->ReadEvent, NotificationEvent, FALSE);
- KeInitializeEvent(&Ccb->WriteEvent, NotificationEvent, FALSE);
+ Privileges = NULL;
- KeLockMutex(&Fcb->CcbListLock);
- InsertTailList(&Fcb->ServerCcbListHead, &Ccb->CcbListEntry);
- KeUnlockMutex(&Fcb->CcbListLock);
+ NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
- FileObject->FsContext = Fcb;
- FileObject->FsContext2 = Ccb;
- FileObject->Flags |= FO_NAMED_PIPE;
+ SubjectSecurityContext = &AccessState->SubjectSecurityContext;
+ SeLockSubjectContext(SubjectSecurityContext);
- Irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ IoStatus.Information = 0;
- DPRINT("Success!\n");
+ AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
+ SubjectSecurityContext,
+ TRUE,
+ DesiredAccess | 4,
+ 0,
+ &Privileges,
+ IoGetFileObjectGenericMapping(),
+ PreviousMode,
+ &GrantedAccess,
+ &IoStatus.Status);
- return STATUS_SUCCESS;
-}
+ if (Privileges)
+ {
+ SeAppendPrivileges(AccessState, Privileges);
+ SeFreePrivileges(Privileges);
+ }
+ if (AccessGranted)
+ {
+ AccessState->PreviouslyGrantedAccess |= GrantedAccess;
+ AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
+ }
-NTSTATUS NTAPI
-NpfsCleanup(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
-{
- //PNPFS_VCB Vcb;
- PIO_STACK_LOCATION IoStack;
- PFILE_OBJECT FileObject;
- PNPFS_CCB Ccb, OtherSide;
- PNPFS_FCB Fcb;
- BOOLEAN Server;
+ ObjectTypeName.Buffer = L"NamedPipe";
+ ObjectTypeName.Length = 18;
+ SeOpenObjectAuditAlarm(&ObjectTypeName,
+ NULL,
+ &FileObject->FileName,
+ Fcb->SecurityDescriptor,
+ AccessState,
+ FALSE,
+ AccessGranted,
+ PreviousMode,
+ &AccessState->GenerateOnClose);
- DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
+ SeUnlockSubjectContext(SubjectSecurityContext);
+ if (!AccessGranted)
+ {
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ return IoStatus;
+ }
- IoStack = IoGetCurrentIrpStackLocation(Irp);
- //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
- FileObject = IoStack->FileObject;
- Ccb = FileObject->FsContext2;
+ if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
+ {
+ IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE;
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ return IoStatus;
+ }
- if (Ccb == NULL)
+ if (Disposition == FILE_CREATE)
{
- DPRINT("Success!\n");
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
+ IoStatus.Status = STATUS_ACCESS_DENIED;
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ return IoStatus;
}
- if (Ccb->Type == CCB_DEVICE)
+ CheckShareAccess = 0;
+ if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX)
{
- DPRINT("Cleanup the file system!\n");
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
+ CheckShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ }
+ else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)
+ {
+ CheckShareAccess = FILE_SHARE_READ;
+ }
+ else if (NamedPipeConfiguration == FILE_PIPE_INBOUND)
+ {
+ CheckShareAccess = FILE_SHARE_WRITE;
}
- if (Ccb->Type == CCB_DIRECTORY)
+ if (CheckShareAccess != ShareAccess)
{
- DPRINT("Cleanup the root directory!\n");
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
+ IoStatus.Status = STATUS_ACCESS_DENIED;
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ return IoStatus;
}
- DPRINT("CCB %p\n", Ccb);
- Fcb = Ccb->Fcb;
+ IoStatus.Status = NpCreateCcb(Fcb,
+ FileObject,
+ FILE_PIPE_LISTENING_STATE,
+ Parameters->ReadMode & 0xFF,
+ Parameters->CompletionMode & 0xFF,
+ Parameters->InboundQuota,
+ Parameters->OutboundQuota,
+ &Ccb);
+ if (!NT_SUCCESS(IoStatus.Status)) return IoStatus;
- DPRINT("Cleaning pipe %wZ\n", &Fcb->PipeName);
+ IoStatus.Status = NpCancelWaiter(&NpVcb->WaitQueue,
+ &Fcb->FullName,
+ FALSE,
+ List);
+ if (!NT_SUCCESS(IoStatus.Status))
+ {
+ --Ccb->Fcb->CurrentInstances;
+ NpDeleteCcb(Ccb, List);
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ return IoStatus;
+ }
- KeLockMutex(&Fcb->CcbListLock);
+ NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
+ Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
+ NpCheckForNotify(Fcb->ParentDcb, 0, List);
- Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END);
+ IoStatus.Status = STATUS_SUCCESS;
+ IoStatus.Information = FILE_OPENED;
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ return IoStatus;
+}
- if (Server)
+NTSTATUS
+NTAPI
+NpCreateNewNamedPipe(IN PNP_DCB Dcb,
+ IN PFILE_OBJECT FileObject,
+ IN UNICODE_STRING PipeName,
+ IN ACCESS_MASK DesiredAccess,
+ IN PACCESS_STATE AccessState,
+ IN USHORT Disposition,
+ IN USHORT ShareAccess,
+ IN PNAMED_PIPE_CREATE_PARAMETERS Parameters,
+ IN PEPROCESS Process,
+ IN PLIST_ENTRY List,
+ OUT PIO_STATUS_BLOCK IoStatus)
+{
+ NTSTATUS Status;
+ USHORT NamedPipeConfiguration;
+ PSECURITY_SUBJECT_CONTEXT SecurityContext;
+ PSECURITY_DESCRIPTOR SecurityDescriptor, CachedSecurityDescriptor;
+ PNP_CCB Ccb;
+ PNP_FCB Fcb;
+ PAGED_CODE();
+ TRACE("Entered\n");
+
+ if (!(Parameters->TimeoutSpecified) ||
+ !(Parameters->MaximumInstances) ||
+ (Parameters->DefaultTimeout.QuadPart >= 0))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quickie;
+ }
+
+ if (Disposition == FILE_OPEN)
{
- /* FIXME: Clean up existing connections here ?? */
- DPRINT("Server\n");
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ goto Quickie;
+ }
+
+ if (ShareAccess == (FILE_SHARE_READ | FILE_SHARE_WRITE))
+ {
+ NamedPipeConfiguration = FILE_PIPE_FULL_DUPLEX;
+ }
+ else if (ShareAccess == FILE_SHARE_READ)
+ {
+ NamedPipeConfiguration = FILE_PIPE_OUTBOUND;
+ }
+ else if (ShareAccess == FILE_SHARE_WRITE)
+ {
+ NamedPipeConfiguration = FILE_PIPE_INBOUND;
}
else
{
- DPRINT("Client\n");
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quickie;
}
- if ((Ccb->PipeState == FILE_PIPE_CONNECTED_STATE) && (Ccb->OtherSide))
+
+ if (Parameters->NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE &&
+ Parameters->ReadMode == FILE_PIPE_MESSAGE_MODE)
{
- OtherSide = Ccb->OtherSide;
- ASSERT(OtherSide->OtherSide == Ccb);
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quickie;
+ }
- /* Lock the server first */
- if (Server)
- {
- ExAcquireFastMutex(&Ccb->DataListLock);
- ExAcquireFastMutex(&OtherSide->DataListLock);
- }
- else
- {
- ExAcquireFastMutex(&OtherSide->DataListLock);
- ExAcquireFastMutex(&Ccb->DataListLock);
- }
+ Status = NpCreateFcb(Dcb,
+ &PipeName,
+ Parameters->MaximumInstances,
+ Parameters->DefaultTimeout,
+ NamedPipeConfiguration,
+ Parameters->NamedPipeType & 0xFFFF,
+ &Fcb);
+ if (!NT_SUCCESS(Status)) goto Quickie;
- /* Unlink FCBs */
- NpfsCcbSetOtherSide(OtherSide, NULL);
- NpfsCcbSetOtherSide(Ccb, 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(&OtherSide->DataListLock);
- ExReleaseFastMutex(&Ccb->DataListLock);
- }
- else
- {
- ExReleaseFastMutex(&Ccb->DataListLock);
- ExReleaseFastMutex(&OtherSide->DataListLock);
- }
- }
- else if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
+ Status = NpCreateCcb(Fcb,
+ FileObject,
+ FILE_PIPE_LISTENING_STATE,
+ Parameters->ReadMode & 0xFF,
+ Parameters->CompletionMode & 0xFF,
+ Parameters->InboundQuota,
+ Parameters->OutboundQuota,
+ &Ccb);
+ if (!NT_SUCCESS(Status))
{
- PLIST_ENTRY Entry;
- PNPFS_WAITER_ENTRY WaitEntry = NULL;
- BOOLEAN Complete = FALSE;
- KIRQL oldIrql;
- PIRP tmpIrp;
+ NpDeleteFcb(Fcb, List);
+ goto Quickie;
+ }
- 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);
- Complete = (NULL != IoSetCancelRoutine(tmpIrp, NULL));
- IoReleaseCancelSpinLock(oldIrql);
- if (Complete)
- {
- tmpIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
- tmpIrp->IoStatus.Information = 0;
- IoCompleteRequest(tmpIrp, IO_NO_INCREMENT);
- }
- break;
- }
- Entry = Entry->Flink;
- }
+ SecurityContext = &AccessState->SubjectSecurityContext;
+ SeLockSubjectContext(SecurityContext);
+ Status = SeAssignSecurity(NULL,
+ AccessState->SecurityDescriptor,
+ &SecurityDescriptor,
+ FALSE,
+ SecurityContext,
+ IoGetFileObjectGenericMapping(),
+ PagedPool);
+ SeUnlockSubjectContext(SecurityContext);
+ if (!NT_SUCCESS(Status))
+ {
+ NpDeleteCcb(Ccb, List);
+ NpDeleteFcb(Fcb, List);
+ goto Quickie;
}
- Ccb->PipeState = FILE_PIPE_CLOSING_STATE;
- KeUnlockMutex(&Fcb->CcbListLock);
+ Status = ObLogSecurityDescriptor(SecurityDescriptor,
+ &CachedSecurityDescriptor,
+ 1);
+ ExFreePoolWithTag(SecurityDescriptor, 0);
- ExAcquireFastMutex(&Ccb->DataListLock);
- if (Ccb->Data)
+ if (!NT_SUCCESS(Status))
{
- ExFreePoolWithTag(Ccb->Data, TAG_NPFS_CCB_DATA);
- Ccb->Data = NULL;
- Ccb->ReadPtr = NULL;
- Ccb->WritePtr = NULL;
+ NpDeleteCcb(Ccb, List);
+ NpDeleteFcb(Fcb, List);
+ goto Quickie;
}
- ExReleaseFastMutex(&Ccb->DataListLock);
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ Fcb->SecurityDescriptor = CachedSecurityDescriptor;
- DPRINT("Success!\n");
+ NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
+ Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
+ NpCheckForNotify(Dcb, TRUE, List);
+
+ IoStatus->Status = STATUS_SUCCESS;
+ IoStatus->Information = FILE_CREATED;
+
+ TRACE("Leaving, STATUS_SUCCESS\n");
return STATUS_SUCCESS;
+
+Quickie:
+ TRACE("Leaving, Status = %lx\n", Status);
+ IoStatus->Information = 0;
+ IoStatus->Status = Status;
+ return Status;
}
-NTSTATUS NTAPI
-NpfsClose(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+NTSTATUS
+NTAPI
+NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
- //PNPFS_VCB Vcb;
- PNPFS_FCB Fcb;
- PNPFS_CCB Ccb;
- BOOLEAN Server;
-
- DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
+ PFILE_OBJECT RelatedFileObject;
+ USHORT Disposition, ShareAccess;
+ PEPROCESS Process;
+ LIST_ENTRY DeferredList;
+ UNICODE_STRING FileName;
+ PNP_FCB Fcb;
+ UNICODE_STRING Prefix;
+ PNAMED_PIPE_CREATE_PARAMETERS Parameters;
+ IO_STATUS_BLOCK IoStatus;
+ TRACE("Entered\n");
+
+ InitializeListHead(&DeferredList);
+ Process = IoGetRequestorProcess(Irp);
IoStack = IoGetCurrentIrpStackLocation(Irp);
- //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
FileObject = IoStack->FileObject;
- Ccb = FileObject->FsContext2;
+ RelatedFileObject = FileObject->RelatedFileObject;
- if (Ccb == NULL)
- {
- DPRINT("Success!\n");
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
- }
+ Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF;
+ ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess & 0xFFFF;
+ Parameters = IoStack->Parameters.CreatePipe.Parameters;
- if (Ccb->Type == CCB_DEVICE)
- {
- DPRINT("Closing the file system!\n");
+ FileName = FileObject->FileName;
- NpfsDereferenceCcb(Ccb);
- FileObject->FsContext = NULL;
- FileObject->FsContext2 = NULL;
+ IoStatus.Information = 0;
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
- }
+ FsRtlEnterFileSystem();
+ NpAcquireExclusiveVcb();
- if (Ccb->Type == CCB_DIRECTORY)
+ if (RelatedFileObject)
{
- DPRINT("Closing the root directory!\n");
-
- if (Ccb->u.Directory.SearchPattern.Buffer != NULL)
- ExFreePoolWithTag(Ccb->u.Directory.SearchPattern.Buffer,
- TAG_NPFS_NAMEBLOCK);
-
- NpfsDereferenceCcb(Ccb);
- FileObject->FsContext = NULL;
- FileObject->FsContext2 = NULL;
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
- }
-
- DPRINT("CCB %p\n", Ccb);
- Fcb = Ccb->Fcb;
-
- DPRINT("Closing pipe %wZ\n", &Fcb->PipeName);
-
- KeLockMutex(&Fcb->CcbListLock);
-
- Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END);
+ Fcb = (PNP_FCB)((ULONG_PTR)RelatedFileObject->FsContext & ~1);
+ if (!(Fcb) ||
+ (Fcb->NodeType != NPFS_NTC_ROOT_DCB) ||
+ (FileName.Length < sizeof(WCHAR)) ||
+ (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
+ {
+ IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
+ goto Quickie;
+ }
- if (Server)
- {
- DPRINT("Server\n");
- Fcb->CurrentInstances--;
+ IoStatus.Status = NpFindRelativePrefix(RelatedFileObject->FsContext,
+ &FileName,
+ TRUE,
+ &Prefix,
+ &Fcb);
+ if (!NT_SUCCESS(IoStatus.Status))
+ {
+ goto Quickie;
+ }
}
else
{
- DPRINT("Client\n");
+ if (FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR) ||
+ FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
+ {
+ IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
+ goto Quickie;
+ }
+
+ Fcb = NpFindPrefix(&FileName, 1, &Prefix);
}
- /* Disconnect the pipes */
- if (Ccb->OtherSide)
+ if (Prefix.Length)
{
- /* FIXME: Timo wants it rewritten */
- /*ASSERT(Ccb->OtherSide->OtherSide == Ccb);*/
- NpfsCcbSetOtherSide(Ccb->OtherSide, NULL);
- NpfsCcbSetOtherSide(Ccb, NULL);
+ if (Fcb->NodeType == NPFS_NTC_ROOT_DCB)
+ {
+ IoStatus.Status = NpCreateNewNamedPipe((PNP_DCB)Fcb,
+ FileObject,
+ FileName,
+ IoStack->Parameters.CreatePipe.
+ SecurityContext->DesiredAccess,
+ IoStack->Parameters.CreatePipe.
+ SecurityContext->AccessState,
+ Disposition,
+ ShareAccess,
+ Parameters,
+ Process,
+ &DeferredList,
+ &IoStatus);
+ goto Quickie;
+ }
+ else
+ {
+ IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
+ goto Quickie;
+ }
}
- ASSERT(Ccb->PipeState == FILE_PIPE_CLOSING_STATE);
-
- FileObject->FsContext2 = NULL;
-
- RemoveEntryList(&Ccb->CcbListEntry);
-
- NpfsDereferenceCcb(Ccb);
-
- KeUnlockMutex(&Fcb->CcbListLock);
-
- NpfsDereferenceFcb(Fcb);
- FileObject->FsContext = NULL;
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- DPRINT("Success!\n");
-
- return STATUS_SUCCESS;
+ if (Fcb->NodeType != NPFS_NTC_FCB)
+ {
+ IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
+ goto Quickie;
+ }
+
+ IoStatus = NpCreateExistingNamedPipe(Fcb,
+ FileObject,
+ IoStack->Parameters.CreatePipe.
+ SecurityContext->DesiredAccess,
+ IoStack->Parameters.CreatePipe.
+ SecurityContext->AccessState,
+ IoStack->Flags &
+ SL_FORCE_ACCESS_CHECK ?
+ UserMode : Irp->RequestorMode,
+ Disposition,
+ ShareAccess,
+ Parameters,
+ Process,
+ &DeferredList);
+
+Quickie:
+ NpReleaseVcb();
+ NpCompleteDeferredIrps(&DeferredList);
+ FsRtlExitFileSystem();
+
+ TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+ Irp->IoStatus = IoStatus;
+ IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+ return IoStatus.Status;
}
/* EOF */