Index: src/installer-ca/wcalog.cpp |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/installer-ca/wcalog.cpp |
@@ -0,0 +1,262 @@ |
+//------------------------------------------------------------------------------------------------- |
+// <copyright file="wcalog.cpp" company="Outercurve Foundation"> |
+// Copyright (c) 2004, Outercurve Foundation. |
+// This software is released under Microsoft Reciprocal License (MS-RL). |
+// The license and further copyright text can be found in the file |
+// LICENSE.TXT at the root directory of the distribution. |
+// </copyright> |
+// |
+// <summary> |
+// Windows Installer XML CustomAction utility library logging functions |
+// </summary> |
+//------------------------------------------------------------------------------------------------- |
+ |
+#include "precomp.h" |
+ |
+/******************************************************************** |
+ IsVerboseLoggingPolicy() - internal helper function to detect if |
+ policy is set for verbose logging. Does |
+ not require database access. |
+********************************************************************/ |
+static BOOL IsVerboseLoggingPolicy() |
+{ |
+ BOOL fVerbose = FALSE; |
+ HKEY hkey = NULL; |
+ WCHAR rgwc[16] = { 0 }; |
+ DWORD cb = sizeof(rgwc); |
+ if (ERROR_SUCCESS == ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Policies\\Microsoft\\Windows\\Installer", 0, KEY_QUERY_VALUE, &hkey)) |
+ { |
+ if (ERROR_SUCCESS == ::RegQueryValueExW(hkey, L"Logging", 0, NULL, reinterpret_cast<BYTE*>(rgwc), &cb)) |
+ { |
+ for (LPCWSTR pwc = rgwc; (cb / sizeof(WCHAR)) > static_cast<DWORD>(pwc - rgwc) && *pwc; pwc++) |
+ { |
+ if (L'v' == *pwc || L'V' == *pwc) |
+ { |
+ fVerbose = TRUE; |
+ break; |
+ } |
+ } |
+ } |
+ |
+ ::RegCloseKey(hkey); |
+ } |
+ return fVerbose; |
+} |
+ |
+/******************************************************************** |
+ IsVerboseLogging() - internal helper function to detect if doing |
+ verbose logging. Checks: |
+ 1. LOGVERBOSE property. |
+ 2. MsiLogging property contains 'v' |
+ 3. Policy from registry. |
+ |
+ Requires database access. |
+********************************************************************/ |
+BOOL WIXAPI IsVerboseLogging() |
+{ |
+ static int iVerbose = -1; |
+ LPWSTR pwzMsiLogging = NULL; |
+ |
+ if (0 > iVerbose) |
+ { |
+ iVerbose = WcaIsPropertySet("LOGVERBOSE"); |
+ if (0 == iVerbose) |
+ { |
+ // if the property wasn't set, check the MsiLogging property (MSI 4.0+) |
+ HRESULT hr = WcaGetProperty(L"MsiLogging", &pwzMsiLogging); |
+ ExitOnFailure(hr, "failed to get MsiLogging property"); |
+ int cchMsiLogging = lstrlenW(pwzMsiLogging); |
+ if (0 < cchMsiLogging) |
+ { |
+ for (int i = 0; i < cchMsiLogging; i++) |
+ { |
+ if (L'v' == pwzMsiLogging[i] || L'V' == pwzMsiLogging[i]) |
+ { |
+ iVerbose = 1; |
+ break; |
+ } |
+ } |
+ } |
+ |
+ // last chance: Check the registry to see if the logging policy was turned on |
+ if (0 == iVerbose && IsVerboseLoggingPolicy()) |
+ { |
+ iVerbose = 1; |
+ } |
+ } |
+ } |
+ |
+LExit: |
+ ReleaseStr(pwzMsiLogging); |
+ Assert(iVerbose >= 0); |
+ return (BOOL)iVerbose; |
+} |
+ |
+/******************************************************************** |
+ SetVerboseLoggingAtom() - Sets one of two global Atoms to specify |
+ if the install should do verbose logging. |
+ Communicates the verbose setting to |
+ deferred CAs. |
+ Set a negative case atom so that we can |
+ distinguish between an unset atom and the |
+ non-verbose case. This helps prevent the |
+ expensive regkey lookup for non-verbose. |
+********************************************************************/ |
+HRESULT WIXAPI SetVerboseLoggingAtom(BOOL bValue) |
+{ |
+ HRESULT hr = S_OK; |
+ ATOM atomVerbose = 0; |
+ |
+ atomVerbose = ::GlobalFindAtomW(L"WcaVerboseLogging"); |
+ if (0 == atomVerbose && bValue) |
+ { |
+ atomVerbose = ::GlobalAddAtomW(L"WcaVerboseLogging"); |
+ ExitOnNullWithLastError(atomVerbose, hr, "Failed to create WcaVerboseLogging global atom."); |
+ } |
+ else if (0 != atomVerbose && !bValue) |
+ { |
+ ::SetLastError(ERROR_SUCCESS); |
+ ::GlobalDeleteAtom(atomVerbose); |
+ ExitOnLastError(hr, "Failed to delete WcaVerboseLogging global atom."); |
+ } |
+ |
+ atomVerbose = ::GlobalFindAtomW(L"WcaNotVerboseLogging"); |
+ if (0 == atomVerbose && !bValue) |
+ { |
+ atomVerbose = ::GlobalAddAtomW(L"WcaNotVerboseLogging"); |
+ ExitOnNullWithLastError(atomVerbose, hr, "Failed to create WcaNotVerboseLogging global atom."); |
+ } |
+ else if (0 != atomVerbose && bValue) |
+ { |
+ ::SetLastError(ERROR_SUCCESS); |
+ ::GlobalDeleteAtom(atomVerbose); |
+ ExitOnLastError(hr, "Failed to delete WcaNotVerboseLogging global atom."); |
+ } |
+ |
+LExit: |
+ return hr; |
+} |
+ |
+/******************************************************************** |
+ IsVerboseLoggingLite() - internal helper function to detect if atom was |
+ previously set to specify verbose logging. |
+ Falls back on policy for an installer that is |
+ unable to set the atom (no immediate CAs). |
+ |
+ Does not require database access. |
+********************************************************************/ |
+static BOOL IsVerboseLoggingLite() |
+{ |
+ ATOM atomVerbose = ::GlobalFindAtomW(L"WcaVerboseLogging"); |
+ if (0 != atomVerbose) |
+ { |
+ return TRUE; |
+ } |
+ |
+ atomVerbose = ::GlobalFindAtomW(L"WcaNotVerboseLogging"); |
+ if (0 != atomVerbose) |
+ { |
+ return FALSE; |
+ } |
+ |
+ return IsVerboseLoggingPolicy(); |
+} |
+ |
+/******************************************************************** |
+ WcaLog() - outputs trace and log info |
+ |
+*******************************************************************/ |
+extern "C" void __cdecl WcaLog( |
+ __in LOGLEVEL llv, |
+ __in_z __format_string PCSTR fmt, |
+ ... |
+ ) |
+{ |
+ static char szFmt[LOG_BUFFER]; |
+ static char szBuf[LOG_BUFFER]; |
+ static bool fInLogPrint = false; |
+ |
+ // prevent re-entrant logprints. (recursion issues between assert/logging code) |
+ if (fInLogPrint) |
+ return; |
+ fInLogPrint = true; |
+ |
+ if (LOGMSG_STANDARD == llv || |
+ (LOGMSG_VERBOSE == llv && IsVerboseLoggingLite()) |
+#ifdef DEBUG |
+ || LOGMSG_TRACEONLY == llv |
+#endif |
+ ) |
+ { |
+ va_list args; |
+ va_start(args, fmt); |
+ |
+ LPCSTR szLogName = WcaGetLogName(); |
+ if (szLogName[0] != 0) |
+ StringCchPrintfA(szFmt, countof(szFmt), "%s: %s", szLogName, fmt); |
+ else |
+ StringCchCopyA(szFmt, countof(szFmt), fmt); |
+ |
+ StringCchVPrintfA(szBuf, countof(szBuf), szFmt, args); |
+ va_end(args); |
+ |
+#ifdef DEBUG |
+ // always write to the log in debug |
+#else |
+ if (llv == LOGMSG_STANDARD || (llv == LOGMSG_VERBOSE && IsVerboseLoggingLite())) |
+#endif |
+ { |
+ PMSIHANDLE hrec = MsiCreateRecord(1); |
+ |
+ ::MsiRecordSetStringA(hrec, 0, szBuf); |
+ // TODO: Recursion on failure. May not be safe to assert from here. |
+ WcaProcessMessage(INSTALLMESSAGE_INFO, hrec); |
+ } |
+ |
+#if DEBUG |
+ StringCchCatA(szBuf, countof(szBuf), "\n"); |
+ OutputDebugStringA(szBuf); |
+#endif |
+ } |
+ |
+ fInLogPrint = false; |
+ return; |
+} |
+ |
+ |
+/******************************************************************** |
+ WcaDisplayAssert() - called before Assert() dialog shows |
+ |
+ NOTE: writes the assert string to the MSI log |
+********************************************************************/ |
+extern "C" BOOL WIXAPI WcaDisplayAssert( |
+ __in LPCSTR sz |
+ ) |
+{ |
+ WcaLog(LOGMSG_STANDARD, "Debug Assert Message: %s", sz); |
+ return TRUE; |
+} |
+ |
+ |
+/******************************************************************** |
+ WcaLogError() - called before ExitOnXXX() macro exists the function |
+ |
+ NOTE: writes the hresult and error string to the MSI log |
+********************************************************************/ |
+extern "C" void WcaLogError( |
+ __in HRESULT hr, |
+ __in LPCSTR szMessage, |
+ ... |
+ ) |
+{ |
+ char szBuffer[LOG_BUFFER]; |
+ va_list dots; |
+ |
+ va_start(dots, szMessage); |
+ StringCchVPrintfA(szBuffer, countof(szBuffer), szMessage, dots); |
+ va_end(dots); |
+ |
+ // log the message if using Wca common layer |
+ if (WcaIsInitialized()) |
+ WcaLog(LOGMSG_STANDARD, "Error 0x%x: %s", hr, szBuffer); |
+} |