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.

943 lines
25 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. ntdlltrc.c
  5. Abstract:
  6. This file implements Event Tracing for Heap functions .
  7. --*/
  8. #include <nt.h>
  9. #include <ntrtl.h> // for ntutrl.h
  10. #include <nturtl.h> // for RTL_CRITICAL_SECTION in winbase.h/wtypes.h
  11. #include "wmiump.h"
  12. #include "evntrace.h"
  13. #include "ntdlltrc.h"
  14. #include "trcapi.h"
  15. #include "traceump.h"
  16. #include "tracelib.h"
  17. LONG NtdllTraceInitializeLock = 0;
  18. LONG NtdllLoggerLock = 0;
  19. PNTDLL_EVENT_HANDLES NtdllTraceHandles = NULL;
  20. BOOL bNtdllTrace = FALSE; // Flag determines that Tracing is enabled or disabled for this process.
  21. ULONG GlobalCounter = 0; // Used to determine that we have stale information about logger
  22. LONG TraceLevel = 0;
  23. extern LONG EtwpLoggerCount;
  24. extern ULONG WmiTraceAlignment;
  25. extern BOOLEAN LdrpInLdrInit;
  26. extern PWMI_LOGGER_CONTEXT EtwpLoggerContext;
  27. extern BOOLEAN EtwLocksInitialized;
  28. extern PWMI_BUFFER_HEADER FASTCALL EtwpSwitchFullBuffer(IN PWMI_BUFFER_HEADER OldBuffer );
  29. extern ULONG EtwpReleaseFullBuffer( IN PWMI_BUFFER_HEADER Buffer );
  30. extern PWMI_BUFFER_HEADER FASTCALL EtwpGetFullFreeBuffer( VOID );
  31. extern ULONG EtwpStopUmLogger( IN ULONG WnodeSize, IN OUT ULONG *SizeUsed,
  32. OUT ULONG *SizeNeeded,IN OUT PWMI_LOGGER_INFORMATION LoggerInfo );
  33. extern ULONG EtwpStartUmLogger( IN ULONG WnodeSize, IN OUT ULONG *SizeUsed, OUT ULONG *SizeNeeded,
  34. IN OUT PWMI_LOGGER_INFORMATION LoggerInfo );
  35. extern
  36. ULONG
  37. WMIAPI
  38. EtwRegisterTraceGuidsA(
  39. IN WMIDPREQUEST RequestAddress,
  40. IN PVOID RequestContext,
  41. IN LPCGUID ControlGuid,
  42. IN ULONG GuidCount,
  43. IN PTRACE_GUID_REGISTRATION GuidReg,
  44. IN LPCSTR MofImagePath,
  45. IN LPCSTR MofResourceName,
  46. IN PTRACEHANDLE RegistrationHandle
  47. );
  48. extern
  49. ULONG
  50. WMIAPI
  51. EtwUnregisterTraceGuids(
  52. IN TRACEHANDLE RegistrationHandle
  53. );
  54. #define MAXSTR 1024
  55. #define BUFFER_STATE_FULL 2
  56. #define EtwpIsLoggerOn() \
  57. (EtwpLoggerContext != NULL) && \
  58. (EtwpLoggerContext != (PWMI_LOGGER_CONTEXT) &EtwpLoggerContext)
  59. #define EtwpLockLogger() InterlockedIncrement(&EtwpLoggerCount)
  60. #define EtwpUnlockLogger() InterlockedDecrement(&EtwpLoggerCount)
  61. NTSTATUS
  62. InitializeEtwHandles(PPNTDLL_EVENT_HANDLES ppEtwHandle)
  63. /*++
  64. Routine Description:
  65. This function does groundwork to start Tracing for Heap and Critcal Section.
  66. With the help of global lock NtdllTraceInitializeLock the function
  67. allocates memory for NtdllTraceHandles and initializes the various variables needed
  68. for heap and critical tracing.
  69. Arguments
  70. ppEtwHandle : OUT Pointer is set to value of NtdllTraceHandles
  71. Return Value:
  72. STATUS_SUCCESS
  73. STATUS_UNSUCCESSFUL
  74. --*/
  75. {
  76. NTSTATUS st = STATUS_UNSUCCESSFUL;
  77. PNTDLL_EVENT_HANDLES pEtwHandle = NULL;
  78. __try {
  79. EtwpInitProcessHeap();
  80. pEtwHandle = (PNTDLL_EVENT_HANDLES)EtwpAlloc(sizeof(NTDLL_EVENT_HANDLES));
  81. if(pEtwHandle){
  82. pEtwHandle->hRegistrationHandle = (TRACEHANDLE)INVALID_HANDLE_VALUE;
  83. pEtwHandle->pThreadListHead = NULL;
  84. //
  85. // Allocate TLS
  86. //
  87. pEtwHandle->dwTlsIndex = EtwpTlsAlloc();
  88. if(pEtwHandle->dwTlsIndex == FAILED_TLSINDEX){
  89. EtwpFree(pEtwHandle);
  90. } else {
  91. st = RtlInitializeCriticalSection(&pEtwHandle->CriticalSection);
  92. if (NT_SUCCESS (st)) {
  93. *ppEtwHandle = pEtwHandle;
  94. st = STATUS_SUCCESS;
  95. }
  96. else {
  97. EtwpFree(pEtwHandle);
  98. *ppEtwHandle = NULL;
  99. }
  100. }
  101. }
  102. } __except (EXCEPTION_EXECUTE_HANDLER) {
  103. if(pEtwHandle !=NULL ) {
  104. EtwpFree(pEtwHandle);
  105. pEtwHandle = NULL;
  106. }
  107. EtwpDebugPrint(("InitializeEtwHandles threw an exception %d\n", GetExceptionCode()));
  108. }
  109. return st;
  110. }
  111. void
  112. CleanOnThreadExit()
  113. /*++
  114. Routine Description:
  115. This function cleans up the Thread buffer and takes its node out of the Link list
  116. which contains information of all threads involved in tracing.
  117. --*/
  118. {
  119. PTHREAD_LOCAL_DATA pThreadLocalData = NULL;
  120. PWMI_BUFFER_HEADER pEtwBuffer;
  121. if(NtdllTraceHandles != NULL ){
  122. pThreadLocalData = (PTHREAD_LOCAL_DATA)EtwpTlsGetValue(NtdllTraceHandles->dwTlsIndex);
  123. //
  124. // Remove the node from the Link List
  125. //
  126. if(pThreadLocalData != NULL ){
  127. RtlEnterCriticalSection(&NtdllTraceHandles->CriticalSection);
  128. __try {
  129. if(pThreadLocalData->BLink == NULL ){
  130. NtdllTraceHandles->pThreadListHead = pThreadLocalData->FLink;
  131. if(NtdllTraceHandles->pThreadListHead){
  132. NtdllTraceHandles->pThreadListHead->BLink = NULL;
  133. }
  134. } else {
  135. pThreadLocalData->BLink->FLink = pThreadLocalData->FLink;
  136. if(pThreadLocalData->FLink != NULL ){
  137. pThreadLocalData->FLink->BLink = pThreadLocalData->BLink;
  138. }
  139. }
  140. pEtwBuffer = pThreadLocalData->pBuffer;
  141. if(pEtwBuffer){
  142. EtwpReleaseFullBuffer(pEtwBuffer);
  143. }
  144. pThreadLocalData->pBuffer = NULL;
  145. pThreadLocalData->ReferenceCount = 0;
  146. EtwpFree(pThreadLocalData);
  147. EtwpTlsSetValue(NtdllTraceHandles->dwTlsIndex, NULL);
  148. } __finally {
  149. RtlLeaveCriticalSection(&NtdllTraceHandles->CriticalSection);
  150. }
  151. }
  152. }
  153. }
  154. void
  155. CleanUpAllThreadBuffers(BOOLEAN Release)
  156. /*++
  157. Routine Description:
  158. This function cleans up the All Thread buffers and sets them to NULL. This
  159. function is called when the tracing is disabled for the process.
  160. --*/
  161. {
  162. PTHREAD_LOCAL_DATA pListHead;
  163. BOOL bAllClear = FALSE;
  164. PWMI_BUFFER_HEADER pEtwBuffer;
  165. int retry = 0;
  166. RtlEnterCriticalSection(&NtdllTraceHandles->CriticalSection);
  167. __try {
  168. while(bAllClear != TRUE && retry <= 10){
  169. bAllClear = TRUE;
  170. pListHead = NtdllTraceHandles->pThreadListHead;
  171. while(pListHead != NULL ){
  172. if(Release){
  173. pEtwBuffer = pListHead->pBuffer;
  174. if(pEtwBuffer){
  175. if(InterlockedIncrement(&(pListHead->ReferenceCount)) == 1){
  176. EtwpReleaseFullBuffer(pEtwBuffer);
  177. pListHead->pBuffer = NULL;
  178. InterlockedDecrement(&(pListHead->ReferenceCount));
  179. } else {
  180. InterlockedDecrement(&(pListHead->ReferenceCount));
  181. bAllClear = FALSE;
  182. }
  183. }
  184. } else {
  185. pListHead->pBuffer = NULL;
  186. pListHead->ReferenceCount = 0;
  187. }
  188. pListHead = pListHead->FLink;
  189. }
  190. retry++;
  191. if(!bAllClear){
  192. EtwpSleep(250);
  193. }
  194. }
  195. } __finally {
  196. RtlLeaveCriticalSection(&NtdllTraceHandles->CriticalSection);
  197. }
  198. }
  199. void
  200. ShutDownEtwHandles()
  201. /*++
  202. Routine Description:
  203. This function is called when the process is exiting. This cleans all the thread
  204. buffers and releases the memory allocated for NtdllTraceHandless.
  205. --*/
  206. {
  207. if(NtdllTraceHandles == NULL) return;
  208. bNtdllTrace = FALSE;
  209. RtlEnterCriticalSection(&NtdllTraceHandles->CriticalSection);
  210. __try {
  211. if(NtdllTraceHandles->hRegistrationHandle != (TRACEHANDLE)INVALID_HANDLE_VALUE){
  212. EtwUnregisterTraceGuids(NtdllTraceHandles->hRegistrationHandle);
  213. }
  214. if(NtdllTraceHandles->pThreadListHead != NULL){
  215. PTHREAD_LOCAL_DATA pListHead, pNextListHead;
  216. pListHead = NtdllTraceHandles->pThreadListHead;
  217. while(pListHead != NULL ){
  218. if(pListHead->pBuffer != NULL){
  219. EtwpReleaseFullBuffer(pListHead->pBuffer);
  220. pListHead->pBuffer = NULL;
  221. InterlockedDecrement(&(pListHead->ReferenceCount));
  222. }
  223. pNextListHead = pListHead->FLink;
  224. EtwpFree(pListHead);
  225. pListHead = pNextListHead;
  226. }
  227. }
  228. EtwpTlsFree(NtdllTraceHandles->dwTlsIndex);
  229. } __finally {
  230. RtlLeaveCriticalSection(&NtdllTraceHandles->CriticalSection);
  231. }
  232. RtlDeleteCriticalSection(&NtdllTraceHandles->CriticalSection);
  233. EtwpFree(NtdllTraceHandles);
  234. NtdllTraceHandles = NULL;
  235. }
  236. NTSTATUS
  237. GetLoggerInfo(PWMI_LOGGER_INFORMATION LoggerInfo)
  238. {
  239. ULONG st = STATUS_UNSUCCESSFUL;
  240. WMINTDLLLOGGERINFO NtdllLoggerInfo;
  241. ULONG BufferSize;
  242. if(LoggerInfo == NULL) return st;
  243. NtdllLoggerInfo.LoggerInfo = LoggerInfo;
  244. NtdllLoggerInfo.LoggerInfo->Wnode.Guid = NtdllTraceGuid;
  245. NtdllLoggerInfo.IsGet = TRUE;
  246. st = EtwpSendWmiKMRequest(
  247. NULL,
  248. IOCTL_WMI_NTDLL_LOGGERINFO,
  249. &NtdllLoggerInfo,
  250. sizeof(WMINTDLLLOGGERINFO),
  251. &NtdllLoggerInfo,
  252. sizeof(WMINTDLLLOGGERINFO),
  253. &BufferSize,
  254. NULL
  255. );
  256. return st;
  257. }
  258. BOOLEAN
  259. GetPidInfo(ULONG CheckPid, PWMI_LOGGER_INFORMATION LoggerInfo)
  260. {
  261. NTSTATUS st;
  262. BOOLEAN Found = FALSE;
  263. PTRACE_ENABLE_FLAG_EXTENSION FlagExt = NULL;
  264. st = GetLoggerInfo(LoggerInfo);
  265. if(NT_SUCCESS(st)){
  266. PULONG PidArray = NULL;
  267. ULONG count;
  268. FlagExt = (PTRACE_ENABLE_FLAG_EXTENSION) &LoggerInfo->EnableFlags;
  269. PidArray = (PULONG)(FlagExt->Offset + (PCHAR)LoggerInfo);
  270. for(count = 0; count < FlagExt->Length; count++){
  271. if(CheckPid == PidArray[count]){
  272. Found = TRUE;
  273. break;
  274. }
  275. }
  276. }
  277. return Found;
  278. }
  279. ULONG
  280. WINAPI
  281. NtdllCtrlCallback(
  282. WMIDPREQUESTCODE RequestCode,
  283. PVOID Context,
  284. ULONG *InOutBufferSize,
  285. PVOID Buffer
  286. )
  287. /*++
  288. Routine Description:
  289. This is WMI control callback function used at the time of registration.
  290. --*/
  291. {
  292. ULONG ret;
  293. ret = ERROR_SUCCESS;
  294. switch (RequestCode)
  295. {
  296. case WMI_ENABLE_EVENTS: //Enable Provider.
  297. {
  298. if(bNtdllTrace == TRUE) break;
  299. if(EtwpIsLoggerOn()){
  300. bNtdllTrace = TRUE;
  301. break;
  302. }
  303. if(InterlockedIncrement(&NtdllLoggerLock) == 1){
  304. if( bNtdllTrace == FALSE ){
  305. BOOLEAN PidEntry = FALSE;
  306. PWMI_LOGGER_INFORMATION LoggerInfo = NULL;
  307. ULONG sizeNeeded = sizeof(WMI_LOGGER_INFORMATION)
  308. + (2 * MAXSTR * sizeof(WCHAR))
  309. + (MAX_PID + 1) * sizeof(ULONG);
  310. //
  311. // Check to see that this process is allowed to log events
  312. // or not.
  313. //
  314. LoggerInfo = EtwpAlloc(sizeNeeded);
  315. if(LoggerInfo){
  316. //
  317. // Check to see that this process is allowed to
  318. // register or not.
  319. //
  320. RtlZeroMemory(LoggerInfo, sizeNeeded);
  321. if(GetPidInfo(EtwpGetCurrentProcessId(), LoggerInfo)){
  322. LoggerInfo->LoggerName.Buffer =
  323. (PWCHAR)(((PUCHAR) LoggerInfo)
  324. + sizeof(WMI_LOGGER_INFORMATION));
  325. LoggerInfo->LogFileName.Buffer =
  326. (PWCHAR)(((PUCHAR) LoggerInfo)
  327. + sizeof(WMI_LOGGER_INFORMATION)
  328. + LoggerInfo->LoggerName.MaximumLength);
  329. LoggerInfo->InstanceCount = 0;
  330. LoggerInfo->InstanceId = EtwpGetCurrentProcessId();
  331. TraceLevel = (LONG)LoggerInfo->Wnode.HistoricalContext;
  332. LoggerInfo->Wnode.HistoricalContext = 0;
  333. LoggerInfo->Wnode.ClientContext =
  334. EVENT_TRACE_CLOCK_CPUCYCLE;
  335. //Start Logger Here
  336. ret = EtwpStartUmLogger(sizeNeeded,
  337. &sizeNeeded,
  338. &sizeNeeded,
  339. LoggerInfo
  340. );
  341. if(ret == ERROR_SUCCESS ){
  342. CleanUpAllThreadBuffers(FALSE);
  343. bNtdllTrace = TRUE;
  344. InterlockedIncrement(&NtdllLoggerLock);
  345. }
  346. }
  347. EtwpFree(LoggerInfo);
  348. } else {
  349. EtwpDebugPrint(("LoggerInfo failed to get Heap Allocation during Enable Events\n"));
  350. }
  351. }
  352. }
  353. InterlockedDecrement(&NtdllLoggerLock);
  354. break;
  355. }
  356. case WMI_DISABLE_EVENTS: //Disable Provider.
  357. {
  358. if( bNtdllTrace == TRUE ){
  359. ULONG WnodeSize,SizeUsed,SizeNeeded;
  360. WMI_LOGGER_INFORMATION LoggerInfo;
  361. bNtdllTrace = FALSE;
  362. //
  363. // The above boolean bNtdllTrace is turned off as this
  364. // function will again be called back by EtwpStopUmLogger
  365. // so it will fall into endless loop of incrementing and
  366. // decrementing NtdllLoggerLock.( see below ).
  367. // This assignment SHOULD NOT BE MOVED FROM THIS PLACE.
  368. //
  369. while( InterlockedIncrement(&NtdllLoggerLock) != 1 ){
  370. InterlockedDecrement(&NtdllLoggerLock);
  371. EtwpSleep(250);
  372. }
  373. if(!EtwpIsLoggerOn()){
  374. InterlockedDecrement(&NtdllLoggerLock);
  375. break;
  376. }
  377. //
  378. // Now release thread buffer memory here.
  379. //
  380. CleanUpAllThreadBuffers(TRUE);
  381. WnodeSize = sizeof(WMI_LOGGER_INFORMATION);
  382. RtlZeroMemory(&LoggerInfo, WnodeSize);
  383. LoggerInfo.Wnode.CountLost = ((PWNODE_HEADER)Buffer)->CountLost;
  384. LoggerInfo.Wnode.BufferSize = WnodeSize;
  385. SizeUsed = 0;
  386. SizeNeeded = 0;
  387. EtwpStopUmLogger(WnodeSize,
  388. &SizeUsed,
  389. &SizeNeeded,
  390. &LoggerInfo);
  391. InterlockedDecrement(&NtdllLoggerLock);
  392. }
  393. break;
  394. }
  395. default:
  396. {
  397. ret = ERROR_INVALID_PARAMETER;
  398. break;
  399. }
  400. }
  401. return ret;
  402. }
  403. ULONG
  404. RegisterNtdllTraceEvents()
  405. /*++
  406. Routine Description:
  407. This function registers the guids with WMI for tracing.
  408. Return Value:
  409. The return value of RegisterTraceGuidsA function.
  410. --*/
  411. {
  412. //Create the guid registration array
  413. NTSTATUS status;
  414. TRACE_GUID_REGISTRATION TraceGuidReg[] =
  415. {
  416. {
  417. (LPGUID) &HeapGuid,
  418. NULL
  419. },
  420. {
  421. (LPGUID) &CritSecGuid,
  422. NULL
  423. }
  424. };
  425. //Now register this process as a WMI trace provider.
  426. status = EtwRegisterTraceGuidsA(
  427. (WMIDPREQUEST)NtdllCtrlCallback, // Enable/disable function.
  428. NULL, // RequestContext parameter
  429. (LPGUID)&NtdllTraceGuid, // Provider GUID
  430. 2, // TraceGuidReg array size
  431. TraceGuidReg, // Array of TraceGuidReg structures
  432. NULL, // Optional WMI - MOFImagePath
  433. NULL, // Optional WMI - MOFResourceName
  434. &(NtdllTraceHandles->hRegistrationHandle) // Handle unregister
  435. );
  436. return status;
  437. }
  438. NTSTATUS
  439. InitializeAndRegisterNtdllTraceEvents()
  440. /*++
  441. Routine Description:
  442. This functions checks for global variable NtdllTraceHandles and if not set then
  443. calls fucntion InitializeEtwHandles to initialize it. NtdllTraceHandles
  444. contains handles used for Heap tracing. If NtdllTraceHandles is already
  445. initialized then a call is made to register the guids.
  446. Return Value:
  447. STATUS_SUCCESS
  448. STATUS_UNSUCCESSFUL
  449. --*/
  450. {
  451. NTSTATUS st = STATUS_UNSUCCESSFUL;
  452. if(NtdllTraceHandles == NULL){
  453. if(InterlockedIncrement(&NtdllTraceInitializeLock) == 1){
  454. st = InitializeEtwHandles(&NtdllTraceHandles);
  455. if(NT_SUCCESS(st)){
  456. st = RegisterNtdllTraceEvents();
  457. }
  458. }
  459. }
  460. return st;
  461. }
  462. NTSTATUS
  463. AllocateMemoryForThreadLocalData(PPTHREAD_LOCAL_DATA ppThreadLocalData)
  464. /*++
  465. Routine Description:
  466. This functions allcates memory for tls and adds it to Link list which
  467. contains informations of all threads involved in tracing.
  468. Arguments
  469. ppThreadLocalData : The OUT pointer to the tls.
  470. Return Value:
  471. STATUS_SUCCESS
  472. STATUS_UNSUCCESSFUL
  473. --*/
  474. {
  475. NTSTATUS st = STATUS_UNSUCCESSFUL;
  476. PTHREAD_LOCAL_DATA pThreadLocalData = NULL;
  477. pThreadLocalData = (PTHREAD_LOCAL_DATA)EtwpAlloc(sizeof(THREAD_LOCAL_DATA));
  478. if(pThreadLocalData != NULL){
  479. if(EtwpTlsSetValue(NtdllTraceHandles->dwTlsIndex, (LPVOID)pThreadLocalData) == TRUE){
  480. pThreadLocalData->pBuffer = NULL;
  481. pThreadLocalData->ReferenceCount = 0;
  482. RtlEnterCriticalSection(&NtdllTraceHandles->CriticalSection);
  483. if(NtdllTraceHandles->pThreadListHead == NULL ){
  484. pThreadLocalData->BLink = NULL;
  485. pThreadLocalData->FLink = NULL;
  486. } else {
  487. pThreadLocalData->FLink = NtdllTraceHandles->pThreadListHead;
  488. pThreadLocalData->BLink = NULL;
  489. NtdllTraceHandles->pThreadListHead->BLink = pThreadLocalData;
  490. }
  491. NtdllTraceHandles->pThreadListHead = pThreadLocalData;
  492. RtlLeaveCriticalSection(&NtdllTraceHandles->CriticalSection);
  493. st = STATUS_SUCCESS;
  494. }
  495. } else {
  496. EtwpDebugPrint(("pThreadLocalData failed to get Heap Allocation\n"));
  497. }
  498. if(!NT_SUCCESS(st) && pThreadLocalData != NULL){
  499. EtwpFree(pThreadLocalData);
  500. pThreadLocalData = NULL;
  501. }
  502. *ppThreadLocalData = pThreadLocalData;
  503. return st;
  504. }
  505. void
  506. ReleaseBufferLocation(PTHREAD_LOCAL_DATA pThreadLocalData)
  507. {
  508. PWMI_BUFFER_HEADER pEtwBuffer;
  509. pEtwBuffer = pThreadLocalData->pBuffer;
  510. if(pEtwBuffer){
  511. PPERFINFO_TRACE_HEADER EventHeader = (PPERFINFO_TRACE_HEADER) (pEtwBuffer->SavedOffset
  512. + (PCHAR)(pEtwBuffer));
  513. EventHeader->Marker = PERFINFO_TRACE_MARKER;
  514. EventHeader->TS = EtwpGetCycleCount();
  515. }
  516. InterlockedDecrement(&(pThreadLocalData->ReferenceCount));
  517. EtwpUnlockLogger();
  518. }
  519. PCHAR
  520. ReserveBufferSpace(PTHREAD_LOCAL_DATA pThreadLocalData, PUSHORT ReqSize)
  521. {
  522. PWMI_BUFFER_HEADER TraceBuffer = pThreadLocalData->pBuffer;
  523. *ReqSize = (USHORT) ALIGN_TO_POWER2(*ReqSize, WmiTraceAlignment);
  524. if(TraceBuffer == NULL) return NULL;
  525. if(EtwpLoggerContext->BufferSize - TraceBuffer->CurrentOffset < *ReqSize) {
  526. PWMI_BUFFER_HEADER NewTraceBuffer = NULL;
  527. NewTraceBuffer = EtwpSwitchFullBuffer(TraceBuffer);
  528. if( NewTraceBuffer == NULL ){
  529. pThreadLocalData->pBuffer = NULL;
  530. return NULL;
  531. } else {
  532. pThreadLocalData->pBuffer = NewTraceBuffer;
  533. TraceBuffer = NewTraceBuffer;
  534. }
  535. }
  536. TraceBuffer->SavedOffset = TraceBuffer->CurrentOffset;
  537. TraceBuffer->CurrentOffset += *ReqSize;
  538. return (PCHAR)( TraceBuffer->SavedOffset + (PCHAR) TraceBuffer );
  539. }
  540. NTSTATUS
  541. AcquireBufferLocation(PVOID *ppEvent, PPTHREAD_LOCAL_DATA ppThreadLocalData, PUSHORT ReqSize)
  542. /*++
  543. Routine Description:
  544. This function is called from heap.c and heapdll.c whenever there is some
  545. Heap activity. It looks up the buffer location where the even can be written
  546. and gives back the pointer.
  547. Arguments:
  548. ppEvent - The pointer to pointer of buffer location
  549. ppThreadLocalData - The pointer to pointer of thread event storing struct.
  550. Return Value:
  551. STATUS_UNSUCCESSFUL if failed otherwise STATUS_SUCCESS
  552. --*/
  553. {
  554. NTSTATUS st = STATUS_SUCCESS;
  555. PWMI_BUFFER_HEADER pEtwBuffer;
  556. if( bNtdllTrace ){
  557. EtwpLockLogger();
  558. if(EtwpIsLoggerOn()){
  559. *ppThreadLocalData = (PTHREAD_LOCAL_DATA)EtwpTlsGetValue(NtdllTraceHandles->dwTlsIndex);
  560. //
  561. //If there is no tls then create one here
  562. //
  563. if(*ppThreadLocalData == NULL ) {
  564. st = AllocateMemoryForThreadLocalData(ppThreadLocalData);
  565. }
  566. //
  567. //If the thread buffer is NULL then get it from logger.
  568. //
  569. if( NT_SUCCESS(st) && (*ppThreadLocalData)->pBuffer == NULL ){
  570. (*ppThreadLocalData)->pBuffer = EtwpGetFullFreeBuffer();
  571. if((*ppThreadLocalData)->pBuffer == NULL){
  572. st = STATUS_UNSUCCESSFUL;
  573. }
  574. }
  575. if(NT_SUCCESS(st)){
  576. //
  577. // Check ReferenceCount. If is 1 then the cleaning process
  578. // might be in progress.
  579. //
  580. pEtwBuffer = (*ppThreadLocalData)->pBuffer;
  581. if(pEtwBuffer){
  582. if(InterlockedIncrement(&((*ppThreadLocalData)->ReferenceCount)) == 1 ){
  583. *ppEvent = ReserveBufferSpace(*ppThreadLocalData, ReqSize );
  584. if(*ppEvent == NULL) {
  585. InterlockedDecrement(&((*ppThreadLocalData)->ReferenceCount));
  586. EtwpUnlockLogger();
  587. }
  588. } else {
  589. InterlockedDecrement(&((*ppThreadLocalData)->ReferenceCount));
  590. }
  591. }
  592. }
  593. } else {
  594. EtwpUnlockLogger();
  595. }
  596. } else if ( LdrpInLdrInit == FALSE && EtwLocksInitialized && NtdllTraceInitializeLock == 0 ){
  597. //
  598. // Make sure that process is not in initialization phase
  599. // Also we test for NtdllTraceInitializeLock. If is
  600. // greater than 0 then it was registered earlier so no
  601. // need to fire IOCTLS everytime
  602. //
  603. if((UserSharedData->TraceLogging >> 16) != GlobalCounter){
  604. PWMI_LOGGER_INFORMATION LoggerInfo = NULL;
  605. ULONG sizeNeeded = sizeof(WMI_LOGGER_INFORMATION)
  606. + (2 * MAXSTR * sizeof(TCHAR))
  607. + (MAX_PID + 1) * sizeof(ULONG);
  608. GlobalCounter = UserSharedData->TraceLogging >> 16;
  609. EtwpInitProcessHeap();
  610. LoggerInfo = EtwpAlloc(sizeNeeded);
  611. if(LoggerInfo != NULL){
  612. //
  613. // Check to see that this process is allowed to register or not.
  614. //
  615. if(GetPidInfo(EtwpGetCurrentProcessId(), LoggerInfo)){
  616. st = InitializeAndRegisterNtdllTraceEvents();
  617. }
  618. EtwpFree(LoggerInfo);
  619. } else {
  620. EtwpDebugPrint(("LoggerInfo failed to get Heap Allocation \n"));
  621. }
  622. }
  623. }
  624. return st;
  625. }