summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--windns/src/windns/wmi/methodcall.cpp104
-rw-r--r--windns/src/windns/wmi/methodcall.h75
2 files changed, 179 insertions, 0 deletions
diff --git a/windns/src/windns/wmi/methodcall.cpp b/windns/src/windns/wmi/methodcall.cpp
new file mode 100644
index 0000000000..fcd4f738c8
--- /dev/null
+++ b/windns/src/windns/wmi/methodcall.cpp
@@ -0,0 +1,104 @@
+#include "stdafx.h"
+#include "methodcall.h"
+#include "windns/comhelpers.h"
+#include <algorithm>
+
+namespace wmi
+{
+
+void MethodCall::addArgument(const std::wstring &name, _variant_t value)
+{
+ m_arguments.emplace_back(Argument(name, value));
+}
+
+void MethodCall::addNullArgument(const std::wstring &name, CIMTYPE type)
+{
+ m_arguments.emplace_back(Argument(name, type));
+}
+
+_variant_t MethodCall::invoke(IConnection &connection, CComPtr<IWbemClassObject> instance, const std::wstring &methodName)
+{
+ std::for_each(m_arguments.begin(), m_arguments.end(), [&](const Argument &arg)
+ {
+ HRESULT status;
+
+ if (arg.nullValue())
+ {
+ status = instance->Put(arg.name().c_str(), 0, nullptr, arg.type());
+ }
+ else
+ {
+ _variant_t &value = const_cast<variant_t &>(arg.value());
+
+ status = instance->Put(arg.name().c_str(), 0, &value, 0);
+ }
+
+ VALIDATE_COM(status, "Register COM method argument");
+ });
+
+ _variant_t path;
+
+ auto status = instance->Get(_bstr_t(L"__PATH"), 0, &path, nullptr, nullptr);
+
+ VALIDATE_COM(status, "Get COM instance path");
+
+ CComPtr<IWbemClassObject> result;
+
+ status = connection.services()->ExecMethod(V_BSTR(&path), _bstr_t(methodName.c_str()), 0, nullptr, instance, &result, nullptr);
+
+ VALIDATE_COM(status, "Execute COM method call");
+
+ return ComGetProperty(result, L"ReturnValue");
+}
+
+
+//
+// the following code is almost what is needed for static method calls
+// just remove the path and the in-arg instance
+// also, update first arg to ExecMethod
+//
+//_variant_t MethodCall::call(Connection &connection, CComPtr<IWbemClassObject> instance, const std::wstring &methodName)
+//{
+// CComPtr<IWbemClassObject> cls;
+//
+// auto status = connection.m_services->GetObject(_bstr_t(L"Win32_NetworkAdapterConfiguration"), 0, nullptr, &cls, nullptr);
+// VALIDATE_COM(status, "Resolve COM class");
+//
+// CComPtr<IWbemClassObject> methodDefinition;
+//
+// status = cls->GetMethod(methodName.c_str(), 0, &methodDefinition, nullptr);
+// VALIDATE_COM(status, "Resolve COM instance method");
+//
+// CComPtr<IWbemClassObject> methodInstance;
+//
+// status = methodDefinition->SpawnInstance(0, &methodInstance);
+// VALIDATE_COM(status, "Instantiate COM class for method call");
+//
+// std::for_each(m_arguments.begin(), m_arguments.end(), [&](const Argument &arg)
+// {
+// _variant_t value(arg.value);
+//
+// // This works for all values except NULL
+// auto hr = methodInstance->Put(arg.name.c_str(), 0, &value, 0);
+//
+// VALIDATE_COM(hr, "Register COM method argument");
+// });
+//
+// _variant_t path;
+//
+// status = instance->Get(_bstr_t(L"__PATH"), 0, &path, nullptr, nullptr);
+// VALIDATE_COM(status, "Get COM instance path");
+//
+// CComPtr<IWbemClassObject> result;
+//
+// status = connection.m_services->ExecMethod(path.bstrVal, _bstr_t(methodName.c_str()), 0, nullptr, methodInstance, &result, nullptr/*?*/);
+// VALIDATE_COM(status, "Execute COM method call");
+//
+// return ComGetProperty(result, L"ReturnValue");
+//}
+//
+
+
+
+
+}
diff --git a/windns/src/windns/wmi/methodcall.h b/windns/src/windns/wmi/methodcall.h
new file mode 100644
index 0000000000..4d964b60db
--- /dev/null
+++ b/windns/src/windns/wmi/methodcall.h
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "iconnection.h"
+#include <string>
+#include <vector>
+#include <stdexcept>
+#include <comutil.h>
+
+namespace wmi
+{
+
+class MethodCall
+{
+public:
+
+ void addArgument(const std::wstring &name, _variant_t value);
+ void addNullArgument(const std::wstring &name, CIMTYPE type);
+
+ _variant_t invoke(IConnection &connection, CComPtr<IWbemClassObject> instance, const std::wstring &methodName);
+
+private:
+
+ class Argument
+ {
+ public:
+
+ Argument(const std::wstring &name, _variant_t value)
+ : m_name(name)
+ , m_value(value)
+ {
+ if (VT_NULL == V_VT(&value) || VT_EMPTY == V_VT(&value))
+ {
+ throw std::runtime_error("Cannot add null-argument without specifying type.");
+ }
+ }
+
+ Argument(const std::wstring &name, CIMTYPE type)
+ : m_name(name)
+ , m_type(type)
+ {
+ }
+
+ bool nullValue() const
+ {
+ return VT_EMPTY == V_VT(&m_value);
+ }
+
+ const std::wstring &name() const
+ {
+ return m_name;
+ }
+
+ const _variant_t &value() const
+ {
+ return m_value;
+ }
+
+ CIMTYPE type() const
+ {
+ return m_type;
+ }
+
+ private:
+
+ std::wstring m_name;
+ _variant_t m_value;
+
+ // Explicitly specify type when the value is NULL.
+ CIMTYPE m_type;
+ };
+
+ std::vector<Argument> m_arguments;
+};
+
+}