Less strict CHECK for DeviceCapabilities results.
[chromium-blink-merge.git] / remoting / base / dispatch_win.h.pump
blobc6a6d5a411affbdb7d87f0f7a087fb80ee637be9
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 COMPILE_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                LPOLESTR 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   HRESULT hr = object->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT,
142                                      &disp_id);
143   if (FAILED(hr))
144     return hr;
146   // Request the return value if asked by the caller.
147   internal::ScopedVariantArg result;
148   VARIANT* disp_result = NULL;
149   if (result_out != NULL)
150     disp_result = &result;
152 $if ARITY > 0 [[
154   // Wrap the parameters into an array of VARIANT structures.
155   internal::ScopedVariantArg disp_args[$(ARITY)];
156 $for ARG [[
158   hr = disp_args[$(ARITY) - $(ARG)].Wrap(p$(ARG));
159   if (FAILED(hr))
160     return hr;
165   // Invoke the method passing the parameters via the DISPPARAMS structure.
166   // DISPATCH_PROPERTYPUT and DISPATCH_PROPERTYPUTREF require the parameter of
167   // the property setter to be named, so |cNamedArgs| and |rgdispidNamedArgs|
168   // structure members should be initialized.
170 $if ARITY > 0 [[
171   DISPPARAMS disp_params = { disp_args, NULL, $(ARITY), 0 };
172 ]] $else [[
173   DISPPARAMS disp_params = { NULL, NULL, 0, 0 };
176   DISPID dispid_named = DISPID_PROPERTYPUT;
177   if (flags == DISPATCH_PROPERTYPUT || flags == DISPATCH_PROPERTYPUTREF) {
178     disp_params.cNamedArgs = 1;
179     disp_params.rgdispidNamedArgs = &dispid_named;
180   }
182   hr = object->Invoke(disp_id, IID_NULL, LOCALE_USER_DEFAULT, flags,
183                       &disp_params, disp_result, NULL, NULL);
184   if (FAILED(hr))
185     return hr;
187 $if ARITY > 0 [[
189   // Unwrap the parameters.
190 $for ARG [[
192   disp_args[$(ARITY) - $(ARG)].Unwrap(p$(ARG));
197   // Unwrap the return value.
198   if (result_out != NULL) {
199     result.Unwrap(result_out);
200   }
202   return S_OK;
207 } // namespace dispatch
209 } // namespace remoting
211 #endif // REMOTING_BASE_IDISPATCH_DRIVER_WIN_H_