summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--windows/windns/src/windns/wmi/eventdispatcher.cpp114
-rw-r--r--windows/windns/src/windns/wmi/eventdispatcher.h103
-rw-r--r--windows/windns/src/windns/wmi/eventsink.cpp93
-rw-r--r--windows/windns/src/windns/wmi/eventsink.h55
-rw-r--r--windows/windns/src/windns/wmi/ieventsink.h38
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;
+};
+
+}