https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d93e516747e3220ba182f…
commit d93e516747e3220ba182f77824e8b1a8b548edae
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Sun Oct 14 15:45:02 2018 +0200
Commit: Mark Jansen <mark.jansen(a)reactos.org>
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 */