private List<DynamicTraceEventData> CreateTemplatesForTMFFile(Guid taskGuid, string tmfPath)
        {
            List<DynamicTraceEventData> templates = new List<DynamicTraceEventData>();
            List<Type> parameterTypes = new List<Type>();

            using (StreamReader tmfData = File.OpenText(tmfPath))
            {
                string taskName = null;
                string providerName = null;
                Guid providerGuid = Guid.Empty;
                Match m;
                for (; ; )
                {
                    var line = tmfData.ReadLine();
                    if (line == null)
                        break;

                    if (providerGuid == Guid.Empty)
                    {
                        m = Regex.Match(line, @"PDB: .*?(\w+)\.pdb\s*$", RegexOptions.IgnoreCase);
                        if (m.Success)
                        {
                            // We use the name of the mof file (which is the same as the PDB file) as the provider name.
                           if (string.IsNullOrEmpty(providerName))
                                providerName = m.Groups[1].Value;

                            string mofFilePath;
                            if (m_tmfDataFilePathsByFileNameBase.TryGetValue(providerName, out mofFilePath))
                            {
                                if (mofFilePath.EndsWith(".mof", StringComparison.OrdinalIgnoreCase))
                                {
                                    using (var mofFile = File.OpenText(mofFilePath))
                                    {
                                        for (; ; )
                                        {
                                            var mofLine = mofFile.ReadLine();
                                            if (mofLine == null)
                                                break;
                                            m = Regex.Match(mofLine, @"guid\(.{(.*)}.\)", RegexOptions.IgnoreCase);
                                            if (m.Success)
                                            {
                                                try { providerGuid = new Guid(m.Groups[1].Value); }
                                                catch (Exception) { }
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (taskName == null)
                    {
                        // 7113b9e1-a0cc-d313-1eab-57efe9d7e56c build.server // SRC=TTSEngineCom.cpp MJ= MN=
                        m = Regex.Match(line, @"^\w+-\w+-\w+-\w+-\w+\s+(\S+)");
                        if (m.Success)
                            taskName = m.Groups[1].Value;
                    }
                    else
                    {
                        // #typev  ttstracing_cpp78 13 "%0%10!s! Error happens in Initializing %11!s!!" //   LEVEL=TRACE_LEVEL_ERROR FLAGS=TTS_Trace_Engine_Initialization FUNC=CTTSTracingHelper::LogComponentInitialization
                        m = Regex.Match(line, "^#typev\\s+(\\S*?)(\\d+)\\s+(\\d+)\\s+\"(.*)\"");
                        if (m.Success)
                        {
                            var fileName = m.Groups[1].Value;
                            var lineNum = int.Parse(m.Groups[2].Value);
                            var eventId = int.Parse(m.Groups[3].Value);
                            var formatStr = m.Groups[4].Value;

                            var eventProviderName = taskName;
                            if (providerName != null)
                                eventProviderName = providerName + "/" + eventProviderName;

                            var template = new DynamicTraceEventData(null, eventId, 0, fileName + "/" + m.Groups[2].Value, taskGuid, 0, "", providerGuid, eventProviderName);
                            template.lookupAsWPP = true;                // Use WPP lookup convetions. 
                            formatStr = formatStr.Replace("%0", "");    // TODO What is this?  Why is it here?  
                            formatStr = Regex.Replace(formatStr, @"%(\d+)!.!", delegate(Match match) { return "%" + (int.Parse(match.Groups[1].Value) - 9).ToString(); });
                            template.MessageFormat = formatStr;

                            parameterTypes.Clear();
                            for (; ; )
                            {
                                line = tmfData.ReadLine();
                                if (line == null)
                                    break;
                                if (line.Trim() == "}")
                                    break;
                                // szPOSHeader, ItemString -- 10
                                m = Regex.Match(line, @"^\S+, Item(\w+) -- (\d+)");
                                if (m.Success)
                                {
                                    var typeStr = m.Groups[1].Value;
                                    Type type = null;
                                    if (typeStr == "String")
                                        type = typeof(string);
                                    else if (typeStr == "Long")
                                        type = typeof(int);
                                    else if (typeStr == "Double")
                                        type = typeof(double);

                                    if (type != null)
                                        parameterTypes.Add(type);
                                }
                            }
                            template.payloadNames = new string[parameterTypes.Count];
                            template.payloadFetches = new DynamicTraceEventData.PayloadFetch[parameterTypes.Count];
                            ushort offset = 0;
                            for (int i = 0; i < parameterTypes.Count; i++)
                            {
                                template.payloadNames[i] = "Arg" + (i + 1).ToString();
                                template.payloadFetches[i].type = parameterTypes[i];
                                template.payloadFetches[i].offset = offset;
                                var size = DynamicTraceEventData.SizeOfType(parameterTypes[i]);
                                if (template.payloadFetches[i].type == typeof(string))
                                    size |= DynamicTraceEventData.IS_ANSI;
                                template.payloadFetches[i].size = size;
                                if (size >= DynamicTraceEventData.SPECIAL_SIZES)
                                    offset = ushort.MaxValue;           // Indicate that the offset must be computed at run time.
                                else
                                    offset += size;
                            }
                            templates.Add(template);
                        }
                    }
                }
            }
            return templates;
        }
        internal void AddProviderEvents(ITraceParserServices source, Action<TraceEvent> callback)
        {
            if (Error != null)
                return;
            if (!inited)
                Init();
            try
            {
                Dictionary<string, int> opcodes = new Dictionary<string, int>();
                opcodes.Add("win:Info", 0);
                opcodes.Add("win:Start", 1);
                opcodes.Add("win:Stop", 2);
                opcodes.Add("win:DC_Start", 3);
                opcodes.Add("win:DC_Stop", 4);
                opcodes.Add("win:Extension", 5);
                opcodes.Add("win:Reply", 6);
                opcodes.Add("win:Resume", 7);
                opcodes.Add("win:Suspend", 8);
                opcodes.Add("win:Send", 9);
                opcodes.Add("win:Receive", 240);
                Dictionary<string, TaskInfo> tasks = new Dictionary<string, TaskInfo>();
                Dictionary<string, TemplateInfo> templates = new Dictionary<string, TemplateInfo>();
                Dictionary<string, IDictionary<long, string>> maps = null;
                Dictionary<string, string> strings = new Dictionary<string, string>();
                IDictionary<long, string> map = null;
                List<EventInfo> events = new List<EventInfo>();
                bool alreadyReadMyCulture = false;            // I read my culture some time in the past (I can igore things)
                string cultureBeingRead = null;
                while (reader.Read())
                {
                    // TODO I currently require opcodes,and tasks BEFORE events BEFORE templates.  
                    // Can be fixed by going multi-pass. 
                    switch (reader.Name)
                    {
                        case "event":
                            {
                                int taskNum = 0;
                                Guid taskGuid = Guid;
                                string taskName = reader.GetAttribute("task");
                                if (taskName != null)
                                {
                                    TaskInfo taskInfo;
                                    if (tasks.TryGetValue(taskName, out taskInfo))
                                    {
                                        taskNum = taskInfo.id;
                                        taskGuid = taskInfo.guid;
                                    }
                                }
                                else
                                    taskName = "";

                                int eventID = int.Parse(reader.GetAttribute("value"));
                                int opcode = 0;
                                string opcodeName = reader.GetAttribute("opcode");
                                if (opcodeName != null)
                                {
                                    opcodes.TryGetValue(opcodeName, out opcode);
                                    // Strip off any namespace prefix.  TODO is this a good idea?
                                    int colon = opcodeName.IndexOf(':');
                                    if (colon >= 0)
                                        opcodeName = opcodeName.Substring(colon + 1);
                                }
                                else
                                {
                                    opcodeName = "";
                                    // opcodeName = "UnknownEvent" + eventID.ToString();
                                }

                                DynamicTraceEventData eventTemplate = new DynamicTraceEventData(
                                callback, eventID, taskNum, taskName, taskGuid, opcode, opcodeName, Guid, Name);
                                events.Add(new EventInfo(eventTemplate, reader.GetAttribute("template")));

                                // This will be looked up in the string table in a second pass.  
                                eventTemplate.MessageFormat = reader.GetAttribute("message");
                            } break;
                        case "template":
                            {
                                string templateName = reader.GetAttribute("tid");
                                Debug.Assert(templateName != null);
#if DEBUG
                                try
                                {
#endif
                                    templates.Add(templateName, ComputeFieldInfo(reader.ReadSubtree(), maps));
#if DEBUG
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine("Error: Exception during processing template {0}: {1}", templateName, e.ToString());
                                    throw;
                                }
#endif
                            } break;
                        case "opcode":
                            // TODO use message for opcode if it is available so it is localized.  
                            opcodes.Add(reader.GetAttribute("name"), int.Parse(reader.GetAttribute("value")));
                            break;
                        case "task":
                            {
                                TaskInfo info = new TaskInfo();
                                info.id = int.Parse(reader.GetAttribute("value"));
                                string guidString = reader.GetAttribute("eventGUID");
                                if (guidString != null)
                                    info.guid = new Guid(guidString);
                                tasks.Add(reader.GetAttribute("name"), info);
                            } break;
                        case "valueMap":
                            map = new Dictionary<long, string>();    // value maps use dictionaries
                            goto DoMap;
                        case "bitMap":
                            map = new SortedList<long, string>();    // Bitmaps stored as sorted lists
                            goto DoMap;
                        DoMap:
                            string name = reader.GetAttribute("name");
                            var mapValues = reader.ReadSubtree();
                            while (mapValues.Read())
                            {
                                if (mapValues.Name == "map")
                                {
                                    string keyStr = reader.GetAttribute("value");
                                    long key;
                                    if (keyStr.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                                        key = long.Parse(keyStr.Substring(2), System.Globalization.NumberStyles.AllowHexSpecifier);
                                    else
                                        key = long.Parse(keyStr);
                                    string value = reader.GetAttribute("message");
                                    map[key] = value;
                                }
                            }
                            if (maps == null)
                                maps = new Dictionary<string, IDictionary<long, string>>();
                            maps[name] = map;
                            break;
                        case "resources":
                            {
                                if (!alreadyReadMyCulture)
                                {
                                    string desiredCulture = System.Globalization.CultureInfo.CurrentCulture.Name;
                                    if (cultureBeingRead != null && string.Compare(cultureBeingRead, desiredCulture, StringComparison.OrdinalIgnoreCase) == 0)
                                        alreadyReadMyCulture = true;
                                    cultureBeingRead = reader.GetAttribute("culture");
                                }
                            } break;
                        case "string":
                            if (!alreadyReadMyCulture)
                                strings[reader.GetAttribute("id")] = reader.GetAttribute("value");
                            break;
                    }
                }

                // localize strings for maps.
                if (maps != null)
                {
                    foreach (IDictionary<long, string> amap in maps.Values)
                    {
                        foreach (var keyValue in new List<KeyValuePair<long, string>>(amap))
                        {
                            Match m = Regex.Match(keyValue.Value, @"^\$\(string\.(.*)\)$");
                            if (m.Success)
                            {
                                string newValue;
                                if (strings.TryGetValue(m.Groups[1].Value, out newValue))
                                    amap[keyValue.Key] = newValue;
                            }
                        }
                    }
                }

                // Register all the events
                foreach (var eventInfo in events)
                {
                    var event_ = eventInfo.eventTemplate;
                    // Set the template if there is any. 
                    if (eventInfo.templateName != null)
                    {
                        var templateInfo = templates[eventInfo.templateName];
                        event_.payloadNames = templateInfo.payloadNames.ToArray();
                        event_.payloadFetches = templateInfo.payloadFetches.ToArray();
                    }
                    else
                    {
                        event_.payloadNames = new string[0];
                        event_.payloadFetches = new DynamicTraceEventData.PayloadFetch[0];
                    }

                    // before registering, localize any message format strings.  
                    string message = event_.MessageFormat;
                    if (message != null)
                    {
                        // Expect $(STRINGNAME) where STRINGNAME needs to be looked up in the string table
                        // TODO currently we just ignore messages without a valid string name.  Is that OK?
                        event_.MessageFormat = null;
                        Match m = Regex.Match(message, @"^\$\(string\.(.*)\)$");
                        if (m.Success)
                            strings.TryGetValue(m.Groups[1].Value, out event_.MessageFormat);
                    }

                    //SLAB update try/catch section
                    try
                    {
                        source.RegisterEventTemplate(event_);
                    }
                    catch (NullReferenceException e)
                    {
                        // This error may be thrown when disposing source. 
                        Error = e;
                        inited = false;     // If we call it again, start over from the begining.  
                        return;
                    }
                }

                //SLAB comment:
                // The below code was commented out to allow receiving manifest updates.  
                // Note that this registration will set the manifest event as handled and will always send
                // the initial manifest (no updates) so this behavior will be useless for manifest caching scenarios
                // where stale manifest should be avoided by receiving new updates.
                // To recap, avoiding manifest event registration will force to get unhandled events on each new manifest event.

                //// Create an event for the manifest event itself so it looks pretty in dumps.  
                //source.RegisterEventTemplate(new DynamicManifestTraceEventData(callback, this));
            }
            catch (Exception e)
            {
                // TODO FIX NOW, log this!
                Debug.Assert(false, "Exception during manifest parsing");
#if DEBUG
                Console.WriteLine("Error: Exception during processing of in-log manifest for provider {0}.  Symbolic information may not be complete.", Name);
#endif
                Error = e;
            }

            inited = false;     // If we call it again, start over from the begining.  
        }
 public EventInfo(DynamicTraceEventData eventTemplate, string templateName)
 {
     this.eventTemplate = eventTemplate;
     this.templateName = templateName;
 }
        protected override DynamicTraceEventData TryLookup(TraceEvent unknownEvent)
        {
            DynamicTraceEventData ret = null;
            // TODO react if 4K is not big enough, cache the buffer?, handle more types, handle structs...
            int buffSize = 4096;
            byte* buffer = (byte*)System.Runtime.InteropServices.Marshal.AllocHGlobal(buffSize);
            int status = TdhGetEventInformation(unknownEvent.eventRecord, 0, null, buffer, &buffSize);
            if (status == 0)
            {
                TRACE_EVENT_INFO* eventInfo = (TRACE_EVENT_INFO*)buffer;
                EVENT_PROPERTY_INFO* propertyInfos = &eventInfo->EventPropertyInfoArray;

                string taskName = null;
                if (eventInfo->TaskNameOffset != 0)
                    taskName = (new string((char*)(&buffer[eventInfo->TaskNameOffset]))).Trim();

                string opcodeName = null;
                if (eventInfo->OpcodeNameOffset != 0)
                {
                    opcodeName = (new string((char*)(&buffer[eventInfo->OpcodeNameOffset]))).Trim();
                    if (opcodeName.StartsWith("win:"))
                        opcodeName = opcodeName.Substring(4);
                }

                string providerName = "UnknownProvider";
                if (eventInfo->ProviderNameOffset != 0)
                    providerName = new string((char*)(&buffer[eventInfo->ProviderNameOffset]));

                var eventID = unknownEvent.ClassicProvider ? TraceEventID.Illegal : unknownEvent.eventID;
                var newTemplate = new DynamicTraceEventData(null, (int)eventID, (int)unknownEvent.task, taskName,
                    unknownEvent.taskGuid, (int)unknownEvent.Opcode, opcodeName, unknownEvent.ProviderGuid, providerName);

                newTemplate.payloadNames = new string[eventInfo->TopLevelPropertyCount];
                newTemplate.payloadFetches = new DynamicTraceEventData.PayloadFetch[eventInfo->TopLevelPropertyCount];
                ushort offset = 0;
                for (int i = 0; i < eventInfo->TopLevelPropertyCount; i++)
                {
                    var propertyInfo = &propertyInfos[i];
                    var propertyName = new string((char*)(&buffer[propertyInfo->NameOffset]));
                    // Remove anything that does not look like an ID (.e.g space)
                    newTemplate.payloadNames[i] = Regex.Replace(propertyName, "[^A-Za-z0-9_]", "");
                    newTemplate.payloadFetches[i].type = GetTypeForTdhInType(propertyInfo->InType);

                    // Determine whether the size variable or not, and set 'size' based on that. 
                    ushort size = DynamicTraceEventData.UNKNOWN_SIZE;
                    // is this dynamically sized with another field specifying the length?
                    if ((propertyInfo->Flags & PROPERTY_FLAGS.ParamLength) != 0)
                    {
                        if (propertyInfo->LengthOrLengthIndex == i - 1)
                        {
                            if (propertyInfos[i - 1].LengthOrLengthIndex == 4)
                                size = DynamicTraceEventData.COUNT32_PRECEEDS;
                            else if (propertyInfos[i - 1].LengthOrLengthIndex == 2)
                                size = DynamicTraceEventData.COUNT16_PRECEEDS;
                            else
                                Trace.WriteLine("WARNING: Unexpected dynamic length, giving up");
                        }

                        if (size != DynamicTraceEventData.UNKNOWN_SIZE && propertyInfo->InType == TdhInputType.AnsiString)
                            size |= DynamicTraceEventData.IS_ANSI;
                    }
                    else
                    {
                        if (propertyInfo->InType == TdhInputType.AnsiString)
                            size = DynamicTraceEventData.NULL_TERMINATED | DynamicTraceEventData.IS_ANSI;
                        else if (propertyInfo->InType == TdhInputType.UnicodeString)
                            size = DynamicTraceEventData.NULL_TERMINATED;
                        else if (propertyInfo->InType == TdhInputType.Pointer)
                            size = DynamicTraceEventData.POINTER_SIZE;
                        else
                        {
                            // No, then it it fixed size (but give up if it is too big)  
                            var fixedSize = propertyInfo->CountOrCountIndex * propertyInfo->LengthOrLengthIndex;
                            if (fixedSize < 0x7FF0)
                            {
                                size = (ushort)fixedSize;
                                if (propertyInfo->InType == TdhInputType.AnsiString)
                                    size += 0x8000;
                            }
                        }
                    }

                    // Currently we give up on any other flags (arrays, structs). 
                    if ((propertyInfo->Flags & ~PROPERTY_FLAGS.ParamLength) != 0)
                        size = DynamicTraceEventData.UNKNOWN_SIZE;

                    newTemplate.payloadFetches[i].size = (ushort)size;
                    newTemplate.payloadFetches[i].offset = offset;
                    if (size >= DynamicTraceEventData.SPECIAL_SIZES)
                        offset = ushort.MaxValue;           // Indicate that the offset must be computed at run time. 
                    else if (offset != ushort.MaxValue)
                    {
                        Debug.Assert(offset + size < ushort.MaxValue);
                        offset += size;
                    }
                }
                ret = newTemplate;      // return this as the event template for this lookup. 
            }

            System.Runtime.InteropServices.Marshal.FreeHGlobal((IntPtr)buffer);
            return ret;
        }