Leaked source code of windows server 2003
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.

596 lines
13 KiB

  1. /******************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. Logging.cpp
  5. Abstract:
  6. This file contains the implementation of a set of logging classes.
  7. Revision History:
  8. Davide Massarenti (Dmassare) 05/27/99
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. #define BUFFER_LINE_LENGTH (1024)
  13. static WCHAR l_EndOfLine[] = L"\n";
  14. /////////////////////////////////////////////////////////////////////////////
  15. static DATE GetMidnight( /*[in]*/ SYSTEMTIME stTime )
  16. {
  17. DATE dTime;
  18. stTime.wHour = 0;
  19. stTime.wMinute = 0;
  20. stTime.wSecond = 0;
  21. stTime.wMilliseconds = 0;
  22. ::SystemTimeToVariantTime( &stTime, &dTime );
  23. return dTime;
  24. }
  25. /////////////////////////////////////////////////////////////////////////////
  26. MPC::FileLog::FileLog( /*[in]*/ bool fCacheHandle, /*[in]*/ bool fUseUnicode )
  27. {
  28. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::FileLog" );
  29. // MPC::wstring m_szLogFile;
  30. m_hFile = INVALID_HANDLE_VALUE; // HANDLE m_hFile;
  31. m_fCacheHandle = fCacheHandle; // bool m_fCacheHandle;
  32. m_fUseUnicode = fUseUnicode; // bool m_fUseUnicode;
  33. }
  34. MPC::FileLog::FileLog( /*[in]*/ const FileLog& fl )
  35. {
  36. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::FileLog" );
  37. m_szLogFile = fl.m_szLogFile; // MPC::wstring m_szLogFile;
  38. m_hFile = INVALID_HANDLE_VALUE; // HANDLE m_hFile;
  39. m_fCacheHandle = fl.m_fCacheHandle; // bool m_fCacheHandle;
  40. m_fUseUnicode = fl.m_fUseUnicode; // bool m_fUseUnicode;
  41. }
  42. MPC::FileLog::~FileLog()
  43. {
  44. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::~FileLog" );
  45. Close();
  46. }
  47. MPC::FileLog& MPC::FileLog::operator=( /*[in]*/ const FileLog& fl )
  48. {
  49. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::operator=" );
  50. Close();
  51. m_szLogFile = fl.m_szLogFile; // MPC::wstring m_szLogFile;
  52. m_hFile = INVALID_HANDLE_VALUE; // HANDLE m_hFile;
  53. m_fCacheHandle = fl.m_fCacheHandle; // bool m_fCacheHandle;
  54. m_fUseUnicode = fl.m_fUseUnicode; // bool m_fUseUnicode;
  55. return *this;
  56. }
  57. /////////////////////////////////////////////////////////////////////////////
  58. HRESULT MPC::FileLog::Open()
  59. {
  60. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::Open" );
  61. HRESULT hr;
  62. Lock();
  63. if(m_hFile == INVALID_HANDLE_VALUE)
  64. {
  65. // Ensure the directory exists.
  66. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( m_szLogFile ));
  67. __MPC_EXIT_IF_INVALID_HANDLE(hr, m_hFile, ::CreateFileW( m_szLogFile.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL ));
  68. ::SetFilePointer( m_hFile, 0, NULL, FILE_END );
  69. }
  70. hr = S_OK;
  71. __MPC_FUNC_CLEANUP;
  72. Unlock();
  73. __MPC_FUNC_EXIT(hr);
  74. }
  75. HRESULT MPC::FileLog::Close()
  76. {
  77. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::Close" );
  78. HRESULT hr;
  79. Lock();
  80. if(m_hFile != INVALID_HANDLE_VALUE)
  81. {
  82. ::CloseHandle( m_hFile );
  83. m_hFile = INVALID_HANDLE_VALUE;
  84. }
  85. hr = S_OK;
  86. Unlock();
  87. __MPC_FUNC_EXIT(hr);
  88. }
  89. /////////////////////////////////////////////////////////////////////////////
  90. HRESULT MPC::FileLog::Rotate( /*[in]*/ DWORD dwDays )
  91. {
  92. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::Rotate" );
  93. HRESULT hr;
  94. SYSTEMTIME st;
  95. WCHAR rgTime[BUFFER_LINE_LENGTH];
  96. MPC::wstring szLogFileNew;
  97. Lock();
  98. //
  99. // Before rotating, check if it's time to do it.
  100. //
  101. if(dwDays)
  102. {
  103. FILETIME ftCreation;
  104. SYSTEMTIME stCreation;
  105. SYSTEMTIME stNow;
  106. DATE dCreation;
  107. DATE dNow;
  108. __MPC_EXIT_IF_METHOD_FAILS(hr, Open());
  109. if(::GetFileTime( m_hFile, &ftCreation, NULL, NULL ))
  110. {
  111. ::FileTimeToSystemTime( &ftCreation, &stCreation );
  112. ::GetSystemTime ( &stNow );
  113. dCreation = GetMidnight( stCreation );
  114. dNow = GetMidnight( stNow );
  115. //
  116. // If it's not been 'dwDays' since the creation of the log, don't rotate.
  117. //
  118. if(dCreation + (DATE)dwDays > dNow)
  119. {
  120. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  121. }
  122. }
  123. }
  124. __MPC_EXIT_IF_METHOD_FAILS(hr, Close());
  125. //
  126. // Append current time.
  127. //
  128. // <FileName>__<Year>_<Month>_<Day>_<hour>-<minute>-<second>
  129. //
  130. ::GetLocalTime( &st );
  131. StringCchPrintfW( rgTime, ARRAYSIZE(rgTime), L"__%04u-%02u-%02u_%02u-%02u-%02u", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond );
  132. szLogFileNew = m_szLogFile;
  133. szLogFileNew.append( rgTime );
  134. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::MoveFileExW( m_szLogFile.c_str(), szLogFileNew.c_str(), MOVEFILE_REPLACE_EXISTING ));
  135. //
  136. // After rotation, SET the date of creation. There's a BUG in NTFS that caches the date from the previous file...
  137. //
  138. if(dwDays)
  139. {
  140. FILETIME ftNow;
  141. SYSTEMTIME stNow;
  142. __MPC_EXIT_IF_METHOD_FAILS(hr, Open());
  143. ::GetSystemTime ( &stNow );
  144. ::SystemTimeToFileTime( &stNow, &ftNow );
  145. ::SetFileTime( m_hFile, &ftNow, NULL, NULL );
  146. __MPC_EXIT_IF_METHOD_FAILS(hr, Close());
  147. }
  148. hr = S_OK;
  149. __MPC_FUNC_CLEANUP;
  150. Unlock();
  151. __MPC_FUNC_EXIT(hr);
  152. }
  153. HRESULT MPC::FileLog::SetLocation( /*[in]*/ LPCWSTR szLogFile )
  154. {
  155. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::SetLocation" );
  156. HRESULT hr;
  157. Lock();
  158. __MPC_PARAMCHECK_BEGIN(hr)
  159. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szLogFile);
  160. __MPC_PARAMCHECK_END();
  161. __MPC_EXIT_IF_METHOD_FAILS(hr, Close());
  162. m_szLogFile = szLogFile;
  163. hr = S_OK;
  164. __MPC_FUNC_CLEANUP;
  165. Unlock();
  166. __MPC_FUNC_EXIT(hr);
  167. }
  168. HRESULT MPC::FileLog::Terminate()
  169. {
  170. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::Terminate" );
  171. HRESULT hr;
  172. __MPC_EXIT_IF_METHOD_FAILS(hr, Close());
  173. hr = S_OK;
  174. __MPC_FUNC_CLEANUP;
  175. __MPC_FUNC_EXIT(hr);
  176. }
  177. /////////////////////////////////////////////////////////////////////////////
  178. HRESULT MPC::FileLog::AppendString( /*[in]*/ LPCWSTR szLine )
  179. {
  180. _ASSERT(m_hFile != INVALID_HANDLE_VALUE);
  181. USES_CONVERSION;
  182. HRESULT hr;
  183. DWORD dwWritten;
  184. LPCVOID lpData;
  185. DWORD dwSize;
  186. if(m_fUseUnicode)
  187. {
  188. lpData = szLine;
  189. dwSize = wcslen( szLine ) * sizeof(WCHAR);
  190. }
  191. else
  192. {
  193. LPCSTR szLineASCII = W2A( szLine );
  194. lpData = szLineASCII;
  195. dwSize = strlen( szLineASCII ) * sizeof(CHAR);
  196. }
  197. if(::WriteFile( m_hFile, lpData, dwSize, &dwWritten, NULL ) == FALSE)
  198. {
  199. hr = HRESULT_FROM_WIN32( ::GetLastError() );
  200. }
  201. else
  202. {
  203. hr = S_OK;
  204. }
  205. return hr;
  206. }
  207. HRESULT MPC::FileLog::WriteEntry( /*[in]*/ LPWSTR szLine )
  208. {
  209. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::WriteEntry" );
  210. HRESULT hr;
  211. WCHAR rgTime[BUFFER_LINE_LENGTH];
  212. SYSTEMTIME st;
  213. Lock();
  214. __MPC_EXIT_IF_METHOD_FAILS(hr, Open());
  215. //
  216. // Prepend current time.
  217. //
  218. ::GetLocalTime( &st );
  219. StringCchPrintfW( rgTime, ARRAYSIZE(rgTime), L"%04u/%02u/%02u %02u:%02u:%02u ", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond );
  220. while(1)
  221. {
  222. LPWSTR szEndOfLine = wcschr( szLine, '\n' );
  223. if(szEndOfLine) *szEndOfLine++ = 0;
  224. __MPC_EXIT_IF_METHOD_FAILS(hr, AppendString( rgTime ));
  225. __MPC_EXIT_IF_METHOD_FAILS(hr, AppendString( szLine ));
  226. __MPC_EXIT_IF_METHOD_FAILS(hr, AppendString( L"\n" ));
  227. //
  228. // Two cases to stop: end of string or NewLine at the end of it.
  229. //
  230. if(!szEndOfLine || !szEndOfLine[0]) break;
  231. szLine = szEndOfLine;
  232. }
  233. hr = S_OK;
  234. __MPC_FUNC_CLEANUP;
  235. if(m_fCacheHandle == false) (void)Close();
  236. Unlock();
  237. __MPC_FUNC_EXIT(hr);
  238. }
  239. HRESULT MPC::FileLog::LogRecordV( /*[in]*/ LPCWSTR szFormat ,
  240. /*[in]*/ va_list arglist )
  241. {
  242. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::WriteEntry" );
  243. HRESULT hr;
  244. WCHAR rgLine[BUFFER_LINE_LENGTH];
  245. __MPC_PARAMCHECK_BEGIN(hr)
  246. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szFormat);
  247. __MPC_PARAMCHECK_END();
  248. StringCchVPrintfW( rgLine, ARRAYSIZE(rgLine), szFormat, arglist );
  249. __MPC_EXIT_IF_METHOD_FAILS(hr, WriteEntry( rgLine ));
  250. hr = S_OK;
  251. __MPC_FUNC_CLEANUP;
  252. __MPC_FUNC_EXIT(hr);
  253. }
  254. HRESULT MPC::FileLog::LogRecordV( /*[in]*/ LPCSTR szFormat ,
  255. /*[in]*/ va_list arglist )
  256. {
  257. __MPC_FUNC_ENTRY( COMMONID, "MPC::FileLog::WriteEntry" );
  258. USES_CONVERSION;
  259. HRESULT hr;
  260. CHAR rgLine[BUFFER_LINE_LENGTH];
  261. __MPC_PARAMCHECK_BEGIN(hr)
  262. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szFormat);
  263. __MPC_PARAMCHECK_END();
  264. StringCchVPrintfA( rgLine, ARRAYSIZE(rgLine), szFormat, arglist );
  265. __MPC_EXIT_IF_METHOD_FAILS(hr, WriteEntry( A2W(rgLine) ));
  266. hr = S_OK;
  267. __MPC_FUNC_CLEANUP;
  268. __MPC_FUNC_EXIT(hr);
  269. }
  270. HRESULT MPC::FileLog::LogRecord( /*[in]*/ LPCWSTR szFormat,
  271. /*[in]*/ ... )
  272. {
  273. va_list arglist;
  274. va_start( arglist, szFormat );
  275. return LogRecordV( szFormat, arglist );
  276. }
  277. HRESULT MPC::FileLog::LogRecord( /*[in]*/ LPCSTR szFormat,
  278. /*[in]*/ ... )
  279. {
  280. va_list arglist;
  281. va_start( arglist, szFormat );
  282. return LogRecordV( szFormat, arglist );
  283. }
  284. /////////////////////////////////////////////////////////////////////////////
  285. /////////////////////////////////////////////////////////////////////////////
  286. /////////////////////////////////////////////////////////////////////////////
  287. MPC::NTEvent::NTEvent()
  288. {
  289. __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::NTEvent" );
  290. m_hEventSource = INVALID_HANDLE_VALUE;
  291. }
  292. MPC::NTEvent::NTEvent( /*[in]*/ const NTEvent& ne )
  293. {
  294. __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::NTEvent" );
  295. m_hEventSource = INVALID_HANDLE_VALUE;
  296. }
  297. MPC::NTEvent::~NTEvent()
  298. {
  299. __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::~NTEvent" );
  300. Terminate();
  301. }
  302. MPC::NTEvent& MPC::NTEvent::operator=( /*[in]*/ const NTEvent& fl )
  303. {
  304. __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::operator=" );
  305. m_hEventSource = INVALID_HANDLE_VALUE;
  306. return *this;
  307. }
  308. /////////////////////////////////////////////////////////////////////////////
  309. HRESULT MPC::NTEvent::Init( /*[in]*/ LPCWSTR szEventSourceName )
  310. {
  311. __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::Init" );
  312. HRESULT hr;
  313. Lock();
  314. //
  315. // Validate params.
  316. //
  317. if(szEventSourceName == NULL)
  318. {
  319. return E_INVALIDARG;
  320. }
  321. if(m_hEventSource != INVALID_HANDLE_VALUE)
  322. {
  323. // only allow one init per lifetime of the object...
  324. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_ALREADY_ASSIGNED);
  325. }
  326. __MPC_EXIT_IF_INVALID_HANDLE(hr, m_hEventSource, ::RegisterEventSourceW( NULL, szEventSourceName ));
  327. hr = S_OK;
  328. __MPC_FUNC_CLEANUP;
  329. Unlock();
  330. __MPC_FUNC_EXIT(hr);
  331. }
  332. HRESULT MPC::NTEvent::Terminate()
  333. {
  334. __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::Terminate" );
  335. HRESULT hr;
  336. Lock();
  337. if(m_hEventSource != INVALID_HANDLE_VALUE)
  338. {
  339. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::DeregisterEventSource( m_hEventSource ));
  340. m_hEventSource = NULL;
  341. }
  342. hr = S_OK;
  343. __MPC_FUNC_CLEANUP;
  344. Unlock();
  345. __MPC_FUNC_EXIT(hr);
  346. }
  347. HRESULT MPC::NTEvent::LogEvent( /*[in]*/ WORD wEventType ,
  348. /*[in]*/ DWORD dwEventID ,
  349. /*[in]*/ ... )
  350. {
  351. __MPC_FUNC_ENTRY( COMMONID, "MPC::NTEvent::LogEvent" );
  352. HRESULT hr;
  353. va_list arglist;
  354. LPCWSTR szParams;
  355. LPCWSTR* pParams = NULL;
  356. DWORD dwParams = 0;
  357. int i;
  358. Lock();
  359. if(m_hEventSource == INVALID_HANDLE_VALUE)
  360. {
  361. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  362. }
  363. //
  364. // Walk through the parameters twice, the first time to count them, the second time to collect them.
  365. //
  366. for(i=0;i<2;i++)
  367. {
  368. va_start( arglist, dwEventID );
  369. dwParams = 0;
  370. while((szParams = va_arg( arglist, LPCWSTR )) != NULL)
  371. {
  372. if(pParams) pParams[dwParams] = szParams;
  373. dwParams++;
  374. }
  375. va_end( arglist );
  376. if(i == 0 && dwParams)
  377. {
  378. pParams = (LPCWSTR*)_alloca( sizeof(*pParams) * dwParams );
  379. }
  380. }
  381. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::ReportEventW( m_hEventSource, wEventType, 0, dwEventID, NULL, dwParams, 0, pParams, NULL ));
  382. hr = S_OK;
  383. __MPC_FUNC_CLEANUP;
  384. Unlock();
  385. __MPC_FUNC_EXIT(hr);
  386. }