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.

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