From cc578af6df1c6299fc2256559dfea80ef172cfd2 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Tue, 31 Oct 2017 23:03:16 +0100 Subject: [PATCH] [RDBSS] Implement RxQueryNameInfo() and RxConjureOriginalName() --- sdk/include/ddk/rxprocs.h | 16 +++ sdk/lib/drivers/rdbsslib/rdbss.c | 165 ++++++++++++++++++++++++++++++- 2 files changed, 179 insertions(+), 2 deletions(-) diff --git a/sdk/include/ddk/rxprocs.h b/sdk/include/ddk/rxprocs.h index 819ba72d039..5c74496be96 100644 --- a/sdk/include/ddk/rxprocs.h +++ b/sdk/include/ddk/rxprocs.h @@ -75,6 +75,22 @@ RxFindOrCreateConnections( _In_ PRX_CONNECTION_ID RxConnectionId); #endif +typedef enum _RX_NAME_CONJURING_METHODS +{ + VNetRoot_As_Prefix, + VNetRoot_As_UNC_Name, + VNetRoot_As_DriveLetter +} RX_NAME_CONJURING_METHODS; + +VOID +RxConjureOriginalName( + _Inout_ PFCB Fcb, + _Inout_ PFOBX Fobx, + _Out_ PULONG ActualNameLength, + _Out_writes_bytes_( *LengthRemaining) PWCHAR OriginalName, + _Inout_ PLONG LengthRemaining, + _In_ RX_NAME_CONJURING_METHODS NameConjuringMethod); + #if (_WIN32_WINNT >= 0x0600) NTSTATUS RxCompleteMdl( diff --git a/sdk/lib/drivers/rdbsslib/rdbss.c b/sdk/lib/drivers/rdbsslib/rdbss.c index 4f888c8c134..154c63ad72d 100644 --- a/sdk/lib/drivers/rdbsslib/rdbss.c +++ b/sdk/lib/drivers/rdbsslib/rdbss.c @@ -4786,6 +4786,134 @@ RxCompleteMdl( return STATUS_SUCCESS; } +/* + * @implemented + */ +VOID +RxConjureOriginalName( + PFCB Fcb, + PFOBX Fobx, + PULONG ActualNameLength, + PWCHAR OriginalName, + PLONG LengthRemaining, + RX_NAME_CONJURING_METHODS NameConjuringMethod) +{ + PWSTR Prefix, Name; + PV_NET_ROOT VNetRoot; + USHORT PrefixLength, NameLength, ToCopy; + + PAGED_CODE(); + + VNetRoot = Fcb->VNetRoot; + /* We will use the prefix contained in NET_ROOT, if we don't have + * a V_NET_ROOT, or if it wasn't null deviced or if we already have + * a UNC path */ + if (VNetRoot == NULL || VNetRoot->PrefixEntry.Prefix.Buffer[1] != L';' || + BooleanFlagOn(Fobx->Flags, FOBX_FLAG_UNC_NAME)) + { + Prefix = ((PNET_ROOT)Fcb->pNetRoot)->PrefixEntry.Prefix.Buffer; + PrefixLength = ((PNET_ROOT)Fcb->pNetRoot)->PrefixEntry.Prefix.Length; + NameLength = 0; + + /* In that case, keep track that we will have a prefix as buffer */ + NameConjuringMethod = VNetRoot_As_Prefix; + } + else + { + ASSERT(NodeType(VNetRoot) == RDBSS_NTC_V_NETROOT); + + /* Otherwise, return the prefix from our V_NET_ROOT */ + Prefix = VNetRoot->PrefixEntry.Prefix.Buffer; + PrefixLength = VNetRoot->PrefixEntry.Prefix.Length; + NameLength = VNetRoot->NamePrefix.Length; + + /* If we want a UNC path, skip potential device */ + if (NameConjuringMethod == VNetRoot_As_UNC_Name) + { + do + { + ++Prefix; + PrefixLength -= sizeof(WCHAR); + } while (PrefixLength > 0 && Prefix[0] != L'\\'); + } + } + + /* If we added an extra backslash, skip it */ + if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_ADDEDBACKSLASH)) + { + NameLength += sizeof(WCHAR); + } + + /* If we're asked for a drive letter, skip the prefix */ + if (NameConjuringMethod == VNetRoot_As_DriveLetter) + { + PrefixLength = 0; + + /* And make sure we arrive at a backslash */ + if (Fcb->FcbTableEntry.Path.Length > NameLength && + Fcb->FcbTableEntry.Path.Buffer[NameLength / sizeof(WCHAR)] != L'\\') + { + NameLength -= sizeof(WCHAR); + } + } + else + { + /* Prepare to copy the prefix, make sure not to overflow */ + if (*LengthRemaining >= PrefixLength) + { + /* Copy everything */ + ToCopy = PrefixLength; + *LengthRemaining = *LengthRemaining - PrefixLength; + } + else + { + /* Copy as much as we can */ + ToCopy = *LengthRemaining; + /* And return failure */ + *LengthRemaining = -1; + } + + /* Copy the prefix */ + RtlCopyMemory(OriginalName, Prefix, ToCopy); + } + + /* Do we have a name to copy now? */ + if (Fcb->FcbTableEntry.Path.Length > NameLength) + { + ToCopy = Fcb->FcbTableEntry.Path.Length - NameLength; + Name = Fcb->FcbTableEntry.Path.Buffer; + } + else + { + /* Just use slash for now */ + ToCopy = sizeof(WCHAR); + NameLength = 0; + Name = L"\\"; + } + + /* Total length we will have in the output buffer (if everything is alright) */ + *ActualNameLength = ToCopy + PrefixLength; + /* If we still have room to write data */ + if (*LengthRemaining != -1) + { + /* If we can copy everything, it's fine! */ + if (*LengthRemaining > ToCopy) + { + *LengthRemaining = *LengthRemaining - ToCopy; + } + /* Otherwise, copy as much as possible, and return failure */ + else + { + ToCopy = *LengthRemaining; + *LengthRemaining = -1; + } + + /* Copy name after the prefix */ + RtlCopyMemory(Add2Ptr(OriginalName, PrefixLength), + Add2Ptr(Name, NameLength), ToCopy); + } +} + /* * @implemented */ @@ -8012,13 +8140,46 @@ RxQueryInternalInfo( return STATUS_NOT_IMPLEMENTED; } +/* + * @implemented + */ NTSTATUS RxQueryNameInfo( PRX_CONTEXT RxContext, PFILE_NAME_INFORMATION NameInfo) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PFCB Fcb; + PFOBX Fobx; + PAGED_CODE(); + + DPRINT("RxQueryNameInfo(%p, %p)\n", RxContext, NameInfo); + + /* Check we can at least copy name size */ + if (RxContext->Info.LengthRemaining < FIELD_OFFSET(FILE_NAME_INFORMATION, FileName)) + { + DPRINT1("Buffer too small: %d\n", RxContext->Info.LengthRemaining); + RxContext->Info.Length = 0; + return STATUS_BUFFER_OVERFLOW; + } + + Fcb = (PFCB)RxContext->pFcb; + Fobx = (PFOBX)RxContext->pFobx; + /* Get the UNC name */ + RxConjureOriginalName(Fcb, Fobx, &NameInfo->FileNameLength, &NameInfo->FileName[0], + &RxContext->Info.Length, VNetRoot_As_UNC_Name); + + /* If RxConjureOriginalName returned a negative len (-1) then output buffer + * was too small, return the appropriate length & status. + */ + if (RxContext->Info.LengthRemaining < 0) + { + DPRINT1("Buffer too small!\n"); + RxContext->Info.Length = 0; + return STATUS_BUFFER_OVERFLOW; + } + + /* All correct */ + return STATUS_SUCCESS; } NTSTATUS