xref: /reactos/dll/appcompat/apphelp/shimeng.c (revision d284c814)
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