diff --git a/reactos/dll/appcompat/shims/layer/CMakeLists.txt b/reactos/dll/appcompat/shims/layer/CMakeLists.txt index d18ee3bbe01..f62c8dd13c9 100644 --- a/reactos/dll/appcompat/shims/layer/CMakeLists.txt +++ b/reactos/dll/appcompat/shims/layer/CMakeLists.txt @@ -6,6 +6,7 @@ spec2def(aclayers.dll layer.spec) list(APPEND SOURCE dispmode.c versionlie.c + vmhorizon.c main.c layer.spec) diff --git a/reactos/dll/appcompat/shims/layer/vmhorizon.c b/reactos/dll/appcompat/shims/layer/vmhorizon.c new file mode 100644 index 00000000000..0330a2f32f7 --- /dev/null +++ b/reactos/dll/appcompat/shims/layer/vmhorizon.c @@ -0,0 +1,142 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Shim library + * FILE: dll/appcompat/shims/layer/vmhorizon.c + * PURPOSE: Shim for VMWare Horizon setup + * PROGRAMMER: Thomas Faber (thomas.faber@reactos.org) + * Mark Jansen (mark.jansen@reactos.org) + */ + +#define WIN32_NO_STATUS +#include +#include +#include "ntndk.h" + +static BOOL Write(PBYTE Address, PBYTE Data, SIZE_T Size) +{ + PVOID BaseAddress = Address; + SIZE_T RegionSize = Size; + ULONG OldProtection; + NTSTATUS Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress, &RegionSize, PAGE_EXECUTE_READWRITE, &OldProtection); + if (NT_SUCCESS(Status)) + { + SIZE_T Bytes; + Status = NtWriteVirtualMemory(NtCurrentProcess(), Address, Data, Size, &Bytes); + if (NT_SUCCESS(Status) && Bytes != Size) + Status = STATUS_MEMORY_NOT_ALLOCATED; + NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress, &RegionSize, OldProtection, &OldProtection); + } + return NT_SUCCESS(Status); +} + +static void FixupDll(PLDR_DATA_TABLE_ENTRY LdrEntry) +{ + static const UCHAR Match1[5] = { 0x0C, 0x8B, 0xFC, 0xF3, 0xA5 }; + static const UCHAR Match2[5] = { 0x0C, 0x8B, 0xFC, 0xF3, 0xA5 }; + static const UCHAR Match3[5] = { 0xB0, 0x8B, 0xFC, 0xF3, 0xA5 }; + UCHAR Replacement1[5] = { 0x10, 0x89, 0x34, 0x24, 0x90 }; + UCHAR Replacement2[5] = { 0x10, 0x89, 0x34, 0x24, 0x90 }; + UCHAR Replacement3[5] = { 0xB4, 0x89, 0x34, 0x24, 0x90 }; +#define OFFSET_1 0x21A6E +#define OFFSET_2 0x21B04 +#define OFFSET_3 0x21C3C + + + UCHAR Buffer[5]; + PBYTE Base = LdrEntry->DllBase; + SIZE_T Bytes; + + /* + 00020E6E: 0C 8B FC F3 A5 --> 10 89 34 24 90 F11A6E - ef0000 = 21A6E + 00020F04: 0C 8B FC F3 A5 --> 10 89 34 24 90 F11B04 - ef0000 = 21B04 + 00021C3C: B0 8B FC F3 A5 --> B4 89 34 24 90 F11C3C - ef0000 = 21C3C + */ + do { + DbgPrint("Module %wZ Loaded at 0x%p, we should patch!\n", &LdrEntry->BaseDllName, LdrEntry->DllBase); + if (!NT_SUCCESS(NtReadVirtualMemory(NtCurrentProcess(), Base + OFFSET_1, Buffer, 5, &Bytes)) || Bytes != 5) + break; + if (memcmp(Buffer, Match1, sizeof(Match1))) + break; + + if (!NT_SUCCESS(NtReadVirtualMemory(NtCurrentProcess(), Base + OFFSET_2, Buffer, 5, &Bytes)) || Bytes != 5) + break; + if (memcmp(Buffer, Match2, sizeof(Match2))) + break; + + if (!NT_SUCCESS(NtReadVirtualMemory(NtCurrentProcess(), Base + OFFSET_3, Buffer, 5, &Bytes)) || Bytes != 5) + break; + if (memcmp(Buffer, Match3, sizeof(Match3))) + break; + + DbgPrint("Module %wZ Loaded at 0x%p, OK to patch!\n", &LdrEntry->BaseDllName, LdrEntry->DllBase); + if (!Write(Base + OFFSET_1, Replacement1, sizeof(Replacement1))) + break; + if (!Write(Base + OFFSET_2, Replacement2, sizeof(Replacement2))) + break; + if (!Write(Base + OFFSET_3, Replacement3, sizeof(Replacement3))) + break; + + NtFlushInstructionCache(NtCurrentProcess(), Base, 0x22000); + + DbgPrint("Module %wZ Loaded at 0x%p, patched!\n", &LdrEntry->BaseDllName, LdrEntry->DllBase); + } while (0); +} + +static BOOLEAN PostfixUnicodeString(const UNICODE_STRING* String1, const UNICODE_STRING* String2) +{ + PWCHAR pc1; + PWCHAR pc2; + ULONG NumChars; + + if (String2->Length < String1->Length) + return FALSE; + + if (!String1->Buffer || !String2->Buffer) + return FALSE; + + NumChars = String1->Length / sizeof(WCHAR); + pc1 = String1->Buffer; + pc2 = String2->Buffer + (String2->Length / sizeof(WCHAR)) - NumChars; + + while (NumChars--) + { + if (RtlUpcaseUnicodeChar(*pc1++) != RtlUpcaseUnicodeChar(*pc2++)) + return FALSE; + } + + return TRUE; +} + +#define SHIM_NS VMHorizonSetup +#include + +#define SHIM_NUM_HOOKS 0 +#define SHIM_NOTIFY_FN SHIM_OBJ_NAME(Notify) + +BOOL WINAPI SHIM_OBJ_NAME(Notify)(DWORD fdwReason, PVOID ptr) +{ + if (fdwReason == SHIM_REASON_DLL_LOAD) + { + static const UNICODE_STRING DllPrefix = RTL_CONSTANT_STRING(L"msi"); + static const UNICODE_STRING DllPostfix = RTL_CONSTANT_STRING(L".tmp"); + PLDR_DATA_TABLE_ENTRY LdrEntry = ptr; + + BOOLEAN Prefix = RtlPrefixUnicodeString(&DllPrefix, &LdrEntry->BaseDllName, TRUE); + BOOLEAN Postfix = PostfixUnicodeString(&DllPostfix, &LdrEntry->BaseDllName); + ULONG ExtraChars = (LdrEntry->BaseDllName.Length - DllPrefix.Length - DllPostfix.Length) / sizeof(WCHAR); + + /* msiN[N].tmp */ + if (Prefix && Postfix && ExtraChars <= 2) + { + PIMAGE_NT_HEADERS ImageNtHeader = RtlImageNtHeader(LdrEntry->DllBase); + if (ImageNtHeader && ImageNtHeader->OptionalHeader.CheckSum == 0x176241) + { + SHIM_MSG("Module %wZ is a match, applying fixups\n", &LdrEntry->BaseDllName); + FixupDll(LdrEntry); + } + } + } + return TRUE; +} + +#include diff --git a/reactos/media/sdb/sysmain.xml b/reactos/media/sdb/sysmain.xml index a8caa7ccc44..118c90e6969 100644 --- a/reactos/media/sdb/sysmain.xml +++ b/reactos/media/sdb/sysmain.xml @@ -170,6 +170,9 @@ acgenral.dll + + aclayers.dll + aclayers.dll @@ -280,6 +283,10 @@ + + + + \ No newline at end of file