|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
perftdet.c
Abstract:
This file implements an Performance Object that presents Thread details performance object data
Created:
Bob Watson 22-Oct-1996
Revision History
--*/ //
// Include Files
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winperf.h>
#include <ntprfctr.h>
#include <perfutil.h>
#include "perfsprc.h"
#include "perfmsg.h"
#include "datatdet.h"
DWORD APIENTRY CollectThreadDetailsObjectData ( IN OUT LPVOID *lppData, IN OUT LPDWORD lpcbTotalBytes, IN OUT LPDWORD lpNumObjectTypes ) /*++
Routine Description:
This routine will return the data for the processor object
Arguments:
IN OUT LPVOID *lppData IN: pointer to the address of the buffer to receive the completed PerfDataBlock and subordinate structures. This routine will append its data to the buffer starting at the point referenced by *lppData. OUT: points to the first byte after the data structure added by this routine. This routine updated the value at lppdata after appending its data.
IN OUT LPDWORD lpcbTotalBytes IN: the address of the DWORD that tells the size in bytes of the buffer referenced by the lppData argument OUT: the number of bytes added by this routine is writted to the DWORD pointed to by this argument
IN OUT LPDWORD NumObjectTypes IN: the address of the DWORD to receive the number of objects added by this routine OUT: the number of objects added by this routine is writted to the DWORD pointed to by this argument
Returns:
0 if successful, else Win 32 error code of failure
--*/ { DWORD TotalLen; // Length of the total return block
PTHREAD_DETAILS_DATA_DEFINITION pThreadDetailDataDefinition; PPERF_INSTANCE_DEFINITION pPerfInstanceDefinition; PTHREAD_DETAILS_COUNTER_DATA pTDCD;
PSYSTEM_PROCESS_INFORMATION ProcessInfo; PSYSTEM_THREAD_INFORMATION ThreadInfo = NULL;
ULONG ProcessNumber; ULONG NumThreadInstances; ULONG ThreadNumber = 0; ULONG ProcessBufferOffset; BOOLEAN NullProcess;
NTSTATUS Status; // return from Nt Calls
LONGLONG llPcValue; // value of current thread PC
OBJECT_ATTRIBUTES Obja; // object attributes for thread context
HANDLE hThread; // handle to current thread
CONTEXT ThreadContext; // current thread context struct
UNICODE_STRING ThreadName; WCHAR ThreadNameBuffer[MAX_THREAD_NAME_LENGTH+1]; BOOL bMoreThreads;
pThreadDetailDataDefinition = (THREAD_DETAILS_DATA_DEFINITION *) *lppData;
//
// Check for sufficient space for Thread object type definition
//
TotalLen = sizeof(THREAD_DETAILS_DATA_DEFINITION) + sizeof(PERF_INSTANCE_DEFINITION) + sizeof(THREAD_DETAILS_COUNTER_DATA);
if ( *lpcbTotalBytes < TotalLen ) { *lpcbTotalBytes = 0; *lpNumObjectTypes = 0; return ERROR_MORE_DATA; }
//
// Define Thread data block
//
ThreadName.Length = ThreadName.MaximumLength = (MAX_THREAD_NAME_LENGTH + 1) * sizeof(WCHAR); ThreadName.Buffer = ThreadNameBuffer;
memcpy (pThreadDetailDataDefinition, &ThreadDetailsDataDefinition, sizeof(THREAD_DETAILS_DATA_DEFINITION));
ProcessBufferOffset = 0;
// Now collect data for each Thread
ProcessNumber = 0; NumThreadInstances = 0;
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)pProcessBuffer;
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *) &pThreadDetailDataDefinition[1];
TotalLen = sizeof (THREAD_DETAILS_DATA_DEFINITION);
bMoreThreads = FALSE; if (ProcessInfo) { if (ProcessInfo->NextEntryOffset != 0) { bMoreThreads = TRUE; } } while ( bMoreThreads && (ProcessInfo != NULL)) {
if ( ProcessInfo->ImageName.Buffer != NULL || ProcessInfo->NumberOfThreads > 0 ) { NullProcess = FALSE; ThreadNumber = 0; // Thread number of this process
ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1); } else { NullProcess = TRUE; }
while ( !NullProcess && ThreadNumber < ProcessInfo->NumberOfThreads ) {
TotalLen += sizeof(PERF_INSTANCE_DEFINITION) + (MAX_THREAD_NAME_LENGTH+1+sizeof(DWORD))* sizeof(WCHAR) + sizeof (THREAD_DETAILS_COUNTER_DATA);
if ( *lpcbTotalBytes < TotalLen ) { *lpcbTotalBytes = 0; *lpNumObjectTypes = 0; return ERROR_MORE_DATA; }
// Get Thread Context Information for Current PC field
llPcValue = 0; InitializeObjectAttributes(&Obja, NULL, 0, NULL, NULL); Status = NtOpenThread( &hThread, THREAD_GET_CONTEXT, &Obja, &ThreadInfo->ClientId ); if ( NT_SUCCESS(Status) ) { ThreadContext.ContextFlags = CONTEXT_CONTROL; Status = NtGetContextThread(hThread,&ThreadContext); NtClose(hThread); if ( NT_SUCCESS(Status) ) { llPcValue = (LONGLONG)CONTEXT_TO_PROGRAM_COUNTER(&ThreadContext); } else { llPcValue = 0; // an error occured so send back 0 PC
} } else { llPcValue = 0; // an error occured so send back 0 PC
}
// The only name we've got is the thread number
RtlIntegerToUnicodeString(ThreadNumber, 10, &ThreadName);
MonBuildInstanceDefinition(pPerfInstanceDefinition, (PVOID *) &pTDCD, EXPROCESS_OBJECT_TITLE_INDEX, ProcessNumber, (DWORD)-1, ThreadName.Buffer);
//
//
// Format and collect Thread data
//
pTDCD->CounterBlock.ByteLength = sizeof (THREAD_DETAILS_COUNTER_DATA);
pTDCD->UserPc = llPcValue;
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)&pTDCD[1]; NumThreadInstances++; ThreadNumber++; ThreadInfo++; }
if (ProcessInfo->NextEntryOffset == 0) { // no more entries so bail out of the loop
bMoreThreads = FALSE; continue; }
ProcessBufferOffset += ProcessInfo->NextEntryOffset; ProcessInfo = (PSYSTEM_PROCESS_INFORMATION) &pProcessBuffer[ProcessBufferOffset];
if ( !NullProcess ) { ProcessNumber++; } }
// Note number of Thread instances
pThreadDetailDataDefinition->ThreadDetailsObjectType.NumInstances = NumThreadInstances;
//
// Now we know how large an area we used for the
// Thread definition, so we can update the offset
// to the next object definition
//
*lpcbTotalBytes = pThreadDetailDataDefinition->ThreadDetailsObjectType.TotalByteLength = (DWORD)((PCHAR) pPerfInstanceDefinition - (PCHAR) pThreadDetailDataDefinition);
#if DBG
if (*lpcbTotalBytes > TotalLen ) { DbgPrint ("\nPERFPROC: Thread Details Perf Ctr. Instance Size Underestimated:"); DbgPrint ("\nPERFPROC: Estimated size: %d, Actual Size: %d", TotalLen, *lpcbTotalBytes); } #endif
*lppData = (LPVOID) pPerfInstanceDefinition;
*lpNumObjectTypes = 1;
return ERROR_SUCCESS; }
|