Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

272 lines
6.9 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. /* File: eventlog.cpp
  3. Description: Implements a subset of the NT event log APIs as a C++ class.
  4. CEventLog is intended only to provide a convenient method for writing
  5. NT event log messages. No reading of event log entries is supported.
  6. Revision History:
  7. Date Description Programmer
  8. -------- --------------------------------------------------- ----------
  9. 02/14/98 Initial creation. BrianAu
  10. */
  11. ///////////////////////////////////////////////////////////////////////////////
  12. #include "pch.h"
  13. #pragma hdrstop
  14. #include "eventlog.h"
  15. #include "registry.h"
  16. TCHAR CEventLog::m_szFmtDec[] = TEXT("%1!d!");
  17. TCHAR CEventLog::m_szFmtHex[] = TEXT("0x%1!X!");
  18. CEventLog::~CEventLog(
  19. void
  20. )
  21. {
  22. DBGTRACE((DM_EVENTLOG, DL_MID, TEXT("CEventLog::~CEventLog")));
  23. Close();
  24. }
  25. //
  26. // Register the specified event source.
  27. // Note that the registry entries must already exist.
  28. // HKLM\System\CurrentControlSet\Services\EventLog\Application\<pszEventSource>
  29. // Requires values "EventMessageFile" and "TypesSupported".
  30. //
  31. HRESULT
  32. CEventLog::Initialize(
  33. LPCTSTR pszEventSource
  34. )
  35. {
  36. DBGTRACE((DM_EVENTLOG, DL_MID, TEXT("CEventLog::Initialize")));
  37. if (NULL != m_hLog)
  38. {
  39. return S_FALSE;
  40. }
  41. HRESULT hr = NOERROR;
  42. m_hLog = RegisterEventSource(NULL, pszEventSource);
  43. if (NULL == m_hLog)
  44. {
  45. hr = HRESULT_FROM_WIN32(GetLastError());
  46. DBGERROR((TEXT("Error 0x%08X registering event source \"%s\""), hr, pszEventSource));
  47. DBGERROR((TEXT("Run regsvr32 on dskquota.dll")));
  48. }
  49. return hr;
  50. }
  51. //
  52. // Deregister the event source.
  53. //
  54. void
  55. CEventLog::Close(
  56. void
  57. )
  58. {
  59. DBGTRACE((DM_EVENTLOG, DL_MID, TEXT("CEventLog::Close")));
  60. if (NULL != m_hLog)
  61. {
  62. DeregisterEventSource(m_hLog);
  63. m_hLog = NULL;
  64. }
  65. }
  66. //
  67. // Report an event. No replaceable parameters explicitly specified.
  68. // If msg string contains replaceable parameters, use Push() to
  69. // build list of replacement strings.
  70. //
  71. HRESULT
  72. CEventLog::ReportEvent(
  73. WORD wType,
  74. WORD wCategory,
  75. DWORD dwEventID,
  76. PSID lpUserSid, // [optional]
  77. LPVOID pvRawData, // [optional]
  78. DWORD cbRawData // [optional]
  79. )
  80. {
  81. DBGTRACE((DM_EVENTLOG, DL_MID, TEXT("CEventLog::ReportEvent")));
  82. if (NULL == m_hLog)
  83. {
  84. DBGERROR((TEXT("Event log not initialized")));
  85. return E_FAIL;
  86. }
  87. BOOL bResult = false;
  88. HRESULT hr = NOERROR;
  89. if (0 < m_rgstrText.Count())
  90. {
  91. bResult = ReportEvent(wType,
  92. wCategory,
  93. dwEventID,
  94. m_rgstrText,
  95. lpUserSid,
  96. pvRawData,
  97. cbRawData);
  98. m_rgstrText.Clear();
  99. }
  100. else
  101. {
  102. bResult = ::ReportEvent(m_hLog,
  103. wType,
  104. wCategory,
  105. dwEventID,
  106. lpUserSid,
  107. 0,
  108. cbRawData,
  109. NULL,
  110. pvRawData);
  111. }
  112. if (!bResult)
  113. {
  114. //
  115. // Special-case ERROR_IO_PENDING. ::ReportEvent will fail with
  116. // this error code even when it succeeds. Don't know exactly why
  117. // but it does. Treat this as success so we don't get unnecessary
  118. // debugger output.
  119. //
  120. DWORD dwError = GetLastError();
  121. if (ERROR_IO_PENDING != dwError)
  122. {
  123. hr = HRESULT_FROM_WIN32(dwError);
  124. DBGERROR((TEXT("Error 0x%08X reporting event"), hr));
  125. }
  126. }
  127. return hr;
  128. }
  129. //
  130. // Report an event. Replacement strings are explicitly specified
  131. // through an array of CString objects.
  132. //
  133. HRESULT
  134. CEventLog::ReportEvent(
  135. WORD wType,
  136. WORD wCategory,
  137. DWORD dwEventID,
  138. const CArray<CString>& rgstr,
  139. PSID lpUserSid,
  140. LPVOID pvRawData,
  141. DWORD cbRawData
  142. )
  143. {
  144. DBGTRACE((DM_EVENTLOG, DL_MID, TEXT("CEventLog::ReportEvent [ with strings ]")));
  145. if (NULL == m_hLog)
  146. {
  147. DBGERROR((TEXT("Event log not initialized")));
  148. return E_FAIL;
  149. }
  150. HRESULT hr = NOERROR;
  151. int cStrings = rgstr.Count();
  152. array_autoptr<LPCTSTR> rgpsz;
  153. if (0 < cStrings)
  154. {
  155. rgpsz = new LPCTSTR[cStrings];
  156. for (int i = 0; i < cStrings; i++)
  157. {
  158. rgpsz[i] = rgstr[i].Cstr();
  159. }
  160. }
  161. if (!::ReportEvent(m_hLog,
  162. wType,
  163. wCategory,
  164. dwEventID,
  165. lpUserSid,
  166. (WORD)cStrings,
  167. cbRawData,
  168. rgpsz.get(),
  169. pvRawData))
  170. {
  171. //
  172. // Special-case ERROR_IO_PENDING. ::ReportEvent will fail with
  173. // this error code even when it succeeds. Don't know exactly why
  174. // but it does. Treat this as success so we don't get unnecessary
  175. // debugger output.
  176. //
  177. DWORD dwError = GetLastError();
  178. if (ERROR_IO_PENDING != dwError)
  179. {
  180. hr = HRESULT_FROM_WIN32(dwError);
  181. DBGERROR((TEXT("Error 0x%08X reporting event"), hr));
  182. }
  183. }
  184. return hr;
  185. }
  186. //
  187. // Push an HRESULT value onto the stack of replacment strings.
  188. //
  189. void
  190. CEventLog::Push(
  191. HRESULT hr,
  192. eFmt fmt
  193. )
  194. {
  195. DBGTRACE((DM_EVENTLOG, DL_LOW, TEXT("CEventLog::Push [ integer ]")));
  196. LPTSTR pszBuffer = NULL;
  197. CString s;
  198. try
  199. {
  200. if (eFmtSysErr == fmt)
  201. {
  202. int cchLoaded = ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
  203. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  204. NULL,
  205. HRESULT_CODE(hr),
  206. 0,
  207. (LPTSTR)&pszBuffer,
  208. 1,
  209. NULL);
  210. if (NULL != pszBuffer && 0 != cchLoaded)
  211. {
  212. s = pszBuffer;
  213. }
  214. }
  215. else
  216. {
  217. s.Format(eFmtDec == fmt ? m_szFmtDec : m_szFmtHex, hr);
  218. }
  219. m_rgstrText.Append(s);
  220. }
  221. catch(CAllocException& e)
  222. {
  223. DBGERROR((TEXT("Out of memory error in CEventLog::Push")));
  224. }
  225. LocalFree(pszBuffer);
  226. }
  227. //
  228. // Push a string onto the stack of replacement strings.
  229. //
  230. void
  231. CEventLog::Push(
  232. LPCTSTR psz
  233. )
  234. {
  235. DBGTRACE((DM_EVENTLOG, DL_LOW, TEXT("CEventLog::Push [ string ]")));
  236. try
  237. {
  238. m_rgstrText.Append(CString(psz));
  239. }
  240. catch(CAllocException& e)
  241. {
  242. DBGERROR((TEXT("Out of memory error in CEventLog::Push")));
  243. }
  244. }