| OLD | NEW |
| (Empty) | |
| 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. Description |
| 3 $$ can be found here: |
| 4 $$ |
| 5 $$ http://code.google.com/p/googletest/wiki/PumpManual |
| 6 |
| 7 $$ MAX_ARITY controls the number of arguments that dispatch::Invoke() supports. |
| 8 $$ It is choosen to match the number of arguments base::Bind() supports. |
| 9 $var MAX_ARITY = 7 |
| 10 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 11 // Use of this source code is governed by a BSD-style license that can be |
| 12 // found in the LICENSE file. |
| 13 |
| 14 #ifndef REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_ |
| 15 #define REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_ |
| 16 |
| 17 #include <oaidl.h> |
| 18 |
| 19 #include "base/basictypes.h" |
| 20 #include "base/template_util.h" |
| 21 #include "base/win/scoped_variant.h" |
| 22 |
| 23 namespace remoting { |
| 24 |
| 25 namespace dispatch { |
| 26 |
| 27 namespace internal { |
| 28 |
| 29 // A helper wrapper for |VARIANTARG| that is used to pass parameters to and from |
| 30 // IDispatch::Invoke(). The latter accepts parameters as an array of |
| 31 // |VARIANTARG| structures. The calling convention is: |
| 32 // - [in] parameters are initialized and freed if needed by the caller. |
| 33 // - [out] parameters are initialized by IDispatch::Invoke(). It is up to |
| 34 // the caller to free leakable variants (such as VT_DISPATCH). |
| 35 // - [in] [out] parameters are combination of both: the caller initializes |
| 36 // them before the call and the callee assigns new values correctly |
| 37 // freeing leakable variants. |
| 38 // |
| 39 // Using |ScopedVariantArg| instead of naked |VARIANTARG| ensures that |
| 40 // the resources allocated during the call will be properly freed. It also |
| 41 // provides wraping methods that convert between C++ types and VARIANTs. |
| 42 // The current convention is: |
| 43 // - constant references are considered input parameters. |
| 44 // - pointers to non-constant objects are considered output parameters. |
| 45 // - [in] [out] parameters are not supported. |
| 46 // |
| 47 // It must be possible to cast a pointer to an array of |ScopedVariantArg| to |
| 48 // a pointer to an array of |VARIANTARG| structures. |
| 49 class ScopedVariantArg : public VARIANTARG { |
| 50 public: |
| 51 ScopedVariantArg() { |
| 52 vt = VT_EMPTY; |
| 53 } |
| 54 |
| 55 ~ScopedVariantArg() { |
| 56 VariantClear(this); |
| 57 } |
| 58 |
| 59 // Wrap() routines pack the input parameters into VARIANTARG structures so |
| 60 // that they can be passed to IDispatch::Invoke. |
| 61 |
| 62 HRESULT Wrap(const VARIANT& param) { |
| 63 return VariantCopy(this, ¶m); |
| 64 } |
| 65 |
| 66 HRESULT Wrap(VARIANT* const & param) { |
| 67 // Do nothing for an [out] parameter. |
| 68 return S_OK; |
| 69 } |
| 70 |
| 71 // Unwrap() routines unpack the output parameters from VARIANTARG structures |
| 72 // to the locations specified by the caller. |
| 73 |
| 74 void Unwrap(const VARIANT& param_out) { |
| 75 // Do nothing for an [in] parameter. |
| 76 } |
| 77 |
| 78 void Unwrap(VARIANT* const & param_out) { |
| 79 *param_out = *this; |
| 80 vt = VT_EMPTY; |
| 81 } |
| 82 |
| 83 private: |
| 84 DISALLOW_COPY_AND_ASSIGN(ScopedVariantArg); |
| 85 }; |
| 86 |
| 87 // Make sure the layouts of |VARIANTARG| and |ScopedVariantArg| are identical. |
| 88 COMPILE_ASSERT(sizeof(ScopedVariantArg) == sizeof(VARIANTARG), |
| 89 scoped_variant_arg_should_not_add_data_members); |
| 90 |
| 91 } // namespace internal |
| 92 |
| 93 // Invoke() is a convenience wrapper for IDispatch::Invoke. It takes care of |
| 94 // calling the desired method by its ID and implements logic for passing |
| 95 // a variable number of in/out parameters to the called method. |
| 96 // |
| 97 // Current limitations: |
| 98 // - in_out parameters are not supported. |
| 99 // - more than $(MAX_ARITY) parameters are not supported. |
| 100 // - the method ID cannot be cached and reused. |
| 101 // - VARIANT is the only supported parameter type at the moment. |
| 102 $range ARITY 0..MAX_ARITY |
| 103 $for ARITY [[ |
| 104 $range ARG 1..ARITY |
| 105 |
| 106 |
| 107 $if ARITY > 0 [[template <$for ARG , [[typename P$(ARG)]]>]] |
| 108 |
| 109 HRESULT Invoke(IDispatch* object, |
| 110 LPOLESTR name, |
| 111 WORD flags, |
| 112 $for ARG [[ |
| 113 |
| 114 const P$(ARG)& p$(ARG), |
| 115 ]] |
| 116 |
| 117 VARIANT* const & result_out) { |
| 118 // Retrieve the ID of the method to be called. |
| 119 DISPID disp_id; |
| 120 HRESULT hr = object->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, |
| 121 &disp_id); |
| 122 if (FAILED(hr)) |
| 123 return hr; |
| 124 |
| 125 // Request the return value if asked by the caller. |
| 126 internal::ScopedVariantArg result; |
| 127 VARIANT* disp_result = NULL; |
| 128 if (result_out != NULL) |
| 129 disp_result = &result; |
| 130 |
| 131 $if ARITY > 0 [[ |
| 132 |
| 133 // Wrap the parameters into an array of VARIANT structures. |
| 134 internal::ScopedVariantArg disp_args[$(ARITY)]; |
| 135 $for ARG [[ |
| 136 |
| 137 hr = disp_args[$(ARITY) - $(ARG)].Wrap(p$(ARG)); |
| 138 if (FAILED(hr)) |
| 139 return hr; |
| 140 ]] |
| 141 ]] |
| 142 |
| 143 |
| 144 // Invoke the method. |
| 145 |
| 146 $if ARITY > 0 [[ |
| 147 DISPPARAMS disp_params = { disp_args, NULL, $(ARITY), 0 }; |
| 148 ]] $else [[ |
| 149 DISPPARAMS disp_params = { NULL, NULL, 0, 0 }; |
| 150 ]] |
| 151 |
| 152 hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags, |
| 153 &disp_params, disp_result, NULL, NULL); |
| 154 if (FAILED(hr)) |
| 155 return hr; |
| 156 |
| 157 $if ARITY > 0 [[ |
| 158 |
| 159 // Unwrap the parameters. |
| 160 $for ARG [[ |
| 161 |
| 162 disp_args[$(ARITY) - $(ARG)].Unwrap(p$(ARG)); |
| 163 ]] |
| 164 ]] |
| 165 |
| 166 |
| 167 // Unwrap the return value. |
| 168 if (result_out != NULL) |
| 169 result.Unwrap(result_out); |
| 170 |
| 171 return S_OK; |
| 172 } |
| 173 |
| 174 ]] |
| 175 |
| 176 } // namespace dispatch |
| 177 |
| 178 } // namespace remoting |
| 179 |
| 180 #endif // REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_ |
| OLD | NEW |