From 93ccf3ca343dbb22a97add30494d7492e0cc36ca Mon Sep 17 00:00:00 2001 From: David Hall Date: Sat, 28 Jan 2023 18:38:16 -0700 Subject: [PATCH] Finished work on TDH methods --- PInvoke/Security/Tdh/tdh.cs | 115 +++++++++++++--------- UnitTests/PInvoke/Security/Tdh/TdhTest.cs | 153 ++++++++++++++++++++++++++++++ 2 files changed, 222 insertions(+), 46 deletions(-) create mode 100644 UnitTests/PInvoke/Security/Tdh/TdhTest.cs diff --git a/PInvoke/Security/Tdh/tdh.cs b/PInvoke/Security/Tdh/tdh.cs index bca6b7ad..48ffca16 100644 --- a/PInvoke/Security/Tdh/tdh.cs +++ b/PInvoke/Security/Tdh/tdh.cs @@ -81,9 +81,6 @@ public static partial class Tdh /// Operation code information defined in the manifest. EventOpcodeInformation, - - /// Reserved. - EventInformationMax, } /// Defines constant values that indicate if the map is a value map, bitmap, or pattern map. @@ -299,7 +296,7 @@ public static partial class Tdh // TDH_INTYPE_NONNULLTERMINATEDANSISTRING, TDH_INTYPE_UNICODECHAR, TDH_INTYPE_ANSICHAR, TDH_INTYPE_SIZET, TDH_INTYPE_HEXDUMP, // TDH_INTYPE_WBEMSID } ; [PInvokeData("tdh.h", MSDNShortId = "NE:tdh._TDH_IN_TYPE")] - public enum TDH_IN_TYPE + public enum TDH_IN_TYPE : ushort { /// TDH_INTYPE_NULL, @@ -424,7 +421,7 @@ public static partial class Tdh // TDH_OUTTYPE_UTF8, TDH_OUTTYPE_PKCS7_WITH_TYPE_INFO, TDH_OUTTYPE_CODE_POINTER, TDH_OUTTYPE_DATETIME_UTC, TDH_OUTTYPE_REDUCEDSTRING, // TDH_OUTTYPE_NOPRINT } ; [PInvokeData("tdh.h", MSDNShortId = "NE:tdh._TDH_OUT_TYPE")] - public enum TDH_OUT_TYPE + public enum TDH_OUT_TYPE : ushort { /// TDH_OUTTYPE_NULL, @@ -585,7 +582,7 @@ public static partial class Tdh // MapInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.EMI_MAP_FORMAT")] public static string? EMI_MAP_FORMAT(SafeCoTaskMemStruct? MapInfo) => - MapInfo is null || MapInfo.Value.FormatStringOffset == 0 || !MapInfo.Value.Flag.IsFlagSet(MAP_FLAGS.EVENTMAP_INFO_FLAG_MANIFEST_PATTERNMAP) ? default : MapInfo.GetOffsetString(MapInfo.Value.FormatStringOffset); + MapInfo is null || !MapInfo.Value.Flag.IsFlagSet(MAP_FLAGS.EVENTMAP_INFO_FLAG_MANIFEST_PATTERNMAP) ? default : MapInfo.GetOffsetString(MapInfo.Value.FormatStringOffset); /// Macro that retrieves the event map input. /// The metadata about the event map (EVENT_MAP_INFO structure). @@ -595,7 +592,7 @@ public static partial class Tdh // PEVENT_MAP_ENTRY Map ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.EMI_MAP_INPUT")] public static string? EMI_MAP_INPUT(SafeCoTaskMemStruct? MapInfo, in EVENT_MAP_ENTRY Map) => - MapInfo is null || Map.InputOffset == 0 || !MapInfo.Value.Flag.IsFlagSet(MAP_FLAGS.EVENTMAP_INFO_FLAG_MANIFEST_PATTERNMAP) ? default : MapInfo.GetOffsetString(Map.InputOffset); + MapInfo is null || !MapInfo.Value.Flag.IsFlagSet(MAP_FLAGS.EVENTMAP_INFO_FLAG_MANIFEST_PATTERNMAP) ? default : MapInfo.GetOffsetString(Map.InputOffset); /// Macro that retrieves the event map name. /// The metadata about the event map (EVENT_MAP_INFO structure). @@ -603,7 +600,7 @@ public static partial class Tdh // https://learn.microsoft.com/en-us/windows/win32/api/tdh/nf-tdh-emi_map_name TDH_INLINE PWSTR EMI_MAP_NAME( PEVENT_MAP_INFO MapInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.EMI_MAP_NAME")] public static string? EMI_MAP_NAME(SafeCoTaskMemStruct? MapInfo) => - MapInfo is null || MapInfo.Value.NameOffset == 0 ? default : MapInfo.GetOffsetString(MapInfo.Value.NameOffset); + MapInfo?.GetOffsetString(MapInfo.Value.NameOffset); /// Macro that retrieves the event map output. /// The metadata about the event map (EVENT_MAP_INFO structure). @@ -613,7 +610,7 @@ public static partial class Tdh // MapInfo, PEVENT_MAP_ENTRY Map ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.EMI_MAP_OUTPUT")] public static string? EMI_MAP_OUTPUT(SafeCoTaskMemStruct? MapInfo, in EVENT_MAP_ENTRY Map) => - MapInfo is null || Map.OutputOffset == 0 ? default : MapInfo.GetOffsetString(Map.OutputOffset); + MapInfo?.GetOffsetString(Map.OutputOffset); /// Macro that retrieves the Provider Event Info (PEI) name. /// @@ -625,7 +622,7 @@ public static partial class Tdh // PPROVIDER_ENUMERATION_INFO ProviderEnum, PTRACE_PROVIDER_INFO ProviderInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.PEI_PROVIDER_NAME")] public static string? PEI_PROVIDER_NAME(SafeCoTaskMemStruct? ProviderEnum, in TRACE_PROVIDER_INFO ProviderInfo) => - ProviderEnum is null || ProviderInfo.ProviderNameOffset == 0 ? null : ProviderEnum.GetOffsetString(ProviderInfo.ProviderNameOffset); + ProviderEnum?.GetOffsetString(ProviderInfo.ProviderNameOffset); /// Macro that retrieves the Provider Field Information (PFI) field message. /// The PROVIDER_FIELD_INFOARRAY structure. @@ -635,7 +632,7 @@ public static partial class Tdh // PPROVIDER_FIELD_INFOARRAY FieldInfoArray, PPROVIDER_FIELD_INFO FieldInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.PFI_FIELD_MESSAGE")] public static string? PFI_FIELD_MESSAGE(SafeCoTaskMemStruct? FieldInfoArray, in PROVIDER_FIELD_INFO FieldInfo) => - FieldInfoArray is null || FieldInfo.DescriptionOffset == 0 ? default : FieldInfoArray.GetOffsetString(FieldInfo.DescriptionOffset); + FieldInfoArray?.GetOffsetString(FieldInfo.DescriptionOffset); /// Macro that retrieves the Provider Field Information (PFI) field name. /// The PROVIDER_FIELD_INFOARRAY structure. @@ -645,26 +642,27 @@ public static partial class Tdh // PPROVIDER_FIELD_INFOARRAY FieldInfoArray, PPROVIDER_FIELD_INFO FieldInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.PFI_FIELD_NAME")] public static string? PFI_FIELD_NAME(SafeCoTaskMemStruct? FieldInfoArray, in PROVIDER_FIELD_INFO FieldInfo) => - FieldInfoArray is null || FieldInfo.NameOffset == 0 ? default : FieldInfoArray.GetOffsetString(FieldInfo.NameOffset); + FieldInfoArray?.GetOffsetString(FieldInfo.NameOffset); /// Macro that filters the Provider Field Information (PFI) field message. - /// Provider filter info (PROVIDER_FILTER_INFO structure). + /// Provider filter info array (PROVIDER_FILTER_INFO array). + /// Index of the filter information in the array. /// The Provider Field Information (PFI) field message, or NULL. // https://learn.microsoft.com/en-us/windows/win32/api/tdh/nf-tdh-pfi_filter_message TDH_INLINE PWSTR PFI_FILTER_MESSAGE( [in] // PPROVIDER_FILTER_INFO FilterInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.PFI_FILTER_MESSAGE")] - public static string? PFI_FILTER_MESSAGE(SafeCoTaskMemStruct? FilterInfo) => - FilterInfo is null || FilterInfo.Value.MessageOffset == 0 ? default : FilterInfo.GetOffsetString(FilterInfo.Value.MessageOffset); + public static string? PFI_FILTER_MESSAGE(SafeNativeArray? FilterInfoArray, int FilterInfoIndex) => + FilterInfoArray?.GetOffsetString(FilterInfoArray[FilterInfoIndex].MessageOffset); /// Macro that retrieves the Provider Field Information (PFI) property name. - /// Provider filter info (PROVIDER_FILTER_INFO structure). + /// Provider filter info array (PROVIDER_FILTER_INFO array). /// Provider property info (EVENT_PROPERTY_INFO structure). /// The Provider Field Information (PFI) property name, or NULL. // https://learn.microsoft.com/en-us/windows/win32/api/tdh/nf-tdh-pfi_property_name TDH_INLINE PWSTR PFI_PROPERTY_NAME( [in] // PPROVIDER_FILTER_INFO FilterInfo, [in] PEVENT_PROPERTY_INFO Property ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.PFI_PROPERTY_NAME")] - public static string? PFI_PROPERTY_NAME(SafeCoTaskMemStruct? FilterInfo, in EVENT_PROPERTY_INFO Property) => - FilterInfo is null || Property.NameOffset == 0 ? default : FilterInfo.GetOffsetString(Property.NameOffset); + public static string? PFI_PROPERTY_NAME(SafeNativeArray? FilterInfoArray, in EVENT_PROPERTY_INFO Property) => + FilterInfoArray?.GetOffsetString(Property.NameOffset); /// /// The TdhAggregatePayloadFilters function aggregates multiple payload filters for a single provider into a single data structure @@ -1482,7 +1480,7 @@ public static partial class Tdh // Buffer, [out] PUSHORT UserDataConsumed ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TdhFormatProperty", MinClient = PInvokeClient.Windows7)] [DllImport(Lib_Tdh, SetLastError = false, ExactSpelling = true)] - public static extern Win32Error TdhFormatProperty(in TRACE_EVENT_INFO EventInfo, in EVENT_MAP_INFO MapInfo, uint PointerSize, + public static extern Win32Error TdhFormatProperty(SafeCoTaskMemStruct EventInfo, in EVENT_MAP_INFO MapInfo, uint PointerSize, ushort PropertyInType, ushort PropertyOutType, ushort PropertyLength, ushort UserDataLength, [In] IntPtr UserData, ref uint BufferSize, [Out, Optional, MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, out ushort UserDataConsumed); @@ -1587,7 +1585,7 @@ public static partial class Tdh // Buffer, [out] PUSHORT UserDataConsumed ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TdhFormatProperty", MinClient = PInvokeClient.Windows7)] [DllImport(Lib_Tdh, SetLastError = false, ExactSpelling = true)] - public static extern Win32Error TdhFormatProperty(in TRACE_EVENT_INFO EventInfo, [In, Optional] IntPtr MapInfo, uint PointerSize, + public static extern Win32Error TdhFormatProperty(SafeCoTaskMemStruct EventInfo, [In, Optional] IntPtr MapInfo, uint PointerSize, ushort PropertyInType, ushort PropertyOutType, ushort PropertyLength, ushort UserDataLength, [In] IntPtr UserData, ref uint BufferSize, [Out, Optional, MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, out ushort UserDataConsumed); @@ -1954,7 +1952,7 @@ public static partial class Tdh // out] ULONG *BufferSize ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TdhGetManifestEventInformation", MinClient = PInvokeClient.Windows81)] public static Win32Error TdhGetManifestEventInformation([In] Guid ProviderGuid, [In] EVENT_DESCRIPTOR EventDescriptor, - out TRACE_EVENT_INFO Buffer) => Get((IntPtr p, ref uint sz) => TdhGetManifestEventInformation(ProviderGuid, EventDescriptor, p, ref sz), out Buffer); + out SafeCoTaskMemStruct? Buffer) => GetMem((IntPtr p, ref uint sz) => TdhGetManifestEventInformation(ProviderGuid, EventDescriptor, p, ref sz), out Buffer); /// Retrieves a property value from the event data. /// The event record passed to your EventRecordCallback callback. For details, see the EVENT_RECORD structure. @@ -2602,7 +2600,7 @@ public static partial class Tdh // PTRACE_EVENT_INFO EventInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TEI_ACTIVITYID_NAME")] public static string? TEI_ACTIVITYID_NAME(SafeCoTaskMemStruct? EventInfo) => - EventInfo is null || EventInfo.Value.ActivityIDNameOffset == 0 ? default : EventInfo.GetOffsetString(EventInfo.Value.ActivityIDNameOffset); + EventInfo?.GetOffsetString(EventInfo.Value.ActivityIDNameOffset); /// Macro that retrieves the Trace Event Information (TEI) channel name. /// @@ -2613,7 +2611,7 @@ public static partial class Tdh // PTRACE_EVENT_INFO EventInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TEI_CHANNEL_NAME")] public static string? TEI_CHANNEL_NAME(SafeCoTaskMemStruct? EventInfo) => - EventInfo is null || EventInfo.Value.ChannelNameOffset == 0 ? default : EventInfo.GetOffsetString(EventInfo.Value.ChannelNameOffset); + EventInfo?.GetOffsetString(EventInfo.Value.ChannelNameOffset); /// Macro that retrieves the Trace Event Information (TEI) message. /// @@ -2624,7 +2622,16 @@ public static partial class Tdh // PTRACE_EVENT_INFO EventInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TEI_EVENT_MESSAGE")] public static string? TEI_EVENT_MESSAGE(SafeCoTaskMemStruct? EventInfo) => - EventInfo is null || EventInfo.Value.EventMessageOffset == 0 ? default : EventInfo.GetOffsetString(EventInfo.Value.EventMessageOffset); + EventInfo?.GetOffsetString(EventInfo.Value.EventMessageOffset); + + /// Macro that retrieves the Trace Event Information (TEI) name. + /// + /// A TRACE_EVENT_INFO structure that contains the event information. To get this structure, call the TdhGetEventInformation function. + /// + /// The TEI name, or NULL. + [PInvokeData("tdh.h")] + public static string? TEI_EVENT_NAME(SafeCoTaskMemStruct? EventInfo) => + EventInfo?.GetOffsetString(EventInfo.Value.EventNameOffset); /// Macro that retrieves the Trace Event Information (TEI) keywords name. /// @@ -2635,7 +2642,7 @@ public static partial class Tdh // PTRACE_EVENT_INFO EventInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TEI_KEYWORDS_NAME")] public static string? TEI_KEYWORDS_NAME(SafeCoTaskMemStruct? EventInfo) => - EventInfo is null || EventInfo.Value.KeywordsNameOffset == 0 ? default : EventInfo.GetOffsetString(EventInfo.Value.KeywordsNameOffset); + EventInfo?.GetOffsetString(EventInfo.Value.KeywordsNameOffset); /// Macro that retrieves the Trace Event Information (TEI) level name. /// @@ -2646,7 +2653,7 @@ public static partial class Tdh // EventInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TEI_LEVEL_NAME")] public static string? TEI_LEVEL_NAME(SafeCoTaskMemStruct? EventInfo) => - EventInfo is null || EventInfo.Value.LevelNameOffset == 0 ? default : EventInfo.GetOffsetString(EventInfo.Value.LevelNameOffset); + EventInfo?.GetOffsetString(EventInfo.Value.LevelNameOffset); /// Macro that retrieves the Trace Event Information (TEI) map name. /// @@ -2658,7 +2665,7 @@ public static partial class Tdh // EventInfo, [in] PEVENT_PROPERTY_INFO Property ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TEI_MAP_NAME")] public static string? TEI_MAP_NAME(SafeCoTaskMemStruct? EventInfo, in EVENT_PROPERTY_INFO Property) => - EventInfo is null || Property.nonStructType.MapNameOffset == 0 ? default : EventInfo.GetOffsetString(Property.nonStructType.MapNameOffset); + EventInfo?.GetOffsetString(Property.nonStructType.MapNameOffset); /// Macro that retrieves the Trace Event Information (TEI) opcode name. /// @@ -2669,7 +2676,7 @@ public static partial class Tdh // PTRACE_EVENT_INFO EventInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TEI_OPCODE_NAME")] public static string? TEI_OPCODE_NAME(SafeCoTaskMemStruct? EventInfo) => - EventInfo is null || EventInfo.Value.OpcodeNameOffset == 0 ? default : EventInfo.GetOffsetString(EventInfo.Value.OpcodeNameOffset); + EventInfo?.GetOffsetString(EventInfo.Value.OpcodeNameOffset); /// Macro that retrieves the Trace Event Information (TEI) property name. /// @@ -2681,7 +2688,7 @@ public static partial class Tdh // PTRACE_EVENT_INFO EventInfo, PEVENT_PROPERTY_INFO Property ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TEI_PROPERTY_NAME")] public static string? TEI_PROPERTY_NAME(SafeCoTaskMemStruct? EventInfo, in EVENT_PROPERTY_INFO Property) => - EventInfo is null || Property.NameOffset == 0 ? default : EventInfo.GetOffsetString(Property.NameOffset); + EventInfo?.GetOffsetString(Property.NameOffset); /// Macro that retrieves the Trace Event Information (TEI) provider message. /// @@ -2692,7 +2699,7 @@ public static partial class Tdh // PTRACE_EVENT_INFO EventInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TEI_PROVIDER_MESSAGE")] public static string? TEI_PROVIDER_MESSAGE(SafeCoTaskMemStruct? EventInfo) => - EventInfo is null || EventInfo.Value.ProviderMessageOffset == 0 ? default : EventInfo.GetOffsetString(EventInfo.Value.ProviderMessageOffset); + EventInfo?.GetOffsetString(EventInfo.Value.ProviderMessageOffset); /// Macro that retrieves the Trace Event Information (TEI) provider name. /// @@ -2703,7 +2710,7 @@ public static partial class Tdh // PTRACE_EVENT_INFO EventInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TEI_PROVIDER_NAME")] public static string? TEI_PROVIDER_NAME(SafeCoTaskMemStruct? EventInfo) => - EventInfo is null || EventInfo.Value.ProviderNameOffset == 0 ? default : EventInfo.GetOffsetString(EventInfo.Value.ProviderNameOffset); + EventInfo?.GetOffsetString(EventInfo.Value.ProviderNameOffset); /// Macro that retrieves the Trace Event Information (TEI) related activity ID name. /// @@ -2714,7 +2721,7 @@ public static partial class Tdh // [in] PTRACE_EVENT_INFO EventInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TEI_RELATEDACTIVITYID_NAME")] public static string? TEI_RELATEDACTIVITYID_NAME(SafeCoTaskMemStruct? EventInfo) => - EventInfo is null || EventInfo.Value.RelatedActivityIDNameOffset == 0 ? default : EventInfo.GetOffsetString(EventInfo.Value.RelatedActivityIDNameOffset); + EventInfo?.GetOffsetString(EventInfo.Value.RelatedActivityIDNameOffset); /// Macro that retrieves the Trace Event Information (TEI) task name. /// @@ -2725,9 +2732,9 @@ public static partial class Tdh // EventInfo ); [PInvokeData("tdh.h", MSDNShortId = "NF:tdh.TEI_TASK_NAME")] public static string? TEI_TASK_NAME(SafeCoTaskMemStruct? EventInfo) => - EventInfo is null || EventInfo.Value.TaskNameOffset == 0 ? default : EventInfo.GetOffsetString(EventInfo.Value.TaskNameOffset); + EventInfo?.GetOffsetString(EventInfo.Value.TaskNameOffset); - private static Win32Error Get(GetD getter, out T value, uint initSz = 0) where T : struct + private static Win32Error Get(GetD getter, out T value) where T : struct { var status = GetMem(getter, out var mem); value = status.Succeeded && mem is not null ? mem.Value : default; @@ -2754,7 +2761,7 @@ public static partial class Tdh } private static string? GetOffsetString(this SafeAllocatedMemoryHandle mem, uint offset, CharSet charSet = CharSet.Unicode) => - StringHelper.GetString(mem.DangerousGetHandle().Offset(offset), charSet, mem.Size - offset); + offset == 0 ? null : StringHelper.GetString(mem.DangerousGetHandle().Offset(offset), charSet, mem.Size - offset); /// Defines a single value map entry. /// @@ -2839,12 +2846,13 @@ public static partial class Tdh // CustomSchemaOffset; } customSchemaType; }; union { USHORT count; USHORT countPropertyIndex; }; union { USHORT length; USHORT // lengthPropertyIndex; }; union { ULONG Reserved; struct { ULONG Tags : 28; }; }; } EVENT_PROPERTY_INFO; [PInvokeData("tdh.h", MSDNShortId = "06b82b31-1f0e-45d5-88ec-9b9835af10df")] - [StructLayout(LayoutKind.Sequential)] + [StructLayout(LayoutKind.Explicit)] public struct EVENT_PROPERTY_INFO { /// /// Flags that indicate if the property is contained in a structure or array. For possible values, see the PROPERTY_FLAGS enumeration. /// + [FieldOffset(0)] public PROPERTY_FLAGS Flags; /// @@ -2852,37 +2860,45 @@ public static partial class Tdh /// the beginning of the TRACE_EVENT_INFO structure. If this is a filter property, the offset is from the beginning of the /// PROVIDER_FILTER_INFO structure. /// + [FieldOffset(4)] public uint NameOffset; /// + [FieldOffset(8)] public NONSTRUCTTYPE nonStructType; /// + [FieldOffset(8)] public STRUCTTYPE structType; /// + [FieldOffset(8)] public CUSTOMSCHEMATYPE customSchemaType; /// Number of elements in the array. Note that this value is 1 for properties that are not defined as an array. + [FieldOffset(16)] public ushort count; /// /// Zero-based index to the element of the property array that contains the number of elements in the array. Use this member if the /// PropertyParamCount flag in Flags is set; otherwise, use the count member. /// - public ushort countPropertyIndex { get => count; set => count = value; } + [FieldOffset(16)] + public ushort countPropertyIndex; /// /// Size of the property, in bytes. Note that variable-sized types such as strings and binary data have a length of zero unless the /// property has length attribute to explicitly indicate its real length. Structures have a length of zero. /// + [FieldOffset(18)] public ushort length; /// /// Zero-based index to the element of the property array that contains the size value of this property. Use this member if the /// PropertyParamLength flag in Flags is set; otherwise, use the length member. /// - public ushort lengthPropertyIndex { get => length; set => length = value; } + [FieldOffset(18)] + public ushort lengthPropertyIndex; /// /// A 28-bit value associated with the field metadata. This value is valid only if the PropertyHasTags flag is set. This value can be @@ -2890,6 +2906,7 @@ public static partial class Tdh /// tag value of 1 might indicate that the field contains a username. The semantics of any values in this field are defined by the /// event provider. /// + [FieldOffset(20)] public uint Tags; /// @@ -2901,7 +2918,7 @@ public static partial class Tdh /// For descriptions of these types, see Event Tracing MOF Qualifiers. /// TdhGetPropertySize TdhGetPropertySize /// - public ushort InType; + public TDH_IN_TYPE InType; /// /// @@ -2910,7 +2927,7 @@ public static partial class Tdh /// /// For descriptions of these types, see Event Tracing MOF Qualifiers. /// - public ushort OutType; + public TDH_OUT_TYPE OutType; /// /// Offset from the beginning of the TRACE_EVENT_INFO structure to a null-terminated Unicode string that contains the name of the @@ -2942,7 +2959,7 @@ public static partial class Tdh /// For descriptions of these types, see Event Tracing MOF Qualifiers. /// TdhGetPropertySize TdhGetPropertySize /// - public ushort InType; + public TDH_IN_TYPE InType; /// /// @@ -2951,7 +2968,7 @@ public static partial class Tdh /// /// For descriptions of these types, see Event Tracing MOF Qualifiers. /// - public ushort OutType; + public TDH_OUT_TYPE OutType; /// /// Offset (in bytes) from the beginning of the TRACE_EVENT_INFO structure to the custom schema information. The custom schema @@ -3432,7 +3449,7 @@ public static partial class Tdh // { ULONG EventAttributesOffset; ULONG RelatedActivityIDNameOffset; }; ULONG PropertyCount; ULONG TopLevelPropertyCount; union { // TEMPLATE_FLAGS Flags; struct { ULONG Reserved : 4; ULONG Tags : 28; }; }; EVENT_PROPERTY_INFO EventPropertyInfoArray[ANYSIZE_ARRAY]; } TRACE_EVENT_INFO; [PInvokeData("tdh.h", MSDNShortId = "ecf57a23-0dd2-4954-82ac-e92f651c226f")] - [StructLayout(LayoutKind.Sequential)] + [StructLayout(LayoutKind.Sequential, Pack = 8)] [VanaraMarshaler(typeof(SafeAnysizeStructMarshaler), nameof(PropertyCount))] public struct TRACE_EVENT_INFO { @@ -3518,7 +3535,10 @@ public static partial class Tdh /// public uint ActivityIDNameOffset; - /// + /// + /// The offset from the beginning of this structure to a null-terminated Unicode string that contains the event's name. Supported for + /// classic ETW events only. + /// public uint EventNameOffset { get => ActivityIDNameOffset; set => ActivityIDNameOffset = value; } /// @@ -3527,7 +3547,10 @@ public static partial class Tdh /// public uint RelatedActivityIDNameOffset; - /// + /// + /// The offset from the beginning of this structure to a null-terminated Unicode string that contains a semicolon-separated list of + /// name=value attributes associated with the event. Supported for legacy ETW events only. + /// public uint EventAttributesOffset { get => RelatedActivityIDNameOffset; set => RelatedActivityIDNameOffset = value; } /// The number of elements in the EventPropertyInfoArray array. @@ -3544,7 +3567,7 @@ public static partial class Tdh /// data with an event for use by an event processing tool. For example, a tag value of 5 might indicate that the event contains /// debugging information. The semantics of any values in this field are defined by the event provider. /// - public uint Tags; + public TEMPLATE_FLAGS Tags; /// An array of EVENT_PROPERTY_INFO structures that provides information about each property of the event's user data. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] diff --git a/UnitTests/PInvoke/Security/Tdh/TdhTest.cs b/UnitTests/PInvoke/Security/Tdh/TdhTest.cs new file mode 100644 index 00000000..1e2b28ed --- /dev/null +++ b/UnitTests/PInvoke/Security/Tdh/TdhTest.cs @@ -0,0 +1,153 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Vanara.Extensions; +using Vanara.InteropServices; +using Vanara.PInvoke; +using Vanara.PInvoke.Tests; +using static Vanara.PInvoke.AdvApi32; +using static Vanara.PInvoke.Tdh; + +namespace Security.Tdh; + +[TestFixture()] +public class TdhTests +{ + [Test] + public void DisplayAllProviders() + { + Win32Error.ThrowIfFailed(TdhEnumerateProviders(out SafeCoTaskMemStruct peInfo)); + List<(Guid id, uint source, string name)> list = new(peInfo.Value.TraceProviderInfoArray.Select(i => (i.ProviderGuid, i.SchemaSource, PEI_PROVIDER_NAME(peInfo, i)))); + list.Sort((x, y) => string.Compare(x.name, y.name)); + + foreach (var (id, source, name) in list) + { + TestContext.WriteLine($"{new string('=', 30)}\n{name} ({id})\n"); + + StringBuilder tmp = new(); + foreach (EVENT_FIELD_TYPE fType in Enum.GetValues(typeof(EVENT_FIELD_TYPE))) + { + if (TdhEnumerateProviderFieldInformation(id, fType, out var pfia).Succeeded) + foreach (var f in pfia.Value.FieldInfoArray) + tmp.AppendLine($" {fType}: {f.Value}, {PFI_FIELD_NAME(pfia, f)}, {PFI_FIELD_MESSAGE(pfia, f)}"); + } + if (tmp.Length > 0) TestContext.WriteLine($" Fields:\n{tmp}"); + + tmp.Clear(); + if (TdhEnumerateManifestProviderEvents(id, out var pei).Succeeded) + foreach (var e in pei.EventDescriptorsArray) + { + tmp.AppendLine($" Id: {e.Id}, Ver: {e.Version}, Chnl: {e.Channel}, Lvl: {e.Level}, Opcode: {e.Opcode}, Task: {e.Task}, Key: 0x{e.Keyword:X}"); + Win32Error.ThrowIfFailed(TdhGetManifestEventInformation(id, e, out SafeCoTaskMemStruct tei)); + if (tei.Value.EventNameOffset > 0) tmp.AppendLine($" EventName: {TEI_EVENT_NAME(tei)}"); + if (tei.Value.KeywordsNameOffset > 0) tmp.AppendLine($" Keywords: {TEI_KEYWORDS_NAME(tei)}"); + if (tei.Value.TaskNameOffset > 0) tmp.AppendLine($" Task: {TEI_TASK_NAME(tei)}"); + if (tei.Value.ChannelNameOffset > 0) tmp.AppendLine($" Channel: {TEI_CHANNEL_NAME(tei)}"); + if (tei.Value.LevelNameOffset > 0) tmp.AppendLine($" Level: {TEI_LEVEL_NAME(tei)}"); + if (tei.Value.OpcodeNameOffset > 0) tmp.AppendLine($" Opcode: {TEI_OPCODE_NAME(tei)}"); + if (tei.Value.ProviderMessageOffset > 0) tmp.AppendLine($" ProvMsg: {TEI_PROVIDER_MESSAGE(tei)}"); + if (tei.Value.EventMessageOffset > 0) tmp.AppendLine($" EventMsg: {TEI_EVENT_MESSAGE(tei)}"); + tmp.AppendLine($" Properties ({tei.Value.PropertyCount}):"); + foreach (EVENT_PROPERTY_INFO p in tei.Value.EventPropertyInfoArray) + { + tmp.AppendLine($" Name: {TEI_PROPERTY_NAME(tei, p)} ({p.Flags}):"); + if (!p.Flags.IsFlagSet(PROPERTY_FLAGS.PropertyStruct)) + { + tmp.AppendLine($" In: {p.nonStructType.InType.ToString().Replace("TDH_INTYPE_", "")}, Out: {p.nonStructType.OutType.ToString().Replace("TDH_OUTTYPE_", "")}, Map: {TEI_MAP_NAME(tei, p)}"); + } + } + tmp.AppendLine(); + } + if (tmp.Length > 0) TestContext.WriteLine($" Events:\n{tmp}"); + + tmp.Clear(); + if (TdhEnumerateProviderFilters(id, null, out SafeNativeArray pfi).Succeeded) + for (int i = 0; i < pfi.Count; i++) + { + PROVIDER_FILTER_INFO l = pfi[i]; + tmp.AppendLine($" Id: {l.Id}, Ver: {l.Version}, Msg: {PFI_FILTER_MESSAGE(pfi, i)}"); + for (int j = 0; j < l.PropertyCount; j++) + tmp.AppendLine($" PropName: {PFI_PROPERTY_NAME(pfi, l.EventPropertyInfoArray[j])} ({l.EventPropertyInfoArray[j].Flags})"); + } + if (tmp.Length > 0) TestContext.WriteLine($" Filters:\n{tmp}"); + } + } + + [Test] + public void TdhOpenDecodingHandleTest() + { + Assert.That(TdhOpenDecodingHandle(out var h), ResultIs.Successful); + try + { + Guid id = new("e5c16d49-2464-4382-bb20-97a4b5465db9"); + uint eventid = 404; // Id: 404, Ver: 0, Chnl: 0, Lvl: 4, Opcode: 0, Task: 0, Key: 0x0 + } + finally + { + TdhCloseDecodingHandle(h); + } + } + + [Test] + public void TdhEnumerateManifestProviderEventsTest() + { + Assert.That(TdhEnumerateManifestProviderEvents(GetProviders().First().ProviderGuid, out PROVIDER_EVENT_INFO peInfo), ResultIs.Successful); + Assert.IsNotNull(peInfo); + uint cnt = peInfo.NumberOfEvents; + Assert.NotZero(cnt); + EVENT_DESCRIPTOR[] a = peInfo.EventDescriptorsArray; + a[0].WriteValues(); + a[cnt - 1].WriteValues(); + } + + [Test] + public void TdhEnumerateProviderFieldInformationTest() + { + Assert.That(TdhEnumerateProviderFieldInformation(GetProviders().First().ProviderGuid, EVENT_FIELD_TYPE.EventLevelInformation, out SafeCoTaskMemStruct peInfo), ResultIs.Successful); + Assert.IsNotNull(peInfo); + uint cnt = peInfo.Value.NumberOfElements; + Assert.NotZero(cnt); + PROVIDER_FIELD_INFO f = peInfo.Value.FieldInfoArray[cnt - 1]; + Assert.IsNotNull(PFI_FIELD_MESSAGE(peInfo, f)); + TestContext.WriteLine($"{f.Value}, {PFI_FIELD_NAME(peInfo, f)}, {PFI_FIELD_MESSAGE(peInfo, f)}"); + } + + [Test] + public void TdhEnumerateProviderFiltersTest() + { + Assert.That(TdhEnumerateProviderFilters(GetProviders().First().ProviderGuid, null, out var pfInfo), ResultIs.Successful); + } + + [Test] + public void TdhEnumerateProvidersForDecodingSourceTest() + { + Assert.That(TdhEnumerateProvidersForDecodingSource(DECODING_SOURCE.DecodingSourceXMLFile, out SafeCoTaskMemStruct peInfo), ResultIs.Successful); + Assert.IsNotNull(peInfo); + uint cnt = peInfo.Value.NumberOfProviders; + Assert.NotZero(cnt); + TRACE_PROVIDER_INFO[] a = peInfo.Value.TraceProviderInfoArray; + Assert.NotNull(PEI_PROVIDER_NAME(peInfo, a[0])); + Assert.NotNull(PEI_PROVIDER_NAME(peInfo, a[cnt - 1])); + Write(peInfo, a[cnt - 1]); + } + + [Test] + public void TdhEnumerateProvidersTest() + { + Assert.That(TdhEnumerateProviders(out SafeCoTaskMemStruct peInfo), ResultIs.Successful); + Assert.IsNotNull(peInfo); + uint cnt = peInfo.Value.NumberOfProviders; + Assert.NotZero(cnt); + TRACE_PROVIDER_INFO[] a = peInfo.Value.TraceProviderInfoArray; + Assert.NotNull(PEI_PROVIDER_NAME(peInfo, a[0])); + Assert.NotNull(PEI_PROVIDER_NAME(peInfo, a[cnt - 1])); + Write(peInfo, a[cnt - 1]); + } + + private static void Write(SafeCoTaskMemStruct peInfo, in TRACE_PROVIDER_INFO i) => + TestContext.WriteLine($"{PEI_PROVIDER_NAME(peInfo, i)}, {i.ProviderGuid}, {i.SchemaSource}"); + + private TRACE_PROVIDER_INFO[] GetProviders() { Win32Error.ThrowIfFailed(TdhEnumerateProviders(out SafeCoTaskMemStruct peInfo)); return peInfo.Value.TraceProviderInfoArray; } +} \ No newline at end of file