123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- $$ This is a pump file for generating file templates. Pump is a python
- $$ script that is part of the Google Test suite of utilities.
- $$ MAX_ARITY controls the number of arguments that dispatch::Invoke() supports.
- $$ It is choosen to match the number of arguments base::BindOnce() 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 of IDispatch::Invoke() 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 wrapping methods that convert between C++ types and VARIANTs.
- // At the moment the only supported parameter type is |VARIANT| (or
- // |VARIANTARG|).
- //
- // 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(const ScopedVariantArg&) = delete;
- ScopedVariantArg& operator=(const ScopedVariantArg&) = delete;
- ~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) {
- DCHECK(vt == VT_EMPTY);
- return VariantCopy(this, ¶m);
- }
- HRESULT Wrap(VARIANT* const & param) {
- DCHECK(vt == VT_EMPTY);
- // Make the input value of an [in] [out] parameter visible to
- // IDispatch::Invoke().
- //
- // N.B. We treat both [out] and [in] [out] parameters as [in] [out]. In
- // other words the caller is always responsible for initializing and freeing
- // [out] and [in] [out] parameters.
- Swap(param);
- 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) {
- // Return the output value of an [in] [out] parameter to the caller.
- Swap(param_out);
- }
- private:
- // Exchanges the value (and ownership) of the passed VARIANT with the one
- // wrapped by |ScopedVariantArg|.
- void Swap(VARIANT* other) {
- VARIANT temp = *other;
- *other = *this;
- *static_cast<VARIANTARG*>(this) = temp;
- }
- };
- // Make sure the layouts of |VARIANTARG| and |ScopedVariantArg| are identical.
- static_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.
- //
- // The calling convention is:
- // - [in] parameters are passsed as a constant reference or by value.
- // - [out] and [in] [out] parameters are passed by pointer. The pointed value
- // is overwritten when the function returns. The pointed-to value must
- // be initialized before the call, and will be replaced when it returns.
- // [out] parameters may be initialized to VT_EMPTY.
- //
- // Current limitations:
- // - 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,
- LPCOLESTR const_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;
- LPOLESTR name = const_cast<LPOLESTR>(const_name);
- 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 passing the parameters via the DISPPARAMS structure.
- // DISPATCH_PROPERTYPUT and DISPATCH_PROPERTYPUTREF require the parameter of
- // the property setter to be named, so |cNamedArgs| and |rgdispidNamedArgs|
- // structure members should be initialized.
- $if ARITY > 0 [[
- DISPPARAMS disp_params = { disp_args, NULL, $(ARITY), 0 };
- ]] $else [[
- DISPPARAMS disp_params = { NULL, NULL, 0, 0 };
- ]]
- DISPID dispid_named = DISPID_PROPERTYPUT;
- if (flags == DISPATCH_PROPERTYPUT || flags == DISPATCH_PROPERTYPUTREF) {
- disp_params.cNamedArgs = 1;
- disp_params.rgdispidNamedArgs = &dispid_named;
- }
- 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_
|