diff --git a/src/TraceEvent/ETWTraceEventSource.cs b/src/TraceEvent/ETWTraceEventSource.cs
index 5fa723796..b6e2b3ed9 100644
--- a/src/TraceEvent/ETWTraceEventSource.cs
+++ b/src/TraceEvent/ETWTraceEventSource.cs
@@ -151,7 +151,7 @@ public override bool Process()
///
/// Reprocess a pre-constructed event which this processor has presumably created. Helpful to re-examine
/// "unknown" events, perhaps after a manifest has been received from the ETW stream.
- /// Note when queuing events to reprocess you must Clone them first
+ /// Note when queuing events to reprocess you must Clone them first
/// or certain internal data may no longer be available and you may receive memory access violations.
///
/// Event to re-process.
diff --git a/src/TraceEvent/RegisteredTraceEventParser.cs b/src/TraceEvent/RegisteredTraceEventParser.cs
index 62665b62a..5b947fb2d 100644
--- a/src/TraceEvent/RegisteredTraceEventParser.cs
+++ b/src/TraceEvent/RegisteredTraceEventParser.cs
@@ -621,6 +621,12 @@ internal override DynamicTraceEventData TryLookup(TraceEvent unknownEvent)
///
internal static DynamicTraceEventData TryLookupWorker(TraceEvent unknownEvent, Dictionary> mapTable = null)
{
+ // We are not able to handle WPP events in this parser.
+ if (unknownEvent.lookupAsWPP)
+ {
+ return null;
+ }
+
// Is this a TraceLogging style
DynamicTraceEventData ret = null;
@@ -1192,7 +1198,7 @@ protected unsafe ExternalTraceEventParser(TraceEventSource source, bool dontRegi
parsedTemplate = TryLookup(unknown);
if (parsedTemplate == null)
{
- m_state.m_templates.Add(unknown.Clone(), null); // add an entry to remember that we tried and failed.
+ m_state.m_templates.Add(unknown.Clone(true), null); // add an entry to remember that we tried and failed.
}
}
if (parsedTemplate == null)
@@ -1369,7 +1375,6 @@ internal class TraceEventComparer : IEqualityComparer
{
public bool Equals(TraceEvent x, TraceEvent y)
{
- Debug.Assert(!(x.lookupAsWPP && x.lookupAsClassic));
if (x.lookupAsClassic != y.lookupAsClassic)
{
return false;
@@ -1380,15 +1385,15 @@ public bool Equals(TraceEvent x, TraceEvent y)
return false;
}
- if (x.lookupAsClassic)
+ if (x.lookupAsWPP)
{
Debug.Assert(x.taskGuid != Guid.Empty && y.taskGuid != Guid.Empty);
- return (x.taskGuid == y.taskGuid) && (x.Opcode == y.Opcode);
+ return (x.taskGuid == y.taskGuid) && (x.ID == y.ID);
}
- else if (x.lookupAsWPP)
+ else if (x.lookupAsClassic)
{
Debug.Assert(x.taskGuid != Guid.Empty && y.taskGuid != Guid.Empty);
- return (x.taskGuid == y.taskGuid) && (x.ID == y.ID);
+ return (x.taskGuid == y.taskGuid) && (x.Opcode == y.Opcode);
}
else
{
diff --git a/src/TraceEvent/TraceEvent.cs b/src/TraceEvent/TraceEvent.cs
index 24dbbf480..32d85428e 100644
--- a/src/TraceEvent/TraceEvent.cs
+++ b/src/TraceEvent/TraceEvent.cs
@@ -977,6 +977,14 @@ public bool IsClassicProvider
// [SecuritySafeCritical]
get { return (eventRecord->EventHeader.Flags & TraceEventNativeMethods.EVENT_HEADER_FLAG_CLASSIC_HEADER) != 0; }
}
+ ///
+ /// Returns true if this event is from the TraceMessage function (typically indicates from a WPP provider)
+ ///
+ public bool IsTraceMessage
+ {
+ // [SecuritySafeCritical]
+ get { return (eventRecord->EventHeader.Flags & TraceEventNativeMethods.EVENT_HEADER_FLAG_TRACE_MESSAGE) != 0; }
+ }
///
/// The ID of the container that emitted the event, if available.
@@ -1341,10 +1349,30 @@ public byte[] EventData(byte[] targetBuffer, int targetStartIndex, int sourceSta
/// This method is more expensive than copy out all the event data from the TraceEvent instance
/// to a type of your construction.
///
- public virtual unsafe TraceEvent Clone()
+ public virtual TraceEvent Clone()
{
- TraceEvent ret = (TraceEvent)MemberwiseClone(); // Clone myself.
- ret.next = null; // the clone is not in any linked list.
+ return Clone(false);
+ }
+
+ internal unsafe TraceEvent Clone(bool toTemplate)
+ {
+ TraceEvent ret = (TraceEvent)MemberwiseClone(); // Clone myself.
+ ret.next = null; // the clone is not in any linked list.
+
+ if (toTemplate)
+ {
+ // We are cloning to a template, so we don't need to clone the data.
+ ret.eventRecord = null;
+ ret.myBuffer = IntPtr.Zero;
+ ret.instanceContainerID = null;
+
+ // Also zero out the dispatch-related fields.
+ ret.traceEventSource = null;
+ ret.Target = null;
+
+ return ret;
+ }
+
if (eventRecord != null)
{
int userDataLength = (EventDataLength + 3) / 4 * 4; // DWORD align
@@ -2013,15 +2041,6 @@ internal int ThreadIDforStacks()
///
protected internal virtual void SetState(object state) { }
- protected internal TraceEvent CloneToTemplate()
- {
- TraceEvent ret = Clone();
- ret.traceEventSource = null;
- ret.eventRecord = null;
- ret.Target = null;
- return ret;
- }
-
#endregion
#region Private
private static char HexDigit(int digit)
@@ -3663,6 +3682,7 @@ internal TraceEvent Lookup(TraceEventNativeMethods.EVENT_RECORD* eventRecord)
#if DEBUG // ASSERT we found the event using the mechanism we expected to use.
Debug.Assert(((eventRecord->EventHeader.Flags & TraceEventNativeMethods.EVENT_HEADER_FLAG_CLASSIC_HEADER) != 0) == curTemplate.lookupAsClassic);
+ Debug.Assert(((eventRecord->EventHeader.Flags & TraceEventNativeMethods.EVENT_HEADER_FLAG_TRACE_MESSAGE) != 0) == curTemplate.lookupAsWPP);
if (curTemplate.lookupAsClassic)
{
Debug.Assert(curTemplate.taskGuid == eventRecord->EventHeader.ProviderId);
@@ -3710,6 +3730,7 @@ internal TraceEvent Lookup(TraceEventNativeMethods.EVENT_RECORD* eventRecord)
unhandledEventTemplate.userData = eventRecord->UserData;
unhandledEventTemplate.eventIndex = currentID;
unhandledEventTemplate.lookupAsClassic = unhandledEventTemplate.IsClassicProvider;
+ unhandledEventTemplate.lookupAsWPP = unhandledEventTemplate.IsTraceMessage;
if ((((int)currentID) & 0xFFFF) == 0) // Every 64K events allow Thread.Interrupt.
{
System.Threading.Thread.Sleep(0);
diff --git a/src/TraceEvent/TraceEventNativeMethods.cs b/src/TraceEvent/TraceEventNativeMethods.cs
index 2cf5af012..314255a79 100644
--- a/src/TraceEvent/TraceEventNativeMethods.cs
+++ b/src/TraceEvent/TraceEventNativeMethods.cs
@@ -399,6 +399,7 @@ internal static extern int TraceQueryInformation(
*/
internal const ushort EVENT_HEADER_FLAG_STRING_ONLY = 0x0004;
+ internal const ushort EVENT_HEADER_FLAG_TRACE_MESSAGE = 0x0008;
internal const ushort EVENT_HEADER_FLAG_NO_CPUTIME = 0x0010;
internal const ushort EVENT_HEADER_FLAG_32_BIT_HEADER = 0x0020;
internal const ushort EVENT_HEADER_FLAG_64_BIT_HEADER = 0x0040;
diff --git a/src/TraceEvent/TraceLog.cs b/src/TraceEvent/TraceLog.cs
index 9ee3f6212..55abfe8c5 100644
--- a/src/TraceEvent/TraceLog.cs
+++ b/src/TraceEvent/TraceLog.cs
@@ -783,7 +783,7 @@ private unsafe TraceLog(TraceEventDispatcher source)
}
if (toSend.containsSelfDescribingMetadata)
{
- var template = toSend.CloneToTemplate();
+ var template = toSend.Clone(true);
realTimeSource.Dynamic.OnNewEventDefintion(template, true);
return true;
}