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.

736 lines
18 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1992 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //
  5. //
  6. // Filename: event.c
  7. //
  8. // Description:
  9. //
  10. // History:
  11. // August 26,1992. Stefan Solomon Created original version.
  12. // August 27,1995. Abolade Gbadegesin Modified to support Unicode.
  13. // See trace.h for notes on how
  14. // this file is used to support
  15. // both ANSI and Unicode.
  16. //
  17. //
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h>
  21. #include <windows.h>
  22. #include <winsvc.h>
  23. #include <tchar.h>
  24. #include <stdio.h>
  25. #include <nb30.h>
  26. #include <lmcons.h>
  27. #include <rtutils.h>
  28. #include <mprapi.h>
  29. #include <raserror.h>
  30. #include <mprerror.h>
  31. #include <mprlog.h>
  32. #define ROUTER_SERVICE RRAS_SERVICE_NAME
  33. HINSTANCE g_hDll;
  34. #if defined(UNICODE) || defined(_UNICODE)
  35. #define STRING_NULL UNICODE_NULL
  36. #define UNICODE_STRING_TAG L'S'
  37. #define ANSI_STRING_TAG L's'
  38. #define TCHAR_STRING_TAG L't'
  39. #define DECIMAL_TAG L'd'
  40. #define IPADDRESS_TAG L'I'
  41. #else
  42. #define STRING_NULL '\0'
  43. #define UNICODE_STRING_TAG 'S'
  44. #define ANSI_STRING_TAG 's'
  45. #define TCHAR_STRING_TAG 't'
  46. #define DECIMAL_TAG 'd'
  47. #define IPADDRESS_TAG 'I'
  48. #endif
  49. #define PRINT_IPADDR(x) \
  50. ((x)&0x000000ff),(((x)&0x0000ff00)>>8),(((x)&0x00ff0000)>>16),(((x)&0xff000000)>>24)
  51. //
  52. //
  53. // Function: LogError
  54. //
  55. // Descr:
  56. //
  57. //
  58. VOID
  59. APIENTRY
  60. LogError(
  61. IN DWORD dwMessageId,
  62. IN DWORD cNumberOfSubStrings,
  63. IN LPTSTR *plpszSubStrings,
  64. IN DWORD dwErrorCode
  65. ) {
  66. HANDLE hLog;
  67. PSID pSidUser = NULL;
  68. hLog = RegisterEventSource(NULL, ROUTER_SERVICE );
  69. if ( dwErrorCode == NO_ERROR )
  70. {
  71. //
  72. // No error codes were specified
  73. //
  74. ReportEvent( hLog,
  75. EVENTLOG_ERROR_TYPE,
  76. 0, // event category
  77. dwMessageId,
  78. pSidUser,
  79. (WORD)cNumberOfSubStrings,
  80. 0,
  81. plpszSubStrings,
  82. (PVOID)NULL
  83. );
  84. }
  85. else
  86. {
  87. //
  88. // Log the error code specified
  89. //
  90. ReportEvent( hLog,
  91. EVENTLOG_ERROR_TYPE,
  92. 0, // event category
  93. dwMessageId,
  94. pSidUser,
  95. (WORD)cNumberOfSubStrings,
  96. sizeof(DWORD),
  97. plpszSubStrings,
  98. (PVOID)&dwErrorCode
  99. );
  100. }
  101. DeregisterEventSource( hLog );
  102. }
  103. //
  104. //
  105. // Function: LogEvent
  106. //
  107. // Descr:
  108. //
  109. //
  110. VOID
  111. APIENTRY
  112. LogEvent(
  113. IN DWORD wEventType,
  114. IN DWORD dwMessageId,
  115. IN DWORD cNumberOfSubStrings,
  116. IN LPTSTR *plpszSubStrings
  117. ) {
  118. HANDLE hLog;
  119. PSID pSidUser = NULL;
  120. // Audit enabled
  121. hLog = RegisterEventSource( NULL, ROUTER_SERVICE );
  122. ReportEvent( hLog,
  123. (WORD)wEventType, // success/failure audit
  124. 0, // event category
  125. dwMessageId,
  126. pSidUser,
  127. (WORD)cNumberOfSubStrings,
  128. 0,
  129. plpszSubStrings,
  130. (PVOID)NULL);
  131. DeregisterEventSource( hLog );
  132. }
  133. //----------------------------------------------------------------------------
  134. // Function: RouterLogRegister
  135. //
  136. // Returns a HANDLE which can be passed to RouterLogEvent
  137. // to log events from the specified source.
  138. //----------------------------------------------------------------------------
  139. HANDLE
  140. RouterLogRegister(
  141. LPCTSTR lpszSource
  142. ) {
  143. return RegisterEventSource(NULL, lpszSource);
  144. }
  145. //----------------------------------------------------------------------------
  146. // Function: RouterLogDeregister
  147. //
  148. // Closes a HANDLE created by RouterLogRegister
  149. //----------------------------------------------------------------------------
  150. VOID
  151. RouterLogDeregister(
  152. HANDLE hLogHandle
  153. ) {
  154. if(NULL != hLogHandle)
  155. {
  156. DeregisterEventSource(hLogHandle);
  157. }
  158. }
  159. //----------------------------------------------------------------------------
  160. // Function: RouterLogEvent
  161. //
  162. // Logs an event using a HANDLE created by RouterLogRegister.
  163. //----------------------------------------------------------------------------
  164. VOID
  165. RouterLogEvent(
  166. IN HANDLE hLogHandle,
  167. IN DWORD dwEventType,
  168. IN DWORD dwMessageId,
  169. IN DWORD dwSubStringCount,
  170. IN LPTSTR *plpszSubStringArray,
  171. IN DWORD dwErrorCode
  172. ) {
  173. if(NULL == hLogHandle)
  174. {
  175. return;
  176. }
  177. if (dwErrorCode == NO_ERROR) {
  178. ReportEvent(
  179. hLogHandle,
  180. (WORD)dwEventType,
  181. 0,
  182. dwMessageId,
  183. NULL,
  184. (WORD)dwSubStringCount,
  185. 0,
  186. plpszSubStringArray,
  187. (PVOID)NULL
  188. );
  189. }
  190. else {
  191. ReportEvent(
  192. hLogHandle,
  193. (WORD)dwEventType,
  194. 0,
  195. dwMessageId,
  196. NULL,
  197. (WORD)dwSubStringCount,
  198. sizeof(DWORD),
  199. plpszSubStringArray,
  200. (PVOID)&dwErrorCode
  201. );
  202. }
  203. }
  204. VOID
  205. RouterLogEventEx(
  206. IN HANDLE hLogHandle,
  207. IN DWORD dwEventType,
  208. IN DWORD dwErrorCode,
  209. IN DWORD dwMessageId,
  210. IN LPCTSTR ptszFormat,
  211. ...
  212. )
  213. {
  214. va_list vlArgList;
  215. if(NULL == hLogHandle)
  216. {
  217. return;
  218. }
  219. va_start(vlArgList, ptszFormat);
  220. RouterLogEventValistEx(
  221. hLogHandle,
  222. dwEventType,
  223. dwErrorCode,
  224. dwMessageId,
  225. ptszFormat,
  226. vlArgList
  227. );
  228. va_end(vlArgList);
  229. }
  230. VOID
  231. RouterLogEventValistEx(
  232. IN HANDLE hLogHandle,
  233. IN DWORD dwEventType,
  234. IN DWORD dwErrorCode,
  235. IN DWORD dwMessageId,
  236. IN LPCTSTR ptszFormat,
  237. IN va_list vlArgList
  238. )
  239. /*++
  240. Routine Description
  241. This function logs an event, but also parses out the insert strings
  242. Locks
  243. None
  244. Arguments
  245. hLogHandle Handle from RegisterLogRegister()
  246. dwEventType EVENTLOG_{ERROR|WARNING|INFORMATION}_TYPE
  247. dwErrorCode The error code to report
  248. dwMessageId The ID of the message string
  249. ptszFormat A string specifying the format of the following insert
  250. values. The type of the value is dictated by the format
  251. string. The format string consists of a series of %<X>
  252. There MUST BE NOTHING ELSE - no escape characters, no
  253. nothing.
  254. Valid <X> are:
  255. S: Unicode string
  256. s: ANSII string
  257. t: TCHAR string
  258. d: integer
  259. I: IP Address in network order
  260. Return Value
  261. None
  262. --*/
  263. {
  264. PWCHAR rgpwszInsertArray[20];
  265. LPCTSTR ptszTemp;
  266. WORD wNumInsert;
  267. ULONG i, ulDecIndex, ulFormatLen;
  268. //
  269. // 22 is enough to hold 2^64
  270. // There can be max 20 insert strings
  271. //
  272. WCHAR rgpwszDecString[20][22];
  273. if (ptszFormat==NULL)
  274. ptszFormat = TEXT("");
  275. if(NULL == hLogHandle)
  276. {
  277. return;
  278. }
  279. //
  280. // First make sure that the format list doesnt specify more than
  281. // 20 characters
  282. //
  283. ptszTemp = ptszFormat;
  284. ulFormatLen = _tcslen(ptszFormat);
  285. wNumInsert = 0;
  286. ulDecIndex = 0;
  287. i = 0;
  288. //
  289. // We will only walk the first 20 format specifiers
  290. //
  291. while((i < ulFormatLen) && (wNumInsert < 20))
  292. {
  293. if(*ptszTemp == __TEXT('%'))
  294. {
  295. //
  296. // Ok so this could be a good specifier - check the next character
  297. //
  298. i++;
  299. ptszTemp++;
  300. switch(*ptszTemp)
  301. {
  302. case UNICODE_STRING_TAG:
  303. {
  304. rgpwszInsertArray[wNumInsert] = va_arg(vlArgList, PWCHAR);
  305. wNumInsert++;
  306. break;
  307. }
  308. case ANSI_STRING_TAG:
  309. {
  310. PCHAR pszString;
  311. PWCHAR pwszWideString;
  312. ULONG ulLen;
  313. pszString = va_arg(vlArgList,
  314. PCHAR);
  315. ulLen = strlen(pszString);
  316. if(ulLen)
  317. {
  318. pwszWideString = _alloca(ulLen * sizeof(WCHAR));
  319. MultiByteToWideChar(CP_ACP,
  320. 0,
  321. pszString,
  322. -1,
  323. pwszWideString,
  324. ulLen);
  325. rgpwszInsertArray[wNumInsert] = pwszWideString;
  326. }
  327. else
  328. {
  329. //
  330. // L"" will be on our stack, but it cant go away
  331. //
  332. rgpwszInsertArray[wNumInsert] = L"";
  333. }
  334. wNumInsert++;
  335. break;
  336. }
  337. case TCHAR_STRING_TAG:
  338. {
  339. #if defined(UNICODE) || defined(_UNICODE)
  340. rgpwszInsertArray[wNumInsert] = va_arg(vlArgList, PWCHAR);
  341. #else
  342. PCHAR pszString;
  343. PWCHAR pwszWideString;
  344. ULONG ulLen;
  345. pszString = va_arg(vlArgList, PCHAR);
  346. ulLen = strlen(pszString);
  347. if(ulLen)
  348. {
  349. pwszWideString = _alloca(ulLen * sizeof(WCHAR));
  350. MultiByteToWideChar(CP_ACP,
  351. 0,
  352. pszString,
  353. -1,
  354. pwszWideString,
  355. ulLen);
  356. rgpwszInsertArray[wNumInsert] = pwszWideString;
  357. }
  358. else
  359. {
  360. //
  361. // L"" will be on our stack, but it cant go away
  362. //
  363. rgpwszInsertArray[wNumInsert] = L"";
  364. }
  365. #endif
  366. wNumInsert++;
  367. break;
  368. }
  369. case DECIMAL_TAG:
  370. {
  371. _snwprintf(&(rgpwszDecString[ulDecIndex][0]),
  372. 21,
  373. L"%d",
  374. va_arg(vlArgList, int));
  375. rgpwszDecString[ulDecIndex][21] = UNICODE_NULL;
  376. rgpwszInsertArray[wNumInsert] =
  377. &(rgpwszDecString[ulDecIndex][0]);
  378. ulDecIndex++;
  379. wNumInsert++;
  380. break;
  381. }
  382. case IPADDRESS_TAG:
  383. {
  384. DWORD dwAddr;
  385. dwAddr = va_arg(vlArgList, int);
  386. _snwprintf(&(rgpwszDecString[ulDecIndex][0]),
  387. 21,
  388. L"%d.%d.%d.%d",
  389. PRINT_IPADDR(dwAddr));
  390. rgpwszDecString[ulDecIndex][21] = UNICODE_NULL;
  391. rgpwszInsertArray[wNumInsert] =
  392. &(rgpwszDecString[ulDecIndex][0]);
  393. ulDecIndex++;
  394. wNumInsert++;
  395. break;
  396. }
  397. }
  398. }
  399. //
  400. // Scan next character
  401. //
  402. ptszTemp++;
  403. i++;
  404. }
  405. if (dwErrorCode == NO_ERROR)
  406. {
  407. ReportEventW(hLogHandle,
  408. (WORD)dwEventType,
  409. 0,
  410. dwMessageId,
  411. NULL,
  412. wNumInsert,
  413. 0,
  414. rgpwszInsertArray,
  415. (PVOID)NULL);
  416. }
  417. else
  418. {
  419. ReportEventW(hLogHandle,
  420. (WORD)dwEventType,
  421. 0,
  422. dwMessageId,
  423. NULL,
  424. wNumInsert,
  425. sizeof(DWORD),
  426. rgpwszInsertArray,
  427. (PVOID)&dwErrorCode);
  428. }
  429. }
  430. //----------------------------------------------------------------------------
  431. // Function: RouterLogEventData
  432. //
  433. // Logs an event using a HANDLE created by RouterLogRegister.
  434. // Allows caller to include data in the eventlog message.
  435. //----------------------------------------------------------------------------
  436. VOID
  437. RouterLogEventData(
  438. IN HANDLE hLogHandle,
  439. IN DWORD dwEventType,
  440. IN DWORD dwMessageId,
  441. IN DWORD dwSubStringCount,
  442. IN LPTSTR *plpszSubStringArray,
  443. IN DWORD dwDataBytes,
  444. IN LPBYTE lpDataBytes
  445. ) {
  446. if(NULL == hLogHandle)
  447. {
  448. return;
  449. }
  450. ReportEvent(
  451. hLogHandle,
  452. (WORD)dwEventType,
  453. 0,
  454. dwMessageId,
  455. NULL,
  456. (WORD)dwSubStringCount,
  457. (WORD)dwDataBytes,
  458. plpszSubStringArray,
  459. (PVOID)lpDataBytes
  460. );
  461. }
  462. //----------------------------------------------------------------------------
  463. // Function: RouterLogEventString
  464. //
  465. // Logs an event using a HANDLE created by RouterLogRegister.
  466. // Allows caller to include an error code string into the log
  467. //----------------------------------------------------------------------------
  468. VOID
  469. RouterLogEventString(
  470. IN HANDLE hLogHandle,
  471. IN DWORD dwEventType,
  472. IN DWORD dwMessageId,
  473. IN DWORD dwSubStringCount,
  474. IN LPTSTR *plpszSubStringArray,
  475. IN DWORD dwErrorCode,
  476. IN DWORD dwErrorIndex
  477. ){
  478. DWORD dwRetCode;
  479. DWORD dwIndex;
  480. DWORD dwSubStringIndex = 0;
  481. LPTSTR plpszStringArray[20];
  482. if(NULL == hLogHandle)
  483. {
  484. return;
  485. }
  486. RTASSERT( dwSubStringCount < 21 );
  487. RTASSERT( dwErrorIndex <= dwSubStringCount );
  488. dwSubStringCount++;
  489. for ( dwIndex = 0; dwIndex < dwSubStringCount; dwIndex++ )
  490. {
  491. if ( dwIndex == dwErrorIndex )
  492. {
  493. dwRetCode = RouterGetErrorString(
  494. dwErrorCode,
  495. &plpszStringArray[dwIndex] );
  496. if ( dwRetCode != NO_ERROR )
  497. {
  498. DbgPrint("Error %d\n",dwRetCode);
  499. //RTASSERT( dwRetCode == NO_ERROR );
  500. return;
  501. }
  502. }
  503. else
  504. {
  505. plpszStringArray[dwIndex] = plpszSubStringArray[dwSubStringIndex++];
  506. }
  507. }
  508. ReportEvent(
  509. hLogHandle,
  510. (WORD)dwEventType,
  511. 0,
  512. dwMessageId,
  513. NULL,
  514. (WORD)dwSubStringCount,
  515. sizeof(DWORD),
  516. plpszStringArray,
  517. (PVOID)&dwErrorCode
  518. );
  519. LocalFree( plpszStringArray[dwErrorIndex] );
  520. }
  521. //----------------------------------------------------------------------------
  522. // Function: RouterGetErrorString
  523. //
  524. // Given an error code from raserror.h mprerror.h or winerror.h will return
  525. // a string associated with it. The caller is required to free the string
  526. // by calling LocalFree.
  527. //----------------------------------------------------------------------------
  528. DWORD
  529. RouterGetErrorString(
  530. IN DWORD dwError,
  531. OUT LPTSTR * lplpszErrorString
  532. )
  533. {
  534. DWORD dwRetCode = NO_ERROR;
  535. DWORD dwBufferSize;
  536. if ( ( ( dwError >= RASBASE ) && ( dwError <= RASBASEEND ) ) ||
  537. ( ( dwError >= ROUTEBASE ) && ( dwError <= ROUTEBASEEND ) ) ||
  538. ( ( dwError >= ROUTER_LOG_BASE) && (dwError <= ROUTER_LOG_BASEEND)))
  539. {
  540. // make sure that load library is called only once
  541. if (InterlockedCompareExchangePointer(
  542. &g_hDll,
  543. INVALID_HANDLE_VALUE,
  544. NULL) == NULL)
  545. {
  546. g_hDll = LoadLibrary( TEXT("mprmsg.dll") );
  547. if(g_hDll == NULL)
  548. {
  549. return( GetLastError() );
  550. }
  551. }
  552. while (*((HINSTANCE volatile *)&g_hDll)==INVALID_HANDLE_VALUE)
  553. Sleep(500);
  554. if (g_hDll==NULL)
  555. return ERROR_CAN_NOT_COMPLETE;
  556. dwRetCode = FormatMessage(
  557. FORMAT_MESSAGE_FROM_HMODULE |
  558. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  559. g_hDll,
  560. dwError,
  561. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  562. (LPTSTR)lplpszErrorString,
  563. 0,
  564. NULL );
  565. }
  566. else
  567. {
  568. dwRetCode = FormatMessage(
  569. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  570. FORMAT_MESSAGE_IGNORE_INSERTS |
  571. FORMAT_MESSAGE_FROM_SYSTEM,
  572. NULL,
  573. dwError,
  574. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  575. (LPTSTR)lplpszErrorString,
  576. 0,
  577. NULL );
  578. }
  579. if ( dwRetCode == 0 )
  580. {
  581. return( GetLastError() );
  582. }
  583. else
  584. {
  585. return( NO_ERROR );
  586. }
  587. }