[RDBSS] More capture
[reactos.git] / sdk / lib / drivers / rdbsslib / rdbss.c
index 4f888c8..46c006d 100644 (file)
@@ -643,6 +643,8 @@ VOID
 CheckForLoudOperations(
     PRX_CONTEXT RxContext)
 {
+    RxCaptureFcb;
+
     PAGED_CODE();
 
 #define ALLSCR_LENGTH (sizeof(L"all.scr") - sizeof(UNICODE_NULL))
@@ -650,11 +652,9 @@ CheckForLoudOperations(
     /* Are loud operations enabled? */
     if (RxLoudLowIoOpsEnabled)
     {
-        PFCB Fcb;
-
         /* If so, the operation will be loud only if filename ends with all.scr */
-        Fcb = (PFCB)RxContext->pFcb;
-        if (RtlCompareMemory(Add2Ptr(Fcb->PrivateAlreadyPrefixedName.Buffer, (Fcb->PrivateAlreadyPrefixedName.Length - ALLSCR_LENGTH)),
+        if (RtlCompareMemory(Add2Ptr(capFcb->PrivateAlreadyPrefixedName.Buffer,
+                             (capFcb->PrivateAlreadyPrefixedName.Length - ALLSCR_LENGTH)),
                              L"all.scr", ALLSCR_LENGTH) == ALLSCR_LENGTH)
         {
             SetFlag(RxContext->LowIoContext.Flags, LOWIO_CONTEXT_FLAG_LOUDOPS);
@@ -701,14 +701,12 @@ __RxWriteReleaseResources(
     PCSTR FileName,
     ULONG SerialNumber)
 {
-    PFCB Fcb;
+    RxCaptureFcb;
 
     PAGED_CODE();
 
     ASSERT(RxContext != NULL);
-
-    Fcb = (PFCB)RxContext->pFcb;
-    ASSERT(Fcb != NULL);
+    ASSERT(capFcb != NULL);
 
     /* If FCB resource was acquired, release it */
     if (RxContext->FcbResourceAcquired)
@@ -716,11 +714,11 @@ __RxWriteReleaseResources(
         /* Taking care of owner */
         if (ResourceOwnerSet)
         {
-            RxReleaseFcbForThread(RxContext, Fcb, RxContext->LowIoContext.ResourceThreadId);
+            RxReleaseFcbForThread(RxContext, capFcb, RxContext->LowIoContext.ResourceThreadId);
         }
         else
         {
-            RxReleaseFcb(RxContext, Fcb);
+            RxReleaseFcb(RxContext, capFcb);
         }
 
         RxContext->FcbResourceAcquired = FALSE;
@@ -732,11 +730,11 @@ __RxWriteReleaseResources(
         /* Taking care of owner */
         if (ResourceOwnerSet)
         {
-            RxReleasePagingIoResourceForThread(RxContext, Fcb, RxContext->LowIoContext.ResourceThreadId);
+            RxReleasePagingIoResourceForThread(RxContext, capFcb, RxContext->LowIoContext.ResourceThreadId);
         }
         else
         {
-            RxReleasePagingIoResource(RxContext, Fcb);
+            RxReleasePagingIoResource(RxContext, capFcb);
         }
 
         /* No need to release boolean here, RxReleasePagingIoResource() takes care of it */
@@ -774,14 +772,14 @@ RxAddToWorkque(
     ULONG Queued;
     KIRQL OldIrql;
     WORK_QUEUE_TYPE Queue;
-    PIO_STACK_LOCATION Stack;
 
-    Stack = RxContext->CurrentIrpSp;
+    RxCaptureParamBlock;
+
     RxContext->PostRequest = FALSE;
 
     /* First of all, select the appropriate queue - delayed for prefix claim, critical for the rest */
     if (RxContext->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
-        Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
+        capPARAMS->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH)
     {
         Queue = DelayedWorkQueue;
         SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE);
@@ -793,7 +791,7 @@ RxAddToWorkque(
     }
 
     /* Check for overflow */
-    if (Stack->FileObject != NULL)
+    if (capPARAMS->FileObject != NULL)
     {
         KeAcquireSpinLock(&RxFileSystemDeviceObject->OverflowQueueSpinLock, &OldIrql);
 
@@ -821,22 +819,23 @@ RxAddToWorkque(
  */
 VOID
 RxAdjustFileTimesAndSize(
-    PRX_CONTEXT Context)
+    PRX_CONTEXT RxContext)
 {
-    PFCB Fcb;
-    PFOBX Fobx;
     NTSTATUS Status;
-    PFILE_OBJECT FileObject;
     LARGE_INTEGER CurrentTime;
     FILE_BASIC_INFORMATION FileBasicInfo;
     FILE_END_OF_FILE_INFORMATION FileEOFInfo;
     BOOLEAN FileModified, SetLastChange, SetLastAccess, SetLastWrite, NeedUpdate;
 
+    RxCaptureFcb;
+    RxCaptureFobx;
+    RxCaptureParamBlock;
+    RxCaptureFileObject;
+
     PAGED_CODE();
 
-    FileObject = Context->CurrentIrpSp->FileObject;
     /* If Cc isn't initialized, the file was not read nor written, nothing to do */
-    if (FileObject->PrivateCacheMap == NULL)
+    if (capFileObject->PrivateCacheMap == NULL)
     {
         return;
     }
@@ -844,17 +843,16 @@ RxAdjustFileTimesAndSize(
     /* Get now */
     KeQuerySystemTime(&CurrentTime);
 
-    Fobx = (PFOBX)Context->pFobx;
     /* Was the file modified? */
-    FileModified = BooleanFlagOn(FileObject->Flags, FO_FILE_MODIFIED);
+    FileModified = BooleanFlagOn(capFileObject->Flags, FO_FILE_MODIFIED);
     /* We'll set last write if it was modified and user didn't update yet */
-    SetLastWrite = FileModified && !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_USER_SET_LAST_WRITE);
+    SetLastWrite = FileModified && !BooleanFlagOn(capFobx->Flags, FOBX_FLAG_USER_SET_LAST_WRITE);
     /* File was accessed if: written or read (fastio), we'll update last access if user didn't */
     SetLastAccess = SetLastWrite ||
-                    (BooleanFlagOn(FileObject->Flags, FO_FILE_FAST_IO_READ) &&
-                     !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_USER_SET_LAST_ACCESS));
+                    (BooleanFlagOn(capFileObject->Flags, FO_FILE_FAST_IO_READ) &&
+                     !BooleanFlagOn(capFobx->Flags, FOBX_FLAG_USER_SET_LAST_ACCESS));
     /* We'll set last change if it was modified and user didn't update yet */
-    SetLastChange = FileModified && !BooleanFlagOn(Fobx->Flags, FOBX_FLAG_USER_SET_LAST_CHANGE);
+    SetLastChange = FileModified && !BooleanFlagOn(capFobx->Flags, FOBX_FLAG_USER_SET_LAST_CHANGE);
 
     /* Nothing to update? Job done */
     if (!FileModified && !SetLastWrite && !SetLastAccess && !SetLastChange)
@@ -862,7 +860,6 @@ RxAdjustFileTimesAndSize(
         return;
     }
 
-    Fcb = (PFCB)Context->pFcb;
     /* By default, we won't issue any MRxSetFileInfoAtCleanup call */
     NeedUpdate = FALSE;
     RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
@@ -871,7 +868,7 @@ RxAdjustFileTimesAndSize(
     if (SetLastWrite)
     {
         NeedUpdate = TRUE;
-        Fcb->LastWriteTime.QuadPart = CurrentTime.QuadPart;
+        capFcb->LastWriteTime.QuadPart = CurrentTime.QuadPart;
         FileBasicInfo.LastWriteTime.QuadPart = CurrentTime.QuadPart;
     }
 
@@ -879,7 +876,7 @@ RxAdjustFileTimesAndSize(
     if (SetLastAccess)
     {
         NeedUpdate = TRUE;
-        Fcb->LastAccessTime.QuadPart = CurrentTime.QuadPart;
+        capFcb->LastAccessTime.QuadPart = CurrentTime.QuadPart;
         FileBasicInfo.LastAccessTime.QuadPart = CurrentTime.QuadPart;
     }
 
@@ -887,31 +884,31 @@ RxAdjustFileTimesAndSize(
     if (SetLastChange)
     {
         NeedUpdate = TRUE;
-        Fcb->LastChangeTime.QuadPart = CurrentTime.QuadPart;
+        capFcb->LastChangeTime.QuadPart = CurrentTime.QuadPart;
         FileBasicInfo.ChangeTime.QuadPart = CurrentTime.QuadPart;
     }
 
     /* If one of the date was modified, issue a call to mini-rdr */
     if (NeedUpdate)
     {
-        Context->Info.FileInformationClass = FileBasicInformation;
-        Context->Info.Buffer = &FileBasicInfo;
-        Context->Info.Length = sizeof(FileBasicInfo);
+        RxContext->Info.FileInformationClass = FileBasicInformation;
+        RxContext->Info.Buffer = &FileBasicInfo;
+        RxContext->Info.Length = sizeof(FileBasicInfo);
 
-        MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxSetFileInfoAtCleanup, (Context));
+        MINIRDR_CALL(Status, RxContext, capFcb->MRxDispatch, MRxSetFileInfoAtCleanup, (RxContext));
         (void)Status;
     }
 
     /* If the file was modified, update its EOF */
     if (FileModified)
     {
-        FileEOFInfo.EndOfFile.QuadPart = Fcb->Header.FileSize.QuadPart;
+        FileEOFInfo.EndOfFile.QuadPart = capFcb->Header.FileSize.QuadPart;
 
-        Context->Info.FileInformationClass = FileEndOfFileInformation;
-        Context->Info.Buffer = &FileEOFInfo;
-        Context->Info.Length = sizeof(FileEOFInfo);
+        RxContext->Info.FileInformationClass = FileEndOfFileInformation;
+        RxContext->Info.Buffer = &FileEOFInfo;
+        RxContext->Info.Length = sizeof(FileEOFInfo);
 
-        MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxSetFileInfoAtCleanup, (Context));
+        MINIRDR_CALL(Status, RxContext, capFcb->MRxDispatch, MRxSetFileInfoAtCleanup, (RxContext));
         (void)Status;
     }
 }
@@ -1244,6 +1241,9 @@ RxCanonicalizeNameAndObtainNetRoot(
     NET_ROOT_TYPE NetRootType;
     UNICODE_STRING CanonicalName;
 
+    RxCaptureParamBlock;
+    RxCaptureFileObject;
+
     PAGED_CODE();
 
     NetRootType = NET_ROOT_WILD;
@@ -1252,7 +1252,7 @@ RxCanonicalizeNameAndObtainNetRoot(
     RtlInitEmptyUnicodeString(&CanonicalName, NULL, 0);
 
     /* if not relative opening, just handle the passed name */
-    if (RxContext->CurrentIrpSp->FileObject->RelatedFileObject == NULL)
+    if (capFileObject->RelatedFileObject == NULL)
     {
         Status = RxFirstCanonicalize(RxContext, FileName, &CanonicalName, &NetRootType);
         if (!NT_SUCCESS(Status))
@@ -1265,9 +1265,8 @@ RxCanonicalizeNameAndObtainNetRoot(
         PFCB Fcb;
 
         /* Make sure we have a valid FCB and a FOBX */
-        Fcb = RxContext->CurrentIrpSp->FileObject->RelatedFileObject->FsContext;
-        if (Fcb == NULL ||
-            RxContext->CurrentIrpSp->FileObject->RelatedFileObject->FsContext2 == NULL)
+        Fcb = capFileObject->RelatedFileObject->FsContext;
+        if (Fcb == NULL || capFileObject->RelatedFileObject->FsContext2 == NULL)
         {
             return STATUS_INVALID_PARAMETER;
         }
@@ -1323,12 +1322,15 @@ RxCanonicalizeNameAndObtainNetRoot(
     return Status;
 }
 
+/*
+ * @implemented
+ */
 VOID
 NTAPI
 RxCheckFcbStructuresForAlignment(
     VOID)
 {
-    UNIMPLEMENTED;
+    PAGED_CODE();
 }
 
 #if DBG
@@ -1613,26 +1615,25 @@ NTSTATUS
 RxCollapseOrCreateSrvOpen(
     PRX_CONTEXT RxContext)
 {
-    PFCB Fcb;
     NTSTATUS Status;
     ULONG Disposition;
     PSRV_OPEN SrvOpen;
     USHORT ShareAccess;
-    PIO_STACK_LOCATION Stack;
     ACCESS_MASK DesiredAccess;
     RX_BLOCK_CONDITION FcbCondition;
 
+    RxCaptureFcb;
+    RxCaptureParamBlock;
+
     PAGED_CODE();
 
     DPRINT("RxCollapseOrCreateSrvOpen(%p)\n", RxContext);
 
-    Fcb = (PFCB)RxContext->pFcb;
-    ASSERT(RxIsFcbAcquiredExclusive(Fcb));
-    ++Fcb->UncleanCount;
+    ASSERT(RxIsFcbAcquiredExclusive(capFcb));
+    ++capFcb->UncleanCount;
 
-    Stack = RxContext->CurrentIrpSp;
-    DesiredAccess = Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_ALL_ACCESS;
-    ShareAccess = Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS;
+    DesiredAccess = capPARAMS->Parameters.Create.SecurityContext->DesiredAccess & FILE_ALL_ACCESS;
+    ShareAccess = capPARAMS->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS;
 
     Disposition = RxContext->Create.NtCreateParameters.Disposition;
 
@@ -1641,7 +1642,7 @@ RxCollapseOrCreateSrvOpen(
     if (Status == STATUS_NOT_FOUND)
     {
         /* If none found, create one */
-        SrvOpen = RxCreateSrvOpen((PV_NET_ROOT)RxContext->Create.pVNetRoot, Fcb);
+        SrvOpen = RxCreateSrvOpen((PV_NET_ROOT)RxContext->Create.pVNetRoot, capFcb);
         if (SrvOpen == NULL)
         {
             Status = STATUS_INSUFFICIENT_RESOURCES;
@@ -1666,7 +1667,7 @@ RxCollapseOrCreateSrvOpen(
             /* Cookie to check the mini-rdr doesn't mess with RX_CONTEXT */
             RxContext->CurrentIrp->IoStatus.Information = 0xABCDEF;
             /* Inform the mini-rdr we're handling a create */
-            MINIRDR_CALL(Status, RxContext, Fcb->MRxDispatch, MRxCreate, (RxContext));
+            MINIRDR_CALL(Status, RxContext, capFcb->MRxDispatch, MRxCreate, (RxContext));
             ASSERT(RxContext->CurrentIrp->IoStatus.Information == 0xABCDEF);
 
             DPRINT("MRxCreate returned: %x\n", Status);
@@ -1675,23 +1676,23 @@ RxCollapseOrCreateSrvOpen(
                 /* In case of overwrite, reset file size */
                 if (Disposition == FILE_OVERWRITE || Disposition == FILE_OVERWRITE_IF)
                 {
-                    RxAcquirePagingIoResource(RxContext, Fcb);
-                    Fcb->Header.AllocationSize.QuadPart = 0LL;
-                    Fcb->Header.FileSize.QuadPart = 0LL;
-                    Fcb->Header.ValidDataLength.QuadPart = 0LL;
-                    RxContext->CurrentIrpSp->FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
-                    CcSetFileSizes(RxContext->CurrentIrpSp->FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
-                    RxReleasePagingIoResource(RxContext, Fcb);
+                    RxAcquirePagingIoResource(RxContext, capFcb);
+                    capFcb->Header.AllocationSize.QuadPart = 0LL;
+                    capFcb->Header.FileSize.QuadPart = 0LL;
+                    capFcb->Header.ValidDataLength.QuadPart = 0LL;
+                    RxContext->CurrentIrpSp->FileObject->SectionObjectPointer = &capFcb->NonPaged->SectionObjectPointers;
+                    CcSetFileSizes(RxContext->CurrentIrpSp->FileObject, (PCC_FILE_SIZES)&capFcb->Header.AllocationSize);
+                    RxReleasePagingIoResource(RxContext, capFcb);
                 }
                 else
                 {
                     /* Otherwise, adjust sizes */
-                    RxContext->CurrentIrpSp->FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
+                    RxContext->CurrentIrpSp->FileObject->SectionObjectPointer = &capFcb->NonPaged->SectionObjectPointers;
                     if (CcIsFileCached(RxContext->CurrentIrpSp->FileObject))
                     {
-                        RxAdjustAllocationSizeforCC(Fcb);
+                        RxAdjustAllocationSizeforCC(capFcb);
                     }
-                    CcSetFileSizes(RxContext->CurrentIrpSp->FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
+                    CcSetFileSizes(RxContext->CurrentIrpSp->FileObject, (PCC_FILE_SIZES)&capFcb->Header.AllocationSize);
                 }
             }
 
@@ -1702,15 +1703,15 @@ RxCollapseOrCreateSrvOpen(
             /* Set SRV_OPEN state - good or bad - depending on whether create succeed */
             RxTransitionSrvOpen(SrvOpen, (Status == STATUS_SUCCESS ? Condition_Good : Condition_Bad));
 
-            ASSERT(RxIsFcbAcquiredExclusive(Fcb));
+            ASSERT(RxIsFcbAcquiredExclusive(capFcb));
 
             RxCompleteSrvOpenKeyAssociation(SrvOpen);
 
             if (Status == STATUS_SUCCESS)
             {
-                if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_DELETE_ON_CLOSE))
+                if (BooleanFlagOn(capPARAMS->Parameters.Create.Options, FILE_DELETE_ON_CLOSE))
                 {
-                    ClearFlag(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED);
+                    ClearFlag(capFcb->FcbState, FCB_STATE_COLLAPSING_ENABLED);
                 }
                 SrvOpen->CreateOptions = RxContext->Create.NtCreateParameters.CreateOptions;
                 FcbCondition = Condition_Good;
@@ -1730,8 +1731,8 @@ RxCollapseOrCreateSrvOpen(
         }
 
         /* Set FCB state -  good or bad - depending on whether create succeed */
-        DPRINT("Transitioning FCB %p to condition %lx\n", Fcb, Fcb->Condition);
-        RxTransitionNetFcb(Fcb, FcbCondition);
+        DPRINT("Transitioning FCB %p to condition %lx\n", capFcb, capFcb->Condition);
+        RxTransitionNetFcb(capFcb, FcbCondition);
     }
     else if (Status == STATUS_SUCCESS)
     {
@@ -1751,12 +1752,12 @@ RxCollapseOrCreateSrvOpen(
             ++SrvOpen->OpenCount;
             ExtraOpen = TRUE;
 
-            RxReleaseFcb(RxContext, Fcb);
+            RxReleaseFcb(RxContext, capFcb);
             RxContext->Create.FcbAcquired = FALSE;
 
             RxWaitForStableSrvOpen(SrvOpen, RxContext);
 
-            if (NT_SUCCESS(RxAcquireExclusiveFcb(RxContext, Fcb)))
+            if (NT_SUCCESS(RxAcquireExclusiveFcb(RxContext, capFcb)))
             {
                 RxContext->Create.FcbAcquired = TRUE;
             }
@@ -1767,9 +1768,9 @@ RxCollapseOrCreateSrvOpen(
         /* Inform the mini-rdr we do an opening with a reused SRV_OPEN */
         if (IsGood)
         {
-            MINIRDR_CALL(Status, RxContext, Fcb->MRxDispatch, MRxCollapseOpen, (RxContext));
+            MINIRDR_CALL(Status, RxContext, capFcb->MRxDispatch, MRxCollapseOpen, (RxContext));
 
-            ASSERT(RxIsFcbAcquiredExclusive(Fcb));
+            ASSERT(RxIsFcbAcquiredExclusive(capFcb));
         }
         else
         {
@@ -1783,7 +1784,7 @@ RxCollapseOrCreateSrvOpen(
         }
     }
 
-    --Fcb->UncleanCount;
+    --capFcb->UncleanCount;
 
     DPRINT("Status: %x\n", Status);
     return Status;
@@ -4786,6 +4787,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
  */
@@ -6640,14 +6769,6 @@ RxIndicateChangeOfBufferingStateForSrvOpen(
     UNIMPLEMENTED;
 }
 
-VOID
-NTAPI
-RxInitializeDebugSupport(
-    VOID)
-{
-    UNIMPLEMENTED;
-}
-
 /*
  * @implemented
  */
@@ -8012,13 +8133,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