https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ee62837ec08f8913754f8d1d57e1593db30cd080

commit ee62837ec08f8913754f8d1d57e1593db30cd080
Author:     Mark Jansen <[email protected]>
AuthorDate: Wed Mar 13 20:15:18 2019 +0100
Commit:     Mark Jansen <[email protected]>
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));

Reply via email to