Index: reactos/dll/appcompat/shims/layer/CMakeLists.txt =================================================================== --- reactos/dll/appcompat/shims/layer/CMakeLists.txt (revision 73422) +++ reactos/dll/appcompat/shims/layer/CMakeLists.txt (working copy) @@ -4,6 +4,7 @@ spec2def(aclayers.dll layer.spec) list(APPEND SOURCE + dispmode.c versionlie.c main.c layer.spec) @@ -14,5 +15,5 @@ set_module_type(aclayers win32dll) target_link_libraries(aclayers shimlib) -add_importlibs(aclayers msvcrt kernel32 ntdll) +add_importlibs(aclayers user32 msvcrt kernel32 ntdll) add_cd_file(TARGET aclayers DESTINATION reactos/AppPatch FOR all) Index: reactos/dll/appcompat/shims/layer/dispmode.c =================================================================== --- reactos/dll/appcompat/shims/layer/dispmode.c (nonexistent) +++ reactos/dll/appcompat/shims/layer/dispmode.c (working copy) @@ -0,0 +1,67 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Shim library + * FILE: dll/appcompat/shims/layer/dispmode.c + * PURPOSE: Display settings related shims + * PROGRAMMER: Mark Jansen + */ + +#include +#include +#include + + +#define SHIM_NS Force8BitColor +#include + +#define SHIM_NUM_HOOKS 0 +#define SHIM_NOTIFY_FN SHIM_OBJ_NAME(Notify) + +BOOL WINAPI SHIM_OBJ_NAME(Notify)(DWORD fdwReason, PVOID ptr) +{ + if (fdwReason == SHIM_REASON_INIT) + { + DEVMODEA dm = { { 0 } }; + dm.dmSize = sizeof(dm); + if (EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dm) && + dm.dmBitsPerPel != 8) + { + dm.dmBitsPerPel = 8; + dm.dmFields |= DM_BITSPERPEL; + ChangeDisplaySettingsA(&dm, CDS_FULLSCREEN); + } + } + return TRUE; +} + +#include + + + +#define SHIM_NS Force640x480 +#include + +#define SHIM_NUM_HOOKS 0 +#define SHIM_NOTIFY_FN SHIM_OBJ_NAME(Notify) + +BOOL WINAPI SHIM_OBJ_NAME(Notify)(DWORD fdwReason, PVOID ptr) +{ + if (fdwReason == SHIM_REASON_INIT) + { + DEVMODEA dm = { { 0 } }; + dm.dmSize = sizeof(dm); + if (EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dm) && + (dm.dmPelsWidth != 640 || dm.dmPelsHeight != 480)) + { + dm.dmPelsWidth = 640; + dm.dmPelsHeight = 480; + dm.dmFields |= (DM_PELSWIDTH | DM_PELSHEIGHT); + ChangeDisplaySettingsA(&dm, CDS_FULLSCREEN); + } + } + return TRUE; +} + +#include + + Index: reactos/dll/appcompat/shims/layer/main.c =================================================================== --- reactos/dll/appcompat/shims/layer/main.c (revision 73422) +++ reactos/dll/appcompat/shims/layer/main.c (working copy) @@ -16,10 +16,10 @@ return ShimLib_GetHookAPIs(szCommandLine, wszShimName, pdwHookCount); } -/* PLDR_DATA_TABLE_ENTRY */ -BOOL WINAPI NotifyShims(DWORD fdwReason, PVOID P) +/* Forward to the generic implementation */ +BOOL WINAPI NotifyShims(DWORD fdwReason, PVOID ptr) { - return TRUE; + return ShimLib_NotifyShims(fdwReason, ptr); } BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) Index: reactos/dll/appcompat/shims/layer/versionlie.c =================================================================== --- reactos/dll/appcompat/shims/layer/versionlie.c (revision 73422) +++ reactos/dll/appcompat/shims/layer/versionlie.c (working copy) @@ -89,7 +89,6 @@ #define SHIM_NS Win95VersionLie - #include DWORD WINAPI SHIM_OBJ_NAME(APIHook_GetVersion)() @@ -128,7 +127,6 @@ #define SHIM_NS Win98VersionLie - #include DWORD WINAPI SHIM_OBJ_NAME(APIHook_GetVersion)() Index: reactos/dll/appcompat/shims/layer/versionlie.inl =================================================================== --- reactos/dll/appcompat/shims/layer/versionlie.inl (revision 73422) +++ reactos/dll/appcompat/shims/layer/versionlie.inl (working copy) @@ -43,9 +43,9 @@ return FALSE; } -BOOL WINAPI SHIM_OBJ_NAME(Notify)(DWORD fdwReason) +BOOL WINAPI SHIM_OBJ_NAME(Notify)(DWORD fdwReason, PVOID ptr) { - if (fdwReason == SHIM_REASON_ATTACH && VERSION_INFO.wServicePackMajor) + if (fdwReason == SHIM_NOTIFY_ATTACH && VERSION_INFO.wServicePackMajor) { static CONST WCHAR szServicePack[] = {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','%','u',0}; HRESULT hr = StringCbPrintfA(VERSION_INFO.szCSDVersionA, sizeof(VERSION_INFO.szCSDVersionA), Index: reactos/dll/appcompat/shims/shimlib/CMakeLists.txt =================================================================== --- reactos/dll/appcompat/shims/shimlib/CMakeLists.txt (revision 73422) +++ reactos/dll/appcompat/shims/shimlib/CMakeLists.txt (working copy) @@ -1,7 +1,11 @@ list(APPEND SOURCE + shimdbgsupp.c shimlib.c - shimlib.h) + shimlib.h + # These .inl functions are included so they show up in vs + setup_shim.inl + implement_shim.inl) add_library(shimlib ${SOURCE}) -add_dependencies(shimlib xdk) +add_dependencies(shimlib psdk) Index: reactos/dll/appcompat/shims/shimlib/implement_shim.inl =================================================================== --- reactos/dll/appcompat/shims/shimlib/implement_shim.inl (revision 73422) +++ reactos/dll/appcompat/shims/shimlib/implement_shim.inl (working copy) @@ -2,7 +2,7 @@ * 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 + * PURPOSE: Shimlib helper file, used to register shims setup with macro's from setup_shim.inl * PROGRAMMER: Mark Jansen */ @@ -18,57 +18,56 @@ #error "setup_shim.inl should be included before this file!" #endif +#if SHIM_NUM_HOOKS > 0 #ifndef SHIM_SETUP_HOOKS #error "Please define a hook: #define SHIM_SETUP_HOOKS SHIM_HOOK(num, dll_name, function_name, your_function)" #endif +#else +#ifdef SHIM_SETUP_HOOKS +#error "Hooks are defined, yet SHIM_NUM_HOOKS is <= 0 !" +#endif +#endif -PHOOKAPI WINAPI SHIM_OBJ_NAME(InitializeHooksMulti)(DWORD fdwReason, PCSTR pszCmdLine, PDWORD pdwHookCount) +PHOOKAPI WINAPI SHIM_OBJ_NAME(GetHookAPIs)(DWORD fdwReason, PCSTR pszCmdLine, PDWORD pdwHookCount) { - if (fdwReason == SHIM_REASON_ATTACH) + if (pszCmdLine) { - 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; + 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) + if (!SHIM_NOTIFY_FN(fdwReason, NULL)) return NULL; #endif - if (fdwReason == SHIM_REASON_ATTACH) - { - SHIM_SETUP_HOOKS - } +#if SHIM_NUM_HOOKS > 0 + SHIM_SETUP_HOOKS +#endif 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); +_SHMALLOC(".shm$BBB") SHIMREG SHIM_OBJ_NAME(_shim_fn) = +{ + SHIM_OBJ_NAME(GetHookAPIs), +#ifdef SHIM_NOTIFY_FN + SHIM_NOTIFY_FN, +#else + NULL, +#endif + SHIM_STRINGIFY(SHIM_NS) +}; #undef SHIM_SETUP_HOOKS #undef SHIM_NOTIFY_FN Index: reactos/dll/appcompat/shims/shimlib/setup_shim.inl =================================================================== --- reactos/dll/appcompat/shims/shimlib/setup_shim.inl (revision 73422) +++ reactos/dll/appcompat/shims/shimlib/setup_shim.inl (working copy) @@ -19,13 +19,15 @@ #define SHIM_STRINGIFY2(X_) # X_ #define SHIM_STRINGIFY(X_) SHIM_STRINGIFY2(X_) +/* TODO: static_assert on (num < SHIM_NUM_HOOKS) */ + #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; + SHIM_OBJ_NAME(g_pAPIHooks)[num].Reserved[0] = NULL; \ + SHIM_OBJ_NAME(g_pAPIHooks)[num].Reserved[1] = NULL; #define CALL_SHIM(SHIM_NUM, SHIM_CALLCONV) \ ((SHIM_CALLCONV)(SHIM_OBJ_NAME(g_pAPIHooks)[SHIM_NUM].OriginalFunction)) Index: reactos/dll/appcompat/shims/shimlib/shimdbgsupp.c =================================================================== --- reactos/dll/appcompat/shims/shimlib/shimdbgsupp.c (nonexistent) +++ reactos/dll/appcompat/shims/shimlib/shimdbgsupp.c (working copy) @@ -0,0 +1,79 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Shim library + * FILE: dll/appcompat/shims/shimlib/shimdbgsupp.c + * PURPOSE: Shim debug helper functions + * PROGRAMMER: Mark Jansen + */ + +#include +#include +#include +#include + +#include "wine/winternl.h" + +#define DPFLTR_APPCOMPAT_ID 123 + +void ApphelppInitDebugSupport(PCWSTR KeyName, PULONG Level); +static void SeiInitDebugSupport() +{ + ApphelppInitDebugSupport(L"SHIMENG_DEBUG_LEVEL", &g_ShimEngDebugLevel); +} + + +/** + * Outputs diagnostic info. + * + * @param [in] Level The level to log this message with, choose any of [SHIM_ERR, + * SHIM_WARN, SHIM_INFO]. + * @param [in] FunctionName The function this log should be attributed to. + * @param [in] Format The format string. + * @param ... Variable arguments providing additional information. + * + * @return Success: TRUE Failure: FALSE. + */ +BOOL WINAPIV SeiDbgPrint(SEI_LOG_LEVEL Level, PCSTR FunctionName, PCSTR Format, ...) +{ + char Buffer[512]; + va_list ArgList; + char* Current = Buffer; + const char* LevelStr; + size_t Length = sizeof(Buffer); + + if (g_ShimEngDebugLevel == 0xffffffff) + SeiInitDebugSupport(); + + if (Level > g_ShimEngDebugLevel) + return FALSE; + + switch (Level) + { + case SEI_ERR: + LevelStr = "Err "; + Level = DPFLTR_MASK | (1 << DPFLTR_ERROR_LEVEL); + break; + case SEI_WARN: + LevelStr = "Warn"; + Level = DPFLTR_MASK | (1 << DPFLTR_WARNING_LEVEL); + break; + case SEI_INFO: + LevelStr = "Info"; + Level = DPFLTR_MASK | (1 << DPFLTR_INFO_LEVEL); + break; + default: + LevelStr = "User"; + Level = DPFLTR_MASK | (1 << DPFLTR_INFO_LEVEL); + break; + } + StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s][%-20s] ", LevelStr, FunctionName); + va_start(ArgList, Format); + StringCchVPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, Format, ArgList); + va_end(ArgList); +#if defined(APPCOMPAT_USE_DBGPRINTEX) && APPCOMPAT_USE_DBGPRINTEX + return NT_SUCCESS(DbgPrintEx(DPFLTR_APPCOMPAT_ID, Level, "%s", Buffer)); +#else + OutputDebugStringA(Buffer); + return TRUE; +#endif +} Index: reactos/dll/appcompat/shims/shimlib/shimlib.c =================================================================== --- reactos/dll/appcompat/shims/shimlib/shimlib.c (revision 73422) +++ reactos/dll/appcompat/shims/shimlib/shimlib.c (working copy) @@ -11,13 +11,22 @@ #include #include -HINSTANCE g_hinstDll; +typedef struct UsedShim +{ + SLIST_ENTRY Entry; + PSHIMREG pShim; +} 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 +52,18 @@ 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 +83,8 @@ #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,18 +93,19 @@ 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; + RtlInterlockedPushEntrySList(g_UsedShims, &(shim->Entry)); + + return ps->GetHookAPIs(SHIM_NOTIFY_ATTACH, szCommandLine, pdwHookCount); } } } @@ -90,3 +112,24 @@ return NULL; } + +/* PLDR_DATA_TABLE_ENTRY */ +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 (Notify) + Notify(fdwReason, ptr); + + pEntry = pEntry->Next; + } + + return TRUE; +} Index: reactos/dll/appcompat/shims/shimlib/shimlib.h =================================================================== --- reactos/dll/appcompat/shims/shimlib/shimlib.h (revision 73422) +++ reactos/dll/appcompat/shims/shimlib/shimlib.h (working copy) @@ -8,33 +8,73 @@ #pragma once -typedef struct tagHOOKAPI { +typedef struct tagHOOKAPI +{ PCSTR LibraryName; PCSTR FunctionName; PVOID ReplacementFunction; PVOID OriginalFunction; - PVOID Unk1; - PVOID Unk2; + PVOID Reserved[2]; } 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); +BOOL ShimLib_StrAEqualsW(PCSTR, PCWSTR); + + +/* Forward events to generic handlers */ +void ShimLib_Init(HINSTANCE); +void ShimLib_Deinit(void); PHOOKAPI WINAPI ShimLib_GetHookAPIs(LPCSTR,LPCWSTR,PDWORD); +BOOL WINAPI ShimLib_NotifyShims(DWORD fdwReason, PVOID ptr); -#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 */ +/* Shims should respond to SHIM_REASON_XXXX in the Notify routines. + SHIM_NOTIFY_ codes are sent by apphelp, and translated to SHIM_REASON_ by the shimlib routines. + The only exception being SHIM_NOTIFY_ATTACH, that is also set for one-time init. + */ +#define SHIM_REASON_INIT 100 +#define SHIM_REASON_DEINIT 101 +#define SHIM_REASON_DLL_LOAD 102 /* Arg: PLDR_DATA_TABLE_ENTRY */ +#define SHIM_REASON_DLL_UNLOAD 103 /* Arg: PLDR_DATA_TABLE_ENTRY */ -typedef PVOID (__cdecl *_PVSHIM)(PCWSTR); +#define SHIM_NOTIFY_ATTACH 1 +#define SHIM_NOTIFY_DETACH 2 +#define SHIM_NOTIFY_DLL_LOAD 3 /* Arg: PLDR_DATA_TABLE_ENTRY */ +#define SHIM_NOTIFY_DLL_UNLOAD 4 /* Arg: PLDR_DATA_TABLE_ENTRY */ + + +typedef enum _SEI_LOG_LEVEL { + SEI_ERR = 1, + SEI_WARN = 2, + SEI_INFO = 3, +} SEI_LOG_LEVEL; + +BOOL WINAPIV SeiDbgPrint(SEI_LOG_LEVEL Level, PCSTR FunctionName, PCSTR Format, ...); +extern ULONG g_ShimEngDebugLevel; + +#define SHIMENG_ERR(fmt, ...) do { if (g_ShimEngDebugLevel) SeiDbgPrint(SEI_ERR, __FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0) +#define SHIMENG_WARN(fmt, ...) do { if (g_ShimEngDebugLevel) SeiDbgPrint(SEI_WARN, __FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0) +#define SHIMENG_INFO(fmt, ...) do { if (g_ShimEngDebugLevel) SeiDbgPrint(SEI_INFO, __FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0) + + + +typedef PHOOKAPI (WINAPI* _PVGetHookAPIs)(DWORD, PCSTR, PDWORD); +typedef BOOL (WINAPI* _PVNotify)(DWORD, PVOID); + +typedef struct tagSHIMREG +{ + _PVGetHookAPIs GetHookAPIs; + _PVNotify Notify; + PCSTR ShimName; + //BOOL* pShimUsed; +} SHIMREG, *PSHIMREG; + + #if defined(_MSC_VER) #define _SHMALLOC(x) __declspec(allocate(x)) #elif defined(__GNUC__)