diff --git a/include/WinStd/ETW.h b/include/WinStd/ETW.h index 7c784e65..9ab9db29 100644 --- a/include/WinStd/ETW.h +++ b/include/WinStd/ETW.h @@ -37,6 +37,7 @@ template inline ULONG TdhGetProperty(_In_ PEVENT_RECORD pE namespace winstd { class WINSTD_API event_data; + class WINSTD_API event_rec; class WINSTD_API event_provider; class WINSTD_API event_session; class WINSTD_API event_trace; @@ -249,6 +250,148 @@ namespace winstd }; + /// + /// EVENT_RECORD wrapper + /// + class WINSTD_API event_rec : public EVENT_RECORD + { + public: + /// + /// Constructs a blank event record. + /// + inline event_rec() + { + memset((EVENT_RECORD*)this, 0, sizeof(EVENT_RECORD)); + } + + + /// + /// Copies an existing event record. + /// + /// \param[in] other Event record to copy from + /// + inline event_rec(_In_ const event_rec &other) : EVENT_RECORD(other) + { + set_extended_data_internal(other.ExtendedDataCount, other.ExtendedData); + set_user_data_internal(other.UserDataLength, other.UserData); + } + + + /// + /// Copies an existing event record. + /// + /// \param[in] other Event record to copy from + /// + inline event_rec(_In_ const EVENT_RECORD &other) : EVENT_RECORD(other) + { + set_extended_data_internal(other.ExtendedDataCount, other.ExtendedData); + set_user_data_internal(other.UserDataLength, other.UserData); + } + + + /// + /// Moves the event record. + /// + /// \param[in] other Event record to move + /// + inline event_rec(_Inout_ event_rec&& other) : EVENT_RECORD(other) + { + memset((EVENT_RECORD*)&other, 0, sizeof(EVENT_RECORD)); + } + + + /// + /// Destroys event record data and frees the allocated memory. + /// + virtual ~event_rec(); + + + /// + /// Copies an existing event record. + /// + /// \param[in] other Event record to copy from + /// + inline event_rec& operator=(_In_ const event_rec &other) + { + if (this != std::addressof(other)) { + (EVENT_RECORD&)*this = other; + set_extended_data_internal(other.ExtendedDataCount, other.ExtendedData); + set_user_data_internal(other.UserDataLength, other.UserData); + } + + return *this; + } + + + /// + /// Copies an existing event record. + /// + /// \param[in] other Event record to copy from + /// + inline event_rec& operator=(_In_ const EVENT_RECORD &other) + { + if (this != std::addressof(other)) { + (EVENT_RECORD&)*this = other; + set_extended_data_internal(other.ExtendedDataCount, other.ExtendedData); + set_user_data_internal(other.UserDataLength, other.UserData); + } + + return *this; + } + + + /// + /// Moves the event record. + /// + /// \param[in] other Event record to move + /// + inline event_rec& operator=(_Inout_ event_rec&& other) + { + if (this != std::addressof(other)) { + (EVENT_RECORD&)*this = other; + memset((EVENT_RECORD*)&other, 0, sizeof(EVENT_RECORD)); + } + + return *this; + } + + + /// + /// Sets event record extended data. + /// + /// \param[in] count \p data size (in number of elements) + /// \param[in] data Record extended data + /// + void set_extended_data(_In_ USHORT count, _In_count_(count) const EVENT_HEADER_EXTENDED_DATA_ITEM *data); + + + /// + /// Sets event record user data. + /// + /// \param[in] size \p data size (in bytes) + /// \param[in] data Record user data + /// + void set_user_data(_In_ USHORT size, _In_bytecount_(size) LPCVOID data); + + protected: + /// + /// Sets event record extended data. + /// + /// \param[in] count \p data size (in number of elements) + /// \param[in] data Record extended data + /// + void set_extended_data_internal(_In_ USHORT count, _In_count_(count) const EVENT_HEADER_EXTENDED_DATA_ITEM *data); + + /// + /// Sets event record user data. + /// + /// \param[in] size \p data size (in bytes) + /// \param[in] data Record user data + /// + void set_user_data_internal(_In_ USHORT size, _In_bytecount_(size) LPCVOID data); + }; + + /// /// ETW event provider /// diff --git a/src/ETW.cpp b/src/ETW.cpp index 379608a8..7d4ca25a 100644 --- a/src/ETW.cpp +++ b/src/ETW.cpp @@ -30,6 +30,88 @@ const winstd::event_data winstd::event_data::blank; +////////////////////////////////////////////////////////////////////// +// winstd::event_rec +////////////////////////////////////////////////////////////////////// + +winstd::event_rec::~event_rec() +{ + if (ExtendedData) + delete (unsigned char*)ExtendedData; + + if (UserData) + delete (unsigned char*)UserData; +} + + +void winstd::event_rec::set_extended_data(_In_ USHORT count, _In_count_(count) const EVENT_HEADER_EXTENDED_DATA_ITEM *data) +{ + if (ExtendedData) + delete (unsigned char*)ExtendedData; + + set_extended_data_internal(count, data); +} + + +void winstd::event_rec::set_user_data(_In_ USHORT size, _In_bytecount_(size) LPCVOID data) +{ + if (UserData) + delete (unsigned char*)UserData; + + set_user_data_internal(size, data); +} + + +void winstd::event_rec::set_extended_data_internal(_In_ USHORT count, _In_count_(count) const EVENT_HEADER_EXTENDED_DATA_ITEM *data) +{ + if (count) { + assert(data); + + // Count the total required memory. + size_t data_size = 0; + for (size_t i = 0; i < count; i++) + data_size += data[i].DataSize; + + // Allocate memory for extended data. + ExtendedData = (EVENT_HEADER_EXTENDED_DATA_ITEM*)(new unsigned char[sizeof(EVENT_HEADER_EXTENDED_DATA_ITEM)*count + data_size]); + + // Bulk-copy extended data descriptors. + memcpy(ExtendedData, data, sizeof(EVENT_HEADER_EXTENDED_DATA_ITEM) * count); + + // Copy the data. + unsigned char *ptr = (unsigned char*)(ExtendedData + count); + for (size_t i = 0; i < count; i++) { + if (data[i].DataSize) { + memcpy(ptr, (void*)(data[i].DataPtr), data[i].DataSize); + ExtendedData[i].DataPtr = (ULONGLONG)ptr; + ptr += data[i].DataSize; + } else + ExtendedData[i].DataPtr = NULL; + } + } else + ExtendedData = NULL; + + ExtendedDataCount = count; +} + + +void winstd::event_rec::set_user_data_internal(_In_ USHORT size, _In_bytecount_(size) LPCVOID data) +{ + if (size) { + assert(data); + + // Allocate memory for user data. + UserData = new unsigned char[size]; + + // Copy user data. + memcpy(UserData, data, size); + } else + UserData = NULL; + + UserDataLength = size; +} + + ////////////////////////////////////////////////////////////////////// // winstd::event_provider //////////////////////////////////////////////////////////////////////