[APPHELP]
[reactos.git] / reactos / dll / appcompat / apphelp / apphelp.c
1 /*
2 * Copyright 2011 André Hentschel
3 * Copyright 2013 Mislav Blažević
4 * Copyright 2015 Mark Jansen
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define WIN32_NO_STATUS
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winver.h"
25 #include "strsafe.h"
26 #include "apphelp.h"
27
28 #include "wine/winternl.h"
29 #include "wine/debug.h"
30 #include "wine/unicode.h"
31
32 /* from dpfilter.h */
33 #define DPFLTR_APPCOMPAT_ID 123
34
35 #ifndef NT_SUCCESS
36 #define NT_SUCCESS(StatCode) ((NTSTATUS)(StatCode) >= 0)
37 #endif
38
39 ULONG g_ShimDebugLevel = 0xffffffff;
40
41 void ApphelppInitDebugLevel(void)
42 {
43 UNICODE_STRING DebugKey, DebugValue;
44 NTSTATUS Status;
45 ULONG NewLevel = 0;
46 WCHAR Buffer[40];
47
48 RtlInitUnicodeString(&DebugKey, L"SHIM_DEBUG_LEVEL");
49 DebugValue.MaximumLength = sizeof(Buffer);
50 DebugValue.Buffer = Buffer;
51 DebugValue.Length = 0;
52
53 /* Hold the lock as short as possible. */
54 RtlAcquirePebLock();
55 Status = RtlQueryEnvironmentVariable_U(NULL, &DebugKey, &DebugValue);
56 RtlReleasePebLock();
57
58 if (NT_SUCCESS(Status))
59 {
60 if (!NT_SUCCESS(RtlUnicodeStringToInteger(&DebugValue, 10, &NewLevel)))
61 NewLevel = 0;
62 }
63 g_ShimDebugLevel = NewLevel;
64 }
65
66 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
67 {
68 switch (reason)
69 {
70 #ifndef __REACTOS__
71 case DLL_WINE_PREATTACH:
72 return FALSE; /* prefer native version */
73 #endif
74 case DLL_PROCESS_ATTACH:
75 DisableThreadLibraryCalls( hinst );
76 SdbpHeapInit();
77 break;
78 case DLL_PROCESS_DETACH:
79 SdbpHeapDeinit();
80 break;
81 }
82 return TRUE;
83 }
84
85
86 /**
87 * Outputs diagnostic info.
88 *
89 * @param [in] Level The level to log this message with, choose any of [SHIM_ERR,
90 * SHIM_WARN, SHIM_INFO].
91 * @param [in] FunctionName The function this log should be attributed to.
92 * @param [in] Format The format string.
93 * @param ... Variable arguments providing additional information.
94 *
95 * @return Success: TRUE Failure: FALSE.
96 */
97 BOOL WINAPIV ShimDbgPrint(SHIM_LOG_LEVEL Level, PCSTR FunctionName, PCSTR Format, ...)
98 {
99 char Buffer[512];
100 va_list ArgList;
101 char* Current = Buffer, *LevelStr;
102 size_t Length = sizeof(Buffer);
103
104 if (g_ShimDebugLevel == 0xffffffff)
105 ApphelppInitDebugLevel();
106
107 if (Level > g_ShimDebugLevel)
108 return FALSE;
109
110 switch (Level)
111 {
112 case SHIM_ERR:
113 LevelStr = "Err ";
114 Level = DPFLTR_MASK | (1 << DPFLTR_ERROR_LEVEL);
115 break;
116 case SHIM_WARN:
117 LevelStr = "Warn";
118 Level = DPFLTR_MASK | (1 << DPFLTR_WARNING_LEVEL);
119 break;
120 case SHIM_INFO:
121 LevelStr = "Info";
122 Level = DPFLTR_MASK | (1 << DPFLTR_INFO_LEVEL);
123 break;
124 default:
125 LevelStr = "User";
126 Level = DPFLTR_MASK | (1 << DPFLTR_INFO_LEVEL);
127 break;
128 }
129 StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s][%-20s] ", LevelStr, FunctionName);
130 va_start(ArgList, Format);
131 StringCchVPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, Format, ArgList);
132 va_end(ArgList);
133 return NT_SUCCESS(DbgPrintEx(DPFLTR_APPCOMPAT_ID, Level, "%s", Buffer));
134 }
135