inline void ut::enable_providers()

in krabs/krabs/ut.hpp [124:202]


    inline void ut::enable_providers(
        const krabs::trace<krabs::details::ut> &trace)
    {
        if (trace.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE)
            return;

        provider_filter_settings provider_flags;

        // This function essentially takes the union of all the provider flags
        // for a given provider GUID. This comes about when multiple providers
        // for the same GUID are provided and request different provider flags.
        // TODO: Only forward the calls that are requested to each provider.
        for (auto &provider : trace.providers_) {
            auto& settings = provider_flags[provider.get().guid_];
            settings.filter_flags_.level_       |= provider.get().level_;
            settings.filter_flags_.any_         |= provider.get().any_;
            settings.filter_flags_.all_         |= provider.get().all_;
            settings.filter_flags_.trace_flags_ |= provider.get().trace_flags_;
            settings.rundown_enabled_           |= provider.get().rundown_enabled_;

            for (const auto& filter : provider.get().filters_) {
                settings.provider_filter_event_ids_.insert(
                    filter.provider_filter_event_ids().begin(),
                    filter.provider_filter_event_ids().end());
            }
        }

        for (auto &provider : provider_flags) {
            ENABLE_TRACE_PARAMETERS parameters;
            parameters.ControlFlags = 0;
            parameters.Version = ENABLE_TRACE_PARAMETERS_VERSION_2;
            parameters.SourceId = provider.first;
            
            GUID guid = provider.first;
            auto& settings = provider.second;

            parameters.EnableProperty = settings.filter_flags_.trace_flags_;
            parameters.EnableFilterDesc = nullptr;
            parameters.FilterDescCount = 0;
            EVENT_FILTER_DESCRIPTOR filterDesc{};
            std::vector<BYTE> filterEventIdBuffer;
            auto filterEventIdCount = settings.provider_filter_event_ids_.size();

            if (filterEventIdCount > 0) {
                //event filters existing, set native filters using API
                parameters.FilterDescCount = 1;
                filterDesc.Type = EVENT_FILTER_TYPE_EVENT_ID;

                //allocate + size of expected events in filter
                DWORD size = FIELD_OFFSET(EVENT_FILTER_EVENT_ID, Events[filterEventIdCount]);
                filterEventIdBuffer.resize(size, 0);

                auto filterEventIds = reinterpret_cast<PEVENT_FILTER_EVENT_ID>(&(filterEventIdBuffer[0]));
                filterEventIds->FilterIn = TRUE;
                filterEventIds->Count = static_cast<USHORT>(filterEventIdCount);

                auto index = 0;
                for (auto filter : settings.provider_filter_event_ids_) {
                    filterEventIds->Events[index] = filter;
                    index++;
                }

                filterDesc.Ptr = reinterpret_cast<ULONGLONG>(filterEventIds);
                filterDesc.Size = size;

                parameters.EnableFilterDesc = &filterDesc;
            }

            ULONG status = EnableTraceEx2(trace.registrationHandle_,
                                          &guid,
                                          EVENT_CONTROL_CODE_ENABLE_PROVIDER,
                                          settings.filter_flags_.level_,
                                          settings.filter_flags_.any_,
                                          settings.filter_flags_.all_,
                                          0,
                                          &parameters);
            error_check_common_conditions(status);
        }
    }