[SHIMLIB] Shim helper functions keep a list of used shims, so that events can be...
[reactos.git] / reactos / dll / appcompat / shims / shimlib / shimlib.c
index 7720305..65aed84 100644 (file)
 #include <shimlib.h>
 #include <strsafe.h>
 
-HINSTANCE g_hinstDll;
+typedef struct UsedShim
+{
+    SLIST_ENTRY Entry;
+    PSHIMREG pShim;
+#if (WINVER > _WIN32_WINNT_WS03)
+    BOOL bInitCalled;
+#endif
+} UsedShim, *pUsedShim;
+
+
 static HANDLE g_ShimLib_Heap;
+static PSLIST_HEADER g_UsedShims;
 
 void ShimLib_Init(HINSTANCE hInstance)
 {
-    g_hinstDll = hInstance;
     g_ShimLib_Heap = HeapCreate(0, 0x10000, 0);
+
+    g_UsedShims = (PSLIST_HEADER)ShimLib_ShimMalloc(sizeof(SLIST_HEADER));
+    RtlInitializeSListHead(g_UsedShims);
 }
 
 void ShimLib_Deinit()
@@ -43,6 +55,18 @@ PCSTR ShimLib_StringDuplicateA(PCSTR szString)
     return lstrcpyA(NewString, szString);
 }
 
+BOOL ShimLib_StrAEqualsW(PCSTR szString, PCWSTR wszString)
+{
+    while (*szString == *wszString)
+    {
+        if (!*szString)
+            return TRUE;
+
+        szString++; wszString++;
+    }
+    return FALSE;
+}
+
 #if defined(_MSC_VER)
 
 #if defined(_M_IA64) || defined(_M_AMD64)
@@ -62,8 +86,8 @@ PCSTR ShimLib_StringDuplicateA(PCSTR szString)
 #endif
 
 
-_SHMALLOC(".shm") _PVSHIM _shim_start = 0;
-_SHMALLOC(".shm$ZZZ") _PVSHIM _shim_end = 0;
+_SHMALLOC(".shm") SHIMREG _shim_start = { 0 };
+_SHMALLOC(".shm$ZZZ") SHIMREG _shim_end = { 0 };
 
 
 /* Generic GetHookAPIs function.
@@ -72,21 +96,53 @@ _SHMALLOC(".shm$ZZZ") _PVSHIM _shim_end = 0;
    This helper function will return the correct shim, and call the init function */
 PHOOKAPI WINAPI ShimLib_GetHookAPIs(IN LPCSTR szCommandLine, IN LPCWSTR wszShimName, OUT PDWORD pdwHookCount)
 {
-    uintptr_t ps = (uintptr_t)&_shim_start;
-    ps += sizeof(uintptr_t);
-    for (; ps != (uintptr_t)&_shim_end; ps += sizeof(uintptr_t))
+    PSHIMREG ps = &_shim_start;
+    ps++;
+    for (; ps != &_shim_end; ps++)
     {
-        _PVSHIM* pfunc = (_PVSHIM *)ps;
-        if (*pfunc != NULL)
+        if (ps->GetHookAPIs != NULL && ps->ShimName != NULL)
         {
-            PVOID res = (*pfunc)(wszShimName);
-            if (res)
+            if (ShimLib_StrAEqualsW(ps->ShimName, wszShimName))
             {
-                PHOOKAPI (WINAPI* PFN)(DWORD, PCSTR, PDWORD) = res;
-                return (*PFN)(SHIM_REASON_ATTACH, szCommandLine, pdwHookCount);
+                pUsedShim shim = (pUsedShim)ShimLib_ShimMalloc(sizeof(UsedShim));
+                shim->pShim = ps;
+#if (WINVER > _WIN32_WINNT_WS03)
+                shim->bInitCalled = FALSE;
+#endif
+                RtlInterlockedPushEntrySList(g_UsedShims, &(shim->Entry));
+
+                return ps->GetHookAPIs(SHIM_NOTIFY_ATTACH, szCommandLine, pdwHookCount);
             }
         }
     }
     return NULL;
 }
 
+
+BOOL WINAPI ShimLib_NotifyShims(DWORD fdwReason, PVOID ptr)
+{
+    PSLIST_ENTRY pEntry = RtlFirstEntrySList(g_UsedShims);
+
+    if (fdwReason < SHIM_REASON_INIT)
+        fdwReason += (SHIM_REASON_INIT - SHIM_NOTIFY_ATTACH);
+
+    while (pEntry)
+    {
+        pUsedShim pUsed = CONTAINING_RECORD(pEntry, UsedShim, Entry);
+        _PVNotify Notify = pUsed->pShim->Notify;
+#if (WINVER > _WIN32_WINNT_WS03)
+        if (pUsed->bInitCalled && fdwReason == SHIM_REASON_INIT)
+            Notify = NULL;
+#endif
+        if (Notify)
+            Notify(fdwReason, ptr);
+#if (WINVER > _WIN32_WINNT_WS03)
+        if (fdwReason == SHIM_REASON_INIT)
+            pUsed->bInitCalled = TRUE;
+#endif
+
+        pEntry = pEntry->Next;
+    }
+
+    return TRUE;
+}