|
|
//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2002 Microsoft Corporation. All rights reserved.
// Copyright (c) 2002 OSR Open Systems Resources, Inc.
//
// LogSession.cpp : implementation of the CLogSession class
//////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <afxtempl.h>
#include "DockDialogBar.h"
#include <tchar.h>
#include <wmistr.h>
#include <initguid.h>
#include <guiddef.h>
extern "C" { #include <evntrace.h>
#include "wppfmtstub.h"
} #include <traceprt.h>
#include "TraceView.h"
#include "utils.h"
#include "LogSession.h"
#include "ListCtrlEx.h"
#include "LogSessionDlg.h"
#include "DisplayDlg.h"
CTraceSession::CTraceSession(ULONG TraceSessionID) { m_traceSessionID = TraceSessionID;
//
// Initialize the temp directory
//
m_tempDirectory.Empty();
//
// Not using kernel logger unless selected by user
//
m_bKernelLogger = FALSE; }
CTraceSession::~CTraceSession() { //
// remove our working directory
//
ClearDirectory(m_tempDirectory);
//
// Now remove it
//
RemoveDirectory(m_tempDirectory); }
BOOL CTraceSession::ProcessPdb() { CString traceDirectory; CString tempPath; CString tmfPath; CString tmcPath; CString providerName; CString temp; GUID directoryGuid; CFileFind fileFind;
if(m_pdbFile.IsEmpty()) { return FALSE; }
if(m_tempDirectory.IsEmpty()) { //
// setup a special directory in which to create our files
//
traceDirectory = (LPCTSTR)((CTraceViewApp *)AfxGetApp())->m_traceDirectory;
//
// create our own unique directory under the temp directory
//
if(S_OK != CoCreateGuid(&directoryGuid)) { AfxMessageBox(_T("Failed To Create Temp Directory\nApplication Will Exit")); return FALSE; }
GuidToString(directoryGuid, temp);
traceDirectory += (LPCTSTR)temp;
traceDirectory += (LPCTSTR)_T("\\");
if(!CreateDirectory(traceDirectory, NULL)) { AfxMessageBox(_T("Failed To Create Temporary Directory For Trace Session")); return FALSE; }
//
// save the directory
//
m_tempDirectory = traceDirectory; }
//
// Clear the directory in case it already existed
//
ClearDirectory(m_tempDirectory);
//
// Now create the TMF and TMC files
//
if(!ParsePdb(m_pdbFile, m_tempDirectory)) { AfxMessageBox(_T("Failed To Parse PDB File")); return FALSE; }
//
// Get the control GUID for this provider
//
tmfPath = (LPCTSTR)m_tempDirectory;
tmcPath = (LPCTSTR)m_tempDirectory;
tmcPath +=_T("\\*.tmc");
if(!fileFind.FindFile(tmcPath)) { AfxMessageBox(_T("Failed To Get Control GUID From PDB")); return FALSE; } else { while(fileFind.FindNextFile()) { tmcPath = fileFind.GetFileName(); m_tmcFile.Add(tmcPath); }
tmcPath = fileFind.GetFileName(); m_tmcFile.Add(tmcPath); }
if(m_tmcFile.GetSize() == 0) { AfxMessageBox(_T("No Control GUIDs Obtained From PDB")); return FALSE; }
//
// Pull the control GUID(s) from the name(s) of the TMC file(s),
// this is a very backwards way of getting a GUID from a PDB
// but its what we got
//
for(LONG ii = 0; ii < m_tmcFile.GetSize(); ii++) { m_controlGuid.Add( (LPCTSTR)m_tmcFile[ii].Left(m_tmcFile[ii].Find('.'))); m_controlGuidFriendlyName.Add(m_pdbFile); }
//
// Now get the full path and name of the TMF file
//
tmfPath +=_T("\\*.tmf");
if(!fileFind.FindFile(tmfPath)) { AfxMessageBox(_T("Failed To Get Format Information From PDB\nEvent Data Will Not Be Formatted")); } else {
while(fileFind.FindNextFile()) { //
// Get the trace event identifier GUID
//
tmfPath = (LPCTSTR)fileFind.GetFileName(); if(!tmfPath.IsEmpty()) { //
// Add format GUID
//
m_formatGuid.Add((LPCTSTR)tmfPath.Left(tmfPath.Find('.'))); //
// Add the TMF filename to the TMF path
//
tmfPath = (LPCTSTR)m_tempDirectory; tmfPath +=_T("\\"); tmfPath += (LPCTSTR)fileFind.GetFileName(); //
// Store the TMF path
//
m_tmfFile.Add(tmfPath); } }
//
// Get the trace event identifier GUID
//
tmfPath = (LPCTSTR)fileFind.GetFileName(); if(!tmfPath.IsEmpty()) { //
// Add format GUID
//
m_formatGuid.Add((LPCTSTR)tmfPath.Left(tmfPath.Find('.'))); //
// Add the TMF filename to the TMF path
//
tmfPath = (LPCTSTR)m_tempDirectory; tmfPath +=_T("\\"); tmfPath += (LPCTSTR)fileFind.GetFileName(); //
// Store the TMF path
//
m_tmfFile.Add(tmfPath); } }
if(m_tmfFile.GetSize() == 0) { AfxMessageBox(_T("Failed To Get Format Information From PDB\nEvent Data Will Not Be Formatted")); }
return TRUE; }
CLogSession::CLogSession(ULONG LogSessionID, CLogSessionDlg *pLogSessionDlg) { //
// Save the log session ID
//
m_logSessionID = LogSessionID;
//
// save the log session dialog pointer
//
m_pLogSessionDlg = pLogSessionDlg;
CString str;
str.Format(_T("m_pLogSession = %p"), this);
//
// initialize class members
//
m_pDisplayDialog = NULL; m_groupID = -1; m_bAppend = FALSE; m_bRealTime = TRUE; m_logFileName.Format(_T("LogSession%d.etl"), m_logSessionID); m_displayName.Format(_T("LogSession%d"), m_logSessionID); m_sessionHandle = (TRACEHANDLE)INVALID_HANDLE_VALUE; m_bTraceActive = FALSE; m_bSessionActive = FALSE; m_bStoppingTrace = FALSE; m_bDisplayExistingLogFileOnly = FALSE;
//
// Initialize default log session parameter values
//
m_logSessionValues.Add("STOPPED"); // State
m_logSessionValues.Add("0"); // Event Count
m_logSessionValues.Add("0"); // Lost Event Count
m_logSessionValues.Add("0"); // Event Buffers Read Count
m_logSessionValues.Add("0xFFFF"); // Flags
m_logSessionValues.Add("1"); // Flush time in seconds
m_logSessionValues.Add("21"); // Maximum buffers
m_logSessionValues.Add("4"); // Minimum buffers
m_logSessionValues.Add("200"); // Buffer size in KB
m_logSessionValues.Add("20"); // Decay value in minutes
m_logSessionValues.Add(""); // Circular file size in MB
m_logSessionValues.Add("200"); // Sequential file size in MB
m_logSessionValues.Add(""); // New file after size in MB
m_logSessionValues.Add("FALSE"); // Use global sequence numbers
m_logSessionValues.Add("TRUE"); // Use local sequence numbers
m_logSessionValues.Add("0"); // Level
//
// Set the default log session name color
//
m_titleTextColor = RGB(0,0,0); m_titleBackgroundColor = RGB(255,255,255);
//
// Default to writing no log file
//
m_bWriteLogFile = FALSE; }
CLogSession::~CLogSession() { CTraceSession *pTraceSession;
//
// free the trace sessions
//
while(m_traceSessionArray.GetSize() > 0) { pTraceSession = (CTraceSession *)m_traceSessionArray[0]; m_traceSessionArray.RemoveAt(0); if(NULL != pTraceSession) { delete pTraceSession; } } }
VOID CLogSession::SetState(LOG_SESSION_STATE StateValue) { LONG index; CString stateText;
switch(StateValue) { case Grouping: //
// set the display text
//
stateText =_T("GROUPING");
m_bGroupingTrace = TRUE;
break;
case UnGrouping: //
// set the display text
//
stateText =_T("UNGROUPING");
m_bGroupingTrace = TRUE;
break;
case Existing: //
// set the display text
//
stateText =_T("EXISTING");
//
// Set our state to show a session is in progress
//
m_bTraceActive = TRUE;
m_bGroupingTrace = FALSE;
break;
case Running: //
// set the display text
//
stateText =_T("RUNNING");
//
// Set our state to show a session is in progress
//
m_bTraceActive = TRUE;
m_bGroupingTrace = FALSE;
break;
case Stopping: if(m_logSessionValues[State].Compare(_T("GROUPING"))) { if(m_logSessionValues[State].Compare(_T("UNGROUPING"))) { if(!m_bDisplayExistingLogFileOnly) { //
// set the display text
//
stateText =_T("STOPPING"); } } }
//
// Indicate we are done stopping the trace
//
m_bStoppingTrace = TRUE;
break;
case Stopped: default:
if(m_logSessionValues[State].Compare(_T("GROUPING"))) { if(m_logSessionValues[State].Compare(_T("UNGROUPING"))) { if(!m_bDisplayExistingLogFileOnly) { //
// set the display text
//
stateText =_T("STOPPED"); } } }
//
// Indicate we are done stopping the trace
//
m_bStoppingTrace = FALSE;
//
// Set our state to show a session is not in progress
//
m_bTraceActive = FALSE;
break; }
//
// Save the state value
//
if(!stateText.IsEmpty()) { m_logSessionValues[State] = stateText; } }
BOOL CLogSession::BeginTrace(BOOL bUseExisting) { ULONG ret; PEVENT_TRACE_PROPERTIES pProperties; PEVENT_TRACE_PROPERTIES pQueryProperties; TRACEHANDLE hSessionHandle = (TRACEHANDLE)INVALID_HANDLE_VALUE; CString str; ULONG sizeNeeded; LPTSTR pLoggerName; LPTSTR pLogFileName; ULONG flags = 0; ULONG level; GUID controlGuid; LONG status; CTraceSession *pTraceSession;
//
// If we are just displaying an existing log file, then just set
// the state and return
//
if(m_bDisplayExistingLogFileOnly) { SetState(Existing); return TRUE; }
//
// setup our buffer size for the properties struct
//
sizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) + (2 * 500 * sizeof(TCHAR));
pProperties = (PEVENT_TRACE_PROPERTIES) new char[sizeNeeded]; if(NULL == pProperties) { AfxMessageBox(_T("Failed To Start Trace, Out Of Resources")); return FALSE; }
//
// zero our structure
//
memset(pProperties, 0, sizeNeeded);
pProperties->Wnode.BufferSize = sizeNeeded; pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID; pProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES); pLoggerName = (LPTSTR)((char*)pProperties + pProperties->LoggerNameOffset); _tcscpy(pLoggerName, GetDisplayName());
//
// If using a log file, then set the parameters for it
//
if(m_bWriteLogFile) { pProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + (500 * sizeof(TCHAR)); pLogFileName = (LPTSTR)((char*)pProperties + pProperties->LogFileNameOffset); _tcscpy(pLogFileName, (LPCTSTR)m_logFileName);
//BUGBUG
//
// Can't have circular and sequential, so we favor circular
// this probably needs to change in that we should limit the
// user to only be able to pick one or the other.
//
if(!m_logSessionValues[Circular].IsEmpty()) { //
// Deliver events to a circular log file.
//
pProperties->LogFileMode |= EVENT_TRACE_FILE_MODE_CIRCULAR;
//
// Circular log files should have a maximum size.
//
pProperties->MaximumFileSize = ConvertStringToNum(m_logSessionValues[Circular]); } else { //
// Deliver events to a sequential log file.
//
pProperties->LogFileMode |= EVENT_TRACE_FILE_MODE_SEQUENTIAL;
//
// Sequential log files can have a maximum size.
//
pProperties->MaximumFileSize = ConvertStringToNum(m_logSessionValues[Sequential]); }
//
// Append to a current logfile.
//
if(m_bAppend) { pProperties->LogFileMode |= EVENT_TRACE_FILE_MODE_APPEND; }
if(!m_logSessionValues[NewFile].IsEmpty()) { //
// Use a new log file when the requested size of data is
// received.
//
pProperties->LogFileMode |= EVENT_TRACE_FILE_MODE_NEWFILE;
//
// Data size.
//
pProperties->MaximumFileSize = ConvertStringToNum(m_logSessionValues[NewFile]); } }
//
// Set the session to generate real-time events
//
if(m_bRealTime) { pProperties->LogFileMode |= EVENT_TRACE_REAL_TIME_MODE; }
//BUGBUG
//
// Again we should limit the user to select one or the other.
// a session can only use global or local sequence numbers so
// we favor global for now.
//
if(m_logSessionValues[GlobalSequence] == "TRUE") { //
// Use global sequence numbers.
//
pProperties->LogFileMode |= EVENT_TRACE_USE_GLOBAL_SEQUENCE; } else if(m_logSessionValues[LocalSequence] == "TRUE") { //
// Use local sequence numbers.
//
pProperties->LogFileMode |= EVENT_TRACE_USE_LOCAL_SEQUENCE; }
//
// Set the buffer settings.
//
pProperties->BufferSize = ConvertStringToNum(m_logSessionValues[BufferSize]); pProperties->MinimumBuffers = ConvertStringToNum(m_logSessionValues[MinimumBuffers]); pProperties->MaximumBuffers = ConvertStringToNum(m_logSessionValues[MaximumBuffers]); pProperties->FlushTimer = ConvertStringToNum(m_logSessionValues[FlushTime]); level = ConvertStringToNum(m_logSessionValues[Level]); pProperties->AgeLimit = ConvertStringToNum(m_logSessionValues[DecayTime]);
//
// get the trace enable flags
//
flags = ConvertStringToNum(m_logSessionValues[Flags]); pProperties->EnableFlags = flags;
//
// Start the session.
//
while(ERROR_SUCCESS != (ret = StartTrace(&hSessionHandle, GetDisplayName(), pProperties))) { if(ret != ERROR_ALREADY_EXISTS) { str.Format(_T("StartTrace failed: %d\n"), ret);
AfxMessageBox(str);
delete [] pProperties;
//
// Reset the session handle
//
SetSessionHandle((TRACEHANDLE)INVALID_HANDLE_VALUE);
return FALSE; }
if(bUseExisting) { SetState(Running);
delete [] pProperties;
return TRUE; }
//
// If the session is already active give the user a chance to kill
// it and restart. (this will happen if the app dies while a log
// session is active)
//
str.Format(_T("Warning: LogSession Already In Progress\n\nSelect Action:\n\n\tYes - Stop And Restart The Log Session\n\n\tNo - Join The Log Session Without Stopping\n\t (Session Will Be Unremovable/Unstoppable Without Restarting TraceView)\n\n\tCancel - Abort Start Operation"));
ret = AfxMessageBox(str, MB_YESNOCANCEL);
//
// If joining an in progress session, we need to query and
// get the correct values for the session
//
if(IDNO == ret) { //
// setup our buffer size for the properties struct for our query
//
sizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) + (2 * 1024 * sizeof(TCHAR));
//
// allocate our memory
//
pQueryProperties = (PEVENT_TRACE_PROPERTIES) new char[sizeNeeded]; if(NULL == pQueryProperties) { return FALSE; }
//
// zero our structures
//
memset(pQueryProperties, 0, sizeNeeded);
//
// Set the size
//
pQueryProperties->Wnode.BufferSize = sizeNeeded;
//
// Set the GUID
//
pQueryProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
//
// Set the logger name offset
//
pQueryProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
//
// Set the logger name for the query
//
pLoggerName = (LPTSTR)((char*)pQueryProperties + pQueryProperties->LoggerNameOffset); _tcscpy(pLoggerName, GetDisplayName());
//
// Set the log file name offset
//
pQueryProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + (500 * sizeof(TCHAR));
//
// Query the log session
//
status = ControlTrace(0, GetDisplayName(), pQueryProperties, EVENT_TRACE_CONTROL_QUERY);
if(ERROR_SUCCESS == status) { if(pQueryProperties->LogFileMode & EVENT_TRACE_FILE_MODE_CIRCULAR) { m_logSessionValues[Circular].Format(_T("%d"), pQueryProperties->MaximumFileSize); m_logSessionValues[Sequential].Empty(); m_logSessionValues[NewFile].Empty(); }
if(pQueryProperties->LogFileMode & EVENT_TRACE_FILE_MODE_SEQUENTIAL) { m_logSessionValues[Sequential].Format(_T("%d"), pQueryProperties->MaximumFileSize); m_logSessionValues[Circular].Empty(); m_logSessionValues[NewFile].Empty(); }
if(pQueryProperties->LogFileMode & EVENT_TRACE_FILE_MODE_NEWFILE) { m_logSessionValues[NewFile].Format(_T("%d"), pQueryProperties->MaximumFileSize); m_logSessionValues[Circular].Empty(); m_logSessionValues[Sequential].Empty(); }
if(pQueryProperties->LogFileMode & EVENT_TRACE_USE_GLOBAL_SEQUENCE) { m_logSessionValues[GlobalSequence].Format(_T("TRUE")); m_logSessionValues[LocalSequence].Format(_T("FALSE")); }
if(pQueryProperties->LogFileMode & EVENT_TRACE_USE_LOCAL_SEQUENCE) { m_logSessionValues[GlobalSequence].Format(_T("FALSE")); m_logSessionValues[LocalSequence].Format(_T("TRUE")); }
m_logSessionValues[BufferSize].Format(_T("%d"), pQueryProperties->BufferSize); m_logSessionValues[MinimumBuffers].Format(_T("%d"), pQueryProperties->MinimumBuffers); m_logSessionValues[MaximumBuffers].Format(_T("%d"), pQueryProperties->MaximumBuffers); m_logSessionValues[FlushTime].Format(_T("%d"), pQueryProperties->FlushTimer); m_logSessionValues[Level].Format(_T("%d"), pQueryProperties->Wnode.HistoricalContext); m_logSessionValues[DecayTime].Format(_T("%d"), pQueryProperties->AgeLimit); m_logSessionValues[Flags].Format(_T("0x%X"), pQueryProperties->EnableFlags);
//
// Now write the values out
//
//::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WM_USER_UPDATE_LOGSESSION_DATA, (WPARAM)this, NULL);
}
hSessionHandle = (TRACEHANDLE)INVALID_HANDLE_VALUE;
break; }
if(IDCANCEL == ret) { this->SetSessionHandle((TRACEHANDLE)INVALID_HANDLE_VALUE);
return FALSE; }
//
// Stop the session, so it can be restarted.
//
ret = ControlTrace(hSessionHandle, GetDisplayName(), pProperties, EVENT_TRACE_CONTROL_STOP); }
delete [] pProperties;
//
// Set the session state flag
//
m_bSessionActive = TRUE;
//
// Save the new session handle
//
SetSessionHandle(hSessionHandle);
//
// If the session handle is invalid, we are hooking up to
// an already running session
//
if((TRACEHANDLE)INVALID_HANDLE_VALUE == (TRACEHANDLE)hSessionHandle) { SetState(Running);
return TRUE; }
//
// Enable the trace(s)
//
for(LONG ii = 0; ii < m_traceSessionArray.GetSize(); ii++) { pTraceSession = (CTraceSession *)m_traceSessionArray[ii]; if(pTraceSession == NULL) { continue; }
//
// Enable all trace providers for this log session
//
for(LONG jj = 0; jj < pTraceSession->m_controlGuid.GetSize(); jj++) { //
// We don't have to enable the kernel logger, so check for it
//
if(!pTraceSession->m_bKernelLogger) { StringToGuid((LPTSTR)(LPCTSTR)pTraceSession->m_controlGuid[jj], &controlGuid); ret = EnableTrace(TRUE, flags, level, &controlGuid, hSessionHandle); if (ret != ERROR_SUCCESS) { if(ret == ERROR_INVALID_FUNCTION) { str.Format(_T("Failed To Enable Trace For Control GUID:\n%ls\n\nEnableTrace Returned %d\n\nThis Error Is Commonly Caused By Multiple Log Sessions\nAttempting To Solicit Events From A Single Provider"), pTraceSession->m_controlGuid[jj], ret); } else { str.Format(_T("Failed To Enable Trace For Control GUID:\n%ls\n\nEnableTrace Returned %d\n"), pTraceSession->m_controlGuid[jj], ret); } AfxMessageBox(str); } } } }
SetState(Running);
return TRUE; }
//
// Updates an active tracing session. Real-Time mode, log file name,
// flush-time, flags, and maximum buffers can be updated.
//
BOOL CLogSession::UpdateSession(PEVENT_TRACE_PROPERTIES pQueryProperties) { PEVENT_TRACE_PROPERTIES pProperties; ULONG sizeNeeded; LPTSTR pLoggerName; LPTSTR pCurrentLogFileName; LPTSTR pLogFileName; ULONG flags; ULONG level; ULONG status; CString logFileName; CString str;
//
// setup our buffer size for the properties struct
//
sizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) + (2 * 1024 * sizeof(TCHAR));
//
// allocate our memory
//
pProperties = (PEVENT_TRACE_PROPERTIES) new char[sizeNeeded]; if(NULL == pProperties) { return FALSE; }
//
// zero our structures
//
memset(pProperties, 0, sizeNeeded);
//
// Set the size
//
pProperties->Wnode.BufferSize = sizeNeeded;
//
// Set the GUID
//
pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
//
// Set the logger name offset
//
pProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
//
// Set the log file name offset
//
pProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + (500 * sizeof(TCHAR));
//
// Get the log file name pointers
//
pLogFileName = (LPTSTR)((char*)pProperties + pProperties->LogFileNameOffset);
//
// Set the log file name
//
if(m_bWriteLogFile) { //
// See if the logfile name is already specified and hasn't changed
// ControlTrace will fail if you specify the same logfile name as it
// is already using
//
if((NULL == pQueryProperties) || (NULL == _tcsstr((LPTSTR)((char*)pQueryProperties + pQueryProperties->LogFileNameOffset), m_logFileName)) || (NULL == (LPTSTR)((char*)pQueryProperties + pQueryProperties->LogFileNameOffset))) {
_tcscpy(pLogFileName, (LPCTSTR)m_logFileName); } }
//
// Set the real-time setting.
//
if(m_bRealTime) { pProperties->LogFileMode |= EVENT_TRACE_REAL_TIME_MODE; }
//
// Set the max buffers setting.
//
pProperties->MaximumBuffers = ConvertStringToNum(m_logSessionValues[MaximumBuffers]);
//
// Set the enable flags setting.
//
flags = ConvertStringToNum(m_logSessionValues[Flags]);
pProperties->EnableFlags = flags;
//
// Set the flush time setting.
//
pProperties->FlushTimer = ConvertStringToNum(m_logSessionValues[FlushTime]);
//
// Attempt to update the session
//
status = ControlTrace(0, GetDisplayName(), pProperties, EVENT_TRACE_CONTROL_UPDATE);
if(ERROR_BAD_PATHNAME == status) { _tcscpy(pLogFileName,_T(""));
//
// If we get an ERROR_BAD_PATHNAME it means we specified the same
// logfile name as the one we were already using. It seems the
// tool should handle this, but it doesn't, so we just try again
// with a blank logfilename. There is no way to clear a logfile
// name from a session, so this seems to work.
//
status = ControlTrace(0, GetDisplayName(), pProperties, EVENT_TRACE_CONTROL_UPDATE); }
if(ERROR_SUCCESS != status) { CString str; str.Format(_T("Failed To Update Session\nControlTrace failed with status %d"), status); AfxMessageBox(str);
delete [] pProperties;
return FALSE; }
delete [] pProperties;
return TRUE; }
LONG CLogSession::EndTrace() { ULONG ret; PEVENT_TRACE_PROPERTIES pProperties; CString str; ULONG sizeNeeded; LPTSTR pLoggerName; LPTSTR pLogFileName; ULONG exitCode = STILL_ACTIVE; LONG startTime; TRACEHANDLE hSessionHandle = (TRACEHANDLE)INVALID_HANDLE_VALUE; LONG status; CTraceSession *pTraceSession; GUID controlGuid;
//
// If an attempt to stop this session has already been made, just return
//
if(m_bStoppingTrace || !m_bTraceActive) { return TRUE; }
SetState(Stopping);
//
// If dealing with an existing log file we terminate the tracing later
//
if(m_bDisplayExistingLogFileOnly) { return TRUE; }
//
// Get our session handle
//
hSessionHandle = GetSessionHandle();
//
// If the session handle is invalid, we hooked up to
// an already running session, so we can't stop the traces
//
if((TRACEHANDLE)INVALID_HANDLE_VALUE != hSessionHandle) {
//
// Disable the trace(s)
//
for(LONG ii = 0; ii < m_traceSessionArray.GetSize(); ii++) { pTraceSession = (CTraceSession *)m_traceSessionArray[ii]; if(pTraceSession == NULL) { continue; }
//
// Disable all trace providers for this log session
//
for(LONG jj = 0; jj < pTraceSession->m_controlGuid.GetSize(); jj++) { StringToGuid((LPTSTR)(LPCTSTR)pTraceSession->m_controlGuid[jj], &controlGuid);
ret = EnableTrace(FALSE, 0, 0, &controlGuid, hSessionHandle); if (ret != ERROR_SUCCESS) { if(ret == ERROR_INVALID_FUNCTION) { str.Format(_T("Failed To Disable Trace For Control GUID:\n%ls\n\nEnableTrace Returned %d"), pTraceSession->m_controlGuid[jj], ret); } else { str.Format(_T("Failed To Disable Trace For Control GUID:\n%ls\n\nEnableTrace Returned %d\n"), pTraceSession->m_controlGuid[jj], ret); } AfxMessageBox(str); } } }
//
// Calculate the size needed to store the properties,
// a LogFileName string, and LoggerName string.
//
sizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) + (2 * 500 * sizeof(TCHAR));
pProperties = (PEVENT_TRACE_PROPERTIES) new char[sizeNeeded]; if(NULL == pProperties) { AfxMessageBox(_T("Failed To Stop Trace, Out Of Resources")); return ERROR_OUTOFMEMORY; }
//
// zero our structure
//
memset(pProperties, 0, sizeNeeded);
//
// setup the struct
//
pProperties->Wnode.BufferSize = sizeNeeded; pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID; pProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES); pLoggerName = (LPTSTR)((char*)pProperties + pProperties->LoggerNameOffset); _tcscpy(pLoggerName, GetDisplayName()); if(m_bWriteLogFile) { pProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + (500 * sizeof(TCHAR)); pLogFileName = (LPTSTR)((char*)pProperties + pProperties->LogFileNameOffset); _tcscpy(pLogFileName, (LPCTSTR)m_logFileName); }
//
// The WNODE_HEADER is being used.
//
pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
//
// end the trace session
//
ret = ControlTrace(hSessionHandle, (LPCTSTR)GetDisplayName(), pProperties, EVENT_TRACE_CONTROL_STOP); if(ERROR_SUCCESS != ret) { str.Format(_T("Failed To Stop Trace: %d, Session Handle = 0x%X"), ret, hSessionHandle); AfxMessageBox(str); }
delete [] pProperties; }
//
// Set the session state flag
//
m_bSessionActive = FALSE;
//
// reset the session handle
//
SetSessionHandle((TRACEHANDLE)INVALID_HANDLE_VALUE);
return ret; }
|