• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_WIN_WINRT_FOUNDATION_HELPERS_H_
6 #define BASE_WIN_WINRT_FOUNDATION_HELPERS_H_
7 
8 #include <windows.foundation.h>
9 #include <wrl/client.h>
10 
11 #include <algorithm>
12 #include <vector>
13 
14 #include "base/check.h"
15 #include "third_party/abseil-cpp/absl/types/optional.h"
16 
17 // This file provides helpers for WinRT types.
18 
19 namespace base::win::internal {
20 
21 // Template tricks needed to dispatch to the correct implementation.
22 //
23 // For all types which are neither InterfaceGroups nor RuntimeClasses, the
24 // following three typedefs are synonyms for a single C++ type.  But for
25 // InterfaceGroups and RuntimeClasses, they are different types:
26 //   LogicalT: The C++ Type for the InterfaceGroup or RuntimeClass, when
27 //             used as a template parameter.  Eg "RCFoo*"
28 //   AbiT:     The C++ type for the default interface used to represent the
29 //             InterfaceGroup or RuntimeClass when passed as a method parameter.
30 //             Eg "IFoo*"
31 //   ComplexT: An instantiation of the Internal "AggregateType" template that
32 //             combines LogicalT with AbiT. Eg "AggregateType<RCFoo*,IFoo*>".
33 //             ComplexT is tightly coupled to the interface being implemented,
34 //             hence defined in headers which include this file.
35 //             For instance base/win/async_operation.h or
36 //             base/win/collection_helpers.h
37 //
38 // windows.foundation.collections.h defines the following template and
39 // semantics in Windows::Foundation::Internal:
40 //
41 // template <class LogicalType, class AbiType>
42 // struct AggregateType;
43 //
44 //   LogicalType - the Windows Runtime type (eg, runtime class, interface group,
45 //                 etc) being provided as an argument to an _impl template, when
46 //                 that type cannot be represented at the ABI.
47 //   AbiType     - the type used for marshalling, ie "at the ABI", for the
48 //                 logical type.
49 template <typename TComplex>
50 using AbiType =
51     typename ABI::Windows::Foundation::Internal::GetAbiType<TComplex>::type;
52 
53 template <typename TComplex>
54 using LogicalType =
55     typename ABI::Windows::Foundation::Internal::GetLogicalType<TComplex>::type;
56 
57 // Compile time switch to decide what container to use for |TComplex|.
58 // Depends on whether the underlying Abi type is a pointer to IUnknown or not.
59 // It queries the internals of Windows::Foundation to obtain this information.
60 template <typename TComplex>
61 using StorageType = std::conditional_t<
62     std::is_convertible<AbiType<TComplex>, IUnknown*>::value,
63     Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiType<TComplex>>>,
64     AbiType<TComplex>>;
65 
66 // Similar to StorageType, but returns a absl::optional in case underlying Abi
67 // type is not a pointer to IUnknown.
68 template <typename TComplex>
69 using OptionalStorageType = std::conditional_t<
70     std::is_convertible<AbiType<TComplex>, IUnknown*>::value,
71     Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiType<TComplex>>>,
72     absl::optional<AbiType<TComplex>>>;
73 
74 template <typename T>
CopyTo(const T & value,T * ptr)75 HRESULT CopyTo(const T& value, T* ptr) {
76   *ptr = value;
77   return S_OK;
78 }
79 
80 template <typename T>
CopyTo(const Microsoft::WRL::ComPtr<T> & value,T ** ptr)81 HRESULT CopyTo(const Microsoft::WRL::ComPtr<T>& value, T** ptr) {
82   return value.CopyTo(ptr);
83 }
84 
85 template <typename T>
CopyTo(const absl::optional<T> & value,T * ptr)86 HRESULT CopyTo(const absl::optional<T>& value, T* ptr) {
87   *ptr = *value;
88   return S_OK;
89 }
90 
91 template <typename T>
CopyN(typename std::vector<T>::const_iterator first,unsigned count,T * result)92 HRESULT CopyN(typename std::vector<T>::const_iterator first,
93               unsigned count,
94               T* result) {
95   std::copy_n(first, count, result);
96   return S_OK;
97 }
98 
99 template <typename T>
CopyN(typename std::vector<Microsoft::WRL::ComPtr<T>>::const_iterator first,unsigned count,T ** result)100 HRESULT CopyN(
101     typename std::vector<Microsoft::WRL::ComPtr<T>>::const_iterator first,
102     unsigned count,
103     T** result) {
104   for (unsigned i = 0; i < count; ++i) {
105     CopyTo(*first++, result++);
106   }
107   return S_OK;
108 }
109 
IsEqual(const HSTRING & lhs,const HSTRING & rhs)110 inline bool IsEqual(const HSTRING& lhs, const HSTRING& rhs) {
111   INT32 result;
112   HRESULT hr = ::WindowsCompareStringOrdinal(lhs, rhs, &result);
113   DCHECK(SUCCEEDED(hr));
114   return result == 0;
115 }
116 
117 template <typename T>
IsEqual(const T & lhs,const T & rhs)118 bool IsEqual(const T& lhs, const T& rhs) {
119   return lhs == rhs;
120 }
121 
122 template <typename T>
IsEqual(const Microsoft::WRL::ComPtr<T> & com_ptr,const T * ptr)123 bool IsEqual(const Microsoft::WRL::ComPtr<T>& com_ptr, const T* ptr) {
124   return com_ptr.Get() == ptr;
125 }
126 
127 struct Less {
operatorLess128   bool operator()(const HSTRING& lhs, const HSTRING& rhs) const {
129     INT32 result;
130     HRESULT hr = ::WindowsCompareStringOrdinal(lhs, rhs, &result);
131     DCHECK(SUCCEEDED(hr));
132     return result < 0;
133   }
134 
135   template <typename T>
operatorLess136   bool operator()(const Microsoft::WRL::ComPtr<T>& com_ptr,
137                   const T* ptr) const {
138     return com_ptr.Get() < ptr;
139   }
140 
141   template <typename T>
operatorLess142   constexpr bool operator()(const T& lhs, const T& rhs) const {
143     return lhs < rhs;
144   }
145 };
146 
147 }  // namespace base::win::internal
148 
149 #endif  // BASE_WIN_WINRT_FOUNDATION_HELPERS_H_
150