1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
use crate::guid::GUID;
use core::marker::PhantomData;
use core::mem::size_of;
use widestring::{U16CStr, U16Str};
use zerocopy::AsBytes;

/// Contains a reference to the data for an event field. The type of the data is not specified in
/// this structure; instead, the type of the data is stored in the event's metadata.
/// (See `win_etw_metadata::InFlag`.)
///
/// The data that this type points to must have a well-defined (stable) byte representation. For
/// example, `u32` has a well-defined byte representation, as long as there is agreement about
/// whether the value is stored in big-endian or little-endian order. Similarly, `[u8]` and
/// `[u32]` have well-defined byte representations. However, types such as `[bool]` do not have a
/// stable byte representation, and so `EventDataDescriptor` cannot point to `&[bool]`.
///
/// This type provides implementations of `From` that can be used to point to event data.
/// All of the `EventDataDescriptor::From` implementations for types require that the types have a
/// stable, guaranteed byte representation, and that is legal (meaningful) to read that byte
/// representation.
///
/// This type is equivalent to the Win32 structure `EVENT_DATA_DESCRIPTOR`, and its representation
/// is guaranteed to be equivalent.
///
/// # Implementation warning!
///
/// This code is responsible for ensuring memory safety. Even though it contains only simple
/// primitives, these primitives are actually native pointers and pointer bounds. This data
/// structure is passed to the ETW implementation, which dereferences those pointers. The Rust
/// type checker cannot "see" these dereferences, since they occur in non-Rust code, so the borrow
/// checker does not know that `EventDataDescriptor` deals with memory safety. This is why the
/// `phantom_ref` field exists, and it is _crucial_ that this code be used and encapsulated
/// correctly.
///
/// For type safety to be conserved, the following invariants *must* be maintained:
///
/// * The `'a` lifetime parameter of `EventDataDescriptor<'a>` must be correctly associated with
///   the lifetime of any reference that is used to construct an instance of `EventDataDescriptor`.
///
/// * The fields of `EventDataDescriptor` must remain private. Arbitrary user code cannot be
///   permitted to construct instances of `EventDataDescriptor` with arbitrary values for these
///   fields.
///
/// * `EventDataDescriptor` should only be used to pass to ETW functions.
#[repr(C)]
#[derive(Clone)]
pub struct EventDataDescriptor<'a> {
    // descriptor: evntprov::EVENT_DATA_DESCRIPTOR,
    ptr: u64,
    size: u32,

    /// In the Windows SDK, this field is marked "reserved" and is a union. However, it is clear
    /// from usage within `traceloggingprovider.h` that this field is used to identify event data,
    /// provider metadata, and event metadata.
    kind: u32,

    /// Represents the lifetime of the pointed-to data.
    phantom_ref: PhantomData<&'a ()>,
}

impl EventDataDescriptor<'static> {
    /// Returns an empty data descriptor.
    pub fn empty() -> Self {
        Self {
            ptr: 0,
            size: 0,
            kind: 0,
            phantom_ref: PhantomData,
        }
    }
}

const EVENT_DATA_DESCRIPTOR_TYPE_PROVIDER_METADATA: u32 = 2;
const EVENT_DATA_DESCRIPTOR_TYPE_EVENT_METADATA: u32 = 1;

impl<'a> EventDataDescriptor<'a> {
    /// Creates an `EventDataDescriptor` for provider metadata.
    pub fn for_provider_metadata(s: &'a [u8]) -> Self {
        Self {
            ptr: s.as_ptr() as usize as u64,
            size: s.len() as u32,
            kind: EVENT_DATA_DESCRIPTOR_TYPE_PROVIDER_METADATA,
            phantom_ref: PhantomData,
        }
    }

    /// Creates an `EventDataDescriptor` for the metadata that describes a single event.
    pub fn for_event_metadata(s: &'a [u8]) -> Self {
        Self {
            ptr: s.as_ptr() as usize as u64,
            size: s.len() as u32,
            kind: EVENT_DATA_DESCRIPTOR_TYPE_EVENT_METADATA,
            phantom_ref: PhantomData,
        }
    }

    /// Creates a `EventDataDescriptor for a slice of bytes.
    pub fn for_bytes(s: &'a [u8]) -> Self {
        Self {
            ptr: s.as_ptr() as usize as u64,
            size: s.len() as u32,
            kind: 0,
            phantom_ref: PhantomData,
        }
    }
}

macro_rules! well_known_types {
    (
        $(
            $t:ident ;
        )*
    ) => {
        $(
            impl<'a> From<&'a $t> for EventDataDescriptor<'a> {
                fn from(value: &'a $t) -> EventDataDescriptor<'a> {
                    EventDataDescriptor::for_bytes(value.as_bytes())
                }
            }

            impl<'a> From<&'a [$t]> for EventDataDescriptor<'a> {
                fn from(value: &'a [$t]) -> EventDataDescriptor<'a> {
                    EventDataDescriptor::for_bytes(value.as_bytes())
                }
            }
        )*
    }
}

well_known_types! {
    bool;
    u8; u16; u32; u64;
    i8; i16; i32; i64;
    f32; f64;
    usize; isize;
}

impl<'a> From<&'a str> for EventDataDescriptor<'a> {
    fn from(value: &'a str) -> EventDataDescriptor<'a> {
        let bytes: &'a [u8] = value.as_bytes();
        EventDataDescriptor::for_bytes(bytes)
    }
}

impl<'a> From<&'a U16Str> for EventDataDescriptor<'a> {
    fn from(value: &'a U16Str) -> EventDataDescriptor<'a> {
        Self {
            ptr: value.as_ptr() as usize as u64,
            size: (value.len() * 2) as u32,
            kind: 0,
            phantom_ref: PhantomData,
        }
    }
}

impl<'a> From<&'a U16CStr> for EventDataDescriptor<'a> {
    fn from(value: &'a U16CStr) -> EventDataDescriptor<'a> {
        Self {
            ptr: value.as_ptr() as usize as u64,
            size: (value.len() * 2) as u32,
            kind: 0,
            phantom_ref: PhantomData,
        }
    }
}

impl<'a> From<&'a GUID> for EventDataDescriptor<'a> {
    fn from(value: &'a GUID) -> EventDataDescriptor<'a> {
        Self {
            ptr: value as *const GUID as usize as u64,
            size: size_of::<GUID>() as u32,
            kind: 0,
            phantom_ref: PhantomData,
        }
    }
}