/// <summary> /// Do intialization common to the contructors. /// </summary> private bool EnableProvider(Guid providerGuid, TraceEventLevel providerLevel, ulong matchAnyKeywords, ulong matchAllKeywords, TraceEventOptions options, int providerDataType, byte[] providerData, int providerDataSize) { if (m_SessionName == KernelTraceEventParser.KernelSessionName) throw new NotSupportedException("Can only enable kernel events on a kernel session."); bool ret = InsureStarted(); TraceEventNativeMethods.EVENT_FILTER_DESCRIPTOR* dataDescrPtr = null; fixed (byte* providerDataPtr = providerData) { string regKeyName = @"Software\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + providerGuid + "}"; byte[] registryData = null; // If this is an update operation, remember the data in registry so that even providers // that have not yet started will get the data. We don't do this for any other kind of command (providerDataType) // since we don't know that they are desired 'on startup'. if (providerData != null && providerDataType == 0) { TraceEventNativeMethods.EVENT_FILTER_DESCRIPTOR dataDescr = new TraceEventNativeMethods.EVENT_FILTER_DESCRIPTOR(); dataDescr.Ptr = null; dataDescr.Size = providerDataSize; dataDescr.Type = providerDataType; dataDescrPtr = &dataDescr; if (providerData == null) providerData = new byte[0]; else dataDescr.Ptr = providerDataPtr; // Set the registry key so providers get the information even if they are not active now registryData = new byte[providerDataSize + 4]; // providerDataType is always zero, but older versions assume it is here, so we put the redundant value here for compatibility. registryData[0] = (byte)(providerDataType); registryData[1] = (byte)(providerDataType >> 8); registryData[2] = (byte)(providerDataType >> 16); registryData[3] = (byte)(providerDataType >> 24); Array.Copy(providerData, 0, registryData, 4, providerDataSize); } SetOrDelete(regKeyName, "ControllerData", registryData); int hr; try { try { // Try the Win7 API TraceEventNativeMethods.ENABLE_TRACE_PARAMETERS parameters = new TraceEventNativeMethods.ENABLE_TRACE_PARAMETERS(); parameters.Version = TraceEventNativeMethods.ENABLE_TRACE_PARAMETERS_VERSION; if ((options & TraceEventOptions.Stacks) != 0) parameters.EnableProperty = TraceEventNativeMethods.EVENT_ENABLE_PROPERTY_STACK_TRACE; parameters.EnableFilterDesc = dataDescrPtr; hr = TraceEventNativeMethods.EnableTraceEx2(m_SessionHandle, ref providerGuid, TraceEventNativeMethods.EVENT_CONTROL_CODE_ENABLE_PROVIDER, (byte)providerLevel, matchAnyKeywords, matchAllKeywords, 0, ref parameters); } catch (EntryPointNotFoundException) { // OK that did not work, try the VISTA API hr = TraceEventNativeMethods.EnableTraceEx(ref providerGuid, null, m_SessionHandle, 1, (byte)providerLevel, matchAnyKeywords, matchAllKeywords, 0, dataDescrPtr); } } catch (EntryPointNotFoundException) { // Try with the old pre-vista API hr = TraceEventNativeMethods.EnableTrace(1, (int)matchAnyKeywords, (int)providerLevel, ref providerGuid, m_SessionHandle); } Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRFromWin32(hr)); } m_IsActive = true; return ret; }
public void ProviderEnableParameters(string providerName, Guid providerGuid, TraceEventLevel level, ulong keywords, TraceEventOptions options) { WriteEvent(14, providerName, providerGuid, (int)level, keywords, (int)options); }
/// <summary> /// Add an additional USER MODE provider prepresented by 'providerGuid' (a list of /// providers is available by using 'logman query providers'). /// </summary> /// <param name="providerGuid"> /// The GUID that represents the event provider to turn on. Use 'logman query providers' or /// for a list of possible providers. Note that additional user mode (but not kernel mode) /// providers can be added to the session by using EnableProvider.</param> /// <param name="providerLevel">The verbosity to turn on</param> /// <param name="matchAnyKeywords">A bitvector representing the areas to turn on. Only the /// low 32 bits are used by classic providers and passed as the 'flags' value. Zero /// is a special value which is a provider defined default, which is usuall 'everything'</param> /// <param name="matchAllKeywords">A bitvector representing keywords of an event that must /// be on for a particular event for the event to be logged. A value of zero means /// that no keyword must be on, which effectively ignores this value. </param> /// <param name="options">Additional options for the provider (e.g. taking a stack trace)</param> /// <param name="values">This is set of key-value strings that are passed to the provider /// for provider-specific interpretation. Can be null if no additional args are needed. /// If the special key-value pair 'Command'='SendManifest' is provided, then the 'SendManifest' /// command will be sent (which causes EventSources to redump their manifest to the ETW log. </param> /// <returns>true if the session already existed and needed to be restarted.</returns> public bool EnableProvider(Guid providerGuid, TraceEventLevel providerLevel = TraceEventLevel.Verbose, ulong matchAnyKeywords = ulong.MaxValue, ulong matchAllKeywords = 0, TraceEventOptions options = 0, IEnumerable<KeyValuePair<string, string>> values = null) { byte[] valueData = null; int valueDataSize = 0; int valueDataType = 0; if (values != null) { valueDataType = 0; // ControllerCommand.Update // TODO use enumeration valueData = new byte[1024]; foreach (KeyValuePair<string, string> keyValue in values) { if (keyValue.Key == "Command") { if (keyValue.Value == "SendManifest") valueDataType = -1; // ControllerCommand.SendManifest else { int val; if (int.TryParse(keyValue.Value, out val)) valueDataType = val; } } valueDataSize += Encoding.UTF8.GetBytes(keyValue.Key, 0, keyValue.Key.Length, valueData, valueDataSize); if (valueDataSize >= 1023) throw new Exception("Too much provider data"); // TODO better message. valueData[valueDataSize++] = 0; valueDataSize += Encoding.UTF8.GetBytes(keyValue.Value, 0, keyValue.Value.Length, valueData, valueDataSize); if (valueDataSize >= 1023) throw new Exception("Too much provider data"); // TODO better message. valueData[valueDataSize++] = 0; } } return EnableProvider(providerGuid, providerLevel, matchAnyKeywords, matchAllKeywords, options, valueDataType, valueData, valueDataSize); }