reactos/drivers/filesystems/npfs/create.c
Pierre Schweitzer 257923cad1
[NPFS] Magic--;
2018-09-30 10:55:44 +02:00

918 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 */