[RDBSS] Implement RxQueryNameInfo() and RxConjureOriginalName()

This commit is contained in:
Pierre Schweitzer 2017-10-31 23:03:16 +01:00
parent f5104a0042
commit cc578af6df
No known key found for this signature in database
GPG key ID: 7545556C3D585B0B
2 changed files with 179 additions and 2 deletions

View file

@ -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(

View file

@ -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