/
githubmirror
/
PowerShell
Обзор
Документация
Войти
/
githubmirror
/
PowerShell
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/Microsoft.PowerShell.CoreCLR.Eventing/DotNetCode/Eventing/Reader/NativeWrapper.cs
1 473 строки
68 KB
xtqqczze
Enable IDE0049 `PreferBuiltInOrFrameworkType` (#14491)
28 июл 2021, 22:39
Не верифицирован
28 июл 2021, 22:39
0f2f23f
Код
Авторство
О чём код?
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. /*============================================================ ** ** ** Purpose: ** 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. ** ============================================================*/ using System.Collections.Generic; using System.ComponentModel; using System.Runtime.InteropServices; using System.Security.Principal; using System.Text; namespace System.Diagnostics.Eventing.Reader { internal static 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() { } } private static void ThrowEventLogException(int errorCode) { string message = new Win32Exception(errorCode).Message; switch (errorCode) { case 2: case 3: case 15007: case 15027: case 15028: case 15002: throw new EventLogNotFoundException(message); case 13: case 15005: throw new EventLogInvalidDataException(message); case 1818: // RPC_S_CALL_CANCELED is converted to ERROR_CANCELLED case 1223: throw new OperationCanceledException(); case 15037: throw new EventLogProviderDisabledException(message); case 5: throw new UnauthorizedAccessException(); case 15011: case 15012: throw new EventLogReadingException(message); default: throw new EventLogException(message); } } [System.Security.SecurityCritical] 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) ThrowEventLogException(win32Error); return handle; } [System.Security.SecurityCritical] 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) ThrowEventLogException(win32Error); } [System.Security.SecurityCritical] 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) ThrowEventLogException(win32Error); return win32Error == 0; } [System.Security.SecuritySafeCritical] public static void EvtCancel(EventLogHandle handle) { if (!UnsafeNativeMethods.EvtCancel(handle)) { int win32Error = Marshal.GetLastWin32Error(); ThrowEventLogException(win32Error); } } [System.Security.SecurityCritical] public static void EvtClose(IntPtr handle) { // // purposely don't check and throw - this is // always called in cleanup / finalize / etc.. // UnsafeNativeMethods.EvtClose(handle); } [System.Security.SecurityCritical] 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) ThrowEventLogException(win32Error); return handle; } [System.Security.SecurityCritical] public static int EvtGetObjectArraySize(EventLogHandle objectArray) { int arraySize; bool status = UnsafeNativeMethods.EvtGetObjectArraySize(objectArray, out arraySize); int win32Error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(win32Error); return arraySize; } [System.Security.SecurityCritical] public static EventLogHandle EvtOpenEventMetadataEnum(EventLogHandle ProviderMetadata, int flags) { EventLogHandle emEnumHandle = UnsafeNativeMethods.EvtOpenEventMetadataEnum(ProviderMetadata, flags); int win32Error = Marshal.GetLastWin32Error(); if (emEnumHandle.IsInvalid) ThrowEventLogException(win32Error); return emEnumHandle; } // returns null if EOF [System.Security.SecurityCritical] 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) ThrowEventLogException(win32Error); return null; } return emHandle; } [System.Security.SecurityCritical] public static EventLogHandle EvtOpenChannelEnum(EventLogHandle session, int flags) { EventLogHandle channelEnum = UnsafeNativeMethods.EvtOpenChannelEnum(session, flags); int win32Error = Marshal.GetLastWin32Error(); if (channelEnum.IsInvalid) ThrowEventLogException(win32Error); return channelEnum; } [System.Security.SecurityCritical] public static EventLogHandle EvtOpenProviderEnum(EventLogHandle session, int flags) { EventLogHandle pubEnum = UnsafeNativeMethods.EvtOpenPublisherEnum(session, flags); int win32Error = Marshal.GetLastWin32Error(); if (pubEnum.IsInvalid) ThrowEventLogException(win32Error); return pubEnum; } [System.Security.SecurityCritical] public static EventLogHandle EvtOpenChannelConfig(EventLogHandle session, string channelPath, int flags) { EventLogHandle handle = UnsafeNativeMethods.EvtOpenChannelConfig(session, channelPath, flags); int win32Error = Marshal.GetLastWin32Error(); if (handle.IsInvalid) ThrowEventLogException(win32Error); return handle; } [System.Security.SecuritySafeCritical] public static void EvtSaveChannelConfig(EventLogHandle channelConfig, int flags) { bool status = UnsafeNativeMethods.EvtSaveChannelConfig(channelConfig, flags); int win32Error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(win32Error); } [System.Security.SecurityCritical] public static EventLogHandle EvtOpenLog(EventLogHandle session, string path, PathType flags) { EventLogHandle logHandle = UnsafeNativeMethods.EvtOpenLog(session, path, flags); int win32Error = Marshal.GetLastWin32Error(); if (logHandle.IsInvalid) ThrowEventLogException(win32Error); return logHandle; } [System.Security.SecuritySafeCritical] 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) ThrowEventLogException(win32Error); } [System.Security.SecuritySafeCritical] 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) ThrowEventLogException(win32Error); } [System.Security.SecuritySafeCritical] 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) ThrowEventLogException(win32Error); } [System.Security.SecurityCritical] public static EventLogHandle EvtCreateRenderContext( int valuePathsCount, string[] valuePaths, UnsafeNativeMethods.EvtRenderContextFlags flags) { EventLogHandle renderContextHandleValues = UnsafeNativeMethods.EvtCreateRenderContext(valuePathsCount, valuePaths, flags); int win32Error = Marshal.GetLastWin32Error(); if (renderContextHandleValues.IsInvalid) ThrowEventLogException(win32Error); return renderContextHandleValues; } [System.Security.SecurityCritical] 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) { ThrowEventLogException(win32Error); } } } [System.Security.SecurityCritical] 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) ThrowEventLogException(win32Error); return handle; } [System.Security.SecurityCritical] public static EventLogHandle EvtCreateBookmark(string bookmarkXml) { EventLogHandle handle = UnsafeNativeMethods.EvtCreateBookmark(bookmarkXml); int win32Error = Marshal.GetLastWin32Error(); if (handle.IsInvalid) ThrowEventLogException(win32Error); return handle; } [System.Security.SecurityCritical] public static void EvtUpdateBookmark(EventLogHandle bookmark, EventLogHandle eventHandle) { bool status = UnsafeNativeMethods.EvtUpdateBookmark(bookmark, eventHandle); int win32Error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(win32Error); } [System.Security.SecuritySafeCritical] 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) ThrowEventLogException(error); } buffer = Marshal.AllocHGlobal((int)bufferNeeded); status = UnsafeNativeMethods.EvtGetEventInfo(handle, enumType, bufferNeeded, buffer, out bufferNeeded); error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(error); UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer); return ConvertToObject(varVal); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } [System.Security.SecurityCritical] 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) ThrowEventLogException(error); } buffer = Marshal.AllocHGlobal((int)bufferNeeded); status = UnsafeNativeMethods.EvtGetQueryInfo(handle, enumType, bufferNeeded, buffer, ref bufferNeeded); error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(error); UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer); return ConvertToObject(varVal); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } [System.Security.SecuritySafeCritical] 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) ThrowEventLogException(error); } buffer = Marshal.AllocHGlobal((int)bufferNeeded); status = UnsafeNativeMethods.EvtGetPublisherMetadataProperty(pmHandle, thePropertyId, 0, bufferNeeded, buffer, out bufferNeeded); error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(error); UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer); return ConvertToObject(varVal); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } [System.Security.SecurityCritical] 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) ThrowEventLogException(error); } buffer = Marshal.AllocHGlobal((int)bufferNeeded); status = UnsafeNativeMethods.EvtGetPublisherMetadataProperty(pmHandle, thePropertyId, 0, bufferNeeded, buffer, out bufferNeeded); error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(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. [System.Security.SecurityCritical] public static string EvtFormatMessage(EventLogHandle handle, uint msgId) { int bufferNeeded; StringBuilder sb = new(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) ThrowEventLogException(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; } ThrowEventLogException(error); } return sb.ToString(); } [System.Security.SecurityCritical] 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) ThrowEventLogException(error); } buffer = Marshal.AllocHGlobal((int)bufferNeeded); status = UnsafeNativeMethods.EvtGetObjectArrayProperty(objArrayHandle, thePropertyId, index, 0, bufferNeeded, buffer, out bufferNeeded); error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(error); UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer); return ConvertToObject(varVal); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } [System.Security.SecurityCritical] 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) ThrowEventLogException(win32Error); } buffer = Marshal.AllocHGlobal((int)bufferNeeded); status = UnsafeNativeMethods.EvtGetEventMetadataProperty(handle, enumType, 0, bufferNeeded, buffer, out bufferNeeded); win32Error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(win32Error); UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer); return ConvertToObject(varVal); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } [System.Security.SecuritySafeCritical] 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) ThrowEventLogException(win32Error); } buffer = Marshal.AllocHGlobal((int)bufferNeeded); status = UnsafeNativeMethods.EvtGetChannelConfigProperty(handle, enumType, 0, bufferNeeded, buffer, out bufferNeeded); win32Error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(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); } } [System.Security.SecuritySafeCritical] public static void EvtSetChannelConfigProperty(EventLogHandle handle, UnsafeNativeMethods.EvtChannelConfigPropertyId enumType, object val) { UnsafeNativeMethods.EvtVariant varVal = new(); CoTaskMemSafeHandle taskMem = new(); using (taskMem) { if (val != null) { switch (enumType) { case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigEnabled: { varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBoolean; if ((bool)val) 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) varVal.Bool = 1; else varVal.Bool = 0; } break; case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigAutoBackup: { varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBoolean; if ((bool)val) 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) ThrowEventLogException(win32Error); } } [System.Security.SecurityCritical] public static string EvtNextChannelPath(EventLogHandle handle, ref bool finish) { StringBuilder sb = new(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) ThrowEventLogException(win32Error); } sb.EnsureCapacity(channelNameNeeded); status = UnsafeNativeMethods.EvtNextChannelPath(handle, channelNameNeeded, sb, out channelNameNeeded); win32Error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(win32Error); return sb.ToString(); } [System.Security.SecurityCritical] public static string EvtNextPublisherId(EventLogHandle handle, ref bool finish) { StringBuilder sb = new(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) ThrowEventLogException(win32Error); } sb.EnsureCapacity(ProviderIdNeeded); status = UnsafeNativeMethods.EvtNextPublisherId(handle, ProviderIdNeeded, sb, out ProviderIdNeeded); win32Error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(win32Error); return sb.ToString(); } [System.Security.SecurityCritical] 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) ThrowEventLogException(win32Error); } buffer = Marshal.AllocHGlobal((int)bufferNeeded); status = UnsafeNativeMethods.EvtGetLogInfo(handle, enumType, bufferNeeded, buffer, out bufferNeeded); win32Error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(win32Error); UnsafeNativeMethods.EvtVariant varVal = Marshal.PtrToStructure<UnsafeNativeMethods.EvtVariant>(buffer); return ConvertToObject(varVal); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } [System.Security.SecuritySafeCritical] 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) ThrowEventLogException(error); } buffer = Marshal.AllocHGlobal((int)bufferNeeded); status = UnsafeNativeMethods.EvtRender(contextHandle, eventHandle, flag, bufferNeeded, buffer, out bufferNeeded, out propCount); int win32Error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(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(((long)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) [System.Security.SecuritySafeCritical] public static IList<object> EvtRenderBufferWithContextUserOrValues(EventLogHandle contextHandle, EventLogHandle eventHandle) { IntPtr buffer = IntPtr.Zero; IntPtr pointer = IntPtr.Zero; int bufferNeeded; int propCount; const 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) ThrowEventLogException(error); } buffer = Marshal.AllocHGlobal((int)bufferNeeded); status = UnsafeNativeMethods.EvtRender(contextHandle, eventHandle, flag, bufferNeeded, buffer, out bufferNeeded, out propCount); int win32Error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(win32Error); List<object> valuesList = new(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(((long)pointer + Marshal.SizeOf(varVal))); } } return valuesList; } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } [System.Security.SecuritySafeCritical] public static string EvtFormatMessageRenderName(EventLogHandle pmHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags flag) { int bufferNeeded; StringBuilder sb = new(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) ThrowEventLogException(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; } ThrowEventLogException(error); } return sb.ToString(); } // The EvtFormatMessage used for the obtaining of the Keywords names. [System.Security.SecuritySafeCritical] public static IEnumerable<string> EvtFormatMessageRenderKeywords(EventLogHandle pmHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags flag) { IntPtr buffer = IntPtr.Zero; int bufferNeeded; try { List<string> keywordsList = new(); 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) ThrowEventLogException(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; } ThrowEventLogException(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((long)pointer + (s.Length * 2) + 2); } return keywordsList.AsReadOnly(); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } [System.Security.SecurityCritical] public static string EvtRenderBookmark(EventLogHandle eventHandle) { IntPtr buffer = IntPtr.Zero; int bufferNeeded; int propCount; const 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) ThrowEventLogException(error); } buffer = Marshal.AllocHGlobal((int)bufferNeeded); status = UnsafeNativeMethods.EvtRender(EventLogHandle.Zero, eventHandle, flag, bufferNeeded, buffer, out bufferNeeded, out propCount); error = Marshal.GetLastWin32Error(); if (!status) ThrowEventLogException(error); return Marshal.PtrToStringUni(buffer); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } // Get the formatted description, using the msgId for FormatDescription(string []) [System.Security.SecuritySafeCritical] 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(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) ThrowEventLogException(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; } ThrowEventLogException(error); } return sb.ToString(); } [System.Security.SecurityCritical] 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 Array.Empty<byte>(); 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 Array.Empty<short>(); short[] arInt16 = new short[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 Array.Empty<int>(); int[] arInt32 = new int[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 Array.Empty<long>(); long[] arInt64 = new long[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 Array.Empty<float>(); float[] arSingle = new float[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 Array.Empty<double>(); 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<ushort>(val, sizeof(ushort)); 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<ulong>(val, sizeof(ulong)); 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<uint>(val, sizeof(uint)); 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(); } } [System.Security.SecurityCritical] 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); } [System.Security.SecurityCritical] public static string ConvertToString(UnsafeNativeMethods.EvtVariant val) { if (val.StringVal == IntPtr.Zero) return string.Empty; else return Marshal.PtrToStringUni(val.StringVal); } [System.Security.SecurityCritical] public static string ConvertToAnsiString(UnsafeNativeMethods.EvtVariant val) { if (val.AnsiString == IntPtr.Zero) return string.Empty; else return Marshal.PtrToStringAnsi(val.AnsiString); } [System.Security.SecurityCritical] public static EventLogHandle ConvertToSafeHandle(UnsafeNativeMethods.EvtVariant val) { if (val.Handle == IntPtr.Zero) return EventLogHandle.Zero; else return new EventLogHandle(val.Handle, true); } [System.Security.SecurityCritical] 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((long)ptr + size); } return array; } } [System.Security.SecurityCritical] 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 Array.Empty<bool>(); } else { bool[] array = new bool[val.Count]; for (int i = 0; i < val.Count; i++) { bool value = Marshal.ReadInt32(ptr) != 0; array[i] = value; ptr = new IntPtr((long)ptr + 4); } return array; } } [System.Security.SecurityCritical] public static Array ConvertToFileTimeArray(UnsafeNativeMethods.EvtVariant val) { IntPtr ptr = val.Reference; if (ptr == IntPtr.Zero) { return Array.Empty<DateTime>(); } 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((long)ptr + 8 * sizeof(byte)); // FILETIME values are 8 bytes } return array; } } [System.Security.SecurityCritical] public static Array ConvertToSysTimeArray(UnsafeNativeMethods.EvtVariant val) { IntPtr ptr = val.Reference; if (ptr == IntPtr.Zero) { return Array.Empty<DateTime>(); } 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((long)ptr + 16 * sizeof(byte)); // SystemTime values are 16 bytes } return array; } } [System.Security.SecurityCritical] public static string[] ConvertToStringArray(UnsafeNativeMethods.EvtVariant val, bool ansi) { if (val.Reference == IntPtr.Zero) { return Array.Empty<string>(); } 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; } } } }