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