diff options
| -rw-r--r-- | windows/windns/src/windns/wmi/eventdispatcher.cpp | 114 | ||||
| -rw-r--r-- | windows/windns/src/windns/wmi/eventdispatcher.h | 103 | ||||
| -rw-r--r-- | windows/windns/src/windns/wmi/eventsink.cpp | 93 | ||||
| -rw-r--r-- | windows/windns/src/windns/wmi/eventsink.h | 55 | ||||
| -rw-r--r-- | windows/windns/src/windns/wmi/ieventsink.h | 38 |
5 files changed, 255 insertions, 148 deletions
diff --git a/windows/windns/src/windns/wmi/eventdispatcher.cpp b/windows/windns/src/windns/wmi/eventdispatcher.cpp new file mode 100644 index 0000000000..5b2c64a9aa --- /dev/null +++ b/windows/windns/src/windns/wmi/eventdispatcher.cpp @@ -0,0 +1,114 @@ +#include "stdafx.h" +#include "eventdispatcher.h" +#include "windns/comhelpers.h" + +namespace wmi +{ + +EventDispatcherBase::EventDispatcherBase() + : m_references(0) + , m_callbacks(0) +{ +} + +bool EventDispatcherBase::processing() const +{ + // + // Cancelling the notification registration WILL NOT wait for the completion of + // callbacks currently in progress :-( + // + // (Observed on Win10) + // + + return 0 != InterlockedAdd(&m_callbacks, 0); +} + +ULONG STDMETHODCALLTYPE EventDispatcherBase::AddRef() +{ + return InterlockedIncrement(&m_references); +} + +ULONG STDMETHODCALLTYPE EventDispatcherBase::Release() +{ + auto refs = InterlockedDecrement(&m_references); + + if (refs == 0) + { + delete this; + } + + return refs; +} + +HRESULT STDMETHODCALLTYPE EventDispatcherBase::QueryInterface(REFIID riid, void **ppv) +{ + if (IID_IUnknown == riid || IID_IWbemObjectSink == riid) + { + *ppv = (IWbemObjectSink *)this; + AddRef(); + + return WBEM_S_NO_ERROR; + } + + return E_NOINTERFACE; +} + +HRESULT STDMETHODCALLTYPE EventDispatcherBase::Indicate +( + LONG numObjects, + IWbemClassObject __RPC_FAR *__RPC_FAR *objects +) +{ + InterlockedIncrement(&m_callbacks); + + for (LONG i = 0; i < numObjects; ++i) + { + CComPtr<IWbemClassObject> eventRecord(objects[i]); + + dispatch(eventRecord); + } + + InterlockedDecrement(&m_callbacks); + + return WBEM_S_NO_ERROR; +} + +HRESULT STDMETHODCALLTYPE EventDispatcherBase::SetStatus +( + LONG, HRESULT, BSTR, IWbemClassObject __RPC_FAR * +) +{ + return WBEM_S_NO_ERROR; +} + +EventDispatcher::EventDispatcher(std::shared_ptr<IEventSink> eventSink) + : m_eventSink(eventSink) +{ +} + +void EventDispatcher::dispatch(CComPtr<IWbemClassObject> eventRecord) +{ + auto rawTarget = ComGetPropertyAlways(eventRecord, L"TargetInstance"); + + CComQIPtr<IWbemClassObject> target(V_UNKNOWN(&rawTarget)); + + m_eventSink->update(target); +} + +ModificationEventDispatcher::ModificationEventDispatcher(std::shared_ptr<IModificationEventSink> eventSink) + : m_eventSink(eventSink) +{ +} + +void ModificationEventDispatcher::dispatch(CComPtr<IWbemClassObject> eventRecord) +{ + auto rawPrevious = ComGetPropertyAlways(eventRecord, L"PreviousInstance"); + auto rawTarget = ComGetPropertyAlways(eventRecord, L"TargetInstance"); + + CComQIPtr<IWbemClassObject> previous(V_UNKNOWN(&rawPrevious)); + CComQIPtr<IWbemClassObject> target(V_UNKNOWN(&rawTarget)); + + m_eventSink->update(previous, target); +} + +} diff --git a/windows/windns/src/windns/wmi/eventdispatcher.h b/windows/windns/src/windns/wmi/eventdispatcher.h new file mode 100644 index 0000000000..ec3b01e32a --- /dev/null +++ b/windows/windns/src/windns/wmi/eventdispatcher.h @@ -0,0 +1,103 @@ +#pragma once + +#include "ieventsink.h" +#include <memory> +#include <atlbase.h> +#include <wbemidl.h> + +namespace wmi +{ + +struct IEventDispatcher : public IWbemObjectSink +{ + virtual ~IEventDispatcher() = 0 + { + } + + virtual bool processing() const = 0; +}; + +// +// EventDispatcherBase +// +// Base class for event dispatcher implementations. +// +// The base class has all the logic and COM management but defers actual dispatching +// to the derived class. +// +// From the perspective of COM, this is an event sink, but from the perspective of +// WINDNS code it's a dispatcher that dispatches to the actual sink. +// +class EventDispatcherBase : public IEventDispatcher +{ +public: + + EventDispatcherBase(); + + virtual ~EventDispatcherBase() = 0 + { + } + + bool processing() const override; + + ULONG STDMETHODCALLTYPE AddRef() override; + ULONG STDMETHODCALLTYPE Release() override; + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv) override; + + HRESULT STDMETHODCALLTYPE Indicate + ( + LONG numObjects, + IWbemClassObject __RPC_FAR *__RPC_FAR *objects + ) + override; + + HRESULT STDMETHODCALLTYPE SetStatus + ( + LONG flags, + HRESULT result, + BSTR param, + IWbemClassObject __RPC_FAR *object + ) + override; + +protected: + + virtual void dispatch(CComPtr<IWbemClassObject> eventRecord) = 0; + +private: + + LONG m_references; + mutable LONG m_callbacks; +}; + +class EventDispatcher : public EventDispatcherBase +{ +public: + + EventDispatcher(std::shared_ptr<IEventSink> eventSink); + +protected: + + void dispatch(CComPtr<IWbemClassObject> eventRecord) override; + +private: + + std::shared_ptr<IEventSink> m_eventSink; +}; + +class ModificationEventDispatcher : public EventDispatcherBase +{ +public: + + ModificationEventDispatcher(std::shared_ptr<IModificationEventSink> eventSink); + +protected: + + void dispatch(CComPtr<IWbemClassObject> eventRecord) override; + +private: + + std::shared_ptr<IModificationEventSink> m_eventSink; +}; + +} diff --git a/windows/windns/src/windns/wmi/eventsink.cpp b/windows/windns/src/windns/wmi/eventsink.cpp deleted file mode 100644 index 516660ff0a..0000000000 --- a/windows/windns/src/windns/wmi/eventsink.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "stdafx.h" -#include "eventsink.h" -#include "windns/comhelpers.h" - -namespace wmi -{ - -EventSink::EventSink(std::shared_ptr<IEventSink> eventSink) - : m_references(0) - , m_callbacks(0) - , m_eventSink(eventSink) -{ -} - -EventSink::~EventSink() -{ -} - -bool EventSink::processing() const -{ - // - // Cancelling the notification registration WILL NOT wait for the completion of - // callbacks currently in progress :-( - // - // (Observed on Win10) - // - - return 0 != InterlockedAdd(&m_callbacks, 0); -} - -ULONG STDMETHODCALLTYPE EventSink::AddRef() -{ - return InterlockedIncrement(&m_references); -} - -ULONG STDMETHODCALLTYPE EventSink::Release() -{ - auto refs = InterlockedDecrement(&m_references); - - if (refs == 0) - { - delete this; - } - - return refs; -} - -HRESULT STDMETHODCALLTYPE EventSink::QueryInterface(REFIID riid, void **ppv) -{ - if (IID_IUnknown == riid || IID_IWbemObjectSink == riid) - { - *ppv = (IWbemObjectSink *)this; - AddRef(); - - return WBEM_S_NO_ERROR; - } - - return E_NOINTERFACE; -} - -HRESULT STDMETHODCALLTYPE EventSink::Indicate -( - LONG numObjects, - IWbemClassObject __RPC_FAR *__RPC_FAR *objects -) -{ - InterlockedIncrement(&m_callbacks); - - for (LONG i = 0; i < numObjects; ++i) - { - CComPtr<IWbemClassObject> eventRecord(objects[i]); - - auto rawTarget = ComGetPropertyAlways(eventRecord, L"TargetInstance"); - - CComQIPtr<IWbemClassObject> target(V_UNKNOWN(&rawTarget)); - - m_eventSink->update(target); - } - - InterlockedDecrement(&m_callbacks); - - return WBEM_S_NO_ERROR; -} - -HRESULT STDMETHODCALLTYPE EventSink::SetStatus -( - LONG, HRESULT, BSTR, IWbemClassObject __RPC_FAR * -) -{ - return WBEM_S_NO_ERROR; -} - -} diff --git a/windows/windns/src/windns/wmi/eventsink.h b/windows/windns/src/windns/wmi/eventsink.h deleted file mode 100644 index 2f0783d81f..0000000000 --- a/windows/windns/src/windns/wmi/eventsink.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include <memory> -#include <atlbase.h> -#include <wbemidl.h> - -namespace wmi -{ - -struct IEventSink -{ - virtual ~IEventSink() = 0 - { - } - - virtual void update(CComPtr<IWbemClassObject> instance) = 0; -}; - -class EventSink : public IWbemObjectSink -{ -public: - - EventSink(std::shared_ptr<IEventSink> eventSink); - ~EventSink(); - - bool processing() const; - - ULONG STDMETHODCALLTYPE AddRef() override; - ULONG STDMETHODCALLTYPE Release() override; - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv) override; - - HRESULT STDMETHODCALLTYPE Indicate - ( - LONG numObjects, - IWbemClassObject __RPC_FAR *__RPC_FAR *objects - ) - override; - - HRESULT STDMETHODCALLTYPE SetStatus - ( - LONG flags, - HRESULT result, - BSTR param, - IWbemClassObject __RPC_FAR *object - ) - override; - -private: - - LONG m_references; - mutable LONG m_callbacks; - std::shared_ptr<IEventSink> m_eventSink; -}; - -} diff --git a/windows/windns/src/windns/wmi/ieventsink.h b/windows/windns/src/windns/wmi/ieventsink.h new file mode 100644 index 0000000000..c8c6c01cea --- /dev/null +++ b/windows/windns/src/windns/wmi/ieventsink.h @@ -0,0 +1,38 @@ +#pragma once + +#include <atlbase.h> +#include <wbemidl.h> + +namespace wmi +{ + +// +// IEventSink, use with: +// +// __InstanceCreationEvent +// __InstanceDeletionEvent +// +struct IEventSink +{ + virtual ~IEventSink() = 0 + { + } + + virtual void update(CComPtr<IWbemClassObject> instance) = 0; +}; + +// +// IModificationEventSink, use with: +// +// __InstanceModificationEvent +// +struct IModificationEventSink +{ + virtual ~IModificationEventSink() = 0 + { + } + + virtual void update(CComPtr<IWbemClassObject> previous, CComPtr<IWbemClassObject> target) = 0; +}; + +} |
