[APPHELP] Begin shimlib implementation. CORE-11329
authorMark Jansen <mark.jansen@reactos.org>
Sat, 28 May 2016 16:42:57 +0000 (16:42 +0000)
committerMark Jansen <mark.jansen@reactos.org>
Sat, 28 May 2016 16:42:57 +0000 (16:42 +0000)
Implement some macro's and functions that help when registering shims.
These are all written in C, so that wine can use the shim libraries as well.

svn path=/trunk/; revision=71439

reactos/dll/appcompat/CMakeLists.txt
reactos/dll/appcompat/shims/CMakeLists.txt [new file with mode: 0644]
reactos/dll/appcompat/shims/shimlib/CMakeLists.txt [new file with mode: 0644]
reactos/dll/appcompat/shims/shimlib/implement_shim.inl [new file with mode: 0644]
reactos/dll/appcompat/shims/shimlib/setup_shim.inl [new file with mode: 0644]
reactos/dll/appcompat/shims/shimlib/shimlib.c [new file with mode: 0644]
reactos/dll/appcompat/shims/shimlib/shimlib.h [new file with mode: 0644]

index 34632ff..c66ab4c 100644 (file)
@@ -1,2 +1,5 @@
+project(appcompat)
 
+set(SHIMLIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/shims/shimlib)
 add_subdirectory(apphelp)
+add_subdirectory(shims)
diff --git a/reactos/dll/appcompat/shims/CMakeLists.txt b/reactos/dll/appcompat/shims/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e9be782
--- /dev/null
@@ -0,0 +1,3 @@
+
+add_subdirectory(shimlib)
+
diff --git a/reactos/dll/appcompat/shims/shimlib/CMakeLists.txt b/reactos/dll/appcompat/shims/shimlib/CMakeLists.txt
new file mode 100644 (file)
index 0000000..77632b2
--- /dev/null
@@ -0,0 +1,7 @@
+
+list(APPEND SOURCE
+    shimlib.c
+    shimlib.h)
+
+add_library(shimlib ${SOURCE})
+add_dependencies(shimlib xdk)
diff --git a/reactos/dll/appcompat/shims/shimlib/implement_shim.inl b/reactos/dll/appcompat/shims/shimlib/implement_shim.inl
new file mode 100644 (file)
index 0000000..b75919f
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Shim library
+ * FILE:            dll/appcompat/shims/shimlib/implement_shim.inl
+ * PURPOSE:         Shimlib helper file, used to register shims using the earlier prepared macro's
+ * PROGRAMMER:      Mark Jansen
+ */
+
+#ifndef SHIM_NS
+#error "A namespace should be provided in SHIM_NS before including this file!"
+#endif
+
+#ifndef SHIM_NUM_HOOKS
+#error "The number of hooks should be provided in SHIM_NUM_HOOKS before including this file!"
+#endif
+
+#ifndef SHIM_OBJ_NAME
+#error "setup_shim.inl should be included before this file!"
+#endif
+
+#ifndef SHIM_SETUP_HOOKS
+#error "Please define a hook: #define SHIM_SETUP_HOOKS SHIM_HOOK(num, dll_name, function_name, your_function)"
+#endif
+
+PHOOKAPI WINAPI SHIM_OBJ_NAME(InitializeHooksMulti)(DWORD fdwReason, PCSTR pszCmdLine, PDWORD pdwHookCount)
+{
+    if (fdwReason == SHIM_REASON_ATTACH)
+    {
+        if (pszCmdLine)
+        {
+            SHIM_OBJ_NAME(g_szCommandLine) = ShimLib_StringDuplicateA(pszCmdLine);
+        }
+        else
+        {
+            SHIM_OBJ_NAME(g_szCommandLine) = "";
+        }
+        SHIM_OBJ_NAME(g_pAPIHooks) = ShimLib_ShimMalloc(sizeof(HOOKAPI) * SHIM_NUM_HOOKS);
+        ZeroMemory(SHIM_OBJ_NAME(g_pAPIHooks), sizeof(HOOKAPI) * SHIM_NUM_HOOKS);
+        *pdwHookCount = SHIM_NUM_HOOKS;
+    }
+
+#ifdef SHIM_NOTIFY_FN
+    if (!SHIM_NOTIFY_FN(fdwReason) && fdwReason == SHIM_REASON_ATTACH)
+        return NULL;
+#endif
+
+    if (fdwReason == SHIM_REASON_ATTACH)
+    {
+        SHIM_SETUP_HOOKS
+    }
+    return SHIM_OBJ_NAME(g_pAPIHooks);
+}
+
+
+PVOID SHIM_OBJ_NAME(FindShim)(PCWSTR wszString)
+{
+    PCSTR szString = SHIM_OBJ_NAME(g_szModuleName);
+    while (*szString == *wszString)
+    {
+        if (!*szString)
+            return SHIM_OBJ_NAME(InitializeHooksMulti);
+        szString++; wszString++;
+    }
+    return NULL;
+}
+
+#if defined(_MSC_VER)
+#pragma section(".shm$BBB",long,read)
+#endif
+
+_SHMALLOC(".shm$BBB") _PVSHIM SHIM_OBJ_NAME(_shim_fn) = SHIM_OBJ_NAME(FindShim);
+
+#undef SHIM_SETUP_HOOKS
+#undef SHIM_NOTIFY_FN
+#undef SHIM_NUM_HOOKS
+#undef SHIM_NS
diff --git a/reactos/dll/appcompat/shims/shimlib/setup_shim.inl b/reactos/dll/appcompat/shims/shimlib/setup_shim.inl
new file mode 100644 (file)
index 0000000..aa366a2
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Shim library
+ * FILE:            dll/appcompat/shims/shimlib/setup_shim.inl
+ * PURPOSE:         Shimlib helper file, used for setting up the macro's used when registering a shim.
+ * PROGRAMMER:      Mark Jansen
+ */
+
+
+#ifndef SHIM_NS
+#error "A namespace should be provided in SHIM_NS before including this file!"
+#endif
+
+#ifndef SHIM_OBJ_NAME
+#define SHIM_OBJ_NAME3(ns, name) ns ## _ ## name
+#define SHIM_OBJ_NAME2(ns, name) SHIM_OBJ_NAME3(ns, name)
+#define SHIM_OBJ_NAME(name) SHIM_OBJ_NAME2(SHIM_NS, name)
+
+#define SHIM_STRINGIFY2(X_) # X_
+#define SHIM_STRINGIFY(X_) SHIM_STRINGIFY2(X_)
+
+#define SHIM_HOOK(num, dll, function, target) \
+    SHIM_OBJ_NAME(g_pAPIHooks)[num].LibraryName = dll; \
+    SHIM_OBJ_NAME(g_pAPIHooks)[num].FunctionName = function; \
+    SHIM_OBJ_NAME(g_pAPIHooks)[num].ReplacementFunction = target; \
+    SHIM_OBJ_NAME(g_pAPIHooks)[num].OriginalFunction = NULL; \
+    SHIM_OBJ_NAME(g_pAPIHooks)[num].Unk1 = NULL; \
+    SHIM_OBJ_NAME(g_pAPIHooks)[num].Unk2 = NULL;
+
+#define CALL_SHIM(SHIM_NUM, SHIM_CALLCONV) \
+    ((SHIM_CALLCONV)(SHIM_OBJ_NAME(g_pAPIHooks)[SHIM_NUM].OriginalFunction))
+
+#endif
+
+
+PCSTR SHIM_OBJ_NAME(g_szModuleName) = SHIM_STRINGIFY(SHIM_NS);
+PCSTR SHIM_OBJ_NAME(g_szCommandLine);
+PHOOKAPI SHIM_OBJ_NAME(g_pAPIHooks);
+
diff --git a/reactos/dll/appcompat/shims/shimlib/shimlib.c b/reactos/dll/appcompat/shims/shimlib/shimlib.c
new file mode 100644 (file)
index 0000000..45dda79
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Shim library
+ * FILE:            dll/appcompat/shims/shimlib/shimlib.c
+ * PURPOSE:         Shim helper functions
+ * PROGRAMMER:      Mark Jansen
+ */
+
+#include <windows.h>
+#include <shimlib.h>
+#include <strsafe.h>
+
+HINSTANCE g_hinstDll;
+static HANDLE g_ShimLib_Heap;
+
+void ShimLib_Init(HINSTANCE hInstance)
+{
+    g_hinstDll = hInstance;
+    g_ShimLib_Heap = HeapCreate(0, 0x10000, 0);
+}
+
+void ShimLib_Deinit()
+{
+    // Is this a good idea?
+    HeapDestroy(g_ShimLib_Heap);
+}
+
+PVOID ShimLib_ShimMalloc(SIZE_T dwSize)
+{
+    return HeapAlloc(g_ShimLib_Heap, 0, dwSize);
+}
+
+void ShimLib_ShimFree(PVOID pData)
+{
+    HeapFree(g_ShimLib_Heap, 0, pData);
+}
+
+PCSTR ShimLib_StringDuplicateA(PCSTR szString)
+{
+    SIZE_T Length = lstrlenA(szString);
+    PSTR NewString = ShimLib_ShimMalloc(Length+1);
+    return lstrcpyA(NewString, szString);
+}
+
+#if defined(_MSC_VER)
+
+#if defined(_M_IA64) || defined(_M_AMD64)
+#define _ATTRIBUTES read
+#else
+#define _ATTRIBUTES read
+#endif
+
+
+#pragma section(".shm",long,read)
+#pragma section(".shm$AAA",long,read)
+#pragma section(".shm$ZZZ",long,read)
+#endif
+
+#ifdef _MSC_VER
+#pragma comment(linker, "/merge:.shm=.rdata")
+#endif
+
+
+_SHMALLOC(".shm") _PVSHIM _shim_start = 0;
+_SHMALLOC(".shm$ZZZ") _PVSHIM _shim_end = 0;
+
+
+/* Generic GetHookAPIs function.
+   The macro's from <setup_shim.inl> and <implement_shim.inl> will register a list of all apis that should be hooked
+   for a specific shim
+   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))
+    {
+        _PVSHIM* pfunc = (_PVSHIM *)ps;
+        if (*pfunc != NULL)
+        {
+            PVOID res = (*pfunc)(wszShimName);
+            if (res)
+            {
+                PHOOKAPI (WINAPI* PFN)(DWORD, PCSTR, PDWORD) = res;
+                return (*PFN)(SHIM_REASON_ATTACH, szCommandLine, pdwHookCount);
+            }
+        }
+    }
+    return NULL;
+}
+
diff --git a/reactos/dll/appcompat/shims/shimlib/shimlib.h b/reactos/dll/appcompat/shims/shimlib/shimlib.h
new file mode 100644 (file)
index 0000000..59e325d
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Shim Engine
+ * FILE:            dll/appcompat/shims/shimlib/shimlib.h
+ * PURPOSE:         ReactOS Shim Engine
+ * PROGRAMMER:      Mark Jansen
+ */
+
+#pragma once
+
+typedef struct tagHOOKAPI {
+    PCSTR LibraryName;
+    PCSTR FunctionName;
+    PVOID ReplacementFunction;
+    PVOID OriginalFunction;
+    PVOID Unk1;
+    PVOID Unk2;
+} HOOKAPI, *PHOOKAPI;
+
+extern HINSTANCE g_hinstDll;
+
+void ShimLib_Init(HINSTANCE);
+void ShimLib_Deinit(void);
+PVOID ShimLib_ShimMalloc(SIZE_T);
+void ShimLib_ShimFree(PVOID);
+PCSTR ShimLib_StringDuplicateA(PCSTR);
+PHOOKAPI WINAPI ShimLib_GetHookAPIs(LPCSTR,LPCWSTR,PDWORD);
+
+
+#define SHIM_REASON_ATTACH      1
+#define SHIM_REASON_DETACH      2
+#define SHIM_REASON_DLL_LOAD    3   /* Arg: PLDR_DATA_TABLE_ENTRY */
+#define SHIM_REASON_DLL_UNLOAD  4   /* Arg: Module Handle */
+
+
+typedef PVOID (__cdecl *_PVSHIM)(PCWSTR);
+
+#if defined(_MSC_VER)
+#define _SHMALLOC(x) __declspec(allocate(x))
+#elif defined(__GNUC__)
+#define _SHMALLOC(x) __attribute__ ((section (x) ))
+#else
+#error Your compiler is not supported.
+#endif
+