dispatch_win.h.pump 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. $$ This is a pump file for generating file templates. Pump is a python
  2. $$ script that is part of the Google Test suite of utilities.
  3. $$ MAX_ARITY controls the number of arguments that dispatch::Invoke() supports.
  4. $$ It is choosen to match the number of arguments base::BindOnce() supports.
  5. $var MAX_ARITY = 7
  6. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file.
  9. #ifndef REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_
  10. #define REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_
  11. #include <oaidl.h>
  12. #include "base/basictypes.h"
  13. #include "base/template_util.h"
  14. #include "base/win/scoped_variant.h"
  15. namespace remoting {
  16. namespace dispatch {
  17. namespace internal {
  18. // A helper wrapper for |VARIANTARG| that is used to pass parameters to and from
  19. // IDispatch::Invoke(). The latter accepts parameters as an array of
  20. // |VARIANTARG| structures. The calling convention of IDispatch::Invoke() is:
  21. // - [in] parameters are initialized and freed if needed by the caller.
  22. // - [out] parameters are initialized by IDispatch::Invoke(). It is up to
  23. // the caller to free leakable variants (such as VT_DISPATCH).
  24. // - [in] [out] parameters are combination of both: the caller initializes
  25. // them before the call and the callee assigns new values correctly
  26. // freeing leakable variants.
  27. //
  28. // Using |ScopedVariantArg| instead of naked |VARIANTARG| ensures that
  29. // the resources allocated during the call will be properly freed. It also
  30. // provides wrapping methods that convert between C++ types and VARIANTs.
  31. // At the moment the only supported parameter type is |VARIANT| (or
  32. // |VARIANTARG|).
  33. //
  34. // It must be possible to cast a pointer to an array of |ScopedVariantArg| to
  35. // a pointer to an array of |VARIANTARG| structures.
  36. class ScopedVariantArg : public VARIANTARG {
  37. public:
  38. ScopedVariantArg() {
  39. vt = VT_EMPTY;
  40. }
  41. ScopedVariantArg(const ScopedVariantArg&) = delete;
  42. ScopedVariantArg& operator=(const ScopedVariantArg&) = delete;
  43. ~ScopedVariantArg() {
  44. VariantClear(this);
  45. }
  46. // Wrap() routines pack the input parameters into VARIANTARG structures so
  47. // that they can be passed to IDispatch::Invoke.
  48. HRESULT Wrap(const VARIANT& param) {
  49. DCHECK(vt == VT_EMPTY);
  50. return VariantCopy(this, &param);
  51. }
  52. HRESULT Wrap(VARIANT* const & param) {
  53. DCHECK(vt == VT_EMPTY);
  54. // Make the input value of an [in] [out] parameter visible to
  55. // IDispatch::Invoke().
  56. //
  57. // N.B. We treat both [out] and [in] [out] parameters as [in] [out]. In
  58. // other words the caller is always responsible for initializing and freeing
  59. // [out] and [in] [out] parameters.
  60. Swap(param);
  61. return S_OK;
  62. }
  63. // Unwrap() routines unpack the output parameters from VARIANTARG structures
  64. // to the locations specified by the caller.
  65. void Unwrap(const VARIANT& param_out) {
  66. // Do nothing for an [in] parameter.
  67. }
  68. void Unwrap(VARIANT* const & param_out) {
  69. // Return the output value of an [in] [out] parameter to the caller.
  70. Swap(param_out);
  71. }
  72. private:
  73. // Exchanges the value (and ownership) of the passed VARIANT with the one
  74. // wrapped by |ScopedVariantArg|.
  75. void Swap(VARIANT* other) {
  76. VARIANT temp = *other;
  77. *other = *this;
  78. *static_cast<VARIANTARG*>(this) = temp;
  79. }
  80. };
  81. // Make sure the layouts of |VARIANTARG| and |ScopedVariantArg| are identical.
  82. static_assert(sizeof(ScopedVariantArg) == sizeof(VARIANTARG),
  83. "scoped variant arg should not add data members");
  84. } // namespace internal
  85. // Invoke() is a convenience wrapper for IDispatch::Invoke. It takes care of
  86. // calling the desired method by its ID and implements logic for passing
  87. // a variable number of in/out parameters to the called method.
  88. //
  89. // The calling convention is:
  90. // - [in] parameters are passsed as a constant reference or by value.
  91. // - [out] and [in] [out] parameters are passed by pointer. The pointed value
  92. // is overwritten when the function returns. The pointed-to value must
  93. // be initialized before the call, and will be replaced when it returns.
  94. // [out] parameters may be initialized to VT_EMPTY.
  95. //
  96. // Current limitations:
  97. // - more than $(MAX_ARITY) parameters are not supported.
  98. // - the method ID cannot be cached and reused.
  99. // - VARIANT is the only supported parameter type at the moment.
  100. $range ARITY 0..MAX_ARITY
  101. $for ARITY [[
  102. $range ARG 1..ARITY
  103. $if ARITY > 0 [[template <$for ARG , [[typename P$(ARG)]]>]]
  104. HRESULT Invoke(IDispatch* object,
  105. LPCOLESTR const_name,
  106. WORD flags,
  107. $for ARG [[
  108. const P$(ARG)& p$(ARG),
  109. ]]
  110. VARIANT* const & result_out) {
  111. // Retrieve the ID of the method to be called.
  112. DISPID disp_id;
  113. LPOLESTR name = const_cast<LPOLESTR>(const_name);
  114. HRESULT hr = object->GetIDsOfNames(
  115. IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &disp_id);
  116. if (FAILED(hr))
  117. return hr;
  118. // Request the return value if asked by the caller.
  119. internal::ScopedVariantArg result;
  120. VARIANT* disp_result = NULL;
  121. if (result_out != NULL)
  122. disp_result = &result;
  123. $if ARITY > 0 [[
  124. // Wrap the parameters into an array of VARIANT structures.
  125. internal::ScopedVariantArg disp_args[$(ARITY)];
  126. $for ARG [[
  127. hr = disp_args[$(ARITY) - $(ARG)].Wrap(p$(ARG));
  128. if (FAILED(hr))
  129. return hr;
  130. ]]
  131. ]]
  132. // Invoke the method passing the parameters via the DISPPARAMS structure.
  133. // DISPATCH_PROPERTYPUT and DISPATCH_PROPERTYPUTREF require the parameter of
  134. // the property setter to be named, so |cNamedArgs| and |rgdispidNamedArgs|
  135. // structure members should be initialized.
  136. $if ARITY > 0 [[
  137. DISPPARAMS disp_params = { disp_args, NULL, $(ARITY), 0 };
  138. ]] $else [[
  139. DISPPARAMS disp_params = { NULL, NULL, 0, 0 };
  140. ]]
  141. DISPID dispid_named = DISPID_PROPERTYPUT;
  142. if (flags == DISPATCH_PROPERTYPUT || flags == DISPATCH_PROPERTYPUTREF) {
  143. disp_params.cNamedArgs = 1;
  144. disp_params.rgdispidNamedArgs = &dispid_named;
  145. }
  146. hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags,
  147. &disp_params, disp_result, NULL, NULL);
  148. if (FAILED(hr))
  149. return hr;
  150. $if ARITY > 0 [[
  151. // Unwrap the parameters.
  152. $for ARG [[
  153. disp_args[$(ARITY) - $(ARG)].Unwrap(p$(ARG));
  154. ]]
  155. ]]
  156. // Unwrap the return value.
  157. if (result_out != NULL) {
  158. result.Unwrap(result_out);
  159. }
  160. return S_OK;
  161. }
  162. ]]
  163. } // namespace dispatch
  164. } // namespace remoting
  165. #endif // REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_