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