aboutsummaryrefslogtreecommitdiff
path: root/src/libs/wcautil/WixToolset.WcaUtil/wcalog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/wcautil/WixToolset.WcaUtil/wcalog.cpp')
-rw-r--r--src/libs/wcautil/WixToolset.WcaUtil/wcalog.cpp269
1 files changed, 269 insertions, 0 deletions
diff --git a/src/libs/wcautil/WixToolset.WcaUtil/wcalog.cpp b/src/libs/wcautil/WixToolset.WcaUtil/wcalog.cpp
new file mode 100644
index 00000000..cc7d1438
--- /dev/null
+++ b/src/libs/wcautil/WixToolset.WcaUtil/wcalog.cpp
@@ -0,0 +1,269 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5/********************************************************************
6 IsVerboseLoggingPolicy() - internal helper function to detect if
7 policy is set for verbose logging. Does
8 not require database access.
9********************************************************************/
10static BOOL IsVerboseLoggingPolicy()
11{
12 BOOL fVerbose = FALSE;
13 HKEY hkey = NULL;
14 WCHAR rgwc[16] = { 0 };
15 DWORD cb = sizeof(rgwc);
16 if (ERROR_SUCCESS == ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Policies\\Microsoft\\Windows\\Installer", 0, KEY_QUERY_VALUE, &hkey))
17 {
18 if (ERROR_SUCCESS == ::RegQueryValueExW(hkey, L"Logging", 0, NULL, reinterpret_cast<BYTE*>(rgwc), &cb))
19 {
20 for (LPCWSTR pwc = rgwc; (cb / sizeof(WCHAR)) > static_cast<DWORD>(pwc - rgwc) && *pwc; pwc++)
21 {
22 if (L'v' == *pwc || L'V' == *pwc)
23 {
24 fVerbose = TRUE;
25 break;
26 }
27 }
28 }
29
30 ::RegCloseKey(hkey);
31 }
32 return fVerbose;
33}
34
35/********************************************************************
36 IsVerboseLogging() - internal helper function to detect if doing
37 verbose logging. Checks:
38 1. LOGVERBOSE property.
39 2. MsiLogging property contains 'v'
40 3. Policy from registry.
41
42 Requires database access.
43********************************************************************/
44BOOL WIXAPI IsVerboseLogging()
45{
46 static int iVerbose = -1;
47 LPWSTR pwzMsiLogging = NULL;
48
49 if (0 > iVerbose)
50 {
51 iVerbose = WcaIsPropertySet("LOGVERBOSE");
52 if (0 == iVerbose)
53 {
54 // if the property wasn't set, check the MsiLogging property (MSI 4.0+)
55 HRESULT hr = WcaGetProperty(L"MsiLogging", &pwzMsiLogging);
56 ExitOnFailure(hr, "failed to get MsiLogging property");
57
58 if (pwzMsiLogging)
59 {
60 for (int i = 0; pwzMsiLogging[i]; i++)
61 {
62 if (L'v' == pwzMsiLogging[i] || L'V' == pwzMsiLogging[i])
63 {
64 iVerbose = 1;
65 break;
66 }
67 }
68 }
69
70 // last chance: Check the registry to see if the logging policy was turned on
71 if (0 == iVerbose && IsVerboseLoggingPolicy())
72 {
73 iVerbose = 1;
74 }
75 }
76 }
77
78LExit:
79 ReleaseStr(pwzMsiLogging);
80 Assert(iVerbose >= 0);
81 return (BOOL)iVerbose;
82}
83
84/********************************************************************
85 SetVerboseLoggingAtom() - Sets one of two global Atoms to specify
86 if the install should do verbose logging.
87 Communicates the verbose setting to
88 deferred CAs.
89 Set a negative case atom so that we can
90 distinguish between an unset atom and the
91 non-verbose case. This helps prevent the
92 expensive regkey lookup for non-verbose.
93********************************************************************/
94HRESULT WIXAPI SetVerboseLoggingAtom(BOOL bValue)
95{
96 HRESULT hr = S_OK;
97 ATOM atomVerbose = 0;
98
99 atomVerbose = ::GlobalFindAtomW(L"WcaVerboseLogging");
100 if (0 == atomVerbose && bValue)
101 {
102 atomVerbose = ::GlobalAddAtomW(L"WcaVerboseLogging");
103 ExitOnNullWithLastError(atomVerbose, hr, "Failed to create WcaVerboseLogging global atom.");
104 }
105 else if (0 != atomVerbose && !bValue)
106 {
107 ::SetLastError(ERROR_SUCCESS);
108 ::GlobalDeleteAtom(atomVerbose);
109 ExitOnLastError(hr, "Failed to delete WcaVerboseLogging global atom.");
110 }
111
112 atomVerbose = ::GlobalFindAtomW(L"WcaNotVerboseLogging");
113 if (0 == atomVerbose && !bValue)
114 {
115 atomVerbose = ::GlobalAddAtomW(L"WcaNotVerboseLogging");
116 ExitOnNullWithLastError(atomVerbose, hr, "Failed to create WcaNotVerboseLogging global atom.");
117 }
118 else if (0 != atomVerbose && bValue)
119 {
120 ::SetLastError(ERROR_SUCCESS);
121 ::GlobalDeleteAtom(atomVerbose);
122 ExitOnLastError(hr, "Failed to delete WcaNotVerboseLogging global atom.");
123 }
124
125LExit:
126 return hr;
127}
128
129/********************************************************************
130 IsVerboseLoggingLite() - internal helper function to detect if atom was
131 previously set to specify verbose logging.
132 Falls back on policy for an installer that is
133 unable to set the atom (no immediate CAs).
134
135 Does not require database access.
136********************************************************************/
137static BOOL IsVerboseLoggingLite()
138{
139 ATOM atomVerbose = ::GlobalFindAtomW(L"WcaVerboseLogging");
140 if (0 != atomVerbose)
141 {
142 return TRUE;
143 }
144
145 atomVerbose = ::GlobalFindAtomW(L"WcaNotVerboseLogging");
146 if (0 != atomVerbose)
147 {
148 return FALSE;
149 }
150
151 return IsVerboseLoggingPolicy();
152}
153
154/********************************************************************
155 WcaLog() - outputs trace and log info
156
157*******************************************************************/
158extern "C" void __cdecl WcaLog(
159 __in LOGLEVEL llv,
160 __in_z __format_string PCSTR fmt,
161 ...
162 )
163{
164 static char szFmt[LOG_BUFFER];
165 static char szBuf[LOG_BUFFER];
166 static bool fInLogPrint = false;
167
168 // prevent re-entrant logprints. (recursion issues between assert/logging code)
169 if (fInLogPrint)
170 return;
171 fInLogPrint = true;
172
173 if (LOGMSG_STANDARD == llv ||
174 (LOGMSG_VERBOSE == llv && IsVerboseLoggingLite())
175#ifdef DEBUG
176 || LOGMSG_TRACEONLY == llv
177#endif
178 )
179 {
180 va_list args;
181 va_start(args, fmt);
182
183 LPCSTR szLogName = WcaGetLogName();
184 if (szLogName[0] != 0)
185 StringCchPrintfA(szFmt, countof(szFmt), "%s: %s", szLogName, fmt);
186 else
187 StringCchCopyA(szFmt, countof(szFmt), fmt);
188
189 StringCchVPrintfA(szBuf, countof(szBuf), szFmt, args);
190 va_end(args);
191
192#ifdef DEBUG
193 // always write to the log in debug
194#else
195 if (llv == LOGMSG_STANDARD || (llv == LOGMSG_VERBOSE && IsVerboseLoggingLite()))
196#endif
197 {
198 PMSIHANDLE hrec = MsiCreateRecord(1);
199
200 ::MsiRecordSetStringA(hrec, 0, szBuf);
201 // TODO: Recursion on failure. May not be safe to assert from here.
202 WcaProcessMessage(INSTALLMESSAGE_INFO, hrec);
203 }
204
205#if DEBUG
206 StringCchCatA(szBuf, countof(szBuf), "\n");
207 OutputDebugStringA(szBuf);
208#endif
209 }
210
211 fInLogPrint = false;
212 return;
213}
214
215
216/********************************************************************
217 WcaDisplayAssert() - called before Assert() dialog shows
218
219 NOTE: writes the assert string to the MSI log
220********************************************************************/
221extern "C" BOOL WIXAPI WcaDisplayAssert(
222 __in LPCSTR sz
223 )
224{
225 WcaLog(LOGMSG_STANDARD, "Debug Assert Message: %s", sz);
226 return TRUE;
227}
228
229
230/********************************************************************
231 WcaLogError() - called before ExitOnXXX() macro exits the function
232
233 NOTE: writes the hresult and error string to the MSI log
234********************************************************************/
235extern "C" void WcaLogError(
236 __in HRESULT hr,
237 __in LPCSTR szMessage,
238 ...
239 )
240{
241 va_list dots;
242
243 va_start(dots, szMessage);
244 WcaLogErrorArgs(hr, szMessage, dots);
245 va_end(dots);
246}
247
248
249/********************************************************************
250 WcaLogErrorArgs() - called before ExitOnXXX() macro exits the function
251
252 NOTE: writes the hresult and error string to the MSI log
253********************************************************************/
254extern "C" void WcaLogErrorArgs(
255 __in HRESULT hr,
256 __in LPCSTR szMessage,
257 __in va_list args
258 )
259{
260 char szBuffer[LOG_BUFFER];
261
262 StringCchVPrintfA(szBuffer, countof(szBuffer), szMessage, args);
263
264 // log the message if using Wca common layer
265 if (WcaIsInitialized())
266 {
267 WcaLog(LOGMSG_STANDARD, "Error 0x%x: %s", hr, szBuffer);
268 }
269}