mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
917 lines
28 KiB
C
917 lines
28 KiB
C
/*
|
|
* 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 *******************************************************************/
|
|
|
|
#include "npfs.h"
|
|
|
|
// File ID number for NPFS bugchecking support
|
|
#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_CREATE)
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
VOID
|
|
NTAPI
|
|
NpCheckForNotify(IN PNP_DCB Dcb,
|
|
IN BOOLEAN SecondList,
|
|
IN PLIST_ENTRY List)
|
|
{
|
|
PLIST_ENTRY NextEntry, ListHead;
|
|
PIRP Irp;
|
|
ULONG i;
|
|
PAGED_CODE();
|
|
|
|
ListHead = &Dcb->NotifyList;
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
ASSERT(IsListEmpty(ListHead));
|
|
while (!IsListEmpty(ListHead))
|
|
{
|
|
NextEntry = RemoveHeadList(ListHead);
|
|
|
|
Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
|
|
|
|
if (IoSetCancelRoutine(Irp, NULL))
|
|
{
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
InsertTailList(List, NextEntry);
|
|
}
|
|
else
|
|
{
|
|
InitializeListHead(NextEntry);
|
|
}
|
|
}
|
|
|
|
if (!SecondList) break;
|
|
ListHead = &Dcb->NotifyList2;
|
|
}
|
|
}
|
|
|
|
IO_STATUS_BLOCK
|
|
NTAPI
|
|
NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject,
|
|
IN ACCESS_MASK DesiredAccess)
|
|
{
|
|
IO_STATUS_BLOCK Status;
|
|
PAGED_CODE();
|
|
TRACE("Entered\n");
|
|
|
|
NpSetFileObject(FileObject, NpVcb, NULL, FALSE);
|
|
++NpVcb->ReferenceCount;
|
|
|
|
Status.Information = FILE_OPENED;
|
|
Status.Status = STATUS_SUCCESS;
|
|
TRACE("Leaving, Status.Status = %lx\n", Status.Status);
|
|
return Status;
|
|
}
|
|
|
|
IO_STATUS_BLOCK
|
|
NTAPI
|
|
NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb,
|
|
IN PFILE_OBJECT FileObject,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN PLIST_ENTRY List)
|
|
{
|
|
IO_STATUS_BLOCK IoStatus;
|
|
PNP_ROOT_DCB_FCB Ccb;
|
|
PAGED_CODE();
|
|
TRACE("Entered\n");
|
|
|
|
IoStatus.Status = NpCreateRootDcbCcb(&Ccb);
|
|
if (NT_SUCCESS(IoStatus.Status))
|
|
{
|
|
NpSetFileObject(FileObject, Dcb, Ccb, FALSE);
|
|
++Dcb->CurrentInstances;
|
|
|
|
IoStatus.Information = FILE_OPENED;
|
|
IoStatus.Status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
IoStatus.Information = 0;
|
|
}
|
|
|
|
TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
|
|
return IoStatus;
|
|
}
|
|
|
|
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)
|
|
{
|
|
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");
|
|
|
|
IoStatus.Information = 0;
|
|
Privileges = NULL;
|
|
|
|
NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
|
|
|
|
SubjectSecurityContext = &AccessState->SubjectSecurityContext;
|
|
SeLockSubjectContext(SubjectSecurityContext);
|
|
|
|
AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
|
|
SubjectSecurityContext,
|
|
TRUE,
|
|
DesiredAccess & ~4,
|
|
0,
|
|
&Privileges,
|
|
IoGetFileObjectGenericMapping(),
|
|
PreviousMode,
|
|
&GrantedAccess,
|
|
&IoStatus.Status);
|
|
|
|
if (Privileges)
|
|
{
|
|
SeAppendPrivileges(AccessState, Privileges);
|
|
SeFreePrivileges(Privileges);
|
|
}
|
|
|
|
if (AccessGranted)
|
|
{
|
|
AccessState->PreviouslyGrantedAccess |= GrantedAccess;
|
|
AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
|
|
}
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
ListHead = &Fcb->CcbList;
|
|
NextEntry = ListHead->Flink;
|
|
while (NextEntry != ListHead)
|
|
{
|
|
Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry);
|
|
if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break;
|
|
|
|
NextEntry = NextEntry->Flink;
|
|
}
|
|
|
|
if (NextEntry == ListHead)
|
|
{
|
|
IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE;
|
|
TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
|
|
return IoStatus;
|
|
}
|
|
|
|
IoStatus.Status = NpInitializeSecurity(Ccb, SecurityQos, Thread);
|
|
if (!NT_SUCCESS(IoStatus.Status)) return IoStatus;
|
|
|
|
IoStatus.Status = NpSetConnectedPipeState(Ccb, FileObject, List);
|
|
if (!NT_SUCCESS(IoStatus.Status))
|
|
{
|
|
NpUninitializeSecurity(Ccb);
|
|
TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
|
|
return IoStatus;
|
|
}
|
|
|
|
Ccb->ClientSession = NULL;
|
|
Ccb->Process = IoThreadToProcess(Thread);
|
|
|
|
IoStatus.Information = FILE_OPENED;
|
|
IoStatus.Status = STATUS_SUCCESS;
|
|
TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
|
|
return IoStatus;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
NpTranslateAlias(
|
|
PUNICODE_STRING PipeName)
|
|
{
|
|
WCHAR UpcaseBuffer[MAX_INDEXED_LENGTH + 1];
|
|
UNICODE_STRING UpcaseString;
|
|
ULONG Length;
|
|
PNPFS_ALIAS CurrentAlias;
|
|
NTSTATUS Status;
|
|
BOOLEAN BufferAllocated, BackSlash;
|
|
LONG Result;
|
|
PAGED_CODE();
|
|
|
|
/* Get the pipe name length and check for empty string */
|
|
Length = PipeName->Length;
|
|
if (Length == 0)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/* Check if the name starts with a path separator */
|
|
BackSlash = (PipeName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR);
|
|
if (BackSlash)
|
|
{
|
|
/* We are only interested in the part after the backslash */
|
|
Length -= sizeof(WCHAR);
|
|
}
|
|
|
|
/* Check if the length is within our indexed list bounds */
|
|
if ((Length >= MIN_INDEXED_LENGTH * sizeof(WCHAR)) &&
|
|
(Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR)))
|
|
{
|
|
/* Length is within bounds, use the list by length */
|
|
CurrentAlias = NpAliasListByLength[(Length / sizeof(WCHAR)) - MIN_INDEXED_LENGTH];
|
|
}
|
|
else
|
|
{
|
|
/* 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;
|
|
}
|
|
|
|
/* Go to the next alias in the list */
|
|
CurrentAlias = CurrentAlias->Next;
|
|
}
|
|
}
|
|
|
|
/* Did we find any alias? */
|
|
if (CurrentAlias == NULL)
|
|
{
|
|
/* Nothing found, no matching alias */
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/* 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);
|
|
|
|
/* Upcase the pipe name */
|
|
Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, FALSE);
|
|
NT_ASSERT(NT_SUCCESS(Status));
|
|
BufferAllocated = FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* Upcase the pipe name, allocate the string buffer */
|
|
Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
BufferAllocated = TRUE;
|
|
}
|
|
|
|
/* Did the original name start with a backslash? */
|
|
if (BackSlash)
|
|
{
|
|
/* Skip it for the comparison */
|
|
UpcaseString.Buffer++;
|
|
UpcaseString.Length -= sizeof(WCHAR);
|
|
}
|
|
|
|
/* Make sure the length matches the "raw" length */
|
|
NT_ASSERT(UpcaseString.Length == Length);
|
|
NT_ASSERT(CurrentAlias->Name.Length == Length);
|
|
|
|
/* Loop while we have aliases */
|
|
do
|
|
{
|
|
/* Compare the names and check if they match */
|
|
Result = NpCompareAliasNames(&UpcaseString, &CurrentAlias->Name);
|
|
if (Result == 0)
|
|
{
|
|
/* The names match, use the target name */
|
|
*PipeName = *CurrentAlias->TargetName;
|
|
|
|
/* Did the original name start with a backslash? */
|
|
if (!BackSlash)
|
|
{
|
|
/* It didn't, so skip it in the target name as well */
|
|
PipeName->Buffer++;
|
|
PipeName->Length -= sizeof(WCHAR);
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* Check if we went past all string candidates */
|
|
if (Result < 0)
|
|
{
|
|
/* Nothing found, we're done */
|
|
break;
|
|
}
|
|
|
|
/* Go to the next alias */
|
|
CurrentAlias = CurrentAlias->Next;
|
|
|
|
/* Keep looping while we have aliases of the right length */
|
|
} while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length == Length));
|
|
|
|
/* Did we allocate a buffer? */
|
|
if (BufferAllocated)
|
|
{
|
|
/* Free the allocated buffer */
|
|
ASSERT(UpcaseString.Buffer != UpcaseBuffer);
|
|
RtlFreeUnicodeString(&UpcaseString);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
IO_STATUS_BLOCK IoStatus;
|
|
PIO_STACK_LOCATION IoStack;
|
|
UNICODE_STRING FileName;
|
|
PFILE_OBJECT FileObject;
|
|
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");
|
|
|
|
InitializeListHead(&DeferredList);
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
FileObject = IoStack->FileObject;
|
|
RelatedFileObject = FileObject->RelatedFileObject;
|
|
FileName = FileObject->FileName;
|
|
DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
|
|
|
|
IoStatus.Information = 0;
|
|
|
|
FsRtlEnterFileSystem();
|
|
NpAcquireExclusiveVcb();
|
|
|
|
if (RelatedFileObject)
|
|
{
|
|
Type = NpDecodeFileObject(RelatedFileObject, (PVOID*)&Fcb, &Ccb, FALSE);
|
|
}
|
|
else
|
|
{
|
|
Type = 0;
|
|
Fcb = NULL;
|
|
Ccb = NULL;
|
|
}
|
|
|
|
if (FileName.Length)
|
|
{
|
|
if ((FileName.Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) &&
|
|
(FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
|
|
!(RelatedFileObject))
|
|
{
|
|
IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
|
|
FileObject,
|
|
DesiredAccess,
|
|
&DeferredList);
|
|
goto Quickie;
|
|
}
|
|
}
|
|
else if (!(RelatedFileObject) || (Type == NPFS_NTC_VCB))
|
|
{
|
|
IoStatus = NpOpenNamedPipeFileSystem(FileObject,
|
|
DesiredAccess);
|
|
goto Quickie;
|
|
}
|
|
else if (Type == NPFS_NTC_ROOT_DCB)
|
|
{
|
|
IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
|
|
FileObject,
|
|
DesiredAccess,
|
|
&DeferredList);
|
|
goto Quickie;
|
|
}
|
|
|
|
IoStatus.Status = NpTranslateAlias(&FileName);
|
|
if (!NT_SUCCESS(IoStatus.Status)) goto Quickie;
|
|
|
|
if (RelatedFileObject)
|
|
{
|
|
if (Type == NPFS_NTC_ROOT_DCB)
|
|
{
|
|
Dcb = (PNP_DCB)Ccb;
|
|
IoStatus.Status = NpFindRelativePrefix(Dcb,
|
|
&FileName,
|
|
1,
|
|
&Prefix,
|
|
&Fcb);
|
|
if (!NT_SUCCESS(IoStatus.Status))
|
|
{
|
|
goto Quickie;
|
|
}
|
|
}
|
|
else if ((Type != NPFS_NTC_CCB) || (FileName.Length))
|
|
{
|
|
IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
|
|
goto Quickie;
|
|
}
|
|
else
|
|
{
|
|
Prefix.Length = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
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);
|
|
}
|
|
|
|
if (Prefix.Length)
|
|
{
|
|
IoStatus.Status = Fcb->NodeType != NPFS_NTC_FCB ?
|
|
STATUS_OBJECT_NAME_NOT_FOUND :
|
|
STATUS_OBJECT_NAME_INVALID;
|
|
goto Quickie;
|
|
}
|
|
|
|
if (Fcb->NodeType != NPFS_NTC_FCB)
|
|
{
|
|
IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
|
|
goto Quickie;
|
|
}
|
|
|
|
if (!Fcb->ServerOpenCount)
|
|
{
|
|
IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
goto Quickie;
|
|
}
|
|
|
|
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);
|
|
|
|
Quickie:
|
|
NpReleaseVcb();
|
|
NpCompleteDeferredIrps(&DeferredList);
|
|
FsRtlExitFileSystem();
|
|
|
|
Irp->IoStatus = IoStatus;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
|
|
return IoStatus.Status;
|
|
}
|
|
|
|
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");
|
|
|
|
Privileges = NULL;
|
|
|
|
NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
|
|
|
|
SubjectSecurityContext = &AccessState->SubjectSecurityContext;
|
|
SeLockSubjectContext(SubjectSecurityContext);
|
|
|
|
IoStatus.Information = 0;
|
|
|
|
AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
|
|
SubjectSecurityContext,
|
|
TRUE,
|
|
DesiredAccess | 4,
|
|
0,
|
|
&Privileges,
|
|
IoGetFileObjectGenericMapping(),
|
|
PreviousMode,
|
|
&GrantedAccess,
|
|
&IoStatus.Status);
|
|
|
|
if (Privileges)
|
|
{
|
|
SeAppendPrivileges(AccessState, Privileges);
|
|
SeFreePrivileges(Privileges);
|
|
}
|
|
|
|
if (AccessGranted)
|
|
{
|
|
AccessState->PreviouslyGrantedAccess |= GrantedAccess;
|
|
AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
|
|
}
|
|
|
|
ObjectTypeName.Buffer = L"NamedPipe";
|
|
ObjectTypeName.Length = 18;
|
|
SeOpenObjectAuditAlarm(&ObjectTypeName,
|
|
NULL,
|
|
&FileObject->FileName,
|
|
Fcb->SecurityDescriptor,
|
|
AccessState,
|
|
FALSE,
|
|
AccessGranted,
|
|
PreviousMode,
|
|
&AccessState->GenerateOnClose);
|
|
|
|
SeUnlockSubjectContext(SubjectSecurityContext);
|
|
if (!AccessGranted)
|
|
{
|
|
TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
|
|
return IoStatus;
|
|
}
|
|
|
|
if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
|
|
{
|
|
IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE;
|
|
TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
|
|
return IoStatus;
|
|
}
|
|
|
|
if (Disposition == FILE_CREATE)
|
|
{
|
|
IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
|
|
return IoStatus;
|
|
}
|
|
|
|
CheckShareAccess = 0;
|
|
if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX)
|
|
{
|
|
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 (CheckShareAccess != ShareAccess)
|
|
{
|
|
IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
|
|
return IoStatus;
|
|
}
|
|
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
|
|
Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
|
|
NpCheckForNotify(Fcb->ParentDcb, 0, List);
|
|
|
|
IoStatus.Status = STATUS_SUCCESS;
|
|
IoStatus.Information = FILE_OPENED;
|
|
TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
|
|
return IoStatus;
|
|
}
|
|
|
|
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)
|
|
{
|
|
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
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto Quickie;
|
|
}
|
|
|
|
if (Parameters->NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE &&
|
|
Parameters->ReadMode == FILE_PIPE_MESSAGE_MODE)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto Quickie;
|
|
}
|
|
|
|
Status = NpCreateFcb(Dcb,
|
|
&PipeName,
|
|
Parameters->MaximumInstances,
|
|
Parameters->DefaultTimeout,
|
|
NamedPipeConfiguration,
|
|
Parameters->NamedPipeType & 0xFFFF,
|
|
&Fcb);
|
|
if (!NT_SUCCESS(Status)) goto Quickie;
|
|
|
|
Status = NpCreateCcb(Fcb,
|
|
FileObject,
|
|
FILE_PIPE_LISTENING_STATE,
|
|
Parameters->ReadMode & 0xFF,
|
|
Parameters->CompletionMode & 0xFF,
|
|
Parameters->InboundQuota,
|
|
Parameters->OutboundQuota,
|
|
&Ccb);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
NpDeleteFcb(Fcb, List);
|
|
goto Quickie;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
Status = ObLogSecurityDescriptor(SecurityDescriptor,
|
|
&CachedSecurityDescriptor,
|
|
1);
|
|
ExFreePoolWithTag(SecurityDescriptor, 0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
NpDeleteCcb(Ccb, List);
|
|
NpDeleteFcb(Fcb, List);
|
|
goto Quickie;
|
|
}
|
|
|
|
Fcb->SecurityDescriptor = CachedSecurityDescriptor;
|
|
|
|
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
|
|
NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
PFILE_OBJECT FileObject;
|
|
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);
|
|
FileObject = IoStack->FileObject;
|
|
RelatedFileObject = FileObject->RelatedFileObject;
|
|
|
|
Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF;
|
|
ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess & 0xFFFF;
|
|
Parameters = IoStack->Parameters.CreatePipe.Parameters;
|
|
|
|
FileName = FileObject->FileName;
|
|
|
|
IoStatus.Information = 0;
|
|
|
|
FsRtlEnterFileSystem();
|
|
NpAcquireExclusiveVcb();
|
|
|
|
if (RelatedFileObject)
|
|
{
|
|
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;
|
|
}
|
|
|
|
IoStatus.Status = NpFindRelativePrefix(RelatedFileObject->FsContext,
|
|
&FileName,
|
|
TRUE,
|
|
&Prefix,
|
|
&Fcb);
|
|
if (!NT_SUCCESS(IoStatus.Status))
|
|
{
|
|
goto Quickie;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
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);
|
|
}
|
|
|
|
if (Prefix.Length)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
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 */
|