From b6d0f03c96d8afc9ac3939df291bd4a76b566b5b Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Sat, 28 May 2016 16:42:57 +0000 Subject: [PATCH] [APPHELP] Begin shimlib implementation. CORE-11329 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 | 3 + reactos/dll/appcompat/shims/CMakeLists.txt | 3 + .../appcompat/shims/shimlib/CMakeLists.txt | 7 ++ .../shims/shimlib/implement_shim.inl | 76 ++++++++++++++++ .../appcompat/shims/shimlib/setup_shim.inl | 39 ++++++++ reactos/dll/appcompat/shims/shimlib/shimlib.c | 91 +++++++++++++++++++ reactos/dll/appcompat/shims/shimlib/shimlib.h | 45 +++++++++ 7 files changed, 264 insertions(+) create mode 100644 reactos/dll/appcompat/shims/CMakeLists.txt create mode 100644 reactos/dll/appcompat/shims/shimlib/CMakeLists.txt create mode 100644 reactos/dll/appcompat/shims/shimlib/implement_shim.inl create mode 100644 reactos/dll/appcompat/shims/shimlib/setup_shim.inl create mode 100644 reactos/dll/appcompat/shims/shimlib/shimlib.c create mode 100644 reactos/dll/appcompat/shims/shimlib/shimlib.h diff --git a/reactos/dll/appcompat/CMakeLists.txt b/reactos/dll/appcompat/CMakeLists.txt index 34632ff866b..c66ab4c7036 100644 --- a/reactos/dll/appcompat/CMakeLists.txt +++ b/reactos/dll/appcompat/CMakeLists.txt @@ -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 index 00000000000..e9be782a083 --- /dev/null +++ b/reactos/dll/appcompat/shims/CMakeLists.txt @@ -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 index 00000000000..77632b2978b --- /dev/null +++ b/reactos/dll/appcompat/shims/shimlib/CMakeLists.txt @@ -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 index 00000000000..b75919f1176 --- /dev/null +++ b/reactos/dll/appcompat/shims/shimlib/implement_shim.inl @@ -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 index 00000000000..aa366a287b6 --- /dev/null +++ b/reactos/dll/appcompat/shims/shimlib/setup_shim.inl @@ -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 index 00000000000..45dda7908b3 --- /dev/null +++ b/reactos/dll/appcompat/shims/shimlib/shimlib.c @@ -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 +#include +#include + +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 and 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 index 00000000000..59e325d7a11 --- /dev/null +++ b/reactos/dll/appcompat/shims/shimlib/shimlib.h @@ -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 + -- 2.17.1