1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Application compatibility module
36969e85bSMark Jansen * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4c2c66affSColin Finck * PURPOSE: Shim engine core
56969e85bSMark Jansen * COPYRIGHT: Copyright 2015-2019 Mark Jansen (mark.jansen@reactos.org)
6c2c66affSColin Finck */
7c2c66affSColin Finck
8c2c66affSColin Finck #define WIN32_NO_STATUS
9c2c66affSColin Finck #include "ntndk.h"
10c2c66affSColin Finck #define IN_APPHELP
11c2c66affSColin Finck #include "shimlib.h"
12c2c66affSColin Finck #include <strsafe.h>
13c2c66affSColin Finck /* Make sure we don't include apphelp logging */
14c2c66affSColin Finck #define APPHELP_NOSDBPAPI
15c2c66affSColin Finck #include "apphelp.h"
16c2c66affSColin Finck #include "shimeng.h"
17c2c66affSColin Finck
18c2c66affSColin Finck
19c2c66affSColin Finck
20c2c66affSColin Finck FARPROC WINAPI StubGetProcAddress(HINSTANCE hModule, LPCSTR lpProcName);
21c2c66affSColin Finck BOOL WINAPI SE_IsShimDll(PVOID BaseAddress);
22c2c66affSColin Finck
236abe0e50SMark Jansen static const UNICODE_STRING Ntdll = RTL_CONSTANT_STRING(L"ntdll.dll");
246abe0e50SMark Jansen static const UNICODE_STRING Kernel32 = RTL_CONSTANT_STRING(L"kernel32.dll");
256abe0e50SMark Jansen static const UNICODE_STRING Verifier = RTL_CONSTANT_STRING(L"verifier.dll");
26c2c66affSColin Finck
27c2c66affSColin Finck extern HMODULE g_hInstance;
28c2c66affSColin Finck static UNICODE_STRING g_WindowsDirectory;
29c2c66affSColin Finck static UNICODE_STRING g_System32Directory;
30c2c66affSColin Finck static UNICODE_STRING g_SxsDirectory;
31511e7935SMark Jansen static UNICODE_STRING g_LoadingShimDll;
32c2c66affSColin Finck ULONG g_ShimEngDebugLevel = 0xffffffff;
33c2c66affSColin Finck BOOL g_bComPlusImage = FALSE;
34c2c66affSColin Finck BOOL g_bShimDuringInit = FALSE;
35*d284c814SMark Jansen BOOL g_bShimEngInitialized = FALSE;
36c2c66affSColin Finck BOOL g_bInternalHooksUsed = FALSE;
37c2c66affSColin Finck static ARRAY g_pShimInfo; /* PSHIMMODULE */
38c2c66affSColin Finck static ARRAY g_pHookArray; /* HOOKMODULEINFO */
39c2c66affSColin Finck static ARRAY g_InExclude; /* INEXCLUDE */
40c2c66affSColin Finck
411570f08bSMark Jansen typedef FARPROC(WINAPI* GETPROCADDRESSPROC)(HINSTANCE, LPCSTR);
42c2c66affSColin Finck /* If we have setup a hook for a function, we should also redirect GetProcAddress for this function */
43c2c66affSColin Finck HOOKAPIEX g_IntHookEx[] =
44c2c66affSColin Finck {
45c2c66affSColin Finck {
46c2c66affSColin Finck "kernel32.dll", /* LibraryName */
47c2c66affSColin Finck "GetProcAddress", /* FunctionName */
48c2c66affSColin Finck StubGetProcAddress, /* ReplacementFunction*/
49c2c66affSColin Finck NULL, /* OriginalFunction */
50c2c66affSColin Finck NULL, /* pShimInfo */
51ee62837eSMark Jansen NULL /* ApiLink */
52c2c66affSColin Finck },
53c2c66affSColin Finck };
54c2c66affSColin Finck
ARRAY_InitWorker(PARRAY Array,DWORD ItemSize)55c2c66affSColin Finck static inline BOOL ARRAY_InitWorker(PARRAY Array, DWORD ItemSize)
56c2c66affSColin Finck {
57c2c66affSColin Finck Array->Data__ = NULL;
58c2c66affSColin Finck Array->Size__ = Array->MaxSize__ = 0;
59c2c66affSColin Finck Array->ItemSize__ = ItemSize;
60c2c66affSColin Finck
61c2c66affSColin Finck return TRUE;
62c2c66affSColin Finck }
63c2c66affSColin Finck
ARRAY_EnsureSize(PARRAY Array,DWORD ItemSize,DWORD GrowWith)64c2c66affSColin Finck static inline BOOL ARRAY_EnsureSize(PARRAY Array, DWORD ItemSize, DWORD GrowWith)
65c2c66affSColin Finck {
66c2c66affSColin Finck PVOID pNewData;
67c2c66affSColin Finck DWORD Count;
68c2c66affSColin Finck
69c2c66affSColin Finck ASSERT(Array);
70c2c66affSColin Finck ASSERT(ItemSize == Array->ItemSize__);
71c2c66affSColin Finck
72c2c66affSColin Finck if (Array->MaxSize__ > Array->Size__)
73c2c66affSColin Finck return TRUE;
74c2c66affSColin Finck
75c2c66affSColin Finck Count = Array->Size__ + GrowWith;
76c2c66affSColin Finck pNewData = SeiAlloc(Count * ItemSize);
77c2c66affSColin Finck
78c2c66affSColin Finck if (!pNewData)
79c2c66affSColin Finck {
80c2c66affSColin Finck SHIMENG_FAIL("Failed to allocate %d bytes\n", Count * ItemSize);
81c2c66affSColin Finck return FALSE;
82c2c66affSColin Finck }
83c2c66affSColin Finck Array->MaxSize__ = Count;
84c2c66affSColin Finck
85c2c66affSColin Finck if (Array->Data__)
86c2c66affSColin Finck {
87c2c66affSColin Finck memcpy(pNewData, Array->Data__, Array->Size__ * ItemSize);
88c2c66affSColin Finck SeiFree(Array->Data__);
89c2c66affSColin Finck }
90c2c66affSColin Finck Array->Data__ = pNewData;
91c2c66affSColin Finck
92c2c66affSColin Finck return TRUE;
93c2c66affSColin Finck }
94c2c66affSColin Finck
ARRAY_AppendWorker(PARRAY Array,DWORD ItemSize,DWORD GrowWith)95c2c66affSColin Finck static inline PVOID ARRAY_AppendWorker(PARRAY Array, DWORD ItemSize, DWORD GrowWith)
96c2c66affSColin Finck {
97c2c66affSColin Finck PBYTE pData;
98c2c66affSColin Finck
99c2c66affSColin Finck if (!ARRAY_EnsureSize(Array, ItemSize, GrowWith))
100c2c66affSColin Finck return NULL;
101c2c66affSColin Finck
102c2c66affSColin Finck pData = Array->Data__;
103c2c66affSColin Finck pData += (Array->Size__ * ItemSize);
104c2c66affSColin Finck Array->Size__++;
105c2c66affSColin Finck
106c2c66affSColin Finck return pData;
107c2c66affSColin Finck }
108c2c66affSColin Finck
ARRAY_AtWorker(PARRAY Array,DWORD ItemSize,DWORD n)109c2c66affSColin Finck static inline PVOID ARRAY_AtWorker(PARRAY Array, DWORD ItemSize, DWORD n)
110c2c66affSColin Finck {
111c2c66affSColin Finck PBYTE pData;
112c2c66affSColin Finck
113c2c66affSColin Finck ASSERT(Array);
114c2c66affSColin Finck ASSERT(ItemSize == Array->ItemSize__);
115c2c66affSColin Finck ASSERT(n < Array->Size__);
116c2c66affSColin Finck
117c2c66affSColin Finck pData = Array->Data__;
118c2c66affSColin Finck return pData + (n * ItemSize);
119c2c66affSColin Finck }
120c2c66affSColin Finck
121c2c66affSColin Finck
122c2c66affSColin Finck #define ARRAY_Init(Array, TypeOfArray) ARRAY_InitWorker((Array), sizeof(TypeOfArray))
123c2c66affSColin Finck #define ARRAY_Append(Array, TypeOfArray) (TypeOfArray*)ARRAY_AppendWorker((Array), sizeof(TypeOfArray), 5)
124c2c66affSColin Finck #define ARRAY_At(Array, TypeOfArray, at) (TypeOfArray*)ARRAY_AtWorker((Array), sizeof(TypeOfArray), at)
125c2c66affSColin Finck #define ARRAY_Size(Array) (Array)->Size__
126c2c66affSColin Finck
127c2c66affSColin Finck
SeiInitDebugSupport(VOID)128c2c66affSColin Finck VOID SeiInitDebugSupport(VOID)
129c2c66affSColin Finck {
130c2c66affSColin Finck static const UNICODE_STRING DebugKey = RTL_CONSTANT_STRING(L"SHIMENG_DEBUG_LEVEL");
131c2c66affSColin Finck UNICODE_STRING DebugValue;
132c2c66affSColin Finck NTSTATUS Status;
133c2c66affSColin Finck ULONG NewLevel = SEI_MSG; /* Show some basic info in the logs, unless configured different */
134c2c66affSColin Finck WCHAR Buffer[40];
135c2c66affSColin Finck
136c2c66affSColin Finck RtlInitEmptyUnicodeString(&DebugValue, Buffer, sizeof(Buffer));
137c2c66affSColin Finck
138c2c66affSColin Finck Status = RtlQueryEnvironmentVariable_U(NULL, &DebugKey, &DebugValue);
139c2c66affSColin Finck
140c2c66affSColin Finck if (NT_SUCCESS(Status))
141c2c66affSColin Finck {
142c2c66affSColin Finck if (!NT_SUCCESS(RtlUnicodeStringToInteger(&DebugValue, 10, &NewLevel)))
143c2c66affSColin Finck NewLevel = 0;
144c2c66affSColin Finck }
145c2c66affSColin Finck g_ShimEngDebugLevel = NewLevel;
146c2c66affSColin Finck }
147c2c66affSColin Finck
148c2c66affSColin Finck
149c2c66affSColin Finck /**
150c2c66affSColin Finck * Outputs diagnostic info.
151c2c66affSColin Finck *
152c2c66affSColin Finck * @param [in] Level The level to log this message with, choose any of [SHIM_ERR,
153c2c66affSColin Finck * SHIM_WARN, SHIM_INFO].
154c2c66affSColin Finck * @param [in] FunctionName The function this log should be attributed to.
155c2c66affSColin Finck * @param [in] Format The format string.
156c2c66affSColin Finck * @param ... Variable arguments providing additional information.
157c2c66affSColin Finck *
158c2c66affSColin Finck * @return Success: TRUE Failure: FALSE.
159c2c66affSColin Finck */
SeiDbgPrint(SEI_LOG_LEVEL Level,PCSTR Function,PCSTR Format,...)160c2c66affSColin Finck BOOL WINAPIV SeiDbgPrint(SEI_LOG_LEVEL Level, PCSTR Function, PCSTR Format, ...)
161c2c66affSColin Finck {
162c2c66affSColin Finck char Buffer[512];
163c2c66affSColin Finck char* Current = Buffer;
164c2c66affSColin Finck const char* LevelStr;
165c2c66affSColin Finck size_t Length = sizeof(Buffer);
166c2c66affSColin Finck va_list ArgList;
167c2c66affSColin Finck HRESULT hr;
168c2c66affSColin Finck
169c2c66affSColin Finck if (g_ShimEngDebugLevel == 0xffffffff)
170c2c66affSColin Finck SeiInitDebugSupport();
171c2c66affSColin Finck
172c2c66affSColin Finck if (Level > g_ShimEngDebugLevel)
173c2c66affSColin Finck return FALSE;
174c2c66affSColin Finck
175c2c66affSColin Finck switch (Level)
176c2c66affSColin Finck {
177c2c66affSColin Finck case SEI_MSG:
178c2c66affSColin Finck LevelStr = "MSG ";
179c2c66affSColin Finck break;
180c2c66affSColin Finck case SEI_FAIL:
181c2c66affSColin Finck LevelStr = "FAIL";
182c2c66affSColin Finck break;
183c2c66affSColin Finck case SEI_WARN:
184c2c66affSColin Finck LevelStr = "WARN";
185c2c66affSColin Finck break;
186c2c66affSColin Finck case SEI_INFO:
187c2c66affSColin Finck LevelStr = "INFO";
188c2c66affSColin Finck break;
189c2c66affSColin Finck default:
190c2c66affSColin Finck LevelStr = "USER";
191c2c66affSColin Finck break;
192c2c66affSColin Finck }
193c2c66affSColin Finck
194c2c66affSColin Finck if (Function)
195c2c66affSColin Finck hr = StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s] [%s] ", LevelStr, Function);
196c2c66affSColin Finck else
197c2c66affSColin Finck hr = StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s] ", LevelStr);
198c2c66affSColin Finck
199c2c66affSColin Finck if (!SUCCEEDED(hr))
200c2c66affSColin Finck return FALSE;
201c2c66affSColin Finck
202c2c66affSColin Finck va_start(ArgList, Format);
203c2c66affSColin Finck hr = StringCchVPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, Format, ArgList);
204c2c66affSColin Finck va_end(ArgList);
205c2c66affSColin Finck if (!SUCCEEDED(hr))
206c2c66affSColin Finck return FALSE;
207c2c66affSColin Finck
208c2c66affSColin Finck DbgPrint("%s", Buffer);
209c2c66affSColin Finck return TRUE;
210c2c66affSColin Finck }
211c2c66affSColin Finck
2121570f08bSMark Jansen static
SeiIsOrdinalName(LPCSTR lpProcName)2131570f08bSMark Jansen BOOL SeiIsOrdinalName(LPCSTR lpProcName)
2141570f08bSMark Jansen {
2151570f08bSMark Jansen return (ULONG_PTR)lpProcName <= MAXUSHORT;
2161570f08bSMark Jansen }
2171570f08bSMark Jansen
SeiPrintFunctionName(LPCSTR lpProcName,char szOrdProcFmt[10])2181570f08bSMark Jansen LPCSTR SeiPrintFunctionName(LPCSTR lpProcName, char szOrdProcFmt[10])
2191570f08bSMark Jansen {
2201570f08bSMark Jansen if (SeiIsOrdinalName(lpProcName))
2211570f08bSMark Jansen {
2221570f08bSMark Jansen StringCchPrintfA(szOrdProcFmt, 10, "#%Iu", (ULONG_PTR)lpProcName);
2231570f08bSMark Jansen return szOrdProcFmt;
2241570f08bSMark Jansen }
2251570f08bSMark Jansen return lpProcName;
2261570f08bSMark Jansen }
2271570f08bSMark Jansen
SeiCompareFunctionName(LPCSTR lpProcName1,LPCSTR lpProcName2)2281570f08bSMark Jansen int SeiCompareFunctionName(LPCSTR lpProcName1, LPCSTR lpProcName2)
2291570f08bSMark Jansen {
2301570f08bSMark Jansen BOOL Ord1 = SeiIsOrdinalName(lpProcName1);
2311570f08bSMark Jansen BOOL Ord2 = SeiIsOrdinalName(lpProcName2);
2321570f08bSMark Jansen
2331570f08bSMark Jansen /* One is an ordinal, the other not */
2341570f08bSMark Jansen if (Ord1 != Ord2)
2351570f08bSMark Jansen return 1;
2361570f08bSMark Jansen
2371570f08bSMark Jansen /* Compare ordinals */
2381570f08bSMark Jansen if (Ord1)
2391570f08bSMark Jansen return (ULONG_PTR)lpProcName1 != (ULONG_PTR)lpProcName2;
2401570f08bSMark Jansen
2411570f08bSMark Jansen /* Compare names */
2421570f08bSMark Jansen return strcmp(lpProcName1, lpProcName2);
2431570f08bSMark Jansen }
2441570f08bSMark Jansen
245c2c66affSColin Finck
SeiGetModuleFromAddress(PVOID addr)246c2c66affSColin Finck PVOID SeiGetModuleFromAddress(PVOID addr)
247c2c66affSColin Finck {
248c2c66affSColin Finck PVOID hModule = NULL;
249c2c66affSColin Finck RtlPcToFileHeader(addr, &hModule);
250c2c66affSColin Finck return hModule;
251c2c66affSColin Finck }
252c2c66affSColin Finck
253c2c66affSColin Finck
254c2c66affSColin Finck /* TODO: Guard against recursive calling / calling init multiple times! */
NotifyShims(DWORD dwReason,PVOID Info)255c2c66affSColin Finck VOID NotifyShims(DWORD dwReason, PVOID Info)
256c2c66affSColin Finck {
257c2c66affSColin Finck DWORD n;
258c2c66affSColin Finck
259c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&g_pShimInfo); ++n)
260c2c66affSColin Finck {
261c2c66affSColin Finck PSHIMMODULE pShimModule = *ARRAY_At(&g_pShimInfo, PSHIMMODULE, n);
262c2c66affSColin Finck if (!pShimModule->pNotifyShims)
263c2c66affSColin Finck continue;
264c2c66affSColin Finck
265c2c66affSColin Finck pShimModule->pNotifyShims(dwReason, Info);
266c2c66affSColin Finck }
267c2c66affSColin Finck }
268c2c66affSColin Finck
269c2c66affSColin Finck
270c2c66affSColin Finck
SeiCheckComPlusImage(PVOID BaseAddress)271c2c66affSColin Finck VOID SeiCheckComPlusImage(PVOID BaseAddress)
272c2c66affSColin Finck {
273c2c66affSColin Finck ULONG ComSectionSize;
274c2c66affSColin Finck g_bComPlusImage = RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &ComSectionSize) != NULL;
275c2c66affSColin Finck
276c2c66affSColin Finck SHIMENG_INFO("COM+ executable %s\n", g_bComPlusImage ? "TRUE" : "FALSE");
277c2c66affSColin Finck }
278c2c66affSColin Finck
279c2c66affSColin Finck
SeiGetShimModuleInfo(PVOID BaseAddress)280c2c66affSColin Finck PSHIMMODULE SeiGetShimModuleInfo(PVOID BaseAddress)
281c2c66affSColin Finck {
282c2c66affSColin Finck DWORD n;
283c2c66affSColin Finck
284c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&g_pShimInfo); ++n)
285c2c66affSColin Finck {
286c2c66affSColin Finck PSHIMMODULE pShimModule = *ARRAY_At(&g_pShimInfo, PSHIMMODULE, n);
287c2c66affSColin Finck
288c2c66affSColin Finck if (pShimModule->BaseAddress == BaseAddress)
289c2c66affSColin Finck return pShimModule;
290c2c66affSColin Finck }
291c2c66affSColin Finck return NULL;
292c2c66affSColin Finck }
293c2c66affSColin Finck
SeiCreateShimModuleInfo(PCWSTR DllName,PVOID BaseAddress)294c2c66affSColin Finck PSHIMMODULE SeiCreateShimModuleInfo(PCWSTR DllName, PVOID BaseAddress)
295c2c66affSColin Finck {
296c2c66affSColin Finck static const ANSI_STRING GetHookAPIs = RTL_CONSTANT_STRING("GetHookAPIs");
297c2c66affSColin Finck static const ANSI_STRING NotifyShims = RTL_CONSTANT_STRING("NotifyShims");
298c2c66affSColin Finck PSHIMMODULE* pData, Data;
299c2c66affSColin Finck PVOID pGetHookAPIs, pNotifyShims;
300c2c66affSColin Finck
301c2c66affSColin Finck if (!NT_SUCCESS(LdrGetProcedureAddress(BaseAddress, (PANSI_STRING)&GetHookAPIs, 0, &pGetHookAPIs)) ||
302c2c66affSColin Finck !NT_SUCCESS(LdrGetProcedureAddress(BaseAddress, (PANSI_STRING)&NotifyShims, 0, &pNotifyShims)))
303c2c66affSColin Finck {
304c2c66affSColin Finck SHIMENG_WARN("Failed to resolve entry points for %S\n", DllName);
305c2c66affSColin Finck return NULL;
306c2c66affSColin Finck }
307c2c66affSColin Finck
308c2c66affSColin Finck pData = ARRAY_Append(&g_pShimInfo, PSHIMMODULE);
309c2c66affSColin Finck if (!pData)
310c2c66affSColin Finck return NULL;
311c2c66affSColin Finck
312c2c66affSColin Finck *pData = SeiAlloc(sizeof(SHIMMODULE));
313c2c66affSColin Finck
314c2c66affSColin Finck Data = *pData;
315c2c66affSColin Finck
316c2c66affSColin Finck RtlCreateUnicodeString(&Data->Name, DllName);
317c2c66affSColin Finck Data->BaseAddress = BaseAddress;
318c2c66affSColin Finck
319c2c66affSColin Finck Data->pGetHookAPIs = pGetHookAPIs;
320c2c66affSColin Finck Data->pNotifyShims = pNotifyShims;
321c2c66affSColin Finck
322c2c66affSColin Finck ARRAY_Init(&Data->EnabledShims, PSHIMINFO);
323c2c66affSColin Finck
324c2c66affSColin Finck return Data;
325c2c66affSColin Finck }
326c2c66affSColin Finck
SeiAppendHookInfo(PSHIMMODULE pShimModuleInfo,PHOOKAPIEX pHookApi,DWORD dwHookCount,PCWSTR ShimName)327c2c66affSColin Finck PSHIMINFO SeiAppendHookInfo(PSHIMMODULE pShimModuleInfo, PHOOKAPIEX pHookApi, DWORD dwHookCount, PCWSTR ShimName)
328c2c66affSColin Finck {
329c2c66affSColin Finck PSHIMINFO* pData, Data;
330c2c66affSColin Finck
331c2c66affSColin Finck pData = ARRAY_Append(&pShimModuleInfo->EnabledShims, PSHIMINFO);
332c2c66affSColin Finck if (!pData)
333c2c66affSColin Finck return NULL;
334c2c66affSColin Finck
335c2c66affSColin Finck *pData = SeiAlloc(sizeof(SHIMINFO));
336c2c66affSColin Finck Data = *pData;
337c2c66affSColin Finck
338c2c66affSColin Finck if (!Data)
339c2c66affSColin Finck return NULL;
340c2c66affSColin Finck
341c2c66affSColin Finck Data->ShimName = SdbpStrDup(ShimName);
342c2c66affSColin Finck if (!Data->ShimName)
343c2c66affSColin Finck return NULL;
344c2c66affSColin Finck
345c2c66affSColin Finck Data->pHookApi = pHookApi;
346c2c66affSColin Finck Data->dwHookCount = dwHookCount;
347c2c66affSColin Finck Data->pShimModule = pShimModuleInfo;
348c2c66affSColin Finck ARRAY_Init(&Data->InExclude, INEXCLUDE);
349c2c66affSColin Finck return Data;
350c2c66affSColin Finck }
351c2c66affSColin Finck
SeiFindHookModuleInfo(PUNICODE_STRING ModuleName,PVOID BaseAddress)352c2c66affSColin Finck PHOOKMODULEINFO SeiFindHookModuleInfo(PUNICODE_STRING ModuleName, PVOID BaseAddress)
353c2c66affSColin Finck {
354c2c66affSColin Finck DWORD n;
355c2c66affSColin Finck
3565f52a61eSMark Jansen if (ModuleName == NULL && BaseAddress == NULL)
3575f52a61eSMark Jansen {
3585f52a61eSMark Jansen BaseAddress = NtCurrentPeb()->ImageBaseAddress;
3595f52a61eSMark Jansen }
3605f52a61eSMark Jansen
361c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&g_pHookArray); ++n)
362c2c66affSColin Finck {
363c2c66affSColin Finck PHOOKMODULEINFO pModuleInfo = ARRAY_At(&g_pHookArray, HOOKMODULEINFO, n);
364c2c66affSColin Finck
365c2c66affSColin Finck if (BaseAddress && BaseAddress == pModuleInfo->BaseAddress)
366c2c66affSColin Finck return pModuleInfo;
367c2c66affSColin Finck
368c2c66affSColin Finck if (!BaseAddress && RtlEqualUnicodeString(ModuleName, &pModuleInfo->Name, TRUE))
369c2c66affSColin Finck return pModuleInfo;
370c2c66affSColin Finck }
371c2c66affSColin Finck
372c2c66affSColin Finck return NULL;
373c2c66affSColin Finck }
374c2c66affSColin Finck
SeiFindHookModuleInfoForImportDescriptor(PBYTE DllBase,PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor)375c2c66affSColin Finck PHOOKMODULEINFO SeiFindHookModuleInfoForImportDescriptor(PBYTE DllBase, PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor)
376c2c66affSColin Finck {
377c2c66affSColin Finck UNICODE_STRING DllName;
378c2c66affSColin Finck PVOID DllHandle;
379c2c66affSColin Finck NTSTATUS Success;
380c2c66affSColin Finck
381c2c66affSColin Finck if (!RtlCreateUnicodeStringFromAsciiz(&DllName, (PCSZ)(DllBase + ImportDescriptor->Name)))
382c2c66affSColin Finck {
383c2c66affSColin Finck SHIMENG_FAIL("Unable to convert dll name to unicode\n");
384c2c66affSColin Finck return NULL;
385c2c66affSColin Finck }
386c2c66affSColin Finck
387c2c66affSColin Finck Success = LdrGetDllHandle(NULL, NULL, &DllName, &DllHandle);
388c2c66affSColin Finck
389c2c66affSColin Finck if (!NT_SUCCESS(Success))
390c2c66affSColin Finck {
391511e7935SMark Jansen SHIMENG_FAIL("Unable to get module handle for %wZ (%p)\n", &DllName, DllBase);
392511e7935SMark Jansen RtlFreeUnicodeString(&DllName);
393511e7935SMark Jansen
394c2c66affSColin Finck return NULL;
395c2c66affSColin Finck }
396511e7935SMark Jansen RtlFreeUnicodeString(&DllName);
397c2c66affSColin Finck
398c2c66affSColin Finck return SeiFindHookModuleInfo(NULL, DllHandle);
399c2c66affSColin Finck }
400c2c66affSColin Finck
SeiGetStringPtr(PDB pdb,TAGID tag,TAG type)401c2c66affSColin Finck static LPCWSTR SeiGetStringPtr(PDB pdb, TAGID tag, TAG type)
402c2c66affSColin Finck {
403c2c66affSColin Finck TAGID tagEntry = SdbFindFirstTag(pdb, tag, type);
404c2c66affSColin Finck if (tagEntry == TAGID_NULL)
405c2c66affSColin Finck return NULL;
406c2c66affSColin Finck
407c2c66affSColin Finck return SdbGetStringTagPtr(pdb, tagEntry);
408c2c66affSColin Finck }
409c2c66affSColin Finck
SeiGetDWORD(PDB pdb,TAGID tag,TAG type)410c2c66affSColin Finck static DWORD SeiGetDWORD(PDB pdb, TAGID tag, TAG type)
411c2c66affSColin Finck {
412c2c66affSColin Finck TAGID tagEntry = SdbFindFirstTag(pdb, tag, type);
413c2c66affSColin Finck if (tagEntry == TAGID_NULL)
414c2c66affSColin Finck return 0;
415c2c66affSColin Finck
4167630bb0eSMark Jansen return SdbReadDWORDTag(pdb, tagEntry, 0);
417c2c66affSColin Finck }
418c2c66affSColin Finck
SeiGetQWORD(PDB pdb,TAGID tag,TAG type)4197630bb0eSMark Jansen static QWORD SeiGetQWORD(PDB pdb, TAGID tag, TAG type)
4207630bb0eSMark Jansen {
4217630bb0eSMark Jansen TAGID tagEntry = SdbFindFirstTag(pdb, tag, type);
4227630bb0eSMark Jansen if (tagEntry == TAGID_NULL)
4237630bb0eSMark Jansen return 0;
4247630bb0eSMark Jansen
4257630bb0eSMark Jansen return SdbReadQWORDTag(pdb, tagEntry, 0);
4267630bb0eSMark Jansen }
427c2c66affSColin Finck
SeiAddShim(TAGREF trShimRef,PARRAY pShimRef)428c2c66affSColin Finck static VOID SeiAddShim(TAGREF trShimRef, PARRAY pShimRef)
429c2c66affSColin Finck {
430c2c66affSColin Finck TAGREF* Data;
431c2c66affSColin Finck
432c2c66affSColin Finck Data = ARRAY_Append(pShimRef, TAGREF);
433c2c66affSColin Finck if (!Data)
434c2c66affSColin Finck return;
435c2c66affSColin Finck
436c2c66affSColin Finck *Data = trShimRef;
437c2c66affSColin Finck }
438c2c66affSColin Finck
SeiAddFlag(PDB pdb,TAGID tiFlagRef,PFLAGINFO pFlagInfo)4397630bb0eSMark Jansen static VOID SeiAddFlag(PDB pdb, TAGID tiFlagRef, PFLAGINFO pFlagInfo)
4407630bb0eSMark Jansen {
4417630bb0eSMark Jansen ULARGE_INTEGER Flag;
4427630bb0eSMark Jansen
4437630bb0eSMark Jansen /* Resolve the FLAG_REF to the real FLAG node */
4447630bb0eSMark Jansen TAGID FlagTag = SeiGetDWORD(pdb, tiFlagRef, TAG_FLAG_TAGID);
4457630bb0eSMark Jansen
4467630bb0eSMark Jansen if (FlagTag == TAGID_NULL)
4477630bb0eSMark Jansen return;
4487630bb0eSMark Jansen
4497630bb0eSMark Jansen pFlagInfo->AppCompatFlags.QuadPart |= SeiGetQWORD(pdb, FlagTag, TAG_FLAG_MASK_KERNEL);
4507630bb0eSMark Jansen pFlagInfo->AppCompatFlagsUser.QuadPart |= SeiGetQWORD(pdb, FlagTag, TAG_FLAG_MASK_USER);
4517630bb0eSMark Jansen Flag.QuadPart = SeiGetQWORD(pdb, FlagTag, TAG_FLAG_PROCESSPARAM);
4527630bb0eSMark Jansen pFlagInfo->ProcessParameters_Flags |= Flag.LowPart;
4537630bb0eSMark Jansen }
4547630bb0eSMark Jansen
455c2c66affSColin Finck /* Propagate layers to child processes */
SeiSetLayerEnvVar(LPCWSTR wszLayer)456c2c66affSColin Finck static VOID SeiSetLayerEnvVar(LPCWSTR wszLayer)
457c2c66affSColin Finck {
458c2c66affSColin Finck NTSTATUS Status;
459c2c66affSColin Finck UNICODE_STRING VarName = RTL_CONSTANT_STRING(L"__COMPAT_LAYER");
460c2c66affSColin Finck UNICODE_STRING Value;
461c2c66affSColin Finck
462c2c66affSColin Finck RtlInitUnicodeString(&Value, wszLayer);
463c2c66affSColin Finck
464c2c66affSColin Finck Status = RtlSetEnvironmentVariable(NULL, &VarName, &Value);
465c2c66affSColin Finck if (NT_SUCCESS(Status))
4661570f08bSMark Jansen SHIMENG_INFO("%wZ=%wZ\n", &VarName, &Value);
467c2c66affSColin Finck else
468c2c66affSColin Finck SHIMENG_FAIL("Failed to set %wZ: 0x%x\n", &VarName, Status);
469c2c66affSColin Finck }
470c2c66affSColin Finck
471c2c66affSColin Finck #define MAX_LAYER_LENGTH 256
472c2c66affSColin Finck
473c2c66affSColin Finck /* Translate all Exe and Layer entries to Shims, and propagate all layers */
SeiBuildShimRefArray(HSDB hsdb,SDBQUERYRESULT * pQuery,PARRAY pShimRef,PFLAGINFO pFlagInfo)4747630bb0eSMark Jansen static VOID SeiBuildShimRefArray(HSDB hsdb, SDBQUERYRESULT* pQuery, PARRAY pShimRef, PFLAGINFO pFlagInfo)
475c2c66affSColin Finck {
476c2c66affSColin Finck WCHAR wszLayerEnvVar[MAX_LAYER_LENGTH] = { 0 };
477c2c66affSColin Finck DWORD n;
478c2c66affSColin Finck
479c2c66affSColin Finck for (n = 0; n < pQuery->dwExeCount; ++n)
480c2c66affSColin Finck {
481c2c66affSColin Finck PDB pdb;
482c2c66affSColin Finck TAGID tag;
483c2c66affSColin Finck if (SdbTagRefToTagID(hsdb, pQuery->atrExes[n], &pdb, &tag))
484c2c66affSColin Finck {
485c2c66affSColin Finck LPCWSTR ExeName = SeiGetStringPtr(pdb, tag, TAG_NAME);
486c2c66affSColin Finck TAGID ShimRef = SdbFindFirstTag(pdb, tag, TAG_SHIM_REF);
4877630bb0eSMark Jansen TAGID FlagRef = SdbFindFirstTag(pdb, tag, TAG_FLAG_REF);
488c2c66affSColin Finck
489c2c66affSColin Finck if (ExeName)
490c2c66affSColin Finck SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(Exe(%S))\n", ExeName);
491c2c66affSColin Finck
492c2c66affSColin Finck while (ShimRef != TAGID_NULL)
493c2c66affSColin Finck {
494c2c66affSColin Finck TAGREF trShimRef;
495c2c66affSColin Finck if (SdbTagIDToTagRef(hsdb, pdb, ShimRef, &trShimRef))
496c2c66affSColin Finck SeiAddShim(trShimRef, pShimRef);
497c2c66affSColin Finck
498c2c66affSColin Finck ShimRef = SdbFindNextTag(pdb, tag, ShimRef);
499c2c66affSColin Finck }
500c2c66affSColin Finck
5017630bb0eSMark Jansen while (FlagRef != TAGID_NULL)
5027630bb0eSMark Jansen {
5037630bb0eSMark Jansen SeiAddFlag(pdb, FlagRef, pFlagInfo);
5047630bb0eSMark Jansen
5057630bb0eSMark Jansen FlagRef = SdbFindNextTag(pdb, tag, FlagRef);
5067630bb0eSMark Jansen }
507c2c66affSColin Finck }
508c2c66affSColin Finck }
509c2c66affSColin Finck
510c2c66affSColin Finck
511c2c66affSColin Finck for (n = 0; n < pQuery->dwLayerCount; ++n)
512c2c66affSColin Finck {
513c2c66affSColin Finck PDB pdb;
514c2c66affSColin Finck TAGID tag;
515c2c66affSColin Finck if (SdbTagRefToTagID(hsdb, pQuery->atrLayers[n], &pdb, &tag))
516c2c66affSColin Finck {
517c2c66affSColin Finck LPCWSTR LayerName = SeiGetStringPtr(pdb, tag, TAG_NAME);
518c2c66affSColin Finck TAGID ShimRef = SdbFindFirstTag(pdb, tag, TAG_SHIM_REF);
5197630bb0eSMark Jansen TAGID FlagRef = SdbFindFirstTag(pdb, tag, TAG_FLAG_REF);
5207630bb0eSMark Jansen
521c2c66affSColin Finck if (LayerName)
522c2c66affSColin Finck {
523c2c66affSColin Finck HRESULT hr;
524c2c66affSColin Finck SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(Layer(%S))\n", LayerName);
525c2c66affSColin Finck if (wszLayerEnvVar[0])
526c2c66affSColin Finck StringCchCatW(wszLayerEnvVar, ARRAYSIZE(wszLayerEnvVar), L" ");
527c2c66affSColin Finck hr = StringCchCatW(wszLayerEnvVar, ARRAYSIZE(wszLayerEnvVar), LayerName);
528c2c66affSColin Finck if (!SUCCEEDED(hr))
529c2c66affSColin Finck {
530c2c66affSColin Finck SHIMENG_FAIL("Unable to append %S\n", LayerName);
531c2c66affSColin Finck }
532c2c66affSColin Finck }
533c2c66affSColin Finck
534c2c66affSColin Finck while (ShimRef != TAGID_NULL)
535c2c66affSColin Finck {
536c2c66affSColin Finck TAGREF trShimRef;
537c2c66affSColin Finck if (SdbTagIDToTagRef(hsdb, pdb, ShimRef, &trShimRef))
538c2c66affSColin Finck SeiAddShim(trShimRef, pShimRef);
539c2c66affSColin Finck
540c2c66affSColin Finck ShimRef = SdbFindNextTag(pdb, tag, ShimRef);
541c2c66affSColin Finck }
542c2c66affSColin Finck
5437630bb0eSMark Jansen while (FlagRef != TAGID_NULL)
5447630bb0eSMark Jansen {
5457630bb0eSMark Jansen SeiAddFlag(pdb, FlagRef, pFlagInfo);
5467630bb0eSMark Jansen
5477630bb0eSMark Jansen FlagRef = SdbFindNextTag(pdb, tag, FlagRef);
5487630bb0eSMark Jansen }
549c2c66affSColin Finck }
550c2c66affSColin Finck }
551c2c66affSColin Finck if (wszLayerEnvVar[0])
552c2c66affSColin Finck SeiSetLayerEnvVar(wszLayerEnvVar);
553c2c66affSColin Finck }
554c2c66affSColin Finck
555c2c66affSColin Finck /* Given the hooks from one shim, find the relevant modules and store the combination of module + hook */
SeiAddHooks(PHOOKAPIEX hooks,DWORD dwHookCount,PSHIMINFO pShim)556c2c66affSColin Finck VOID SeiAddHooks(PHOOKAPIEX hooks, DWORD dwHookCount, PSHIMINFO pShim)
557c2c66affSColin Finck {
558c2c66affSColin Finck DWORD n, j;
559c2c66affSColin Finck UNICODE_STRING UnicodeModName;
560c2c66affSColin Finck WCHAR Buf[512];
561c2c66affSColin Finck
562c2c66affSColin Finck RtlInitEmptyUnicodeString(&UnicodeModName, Buf, sizeof(Buf));
563c2c66affSColin Finck
564c2c66affSColin Finck for (n = 0; n < dwHookCount; ++n)
565c2c66affSColin Finck {
566c2c66affSColin Finck ANSI_STRING AnsiString;
567c2c66affSColin Finck PVOID DllHandle;
568c2c66affSColin Finck PHOOKAPIEX hook = hooks + n;
569c2c66affSColin Finck PHOOKAPIEX* pHookApi;
570c2c66affSColin Finck PHOOKMODULEINFO HookModuleInfo;
571c2c66affSColin Finck
572c2c66affSColin Finck RtlInitAnsiString(&AnsiString, hook->LibraryName);
573c2c66affSColin Finck if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeModName, &AnsiString, FALSE)))
574c2c66affSColin Finck {
575c2c66affSColin Finck SHIMENG_FAIL("Unable to convert %s to Unicode\n", hook->LibraryName);
576c2c66affSColin Finck continue;
577c2c66affSColin Finck }
578c2c66affSColin Finck
579c2c66affSColin Finck if (NT_SUCCESS(LdrGetDllHandle(NULL, 0, &UnicodeModName, &DllHandle)))
580c2c66affSColin Finck {
581c2c66affSColin Finck HookModuleInfo = SeiFindHookModuleInfo(NULL, DllHandle);
582c2c66affSColin Finck }
583c2c66affSColin Finck else
584c2c66affSColin Finck {
585c2c66affSColin Finck HookModuleInfo = SeiFindHookModuleInfo(&UnicodeModName, NULL);
586c2c66affSColin Finck DllHandle = NULL;
587c2c66affSColin Finck }
588c2c66affSColin Finck
589c2c66affSColin Finck if (!HookModuleInfo)
590c2c66affSColin Finck {
591c2c66affSColin Finck HookModuleInfo = ARRAY_Append(&g_pHookArray, HOOKMODULEINFO);
592c2c66affSColin Finck if (!HookModuleInfo)
593c2c66affSColin Finck continue;
594c2c66affSColin Finck
595c2c66affSColin Finck HookModuleInfo->BaseAddress = DllHandle;
596c2c66affSColin Finck ARRAY_Init(&HookModuleInfo->HookApis, PHOOKAPIEX);
597c2c66affSColin Finck RtlCreateUnicodeString(&HookModuleInfo->Name, UnicodeModName.Buffer);
598c2c66affSColin Finck }
599c2c66affSColin Finck
600c2c66affSColin Finck hook->pShimInfo = pShim;
601c2c66affSColin Finck
602c2c66affSColin Finck for (j = 0; j < ARRAY_Size(&HookModuleInfo->HookApis); ++j)
603c2c66affSColin Finck {
604c2c66affSColin Finck PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX, j);
6051570f08bSMark Jansen int CmpResult = SeiCompareFunctionName(hook->FunctionName, HookApi->FunctionName);
606c2c66affSColin Finck if (CmpResult == 0)
607c2c66affSColin Finck {
608ee62837eSMark Jansen while (HookApi->ApiLink)
609ee62837eSMark Jansen {
610ee62837eSMark Jansen HookApi = HookApi->ApiLink;
611ee62837eSMark Jansen }
612ee62837eSMark Jansen HookApi->ApiLink = hook;
613ee62837eSMark Jansen hook = NULL;
614ee62837eSMark Jansen break;
615c2c66affSColin Finck }
616c2c66affSColin Finck }
617ee62837eSMark Jansen /* No place found yet, append it */
618ee62837eSMark Jansen if (hook)
619ee62837eSMark Jansen {
620c2c66affSColin Finck pHookApi = ARRAY_Append(&HookModuleInfo->HookApis, PHOOKAPIEX);
6216969e85bSMark Jansen if (pHookApi)
622c2c66affSColin Finck *pHookApi = hook;
623c2c66affSColin Finck }
624c2c66affSColin Finck }
625ee62837eSMark Jansen }
626c2c66affSColin Finck
627c2c66affSColin Finck /* Check if we should fake the return from GetProcAddress (because we also redirected the iat for this module) */
StubGetProcAddress(HINSTANCE hModule,LPCSTR lpProcName)628c2c66affSColin Finck FARPROC WINAPI StubGetProcAddress(HINSTANCE hModule, LPCSTR lpProcName)
629c2c66affSColin Finck {
630c2c66affSColin Finck PVOID Addr = _ReturnAddress();
631c2c66affSColin Finck PHOOKMODULEINFO HookModuleInfo;
632c2c66affSColin Finck FARPROC proc = ((GETPROCADDRESSPROC)g_IntHookEx[0].OriginalFunction)(hModule, lpProcName);
6331570f08bSMark Jansen char szOrdProcFmt[10];
634c2c66affSColin Finck
635c2c66affSColin Finck Addr = SeiGetModuleFromAddress(Addr);
636c2c66affSColin Finck if (SE_IsShimDll(Addr))
637c2c66affSColin Finck {
6381570f08bSMark Jansen SHIMENG_MSG("Not touching GetProcAddress for shim dll (%p!%s)", hModule, SeiPrintFunctionName(lpProcName, szOrdProcFmt));
639c2c66affSColin Finck return proc;
640c2c66affSColin Finck }
641c2c66affSColin Finck
6421570f08bSMark Jansen SHIMENG_INFO("(GetProcAddress(%p!%s) => %p\n", hModule, SeiPrintFunctionName(lpProcName, szOrdProcFmt), proc);
643c2c66affSColin Finck
644c2c66affSColin Finck HookModuleInfo = SeiFindHookModuleInfo(NULL, hModule);
645c2c66affSColin Finck
6461570f08bSMark Jansen if (HookModuleInfo)
647c2c66affSColin Finck {
648c2c66affSColin Finck DWORD n;
649c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&HookModuleInfo->HookApis); ++n)
650c2c66affSColin Finck {
651c2c66affSColin Finck PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX, n);
6521570f08bSMark Jansen int CmpResult = SeiCompareFunctionName(lpProcName, HookApi->FunctionName);
653c2c66affSColin Finck if (CmpResult == 0)
654c2c66affSColin Finck {
655c2c66affSColin Finck SHIMENG_MSG("Redirecting %p to %p\n", proc, HookApi->ReplacementFunction);
656c2c66affSColin Finck proc = HookApi->ReplacementFunction;
657c2c66affSColin Finck break;
658c2c66affSColin Finck }
659c2c66affSColin Finck }
660c2c66affSColin Finck }
661c2c66affSColin Finck
662c2c66affSColin Finck return proc;
663c2c66affSColin Finck }
664c2c66affSColin Finck
SeiResolveAPI(PHOOKMODULEINFO HookModuleInfo)665ee62837eSMark Jansen VOID SeiResolveAPI(PHOOKMODULEINFO HookModuleInfo)
666ee62837eSMark Jansen {
667ee62837eSMark Jansen DWORD n;
668ee62837eSMark Jansen ANSI_STRING AnsiString;
669ee62837eSMark Jansen
670ee62837eSMark Jansen ASSERT(HookModuleInfo->BaseAddress != NULL);
671ee62837eSMark Jansen
672ee62837eSMark Jansen for (n = 0; n < ARRAY_Size(&HookModuleInfo->HookApis); ++n)
673ee62837eSMark Jansen {
6741570f08bSMark Jansen NTSTATUS Status;
675ee62837eSMark Jansen PVOID ProcAddress;
676ee62837eSMark Jansen PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX, n);
677ee62837eSMark Jansen
6781570f08bSMark Jansen if (!SeiIsOrdinalName(HookApi->FunctionName))
679ee62837eSMark Jansen {
6801570f08bSMark Jansen RtlInitAnsiString(&AnsiString, HookApi->FunctionName);
6811570f08bSMark Jansen Status = LdrGetProcedureAddress(HookModuleInfo->BaseAddress, &AnsiString, 0, &ProcAddress);
6821570f08bSMark Jansen }
6831570f08bSMark Jansen else
6841570f08bSMark Jansen {
6851570f08bSMark Jansen Status = LdrGetProcedureAddress(HookModuleInfo->BaseAddress, NULL, (ULONG_PTR)HookApi->FunctionName, &ProcAddress);
6861570f08bSMark Jansen }
6871570f08bSMark Jansen
6881570f08bSMark Jansen if (!NT_SUCCESS(Status))
6891570f08bSMark Jansen {
6901570f08bSMark Jansen char szOrdProcFmt[10];
6911570f08bSMark Jansen LPCSTR lpFunctionName = SeiPrintFunctionName(HookApi->FunctionName, szOrdProcFmt);
6921570f08bSMark Jansen SHIMENG_FAIL("Unable to retrieve %s!%s\n", HookApi->LibraryName, lpFunctionName);
693ee62837eSMark Jansen continue;
694ee62837eSMark Jansen }
695ee62837eSMark Jansen
696ee62837eSMark Jansen HookApi->OriginalFunction = ProcAddress;
697ee62837eSMark Jansen if (HookApi->ApiLink)
698ee62837eSMark Jansen {
699ee62837eSMark Jansen SHIMENG_MSG("TODO: Figure out how to handle conflicting In/Exports with ApiLink!\n");
700ee62837eSMark Jansen }
701ee62837eSMark Jansen while (HookApi->ApiLink)
702ee62837eSMark Jansen {
703ee62837eSMark Jansen HookApi->ApiLink->OriginalFunction = HookApi->OriginalFunction;
704ee62837eSMark Jansen HookApi->OriginalFunction = HookApi->ApiLink->ReplacementFunction;
705ee62837eSMark Jansen HookApi = HookApi->ApiLink;
706ee62837eSMark Jansen }
707ee62837eSMark Jansen }
708ee62837eSMark Jansen }
709ee62837eSMark Jansen
710c2c66affSColin Finck /* Walk all shim modules / enabled shims, and add their hooks */
SeiResolveAPIs(VOID)711c2c66affSColin Finck VOID SeiResolveAPIs(VOID)
712c2c66affSColin Finck {
713ee62837eSMark Jansen DWORD n;
714ee62837eSMark Jansen
715ee62837eSMark Jansen for (n = 0; n < ARRAY_Size(&g_pHookArray); ++n)
716ee62837eSMark Jansen {
717ee62837eSMark Jansen PHOOKMODULEINFO pModuleInfo = ARRAY_At(&g_pHookArray, HOOKMODULEINFO, n);
718ee62837eSMark Jansen
719ee62837eSMark Jansen /* Is this module loaded? */
720ee62837eSMark Jansen if (pModuleInfo->BaseAddress)
721ee62837eSMark Jansen {
722ee62837eSMark Jansen SeiResolveAPI(pModuleInfo);
723ee62837eSMark Jansen }
724ee62837eSMark Jansen }
725ee62837eSMark Jansen }
726ee62837eSMark Jansen
SeiCombineHookInfo(VOID)727ee62837eSMark Jansen VOID SeiCombineHookInfo(VOID)
728ee62837eSMark Jansen {
729c2c66affSColin Finck DWORD mod, n;
730c2c66affSColin Finck
731c2c66affSColin Finck /* Enumerate all Shim modules */
732c2c66affSColin Finck for (mod = 0; mod < ARRAY_Size(&g_pShimInfo); ++mod)
733c2c66affSColin Finck {
734c2c66affSColin Finck PSHIMMODULE pShimModule = *ARRAY_At(&g_pShimInfo, PSHIMMODULE, mod);
735c2c66affSColin Finck DWORD dwShimCount = ARRAY_Size(&pShimModule->EnabledShims);
736c2c66affSColin Finck
737c2c66affSColin Finck /* Enumerate all Shims */
738c2c66affSColin Finck for (n = 0; n < dwShimCount; ++n)
739c2c66affSColin Finck {
740c2c66affSColin Finck PSHIMINFO pShim = *ARRAY_At(&pShimModule->EnabledShims, PSHIMINFO, n);
741c2c66affSColin Finck
742c2c66affSColin Finck PHOOKAPIEX hooks = pShim->pHookApi;
743c2c66affSColin Finck DWORD dwHookCount = pShim->dwHookCount;
744c2c66affSColin Finck
745c2c66affSColin Finck SeiAddHooks(hooks, dwHookCount, pShim);
746c2c66affSColin Finck }
747c2c66affSColin Finck }
748c2c66affSColin Finck }
749c2c66affSColin Finck
750c2c66affSColin Finck /* If we hooked something, we should also redirect GetProcAddress */
SeiAddInternalHooks(DWORD dwNumHooks)751c2c66affSColin Finck VOID SeiAddInternalHooks(DWORD dwNumHooks)
752c2c66affSColin Finck {
753c2c66affSColin Finck if (dwNumHooks == 0)
754c2c66affSColin Finck {
755c2c66affSColin Finck g_bInternalHooksUsed = FALSE;
756c2c66affSColin Finck return;
757c2c66affSColin Finck }
758c2c66affSColin Finck
759c2c66affSColin Finck SeiAddHooks(g_IntHookEx, ARRAYSIZE(g_IntHookEx), NULL);
760c2c66affSColin Finck g_bInternalHooksUsed = TRUE;
761c2c66affSColin Finck }
762c2c66affSColin Finck
763c2c66affSColin Finck /* Patch one function in the iat */
SeiPatchNewImport(PIMAGE_THUNK_DATA FirstThunk,PHOOKAPIEX HookApi,PLDR_DATA_TABLE_ENTRY LdrEntry)764c2c66affSColin Finck VOID SeiPatchNewImport(PIMAGE_THUNK_DATA FirstThunk, PHOOKAPIEX HookApi, PLDR_DATA_TABLE_ENTRY LdrEntry)
765c2c66affSColin Finck {
766c2c66affSColin Finck ULONG OldProtection = 0;
767c2c66affSColin Finck PVOID Ptr;
768e59d7a56STimo Kreuzer SIZE_T Size;
769c2c66affSColin Finck NTSTATUS Status;
7701570f08bSMark Jansen char szOrdProcFmt[10];
771c2c66affSColin Finck
7721570f08bSMark Jansen SHIMENG_INFO("Hooking API \"%s!%s\" for DLL \"%wZ\"\n", HookApi->LibraryName, SeiPrintFunctionName(HookApi->FunctionName, szOrdProcFmt), &LdrEntry->BaseDllName);
773c2c66affSColin Finck
774c2c66affSColin Finck Ptr = &FirstThunk->u1.Function;
775c2c66affSColin Finck Size = sizeof(FirstThunk->u1.Function);
776c2c66affSColin Finck Status = NtProtectVirtualMemory(NtCurrentProcess(), &Ptr, &Size, PAGE_EXECUTE_READWRITE, &OldProtection);
777c2c66affSColin Finck
778c2c66affSColin Finck if (!NT_SUCCESS(Status))
779c2c66affSColin Finck {
780c2c66affSColin Finck SHIMENG_FAIL("Unable to unprotect 0x%p\n", &FirstThunk->u1.Function);
781c2c66affSColin Finck return;
782c2c66affSColin Finck }
783c2c66affSColin Finck
784c2c66affSColin Finck SHIMENG_INFO("changing 0x%p to 0x%p\n", FirstThunk->u1.Function, HookApi->ReplacementFunction);
7851570f08bSMark Jansen FirstThunk->u1.Function = (ULONG_PTR)HookApi->ReplacementFunction;
786c2c66affSColin Finck
787c2c66affSColin Finck Size = sizeof(FirstThunk->u1.Function);
788c2c66affSColin Finck Status = NtProtectVirtualMemory(NtCurrentProcess(), &Ptr, &Size, OldProtection, &OldProtection);
789c2c66affSColin Finck
790c2c66affSColin Finck if (!NT_SUCCESS(Status))
791c2c66affSColin Finck {
792c2c66affSColin Finck SHIMENG_WARN("Unable to reprotect 0x%p\n", &FirstThunk->u1.Function);
793c2c66affSColin Finck }
794c2c66affSColin Finck }
795c2c66affSColin Finck
796c2c66affSColin Finck
SeiFindInExclude(PARRAY InExclude,PCUNICODE_STRING DllName)797c2c66affSColin Finck PINEXCLUDE SeiFindInExclude(PARRAY InExclude, PCUNICODE_STRING DllName)
798c2c66affSColin Finck {
799c2c66affSColin Finck DWORD n;
800c2c66affSColin Finck
801c2c66affSColin Finck for (n = 0; n < ARRAY_Size(InExclude); ++n)
802c2c66affSColin Finck {
803c2c66affSColin Finck PINEXCLUDE InEx = ARRAY_At(InExclude, INEXCLUDE, n);
804c2c66affSColin Finck
805c2c66affSColin Finck if (RtlEqualUnicodeString(&InEx->Module, DllName, TRUE))
806c2c66affSColin Finck return InEx;
807c2c66affSColin Finck }
808c2c66affSColin Finck
809c2c66affSColin Finck return NULL;
810c2c66affSColin Finck }
811c2c66affSColin Finck
SeiIsExcluded(PLDR_DATA_TABLE_ENTRY LdrEntry,PHOOKAPIEX HookApi)812c2c66affSColin Finck BOOL SeiIsExcluded(PLDR_DATA_TABLE_ENTRY LdrEntry, PHOOKAPIEX HookApi)
813c2c66affSColin Finck {
814c2c66affSColin Finck PSHIMINFO pShimInfo = HookApi->pShimInfo;
815c2c66affSColin Finck PINEXCLUDE InExclude;
816c2c66affSColin Finck BOOL IsExcluded = FALSE;
8171570f08bSMark Jansen char szOrdProcFmt[10];
818c2c66affSColin Finck
819c2c66affSColin Finck if (!pShimInfo)
820c2c66affSColin Finck {
821c2c66affSColin Finck /* Internal hook, do not exclude it */
822c2c66affSColin Finck return FALSE;
823c2c66affSColin Finck }
824c2c66affSColin Finck
825c2c66affSColin Finck /* By default, everything from System32 or WinSxs is excluded */
826c2c66affSColin Finck if (RtlPrefixUnicodeString(&g_System32Directory, &LdrEntry->FullDllName, TRUE) ||
827c2c66affSColin Finck RtlPrefixUnicodeString(&g_SxsDirectory, &LdrEntry->FullDllName, TRUE))
828c2c66affSColin Finck IsExcluded = TRUE;
829c2c66affSColin Finck
830c2c66affSColin Finck InExclude = SeiFindInExclude(&pShimInfo->InExclude, &LdrEntry->BaseDllName);
831c2c66affSColin Finck if (InExclude)
832c2c66affSColin Finck {
833c2c66affSColin Finck /* If it is on the 'exclude' list, bail out */
834c2c66affSColin Finck if (!InExclude->Include)
835c2c66affSColin Finck {
836c2c66affSColin Finck SHIMENG_INFO("Module '%wZ' excluded for shim %S, API '%s!%s', because it on in the exclude list.\n",
8371570f08bSMark Jansen &LdrEntry->BaseDllName, pShimInfo->ShimName, HookApi->LibraryName, SeiPrintFunctionName(HookApi->FunctionName, szOrdProcFmt));
838c2c66affSColin Finck
839c2c66affSColin Finck return TRUE;
840c2c66affSColin Finck }
841c2c66affSColin Finck /* If it is on the 'include' list, override System32 / Winsxs check. */
842c2c66affSColin Finck if (IsExcluded)
843c2c66affSColin Finck {
844c2c66affSColin Finck SHIMENG_INFO("Module '%wZ' included for shim %S, API '%s!%s', because it is on the include list.\n",
8451570f08bSMark Jansen &LdrEntry->BaseDllName, pShimInfo->ShimName, HookApi->LibraryName, SeiPrintFunctionName(HookApi->FunctionName, szOrdProcFmt));
846c2c66affSColin Finck
847c2c66affSColin Finck }
848c2c66affSColin Finck IsExcluded = FALSE;
849c2c66affSColin Finck }
850c2c66affSColin Finck
851c2c66affSColin Finck if (IsExcluded)
852c2c66affSColin Finck {
853c2c66affSColin Finck SHIMENG_INFO("Module '%wZ' excluded for shim %S, API '%s!%s', because it is in System32/WinSXS.\n",
8541570f08bSMark Jansen &LdrEntry->BaseDllName, pShimInfo->ShimName, HookApi->LibraryName, SeiPrintFunctionName(HookApi->FunctionName, szOrdProcFmt));
855c2c66affSColin Finck }
856c2c66affSColin Finck
857c2c66affSColin Finck return IsExcluded;
858c2c66affSColin Finck }
859c2c66affSColin Finck
SeiAppendInExclude(PARRAY dest,PCWSTR ModuleName,BOOL IsInclude)860c2c66affSColin Finck VOID SeiAppendInExclude(PARRAY dest, PCWSTR ModuleName, BOOL IsInclude)
861c2c66affSColin Finck {
862c2c66affSColin Finck PINEXCLUDE InExclude;
863c2c66affSColin Finck UNICODE_STRING ModuleNameU;
864c2c66affSColin Finck RtlInitUnicodeString(&ModuleNameU, ModuleName);
865c2c66affSColin Finck
866c2c66affSColin Finck InExclude = SeiFindInExclude(dest, &ModuleNameU);
867c2c66affSColin Finck if (InExclude)
868c2c66affSColin Finck {
869c2c66affSColin Finck InExclude->Include = IsInclude;
870c2c66affSColin Finck return;
871c2c66affSColin Finck }
872c2c66affSColin Finck
873c2c66affSColin Finck InExclude = ARRAY_Append(dest, INEXCLUDE);
874c2c66affSColin Finck if (InExclude)
875c2c66affSColin Finck {
876c2c66affSColin Finck PCWSTR ModuleNameCopy = SdbpStrDup(ModuleName);
877c2c66affSColin Finck RtlInitUnicodeString(&InExclude->Module, ModuleNameCopy);
878c2c66affSColin Finck InExclude->Include = IsInclude;
879c2c66affSColin Finck }
880c2c66affSColin Finck }
881c2c66affSColin Finck
88293e88edbSMark Jansen /* Read the INEXCLUD tags from a given parent tag
88393e88edbSMark Jansen FIXME:
88493e88edbSMark Jansen Some observed tags:
88593e88edbSMark Jansen '*' with include
88693e88edbSMark Jansen '$' with include, followed by '*' without include
88793e88edbSMark Jansen Include list logging, referring to: (MODE: EA)
88893e88edbSMark Jansen */
SeiReadInExclude(PDB pdb,TAGID parent,PARRAY dest)889c2c66affSColin Finck VOID SeiReadInExclude(PDB pdb, TAGID parent, PARRAY dest)
890c2c66affSColin Finck {
891c2c66affSColin Finck TAGID InExcludeTag;
892c2c66affSColin Finck
893c2c66affSColin Finck InExcludeTag = SdbFindFirstTag(pdb, parent, TAG_INEXCLUD);
894c2c66affSColin Finck
895c2c66affSColin Finck while (InExcludeTag != TAGID_NULL)
896c2c66affSColin Finck {
897c2c66affSColin Finck PCWSTR ModuleName;
898c2c66affSColin Finck TAGID ModuleTag = SdbFindFirstTag(pdb, InExcludeTag, TAG_MODULE);
899c2c66affSColin Finck TAGID IncludeTag = SdbFindFirstTag(pdb, InExcludeTag, TAG_INCLUDE);
900c2c66affSColin Finck
901c2c66affSColin Finck ModuleName = SdbGetStringTagPtr(pdb, ModuleTag);
902c2c66affSColin Finck if (ModuleName)
903c2c66affSColin Finck {
904c2c66affSColin Finck SeiAppendInExclude(dest, ModuleName, IncludeTag != TAGID_NULL);
905c2c66affSColin Finck }
906c2c66affSColin Finck else
907c2c66affSColin Finck {
908c2c66affSColin Finck SHIMENG_WARN("INEXCLUDE without Module: 0x%x\n", InExcludeTag);
909c2c66affSColin Finck }
910c2c66affSColin Finck
911c2c66affSColin Finck InExcludeTag = SdbFindNextTag(pdb, parent, InExcludeTag);
912c2c66affSColin Finck }
913c2c66affSColin Finck }
914c2c66affSColin Finck
SeiBuildGlobalInclExclList(HSDB hsdb)915c2c66affSColin Finck VOID SeiBuildGlobalInclExclList(HSDB hsdb)
916c2c66affSColin Finck {
917c2c66affSColin Finck PDB pdb;
918c2c66affSColin Finck TAGREF tr = TAGREF_ROOT;
919c2c66affSColin Finck TAGID root, db, library;
920c2c66affSColin Finck
921c2c66affSColin Finck if (!SdbTagRefToTagID(hsdb, tr, &pdb, &root))
922c2c66affSColin Finck {
923c2c66affSColin Finck SHIMENG_WARN("Unable to resolve database root\n");
924c2c66affSColin Finck return;
925c2c66affSColin Finck }
926c2c66affSColin Finck db = SdbFindFirstTag(pdb, root, TAG_DATABASE);
927c2c66affSColin Finck if (db == TAGID_NULL)
928c2c66affSColin Finck {
929c2c66affSColin Finck SHIMENG_WARN("Unable to resolve database\n");
930c2c66affSColin Finck return;
931c2c66affSColin Finck }
932c2c66affSColin Finck library = SdbFindFirstTag(pdb, db, TAG_LIBRARY);
933c2c66affSColin Finck if (library == TAGID_NULL)
934c2c66affSColin Finck {
935c2c66affSColin Finck SHIMENG_WARN("Unable to resolve library\n");
936c2c66affSColin Finck return;
937c2c66affSColin Finck }
938c2c66affSColin Finck
939c2c66affSColin Finck SeiReadInExclude(pdb, library, &g_InExclude);
940c2c66affSColin Finck }
941c2c66affSColin Finck
SeiBuildInclExclList(PDB pdb,TAGID ShimTag,PSHIMINFO pShimInfo)942c2c66affSColin Finck VOID SeiBuildInclExclList(PDB pdb, TAGID ShimTag, PSHIMINFO pShimInfo)
943c2c66affSColin Finck {
944c2c66affSColin Finck DWORD n;
945c2c66affSColin Finck
946c2c66affSColin Finck /* First duplicate the global in/excludes */
947c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&g_InExclude); ++n)
948c2c66affSColin Finck {
949c2c66affSColin Finck PINEXCLUDE InEx = ARRAY_At(&g_InExclude, INEXCLUDE, n);
950c2c66affSColin Finck SeiAppendInExclude(&pShimInfo->InExclude, InEx->Module.Buffer, InEx->Include);
951c2c66affSColin Finck }
952c2c66affSColin Finck
953c2c66affSColin Finck /* Now read this shim's in/excludes (possibly overriding the global ones) */
954c2c66affSColin Finck SeiReadInExclude(pdb, ShimTag, &pShimInfo->InExclude);
955c2c66affSColin Finck }
956c2c66affSColin Finck
957c2c66affSColin Finck /* Given one loaded module, redirect (hook) all functions from the iat that are registered by shims */
SeiHookImports(PLDR_DATA_TABLE_ENTRY LdrEntry)958c2c66affSColin Finck VOID SeiHookImports(PLDR_DATA_TABLE_ENTRY LdrEntry)
959c2c66affSColin Finck {
960c2c66affSColin Finck ULONG Size;
961c2c66affSColin Finck PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
962c2c66affSColin Finck PBYTE DllBase = LdrEntry->DllBase;
963c2c66affSColin Finck
9646abe0e50SMark Jansen if (SE_IsShimDll(DllBase) ||
9656abe0e50SMark Jansen g_hInstance == LdrEntry->DllBase ||
9666abe0e50SMark Jansen RtlEqualUnicodeString(&g_LoadingShimDll, &LdrEntry->BaseDllName, TRUE))
967c2c66affSColin Finck {
968c2c66affSColin Finck SHIMENG_INFO("Skipping shim module 0x%p \"%wZ\"\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
969c2c66affSColin Finck return;
970c2c66affSColin Finck }
971c2c66affSColin Finck
97206c1e134SMark Jansen if (LdrEntry->Flags & LDRP_COMPAT_DATABASE_PROCESSED)
97306c1e134SMark Jansen {
97406c1e134SMark Jansen SHIMENG_INFO("Skipping module 0x%p \"%wZ\" because it was already processed\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
97506c1e134SMark Jansen return;
97606c1e134SMark Jansen }
97706c1e134SMark Jansen
978c2c66affSColin Finck ImportDescriptor = RtlImageDirectoryEntryToData(DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &Size);
979c2c66affSColin Finck if (!ImportDescriptor)
980c2c66affSColin Finck {
981c2c66affSColin Finck SHIMENG_INFO("Skipping module 0x%p \"%wZ\" due to no iat found\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
982c2c66affSColin Finck return;
983c2c66affSColin Finck }
984c2c66affSColin Finck
985c2c66affSColin Finck SHIMENG_INFO("Hooking module 0x%p \"%wZ\"\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
986c2c66affSColin Finck
987c2c66affSColin Finck for ( ;ImportDescriptor->Name && ImportDescriptor->OriginalFirstThunk; ImportDescriptor++)
988c2c66affSColin Finck {
989c2c66affSColin Finck PHOOKMODULEINFO HookModuleInfo;
990c2c66affSColin Finck
991c2c66affSColin Finck /* Do we have hooks for this module? */
992c2c66affSColin Finck HookModuleInfo = SeiFindHookModuleInfoForImportDescriptor(DllBase, ImportDescriptor);
993c2c66affSColin Finck
994c2c66affSColin Finck if (HookModuleInfo)
995c2c66affSColin Finck {
996c2c66affSColin Finck PIMAGE_THUNK_DATA OriginalThunk, FirstThunk;
997c2c66affSColin Finck DWORD n;
998c2c66affSColin Finck
999c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&HookModuleInfo->HookApis); ++n)
1000c2c66affSColin Finck {
1001c2c66affSColin Finck DWORD dwFound = 0;
1002c2c66affSColin Finck PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX, n);
1003c2c66affSColin Finck
1004c2c66affSColin Finck /* Check if this module should be excluded from being hooked (system32/winsxs, global or shim exclude) */
1005c2c66affSColin Finck if (SeiIsExcluded(LdrEntry, HookApi))
1006c2c66affSColin Finck {
1007c2c66affSColin Finck continue;
1008c2c66affSColin Finck }
1009c2c66affSColin Finck
1010c2c66affSColin Finck OriginalThunk = (PIMAGE_THUNK_DATA)(DllBase + ImportDescriptor->OriginalFirstThunk);
1011c2c66affSColin Finck FirstThunk = (PIMAGE_THUNK_DATA)(DllBase + ImportDescriptor->FirstThunk);
1012c2c66affSColin Finck
1013c2c66affSColin Finck /* Walk all imports */
1014c2c66affSColin Finck for (;OriginalThunk->u1.AddressOfData && FirstThunk->u1.Function; OriginalThunk++, FirstThunk++)
1015c2c66affSColin Finck {
10161570f08bSMark Jansen if (!IMAGE_SNAP_BY_ORDINAL(OriginalThunk->u1.Function))
10171570f08bSMark Jansen {
10181570f08bSMark Jansen if (!SeiIsOrdinalName(HookApi->FunctionName))
1019c2c66affSColin Finck {
1020c2c66affSColin Finck PIMAGE_IMPORT_BY_NAME ImportName;
1021c2c66affSColin Finck
10221570f08bSMark Jansen ImportName = (PIMAGE_IMPORT_BY_NAME)(DllBase + OriginalThunk->u1.Function);
1023c2c66affSColin Finck if (!strcmp((PCSTR)ImportName->Name, HookApi->FunctionName))
1024c2c66affSColin Finck {
1025c2c66affSColin Finck SeiPatchNewImport(FirstThunk, HookApi, LdrEntry);
1026c2c66affSColin Finck
1027c2c66affSColin Finck /* Sadly, iat does not have to be sorted, and can even contain duplicate entries. */
1028c2c66affSColin Finck dwFound++;
1029c2c66affSColin Finck }
1030c2c66affSColin Finck }
10311570f08bSMark Jansen }
1032c2c66affSColin Finck else
1033c2c66affSColin Finck {
10341570f08bSMark Jansen if (SeiIsOrdinalName(HookApi->FunctionName))
10351570f08bSMark Jansen {
10361570f08bSMark Jansen if ((PCSTR)IMAGE_ORDINAL(OriginalThunk->u1.Function) == HookApi->FunctionName)
10371570f08bSMark Jansen {
10381570f08bSMark Jansen SeiPatchNewImport(FirstThunk, HookApi, LdrEntry);
10391570f08bSMark Jansen dwFound++;
10401570f08bSMark Jansen }
10411570f08bSMark Jansen }
1042c2c66affSColin Finck }
1043c2c66affSColin Finck }
1044c2c66affSColin Finck
1045c2c66affSColin Finck if (dwFound != 1)
1046c2c66affSColin Finck {
10471570f08bSMark Jansen char szOrdProcFmt[10];
10481570f08bSMark Jansen LPCSTR FuncName = SeiPrintFunctionName(HookApi->FunctionName, szOrdProcFmt);
10491570f08bSMark Jansen
1050c2c66affSColin Finck /* One entry not found. */
1051c2c66affSColin Finck if (!dwFound)
10521570f08bSMark Jansen SHIMENG_INFO("Entry \"%s!%s\" not found for \"%wZ\"\n", HookApi->LibraryName, FuncName, &LdrEntry->BaseDllName);
1053c2c66affSColin Finck else
10541570f08bSMark Jansen SHIMENG_INFO("Entry \"%s!%s\" found %d times for \"%wZ\"\n", HookApi->LibraryName, FuncName, dwFound, &LdrEntry->BaseDllName);
1055c2c66affSColin Finck }
1056c2c66affSColin Finck }
1057c2c66affSColin Finck }
1058c2c66affSColin Finck }
105906c1e134SMark Jansen
106006c1e134SMark Jansen /* Mark this module as processed. */
106106c1e134SMark Jansen LdrEntry->Flags |= LDRP_COMPAT_DATABASE_PROCESSED;
1062c2c66affSColin Finck }
1063c2c66affSColin Finck
1064c2c66affSColin Finck
PatchNewModules(PPEB Peb)1065c2c66affSColin Finck VOID PatchNewModules(PPEB Peb)
1066c2c66affSColin Finck {
1067c2c66affSColin Finck PLIST_ENTRY ListHead, ListEntry;
1068c2c66affSColin Finck PLDR_DATA_TABLE_ENTRY LdrEntry;
1069c2c66affSColin Finck
1070c2c66affSColin Finck ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
1071c2c66affSColin Finck ListEntry = ListHead->Flink;
1072c2c66affSColin Finck
1073c2c66affSColin Finck while (ListHead != ListEntry)
1074c2c66affSColin Finck {
1075c2c66affSColin Finck LdrEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
1076c2c66affSColin Finck SeiHookImports(LdrEntry);
1077c2c66affSColin Finck
1078c2c66affSColin Finck ListEntry = ListEntry->Flink;
1079c2c66affSColin Finck }
1080c2c66affSColin Finck }
1081c2c66affSColin Finck
1082c2c66affSColin Finck
SeiInitPaths(VOID)1083c2c66affSColin Finck VOID SeiInitPaths(VOID)
1084c2c66affSColin Finck {
1085c2c66affSColin Finck #define SYSTEM32 L"\\system32"
1086c2c66affSColin Finck #define WINSXS L"\\winsxs"
1087c2c66affSColin Finck
1088c2c66affSColin Finck PWSTR WindowsDirectory = SdbpStrDup(SharedUserData->NtSystemRoot);
1089c2c66affSColin Finck RtlInitUnicodeString(&g_WindowsDirectory, WindowsDirectory);
1090c2c66affSColin Finck
1091c2c66affSColin Finck g_System32Directory.MaximumLength = g_WindowsDirectory.Length + SdbpStrsize(SYSTEM32);
1092c2c66affSColin Finck g_System32Directory.Buffer = SdbpAlloc(g_System32Directory.MaximumLength);
1093c2c66affSColin Finck RtlCopyUnicodeString(&g_System32Directory, &g_WindowsDirectory);
1094c2c66affSColin Finck RtlAppendUnicodeToString(&g_System32Directory, SYSTEM32);
1095c2c66affSColin Finck
1096c2c66affSColin Finck g_SxsDirectory.MaximumLength = g_WindowsDirectory.Length + SdbpStrsize(WINSXS);
1097c2c66affSColin Finck g_SxsDirectory.Buffer = SdbpAlloc(g_SxsDirectory.MaximumLength);
1098c2c66affSColin Finck RtlCopyUnicodeString(&g_SxsDirectory, &g_WindowsDirectory);
1099c2c66affSColin Finck RtlAppendUnicodeToString(&g_SxsDirectory, WINSXS);
1100c2c66affSColin Finck
1101c2c66affSColin Finck #undef SYSTEM32
1102c2c66affSColin Finck #undef WINSXS
1103c2c66affSColin Finck }
1104c2c66affSColin Finck
SeiSetEntryProcessed(PPEB Peb)11056abe0e50SMark Jansen VOID SeiSetEntryProcessed(PPEB Peb)
11066abe0e50SMark Jansen {
11076abe0e50SMark Jansen PLIST_ENTRY ListHead, Entry;
11086abe0e50SMark Jansen PLDR_DATA_TABLE_ENTRY LdrEntry;
11096abe0e50SMark Jansen
11106abe0e50SMark Jansen ListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
11116abe0e50SMark Jansen Entry = ListHead->Flink;
11126abe0e50SMark Jansen while (Entry != ListHead)
11136abe0e50SMark Jansen {
11146abe0e50SMark Jansen LdrEntry = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
11156abe0e50SMark Jansen Entry = Entry->Flink;
11166abe0e50SMark Jansen
11176abe0e50SMark Jansen if (RtlEqualUnicodeString(&LdrEntry->BaseDllName, &Ntdll, TRUE) ||
11186abe0e50SMark Jansen RtlEqualUnicodeString(&LdrEntry->BaseDllName, &Kernel32, TRUE) ||
11196abe0e50SMark Jansen RtlEqualUnicodeString(&LdrEntry->BaseDllName, &Verifier, TRUE) ||
11206abe0e50SMark Jansen RtlEqualUnicodeString(&LdrEntry->BaseDllName, &g_LoadingShimDll, TRUE) ||
11216abe0e50SMark Jansen SE_IsShimDll(LdrEntry->DllBase) ||
11226abe0e50SMark Jansen (LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
11236abe0e50SMark Jansen {
11246abe0e50SMark Jansen SHIMENG_WARN("Don't mess with 0x%p '%wZ'\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
11256abe0e50SMark Jansen }
11266abe0e50SMark Jansen else
11276abe0e50SMark Jansen {
11286abe0e50SMark Jansen SHIMENG_WARN("Touching 0x%p '%wZ'\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
11296abe0e50SMark Jansen LdrEntry->Flags |= (LDRP_ENTRY_PROCESSED | LDRP_SHIMENG_SUPPRESSED_ENTRY);
11306abe0e50SMark Jansen }
11316abe0e50SMark Jansen }
11326abe0e50SMark Jansen
11336abe0e50SMark Jansen ListHead = &NtCurrentPeb()->Ldr->InMemoryOrderModuleList;
11346abe0e50SMark Jansen Entry = ListHead->Flink;
11356abe0e50SMark Jansen SHIMENG_INFO("In memory:\n");
11366abe0e50SMark Jansen while (Entry != ListHead)
11376abe0e50SMark Jansen {
11386abe0e50SMark Jansen LdrEntry = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
11396abe0e50SMark Jansen Entry = Entry->Flink;
11406abe0e50SMark Jansen
11416abe0e50SMark Jansen SHIMENG_INFO(" 0x%p '%wZ'\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
11426abe0e50SMark Jansen }
11436abe0e50SMark Jansen
11446abe0e50SMark Jansen ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
11456abe0e50SMark Jansen Entry = ListHead->Flink;
11466abe0e50SMark Jansen SHIMENG_INFO("In load:\n");
11476abe0e50SMark Jansen while (Entry != ListHead)
11486abe0e50SMark Jansen {
11496abe0e50SMark Jansen LdrEntry = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
11506abe0e50SMark Jansen Entry = Entry->Flink;
11516abe0e50SMark Jansen
11526abe0e50SMark Jansen SHIMENG_INFO(" 0x%p '%wZ'\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
11536abe0e50SMark Jansen }
11546abe0e50SMark Jansen }
11556abe0e50SMark Jansen
SeiResetEntryProcessed(PPEB Peb)11566abe0e50SMark Jansen VOID SeiResetEntryProcessed(PPEB Peb)
11576abe0e50SMark Jansen {
11586abe0e50SMark Jansen PLIST_ENTRY ListHead, Entry;
11596abe0e50SMark Jansen PLDR_DATA_TABLE_ENTRY LdrEntry;
11606abe0e50SMark Jansen
11616abe0e50SMark Jansen ListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
11626abe0e50SMark Jansen Entry = ListHead->Flink;
11636abe0e50SMark Jansen while (Entry != ListHead)
11646abe0e50SMark Jansen {
11656abe0e50SMark Jansen LdrEntry = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
11666abe0e50SMark Jansen Entry = Entry->Flink;
11676abe0e50SMark Jansen
11686abe0e50SMark Jansen if (SE_IsShimDll(LdrEntry->DllBase) ||
11696abe0e50SMark Jansen g_hInstance == LdrEntry->DllBase ||
11706abe0e50SMark Jansen RtlEqualUnicodeString(&LdrEntry->BaseDllName, &Ntdll, TRUE) ||
11716abe0e50SMark Jansen RtlEqualUnicodeString(&LdrEntry->BaseDllName, &Kernel32, TRUE) ||
11726abe0e50SMark Jansen RtlEqualUnicodeString(&LdrEntry->BaseDllName, &Verifier, TRUE) ||
11736abe0e50SMark Jansen !(LdrEntry->Flags & LDRP_SHIMENG_SUPPRESSED_ENTRY))
11746abe0e50SMark Jansen {
11756abe0e50SMark Jansen SHIMENG_WARN("Don't mess with 0x%p '%wZ'\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
11766abe0e50SMark Jansen }
11776abe0e50SMark Jansen else
11786abe0e50SMark Jansen {
11796abe0e50SMark Jansen SHIMENG_WARN("Resetting 0x%p '%wZ'\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
11806abe0e50SMark Jansen LdrEntry->Flags &= ~(LDRP_ENTRY_PROCESSED | LDRP_SHIMENG_SUPPRESSED_ENTRY);
11816abe0e50SMark Jansen }
11826abe0e50SMark Jansen }
11836abe0e50SMark Jansen }
11846abe0e50SMark Jansen
SeiInit(LPCWSTR ProcessImage,HSDB hsdb,SDBQUERYRESULT * pQuery,BOOLEAN ProcessInit)118593e88edbSMark Jansen VOID SeiInit(LPCWSTR ProcessImage, HSDB hsdb, SDBQUERYRESULT* pQuery, BOOLEAN ProcessInit)
1186c2c66affSColin Finck {
1187c2c66affSColin Finck DWORD n;
1188c2c66affSColin Finck ARRAY ShimRefArray;
1189c2c66affSColin Finck DWORD dwTotalHooks = 0;
11907630bb0eSMark Jansen FLAGINFO ShimFlags;
1191c2c66affSColin Finck
1192c2c66affSColin Finck PPEB Peb = NtCurrentPeb();
1193c2c66affSColin Finck
1194c2c66affSColin Finck /* We should only be called once! */
1195c2c66affSColin Finck ASSERT(g_pShimInfo.ItemSize__ == 0);
1196c2c66affSColin Finck
1197c2c66affSColin Finck ARRAY_Init(&ShimRefArray, TAGREF);
1198c2c66affSColin Finck ARRAY_Init(&g_pShimInfo, PSHIMMODULE);
1199c2c66affSColin Finck ARRAY_Init(&g_pHookArray, HOOKMODULEINFO);
1200c2c66affSColin Finck ARRAY_Init(&g_InExclude, INEXCLUDE);
12017630bb0eSMark Jansen RtlZeroMemory(&ShimFlags, sizeof(ShimFlags));
1202c2c66affSColin Finck
1203c2c66affSColin Finck SeiInitPaths();
1204c2c66affSColin Finck
1205c2c66affSColin Finck SeiCheckComPlusImage(Peb->ImageBaseAddress);
1206c2c66affSColin Finck
120793e88edbSMark Jansen if (ProcessInit)
120893e88edbSMark Jansen {
12096abe0e50SMark Jansen /* Mark all modules loaded until now as 'LDRP_ENTRY_PROCESSED' so that their entrypoint is not called while we are loading shims */
12106abe0e50SMark Jansen SeiSetEntryProcessed(Peb);
121193e88edbSMark Jansen }
12126abe0e50SMark Jansen
1213c2c66affSColin Finck /* TODO:
1214c2c66affSColin Finck if (pQuery->trApphelp)
1215c2c66affSColin Finck SeiDisplayAppHelp(?pQuery->trApphelp?);
1216c2c66affSColin Finck */
1217c2c66affSColin Finck
121893e88edbSMark Jansen SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(ExePath(%S))\n", ProcessImage);
12197630bb0eSMark Jansen SeiBuildShimRefArray(hsdb, pQuery, &ShimRefArray, &ShimFlags);
12207630bb0eSMark Jansen if (ShimFlags.AppCompatFlags.QuadPart)
12217630bb0eSMark Jansen {
12227630bb0eSMark Jansen SeiDbgPrint(SEI_MSG, NULL, "Using KERNEL apphack flags 0x%I64x\n", ShimFlags.AppCompatFlags.QuadPart);
12237630bb0eSMark Jansen Peb->AppCompatFlags.QuadPart |= ShimFlags.AppCompatFlags.QuadPart;
12247630bb0eSMark Jansen }
12257630bb0eSMark Jansen if (ShimFlags.AppCompatFlagsUser.QuadPart)
12267630bb0eSMark Jansen {
12277630bb0eSMark Jansen SeiDbgPrint(SEI_MSG, NULL, "Using USER apphack flags 0x%I64x\n", ShimFlags.AppCompatFlagsUser.QuadPart);
12287630bb0eSMark Jansen Peb->AppCompatFlagsUser.QuadPart |= ShimFlags.AppCompatFlagsUser.QuadPart;
12297630bb0eSMark Jansen }
12307630bb0eSMark Jansen if (ShimFlags.ProcessParameters_Flags)
12317630bb0eSMark Jansen {
12327630bb0eSMark Jansen SeiDbgPrint(SEI_MSG, NULL, "Using ProcessParameters flags 0x%x\n", ShimFlags.ProcessParameters_Flags);
12337630bb0eSMark Jansen Peb->ProcessParameters->Flags |= ShimFlags.ProcessParameters_Flags;
12347630bb0eSMark Jansen }
1235c2c66affSColin Finck SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(Complete)\n");
1236c2c66affSColin Finck
1237c2c66affSColin Finck SHIMENG_INFO("Got %d shims\n", ARRAY_Size(&ShimRefArray));
1238c2c66affSColin Finck SeiBuildGlobalInclExclList(hsdb);
1239c2c66affSColin Finck
1240c2c66affSColin Finck /* Walk all shims referenced (in layers + exes), and load their modules */
1241c2c66affSColin Finck for (n = 0; n < ARRAY_Size(&ShimRefArray); ++n)
1242c2c66affSColin Finck {
1243c2c66affSColin Finck PDB pdb;
1244c2c66affSColin Finck TAGID ShimRef;
1245c2c66affSColin Finck
1246c2c66affSColin Finck TAGREF tr = *ARRAY_At(&ShimRefArray, TAGREF, n);
1247c2c66affSColin Finck
1248c2c66affSColin Finck if (SdbTagRefToTagID(hsdb, tr, &pdb, &ShimRef))
1249c2c66affSColin Finck {
1250c2c66affSColin Finck LPCWSTR ShimName, DllName, CommandLine = NULL;
1251c2c66affSColin Finck TAGID ShimTag;
1252c2c66affSColin Finck WCHAR FullNameBuffer[MAX_PATH];
1253c2c66affSColin Finck UNICODE_STRING UnicodeDllName;
1254c2c66affSColin Finck PVOID BaseAddress;
1255c2c66affSColin Finck PSHIMMODULE pShimModuleInfo = NULL;
1256c2c66affSColin Finck ANSI_STRING AnsiCommandLine = RTL_CONSTANT_STRING("");
1257c2c66affSColin Finck PSHIMINFO pShimInfo = NULL;
1258c2c66affSColin Finck PHOOKAPIEX pHookApi;
1259c2c66affSColin Finck DWORD dwHookCount;
1260c2c66affSColin Finck
1261c2c66affSColin Finck ShimName = SeiGetStringPtr(pdb, ShimRef, TAG_NAME);
1262c2c66affSColin Finck if (!ShimName)
1263c2c66affSColin Finck {
1264c2c66affSColin Finck SHIMENG_FAIL("Failed to retrieve the name for 0x%x\n", tr);
1265c2c66affSColin Finck continue;
1266c2c66affSColin Finck }
1267c2c66affSColin Finck
1268c2c66affSColin Finck CommandLine = SeiGetStringPtr(pdb, ShimRef, TAG_COMMAND_LINE);
1269c2c66affSColin Finck if (CommandLine && *CommandLine)
1270c2c66affSColin Finck {
1271c2c66affSColin Finck RtlInitUnicodeString(&UnicodeDllName, CommandLine);
1272c2c66affSColin Finck if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiCommandLine, &UnicodeDllName, TRUE)))
1273c2c66affSColin Finck {
1274c2c66affSColin Finck SHIMENG_INFO("COMMAND LINE %s for %S", AnsiCommandLine.Buffer, ShimName);
1275c2c66affSColin Finck }
1276c2c66affSColin Finck else
1277c2c66affSColin Finck {
1278c2c66affSColin Finck AnsiCommandLine.Buffer = "";
1279c2c66affSColin Finck CommandLine = NULL;
1280c2c66affSColin Finck }
1281c2c66affSColin Finck }
1282c2c66affSColin Finck
1283c2c66affSColin Finck ShimTag = SeiGetDWORD(pdb, ShimRef, TAG_SHIM_TAGID);
1284c2c66affSColin Finck if (!ShimTag)
1285c2c66affSColin Finck {
1286c2c66affSColin Finck SHIMENG_FAIL("Failed to resolve %S to a shim\n", ShimName);
1287c2c66affSColin Finck continue;
1288c2c66affSColin Finck }
1289c2c66affSColin Finck
1290f9395e92SMark Jansen if (!SUCCEEDED(SdbGetAppPatchDir(NULL, FullNameBuffer, ARRAYSIZE(FullNameBuffer))))
1291c2c66affSColin Finck {
1292c2c66affSColin Finck SHIMENG_WARN("Failed to get the AppPatch dir\n");
1293c2c66affSColin Finck continue;
1294c2c66affSColin Finck }
1295c2c66affSColin Finck
1296c2c66affSColin Finck DllName = SeiGetStringPtr(pdb, ShimTag, TAG_DLLFILE);
1297c2c66affSColin Finck if (DllName == NULL ||
1298c2c66affSColin Finck !SUCCEEDED(StringCchCatW(FullNameBuffer, ARRAYSIZE(FullNameBuffer), L"\\")) ||
1299c2c66affSColin Finck !SUCCEEDED(StringCchCatW(FullNameBuffer, ARRAYSIZE(FullNameBuffer), DllName)))
1300c2c66affSColin Finck {
1301c2c66affSColin Finck SHIMENG_WARN("Failed to build a full path for %S\n", ShimName);
1302c2c66affSColin Finck continue;
1303c2c66affSColin Finck }
1304c2c66affSColin Finck
1305511e7935SMark Jansen RtlInitUnicodeString(&g_LoadingShimDll, DllName);
1306c2c66affSColin Finck RtlInitUnicodeString(&UnicodeDllName, FullNameBuffer);
1307c2c66affSColin Finck if (NT_SUCCESS(LdrGetDllHandle(NULL, NULL, &UnicodeDllName, &BaseAddress)))
1308c2c66affSColin Finck {
1309c2c66affSColin Finck /* This shim dll was already loaded, let's find it */
1310c2c66affSColin Finck pShimModuleInfo = SeiGetShimModuleInfo(BaseAddress);
1311c2c66affSColin Finck }
1312c2c66affSColin Finck else if (!NT_SUCCESS(LdrLoadDll(NULL, NULL, &UnicodeDllName, &BaseAddress)))
1313c2c66affSColin Finck {
1314c2c66affSColin Finck SHIMENG_WARN("Failed to load %wZ for %S\n", &UnicodeDllName, ShimName);
1315c2c66affSColin Finck continue;
1316c2c66affSColin Finck }
1317511e7935SMark Jansen RtlInitUnicodeString(&g_LoadingShimDll, NULL);
1318c2c66affSColin Finck /* No shim module found (or we just loaded it) */
1319c2c66affSColin Finck if (!pShimModuleInfo)
1320c2c66affSColin Finck {
1321c2c66affSColin Finck pShimModuleInfo = SeiCreateShimModuleInfo(DllName, BaseAddress);
1322c2c66affSColin Finck if (!pShimModuleInfo)
1323c2c66affSColin Finck {
1324c2c66affSColin Finck SHIMENG_FAIL("Failed to allocate ShimInfo for %S\n", DllName);
1325c2c66affSColin Finck continue;
1326c2c66affSColin Finck }
1327c2c66affSColin Finck }
1328c2c66affSColin Finck
1329c2c66affSColin Finck SHIMENG_INFO("Shim DLL 0x%p \"%wZ\" loaded\n", BaseAddress, &UnicodeDllName);
1330c2c66affSColin Finck SHIMENG_INFO("Using SHIM \"%S!%S\"\n", DllName, ShimName);
1331c2c66affSColin Finck
1332c2c66affSColin Finck /* Ask this shim what hooks it needs (and pass along the commandline) */
1333cfdb7d56SMark Jansen dwHookCount = 0;
1334c2c66affSColin Finck pHookApi = pShimModuleInfo->pGetHookAPIs(AnsiCommandLine.Buffer, ShimName, &dwHookCount);
1335c2c66affSColin Finck SHIMENG_INFO("GetHookAPIs returns %d hooks for DLL \"%wZ\" SHIM \"%S\"\n", dwHookCount, &UnicodeDllName, ShimName);
1336cfdb7d56SMark Jansen if (dwHookCount && pHookApi)
1337c2c66affSColin Finck pShimInfo = SeiAppendHookInfo(pShimModuleInfo, pHookApi, dwHookCount, ShimName);
1338cfdb7d56SMark Jansen else
1339cfdb7d56SMark Jansen dwHookCount = 0;
1340c2c66affSColin Finck
1341c2c66affSColin Finck /* If this shim has hooks, create the include / exclude lists */
1342c2c66affSColin Finck if (pShimInfo)
1343c2c66affSColin Finck SeiBuildInclExclList(pdb, ShimTag, pShimInfo);
1344c2c66affSColin Finck
1345c2c66affSColin Finck if (CommandLine && *CommandLine)
1346c2c66affSColin Finck RtlFreeAnsiString(&AnsiCommandLine);
1347c2c66affSColin Finck
1348c2c66affSColin Finck dwTotalHooks += dwHookCount;
1349c2c66affSColin Finck }
1350c2c66affSColin Finck }
1351c2c66affSColin Finck
1352c2c66affSColin Finck SeiAddInternalHooks(dwTotalHooks);
1353ee62837eSMark Jansen SeiCombineHookInfo();
1354c2c66affSColin Finck SeiResolveAPIs();
1355c2c66affSColin Finck PatchNewModules(Peb);
13566abe0e50SMark Jansen
135793e88edbSMark Jansen if (ProcessInit)
135893e88edbSMark Jansen {
13596abe0e50SMark Jansen /* Remove the 'LDRP_ENTRY_PROCESSED' flag from entries we modified, so that the loader can continue to process them */
13606abe0e50SMark Jansen SeiResetEntryProcessed(Peb);
1361c2c66affSColin Finck }
1362*d284c814SMark Jansen g_bShimEngInitialized = TRUE;
136393e88edbSMark Jansen }
1364c2c66affSColin Finck
1365c2c66affSColin Finck
1366c2c66affSColin Finck /* Load the database + unpack the shim data (if this process is allowed) */
SeiGetShimData(PUNICODE_STRING ProcessImage,PVOID pShimData,HSDB * pHsdb,SDBQUERYRESULT * pQuery)1367c2c66affSColin Finck BOOL SeiGetShimData(PUNICODE_STRING ProcessImage, PVOID pShimData, HSDB* pHsdb, SDBQUERYRESULT* pQuery)
1368c2c66affSColin Finck {
1369c2c66affSColin Finck static const UNICODE_STRING ForbiddenShimmingApps[] = {
1370c2c66affSColin Finck RTL_CONSTANT_STRING(L"ntsd.exe"),
1371c2c66affSColin Finck RTL_CONSTANT_STRING(L"windbg.exe"),
1372c2c66affSColin Finck #if WINVER >= 0x600
1373c2c66affSColin Finck RTL_CONSTANT_STRING(L"slsvc.exe"),
1374c2c66affSColin Finck #endif
1375c2c66affSColin Finck };
13761570f08bSMark Jansen static const UNICODE_STRING PathDividerFind = RTL_CONSTANT_STRING(L"\\/");
1377c2c66affSColin Finck UNICODE_STRING ProcessName;
13781570f08bSMark Jansen USHORT PathDivider;
1379c2c66affSColin Finck HSDB hsdb;
1380c2c66affSColin Finck DWORD n;
1381c2c66affSColin Finck
13821570f08bSMark Jansen if (!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END, ProcessImage, &PathDividerFind, &PathDivider)))
13831570f08bSMark Jansen PathDivider = 0;
1384c2c66affSColin Finck
13851570f08bSMark Jansen if (PathDivider)
13861570f08bSMark Jansen PathDivider += sizeof(WCHAR);
1387c2c66affSColin Finck
13881570f08bSMark Jansen ProcessName.Buffer = ProcessImage->Buffer + PathDivider / sizeof(WCHAR);
13891570f08bSMark Jansen ProcessName.Length = ProcessImage->Length - PathDivider;
13901570f08bSMark Jansen ProcessName.MaximumLength = ProcessImage->MaximumLength - PathDivider;
1391c2c66affSColin Finck
1392c2c66affSColin Finck for (n = 0; n < ARRAYSIZE(ForbiddenShimmingApps); ++n)
1393c2c66affSColin Finck {
1394c2c66affSColin Finck if (RtlEqualUnicodeString(&ProcessName, ForbiddenShimmingApps + n, TRUE))
1395c2c66affSColin Finck {
1396c2c66affSColin Finck SHIMENG_MSG("Not shimming %wZ\n", ForbiddenShimmingApps + n);
1397c2c66affSColin Finck return FALSE;
1398c2c66affSColin Finck }
1399c2c66affSColin Finck }
1400c2c66affSColin Finck
1401c2c66affSColin Finck /* We should probably load all db's here, but since we do not support that yet... */
1402c2c66affSColin Finck hsdb = SdbInitDatabase(HID_DOS_PATHS | SDB_DATABASE_MAIN_SHIM, NULL);
1403c2c66affSColin Finck if (hsdb)
1404c2c66affSColin Finck {
1405c2c66affSColin Finck if (SdbUnpackAppCompatData(hsdb, ProcessImage->Buffer, pShimData, pQuery))
1406c2c66affSColin Finck {
1407c2c66affSColin Finck *pHsdb = hsdb;
1408c2c66affSColin Finck return TRUE;
1409c2c66affSColin Finck }
1410c2c66affSColin Finck SdbReleaseDatabase(hsdb);
1411c2c66affSColin Finck }
1412c2c66affSColin Finck return FALSE;
1413c2c66affSColin Finck }
1414c2c66affSColin Finck
1415c2c66affSColin Finck
1416c2c66affSColin Finck
SE_InstallBeforeInit(PUNICODE_STRING ProcessImage,PVOID pShimData)1417c2c66affSColin Finck VOID NTAPI SE_InstallBeforeInit(PUNICODE_STRING ProcessImage, PVOID pShimData)
1418c2c66affSColin Finck {
1419c2c66affSColin Finck HSDB hsdb = NULL;
1420c2c66affSColin Finck SDBQUERYRESULT QueryResult = { { 0 } };
142106d7926eSMark Jansen SHIMENG_INFO("(%wZ, %p)\n", ProcessImage, pShimData);
1422c2c66affSColin Finck
1423c2c66affSColin Finck if (!SeiGetShimData(ProcessImage, pShimData, &hsdb, &QueryResult))
1424c2c66affSColin Finck {
1425c2c66affSColin Finck SHIMENG_FAIL("Failed to get shim data\n");
1426c2c66affSColin Finck return;
1427c2c66affSColin Finck }
1428c2c66affSColin Finck
1429c2c66affSColin Finck g_bShimDuringInit = TRUE;
143093e88edbSMark Jansen SeiInit(ProcessImage->Buffer, hsdb, &QueryResult, TRUE);
1431c2c66affSColin Finck g_bShimDuringInit = FALSE;
1432c2c66affSColin Finck
1433c2c66affSColin Finck SdbReleaseDatabase(hsdb);
1434c2c66affSColin Finck }
1435c2c66affSColin Finck
SE_InstallAfterInit(PUNICODE_STRING ProcessImage,PVOID pShimData)1436c2c66affSColin Finck VOID NTAPI SE_InstallAfterInit(PUNICODE_STRING ProcessImage, PVOID pShimData)
1437c2c66affSColin Finck {
1438c2c66affSColin Finck NotifyShims(SHIM_NOTIFY_ATTACH, NULL);
1439c2c66affSColin Finck }
1440c2c66affSColin Finck
SE_ProcessDying(VOID)1441c2c66affSColin Finck VOID NTAPI SE_ProcessDying(VOID)
1442c2c66affSColin Finck {
1443c2c66affSColin Finck SHIMENG_MSG("()\n");
1444c2c66affSColin Finck NotifyShims(SHIM_NOTIFY_DETACH, NULL);
1445c2c66affSColin Finck }
1446c2c66affSColin Finck
SE_DllLoaded(PLDR_DATA_TABLE_ENTRY LdrEntry)1447c2c66affSColin Finck VOID WINAPI SE_DllLoaded(PLDR_DATA_TABLE_ENTRY LdrEntry)
1448c2c66affSColin Finck {
1449ee62837eSMark Jansen PHOOKMODULEINFO HookModuleInfo;
1450c2c66affSColin Finck SHIMENG_INFO("%sINIT. loading DLL \"%wZ\"\n", g_bShimDuringInit ? "" : "AFTER ", &LdrEntry->BaseDllName);
145106c1e134SMark Jansen
1452ee62837eSMark Jansen HookModuleInfo = SeiFindHookModuleInfo(&LdrEntry->BaseDllName, NULL);
1453ee62837eSMark Jansen if (HookModuleInfo)
1454ee62837eSMark Jansen {
1455ee62837eSMark Jansen ASSERT(HookModuleInfo->BaseAddress == NULL);
1456ee62837eSMark Jansen HookModuleInfo->BaseAddress = LdrEntry->DllBase;
1457ee62837eSMark Jansen SeiResolveAPI(HookModuleInfo);
1458ee62837eSMark Jansen }
1459ee62837eSMark Jansen
146006c1e134SMark Jansen SeiHookImports(LdrEntry);
146106c1e134SMark Jansen
1462c2c66affSColin Finck NotifyShims(SHIM_REASON_DLL_LOAD, LdrEntry);
1463c2c66affSColin Finck }
1464c2c66affSColin Finck
SE_DllUnloaded(PLDR_DATA_TABLE_ENTRY LdrEntry)1465c2c66affSColin Finck VOID WINAPI SE_DllUnloaded(PLDR_DATA_TABLE_ENTRY LdrEntry)
1466c2c66affSColin Finck {
1467c2c66affSColin Finck SHIMENG_INFO("(%p)\n", LdrEntry);
146806c1e134SMark Jansen
146906c1e134SMark Jansen /* Should we unhook here? */
147006c1e134SMark Jansen
1471c2c66affSColin Finck NotifyShims(SHIM_REASON_DLL_UNLOAD, LdrEntry);
1472c2c66affSColin Finck }
1473c2c66affSColin Finck
SE_IsShimDll(PVOID BaseAddress)1474c2c66affSColin Finck BOOL WINAPI SE_IsShimDll(PVOID BaseAddress)
1475c2c66affSColin Finck {
1476c2c66affSColin Finck SHIMENG_INFO("(%p)\n", BaseAddress);
1477c2c66affSColin Finck
1478c2c66affSColin Finck return SeiGetShimModuleInfo(BaseAddress) != NULL;
1479c2c66affSColin Finck }
1480c2c66affSColin Finck
148193e88edbSMark Jansen /* 'Private' ntdll function */
148293e88edbSMark Jansen BOOLEAN
148393e88edbSMark Jansen NTAPI
148493e88edbSMark Jansen LdrInitShimEngineDynamic(IN PVOID BaseAddress);
148593e88edbSMark Jansen
148693e88edbSMark Jansen
SE_DynamicShim(LPCWSTR ProcessImage,HSDB hsdb,PVOID pQueryResult,LPCSTR Module,LPDWORD lpdwDynamicToken)148793e88edbSMark Jansen BOOL WINAPI SE_DynamicShim(LPCWSTR ProcessImage, HSDB hsdb, PVOID pQueryResult, LPCSTR Module, LPDWORD lpdwDynamicToken)
148893e88edbSMark Jansen {
1489*d284c814SMark Jansen if (g_bShimEngInitialized)
1490*d284c814SMark Jansen {
1491*d284c814SMark Jansen SHIMENG_MSG("ReactOS HACK(CORE-13283): ShimEng already initialized!\n");
1492*d284c814SMark Jansen return TRUE;
1493*d284c814SMark Jansen }
1494*d284c814SMark Jansen
149593e88edbSMark Jansen g_bShimDuringInit = TRUE;
149693e88edbSMark Jansen SeiInit(ProcessImage, hsdb, pQueryResult, FALSE);
149793e88edbSMark Jansen g_bShimDuringInit = FALSE;
149893e88edbSMark Jansen
149993e88edbSMark Jansen LdrInitShimEngineDynamic(g_hInstance);
150093e88edbSMark Jansen
150193e88edbSMark Jansen return TRUE;
150293e88edbSMark Jansen }
150393e88edbSMark Jansen
1504