1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * PROJECT: ReactOS 'Layers' Shim library
3*c2c66affSColin Finck * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4*c2c66affSColin Finck * PURPOSE: Shim for VMWare Horizon setup
5*c2c66affSColin Finck * COPYRIGHT: Copyright 2017 Thomas Faber (thomas.faber@reactos.org)
6*c2c66affSColin Finck * Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
7*c2c66affSColin Finck */
8*c2c66affSColin Finck
9*c2c66affSColin Finck #define WIN32_NO_STATUS
10*c2c66affSColin Finck #include <windef.h>
11*c2c66affSColin Finck #include <winbase.h>
12*c2c66affSColin Finck #include <shimlib.h>
13*c2c66affSColin Finck #include "ntndk.h"
14*c2c66affSColin Finck
Write(PBYTE Address,PBYTE Data,SIZE_T Size)15*c2c66affSColin Finck static BOOL Write(PBYTE Address, PBYTE Data, SIZE_T Size)
16*c2c66affSColin Finck {
17*c2c66affSColin Finck PVOID BaseAddress = Address;
18*c2c66affSColin Finck SIZE_T RegionSize = Size;
19*c2c66affSColin Finck ULONG OldProtection;
20*c2c66affSColin Finck NTSTATUS Status = NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress, &RegionSize, PAGE_EXECUTE_READWRITE, &OldProtection);
21*c2c66affSColin Finck if (NT_SUCCESS(Status))
22*c2c66affSColin Finck {
23*c2c66affSColin Finck SIZE_T Bytes;
24*c2c66affSColin Finck Status = NtWriteVirtualMemory(NtCurrentProcess(), Address, Data, Size, &Bytes);
25*c2c66affSColin Finck if (NT_SUCCESS(Status) && Bytes != Size)
26*c2c66affSColin Finck Status = STATUS_MEMORY_NOT_ALLOCATED;
27*c2c66affSColin Finck NtProtectVirtualMemory(NtCurrentProcess(), &BaseAddress, &RegionSize, OldProtection, &OldProtection);
28*c2c66affSColin Finck }
29*c2c66affSColin Finck return NT_SUCCESS(Status);
30*c2c66affSColin Finck }
31*c2c66affSColin Finck
FixupDll(PLDR_DATA_TABLE_ENTRY LdrEntry)32*c2c66affSColin Finck static void FixupDll(PLDR_DATA_TABLE_ENTRY LdrEntry)
33*c2c66affSColin Finck {
34*c2c66affSColin Finck static const UCHAR Match1[5] = { 0x0C, 0x8B, 0xFC, 0xF3, 0xA5 };
35*c2c66affSColin Finck static const UCHAR Match2[5] = { 0x0C, 0x8B, 0xFC, 0xF3, 0xA5 };
36*c2c66affSColin Finck static const UCHAR Match3[5] = { 0xB0, 0x8B, 0xFC, 0xF3, 0xA5 };
37*c2c66affSColin Finck UCHAR Replacement1[5] = { 0x10, 0x89, 0x34, 0x24, 0x90 };
38*c2c66affSColin Finck UCHAR Replacement2[5] = { 0x10, 0x89, 0x34, 0x24, 0x90 };
39*c2c66affSColin Finck UCHAR Replacement3[5] = { 0xB4, 0x89, 0x34, 0x24, 0x90 };
40*c2c66affSColin Finck #define OFFSET_1 0x21A6E
41*c2c66affSColin Finck #define OFFSET_2 0x21B04
42*c2c66affSColin Finck #define OFFSET_3 0x21C3C
43*c2c66affSColin Finck
44*c2c66affSColin Finck
45*c2c66affSColin Finck UCHAR Buffer[5];
46*c2c66affSColin Finck PBYTE Base = LdrEntry->DllBase;
47*c2c66affSColin Finck SIZE_T Bytes;
48*c2c66affSColin Finck
49*c2c66affSColin Finck /*
50*c2c66affSColin Finck 00020E6E: 0C 8B FC F3 A5 --> 10 89 34 24 90 F11A6E - ef0000 = 21A6E
51*c2c66affSColin Finck 00020F04: 0C 8B FC F3 A5 --> 10 89 34 24 90 F11B04 - ef0000 = 21B04
52*c2c66affSColin Finck 00021C3C: B0 8B FC F3 A5 --> B4 89 34 24 90 F11C3C - ef0000 = 21C3C
53*c2c66affSColin Finck */
54*c2c66affSColin Finck do {
55*c2c66affSColin Finck DbgPrint("Module %wZ Loaded at 0x%p, we should patch!\n", &LdrEntry->BaseDllName, LdrEntry->DllBase);
56*c2c66affSColin Finck if (!NT_SUCCESS(NtReadVirtualMemory(NtCurrentProcess(), Base + OFFSET_1, Buffer, 5, &Bytes)) || Bytes != 5)
57*c2c66affSColin Finck break;
58*c2c66affSColin Finck if (memcmp(Buffer, Match1, sizeof(Match1)))
59*c2c66affSColin Finck break;
60*c2c66affSColin Finck
61*c2c66affSColin Finck if (!NT_SUCCESS(NtReadVirtualMemory(NtCurrentProcess(), Base + OFFSET_2, Buffer, 5, &Bytes)) || Bytes != 5)
62*c2c66affSColin Finck break;
63*c2c66affSColin Finck if (memcmp(Buffer, Match2, sizeof(Match2)))
64*c2c66affSColin Finck break;
65*c2c66affSColin Finck
66*c2c66affSColin Finck if (!NT_SUCCESS(NtReadVirtualMemory(NtCurrentProcess(), Base + OFFSET_3, Buffer, 5, &Bytes)) || Bytes != 5)
67*c2c66affSColin Finck break;
68*c2c66affSColin Finck if (memcmp(Buffer, Match3, sizeof(Match3)))
69*c2c66affSColin Finck break;
70*c2c66affSColin Finck
71*c2c66affSColin Finck DbgPrint("Module %wZ Loaded at 0x%p, OK to patch!\n", &LdrEntry->BaseDllName, LdrEntry->DllBase);
72*c2c66affSColin Finck if (!Write(Base + OFFSET_1, Replacement1, sizeof(Replacement1)))
73*c2c66affSColin Finck break;
74*c2c66affSColin Finck if (!Write(Base + OFFSET_2, Replacement2, sizeof(Replacement2)))
75*c2c66affSColin Finck break;
76*c2c66affSColin Finck if (!Write(Base + OFFSET_3, Replacement3, sizeof(Replacement3)))
77*c2c66affSColin Finck break;
78*c2c66affSColin Finck
79*c2c66affSColin Finck NtFlushInstructionCache(NtCurrentProcess(), Base, 0x22000);
80*c2c66affSColin Finck
81*c2c66affSColin Finck DbgPrint("Module %wZ Loaded at 0x%p, patched!\n", &LdrEntry->BaseDllName, LdrEntry->DllBase);
82*c2c66affSColin Finck } while (0);
83*c2c66affSColin Finck }
84*c2c66affSColin Finck
PostfixUnicodeString(const UNICODE_STRING * String1,const UNICODE_STRING * String2)85*c2c66affSColin Finck static BOOLEAN PostfixUnicodeString(const UNICODE_STRING* String1, const UNICODE_STRING* String2)
86*c2c66affSColin Finck {
87*c2c66affSColin Finck PWCHAR pc1;
88*c2c66affSColin Finck PWCHAR pc2;
89*c2c66affSColin Finck ULONG NumChars;
90*c2c66affSColin Finck
91*c2c66affSColin Finck if (String2->Length < String1->Length)
92*c2c66affSColin Finck return FALSE;
93*c2c66affSColin Finck
94*c2c66affSColin Finck if (!String1->Buffer || !String2->Buffer)
95*c2c66affSColin Finck return FALSE;
96*c2c66affSColin Finck
97*c2c66affSColin Finck NumChars = String1->Length / sizeof(WCHAR);
98*c2c66affSColin Finck pc1 = String1->Buffer;
99*c2c66affSColin Finck pc2 = String2->Buffer + (String2->Length / sizeof(WCHAR)) - NumChars;
100*c2c66affSColin Finck
101*c2c66affSColin Finck while (NumChars--)
102*c2c66affSColin Finck {
103*c2c66affSColin Finck if (RtlUpcaseUnicodeChar(*pc1++) != RtlUpcaseUnicodeChar(*pc2++))
104*c2c66affSColin Finck return FALSE;
105*c2c66affSColin Finck }
106*c2c66affSColin Finck
107*c2c66affSColin Finck return TRUE;
108*c2c66affSColin Finck }
109*c2c66affSColin Finck
110*c2c66affSColin Finck #define SHIM_NS VMHorizonSetup
111*c2c66affSColin Finck #include <setup_shim.inl>
112*c2c66affSColin Finck
113*c2c66affSColin Finck #define SHIM_NUM_HOOKS 0
114*c2c66affSColin Finck #define SHIM_NOTIFY_FN SHIM_OBJ_NAME(Notify)
115*c2c66affSColin Finck
SHIM_OBJ_NAME(Notify)116*c2c66affSColin Finck BOOL WINAPI SHIM_OBJ_NAME(Notify)(DWORD fdwReason, PVOID ptr)
117*c2c66affSColin Finck {
118*c2c66affSColin Finck if (fdwReason == SHIM_REASON_DLL_LOAD)
119*c2c66affSColin Finck {
120*c2c66affSColin Finck static const UNICODE_STRING DllPrefix = RTL_CONSTANT_STRING(L"msi");
121*c2c66affSColin Finck static const UNICODE_STRING DllPostfix = RTL_CONSTANT_STRING(L".tmp");
122*c2c66affSColin Finck PLDR_DATA_TABLE_ENTRY LdrEntry = ptr;
123*c2c66affSColin Finck
124*c2c66affSColin Finck BOOLEAN Prefix = RtlPrefixUnicodeString(&DllPrefix, &LdrEntry->BaseDllName, TRUE);
125*c2c66affSColin Finck BOOLEAN Postfix = PostfixUnicodeString(&DllPostfix, &LdrEntry->BaseDllName);
126*c2c66affSColin Finck ULONG ExtraChars = (LdrEntry->BaseDllName.Length - DllPrefix.Length - DllPostfix.Length) / sizeof(WCHAR);
127*c2c66affSColin Finck
128*c2c66affSColin Finck /* msiN[N].tmp */
129*c2c66affSColin Finck if (Prefix && Postfix && ExtraChars <= 2)
130*c2c66affSColin Finck {
131*c2c66affSColin Finck PIMAGE_NT_HEADERS ImageNtHeader = RtlImageNtHeader(LdrEntry->DllBase);
132*c2c66affSColin Finck if (ImageNtHeader && ImageNtHeader->OptionalHeader.CheckSum == 0x176241)
133*c2c66affSColin Finck {
134*c2c66affSColin Finck SHIM_MSG("Module %wZ is a match, applying fixups\n", &LdrEntry->BaseDllName);
135*c2c66affSColin Finck FixupDll(LdrEntry);
136*c2c66affSColin Finck }
137*c2c66affSColin Finck }
138*c2c66affSColin Finck }
139*c2c66affSColin Finck return TRUE;
140*c2c66affSColin Finck }
141*c2c66affSColin Finck
142*c2c66affSColin Finck #include <implement_shim.inl>
143