Make multiple-connections.html less aggressive.
[chromium-blink-merge.git] / remoting / base / dispatch_win.h.pump
blob31c34a5b634827a191f403f4b8dc141f9ac3aedb
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
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.
14 #ifndef REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_
15 #define REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_
17 #include <oaidl.h>
19 #include "base/basictypes.h"
20 #include "base/template_util.h"
21 #include "base/win/scoped_variant.h"
23 namespace remoting {
25 namespace dispatch {
27 namespace internal {
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 of IDispatch::Invoke() 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.
39 // Using |ScopedVariantArg| instead of naked |VARIANTARG| ensures that
40 // the resources allocated during the call will be properly freed. It also
41 // provides wrapping methods that convert between C++ types and VARIANTs.
42 // At the moment the only supported parameter type is |VARIANT| (or
43 // |VARIANTARG|).
45 // It must be possible to cast a pointer to an array of |ScopedVariantArg| to
46 // a pointer to an array of |VARIANTARG| structures.
47 class ScopedVariantArg : public VARIANTARG {
48  public:
49   ScopedVariantArg() {
50     vt = VT_EMPTY;
51   }
53   ~ScopedVariantArg() {
54     VariantClear(this);
55   }
57   // Wrap() routines pack the input parameters into VARIANTARG structures so
58   // that they can be passed to IDispatch::Invoke.
60   HRESULT Wrap(const VARIANT& param) {
61     DCHECK(vt == VT_EMPTY);
62     return VariantCopy(this, &param);
63   }
65   HRESULT Wrap(VARIANT* const & param) {
66     DCHECK(vt == VT_EMPTY);
68     // Make the input value of an [in] [out] parameter visible to
69     // IDispatch::Invoke().
70     //
71     // N.B. We treat both [out] and [in] [out] parameters as [in] [out]. In
72     // other words the caller is always responsible for initializing and freeing
73     // [out] and [in] [out] parameters.
74     Swap(param);
75     return S_OK;
76   }
78   // Unwrap() routines unpack the output parameters from VARIANTARG structures
79   // to the locations specified by the caller.
81   void Unwrap(const VARIANT& param_out) {
82     // Do nothing for an [in] parameter.
83   }
85   void Unwrap(VARIANT* const & param_out) {
86     // Return the output value of an [in] [out] parameter to the caller.
87     Swap(param_out);
88   }
90  private:
91   // Exchanges the value (and ownership) of the passed VARIANT with the one
92   // wrapped by |ScopedVariantArg|.
93   void Swap(VARIANT* other) {
94     VARIANT temp = *other;
95     *other = *this;
96     *static_cast<VARIANTARG*>(this) = temp;
97   }
99   DISALLOW_COPY_AND_ASSIGN(ScopedVariantArg);
102 // Make sure the layouts of |VARIANTARG| and |ScopedVariantArg| are identical.
103 static_assert(sizeof(ScopedVariantArg) == sizeof(VARIANTARG),
104               "scoped variant arg should not add data members");
106 }  // namespace internal
108 // Invoke() is a convenience wrapper for IDispatch::Invoke. It takes care of
109 // calling the desired method by its ID and implements logic for passing
110 // a variable number of in/out parameters to the called method.
112 // The calling convention is:
113 //   - [in] parameters are passsed as a constant reference or by value.
114 //   - [out] and [in] [out] parameters are passed by pointer. The pointed value
115 //         is overwritten when the function returns. The pointed-to value must
116 //         be initialized before the call, and will be replaced when it returns.
117 //         [out] parameters may be initialized to VT_EMPTY.
119 // Current limitations:
120 //   - more than $(MAX_ARITY) parameters are not supported.
121 //   - the method ID cannot be cached and reused.
122 //   - VARIANT is the only supported parameter type at the moment.
123 $range ARITY 0..MAX_ARITY
124 $for ARITY [[
125 $range ARG 1..ARITY
128 $if ARITY > 0 [[template <$for ARG , [[typename P$(ARG)]]>]]
130 HRESULT Invoke(IDispatch* object,
131                LPCOLESTR const_name,
132                WORD flags,
133 $for ARG [[
135                const P$(ARG)& p$(ARG),
138                VARIANT* const & result_out) {
139   // Retrieve the ID of the method to be called.
140   DISPID disp_id;
141   LPOLESTR name = const_cast<LPOLESTR>(const_name);
142   HRESULT hr = object->GetIDsOfNames(
143       IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &disp_id);
144   if (FAILED(hr))
145     return hr;
147   // Request the return value if asked by the caller.
148   internal::ScopedVariantArg result;
149   VARIANT* disp_result = NULL;
150   if (result_out != NULL)
151     disp_result = &result;
153 $if ARITY > 0 [[
155   // Wrap the parameters into an array of VARIANT structures.
156   internal::ScopedVariantArg disp_args[$(ARITY)];
157 $for ARG [[
159   hr = disp_args[$(ARITY) - $(ARG)].Wrap(p$(ARG));
160   if (FAILED(hr))
161     return hr;
166   // Invoke the method passing the parameters via the DISPPARAMS structure.
167   // DISPATCH_PROPERTYPUT and DISPATCH_PROPERTYPUTREF require the parameter of
168   // the property setter to be named, so |cNamedArgs| and |rgdispidNamedArgs|
169   // structure members should be initialized.
171 $if ARITY > 0 [[
172   DISPPARAMS disp_params = { disp_args, NULL, $(ARITY), 0 };
173 ]] $else [[
174   DISPPARAMS disp_params = { NULL, NULL, 0, 0 };
177   DISPID dispid_named = DISPID_PROPERTYPUT;
178   if (flags == DISPATCH_PROPERTYPUT || flags == DISPATCH_PROPERTYPUTREF) {
179     disp_params.cNamedArgs = 1;
180     disp_params.rgdispidNamedArgs = &dispid_named;
181   }
183   hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags,
184                       &disp_params, disp_result, NULL, NULL);
185   if (FAILED(hr))
186     return hr;
188 $if ARITY > 0 [[
190   // Unwrap the parameters.
191 $for ARG [[
193   disp_args[$(ARITY) - $(ARG)].Unwrap(p$(ARG));
198   // Unwrap the return value.
199   if (result_out != NULL) {
200     result.Unwrap(result_out);
201   }
203   return S_OK;
208 } // namespace dispatch
210 } // namespace remoting
212 #endif // REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_