https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d93e516747e3220ba182f77824e8b1a8b548edae

commit d93e516747e3220ba182f77824e8b1a8b548edae
Author:     Mark Jansen <[email protected]>
AuthorDate: Sun Oct 14 15:45:02 2018 +0200
Commit:     Mark Jansen <[email protected]>
CommitDate: Thu Feb 7 18:48:49 2019 +0100

    [LDR] Add support for .local files
    CORE-187
---
 dll/ntdll/include/ntdllp.h |  8 ++++++
 dll/ntdll/ldr/ldrinit.c    | 70 ++++++++++++++++++++++++++++++++++++++++++----
 dll/ntdll/rtl/libsupp.c    | 68 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 140 insertions(+), 6 deletions(-)

diff --git a/dll/ntdll/include/ntdllp.h b/dll/ntdll/include/ntdllp.h
index 11f1e826f3..0f122a642d 100644
--- a/dll/ntdll/include/ntdllp.h
+++ b/dll/ntdll/include/ntdllp.h
@@ -203,4 +203,12 @@ VOID
 NTAPI
 LdrpFinalizeAndDeallocateDataTableEntry(IN PLDR_DATA_TABLE_ENTRY Entry);
 
+
+/* path.c */
+BOOLEAN
+NTAPI
+RtlDoesFileExists_UStr(
+    IN PUNICODE_STRING FileName
+);
+
 /* EOF */
diff --git a/dll/ntdll/ldr/ldrinit.c b/dll/ntdll/ldr/ldrinit.c
index d28cb6e8a1..39567578d9 100644
--- a/dll/ntdll/ldr/ldrinit.c
+++ b/dll/ntdll/ldr/ldrinit.c
@@ -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 */
diff --git a/dll/ntdll/rtl/libsupp.c b/dll/ntdll/rtl/libsupp.c
index d29ccaf82d..94c6f0e5b0 100644
--- a/dll/ntdll/rtl/libsupp.c
+++ b/dll/ntdll/rtl/libsupp.c
@@ -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 */

Reply via email to