| 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 | 
|---|