| 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 if 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 marshaling 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 should 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 // Marshal() routines pack the input parameters into VARIANTARG structures so |
| 60 // that they can be passed to IDispatch::Invoke. |
| 61 HRESULT Marshal(const VARIANT& param) { |
| 62 return VariantCopy(this, ¶m); |
| 63 } |
| 64 |
| 65 HRESULT Marshal(VARIANT* const & param) { |
| 66 // Do nothing for an [out] parameter. |
| 67 return S_OK; |
| 68 } |
| 69 |
| 70 // Unmarshal() routines unpack the output parameter from VARIANTARG structures |
| 71 // to the locations specified by the caller. |
| 72 void Unmarshal(const VARIANT& param_out) { |
| 73 // Do nothing for an [in] parameter. |
| 74 } |
| 75 |
| 76 void Unmarshal(VARIANT* const & param_out) { |
| 77 *param_out = *this; |
| 78 vt = VT_EMPTY; |
| 79 } |
| 80 |
| 81 private: |
| 82 DISALLOW_COPY_AND_ASSIGN(ScopedVariantArg); |
| 83 }; |
| 84 |
| 85 // Make sure the layouts of |VARIANTARG| and |ScopedVariantArg| are identical. |
| 86 COMPILE_ASSERT(sizeof(ScopedVariantArg) == sizeof(VARIANTARG), |
| 87 scoped_variant_arg_should_not_add_data_members); |
| 88 |
| 89 } // namespace internal |
| 90 |
| 91 // Invoke() is a convenience wrapper for IDispatch::Invoke. It takes care of |
| 92 // calling the desired method by its ID and implements logic for passing |
| 93 // a variable number of in/out parameters to the called method. |
| 94 // |
| 95 // Current limitations: |
| 96 // - in_out parameters are not supported. |
| 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 |
| 104 |
| 105 $if ARITY > 0 [[template <$for ARG , [[typename P$(ARG)]]>]] |
| 106 |
| 107 HRESULT Invoke(IDispatch* object, |
| 108 LPOLESTR name, |
| 109 WORD flags, |
| 110 $for ARG [[ |
| 111 |
| 112 const P$(ARG)& p$(ARG), |
| 113 ]] |
| 114 |
| 115 VARIANT* const & result_out) { |
| 116 // Retrieve the ID of the method to be called. |
| 117 DISPID disp_id; |
| 118 HRESULT hr = object->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, |
| 119 &disp_id); |
| 120 if (FAILED(hr)) |
| 121 return hr; |
| 122 |
| 123 // Request the return value if asked by the caller. |
| 124 internal::ScopedVariantArg result; |
| 125 VARIANT* disp_result = NULL; |
| 126 if (result_out != NULL) |
| 127 disp_result = &result; |
| 128 |
| 129 $if ARITY > 0 [[ |
| 130 |
| 131 // Marshal the parameters into an array of VARIANT structures. |
| 132 internal::ScopedVariantArg disp_args[$(ARITY)]; |
| 133 $for ARG [[ |
| 134 |
| 135 hr = disp_args[$(ARITY) - $(ARG)].Marshal(p$(ARG)); |
| 136 if (FAILED(hr)) |
| 137 return hr; |
| 138 ]] |
| 139 ]] |
| 140 |
| 141 |
| 142 // Invoke the method. |
| 143 |
| 144 $if ARITY > 0 [[ |
| 145 DISPPARAMS disp_params = { disp_args, NULL, $(ARITY), 0 }; |
| 146 ]] $else [[ |
| 147 DISPPARAMS disp_params = { NULL, NULL, 0, 0 }; |
| 148 ]] |
| 149 |
| 150 hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags, |
| 151 &disp_params, disp_result, NULL, NULL); |
| 152 if (FAILED(hr)) |
| 153 return hr; |
| 154 |
| 155 $if ARITY > 0 [[ |
| 156 |
| 157 // Unmarshal the parameters. |
| 158 $for ARG [[ |
| 159 |
| 160 disp_args[$(ARITY) - $(ARG)].Unmarshal(p$(ARG)); |
| 161 ]] |
| 162 ]] |
| 163 |
| 164 |
| 165 // Unmarshal the return value. |
| 166 if (result_out != NULL) |
| 167 result.Unmarshal(result_out); |
| 168 |
| 169 return S_OK; |
| 170 } |
| 171 |
| 172 ]] |
| 173 |
| 174 } // namespace dispatch |
| 175 |
| 176 } // namespace remoting |
| 177 |
| 178 #endif // REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_ |
| OLD | NEW |