Windows NT 4.0 source code leak
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.

914 lines
28 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. stktrace.c
  5. Abstract:
  6. This module implements routines to do dyanmic logging of system events.
  7. Author:
  8. Steve Wood (stevewo) 09-Sep-1993
  9. Revision History:
  10. --*/
  11. #include "ntrtlp.h"
  12. #if DBG
  13. PRTL_EVENT
  14. RtlpAllocEventRecord(
  15. IN PRTL_EVENT_LOG EventLog,
  16. IN ULONG Size
  17. );
  18. PRTL_EVENT_LOG
  19. RtlpServerAcquireEventLog( VOID );
  20. VOID
  21. RtlpServerReleaseEventLog(
  22. IN PRTL_EVENT_LOG EventLog
  23. );
  24. VOID
  25. RtlCloseEventLog( VOID );
  26. #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  27. #pragma alloc_text(PAGE,RtlpAllocEventRecord)
  28. #pragma alloc_text(PAGE,RtlpServerAcquireEventLog)
  29. #pragma alloc_text(PAGE,RtlpServerReleaseEventLog)
  30. #pragma alloc_text(PAGE,RtlCreateEventId)
  31. #pragma alloc_text(PAGE,RtlAreLogging)
  32. #pragma alloc_text(PAGE,RtlLogEvent)
  33. #pragma alloc_text(PAGE,RtlCloseEventLog)
  34. #endif
  35. PRTL_EVENT
  36. RtlpAllocEventRecord(
  37. IN PRTL_EVENT_LOG EventLog,
  38. IN ULONG Size
  39. )
  40. {
  41. PRTL_EVENT Event;
  42. RTL_PAGED_CODE();
  43. if (EventLog->CurrentWriteOffset < EventLog->CurrentReadOffset &&
  44. (EventLog->CurrentWriteOffset + Size) > EventLog->CurrentReadOffset
  45. ) {
  46. return NULL;
  47. }
  48. if ((EventLog->CurrentWriteOffset + Size) >= EventLog->MaximumOffset) {
  49. Event = (PRTL_EVENT)((PCHAR)EventLog + EventLog->CurrentWriteOffset);
  50. if ((EventLog->MinimumOffset + Size) > EventLog->CurrentReadOffset) {
  51. return NULL;
  52. }
  53. Event->Length = 0xFFFF;
  54. EventLog->CurrentWriteOffset = EventLog->MinimumOffset;
  55. }
  56. Event = (PRTL_EVENT)((PCHAR)EventLog + EventLog->CurrentWriteOffset);
  57. EventLog->CurrentWriteOffset += Size;
  58. return Event;
  59. }
  60. PRTL_EVENT_LOG
  61. RtlpServerAcquireEventLog( VOID )
  62. {
  63. NTSTATUS Status;
  64. PRTL_EVENT_LOG EventLog;
  65. RTL_PAGED_CODE();
  66. if (NtCurrentPeb() == NULL) {
  67. return NULL;
  68. }
  69. EventLog = NtCurrentPeb()->EventLog;
  70. if (EventLog == NULL) {
  71. return NULL;
  72. }
  73. Status = NtWaitForSingleObject( EventLog->ServerMutant, TRUE, NULL );
  74. if (NT_SUCCESS( Status )) {
  75. return NtCurrentPeb()->EventLog;
  76. }
  77. else {
  78. return NULL;
  79. }
  80. }
  81. VOID
  82. RtlpServerReleaseEventLog(
  83. IN PRTL_EVENT_LOG EventLog
  84. )
  85. {
  86. NTSTATUS Status;
  87. RTL_PAGED_CODE();
  88. Status = NtReleaseMutant( EventLog->ServerMutant, NULL );
  89. return;
  90. }
  91. USHORT RtlpNextEventId;
  92. PRTL_EVENT_ID_INFO
  93. RtlCreateEventId(
  94. IN OUT PVOID *Buffer OPTIONAL,
  95. IN PULONG Size OPTIONAL,
  96. IN PCHAR Name,
  97. IN ULONG NumberOfParameters OPTIONAL,
  98. ...
  99. )
  100. {
  101. va_list arglist;
  102. NTSTATUS Status;
  103. ULONG i, j, k, CurrentOffset;
  104. ULONG BufferSize;
  105. ULONG ParameterType[ RTL_EVENT_MAXIMUM_PARAMETERS ];
  106. PCHAR ParameterName[ RTL_EVENT_MAXIMUM_PARAMETERS ];
  107. ULONG ParameterNumberOfValues[ RTL_EVENT_MAXIMUM_PARAMETERS ];
  108. ULONG ParameterValues[ RTL_EVENT_MAXIMUM_VALUE_PAIRS ];
  109. PCHAR ParameterValueNames[ RTL_EVENT_MAXIMUM_VALUE_PAIRS ];
  110. ULONG TotalNumberOfParameterValues;
  111. PRTL_EVENT_ID_INFO EventId, OldEventId;
  112. PRTL_EVENT_PARAMETER_INFO ParameterInfo;
  113. PRTL_EVENT_PARAMETER_VALUE_INFO ValueInfo;
  114. RTL_PAGED_CODE();
  115. if (NumberOfParameters > RTL_EVENT_MAXIMUM_PARAMETERS) {
  116. return NULL;
  117. }
  118. EventId = NULL;
  119. //
  120. // Capture variable length argument list into stack array.
  121. //
  122. BufferSize = sizeof( RTL_EVENT_ID_INFO );
  123. BufferSize += strlen( Name );
  124. BufferSize = ALIGN_UP( BufferSize, ULONG );
  125. TotalNumberOfParameterValues = 0;
  126. va_start( arglist, NumberOfParameters );
  127. for (i=0; i<NumberOfParameters; i++) {
  128. ParameterType[ i ] = va_arg( arglist, ULONG );
  129. ParameterName[ i ] = va_arg( arglist, PCHAR );
  130. ParameterNumberOfValues[ i ] = va_arg( arglist, ULONG );
  131. BufferSize += sizeof( RTL_EVENT_PARAMETER_INFO );
  132. BufferSize += strlen( ParameterName[ i ] );
  133. BufferSize = ALIGN_UP( BufferSize, ULONG );
  134. for (j=0; j<ParameterNumberOfValues[ i ]; j++) {
  135. TotalNumberOfParameterValues += 1;
  136. if (TotalNumberOfParameterValues > RTL_EVENT_MAXIMUM_VALUE_PAIRS) {
  137. return NULL;
  138. }
  139. ParameterValues[ TotalNumberOfParameterValues - 1 ] = va_arg( arglist, ULONG );
  140. ParameterValueNames[ TotalNumberOfParameterValues - 1 ] = va_arg( arglist, PCHAR );
  141. BufferSize += sizeof( RTL_EVENT_PARAMETER_VALUE_INFO );
  142. BufferSize += strlen( ParameterValueNames[ TotalNumberOfParameterValues - 1 ] );
  143. BufferSize = ALIGN_UP( BufferSize, ULONG );
  144. }
  145. }
  146. va_end( arglist );
  147. //
  148. // Allocate space for the RTL_EVENT_ID_INFO structure.
  149. //
  150. if (ARGUMENT_PRESENT( Buffer )) {
  151. if (BufferSize > *Size) {
  152. DbgPrint( "RTL: CreateEventId - static buffer size %x < %x\n", *Size, BufferSize );
  153. return NULL;
  154. }
  155. else {
  156. EventId = (PRTL_EVENT_ID_INFO)*Buffer;
  157. *Size -= BufferSize;
  158. *Buffer = (PCHAR)*Buffer + BufferSize;
  159. }
  160. }
  161. else {
  162. #ifdef NTOS_KERNEL_RUNTIME
  163. EventId = (PRTL_EVENT_ID_INFO)ExAllocatePoolWithTag( PagedPool, BufferSize, 'divE' );
  164. #else
  165. EventId = (PRTL_EVENT_ID_INFO)RtlAllocateHeap( RtlProcessHeap(), 0, BufferSize );
  166. #endif // NTOS_KERNEL_RUNTIME
  167. if (EventId == NULL) {
  168. return NULL;
  169. }
  170. }
  171. EventId->Length = (USHORT)BufferSize;
  172. EventId->EventId = (USHORT)0;
  173. EventId->NumberOfParameters = (USHORT)NumberOfParameters;
  174. strcpy( EventId->Name, Name );
  175. CurrentOffset = sizeof( *EventId );
  176. CurrentOffset += strlen( Name );
  177. CurrentOffset = ALIGN_UP( CurrentOffset, ULONG );
  178. k = 0;
  179. EventId->OffsetToParameterInfo = (USHORT)CurrentOffset;
  180. for (i=0; i<NumberOfParameters; i++) {
  181. ParameterInfo = (PRTL_EVENT_PARAMETER_INFO)((PCHAR)EventId + CurrentOffset);
  182. ParameterInfo->Length = sizeof( *ParameterInfo );
  183. ParameterInfo->Length += strlen( ParameterName[ i ] );
  184. ParameterInfo->Length = (USHORT)(ALIGN_UP( ParameterInfo->Length, ULONG ));
  185. ParameterInfo->Type = (USHORT)ParameterType[ i ];
  186. strcpy( ParameterInfo->Label, ParameterName[ i ] );
  187. ParameterInfo->NumberOfValueNames = (USHORT)ParameterNumberOfValues[ i ];
  188. ParameterInfo->OffsetToValueNames = ParameterInfo->Length;
  189. for (j=0; j<ParameterInfo->NumberOfValueNames; j++) {
  190. ValueInfo = (PRTL_EVENT_PARAMETER_VALUE_INFO)((PCHAR)ParameterInfo + ParameterInfo->Length);
  191. ValueInfo->Value = ParameterValues[ k + j ];
  192. strcpy( ValueInfo->ValueName, ParameterValueNames[ k + j ] );
  193. ValueInfo->Length = sizeof( *ValueInfo ) + strlen( ValueInfo->ValueName );
  194. ValueInfo->Length = ALIGN_UP( ValueInfo->Length, ULONG );
  195. ParameterInfo->Length = (USHORT)(ParameterInfo->Length + ValueInfo->Length);
  196. }
  197. CurrentOffset += ParameterInfo->Length;
  198. k += ParameterInfo->NumberOfValueNames;
  199. }
  200. #ifdef NTOS_KERNEL_RUNTIME
  201. OldEventId = ExDefineEventId( EventId );
  202. if (OldEventId != EventId) {
  203. ExFreePool( EventId );
  204. EventId = OldEventId;
  205. }
  206. #else
  207. Status = NtQuerySystemInformation( SystemNextEventIdInformation,
  208. (PVOID)EventId,
  209. EventId->Length,
  210. NULL
  211. );
  212. if (!NT_SUCCESS( Status )) {
  213. if (!ARGUMENT_PRESENT( Buffer )) {
  214. RtlFreeHeap( RtlProcessHeap(), 0, EventId );
  215. }
  216. EventId = NULL;
  217. }
  218. #endif // NTOS_KERNEL_RUNTIME
  219. return EventId;
  220. }
  221. BOOLEAN
  222. RtlAreLogging(
  223. IN ULONG EventClass
  224. )
  225. {
  226. #ifdef NTOS_KERNEL_RUNTIME
  227. PPEB Peb;
  228. PRTL_EVENT_LOG EventLog;
  229. RTL_PAGED_CODE();
  230. if (!PsGetCurrentProcess()->ExitProcessCalled &&
  231. (Peb = PsGetCurrentProcess()->Peb) != NULL &&
  232. (EventLog = Peb->EventLog) != NULL &&
  233. (EventLog->EventClassMask & EventClass) != 0
  234. ) {
  235. return TRUE;
  236. }
  237. else {
  238. return FALSE;
  239. }
  240. #else
  241. if ((NtCurrentTeb() != NULL) && \
  242. (NtCurrentPeb()->EventLog != NULL) && \
  243. (((PRTL_EVENT_LOG)NtCurrentPeb()->EventLog)->EventClassMask & EventClass) \
  244. ) {
  245. return TRUE;
  246. }
  247. else {
  248. return FALSE;
  249. }
  250. #endif // NTOS_KERNEL_RUNTIME
  251. }
  252. NTSTATUS
  253. RtlLogEvent(
  254. IN PRTL_EVENT_ID_INFO EventId,
  255. IN ULONG EventClassMask,
  256. ...
  257. )
  258. {
  259. va_list arglist;
  260. NTSTATUS Status;
  261. PRTL_EVENT_LOG EventLog;
  262. ULONG i, BufferSize;
  263. PRTL_EVENT_PARAMETER_INFO ParameterInfo;
  264. PRTL_EVENT Event;
  265. ULONG Parameters[ RTL_EVENT_MAXIMUM_PARAMETERS ];
  266. USHORT StackBackTraceLength;
  267. ULONG Hash;
  268. PVOID StackBackTrace[ MAX_STACK_DEPTH ];
  269. PULONG ParameterData;
  270. PWSTR Src, Dst;
  271. LPSTR AnsiSrc, AnsiDst;
  272. RTL_PAGED_CODE();
  273. EventLog = RtlpServerAcquireEventLog();
  274. if (EventId == NULL || EventLog == NULL) {
  275. return STATUS_UNSUCCESSFUL;
  276. }
  277. if (EventClassMask != 0 && !(EventClassMask & EventLog->EventClassMask)) {
  278. RtlpServerReleaseEventLog( EventLog );
  279. return STATUS_SUCCESS;
  280. }
  281. #if i386
  282. try {
  283. Hash = 0;
  284. StackBackTraceLength = RtlCaptureStackBackTrace( 1,
  285. MAX_STACK_DEPTH,
  286. StackBackTrace,
  287. &Hash
  288. );
  289. }
  290. except( EXCEPTION_EXECUTE_HANDLER ) {
  291. StackBackTraceLength = 0;
  292. }
  293. #else
  294. StackBackTraceLength = 0;
  295. #endif
  296. va_start( arglist, EventClassMask );
  297. while (StackBackTraceLength != 0) {
  298. if (StackBackTrace[ StackBackTraceLength - 1 ] != 0) {
  299. break;
  300. }
  301. else {
  302. StackBackTraceLength -= 1;
  303. }
  304. }
  305. Status = STATUS_SUCCESS;
  306. try {
  307. if (NtCurrentTeb()->RealClientId.UniqueProcess == EventLog->DisplayClientId.UniqueProcess) {
  308. leave;
  309. }
  310. ParameterInfo = (PRTL_EVENT_PARAMETER_INFO)
  311. ((PCHAR)EventId + EventId->OffsetToParameterInfo);
  312. BufferSize = sizeof( RTL_EVENT ) +
  313. (StackBackTraceLength * sizeof( ULONG )) +
  314. (EventId->NumberOfParameters * sizeof( ULONG ));
  315. for (i=0; i<EventId->NumberOfParameters; i++) {
  316. Parameters[ i ] = va_arg( arglist, ULONG );
  317. switch( ParameterInfo->Type ) {
  318. //
  319. // No additional data for these parameter types;
  320. //
  321. case RTL_EVENT_STATUS_PARAM:
  322. case RTL_EVENT_ULONG_PARAM:
  323. case RTL_EVENT_ENUM_PARAM:
  324. case RTL_EVENT_FLAGS_PARAM:
  325. case RTL_EVENT_ADDRESS_PARAM:
  326. break;
  327. case RTL_EVENT_PWSTR_PARAM:
  328. try {
  329. BufferSize += wcslen( (PWSTR)Parameters[ i ] ) * sizeof( WCHAR );
  330. }
  331. except( EXCEPTION_EXECUTE_HANDLER ) {
  332. }
  333. BufferSize += sizeof( UNICODE_NULL );
  334. BufferSize = ALIGN_UP( BufferSize, ULONG );
  335. break;
  336. case RTL_EVENT_PUNICODE_STRING_PARAM:
  337. try {
  338. BufferSize += ((PUNICODE_STRING)Parameters[ i ])->Length;
  339. }
  340. except( EXCEPTION_EXECUTE_HANDLER ) {
  341. }
  342. BufferSize += sizeof( UNICODE_NULL );
  343. BufferSize = ALIGN_UP( BufferSize, ULONG );
  344. break;
  345. case RTL_EVENT_PANSI_STRING_PARAM:
  346. try {
  347. BufferSize += ((PANSI_STRING)Parameters[ i ])->Length;
  348. }
  349. except( EXCEPTION_EXECUTE_HANDLER ) {
  350. }
  351. BufferSize += sizeof( '\0' );
  352. BufferSize = ALIGN_UP( BufferSize, ULONG );
  353. break;
  354. case RTL_EVENT_STRUCTURE_PARAM:
  355. default:
  356. break;
  357. }
  358. ParameterInfo = (PRTL_EVENT_PARAMETER_INFO)
  359. ((PCHAR)ParameterInfo + ParameterInfo->Length);
  360. }
  361. Event = RtlpAllocEventRecord( EventLog, BufferSize );
  362. if (Event == NULL) {
  363. leave;
  364. }
  365. Event->Length = (USHORT)BufferSize;
  366. Event->EventId = EventId->EventId;
  367. Event->ClientId = NtCurrentTeb()->ClientId;
  368. ParameterData = (PULONG)(Event + 1);
  369. if (Event->StackBackTraceLength = (USHORT)StackBackTraceLength) {
  370. RtlMoveMemory( ParameterData, StackBackTrace, StackBackTraceLength * sizeof( ULONG ));
  371. ParameterData += StackBackTraceLength;
  372. }
  373. Event->OffsetToParameterData = (PCHAR)ParameterData - (PCHAR)Event;
  374. ParameterInfo = (PRTL_EVENT_PARAMETER_INFO)
  375. ((PCHAR)EventId + EventId->OffsetToParameterInfo);
  376. for (i=0; i<EventId->NumberOfParameters; i++) {
  377. switch( ParameterInfo->Type ) {
  378. //
  379. // No additional data for these parameter types;
  380. //
  381. case RTL_EVENT_STATUS_PARAM:
  382. case RTL_EVENT_ULONG_PARAM:
  383. case RTL_EVENT_ENUM_PARAM:
  384. case RTL_EVENT_FLAGS_PARAM:
  385. case RTL_EVENT_ADDRESS_PARAM:
  386. *ParameterData++ = Parameters[ i ];
  387. break;
  388. case RTL_EVENT_PWSTR_PARAM:
  389. Src = (PWSTR)Parameters[ i ];
  390. Dst = (PWSTR)ParameterData;
  391. try {
  392. while (*Dst = *Src++) {
  393. Dst += 1;
  394. }
  395. }
  396. except( EXCEPTION_EXECUTE_HANDLER ) {
  397. }
  398. *Dst = UNICODE_NULL;
  399. ParameterData = (PULONG)ALIGN_UP( Dst, ULONG );
  400. break;
  401. case RTL_EVENT_PUNICODE_STRING_PARAM:
  402. try {
  403. Src = ((PUNICODE_STRING)Parameters[ i ])->Buffer;
  404. Dst = (PWSTR)ParameterData;
  405. RtlMoveMemory( Dst, Src, ((PUNICODE_STRING)Parameters[ i ])->Length );
  406. Dst += ((PUNICODE_STRING)Parameters[ i ])->Length / sizeof( WCHAR );
  407. }
  408. except( EXCEPTION_EXECUTE_HANDLER ) {
  409. }
  410. *Dst++ = UNICODE_NULL;
  411. ParameterData = (PULONG)ALIGN_UP( Dst, ULONG );
  412. break;
  413. case RTL_EVENT_PANSI_STRING_PARAM:
  414. try {
  415. AnsiSrc = ((PANSI_STRING)Parameters[ i ])->Buffer;
  416. AnsiDst = (LPSTR)ParameterData;
  417. RtlMoveMemory( AnsiDst, AnsiSrc, ((PANSI_STRING)Parameters[ i ])->Length );
  418. AnsiDst += ((PANSI_STRING)Parameters[ i ])->Length;
  419. }
  420. except( EXCEPTION_EXECUTE_HANDLER ) {
  421. }
  422. *AnsiDst++ = '\0';
  423. ParameterData = (PULONG)ALIGN_UP( AnsiDst, ULONG );
  424. break;
  425. case RTL_EVENT_STRUCTURE_PARAM:
  426. default:
  427. break;
  428. }
  429. ParameterInfo = (PRTL_EVENT_PARAMETER_INFO)
  430. ((PCHAR)ParameterInfo + ParameterInfo->Length);
  431. }
  432. if (EventLog->ClientSemaphore != NULL) {
  433. NtReleaseSemaphore( EventLog->ServerSemaphore, 1, NULL );
  434. }
  435. else {
  436. NtClose( NtCurrentPeb()->EventLogSection );
  437. NtCurrentPeb()->EventLogSection = NULL;
  438. NtCurrentPeb()->EventLog = NULL;
  439. NtClose( EventLog->ServerMutant );
  440. NtClose( EventLog->ServerSemaphore );
  441. NtUnmapViewOfSection( NtCurrentProcess(), EventLog );
  442. EventLog = NULL;
  443. }
  444. }
  445. finally {
  446. if (EventLog != NULL) {
  447. RtlpServerReleaseEventLog( EventLog );
  448. }
  449. }
  450. va_end( arglist );
  451. return Status;
  452. }
  453. VOID
  454. RtlCloseEventLog( VOID )
  455. {
  456. PRTL_EVENT_LOG EventLog;
  457. EventLog = RtlpServerAcquireEventLog();
  458. if (EventLog == NULL) {
  459. return;
  460. }
  461. try {
  462. NtCurrentPeb()->EventLogSection = NULL;
  463. NtCurrentPeb()->EventLog = NULL;
  464. NtClose( EventLog->ServerMutant );
  465. NtClose( EventLog->ServerSemaphore );
  466. NtUnmapViewOfSection( NtCurrentProcess(), EventLog );
  467. EventLog = NULL;
  468. }
  469. finally {
  470. if (EventLog != NULL) {
  471. RtlpServerReleaseEventLog( EventLog );
  472. }
  473. }
  474. return;
  475. }
  476. #ifndef NTOS_KERNEL_RUNTIME
  477. NTSTATUS
  478. RtlCreateEventLog(
  479. IN HANDLE TargetProcess,
  480. IN ULONG Flags,
  481. IN ULONG EventClassMask,
  482. OUT PRTL_EVENT_LOG* ReturnedEventLog
  483. )
  484. {
  485. NTSTATUS Status;
  486. OBJECT_ATTRIBUTES ObjectAttributes;
  487. LARGE_INTEGER MaximumSize;
  488. ULONG CommitSize;
  489. HANDLE Section, ServerSection;
  490. PRTL_EVENT_LOG EventLog, ServerEventLog;
  491. BOOLEAN Inherited;
  492. PROCESS_BASIC_INFORMATION ProcessInformation;
  493. if (Flags & RTL_EVENT_LOG_INHERIT) {
  494. Inherited = TRUE;
  495. }
  496. else {
  497. Inherited = FALSE;
  498. }
  499. InitializeObjectAttributes( &ObjectAttributes,
  500. NULL,
  501. Inherited ? OBJ_INHERIT : 0,
  502. NULL,
  503. NULL
  504. );
  505. MaximumSize.LowPart = 1024 * 1024;
  506. MaximumSize.HighPart = 0;
  507. Status = NtCreateSection( &Section,
  508. SECTION_ALL_ACCESS,
  509. &ObjectAttributes,
  510. &MaximumSize,
  511. PAGE_READWRITE,
  512. SEC_RESERVE,
  513. NULL
  514. );
  515. if (!NT_SUCCESS( Status )) {
  516. return Status;
  517. }
  518. EventLog = NULL;
  519. Status = NtMapViewOfSection( Section,
  520. NtCurrentProcess(),
  521. &EventLog,
  522. 0,
  523. 0,
  524. NULL,
  525. &MaximumSize.LowPart,
  526. ViewUnmap,
  527. 0,
  528. PAGE_READWRITE
  529. );
  530. if (!NT_SUCCESS( Status )) {
  531. NtClose( Section );
  532. return Status;
  533. }
  534. ServerEventLog = NULL;
  535. Status = NtMapViewOfSection( Section,
  536. TargetProcess,
  537. &ServerEventLog,
  538. 0,
  539. 0,
  540. NULL,
  541. &MaximumSize.LowPart,
  542. ViewUnmap,
  543. 0,
  544. PAGE_READWRITE
  545. );
  546. if (!NT_SUCCESS( Status )) {
  547. NtUnmapViewOfSection( NtCurrentProcess(), EventLog );
  548. NtClose( Section );
  549. return Status;
  550. }
  551. CommitSize = 1024 * 16;
  552. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  553. &EventLog,
  554. 0,
  555. &CommitSize,
  556. MEM_COMMIT,
  557. PAGE_READWRITE
  558. );
  559. if (!NT_SUCCESS( Status )) {
  560. NtUnmapViewOfSection( NtCurrentProcess(), ServerEventLog );
  561. NtUnmapViewOfSection( NtCurrentProcess(), EventLog );
  562. NtClose( Section );
  563. return Status;
  564. }
  565. EventLog->EventClassMask = EventClassMask;
  566. EventLog->DisplayClientId = NtCurrentTeb()->ClientId;
  567. EventLog->ClientMutant = NULL;
  568. EventLog->ClientSemaphore = NULL;
  569. EventLog->ServerMutant = NULL;
  570. EventLog->ServerSemaphore = NULL;
  571. EventLog->MinimumOffset = sizeof( *EventLog );
  572. EventLog->MaximumOffset = CommitSize;
  573. EventLog->CurrentReadOffset = EventLog->MinimumOffset;
  574. EventLog->CurrentWriteOffset = EventLog->MinimumOffset;
  575. EventLog->CommitLimitOffset = MaximumSize.LowPart;
  576. Status = NtCreateSemaphore( &EventLog->ClientSemaphore,
  577. SEMAPHORE_ALL_ACCESS,
  578. &ObjectAttributes,
  579. 0,
  580. 0x7FFFFFFF
  581. );
  582. if (NT_SUCCESS( Status )) {
  583. Status = NtCreateMutant( &EventLog->ClientMutant,
  584. MUTANT_ALL_ACCESS,
  585. &ObjectAttributes,
  586. FALSE
  587. );
  588. Status = NtDuplicateObject( NtCurrentProcess(),
  589. EventLog->ClientSemaphore,
  590. TargetProcess,
  591. &EventLog->ServerSemaphore,
  592. 0,
  593. 0,
  594. DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES
  595. );
  596. if (NT_SUCCESS( Status )) {
  597. Status = NtDuplicateObject( NtCurrentProcess(),
  598. EventLog->ClientMutant,
  599. TargetProcess,
  600. &EventLog->ServerMutant,
  601. 0,
  602. 0,
  603. DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES
  604. );
  605. if (NT_SUCCESS( Status )) {
  606. Status = NtDuplicateObject( NtCurrentProcess(),
  607. Section,
  608. TargetProcess,
  609. &ServerSection,
  610. 0,
  611. 0,
  612. DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES
  613. );
  614. if (NT_SUCCESS( Status )) {
  615. Status = NtQueryInformationProcess( TargetProcess,
  616. ProcessBasicInformation,
  617. &ProcessInformation,
  618. sizeof( ProcessInformation ),
  619. NULL
  620. );
  621. if (NT_SUCCESS( Status )) {
  622. Status = NtWriteVirtualMemory( TargetProcess,
  623. &ProcessInformation.PebBaseAddress->EventLogSection,
  624. &ServerSection,
  625. sizeof( ServerSection ),
  626. NULL
  627. );
  628. if (NT_SUCCESS( Status )) {
  629. Status = NtWriteVirtualMemory( TargetProcess,
  630. &ProcessInformation.PebBaseAddress->EventLog,
  631. &ServerEventLog,
  632. sizeof( ServerEventLog ),
  633. NULL
  634. );
  635. }
  636. }
  637. }
  638. }
  639. }
  640. }
  641. NtClose( Section );
  642. if (!NT_SUCCESS( Status )) {
  643. NtClose( EventLog->ClientSemaphore );
  644. NtClose( EventLog->ClientMutant );
  645. NtClose( EventLog->ServerSemaphore );
  646. NtClose( EventLog->ServerMutant );
  647. NtUnmapViewOfSection( NtCurrentProcess(), EventLog );
  648. return Status;
  649. }
  650. EventLog->CountOfClients = 1;
  651. *ReturnedEventLog = EventLog;
  652. return Status;
  653. }
  654. PRTL_EVENT_ID_INFO
  655. RtlpFindEventIdForEvent(
  656. PRTL_EVENT Event
  657. );
  658. NTSTATUS
  659. RtlWaitForEvent(
  660. IN PRTL_EVENT_LOG EventLog,
  661. IN ULONG EventBufferSize,
  662. OUT PRTL_EVENT EventBuffer,
  663. OUT PRTL_EVENT_ID_INFO *ReturnedEventId
  664. )
  665. {
  666. NTSTATUS Status;
  667. HANDLE WaitObjects[ 2 ];
  668. PRTL_EVENT Event;
  669. WaitObjects[ 0 ] = EventLog->ClientSemaphore;
  670. WaitObjects[ 1 ] = EventLog->ClientMutant;
  671. Status = NtWaitForMultipleObjects( 2,
  672. WaitObjects,
  673. WaitAll,
  674. TRUE,
  675. NULL
  676. );
  677. if (!NT_SUCCESS( Status )) {
  678. return Status;
  679. }
  680. try {
  681. Event = (PRTL_EVENT)((PCHAR)EventLog + EventLog->CurrentReadOffset);
  682. if (Event->Length == 0xFFFF) {
  683. Event = (PRTL_EVENT)((PCHAR)EventLog + EventLog->MinimumOffset);
  684. EventLog->CurrentReadOffset = EventLog->MinimumOffset;
  685. }
  686. if (Event->Length <= EventBufferSize) {
  687. RtlMoveMemory( EventBuffer, Event, Event->Length );
  688. EventLog->CurrentReadOffset += Event->Length;
  689. *ReturnedEventId = RtlpFindEventIdForEvent( Event );
  690. }
  691. else {
  692. RtlMoveMemory( EventBuffer, Event, EventBufferSize );
  693. EventLog->CurrentReadOffset += Event->Length;
  694. *ReturnedEventId = RtlpFindEventIdForEvent( Event );
  695. Status = STATUS_BUFFER_TOO_SMALL;
  696. }
  697. }
  698. finally {
  699. NtReleaseMutant( EventLog->ClientMutant, NULL );
  700. }
  701. return Status;
  702. }
  703. PRTL_EVENT_ID_INFO RtlpEventIds;
  704. PRTL_EVENT_ID_INFO
  705. RtlpFindEventIdForEvent(
  706. PRTL_EVENT Event
  707. )
  708. {
  709. PRTL_EVENT_ID_INFO EventId;
  710. BOOLEAN EventIdsFetched;
  711. NTSTATUS Status;
  712. ULONG Size;
  713. EventIdsFetched = FALSE;
  714. while (TRUE) {
  715. EventId = RtlpEventIds;
  716. if (EventId != NULL) {
  717. while (EventId->Length != 0) {
  718. if (Event->EventId == EventId->EventId) {
  719. return EventId;
  720. }
  721. EventId = (PRTL_EVENT_ID_INFO)((PCHAR)EventId + EventId->Length);
  722. }
  723. }
  724. if (EventIdsFetched) {
  725. return NULL;
  726. }
  727. if (RtlpEventIds != NULL) {
  728. Size = 0;
  729. NtFreeVirtualMemory( NtCurrentProcess(),
  730. &RtlpEventIds,
  731. &Size,
  732. MEM_RELEASE
  733. );
  734. }
  735. retryEventIds:
  736. Status = NtQuerySystemInformation( SystemEventIdsInformation,
  737. NULL,
  738. 0,
  739. &Size
  740. );
  741. if (Status != STATUS_INFO_LENGTH_MISMATCH) {
  742. return NULL;
  743. }
  744. RtlpEventIds = NULL;
  745. Status = NtAllocateVirtualMemory( NtCurrentProcess(),
  746. &RtlpEventIds,
  747. 0,
  748. &Size,
  749. MEM_COMMIT,
  750. PAGE_READWRITE
  751. );
  752. if (!NT_SUCCESS( Status )) {
  753. return NULL;
  754. }
  755. Status = NtQuerySystemInformation( SystemEventIdsInformation,
  756. RtlpEventIds,
  757. Size,
  758. NULL
  759. );
  760. if (!NT_SUCCESS( Status )) {
  761. if (Status != STATUS_INFO_LENGTH_MISMATCH) {
  762. return NULL;
  763. }
  764. else {
  765. goto retryEventIds;
  766. }
  767. }
  768. EventIdsFetched = TRUE;
  769. }
  770. }
  771. NTSTATUS
  772. RtlDestroyEventLog(
  773. IN PRTL_EVENT_LOG EventLog
  774. )
  775. {
  776. NtClose( EventLog->ClientMutant );
  777. NtClose( EventLog->ClientSemaphore );
  778. EventLog->ClientMutant = NULL;
  779. EventLog->ClientSemaphore = NULL;
  780. EventLog->CurrentReadOffset = 0;
  781. return NtUnmapViewOfSection( NtCurrentProcess(), EventLog );
  782. }
  783. #endif // ndef NTOS_KERNEL_RUNTIME
  784. #endif // DBG