Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: src/installer-ca/wcalog.cpp

Issue 11521026: initial custom action library, "hello, world" quality (Closed)
Patch Set: Created Sept. 3, 2013, 12:48 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
+}

Powered by Google App Engine
This is Rietveld