From c7afd6f90c5854a5a9029f4ffe40b658bbc68888 Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Sat, 13 May 2017 18:49:27 +0000 Subject: [PATCH] [APPHELP][SHIMLIB] Forward some events to loaded shims. CORE-11329 svn path=/trunk/; revision=74535 --- reactos/dll/appcompat/apphelp/CMakeLists.txt | 1 + reactos/dll/appcompat/apphelp/apphelp.spec | 14 +- reactos/dll/appcompat/apphelp/shimeng.c | 163 ++++++++++++++++++ .../appcompat/shims/shimlib/CMakeLists.txt | 1 - .../dll/appcompat/shims/shimlib/shimdbgsupp.c | 79 --------- reactos/dll/appcompat/shims/shimlib/shimlib.h | 12 +- 6 files changed, 179 insertions(+), 91 deletions(-) create mode 100644 reactos/dll/appcompat/apphelp/shimeng.c delete mode 100644 reactos/dll/appcompat/shims/shimlib/shimdbgsupp.c diff --git a/reactos/dll/appcompat/apphelp/CMakeLists.txt b/reactos/dll/appcompat/apphelp/CMakeLists.txt index 019a8747410..d2fa858d3c8 100644 --- a/reactos/dll/appcompat/apphelp/CMakeLists.txt +++ b/reactos/dll/appcompat/apphelp/CMakeLists.txt @@ -15,6 +15,7 @@ list(APPEND SOURCE sdbread.c sdbstringtable.c sdbwrite.c + shimeng.c apphelp.spec apphelp.h ${CMAKE_CURRENT_BINARY_DIR}/apphelp_stubs.c) diff --git a/reactos/dll/appcompat/apphelp/apphelp.spec b/reactos/dll/appcompat/apphelp/apphelp.spec index 51a3019c560..dfebf83e882 100644 --- a/reactos/dll/appcompat/apphelp/apphelp.spec +++ b/reactos/dll/appcompat/apphelp/apphelp.spec @@ -157,17 +157,19 @@ @ stdcall SdbWriteStringTag(ptr long wstr) @ stub SdbWriteStringTagDirect @ stdcall SdbWriteWORDTag(ptr long long) -@ stub SE_DllLoaded -@ stub SE_DllUnloaded +@ stdcall SE_DllLoaded(ptr) +@ stdcall SE_DllUnloaded(ptr) +@ stub SE_DynamicShim +@ stub SE_DynamicUnshim +@ stdcall SE_InstallAfterInit(ptr ptr) +@ stdcall SE_InstallBeforeInit(ptr ptr) +@ stdcall SE_IsShimDll(ptr) +@ stdcall SE_ProcessDying() @ stub SE_GetHookAPIs @ stub SE_GetMaxShimCount @ stub SE_GetProcAddressLoad @ stub SE_GetShimCount -@ stub SE_InstallAfterInit -@ stub SE_InstallBeforeInit -@ stub SE_IsShimDll @ stub SE_LdrEntryRemoved -@ stub SE_ProcessDying @ stub SetPermLayers @ cdecl ShimDbgPrint(long str str) @ stub ShimDumpCache diff --git a/reactos/dll/appcompat/apphelp/shimeng.c b/reactos/dll/appcompat/apphelp/shimeng.c new file mode 100644 index 00000000000..21fe7817831 --- /dev/null +++ b/reactos/dll/appcompat/apphelp/shimeng.c @@ -0,0 +1,163 @@ +/* + * Copyright 2015-2017 Mark Jansen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define WIN32_NO_STATUS +#include "windows.h" +#include "ntndk.h" +#include "shimlib.h" +#include + +HANDLE g_pShimEngModHandle = 0; + + +ULONG g_ShimEngDebugLevel = 0xffffffff; + + + + +VOID SeiInitDebugSupport(VOID) +{ + static const UNICODE_STRING DebugKey = RTL_CONSTANT_STRING(L"SHIMENG_DEBUG_LEVEL"); + UNICODE_STRING DebugValue; + NTSTATUS Status; + ULONG NewLevel = 0; + WCHAR Buffer[40]; + + RtlInitEmptyUnicodeString(&DebugValue, Buffer, sizeof(Buffer)); + + Status = RtlQueryEnvironmentVariable_U(NULL, &DebugKey, &DebugValue); + + if (NT_SUCCESS(Status)) + { + if (!NT_SUCCESS(RtlUnicodeStringToInteger(&DebugValue, 10, &NewLevel))) + NewLevel = 0; + } + g_ShimEngDebugLevel = NewLevel; +} + + +/** + * 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 Function, PCSTR Format, ...) +{ + char Buffer[512]; + char* Current = Buffer; + const char* LevelStr; + size_t Length = sizeof(Buffer); + va_list ArgList; + HRESULT hr; + + if (g_ShimEngDebugLevel == 0xffffffff) + SeiInitDebugSupport(); + + if (Level > g_ShimEngDebugLevel) + return FALSE; + + switch (Level) + { + case SEI_MSG: + LevelStr = "MSG "; + break; + case SEI_FAIL: + LevelStr = "FAIL"; + break; + case SEI_WARN: + LevelStr = "WARN"; + break; + case SEI_INFO: + LevelStr = "INFO"; + break; + default: + LevelStr = "USER"; + break; + } + + if (Function) + hr = StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s] [%s] ", LevelStr, Function); + else + hr = StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s] ", LevelStr); + + if (!SUCCEEDED(hr)) + return FALSE; + + va_start(ArgList, Format); + hr = StringCchVPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, Format, ArgList); + va_end(ArgList); + if (!SUCCEEDED(hr)) + return FALSE; + + DbgPrint("%s", Buffer); + return TRUE; +} + + + + + + +VOID NotifyShims(DWORD dwReason, PVOID Info) +{ + /* Enumerate all loaded shims */ +} + + +VOID NTAPI SE_InstallBeforeInit(PUNICODE_STRING ProcessImage, PVOID pShimData) +{ + SHIMENG_FAIL("(%wZ, %p)", ProcessImage, pShimData); + /* Find & Load all shims.. */ +} + +VOID NTAPI SE_InstallAfterInit(PUNICODE_STRING ProcessImage, PVOID pShimData) +{ + SHIMENG_FAIL("(%wZ, %p)", ProcessImage, pShimData); + NotifyShims(SHIM_NOTIFY_ATTACH, NULL); +} + +VOID NTAPI SE_ProcessDying(VOID) +{ + SHIMENG_FAIL("()"); + NotifyShims(SHIM_NOTIFY_DETACH, NULL); +} + +VOID WINAPI SE_DllLoaded(PLDR_DATA_TABLE_ENTRY LdrEntry) +{ + SHIMENG_FAIL("(%p)", LdrEntry); + NotifyShims(SHIM_REASON_DLL_LOAD, LdrEntry); +} + +VOID WINAPI SE_DllUnloaded(PLDR_DATA_TABLE_ENTRY LdrEntry) +{ + SHIMENG_FAIL("(%p)", LdrEntry); + NotifyShims(SHIM_REASON_DLL_UNLOAD, LdrEntry); +} + +BOOL WINAPI SE_IsShimDll(PVOID BaseAddress) +{ + SHIMENG_FAIL("(%p)", BaseAddress); + return FALSE; +} + diff --git a/reactos/dll/appcompat/shims/shimlib/CMakeLists.txt b/reactos/dll/appcompat/shims/shimlib/CMakeLists.txt index 1b233162c0c..2c799c90354 100644 --- a/reactos/dll/appcompat/shims/shimlib/CMakeLists.txt +++ b/reactos/dll/appcompat/shims/shimlib/CMakeLists.txt @@ -1,6 +1,5 @@ list(APPEND SOURCE - shimdbgsupp.c shimlib.c shimlib.h # These .inl functions are included so they show up in vs diff --git a/reactos/dll/appcompat/shims/shimlib/shimdbgsupp.c b/reactos/dll/appcompat/shims/shimlib/shimdbgsupp.c deleted file mode 100644 index 7861ec705b9..00000000000 --- a/reactos/dll/appcompat/shims/shimlib/shimdbgsupp.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 -} diff --git a/reactos/dll/appcompat/shims/shimlib/shimlib.h b/reactos/dll/appcompat/shims/shimlib/shimlib.h index d7926f59e1a..6f1efd9c5cf 100644 --- a/reactos/dll/appcompat/shims/shimlib/shimlib.h +++ b/reactos/dll/appcompat/shims/shimlib/shimlib.h @@ -49,15 +49,17 @@ BOOL WINAPI ShimLib_NotifyShims(DWORD fdwReason, PVOID ptr); typedef enum _SEI_LOG_LEVEL { - SEI_ERR = 1, - SEI_WARN = 2, - SEI_INFO = 3, + SEI_MSG = 1, + SEI_FAIL = 2, + SEI_WARN = 3, + SEI_INFO = 4, } SEI_LOG_LEVEL; -BOOL WINAPIV SeiDbgPrint(SEI_LOG_LEVEL Level, PCSTR FunctionName, PCSTR Format, ...); +BOOL WINAPIV SeiDbgPrint(SEI_LOG_LEVEL Level, PCSTR Function, 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_MSG(fmt, ...) do { if (g_ShimEngDebugLevel) SeiDbgPrint(SEI_MSG, __FUNCTION__, fmt, ##__VA_ARGS__ ); } while (0) +#define SHIMENG_FAIL(fmt, ...) do { if (g_ShimEngDebugLevel) SeiDbgPrint(SEI_FAIL, __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)