158433b2263b431a6b35787bb395818dfa5febdc
[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
30 /* from dpfilter.h */
31 #define DPFLTR_APPCOMPAT_ID 123
32
33 #ifndef NT_SUCCESS
34 #define NT_SUCCESS(StatCode) ((NTSTATUS)(StatCode) >= 0)
35 #endif
36
37 ULONG g_ShimDebugLevel = 0xffffffff;
38
39 void ApphelppInitDebugLevel(void)
40 {
41 UNICODE_STRING DebugKey, DebugValue;
42 NTSTATUS Status;
43 ULONG NewLevel = SHIM_ERR;
44 WCHAR Buffer[40];
45
46 RtlInitUnicodeString(&DebugKey, L"SHIM_DEBUG_LEVEL");
47 DebugValue.MaximumLength = sizeof(Buffer);
48 DebugValue.Buffer = Buffer;
49 DebugValue.Length = 0;
50
51 /* Hold the lock as short as possible. */
52 RtlAcquirePebLock();
53 Status = RtlQueryEnvironmentVariable_U(NULL, &DebugKey, &DebugValue);
54 RtlReleasePebLock();
55
56 if (NT_SUCCESS(Status))
57 {
58 if (!NT_SUCCESS(RtlUnicodeStringToInteger(&DebugValue, 10, &NewLevel)))
59 NewLevel = 0;
60 }
61 g_ShimDebugLevel = NewLevel;
62 }
63
64 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
65 {
66 switch (reason)
67 {
68 #ifndef __REACTOS__
69 case DLL_WINE_PREATTACH:
70 return FALSE; /* prefer native version */
71 #endif
72 case DLL_PROCESS_ATTACH:
73 DisableThreadLibraryCalls( hinst );
74 SdbpHeapInit();
75 break;
76 case DLL_PROCESS_DETACH:
77 SdbpHeapDeinit();
78 break;
79 }
80 return TRUE;
81 }
82
83 BOOL WINAPI ApphelpCheckInstallShieldPackage(void* ptr, LPCWSTR path)
84 {
85 SHIM_WARN("stub: ptr=%p path='%S'\r\n", ptr, path);
86 return TRUE;
87 }
88
89
90 /**
91 * Outputs diagnostic info.
92 *
93 * @param [in] Level The level to log this message with, choose any of [SHIM_ERR,
94 * SHIM_WARN, SHIM_INFO].
95 * @param [in] FunctionName The function this log should be attributed to.
96 * @param [in] Format The format string.
97 * @param ... Variable arguments providing additional information.
98 *
99 * @return Success: TRUE Failure: FALSE.
100 */
101 BOOL WINAPIV ShimDbgPrint(SHIM_LOG_LEVEL Level, PCSTR FunctionName, PCSTR Format, ...)
102 {
103 char Buffer[512];
104 va_list ArgList;
105 char* Current = Buffer;
106 const char* LevelStr;
107 size_t Length = sizeof(Buffer);
108
109 if (g_ShimDebugLevel == 0xffffffff)
110 ApphelppInitDebugLevel();
111
112 if (Level > g_ShimDebugLevel)
113 return FALSE;
114
115 switch (Level)
116 {
117 case SHIM_ERR:
118 LevelStr = "Err ";
119 Level = DPFLTR_MASK | (1 << DPFLTR_ERROR_LEVEL);
120 break;
121 case SHIM_WARN:
122 LevelStr = "Warn";
123 Level = DPFLTR_MASK | (1 << DPFLTR_WARNING_LEVEL);
124 break;
125 case SHIM_INFO:
126 LevelStr = "Info";
127 Level = DPFLTR_MASK | (1 << DPFLTR_INFO_LEVEL);
128 break;
129 default:
130 LevelStr = "User";
131 Level = DPFLTR_MASK | (1 << DPFLTR_INFO_LEVEL);
132 break;
133 }
134 StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s][%-20s] ", LevelStr, FunctionName);
135 va_start(ArgList, Format);
136 StringCchVPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, Format, ArgList);
137 va_end(ArgList);
138 #if defined(APPCOMPAT_USE_DBGPRINTEX) && APPCOMPAT_USE_DBGPRINTEX
139 return NT_SUCCESS(DbgPrintEx(DPFLTR_APPCOMPAT_ID, Level, "%s", Buffer));
140 #else
141 OutputDebugStringA(Buffer);
142 return TRUE;
143 #endif
144 }
145