From 116dfc5bd7e29f1b6891bc775ea4d861744f0fb4 Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Sun, 16 Jul 2017 13:50:23 +0000 Subject: [PATCH] [SHIMLIB] Add debug print functionality for shims. CORE-11329 svn path=/trunk/; revision=75358 --- reactos/dll/appcompat/apphelp/shimeng.c | 1 + reactos/dll/appcompat/shims/shimlib/shimlib.c | 91 ++++++++++++++++++- reactos/dll/appcompat/shims/shimlib/shimlib.h | 13 ++- 3 files changed, 101 insertions(+), 4 deletions(-) diff --git a/reactos/dll/appcompat/apphelp/shimeng.c b/reactos/dll/appcompat/apphelp/shimeng.c index c04d5d3d4df..b6bf2e85a61 100644 --- a/reactos/dll/appcompat/apphelp/shimeng.c +++ b/reactos/dll/appcompat/apphelp/shimeng.c @@ -19,6 +19,7 @@ #define WIN32_NO_STATUS #include "windows.h" #include "ntndk.h" +#define IN_APPHELP #include "shimlib.h" #include /* Make sure we don't include apphelp logging */ diff --git a/reactos/dll/appcompat/shims/shimlib/shimlib.c b/reactos/dll/appcompat/shims/shimlib/shimlib.c index 65aed846a56..b5f04c28081 100644 --- a/reactos/dll/appcompat/shims/shimlib/shimlib.c +++ b/reactos/dll/appcompat/shims/shimlib/shimlib.c @@ -3,13 +3,15 @@ * PROJECT: ReactOS Shim library * FILE: dll/appcompat/shims/shimlib/shimlib.c * PURPOSE: Shim helper functions - * PROGRAMMER: Mark Jansen + * PROGRAMMER: Mark Jansen (mark.jansen@reactos.org) */ +#define WIN32_NO_STATUS #include #include #include #include +#include typedef struct UsedShim { @@ -21,6 +23,7 @@ typedef struct UsedShim } UsedShim, *pUsedShim; +ULONG g_ShimEngDebugLevel = 0xffffffff; static HANDLE g_ShimLib_Heap; static PSLIST_HEADER g_UsedShims; @@ -146,3 +149,89 @@ BOOL WINAPI ShimLib_NotifyShims(DWORD fdwReason, PVOID ptr) return TRUE; } + + +VOID SeiInitDebugSupport(VOID) +{ + static const UNICODE_STRING DebugKey = RTL_CONSTANT_STRING(L"SHIM_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; +} + diff --git a/reactos/dll/appcompat/shims/shimlib/shimlib.h b/reactos/dll/appcompat/shims/shimlib/shimlib.h index 6f1efd9c5cf..8372b05065d 100644 --- a/reactos/dll/appcompat/shims/shimlib/shimlib.h +++ b/reactos/dll/appcompat/shims/shimlib/shimlib.h @@ -3,7 +3,7 @@ * PROJECT: ReactOS Shim Engine * FILE: dll/appcompat/shims/shimlib/shimlib.h * PURPOSE: ReactOS Shim Engine - * PROGRAMMER: Mark Jansen + * PROGRAMMER: Mark Jansen (mark.jansen@reactos.org) */ #pragma once @@ -58,12 +58,19 @@ typedef enum _SEI_LOG_LEVEL { BOOL WINAPIV SeiDbgPrint(SEI_LOG_LEVEL Level, PCSTR Function, PCSTR Format, ...); extern ULONG g_ShimEngDebugLevel; +#if defined(IN_APPHELP) +/* Apphelp shimeng logging uses the function name */ #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) - - +#else +/* Shims use the shim name */ +#define SHIM_MSG(fmt, ...) do { if (g_ShimEngDebugLevel) SeiDbgPrint(SEI_MSG, SHIM_OBJ_NAME(g_szModuleName), fmt, ##__VA_ARGS__ ); } while (0) +#define SHIM_FAIL(fmt, ...) do { if (g_ShimEngDebugLevel) SeiDbgPrint(SEI_FAIL, SHIM_OBJ_NAME(g_szModuleName), fmt, ##__VA_ARGS__ ); } while (0) +#define SHIM_WARN(fmt, ...) do { if (g_ShimEngDebugLevel) SeiDbgPrint(SEI_WARN, SHIM_OBJ_NAME(g_szModuleName), fmt, ##__VA_ARGS__ ); } while (0) +#define SHIM_INFO(fmt, ...) do { if (g_ShimEngDebugLevel) SeiDbgPrint(SEI_INFO, SHIM_OBJ_NAME(g_szModuleName), fmt, ##__VA_ARGS__ ); } while (0) +#endif typedef PHOOKAPI (WINAPI* _PVGetHookAPIs)(DWORD, PCSTR, PDWORD); typedef BOOL (WINAPI* _PVNotify)(DWORD, PVOID);