in extensions/windows-event-log/CollectorInitiatedSubscription.cpp [326:451]
bool CollectorInitiatedSubscription::createSubscription(const std::shared_ptr<core::ProcessContext>& context) {
gsl_Expects(context);
// If subcription already exists, delete it.
EC_HANDLE hSubscription = EcOpenSubscription(subscription_name_.c_str(), EC_READ_ACCESS, EC_OPEN_EXISTING);
if (hSubscription) {
EcClose(hSubscription);
if (!EcDeleteSubscription(subscription_name_.c_str(), 0)) {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcDeleteSubscription");
return false;
}
}
// Create subscription.
hSubscription = EcOpenSubscription(subscription_name_.c_str(), EC_READ_ACCESS | EC_WRITE_ACCESS, EC_CREATE_NEW);
if (!hSubscription) {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcOpenSubscription");
return false;
}
const auto guard_hSubscription = gsl::finally([hSubscription]() { EcClose(hSubscription); });
struct SubscriptionProperty {
SubscriptionProperty(EC_SUBSCRIPTION_PROPERTY_ID propId, const std::wstring& val) {
propId_ = propId;
prop_.Type = EcVarTypeString;
prop_.StringVal = val.c_str();
}
SubscriptionProperty(EC_SUBSCRIPTION_PROPERTY_ID propId, uint32_t val) {
propId_ = propId;
prop_.Type = EcVarTypeUInt32;
prop_.UInt32Val = val;
}
SubscriptionProperty(EC_SUBSCRIPTION_PROPERTY_ID propId, bool val) {
propId_ = propId;
prop_.Type = EcVarTypeBoolean;
prop_.BooleanVal = val;
}
EC_SUBSCRIPTION_PROPERTY_ID propId_;
EC_VARIANT prop_;
};
const auto subscription_description = to_wstring(context->getProperty(SubscriptionDescription).value());
const auto source_channels = to_wstring(context->getProperty(SourceChannels).value());
const auto channel = to_wstring(context->getProperty(Channel).value());
const auto max_delivery_items = context->getProperty<core::DataSizeValue>(MaxDeliveryItems).value().getValue();
const auto delivery_max_latency_time = context->getProperty<core::TimePeriodValue>(DeliveryMaxLatencyTime).value().getMilliseconds().count();
const auto heartbeat_interval = context->getProperty<core::TimePeriodValue>(HeartbeatInterval).value().getMilliseconds().count();
const auto source_user_name = to_wstring(context->getProperty(SourceUserName).value());
const auto source_password = to_wstring(context->getProperty(SourcePassword).value());
std::vector<SubscriptionProperty> listProperty = {
{EcSubscriptionDescription, subscription_description},
{EcSubscriptionURI, std::wstring(L"http://schemas.microsoft.com/wbem/wsman/1/windows/EventLog")},
{EcSubscriptionQuery, L"<QueryList><Query Path=\"" + source_channels + L"\"><Select>*</Select></Query></QueryList>"},
{EcSubscriptionLogFile, channel},
{EcSubscriptionConfigurationMode, static_cast<uint32_t>(EcConfigurationModeCustom)},
{EcSubscriptionDeliveryMode, static_cast<uint32_t>(EcDeliveryModePull)},
{EcSubscriptionDeliveryMaxItems, static_cast<uint32_t>(max_delivery_items)},
{EcSubscriptionDeliveryMaxLatencyTime, static_cast<uint32_t>(delivery_max_latency_time)},
{EcSubscriptionHeartbeatInterval, static_cast<uint32_t>(heartbeat_interval)},
{EcSubscriptionContentFormat, static_cast<uint32_t>(EcContentFormatRenderedText)},
{EcSubscriptionCredentialsType, static_cast<uint32_t>(EcSubscriptionCredDefault)},
{EcSubscriptionEnabled, true},
{EcSubscriptionCommonUserName, source_user_name},
{EcSubscriptionCommonPassword, source_password}
};
for (auto& prop : listProperty) {
if (!EcSetSubscriptionProperty(hSubscription, prop.propId_, 0, &prop.prop_)) {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcSetSubscriptionProperty id: " + std::to_string(prop.propId_));
return false;
}
}
// Get the EventSources array so a new event source can be added for the specified target.
std::vector<BYTE> buffer;
PEC_VARIANT vProperty = NULL;
if (!getSubscriptionProperty(hSubscription, EcSubscriptionEventSources, 0, buffer, vProperty))
return false;
// Event Sources is a collection. Ensure that we have obtained handle to the Array Property.
if (vProperty->Type != EcVarTypeNull && vProperty->Type != EcVarObjectArrayPropertyHandle) {
logInvalidSubscriptionPropertyType(__LINE__, vProperty->Type);
return false;
}
if (vProperty->Type == EcVarTypeNull) {
LOG_SUBSCRIPTION_ERROR("!hArray");
return false;
}
const EC_OBJECT_ARRAY_PROPERTY_HANDLE hArray = vProperty->PropertyHandleVal;
const auto guard_hArray = gsl::finally([hArray]() { EcClose(hArray); });
DWORD dwEventSourceCount{};
if (!EcGetObjectArraySize(hArray, &dwEventSourceCount)) {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcGetObjectArraySize");
return false;
}
// Add a new EventSource to the EventSources array object.
if (!EcInsertObjectArrayElement(hArray, dwEventSourceCount)) {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcInsertObjectArrayElement");
return false;
}
const auto source_address = to_wstring(context->getProperty(SourceAddress).value());
for (auto& prop : std::vector<SubscriptionProperty>{{EcSubscriptionEventSourceAddress, source_address}, {EcSubscriptionEventSourceEnabled, true}}) {
if (!EcSetObjectArrayProperty(hArray, prop.propId_, dwEventSourceCount, 0, &prop.prop_)) {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcSetObjectArrayProperty id: " + std::to_string(prop.propId_));
return false;
}
}
if (!EcSaveSubscription(hSubscription, NULL)) {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcSaveSubscription");
return false;
}
return true;
}