From e4cfb86b3eda2d3fde4746a27e65a235d66b963e Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Sun, 30 Jul 2017 12:24:26 +0000 Subject: [PATCH] [RDBSS] Implement RxPrepareToReparseSymbolicLink(). This allows symbolic links to work on a NFS share, we can now follow links that would have been exported by the server. Safe to merge. CORE-8204 CORE-11327 CORE-13615 svn path=/trunk/; revision=75451 --- reactos/sdk/lib/drivers/rdbsslib/rdbss.c | 73 +++++++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/reactos/sdk/lib/drivers/rdbsslib/rdbss.c b/reactos/sdk/lib/drivers/rdbsslib/rdbss.c index 852c1c25544..ad6be6fde9c 100644 --- a/reactos/sdk/lib/drivers/rdbsslib/rdbss.c +++ b/reactos/sdk/lib/drivers/rdbsslib/rdbss.c @@ -7492,6 +7492,9 @@ Leave: return Status; } +/* + * @implemented + */ NTSTATUS NTAPI RxPrepareToReparseSymbolicLink( @@ -7501,8 +7504,74 @@ RxPrepareToReparseSymbolicLink( BOOLEAN NewPathIsAbsolute, PBOOLEAN ReparseRequired) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PWSTR NewBuffer; + USHORT NewLength; + PFILE_OBJECT FileObject; + + /* Assume no reparse is required first */ + *ReparseRequired = FALSE; + + /* Only supported for IRP_MJ_CREATE */ + if (RxContext->MajorFunction != IRP_MJ_CREATE) + { + return STATUS_INVALID_PARAMETER; + } + + /* If symbolic link is not embedded, and DELETE is specified, fail */ + if (!SymbolicLinkEmbeddedInOldPath) + { + /* Excepted if DELETE is the only flag specified, then, open has to succeed + * See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff554649(v=vs.85).aspx (remarks) + */ + if (BooleanFlagOn(RxContext->Create.NtCreateParameters.DesiredAccess, DELETE) && + BooleanFlagOn(RxContext->Create.NtCreateParameters.DesiredAccess, ~DELETE)) + { + return STATUS_ACCESS_DENIED; + } + } + + /* At that point, assume reparse will be required */ + *ReparseRequired = TRUE; + + /* If new path isn't absolute, it's up to us to make it absolute */ + if (!NewPathIsAbsolute) + { + /* The prefix will be \Device\Mup */ + NewLength = NewPath->Length + (sizeof(L"\\Device\\Mup") - sizeof(UNICODE_NULL)); + NewBuffer = ExAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION, NewLength, + RX_MISC_POOLTAG); + if (NewBuffer == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Copy data for the new path */ + RtlMoveMemory(NewBuffer, L"\\Device\\Mup", (sizeof(L"\\Device\\Mup") - sizeof(UNICODE_NULL))); + RtlMoveMemory(Add2Ptr(NewBuffer, (sizeof(L"\\Device\\Mup") - sizeof(UNICODE_NULL))), + NewPath->Buffer, NewPath->Length); + } + /* Otherwise, use caller path as it */ + else + { + NewLength = NewPath->Length; + NewBuffer = NewPath->Buffer; + } + + /* Get the FILE_OBJECT we'll modify */ + FileObject = RxContext->CurrentIrpSp->FileObject; + + /* Free old path first */ + ExFreePoolWithTag(FileObject->FileName.Buffer, 0); + /* And setup new one */ + FileObject->FileName.Length = NewLength; + FileObject->FileName.MaximumLength = NewLength; + FileObject->FileName.Buffer = NewBuffer; + + /* And set reparse flag */ + SetFlag(RxContext->Create.Flags, RX_CONTEXT_CREATE_FLAG_REPARSE); + + /* Done! */ + return STATUS_SUCCESS; } /* -- 2.17.1