653 lines
18 KiB
C
653 lines
18 KiB
C
/*++
|
|
|
|
Copyright (c) 1998-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
main.c
|
|
|
|
Abstract:
|
|
|
|
TRACELIB dll main file
|
|
|
|
Author:
|
|
|
|
08-Apr-1998 mraghu
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <stdio.h>
|
|
#include "cpdata.h"
|
|
#include "tracectr.h"
|
|
|
|
// Globals
|
|
extern ULONGLONG StartTime;
|
|
extern ULONGLONG EndTime;
|
|
|
|
SYSTEM_RECORD CurrentSystem;
|
|
static ULONG lCachedFlushTimer = 1;
|
|
PTRACE_CONTEXT_BLOCK TraceContext = NULL;
|
|
RTL_CRITICAL_SECTION TLCritSect;
|
|
|
|
BOOLEAN fDSOnly = FALSE;
|
|
ULONGLONG DSStartTime = 0;
|
|
ULONGLONG DSEndTime = 0;
|
|
ULONG TotalBuffersRead = 0;
|
|
WCHAR TempFile[MAXSTR] = L"";
|
|
|
|
ULONG
|
|
WINAPI
|
|
TerminateOnBufferCallback(
|
|
PEVENT_TRACE_LOGFILE pLog
|
|
);
|
|
|
|
extern WriteProc(
|
|
LPWSTR filename,
|
|
ULONG flags,
|
|
PVOID pUserContext
|
|
);
|
|
|
|
HRESULT
|
|
OnProcess(
|
|
PTRACE_CONTEXT_BLOCK TraceContext
|
|
);
|
|
|
|
ULONG GetMoreBuffers(
|
|
PEVENT_TRACE_LOGFILE logfile
|
|
);
|
|
|
|
void
|
|
ReorderThreadList()
|
|
{
|
|
PLIST_ENTRY Head, Next;
|
|
PTHREAD_RECORD Thread;
|
|
int i;
|
|
PPROCESS_RECORD Process;
|
|
for (i=0; i < THREAD_HASH_TABLESIZE; i++) {
|
|
|
|
Head = &CurrentSystem.ThreadHashList[i];
|
|
Next = Head->Flink;
|
|
while (Next != Head) {
|
|
Thread = CONTAINING_RECORD( Next, THREAD_RECORD, Entry );
|
|
Next = Next->Flink;
|
|
RemoveEntryList( &Thread->Entry );
|
|
Process = Thread->pProcess;
|
|
if(Process != NULL){
|
|
InsertTailList( &Process->ThreadListHead, &Thread->Entry );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ULONG
|
|
CPDAPI
|
|
GetMaxLoggers()
|
|
{
|
|
return MAXLOGGERS;
|
|
}
|
|
|
|
ULONG
|
|
CPDAPI
|
|
InitTraceContextW(
|
|
PTRACE_BASIC_INFOW pUserInfo
|
|
)
|
|
{
|
|
UINT i, j;
|
|
PFILE_OBJECT *fileTable;
|
|
ULONG SizeNeeded, SizeIncrement;
|
|
char * pStorage;
|
|
HRESULT hr;
|
|
BOOL bProcessing = FALSE;
|
|
|
|
if (pUserInfo == NULL) {
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
//
|
|
// Must provide at least one logfile or a trace seassion to process
|
|
//
|
|
|
|
if ( (pUserInfo->LoggerCount == 0) && (pUserInfo->LogFileCount == 0) ) {
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
//
|
|
// Can not process both RealTime stream and a logfile at the same time
|
|
//
|
|
|
|
if ( (pUserInfo->LoggerCount > 0) && (pUserInfo->LogFileCount > 0) ) {
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
//
|
|
// Compute the Size Needed for allocation.
|
|
//
|
|
|
|
SizeNeeded = sizeof(TRACE_CONTEXT_BLOCK);
|
|
|
|
// Add LogFileName Strings
|
|
|
|
for (i = 0; i < pUserInfo->LogFileCount; i++) {
|
|
SizeNeeded += sizeof(WCHAR) * ( wcslen( pUserInfo->LogFileName[i] ) + 1);
|
|
SizeNeeded = (SizeNeeded + 7) & ~7;
|
|
}
|
|
|
|
// Add LoggerName Strings
|
|
|
|
for (i = 0; i < pUserInfo->LoggerCount; i++) {
|
|
SizeNeeded += sizeof(WCHAR) * ( wcslen(pUserInfo->LoggerName[i]) + 1);
|
|
SizeNeeded = (SizeNeeded + 7) & ~7;
|
|
}
|
|
|
|
//
|
|
// Add ProcFile, MofFile, DumpFile, SummaryFile, TempFile name strings
|
|
|
|
if (pUserInfo->ProcFileName != NULL) {
|
|
SizeNeeded += sizeof(WCHAR) * (wcslen(pUserInfo->ProcFileName) + 1);
|
|
SizeNeeded = (SizeNeeded + 7) & ~7;
|
|
}
|
|
|
|
if (pUserInfo->MofFileName != NULL) {
|
|
SizeNeeded += sizeof(WCHAR) * (wcslen(pUserInfo->MofFileName) + 1);
|
|
SizeNeeded = (SizeNeeded + 7) & ~7;
|
|
}
|
|
|
|
if (pUserInfo->DumpFileName != NULL) {
|
|
SizeNeeded += sizeof(WCHAR) * (wcslen(pUserInfo->DumpFileName) + 1);
|
|
SizeNeeded = (SizeNeeded + 7) & ~7;
|
|
}
|
|
|
|
if (pUserInfo->MergeFileName != NULL) {
|
|
SizeNeeded += sizeof(WCHAR) * (wcslen(pUserInfo->MergeFileName) + 1);
|
|
SizeNeeded = (SizeNeeded + 7) & ~7;
|
|
}
|
|
|
|
if (pUserInfo->CompFileName != NULL) {
|
|
SizeNeeded += sizeof(WCHAR) * (wcslen(pUserInfo->CompFileName) + 1);
|
|
SizeNeeded = (SizeNeeded + 7) & ~7;
|
|
}
|
|
|
|
if (pUserInfo->SummaryFileName != NULL) {
|
|
SizeNeeded += sizeof(WCHAR) * (wcslen(pUserInfo->SummaryFileName) + 1);
|
|
SizeNeeded = (SizeNeeded + 7) & ~7;
|
|
}
|
|
|
|
//
|
|
// Add Room for the FileTable Caching
|
|
//
|
|
|
|
SizeNeeded += sizeof(PFILE_OBJECT) * MAX_FILE_TABLE_SIZE;
|
|
|
|
|
|
//
|
|
// Add Room for Thread Hash List
|
|
//
|
|
|
|
SizeNeeded += sizeof(LIST_ENTRY) * THREAD_HASH_TABLESIZE;
|
|
|
|
|
|
//
|
|
// Allocate Memory for TraceContext
|
|
//
|
|
|
|
pStorage = malloc(SizeNeeded);
|
|
if (pStorage == NULL) {
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
|
|
RtlZeroMemory(pStorage, SizeNeeded);
|
|
|
|
TraceContext = (PTRACE_CONTEXT_BLOCK)pStorage;
|
|
|
|
pStorage += sizeof(TRACE_CONTEXT_BLOCK);
|
|
|
|
//
|
|
// Initialize HandleArray
|
|
//
|
|
|
|
for (i=0; i < MAXLOGGERS; i++) {
|
|
TraceContext->HandleArray[i] = (TRACEHANDLE)INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
//
|
|
// Copy LogFileNames
|
|
//
|
|
|
|
for (i = 0; i < pUserInfo->LogFileCount; i++) {
|
|
TraceContext->LogFileName[i] = (LPWSTR)pStorage;
|
|
wcscpy(TraceContext->LogFileName[i], pUserInfo->LogFileName[i]);
|
|
SizeIncrement = (wcslen(TraceContext->LogFileName[i]) + 1) * sizeof(WCHAR);
|
|
SizeIncrement = (SizeIncrement + 7) & ~7;
|
|
pStorage += SizeIncrement;
|
|
}
|
|
|
|
//
|
|
// Copy LoggerNames
|
|
//
|
|
|
|
for (i = 0; i < pUserInfo->LoggerCount; i++) {
|
|
j = i + pUserInfo->LogFileCount;
|
|
TraceContext->LoggerName[j] =(LPWSTR) pStorage;
|
|
wcscpy(TraceContext->LoggerName[j], pUserInfo->LoggerName[i]);
|
|
SizeIncrement = (wcslen(TraceContext->LoggerName[j]) + 1) * sizeof(WCHAR);
|
|
SizeIncrement = (SizeIncrement + 7) & ~7;
|
|
pStorage += SizeIncrement;
|
|
}
|
|
|
|
//
|
|
// Copy Other File Names
|
|
//
|
|
|
|
if (pUserInfo->ProcFileName != NULL) {
|
|
TraceContext->ProcFileName = (LPWSTR)pStorage;
|
|
wcscpy( TraceContext->ProcFileName, pUserInfo->ProcFileName);
|
|
SizeIncrement = (wcslen(TraceContext->ProcFileName) + 1) * sizeof(WCHAR);
|
|
SizeIncrement = (SizeIncrement + 7) & ~7;
|
|
pStorage += SizeIncrement;
|
|
}
|
|
|
|
if (pUserInfo->DumpFileName != NULL) {
|
|
TraceContext->DumpFileName = (LPWSTR)pStorage;
|
|
wcscpy( TraceContext->DumpFileName, pUserInfo->DumpFileName);
|
|
SizeIncrement = (wcslen(TraceContext->DumpFileName) + 1) * sizeof(WCHAR);
|
|
SizeIncrement = (SizeIncrement + 7) & ~7;
|
|
pStorage += SizeIncrement;
|
|
}
|
|
|
|
if (pUserInfo->MofFileName != NULL) {
|
|
TraceContext->MofFileName = (LPWSTR)pStorage;
|
|
wcscpy( TraceContext->MofFileName, pUserInfo->MofFileName);
|
|
SizeIncrement = (wcslen(TraceContext->MofFileName) + 1) * sizeof(WCHAR);
|
|
SizeIncrement = (SizeIncrement + 7) & ~7;
|
|
pStorage += SizeIncrement;
|
|
}
|
|
|
|
if (pUserInfo->MergeFileName != NULL) {
|
|
TraceContext->MergeFileName = (LPWSTR)pStorage;
|
|
wcscpy( TraceContext->MergeFileName, pUserInfo->MergeFileName);
|
|
SizeIncrement = (wcslen(TraceContext->MergeFileName) + 1) * sizeof(WCHAR);
|
|
SizeIncrement = (SizeIncrement + 7) & ~7;
|
|
pStorage += SizeIncrement;
|
|
}
|
|
|
|
if (pUserInfo->CompFileName != NULL) {
|
|
TraceContext->CompFileName = (LPWSTR)pStorage;
|
|
wcscpy( TraceContext->CompFileName, pUserInfo->CompFileName);
|
|
SizeIncrement = (wcslen(TraceContext->CompFileName) + 1) * sizeof(WCHAR);
|
|
SizeIncrement = (SizeIncrement + 7) & ~7;
|
|
pStorage += SizeIncrement;
|
|
}
|
|
|
|
if (pUserInfo->SummaryFileName != NULL) {
|
|
TraceContext->SummaryFileName = (LPWSTR)pStorage;
|
|
wcscpy( TraceContext->SummaryFileName, pUserInfo->SummaryFileName);
|
|
SizeIncrement = (wcslen(TraceContext->SummaryFileName) + 1) * sizeof(WCHAR);
|
|
SizeIncrement = (SizeIncrement + 7) & ~7;
|
|
pStorage += SizeIncrement;
|
|
}
|
|
|
|
TraceContext->LogFileCount = pUserInfo->LogFileCount;
|
|
TraceContext->LoggerCount = pUserInfo->LoggerCount;
|
|
TraceContext->StartTime = pUserInfo->StartTime;
|
|
TraceContext->EndTime = pUserInfo->EndTime;
|
|
TraceContext->Flags = pUserInfo->Flags;
|
|
TraceContext->hEvent = pUserInfo->hEvent;
|
|
TraceContext->pUserContext = pUserInfo->pUserContext;
|
|
|
|
RtlZeroMemory(&CurrentSystem, sizeof(SYSTEM_RECORD));
|
|
InitializeListHead ( &CurrentSystem.ProcessListHead );
|
|
InitializeListHead ( &CurrentSystem.GlobalThreadListHead );
|
|
InitializeListHead ( &CurrentSystem.GlobalDiskListHead );
|
|
InitializeListHead ( &CurrentSystem.HotFileListHead );
|
|
InitializeListHead ( &CurrentSystem.WorkloadListHead );
|
|
InitializeListHead ( &CurrentSystem.InstanceListHead );
|
|
InitializeListHead ( &CurrentSystem.EventListHead );
|
|
InitializeListHead ( &CurrentSystem.GlobalModuleListHead );
|
|
InitializeListHead ( &CurrentSystem.ProcessFileListHead );
|
|
InitializeListHead ( &CurrentSystem.JobListHead);
|
|
|
|
CurrentSystem.FileTable = (PFILE_OBJECT *) pStorage;
|
|
pStorage += ( sizeof(PFILE_OBJECT) * MAX_FILE_TABLE_SIZE);
|
|
|
|
CurrentSystem.ThreadHashList = (PLIST_ENTRY)pStorage;
|
|
pStorage += (sizeof(LIST_ENTRY) * THREAD_HASH_TABLESIZE);
|
|
|
|
RtlZeroMemory(CurrentSystem.ThreadHashList, sizeof(LIST_ENTRY) * THREAD_HASH_TABLESIZE);
|
|
|
|
for (i=0; i < THREAD_HASH_TABLESIZE; i++) {
|
|
InitializeListHead (&CurrentSystem.ThreadHashList[i]);
|
|
}
|
|
|
|
if( (pUserInfo->Flags & TRACE_DUMP) && NULL != pUserInfo->DumpFileName ){
|
|
TraceContext->Flags |= TRACE_DUMP;
|
|
}
|
|
|
|
if( (pUserInfo->Flags & TRACE_SUMMARY) && NULL != pUserInfo->SummaryFileName ){
|
|
TraceContext->Flags |= TRACE_SUMMARY;
|
|
}
|
|
|
|
if( (pUserInfo->Flags & TRACE_INTERPRET) && NULL != pUserInfo->CompFileName ){
|
|
TraceContext->Flags |= TRACE_INTERPRET;
|
|
}
|
|
|
|
hr = GetTempName( TempFile, MAXSTR );
|
|
CHECK_HR(hr);
|
|
|
|
CurrentSystem.TempFile = _wfopen( TempFile, L"w+");
|
|
if( CurrentSystem.TempFile == NULL ){
|
|
hr = GetLastError();
|
|
}
|
|
CHECK_HR(hr);
|
|
|
|
CurrentSystem.fNoEndTime = FALSE;
|
|
fileTable = CurrentSystem.FileTable;
|
|
for ( i= 0; i<MAX_FILE_TABLE_SIZE; i++){ fileTable[i] = NULL; }
|
|
|
|
//
|
|
// Set the default Processing Flags to Dump
|
|
//
|
|
|
|
if( pUserInfo->Flags & TRACE_EXTENDED_FMT ){
|
|
TraceContext->Flags |= TRACE_EXTENDED_FMT;
|
|
}
|
|
|
|
if( pUserInfo->Flags & TRACE_REDUCE ) {
|
|
TraceContext->Flags |= TRACE_REDUCE;
|
|
TraceContext->Flags |= TRACE_LOG_REPORT_BASIC;
|
|
}
|
|
|
|
if (TraceContext->Flags & TRACE_DS_ONLY) {
|
|
fDSOnly = TRUE;
|
|
DSStartTime = pUserInfo->DSStartTime;
|
|
DSEndTime = pUserInfo->DSEndTime;
|
|
}
|
|
|
|
if( TraceContext->Flags & TRACE_MERGE_ETL ){
|
|
hr = EtwRelogEtl( TraceContext );
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
bProcessing = TRUE;
|
|
|
|
RtlInitializeCriticalSection(&TLCritSect);
|
|
|
|
//
|
|
// Startup a Thread to update the counters.
|
|
// For Logfile replay we burn a thread and throttle it at the
|
|
// BufferCallbacks.
|
|
//
|
|
|
|
hr = OnProcess(TraceContext);// Then process Trace Event Data.
|
|
|
|
ShutdownThreads();
|
|
ShutdownProcesses();
|
|
ReorderThreadList();
|
|
|
|
cleanup:
|
|
if( ERROR_SUCCESS != hr ){
|
|
__try{
|
|
if( TraceContext->hDumpFile ){
|
|
fclose( TraceContext->hDumpFile );
|
|
}
|
|
if( bProcessing ){
|
|
Cleanup();
|
|
RtlDeleteCriticalSection(&TLCritSect);
|
|
}
|
|
if( CurrentSystem.TempFile != NULL ){
|
|
fclose( CurrentSystem.TempFile );
|
|
DeleteFile( TempFile );
|
|
}
|
|
if( NULL != TraceContext ){
|
|
free(TraceContext);
|
|
TraceContext = NULL;
|
|
}
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// Buffer Callback. Used to send a flag to the logstream processing thread.
|
|
//
|
|
ULONG
|
|
GetMoreBuffers(
|
|
PEVENT_TRACE_LOGFILE logfile
|
|
)
|
|
{
|
|
TotalBuffersRead++;
|
|
|
|
if (TraceContext->hEvent) {
|
|
SetEvent(TraceContext->hEvent);
|
|
}
|
|
//
|
|
// While processing logfile playback, we can throttle the processing
|
|
// of buffers by the FlushTimer value (in Seconds)
|
|
//
|
|
|
|
if (TraceContext->Flags & TRACE_LOG_REPLAY) {
|
|
_sleep(TraceContext->LoggerInfo->FlushTimer * 1000);
|
|
}
|
|
if(logfile->EventsLost) {
|
|
#if DBG
|
|
DbgPrint("(TRACECTR) GetMorBuffers(Lost: %9d Filled: %9d\n",
|
|
logfile->EventsLost, logfile->Filled );
|
|
#endif
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
ULONG
|
|
CPDAPI
|
|
DeinitTraceContext(
|
|
PTRACE_BASIC_INFOW pUserInfo
|
|
)
|
|
{
|
|
ULONG Status = ERROR_SUCCESS;
|
|
ULONG LogFileCount, i;
|
|
|
|
if (TraceContext == NULL) {
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
LogFileCount = TraceContext->LogFileCount + TraceContext->LoggerCount;
|
|
for (i=0; i < LogFileCount; i++) {
|
|
if (TraceContext->HandleArray[i] != (TRACEHANDLE)INVALID_HANDLE_VALUE) {
|
|
|
|
CloseTrace(TraceContext->HandleArray[i]);
|
|
TraceContext->HandleArray[i] = (TRACEHANDLE)INVALID_HANDLE_VALUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Write the Summary File
|
|
//
|
|
|
|
if (TraceContext->Flags & TRACE_SUMMARY) {
|
|
WriteSummary();
|
|
}
|
|
|
|
if (TraceContext->Flags & TRACE_REDUCE) {
|
|
if ((TraceContext->ProcFileName != NULL) &&
|
|
(lstrlenW(TraceContext->ProcFileName) ) ){
|
|
|
|
|
|
WriteProc(TraceContext->ProcFileName,
|
|
TraceContext->Flags,
|
|
TraceContext->pUserContext
|
|
);
|
|
}
|
|
}
|
|
|
|
if( CurrentSystem.TempFile != NULL ){
|
|
fclose(CurrentSystem.TempFile);
|
|
DeleteFile( TempFile );
|
|
}
|
|
|
|
if (TraceContext->Flags & TRACE_DUMP) {
|
|
if (TraceContext->hDumpFile != NULL) {
|
|
fclose(TraceContext->hDumpFile);
|
|
}
|
|
}
|
|
|
|
Cleanup();
|
|
|
|
RtlDeleteCriticalSection(&TLCritSect);
|
|
|
|
free (TraceContext);
|
|
TraceContext = NULL;
|
|
|
|
return (Status);
|
|
}
|
|
|
|
HRESULT
|
|
OnProcess(
|
|
PTRACE_CONTEXT_BLOCK TraceContext
|
|
)
|
|
{
|
|
ULONG LogFileCount;
|
|
ULONG i;
|
|
|
|
ULONG Status;
|
|
PEVENT_TRACE_LOGFILE LogFile[MAXLOGGERS];
|
|
BOOL bRealTime;
|
|
SYSTEMTIME stLocalTime;
|
|
FILETIME ftLocalTime;
|
|
|
|
RtlZeroMemory( &LogFile[0], sizeof(PVOID) * MAXLOGGERS );
|
|
|
|
if( TraceContext->LogFileCount > 0 ){
|
|
LogFileCount = TraceContext->LogFileCount;
|
|
bRealTime = FALSE;
|
|
}else{
|
|
LogFileCount = TraceContext->LoggerCount;
|
|
bRealTime = TRUE;
|
|
}
|
|
|
|
for (i = 0; i < LogFileCount; i++) {
|
|
LogFile[i] = malloc(sizeof(EVENT_TRACE_LOGFILE));
|
|
if (LogFile[i] == NULL) {
|
|
Status = ERROR_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
RtlZeroMemory(LogFile[i], sizeof(EVENT_TRACE_LOGFILE));
|
|
|
|
LogFile[i]->BufferCallback = (PEVENT_TRACE_BUFFER_CALLBACK)&TerminateOnBufferCallback;
|
|
|
|
if( bRealTime ){
|
|
LogFile[i]->LoggerName = TraceContext->LoggerName[i];
|
|
LogFile[i]->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
|
|
}else{
|
|
LogFile[i]->LogFileName = TraceContext->LogFileName[i];
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < LogFileCount; i++) {
|
|
|
|
TraceContext->HandleArray[i] = OpenTrace(LogFile[i]);;
|
|
|
|
if ((TRACEHANDLE)INVALID_HANDLE_VALUE == TraceContext->HandleArray[i] ) {
|
|
Status = GetLastError();
|
|
goto cleanup;
|
|
}
|
|
|
|
Status = ProcessTrace( &(TraceContext->HandleArray[i]), 1, NULL, NULL);
|
|
if( ERROR_CANCELLED != Status && ERROR_SUCCESS != Status ){
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < LogFileCount; i++){
|
|
Status = CloseTrace(TraceContext->HandleArray[i]);
|
|
}
|
|
|
|
for (i=0; i<LogFileCount; i++) {
|
|
|
|
LogFile[i]->BufferCallback = (PEVENT_TRACE_BUFFER_CALLBACK)&GetMoreBuffers;
|
|
LogFile[i]->EventCallback = (PEVENT_CALLBACK)GeneralEventCallback;
|
|
|
|
TraceContext->HandleArray[i] = OpenTrace( (PEVENT_TRACE_LOGFILE)LogFile[i]);
|
|
|
|
if ( TraceContext->HandleArray[i] == (TRACEHANDLE)INVALID_HANDLE_VALUE) {
|
|
Status = GetLastError();
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if( TraceContext->Flags & TRACE_DUMP ){
|
|
FILE* f = _wfopen ( TraceContext->DumpFileName, L"w" );
|
|
if( f == NULL) {
|
|
Status = GetLastError();
|
|
goto cleanup;
|
|
}
|
|
if( TraceContext->Flags & TRACE_EXTENDED_FMT ){
|
|
_ftprintf( f,
|
|
_T("%12s, %10s, %8s,%8s,%8s,%7s,%21s,%11s,%11s, User Data\n"),
|
|
_T("Event Name"), _T("Type"),
|
|
_T("Type"), _T("Level"), _T("Version"),
|
|
_T("TID"), _T("Clock-Time"),
|
|
_T("Kernel(ms)"), _T("User(ms)")
|
|
);
|
|
}else{
|
|
_ftprintf( f,
|
|
_T("%12s, %10s,%7s,%21s,%11s,%11s, User Data\n"),
|
|
_T("Event Name"), _T("Type"), _T("TID"), _T("Clock-Time"),
|
|
_T("Kernel(ms)"), _T("User(ms)")
|
|
);
|
|
}
|
|
TraceContext->hDumpFile = f;
|
|
}
|
|
|
|
DeclareKernelEvents();
|
|
|
|
GetLocalTime (&stLocalTime);
|
|
SystemTimeToFileTime (&stLocalTime, &ftLocalTime);
|
|
|
|
StartTime =
|
|
(((ULONGLONG) ftLocalTime.dwHighDateTime) << 32) +
|
|
ftLocalTime.dwLowDateTime;
|
|
|
|
Status = ProcessTrace(TraceContext->HandleArray,
|
|
LogFileCount,
|
|
NULL,
|
|
NULL);
|
|
|
|
if( 0 == EndTime ){
|
|
GetLocalTime (&stLocalTime);
|
|
SystemTimeToFileTime (&stLocalTime, &ftLocalTime);
|
|
|
|
EndTime =
|
|
(((ULONGLONG) ftLocalTime.dwHighDateTime) << 32) +
|
|
ftLocalTime.dwLowDateTime;
|
|
}
|
|
|
|
if( bRealTime && (ERROR_WMI_INSTANCE_NOT_FOUND == Status) ){
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
|
|
CurrentSystem.ElapseTime = (ULONG) ( CurrentSystem.EndTime
|
|
- CurrentSystem.StartTime);
|
|
|
|
cleanup:
|
|
for (i=0; i < LogFileCount; i++){
|
|
|
|
if( (TRACEHANDLE)INVALID_HANDLE_VALUE != TraceContext->HandleArray[i] ){
|
|
|
|
CloseTrace(TraceContext->HandleArray[i]);
|
|
TraceContext->HandleArray[i] = (TRACEHANDLE)INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
if( NULL != LogFile[i] ){
|
|
free(LogFile[i]);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|