/// <summary> /// Initializes some of the fields of the NativeMethods.EVENT_TRACE_PROPERTIES structure /// with values that are common to all the ETW methods used in this class. /// </summary> /// <returns>The initialized NativeMethods.EVENT_TRACE_PROPERTIES structure.</returns> private NativeMethods.EventTraceProperties CommonEventTraceProperties() { var properties = new NativeMethods.EventTraceProperties(); properties.WNode.BufferSize = NativeMethods.EventTracePropertiesStructSize + (NativeMethods.EventTracePropertiesStringSize * 2); properties.WNode.Guid = _guid; properties.LoggerNameOffset = NativeMethods.EventTracePropertiesStructSize; properties.LogFileNameOffset = 0; properties.FlushTimer = 0; properties.BufferSize = CDFMonitor.Instance.Config.AppSettings.BufferSize != 0 ? (uint)CDFMonitor.Instance.Config.AppSettings.BufferSize : 10; properties.MinimumBuffers = CDFMonitor.Instance.Config.AppSettings.BufferMin != 0 ? (uint)CDFMonitor.Instance.Config.AppSettings.BufferMin : 40; properties.MaximumBuffers = CDFMonitor.Instance.Config.AppSettings.BufferMax != 0 ? (uint)CDFMonitor.Instance.Config.AppSettings.BufferMax : 80; properties.EnableFlags = 0; if (_isKernelController) { // http: //msdn.microsoft.com/en-us/library/windows/desktop/aa364085(v=vs.85).aspx properties.WNode.Guid = new NativeMethods.publicGuid(new Guid("9e814aad-3204-11d2-9a82-006008a86939").ToByteArray()); properties.EnableFlags = CDFMonitor.Instance.Config.IsKernelTraceConfigured() ? (uint)CDFMonitor.Instance.Config.AppSettings.EnableFlags : 0; } return(properties); }
/// <summary> /// Flush the ETW session. /// </summary> /// <exception cref="System.ComponentModel.Win32Exception"></exception> public void FlushTrace() { Debug.Assert(0 != _handle && NativeMethods.IsValidHandle(_handle), "0 != _handle && NativeMethods.IsValidHandle(_handle)"); NativeMethods.EventTraceProperties properties = CommonEventTraceProperties(); CDFMonitor.LogOutputHandler("DEBUG:FlushTrace:Flushing trace"); uint processResult = NativeMethods.FlushTrace(_handle, _sessionName, ref properties); if (processResult != NativeMethods.ERROR_SUCCESS && processResult != NativeMethods.ERROR_CANCELLED) { throw new Win32Exception((int)processResult); } }
/// <summary> /// Start the ETW session. /// </summary> /// <param name="logFileMode">The log file mode.</param> /// <param name="logFileMaxSize">Size of the log file max.</param> /// <param name="logFileName">Name of the log file.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> public bool StartTrace(NativeMethods.EventTraceFileMode logFileMode = NativeMethods.EventTraceFileMode.RealTime, uint logFileMaxSize = 0, string logFileName = null) { Debug.Assert(_handle == 0, "_handle == 0"); NativeMethods.EventTraceProperties properties = CommonEventTraceProperties(); properties.WNode.Flags = NativeMethods.WNodeFlags.TracedGuid; properties.WNode.ClientContext = 1; properties.LogFileMode = logFileMode; properties.FlushTimer = 1; if (logFileMode != NativeMethods.EventTraceFileMode.RealTime) { properties.MaximumFileSize = logFileMaxSize; //32 bit different uint offset = 4; if (IntPtr.Size == 8) //64 bit { offset = 0; } properties.LogFileNameOffset = NativeMethods.EventTracePropertiesStructSize + (NativeMethods.EventTracePropertiesStringSize) - offset; properties.LogFileName = logFileName; properties.FlushTimer = 0; } CDFMonitor.LogOutputHandler("DEBUG:ETWController.StartTrace:starting trace."); uint processResult = NativeMethods.StartTrace(out _handle, _sessionName, ref properties); int lastError = Marshal.GetLastWin32Error(); if (!NativeMethods.IsValidHandle(_handle)) { CDFMonitor.LogOutputHandler("DEBUG:StartTrace: exception. lastError:" + lastError.ToString()); return(false); } if (processResult != NativeMethods.ERROR_SUCCESS && processResult != NativeMethods.ERROR_CANCELLED && processResult != NativeMethods.ERROR_ALREADY_EXISTS) { CDFMonitor.LogOutputHandler("StartTrace: exception. process result:" + processResult.ToString()); return(false); } return(true); }
/// <summary> /// Queries the trace. /// </summary> /// <param name="handle">The handle.</param> /// <param name="sessionName">Name of the session.</param> /// <returns>true if trace exists, otherwise false</returns> private bool QueryTrace(ulong handle, string sessionName) { Debug.Assert(!String.IsNullOrEmpty(sessionName) || handle != 0, "!String.IsNullOrEmpty(sessionName) || handle != 0"); NativeMethods.EventTraceProperties properties = CommonEventTraceProperties(); CDFMonitor.LogOutputHandler("DEBUG:QueryTrace: querying trace"); uint processResult = NativeMethods.QueryTrace(handle, sessionName, ref properties); if (processResult == NativeMethods.ERROR_WMI_INSTANCE_NOT_FOUND) { CDFMonitor.LogOutputHandler("DEBUG:QueryTrace: trace does not exist:" + sessionName); return(false); } MissedControllerEvents = properties.EventsLost; CDFMonitor.LogOutputHandler("DEBUG:QueryTrace: trace exists:" + sessionName); return(true); }
/// <summary> /// Stop the named ETW session (if it exists). /// </summary> /// <param name="handle">Handle to the ETW session</param> /// <param name="sessionName">Name of the ETW session</param> /// <exception cref="System.ComponentModel.Win32Exception"></exception> /// <remarks> /// The session should be specified by either the handle or the session name. /// </remarks> private void StopTrace(ulong handle, string sessionName) { Debug.Assert(!String.IsNullOrEmpty(sessionName) || handle != 0, "!String.IsNullOrEmpty(sessionName) || handle != 0"); Running = false; if (!QueryTrace(handle, sessionName)) { return; } NativeMethods.EventTraceProperties properties = CommonEventTraceProperties(); CDFMonitor.LogOutputHandler("DEBUG:ETWController.StopTrace:stopping trace:" + sessionName); uint processResult = NativeMethods.StopTrace(handle, sessionName, ref properties); if (processResult != NativeMethods.ERROR_SUCCESS && processResult != NativeMethods.ERROR_CANCELLED && processResult != NativeMethods.ERROR_WMI_INSTANCE_NOT_FOUND) { throw new Win32Exception((int)processResult); } }
/// <summary> /// Enable/Disable the ETW session. /// </summary> /// <param name="enable">Indicates if the session should be enabled or disabled</param> /// <param name="strguid">The strguid.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> public bool EnableTrace(bool enable, string strguid) { Debug.Assert(!_isKernelController, "!_isKernelController"); NativeMethods.publicGuid guid = new NativeMethods.publicGuid(); try { CDFMonitor.LogOutputHandler(string.Format("DEBUG:EnableTrace:enabling trace:strguid:{0}", strguid)); guid = new NativeMethods.publicGuid(new Guid(strguid).ToByteArray()); Debug.Assert(_handle != 0 && NativeMethods.IsValidHandle(_handle), "_handle != 0 && NativeMethods.IsValidHandle(_handle)"); NativeMethods.EventTraceProperties properties = CommonEventTraceProperties(); if (properties.EnableFlags != 0) { CDFMonitor.LogOutputHandler(string.Format("EnableTrace:KernelFlags configured/enabled. overriding EnableFlags and modules. returning:{0}", strguid)); return(true); } uint flags = 0xffffffff; uint processResult = NativeMethods.EnableTrace(enable ? 1U : 0U, flags /* enableFlag */, (uint)CDFMonitor.Instance.Config.AppSettings.LogLevel /* enableLevel */, ref guid, _handle); if (processResult != NativeMethods.ERROR_SUCCESS && processResult != NativeMethods.ERROR_CANCELLED) { CDFMonitor.LogOutputHandler("DEBUG:EnableTrace:enabling trace error:" + processResult.ToString()); return(false); } return(true); } catch (Exception e) { CDFMonitor.LogOutputHandler(string.Format("EnableTrace: exception enabling trace error:{0} guid:{1}", e, guid.ToString())); return(false); } }