summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralexeypa@google.com <alexeypa@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-14 23:29:10 +0000
committeralexeypa@google.com <alexeypa@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-14 23:29:10 +0000
commit760787b84169d6c49878e5f754d69b338b1626a7 (patch)
tree0e2ac67d034a7cb643b5007a013eaebafca7b20c
parent0b26a2899272962c98982d741fd70747fa23b34c (diff)
downloadchromium_src-760787b84169d6c49878e5f754d69b338b1626a7.zip
chromium_src-760787b84169d6c49878e5f754d69b338b1626a7.tar.gz
chromium_src-760787b84169d6c49878e5f754d69b338b1626a7.tar.bz2
Merge 141960 - [Chromoting] Using IDispatch::Invoke() to call Omaha inetrfaces.
Omaha uses non-standard scheme for versioning its COM interfaces. Instead of letting the callers to know a fixed UUID and prototype of an interface, Omaha relies on the callers to use late binding via IDispatch::Invoke. This way it can extend an interface after it has been released by adding new members and changing its UUID. The limitation is that vtable can no longer be used. BUG=131498 Review URL: https://chromiumcodereview.appspot.com/10532099 TBR=alexeypa@chromium.org Review URL: https://chromiumcodereview.appspot.com/10540167 git-svn-id: svn://svn.chromium.org/chrome/branches/1132/src@142271 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--remoting/base/dispatch_win.h536
-rw-r--r--remoting/base/dispatch_win.h.pump180
-rw-r--r--remoting/host/plugin/daemon_installer_win.cc99
-rw-r--r--remoting/remoting.gyp1
4 files changed, 772 insertions, 44 deletions
diff --git a/remoting/base/dispatch_win.h b/remoting/base/dispatch_win.h
new file mode 100644
index 0000000..1d12a70
--- /dev/null
+++ b/remoting/base/dispatch_win.h
@@ -0,0 +1,536 @@
+// This file was GENERATED by command:
+// pump.py dispatch_win.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_
+#define REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_
+
+#include <oaidl.h>
+
+#include "base/basictypes.h"
+#include "base/template_util.h"
+#include "base/win/scoped_variant.h"
+
+namespace remoting {
+
+namespace dispatch {
+
+namespace internal {
+
+// A helper wrapper for |VARIANTARG| that is used to pass parameters to and from
+// IDispatch::Invoke(). The latter accepts parameters as an array of
+// |VARIANTARG| structures. The calling convention is:
+// - [in] parameters are initialized and freed if needed by the caller.
+// - [out] parameters are initialized by IDispatch::Invoke(). It is up to
+// the caller to free leakable variants (such as VT_DISPATCH).
+// - [in] [out] parameters are combination of both: the caller initializes
+// them before the call and the callee assigns new values correctly
+// freeing leakable variants.
+//
+// Using |ScopedVariantArg| instead of naked |VARIANTARG| ensures that
+// the resources allocated during the call will be properly freed. It also
+// provides wraping methods that convert between C++ types and VARIANTs.
+// The current convention is:
+// - constant references are considered input parameters.
+// - pointers to non-constant objects are considered output parameters.
+// - [in] [out] parameters are not supported.
+//
+// It must be possible to cast a pointer to an array of |ScopedVariantArg| to
+// a pointer to an array of |VARIANTARG| structures.
+class ScopedVariantArg : public VARIANTARG {
+ public:
+ ScopedVariantArg() {
+ vt = VT_EMPTY;
+ }
+
+ ~ScopedVariantArg() {
+ VariantClear(this);
+ }
+
+ // Wrap() routines pack the input parameters into VARIANTARG structures so
+ // that they can be passed to IDispatch::Invoke.
+
+ HRESULT Wrap(const VARIANT& param) {
+ return VariantCopy(this, &param);
+ }
+
+ HRESULT Wrap(VARIANT* const & param) {
+ // Do nothing for an [out] parameter.
+ return S_OK;
+ }
+
+ // Unwrap() routines unpack the output parameters from VARIANTARG structures
+ // to the locations specified by the caller.
+
+ void Unwrap(const VARIANT& param_out) {
+ // Do nothing for an [in] parameter.
+ }
+
+ void Unwrap(VARIANT* const & param_out) {
+ *param_out = *this;
+ vt = VT_EMPTY;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedVariantArg);
+};
+
+// Make sure the layouts of |VARIANTARG| and |ScopedVariantArg| are identical.
+COMPILE_ASSERT(sizeof(ScopedVariantArg) == sizeof(VARIANTARG),
+ scoped_variant_arg_should_not_add_data_members);
+
+} // namespace internal
+
+// Invoke() is a convenience wrapper for IDispatch::Invoke. It takes care of
+// calling the desired method by its ID and implements logic for passing
+// a variable number of in/out parameters to the called method.
+//
+// Current limitations:
+// - in_out parameters are not supported.
+// - more than 7 parameters are not supported.
+// - the method ID cannot be cached and reused.
+// - VARIANT is the only supported parameter type at the moment.
+
+HRESULT Invoke(IDispatch* object,
+ LPOLESTR name,
+ WORD flags,
+ VARIANT* const & result_out) {
+ // Retrieve the ID of the method to be called.
+ DISPID disp_id;
+ HRESULT hr = object->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT,
+ &disp_id);
+ if (FAILED(hr))
+ return hr;
+
+ // Request the return value if asked by the caller.
+ internal::ScopedVariantArg result;
+ VARIANT* disp_result = NULL;
+ if (result_out != NULL)
+ disp_result = &result;
+
+
+ // Invoke the method.
+ DISPPARAMS disp_params = { NULL, NULL, 0, 0 };
+ hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags,
+ &disp_params, disp_result, NULL, NULL);
+ if (FAILED(hr))
+ return hr;
+
+
+ // Unwrap the return value.
+ if (result_out != NULL)
+ result.Unwrap(result_out);
+
+ return S_OK;
+}
+
+template <typename P1>
+HRESULT Invoke(IDispatch* object,
+ LPOLESTR name,
+ WORD flags,
+ const P1& p1,
+ VARIANT* const & result_out) {
+ // Retrieve the ID of the method to be called.
+ DISPID disp_id;
+ HRESULT hr = object->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT,
+ &disp_id);
+ if (FAILED(hr))
+ return hr;
+
+ // Request the return value if asked by the caller.
+ internal::ScopedVariantArg result;
+ VARIANT* disp_result = NULL;
+ if (result_out != NULL)
+ disp_result = &result;
+
+ // Wrap the parameters into an array of VARIANT structures.
+ internal::ScopedVariantArg disp_args[1];
+ hr = disp_args[1 - 1].Wrap(p1);
+ if (FAILED(hr))
+ return hr;
+
+ // Invoke the method.
+ DISPPARAMS disp_params = { disp_args, NULL, 1, 0 };
+ hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags,
+ &disp_params, disp_result, NULL, NULL);
+ if (FAILED(hr))
+ return hr;
+
+ // Unwrap the parameters.
+ disp_args[1 - 1].Unwrap(p1);
+
+ // Unwrap the return value.
+ if (result_out != NULL)
+ result.Unwrap(result_out);
+
+ return S_OK;
+}
+
+template <typename P1, typename P2>
+HRESULT Invoke(IDispatch* object,
+ LPOLESTR name,
+ WORD flags,
+ const P1& p1,
+ const P2& p2,
+ VARIANT* const & result_out) {
+ // Retrieve the ID of the method to be called.
+ DISPID disp_id;
+ HRESULT hr = object->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT,
+ &disp_id);
+ if (FAILED(hr))
+ return hr;
+
+ // Request the return value if asked by the caller.
+ internal::ScopedVariantArg result;
+ VARIANT* disp_result = NULL;
+ if (result_out != NULL)
+ disp_result = &result;
+
+ // Wrap the parameters into an array of VARIANT structures.
+ internal::ScopedVariantArg disp_args[2];
+ hr = disp_args[2 - 1].Wrap(p1);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[2 - 2].Wrap(p2);
+ if (FAILED(hr))
+ return hr;
+
+ // Invoke the method.
+ DISPPARAMS disp_params = { disp_args, NULL, 2, 0 };
+ hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags,
+ &disp_params, disp_result, NULL, NULL);
+ if (FAILED(hr))
+ return hr;
+
+ // Unwrap the parameters.
+ disp_args[2 - 1].Unwrap(p1);
+ disp_args[2 - 2].Unwrap(p2);
+
+ // Unwrap the return value.
+ if (result_out != NULL)
+ result.Unwrap(result_out);
+
+ return S_OK;
+}
+
+template <typename P1, typename P2, typename P3>
+HRESULT Invoke(IDispatch* object,
+ LPOLESTR name,
+ WORD flags,
+ const P1& p1,
+ const P2& p2,
+ const P3& p3,
+ VARIANT* const & result_out) {
+ // Retrieve the ID of the method to be called.
+ DISPID disp_id;
+ HRESULT hr = object->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT,
+ &disp_id);
+ if (FAILED(hr))
+ return hr;
+
+ // Request the return value if asked by the caller.
+ internal::ScopedVariantArg result;
+ VARIANT* disp_result = NULL;
+ if (result_out != NULL)
+ disp_result = &result;
+
+ // Wrap the parameters into an array of VARIANT structures.
+ internal::ScopedVariantArg disp_args[3];
+ hr = disp_args[3 - 1].Wrap(p1);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[3 - 2].Wrap(p2);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[3 - 3].Wrap(p3);
+ if (FAILED(hr))
+ return hr;
+
+ // Invoke the method.
+ DISPPARAMS disp_params = { disp_args, NULL, 3, 0 };
+ hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags,
+ &disp_params, disp_result, NULL, NULL);
+ if (FAILED(hr))
+ return hr;
+
+ // Unwrap the parameters.
+ disp_args[3 - 1].Unwrap(p1);
+ disp_args[3 - 2].Unwrap(p2);
+ disp_args[3 - 3].Unwrap(p3);
+
+ // Unwrap the return value.
+ if (result_out != NULL)
+ result.Unwrap(result_out);
+
+ return S_OK;
+}
+
+template <typename P1, typename P2, typename P3, typename P4>
+HRESULT Invoke(IDispatch* object,
+ LPOLESTR name,
+ WORD flags,
+ const P1& p1,
+ const P2& p2,
+ const P3& p3,
+ const P4& p4,
+ VARIANT* const & result_out) {
+ // Retrieve the ID of the method to be called.
+ DISPID disp_id;
+ HRESULT hr = object->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT,
+ &disp_id);
+ if (FAILED(hr))
+ return hr;
+
+ // Request the return value if asked by the caller.
+ internal::ScopedVariantArg result;
+ VARIANT* disp_result = NULL;
+ if (result_out != NULL)
+ disp_result = &result;
+
+ // Wrap the parameters into an array of VARIANT structures.
+ internal::ScopedVariantArg disp_args[4];
+ hr = disp_args[4 - 1].Wrap(p1);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[4 - 2].Wrap(p2);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[4 - 3].Wrap(p3);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[4 - 4].Wrap(p4);
+ if (FAILED(hr))
+ return hr;
+
+ // Invoke the method.
+ DISPPARAMS disp_params = { disp_args, NULL, 4, 0 };
+ hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags,
+ &disp_params, disp_result, NULL, NULL);
+ if (FAILED(hr))
+ return hr;
+
+ // Unwrap the parameters.
+ disp_args[4 - 1].Unwrap(p1);
+ disp_args[4 - 2].Unwrap(p2);
+ disp_args[4 - 3].Unwrap(p3);
+ disp_args[4 - 4].Unwrap(p4);
+
+ // Unwrap the return value.
+ if (result_out != NULL)
+ result.Unwrap(result_out);
+
+ return S_OK;
+}
+
+template <typename P1, typename P2, typename P3, typename P4, typename P5>
+HRESULT Invoke(IDispatch* object,
+ LPOLESTR name,
+ WORD flags,
+ const P1& p1,
+ const P2& p2,
+ const P3& p3,
+ const P4& p4,
+ const P5& p5,
+ VARIANT* const & result_out) {
+ // Retrieve the ID of the method to be called.
+ DISPID disp_id;
+ HRESULT hr = object->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT,
+ &disp_id);
+ if (FAILED(hr))
+ return hr;
+
+ // Request the return value if asked by the caller.
+ internal::ScopedVariantArg result;
+ VARIANT* disp_result = NULL;
+ if (result_out != NULL)
+ disp_result = &result;
+
+ // Wrap the parameters into an array of VARIANT structures.
+ internal::ScopedVariantArg disp_args[5];
+ hr = disp_args[5 - 1].Wrap(p1);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[5 - 2].Wrap(p2);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[5 - 3].Wrap(p3);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[5 - 4].Wrap(p4);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[5 - 5].Wrap(p5);
+ if (FAILED(hr))
+ return hr;
+
+ // Invoke the method.
+ DISPPARAMS disp_params = { disp_args, NULL, 5, 0 };
+ hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags,
+ &disp_params, disp_result, NULL, NULL);
+ if (FAILED(hr))
+ return hr;
+
+ // Unwrap the parameters.
+ disp_args[5 - 1].Unwrap(p1);
+ disp_args[5 - 2].Unwrap(p2);
+ disp_args[5 - 3].Unwrap(p3);
+ disp_args[5 - 4].Unwrap(p4);
+ disp_args[5 - 5].Unwrap(p5);
+
+ // Unwrap the return value.
+ if (result_out != NULL)
+ result.Unwrap(result_out);
+
+ return S_OK;
+}
+
+template <typename P1, typename P2, typename P3, typename P4, typename P5,
+ typename P6>
+HRESULT Invoke(IDispatch* object,
+ LPOLESTR name,
+ WORD flags,
+ const P1& p1,
+ const P2& p2,
+ const P3& p3,
+ const P4& p4,
+ const P5& p5,
+ const P6& p6,
+ VARIANT* const & result_out) {
+ // Retrieve the ID of the method to be called.
+ DISPID disp_id;
+ HRESULT hr = object->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT,
+ &disp_id);
+ if (FAILED(hr))
+ return hr;
+
+ // Request the return value if asked by the caller.
+ internal::ScopedVariantArg result;
+ VARIANT* disp_result = NULL;
+ if (result_out != NULL)
+ disp_result = &result;
+
+ // Wrap the parameters into an array of VARIANT structures.
+ internal::ScopedVariantArg disp_args[6];
+ hr = disp_args[6 - 1].Wrap(p1);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[6 - 2].Wrap(p2);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[6 - 3].Wrap(p3);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[6 - 4].Wrap(p4);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[6 - 5].Wrap(p5);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[6 - 6].Wrap(p6);
+ if (FAILED(hr))
+ return hr;
+
+ // Invoke the method.
+ DISPPARAMS disp_params = { disp_args, NULL, 6, 0 };
+ hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags,
+ &disp_params, disp_result, NULL, NULL);
+ if (FAILED(hr))
+ return hr;
+
+ // Unwrap the parameters.
+ disp_args[6 - 1].Unwrap(p1);
+ disp_args[6 - 2].Unwrap(p2);
+ disp_args[6 - 3].Unwrap(p3);
+ disp_args[6 - 4].Unwrap(p4);
+ disp_args[6 - 5].Unwrap(p5);
+ disp_args[6 - 6].Unwrap(p6);
+
+ // Unwrap the return value.
+ if (result_out != NULL)
+ result.Unwrap(result_out);
+
+ return S_OK;
+}
+
+template <typename P1, typename P2, typename P3, typename P4, typename P5,
+ typename P6, typename P7>
+HRESULT Invoke(IDispatch* object,
+ LPOLESTR name,
+ WORD flags,
+ const P1& p1,
+ const P2& p2,
+ const P3& p3,
+ const P4& p4,
+ const P5& p5,
+ const P6& p6,
+ const P7& p7,
+ VARIANT* const & result_out) {
+ // Retrieve the ID of the method to be called.
+ DISPID disp_id;
+ HRESULT hr = object->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT,
+ &disp_id);
+ if (FAILED(hr))
+ return hr;
+
+ // Request the return value if asked by the caller.
+ internal::ScopedVariantArg result;
+ VARIANT* disp_result = NULL;
+ if (result_out != NULL)
+ disp_result = &result;
+
+ // Wrap the parameters into an array of VARIANT structures.
+ internal::ScopedVariantArg disp_args[7];
+ hr = disp_args[7 - 1].Wrap(p1);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[7 - 2].Wrap(p2);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[7 - 3].Wrap(p3);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[7 - 4].Wrap(p4);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[7 - 5].Wrap(p5);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[7 - 6].Wrap(p6);
+ if (FAILED(hr))
+ return hr;
+ hr = disp_args[7 - 7].Wrap(p7);
+ if (FAILED(hr))
+ return hr;
+
+ // Invoke the method.
+ DISPPARAMS disp_params = { disp_args, NULL, 7, 0 };
+ hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags,
+ &disp_params, disp_result, NULL, NULL);
+ if (FAILED(hr))
+ return hr;
+
+ // Unwrap the parameters.
+ disp_args[7 - 1].Unwrap(p1);
+ disp_args[7 - 2].Unwrap(p2);
+ disp_args[7 - 3].Unwrap(p3);
+ disp_args[7 - 4].Unwrap(p4);
+ disp_args[7 - 5].Unwrap(p5);
+ disp_args[7 - 6].Unwrap(p6);
+ disp_args[7 - 7].Unwrap(p7);
+
+ // Unwrap the return value.
+ if (result_out != NULL)
+ result.Unwrap(result_out);
+
+ return S_OK;
+}
+
+} // namespace dispatch
+
+} // namespace remoting
+
+#endif // REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_
diff --git a/remoting/base/dispatch_win.h.pump b/remoting/base/dispatch_win.h.pump
new file mode 100644
index 0000000..fd9ad1d
--- /dev/null
+++ b/remoting/base/dispatch_win.h.pump
@@ -0,0 +1,180 @@
+$$ This is a pump file for generating file templates. Pump is a python
+$$ script that is part of the Google Test suite of utilities. Description
+$$ can be found here:
+$$
+$$ http://code.google.com/p/googletest/wiki/PumpManual
+
+$$ MAX_ARITY controls the number of arguments that dispatch::Invoke() supports.
+$$ It is choosen to match the number of arguments base::Bind() supports.
+$var MAX_ARITY = 7
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_
+#define REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_
+
+#include <oaidl.h>
+
+#include "base/basictypes.h"
+#include "base/template_util.h"
+#include "base/win/scoped_variant.h"
+
+namespace remoting {
+
+namespace dispatch {
+
+namespace internal {
+
+// A helper wrapper for |VARIANTARG| that is used to pass parameters to and from
+// IDispatch::Invoke(). The latter accepts parameters as an array of
+// |VARIANTARG| structures. The calling convention is:
+// - [in] parameters are initialized and freed if needed by the caller.
+// - [out] parameters are initialized by IDispatch::Invoke(). It is up to
+// the caller to free leakable variants (such as VT_DISPATCH).
+// - [in] [out] parameters are combination of both: the caller initializes
+// them before the call and the callee assigns new values correctly
+// freeing leakable variants.
+//
+// Using |ScopedVariantArg| instead of naked |VARIANTARG| ensures that
+// the resources allocated during the call will be properly freed. It also
+// provides wraping methods that convert between C++ types and VARIANTs.
+// The current convention is:
+// - constant references are considered input parameters.
+// - pointers to non-constant objects are considered output parameters.
+// - [in] [out] parameters are not supported.
+//
+// It must be possible to cast a pointer to an array of |ScopedVariantArg| to
+// a pointer to an array of |VARIANTARG| structures.
+class ScopedVariantArg : public VARIANTARG {
+ public:
+ ScopedVariantArg() {
+ vt = VT_EMPTY;
+ }
+
+ ~ScopedVariantArg() {
+ VariantClear(this);
+ }
+
+ // Wrap() routines pack the input parameters into VARIANTARG structures so
+ // that they can be passed to IDispatch::Invoke.
+
+ HRESULT Wrap(const VARIANT& param) {
+ return VariantCopy(this, &param);
+ }
+
+ HRESULT Wrap(VARIANT* const & param) {
+ // Do nothing for an [out] parameter.
+ return S_OK;
+ }
+
+ // Unwrap() routines unpack the output parameters from VARIANTARG structures
+ // to the locations specified by the caller.
+
+ void Unwrap(const VARIANT& param_out) {
+ // Do nothing for an [in] parameter.
+ }
+
+ void Unwrap(VARIANT* const & param_out) {
+ *param_out = *this;
+ vt = VT_EMPTY;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedVariantArg);
+};
+
+// Make sure the layouts of |VARIANTARG| and |ScopedVariantArg| are identical.
+COMPILE_ASSERT(sizeof(ScopedVariantArg) == sizeof(VARIANTARG),
+ scoped_variant_arg_should_not_add_data_members);
+
+} // namespace internal
+
+// Invoke() is a convenience wrapper for IDispatch::Invoke. It takes care of
+// calling the desired method by its ID and implements logic for passing
+// a variable number of in/out parameters to the called method.
+//
+// Current limitations:
+// - in_out parameters are not supported.
+// - more than $(MAX_ARITY) parameters are not supported.
+// - the method ID cannot be cached and reused.
+// - VARIANT is the only supported parameter type at the moment.
+$range ARITY 0..MAX_ARITY
+$for ARITY [[
+$range ARG 1..ARITY
+
+
+$if ARITY > 0 [[template <$for ARG , [[typename P$(ARG)]]>]]
+
+HRESULT Invoke(IDispatch* object,
+ LPOLESTR name,
+ WORD flags,
+$for ARG [[
+
+ const P$(ARG)& p$(ARG),
+]]
+
+ VARIANT* const & result_out) {
+ // Retrieve the ID of the method to be called.
+ DISPID disp_id;
+ HRESULT hr = object->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT,
+ &disp_id);
+ if (FAILED(hr))
+ return hr;
+
+ // Request the return value if asked by the caller.
+ internal::ScopedVariantArg result;
+ VARIANT* disp_result = NULL;
+ if (result_out != NULL)
+ disp_result = &result;
+
+$if ARITY > 0 [[
+
+ // Wrap the parameters into an array of VARIANT structures.
+ internal::ScopedVariantArg disp_args[$(ARITY)];
+$for ARG [[
+
+ hr = disp_args[$(ARITY) - $(ARG)].Wrap(p$(ARG));
+ if (FAILED(hr))
+ return hr;
+]]
+]]
+
+
+ // Invoke the method.
+
+$if ARITY > 0 [[
+ DISPPARAMS disp_params = { disp_args, NULL, $(ARITY), 0 };
+]] $else [[
+ DISPPARAMS disp_params = { NULL, NULL, 0, 0 };
+]]
+
+ hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags,
+ &disp_params, disp_result, NULL, NULL);
+ if (FAILED(hr))
+ return hr;
+
+$if ARITY > 0 [[
+
+ // Unwrap the parameters.
+$for ARG [[
+
+ disp_args[$(ARITY) - $(ARG)].Unwrap(p$(ARG));
+]]
+]]
+
+
+ // Unwrap the return value.
+ if (result_out != NULL)
+ result.Unwrap(result_out);
+
+ return S_OK;
+}
+
+]]
+
+} // namespace dispatch
+
+} // namespace remoting
+
+#endif // REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_
diff --git a/remoting/host/plugin/daemon_installer_win.cc b/remoting/host/plugin/daemon_installer_win.cc
index 6eedd96..35cfea7 100644
--- a/remoting/host/plugin/daemon_installer_win.cc
+++ b/remoting/host/plugin/daemon_installer_win.cc
@@ -19,6 +19,8 @@
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_handle.h"
+#include "base/win/scoped_variant.h"
+#include "remoting/base/dispatch_win.h"
namespace omaha {
#include "google_update/google_update_idl.h"
@@ -26,6 +28,7 @@ namespace omaha {
using base::win::ScopedBstr;
using base::win::ScopedComPtr;
+using base::win::ScopedVariant;
namespace {
@@ -65,7 +68,7 @@ namespace remoting {
// per-machine Omaha instance.
class DaemonComInstallerWin : public DaemonInstallerWin {
public:
- DaemonComInstallerWin(const ScopedComPtr<omaha::IGoogleUpdate3Web>& update3,
+ DaemonComInstallerWin(const ScopedComPtr<IDispatch>& update3,
const CompletionCallback& done);
// DaemonInstallerWin implementation.
@@ -77,9 +80,9 @@ class DaemonComInstallerWin : public DaemonInstallerWin {
void PollInstallationStatus();
// Omaha interfaces.
- ScopedComPtr<omaha::IAppWeb> app_;
- ScopedComPtr<omaha::IAppBundleWeb> bundle_;
- ScopedComPtr<omaha::IGoogleUpdate3Web> update3_;
+ ScopedVariant app_;
+ ScopedVariant bundle_;
+ ScopedComPtr<IDispatch> update3_;
base::Timer polling_timer_;
};
@@ -108,7 +111,7 @@ class DaemonCommandLineInstallerWin
};
DaemonComInstallerWin::DaemonComInstallerWin(
- const ScopedComPtr<omaha::IGoogleUpdate3Web>& update3,
+ const ScopedComPtr<IDispatch>& update3,
const CompletionCallback& done)
: DaemonInstallerWin(done),
update3_(update3),
@@ -123,52 +126,50 @@ DaemonComInstallerWin::DaemonComInstallerWin(
void DaemonComInstallerWin::Install() {
// Create an app bundle.
- ScopedComPtr<IDispatch> dispatch;
- HRESULT hr = update3_->createAppBundleWeb(dispatch.Receive());
+ HRESULT hr = dispatch::Invoke(update3_.get(), L"createAppBundleWeb",
+ DISPATCH_METHOD, bundle_.Receive());
if (FAILED(hr)) {
Done(hr);
return;
}
-
- hr = dispatch.QueryInterface(omaha::IID_IAppBundleWeb, bundle_.ReceiveVoid());
- if (FAILED(hr)) {
- Done(hr);
+ if (bundle_.type() != VT_DISPATCH) {
+ Done(DISP_E_TYPEMISMATCH);
return;
}
- hr = bundle_->initialize();
+ hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"initialize", DISPATCH_METHOD,
+ NULL);
if (FAILED(hr)) {
Done(hr);
return;
}
// Add Chromoting Host to the bundle.
- ScopedBstr appid(kOmahaAppid);
- ScopedBstr empty(kOmahaEmpty);
- ScopedBstr language(kOmahaLanguage);
- hr = bundle_->createApp(appid, empty, language, empty);
+ ScopedVariant appid(kOmahaAppid);
+ ScopedVariant empty(kOmahaEmpty);
+ ScopedVariant language(kOmahaLanguage);
+ hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"createApp", DISPATCH_METHOD,
+ appid, empty, language, empty, NULL);
if (FAILED(hr)) {
Done(hr);
return;
}
- hr = bundle_->checkForUpdate();
+ hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"checkForUpdate",
+ DISPATCH_METHOD, NULL);
if (FAILED(hr)) {
Done(hr);
return;
}
- dispatch.Release();
- hr = bundle_->get_appWeb(0, dispatch.Receive());
+ hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"appWeb",
+ DISPATCH_PROPERTYGET, ScopedVariant(0), app_.Receive());
if (FAILED(hr)) {
Done(hr);
return;
}
-
- hr = dispatch.QueryInterface(omaha::IID_IAppWeb,
- app_.ReceiveVoid());
- if (FAILED(hr)) {
- Done(hr);
+ if (app_.type() != VT_DISPATCH) {
+ Done(DISP_E_TYPEMISMATCH);
return;
}
@@ -181,30 +182,32 @@ void DaemonComInstallerWin::PollInstallationStatus() {
// N.B. The object underlying the ICurrentState interface has static data that
// does not get updated as the server state changes. To get the most "current"
// state, the currentState property needs to be queried again.
- ScopedComPtr<IDispatch> dispatch;
- HRESULT hr = app_->get_currentState(dispatch.Receive());
+ ScopedVariant current_state;
+ HRESULT hr = dispatch::Invoke(V_DISPATCH(&app_), L"currentState",
+ DISPATCH_PROPERTYGET, current_state.Receive());
if (FAILED(hr)) {
Done(hr);
return;
}
-
- ScopedComPtr<omaha::ICurrentState> current_state;
- hr = dispatch.QueryInterface(omaha::IID_ICurrentState,
- current_state.ReceiveVoid());
- if (FAILED(hr)) {
- Done(hr);
+ if (current_state.type() != VT_DISPATCH) {
+ Done(DISP_E_TYPEMISMATCH);
return;
}
- LONG state;
- hr = current_state->get_stateValue(&state);
+ ScopedVariant state;
+ hr = dispatch::Invoke(V_DISPATCH(&current_state), L"stateValue",
+ DISPATCH_PROPERTYGET, state.Receive());
if (FAILED(hr)) {
Done(hr);
return;
}
+ if (state.type() != VT_I4) {
+ Done(DISP_E_TYPEMISMATCH);
+ return;
+ }
// Perform state-specific actions.
- switch (state) {
+ switch (V_I4(&state)) {
case omaha::STATE_INIT:
case omaha::STATE_WAITING_TO_CHECK_FOR_UPDATE:
case omaha::STATE_CHECKING_FOR_UPDATE:
@@ -217,7 +220,8 @@ void DaemonComInstallerWin::PollInstallationStatus() {
break;
case omaha::STATE_UPDATE_AVAILABLE:
- hr = bundle_->download();
+ hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"download",
+ DISPATCH_METHOD, NULL);
if (FAILED(hr)) {
Done(hr);
return;
@@ -228,7 +232,8 @@ void DaemonComInstallerWin::PollInstallationStatus() {
case omaha::STATE_EXTRACTING:
case omaha::STATE_APPLYING_DIFFERENTIAL_PATCH:
case omaha::STATE_READY_TO_INSTALL:
- hr = bundle_->install();
+ hr = dispatch::Invoke(V_DISPATCH(&bundle_), L"install",
+ DISPATCH_METHOD, NULL);
if (FAILED(hr)) {
Done(hr);
return;
@@ -242,17 +247,23 @@ void DaemonComInstallerWin::PollInstallationStatus() {
return;
case omaha::STATE_ERROR: {
- HRESULT error_code;
- hr = current_state->get_errorCode(&error_code);
+ ScopedVariant error_code;
+ hr = dispatch::Invoke(V_DISPATCH(&current_state), L"errorCode",
+ DISPATCH_PROPERTYGET, error_code.Receive());
if (FAILED(hr)) {
- error_code = hr;
+ Done(hr);
+ return;
+ }
+ if (error_code.type() != VT_UI4) {
+ Done(DISP_E_TYPEMISMATCH);
+ return;
}
- Done(error_code);
+ Done(V_UI4(&error_code));
return;
}
default:
- LOG(ERROR) << "Unknown bundle state: " << state << ".";
+ LOG(ERROR) << "Unknown bundle state: " << V_I4(&state) << ".";
Done(E_FAIL);
return;
}
@@ -341,11 +352,11 @@ scoped_ptr<DaemonInstallerWin> DaemonInstallerWin::Create(
bind_options.hwnd = GetTopLevelWindow(window_handle);
bind_options.dwClassContext = CLSCTX_LOCAL_SERVER;
- ScopedComPtr<omaha::IGoogleUpdate3Web> update3;
+ ScopedComPtr<IDispatch> update3;
HRESULT result = ::CoGetObject(
kOmahaElevationMoniker,
&bind_options,
- omaha::IID_IGoogleUpdate3Web,
+ IID_IDispatch,
update3.ReceiveVoid());
if (SUCCEEDED(result)) {
// The machine instance of Omaha is available and we successfully passed
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 6a589bf..c38a301 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -875,6 +875,7 @@
'../third_party/npapi/npapi.gyp:npapi',
],
'sources': [
+ 'base/dispatch_win.h',
'host/branding.cc',
'host/branding.h',
'host/host_ui_resource.h',