|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using Microsoft.Win32;
namespace System.Diagnostics.Eventing.Reader
{
/// <summary>
/// Exposes all the metadata for a specific event Provider. An instance
/// of this class is obtained from EventLogManagement and is scoped to a
/// single Locale.
/// </summary>
public class ProviderMetadata : IDisposable
{
//
// access to the data member reference is safe, while
// invoking methods on it is marked SecurityCritical as appropriate.
//
private readonly EventLogHandle _handle = EventLogHandle.Zero;
private EventLogHandle _defaultProviderHandle = EventLogHandle.Zero;
private readonly EventLogSession _session;
private readonly string _providerName;
private readonly CultureInfo _cultureInfo;
private readonly string? _logFilePath;
// caching of the IEnumerable<EventLevel>, <EventTask>, <EventKeyword>, <EventOpcode> on the ProviderMetadata
// they do not change with every call.
private IList<EventLevel>? _levels;
private IList<EventOpcode>? _opcodes;
private IList<EventTask>? _tasks;
private IList<EventKeyword>? _keywords;
private IList<EventLevel>? _standardLevels;
private IList<EventOpcode>? _standardOpcodes;
private IList<EventTask>? _standardTasks;
private IList<EventKeyword>? _standardKeywords;
private IList<EventLogLink>? _channelReferences;
private readonly object _syncObject;
public ProviderMetadata(string providerName)
: this(providerName, null, null, null)
{
}
public ProviderMetadata(string providerName, EventLogSession? session, CultureInfo? targetCultureInfo)
: this(providerName, session, targetCultureInfo, null)
{
}
internal ProviderMetadata(string providerName, EventLogSession? session, CultureInfo? targetCultureInfo, string? logFilePath)
{
targetCultureInfo ??= CultureInfo.CurrentCulture;
session ??= EventLogSession.GlobalSession;
_session = session;
_providerName = providerName;
_cultureInfo = targetCultureInfo;
_logFilePath = logFilePath;
_handle = NativeWrapper.EvtOpenProviderMetadata(_session.Handle, _providerName, _logFilePath, 0);
_syncObject = new object();
}
internal EventLogHandle Handle
{
get
{
return _handle;
}
}
public string Name
{
get { return _providerName; }
}
public Guid Id
{
get
{
return (Guid)NativeWrapper.EvtGetPublisherMetadataProperty(_handle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataPublisherGuid)!;
}
}
public string? MessageFilePath
{
get
{
return (string?)NativeWrapper.EvtGetPublisherMetadataProperty(_handle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataMessageFilePath);
}
}
public string? ResourceFilePath
{
get
{
return (string?)NativeWrapper.EvtGetPublisherMetadataProperty(_handle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataResourceFilePath);
}
}
public string? ParameterFilePath
{
get
{
return (string?)NativeWrapper.EvtGetPublisherMetadataProperty(_handle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataParameterFilePath);
}
}
public Uri? HelpLink
{
get
{
string? helpLinkStr = (string?)NativeWrapper.EvtGetPublisherMetadataProperty(_handle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataHelpLink);
if (string.IsNullOrEmpty(helpLinkStr))
return null;
return new Uri(helpLinkStr);
}
}
private uint ProviderMessageID
{
get
{
return (uint)NativeWrapper.EvtGetPublisherMetadataProperty(_handle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataPublisherMessageID)!;
}
}
public string? DisplayName
{
get
{
uint msgId = (uint)this.ProviderMessageID;
if (msgId == 0xffffffff)
return null;
return NativeWrapper.EvtFormatMessage(_handle, msgId);
}
}
public IList<EventLogLink> LogLinks
{
get
{
EventLogHandle elHandle = EventLogHandle.Zero;
try
{
lock (_syncObject)
{
if (_channelReferences != null)
return _channelReferences;
elHandle = NativeWrapper.EvtGetPublisherMetadataPropertyHandle(_handle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataChannelReferences);
int arraySize = NativeWrapper.EvtGetObjectArraySize(elHandle);
List<EventLogLink> channelList = new List<EventLogLink>(arraySize);
for (int index = 0; index < arraySize; index++)
{
string? channelName = (string?)NativeWrapper.EvtGetObjectArrayProperty(elHandle, index, (int)UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataChannelReferencePath);
uint channelId = (uint)NativeWrapper.EvtGetObjectArrayProperty(elHandle, index, (int)UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataChannelReferenceID)!;
uint flag = (uint)NativeWrapper.EvtGetObjectArrayProperty(elHandle, index, (int)UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataChannelReferenceFlags)!;
bool isImported;
if (flag == (int)UnsafeNativeMethods.EvtChannelReferenceFlags.EvtChannelReferenceImported)
isImported = true;
else
isImported = false;
int channelRefMessageId = unchecked((int)((uint)NativeWrapper.EvtGetObjectArrayProperty(elHandle, index, (int)UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataChannelReferenceMessageID)!));
string? channelRefDisplayName;
// if channelRefMessageId == -1, we do not have anything in the message table.
if (channelRefMessageId == -1)
{
channelRefDisplayName = null;
}
else
{
channelRefDisplayName = NativeWrapper.EvtFormatMessage(_handle, unchecked((uint)channelRefMessageId));
}
if (channelRefDisplayName == null && isImported)
{
if (string.Equals(channelName, "Application", StringComparison.OrdinalIgnoreCase))
channelRefMessageId = 256;
else if (string.Equals(channelName, "System", StringComparison.OrdinalIgnoreCase))
channelRefMessageId = 258;
else if (string.Equals(channelName, "Security", StringComparison.OrdinalIgnoreCase))
channelRefMessageId = 257;
else
channelRefMessageId = -1;
if (channelRefMessageId != -1)
{
if (_defaultProviderHandle.IsInvalid)
{
_defaultProviderHandle = NativeWrapper.EvtOpenProviderMetadata(_session.Handle, null, null, 0);
}
channelRefDisplayName = NativeWrapper.EvtFormatMessage(_defaultProviderHandle, unchecked((uint)channelRefMessageId));
}
}
channelList.Add(new EventLogLink(channelName, isImported, channelRefDisplayName, channelId));
}
_channelReferences = channelList.AsReadOnly();
}
return _channelReferences;
}
finally
{
elHandle.Dispose();
}
}
}
internal enum ObjectTypeName
{
Level = 0,
Opcode = 1,
Task = 2,
Keyword = 3
}
internal string? FindStandardLevelDisplayName(string? name, uint value)
{
_standardLevels ??= (List<EventLevel>)GetProviderListProperty(_defaultProviderHandle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataLevels)!;
foreach (EventLevel standardLevel in _standardLevels)
{
if (standardLevel.Name == name && standardLevel.Value == value)
return standardLevel.DisplayName;
}
return null;
}
internal string? FindStandardOpcodeDisplayName(string? name, uint value)
{
_standardOpcodes ??= (List<EventOpcode>)GetProviderListProperty(_defaultProviderHandle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataOpcodes)!;
foreach (EventOpcode standardOpcode in _standardOpcodes)
{
if (standardOpcode.Name == name && standardOpcode.Value == value)
return standardOpcode.DisplayName;
}
return null;
}
internal string? FindStandardKeywordDisplayName(string? name, long value)
{
_standardKeywords ??= (List<EventKeyword>)GetProviderListProperty(_defaultProviderHandle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataKeywords)!;
foreach (EventKeyword standardKeyword in _standardKeywords)
{
if (standardKeyword.Name == name && standardKeyword.Value == value)
return standardKeyword.DisplayName;
}
return null;
}
internal string? FindStandardTaskDisplayName(string? name, uint value)
{
_standardTasks ??= (List<EventTask>)GetProviderListProperty(_defaultProviderHandle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataTasks)!;
foreach (EventTask standardTask in _standardTasks)
{
if (standardTask.Name == name && standardTask.Value == value)
return standardTask.DisplayName;
}
return null;
}
internal object? GetProviderListProperty(EventLogHandle providerHandle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId metadataProperty)
{
EventLogHandle elHandle = EventLogHandle.Zero;
try
{
UnsafeNativeMethods.EvtPublisherMetadataPropertyId propName;
UnsafeNativeMethods.EvtPublisherMetadataPropertyId propValue;
UnsafeNativeMethods.EvtPublisherMetadataPropertyId propMessageId;
ObjectTypeName objectTypeName;
List<EventLevel>? levelList = null;
List<EventOpcode>? opcodeList = null;
List<EventKeyword>? keywordList = null;
List<EventTask>? taskList = null;
elHandle = NativeWrapper.EvtGetPublisherMetadataPropertyHandle(providerHandle, metadataProperty);
int arraySize = NativeWrapper.EvtGetObjectArraySize(elHandle);
switch (metadataProperty)
{
case UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataLevels:
propName = UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataLevelName;
propValue = UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataLevelValue;
propMessageId = UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataLevelMessageID;
objectTypeName = ObjectTypeName.Level;
levelList = new List<EventLevel>(arraySize);
break;
case UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataOpcodes:
propName = UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataOpcodeName;
propValue = UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataOpcodeValue;
propMessageId = UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataOpcodeMessageID;
objectTypeName = ObjectTypeName.Opcode;
opcodeList = new List<EventOpcode>(arraySize);
break;
case UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataKeywords:
propName = UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataKeywordName;
propValue = UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataKeywordValue;
propMessageId = UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataKeywordMessageID;
objectTypeName = ObjectTypeName.Keyword;
keywordList = new List<EventKeyword>(arraySize);
break;
case UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataTasks:
propName = UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataTaskName;
propValue = UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataTaskValue;
propMessageId = UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataTaskMessageID;
objectTypeName = ObjectTypeName.Task;
taskList = new List<EventTask>(arraySize);
break;
default:
return null;
}
for (int index = 0; index < arraySize; index++)
{
string? generalName = (string?)NativeWrapper.EvtGetObjectArrayProperty(elHandle, index, (int)propName);
uint generalValue = 0;
long generalValueKeyword = 0;
if (objectTypeName != ObjectTypeName.Keyword)
{
generalValue = (uint)NativeWrapper.EvtGetObjectArrayProperty(elHandle, index, (int)propValue)!;
}
else
{
generalValueKeyword = unchecked((long)((ulong)NativeWrapper.EvtGetObjectArrayProperty(elHandle, index, (int)propValue)!));
}
int generalMessageId = unchecked((int)((uint)NativeWrapper.EvtGetObjectArrayProperty(elHandle, index, (int)propMessageId)!));
string? generalDisplayName = null;
if (generalMessageId == -1)
{
if (providerHandle != _defaultProviderHandle)
{
if (_defaultProviderHandle.IsInvalid)
{
_defaultProviderHandle = NativeWrapper.EvtOpenProviderMetadata(_session.Handle, null, null, 0);
}
generalDisplayName = objectTypeName switch
{
ObjectTypeName.Level => FindStandardLevelDisplayName(generalName, generalValue),
ObjectTypeName.Opcode => FindStandardOpcodeDisplayName(generalName, generalValue >> 16),
ObjectTypeName.Keyword => FindStandardKeywordDisplayName(generalName, generalValueKeyword),
ObjectTypeName.Task => FindStandardTaskDisplayName(generalName, generalValue),
_ => null,
};
}
}
else
{
generalDisplayName = NativeWrapper.EvtFormatMessage(providerHandle, unchecked((uint)generalMessageId));
}
switch (objectTypeName)
{
case ObjectTypeName.Level:
levelList!.Add(new EventLevel(generalName, (int)generalValue, generalDisplayName));
break;
case ObjectTypeName.Opcode:
opcodeList!.Add(new EventOpcode(generalName, (int)(generalValue >> 16), generalDisplayName));
break;
case ObjectTypeName.Keyword:
keywordList!.Add(new EventKeyword(generalName, (long)generalValueKeyword, generalDisplayName));
break;
case ObjectTypeName.Task:
Guid taskGuid = (Guid)NativeWrapper.EvtGetObjectArrayProperty(elHandle, index, (int)UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataTaskEventGuid)!;
taskList!.Add(new EventTask(generalName, (int)generalValue, generalDisplayName, taskGuid));
break;
default:
return null;
}
}
return objectTypeName switch
{
ObjectTypeName.Level => levelList,
ObjectTypeName.Opcode => opcodeList,
ObjectTypeName.Keyword => keywordList,
ObjectTypeName.Task => taskList,
_ => null,
};
}
finally
{
elHandle.Dispose();
}
}
public IList<EventLevel> Levels
{
get
{
List<EventLevel> el;
lock (_syncObject)
{
if (_levels != null)
return _levels;
el = (List<EventLevel>)this.GetProviderListProperty(_handle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataLevels)!;
_levels = el.AsReadOnly();
}
return _levels;
}
}
public IList<EventOpcode> Opcodes
{
get
{
List<EventOpcode> eo;
lock (_syncObject)
{
if (_opcodes != null)
return _opcodes;
eo = (List<EventOpcode>)this.GetProviderListProperty(_handle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataOpcodes)!;
_opcodes = eo.AsReadOnly();
}
return _opcodes;
}
}
public IList<EventKeyword> Keywords
{
get
{
List<EventKeyword> ek;
lock (_syncObject)
{
if (_keywords != null)
return _keywords;
ek = (List<EventKeyword>)this.GetProviderListProperty(_handle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataKeywords)!;
_keywords = ek.AsReadOnly();
}
return _keywords;
}
}
public IList<EventTask> Tasks
{
get
{
List<EventTask> et;
lock (_syncObject)
{
if (_tasks != null)
return _tasks;
et = (List<EventTask>)this.GetProviderListProperty(_handle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataTasks)!;
_tasks = et.AsReadOnly();
}
return _tasks;
}
}
public IEnumerable<EventMetadata> Events
{
get
{
List<EventMetadata> emList = new List<EventMetadata>();
EventLogHandle emEnumHandle = NativeWrapper.EvtOpenEventMetadataEnum(_handle, 0);
using (emEnumHandle)
{
while (true)
{
EventLogHandle? emHandle = NativeWrapper.EvtNextEventMetadata(emEnumHandle, 0);
if (emHandle == null)
break;
using (emHandle)
{
unchecked
{
uint emId = (uint)NativeWrapper.EvtGetEventMetadataProperty(emHandle, UnsafeNativeMethods.EvtEventMetadataPropertyId.EventMetadataEventID)!;
byte emVersion = (byte)((uint)(NativeWrapper.EvtGetEventMetadataProperty(emHandle, UnsafeNativeMethods.EvtEventMetadataPropertyId.EventMetadataEventVersion))!);
byte emChannelId = (byte)((uint)NativeWrapper.EvtGetEventMetadataProperty(emHandle, UnsafeNativeMethods.EvtEventMetadataPropertyId.EventMetadataEventChannel)!);
byte emLevel = (byte)((uint)NativeWrapper.EvtGetEventMetadataProperty(emHandle, UnsafeNativeMethods.EvtEventMetadataPropertyId.EventMetadataEventLevel)!);
byte emOpcode = (byte)((uint)NativeWrapper.EvtGetEventMetadataProperty(emHandle, UnsafeNativeMethods.EvtEventMetadataPropertyId.EventMetadataEventOpcode)!);
short emTask = (short)((uint)NativeWrapper.EvtGetEventMetadataProperty(emHandle, UnsafeNativeMethods.EvtEventMetadataPropertyId.EventMetadataEventTask)!);
long emKeywords = (long)(ulong)NativeWrapper.EvtGetEventMetadataProperty(emHandle, UnsafeNativeMethods.EvtEventMetadataPropertyId.EventMetadataEventKeyword)!;
string? emTemplate = (string?)NativeWrapper.EvtGetEventMetadataProperty(emHandle, UnsafeNativeMethods.EvtEventMetadataPropertyId.EventMetadataEventTemplate);
int messageId = (int)((uint)NativeWrapper.EvtGetEventMetadataProperty(emHandle, UnsafeNativeMethods.EvtEventMetadataPropertyId.EventMetadataEventMessageID)!);
string? emMessage = (messageId == -1)
? null
: NativeWrapper.EvtFormatMessage(_handle, (uint)messageId);
EventMetadata em = new EventMetadata(emId, emVersion, emChannelId, emLevel, emOpcode, emTask, emKeywords, emTemplate, emMessage, this);
emList.Add(em);
}
}
}
return emList.AsReadOnly();
}
}
}
// throws if Provider metadata has been uninstalled since this object was created.
internal void CheckReleased()
{
lock (_syncObject)
{
this.GetProviderListProperty(_handle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId.EvtPublisherMetadataTasks);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_handle != null && !_handle.IsInvalid)
_handle.Dispose();
}
}
}
|