using System; using System.Runtime.InteropServices; using Vanara.InteropServices; namespace Vanara.PInvoke { public static partial class AdvApi32 { /// /// Providers implement this function to receive enable or disable notification requests. /// /// The PENABLECALLBACK type defines a pointer to this callback function. EnableCallback is a placeholder for the /// application-defined function name. /// /// /// /// GUID that identifies the session that enabled the provider. The value is GUID_NULL if EnableTraceEx did not specify a source identifier. /// /// /// /// Indicates if the session is enabling or disabling the provider. A value of zero indicates that the session is disabling the /// provider. A value of 1 indicates that the session is enabling the provider. Beginning with Windows 7, this value can be one of /// the following values: /// /// /// /// Value /// Meaning /// /// /// EVENT_CONTROL_CODE_DISABLE_PROVIDER 0 /// The session is disabling the provider. /// /// /// EVENT_CONTROL_CODE_ENABLE_PROVIDER 1 /// The session is enabling the provider. /// /// /// EVENT_CONTROL_CODE_CAPTURE_STATE 2 /// /// The session is requesting that the provider log its state information. The provider determines the state information that it logs. /// /// /// /// /// If you receive a value (for example, EVENT_CONTROL_CODE_CAPTURE_STATE) that you do not support, ignore the value (do not fail). /// /// /// /// /// Provider-defined value that specifies the verboseness of the events that the provider writes. The provider must write the event /// if this value is less than or equal to the level value that the event defines. /// /// This value is passed in the Level parameter of the EnableTraceEx function or the EnableLevel parameter of EnableTrace. /// /// /// Bitmask of keywords that the provider uses to determine the category of events that it writes. /// This value is passed in the MatchAnyKeyword parameter of the EnableTraceEx function or the EnableFlag parameter of EnableTrace. /// /// /// /// /// A list of filter data that one or more sessions passed to the provider. A session can specify only one filter but the list will /// contain filters from all sessions that used filter data to enable the provider. /// /// The filter data is valid only within the callback, so providers should make a local copy of the data. /// /// Context of the callback defined when the provider called EventRegister to register itself. /// This callback function does not return a value. /// /// /// To specify that you want to receive notification when a session enables or disables your provider, set the EnableCallback /// parameter when calling the EventRegister function. /// /// /// Classic providers needed to specify and implement a callback because it used the information that was passed to the callback to /// determine the types of events to log and the level of verboseness to use when logging the events. However, with manifest-based /// providers, the callback is optional and is used for informational purposes; you do not need to specify or implement the callback /// when registering the provider unless your provider supports filtering. Providers can now just write events and ETW will determine /// if the event is logged to the session. If you want to verify that the event should be written before writing the event, you can /// call either the EventEnabled or EventProviderEnabled function. /// /// /// Each time a new session enables the provider or a current session updates the provider, ETW calls the provider's callback /// function, if implemented. The level value that ETW passes to the callback is the highest level value specified amongst all the /// sessions. For example, if session A enabled the provider for warning (3) events and then session B enabled the provider for /// critical (1) events, the level value for the second callback is also 3, not 1. /// /// /// The MatchAnyKeyword value that ETW passes to the callback is a composite value of all MatchAnyKeyword values specified for all /// sessions that enabled the provider. The same is true for the MatchAllKeywords value. The SourceId and FilterData values are those /// values passed to the EnableTraceEx call. /// /// /// Your callback function must not call anything that may incur LoadLibrary (more specifically, anything that requires a loader lock). /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nc-evntprov-penablecallback PENABLECALLBACK Penablecallback; void // Penablecallback( LPCGUID SourceId, ULONG IsEnabled, UCHAR Level, ULONGLONG MatchAnyKeyword, ULONGLONG MatchAllKeyword, // PEVENT_FILTER_DESCRIPTOR FilterData, PVOID CallbackContext ) {...} [UnmanagedFunctionPointer(CallingConvention.Winapi)] [PInvokeData("evntprov.h", MSDNShortId = "f339323e-9da9-495f-aac5-f44969a018eb")] public delegate void EnableCallback(in Guid SourceId, [MarshalAs(UnmanagedType.Bool)] bool IsEnabled, byte Level, ulong MatchAnyKeyword, ulong MatchAllKeyword, IntPtr FilterData, IntPtr CallbackContext); /// A control code that specifies if you want to create, query or set the current activity identifier. [PInvokeData("evntprov.h", MSDNShortId = "1c412909-bdff-4181-9750-f3444fda4c8f")] public enum EVENT_ACTIVITY_CTRL { /// Sets the ActivityId parameter to the current identifier value from thread local storage. EVENT_ACTIVITY_CTRL_GET_ID = 1, /// /// Uses the identifier in the ActivityId parameter to set the value of the current identifier in the thread local storage. /// EVENT_ACTIVITY_CTRL_SET_ID = 2, /// Creates a new identifier and sets the ActivityId parameter to the value of the new identifier. EVENT_ACTIVITY_CTRL_CREATE_ID = 3, /// /// Performs the following: /// /// /// Copies the current identifier from thread local storage. /// /// /// Sets the current identifier in thread local storage to the new identifier specified in the ActivityId parameter. /// /// /// Sets the ActivityId parameter to the copy of the previous current identifier. /// /// /// EVENT_ACTIVITY_CTRL_GET_SET_ID = 4, /// /// Performs the following: /// /// /// Copies the current identifier from thread local storage. /// /// /// Creates a new identifier and sets the current identifier in thread local storage to the new identifier. /// /// /// Sets the ActivityId parameter to the copy of the previous current identifier. /// /// /// EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5, } /// The EVENT_INFO_CLASS enumerated type defines a type of operation to perform on a registration object. // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ne-evntprov-_event_info_class typedef enum _EVENT_INFO_CLASS { // EventProviderBinaryTrackInfo, EventProviderSetReserved1, EventProviderSetTraits, EventProviderUseDescriptorType, MaxEventInfo } EVENT_INFO_CLASS; [PInvokeData("evntprov.h", MSDNShortId = "76ac2b93-d5df-4504-b36d-1530bbb12ab4")] public enum EVENT_INFO_CLASS { /// Tracks the full path for the binary (DLL or EXE) from which the ETW registration was made. EventProviderBinaryTrackInfo, /// EventProviderSetReserved1, /// /// Sets traits for the provider. Implicitly indicates that the provider correctly initializes the EVENT_DATA_DESCRIPTOR values /// passed to EventWrite APIs, so the EVENT_DATA_DESCRIPTOR::Type field will be respected. For more information on the format of /// the traits, see Provider Traits. /// EventProviderSetTraits, /// /// Indicates whether the provider correctly initializes the EVENT_DATA_DESCRIPTOR values passed to EventWrite APIs, which in /// turn indicates whether the EVENT_DATA_DESCRIPTOR::Type field will be respected by the EventWrite APIs. /// [CorrespondingType(typeof(byte), CorrespondingAction.Set)] EventProviderUseDescriptorType, } /// Creates, queries, and sets the current activity identifier used by the EventWriteTransfer function. /// /// A control code that specifies if you want to create, query or set the current activity identifier. You can specify one of the /// following codes. /// /// /// A GUID that uniquely identifies the activity. To determine when this parameter is an input parameter, an output parameter or /// both, see the descriptions for the ControlCodes parameter. /// /// Returns ERROR_SUCCESS if successful. /// /// The EVENT_ACTIVITY_CTRL_GET_ID control code returns a GUID with all zeros (GUID_NULL) if the identifier has not been set. /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventactivityidcontrol ULONG EVNTAPI // EventActivityIdControl( ULONG ControlCode, LPGUID ActivityId ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("evntprov.h", MSDNShortId = "1c412909-bdff-4181-9750-f3444fda4c8f")] public static extern Win32Error EventActivityIdControl(EVENT_ACTIVITY_CTRL ControlCode, ref Guid ActivityId); /// Determines if the event is enabled for any session. /// /// Registration handle of the provider. The handle comes from EventRegister. /// Note A valid registration handle must be used. /// /// Describes the event. For details, see EVENT_DESCRIPTOR. /// Returns TRUE if the event is enabled for a session; otherwise, FALSE. /// /// /// Typically, providers do not call this function to determine if a session is expecting this event, they simply write the event and /// ETW determines if the event is logged to the session. /// /// /// Providers may want to call this function if they need to perform extra work to generate the event. Calling this function first to /// determine if a session is expecting this event or not, may save resources and time. /// /// /// The provider would call this function if the provider generated an EVENT_DESCRIPTOR structure for the event from the manifest. If /// the event descriptor is not available, call the EventProviderEnabled function. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventenabled BOOLEAN EVNTAPI EventEnabled( REGHANDLE // RegHandle, PCEVENT_DESCRIPTOR EventDescriptor ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("evntprov.h", MSDNShortId = "b332b6d4-6921-40bd-bebc-6646b5b9bcde")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool EventEnabled(REGHANDLE RegHandle, in EVENT_DESCRIPTOR EventDescriptor); /// Determines if the event is enabled for any session. /// Registration handle of the provider. The handle comes from EventRegister. /// /// Level of detail included in the event. Specify one of the following levels that are defined in Winmeta.h. Higher numbers imply /// that you get lower levels as well. For example, if you specify TRACE_LEVEL_WARNING, you also receive all warning, error, and /// fatal events. /// /// /// Bitmask that specifies the event category. This mask should be the same keyword mask that you defined in the manifest for the event. /// /// Returns TRUE if the event is enabled for a session; otherwise, returns FALSE. /// /// /// Typically, providers do not call this function to determine if a session is expecting this event; they simply write the event and /// ETW determines if the event is logged to the session. /// /// /// Providers may want to call this function if they need to perform extra work to generate the event. In this case, calling this /// function first (to determine if a session is expecting this event or not) may save resources and time. /// /// /// The provider would call this function if the provider did not generate an EVENT_DESCRIPTOR structure for the event from the /// manifest. If the event descriptor is available, call the EventEnabled function. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventproviderenabled BOOLEAN EVNTAPI // EventProviderEnabled( REGHANDLE RegHandle, UCHAR Level, ULONGLONG Keyword ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("evntprov.h", MSDNShortId = "84c035b1-cdc7-47b7-b887-e5b508f17266")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool EventProviderEnabled(REGHANDLE RegHandle, byte Level, ulong Keyword); /// Registers the provider. /// GUID that uniquely identifies the provider. /// /// Callback that ETW calls to notify you when a session enables or disables your provider. Can be NULL. /// /// /// Provider-defined context data to pass to the callback when the provider is enabled or disabled. Can be NULL. /// /// /// Registration handle. The handle is used by most provider function calls. Before your provider exits, you must pass this handle to /// EventUnregister to free the handle. /// /// Returns ERROR_SUCCESS if successful. /// /// Use this function to register your provider if you call EventWrite to write your events. /// /// A process can register up to 1,024 provider GUIDs; however, you should limit the number of providers that your process registers /// to one or two. This limit includes those registered using this function and the RegisterTraceGuids function. /// /// Prior to Windows Vista: There is no limit to the number of providers that a process can register. /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventregister ULONG EVNTAPI EventRegister( LPCGUID // ProviderId, PENABLECALLBACK EnableCallback, PVOID CallbackContext, PREGHANDLE RegHandle ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("evntprov.h", MSDNShortId = "6025c3a6-7d88-49dc-bbc3-655c172dde3c")] public static extern Win32Error EventRegister(in Guid ProviderId, [Optional] EnableCallback EnableCallback, [Optional] IntPtr CallbackContext, out SafeREGHANDLE RegHandle); /// Performs operations on a registration object. /// /// Type: REGHANDLE /// Registration handle returned by EventRegister. /// /// /// Type: EVENT_INFO_CLASS /// Type of operation to be performed on the registration object. /// /// /// Type: PVOID /// The input buffer. /// /// /// Type: ULONG /// Size of the input buffer. /// /// /// Type: ULONG /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is one of the following error codes. /// /// /// Return code /// Description /// /// /// ERROR_INVALID_PARAMETER /// The parameter is incorrect. This error is returned if the RegHandle parameter is not a valid registration handle. /// /// /// ERROR_NOT_SUPPORTED /// The request is not supported. /// /// /// Other /// Use FormatMessage to obtain the message string for the returned error. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventsetinformation ULONG EVNTAPI EventSetInformation( // REGHANDLE RegHandle, EVENT_INFO_CLASS InformationClass, PVOID EventInformation, ULONG InformationLength ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("evntprov.h", MSDNShortId = "e8b408ba-4bb5-4166-bf43-d18e4fe8de32")] public static extern Win32Error EventSetInformation(REGHANDLE RegHandle, EVENT_INFO_CLASS InformationClass, IntPtr EventInformation, uint InformationLength); /// Removes the provider's registration. You must call this function before your process exits. /// Registration handle returned by EventRegister. /// Returns ERROR_SUCCESS if successful. /// /// For private sessions, you must stop the trace (call the ControlTrace function with the ControlCode parameter set to /// EVENT_TRACE_CONTROL_STOP) before calling this function. /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventunregister ULONG EVNTAPI EventUnregister( REGHANDLE // RegHandle ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("evntprov.h", MSDNShortId = "fdcccf6f-2f31-4356-a4ee-3b6229c01b75")] public static extern Win32Error EventUnregister(REGHANDLE RegHandle); /// Use this function to write an event. /// Registration handle of the provider. The handle comes from EventRegister. /// Metadata that identifies the event to write. For details, see EVENT_DESCRIPTOR. /// Number of EVENT_DATA_DESCRIPTOR structures in UserData. The maximum number is 128. /// /// The event data to write. Allocate a block of memory that contains one or more EVENT_DATA_DESCRIPTOR structures. Set this /// parameter to NULL if UserDataCount is zero. The data must be in the order specified in the manifest. /// /// Returns ERROR_SUCCESS if successful or one of the following values on error. /// /// Event data written with this function requires a manifest to consume the data. /// ETW decides based on the event descriptor if the event is written to a session (for details, see EnableTraceEx). /// /// If you call the EventActivityIdControl function to specify an activity identifier for the event, EventWrite retrieves the /// identifier from thread local storage and includes it with the event. /// /// Examples /// For an example that uses EventWrite, see Writing Manifest-based Events. /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventwrite ULONG EVNTAPI EventWrite( REGHANDLE // RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, ULONG UserDataCount, PEVENT_DATA_DESCRIPTOR UserData ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("evntprov.h", MSDNShortId = "93070eb7-c167-4419-abff-e861877dad07")] public static extern Win32Error EventWrite(REGHANDLE RegHandle, in EVENT_DESCRIPTOR EventDescriptor, uint UserDataCount, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] EVENT_DATA_DESCRIPTOR[] UserData); /// Use this function to write an event. /// Registration handle of the provider. The handle comes from EventRegister. /// /// A descriptor that contains the metadata that identifies the event to write. For details, see EVENT_DESCRIPTOR. /// /// /// The instance identifiers that identify the session to which the event will not written. Use a bitwise OR to specify multiple /// identifiers. Set to zero if you do not support filters or if the event is being written to all sessions (no filters failed). For /// information on getting the identifier for a session, see the FilterData parameter of your EnableCallback callback. /// /// Reserved. Must be zero. /// /// GUID that uniquely identifies this activity. If NULL, ETW gets the identifier from the thread local storage. For details /// on getting this identifier, see EventActivityIdControl. /// /// /// Activity identifier from the previous component. Use this parameter to link your component's events to the previous component's /// events. To get the activity identifier that was set for the previous component, see the descriptions for the ControlCode /// parameter of the EventActivityIdControl function. /// /// Number of EVENT_DATA_DESCRIPTOR structures in UserData. The maximum number is 128. /// /// The event data to write. Allocate a block of memory that contains one or more EVENT_DATA_DESCRIPTOR structures. Set this /// parameter to NULL if UserDataCount is zero. The data must be in the order specified in the manifest. /// /// Returns ERROR_SUCCESS if successful or one of the following values on error. /// /// /// Event data written with this function requires a manifest. Since the manifest is embedded in the provider, the provider must be /// available for a consumer to consume the data written by the provider. /// /// /// Use the ActivityId and RelatedActivityId parameters when several components want to relate their events in an end-to-end tracing /// scenario. For example, components A, B, and C perform work on a related activity and want to link their events so that a consumer /// can consume all the events related to that activity. ETW uses thread local storage to make available to the next component the /// previous component's activity identifier. The component retrieves from the local storage the previous component's identifier and /// sets the related activity identifier to it. The consumer can then use the related activity identifier to walk the chain of the /// events from one component to the next. /// /// If each component defined their own activity identifier, the components can make the following calls to link the events: /// /// /// /// Call the EventActivityIdControl function using the EVENT_ACTIVITY_CTRL_GET_SET_ID control code. The function uses your identifier /// to set the activity identifier in the thread local storage and returns the activity identifier for the previous component, if set. /// /// /// /// /// Set the RelatedActivityId parameter of this function to the ActivityId value that the EventActivityIdControl function returned. /// Note that for the first component, the related identifier will be all zeros (GUID_NULL). /// /// /// /// Set the ActivityId of this function to NULL to use the activity identifier that you set in thread local storage. /// /// /// /// A provider can define filters that a session uses to filter events based on event data. With level and keywords, ETW determines /// whether the event is written to the session but with filters, the provider uses the filter data to determine whether it writes /// the event to the session. For example, if your provider generates process events, you could define a data filter that filters /// process events based on the process identifier. If the identifier of the process did not match the identifier that the session /// passed as filter data, you would set (perform a bitwise OR) the Filter parameter to the session's instance identifier to prevent /// the event from being written to that session. /// /// Examples /// For an example that uses EventWrite, see Writing Manifest-based Events. /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventwriteex ULONG EVNTAPI EventWriteEx( REGHANDLE // RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, ULONG64 Filter, ULONG Flags, LPCGUID ActivityId, LPCGUID RelatedActivityId, ULONG // UserDataCount, PEVENT_DATA_DESCRIPTOR UserData ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("evntprov.h", MSDNShortId = "00b907cb-45cd-48c7-bea4-4d8a39b4fa24")] public static extern Win32Error EventWriteEx(REGHANDLE RegHandle, in EVENT_DESCRIPTOR EventDescriptor, uint Filter, [Optional] uint Flags, in Guid ActivityId, in Guid RelatedActivityId, uint UserDataCount, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)] EVENT_DATA_DESCRIPTOR[] UserData); /// Use this function to write an event. /// Registration handle of the provider. The handle comes from EventRegister. /// /// A descriptor that contains the metadata that identifies the event to write. For details, see EVENT_DESCRIPTOR. /// /// /// The instance identifiers that identify the session to which the event will not written. Use a bitwise OR to specify multiple /// identifiers. Set to zero if you do not support filters or if the event is being written to all sessions (no filters failed). For /// information on getting the identifier for a session, see the FilterData parameter of your EnableCallback callback. /// /// Reserved. Must be zero. /// /// GUID that uniquely identifies this activity. If NULL, ETW gets the identifier from the thread local storage. For details /// on getting this identifier, see EventActivityIdControl. /// /// /// Activity identifier from the previous component. Use this parameter to link your component's events to the previous component's /// events. To get the activity identifier that was set for the previous component, see the descriptions for the ControlCode /// parameter of the EventActivityIdControl function. /// /// Number of EVENT_DATA_DESCRIPTOR structures in UserData. The maximum number is 128. /// /// The event data to write. Allocate a block of memory that contains one or more EVENT_DATA_DESCRIPTOR structures. Set this /// parameter to NULL if UserDataCount is zero. The data must be in the order specified in the manifest. /// /// Returns ERROR_SUCCESS if successful or one of the following values on error. /// /// /// Event data written with this function requires a manifest. Since the manifest is embedded in the provider, the provider must be /// available for a consumer to consume the data written by the provider. /// /// /// Use the ActivityId and RelatedActivityId parameters when several components want to relate their events in an end-to-end tracing /// scenario. For example, components A, B, and C perform work on a related activity and want to link their events so that a consumer /// can consume all the events related to that activity. ETW uses thread local storage to make available to the next component the /// previous component's activity identifier. The component retrieves from the local storage the previous component's identifier and /// sets the related activity identifier to it. The consumer can then use the related activity identifier to walk the chain of the /// events from one component to the next. /// /// If each component defined their own activity identifier, the components can make the following calls to link the events: /// /// /// /// Call the EventActivityIdControl function using the EVENT_ACTIVITY_CTRL_GET_SET_ID control code. The function uses your identifier /// to set the activity identifier in the thread local storage and returns the activity identifier for the previous component, if set. /// /// /// /// /// Set the RelatedActivityId parameter of this function to the ActivityId value that the EventActivityIdControl function returned. /// Note that for the first component, the related identifier will be all zeros (GUID_NULL). /// /// /// /// Set the ActivityId of this function to NULL to use the activity identifier that you set in thread local storage. /// /// /// /// A provider can define filters that a session uses to filter events based on event data. With level and keywords, ETW determines /// whether the event is written to the session but with filters, the provider uses the filter data to determine whether it writes /// the event to the session. For example, if your provider generates process events, you could define a data filter that filters /// process events based on the process identifier. If the identifier of the process did not match the identifier that the session /// passed as filter data, you would set (perform a bitwise OR) the Filter parameter to the session's instance identifier to prevent /// the event from being written to that session. /// /// Examples /// For an example that uses EventWrite, see Writing Manifest-based Events. /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventwriteex ULONG EVNTAPI EventWriteEx( REGHANDLE // RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, ULONG64 Filter, ULONG Flags, LPCGUID ActivityId, LPCGUID RelatedActivityId, ULONG // UserDataCount, PEVENT_DATA_DESCRIPTOR UserData ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("evntprov.h", MSDNShortId = "00b907cb-45cd-48c7-bea4-4d8a39b4fa24")] public static extern Win32Error EventWriteEx(REGHANDLE RegHandle, in EVENT_DESCRIPTOR EventDescriptor, uint Filter, [Optional] uint Flags, [Optional] IntPtr ActivityId, [Optional] IntPtr RelatedActivityId, uint UserDataCount, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)] EVENT_DATA_DESCRIPTOR[] UserData); /// Writes an event that contains a string as its data. /// Registration handle of the provider. The handle comes from EventRegister. /// /// Level of detail included in the event. If the provider uses a manifest to define the event, set this value to the same level /// defined in the manifest. If the event is not defined in a manifest, set this value to 0 to ensure the event is written, /// otherwise, the event is written based on the level rule defined in EnableTraceEx. /// /// /// Bitmask that specifies the event category. If the provider uses a manifest to define the event, set this value to the same /// keyword mask defined in the manifest. If the event is not defined in a manifest, set this value to 0 to ensure the event is /// written, otherwise, the event is written based on the keyword rules defined in EnableTraceEx. /// /// Null-terminated string to write as the event data. /// Returns ERROR_SUCCESS if successful or one of the following values on error. /// /// /// The provider does not need a manifest to use this function to write the event, unlike the EventWrite function which does require /// a manifest. Consumers also do not need a manifest to consume events written with this function. /// /// This function gets the acitivity identifier from the thread local storage, if set. /// ETW decides based on the level and keyword mask whether the event is written to a session (for details, see EnableTraceEx). /// This function cannot be used to write events to the Admin or Operational channels. /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventwritestring ULONG EVNTAPI EventWriteString( // REGHANDLE RegHandle, UCHAR Level, ULONGLONG Keyword, PCWSTR String ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("evntprov.h", MSDNShortId = "ecdb0e92-fcc1-4b4f-99ea-6812b6b49381")] public static extern Win32Error EventWriteString(REGHANDLE RegHandle, byte Level, ulong Keyword, [MarshalAs(UnmanagedType.LPWStr)] string String); /// Links events together when tracing events in an end-to-end scenario. /// Registration handle of the provider. The handle comes from EventRegister. /// Metadata that identifies the event to write. For details, see EVENT_DESCRIPTOR. /// /// GUID that uniquely identifies this activity. If NULL, ETW gets the identifier from the thread local storage. For details /// on getting this identifier, see EventActivityIdControl. /// /// /// Activity identifier from the previous component. Use this parameter to link your component's events to the previous component's /// events. To get the activity identifier that was set for the previous component, see the descriptions for the ControlCode /// parameter of the EventActivityIdControl function. /// /// Number of EVENT_DATA_DESCRIPTOR structures in UserData. The maximum number is 128. /// /// The event data to write. Allocate a block of memory that contains one or more EVENT_DATA_DESCRIPTOR structures. Set this /// parameter to NULL if UserDataCount is zero. The data must be in the order specified in the manifest. /// /// Returns ERROR_SUCCESS if successful or one of the following values on error. /// /// Beginning with Windows 7 and Windows Server 2008 R2, use EventWriteEx to write transfer events in an end-to-end scenario. /// /// Use this function when several components want to relate their events in an end-to-end tracing scenario. For example, components /// A, B, and C perform work on a related activity and want to link their events so that a consumer can consume all the events /// related to that activity. ETW uses thread local storage to make available to the next component the previous component's activity /// identifier. The component retrieves from the local storage the previous component's identifier and sets the related activity /// identifier to it. The consumer can then use the related activity identifier to walk the chain of the events from one component to /// the next. /// /// If each component defined their own activity identifier, the components can make the following calls to link the events: /// /// /// /// Call the EventActivityIdControl function using the EVENT_ACTIVITY_CTRL_GET_SET_ID control code. The function uses your identifier /// to set the activity identifier in the thread local storage and returns the activity identifier for the previous component, if set. /// /// /// /// /// Set the RelatedActivityId parameter of this function to the ActivityId value that the EventActivityIdControl function returned. /// Note that for the first component, the related identifier will be all zeros (GUID_NULL). /// /// /// /// Set the ActivityId of this function to NULL to use the activity identifier that you set in thread local storage. /// /// /// /// Event data written with this function requires a manifest. Since the manifest is embedded in the provider, the provider must be /// available for a consumer to consume the data written by the provider. /// /// ETW decides based on the event descriptor if the event is written to a session (for details, see EnableTraceEx). /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventwritetransfer ULONG EVNTAPI EventWriteTransfer( // REGHANDLE RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, LPCGUID ActivityId, LPCGUID RelatedActivityId, ULONG UserDataCount, // PEVENT_DATA_DESCRIPTOR UserData ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("evntprov.h", MSDNShortId = "798cf3ba-e1cc-4eaf-a1d2-2313a64aab1a")] public static extern Win32Error EventWriteTransfer(REGHANDLE RegHandle, in EVENT_DESCRIPTOR EventDescriptor, in Guid ActivityId, in Guid RelatedActivityId, uint UserDataCount, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] EVENT_DATA_DESCRIPTOR[] UserData); /// Links events together when tracing events in an end-to-end scenario. /// Registration handle of the provider. The handle comes from EventRegister. /// Metadata that identifies the event to write. For details, see EVENT_DESCRIPTOR. /// /// GUID that uniquely identifies this activity. If NULL, ETW gets the identifier from the thread local storage. For details /// on getting this identifier, see EventActivityIdControl. /// /// /// Activity identifier from the previous component. Use this parameter to link your component's events to the previous component's /// events. To get the activity identifier that was set for the previous component, see the descriptions for the ControlCode /// parameter of the EventActivityIdControl function. /// /// Number of EVENT_DATA_DESCRIPTOR structures in UserData. The maximum number is 128. /// /// The event data to write. Allocate a block of memory that contains one or more EVENT_DATA_DESCRIPTOR structures. Set this /// parameter to NULL if UserDataCount is zero. The data must be in the order specified in the manifest. /// /// Returns ERROR_SUCCESS if successful or one of the following values on error. /// /// Beginning with Windows 7 and Windows Server 2008 R2, use EventWriteEx to write transfer events in an end-to-end scenario. /// /// Use this function when several components want to relate their events in an end-to-end tracing scenario. For example, components /// A, B, and C perform work on a related activity and want to link their events so that a consumer can consume all the events /// related to that activity. ETW uses thread local storage to make available to the next component the previous component's activity /// identifier. The component retrieves from the local storage the previous component's identifier and sets the related activity /// identifier to it. The consumer can then use the related activity identifier to walk the chain of the events from one component to /// the next. /// /// If each component defined their own activity identifier, the components can make the following calls to link the events: /// /// /// /// Call the EventActivityIdControl function using the EVENT_ACTIVITY_CTRL_GET_SET_ID control code. The function uses your identifier /// to set the activity identifier in the thread local storage and returns the activity identifier for the previous component, if set. /// /// /// /// /// Set the RelatedActivityId parameter of this function to the ActivityId value that the EventActivityIdControl function returned. /// Note that for the first component, the related identifier will be all zeros (GUID_NULL). /// /// /// /// Set the ActivityId of this function to NULL to use the activity identifier that you set in thread local storage. /// /// /// /// Event data written with this function requires a manifest. Since the manifest is embedded in the provider, the provider must be /// available for a consumer to consume the data written by the provider. /// /// ETW decides based on the event descriptor if the event is written to a session (for details, see EnableTraceEx). /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventwritetransfer ULONG EVNTAPI EventWriteTransfer( // REGHANDLE RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, LPCGUID ActivityId, LPCGUID RelatedActivityId, ULONG UserDataCount, // PEVENT_DATA_DESCRIPTOR UserData ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("evntprov.h", MSDNShortId = "798cf3ba-e1cc-4eaf-a1d2-2313a64aab1a")] public static extern Win32Error EventWriteTransfer(REGHANDLE RegHandle, in EVENT_DESCRIPTOR EventDescriptor, [Optional] IntPtr ActivityId, [Optional] IntPtr RelatedActivityId, uint UserDataCount, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] EVENT_DATA_DESCRIPTOR[] UserData); /// /// The EVENT_DATA_DESCRIPTOR structure is used with the user mode EventWrite and the kernel mode EtwWrite functions to send events. /// The EVENT_DATA_DESCRIPTOR structure describes the event payload. /// /// /// The most convenient method of populating the EVENT_DATA_DESCRIPTOR structure is to use the EventDataDescCreate macro. This /// macro is declared in Evntprov.h and its use is documented in the Microsoft Windows SDK documentation. The following example uses /// the EventDataDescCreate macro to populate an array of three EVENT_DATA_DESCRIPTOR structures. This array is then passed to /// the EtwWrite function. /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ns-evntprov-_event_data_descriptor typedef struct // _EVENT_DATA_DESCRIPTOR { ULONGLONG Ptr; ULONG Size; union { ULONG Reserved; struct { UCHAR Type; UCHAR Reserved1; USHORT // Reserved2; } DUMMYSTRUCTNAME; } DUMMYUNIONNAME; } EVENT_DATA_DESCRIPTOR, *PEVENT_DATA_DESCRIPTOR; [PInvokeData("evntprov.h", MSDNShortId = "eb2b7ab6-52da-4d16-b315-6adab3131a05")] [StructLayout(LayoutKind.Sequential)] public struct EVENT_DATA_DESCRIPTOR { /// A pointer to the event descriptor data. public ulong Ptr; /// The size of the payload field, in bytes. public uint Size; /// public byte Type; /// public byte Reserved1; /// public ushort Reserved2; /// Initializes a new instance of the struct. /// /// A pointer to the event data used to set the Ptr member of EVENT_DATA_DESCRIPTOR. /// If the event data's type is a NULL-terminated string, the DataPtr parameter must not be NULL. /// /// If the event data's type is a string whose size is described by some other field in the event, the DataPtr parameter may be NULL. /// /// /// The size of the event data. The value is used to set the Size member of EVENT_DATA_DESCRIPTOR. public EVENT_DATA_DESCRIPTOR(IntPtr DataPtr, uint DataSize) { Ptr = unchecked((ulong)DataPtr.ToInt64()); Size = DataSize; Reserved2 = Reserved1 = Type = 0; } } /// The EVENT_DESCRIPTOR structure identifies the description information that is available for each event. /// /// /// The Id member is the event identifier. The structure members Id and Version can be used together to identify /// all events for a specific provider. When the Id and Version are used in conjunction with the manifest, you can /// precisely identify the structure and metadata of the event. /// /// /// The pointer to the EVENT_DESCRIPTOR is passed to the EtwEventEnabled, EtwWrite, and EtwWriteTransfer functions. The most /// convenient method of populating the EVENT_DESCRIPTOR structure is to use the EventDescCreate macro. This macro is declared /// in Evntprov.h and its use is documented in the Microsoft Windows SDK. /// /// /// The following is a list of the convenience macros that you can use to create the event descriptors and to extract and set fields /// in the structure. For information on these macros, see Event Tracing Macros. /// /// Macros to create event descriptors: /// /// /// EventDescCreate /// /// /// EventDescZero /// /// /// Macros to extract information from an event descriptor: /// /// /// EventDescGetId /// /// /// EventDescGetVersion /// /// /// EventDescGetTask /// /// /// EventDescGetOpcode /// /// /// EventDescGetChannel /// /// /// EventDescGetLevel /// /// /// EventDescGetKeyword /// /// /// Macros to set fields in an event descriptor: /// /// /// EventDescSetId /// /// /// EventDescSetVersion /// /// /// EventDescSetTask /// /// /// EventDescSetOpcode /// /// /// EventDescSetLevel /// /// /// EventDescSetChannel /// /// /// EventDescSetKeyword /// /// /// EventDescOrKeyword /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ns-evntprov-_event_descriptor typedef struct _EVENT_DESCRIPTOR { // USHORT Id; UCHAR Version; UCHAR Channel; UCHAR Level; UCHAR Opcode; USHORT Task; ULONGLONG Keyword; } EVENT_DESCRIPTOR, *PEVENT_DESCRIPTOR; [PInvokeData("evntprov.h", MSDNShortId = "cfe84b3d-fed2-4624-9899-8451e5b39de0")] [StructLayout(LayoutKind.Sequential)] public struct EVENT_DESCRIPTOR { /// The event identifier. Each event is associated with a 16-bit numeric value. public ushort Id; /// /// A numeric value that represents a version of the event. Component updates can change this value for a specific event. /// public byte Version; /// /// The channel that the event is intended for. Note that the channel name is not stored here. The value of the channel is /// assigned by the message compiler. /// public byte Channel; /// /// The level of the event. The level indicates the severity or verbosity of the event. The level is used with earlier versions /// of the ETW and WPP event fields. The levels have names with values, such as Error, Warning, Information, and so on. /// public byte Level; /// /// The activity that the driver was performing at the time of the event. The Opcode member is defined by the provider or /// is one of the system-defined values defined in the Winmeta.xml file that is provided with the Windows Driver Kit (WDK) in the /// %Winddk%<i>version\inc\api directory. /// public byte Opcode; /// /// The Task corresponds to the logical activity that the driver was performing when it raised the event. The /// Opcode member refers to a specific action within that logical activity. /// public ushort Task; /// /// The categories or tags assigned to the event. Each keyword categorizes the event in some way. For example, a category could /// be Network, Storage, or Not Found. An event can belong to more then one category, in which case multiple /// keywords are specified for the event. The keyword values are bitmasks and can be combined. /// public ulong Keyword; /// Initializes a new instance of the struct. /// Event identifier. The value is used to set the Id member of EVENT_DESCRIPTOR. /// Version of the event. The value is used to set the Version member of EVENT_DESCRIPTOR. /// /// The category of events to which this event belongs. The value is used to set the Channel member of EVENT_DESCRIPTOR. /// /// Specifies the severity of the event. The value is used to set the Level member of EVENT_DESCRIPTOR. /// /// Identifies a logical component of the application whose events you want to enable. The value is used to set the Task /// member of EVENT_DESCRIPTOR. /// /// /// Operation being performed at the time the event was written. The value is used to set the Opcode member of EVENT_DESCRIPTOR. /// /// /// Bitmask that further defines the category of events to which the event belongs. The value is used to set the Keyword /// member of EVENT_DESCRIPTOR. /// public EVENT_DESCRIPTOR(ushort Id, byte Version, byte Channel, byte Level, ushort Task, byte Opcode, ulong Keyword) { this.Channel = Channel; this.Id = Id; this.Keyword = Keyword; this.Level = Level; this.Opcode = Opcode; this.Task = Task; this.Version = Version; } } /// /// The EVENT_FILTER_DESCRIPTOR structure supplements the event provider, level, and keyword data that determines which events are /// reported and traced. The EVENT_FILTER_DESCRIPTOR structure gives the event provider greater control over the selection of events /// for reporting and tracing. /// /// /// You pass a pointer to the EVENT_FILTER_DESCRIPTOR structure when you create the optional driver-supplied /// EtwEnableCallbackfunction. When you register the driver with ETW, the EtwRegister function takes a pointer to the /// EtwEnableCallback function as a parameter. /// // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ns-evntprov-_event_filter_descriptor typedef struct // _EVENT_FILTER_DESCRIPTOR { ULONGLONG Ptr; ULONG Size; ULONG Type; } EVENT_FILTER_DESCRIPTOR, *PEVENT_FILTER_DESCRIPTOR; [PInvokeData("evntprov.h", MSDNShortId = "3870a471-a3cf-424f-bba3-bc06de1ebecc")] [StructLayout(LayoutKind.Sequential)] public struct EVENT_FILTER_DESCRIPTOR { /// A pointer to the filter data. public ulong Ptr; /// The size of the filter data, in bytes. The maximum size is 1024 bytes. public uint Size; /// /// The type of filter data. The type is application-defined. An event controller that knows about the provider and knows details /// about the provider's events can use the Type field to send the provider an arbitrary set of data for use as /// enhancements to the filtering of events. /// public uint Type; } /// Provides a handle to a provider registration handle. [StructLayout(LayoutKind.Sequential)] public struct REGHANDLE : IHandle { private IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public REGHANDLE(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static REGHANDLE NULL => new REGHANDLE(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(REGHANDLE h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator REGHANDLE(IntPtr h) => new REGHANDLE(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(REGHANDLE h1, REGHANDLE h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(REGHANDLE h1, REGHANDLE h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is REGHANDLE h ? handle == h.handle : false; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// Provides a for that is disposed using . public class SafeREGHANDLE : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeREGHANDLE(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeREGHANDLE() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator REGHANDLE(SafeREGHANDLE h) => h.handle; /// protected override bool InternalReleaseHandle() => EventUnregister(handle).Succeeded; } } }