// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+// ------------------------------------------------------------------------------
+// Changes to this file must follow the http://aka.ms/api-review process.
+// ------------------------------------------------------------------------------
namespace System.Diagnostics
{
public string Source { get { throw null; } set { } }
[System.ComponentModel.BrowsableAttribute(false)]
[System.ComponentModel.DefaultValueAttribute(null)]
- public System.ComponentModel.ISynchronizeInvoke SynchronizingObject { [System.Security.Permissions.HostProtectionAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Synchronization = true)]get { throw null; } set { } }
+ public System.ComponentModel.ISynchronizeInvoke SynchronizingObject { get { throw null; } set { } }
public event System.Diagnostics.EntryWrittenEventHandler EntryWritten { add { } remove { } }
public void BeginInit() { }
public void Clear() { }
OverwriteOlder = 1,
}
}
+namespace System.Diagnostics.Eventing.Reader
+{
+ public partial class EventBookmark
+ {
+ internal EventBookmark() { }
+ }
+ public sealed partial class EventKeyword
+ {
+ internal EventKeyword() { }
+ public string DisplayName { get { throw null; } }
+ public string Name { get { throw null; } }
+ public long Value { get { throw null; } }
+ }
+ public sealed partial class EventLevel
+ {
+ internal EventLevel() { }
+ public string DisplayName { get { throw null; } }
+ public string Name { get { throw null; } }
+ public int Value { get { throw null; } }
+ }
+ public partial class EventLogConfiguration : System.IDisposable
+ {
+ public EventLogConfiguration(string logName) { }
+ public EventLogConfiguration(string logName, System.Diagnostics.Eventing.Reader.EventLogSession session) { }
+ public bool IsClassicLog { get { throw null; } }
+ public bool IsEnabled { get { throw null; } set { } }
+ public string LogFilePath { get { throw null; } set { } }
+ public System.Diagnostics.Eventing.Reader.EventLogIsolation LogIsolation { get { throw null; } }
+ public System.Diagnostics.Eventing.Reader.EventLogMode LogMode { get { throw null; } set { } }
+ public string LogName { get { throw null; } }
+ public System.Diagnostics.Eventing.Reader.EventLogType LogType { get { throw null; } }
+ public long MaximumSizeInBytes { get { throw null; } set { } }
+ public string OwningProviderName { get { throw null; } }
+ public System.Nullable<int> ProviderBufferSize { get { throw null; } }
+ public System.Nullable<System.Guid> ProviderControlGuid { get { throw null; } }
+ public System.Nullable<long> ProviderKeywords { get { throw null; } set { } }
+ public System.Nullable<int> ProviderLatency { get { throw null; } }
+ public System.Nullable<int> ProviderLevel { get { throw null; } set { } }
+ public System.Nullable<int> ProviderMaximumNumberOfBuffers { get { throw null; } }
+ public System.Nullable<int> ProviderMinimumNumberOfBuffers { get { throw null; } }
+ public System.Collections.Generic.IEnumerable<string> ProviderNames { get { throw null; } }
+ public string SecurityDescriptor { get { throw null; } set { } }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public void SaveChanges() { }
+ }
+ public partial class EventLogException : System.Exception
+ {
+ public EventLogException() { }
+ protected EventLogException(int errorCode) { }
+ public EventLogException(string message) { }
+ public EventLogException(string message, System.Exception innerException) { }
+ public override string Message { get { throw null; } }
+ }
+ public sealed partial class EventLogInformation
+ {
+ internal EventLogInformation() { }
+ public System.Nullable<int> Attributes { get { throw null; } }
+ public System.Nullable<System.DateTime> CreationTime { get { throw null; } }
+ public System.Nullable<long> FileSize { get { throw null; } }
+ public System.Nullable<bool> IsLogFull { get { throw null; } }
+ public System.Nullable<System.DateTime> LastAccessTime { get { throw null; } }
+ public System.Nullable<System.DateTime> LastWriteTime { get { throw null; } }
+ public System.Nullable<long> OldestRecordNumber { get { throw null; } }
+ public System.Nullable<long> RecordCount { get { throw null; } }
+ }
+ public partial class EventLogInvalidDataException : System.Diagnostics.Eventing.Reader.EventLogException
+ {
+ public EventLogInvalidDataException() { }
+ public EventLogInvalidDataException(string message) { }
+ public EventLogInvalidDataException(string message, System.Exception innerException) { }
+ }
+ public enum EventLogIsolation
+ {
+ Application = 0,
+ Custom = 2,
+ System = 1,
+ }
+ public sealed partial class EventLogLink
+ {
+ internal EventLogLink() { }
+ public string DisplayName { get { throw null; } }
+ public bool IsImported { get { throw null; } }
+ public string LogName { get { throw null; } }
+ }
+ public enum EventLogMode
+ {
+ AutoBackup = 1,
+ Circular = 0,
+ Retain = 2,
+ }
+ public partial class EventLogNotFoundException : System.Diagnostics.Eventing.Reader.EventLogException
+ {
+ public EventLogNotFoundException() { }
+ public EventLogNotFoundException(string message) { }
+ public EventLogNotFoundException(string message, System.Exception innerException) { }
+ }
+ public partial class EventLogPropertySelector : System.IDisposable
+ {
+ public EventLogPropertySelector(System.Collections.Generic.IEnumerable<string> propertyQueries) { }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ }
+ public partial class EventLogProviderDisabledException : System.Diagnostics.Eventing.Reader.EventLogException
+ {
+ public EventLogProviderDisabledException() { }
+ public EventLogProviderDisabledException(string message) { }
+ public EventLogProviderDisabledException(string message, System.Exception innerException) { }
+ }
+ public partial class EventLogQuery
+ {
+ public EventLogQuery(string path, System.Diagnostics.Eventing.Reader.PathType pathType) { }
+ public EventLogQuery(string path, System.Diagnostics.Eventing.Reader.PathType pathType, string query) { }
+ public bool ReverseDirection { get { throw null; } set { } }
+ public System.Diagnostics.Eventing.Reader.EventLogSession Session { get { throw null; } set { } }
+ public bool TolerateQueryErrors { get { throw null; } set { } }
+ }
+ public partial class EventLogReader : System.IDisposable
+ {
+ public EventLogReader(System.Diagnostics.Eventing.Reader.EventLogQuery eventQuery) { }
+ public EventLogReader(System.Diagnostics.Eventing.Reader.EventLogQuery eventQuery, System.Diagnostics.Eventing.Reader.EventBookmark bookmark) { }
+ public EventLogReader(string path) { }
+ public EventLogReader(string path, System.Diagnostics.Eventing.Reader.PathType pathType) { }
+ public int BatchSize { get { throw null; } set { } }
+ public System.Collections.Generic.IList<System.Diagnostics.Eventing.Reader.EventLogStatus> LogStatus { get { throw null; } }
+ public void CancelReading() { }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public System.Diagnostics.Eventing.Reader.EventRecord ReadEvent() { throw null; }
+ public System.Diagnostics.Eventing.Reader.EventRecord ReadEvent(System.TimeSpan timeout) { throw null; }
+ public void Seek(System.Diagnostics.Eventing.Reader.EventBookmark bookmark) { }
+ public void Seek(System.Diagnostics.Eventing.Reader.EventBookmark bookmark, long offset) { }
+ public void Seek(System.IO.SeekOrigin origin, long offset) { }
+ }
+ public partial class EventLogReadingException : System.Diagnostics.Eventing.Reader.EventLogException
+ {
+ public EventLogReadingException() { }
+ public EventLogReadingException(string message) { }
+ public EventLogReadingException(string message, System.Exception innerException) { }
+ }
+ public partial class EventLogRecord : System.Diagnostics.Eventing.Reader.EventRecord
+ {
+ internal EventLogRecord() { }
+ public override System.Nullable<System.Guid> ActivityId { get { throw null; } }
+ public override System.Diagnostics.Eventing.Reader.EventBookmark Bookmark { get { throw null; } }
+ public string ContainerLog { get { throw null; } }
+ public override int Id { get { throw null; } }
+ public override System.Nullable<long> Keywords { get { throw null; } }
+ public override System.Collections.Generic.IEnumerable<string> KeywordsDisplayNames { get { throw null; } }
+ public override System.Nullable<byte> Level { get { throw null; } }
+ public override string LevelDisplayName { get { throw null; } }
+ public override string LogName { get { throw null; } }
+ public override string MachineName { get { throw null; } }
+ public System.Collections.Generic.IEnumerable<int> MatchedQueryIds { get { throw null; } }
+ public override System.Nullable<short> Opcode { get { throw null; } }
+ public override string OpcodeDisplayName { get { throw null; } }
+ public override System.Nullable<int> ProcessId { get { throw null; } }
+ public override System.Collections.Generic.IList<System.Diagnostics.Eventing.Reader.EventProperty> Properties { get { throw null; } }
+ public override System.Nullable<System.Guid> ProviderId { get { throw null; } }
+ public override string ProviderName { get { throw null; } }
+ public override System.Nullable<int> Qualifiers { get { throw null; } }
+ public override System.Nullable<long> RecordId { get { throw null; } }
+ public override System.Nullable<System.Guid> RelatedActivityId { get { throw null; } }
+ public override System.Nullable<int> Task { get { throw null; } }
+ public override string TaskDisplayName { get { throw null; } }
+ public override System.Nullable<int> ThreadId { get { throw null; } }
+ public override System.Nullable<System.DateTime> TimeCreated { get { throw null; } }
+ public override System.Security.Principal.SecurityIdentifier UserId { get { throw null; } }
+ public override System.Nullable<byte> Version { get { throw null; } }
+ protected override void Dispose(bool disposing) { }
+ public override string FormatDescription() { throw null; }
+ public override string FormatDescription(System.Collections.Generic.IEnumerable<object> values) { throw null; }
+ public System.Collections.Generic.IList<object> GetPropertyValues(System.Diagnostics.Eventing.Reader.EventLogPropertySelector propertySelector) { throw null; }
+ public override string ToXml() { throw null; }
+ }
+ public partial class EventLogSession : System.IDisposable
+ {
+ public EventLogSession() { }
+ public EventLogSession(string server) { }
+ public EventLogSession(string server, string domain, string user, System.Security.SecureString password, System.Diagnostics.Eventing.Reader.SessionAuthentication logOnType) { }
+ public static System.Diagnostics.Eventing.Reader.EventLogSession GlobalSession { get { throw null; } }
+ public void CancelCurrentOperations() { }
+ public void ClearLog(string logName) { }
+ public void ClearLog(string logName, string backupPath) { }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public void ExportLog(string path, System.Diagnostics.Eventing.Reader.PathType pathType, string query, string targetFilePath) { }
+ public void ExportLog(string path, System.Diagnostics.Eventing.Reader.PathType pathType, string query, string targetFilePath, bool tolerateQueryErrors) { }
+ public void ExportLogAndMessages(string path, System.Diagnostics.Eventing.Reader.PathType pathType, string query, string targetFilePath) { }
+ public void ExportLogAndMessages(string path, System.Diagnostics.Eventing.Reader.PathType pathType, string query, string targetFilePath, bool tolerateQueryErrors, System.Globalization.CultureInfo targetCultureInfo) { }
+ public System.Diagnostics.Eventing.Reader.EventLogInformation GetLogInformation(string logName, System.Diagnostics.Eventing.Reader.PathType pathType) { throw null; }
+ public System.Collections.Generic.IEnumerable<string> GetLogNames() { throw null; }
+ public System.Collections.Generic.IEnumerable<string> GetProviderNames() { throw null; }
+ }
+ public sealed partial class EventLogStatus
+ {
+ internal EventLogStatus() { }
+ public string LogName { get { throw null; } }
+ public int StatusCode { get { throw null; } }
+ }
+ public enum EventLogType
+ {
+ Administrative = 0,
+ Analytical = 2,
+ Debug = 3,
+ Operational = 1,
+ }
+ public partial class EventLogWatcher : System.IDisposable
+ {
+ public EventLogWatcher(System.Diagnostics.Eventing.Reader.EventLogQuery eventQuery) { }
+ public EventLogWatcher(System.Diagnostics.Eventing.Reader.EventLogQuery eventQuery, System.Diagnostics.Eventing.Reader.EventBookmark bookmark) { }
+ public EventLogWatcher(System.Diagnostics.Eventing.Reader.EventLogQuery eventQuery, System.Diagnostics.Eventing.Reader.EventBookmark bookmark, bool readExistingEvents) { }
+ public EventLogWatcher(string path) { }
+ public bool Enabled { get { throw null; } set { } }
+ public event System.EventHandler<System.Diagnostics.Eventing.Reader.EventRecordWrittenEventArgs> EventRecordWritten { add { } remove { } }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ }
+ public sealed partial class EventMetadata
+ {
+ internal EventMetadata() { }
+ public string Description { get { throw null; } }
+ public long Id { get { throw null; } }
+ public System.Collections.Generic.IEnumerable<System.Diagnostics.Eventing.Reader.EventKeyword> Keywords { get { throw null; } }
+ public System.Diagnostics.Eventing.Reader.EventLevel Level { get { throw null; } }
+ public System.Diagnostics.Eventing.Reader.EventLogLink LogLink { get { throw null; } }
+ public System.Diagnostics.Eventing.Reader.EventOpcode Opcode { get { throw null; } }
+ public System.Diagnostics.Eventing.Reader.EventTask Task { get { throw null; } }
+ public string Template { get { throw null; } }
+ public byte Version { get { throw null; } }
+ }
+ public sealed partial class EventOpcode
+ {
+ internal EventOpcode() { }
+ public string DisplayName { get { throw null; } }
+ public string Name { get { throw null; } }
+ public int Value { get { throw null; } }
+ }
+ public sealed partial class EventProperty
+ {
+ internal EventProperty() { }
+ public object Value { get { throw null; } }
+ }
+ public abstract partial class EventRecord : System.IDisposable
+ {
+ protected EventRecord() { }
+ public abstract System.Nullable<System.Guid> ActivityId { get; }
+ public abstract System.Diagnostics.Eventing.Reader.EventBookmark Bookmark { get; }
+ public abstract int Id { get; }
+ public abstract System.Nullable<long> Keywords { get; }
+ public abstract System.Collections.Generic.IEnumerable<string> KeywordsDisplayNames { get; }
+ public abstract System.Nullable<byte> Level { get; }
+ public abstract string LevelDisplayName { get; }
+ public abstract string LogName { get; }
+ public abstract string MachineName { get; }
+ public abstract System.Nullable<short> Opcode { get; }
+ public abstract string OpcodeDisplayName { get; }
+ public abstract System.Nullable<int> ProcessId { get; }
+ public abstract System.Collections.Generic.IList<System.Diagnostics.Eventing.Reader.EventProperty> Properties { get; }
+ public abstract System.Nullable<System.Guid> ProviderId { get; }
+ public abstract string ProviderName { get; }
+ public abstract System.Nullable<int> Qualifiers { get; }
+ public abstract System.Nullable<long> RecordId { get; }
+ public abstract System.Nullable<System.Guid> RelatedActivityId { get; }
+ public abstract System.Nullable<int> Task { get; }
+ public abstract string TaskDisplayName { get; }
+ public abstract System.Nullable<int> ThreadId { get; }
+ public abstract System.Nullable<System.DateTime> TimeCreated { get; }
+ public abstract System.Security.Principal.SecurityIdentifier UserId { get; }
+ public abstract System.Nullable<byte> Version { get; }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public abstract string FormatDescription();
+ public abstract string FormatDescription(System.Collections.Generic.IEnumerable<object> values);
+ public abstract string ToXml();
+ }
+ public sealed partial class EventRecordWrittenEventArgs : System.EventArgs
+ {
+ internal EventRecordWrittenEventArgs() { }
+ public System.Exception EventException { get { throw null; } }
+ public System.Diagnostics.Eventing.Reader.EventRecord EventRecord { get { throw null; } }
+ }
+ public sealed partial class EventTask
+ {
+ internal EventTask() { }
+ public string DisplayName { get { throw null; } }
+ public System.Guid EventGuid { get { throw null; } }
+ public string Name { get { throw null; } }
+ public int Value { get { throw null; } }
+ }
+ public enum PathType
+ {
+ FilePath = 2,
+ LogName = 1,
+ }
+ public partial class ProviderMetadata : System.IDisposable
+ {
+ public ProviderMetadata(string providerName) { }
+ public ProviderMetadata(string providerName, System.Diagnostics.Eventing.Reader.EventLogSession session, System.Globalization.CultureInfo targetCultureInfo) { }
+ public string DisplayName { get { throw null; } }
+ public System.Collections.Generic.IEnumerable<System.Diagnostics.Eventing.Reader.EventMetadata> Events { get { throw null; } }
+ public System.Uri HelpLink { get { throw null; } }
+ public System.Guid Id { get { throw null; } }
+ public System.Collections.Generic.IList<System.Diagnostics.Eventing.Reader.EventKeyword> Keywords { get { throw null; } }
+ public System.Collections.Generic.IList<System.Diagnostics.Eventing.Reader.EventLevel> Levels { get { throw null; } }
+ public System.Collections.Generic.IList<System.Diagnostics.Eventing.Reader.EventLogLink> LogLinks { get { throw null; } }
+ public string MessageFilePath { get { throw null; } }
+ public string Name { get { throw null; } }
+ public System.Collections.Generic.IList<System.Diagnostics.Eventing.Reader.EventOpcode> Opcodes { get { throw null; } }
+ public string ParameterFilePath { get { throw null; } }
+ public string ResourceFilePath { get { throw null; } }
+ public System.Collections.Generic.IList<System.Diagnostics.Eventing.Reader.EventTask> Tasks { get { throw null; } }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ }
+ public enum SessionAuthentication
+ {
+ Default = 0,
+ Kerberos = 2,
+ Negotiate = 1,
+ Ntlm = 3,
+ }
+ [System.FlagsAttribute]
+ public enum StandardEventKeywords : long
+ {
+ AuditFailure = (long)4503599627370496,
+ AuditSuccess = (long)9007199254740992,
+ [System.ObsoleteAttribute("Incorrect value: use CorrelationHint2 instead", false)]
+ CorrelationHint = (long)4503599627370496,
+ CorrelationHint2 = (long)18014398509481984,
+ EventLogClassic = (long)36028797018963968,
+ None = (long)0,
+ ResponseTime = (long)281474976710656,
+ Sqm = (long)2251799813685248,
+ WdiContext = (long)562949953421312,
+ WdiDiagnostic = (long)1125899906842624,
+ }
+ public enum StandardEventLevel
+ {
+ Critical = 1,
+ Error = 2,
+ Informational = 4,
+ LogAlways = 0,
+ Verbose = 5,
+ Warning = 3,
+ }
+ public enum StandardEventOpcode
+ {
+ DataCollectionStart = 3,
+ DataCollectionStop = 4,
+ Extension = 5,
+ Info = 0,
+ Receive = 240,
+ Reply = 6,
+ Resume = 7,
+ Send = 9,
+ Start = 1,
+ Stop = 2,
+ Suspend = 8,
+ }
+ public enum StandardEventTask
+ {
+ None = 0,
+ }
+}
<Reference Include="mscorlib" />
<Reference Include="System" />
</ItemGroup>
-</Project>
\ No newline at end of file
+ <ItemGroup Condition="'$(TargetsNetFx)' != 'true'">
+ <ProjectReference Include="..\..\System.Security.Principal.Windows\ref\System.Security.Principal.Windows.csproj" />
+ </ItemGroup>
+</Project>
--- /dev/null
+kernel32.dll!CreateFile
+advapi32.dll!ClearEventLog
+advapi32.dll!CloseEventLog
+advapi32.dll!GetNumberOfEventLogRecords
+advapi32.dll!GetOldestEventLogRecord
+advapi32.dll!NotifyChangeEventLog
+advapi32.dll!OpenEventLog
+advapi32.dll!ReadEventLog
+wevtapi.dll!EvtQuery
+wevtapi.dll!EvtSeek
+wevtapi.dll!EvtSubscribe
+wevtapi.dll!EvtNext
+wevtapi.dll!EvtCancel
+wevtapi.dll!EvtGetEventInfo
+wevtapi.dll!EvtClose
+wevtapi.dll!EvtGetQueryInfo
+wevtapi.dll!EvtOpenPublisherMetadata
+wevtapi.dll!EvtGetPublisherMetadataProperty
+wevtapi.dll!EvtGetObjectArraySize
+wevtapi.dll!EvtGetObjectArrayProperty
+wevtapi.dll!EvtOpenEventMetadataEnum
+wevtapi.dll!EvtNextEventMetadata
+wevtapi.dll!EvtGetEventMetadataProperty
+wevtapi.dll!EvtOpenChannelEnum
+wevtapi.dll!EvtNextChannelPath
+wevtapi.dll!EvtOpenPublisherEnum
+wevtapi.dll!EvtNextPublisherId
+wevtapi.dll!EvtOpenChannelConfig
+wevtapi.dll!EvtSaveChannelConfig
+wevtapi.dll!EvtSetChannelConfigProperty
+wevtapi.dll!EvtGetChannelConfigProperty
+wevtapi.dll!EvtOpenLog
+wevtapi.dll!EvtGetLogInfo
+wevtapi.dll!EvtExportLog
+wevtapi.dll!EvtArchiveExportedLog
+wevtapi.dll!EvtClearLog
+wevtapi.dll!EvtCreateRenderContext
+wevtapi.dll!EvtRender
+wevtapi.dll!EvtFormatMessage
+wevtapi.dll!EvtOpenSession
+wevtapi.dll!EvtUpdateBookmark
+wevtapi.dll!EvtCreateBookmark
+
<data name="LogAlreadyExistsAsSource" xml:space="preserve">
<value>Log {0} has already been registered as a source on the local computer.</value>
</data>
-</root>
\ No newline at end of file
+ <data name="NotSupported_IONonFileDevices" xml:space="preserve">
+ <value>Opening Win32 devices other than file such as COM ports, printers, disk partitions and tape drives is not supported. Avoid use of "\\\\.\\" in the path.</value>
+ </data>
+</root>
<Compile Include="System\Diagnostics\EventLogEntry.cs">
<SubType>Component</SubType>
</Compile>
+ <Compile Include="System\Diagnostics\Reader\CoTaskMemSafeHandle.cs" />
+ <Compile Include="System\Diagnostics\Reader\CoTaskMemUnicodeSafeHandle.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventBookmark.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventKeyword.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLevel.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogConfiguration.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogException.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogHandle.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogInformation.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogLink.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogPropertySelector.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogQuery.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogReader.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogRecord.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogSession.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogStatus.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogWatcher.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventMetadata.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventOpcode.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventProperty.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventRecord.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventRecordWrittenEventArgs.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventTask.cs" />
+ <Compile Include="System\Diagnostics\Reader\NativeWrapper.cs" />
+ <Compile Include="System\Diagnostics\Reader\ProviderMetadata.cs" />
+ <Compile Include="System\Diagnostics\Reader\ProviderMetadataCachedInformation.cs" />
+ <Compile Include="System\Diagnostics\Reader\Winmeta.cs" />
+ <Compile Include="System\Diagnostics\Reader\UnsafeNativeMethods.cs" />
<Compile Include="System\Diagnostics\EventLogEntryCollection.cs" />
<Compile Include="System\Diagnostics\EventLogEntryType.cs" />
<Compile Include="System\Diagnostics\EventLogInternal.cs" />
<ItemGroup Condition="'$(TargetsNetFx)' != 'true'">
<Reference Include="Microsoft.Win32.Primitives" />
<Reference Include="Microsoft.Win32.Registry" />
+ <Reference Include="System.Collections" />
<Reference Include="System.Collections.Specialized" />
<Reference Include="System.ComponentModel" />
<Reference Include="System.ComponentModel.Primitives" />
<Reference Include="System.Security.Principal.Windows" />
<Reference Include="System.Threading" />
<Reference Include="System.Threading.AccessControl" />
+ <Reference Include="System.Threading.Tasks" />
<Reference Include="System.Threading.Thread" />
<Reference Include="System.Threading.ThreadPool" />
+ <Reference Include="System.Threading.Overlapped" />
</ItemGroup>
</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// A SafeHandle implementation over a native CoTaskMem allocated via StringToCoTaskMemAuto.
+ /// </summary>
+ internal sealed class CoTaskMemSafeHandle : SafeHandle
+ {
+ internal CoTaskMemSafeHandle()
+ : base(IntPtr.Zero, true)
+ {
+ }
+
+ internal void SetMemory(IntPtr handle)
+ {
+ SetHandle(handle);
+ }
+
+ internal IntPtr GetMemory()
+ {
+ return handle;
+ }
+
+ public override bool IsInvalid
+ {
+ get
+ {
+ return IsClosed || handle == IntPtr.Zero;
+ }
+ }
+
+ protected override bool ReleaseHandle()
+ {
+ Marshal.FreeCoTaskMem(handle);
+ handle = IntPtr.Zero;
+ return true;
+ }
+
+ //
+ // DONT compare CoTaskMemSafeHandle with CoTaskMemSafeHandle.Zero
+ // use IsInvalid instead. Zero is provided where a NULL handle needed
+ //
+ public static CoTaskMemSafeHandle Zero
+ {
+ get
+ {
+ return new CoTaskMemSafeHandle();
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// A SafeHandle implementation over a native CoTaskMem allocated via SecureStringToCoTaskMemUnicode.
+ /// </summary>
+ internal sealed class CoTaskMemUnicodeSafeHandle : SafeHandle
+ {
+ internal CoTaskMemUnicodeSafeHandle()
+ : base(IntPtr.Zero, true)
+ {
+ }
+
+ internal CoTaskMemUnicodeSafeHandle(IntPtr handle, bool ownsHandle)
+ : base(IntPtr.Zero, ownsHandle)
+ {
+ SetHandle(handle);
+ }
+
+ internal void SetMemory(IntPtr handle)
+ {
+ SetHandle(handle);
+ }
+
+ internal IntPtr GetMemory()
+ {
+ return handle;
+ }
+
+ public override bool IsInvalid
+ {
+ get
+ {
+ return IsClosed || handle == IntPtr.Zero;
+ }
+ }
+
+ protected override bool ReleaseHandle()
+ {
+ Marshal.ZeroFreeCoTaskMemUnicode(handle);
+ handle = IntPtr.Zero;
+ return true;
+ }
+
+ // DONT compare CoTaskMemUnicodeSafeHandle with CoTaskMemUnicodeSafeHandle.Zero
+ // use IsInvalid instead. Zero is provided where a NULL handle needed
+ public static CoTaskMemUnicodeSafeHandle Zero
+ {
+ get
+ {
+ return new CoTaskMemUnicodeSafeHandle();
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ //
+ // NOTE: This class must be generic enough to be used across
+ // eventing base implementations. Cannot add anything
+ // that ties it to one particular implementation.
+ //
+
+ /// <summary>
+ /// Represents an opaque Event Bookmark obtained from an EventRecord.
+ /// The bookmark denotes a unique identifier for the event instance as
+ /// well as marks the location in the the result set of the EventReader
+ /// that the event instance was obtained from.
+ /// </summary>
+ public class EventBookmark
+ {
+ internal EventBookmark(string bookmarkText)
+ {
+ BookmarkText = bookmarkText ?? throw new ArgumentNullException(nameof(bookmarkText));
+ }
+
+ internal string BookmarkText { get; }
+ }
+}
+
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Describes the metadata for a specific Keyword defined by a Provider.
+ /// An instance of this class is obtained from a ProviderMetadata object.
+ /// </summary>
+ public sealed class EventKeyword
+ {
+ private string _name;
+ private string _displayName;
+ private bool _dataReady;
+ private ProviderMetadata _pmReference;
+ private object _syncObject;
+
+ internal EventKeyword(long value, ProviderMetadata pmReference)
+ {
+ Value = value;
+ _pmReference = pmReference;
+ _syncObject = new object();
+ }
+
+ internal EventKeyword(string name, long value, string displayName)
+ {
+ Value = value;
+ _name = name;
+ _displayName = displayName;
+ _dataReady = true;
+ _syncObject = new object();
+ }
+
+ internal void PrepareData()
+ {
+ if (_dataReady == true)
+ return;
+
+ lock (_syncObject)
+ {
+ if (_dataReady == true)
+ return;
+
+ IEnumerable<EventKeyword> result = _pmReference.Keywords;
+
+ _name = null;
+ _displayName = null;
+ _dataReady = true;
+
+ foreach (EventKeyword key in result)
+ {
+ if (key.Value == Value)
+ {
+ _name = key.Name;
+ _displayName = key.DisplayName;
+ break;
+ }
+ }
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ PrepareData();
+ return _name;
+ }
+ }
+
+ public long Value { get; }
+
+ public string DisplayName
+ {
+ get
+ {
+ PrepareData();
+ return _displayName;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Describes the metadata for a specific Level defined by a Provider.
+ /// An instance of this class is obtained from a ProviderMetadata object.
+ /// </summary>
+ public sealed class EventLevel
+ {
+ private string _name;
+ private string _displayName;
+ private bool _dataReady;
+ private ProviderMetadata _pmReference;
+ private object _syncObject;
+
+ internal EventLevel(int value, ProviderMetadata pmReference)
+ {
+ Value = value;
+ _pmReference = pmReference;
+ _syncObject = new object();
+ }
+
+ internal EventLevel(string name, int value, string displayName)
+ {
+ Value = value;
+ _name = name;
+ _displayName = displayName;
+ _dataReady = true;
+ _syncObject = new object();
+ }
+
+ internal void PrepareData()
+ {
+ if (_dataReady == true)
+ return;
+
+ lock (_syncObject)
+ {
+ if (_dataReady == true)
+ return;
+
+ IEnumerable<EventLevel> result = _pmReference.Levels;
+ _name = null;
+ _displayName = null;
+ _dataReady = true;
+ foreach (EventLevel lev in result)
+ {
+ if (lev.Value == Value)
+ {
+ _name = lev.Name;
+ _displayName = lev.DisplayName;
+ break;
+ }
+ }
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ PrepareData();
+ return _name;
+ }
+ }
+
+ public int Value { get; }
+
+ public string DisplayName
+ {
+ get
+ {
+ PrepareData();
+ return _displayName;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Log Type
+ /// </summary>
+ public enum EventLogType
+ {
+ Administrative = 0,
+ Operational,
+ Analytical,
+ Debug
+ }
+
+ /// <summary>
+ /// Log Isolation
+ /// </summary>
+ public enum EventLogIsolation
+ {
+ Application = 0,
+ System,
+ Custom
+ }
+
+ /// <summary>
+ /// Log Mode
+ /// </summary>
+ public enum EventLogMode
+ {
+ Circular = 0,
+ AutoBackup,
+ Retain
+ }
+
+ /// <summary>
+ /// Provides access to static log information and configures
+ /// log publishing and log file properties.
+ /// </summary>
+ public class EventLogConfiguration : IDisposable
+ {
+ private EventLogHandle _handle = EventLogHandle.Zero;
+
+ private EventLogSession _session = null;
+
+ public EventLogConfiguration(string logName) : this(logName, null) { }
+
+ public EventLogConfiguration(string logName, EventLogSession session)
+ {
+ if (session == null)
+ session = EventLogSession.GlobalSession;
+
+ _session = session;
+ LogName = logName;
+
+ _handle = NativeWrapper.EvtOpenChannelConfig(_session.Handle, LogName, 0);
+ }
+
+ public string LogName { get; }
+
+ public EventLogType LogType
+ {
+ get
+ {
+ return (EventLogType)((uint)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigType));
+ }
+ }
+
+ public EventLogIsolation LogIsolation
+ {
+ get
+ {
+ return (EventLogIsolation)((uint)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigIsolation));
+ }
+ }
+
+ public bool IsEnabled
+ {
+ get
+ {
+ return (bool)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigEnabled);
+ }
+ set
+ {
+ NativeWrapper.EvtSetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigEnabled, (object)value);
+ }
+ }
+
+ public bool IsClassicLog
+ {
+ get
+ {
+ return (bool)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigClassicEventlog);
+ }
+ }
+
+ public string SecurityDescriptor
+ {
+ get
+ {
+ return (string)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigAccess);
+ }
+ set
+ {
+ NativeWrapper.EvtSetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigAccess, (object)value);
+ }
+ }
+
+ public string LogFilePath
+ {
+ get
+ {
+ return (string)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigLogFilePath);
+ }
+ set
+ {
+ NativeWrapper.EvtSetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigLogFilePath, (object)value);
+ }
+ }
+
+ public long MaximumSizeInBytes
+ {
+ get
+ {
+ return (long)((ulong)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigMaxSize));
+ }
+ set
+ {
+ NativeWrapper.EvtSetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigMaxSize, (object)value);
+ }
+ }
+
+ public EventLogMode LogMode
+ {
+ get
+ {
+ object nativeRetentionObject = NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigRetention);
+ object nativeAutoBackupObject = NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigAutoBackup);
+
+ bool nativeRetention = nativeRetentionObject == null ? false : (bool)nativeRetentionObject;
+ bool nativeAutoBackup = nativeAutoBackupObject == null ? false : (bool)nativeAutoBackupObject;
+
+ if (nativeAutoBackup)
+ return EventLogMode.AutoBackup;
+
+ if (nativeRetention)
+ return EventLogMode.Retain;
+
+ return EventLogMode.Circular;
+ }
+ set
+ {
+ switch (value)
+ {
+ case EventLogMode.Circular:
+ NativeWrapper.EvtSetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigAutoBackup, (object)false);
+ NativeWrapper.EvtSetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigRetention, (object)false);
+ break;
+ case EventLogMode.AutoBackup:
+ NativeWrapper.EvtSetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigAutoBackup, (object)true);
+ NativeWrapper.EvtSetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigRetention, (object)true);
+ break;
+ case EventLogMode.Retain:
+ NativeWrapper.EvtSetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigAutoBackup, (object)false);
+ NativeWrapper.EvtSetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigRetention, (object)true);
+ break;
+ }
+ }
+ }
+
+ public string OwningProviderName
+ {
+ get
+ {
+ return (string)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigOwningPublisher);
+ }
+ }
+
+ public IEnumerable<string> ProviderNames
+ {
+ get
+ {
+ return (string[])NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublisherList);
+ }
+ }
+
+ public int? ProviderLevel
+ {
+ get
+ {
+ return (int?)((uint?)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigLevel));
+ }
+ set
+ {
+ NativeWrapper.EvtSetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigLevel, (object)value);
+ }
+ }
+
+ public long? ProviderKeywords
+ {
+ get
+ {
+ return (long?)((ulong?)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigKeywords));
+ }
+ set
+ {
+ NativeWrapper.EvtSetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigKeywords, (object)value);
+ }
+ }
+
+ public int? ProviderBufferSize
+ {
+ get
+ {
+ return (int?)((uint?)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigBufferSize));
+ }
+ }
+
+ public int? ProviderMinimumNumberOfBuffers
+ {
+ get
+ {
+ return (int?)((uint?)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigMinBuffers));
+ }
+ }
+
+ public int? ProviderMaximumNumberOfBuffers
+ {
+ get
+ {
+ return (int?)((uint?)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigMaxBuffers));
+ }
+ }
+
+ public int? ProviderLatency
+ {
+ get
+ {
+ return (int?)((uint?)NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigLatency));
+ }
+ }
+
+ public Guid? ProviderControlGuid
+ {
+ get
+ {
+ return (Guid?)(NativeWrapper.EvtGetChannelConfigProperty(_handle, UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigControlGuid));
+ }
+ }
+
+ public void SaveChanges()
+ {
+ NativeWrapper.EvtSaveChannelConfig(_handle, 0);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_handle != null && !_handle.IsInvalid)
+ _handle.Dispose();
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.ComponentModel;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// describes an exception thrown from Event Log related classes.
+ /// </summary>
+ public class EventLogException : Exception
+ {
+ internal static void Throw(int errorCode)
+ {
+ switch (errorCode)
+ {
+ case 2:
+ case 3:
+ case 15007:
+ case 15027:
+ case 15028:
+ case 15002:
+ throw new EventLogNotFoundException(errorCode);
+
+ case 13:
+ case 15005:
+ throw new EventLogInvalidDataException(errorCode);
+
+ case 1818: // RPC_S_CALL_CANCELED is converted to ERROR_CANCELLED
+ case 1223:
+ throw new OperationCanceledException();
+
+ case 15037:
+ throw new EventLogProviderDisabledException(errorCode);
+
+ case 5:
+ throw new UnauthorizedAccessException();
+
+ case 15011:
+ case 15012:
+ throw new EventLogReadingException(errorCode);
+
+ default:
+ throw new EventLogException(errorCode);
+ }
+ }
+
+ public EventLogException() { }
+ public EventLogException(string message) : base(message) { }
+ public EventLogException(string message, Exception innerException) : base(message, innerException) { }
+ protected EventLogException(int errorCode) { _errorCode = errorCode; }
+
+ public override string Message
+ {
+ get
+ {
+ Win32Exception win32Exception = new Win32Exception(_errorCode);
+ return win32Exception.Message;
+ }
+ }
+
+ private int _errorCode;
+ }
+
+ /// <summary>
+ /// The object requested by the operation is not found.
+ /// </summary>
+ public class EventLogNotFoundException : EventLogException
+ {
+ public EventLogNotFoundException() { }
+ public EventLogNotFoundException(string message) : base(message) { }
+ public EventLogNotFoundException(string message, Exception innerException) : base(message, innerException) { }
+ internal EventLogNotFoundException(int errorCode) : base(errorCode) { }
+ }
+
+ /// <summary>
+ /// The state of the reader cursor has become invalid, most likely due to the fact
+ /// that the log has been cleared. User needs to obtain a new reader object if
+ /// they wish to continue navigating result set.
+ /// </summary>
+ public class EventLogReadingException : EventLogException
+ {
+ public EventLogReadingException() { }
+ public EventLogReadingException(string message) : base(message) { }
+ public EventLogReadingException(string message, Exception innerException) : base(message, innerException) { }
+ internal EventLogReadingException(int errorCode) : base(errorCode) { }
+ }
+
+ /// <summary>
+ /// Provider has been uninstalled while ProviderMetadata operations are being performed.
+ /// Obtain a new ProviderMetadata object, when provider is reinstalled, to continue navigating
+ /// provider's metadata.
+ /// </summary>
+ public class EventLogProviderDisabledException : EventLogException
+ {
+ public EventLogProviderDisabledException() { }
+ public EventLogProviderDisabledException(string message) : base(message) { }
+ public EventLogProviderDisabledException(string message, Exception innerException) : base(message, innerException) { }
+ internal EventLogProviderDisabledException(int errorCode) : base(errorCode) { }
+ }
+
+ /// <summary>
+ /// Data obtained from the eventlog service, for the current operation, is invalid .
+ /// </summary>
+ public class EventLogInvalidDataException : EventLogException
+ {
+ public EventLogInvalidDataException() { }
+ public EventLogInvalidDataException(string message) : base(message) { }
+ public EventLogInvalidDataException(string message, Exception innerException) : base(message, innerException) { }
+ internal EventLogInvalidDataException(int errorCode) : base(errorCode) { }
+ }
+}
+
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// A SafeHandle implementation over native EVT_HANDLE
+ /// obtained from EventLog Native Methods.
+ /// </summary>
+ internal sealed class EventLogHandle : SafeHandle
+ {
+ // Called by P/Invoke when returning SafeHandles
+ private EventLogHandle()
+ : base(IntPtr.Zero, true)
+ {
+ }
+
+ internal EventLogHandle(IntPtr handle, bool ownsHandle)
+ : base(IntPtr.Zero, ownsHandle)
+ {
+ SetHandle(handle);
+ }
+
+ public override bool IsInvalid
+ {
+ get
+ {
+ return IsClosed || handle == IntPtr.Zero;
+ }
+ }
+
+ protected override bool ReleaseHandle()
+ {
+ NativeWrapper.EvtClose(handle);
+ handle = IntPtr.Zero;
+ return true;
+ }
+
+ // DONT compare EventLogHandle with EventLogHandle.Zero
+ // use IsInvalid instead. Zero is provided where a NULL handle needed
+ public static EventLogHandle Zero
+ {
+ get
+ {
+ return new EventLogHandle();
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Describes the run-time properties of logs and external log files. An instance
+ /// of this class is obtained from EventLogSession.
+ /// </summary>
+ public sealed class EventLogInformation
+ {
+ internal EventLogInformation(EventLogSession session, string channelName, PathType pathType)
+ {
+ EventLogHandle logHandle = NativeWrapper.EvtOpenLog(session.Handle, channelName, pathType);
+
+ using (logHandle)
+ {
+ CreationTime = (DateTime?)NativeWrapper.EvtGetLogInfo(logHandle, UnsafeNativeMethods.EvtLogPropertyId.EvtLogCreationTime);
+ LastAccessTime = (DateTime?)NativeWrapper.EvtGetLogInfo(logHandle, UnsafeNativeMethods.EvtLogPropertyId.EvtLogLastAccessTime);
+ LastWriteTime = (DateTime?)NativeWrapper.EvtGetLogInfo(logHandle, UnsafeNativeMethods.EvtLogPropertyId.EvtLogLastWriteTime);
+ FileSize = (long?)((ulong?)NativeWrapper.EvtGetLogInfo(logHandle, UnsafeNativeMethods.EvtLogPropertyId.EvtLogFileSize));
+ Attributes = (int?)((uint?)NativeWrapper.EvtGetLogInfo(logHandle, UnsafeNativeMethods.EvtLogPropertyId.EvtLogAttributes));
+ RecordCount = (long?)((ulong?)NativeWrapper.EvtGetLogInfo(logHandle, UnsafeNativeMethods.EvtLogPropertyId.EvtLogNumberOfLogRecords));
+ OldestRecordNumber = (long?)((ulong?)NativeWrapper.EvtGetLogInfo(logHandle, UnsafeNativeMethods.EvtLogPropertyId.EvtLogOldestRecordNumber));
+ IsLogFull = (bool?)NativeWrapper.EvtGetLogInfo(logHandle, UnsafeNativeMethods.EvtLogPropertyId.EvtLogFull);
+ }
+ }
+
+ public DateTime? CreationTime { get; }
+ public DateTime? LastAccessTime { get; }
+ public DateTime? LastWriteTime { get; }
+ public long? FileSize { get; }
+ public int? Attributes { get; }
+ public long? RecordCount { get; }
+ public long? OldestRecordNumber { get; }
+ public bool? IsLogFull { get; }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Describes the metadata for a specific Log Reference defined
+ /// by a Provider. An instance of this class is obtained from
+ /// a ProviderMetadata object.
+ /// </summary>
+ public sealed class EventLogLink
+ {
+ private string _channelName;
+ private bool _isImported;
+ private string _displayName;
+ private bool _dataReady;
+ private ProviderMetadata _pmReference;
+ private object _syncObject;
+
+ internal EventLogLink(uint channelId, ProviderMetadata pmReference)
+ {
+ ChannelId = channelId;
+ _pmReference = pmReference;
+ _syncObject = new object();
+ }
+
+ internal EventLogLink(string channelName, bool isImported, string displayName, uint channelId)
+ {
+ _channelName = channelName;
+ _isImported = isImported;
+ _displayName = displayName;
+ ChannelId = channelId;
+
+ _dataReady = true;
+ _syncObject = new object();
+ }
+
+ private void PrepareData()
+ {
+ if (_dataReady == true)
+ return;
+
+ lock (_syncObject)
+ {
+ if (_dataReady == true)
+ return;
+
+ IEnumerable<EventLogLink> result = _pmReference.LogLinks;
+
+ _channelName = null;
+ _isImported = false;
+ _displayName = null;
+ _dataReady = true;
+
+ foreach (EventLogLink ch in result)
+ {
+ if (ch.ChannelId == ChannelId)
+ {
+ _channelName = ch.LogName;
+ _isImported = ch.IsImported;
+ _displayName = ch.DisplayName;
+
+ _dataReady = true;
+
+ break;
+ }
+ }
+ }
+ }
+
+ public string LogName
+ {
+ get
+ {
+ this.PrepareData();
+ return _channelName;
+ }
+ }
+
+ public bool IsImported
+ {
+ get
+ {
+ this.PrepareData();
+ return _isImported;
+ }
+ }
+
+ public string DisplayName
+ {
+ get
+ {
+ this.PrepareData();
+ return _displayName;
+ }
+ }
+
+ internal uint ChannelId { get; }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Encapsulates the information for fast access to Event Values
+ /// of an EventLogRecord. An instance of this class is constructed
+ /// and then passed to EventLogRecord.GetEventPropertyValues.
+ /// </summary>
+ public class EventLogPropertySelector : IDisposable
+ {
+ public EventLogPropertySelector(IEnumerable<string> propertyQueries)
+ {
+ if (propertyQueries == null)
+ throw new ArgumentNullException(nameof(propertyQueries));
+
+ string[] paths;
+
+ ICollection<string> coll = propertyQueries as ICollection<string>;
+ if (coll != null)
+ {
+ paths = new string[coll.Count];
+ coll.CopyTo(paths, 0);
+ }
+ else
+ {
+ List<string> queries;
+ queries = new List<string>(propertyQueries);
+ paths = queries.ToArray();
+ }
+
+ Handle = NativeWrapper.EvtCreateRenderContext(paths.Length, paths, UnsafeNativeMethods.EvtRenderContextFlags.EvtRenderContextValues);
+ }
+
+ internal EventLogHandle Handle { get; }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (Handle != null && !Handle.IsInvalid)
+ Handle.Dispose();
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Allows a user to define events of interest. An instance of this
+ /// class is passed to an EventReader to actually obtain the EventRecords.
+ /// The EventLogQuery can be as simple specifying that all events are of
+ /// interest, or it can contain query / xpath expressions that indicate exactly
+ /// what characteristics events should have.
+ /// </summary>
+ public class EventLogQuery
+ {
+ public EventLogQuery(string path, PathType pathType)
+ : this(path, pathType, null)
+ {
+ }
+
+ public EventLogQuery(string path, PathType pathType, string query)
+ {
+ Session = EventLogSession.GlobalSession;
+ Path = path; // can be null
+ ThePathType = pathType;
+
+ if (query == null)
+ {
+ if (path == null)
+ throw new ArgumentNullException(nameof(path));
+ }
+ else
+ {
+ Query = query;
+ }
+ }
+
+ public EventLogSession Session { get; set; }
+
+ public bool TolerateQueryErrors { get; set; } = false;
+
+ public bool ReverseDirection { get; set; } = false;
+
+ internal string Path { get; }
+
+ internal PathType ThePathType { get; }
+
+ internal string Query { get; }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.IO;
+using System.Collections.Generic;
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// This public class is used for reading event records from event log.
+ /// </summary>
+ public class EventLogReader : IDisposable
+ {
+ private EventLogQuery _eventQuery;
+
+ private int _batchSize;
+
+ //
+ // access to the data member reference is safe, while
+ // invoking methods on it is marked SecurityCritical as appropriate.
+ //
+ private EventLogHandle _handle;
+
+ /// <summary>
+ /// events buffer holds batched event (handles).
+ /// </summary>
+ private IntPtr[] _eventsBuffer;
+ /// <summary>
+ /// The current index where the function GetNextEvent is (inside the eventsBuffer).
+ /// </summary>
+ private int _currentIndex;
+ /// <summary>
+ /// The number of events read from the batch into the eventsBuffer
+ /// </summary>
+ private int _eventCount;
+
+ /// <summary>
+ /// When the reader finishes (will always return only ERROR_NO_MORE_ITEMS).
+ /// For subscription, this means we need to wait for next event.
+ /// </summary>
+ private bool _isEof;
+
+ /// <summary>
+ /// Maintains cached display / metadata information returned from
+ /// EventRecords that were obtained from this reader.
+ /// </summary>
+ private ProviderMetadataCachedInformation _cachedMetadataInformation;
+
+ public EventLogReader(string path)
+ : this(new EventLogQuery(path, PathType.LogName), null)
+ {
+ }
+
+ public EventLogReader(string path, PathType pathType)
+ : this(new EventLogQuery(path, pathType), null)
+ {
+ }
+
+ public EventLogReader(EventLogQuery eventQuery)
+ : this(eventQuery, null)
+ {
+ }
+
+ public EventLogReader(EventLogQuery eventQuery, EventBookmark bookmark)
+ {
+ if (eventQuery == null)
+ throw new ArgumentNullException(nameof(eventQuery));
+
+ string logfile = null;
+ if (eventQuery.ThePathType == PathType.FilePath)
+ logfile = eventQuery.Path;
+
+ _cachedMetadataInformation = new ProviderMetadataCachedInformation(eventQuery.Session, logfile, 50);
+
+ // Explicit data
+ _eventQuery = eventQuery;
+
+ // Implicit
+ _batchSize = 64;
+ _eventsBuffer = new IntPtr[_batchSize];
+
+ //
+ // compute the flag.
+ //
+ int flag = 0;
+
+ if (_eventQuery.ThePathType == PathType.LogName)
+ flag |= (int)UnsafeNativeMethods.EvtQueryFlags.EvtQueryChannelPath;
+ else
+ flag |= (int)UnsafeNativeMethods.EvtQueryFlags.EvtQueryFilePath;
+
+ if (_eventQuery.ReverseDirection)
+ flag |= (int)UnsafeNativeMethods.EvtQueryFlags.EvtQueryReverseDirection;
+
+ if (_eventQuery.TolerateQueryErrors)
+ flag |= (int)UnsafeNativeMethods.EvtQueryFlags.EvtQueryTolerateQueryErrors;
+
+ _handle = NativeWrapper.EvtQuery(_eventQuery.Session.Handle,
+ _eventQuery.Path, _eventQuery.Query,
+ flag);
+
+ EventLogHandle bookmarkHandle = EventLogRecord.GetBookmarkHandleFromBookmark(bookmark);
+
+ if (!bookmarkHandle.IsInvalid)
+ {
+ using (bookmarkHandle)
+ {
+ NativeWrapper.EvtSeek(_handle, 1, bookmarkHandle, 0, UnsafeNativeMethods.EvtSeekFlags.EvtSeekRelativeToBookmark);
+ }
+ }
+ }
+
+ public int BatchSize
+ {
+ get
+ {
+ return _batchSize;
+ }
+ set
+ {
+ if (value < 1)
+ throw new ArgumentOutOfRangeException(nameof(value));
+ _batchSize = value;
+ }
+ }
+
+ private bool GetNextBatch(TimeSpan ts)
+ {
+ int timeout = -1;
+ if (ts != TimeSpan.MaxValue)
+ timeout = (int)ts.TotalMilliseconds;
+
+ // batchSize was changed by user, reallocate buffer.
+ if (_batchSize != _eventsBuffer.Length)
+ _eventsBuffer = new IntPtr[_batchSize];
+
+ int newEventCount = 0;
+ bool results = NativeWrapper.EvtNext(_handle, _batchSize, _eventsBuffer, timeout, 0, ref newEventCount);
+
+ if (!results)
+ {
+ _eventCount = 0;
+ _currentIndex = 0;
+ return false; // No more events in the result set
+ }
+
+ _currentIndex = 0;
+ _eventCount = newEventCount;
+ return true;
+ }
+
+ public EventRecord ReadEvent()
+ {
+ return ReadEvent(TimeSpan.MaxValue);
+ }
+
+ public EventRecord ReadEvent(TimeSpan timeout)
+ {
+ if (_isEof)
+ throw new InvalidOperationException();
+
+ if (_currentIndex >= _eventCount)
+ {
+ // buffer is empty, get next batch.
+ GetNextBatch(timeout);
+
+ if (_currentIndex >= _eventCount)
+ {
+ _isEof = true;
+ return null;
+ }
+ }
+
+ EventLogRecord eventInstance = new EventLogRecord(new EventLogHandle(_eventsBuffer[_currentIndex], true), _eventQuery.Session, _cachedMetadataInformation);
+ _currentIndex++;
+ return eventInstance;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ while (_currentIndex < _eventCount)
+ {
+ NativeWrapper.EvtClose(_eventsBuffer[_currentIndex]);
+ _currentIndex++;
+ }
+
+ if (_handle != null && !_handle.IsInvalid)
+ _handle.Dispose();
+ }
+
+ internal void SeekReset()
+ {
+ //
+ // Close all unread event handles in the buffer
+ //
+ while (_currentIndex < _eventCount)
+ {
+ NativeWrapper.EvtClose(_eventsBuffer[_currentIndex]);
+ _currentIndex++;
+ }
+
+ // Reset the indexes used by Next
+ _currentIndex = 0;
+ _eventCount = 0;
+ _isEof = false;
+ }
+
+ internal void SeekCommon(long offset)
+ {
+ //
+ // modify offset that we're going to send to service to account for the
+ // fact that we've already read some events in our buffer that the user
+ // hasn't seen yet.
+ //
+ offset = offset - (_eventCount - _currentIndex);
+
+ SeekReset();
+
+ NativeWrapper.EvtSeek(_handle, offset, EventLogHandle.Zero, 0, UnsafeNativeMethods.EvtSeekFlags.EvtSeekRelativeToCurrent);
+ }
+
+ public void Seek(EventBookmark bookmark)
+ {
+ Seek(bookmark, 0);
+ }
+
+ public void Seek(EventBookmark bookmark, long offset)
+ {
+ if (bookmark == null)
+ throw new ArgumentNullException(nameof(bookmark));
+
+ SeekReset();
+ using (EventLogHandle bookmarkHandle = EventLogRecord.GetBookmarkHandleFromBookmark(bookmark))
+ {
+ NativeWrapper.EvtSeek(_handle, offset, bookmarkHandle, 0, UnsafeNativeMethods.EvtSeekFlags.EvtSeekRelativeToBookmark);
+ }
+ }
+
+ public void Seek(SeekOrigin origin, long offset)
+ {
+ switch (origin)
+ {
+ case SeekOrigin.Begin:
+
+ SeekReset();
+ NativeWrapper.EvtSeek(_handle, offset, EventLogHandle.Zero, 0, UnsafeNativeMethods.EvtSeekFlags.EvtSeekRelativeToFirst);
+ return;
+
+ case SeekOrigin.End:
+
+ SeekReset();
+ NativeWrapper.EvtSeek(_handle, offset, EventLogHandle.Zero, 0, UnsafeNativeMethods.EvtSeekFlags.EvtSeekRelativeToLast);
+ return;
+
+ case SeekOrigin.Current:
+ if (offset >= 0)
+ {
+ // We can reuse elements in the batch.
+ if (_currentIndex + offset < _eventCount)
+ {
+ //
+ // We don't call Seek here, we can reposition within the batch.
+ //
+
+ // Close all event handles between [currentIndex, currentIndex + offset)
+ int index = _currentIndex;
+ while (index < _currentIndex + offset)
+ {
+ NativeWrapper.EvtClose(_eventsBuffer[index]);
+ index++;
+ }
+
+ _currentIndex = (int)(_currentIndex + offset);
+ // Leave the eventCount unchanged
+ // Leave the same Eof
+ }
+ else
+ {
+ SeekCommon(offset);
+ }
+ }
+ else
+ {
+ SeekCommon(offset);
+ }
+ return;
+ }
+ }
+
+ public void CancelReading()
+ {
+ NativeWrapper.EvtCancel(_handle);
+ }
+
+ public IList<EventLogStatus> LogStatus
+ {
+ get
+ {
+ List<EventLogStatus> list = null;
+ string[] channelNames = null;
+ int[] errorStatuses = null;
+ EventLogHandle queryHandle = _handle;
+
+ if (queryHandle.IsInvalid)
+ throw new InvalidOperationException();
+
+ channelNames = (string[])NativeWrapper.EvtGetQueryInfo(queryHandle, UnsafeNativeMethods.EvtQueryPropertyId.EvtQueryNames);
+ errorStatuses = (int[])NativeWrapper.EvtGetQueryInfo(queryHandle, UnsafeNativeMethods.EvtQueryPropertyId.EvtQueryStatuses);
+
+ if (channelNames.Length != errorStatuses.Length)
+ throw new InvalidOperationException();
+
+ list = new List<EventLogStatus>(channelNames.Length);
+ for (int i = 0; i < channelNames.Length; i++)
+ {
+ EventLogStatus cs = new EventLogStatus(channelNames[i], errorStatuses[i]);
+ list.Add(cs);
+ }
+ return list.AsReadOnly();
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ public class EventLogRecord : EventRecord
+ {
+ private const int SYSTEM_PROPERTY_COUNT = 18;
+ private EventLogSession _session;
+
+ private NativeWrapper.SystemProperties _systemProperties;
+ private string _containerChannel;
+ private int[] _matchedQueryIds;
+
+ // A dummy object which is used only for the locking.
+ private object _syncObject;
+
+ // Cached DisplayNames for each instance
+ private string _levelName = null;
+ private string _taskName = null;
+ private string _opcodeName = null;
+ private IEnumerable<string> _keywordsNames = null;
+
+ // Cached DisplayNames for each instance
+ private bool _levelNameReady;
+ private bool _taskNameReady;
+ private bool _opcodeNameReady;
+
+ private ProviderMetadataCachedInformation _cachedMetadataInformation;
+
+ internal EventLogRecord(EventLogHandle handle, EventLogSession session, ProviderMetadataCachedInformation cachedMetadataInfo)
+ {
+ _cachedMetadataInformation = cachedMetadataInfo;
+ Handle = handle;
+ _session = session;
+ _systemProperties = new NativeWrapper.SystemProperties();
+ _syncObject = new object();
+ }
+
+ internal EventLogHandle Handle
+ {
+ get;
+ }
+
+ internal void PrepareSystemData()
+ {
+ if (_systemProperties.filled)
+ return;
+
+ // Prepare the System Context, if it is not already initialized.
+ _session.SetupSystemContext();
+
+ lock (_syncObject)
+ {
+ if (_systemProperties.filled == false)
+ {
+ NativeWrapper.EvtRenderBufferWithContextSystem(_session.renderContextHandleSystem, Handle, UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventValues, _systemProperties, SYSTEM_PROPERTY_COUNT);
+ _systemProperties.filled = true;
+ }
+ }
+ }
+
+ public override int Id
+ {
+ get
+ {
+ PrepareSystemData();
+ if (_systemProperties.Id == null)
+ return 0;
+ return (int)_systemProperties.Id;
+ }
+ }
+
+ public override byte? Version
+ {
+ get
+ {
+ PrepareSystemData();
+ return _systemProperties.Version;
+ }
+ }
+
+ public override int? Qualifiers
+ {
+ get
+ {
+ PrepareSystemData();
+ return (int?)(uint?)_systemProperties.Qualifiers;
+ }
+ }
+
+ public override byte? Level
+ {
+ get
+ {
+ PrepareSystemData();
+ return _systemProperties.Level;
+ }
+ }
+
+ public override int? Task
+ {
+ get
+ {
+ PrepareSystemData();
+ return (int?)(uint?)_systemProperties.Task;
+ }
+ }
+
+ public override short? Opcode
+ {
+ get
+ {
+ PrepareSystemData();
+ return (short?)(ushort?)_systemProperties.Opcode;
+ }
+ }
+
+ public override long? Keywords
+ {
+ get
+ {
+ PrepareSystemData();
+ return (long?)_systemProperties.Keywords;
+ }
+ }
+
+ public override long? RecordId
+ {
+ get
+ {
+ PrepareSystemData();
+ return (long?)_systemProperties.RecordId;
+ }
+ }
+
+ public override string ProviderName
+ {
+ get
+ {
+ PrepareSystemData();
+ return _systemProperties.ProviderName;
+ }
+ }
+
+ public override Guid? ProviderId
+ {
+ get
+ {
+ PrepareSystemData();
+ return _systemProperties.ProviderId;
+ }
+ }
+
+ public override string LogName
+ {
+ get
+ {
+ PrepareSystemData();
+ return _systemProperties.ChannelName;
+ }
+ }
+
+ public override int? ProcessId
+ {
+ get
+ {
+ PrepareSystemData();
+ return (int?)_systemProperties.ProcessId;
+ }
+ }
+
+ public override int? ThreadId
+ {
+ get
+ {
+ PrepareSystemData();
+ return (int?)_systemProperties.ThreadId;
+ }
+ }
+
+ public override string MachineName
+ {
+ get
+ {
+ PrepareSystemData();
+ return _systemProperties.ComputerName;
+ }
+ }
+
+ public override System.Security.Principal.SecurityIdentifier UserId
+ {
+ get
+ {
+ PrepareSystemData();
+ return _systemProperties.UserId;
+ }
+ }
+
+ public override DateTime? TimeCreated
+ {
+ get
+ {
+ PrepareSystemData();
+ return _systemProperties.TimeCreated;
+ }
+ }
+
+ public override Guid? ActivityId
+ {
+ get
+ {
+ PrepareSystemData();
+ return _systemProperties.ActivityId;
+ }
+ }
+
+ public override Guid? RelatedActivityId
+ {
+ get
+ {
+ PrepareSystemData();
+ return _systemProperties.RelatedActivityId;
+ }
+ }
+
+ public string ContainerLog
+ {
+ get
+ {
+ if (_containerChannel != null)
+ return _containerChannel;
+ lock (_syncObject)
+ {
+ if (_containerChannel == null)
+ {
+ _containerChannel = (string)NativeWrapper.EvtGetEventInfo(this.Handle, UnsafeNativeMethods.EvtEventPropertyId.EvtEventPath);
+ }
+ return _containerChannel;
+ }
+ }
+ }
+
+ public IEnumerable<int> MatchedQueryIds
+ {
+ get
+ {
+ if (_matchedQueryIds != null)
+ return _matchedQueryIds;
+ lock (_syncObject)
+ {
+ if (_matchedQueryIds == null)
+ {
+ _matchedQueryIds = (int[])NativeWrapper.EvtGetEventInfo(this.Handle, UnsafeNativeMethods.EvtEventPropertyId.EvtEventQueryIDs);
+ }
+ return _matchedQueryIds;
+ }
+ }
+ }
+
+ public override EventBookmark Bookmark
+ {
+ get
+ {
+ EventLogHandle bookmarkHandle = NativeWrapper.EvtCreateBookmark(null);
+ NativeWrapper.EvtUpdateBookmark(bookmarkHandle, Handle);
+ string bookmarkText = NativeWrapper.EvtRenderBookmark(bookmarkHandle);
+
+ return new EventBookmark(bookmarkText);
+ }
+ }
+
+ public override string FormatDescription()
+ {
+ return _cachedMetadataInformation.GetFormatDescription(this.ProviderName, Handle);
+ }
+
+ public override string FormatDescription(IEnumerable<object> values)
+ {
+ if (values == null)
+ return this.FormatDescription();
+
+ // Copy the value IEnumerable to an array.
+ string[] theValues = new string[0];
+ int i = 0;
+ foreach (object o in values)
+ {
+ if (theValues.Length == i)
+ Array.Resize(ref theValues, i + 1);
+ theValues[i] = o.ToString();
+ i++;
+ }
+
+ return _cachedMetadataInformation.GetFormatDescription(this.ProviderName, Handle, theValues);
+ }
+
+ public override string LevelDisplayName
+ {
+ get
+ {
+ if (_levelNameReady)
+ return _levelName;
+ lock (_syncObject)
+ {
+ if (_levelNameReady == false)
+ {
+ _levelNameReady = true;
+ _levelName = _cachedMetadataInformation.GetLevelDisplayName(this.ProviderName, Handle);
+ }
+ return _levelName;
+ }
+ }
+ }
+
+ public override string OpcodeDisplayName
+ {
+ get
+ {
+ lock (_syncObject)
+ {
+ if (_opcodeNameReady == false)
+ {
+ _opcodeNameReady = true;
+ _opcodeName = _cachedMetadataInformation.GetOpcodeDisplayName(this.ProviderName, Handle);
+ }
+ return _opcodeName;
+ }
+ }
+ }
+
+ public override string TaskDisplayName
+ {
+ get
+ {
+ if (_taskNameReady == true)
+ return _taskName;
+ lock (_syncObject)
+ {
+ if (_taskNameReady == false)
+ {
+ _taskNameReady = true;
+ _taskName = _cachedMetadataInformation.GetTaskDisplayName(this.ProviderName, Handle);
+ }
+ return _taskName;
+ }
+ }
+ }
+
+ public override IEnumerable<string> KeywordsDisplayNames
+ {
+ get
+ {
+ if (_keywordsNames != null)
+ return _keywordsNames;
+ lock (_syncObject)
+ {
+ if (_keywordsNames == null)
+ {
+ _keywordsNames = _cachedMetadataInformation.GetKeywordDisplayNames(this.ProviderName, Handle);
+ }
+ return _keywordsNames;
+ }
+ }
+ }
+
+ public override IList<EventProperty> Properties
+ {
+ get
+ {
+ _session.SetupUserContext();
+ IList<object> properties = NativeWrapper.EvtRenderBufferWithContextUserOrValues(_session.renderContextHandleUser, Handle);
+ List<EventProperty> list = new List<EventProperty>();
+ foreach (object value in properties)
+ {
+ list.Add(new EventProperty(value));
+ }
+ return list;
+ }
+ }
+
+ public IList<object> GetPropertyValues(EventLogPropertySelector propertySelector)
+ {
+ if (propertySelector == null)
+ throw new ArgumentNullException(nameof(propertySelector));
+ return NativeWrapper.EvtRenderBufferWithContextUserOrValues(propertySelector.Handle, Handle);
+ }
+
+ public override string ToXml()
+ {
+ StringBuilder renderBuffer = new StringBuilder(2000);
+ NativeWrapper.EvtRender(EventLogHandle.Zero, Handle, UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventXml, renderBuffer);
+ return renderBuffer.ToString();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ try
+ {
+ if (Handle != null && !Handle.IsInvalid)
+ Handle.Dispose();
+ }
+ finally
+ {
+ base.Dispose(disposing);
+ }
+ }
+
+ internal static EventLogHandle GetBookmarkHandleFromBookmark(EventBookmark bookmark)
+ {
+ if (bookmark == null)
+ return EventLogHandle.Zero;
+ EventLogHandle handle = NativeWrapper.EvtCreateBookmark(bookmark.BookmarkText);
+ return handle;
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Security;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Session Login Type
+ /// </summary>
+ public enum SessionAuthentication
+ {
+ Default = 0,
+ Negotiate = 1,
+ Kerberos = 2,
+ Ntlm = 3
+ }
+
+ /// <summary>
+ /// The type: log / external log file to query
+ /// </summary>
+ public enum PathType
+ {
+ LogName = 1,
+ FilePath = 2
+ }
+
+ /// <summary>
+ /// Defines a session for Event Log operations. The session can
+ /// be configured for a remote machine and can use specific
+ /// user credentials.
+ /// </summary>
+ public class EventLogSession : IDisposable
+ {
+ //
+ // the two context handles for rendering (for EventLogRecord).
+ // the system and user context handles. They are both common for all the event instances and can be created only once.
+ // access to the data member references is safe, while
+ // invoking methods on it is marked SecurityCritical as appropriate.
+ //
+ internal EventLogHandle renderContextHandleSystem = EventLogHandle.Zero;
+ internal EventLogHandle renderContextHandleUser = EventLogHandle.Zero;
+
+ // The dummy sync object for the two contexts.
+ private object _syncObject = null;
+
+ private string _server;
+ private string _user;
+ private string _domain;
+ private SessionAuthentication _logOnType;
+
+ // Setup the System Context, once for all the EventRecords.
+ internal void SetupSystemContext()
+ {
+ if (!this.renderContextHandleSystem.IsInvalid)
+ return;
+ lock (_syncObject)
+ {
+ if (this.renderContextHandleSystem.IsInvalid)
+ {
+ // Create the SYSTEM render context
+ // Call the EvtCreateRenderContext to get the renderContextHandleSystem, so that we can get the system/values/user properties.
+ this.renderContextHandleSystem = NativeWrapper.EvtCreateRenderContext(0, null, UnsafeNativeMethods.EvtRenderContextFlags.EvtRenderContextSystem);
+ }
+ }
+ }
+
+ internal void SetupUserContext()
+ {
+ lock (_syncObject)
+ {
+ if (this.renderContextHandleUser.IsInvalid)
+ {
+ // Create the USER render context
+ this.renderContextHandleUser = NativeWrapper.EvtCreateRenderContext(0, null, UnsafeNativeMethods.EvtRenderContextFlags.EvtRenderContextUser);
+ }
+ }
+ }
+
+ public EventLogSession()
+ {
+ // handle = EventLogHandle.Zero;
+ _syncObject = new object();
+ }
+
+ public EventLogSession(string server)
+ :
+ this(server, null, null, (SecureString)null, SessionAuthentication.Default)
+ {
+ }
+
+ public EventLogSession(string server, string domain, string user, SecureString password, SessionAuthentication logOnType)
+ {
+ if (server == null)
+ server = "localhost";
+
+ _syncObject = new object();
+
+ _server = server;
+ _domain = domain;
+ _user = user;
+ _logOnType = logOnType;
+
+ UnsafeNativeMethods.EvtRpcLogin erLogin = new UnsafeNativeMethods.EvtRpcLogin();
+ erLogin.Server = _server;
+ erLogin.User = _user;
+ erLogin.Domain = _domain;
+ erLogin.Flags = (int)_logOnType;
+ erLogin.Password = CoTaskMemUnicodeSafeHandle.Zero;
+
+ try
+ {
+ if (password != null)
+ erLogin.Password.SetMemory(SecureStringMarshal.SecureStringToCoTaskMemUnicode(password));
+ // Open a session using the erLogin structure.
+ Handle = NativeWrapper.EvtOpenSession(UnsafeNativeMethods.EvtLoginClass.EvtRpcLogin, ref erLogin, 0, 0);
+ }
+ finally
+ {
+ erLogin.Password.Dispose();
+ }
+ }
+
+ internal EventLogHandle Handle { get; } = EventLogHandle.Zero;
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (this == s_globalSession)
+ throw new InvalidOperationException();
+ }
+
+ if (this.renderContextHandleSystem != null &&
+ !this.renderContextHandleSystem.IsInvalid)
+ this.renderContextHandleSystem.Dispose();
+
+ if (this.renderContextHandleUser != null &&
+ !this.renderContextHandleUser.IsInvalid)
+ this.renderContextHandleUser.Dispose();
+
+ if (Handle != null && !Handle.IsInvalid)
+ Handle.Dispose();
+ }
+
+ public void CancelCurrentOperations()
+ {
+ NativeWrapper.EvtCancel(Handle);
+ }
+
+ private static EventLogSession s_globalSession = new EventLogSession();
+ public static EventLogSession GlobalSession
+ {
+ get { return s_globalSession; }
+ }
+
+ public IEnumerable<string> GetProviderNames()
+ {
+ List<string> namesList = new List<string>(100);
+
+ using (EventLogHandle ProviderEnum = NativeWrapper.EvtOpenProviderEnum(this.Handle, 0))
+ {
+ bool finish = false;
+
+ do
+ {
+ string s = NativeWrapper.EvtNextPublisherId(ProviderEnum, ref finish);
+ if (finish == false)
+ namesList.Add(s);
+ }
+ while (finish == false);
+
+ return namesList;
+ }
+ }
+
+ public IEnumerable<string> GetLogNames()
+ {
+ List<string> namesList = new List<string>(100);
+
+ using (EventLogHandle channelEnum = NativeWrapper.EvtOpenChannelEnum(this.Handle, 0))
+ {
+ bool finish = false;
+
+ do
+ {
+ string s = NativeWrapper.EvtNextChannelPath(channelEnum, ref finish);
+ if (finish == false)
+ namesList.Add(s);
+ }
+ while (finish == false);
+
+ return namesList;
+ }
+ }
+
+ public EventLogInformation GetLogInformation(string logName, PathType pathType)
+ {
+ if (logName == null)
+ throw new ArgumentNullException(nameof(logName));
+
+ return new EventLogInformation(this, logName, pathType);
+ }
+
+ public void ExportLog(string path, PathType pathType, string query, string targetFilePath)
+ {
+ this.ExportLog(path, pathType, query, targetFilePath, false);
+ }
+
+ public void ExportLog(string path, PathType pathType, string query, string targetFilePath, bool tolerateQueryErrors)
+ {
+ if (path == null)
+ throw new ArgumentNullException(nameof(path));
+
+ if (targetFilePath == null)
+ throw new ArgumentNullException(nameof(targetFilePath));
+
+ UnsafeNativeMethods.EvtExportLogFlags flag;
+ switch (pathType)
+ {
+ case PathType.LogName:
+ flag = UnsafeNativeMethods.EvtExportLogFlags.EvtExportLogChannelPath;
+ break;
+ case PathType.FilePath:
+ flag = UnsafeNativeMethods.EvtExportLogFlags.EvtExportLogFilePath;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(pathType));
+ }
+
+ if (tolerateQueryErrors == false)
+ NativeWrapper.EvtExportLog(this.Handle, path, query, targetFilePath, (int)flag);
+ else
+ NativeWrapper.EvtExportLog(this.Handle, path, query, targetFilePath, (int)flag | (int)UnsafeNativeMethods.EvtExportLogFlags.EvtExportLogTolerateQueryErrors);
+ }
+
+ public void ExportLogAndMessages(string path, PathType pathType, string query, string targetFilePath)
+ {
+ this.ExportLogAndMessages(path, pathType, query, targetFilePath, false, CultureInfo.CurrentCulture);
+ }
+
+ public void ExportLogAndMessages(string path, PathType pathType, string query, string targetFilePath, bool tolerateQueryErrors, CultureInfo targetCultureInfo)
+ {
+ if (targetCultureInfo == null)
+ targetCultureInfo = CultureInfo.CurrentCulture;
+ ExportLog(path, pathType, query, targetFilePath, tolerateQueryErrors);
+ // Ignore the CultureInfo, pass 0 to use the calling thread's locale
+ NativeWrapper.EvtArchiveExportedLog(this.Handle, targetFilePath, 0, 0);
+ }
+
+ public void ClearLog(string logName)
+ {
+ this.ClearLog(logName, null);
+ }
+
+ public void ClearLog(string logName, string backupPath)
+ {
+ if (logName == null)
+ throw new ArgumentNullException(nameof(logName));
+
+ NativeWrapper.EvtClearLog(this.Handle, logName, backupPath, 0);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Describes the status of a particular log with respect to
+ /// an instantiated EventLogReader. Since it is possible to
+ /// instantiate an EventLogReader with a query containing
+ /// multiple logs and the reader can be configured to tolerate
+ /// errors in attaching to those logs, this class allows the
+ /// user to determine exactly what the status of those logs is.
+ /// </summary>
+ public sealed class EventLogStatus
+ {
+ internal EventLogStatus(string channelName, int win32ErrorCode)
+ {
+ LogName = channelName;
+ StatusCode = win32ErrorCode;
+ }
+
+ public string LogName { get; }
+
+ public int StatusCode { get; }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Threading;
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Used for subscribing to event record notifications from
+ /// event log.
+ /// </summary>
+ public class EventLogWatcher : IDisposable
+ {
+ public event EventHandler<EventRecordWrittenEventArgs> EventRecordWritten;
+
+ private EventLogQuery _eventQuery;
+ private EventBookmark _bookmark;
+ private bool _readExistingEvents;
+
+ private EventLogHandle _handle;
+ private IntPtr[] _eventsBuffer;
+ private int _numEventsInBuffer;
+ private bool _isSubscribing;
+ private int _callbackThreadId;
+ private AutoResetEvent _subscriptionWaitHandle;
+ private AutoResetEvent _unregisterDoneHandle;
+ private RegisteredWaitHandle _registeredWaitHandle;
+
+ /// <summary>
+ /// Maintains cached display / metadata information returned from
+ /// EventRecords that were obtained from this reader.
+ /// </summary>
+ private ProviderMetadataCachedInformation cachedMetadataInformation;
+ private EventLogException asyncException;
+
+ public EventLogWatcher(string path)
+ : this(new EventLogQuery(path, PathType.LogName), null, false)
+ {
+ }
+
+ public EventLogWatcher(EventLogQuery eventQuery)
+ : this(eventQuery, null, false)
+ {
+ }
+
+ public EventLogWatcher(EventLogQuery eventQuery, EventBookmark bookmark)
+ : this(eventQuery, bookmark, false)
+ {
+ }
+
+ public EventLogWatcher(EventLogQuery eventQuery, EventBookmark bookmark, bool readExistingEvents)
+ {
+
+ if (eventQuery == null)
+ {
+ throw new ArgumentNullException(nameof(eventQuery));
+ }
+
+ if (bookmark != null)
+ {
+ readExistingEvents = false;
+ }
+
+ // Explicit data
+ _eventQuery = eventQuery;
+ _readExistingEvents = readExistingEvents;
+
+ if (_eventQuery.ReverseDirection)
+ {
+ throw new InvalidOperationException();
+ }
+
+ _eventsBuffer = new IntPtr[64];
+ cachedMetadataInformation = new ProviderMetadataCachedInformation(eventQuery.Session, null, 50);
+ _bookmark = bookmark;
+ }
+
+ public bool Enabled
+ {
+ get
+ {
+ return _isSubscribing;
+ }
+ set
+ {
+ if (value && !_isSubscribing)
+ {
+ StartSubscribing();
+ }
+ else if (!value && _isSubscribing)
+ {
+ StopSubscribing();
+ }
+ }
+ }
+
+ internal void StopSubscribing()
+ {
+ // C:\public\System.Diagnostics.Eventing\Microsoft\Win32\SafeHandles;
+
+ // Need to set isSubscribing to false before waiting for completion of callback.
+ _isSubscribing = false;
+
+ if (_registeredWaitHandle != null)
+ {
+
+ _registeredWaitHandle.Unregister(_unregisterDoneHandle);
+
+ if (_callbackThreadId != Thread.CurrentThread.ManagedThreadId)
+ {
+ // Not calling Stop from within callback - wait for
+ // Any outstanding callbacks to complete.
+ if (_unregisterDoneHandle != null)
+ {
+ _unregisterDoneHandle.WaitOne();
+ }
+ }
+
+ _registeredWaitHandle = null;
+ }
+
+ if (_unregisterDoneHandle != null)
+ {
+ _unregisterDoneHandle.Close();
+ _unregisterDoneHandle = null;
+ }
+
+ if (_subscriptionWaitHandle != null)
+ {
+ _subscriptionWaitHandle.Close();
+ _subscriptionWaitHandle = null;
+ }
+
+ for (int i = 0; i < _numEventsInBuffer; i++)
+ {
+
+ if (_eventsBuffer[i] != IntPtr.Zero)
+ {
+ UnsafeNativeMethods.EvtClose(_eventsBuffer[i]);
+ _eventsBuffer[i] = IntPtr.Zero;
+ }
+ }
+
+ _numEventsInBuffer = 0;
+
+ if (_handle != null && !_handle.IsInvalid)
+ {
+ _handle.Dispose();
+ }
+ }
+
+ internal void StartSubscribing()
+ {
+ if (_isSubscribing)
+ {
+ throw new InvalidOperationException();
+ }
+
+ int flag = 0;
+ if (_bookmark != null)
+ {
+ flag |= (int)UnsafeNativeMethods.EvtSubscribeFlags.EvtSubscribeStartAfterBookmark;
+ }
+ else if (_readExistingEvents)
+ {
+ flag |= (int)UnsafeNativeMethods.EvtSubscribeFlags.EvtSubscribeStartAtOldestRecord;
+ }
+ else
+ {
+ flag |= (int)UnsafeNativeMethods.EvtSubscribeFlags.EvtSubscribeToFutureEvents;
+ }
+
+ if (_eventQuery.TolerateQueryErrors)
+ {
+ flag |= (int)UnsafeNativeMethods.EvtSubscribeFlags.EvtSubscribeTolerateQueryErrors;
+ }
+
+ // C:\public\System.Diagnostics.Eventing\Microsoft\Win32\SafeHandles;
+
+ _callbackThreadId = -1;
+ _unregisterDoneHandle = new AutoResetEvent(false);
+ _subscriptionWaitHandle = new AutoResetEvent(false);
+
+ EventLogHandle bookmarkHandle = EventLogRecord.GetBookmarkHandleFromBookmark(_bookmark);
+
+ using (bookmarkHandle)
+ {
+
+ _handle = UnsafeNativeMethods.EvtSubscribe(_eventQuery.Session.Handle,
+ _subscriptionWaitHandle.SafeWaitHandle,
+ _eventQuery.Path,
+ _eventQuery.Query,
+ bookmarkHandle,
+ IntPtr.Zero,
+ IntPtr.Zero,
+ flag);
+ }
+
+ _isSubscribing = true;
+
+ RequestEvents();
+
+ _registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(
+ _subscriptionWaitHandle,
+ new WaitOrTimerCallback(SubscribedEventsAvailableCallback),
+ null,
+ -1,
+ false);
+ }
+
+ internal void SubscribedEventsAvailableCallback(object state, bool timedOut)
+ {
+ _callbackThreadId = Thread.CurrentThread.ManagedThreadId;
+ try
+ {
+ RequestEvents();
+ }
+ finally
+ {
+ _callbackThreadId = -1;
+ }
+ }
+
+ private void RequestEvents()
+ {
+ // C:\public\System.Diagnostics.Eventing\Microsoft\Win32\SafeHandles;
+
+ asyncException = null;
+ Debug.Assert(_numEventsInBuffer == 0);
+
+ bool results = false;
+
+ do
+ {
+ if (!_isSubscribing)
+ {
+ break;
+ }
+
+ try
+ {
+ results = NativeWrapper.EvtNext(_handle, _eventsBuffer.Length, _eventsBuffer, 0, 0, ref _numEventsInBuffer);
+
+ if (!results)
+ {
+ return;
+ }
+ }
+ catch (Exception e)
+ {
+ asyncException = new EventLogException();
+ asyncException.Data.Add("RealException", e);
+ }
+
+ HandleEventsRequestCompletion();
+
+ } while (results);
+ }
+
+ private void IssueCallback(EventRecordWrittenEventArgs eventArgs)
+ {
+ if (EventRecordWritten != null)
+ {
+ EventRecordWritten(this, eventArgs);
+ }
+ }
+
+ private void HandleEventsRequestCompletion()
+ {
+ if (asyncException != null)
+ {
+ EventRecordWrittenEventArgs args = new EventRecordWrittenEventArgs(asyncException.Data["RealException"] as Exception);
+ IssueCallback(args);
+ }
+
+ for (int i = 0; i < _numEventsInBuffer; i++)
+ {
+ if (!_isSubscribing)
+ {
+ break;
+ }
+
+ EventLogRecord record = new EventLogRecord(new EventLogHandle(_eventsBuffer[i], true), _eventQuery.Session, cachedMetadataInformation);
+ EventRecordWrittenEventArgs args = new EventRecordWrittenEventArgs(record);
+ _eventsBuffer[i] = IntPtr.Zero; // user is responsible for calling Dispose().
+ IssueCallback(args);
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ StopSubscribing();
+ return;
+ }
+
+ for (int i = 0; i < _numEventsInBuffer; i++)
+ {
+
+ if (_eventsBuffer[i] != IntPtr.Zero)
+ {
+ NativeWrapper.EvtClose(_eventsBuffer[i]);
+ _eventsBuffer[i] = IntPtr.Zero;
+ }
+ }
+
+ _numEventsInBuffer = 0;
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Event Metadata
+ /// </summary>
+ public sealed class EventMetadata
+ {
+ private byte _channelId;
+ private byte _level;
+ private short _opcode;
+ private int _task;
+ private long _keywords;
+ private ProviderMetadata _pmReference;
+
+ internal EventMetadata(uint id, byte version, byte channelId,
+ byte level, byte opcode, short task, long keywords,
+ string template, string description, ProviderMetadata pmReference)
+ {
+ Id = id;
+ Version = version;
+ _channelId = channelId;
+ _level = level;
+ _opcode = opcode;
+ _task = task;
+ _keywords = keywords;
+ Template = template;
+ Description = description;
+ _pmReference = pmReference;
+ }
+
+ //
+ // Max value will be UINT32.MaxValue - it is a long because this property
+ // is really a UINT32. The legacy API allows event message ids to be declared
+ // as UINT32 and these event/messages may be migrated into a Provider's
+ // manifest as UINT32. Note that EventRecord ids are
+ // still declared as int, because those ids max value is UINT16.MaxValue
+ // and rest of the bits of the legacy event id would be stored in
+ // Qualifiers property.
+ //
+ public long Id { get; }
+
+ public byte Version { get; }
+
+ public EventLogLink LogLink
+ {
+ get
+ {
+ return new EventLogLink((uint)_channelId, _pmReference);
+ }
+ }
+
+ public EventLevel Level
+ {
+ get
+ {
+ return new EventLevel(_level, _pmReference);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Opcode", Justification = "matell: Shipped public in 3.5, breaking change to fix now.")]
+ public EventOpcode Opcode
+ {
+ get
+ {
+ return new EventOpcode(_opcode, _pmReference);
+ }
+ }
+
+ public EventTask Task
+ {
+ get
+ {
+ return new EventTask(_task, _pmReference);
+ }
+ }
+
+ public IEnumerable<EventKeyword> Keywords
+ {
+ get
+ {
+ List<EventKeyword> list = new List<EventKeyword>();
+
+ ulong theKeywords = unchecked((ulong)_keywords);
+ ulong mask = 0x8000000000000000;
+
+ // For every bit
+ // for (int i = 0; i < 64 && theKeywords != 0; i++)
+ for (int i = 0; i < 64; i++)
+ {
+ // If this bit is set
+ if ((theKeywords & mask) > 0)
+ {
+ // The mask is the keyword we will be searching for.
+ list.Add(new EventKeyword(unchecked((long)mask), _pmReference));
+ // theKeywords = theKeywords - mask;
+ }
+ // Modify the mask to check next bit.
+ mask = mask >> 1;
+ }
+
+ return list;
+ }
+ }
+
+ public string Template { get; }
+
+ public string Description { get; }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// The metadata for a specific Opcode defined by a Provider.
+ /// An instance of this class is obtained from a ProviderMetadata object.
+ /// </summary>
+ [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Opcode", Justification = "matell: Shipped public in 3.5, breaking change to fix now.")]
+ public sealed class EventOpcode
+ {
+ private int _value;
+ private string _name;
+ private string _displayName;
+ private bool _dataReady;
+ private ProviderMetadata _pmReference;
+ private object _syncObject;
+
+ internal EventOpcode(int value, ProviderMetadata pmReference)
+ {
+ _value = value;
+ _pmReference = pmReference;
+ _syncObject = new object();
+ }
+
+ internal EventOpcode(string name, int value, string displayName)
+ {
+ _value = value;
+ _name = name;
+ _displayName = displayName;
+ _dataReady = true;
+ _syncObject = new object();
+ }
+
+ internal void PrepareData()
+ {
+ lock (_syncObject)
+ {
+ if (_dataReady == true)
+ return;
+
+ // Get the data
+ IEnumerable<EventOpcode> result = _pmReference.Opcodes;
+ // Set the names and display names to null
+ _name = null;
+ _displayName = null;
+ _dataReady = true;
+ foreach (EventOpcode op in result)
+ {
+ if (op.Value == _value)
+ {
+ _name = op.Name;
+ _displayName = op.DisplayName;
+ _dataReady = true;
+ break;
+ }
+ }
+ }
+ } // End Prepare Data
+
+ public string Name
+ {
+ get
+ {
+ PrepareData();
+ return _name;
+ }
+ }
+
+ public int Value
+ {
+ get
+ {
+ return _value;
+ }
+ }
+
+ public string DisplayName
+ {
+ get
+ {
+ PrepareData();
+ return _displayName;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ public sealed class EventProperty
+ {
+ internal EventProperty(object value)
+ {
+ Value = value;
+ }
+
+ public object Value { get; }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Security.Principal;
+using System.Diagnostics.CodeAnalysis;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Represents an event obtained from an EventReader.
+ /// </summary>
+ public abstract class EventRecord : IDisposable
+ {
+ public abstract int Id { get; }
+ public abstract byte? Version { get; }
+ public abstract byte? Level { get; }
+ public abstract int? Task { get; }
+
+ [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Opcode", Justification = "matell: Shipped public in 3.5, breaking change to fix now.")]
+ public abstract short? Opcode { get; }
+ public abstract long? Keywords { get; }
+
+ public abstract long? RecordId { get; }
+
+ public abstract string ProviderName { get; }
+ public abstract Guid? ProviderId { get; }
+ public abstract string LogName { get; }
+
+ public abstract int? ProcessId { get; }
+ public abstract int? ThreadId { get; }
+ public abstract string MachineName { get; }
+ public abstract SecurityIdentifier UserId { get; }
+ public abstract DateTime? TimeCreated { get; }
+
+ public abstract Guid? ActivityId { get; }
+ public abstract Guid? RelatedActivityId { get; }
+ public abstract int? Qualifiers { get; }
+
+ public abstract string FormatDescription();
+ public abstract string FormatDescription(IEnumerable<object> values);
+
+ public abstract string LevelDisplayName { get; }
+
+ [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Opcode", Justification = "matell: Shipped public in 3.5, breaking change to fix now.")]
+ public abstract string OpcodeDisplayName { get; }
+ public abstract string TaskDisplayName { get; }
+ public abstract IEnumerable<string> KeywordsDisplayNames { get; }
+
+ public abstract EventBookmark Bookmark { get; }
+
+ public abstract IList<EventProperty> Properties { get; }
+
+ public abstract string ToXml();
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ protected virtual void Dispose(bool disposing) { }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// The custom event handler args.
+ /// </summary>
+ public sealed class EventRecordWrittenEventArgs : EventArgs
+ {
+ internal EventRecordWrittenEventArgs(EventLogRecord record) { EventRecord = record; }
+ internal EventRecordWrittenEventArgs(Exception exception) { EventException = exception; }
+
+ /// <summary>
+ /// The EventRecord being notified.
+ /// NOTE: If non null, then caller is required to call Dispose().
+ /// </summary>
+ public EventRecord EventRecord { get; }
+
+ /// <summary>
+ /// If any error occured during subscription, this will be non-null.
+ /// After a notification containing an exception, no more notifications will
+ /// be made for this subscription.
+ /// </summary>
+ public Exception EventException { get; }
+ }
+
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// Describes the metadata for a specific Task defined by a Provider.
+ /// An instance of this class is obtained from a ProviderMetadata object.
+ /// </summary>
+ public sealed class EventTask
+ {
+ private string _name;
+ private string _displayName;
+ private Guid _guid;
+ private bool _dataReady;
+ private ProviderMetadata _pmReference;
+ private object _syncObject;
+
+ internal EventTask(int value, ProviderMetadata pmReference)
+ {
+ Value = value;
+ _pmReference = pmReference;
+ _syncObject = new object();
+ }
+
+ internal EventTask(string name, int value, string displayName, Guid guid)
+ {
+ Value = value;
+ _name = name;
+ _displayName = displayName;
+ _guid = guid;
+ _dataReady = true;
+ _syncObject = new object();
+ }
+
+ internal void PrepareData()
+ {
+ lock (_syncObject)
+ {
+ if (_dataReady == true)
+ return;
+
+ IEnumerable<EventTask> result = _pmReference.Tasks;
+
+ _name = null;
+ _displayName = null;
+ _guid = Guid.Empty;
+ _dataReady = true;
+
+ foreach (EventTask task in result)
+ {
+ if (task.Value == Value)
+ {
+ _name = task.Name;
+ _displayName = task.DisplayName;
+ _guid = task.EventGuid;
+ _dataReady = true;
+ break;
+ }
+ }
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ PrepareData();
+ return _name;
+ }
+ }
+
+ public int Value { get; }
+
+ public string DisplayName
+ {
+ get
+ {
+ PrepareData();
+ return _displayName;
+ }
+ }
+
+ public Guid EventGuid
+ {
+ get
+ {
+ PrepareData();
+ return _guid;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Security.Principal;
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// This internal class contains wrapper methods over the Native
+ /// Methods of the Eventlog API. Unlike the raw Native Methods,
+ /// these methods throw EventLogExceptions, check platform
+ /// availability and perform additional helper functionality
+ /// specific to function. Also, all methods of this class expose
+ /// the Link Demand for Unmanaged Permission to callers.
+ /// </summary>
+ internal class NativeWrapper
+ {
+ public class SystemProperties
+ {
+ // Indicates if the SystemProperties values were already computed (for this event Instance, surely).
+ public bool filled = false;
+
+ public ushort? Id = null;
+ public byte? Version = null;
+ public ushort? Qualifiers = null;
+ public byte? Level = null;
+ public ushort? Task = null;
+ public byte? Opcode = null;
+ public ulong? Keywords = null;
+ public ulong? RecordId = null;
+ public string ProviderName = null;
+ public Guid? ProviderId = null;
+ public string ChannelName = null;
+ public uint? ProcessId = null;
+ public uint? ThreadId = null;
+ public string ComputerName = null;
+ public System.Security.Principal.SecurityIdentifier UserId = null;
+ public DateTime? TimeCreated = null;
+ public Guid? ActivityId = null;
+ public Guid? RelatedActivityId = null;
+
+ public SystemProperties()
+ {
+ }
+ }
+
+ public static EventLogHandle EvtQuery(
+ EventLogHandle session,
+ string path,
+ string query,
+ int flags)
+ {
+ EventLogHandle handle = UnsafeNativeMethods.EvtQuery(session, path, query, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (handle.IsInvalid)
+ EventLogException.Throw(win32Error);
+ return handle;
+ }
+
+ public static void EvtSeek(
+ EventLogHandle resultSet,
+ long position,
+ EventLogHandle bookmark,
+ int timeout,
+ UnsafeNativeMethods.EvtSeekFlags flags)
+ {
+ bool status = UnsafeNativeMethods.EvtSeek(resultSet, position, bookmark, timeout, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+ }
+
+ public static bool EvtNext(
+ EventLogHandle queryHandle,
+ int eventSize,
+ IntPtr[] events,
+ int timeout,
+ int flags,
+ ref int returned)
+ {
+ bool status = UnsafeNativeMethods.EvtNext(queryHandle, eventSize, events, timeout, flags, ref returned);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status && win32Error != UnsafeNativeMethods.ERROR_NO_MORE_ITEMS)
+ EventLogException.Throw(win32Error);
+ return win32Error == 0;
+ }
+
+ public static void EvtCancel(EventLogHandle handle)
+ {
+ if (!UnsafeNativeMethods.EvtCancel(handle))
+ {
+ int win32Error = Marshal.GetLastWin32Error();
+ EventLogException.Throw(win32Error);
+ }
+ }
+
+ public static void EvtClose(IntPtr handle)
+ {
+ //
+ // purposely don't check and throw - this is
+ // always called in cleanup / finalize / etc..
+ //
+ UnsafeNativeMethods.EvtClose(handle);
+ }
+
+ public static EventLogHandle EvtOpenProviderMetadata(
+ EventLogHandle session,
+ string ProviderId,
+ string logFilePath,
+ int locale,
+ int flags)
+ {
+ // ignore locale and pass 0 instead: that way, the thread locale will be retrieved in the API layer
+ // and the "strict rendering" flag will NOT be set. Otherwise, the fall back logic is broken and the descriptions
+ // are not returned if the exact locale is not present on the server.
+ EventLogHandle handle = UnsafeNativeMethods.EvtOpenPublisherMetadata(session, ProviderId, logFilePath, 0, flags);
+
+ int win32Error = Marshal.GetLastWin32Error();
+ if (handle.IsInvalid)
+ EventLogException.Throw(win32Error);
+ return handle;
+ }
+
+ public static int EvtGetObjectArraySize(EventLogHandle objectArray)
+ {
+ int arraySize;
+ bool status = UnsafeNativeMethods.EvtGetObjectArraySize(objectArray, out arraySize);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+ return arraySize;
+ }
+
+ public static EventLogHandle EvtOpenEventMetadataEnum(EventLogHandle ProviderMetadata, int flags)
+ {
+ EventLogHandle emEnumHandle = UnsafeNativeMethods.EvtOpenEventMetadataEnum(ProviderMetadata, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (emEnumHandle.IsInvalid)
+ EventLogException.Throw(win32Error);
+ return emEnumHandle;
+ }
+
+ // returns null if EOF
+ public static EventLogHandle EvtNextEventMetadata(EventLogHandle eventMetadataEnum, int flags)
+ {
+ EventLogHandle emHandle = UnsafeNativeMethods.EvtNextEventMetadata(eventMetadataEnum, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+
+ if (emHandle.IsInvalid)
+ {
+ if (win32Error != UnsafeNativeMethods.ERROR_NO_MORE_ITEMS)
+ EventLogException.Throw(win32Error);
+ return null;
+ }
+
+ return emHandle;
+ }
+
+ public static EventLogHandle EvtOpenChannelEnum(EventLogHandle session, int flags)
+ {
+ EventLogHandle channelEnum = UnsafeNativeMethods.EvtOpenChannelEnum(session, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (channelEnum.IsInvalid)
+ EventLogException.Throw(win32Error);
+ return channelEnum;
+ }
+
+ public static EventLogHandle EvtOpenProviderEnum(EventLogHandle session, int flags)
+ {
+ EventLogHandle pubEnum = UnsafeNativeMethods.EvtOpenPublisherEnum(session, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (pubEnum.IsInvalid)
+ EventLogException.Throw(win32Error);
+ return pubEnum;
+ }
+
+ public static EventLogHandle EvtOpenChannelConfig(EventLogHandle session, String channelPath, int flags)
+ {
+ EventLogHandle handle = UnsafeNativeMethods.EvtOpenChannelConfig(session, channelPath, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (handle.IsInvalid)
+ EventLogException.Throw(win32Error);
+ return handle;
+ }
+
+ public static void EvtSaveChannelConfig(EventLogHandle channelConfig, int flags)
+ {
+ bool status = UnsafeNativeMethods.EvtSaveChannelConfig(channelConfig, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+ }
+
+ public static EventLogHandle EvtOpenLog(EventLogHandle session, string path, PathType flags)
+ {
+ EventLogHandle logHandle = UnsafeNativeMethods.EvtOpenLog(session, path, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (logHandle.IsInvalid)
+ EventLogException.Throw(win32Error);
+ return logHandle;
+ }
+
+ public static void EvtExportLog(
+ EventLogHandle session,
+ string channelPath,
+ string query,
+ string targetFilePath,
+ int flags)
+ {
+ bool status;
+ status = UnsafeNativeMethods.EvtExportLog(session, channelPath, query, targetFilePath, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+ }
+
+ public static void EvtArchiveExportedLog(
+ EventLogHandle session,
+ string logFilePath,
+ int locale,
+ int flags)
+ {
+ bool status;
+ status = UnsafeNativeMethods.EvtArchiveExportedLog(session, logFilePath, locale, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+ }
+
+ public static void EvtClearLog(
+ EventLogHandle session,
+ string channelPath,
+ string targetFilePath,
+ int flags)
+ {
+ bool status;
+ status = UnsafeNativeMethods.EvtClearLog(session, channelPath, targetFilePath, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+ }
+
+ public static EventLogHandle EvtCreateRenderContext(
+ Int32 valuePathsCount,
+ String[] valuePaths,
+ UnsafeNativeMethods.EvtRenderContextFlags flags)
+ {
+ EventLogHandle renderContextHandleValues = UnsafeNativeMethods.EvtCreateRenderContext(valuePathsCount, valuePaths, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (renderContextHandleValues.IsInvalid)
+ EventLogException.Throw(win32Error);
+ return renderContextHandleValues;
+ }
+
+ public static void EvtRender(
+ EventLogHandle context,
+ EventLogHandle eventHandle,
+ UnsafeNativeMethods.EvtRenderFlags flags,
+ StringBuilder buffer)
+ {
+ int buffUsed;
+ int propCount;
+ bool status = UnsafeNativeMethods.EvtRender(context, eventHandle, flags, buffer.Capacity, buffer, out buffUsed, out propCount);
+ int win32Error = Marshal.GetLastWin32Error();
+
+ if (!status)
+ {
+ if (win32Error == UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ {
+ // Reallocate the new RenderBuffer with the right size.
+ buffer.Capacity = buffUsed;
+ status = UnsafeNativeMethods.EvtRender(context, eventHandle, flags, buffer.Capacity, buffer, out buffUsed, out propCount);
+ win32Error = Marshal.GetLastWin32Error();
+ }
+ if (!status)
+ {
+ EventLogException.Throw(win32Error);
+ }
+ }
+ }
+
+ public static EventLogHandle EvtOpenSession(UnsafeNativeMethods.EvtLoginClass loginClass, ref UnsafeNativeMethods.EvtRpcLogin login, int timeout, int flags)
+ {
+ EventLogHandle handle = UnsafeNativeMethods.EvtOpenSession(loginClass, ref login, timeout, flags);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (handle.IsInvalid)
+ EventLogException.Throw(win32Error);
+ return handle;
+ }
+
+ public static EventLogHandle EvtCreateBookmark(string bookmarkXml)
+ {
+ EventLogHandle handle = UnsafeNativeMethods.EvtCreateBookmark(bookmarkXml);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (handle.IsInvalid)
+ EventLogException.Throw(win32Error);
+ return handle;
+ }
+
+ public static void EvtUpdateBookmark(EventLogHandle bookmark, EventLogHandle eventHandle)
+ {
+ bool status = UnsafeNativeMethods.EvtUpdateBookmark(bookmark, eventHandle);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+ }
+
+ public static object EvtGetEventInfo(EventLogHandle handle, UnsafeNativeMethods.EvtEventPropertyId enumType)
+ {
+ IntPtr buffer = IntPtr.Zero;
+ int bufferNeeded;
+
+ try
+ {
+ bool status = UnsafeNativeMethods.EvtGetEventInfo(handle, enumType, 0, IntPtr.Zero, out bufferNeeded);
+ int error = Marshal.GetLastWin32Error();
+ if (!status)
+ {
+ if (error == UnsafeNativeMethods.ERROR_SUCCESS)
+ { }
+ else
+ if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(error);
+ }
+ buffer = Marshal.AllocHGlobal((int)bufferNeeded);
+ status = UnsafeNativeMethods.EvtGetEventInfo(handle, enumType, bufferNeeded, buffer, out bufferNeeded);
+ error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(error);
+
+ UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer);
+ return ConvertToObject(varVal);
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ public static object EvtGetQueryInfo(EventLogHandle handle, UnsafeNativeMethods.EvtQueryPropertyId enumType)
+ {
+ IntPtr buffer = IntPtr.Zero;
+ int bufferNeeded = 0;
+ try
+ {
+ bool status = UnsafeNativeMethods.EvtGetQueryInfo(handle, enumType, 0, IntPtr.Zero, ref bufferNeeded);
+ int error = Marshal.GetLastWin32Error();
+ if (!status)
+ {
+ if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(error);
+ }
+ buffer = Marshal.AllocHGlobal((int)bufferNeeded);
+ status = UnsafeNativeMethods.EvtGetQueryInfo(handle, enumType, bufferNeeded, buffer, ref bufferNeeded);
+ error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(error);
+
+ UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer);
+ return ConvertToObject(varVal);
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ public static object EvtGetPublisherMetadataProperty(EventLogHandle pmHandle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId thePropertyId)
+ {
+ IntPtr buffer = IntPtr.Zero;
+ int bufferNeeded;
+
+ try
+ {
+ bool status = UnsafeNativeMethods.EvtGetPublisherMetadataProperty(pmHandle, thePropertyId, 0, 0, IntPtr.Zero, out bufferNeeded);
+ int error = Marshal.GetLastWin32Error();
+ if (!status)
+ {
+ if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(error);
+ }
+ buffer = Marshal.AllocHGlobal((int)bufferNeeded);
+ status = UnsafeNativeMethods.EvtGetPublisherMetadataProperty(pmHandle, thePropertyId, 0, bufferNeeded, buffer, out bufferNeeded);
+ error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(error);
+
+ UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer);
+ return ConvertToObject(varVal);
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ internal static EventLogHandle EvtGetPublisherMetadataPropertyHandle(EventLogHandle pmHandle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId thePropertyId)
+ {
+ IntPtr buffer = IntPtr.Zero;
+ try
+ {
+ int bufferNeeded;
+ bool status = UnsafeNativeMethods.EvtGetPublisherMetadataProperty(pmHandle, thePropertyId, 0, 0, IntPtr.Zero, out bufferNeeded);
+ int error = Marshal.GetLastWin32Error();
+ if (!status)
+ {
+ if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(error);
+ }
+ buffer = Marshal.AllocHGlobal((int)bufferNeeded);
+ status = UnsafeNativeMethods.EvtGetPublisherMetadataProperty(pmHandle, thePropertyId, 0, bufferNeeded, buffer, out bufferNeeded);
+ error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(error);
+
+ //
+ // note: there is a case where returned variant does have allocated native resources
+ // associated with (e.g. ConfigArrayHandle). If PtrToStructure throws, then we would
+ // leak that resource - fortunately PtrToStructure only throws InvalidArgument which
+ // is a logic error - not a possible runtime condition here. Other System exceptions
+ // shouldn't be handled anyhow and the application will terminate.
+ //
+ UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer);
+ return ConvertToSafeHandle(varVal);
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ // implies UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageId flag.
+ public static string EvtFormatMessage(EventLogHandle handle, uint msgId)
+ {
+ int bufferNeeded;
+
+ StringBuilder sb = new StringBuilder(null);
+ bool status = UnsafeNativeMethods.EvtFormatMessage(handle, EventLogHandle.Zero, msgId, 0, null, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageId, 0, sb, out bufferNeeded);
+ int error = Marshal.GetLastWin32Error();
+
+ // ERROR_EVT_UNRESOLVED_VALUE_INSERT and its cousins are commonly returned for raw message text.
+ if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT
+ && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_PARAMETER_INSERT
+ && error != UnsafeNativeMethods.ERROR_EVT_MAX_INSERTS_REACHED)
+ {
+ switch (error)
+ {
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
+ return null;
+ }
+ if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(error);
+ }
+
+ sb.EnsureCapacity(bufferNeeded);
+ status = UnsafeNativeMethods.EvtFormatMessage(handle, EventLogHandle.Zero, msgId, 0, null, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageId, bufferNeeded, sb, out bufferNeeded);
+ error = Marshal.GetLastWin32Error();
+
+ if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT
+ && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_PARAMETER_INSERT
+ && error != UnsafeNativeMethods.ERROR_EVT_MAX_INSERTS_REACHED)
+ {
+ switch (error)
+ {
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
+ return null;
+ }
+ if (error == UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT)
+ {
+ return null;
+ }
+ EventLogException.Throw(error);
+ }
+ return sb.ToString();
+ }
+
+ public static object EvtGetObjectArrayProperty(EventLogHandle objArrayHandle, int index, int thePropertyId)
+ {
+ IntPtr buffer = IntPtr.Zero;
+ int bufferNeeded;
+
+ try
+ {
+ bool status = UnsafeNativeMethods.EvtGetObjectArrayProperty(objArrayHandle, thePropertyId, index, 0, 0, IntPtr.Zero, out bufferNeeded);
+ int error = Marshal.GetLastWin32Error();
+
+ if (!status)
+ {
+ if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(error);
+ }
+ buffer = Marshal.AllocHGlobal((int)bufferNeeded);
+ status = UnsafeNativeMethods.EvtGetObjectArrayProperty(objArrayHandle, thePropertyId, index, 0, bufferNeeded, buffer, out bufferNeeded);
+ error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(error);
+
+ UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer);
+ return ConvertToObject(varVal);
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ public static object EvtGetEventMetadataProperty(EventLogHandle handle, UnsafeNativeMethods.EvtEventMetadataPropertyId enumType)
+ {
+ IntPtr buffer = IntPtr.Zero;
+ int bufferNeeded;
+
+ try
+ {
+ bool status = UnsafeNativeMethods.EvtGetEventMetadataProperty(handle, enumType, 0, 0, IntPtr.Zero, out bufferNeeded);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ {
+ if (win32Error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(win32Error);
+ }
+ buffer = Marshal.AllocHGlobal((int)bufferNeeded);
+ status = UnsafeNativeMethods.EvtGetEventMetadataProperty(handle, enumType, 0, bufferNeeded, buffer, out bufferNeeded);
+ win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+
+ UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer);
+ return ConvertToObject(varVal);
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ public static object EvtGetChannelConfigProperty(EventLogHandle handle, UnsafeNativeMethods.EvtChannelConfigPropertyId enumType)
+ {
+ IntPtr buffer = IntPtr.Zero;
+ int bufferNeeded;
+
+ try
+ {
+ bool status = UnsafeNativeMethods.EvtGetChannelConfigProperty(handle, enumType, 0, 0, IntPtr.Zero, out bufferNeeded);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ {
+ if (win32Error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(win32Error);
+ }
+ buffer = Marshal.AllocHGlobal((int)bufferNeeded);
+ status = UnsafeNativeMethods.EvtGetChannelConfigProperty(handle, enumType, 0, bufferNeeded, buffer, out bufferNeeded);
+ win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+
+ //
+ // note: there is a case where returned variant does have allocated native resources
+ // associated with (e.g. ConfigArrayHandle). If PtrToStructure throws, then we would
+ // leak that resource - fortunately PtrToStructure only throws InvalidArgument which
+ // is a logic error - not a possible runtime condition here. Other System exceptions
+ // shouldn't be handled anyhow and the application will terminate.
+ //
+ UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer);
+ return ConvertToObject(varVal);
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ public static void EvtSetChannelConfigProperty(EventLogHandle handle, UnsafeNativeMethods.EvtChannelConfigPropertyId enumType, object val)
+ {
+ UnsafeNativeMethods.EvtVariant varVal = new UnsafeNativeMethods.EvtVariant();
+
+ CoTaskMemSafeHandle taskMem = new CoTaskMemSafeHandle();
+
+ using (taskMem)
+ {
+ if (val != null)
+ {
+ switch (enumType)
+ {
+ case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigEnabled:
+ {
+ varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBoolean;
+ if ((bool)val == true)
+ varVal.Bool = 1;
+ else
+ varVal.Bool = 0;
+ }
+ break;
+ case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigAccess:
+ {
+ varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeString;
+ taskMem.SetMemory(Marshal.StringToCoTaskMemUni((string)val));
+ varVal.StringVal = taskMem.GetMemory();
+ }
+ break;
+ case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigLogFilePath:
+ {
+ varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeString;
+ taskMem.SetMemory(Marshal.StringToCoTaskMemUni((string)val));
+ varVal.StringVal = taskMem.GetMemory();
+ }
+ break;
+ case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigMaxSize:
+ {
+ varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt64;
+ varVal.ULong = (ulong)((long)val);
+ }
+ break;
+ case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigLevel:
+ {
+ varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt32;
+ varVal.UInteger = (uint)((int)val);
+ }
+ break;
+ case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigKeywords:
+ {
+ varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt64;
+ varVal.ULong = (ulong)((long)val);
+ }
+ break;
+ case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigRetention:
+ {
+ varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBoolean;
+ if ((bool)val == true)
+ varVal.Bool = 1;
+ else
+ varVal.Bool = 0;
+ }
+ break;
+ case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigAutoBackup:
+ {
+ varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBoolean;
+ if ((bool)val == true)
+ varVal.Bool = 1;
+ else
+ varVal.Bool = 0;
+ }
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+ else
+ {
+ varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeNull;
+ }
+ bool status = UnsafeNativeMethods.EvtSetChannelConfigProperty(handle, enumType, 0, ref varVal);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+ }
+ }
+
+ public static string EvtNextChannelPath(EventLogHandle handle, ref bool finish)
+ {
+ StringBuilder sb = new StringBuilder(null);
+ int channelNameNeeded;
+
+ bool status = UnsafeNativeMethods.EvtNextChannelPath(handle, 0, sb, out channelNameNeeded);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ {
+ if (win32Error == UnsafeNativeMethods.ERROR_NO_MORE_ITEMS)
+ {
+ finish = true;
+ return null;
+ }
+
+ if (win32Error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(win32Error);
+ }
+
+ sb.EnsureCapacity(channelNameNeeded);
+ status = UnsafeNativeMethods.EvtNextChannelPath(handle, channelNameNeeded, sb, out channelNameNeeded);
+ win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+
+ return sb.ToString();
+ }
+
+ public static string EvtNextPublisherId(EventLogHandle handle, ref bool finish)
+ {
+ StringBuilder sb = new StringBuilder(null);
+ int ProviderIdNeeded;
+
+ bool status = UnsafeNativeMethods.EvtNextPublisherId(handle, 0, sb, out ProviderIdNeeded);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ {
+ if (win32Error == UnsafeNativeMethods.ERROR_NO_MORE_ITEMS)
+ {
+ finish = true;
+ return null;
+ }
+
+ if (win32Error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(win32Error);
+ }
+
+ sb.EnsureCapacity(ProviderIdNeeded);
+ status = UnsafeNativeMethods.EvtNextPublisherId(handle, ProviderIdNeeded, sb, out ProviderIdNeeded);
+ win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+
+ return sb.ToString();
+ }
+
+ public static object EvtGetLogInfo(EventLogHandle handle, UnsafeNativeMethods.EvtLogPropertyId enumType)
+ {
+ IntPtr buffer = IntPtr.Zero;
+ int bufferNeeded;
+
+ try
+ {
+ bool status = UnsafeNativeMethods.EvtGetLogInfo(handle, enumType, 0, IntPtr.Zero, out bufferNeeded);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ {
+ if (win32Error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(win32Error);
+ }
+ buffer = Marshal.AllocHGlobal((int)bufferNeeded);
+ status = UnsafeNativeMethods.EvtGetLogInfo(handle, enumType, bufferNeeded, buffer, out bufferNeeded);
+ win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+
+ UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer);
+ return ConvertToObject(varVal);
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ public static void EvtRenderBufferWithContextSystem(EventLogHandle contextHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtRenderFlags flag, SystemProperties systemProperties, int SYSTEM_PROPERTY_COUNT)
+ {
+ IntPtr buffer = IntPtr.Zero;
+ IntPtr pointer = IntPtr.Zero;
+ int bufferNeeded;
+ int propCount;
+
+ try
+ {
+ bool status = UnsafeNativeMethods.EvtRender(contextHandle, eventHandle, flag, 0, IntPtr.Zero, out bufferNeeded, out propCount);
+ if (!status)
+ {
+ int error = Marshal.GetLastWin32Error();
+ if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(error);
+ }
+
+ buffer = Marshal.AllocHGlobal((int)bufferNeeded);
+ status = UnsafeNativeMethods.EvtRender(contextHandle, eventHandle, flag, bufferNeeded, buffer, out bufferNeeded, out propCount);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+
+ if (propCount != SYSTEM_PROPERTY_COUNT)
+ throw new InvalidOperationException("We do not have " + SYSTEM_PROPERTY_COUNT + " variants given for the UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventValues flag. (System Properties)");
+
+ pointer = buffer;
+ // Read each Variant structure
+ for (int i = 0; i < propCount; i++)
+ {
+ UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(pointer);
+ switch (i)
+ {
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemProviderName:
+ systemProperties.ProviderName = (string)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeString);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemProviderGuid:
+ systemProperties.ProviderId = (Guid?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeGuid);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemEventID:
+ systemProperties.Id = (ushort?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt16);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemQualifiers:
+ systemProperties.Qualifiers = (ushort?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt16);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemLevel:
+ systemProperties.Level = (byte?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeByte);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemTask:
+ systemProperties.Task = (ushort?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt16);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemOpcode:
+ systemProperties.Opcode = (byte?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeByte);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemKeywords:
+ systemProperties.Keywords = (ulong?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeHexInt64);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemTimeCreated:
+ systemProperties.TimeCreated = (DateTime?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeFileTime);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemEventRecordId:
+ systemProperties.RecordId = (ulong?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt64);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemActivityID:
+ systemProperties.ActivityId = (Guid?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeGuid);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemRelatedActivityID:
+ systemProperties.RelatedActivityId = (Guid?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeGuid);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemProcessID:
+ systemProperties.ProcessId = (uint?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt32);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemThreadID:
+ systemProperties.ThreadId = (uint?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt32);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemChannel:
+ systemProperties.ChannelName = (string)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeString);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemComputer:
+ systemProperties.ComputerName = (string)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeString);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemUserID:
+ systemProperties.UserId = (SecurityIdentifier)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeSid);
+ break;
+ case (int)UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemVersion:
+ systemProperties.Version = (byte?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeByte);
+ break;
+ }
+ pointer = new IntPtr(((Int64)pointer + Marshal.SizeOf(varVal)));
+ }
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ // EvtRenderContextFlags can be both: EvtRenderContextFlags.EvtRenderContextUser and EvtRenderContextFlags.EvtRenderContextValues
+ // Render with Context = ContextUser or ContextValues (with user defined Xpath query strings)
+ public static IList<object> EvtRenderBufferWithContextUserOrValues(EventLogHandle contextHandle, EventLogHandle eventHandle)
+ {
+ IntPtr buffer = IntPtr.Zero;
+ IntPtr pointer = IntPtr.Zero;
+ int bufferNeeded;
+ int propCount;
+ UnsafeNativeMethods.EvtRenderFlags flag = UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventValues;
+
+ try
+ {
+ bool status = UnsafeNativeMethods.EvtRender(contextHandle, eventHandle, flag, 0, IntPtr.Zero, out bufferNeeded, out propCount);
+ if (!status)
+ {
+ int error = Marshal.GetLastWin32Error();
+ if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(error);
+ }
+
+ buffer = Marshal.AllocHGlobal((int)bufferNeeded);
+ status = UnsafeNativeMethods.EvtRender(contextHandle, eventHandle, flag, bufferNeeded, buffer, out bufferNeeded, out propCount);
+ int win32Error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(win32Error);
+
+ List<object> valuesList = new List<object>(propCount);
+ if (propCount > 0)
+ {
+ pointer = buffer;
+ for (int i = 0; i < propCount; i++)
+ {
+ UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(pointer);
+ valuesList.Add(ConvertToObject(varVal));
+ pointer = new IntPtr(((Int64)pointer + Marshal.SizeOf(varVal)));
+ }
+ }
+ return valuesList;
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ public static string EvtFormatMessageRenderName(EventLogHandle pmHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags flag)
+ {
+ int bufferNeeded;
+ StringBuilder sb = new StringBuilder(null);
+
+ bool status = UnsafeNativeMethods.EvtFormatMessage(pmHandle, eventHandle, 0, 0, null, flag, 0, sb, out bufferNeeded);
+ int error = Marshal.GetLastWin32Error();
+
+ if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT)
+ {
+ //
+ // ERROR_EVT_UNRESOLVED_VALUE_INSERT can be returned. It means
+ // message may have one or more unsubstituted strings. This is
+ // not an exception, but we have no way to convey the partial
+ // success out to enduser.
+ //
+ switch (error)
+ {
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
+ return null;
+ }
+ if (error != (int)UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(error);
+ }
+
+ sb.EnsureCapacity(bufferNeeded);
+ status = UnsafeNativeMethods.EvtFormatMessage(pmHandle, eventHandle, 0, 0, null, flag, bufferNeeded, sb, out bufferNeeded);
+ error = Marshal.GetLastWin32Error();
+
+ if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT)
+ {
+ switch (error)
+ {
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
+ return null;
+ }
+ EventLogException.Throw(error);
+ }
+ return sb.ToString();
+ }
+
+ // The EvtFormatMessage used for the obtaining of the Keywords names.
+ public static IEnumerable<string> EvtFormatMessageRenderKeywords(EventLogHandle pmHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags flag)
+ {
+ IntPtr buffer = IntPtr.Zero;
+ int bufferNeeded;
+
+ try
+ {
+ List<string> keywordsList = new List<string>();
+ bool status = UnsafeNativeMethods.EvtFormatMessageBuffer(pmHandle, eventHandle, 0, 0, IntPtr.Zero, flag, 0, IntPtr.Zero, out bufferNeeded);
+ int error = Marshal.GetLastWin32Error();
+
+ if (!status)
+ {
+ switch (error)
+ {
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
+ return keywordsList.AsReadOnly();
+ }
+ if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(error);
+ }
+
+ buffer = Marshal.AllocHGlobal(bufferNeeded * 2);
+ status = UnsafeNativeMethods.EvtFormatMessageBuffer(pmHandle, eventHandle, 0, 0, IntPtr.Zero, flag, bufferNeeded, buffer, out bufferNeeded);
+ error = Marshal.GetLastWin32Error();
+ if (!status)
+ {
+ switch (error)
+ {
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
+ return keywordsList;
+ }
+ EventLogException.Throw(error);
+ }
+
+ IntPtr pointer = buffer;
+
+ while (true)
+ {
+ string s = Marshal.PtrToStringUni(pointer);
+ if (String.IsNullOrEmpty(s))
+ break;
+ keywordsList.Add(s);
+ // nr of bytes = # chars * 2 + 2 bytes for character '\0'.
+ pointer = new IntPtr((Int64)pointer + (s.Length * 2) + 2);
+ }
+
+ return keywordsList.AsReadOnly();
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ public static string EvtRenderBookmark(EventLogHandle eventHandle)
+ {
+ IntPtr buffer = IntPtr.Zero;
+ int bufferNeeded;
+ int propCount;
+ UnsafeNativeMethods.EvtRenderFlags flag = UnsafeNativeMethods.EvtRenderFlags.EvtRenderBookmark;
+
+ try
+ {
+ bool status = UnsafeNativeMethods.EvtRender(EventLogHandle.Zero, eventHandle, flag, 0, IntPtr.Zero, out bufferNeeded, out propCount);
+ int error = Marshal.GetLastWin32Error();
+ if (!status)
+ {
+ if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(error);
+ }
+
+ buffer = Marshal.AllocHGlobal((int)bufferNeeded);
+ status = UnsafeNativeMethods.EvtRender(EventLogHandle.Zero, eventHandle, flag, bufferNeeded, buffer, out bufferNeeded, out propCount);
+ error = Marshal.GetLastWin32Error();
+ if (!status)
+ EventLogException.Throw(error);
+
+ return Marshal.PtrToStringUni(buffer);
+ }
+ finally
+ {
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(buffer);
+ }
+ }
+
+ // Get the formatted description, using the msgId for FormatDescription(string [])
+ public static string EvtFormatMessageFormatDescription(EventLogHandle handle, EventLogHandle eventHandle, string[] values)
+ {
+ int bufferNeeded;
+
+ UnsafeNativeMethods.EvtStringVariant[] stringVariants = new UnsafeNativeMethods.EvtStringVariant[values.Length];
+ for (int i = 0; i < values.Length; i++)
+ {
+ stringVariants[i].Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeString;
+ stringVariants[i].StringVal = values[i];
+ }
+
+ StringBuilder sb = new StringBuilder(null);
+ bool status = UnsafeNativeMethods.EvtFormatMessage(handle, eventHandle, 0xffffffff, values.Length, stringVariants, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageEvent, 0, sb, out bufferNeeded);
+ int error = Marshal.GetLastWin32Error();
+
+ if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT)
+ {
+ //
+ // ERROR_EVT_UNRESOLVED_VALUE_INSERT can be returned. It means
+ // message may have one or more unsubstituted strings. This is
+ // not an exception, but we have no way to convey the partial
+ // success out to enduser.
+ //
+ switch (error)
+ {
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
+ return null;
+ }
+ if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
+ EventLogException.Throw(error);
+ }
+
+ sb.EnsureCapacity(bufferNeeded);
+ status = UnsafeNativeMethods.EvtFormatMessage(handle, eventHandle, 0xffffffff, values.Length, stringVariants, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageEvent, bufferNeeded, sb, out bufferNeeded);
+ error = Marshal.GetLastWin32Error();
+
+ if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT)
+ {
+ switch (error)
+ {
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
+ case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
+ return null;
+ }
+ EventLogException.Throw(error);
+ }
+ return sb.ToString();
+ }
+
+ private static object ConvertToObject(UnsafeNativeMethods.EvtVariant val)
+ {
+ switch (val.Type)
+ {
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt32:
+ return val.UInteger;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt32:
+ return val.Integer;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt16:
+ return val.UShort;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt16:
+ return val.SByte;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeByte:
+ return val.UInt8;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSByte:
+ return val.SByte;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt64:
+ return val.ULong;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt64:
+ return val.Long;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeHexInt64:
+ return val.ULong;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeHexInt32:
+ return val.Integer;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSingle:
+ return val.Single;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeDouble:
+ return val.Double;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeNull:
+ return null;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeString:
+ return ConvertToString(val);
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeAnsiString:
+ return ConvertToAnsiString(val);
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSid:
+ return (val.SidVal == IntPtr.Zero) ? null : new SecurityIdentifier(val.SidVal);
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeGuid:
+ return (val.GuidReference == IntPtr.Zero) ? Guid.Empty : Marshal.PtrToStructure<Guid>(val.GuidReference);
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeEvtHandle:
+ return ConvertToSafeHandle(val);
+ case (int)(int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeFileTime:
+ return DateTime.FromFileTime((long)val.FileTime);
+ case (int)(int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSysTime:
+ UnsafeNativeMethods.SystemTime sysTime = Marshal.PtrToStructure<UnsafeNativeMethods.SystemTime>(val.SystemTime);
+ return new DateTime(sysTime.Year, sysTime.Month, sysTime.Day, sysTime.Hour, sysTime.Minute, sysTime.Second, sysTime.Milliseconds);
+ case (int)(int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSizeT:
+ return val.SizeT;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBoolean:
+ if (val.Bool != 0)
+ return true;
+ else
+ return false;
+ case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBinary:
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeByte):
+ if (val.Reference == IntPtr.Zero)
+ return new Byte[0];
+ Byte[] arByte = new Byte[val.Count];
+ Marshal.Copy(val.Reference, arByte, 0, (int)val.Count);
+ return arByte;
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt16):
+ if (val.Reference == IntPtr.Zero)
+ return new Int16[0];
+ Int16[] arInt16 = new Int16[val.Count];
+ Marshal.Copy(val.Reference, arInt16, 0, (int)val.Count);
+ return arInt16;
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt32):
+ if (val.Reference == IntPtr.Zero)
+ return new Int32[0];
+ Int32[] arInt32 = new Int32[val.Count];
+ Marshal.Copy(val.Reference, arInt32, 0, (int)val.Count);
+ return arInt32;
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt64):
+ if (val.Reference == IntPtr.Zero)
+ return new Int64[0];
+ Int64[] arInt64 = new Int64[val.Count];
+ Marshal.Copy(val.Reference, arInt64, 0, (int)val.Count);
+ return arInt64;
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSingle):
+ if (val.Reference == IntPtr.Zero)
+ return new Single[0];
+ Single[] arSingle = new Single[val.Count];
+ Marshal.Copy(val.Reference, arSingle, 0, (int)val.Count);
+ return arSingle;
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeDouble):
+ if (val.Reference == IntPtr.Zero)
+ return new Double[0];
+ Double[] arDouble = new Double[val.Count];
+ Marshal.Copy(val.Reference, arDouble, 0, (int)val.Count);
+ return arDouble;
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSByte):
+ return ConvertToArray<SByte>(val, sizeof(SByte)); // not CLS-compliant
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt16):
+ return ConvertToArray<UInt16>(val, sizeof(UInt16));
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt64):
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeHexInt64):
+ return ConvertToArray<UInt64>(val, sizeof(UInt64));
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt32):
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeHexInt32):
+ return ConvertToArray<UInt32>(val, sizeof(UInt32));
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeString):
+ return ConvertToStringArray(val, false);
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeAnsiString):
+ return ConvertToStringArray(val, true);
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBoolean):
+ return ConvertToBoolArray(val);
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeGuid):
+ return ConvertToArray<Guid>(val, 16 * sizeof(byte));
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeFileTime):
+ return ConvertToFileTimeArray(val);
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSysTime):
+ return ConvertToSysTimeArray(val);
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBinary): // both length and count in the manifest: tracrpt supports, Crimson APIs don't
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSizeT): // unused: array of win:pointer is returned as HexIntXX
+ case ((int)UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSid): // unsupported by native APIs
+ default:
+ throw new EventLogInvalidDataException();
+ }
+ }
+
+ public static object ConvertToObject(UnsafeNativeMethods.EvtVariant val, UnsafeNativeMethods.EvtVariantType desiredType)
+ {
+ if (val.Type == (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeNull)
+ return null;
+ if (val.Type != (int)desiredType)
+ throw new EventLogInvalidDataException();
+
+ return ConvertToObject(val);
+ }
+
+ public static string ConvertToString(UnsafeNativeMethods.EvtVariant val)
+ {
+ if (val.StringVal == IntPtr.Zero)
+ return string.Empty;
+ else
+ return Marshal.PtrToStringUni(val.StringVal);
+ }
+
+ public static string ConvertToAnsiString(UnsafeNativeMethods.EvtVariant val)
+ {
+ if (val.AnsiString == IntPtr.Zero)
+ return string.Empty;
+ else
+ return Marshal.PtrToStringAnsi(val.AnsiString);
+ }
+
+ public static EventLogHandle ConvertToSafeHandle(UnsafeNativeMethods.EvtVariant val)
+ {
+ if (val.Handle == IntPtr.Zero)
+ return EventLogHandle.Zero;
+ else
+ return new EventLogHandle(val.Handle, true);
+ }
+
+ public static Array ConvertToArray<T>(UnsafeNativeMethods.EvtVariant val, int size) where T : struct
+ {
+ IntPtr ptr = val.Reference;
+ if (ptr == IntPtr.Zero)
+ {
+ return Array.CreateInstance(typeof(T), 0);
+ }
+ else
+ {
+ Array array = Array.CreateInstance(typeof(T), (int)val.Count);
+ for (int i = 0; i < val.Count; i++)
+ {
+ array.SetValue(Marshal.PtrToStructure<T>(ptr), i);
+ ptr = new IntPtr((Int64)ptr + size);
+ }
+ return array;
+ }
+ }
+
+ public static Array ConvertToBoolArray(UnsafeNativeMethods.EvtVariant val)
+ {
+ // NOTE: booleans are padded to 4 bytes in ETW
+ IntPtr ptr = val.Reference;
+ if (ptr == IntPtr.Zero)
+ {
+ return new bool[0];
+ }
+ else
+ {
+ bool[] array = new bool[val.Count];
+ for (int i = 0; i < val.Count; i++)
+ {
+ bool value = (Marshal.ReadInt32(ptr) != 0) ? true : false;
+ array[i] = value;
+ ptr = new IntPtr((Int64)ptr + 4);
+ }
+ return array;
+ }
+ }
+
+ public static Array ConvertToFileTimeArray(UnsafeNativeMethods.EvtVariant val)
+ {
+ IntPtr ptr = val.Reference;
+ if (ptr == IntPtr.Zero)
+ {
+ return new DateTime[0];
+ }
+ else
+ {
+ DateTime[] array = new DateTime[val.Count];
+ for (int i = 0; i < val.Count; i++)
+ {
+ array[i] = DateTime.FromFileTime(Marshal.ReadInt64(ptr));
+ ptr = new IntPtr((Int64)ptr + 8 * sizeof(byte)); // FILETIME values are 8 bytes
+ }
+ return array;
+ }
+ }
+
+ public static Array ConvertToSysTimeArray(UnsafeNativeMethods.EvtVariant val)
+ {
+ IntPtr ptr = val.Reference;
+ if (ptr == IntPtr.Zero)
+ {
+ return new DateTime[0];
+ }
+ else
+ {
+ DateTime[] array = new DateTime[val.Count];
+ for (int i = 0; i < val.Count; i++)
+ {
+ UnsafeNativeMethods.SystemTime sysTime = Marshal.PtrToStructure<UnsafeNativeMethods.SystemTime>(ptr);
+ array[i] = new DateTime(sysTime.Year, sysTime.Month, sysTime.Day, sysTime.Hour, sysTime.Minute, sysTime.Second, sysTime.Milliseconds);
+ ptr = new IntPtr((Int64)ptr + 16 * sizeof(byte)); // SystemTime values are 16 bytes
+ }
+ return array;
+ }
+ }
+
+ public static string[] ConvertToStringArray(UnsafeNativeMethods.EvtVariant val, bool ansi)
+ {
+ if (val.Reference == IntPtr.Zero)
+ {
+ return new string[0];
+ }
+ else
+ {
+ IntPtr ptr = val.Reference;
+ IntPtr[] pointersToString = new IntPtr[val.Count];
+ Marshal.Copy(ptr, pointersToString, 0, (int)val.Count);
+ string[] stringArray = new string[val.Count];
+ for (int i = 0; i < val.Count; i++)
+ {
+ stringArray[i] = ansi ? Marshal.PtrToStringAnsi(pointersToString[i]) : Marshal.PtrToStringUni(pointersToString[i]);
+ }
+ return stringArray;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Globalization;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+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 EventLogHandle _handle = EventLogHandle.Zero;
+
+ private EventLogHandle _defaultProviderHandle = EventLogHandle.Zero;
+
+ private EventLogSession _session = null;
+
+ private string _providerName;
+ private CultureInfo _cultureInfo;
+ private string _logFilePath;
+
+ // caching of the IEnumerable<EventLevel>, <EventTask>, <EventKeyword>, <EventOpcode> on the ProviderMetadata
+ // they do not change with every call.
+ private IList<EventLevel> _levels = null;
+ private IList<EventOpcode> _opcodes = null;
+ private IList<EventTask> _tasks = null;
+ private IList<EventKeyword> _keywords = null;
+ private IList<EventLevel> _standardLevels = null;
+ private IList<EventOpcode> _standardOpcodes = null;
+ private IList<EventTask> _standardTasks = null;
+ private IList<EventKeyword> _standardKeywords = null;
+ private IList<EventLogLink> _channelReferences = null;
+
+ private 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)
+ {
+ if (targetCultureInfo == null)
+ targetCultureInfo = CultureInfo.CurrentCulture;
+
+ if (session == null)
+ session = EventLogSession.GlobalSession;
+
+ _session = session;
+ _providerName = providerName;
+ _cultureInfo = targetCultureInfo;
+ _logFilePath = logFilePath;
+
+ _handle = NativeWrapper.EvtOpenProviderMetadata(_session.Handle, _providerName, _logFilePath, 0, 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 (helpLinkStr == null || helpLinkStr.Length == 0)
+ 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.Compare(channelName, "Application", StringComparison.OrdinalIgnoreCase) == 0)
+ channelRefMessageId = 256;
+ else if (String.Compare(channelName, "System", StringComparison.OrdinalIgnoreCase) == 0)
+ channelRefMessageId = 258;
+ else if (String.Compare(channelName, "Security", StringComparison.OrdinalIgnoreCase) == 0)
+ channelRefMessageId = 257;
+ else
+ channelRefMessageId = -1;
+
+ if (channelRefMessageId != -1)
+ {
+ if (_defaultProviderHandle.IsInvalid)
+ {
+ _defaultProviderHandle = NativeWrapper.EvtOpenProviderMetadata(_session.Handle, null, null, 0, 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)
+ {
+ if (_standardLevels == null)
+ _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)
+ {
+ if (_standardOpcodes == null)
+ _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)
+ {
+ if (_standardKeywords == null)
+ _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)
+ {
+ if (_standardTasks == null)
+ _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, 0);
+ }
+
+ switch (objectTypeName)
+ {
+ case ObjectTypeName.Level:
+ generalDisplayName = FindStandardLevelDisplayName(generalName, generalValue);
+ break;
+ case ObjectTypeName.Opcode:
+ generalDisplayName = FindStandardOpcodeDisplayName(generalName, generalValue >> 16);
+ break;
+ case ObjectTypeName.Keyword:
+ generalDisplayName = FindStandardKeywordDisplayName(generalName, generalValueKeyword);
+ break;
+ case ObjectTypeName.Task:
+ generalDisplayName = FindStandardTaskDisplayName(generalName, generalValue);
+ break;
+ default:
+ generalDisplayName = null;
+ break;
+ }
+ }
+ }
+ 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;
+ }
+ }
+
+ switch (objectTypeName)
+ {
+ case ObjectTypeName.Level:
+ return levelList;
+ case ObjectTypeName.Opcode:
+ return opcodeList;
+ case ObjectTypeName.Keyword:
+ return keywordList;
+ case ObjectTypeName.Task:
+ return taskList;
+ }
+ return 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;
+ }
+ }
+
+ [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Opcodes", Justification = "matell: Shipped public in 3.5, breaking change to fix now.")]
+ 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 = 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();
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Globalization;
+using System.Collections.Generic;
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// This class does not expose underlying Provider metadata objects. Instead it
+ /// exposes a limited set of Provider metadata information from the cache. The reason
+ /// for this is so the cache can easily Dispose the metadata object without worrying
+ /// about who is using it.
+ /// </summary>
+ internal class ProviderMetadataCachedInformation
+ {
+ private Dictionary<ProviderMetadataId, CacheItem> _cache;
+ private int _maximumCacheSize;
+ private EventLogSession _session;
+ private string _logfile;
+
+ private class ProviderMetadataId
+ {
+ public ProviderMetadataId(string providerName, CultureInfo cultureInfo)
+ {
+ ProviderName = providerName;
+ TheCultureInfo = cultureInfo;
+ }
+
+ public override bool Equals(object obj)
+ {
+ ProviderMetadataId rhs = obj as ProviderMetadataId;
+ if (rhs == null)
+ return false;
+ if (ProviderName.Equals(rhs.ProviderName) && (TheCultureInfo == rhs.TheCultureInfo))
+ return true;
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return ProviderName.GetHashCode() ^ TheCultureInfo.GetHashCode();
+ }
+
+ public string ProviderName { get; }
+ public CultureInfo TheCultureInfo { get; }
+ }
+
+ private class CacheItem
+ {
+ public CacheItem(ProviderMetadata pm)
+ {
+ ProviderMetadata = pm;
+ TheTime = DateTime.Now;
+ }
+
+ public DateTime TheTime { get; set; }
+
+ public ProviderMetadata ProviderMetadata { get; }
+ }
+
+ public ProviderMetadataCachedInformation(EventLogSession session, string logfile, int maximumCacheSize)
+ {
+ Debug.Assert(session != null);
+ _session = session;
+ _logfile = logfile;
+ _cache = new Dictionary<ProviderMetadataId, CacheItem>();
+ _maximumCacheSize = maximumCacheSize;
+ }
+
+ private bool IsCacheFull()
+ {
+ return _cache.Count == _maximumCacheSize;
+ }
+
+ private bool IsProviderinCache(ProviderMetadataId key)
+ {
+ return _cache.ContainsKey(key);
+ }
+
+ private void DeleteCacheEntry(ProviderMetadataId key)
+ {
+ if (!IsProviderinCache(key))
+ return;
+
+ CacheItem value = _cache[key];
+ _cache.Remove(key);
+
+ value.ProviderMetadata.Dispose();
+ }
+
+ private void AddCacheEntry(ProviderMetadataId key, ProviderMetadata pm)
+ {
+ if (IsCacheFull())
+ FlushOldestEntry();
+
+ CacheItem value = new CacheItem(pm);
+ _cache.Add(key, value);
+ return;
+ }
+
+ private void FlushOldestEntry()
+ {
+ double maxPassedTime = -10;
+ DateTime timeNow = DateTime.Now;
+ ProviderMetadataId keyToDelete = null;
+
+ // Get the entry in the cache which was not accessed for the longest time.
+ foreach (KeyValuePair<ProviderMetadataId, CacheItem> kvp in _cache)
+ {
+ // The time difference (in ms) between the timeNow and the last used time of each entry
+ TimeSpan timeDifference = timeNow.Subtract(kvp.Value.TheTime);
+
+ // For the "unused" items (with ReferenceCount == 0) -> can possible be deleted.
+ if (timeDifference.TotalMilliseconds >= maxPassedTime)
+ {
+ maxPassedTime = timeDifference.TotalMilliseconds;
+ keyToDelete = kvp.Key;
+ }
+ }
+
+ if (keyToDelete != null)
+ DeleteCacheEntry(keyToDelete);
+ }
+
+ private static void UpdateCacheValueInfoForHit(CacheItem cacheItem)
+ {
+ cacheItem.TheTime = DateTime.Now;
+ }
+
+ private ProviderMetadata GetProviderMetadata(ProviderMetadataId key)
+ {
+ if (!IsProviderinCache(key))
+ {
+ ProviderMetadata pm;
+ try
+ {
+ pm = new ProviderMetadata(key.ProviderName, _session, key.TheCultureInfo, _logfile);
+ }
+ catch (EventLogNotFoundException)
+ {
+ pm = new ProviderMetadata(key.ProviderName, _session, key.TheCultureInfo);
+ }
+ AddCacheEntry(key, pm);
+ return pm;
+ }
+ else
+ {
+ CacheItem cacheItem = _cache[key];
+ ProviderMetadata pm = cacheItem.ProviderMetadata;
+
+ // check Provider metadata to be sure it's hasn't been
+ // uninstalled since last time it was used.
+
+ try
+ {
+ pm.CheckReleased();
+ UpdateCacheValueInfoForHit(cacheItem);
+ }
+ catch (EventLogException)
+ {
+ DeleteCacheEntry(key);
+ try
+ {
+ pm = new ProviderMetadata(key.ProviderName, _session, key.TheCultureInfo, _logfile);
+ }
+ catch (EventLogNotFoundException)
+ {
+ pm = new ProviderMetadata(key.ProviderName, _session, key.TheCultureInfo);
+ }
+ AddCacheEntry(key, pm);
+ }
+
+ return pm;
+ }
+ }
+
+ public string GetFormatDescription(string ProviderName, EventLogHandle eventHandle)
+ {
+ lock (this)
+ {
+ ProviderMetadataId key = new ProviderMetadataId(ProviderName, CultureInfo.CurrentCulture);
+
+ try
+ {
+ ProviderMetadata pm = GetProviderMetadata(key);
+ return NativeWrapper.EvtFormatMessageRenderName(pm.Handle, eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageEvent);
+ }
+ catch (EventLogNotFoundException)
+ {
+ return null;
+ }
+ }
+ }
+
+ public string GetFormatDescription(string ProviderName, EventLogHandle eventHandle, string[] values)
+ {
+ lock (this)
+ {
+ ProviderMetadataId key = new ProviderMetadataId(ProviderName, CultureInfo.CurrentCulture);
+ ProviderMetadata pm = GetProviderMetadata(key);
+ try
+ {
+ return NativeWrapper.EvtFormatMessageFormatDescription(pm.Handle, eventHandle, values);
+ }
+ catch (EventLogNotFoundException)
+ {
+ return null;
+ }
+ }
+ }
+
+ public string GetLevelDisplayName(string ProviderName, EventLogHandle eventHandle)
+ {
+ lock (this)
+ {
+ ProviderMetadataId key = new ProviderMetadataId(ProviderName, CultureInfo.CurrentCulture);
+ ProviderMetadata pm = GetProviderMetadata(key);
+ return NativeWrapper.EvtFormatMessageRenderName(pm.Handle, eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageLevel);
+ }
+ }
+
+ public string GetOpcodeDisplayName(string ProviderName, EventLogHandle eventHandle)
+ {
+ lock (this)
+ {
+ ProviderMetadataId key = new ProviderMetadataId(ProviderName, CultureInfo.CurrentCulture);
+ ProviderMetadata pm = GetProviderMetadata(key);
+ return NativeWrapper.EvtFormatMessageRenderName(pm.Handle, eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageOpcode);
+ }
+ }
+
+ public string GetTaskDisplayName(string ProviderName, EventLogHandle eventHandle)
+ {
+ lock (this)
+ {
+ ProviderMetadataId key = new ProviderMetadataId(ProviderName, CultureInfo.CurrentCulture);
+ ProviderMetadata pm = GetProviderMetadata(key);
+ return NativeWrapper.EvtFormatMessageRenderName(pm.Handle, eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageTask);
+ }
+ }
+
+ public IEnumerable<string> GetKeywordDisplayNames(string ProviderName, EventLogHandle eventHandle)
+ {
+ lock (this)
+ {
+ ProviderMetadataId key = new ProviderMetadataId(ProviderName, CultureInfo.CurrentCulture);
+ ProviderMetadata pm = GetProviderMetadata(key);
+ return NativeWrapper.EvtFormatMessageRenderKeywords(pm.Handle, eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageKeyword);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.Configuration.Assemblies;
+using System.Diagnostics.Eventing;
+using System.Diagnostics.Eventing.Reader;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Runtime.Versioning;
+using System.Security;
+using System.Security.Permissions;
+using System.Security.Principal;
+using System.Text;
+using System.Threading;
+
+namespace Microsoft.Win32
+{
+ internal static partial class UnsafeNativeMethods
+ {
+ internal const String WEVTAPI = "wevtapi.dll";
+
+ // WinError.h codes:
+
+ internal const int ERROR_SUCCESS = 0x0;
+ internal const int ERROR_FILE_NOT_FOUND = 0x2;
+ internal const int ERROR_PATH_NOT_FOUND = 0x3;
+ internal const int ERROR_ACCESS_DENIED = 0x5;
+ internal const int ERROR_INVALID_HANDLE = 0x6;
+
+ // Can occurs when filled buffers are trying to flush to disk, but disk IOs are not fast enough.
+ // This happens when the disk is slow and event traffic is heavy.
+ // Eventually, there are no more free (empty) buffers and the event is dropped.
+ internal const int ERROR_NOT_ENOUGH_MEMORY = 0x8;
+
+ internal const int ERROR_INVALID_DRIVE = 0xF;
+ internal const int ERROR_NO_MORE_FILES = 0x12;
+ internal const int ERROR_NOT_READY = 0x15;
+ internal const int ERROR_BAD_LENGTH = 0x18;
+ internal const int ERROR_SHARING_VIOLATION = 0x20;
+ internal const int ERROR_LOCK_VIOLATION = 0x21; // 33
+ internal const int ERROR_HANDLE_EOF = 0x26; // 38
+ internal const int ERROR_FILE_EXISTS = 0x50;
+ internal const int ERROR_INVALID_PARAMETER = 0x57; // 87
+ internal const int ERROR_BROKEN_PIPE = 0x6D; // 109
+ internal const int ERROR_INSUFFICIENT_BUFFER = 0x7A; // 122
+ internal const int ERROR_INVALID_NAME = 0x7B;
+ internal const int ERROR_BAD_PATHNAME = 0xA1;
+ internal const int ERROR_ALREADY_EXISTS = 0xB7;
+ internal const int ERROR_ENVVAR_NOT_FOUND = 0xCB;
+ internal const int ERROR_FILENAME_EXCED_RANGE = 0xCE; // filename too long
+ internal const int ERROR_PIPE_BUSY = 0xE7; // 231
+ internal const int ERROR_NO_DATA = 0xE8; // 232
+ internal const int ERROR_PIPE_NOT_CONNECTED = 0xE9; // 233
+ internal const int ERROR_MORE_DATA = 0xEA;
+ internal const int ERROR_NO_MORE_ITEMS = 0x103; // 259
+ internal const int ERROR_PIPE_CONNECTED = 0x217; // 535
+ internal const int ERROR_PIPE_LISTENING = 0x218; // 536
+ internal const int ERROR_OPERATION_ABORTED = 0x3E3; // 995; For IO Cancellation
+ internal const int ERROR_IO_PENDING = 0x3E5; // 997
+ internal const int ERROR_NOT_FOUND = 0x490; // 1168
+
+ // The event size is larger than the allowed maximum (64k - header).
+ internal const int ERROR_ARITHMETIC_OVERFLOW = 0x216; // 534
+
+ internal const int ERROR_RESOURCE_LANG_NOT_FOUND = 0x717; // 1815
+
+ // Event log specific codes:
+
+ internal const int ERROR_EVT_MESSAGE_NOT_FOUND = 15027;
+ internal const int ERROR_EVT_MESSAGE_ID_NOT_FOUND = 15028;
+ internal const int ERROR_EVT_UNRESOLVED_VALUE_INSERT = 15029;
+ internal const int ERROR_EVT_UNRESOLVED_PARAMETER_INSERT = 15030;
+ internal const int ERROR_EVT_MAX_INSERTS_REACHED = 15031;
+ internal const int ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND = 15033;
+ internal const int ERROR_MUI_FILE_NOT_FOUND = 15100;
+
+ internal enum EvtQueryFlags
+ {
+ EvtQueryChannelPath = 0x1,
+ EvtQueryFilePath = 0x2,
+ EvtQueryForwardDirection = 0x100,
+ EvtQueryReverseDirection = 0x200,
+ EvtQueryTolerateQueryErrors = 0x1000
+ }
+
+ [Flags]
+ internal enum EvtSubscribeFlags
+ {
+ EvtSubscribeToFutureEvents = 1,
+ EvtSubscribeStartAtOldestRecord = 2,
+ EvtSubscribeStartAfterBookmark = 3,
+ EvtSubscribeTolerateQueryErrors = 0x1000,
+ EvtSubscribeStrict = 0x10000
+ }
+
+ /// <summary>
+ /// Evt Variant types
+ /// </summary>
+ internal enum EvtVariantType
+ {
+ EvtVarTypeNull = 0,
+ EvtVarTypeString = 1,
+ EvtVarTypeAnsiString = 2,
+ EvtVarTypeSByte = 3,
+ EvtVarTypeByte = 4,
+ EvtVarTypeInt16 = 5,
+ EvtVarTypeUInt16 = 6,
+ EvtVarTypeInt32 = 7,
+ EvtVarTypeUInt32 = 8,
+ EvtVarTypeInt64 = 9,
+ EvtVarTypeUInt64 = 10,
+ EvtVarTypeSingle = 11,
+ EvtVarTypeDouble = 12,
+ EvtVarTypeBoolean = 13,
+ EvtVarTypeBinary = 14,
+ EvtVarTypeGuid = 15,
+ EvtVarTypeSizeT = 16,
+ EvtVarTypeFileTime = 17,
+ EvtVarTypeSysTime = 18,
+ EvtVarTypeSid = 19,
+ EvtVarTypeHexInt32 = 20,
+ EvtVarTypeHexInt64 = 21,
+ // these types used internally
+ EvtVarTypeEvtHandle = 32,
+ EvtVarTypeEvtXml = 35,
+ // Array = 128
+ EvtVarTypeStringArray = 129,
+ EvtVarTypeUInt32Array = 136
+ }
+
+ internal enum EvtMasks
+ {
+ EVT_VARIANT_TYPE_MASK = 0x7f,
+ EVT_VARIANT_TYPE_ARRAY = 128
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SystemTime
+ {
+ [MarshalAs(UnmanagedType.U2)]
+ public short Year;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Month;
+ [MarshalAs(UnmanagedType.U2)]
+ public short DayOfWeek;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Day;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Hour;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Minute;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Second;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Milliseconds;
+ }
+
+ [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
+#pragma warning disable 618 // Ssytem.Core still uses SecurityRuleSet.Level1
+ [SecurityCritical(SecurityCriticalScope.Everything)]
+#pragma warning restore 618
+ internal struct EvtVariant
+ {
+ [FieldOffset(0)]
+ public UInt32 UInteger;
+ [FieldOffset(0)]
+ public Int32 Integer;
+ [FieldOffset(0)]
+ public byte UInt8;
+ [FieldOffset(0)]
+ public short Short;
+ [FieldOffset(0)]
+ public ushort UShort;
+ [FieldOffset(0)]
+ public UInt32 Bool;
+ [FieldOffset(0)]
+ public Byte ByteVal;
+ [FieldOffset(0)]
+ public byte SByte;
+ [FieldOffset(0)]
+ public UInt64 ULong;
+ [FieldOffset(0)]
+ public Int64 Long;
+ [FieldOffset(0)]
+ public Single Single;
+ [FieldOffset(0)]
+ public Double Double;
+ [FieldOffset(0)]
+ public IntPtr StringVal;
+ [FieldOffset(0)]
+ public IntPtr AnsiString;
+ [FieldOffset(0)]
+ public IntPtr SidVal;
+ [FieldOffset(0)]
+ public IntPtr Binary;
+ [FieldOffset(0)]
+ public IntPtr Reference;
+ [FieldOffset(0)]
+ public IntPtr Handle;
+ [FieldOffset(0)]
+ public IntPtr GuidReference;
+ [FieldOffset(0)]
+ public UInt64 FileTime;
+ [FieldOffset(0)]
+ public IntPtr SystemTime;
+ [FieldOffset(0)]
+ public IntPtr SizeT;
+ [FieldOffset(8)]
+ public UInt32 Count; // number of elements (not length) in bytes.
+ [FieldOffset(12)]
+ public UInt32 Type;
+ }
+
+ internal enum EvtEventPropertyId
+ {
+ EvtEventQueryIDs = 0,
+ EvtEventPath = 1
+ }
+
+ /// <summary>
+ /// The query flags to get information about query
+ /// </summary>
+ internal enum EvtQueryPropertyId
+ {
+ EvtQueryNames = 0, //String; //Variant will be array of EvtVarTypeString
+ EvtQueryStatuses = 1 //UInt32; //Variant will be Array of EvtVarTypeUInt32
+ }
+
+ /// <summary>
+ /// Publisher Metadata properties
+ /// </summary>
+ internal enum EvtPublisherMetadataPropertyId
+ {
+ EvtPublisherMetadataPublisherGuid = 0, // EvtVarTypeGuid
+ EvtPublisherMetadataResourceFilePath = 1, // EvtVarTypeString
+ EvtPublisherMetadataParameterFilePath = 2, // EvtVarTypeString
+ EvtPublisherMetadataMessageFilePath = 3, // EvtVarTypeString
+ EvtPublisherMetadataHelpLink = 4, // EvtVarTypeString
+ EvtPublisherMetadataPublisherMessageID = 5, // EvtVarTypeUInt32
+
+ EvtPublisherMetadataChannelReferences = 6, // EvtVarTypeEvtHandle, ObjectArray
+ EvtPublisherMetadataChannelReferencePath = 7, // EvtVarTypeString
+ EvtPublisherMetadataChannelReferenceIndex = 8, // EvtVarTypeUInt32
+ EvtPublisherMetadataChannelReferenceID = 9, // EvtVarTypeUInt32
+ EvtPublisherMetadataChannelReferenceFlags = 10, // EvtVarTypeUInt32
+ EvtPublisherMetadataChannelReferenceMessageID = 11, // EvtVarTypeUInt32
+
+ EvtPublisherMetadataLevels = 12, // EvtVarTypeEvtHandle, ObjectArray
+ EvtPublisherMetadataLevelName = 13, // EvtVarTypeString
+ EvtPublisherMetadataLevelValue = 14, // EvtVarTypeUInt32
+ EvtPublisherMetadataLevelMessageID = 15, // EvtVarTypeUInt32
+
+ EvtPublisherMetadataTasks = 16, // EvtVarTypeEvtHandle, ObjectArray
+ EvtPublisherMetadataTaskName = 17, // EvtVarTypeString
+ EvtPublisherMetadataTaskEventGuid = 18, // EvtVarTypeGuid
+ EvtPublisherMetadataTaskValue = 19, // EvtVarTypeUInt32
+ EvtPublisherMetadataTaskMessageID = 20, // EvtVarTypeUInt32
+
+ EvtPublisherMetadataOpcodes = 21, // EvtVarTypeEvtHandle, ObjectArray
+ EvtPublisherMetadataOpcodeName = 22, // EvtVarTypeString
+ EvtPublisherMetadataOpcodeValue = 23, // EvtVarTypeUInt32
+ EvtPublisherMetadataOpcodeMessageID = 24, // EvtVarTypeUInt32
+
+ EvtPublisherMetadataKeywords = 25, // EvtVarTypeEvtHandle, ObjectArray
+ EvtPublisherMetadataKeywordName = 26, // EvtVarTypeString
+ EvtPublisherMetadataKeywordValue = 27, // EvtVarTypeUInt64
+ EvtPublisherMetadataKeywordMessageID = 28//, // EvtVarTypeUInt32
+ // EvtPublisherMetadataPropertyIdEND
+ }
+
+ internal enum EvtChannelReferenceFlags
+ {
+ EvtChannelReferenceImported = 1
+ }
+
+ internal enum EvtEventMetadataPropertyId
+ {
+ EventMetadataEventID, // EvtVarTypeUInt32
+ EventMetadataEventVersion, // EvtVarTypeUInt32
+ EventMetadataEventChannel, // EvtVarTypeUInt32
+ EventMetadataEventLevel, // EvtVarTypeUInt32
+ EventMetadataEventOpcode, // EvtVarTypeUInt32
+ EventMetadataEventTask, // EvtVarTypeUInt32
+ EventMetadataEventKeyword, // EvtVarTypeUInt64
+ EventMetadataEventMessageID,// EvtVarTypeUInt32
+ EventMetadataEventTemplate // EvtVarTypeString
+ // EvtEventMetadataPropertyIdEND
+ }
+
+ // CHANNEL CONFIGURATION
+ internal enum EvtChannelConfigPropertyId
+ {
+ EvtChannelConfigEnabled = 0, // EvtVarTypeBoolean
+ EvtChannelConfigIsolation, // EvtVarTypeUInt32, EVT_CHANNEL_ISOLATION_TYPE
+ EvtChannelConfigType, // EvtVarTypeUInt32, EVT_CHANNEL_TYPE
+ EvtChannelConfigOwningPublisher, // EvtVarTypeString
+ EvtChannelConfigClassicEventlog, // EvtVarTypeBoolean
+ EvtChannelConfigAccess, // EvtVarTypeString
+ EvtChannelLoggingConfigRetention, // EvtVarTypeBoolean
+ EvtChannelLoggingConfigAutoBackup, // EvtVarTypeBoolean
+ EvtChannelLoggingConfigMaxSize, // EvtVarTypeUInt64
+ EvtChannelLoggingConfigLogFilePath, // EvtVarTypeString
+ EvtChannelPublishingConfigLevel, // EvtVarTypeUInt32
+ EvtChannelPublishingConfigKeywords, // EvtVarTypeUInt64
+ EvtChannelPublishingConfigControlGuid, // EvtVarTypeGuid
+ EvtChannelPublishingConfigBufferSize, // EvtVarTypeUInt32
+ EvtChannelPublishingConfigMinBuffers, // EvtVarTypeUInt32
+ EvtChannelPublishingConfigMaxBuffers, // EvtVarTypeUInt32
+ EvtChannelPublishingConfigLatency, // EvtVarTypeUInt32
+ EvtChannelPublishingConfigClockType, // EvtVarTypeUInt32, EVT_CHANNEL_CLOCK_TYPE
+ EvtChannelPublishingConfigSidType, // EvtVarTypeUInt32, EVT_CHANNEL_SID_TYPE
+ EvtChannelPublisherList, // EvtVarTypeString | EVT_VARIANT_TYPE_ARRAY
+ EvtChannelConfigPropertyIdEND
+ }
+
+ // LOG INFORMATION
+ internal enum EvtLogPropertyId
+ {
+ EvtLogCreationTime = 0, // EvtVarTypeFileTime
+ EvtLogLastAccessTime, // EvtVarTypeFileTime
+ EvtLogLastWriteTime, // EvtVarTypeFileTime
+ EvtLogFileSize, // EvtVarTypeUInt64
+ EvtLogAttributes, // EvtVarTypeUInt32
+ EvtLogNumberOfLogRecords, // EvtVarTypeUInt64
+ EvtLogOldestRecordNumber, // EvtVarTypeUInt64
+ EvtLogFull, // EvtVarTypeBoolean
+ }
+
+ internal enum EvtExportLogFlags
+ {
+ EvtExportLogChannelPath = 1,
+ EvtExportLogFilePath = 2,
+ EvtExportLogTolerateQueryErrors = 0x1000
+ }
+
+ // RENDERING
+ internal enum EvtRenderContextFlags
+ {
+ EvtRenderContextValues = 0, // Render specific properties
+ EvtRenderContextSystem = 1, // Render all system properties (System)
+ EvtRenderContextUser = 2 // Render all user properties (User/EventData)
+ }
+
+ internal enum EvtRenderFlags
+ {
+ EvtRenderEventValues = 0, // Variants
+ EvtRenderEventXml = 1, // XML
+ EvtRenderBookmark = 2 // Bookmark
+ }
+
+ internal enum EvtFormatMessageFlags
+ {
+ EvtFormatMessageEvent = 1,
+ EvtFormatMessageLevel = 2,
+ EvtFormatMessageTask = 3,
+ EvtFormatMessageOpcode = 4,
+ EvtFormatMessageKeyword = 5,
+ EvtFormatMessageChannel = 6,
+ EvtFormatMessageProvider = 7,
+ EvtFormatMessageId = 8,
+ EvtFormatMessageXml = 9
+ }
+
+ internal enum EvtSystemPropertyId
+ {
+ EvtSystemProviderName = 0, // EvtVarTypeString
+ EvtSystemProviderGuid, // EvtVarTypeGuid
+ EvtSystemEventID, // EvtVarTypeUInt16
+ EvtSystemQualifiers, // EvtVarTypeUInt16
+ EvtSystemLevel, // EvtVarTypeUInt8
+ EvtSystemTask, // EvtVarTypeUInt16
+ EvtSystemOpcode, // EvtVarTypeUInt8
+ EvtSystemKeywords, // EvtVarTypeHexInt64
+ EvtSystemTimeCreated, // EvtVarTypeFileTime
+ EvtSystemEventRecordId, // EvtVarTypeUInt64
+ EvtSystemActivityID, // EvtVarTypeGuid
+ EvtSystemRelatedActivityID, // EvtVarTypeGuid
+ EvtSystemProcessID, // EvtVarTypeUInt32
+ EvtSystemThreadID, // EvtVarTypeUInt32
+ EvtSystemChannel, // EvtVarTypeString
+ EvtSystemComputer, // EvtVarTypeString
+ EvtSystemUserID, // EvtVarTypeSid
+ EvtSystemVersion, // EvtVarTypeUInt8
+ EvtSystemPropertyIdEND
+ }
+
+ // SESSION
+ internal enum EvtLoginClass
+ {
+ EvtRpcLogin = 1
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ internal struct EvtRpcLogin
+ {
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string Server;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string User;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string Domain;
+ public CoTaskMemUnicodeSafeHandle Password;
+ public int Flags;
+ }
+
+ // SEEK
+ [Flags]
+ internal enum EvtSeekFlags
+ {
+ EvtSeekRelativeToFirst = 1,
+ EvtSeekRelativeToLast = 2,
+ EvtSeekRelativeToCurrent = 3,
+ EvtSeekRelativeToBookmark = 4,
+ EvtSeekOriginMask = 7,
+ EvtSeekStrict = 0x10000
+ }
+
+ [DllImport(WEVTAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ internal static extern EventLogHandle EvtQuery(
+ EventLogHandle session,
+ [MarshalAs(UnmanagedType.LPWStr)]string path,
+ [MarshalAs(UnmanagedType.LPWStr)]string query,
+ int flags);
+
+ // SEEK
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtSeek(
+ EventLogHandle resultSet,
+ long position,
+ EventLogHandle bookmark,
+ int timeout,
+ [MarshalAs(UnmanagedType.I4)]EvtSeekFlags flags
+ );
+
+ [DllImport(WEVTAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ internal static extern EventLogHandle EvtSubscribe(
+ EventLogHandle session,
+ SafeWaitHandle signalEvent,
+ [MarshalAs(UnmanagedType.LPWStr)]string path,
+ [MarshalAs(UnmanagedType.LPWStr)]string query,
+ EventLogHandle bookmark,
+ IntPtr context,
+ IntPtr callback,
+ int flags);
+
+ [DllImport(WEVTAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ internal static extern bool EvtNext(
+ EventLogHandle queryHandle,
+ int eventSize,
+ [MarshalAs(UnmanagedType.LPArray)] IntPtr[] events,
+ int timeout,
+ int flags,
+ ref int returned);
+
+ [DllImport(WEVTAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ internal static extern bool EvtCancel(EventLogHandle handle);
+
+ [DllImport(WEVTAPI)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool EvtClose(IntPtr handle);
+
+ /*
+ [DllImport(WEVTAPI, EntryPoint = "EvtClose", SetLastError = true)]
+ public static extern bool EvtClose(
+ IntPtr eventHandle
+ );
+ */
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtGetEventInfo(
+ EventLogHandle eventHandle,
+ // int propertyId
+ [MarshalAs(UnmanagedType.I4)]EvtEventPropertyId propertyId,
+ int bufferSize,
+ IntPtr bufferPtr,
+ out int bufferUsed
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtGetQueryInfo(
+ EventLogHandle queryHandle,
+ [MarshalAs(UnmanagedType.I4)]EvtQueryPropertyId propertyId,
+ int bufferSize,
+ IntPtr buffer,
+ ref int bufferRequired
+ );
+
+ // PUBLISHER METADATA
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern EventLogHandle EvtOpenPublisherMetadata(
+ EventLogHandle session,
+ [MarshalAs(UnmanagedType.LPWStr)] string publisherId,
+ [MarshalAs(UnmanagedType.LPWStr)] string logFilePath,
+ int locale,
+ int flags
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtGetPublisherMetadataProperty(
+ EventLogHandle publisherMetadataHandle,
+ [MarshalAs(UnmanagedType.I4)] EvtPublisherMetadataPropertyId propertyId,
+ int flags,
+ int publisherMetadataPropertyBufferSize,
+ IntPtr publisherMetadataPropertyBuffer,
+ out int publisherMetadataPropertyBufferUsed
+ );
+
+ // NEW
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtGetObjectArraySize(
+ EventLogHandle objectArray,
+ out int objectArraySize
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtGetObjectArrayProperty(
+ EventLogHandle objectArray,
+ int propertyId,
+ int arrayIndex,
+ int flags,
+ int propertyValueBufferSize,
+ IntPtr propertyValueBuffer,
+ out int propertyValueBufferUsed
+ );
+
+ // NEW 2
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern EventLogHandle EvtOpenEventMetadataEnum(
+ EventLogHandle publisherMetadata,
+ int flags
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ // public static extern IntPtr EvtNextEventMetadata(
+ internal static extern EventLogHandle EvtNextEventMetadata(
+ EventLogHandle eventMetadataEnum,
+ int flags
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtGetEventMetadataProperty(
+ EventLogHandle eventMetadata,
+ [MarshalAs(UnmanagedType.I4)] EvtEventMetadataPropertyId propertyId,
+ int flags,
+ int eventMetadataPropertyBufferSize,
+ IntPtr eventMetadataPropertyBuffer,
+ out int eventMetadataPropertyBufferUsed
+ );
+
+ // Channel Configuration Native Api
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern EventLogHandle EvtOpenChannelEnum(
+ EventLogHandle session,
+ int flags
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtNextChannelPath(
+ EventLogHandle channelEnum,
+ int channelPathBufferSize,
+ // StringBuilder channelPathBuffer,
+ [Out, MarshalAs(UnmanagedType.LPWStr)]StringBuilder channelPathBuffer,
+ out int channelPathBufferUsed
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern EventLogHandle EvtOpenPublisherEnum(
+ EventLogHandle session,
+ int flags
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtNextPublisherId(
+ EventLogHandle publisherEnum,
+ int publisherIdBufferSize,
+ [Out, MarshalAs(UnmanagedType.LPWStr)]StringBuilder publisherIdBuffer,
+ out int publisherIdBufferUsed
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern EventLogHandle EvtOpenChannelConfig(
+ EventLogHandle session,
+ [MarshalAs(UnmanagedType.LPWStr)]String channelPath,
+ int flags
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtSaveChannelConfig(
+ EventLogHandle channelConfig,
+ int flags
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtSetChannelConfigProperty(
+ EventLogHandle channelConfig,
+ [MarshalAs(UnmanagedType.I4)]EvtChannelConfigPropertyId propertyId,
+ int flags,
+ ref EvtVariant propertyValue
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtGetChannelConfigProperty(
+ EventLogHandle channelConfig,
+ [MarshalAs(UnmanagedType.I4)]EvtChannelConfigPropertyId propertyId,
+ int flags,
+ int propertyValueBufferSize,
+ IntPtr propertyValueBuffer,
+ out int propertyValueBufferUsed
+ );
+
+ // Log Information Native Api
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern EventLogHandle EvtOpenLog(
+ EventLogHandle session,
+ [MarshalAs(UnmanagedType.LPWStr)] string path,
+ [MarshalAs(UnmanagedType.I4)]PathType flags
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtGetLogInfo(
+ EventLogHandle log,
+ [MarshalAs(UnmanagedType.I4)]EvtLogPropertyId propertyId,
+ int propertyValueBufferSize,
+ IntPtr propertyValueBuffer,
+ out int propertyValueBufferUsed
+ );
+
+ // LOG MANIPULATION
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtExportLog(
+ EventLogHandle session,
+ [MarshalAs(UnmanagedType.LPWStr)]string channelPath,
+ [MarshalAs(UnmanagedType.LPWStr)]string query,
+ [MarshalAs(UnmanagedType.LPWStr)]string targetFilePath,
+ int flags
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtArchiveExportedLog(
+ EventLogHandle session,
+ [MarshalAs(UnmanagedType.LPWStr)]string logFilePath,
+ int locale,
+ int flags
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtClearLog(
+ EventLogHandle session,
+ [MarshalAs(UnmanagedType.LPWStr)]string channelPath,
+ [MarshalAs(UnmanagedType.LPWStr)]string targetFilePath,
+ int flags
+ );
+
+ // RENDERING
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern EventLogHandle EvtCreateRenderContext(
+ Int32 valuePathsCount,
+ [MarshalAs(UnmanagedType.LPArray,ArraySubType = UnmanagedType.LPWStr)]
+ String[] valuePaths,
+ [MarshalAs(UnmanagedType.I4)]EvtRenderContextFlags flags
+ );
+
+ [DllImport(WEVTAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ internal static extern bool EvtRender(
+ EventLogHandle context,
+ EventLogHandle eventHandle,
+ EvtRenderFlags flags,
+ int buffSize,
+ [Out, MarshalAs(UnmanagedType.LPWStr)]StringBuilder buffer,
+ out int buffUsed,
+ out int propCount
+ );
+
+ [DllImport(WEVTAPI, EntryPoint = "EvtRender", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ internal static extern bool EvtRender(
+ EventLogHandle context,
+ EventLogHandle eventHandle,
+ EvtRenderFlags flags,
+ int buffSize,
+ IntPtr buffer,
+ out int buffUsed,
+ out int propCount
+ );
+
+ [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
+ internal struct EvtStringVariant
+ {
+ [MarshalAs(UnmanagedType.LPWStr), FieldOffset(0)]
+ public string StringVal;
+ [FieldOffset(8)]
+ public UInt32 Count;
+ [FieldOffset(12)]
+ public UInt32 Type;
+ };
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtFormatMessage(
+ EventLogHandle publisherMetadataHandle,
+ EventLogHandle eventHandle,
+ uint messageId,
+ int valueCount,
+ EvtStringVariant[] values,
+ [MarshalAs(UnmanagedType.I4)]EvtFormatMessageFlags flags,
+ int bufferSize,
+ [Out, MarshalAs(UnmanagedType.LPWStr)]StringBuilder buffer,
+ out int bufferUsed
+ );
+
+ [DllImport(WEVTAPI, EntryPoint = "EvtFormatMessage", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtFormatMessageBuffer(
+ EventLogHandle publisherMetadataHandle,
+ EventLogHandle eventHandle,
+ uint messageId,
+ int valueCount,
+ IntPtr values,
+ [MarshalAs(UnmanagedType.I4)]EvtFormatMessageFlags flags,
+ int bufferSize,
+ IntPtr buffer,
+ out int bufferUsed
+ );
+
+ // SESSION
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern EventLogHandle EvtOpenSession(
+ [MarshalAs(UnmanagedType.I4)]EvtLoginClass loginClass,
+ ref EvtRpcLogin login,
+ int timeout,
+ int flags
+ );
+
+ // BOOKMARK
+ [DllImport(WEVTAPI, EntryPoint = "EvtCreateBookmark", CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern EventLogHandle EvtCreateBookmark(
+ [MarshalAs(UnmanagedType.LPWStr)] string bookmarkXml
+ );
+
+ [DllImport(WEVTAPI, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern bool EvtUpdateBookmark(
+ EventLogHandle bookmark,
+ EventLogHandle eventHandle
+ );
+ //
+ // EventLog
+ //
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.CodeAnalysis;
+
+namespace System.Diagnostics.Eventing.Reader
+{
+ /// <summary>
+ /// WindowsEventLevel
+ /// </summary>
+ public enum StandardEventLevel
+ {
+ /// <summary>
+ /// Log always
+ /// </summary>
+ LogAlways = 0,
+ /// <summary>
+ /// Only critical errors
+ /// </summary>
+ Critical,
+ /// <summary>
+ /// All errors, including previous levels
+ /// </summary>
+ Error,
+ /// <summary>
+ /// All warnings, including previous levels
+ /// </summary>
+ Warning,
+ /// <summary>
+ /// All informational events, including previous levels
+ /// </summary>
+ Informational,
+ /// <summary>
+ /// All events, including previous levels
+ /// </summary>
+ Verbose
+ }
+
+ /// <summary>
+ /// WindowsEventTask
+ /// </summary>
+ public enum StandardEventTask
+ {
+ /// <summary>
+ /// Undefined task
+ /// </summary>
+ None = 0
+ }
+
+ /// <summary>
+ /// EventOpcode
+ /// </summary>
+ [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Opcode", Justification = "matell: Shipped public in 3.5, breaking change to fix now.")]
+ public enum StandardEventOpcode
+ {
+ /// <summary>
+ /// An informational event
+ /// </summary>
+ Info = 0,
+ /// <summary>
+ /// An activity start event
+ /// </summary>
+ Start,
+ /// <summary>
+ /// An activity end event
+ /// </summary>
+ Stop,
+ /// <summary>
+ /// A trace collection start event
+ /// </summary>
+ DataCollectionStart,
+ /// <summary>
+ /// A trace collection end event
+ /// </summary>
+ DataCollectionStop,
+ /// <summary>
+ /// An extensional event
+ /// </summary>
+ Extension,
+ /// <summary>
+ /// A reply event
+ /// </summary>
+ Reply,
+ /// <summary>
+ /// An event representing the activity resuming from the suspension
+ /// </summary>
+ Resume,
+ /// <summary>
+ /// An event representing the activity is suspended, pending another activity's completion
+ /// </summary>
+ Suspend,
+ /// <summary>
+ /// An event representing the activity is transferred to another component, and can continue to work
+ /// </summary>
+ Send,
+ /// <summary>
+ /// An event representing receiving an activity transfer from another component
+ /// </summary>
+ Receive = 240
+ }
+
+ /// <summary>
+ /// EventOpcode
+ /// </summary>
+ [Flags]
+ public enum StandardEventKeywords : long
+ {
+ /// <summary>
+ /// Wild card value
+ /// </summary>
+ None = 0x0,
+ /// <summary>
+ /// Events providing response time information
+ /// </summary>
+ ResponseTime = 0x01000000000000,
+ /// <summary>
+ /// WDI context events
+ /// </summary>
+ WdiContext = 0x02000000000000,
+ /// <summary>
+ /// WDI diagnostic events
+ /// </summary>
+ WdiDiagnostic = 0x04000000000000,
+ /// <summary>
+ /// SQM events
+ /// </summary>
+ Sqm = 0x08000000000000,
+ /// <summary>
+ /// FAiled security audits
+ /// </summary>
+ AuditFailure = 0x10000000000000,
+ /// <summary>
+ /// Successful security audits
+ /// </summary>
+ AuditSuccess = 0x20000000000000,
+ /// <summary>
+ /// Incorrect CorrelationHint value mistakenly shipped in .NET 3.5. Don't use: duplicates AuditFailure.
+ /// </summary>
+ [Obsolete("Incorrect value: use CorrelationHint2 instead", false)]
+ CorrelationHint = 0x10000000000000,
+ /// <summary>
+ /// Transfer events where the related Activity ID is a computed value and not a GUID
+ /// </summary>
+ CorrelationHint2 = 0x40000000000000,
+ /// <summary>
+ /// Events raised using classic eventlog API
+ /// </summary>
+ EventLogClassic = 0x80000000000000
+ }
+}
{
public class EventLogEntryEventWrittenTest
{
- static AutoResetEvent signal;
+ private static AutoResetEvent signal;
private const string message = "EventLogEntryEventWrittenTestMessage";
private int eventCounter;
// See the LICENSE file in the project root for more information.
using System.ComponentModel;
+using System.Diagnostics.Eventing.Reader;
using System.Threading;
using Xunit;
{
internal class Helpers
{
+ public static bool NotElevatedAndSupportsEventLogs { get => !AdminHelpers.IsProcessElevated() && SupportsEventLogs; }
public static bool IsElevatedAndSupportsEventLogs { get => AdminHelpers.IsProcessElevated() && SupportsEventLogs; }
public static bool SupportsEventLogs { get => PlatformDetection.IsNotWindowsNanoServer; }
Assert.Equal(entriesExpected, RetryOnWin7((() => eventLog.Entries.Count)));
}
+
+ internal static EventBookmark GetBookmark(string log, PathType pathType)
+ {
+ var elq = new EventLogQuery(log, pathType) { ReverseDirection = true };
+ var reader = new EventLogReader(elq);
+ EventRecord record = reader.ReadEvent();
+ return record?.Bookmark;
+ }
}
}
<ItemGroup>
<Compile Include="EventInstanceTests.cs" />
<Compile Include="EventLogEntryCollectionTests.cs" />
- <Compile Include="EventLogTraceListenerTests.cs" />
<Compile Include="EventLogTests\EventLogEntryWrittenTest.cs" />
<Compile Include="EventLogTests\EventLogSourceCreationTests.cs" />
<Compile Include="EventLogTests\EventLogTests.cs" />
<Compile Include="EventLogTests\EventLogWriteEntryTests.cs" />
+ <Compile Include="EventLogTraceListenerTests.cs" />
<Compile Include="Helpers.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogConfigurationTests.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogExceptionTests.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogInformationTests.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogPropertySelectorTests.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogQueryTests.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogReaderTests.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogRecordTests.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogSessionTests.cs" />
+ <Compile Include="System\Diagnostics\Reader\EventLogWatcherTests.cs" />
+ <Compile Include="System\Diagnostics\Reader\ProviderMetadataTests.cs" />
</ItemGroup>
</Project>
\ No newline at end of file
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Eventing.Reader;
+using Xunit;
+
+namespace System.Diagnostics.Tests
+{
+ public class EventLogConfigurationTests
+ {
+ [ConditionalTheory(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ [InlineData("Microsoft-Windows-TaskScheduler/Operational")]
+ [InlineData("Application")]
+ public void EventLogConfiguration_CheckProperties_RemainsTheSame(string logName)
+ {
+ bool isEnabled;
+ string securityDescriptor;
+ EventLogMode logMode;
+ int? providerBufferSize;
+ long maximumSizeInBytes;
+ int? providerMinimumNumberOfBuffers;
+ int? providerMaximumNumberOfBuffers;
+ int? providerLatency;
+ int? providerLevel;
+ long? providerKeywords;
+ Guid? providerControlGuid;
+
+ using (var session = new EventLogSession())
+ {
+ EventLogConfiguration configuration = null;
+ try
+ {
+ configuration = new EventLogConfiguration(logName, session);
+ }
+ catch (EventLogNotFoundException)
+ {
+ configuration?.Dispose();
+ return;
+ }
+
+ Assert.Equal(logName, configuration.LogName);
+ Assert.NotEmpty(configuration.ProviderNames);
+ Assert.Equal("Application", configuration.LogIsolation.ToString());
+
+ if (logName.Equals("Application"))
+ {
+ Assert.Equal(EventLogType.Administrative, configuration.LogType);
+ Assert.True(configuration.IsClassicLog);
+ Assert.Contains("Application.evtx", configuration.LogFilePath);
+ Assert.Empty(configuration.OwningProviderName);
+ }
+ else
+ {
+ Assert.Equal(EventLogType.Operational, configuration.LogType);
+ Assert.False(configuration.IsClassicLog);
+ Assert.Contains("Microsoft-Windows-TaskScheduler%4Operational.evtx", configuration.LogFilePath);
+ Assert.Equal("Microsoft-Windows-TaskScheduler", configuration.OwningProviderName);
+ }
+
+ isEnabled = configuration.IsEnabled;
+ securityDescriptor = configuration.SecurityDescriptor;
+ logMode = configuration.LogMode;
+ providerBufferSize = configuration.ProviderBufferSize;
+ maximumSizeInBytes = configuration.MaximumSizeInBytes;
+ providerMinimumNumberOfBuffers = configuration.ProviderMinimumNumberOfBuffers;
+ providerMaximumNumberOfBuffers = configuration.ProviderMaximumNumberOfBuffers;
+ providerLevel = configuration.ProviderLevel;
+ providerKeywords = configuration.ProviderKeywords;
+ providerControlGuid = configuration.ProviderControlGuid;
+ providerLatency = configuration.ProviderLatency;
+
+ configuration.Dispose();
+ }
+ using (var session = new EventLogSession())
+ {
+ using (var configuration = new EventLogConfiguration(logName, session))
+ {
+ Assert.Equal(isEnabled, configuration.IsEnabled);
+ Assert.Equal(securityDescriptor, configuration.SecurityDescriptor);
+ Assert.Equal(logMode, configuration.LogMode);
+ Assert.Equal(providerBufferSize, configuration.ProviderBufferSize);
+ Assert.Equal(maximumSizeInBytes, configuration.MaximumSizeInBytes);
+ Assert.Equal(providerMinimumNumberOfBuffers, configuration.ProviderMinimumNumberOfBuffers);
+ Assert.Equal(providerMaximumNumberOfBuffers, configuration.ProviderMaximumNumberOfBuffers);
+ Assert.Equal(providerLevel, configuration.ProviderLevel);
+ Assert.Equal(providerKeywords, configuration.ProviderKeywords);
+ Assert.Equal(providerControlGuid, configuration.ProviderControlGuid);
+ Assert.Equal(providerLatency, configuration.ProviderLatency);
+ }
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.NotElevatedAndSupportsEventLogs))]
+ public void SetProperties_SaveChanges_NotAdmin_Throws()
+ {
+ const string LogName = "Application";
+ using (var session = new EventLogSession())
+ {
+ EventLogConfiguration configuration = null;
+ try
+ {
+ configuration = new EventLogConfiguration(LogName, session);
+ }
+ catch (EventLogNotFoundException)
+ {
+ configuration?.Dispose();
+ return;
+ }
+
+ configuration.IsEnabled = false;
+ configuration.SecurityDescriptor = string.Empty;
+ configuration.LogFilePath = null;
+ configuration.LogMode = EventLogMode.Retain;
+ configuration.ProviderLevel = 1;
+ configuration.ProviderKeywords = 1;
+ configuration.MaximumSizeInBytes = long.MaxValue;
+ Assert.Throws<UnauthorizedAccessException>(() => configuration.SaveChanges());
+
+ configuration.Dispose();
+ session.CancelCurrentOperations();
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Eventing.Reader;
+using Xunit;
+
+namespace System.Diagnostics.Tests
+{
+ public class EventLogExceptionTests
+ {
+ [Fact]
+ public void EventLogNotFoundException_Ctor()
+ {
+ Assert.ThrowsAsync<EventLogNotFoundException>(() => throw new EventLogNotFoundException());
+ Assert.ThrowsAsync<EventLogNotFoundException>(() => throw new EventLogNotFoundException("message"));
+ Assert.ThrowsAsync<EventLogNotFoundException>(() => throw new EventLogNotFoundException("message", new Exception("inner exception")));
+ }
+
+ [Fact]
+ public void EventLogReadingException_Ctor()
+ {
+ Assert.ThrowsAsync<EventLogReadingException>(() => throw new EventLogReadingException());
+ Assert.ThrowsAsync<EventLogReadingException>(() => throw new EventLogReadingException("message"));
+ Assert.ThrowsAsync<EventLogReadingException>(() => throw new EventLogReadingException("message", new Exception("inner exception")));
+ }
+
+ [Fact]
+ public void EventLogProviderDisabledException_Ctor()
+ {
+ Assert.ThrowsAsync<EventLogProviderDisabledException>(() => throw new EventLogProviderDisabledException());
+ Assert.ThrowsAsync<EventLogProviderDisabledException>(() => throw new EventLogProviderDisabledException("message"));
+ Assert.ThrowsAsync<EventLogProviderDisabledException>(() => throw new EventLogProviderDisabledException("message", new Exception("inner exception")));
+ }
+
+ [Fact]
+ public void EventLogInvalidDataException_Ctor()
+ {
+ Assert.ThrowsAsync<EventLogInvalidDataException>(() => throw new EventLogInvalidDataException());
+ Assert.ThrowsAsync<EventLogInvalidDataException>(() => throw new EventLogInvalidDataException("message"));
+ Assert.ThrowsAsync<EventLogInvalidDataException>(() => throw new EventLogInvalidDataException("message", new Exception("inner exception")));
+ }
+
+ }
+}
\ No newline at end of file
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Eventing.Reader;
+using Xunit;
+
+namespace System.Diagnostics.Tests
+{
+ public class EventLogInformationTests
+ {
+ [ConditionalTheory(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void GetLogInformation_NullLogName_Throws(bool usingDefaultCtor)
+ {
+ using (var session = usingDefaultCtor ? new EventLogSession() : new EventLogSession(null))
+ {
+ Assert.Throws<ArgumentNullException>(() => session.GetLogInformation(null, PathType.LogName));
+ }
+ }
+
+ [ConditionalTheory(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ [InlineData("Microsoft-Windows-TaskScheduler/Operational")]
+ [InlineData("Application")]
+ public void GetLogInformation_UsingLogName_DoesNotThrow(string logName)
+ {
+ DateTime? creationTime, lastAccessTime, lastWriteTime;
+ long? fileSize, recordCount, oldestRecordNumber;
+ int? attributes;
+ bool? isLogFull;
+ using (var session = new EventLogSession())
+ {
+ EventLogConfiguration configuration = null;
+ try
+ {
+ configuration = new EventLogConfiguration(logName, session);
+ }
+ catch (EventLogNotFoundException)
+ {
+ configuration?.Dispose();
+ return;
+ }
+
+ EventLogInformation logInfo = session.GetLogInformation(configuration.LogName, PathType.LogName);
+ creationTime = logInfo.CreationTime;
+ lastAccessTime = logInfo.LastAccessTime;
+ lastWriteTime = logInfo.LastWriteTime;
+ fileSize = logInfo.FileSize;
+ attributes = logInfo.Attributes;
+ recordCount = logInfo.RecordCount;
+ oldestRecordNumber = logInfo.OldestRecordNumber;
+ isLogFull = logInfo.IsLogFull;
+
+ configuration.Dispose();
+ }
+ using (var session = new EventLogSession())
+ {
+ using (var configuration = new EventLogConfiguration(logName, session))
+ {
+ EventLogInformation logInfo = session.GetLogInformation(configuration.LogName, PathType.LogName);
+ Assert.Equal(creationTime, logInfo.CreationTime);
+ Assert.Equal(lastAccessTime, logInfo.LastAccessTime);
+ Assert.Equal(lastWriteTime, logInfo.LastWriteTime);
+ Assert.Equal(fileSize, logInfo.FileSize);
+ Assert.Equal(attributes, logInfo.Attributes);
+ Assert.Equal(recordCount, logInfo.RecordCount);
+ Assert.Equal(oldestRecordNumber, logInfo.OldestRecordNumber);
+ Assert.Equal(isLogFull, logInfo.IsLogFull);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.even
+
+using System.Collections.Generic;
+using System.Diagnostics.Eventing.Reader;
+using Xunit;
+
+namespace System.Diagnostics.Tests
+{
+ public class EventLogPropertySelectorTests
+ {
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void Ctor_NullPropertyQueries_Throws()
+ {
+ Assert.Throws<ArgumentNullException>(() => new EventLogPropertySelector(null));
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void Ctor_NonEmptyPropertyQuery_Success()
+ {
+ IDictionary<string, string> dictionary = new SortedDictionary<string, string>() { ["key"] = "value" };
+ var selector = new EventLogPropertySelector(dictionary.Keys);
+ Assert.NotNull(selector);
+ selector.Dispose();
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void GetPropertyValues_MatchProviderIdUsingProviderMetadata_Success()
+ {
+ Dictionary<string, Guid> providerNameAndIds = new Dictionary<string, Guid>();
+
+ string logName = "Application";
+ string queryString = "*[System/Level=4]";
+ var xPathEnum = new List<string>() { "Event/System/EventID", "Event/System/Provider/@Name" };
+ var logPropertyContext = new EventLogPropertySelector(xPathEnum);
+ var eventsQuery = new EventLogQuery(logName, PathType.LogName, queryString);
+ try
+ {
+ using (var logReader = new EventLogReader(eventsQuery))
+ {
+ for (EventLogRecord eventRecord = (EventLogRecord)logReader.ReadEvent();
+ eventRecord != null;
+ eventRecord = (EventLogRecord)logReader.ReadEvent())
+ {
+ IList<object> logEventProps;
+ logEventProps = eventRecord.GetPropertyValues(logPropertyContext);
+ int eventId;
+ Assert.True(int.TryParse(string.Format("{0}", logEventProps[0]), out eventId));
+ string providerName = (string)logEventProps[1];
+ if (!providerNameAndIds.ContainsKey(providerName) && eventRecord.ProviderId.HasValue)
+ {
+ providerNameAndIds.Add(providerName, eventRecord.ProviderId.Value);
+ }
+ }
+ }
+ }
+ catch (EventLogNotFoundException) { }
+
+ if (providerNameAndIds.Count > 0)
+ {
+ using (var session = new EventLogSession())
+ {
+ foreach (var nameAndId in providerNameAndIds)
+ {
+ ProviderMetadata providerMetadata = null;
+ try
+ {
+ providerMetadata = new ProviderMetadata(nameAndId.Key);
+ Assert.Equal(providerMetadata.Id, nameAndId.Value);
+ }
+ catch (EventLogException)
+ {
+ continue;
+ }
+ finally
+ {
+ providerMetadata?.Dispose();
+ }
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.even
+
+using System.Diagnostics.Eventing.Reader;
+using Xunit;
+
+namespace System.Diagnostics.Tests
+{
+ public class EventLogQueryTests
+ {
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void Ctor_PathAndQueryNull_Throws()
+ {
+ if (PlatformDetection.IsWindows7) // Null events in PowerShell log
+ return;
+ Assert.Throws<ArgumentNullException>(() => new EventLogQuery(null, PathType.LogName, null));
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void QueryByLevel_LevelMatchesQuery()
+ {
+ EventLogQuery eventsQuery = new EventLogQuery("Application", PathType.LogName, "*[System/Level=4]");
+ using (var logReader = new EventLogReader(eventsQuery))
+ {
+ int count = 0;
+ // For each event returned from the query
+ for (EventRecord eventRecord = logReader.ReadEvent();
+ eventRecord != null;
+ eventRecord = logReader.ReadEvent())
+ {
+ count++;
+ if (eventRecord.Level.HasValue)
+ Assert.Equal(4, eventRecord.Level.Value);
+ }
+ Assert.NotEqual(0, count);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Eventing.Reader;
+using Xunit;
+
+namespace System.Diagnostics.Tests
+{
+ public class EventLogReaderTests
+ {
+ [ConditionalTheory(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ [InlineData("Application", false)]
+ [InlineData("Application", true)]
+ public void ReadEvent(string logName, bool useQuery)
+ {
+ var eventLog =
+ useQuery
+ ? new EventLogReader(
+ new EventLogQuery(logName, PathType.LogName) { ReverseDirection = true })
+ : new EventLogReader(logName);
+
+ using (eventLog)
+ {
+ using (EventRecord record = eventLog.ReadEvent())
+ {
+ Assert.NotNull(record);
+ Assert.Equal(logName, record.LogName);
+ }
+ }
+ }
+
+ [ConditionalTheory(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ [InlineData("Microsoft-Windows-PowerShell/Operational", false)]
+ [InlineData("Microsoft-Windows-PowerShell/Operational", true)]
+ public void ReadEventPsh(string logName, bool useQuery)
+ {
+ if (PlatformDetection.IsWindows7) // Null events in PowerShell log
+ return;
+
+ ReadEvent(logName, useQuery);
+ }
+
+ [ConditionalTheory(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void WrongPathType_ReverseDirection_Throws(bool useBookmark)
+ {
+ if (PlatformDetection.IsWindows7) // Null events in PowerShell log
+ return;
+ var query = new EventLogQuery(null, PathType.FilePath, "*[System[(Level=2)]]") { ReverseDirection = true };
+ if (useBookmark)
+ {
+ Assert.Throws<EventLogException>(() => new EventLogReader(query, bookmark: null));
+ Assert.Throws<EventLogException>(() => new EventLogReader(query, bookmark: Helpers.GetBookmark("Application", PathType.LogName)));
+ }
+ else
+ {
+ Assert.Throws<EventLogException>(() => new EventLogReader(query));
+ }
+ }
+
+ [ConditionalTheory(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void WrongPathType_TolerateQueryErrors_Throws(bool useBookmark)
+ {
+ if (PlatformDetection.IsWindows7) // Null events in PowerShell log
+ return;
+ var query = new EventLogQuery(null, PathType.FilePath, "*[System[(Level=2)]]") { TolerateQueryErrors = true };
+ if (useBookmark)
+ {
+ Assert.Throws<EventLogException>(() => new EventLogReader(query, bookmark: null));
+ Assert.Throws<EventLogException>(() => new EventLogReader(query, bookmark: Helpers.GetBookmark("Application", PathType.LogName)));
+ }
+ else
+ {
+ Assert.Throws<EventLogException>(() => new EventLogReader(query));
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void CastToEventLogRecord_NotNull()
+ {
+ if (PlatformDetection.IsWindows7) // Null events in PowerShell log
+ return;
+ var query = new EventLogQuery("Application", PathType.LogName, "*[System]") { ReverseDirection = true };
+ var eventLog = new EventLogReader(query, Helpers.GetBookmark("Application", PathType.LogName));
+ using (eventLog)
+ {
+ using (var record = (EventLogRecord)eventLog.ReadEvent())
+ {
+ Assert.NotNull(record);
+ }
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void Seek()
+ {
+ using (var eventLog = new EventLogReader("Application"))
+ {
+ using (EventRecord record = eventLog.ReadEvent())
+ {
+ eventLog.Seek(record.Bookmark);
+ eventLog.Seek(IO.SeekOrigin.Begin, 0);
+ eventLog.Seek(IO.SeekOrigin.Current, 0);
+ eventLog.Seek(IO.SeekOrigin.End, 0);
+ }
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void CancelReading()
+ {
+ using (var eventLog = new EventLogReader("Application"))
+ {
+ eventLog.CancelReading();
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void LogStatus()
+ {
+ using (var eventLog = new EventLogReader("Application"))
+ {
+ Assert.NotEmpty(eventLog.LogStatus);
+ foreach (var logStatus in eventLog.LogStatus)
+ {
+ Assert.Equal("Application", logStatus.LogName);
+ Assert.Equal(0, logStatus.StatusCode);
+ }
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void BatchSize_OtherCtor()
+ {
+ using (var eventLog = new EventLogReader("Application", PathType.LogName))
+ {
+ Assert.Equal(64, eventLog.BatchSize);
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void Ctor_NullQuery_Throws()
+ {
+ Assert.Throws<ArgumentNullException>(() => new EventLogReader(null, null));
+ }
+ }
+}
+
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics.Eventing.Reader;
+using System.Security.Principal;
+using Xunit;
+
+namespace System.Diagnostics.Tests
+{
+ public class EventLogRecordTests
+ {
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void GetPropertyValues()
+ {
+ if (PlatformDetection.IsWindows7) // Null events in PowerShell log
+ return;
+ var query = new EventLogQuery("Application", PathType.LogName, "*[System]") { ReverseDirection = true };
+ var eventLog = new EventLogReader(query, Helpers.GetBookmark("Application", PathType.LogName));
+ using (eventLog)
+ {
+ using (var record = (EventLogRecord)eventLog.ReadEvent())
+ {
+ Assert.Throws<ArgumentNullException>(() => record.GetPropertyValues(null));
+ Assert.NotNull(record.GetPropertyValues(new EventLogPropertySelector(new [] {"dummy"})));
+ }
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)]
+ public void FormatDescription()
+ {
+ if (PlatformDetection.IsWindows7) // Null events in PowerShell log
+ return;
+ var query = new EventLogQuery("Application", PathType.LogName, "*[System]") { ReverseDirection = true };
+ var eventLog = new EventLogReader(query, Helpers.GetBookmark("Application", PathType.LogName));
+ using (eventLog)
+ {
+ using (var record = (EventLogRecord)eventLog.ReadEvent())
+ {
+ Assert.Throws<EventLogNotFoundException>(() => record.FormatDescription(new[] {"dummy"}));
+ Assert.Null(record.FormatDescription());
+ Assert.Throws<EventLogNotFoundException>(() => ((EventRecord)record).FormatDescription(new[] {"dummy"}));
+ Assert.Null(((EventRecord)record).FormatDescription(null));
+ Assert.Null(((EventRecord)record).FormatDescription());
+ }
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void Properties()
+ {
+ if (PlatformDetection.IsWindows7) // Null events in PowerShell log
+ return;
+ var query = new EventLogQuery("Application", PathType.LogName, "*[System]") { ReverseDirection = true };
+ var eventLog = new EventLogReader(query, Helpers.GetBookmark("Application", PathType.LogName));
+ using (eventLog)
+ {
+ using (var record = (EventLogRecord)eventLog.ReadEvent())
+ {
+ Assert.NotNull(record.Properties);
+ foreach (EventProperty eventProperty in record.Properties)
+ {
+ Assert.NotNull(eventProperty.Value);
+ }
+ }
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void ToXml()
+ {
+ if (PlatformDetection.IsWindows7) // Null events in PowerShell log
+ return;
+ var query = new EventLogQuery("Application", PathType.LogName, "*[System]") { ReverseDirection = true };
+ var eventLog = new EventLogReader(query, Helpers.GetBookmark("Application", PathType.LogName));
+ using (eventLog)
+ {
+ using (var record = (EventLogRecord)eventLog.ReadEvent())
+ {
+ Assert.NotNull(record.ToXml());
+ }
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void ExceptionOnce()
+ {
+ if (PlatformDetection.IsWindows7) // Null events in PowerShell log
+ return;
+ var query = new EventLogQuery("Application", PathType.LogName, "*[System]") { ReverseDirection = true };
+ var eventLog = new EventLogReader(query, Helpers.GetBookmark("Application", PathType.LogName));
+ string levelDisplayName = null, opcodeDisplayName = null, taskDisplayName = null;
+ using (eventLog)
+ {
+ using (var record = (EventLogRecord)eventLog.ReadEvent())
+ {
+ ThrowsMaxOnce<EventLogNotFoundException>(() => levelDisplayName = record.LevelDisplayName);
+ ThrowsMaxOnce<EventLogNotFoundException>(() => opcodeDisplayName = record.OpcodeDisplayName);
+ ThrowsMaxOnce<EventLogNotFoundException>(() => taskDisplayName = record.TaskDisplayName);
+ Assert.Equal(levelDisplayName, record.LevelDisplayName);
+ Assert.Equal(opcodeDisplayName, record.OpcodeDisplayName);
+ Assert.Equal(taskDisplayName, record.TaskDisplayName);
+ }
+ }
+ }
+
+ private void ThrowsMaxOnce<T>(Action action) where T : Exception
+ {
+ try
+ {
+ action();
+ }
+ catch (T)
+ {
+ action();
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void EventLogRecord_CheckProperties_RemainSame()
+ {
+ if (PlatformDetection.IsWindows7) // Null events in PowerShell log
+ return;
+
+ SecurityIdentifier userId;
+ byte? version, level;
+ short? opcode;
+ Guid? providerId, activityId, relatedActivityId;
+ int? processId, threadId, qualifiers, task;
+ long? keywords, recordId;
+ string providerName, machineName, containerLog;
+ DateTime? timeCreated;
+ IEnumerable<int> matchedQueryIds;
+ EventBookmark bookmark, bookmarkArg = Helpers.GetBookmark("Application", PathType.LogName);
+
+ var query = new EventLogQuery("Application", PathType.LogName, "*[System]") { ReverseDirection = true };
+ var eventLog = new EventLogReader(query, bookmarkArg);
+ using (eventLog)
+ {
+ using (var record = (EventLogRecord)eventLog.ReadEvent())
+ {
+ userId = record.UserId;
+ version = record.Version;
+ opcode = record.Opcode;
+ providerId = record.ProviderId;
+ processId = record.ProcessId;
+ recordId = record.RecordId;
+ threadId = record.ThreadId;
+ qualifiers = record.Qualifiers;
+ level = record.Level;
+ keywords = record.Keywords;
+ task = record.Task;
+ providerName = record.ProviderName;
+ machineName = record.MachineName;
+ timeCreated = record.TimeCreated;
+ containerLog = record.ContainerLog;
+ matchedQueryIds = record.MatchedQueryIds;
+ activityId = record.ActivityId;
+ relatedActivityId = record.RelatedActivityId;
+ bookmark = record.Bookmark;
+ }
+ }
+
+ using (eventLog = new EventLogReader(query, bookmarkArg))
+ {
+ using (var record = (EventLogRecord)eventLog.ReadEvent())
+ {
+ Assert.Equal(userId, record.UserId);
+ Assert.Equal(version, record.Version);
+ Assert.Equal(opcode, record.Opcode);
+ Assert.Equal(providerId, record.ProviderId);
+ Assert.Equal(processId, record.ProcessId);
+ Assert.Equal(recordId, record.RecordId);
+ Assert.Equal(threadId, record.ThreadId);
+ Assert.Equal(qualifiers, record.Qualifiers);
+ Assert.Equal(level, record.Level);
+ Assert.Equal(keywords, record.Keywords);
+ Assert.Equal(task, record.Task);
+ Assert.Equal(providerName, record.ProviderName);
+ Assert.Equal(machineName, record.MachineName);
+ Assert.Equal(timeCreated, record.TimeCreated);
+ Assert.Equal(containerLog, record.ContainerLog);
+ Assert.Equal(matchedQueryIds, record.MatchedQueryIds);
+ Assert.Equal(activityId, record.ActivityId);
+ Assert.Equal(relatedActivityId, record.RelatedActivityId);
+ Assert.NotNull(record.Bookmark);
+ Assert.NotEqual(bookmark, record.Bookmark);
+ }
+ }
+ }
+ }
+}
+
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Eventing.Reader;
+using System.Globalization;
+using System.IO;
+using System.Security;
+using Xunit;
+
+namespace System.Diagnostics.Tests
+{
+ public class EventLogSessionTests : FileCleanupTestBase
+ {
+ private const string LogName = "Application";
+
+ [ConditionalTheory(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void Ctors_ProviderNames_LogNames_NotEmpty(bool usingDefaultCtor)
+ {
+ using (var session = usingDefaultCtor ? new EventLogSession() : new EventLogSession(null))
+ {
+ Assert.NotEmpty(session.GetProviderNames());
+ Assert.NotEmpty(session.GetLogNames());
+ }
+ }
+
+ [ConditionalTheory(typeof(Helpers), nameof(Helpers.IsElevatedAndSupportsEventLogs))]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void ExportLogAndMessages_NullPath_Throws(bool usingDefaultCtor)
+ {
+ using (var session = usingDefaultCtor ? new EventLogSession() : new EventLogSession(null))
+ {
+ Assert.Throws<ArgumentNullException>(() => session.ExportLogAndMessages(null, PathType.LogName, LogName, GetTestFilePath()));
+ // Does not throw:
+ session.ExportLogAndMessages(LogName, PathType.LogName, LogName, GetTestFilePath());
+ session.ExportLogAndMessages(LogName, PathType.LogName, LogName, GetTestFilePath(), false, targetCultureInfo: CultureInfo.CurrentCulture);
+ session.CancelCurrentOperations();
+ }
+ }
+
+ [ConditionalTheory(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void ExportLog_InvalidInputCombinations_Throws(bool usingDefaultCtor)
+ {
+ using (var session = usingDefaultCtor ? new EventLogSession() : new EventLogSession(null))
+ {
+ Assert.Throws<ArgumentNullException>(() => session.ExportLog(null, PathType.LogName, LogName, GetTestFilePath()));
+ Assert.Throws<ArgumentNullException>(() => session.ExportLog(LogName, PathType.LogName, LogName, null));
+ Assert.Throws<ArgumentOutOfRangeException>(() => session.ExportLog(LogName, (PathType)0, LogName, GetTestFilePath()));
+ Assert.Throws<EventLogNotFoundException>(() => session.ExportLog(LogName, PathType.FilePath, LogName, GetTestFilePath()));
+ // Does not throw:
+ session.ExportLog(LogName, PathType.LogName, LogName, GetTestFilePath(), tolerateQueryErrors: true);
+ session.CancelCurrentOperations();
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void GetProviderNames_WithPassword_Throws()
+ {
+ var password = new SecureString();
+ password.AppendChar('a');
+ using (var session = new EventLogSession(null, null, null, password, SessionAuthentication.Default))
+ {
+ Assert.Throws<UnauthorizedAccessException>(() => session.GetProviderNames());
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndSupportsEventLogs))]
+ public void ClearLog_LogNameNullEmptyOrNotExist_Throws()
+ {
+ using (var session = new EventLogSession())
+ {
+ Assert.Throws<ArgumentNullException>(() => session.ClearLog(null));
+ Assert.Throws<ArgumentNullException>(() => session.ClearLog(null, backupPath: GetTestFilePath()));
+ Assert.Throws<EventLogException>(() => session.ClearLog(""));
+ Assert.Throws<EventLogNotFoundException>(() => session.ClearLog(logName: nameof(ClearLog_LogNameNullEmptyOrNotExist_Throws)));
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndSupportsEventLogs))]
+ public void ClearLog_LogExists_Success()
+ {
+ using (var session = new EventLogSession())
+ {
+ string log = "Log_" + nameof(ClearLog_LogExists_Success);
+ string source = "Source_" + nameof(ClearLog_LogExists_Success);
+ try
+ {
+ EventLog.CreateEventSource(source, log);
+ using (EventLog eventLog = new EventLog())
+ {
+ eventLog.Source = source;
+ eventLog.WriteEntry("Writing to event log.");
+ Assert.NotEqual(0, eventLog.Entries.Count);
+ session.ClearLog(logName: log);
+ Assert.Equal(0, eventLog.Entries.Count);
+ }
+ }
+ finally
+ {
+ EventLog.DeleteEventSource(source);
+ }
+ session.CancelCurrentOperations();
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Eventing.Reader;
+using System.Threading;
+using Xunit;
+
+namespace System.Diagnostics.Tests
+{
+ public class EventLogWatcherTests
+ {
+ private static AutoResetEvent signal;
+ private const string message = "EventRecordWrittenTestMessage";
+ private int eventCounter;
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void Ctor_Default()
+ {
+ using (var eventLogWatcher = new EventLogWatcher("Application"))
+ {
+ Assert.False(eventLogWatcher.Enabled);
+ eventLogWatcher.Enabled = true;
+ Assert.True(eventLogWatcher.Enabled);
+ eventLogWatcher.Enabled = false;
+ Assert.False(eventLogWatcher.Enabled);
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void Ctor_UsingBookmark()
+ {
+ EventBookmark bookmark = GetBookmark();
+ Assert.Throws<ArgumentNullException>(() => new EventLogWatcher(null, bookmark, true));
+ Assert.Throws<InvalidOperationException>(() => new EventLogWatcher(new EventLogQuery("Application", PathType.LogName, "*[System]") { ReverseDirection = true }, bookmark, true));
+
+ var query = new EventLogQuery("Application", PathType.LogName, "*[System]");
+ using (var eventLogWatcher = new EventLogWatcher(query, bookmark))
+ {
+ Assert.False(eventLogWatcher.Enabled);
+ eventLogWatcher.Enabled = true;
+ Assert.True(eventLogWatcher.Enabled);
+ eventLogWatcher.Enabled = false;
+ Assert.False(eventLogWatcher.Enabled);
+ }
+ }
+
+ private EventBookmark GetBookmark()
+ {
+ EventBookmark bookmark;
+ EventLogQuery eventLogQuery = new EventLogQuery("Application", PathType.LogName, "*[System]");
+ using (var eventLog = new EventLogReader(eventLogQuery))
+ using (var record = eventLog.ReadEvent())
+ {
+ Assert.NotNull(record);
+ bookmark = record.Bookmark;
+ Assert.NotNull(record.Bookmark);
+ }
+ return bookmark;
+ }
+
+ public void RaisingEvent(string log, string methodName, bool waitOnEvent = true)
+ {
+ signal = new AutoResetEvent(false);
+ eventCounter = 0;
+ string source = "Source_" + methodName;
+
+ try
+ {
+ EventLog.CreateEventSource(source, log);
+ var query = new EventLogQuery(log, PathType.LogName);
+ using (EventLog eventLog = new EventLog())
+ using (EventLogWatcher eventLogWatcher = new EventLogWatcher(query))
+ {
+ eventLog.Source = source;
+ eventLogWatcher.EventRecordWritten += (s, e) =>
+ {
+ eventCounter += 1;
+ Assert.True(e.EventException != null || e.EventRecord != null);
+ signal.Set();
+ };
+ Helpers.RetryOnWin7(() => eventLogWatcher.Enabled = waitOnEvent);
+ Helpers.RetryOnWin7(() => eventLog.WriteEntry(message, EventLogEntryType.Information));
+ if (waitOnEvent)
+ {
+ Assert.True(signal.WaitOne(6000));
+ }
+ }
+ }
+ finally
+ {
+ EventLog.DeleteEventSource(source);
+ Helpers.RetryOnWin7(() => EventLog.Delete(log));
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndSupportsEventLogs))]
+ public void RecordWrittenEventRaised()
+ {
+ RaisingEvent("EnableEvent", nameof(RecordWrittenEventRaised));
+ Assert.NotEqual(0, eventCounter);
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndSupportsEventLogs))]
+ public void RecordWrittenEventRaiseDisable()
+ {
+ RaisingEvent("DisableEvent", nameof(RecordWrittenEventRaiseDisable), waitOnEvent: false);
+ Assert.Equal(0, eventCounter);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics.Eventing.Reader;
+using System.Globalization;
+using System.Linq;
+using Xunit;
+
+namespace System.Diagnostics.Tests
+{
+ public class ProviderMetadataTests
+ {
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void SourceDoesNotExist_Throws()
+ {
+ Assert.Throws<EventLogNotFoundException>(() => new ProviderMetadata("Source_Does_Not_Exist"));
+ }
+
+ [ConditionalTheory(typeof(Helpers), nameof(Helpers.IsElevatedAndSupportsEventLogs))]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void ProviderNameTests(bool noProviderName)
+ {
+ string log = "Application";
+ string source = "Source_" + nameof(ProviderNameTests);
+ using (var session = new EventLogSession())
+ {
+ try
+ {
+ EventLog.CreateEventSource(source, log);
+
+ string providerName = noProviderName ? "" : source;
+ using (var providerMetadata = new ProviderMetadata(providerName))
+ {
+ Assert.Null(providerMetadata.DisplayName);
+ Assert.Equal(providerName, providerMetadata.Name);
+ Assert.Equal(new Guid(), providerMetadata.Id);
+ Assert.Empty(providerMetadata.Events);
+ Assert.Empty(providerMetadata.Keywords);
+ Assert.Empty(providerMetadata.Levels);
+ Assert.Empty(providerMetadata.Opcodes);
+ Assert.Empty(providerMetadata.Tasks);
+ Assert.NotEmpty(providerMetadata.LogLinks);
+ if (!string.IsNullOrEmpty(providerName))
+ {
+ foreach (var logLink in providerMetadata.LogLinks)
+ {
+ Assert.True(logLink.IsImported);
+ Assert.Equal(log, logLink.LogName);
+ Assert.NotEmpty(logLink.DisplayName);
+ if (CultureInfo.CurrentCulture.Name.Split('-')[0] == "en" )
+ {
+ Assert.Equal("Application", logLink.DisplayName);
+ }
+ else if (CultureInfo.CurrentCulture.Name.Split('-')[0] == "es" )
+ {
+ Assert.Equal("AplicaciĆ³n", logLink.DisplayName);
+ }
+ }
+ Assert.Contains("EventLogMessages.dll", providerMetadata.MessageFilePath);
+ Assert.Contains("EventLogMessages.dll", providerMetadata.HelpLink.ToString());
+ }
+ else
+ {
+ Assert.Null(providerMetadata.MessageFilePath);
+ Assert.Null(providerMetadata.HelpLink);
+ }
+ Assert.Null(providerMetadata.ResourceFilePath);
+ Assert.Null(providerMetadata.ParameterFilePath);
+ }
+ }
+ finally
+ {
+ EventLog.DeleteEventSource(source);
+ }
+ session.CancelCurrentOperations();
+ }
+ }
+
+ [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))]
+ public void GetProviderNames_AssertProperties()
+ {
+ const string Prefix = "win:";
+ var standardOpcodeNames = new List<string>(Enum.GetNames(typeof(StandardEventOpcode))).Select(x => Prefix + x).ToList();
+ using (var session = new EventLogSession())
+ {
+ Assert.NotEmpty(session.GetProviderNames());
+ foreach (string providerName in session.GetProviderNames())
+ {
+ try
+ {
+ using (var providerMetadata = new ProviderMetadata(providerName))
+ {
+ foreach (var keyword in providerMetadata.Keywords)
+ {
+ Assert.NotEmpty(keyword.Name);
+ Assert.NotNull(keyword.Value);
+ }
+ foreach (var logLink in providerMetadata.LogLinks)
+ {
+ Assert.NotEmpty(logLink.LogName);
+ }
+ foreach (var opcode in providerMetadata.Opcodes)
+ {
+ if (opcode != null && standardOpcodeNames.Contains(opcode.Name))
+ {
+ Assert.Contains((((StandardEventOpcode)(opcode.Value)).ToString()), opcode.Name);
+ }
+ }
+ foreach (var eventMetadata in providerMetadata.Events)
+ {
+ EventLogLink logLink = eventMetadata.LogLink;
+ if(logLink != null)
+ {
+ if (logLink.DisplayName != null && logLink.DisplayName.Equals("System"))
+ {
+ Assert.Equal("System", logLink.LogName);
+ Assert.True(logLink.IsImported);
+ }
+ }
+ EventLevel eventLevel = eventMetadata.Level;
+ if(eventLevel != null)
+ {
+ if (eventLevel.Name != null)
+ {
+ // https://github.com/Microsoft/perfview/blob/d4b044abdfb4c8e40a344ca05383e04b5b6dc13a/src/related/EventRegister/winmeta.xml#L39
+ if (eventLevel.Name.StartsWith(Prefix) && !eventLevel.Name.Contains("ReservedLevel"))
+ {
+ Assert.True(System.Enum.IsDefined(typeof(StandardEventLevel), eventLevel.Value));
+ Assert.Contains(eventLevel.Name.Substring(4), Enum.GetNames(typeof(StandardEventLevel)));
+ }
+ }
+ }
+ EventOpcode opcode = eventMetadata.Opcode;
+ if(opcode != null)
+ {
+ if (opcode.Name != null && opcode.DisplayName != null && opcode.DisplayName.ToLower().Equals("apprun"))
+ {
+ Assert.Contains(opcode.DisplayName.ToLower(), opcode.Name.ToLower());
+ }
+ }
+ EventTask task = eventMetadata.Task;
+ if(task != null)
+ {
+ Assert.NotEqual(task, eventMetadata.Task);
+ Assert.Equal(task.DisplayName, eventMetadata.Task.DisplayName);
+ Assert.Equal(task.Name, eventMetadata.Task.Name);
+ Assert.Equal(task.Value, eventMetadata.Task.Value);
+ }
+ IEnumerable<EventKeyword> keywords = eventMetadata.Keywords;
+ if(eventMetadata.Keywords != null)
+ {
+ foreach(var keyword in eventMetadata.Keywords)
+ {
+ if (keyword.Name != null && keyword.Name.StartsWith(Prefix))
+ {
+ Assert.True(System.Enum.IsDefined(typeof(StandardEventKeywords), keyword.Value));
+ }
+ }
+ }
+ Assert.NotNull(eventMetadata.Template);
+ }
+ }
+ }
+ catch (EventLogException)
+ {
+ continue;
+ }
+ }
+ }
+ }
+ }
+}