[LDR] Add support for .local files 1339/head
authorMark Jansen <mark.jansen@reactos.org>
Sun, 14 Oct 2018 13:45:02 +0000 (15:45 +0200)
committerMark Jansen <mark.jansen@reactos.org>
Thu, 7 Feb 2019 17:48:49 +0000 (18:48 +0100)
CORE-187

dll/ntdll/include/ntdllp.h
dll/ntdll/ldr/ldrinit.c
dll/ntdll/rtl/libsupp.c

index 11f1e82..0f122a6 100644 (file)
@@ -203,4 +203,12 @@ VOID
 NTAPI
 LdrpFinalizeAndDeallocateDataTableEntry(IN PLDR_DATA_TABLE_ENTRY Entry);
 
+
+/* path.c */
+BOOLEAN
+NTAPI
+RtlDoesFileExists_UStr(
+    IN PUNICODE_STRING FileName
+);
+
 /* EOF */
index d28cb6e..3956757 100644 (file)
@@ -25,6 +25,7 @@ UNICODE_STRING ImageExecOptionsString = RTL_CONSTANT_STRING(L"\\Registry\\Machin
 UNICODE_STRING Wow64OptionsString = RTL_CONSTANT_STRING(L"");
 UNICODE_STRING NtDllString = RTL_CONSTANT_STRING(L"ntdll.dll");
 UNICODE_STRING Kernel32String = RTL_CONSTANT_STRING(L"kernel32.dll");
+const UNICODE_STRING LdrpDotLocal = RTL_CONSTANT_STRING(L".Local");
 
 BOOLEAN LdrpInLdrInit;
 LONG LdrpProcessInitialized;
@@ -1626,6 +1627,66 @@ LdrpInitializeProcessCompat(PVOID* pOldShimData)
     }
 }
 
+VOID
+NTAPI
+LdrpInitializeDotLocalSupport(PRTL_USER_PROCESS_PARAMETERS ProcessParameters)
+{
+    UNICODE_STRING ImagePathName = ProcessParameters->ImagePathName;
+    WCHAR LocalBuffer[MAX_PATH];
+    UNICODE_STRING DotLocal;
+    NTSTATUS Status;
+    ULONG RequiredSize;
+
+    RequiredSize = ImagePathName.Length + LdrpDotLocal.Length + sizeof(UNICODE_NULL);
+    if (RequiredSize <= sizeof(LocalBuffer))
+    {
+        RtlInitEmptyUnicodeString(&DotLocal, LocalBuffer, sizeof(LocalBuffer));
+    }
+    else if (RequiredSize <= UNICODE_STRING_MAX_BYTES)
+    {
+        DotLocal.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, RequiredSize);
+        DotLocal.Length = 0;
+        DotLocal.MaximumLength = RequiredSize;
+        if (!DotLocal.Buffer)
+            DPRINT1("LDR: Failed to allocate memory for .local check\n");
+    }
+    else
+    {
+        DotLocal.Buffer = NULL;
+        DotLocal.Length = 0;
+        DotLocal.MaximumLength = 0;
+        DPRINT1("LDR: String too big for .local check\n");
+    }
+
+    if (DotLocal.Buffer)
+    {
+        Status = RtlAppendUnicodeStringToString(&DotLocal, &ImagePathName);
+        ASSERT(NT_SUCCESS(Status));
+        if (NT_SUCCESS(Status))
+        {
+            Status = RtlAppendUnicodeStringToString(&DotLocal, &LdrpDotLocal);
+            ASSERT(NT_SUCCESS(Status));
+        }
+
+        if (NT_SUCCESS(Status))
+        {
+            if (RtlDoesFileExists_UStr(&DotLocal))
+            {
+                ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH;
+            }
+        }
+        else
+        {
+            DPRINT1("LDR: Failed to append: 0x%lx\n", Status);
+        }
+
+        if (DotLocal.Buffer != LocalBuffer)
+        {
+            RtlFreeHeap(RtlGetProcessHeap(), 0, DotLocal.Buffer);
+        }
+    }
+}
+
 
 NTSTATUS
 NTAPI
@@ -2135,13 +2196,10 @@ LdrpInitializeProcess(IN PCONTEXT Context,
         if (FreeCurDir) RtlFreeUnicodeString(&CurrentDirectory);
     }
 
-    /* Check if we should look for a .local file 
-        FIXME: Thomas suggested that this check might actually be reversed, we should check this file
-               if the flag is NOT set. */
-    if (ProcessParameters && (ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH))
+    /* Check if we should look for a .local file */
+    if (ProcessParameters && !(ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH))
     {
-        /* FIXME */
-        DPRINT1("We don't support .local overrides yet\n");
+        LdrpInitializeDotLocalSupport(ProcessParameters);
     }
 
     /* Check if the Application Verifier was enabled */
index d29ccaf..94c6f0e 100644 (file)
@@ -792,6 +792,8 @@ RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags,
     WCHAR *p;
     BOOLEAN GotExtension;
     WCHAR c;
+    C_ASSERT(sizeof(UNICODE_NULL) == sizeof(WCHAR));
+
 
     /* Check for invalid parameters */
     if (!OriginalName)
@@ -819,6 +821,72 @@ RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags,
         return STATUS_SXS_KEY_NOT_FOUND;
     }
 
+    if (NtCurrentPeb()->ProcessParameters &&
+        (NtCurrentPeb()->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH))
+    {
+        UNICODE_STRING RealName, LocalName;
+        WCHAR RealNameBuf[MAX_PATH], LocalNameBuf[MAX_PATH];
+
+        RtlInitEmptyUnicodeString(&RealName, RealNameBuf, sizeof(RealNameBuf));
+        RtlInitEmptyUnicodeString(&LocalName, LocalNameBuf, sizeof(LocalNameBuf));
+
+        Status = RtlComputePrivatizedDllName_U(OriginalName, &RealName, &LocalName);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("RtlComputePrivatizedDllName_U failed for %wZ: 0x%lx\n", OriginalName, Status);
+            return Status;
+        }
+
+        if (RtlDoesFileExists_UStr(&LocalName))
+        {
+            Status = get_buffer(&fullname, LocalName.Length + sizeof(UNICODE_NULL), StaticString, DynamicString != NULL);
+            if (NT_SUCCESS(Status))
+            {
+                RtlCopyMemory(fullname, LocalName.Buffer, LocalName.Length + sizeof(UNICODE_NULL));
+            }
+            else
+            {
+                DPRINT1("Error while retrieving buffer for %wZ: 0x%lx\n", OriginalName, Status);
+            }
+        }
+        else if (RtlDoesFileExists_UStr(&RealName))
+        {
+            Status = get_buffer(&fullname, RealName.Length + sizeof(UNICODE_NULL), StaticString, DynamicString != NULL);
+            if (NT_SUCCESS(Status))
+            {
+                RtlCopyMemory(fullname, RealName.Buffer, RealName.Length + sizeof(UNICODE_NULL));
+            }
+            else
+            {
+                DPRINT1("Error while retrieving buffer for %wZ: 0x%lx\n", OriginalName, Status);
+            }
+        }
+        else
+        {
+            Status = STATUS_NOT_FOUND;
+        }
+
+        if (RealName.Buffer != RealNameBuf)
+            RtlFreeUnicodeString(&RealName);
+        if (LocalName.Buffer != LocalNameBuf)
+            RtlFreeUnicodeString(&LocalName);
+
+        if (NT_SUCCESS(Status))
+        {
+            DPRINT("Redirecting %wZ to %S\n", OriginalName, fullname);
+            if (!StaticString || StaticString->Buffer != fullname)
+            {
+                RtlInitUnicodeString(DynamicString, fullname);
+                *NewName = DynamicString;
+            }
+            else
+            {
+                *NewName = StaticString;
+            }
+            return Status;
+        }
+    }
+
     pstrParam = OriginalName;
 
     /* Get the file name with an extension */