[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
This commit is contained in:
Mark Jansen 2016-05-28 16:42:57 +00:00
parent 849c418010
commit b6d0f03c96
7 changed files with 264 additions and 0 deletions

View file

@ -1,2 +1,5 @@
project(appcompat)
set(SHIMLIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/shims/shimlib)
add_subdirectory(apphelp)
add_subdirectory(shims)

View file

@ -0,0 +1,3 @@
add_subdirectory(shimlib)

View file

@ -0,0 +1,7 @@
list(APPEND SOURCE
shimlib.c
shimlib.h)
add_library(shimlib ${SOURCE})
add_dependencies(shimlib xdk)

View file

@ -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

View file

@ -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);

View file

@ -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;
}

View file

@ -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