in extensions/windows-event-log/CollectorInitiatedSubscription.cpp [126:302]
bool CollectorInitiatedSubscription::checkSubscriptionRuntimeStatus() {
EC_HANDLE hSubscription = EcOpenSubscription(subscription_name_.c_str(), EC_READ_ACCESS, EC_OPEN_EXISTING);
if (!hSubscription) {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcOpenSubscription");
return false;
}
const auto guard_hSubscription = gsl::finally([hSubscription]() { EcClose(hSubscription); });
PEC_VARIANT vProperty = NULL;
std::vector<BYTE> buffer;
if (!getSubscriptionProperty(hSubscription, EcSubscriptionEventSources, 0, buffer, vProperty)) {
return false;
}
// 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); });
// Get the EventSources array size (number of elements).
DWORD dwEventSourceCount{};
if (!EcGetObjectArraySize(hArray, &dwEventSourceCount)) {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcGetObjectArraySize");
return false;
}
auto getArrayProperty = [this](EC_OBJECT_ARRAY_PROPERTY_HANDLE hArray, EC_SUBSCRIPTION_PROPERTY_ID propID, DWORD arrayIndex, DWORD flags, std::vector<BYTE>& buffer, PEC_VARIANT& vProperty) -> bool {
buffer.clear();
buffer.resize(sizeof(EC_VARIANT));
DWORD dwBufferSizeUsed{};
if (!EcGetObjectArrayProperty(hArray, propID, arrayIndex, flags, static_cast<DWORD>(buffer.size()), reinterpret_cast<PEC_VARIANT>(&buffer[0]), &dwBufferSizeUsed)) {
if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
buffer.resize(dwBufferSizeUsed);
if (!EcGetObjectArrayProperty(hArray, propID, arrayIndex, flags, static_cast<DWORD>(buffer.size()), reinterpret_cast<PEC_VARIANT>(&buffer[0]), &dwBufferSizeUsed)) {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcGetObjectArrayProperty");
return false;
}
} else {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcGetObjectArrayProperty");
return false;
}
}
vProperty = reinterpret_cast<PEC_VARIANT>(&buffer[0]);
return true;
};
auto getStatus = [this](const std::wstring& eventSource, EC_SUBSCRIPTION_RUNTIME_STATUS_INFO_ID statusInfoID, DWORD flags, std::vector<BYTE>& buffer, PEC_VARIANT& vStatus) -> bool {
buffer.clear();
buffer.resize(sizeof(EC_VARIANT));
DWORD dwBufferSize{};
if (!EcGetSubscriptionRunTimeStatus(
subscription_name_.c_str(),
statusInfoID,
eventSource.c_str(),
flags,
static_cast<DWORD>(buffer.size()),
reinterpret_cast<PEC_VARIANT>(&buffer[0]),
&dwBufferSize)) {
if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
buffer.resize(dwBufferSize);
if (!EcGetSubscriptionRunTimeStatus(subscription_name_.c_str(),
statusInfoID,
eventSource.c_str(),
flags,
static_cast<DWORD>(buffer.size()),
reinterpret_cast<PEC_VARIANT>(&buffer[0]),
&dwBufferSize)) {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcGetSubscriptionRunTimeStatus");
}
} else {
LOG_SUBSCRIPTION_WINDOWS_ERROR("EcGetSubscriptionRunTimeStatus");
}
}
vStatus = reinterpret_cast<PEC_VARIANT>(&buffer[0]);
return true;
};
for (DWORD i = 0; i < dwEventSourceCount; i++) {
std::vector<BYTE> eventSourceBuffer;
PEC_VARIANT vProperty = NULL;
if (!getArrayProperty(hArray, EcSubscriptionEventSourceAddress, i, 0, eventSourceBuffer, vProperty)) {
return false;
}
if (vProperty->Type != EcVarTypeNull && vProperty->Type != EcVarTypeString) {
logInvalidSubscriptionPropertyType(__LINE__, vProperty->Type);
return false;
}
if (vProperty->Type == EcVarTypeNull)
continue;
const std::wstring eventSource = vProperty->StringVal;
if (!getStatus(eventSource.c_str(), EcSubscriptionRunTimeStatusActive, 0, buffer, vProperty)) {
return false;
}
if (vProperty->Type != EcVarTypeUInt32) {
logInvalidSubscriptionPropertyType(__LINE__, vProperty->Type);
return false;
}
const auto runtimeStatus = vProperty->UInt32Val;
std::wstring strRuntimeStatus;
switch (runtimeStatus) {
case EcRuntimeStatusActiveStatusActive:
strRuntimeStatus = L"Active";
break;
case EcRuntimeStatusActiveStatusDisabled:
strRuntimeStatus = L"Disabled";
break;
case EcRuntimeStatusActiveStatusInactive:
strRuntimeStatus = L"Inactive";
break;
case EcRuntimeStatusActiveStatusTrying:
strRuntimeStatus = L"Trying";
break;
default:
strRuntimeStatus = L"Unknown";
break;
}
// Get Subscription Last Error.
if (!getStatus(eventSource, EcSubscriptionRunTimeStatusLastError, 0, buffer, vProperty)) {
return false;
}
if (vProperty->Type != EcVarTypeUInt32) {
logInvalidSubscriptionPropertyType(__LINE__, vProperty->Type);
return false;
}
const auto lastError = vProperty->UInt32Val;
if (lastError == 0 && (runtimeStatus == EcRuntimeStatusActiveStatusActive || runtimeStatus == EcRuntimeStatusActiveStatusTrying)) {
logger_->log_info("Subscription '%ws': status '%ws', no error.", subscription_name_.c_str(), strRuntimeStatus.c_str());
return true;
}
// Obtain the associated Error Message.
if (!getStatus(eventSource, EcSubscriptionRunTimeStatusLastErrorMessage, 0, buffer, vProperty)) {
return false;
}
if (vProperty->Type != EcVarTypeNull && vProperty->Type != EcVarTypeString) {
logInvalidSubscriptionPropertyType(__LINE__, vProperty->Type);
return false;
}
std::wstring lastErrorMessage;
if (vProperty->Type == EcVarTypeString) {
lastErrorMessage = vProperty->StringVal;
}
logger_->log_error("Runtime status: %ws, last error: %d, last error message: %ws", strRuntimeStatus.c_str(), lastError, lastErrorMessage.c_str());
return false;
}
return true;
}