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.

934 lines
20 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. eventlog.c
  5. Abstract:
  6. This module provides common eventlog services for the cluster service
  7. Author:
  8. John Vert (jvert) 9/13/1996
  9. Revision History:
  10. --*/
  11. #define UNICODE 1
  12. #include "clusrtlp.h"
  13. HANDLE LocalEventLog=NULL;
  14. CRITICAL_SECTION EventLogLock;
  15. //
  16. // [GN] June 19/1999: added Async EventReporting
  17. //
  18. // Use ClRtlEventLogSetWorkQueue to set a queue
  19. // for async event reporting. If it the queue is not set,
  20. // event reporting is synchronous as it used to be before
  21. //
  22. static CLRTL_WORK_ITEM EvtReporterWorkItem;
  23. static PCLRTL_WORK_QUEUE EvtReporterWorkQueue;
  24. typedef struct _EVENT_LOG_PACKET {
  25. WORD wType;
  26. WORD wCategory;
  27. DWORD dwEventID;
  28. WORD wNumStrings;
  29. DWORD dwDataSize;
  30. LPVOID lpRawData;
  31. LPWSTR lpStrings[0];
  32. } *PEVENT_LOG_PACKET, EVENT_LOG_PACKET;
  33. VOID
  34. ClRtlEventLogSetWorkQueue(
  35. PCLRTL_WORK_QUEUE WorkQueue
  36. )
  37. {
  38. EnterCriticalSection( &EventLogLock );
  39. EvtReporterWorkQueue = WorkQueue;
  40. LeaveCriticalSection( &EventLogLock );
  41. }
  42. VOID
  43. EvtReporter(
  44. IN PCLRTL_WORK_ITEM WorkItem,
  45. IN DWORD Status,
  46. IN DWORD BytesTransferred,
  47. IN ULONG_PTR IoContext
  48. )
  49. /*++
  50. Routine Description:
  51. Reports queued event via advapi32!ReportEvent
  52. Arguments:
  53. IoContext == EVENT_LOG_PACKET
  54. Return Value:
  55. None
  56. --*/
  57. {
  58. PEVENT_LOG_PACKET data = (PEVENT_LOG_PACKET)IoContext;
  59. ReportEventW(LocalEventLog,
  60. data->wType,
  61. data->wCategory,
  62. data->dwEventID,
  63. NULL,
  64. data->wNumStrings,
  65. data->dwDataSize,
  66. data->lpStrings,
  67. data->lpRawData);
  68. LocalFree(data);
  69. }
  70. VOID
  71. ClRtlEventLogInit(
  72. VOID
  73. )
  74. /*++
  75. Routine Description:
  76. initializes the event log
  77. Arguments:
  78. None
  79. Return Value:
  80. None
  81. --*/
  82. {
  83. InitializeCriticalSection(&EventLogLock);
  84. EvtReporterWorkQueue = 0;
  85. ClRtlInitializeWorkItem(
  86. &EvtReporterWorkItem,
  87. EvtReporter,
  88. 0
  89. );
  90. }
  91. VOID
  92. ClRtlEventLogCleanup(
  93. VOID
  94. )
  95. {
  96. DeleteCriticalSection( &EventLogLock );
  97. }
  98. PEVENT_LOG_PACKET
  99. ClRtlpBuildEventPacket(
  100. WORD wType,
  101. WORD wCategory,
  102. DWORD dwEventID,
  103. WORD wNumStrings,
  104. DWORD dwDataSize,
  105. LPCWSTR *lpStrings,
  106. LPVOID lpRawData
  107. )
  108. {
  109. PEVENT_LOG_PACKET data = 0;
  110. DWORD Count;
  111. UINT i;
  112. LPBYTE ptr;
  113. Count = sizeof(EVENT_LOG_PACKET) +
  114. dwDataSize +
  115. wNumStrings * (sizeof(LPCWSTR) + sizeof(UNICODE_NULL));
  116. for (i = 0; i < wNumStrings; ++i) {
  117. int len = lstrlenW( lpStrings[i] );
  118. Count += len * sizeof(WCHAR); // (null is already accounted for)
  119. }
  120. data = LocalAlloc(LMEM_FIXED, Count);
  121. if (!data) {
  122. return 0;
  123. }
  124. data->wType = wType;
  125. data->wCategory = wCategory;
  126. data->dwEventID = dwEventID;
  127. data->wNumStrings = wNumStrings;
  128. data->dwDataSize = dwDataSize;
  129. data->lpRawData = &data->lpStrings[wNumStrings];
  130. // lpStrings will be filled later
  131. if (dwDataSize) {
  132. CopyMemory(data->lpRawData, lpRawData, dwDataSize);
  133. }
  134. ptr = (LPBYTE)data->lpRawData + dwDataSize;
  135. for (i = 0; i < wNumStrings; ++i) {
  136. int nBytes = (lstrlenW( lpStrings[i] ) + 1) * sizeof(WCHAR);
  137. CopyMemory(ptr, lpStrings[i], nBytes);
  138. data->lpStrings[i] = (LPWSTR)ptr;
  139. ptr += nBytes;
  140. }
  141. CL_ASSERT(ptr <= (LPBYTE)data + Count);
  142. return data;
  143. }
  144. VOID
  145. ClRtlpReportEvent(
  146. WORD wType,
  147. WORD wCategory,
  148. DWORD dwEventID,
  149. WORD wNumStrings,
  150. DWORD dwDataSize,
  151. LPCWSTR *lpStrings,
  152. LPVOID lpRawData
  153. )
  154. /*++
  155. Routine Description:
  156. Common routine for reporting an event to the event log. Opens a handle
  157. to the event log if necessary.
  158. Arguments:
  159. Identical arguments to ReportEventW
  160. Return Value:
  161. None
  162. --*/
  163. {
  164. BOOL Success = FALSE;
  165. DWORD Status;
  166. //
  167. // If the event log hasn't been opened, try and open it now.
  168. //
  169. if (LocalEventLog == NULL) {
  170. EnterCriticalSection(&EventLogLock);
  171. if (LocalEventLog == NULL) {
  172. LocalEventLog = RegisterEventSource(NULL, L"ClusSvc");
  173. }
  174. LeaveCriticalSection(&EventLogLock);
  175. if (LocalEventLog == NULL) {
  176. Status = GetLastError();
  177. return;
  178. }
  179. }
  180. if (EvtReporterWorkQueue) {
  181. PEVENT_LOG_PACKET data =
  182. ClRtlpBuildEventPacket(wType,
  183. wCategory,
  184. dwEventID,
  185. wNumStrings,
  186. dwDataSize,
  187. lpStrings,
  188. lpRawData);
  189. if (data) {
  190. EnterCriticalSection( &EventLogLock );
  191. if (EvtReporterWorkQueue) {
  192. Status = ClRtlPostItemWorkQueue(
  193. EvtReporterWorkQueue,
  194. &EvtReporterWorkItem,
  195. 0,
  196. (ULONG_PTR)data
  197. );
  198. if (Status == ERROR_SUCCESS) {
  199. // worker will free data //
  200. data = NULL;
  201. Success = TRUE;
  202. }
  203. }
  204. LeaveCriticalSection( &EventLogLock );
  205. LocalFree( data ); // free(0) is OK
  206. if (Success) {
  207. return;
  208. }
  209. }
  210. }
  211. Success = ReportEventW(LocalEventLog,
  212. wType,
  213. wCategory,
  214. dwEventID,
  215. NULL,
  216. wNumStrings,
  217. dwDataSize,
  218. lpStrings,
  219. lpRawData);
  220. }
  221. VOID
  222. ClusterLogEvent0(
  223. IN DWORD LogLevel,
  224. IN DWORD LogModule,
  225. IN LPSTR FileName,
  226. IN DWORD LineNumber,
  227. IN DWORD MessageId,
  228. IN DWORD dwByteCount,
  229. IN PVOID lpBytes
  230. )
  231. /*++
  232. Routine Description:
  233. Logs an event to the event log
  234. Arguments:
  235. LogLevel - Supplies the logging level, one of
  236. LOG_CRITICAL 1
  237. LOG_UNUSUAL 2
  238. LOG_NOISE 3
  239. LogModule - Supplies the module ID.
  240. FileName - Supplies the filename of the caller
  241. LineNumber - Supplies the line number of the caller
  242. MessageId - Supplies the message ID to be logged.
  243. dwByteCount - Supplies the number of error-specific bytes to log. If this
  244. is zero, lpBytes is ignored.
  245. lpBytes - Supplies the error-specific bytes to log.
  246. Return Value:
  247. None.
  248. --*/
  249. {
  250. BOOL Success;
  251. DWORD Status;
  252. WORD wType;
  253. switch (LogLevel) {
  254. case LOG_CRITICAL:
  255. wType = EVENTLOG_ERROR_TYPE;
  256. break;
  257. case LOG_UNUSUAL:
  258. wType = EVENTLOG_WARNING_TYPE;
  259. break;
  260. case LOG_NOISE:
  261. wType = EVENTLOG_INFORMATION_TYPE;
  262. break;
  263. default:
  264. // Assert if invalid so that in retail we don't bring down the entire process.
  265. //
  266. CL_ASSERT( 0 );
  267. // Fall through to normal logging...
  268. wType = EVENTLOG_ERROR_TYPE;
  269. }
  270. ClRtlpReportEvent(wType,
  271. (WORD)LogModule,
  272. MessageId,
  273. 0,
  274. dwByteCount,
  275. NULL,
  276. lpBytes);
  277. }
  278. VOID
  279. ClusterLogEvent1(
  280. IN DWORD LogLevel,
  281. IN DWORD LogModule,
  282. IN LPSTR FileName,
  283. IN DWORD LineNumber,
  284. IN DWORD MessageId,
  285. IN DWORD dwByteCount,
  286. IN PVOID lpBytes,
  287. IN LPCWSTR Arg1
  288. )
  289. /*++
  290. Routine Description:
  291. Logs an event to the event log
  292. Arguments:
  293. LogLevel - Supplies the logging level, one of
  294. LOG_CRITICAL 1
  295. LOG_UNUSUAL 2
  296. LOG_NOISE 3
  297. LogModule - Supplies the module ID.
  298. FileName - Supplies the filename of the caller
  299. LineNumber - Supplies the line number of the caller
  300. MessageId - Supplies the message ID to be logged.
  301. dwByteCount - Supplies the number of error-specific bytes to log. If this
  302. is zero, lpBytes is ignored.
  303. lpBytes - Supplies the error-specific bytes to log.
  304. Arg1 - Supplies an insertion string
  305. Return Value:
  306. None.
  307. --*/
  308. {
  309. BOOL Success;
  310. DWORD Status;
  311. WORD wType;
  312. switch (LogLevel) {
  313. case LOG_CRITICAL:
  314. wType = EVENTLOG_ERROR_TYPE;
  315. break;
  316. case LOG_UNUSUAL:
  317. wType = EVENTLOG_WARNING_TYPE;
  318. break;
  319. case LOG_NOISE:
  320. wType = EVENTLOG_INFORMATION_TYPE;
  321. break;
  322. default:
  323. // Assert if invalid so that in retail we don't bring down the entire process.
  324. //
  325. CL_ASSERT( 0 );
  326. // Fall through to normal logging...
  327. wType = EVENTLOG_ERROR_TYPE;
  328. }
  329. ClRtlpReportEvent(wType,
  330. (WORD)LogModule,
  331. MessageId,
  332. 1,
  333. dwByteCount,
  334. &Arg1,
  335. lpBytes);
  336. }
  337. VOID
  338. ClusterLogEvent2(
  339. IN DWORD LogLevel,
  340. IN DWORD LogModule,
  341. IN LPSTR FileName,
  342. IN DWORD LineNumber,
  343. IN DWORD MessageId,
  344. IN DWORD dwByteCount,
  345. IN PVOID lpBytes,
  346. IN LPCWSTR Arg1,
  347. IN LPCWSTR Arg2
  348. )
  349. /*++
  350. Routine Description:
  351. Logs an event to the event log
  352. Arguments:
  353. LogLevel - Supplies the logging level, one of
  354. LOG_CRITICAL 1
  355. LOG_UNUSUAL 2
  356. LOG_NOISE 3
  357. LogModule - Supplies the module ID.
  358. FileName - Supplies the filename of the caller
  359. LineNumber - Supplies the line number of the caller
  360. MessageId - Supplies the message ID to be logged.
  361. dwByteCount - Supplies the number of error-specific bytes to log. If this
  362. is zero, lpBytes is ignored.
  363. lpBytes - Supplies the error-specific bytes to log.
  364. Arg1 - Supplies the first insertion string
  365. Arg2 - Supplies the second insertion string
  366. Return Value:
  367. None.
  368. --*/
  369. {
  370. BOOL Success;
  371. DWORD Status;
  372. WORD wType;
  373. LPCWSTR ArgArray[2];
  374. switch (LogLevel) {
  375. case LOG_CRITICAL:
  376. wType = EVENTLOG_ERROR_TYPE;
  377. break;
  378. case LOG_UNUSUAL:
  379. wType = EVENTLOG_WARNING_TYPE;
  380. break;
  381. case LOG_NOISE:
  382. wType = EVENTLOG_INFORMATION_TYPE;
  383. break;
  384. default:
  385. // Assert if invalid so that in retail we don't bring down the entire process.
  386. //
  387. CL_ASSERT( 0 );
  388. // Fall through to normal logging...
  389. wType = EVENTLOG_ERROR_TYPE;
  390. }
  391. ArgArray[0] = Arg1;
  392. ArgArray[1] = Arg2;
  393. ClRtlpReportEvent(wType,
  394. (WORD)LogModule,
  395. MessageId,
  396. 2,
  397. dwByteCount,
  398. ArgArray,
  399. lpBytes);
  400. }
  401. VOID
  402. ClusterLogEvent3(
  403. IN DWORD LogLevel,
  404. IN DWORD LogModule,
  405. IN LPSTR FileName,
  406. IN DWORD LineNumber,
  407. IN DWORD MessageId,
  408. IN DWORD dwByteCount,
  409. IN PVOID lpBytes,
  410. IN LPCWSTR Arg1,
  411. IN LPCWSTR Arg2,
  412. IN LPCWSTR Arg3
  413. )
  414. /*++
  415. Routine Description:
  416. Logs an event to the event log
  417. Arguments:
  418. LogLevel - Supplies the logging level, one of
  419. LOG_CRITICAL 1
  420. LOG_UNUSUAL 2
  421. LOG_NOISE 3
  422. LogModule - Supplies the module ID.
  423. FileName - Supplies the filename of the caller
  424. LineNumber - Supplies the line number of the caller
  425. MessageId - Supplies the message ID to be logged.
  426. dwByteCount - Supplies the number of error-specific bytes to log. If this
  427. is zero, lpBytes is ignored.
  428. lpBytes - Supplies the error-specific bytes to log.
  429. Arg1 - Supplies the first insertion string
  430. Arg2 - Supplies the second insertion string
  431. Arg3 - Supplies the third insertion string
  432. Return Value:
  433. None.
  434. --*/
  435. {
  436. BOOL Success;
  437. DWORD Status;
  438. WORD wType;
  439. LPCWSTR ArgArray[3];
  440. switch (LogLevel) {
  441. case LOG_CRITICAL:
  442. wType = EVENTLOG_ERROR_TYPE;
  443. break;
  444. case LOG_UNUSUAL:
  445. wType = EVENTLOG_WARNING_TYPE;
  446. break;
  447. case LOG_NOISE:
  448. wType = EVENTLOG_INFORMATION_TYPE;
  449. break;
  450. default:
  451. // Assert if invalid so that in retail we don't bring down the entire process.
  452. //
  453. CL_ASSERT( 0 );
  454. // Fall through to normal logging...
  455. wType = EVENTLOG_ERROR_TYPE;
  456. }
  457. ArgArray[0] = Arg1;
  458. ArgArray[1] = Arg2;
  459. ArgArray[2] = Arg3;
  460. ClRtlpReportEvent(wType,
  461. (WORD)LogModule,
  462. MessageId,
  463. 3,
  464. dwByteCount,
  465. ArgArray,
  466. lpBytes);
  467. }
  468. VOID
  469. ClusterLogEvent4(
  470. IN DWORD LogLevel,
  471. IN DWORD LogModule,
  472. IN LPSTR FileName,
  473. IN DWORD LineNumber,
  474. IN DWORD MessageId,
  475. IN DWORD dwByteCount,
  476. IN PVOID lpBytes,
  477. IN LPCWSTR Arg1,
  478. IN LPCWSTR Arg2,
  479. IN LPCWSTR Arg3,
  480. IN LPCWSTR Arg4
  481. )
  482. /*++
  483. Routine Description:
  484. Logs an event to the event log
  485. Arguments:
  486. LogLevel - Supplies the logging level, one of
  487. LOG_CRITICAL 1
  488. LOG_UNUSUAL 2
  489. LOG_NOISE 3
  490. LogModule - Supplies the module ID.
  491. FileName - Supplies the filename of the caller
  492. LineNumber - Supplies the line number of the caller
  493. MessageId - Supplies the message ID to be logged.
  494. dwByteCount - Supplies the number of error-specific bytes to log. If this
  495. is zero, lpBytes is ignored.
  496. lpBytes - Supplies the error-specific bytes to log.
  497. Arg1 - Supplies the first insertion string
  498. Arg2 - Supplies the second insertion string
  499. Arg3 - Supplies the third insertion string
  500. Arg4 - Supplies the fourth insertion string
  501. Return Value:
  502. None.
  503. --*/
  504. {
  505. BOOL Success;
  506. DWORD Status;
  507. WORD wType;
  508. LPCWSTR ArgArray[4];
  509. switch (LogLevel) {
  510. case LOG_CRITICAL:
  511. wType = EVENTLOG_ERROR_TYPE;
  512. break;
  513. case LOG_UNUSUAL:
  514. wType = EVENTLOG_WARNING_TYPE;
  515. break;
  516. case LOG_NOISE:
  517. wType = EVENTLOG_INFORMATION_TYPE;
  518. break;
  519. default:
  520. // Assert if invalid so that in retail we don't bring down the entire process.
  521. //
  522. CL_ASSERT( 0 );
  523. // Fall through to normal logging...
  524. wType = EVENTLOG_ERROR_TYPE;
  525. }
  526. ArgArray[0] = Arg1;
  527. ArgArray[1] = Arg2;
  528. ArgArray[2] = Arg3;
  529. ArgArray[3] = Arg4;
  530. ClRtlpReportEvent(wType,
  531. (WORD)LogModule,
  532. MessageId,
  533. 4,
  534. dwByteCount,
  535. ArgArray,
  536. lpBytes);
  537. }
  538. VOID
  539. ClusterCommonLogError(
  540. IN ULONG MessageId,
  541. IN ULONG LogModule,
  542. IN ULONG Line,
  543. IN LPSTR File,
  544. IN ULONG ErrCode
  545. )
  546. /*++
  547. Routine Description:
  548. Logs an error to the eventlog
  549. Arguments:
  550. MessageId - Supplies the message ID to use.
  551. LogModule - Supplies the module.
  552. Line - Supplies the line number of the caller.
  553. File - Supplies the filename of the caller.
  554. ErrCode - Supplies the specific error code.
  555. Return Value:
  556. None.
  557. --*/
  558. {
  559. WCHAR LineString[20];
  560. WCHAR ErrString[32];
  561. WCHAR FileName[255];
  562. WCHAR Buffer[256];
  563. LPWSTR Strings[3];
  564. DWORD Bytes;
  565. swprintf(LineString, L"%d", Line);
  566. swprintf(ErrString, L"%d", ErrCode);
  567. mbstowcs(FileName, File, sizeof(FileName)/sizeof(WCHAR));
  568. Strings[0] = LineString;
  569. Strings[1] = FileName;
  570. Strings[2] = ErrString;
  571. ClRtlpReportEvent(EVENTLOG_ERROR_TYPE,
  572. (WORD)LogModule,
  573. MessageId,
  574. 3,
  575. 0,
  576. Strings,
  577. NULL);
  578. Bytes = FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE |
  579. FORMAT_MESSAGE_ARGUMENT_ARRAY |
  580. FORMAT_MESSAGE_MAX_WIDTH_MASK, // remove embedded line breaks
  581. NULL,
  582. MessageId,
  583. 0,
  584. Buffer,
  585. sizeof(Buffer) / sizeof(WCHAR),
  586. (va_list *)Strings);
  587. if (Bytes != 0) {
  588. OutputDebugStringW(Buffer);
  589. ClRtlLogPrint(LOG_CRITICAL, "%1!ws!\n",Buffer);
  590. }
  591. }
  592. VOID
  593. ClusterLogFatalError(
  594. IN ULONG LogModule,
  595. IN ULONG Line,
  596. IN LPSTR File,
  597. IN ULONG ErrCode
  598. )
  599. /*++
  600. Routine Description:
  601. Logs a fatal error to the eventlog and breaks into the debugger if present.
  602. Exits the process on fatal error.
  603. Arguments:
  604. LogModule - Supplies the module.
  605. Line - Supplies the line number of the caller.
  606. File - Supplies the filename of the caller.
  607. ErrCode - Supplies the specific error code.
  608. Return Value:
  609. None.
  610. --*/
  611. {
  612. ClusterCommonLogError(UNEXPECTED_FATAL_ERROR,
  613. LogModule,
  614. Line,
  615. File,
  616. ErrCode);
  617. if (IsDebuggerPresent()) {
  618. DebugBreak();
  619. }
  620. ClRtlpFlushLogBuffers();
  621. ExitProcess(ErrCode);
  622. }
  623. VOID
  624. ClusterLogNonFatalError(
  625. IN ULONG LogModule,
  626. IN ULONG Line,
  627. IN LPSTR File,
  628. IN ULONG ErrCode
  629. )
  630. /*++
  631. Routine Description:
  632. Logs a nonfatal error to the eventlog
  633. Arguments:
  634. LogModule - Supplies the module.
  635. Line - Supplies the line number of the caller.
  636. File - Supplies the filename of the caller.
  637. ErrCode - Supplies the specific error code.
  638. Return Value:
  639. None.
  640. --*/
  641. {
  642. ClusterCommonLogError(LOG_FAILURE,
  643. LogModule,
  644. Line,
  645. File,
  646. ErrCode);
  647. }
  648. VOID
  649. ClusterLogAssertionFailure(
  650. IN ULONG LogModule,
  651. IN ULONG Line,
  652. IN LPSTR File,
  653. IN LPSTR Expression
  654. )
  655. /*++
  656. Routine Description:
  657. Logs an assertion failure to the eventlog.
  658. Arguments:
  659. LogModule - Supplies the module.
  660. Line - Supplies the line number of the caller.
  661. File - Supplies the filename of the caller.
  662. Express - Supplies the ASSERTion expression
  663. Return Value:
  664. None.
  665. --*/
  666. {
  667. WCHAR LineString[10];
  668. WCHAR FileName[255];
  669. WCHAR Buffer[256];
  670. LPWSTR Strings[4];
  671. DWORD Bytes;
  672. swprintf(LineString, L"%d", Line);
  673. mbstowcs(FileName, File, sizeof(FileName)/sizeof(WCHAR));
  674. mbstowcs(Buffer, Expression, sizeof(Buffer)/sizeof(WCHAR));
  675. Strings[0] = LineString;
  676. Strings[1] = FileName;
  677. Strings[2] = Buffer;
  678. ClRtlpReportEvent(EVENTLOG_ERROR_TYPE,
  679. (WORD)LogModule,
  680. ASSERTION_FAILURE,
  681. 3,
  682. 0,
  683. Strings,
  684. NULL);
  685. Bytes = FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE |
  686. FORMAT_MESSAGE_ARGUMENT_ARRAY |
  687. FORMAT_MESSAGE_MAX_WIDTH_MASK, // removed embedded line breaks
  688. NULL,
  689. ASSERTION_FAILURE,
  690. 0,
  691. Buffer,
  692. sizeof(Buffer) / sizeof(WCHAR),
  693. (va_list *)Strings);
  694. if (Bytes != 0) {
  695. OutputDebugStringW(Buffer);
  696. ClRtlLogPrint(LOG_CRITICAL, "%1!ws!\n",Buffer);
  697. }
  698. if (IsDebuggerPresent()) {
  699. DebugBreak();
  700. } else {
  701. ClRtlpFlushLogBuffers();
  702. ExitProcess(Line);
  703. }
  704. }
  705.