https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ee62837ec08f8913754f8d...
commit ee62837ec08f8913754f8d1d57e1593db30cd080 Author: Mark Jansen mark.jansen@reactos.org AuthorDate: Wed Mar 13 20:15:18 2019 +0100 Commit: Mark Jansen mark.jansen@reactos.org CommitDate: Thu Mar 14 20:02:01 2019 +0100
[SHIMENG] Implement experimental support for multiple hooks on the same function --- dll/appcompat/apphelp/shimeng.c | 91 +++++++++++++++++++++++++++++++++-------- dll/appcompat/apphelp/shimeng.h | 6 ++- 2 files changed, 78 insertions(+), 19 deletions(-)
diff --git a/dll/appcompat/apphelp/shimeng.c b/dll/appcompat/apphelp/shimeng.c index e3c152bbdf..3e8a169617 100644 --- a/dll/appcompat/apphelp/shimeng.c +++ b/dll/appcompat/apphelp/shimeng.c @@ -46,7 +46,7 @@ HOOKAPIEX g_IntHookEx[] = StubGetProcAddress, /* ReplacementFunction*/ NULL, /* OriginalFunction */ NULL, /* pShimInfo */ - NULL /* Unused */ + NULL /* ApiLink */ }, };
@@ -545,17 +545,7 @@ VOID SeiAddHooks(PHOOKAPIEX hooks, DWORD dwHookCount, PSHIMINFO pShim) RtlInitAnsiString(&AnsiString, hook->FunctionName); if (NT_SUCCESS(LdrGetDllHandle(NULL, 0, &UnicodeModName, &DllHandle))) { - PVOID ProcAddress; - - - if (!NT_SUCCESS(LdrGetProcedureAddress(DllHandle, &AnsiString, 0, &ProcAddress))) - { - SHIMENG_FAIL("Unable to retrieve %s!%s\n", hook->LibraryName, hook->FunctionName); - continue; - } - HookModuleInfo = SeiFindHookModuleInfo(NULL, DllHandle); - hook->OriginalFunction = ProcAddress; } else { @@ -582,14 +572,22 @@ VOID SeiAddHooks(PHOOKAPIEX hooks, DWORD dwHookCount, PSHIMINFO pShim) int CmpResult = strcmp(hook->FunctionName, HookApi->FunctionName); if (CmpResult == 0) { - /* Multiple hooks on one function? --> use ApiLink */ - SHIMENG_FAIL("Multiple hooks on one API is not yet supported!\n"); - ASSERT(0); + while (HookApi->ApiLink) + { + HookApi = HookApi->ApiLink; + } + HookApi->ApiLink = hook; + hook = NULL; + break; } } - pHookApi = ARRAY_Append(&HookModuleInfo->HookApis, PHOOKAPIEX); - if (pHookApi) - *pHookApi = hook; + /* No place found yet, append it */ + if (hook) + { + pHookApi = ARRAY_Append(&HookModuleInfo->HookApis, PHOOKAPIEX); + if (pHookApi) + *pHookApi = hook; + } } }
@@ -641,8 +639,57 @@ FARPROC WINAPI StubGetProcAddress(HINSTANCE hModule, LPCSTR lpProcName) return proc; }
+VOID SeiResolveAPI(PHOOKMODULEINFO HookModuleInfo) +{ + DWORD n; + ANSI_STRING AnsiString; + + ASSERT(HookModuleInfo->BaseAddress != NULL); + + for (n = 0; n < ARRAY_Size(&HookModuleInfo->HookApis); ++n) + { + PVOID ProcAddress; + PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX, n); + RtlInitAnsiString(&AnsiString, HookApi->FunctionName); + + if (!NT_SUCCESS(LdrGetProcedureAddress(HookModuleInfo->BaseAddress, &AnsiString, 0, &ProcAddress))) + { + SHIMENG_FAIL("Unable to retrieve %s!%s\n", HookApi->LibraryName, HookApi->FunctionName); + continue; + } + + HookApi->OriginalFunction = ProcAddress; + if (HookApi->ApiLink) + { + SHIMENG_MSG("TODO: Figure out how to handle conflicting In/Exports with ApiLink!\n"); + } + while (HookApi->ApiLink) + { + HookApi->ApiLink->OriginalFunction = HookApi->OriginalFunction; + HookApi->OriginalFunction = HookApi->ApiLink->ReplacementFunction; + HookApi = HookApi->ApiLink; + } + } +} + /* Walk all shim modules / enabled shims, and add their hooks */ VOID SeiResolveAPIs(VOID) +{ + DWORD n; + + for (n = 0; n < ARRAY_Size(&g_pHookArray); ++n) + { + PHOOKMODULEINFO pModuleInfo = ARRAY_At(&g_pHookArray, HOOKMODULEINFO, n); + + /* Is this module loaded? */ + if (pModuleInfo->BaseAddress) + { + SeiResolveAPI(pModuleInfo); + } + } +} + +VOID SeiCombineHookInfo(VOID) { DWORD mod, n;
@@ -1249,6 +1296,7 @@ VOID SeiInit(PUNICODE_STRING ProcessImage, HSDB hsdb, SDBQUERYRESULT* pQuery) }
SeiAddInternalHooks(dwTotalHooks); + SeiCombineHookInfo(); SeiResolveAPIs(); PatchNewModules(Peb);
@@ -1347,8 +1395,17 @@ VOID NTAPI SE_ProcessDying(VOID)
VOID WINAPI SE_DllLoaded(PLDR_DATA_TABLE_ENTRY LdrEntry) { + PHOOKMODULEINFO HookModuleInfo; SHIMENG_INFO("%sINIT. loading DLL "%wZ"\n", g_bShimDuringInit ? "" : "AFTER ", &LdrEntry->BaseDllName);
+ HookModuleInfo = SeiFindHookModuleInfo(&LdrEntry->BaseDllName, NULL); + if (HookModuleInfo) + { + ASSERT(HookModuleInfo->BaseAddress == NULL); + HookModuleInfo->BaseAddress = LdrEntry->DllBase; + SeiResolveAPI(HookModuleInfo); + } + SeiHookImports(LdrEntry);
NotifyShims(SHIM_REASON_DLL_LOAD, LdrEntry); diff --git a/dll/appcompat/apphelp/shimeng.h b/dll/appcompat/apphelp/shimeng.h index 0081c49bc9..c6e3888d53 100644 --- a/dll/appcompat/apphelp/shimeng.h +++ b/dll/appcompat/apphelp/shimeng.h @@ -23,6 +23,8 @@ typedef struct _ARRAY typedef struct _SHIMINFO *PSHIMINFO; typedef struct _SHIMMODULE *PSHIMMODULE;
+typedef struct tagHOOKAPIEX *PHOOKAPIEX; + /* Shims know this structure as HOOKAPI, with 2 reserved members (the last 2). */ typedef struct tagHOOKAPIEX { @@ -31,8 +33,8 @@ typedef struct tagHOOKAPIEX PVOID ReplacementFunction; PVOID OriginalFunction; PSHIMINFO pShimInfo; - PVOID Unused; -} HOOKAPIEX, *PHOOKAPIEX; + PHOOKAPIEX ApiLink; +} HOOKAPIEX;
C_ASSERT(sizeof(HOOKAPIEX) == sizeof(HOOKAPI)); C_ASSERT(offsetof(HOOKAPIEX, pShimInfo) == offsetof(HOOKAPI, Reserved));