Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

2233 wiersze
87 KiB

  1. //*********************************************************
  2. //
  3. // Copyright (c) Microsoft. All rights reserved.
  4. // This code is licensed under the MIT License.
  5. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
  6. // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  7. // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  8. // PARTICULAR PURPOSE AND NONINFRINGEMENT.
  9. //
  10. //*********************************************************
  11. #ifndef __WIL_WINRT_INCLUDED
  12. #define __WIL_WINRT_INCLUDED
  13. #include <hstring.h>
  14. #include <wrl\client.h>
  15. #include <wrl\implements.h>
  16. #include <wrl\async.h>
  17. #include <wrl\wrappers\corewrappers.h>
  18. #include "result.h"
  19. #include "com.h"
  20. #include "resource.h"
  21. #include <windows.foundation.collections.h>
  22. #ifdef __cplusplus_winrt
  23. #include <collection.h> // bring in the CRT iterator for support for C++ CX code
  24. #endif
  25. #ifdef WIL_ENABLE_EXCEPTIONS
  26. #pragma warning(push)
  27. #pragma warning(disable:4643)
  28. /// @cond
  29. namespace std
  30. {
  31. template<class _Ty>
  32. struct less;
  33. }
  34. /// @endcond
  35. #pragma warning(pop)
  36. #endif
  37. // This enables this code to be used in code that uses the ABI prefix or not.
  38. // Code using the public SDK and C++ CX code has the ABI prefix, windows internal
  39. // is built in a way that does not.
  40. #if !defined(MIDL_NS_PREFIX) && !defined(____x_ABI_CWindows_CFoundation_CIClosable_FWD_DEFINED__)
  41. // Internal .idl files use the namespace without the ABI prefix. Macro out ABI for that case
  42. #pragma push_macro("ABI")
  43. #undef ABI
  44. #define ABI
  45. #endif
  46. namespace wil
  47. {
  48. #ifdef _INC_TIME
  49. // time_t is the number of 1 - second intervals since January 1, 1970.
  50. long long const SecondsToStartOf1970 = 0x2b6109100;
  51. long long const HundredNanoSecondsInSecond = 10000000LL;
  52. inline __time64_t DateTime_to_time_t(ABI::Windows::Foundation::DateTime dateTime)
  53. {
  54. // DateTime is the number of 100 - nanosecond intervals since January 1, 1601.
  55. return (dateTime.UniversalTime / HundredNanoSecondsInSecond - SecondsToStartOf1970);
  56. }
  57. inline ABI::Windows::Foundation::DateTime time_t_to_DateTime(__time64_t timeT)
  58. {
  59. ABI::Windows::Foundation::DateTime dateTime;
  60. dateTime.UniversalTime = (timeT + SecondsToStartOf1970) * HundredNanoSecondsInSecond;
  61. return dateTime;
  62. }
  63. #endif // _INC_TIME
  64. #pragma region HSTRING Helpers
  65. /// @cond
  66. namespace details
  67. {
  68. // hstring_compare is used to assist in HSTRING comparison of two potentially non-similar string types. E.g.
  69. // comparing a raw HSTRING with WRL's HString/HStringReference/etc. The consumer can optionally inhibit the
  70. // deduction of array sizes by providing 'true' for the 'InhibitStringArrays' template argument. This is
  71. // generally done in scenarios where the consumer cannot guarantee that the input argument types are perfectly
  72. // preserved from end-to-end. E.g. if a single function in the execution path captures an array as const T&,
  73. // then it is impossible to differentiate const arrays (where we generally do want to deduce length) from
  74. // non-const arrays (where we generally do not want to deduce length). The consumer can also optionally choose
  75. // to perform case-insensitive comparison by providing 'true' for the 'IgnoreCase' template argument.
  76. template <bool InhibitStringArrays, bool IgnoreCase>
  77. struct hstring_compare
  78. {
  79. // get_buffer returns the string buffer and length for the supported string types
  80. static const wchar_t* get_buffer(HSTRING hstr, UINT32* length) WI_NOEXCEPT
  81. {
  82. return ::WindowsGetStringRawBuffer(hstr, length);
  83. }
  84. static const wchar_t* get_buffer(const Microsoft::WRL::Wrappers::HString& hstr, UINT32* length) WI_NOEXCEPT
  85. {
  86. return hstr.GetRawBuffer(length);
  87. }
  88. static const wchar_t* get_buffer(
  89. const Microsoft::WRL::Wrappers::HStringReference& hstr,
  90. UINT32* length) WI_NOEXCEPT
  91. {
  92. return hstr.GetRawBuffer(length);
  93. }
  94. static const wchar_t* get_buffer(const unique_hstring& str, UINT32* length) WI_NOEXCEPT
  95. {
  96. return ::WindowsGetStringRawBuffer(str.get(), length);
  97. }
  98. template <bool..., bool Enable = InhibitStringArrays>
  99. static wistd::enable_if_t<Enable, const wchar_t*> get_buffer(const wchar_t* str, UINT32* length) WI_NOEXCEPT
  100. {
  101. str = (str != nullptr) ? str : L"";
  102. *length = static_cast<UINT32>(wcslen(str));
  103. return str;
  104. }
  105. template <typename StringT, bool..., bool Enable = !InhibitStringArrays>
  106. static wistd::enable_if_t<
  107. wistd::conjunction<
  108. wistd::is_pointer<StringT>,
  109. wistd::is_same<wistd::decay_t<wistd::remove_pointer_t<StringT>>, wchar_t>,
  110. wistd::bool_constant<Enable>
  111. >::value,
  112. const wchar_t*> get_buffer(StringT str, UINT32* length) WI_NOEXCEPT
  113. {
  114. str = (str != nullptr) ? str : L"";
  115. *length = static_cast<UINT32>(wcslen(str));
  116. return str;
  117. }
  118. template <size_t Size, bool..., bool Enable = !InhibitStringArrays>
  119. static wistd::enable_if_t<Enable, const wchar_t*> get_buffer(
  120. const wchar_t (&str)[Size],
  121. UINT32* length) WI_NOEXCEPT
  122. {
  123. *length = Size - 1;
  124. return str;
  125. }
  126. template <size_t Size, bool..., bool Enable = !InhibitStringArrays>
  127. static wistd::enable_if_t<Enable, const wchar_t*> get_buffer(wchar_t (&str)[Size], UINT32* length) WI_NOEXCEPT
  128. {
  129. *length = static_cast<UINT32>(wcslen(str));
  130. return str;
  131. }
  132. // Overload for std::wstring, or at least things that behave like std::wstring, without adding a dependency
  133. // on STL headers
  134. template <typename StringT>
  135. static wistd::enable_if_t<wistd::conjunction_v<
  136. wistd::is_same<const wchar_t*, decltype(wistd::declval<StringT>().c_str())>,
  137. wistd::is_same<typename StringT::size_type, decltype(wistd::declval<StringT>().length())>>,
  138. const wchar_t*> get_buffer(const StringT& str, UINT32* length) WI_NOEXCEPT
  139. {
  140. *length = static_cast<UINT32>(str.length());
  141. return str.c_str();
  142. }
  143. template <typename LhsT, typename RhsT>
  144. static auto compare(LhsT&& lhs, RhsT&& rhs) ->
  145. decltype(get_buffer(lhs, wistd::declval<UINT32*>()), get_buffer(rhs, wistd::declval<UINT32*>()), int())
  146. {
  147. UINT32 lhsLength;
  148. UINT32 rhsLength;
  149. auto lhsBuffer = get_buffer(wistd::forward<LhsT>(lhs), &lhsLength);
  150. auto rhsBuffer = get_buffer(wistd::forward<RhsT>(rhs), &rhsLength);
  151. const auto result = ::CompareStringOrdinal(
  152. lhsBuffer,
  153. lhsLength,
  154. rhsBuffer,
  155. rhsLength,
  156. IgnoreCase ? TRUE : FALSE);
  157. WI_ASSERT(result != 0);
  158. return result;
  159. }
  160. template <typename LhsT, typename RhsT>
  161. static auto equals(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT ->
  162. decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
  163. {
  164. return compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)) == CSTR_EQUAL;
  165. }
  166. template <typename LhsT, typename RhsT>
  167. static auto not_equals(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT ->
  168. decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
  169. {
  170. return compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)) != CSTR_EQUAL;
  171. }
  172. template <typename LhsT, typename RhsT>
  173. static auto less(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT ->
  174. decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
  175. {
  176. return compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)) == CSTR_LESS_THAN;
  177. }
  178. template <typename LhsT, typename RhsT>
  179. static auto less_equals(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT ->
  180. decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
  181. {
  182. return compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)) != CSTR_GREATER_THAN;
  183. }
  184. template <typename LhsT, typename RhsT>
  185. static auto greater(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT ->
  186. decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
  187. {
  188. return compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)) == CSTR_GREATER_THAN;
  189. }
  190. template <typename LhsT, typename RhsT>
  191. static auto greater_equals(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT ->
  192. decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
  193. {
  194. return compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)) != CSTR_LESS_THAN;
  195. }
  196. };
  197. }
  198. /// @endcond
  199. //! Detects if one or more embedded null is present in an HSTRING.
  200. inline bool HasEmbeddedNull(_In_opt_ HSTRING value)
  201. {
  202. BOOL hasEmbeddedNull;
  203. WindowsStringHasEmbeddedNull(value, &hasEmbeddedNull);
  204. return hasEmbeddedNull != FALSE;
  205. }
  206. /** TwoPhaseHStringConstructor help using the 2 phase constructor pattern for HSTRINGs.
  207. ~~~
  208. auto stringConstructor = wil::TwoPhaseHStringConstructor::Preallocate(size);
  209. RETURN_IF_NULL_ALLOC(stringConstructor.Get());
  210. RETURN_IF_FAILED(stream->Read(stringConstructor.Get(), stringConstructor.ByteSize(), &bytesRead));
  211. // Validate stream contents, sizes must match, string must be null terminated.
  212. RETURN_IF_FAILED(stringConstructor.Validate(bytesRead));
  213. wil::unique_hstring string { stringConstructor.Promote() };
  214. ~~~
  215. See also wil::unique_hstring_buffer.
  216. */
  217. struct TwoPhaseHStringConstructor
  218. {
  219. TwoPhaseHStringConstructor() = delete;
  220. TwoPhaseHStringConstructor(const TwoPhaseHStringConstructor&) = delete;
  221. void operator=(const TwoPhaseHStringConstructor&) = delete;
  222. TwoPhaseHStringConstructor(TwoPhaseHStringConstructor&& other) WI_NOEXCEPT
  223. {
  224. m_characterLength = other.m_characterLength;
  225. other.m_characterLength = 0;
  226. m_maker = wistd::move(other.m_maker);
  227. }
  228. static TwoPhaseHStringConstructor Preallocate(UINT32 characterLength)
  229. {
  230. return TwoPhaseHStringConstructor{ characterLength };
  231. }
  232. //! Returns the HSTRING after it has been populated like Detatch() or release(); be sure to put this in a RAII type to manage its lifetime.
  233. HSTRING Promote()
  234. {
  235. m_characterLength = 0;
  236. return m_maker.release().release();
  237. }
  238. ~TwoPhaseHStringConstructor() = default;
  239. explicit operator PCWSTR() const
  240. {
  241. // This is set by WindowsPromoteStringBuffer() which must be called to
  242. // construct this object via the static method Preallocate().
  243. return m_maker.buffer();
  244. }
  245. //! Returns a pointer for the buffer so it can be populated
  246. wchar_t* Get() const { return const_cast<wchar_t*>(m_maker.buffer()); }
  247. //! Used to validate range of buffer when populating.
  248. ULONG ByteSize() const { return m_characterLength * sizeof(wchar_t); }
  249. /** Ensure that the size of the data provided is consistent with the pre-allocated buffer.
  250. It seems that WindowsPreallocateStringBuffer() provides the null terminator in the buffer
  251. (based on testing) so this can be called before populating the buffer.
  252. */
  253. HRESULT Validate(ULONG bytesRead) const
  254. {
  255. // Null termination is required for the buffer before calling WindowsPromoteStringBuffer().
  256. RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_DATA),
  257. (bytesRead != ByteSize()) ||
  258. (Get()[m_characterLength] != L'\0'));
  259. return S_OK;
  260. }
  261. private:
  262. TwoPhaseHStringConstructor(UINT32 characterLength) : m_characterLength(characterLength)
  263. {
  264. (void)m_maker.make(nullptr, characterLength);
  265. }
  266. UINT32 m_characterLength;
  267. details::string_maker<unique_hstring> m_maker;
  268. };
  269. //! A transparent less-than comparison function object that enables comparison of various string types intended for
  270. //! use with associative containers (such as `std::set`, `std::map`, etc.) that use
  271. //! `Microsoft::WRL::Wrappers::HString` as the key type. This removes the need for the consumer to explicitly
  272. //! create an `HString` object when using lookup functions such as `find`, `lower_bound`, etc. For example, the
  273. //! following scenarios would all work exactly as you would expect them to:
  274. //! ~~~
  275. //! std::map<HString, int, wil::hstring_less> map;
  276. //! const wchar_t constArray[] = L"foo";
  277. //! wchar_t nonConstArray[MAX_PATH] = L"foo";
  278. //!
  279. //! HString key;
  280. //! THROW_IF_FAILED(key.Set(constArray));
  281. //! map.emplace(std::move(key), 42);
  282. //!
  283. //! HString str;
  284. //! wil::unique_hstring uniqueStr;
  285. //! THROW_IF_FAILED(str.Set(L"foo"));
  286. //! THROW_IF_FAILED(str.CopyTo(&uniqueStr));
  287. //!
  288. //! // All of the following return an iterator to the pair { L"foo", 42 }
  289. //! map.find(str);
  290. //! map.find(str.Get());
  291. //! map.find(HStringReference(constArray));
  292. //! map.find(uniqueStr);
  293. //! map.find(std::wstring(constArray));
  294. //! map.find(constArray);
  295. //! map.find(nonConstArray);
  296. //! map.find(static_cast<const wchar_t*>(constArray));
  297. //! ~~~
  298. //! The first four calls in the example above use `WindowsGetStringRawBuffer` (or equivalent) to get the string
  299. //! buffer and length for the comparison. The fifth example uses `std::wstring::c_str` and `std::wstring::length`
  300. //! for getting these two values. The remaining three examples use only the string buffer and call `wcslen` for the
  301. //! length. That is, the length is *not* deduced for either array. This is because argument types are not always
  302. //! perfectly preserved by container functions and in fact are often captured as const references making it
  303. //! impossible to differentiate const arrays - where we can safely deduce length - from non const arrays - where we
  304. //! cannot safely deduce length since the buffer may be larger than actually needed (e.g. creating a
  305. //! `char[MAX_PATH]` array, but only filling it with 10 characters). The implications of this behavior is that
  306. //! string literals that contain embedded null characters will only include the part of the buffer up to the first
  307. //! null character. For example, the following example will result in all calls to `find` returning an end
  308. //! iterator.
  309. //! ~~~
  310. //! std::map<HString, int, wil::hstring_less> map;
  311. //! const wchar_t constArray[] = L"foo\0bar";
  312. //! wchar_t nonConstArray[MAX_PATH] = L"foo\0bar";
  313. //!
  314. //! // Create the key with the embedded null character
  315. //! HString key;
  316. //! THROW_IF_FAILED(key.Set(constArray));
  317. //! map.emplace(std::move(key), 42);
  318. //!
  319. //! // All of the following return map.end() since they look for the string "foo"
  320. //! map.find(constArray);
  321. //! map.find(nonConstArray);
  322. //! map.find(static_cast<const wchar_t*>(constArray));
  323. //! ~~~
  324. //! In order to search using a string literal that contains embedded null characters, a simple alternative is to
  325. //! first create an `HStringReference` and use that for the function call:
  326. //! ~~~
  327. //! // HStringReference's constructor *will* deduce the length of const arrays
  328. //! map.find(HStringReference(constArray));
  329. //! ~~~
  330. struct hstring_less
  331. {
  332. using is_transparent = void;
  333. template <typename LhsT, typename RhsT>
  334. auto operator()(const LhsT& lhs, const RhsT& rhs) const WI_NOEXCEPT ->
  335. decltype(details::hstring_compare<true, false>::less(lhs, rhs))
  336. {
  337. return details::hstring_compare<true, false>::less(lhs, rhs);
  338. }
  339. };
  340. //! A transparent less-than comparison function object whose behavior is equivalent to that of @ref hstring_less
  341. //! with the one difference that comparisons are case-insensitive. That is, the following example will correctly
  342. //! find the inserted value:
  343. //! ~~~
  344. //! std::map<HString, int, wil::hstring_insensitive_less> map;
  345. //!
  346. //! HString key;
  347. //! THROW_IF_FAILED(key.Set(L"foo"));
  348. //! map.emplace(std::move(key), 42);
  349. //!
  350. //! // All of the following return an iterator to the pair { L"foo", 42 }
  351. //! map.find(L"FOo");
  352. //! map.find(HStringReference(L"fOo"));
  353. //! map.find(HStringReference(L"fOO").Get());
  354. //! ~~~
  355. struct hstring_insensitive_less
  356. {
  357. using is_transparent = void;
  358. template <typename LhsT, typename RhsT>
  359. auto operator()(const LhsT& lhs, const RhsT& rhs) const WI_NOEXCEPT ->
  360. decltype(details::hstring_compare<true, true>::less(lhs, rhs))
  361. {
  362. return details::hstring_compare<true, true>::less(lhs, rhs);
  363. }
  364. };
  365. #pragma endregion
  366. /// @cond
  367. namespace details
  368. {
  369. // MapToSmartType<T>::type is used to map a raw type into an RAII expression
  370. // of it. This is needed when lifetime management of the type is needed, for example
  371. // when holding them as a value produced in an iterator.
  372. // This type has a common set of methods used to abstract the access to the value
  373. // that is similar to ComPtr<> and the WRL Wrappers: Get(), GetAddressOf() and other operators.
  374. // Clients of the smart type must use those to access the value.
  375. // TODO: Having the base definition defined will result in creating leaks if a type
  376. // that needs resource management (e.g. PROPVARIANT) that has not specialized is used.
  377. //
  378. // One fix is to use std::is_enum to cover that case and leave the base definition undefined.
  379. // That base should use static_assert to inform clients how to fix the lack of specialization.
  380. template<typename T, typename Enable = void> struct MapToSmartType
  381. {
  382. #pragma warning(push)
  383. #pragma warning(disable:4702) // https://github.com/Microsoft/wil/issues/2
  384. struct type // T holder
  385. {
  386. type() {};
  387. type(T&& value) : m_value(wistd::forward<T>(value)) {};
  388. operator T() const { return m_value; }
  389. type& operator=(T&& value) { m_value = wistd::forward<T>(value); return *this; }
  390. T Get() const { return m_value; }
  391. // Returning T&& to support move only types
  392. // In case of absense of T::operator=(T&&) a call to T::operator=(const T&) will happen
  393. T&& Get() { return wistd::move(m_value); }
  394. HRESULT CopyTo(T* result) const { *result = m_value; return S_OK; }
  395. T* GetAddressOf() { return &m_value; }
  396. T* ReleaseAndGetAddressOf() { return &m_value; }
  397. T* operator&() { return &m_value; }
  398. T m_value{};
  399. };
  400. #pragma warning(pop)
  401. };
  402. // IUnknown * derived -> Microsoft::WRL::ComPtr<>
  403. template <typename T>
  404. struct MapToSmartType<T, typename wistd::enable_if<wistd::is_base_of<IUnknown, typename wistd::remove_pointer<T>::type>::value>::type>
  405. {
  406. typedef Microsoft::WRL::ComPtr<typename wistd::remove_pointer<T>::type> type;
  407. };
  408. // HSTRING -> Microsoft::WRL::Wrappers::HString
  409. template <> struct MapToSmartType<HSTRING, void>
  410. {
  411. class HStringWithRelease : public Microsoft::WRL::Wrappers::HString
  412. {
  413. public:
  414. // Unlike all other WRL types HString does not have ReleaseAndGetAddressOf and
  415. // GetAddressOf() has non-standard behavior, calling Release().
  416. HSTRING* ReleaseAndGetAddressOf() WI_NOEXCEPT
  417. {
  418. Release();
  419. return &hstr_;
  420. }
  421. };
  422. typedef HStringWithRelease type;
  423. };
  424. // WinRT interfaces like IVector<>, IAsyncOperation<> and IIterable<> can be templated
  425. // on a runtime class (instead of an interface or primitive type). In these cases the objects
  426. // produced by those interfaces implement an interface defined by the runtime class default interface.
  427. //
  428. // These templates deduce the type of the produced interface or pass through
  429. // the type unmodified in the non runtime class case.
  430. //
  431. // for example:
  432. // IAsyncOperation<StorageFile*> -> IAsyncOperation<IStorageFile*>
  433. // For IVector<T>, IVectorView<T>.
  434. template<typename VectorType> struct MapVectorResultType
  435. {
  436. template<typename TVector, typename TResult>
  437. static TResult PeekGetAtType(HRESULT(STDMETHODCALLTYPE TVector::*)(unsigned, TResult*));
  438. typedef decltype(PeekGetAtType(&VectorType::GetAt)) type;
  439. };
  440. // For IIterator<T>.
  441. template<typename T> struct MapIteratorResultType
  442. {
  443. template<typename TIterable, typename TResult>
  444. static TResult PeekCurrentType(HRESULT(STDMETHODCALLTYPE TIterable::*)(TResult*));
  445. typedef decltype(PeekCurrentType(&ABI::Windows::Foundation::Collections::IIterator<T>::get_Current)) type;
  446. };
  447. // For IAsyncOperation<T>.
  448. template<typename T> struct MapAsyncOpResultType
  449. {
  450. template<typename TAsyncOperation, typename TResult>
  451. static TResult PeekGetResultsType(HRESULT(STDMETHODCALLTYPE TAsyncOperation::*)(TResult*));
  452. typedef decltype(PeekGetResultsType(&ABI::Windows::Foundation::IAsyncOperation<T>::GetResults)) type;
  453. };
  454. // For IAsyncOperationWithProgress<T, P>.
  455. template<typename T, typename P> struct MapAsyncOpProgressResultType
  456. {
  457. template<typename TAsyncOperation, typename TResult>
  458. static TResult PeekGetResultsType(HRESULT(STDMETHODCALLTYPE TAsyncOperation::*)(TResult*));
  459. typedef decltype(PeekGetResultsType(&ABI::Windows::Foundation::IAsyncOperationWithProgress<T, P>::GetResults)) type;
  460. };
  461. // No support for IAsyncActionWithProgress<P> none of these (currently) use
  462. // a runtime class for the progress type.
  463. }
  464. /// @endcond
  465. #pragma region C++ iterators for WinRT collections for use with range based for and STL algorithms
  466. /** Range base for and STL algorithms support for WinRT ABI collection types, IVector<T>, IVectorView<T>, IIterable<T>
  467. similar to support provided by <collection.h> for C++ CX. Three error handling policies are supported.
  468. ~~~
  469. ComPtr<CollectionType> collection = GetCollection(); // can be IVector<HSTRING>, IVectorView<HSTRING> or IIterable<HSTRING>
  470. for (auto const& element : wil::get_range(collection.Get())) // exceptions
  471. for (auto const& element : wil::get_range_nothrow(collection.Get(), &hr)) // error code
  472. for (auto const& element : wil::get_range_failfast(collection.Get())) // fail fast
  473. {
  474. // use element
  475. }
  476. ~~~
  477. Standard algorithm example:
  478. ~~~
  479. ComPtr<IVectorView<StorageFile*>> files = GetFiles();
  480. auto fileRange = wil::get_range_nothrow(files.Get());
  481. auto itFound = std::find_if(fileRange.begin(), fileRange.end(), [](ComPtr<IStorageFile> file) -> bool
  482. {
  483. return true; // first element in range
  484. });
  485. ~~~
  486. */
  487. #pragma region exception and fail fast based IVector<>/IVectorView<>
  488. template <typename VectorType, typename err_policy = err_exception_policy>
  489. class vector_range
  490. {
  491. public:
  492. typedef typename details::MapVectorResultType<VectorType>::type TResult;
  493. typedef typename details::MapToSmartType<TResult>::type TSmart;
  494. vector_range() = delete;
  495. explicit vector_range(_In_ VectorType *vector) : m_v(vector)
  496. {
  497. }
  498. class vector_iterator
  499. {
  500. public:
  501. #ifdef _XUTILITY_
  502. // could be random_access_iterator_tag but missing some features
  503. typedef ::std::bidirectional_iterator_tag iterator_category;
  504. #endif
  505. typedef TSmart value_type;
  506. typedef ptrdiff_t difference_type;
  507. typedef const TSmart* pointer;
  508. typedef const TSmart& reference;
  509. // for begin()
  510. vector_iterator(VectorType* v, unsigned int pos)
  511. : m_v(v), m_i(pos)
  512. {
  513. }
  514. // for end()
  515. vector_iterator() : m_v(nullptr), m_i(-1) {}
  516. vector_iterator(const vector_iterator& other)
  517. {
  518. m_v = other.m_v;
  519. m_i = other.m_i;
  520. err_policy::HResult(other.m_element.CopyTo(m_element.GetAddressOf()));
  521. }
  522. vector_iterator& operator=(const vector_iterator& other)
  523. {
  524. if (this != wistd::addressof(other))
  525. {
  526. m_v = other.m_v;
  527. m_i = other.m_i;
  528. err_policy::HResult(other.m_element.CopyTo(m_element.ReleaseAndGetAddressOf()));
  529. }
  530. return *this;
  531. }
  532. reference operator*()
  533. {
  534. err_policy::HResult(m_v->GetAt(m_i, m_element.ReleaseAndGetAddressOf()));
  535. return m_element;
  536. }
  537. pointer operator->()
  538. {
  539. err_policy::HResult(m_v->GetAt(m_i, m_element.ReleaseAndGetAddressOf()));
  540. return wistd::addressof(m_element);
  541. }
  542. vector_iterator& operator++()
  543. {
  544. ++m_i;
  545. return *this;
  546. }
  547. vector_iterator& operator--()
  548. {
  549. --m_i;
  550. return *this;
  551. }
  552. vector_iterator operator++(int)
  553. {
  554. vector_iterator old(*this);
  555. ++*this;
  556. return old;
  557. }
  558. vector_iterator operator--(int)
  559. {
  560. vector_iterator old(*this);
  561. --*this;
  562. return old;
  563. }
  564. vector_iterator& operator+=(int n)
  565. {
  566. m_i += n;
  567. return *this;
  568. }
  569. vector_iterator& operator-=(int n)
  570. {
  571. m_i -= n;
  572. return *this;
  573. }
  574. vector_iterator operator+(int n) const
  575. {
  576. vector_iterator ret(*this);
  577. ret += n;
  578. return ret;
  579. }
  580. vector_iterator operator-(int n) const
  581. {
  582. vector_iterator ret(*this);
  583. ret -= n;
  584. return ret;
  585. }
  586. ptrdiff_t operator-(const vector_iterator& other) const
  587. {
  588. return m_i - other.m_i;
  589. }
  590. bool operator==(const vector_iterator& other) const
  591. {
  592. return m_i == other.m_i;
  593. }
  594. bool operator!=(const vector_iterator& other) const
  595. {
  596. return m_i != other.m_i;
  597. }
  598. bool operator<(const vector_iterator& other) const
  599. {
  600. return m_i < other.m_i;
  601. }
  602. bool operator>(const vector_iterator& other) const
  603. {
  604. return m_i > other.m_i;
  605. }
  606. bool operator<=(const vector_iterator& other) const
  607. {
  608. return m_i <= other.m_i;
  609. }
  610. bool operator>=(const vector_iterator& other) const
  611. {
  612. return m_i >= other.m_i;
  613. }
  614. private:
  615. VectorType* m_v; // weak, collection must outlive iterators.
  616. unsigned int m_i;
  617. TSmart m_element;
  618. };
  619. vector_iterator begin()
  620. {
  621. return vector_iterator(m_v, 0);
  622. }
  623. vector_iterator end()
  624. {
  625. unsigned int size;
  626. err_policy::HResult(m_v->get_Size(&size));
  627. return vector_iterator(m_v, size);
  628. }
  629. private:
  630. VectorType* m_v; // weak, collection must outlive iterators.
  631. };
  632. #pragma endregion
  633. #pragma region error code based IVector<>/IVectorView<>
  634. template <typename VectorType>
  635. class vector_range_nothrow
  636. {
  637. public:
  638. typedef typename details::MapVectorResultType<VectorType>::type TResult;
  639. typedef typename details::MapToSmartType<TResult>::type TSmart;
  640. vector_range_nothrow() = delete;
  641. vector_range_nothrow(const vector_range_nothrow&) = delete;
  642. vector_range_nothrow& operator=(const vector_range_nothrow&) = delete;
  643. vector_range_nothrow(vector_range_nothrow&& other) :
  644. m_v(other.m_v), m_size(other.m_size), m_result(other.m_result), m_resultStorage(other.m_resultStorage),
  645. m_currentElement(wistd::move(other.m_currentElement))
  646. {
  647. }
  648. vector_range_nothrow(_In_ VectorType *vector, HRESULT* result = nullptr)
  649. : m_v(vector), m_result(result ? result : &m_resultStorage)
  650. {
  651. *m_result = m_v->get_Size(&m_size);
  652. }
  653. class vector_iterator_nothrow
  654. {
  655. public:
  656. #ifdef _XUTILITY_
  657. // must be input_iterator_tag as use (via ++, --, etc.) of one invalidates the other.
  658. typedef ::std::input_iterator_tag iterator_category;
  659. #endif
  660. typedef TSmart value_type;
  661. typedef ptrdiff_t difference_type;
  662. typedef const TSmart* pointer;
  663. typedef const TSmart& reference;
  664. vector_iterator_nothrow() = delete;
  665. vector_iterator_nothrow(vector_range_nothrow<VectorType>* range, unsigned int pos)
  666. : m_range(range), m_i(pos)
  667. {
  668. }
  669. reference operator*() const
  670. {
  671. return m_range->m_currentElement;
  672. }
  673. pointer operator->() const
  674. {
  675. return wistd::addressof(m_range->m_currentElement);
  676. }
  677. vector_iterator_nothrow& operator++()
  678. {
  679. ++m_i;
  680. m_range->get_at_current(m_i);
  681. return *this;
  682. }
  683. vector_iterator_nothrow& operator--()
  684. {
  685. --m_i;
  686. m_range->get_at_current(m_i);
  687. return *this;
  688. }
  689. vector_iterator_nothrow operator++(int)
  690. {
  691. vector_iterator_nothrow old(*this);
  692. ++*this;
  693. return old;
  694. }
  695. vector_iterator_nothrow operator--(int)
  696. {
  697. vector_iterator_nothrow old(*this);
  698. --*this;
  699. return old;
  700. }
  701. vector_iterator_nothrow& operator+=(int n)
  702. {
  703. m_i += n;
  704. m_range->get_at_current(m_i);
  705. return *this;
  706. }
  707. vector_iterator_nothrow& operator-=(int n)
  708. {
  709. m_i -= n;
  710. m_range->get_at_current(m_i);
  711. return *this;
  712. }
  713. bool operator==(vector_iterator_nothrow const& other) const
  714. {
  715. return FAILED(*m_range->m_result) || (m_i == other.m_i);
  716. }
  717. bool operator!=(vector_iterator_nothrow const& other) const
  718. {
  719. return !operator==(other);
  720. }
  721. private:
  722. vector_range_nothrow<VectorType>* m_range;
  723. unsigned int m_i = 0;
  724. };
  725. vector_iterator_nothrow begin()
  726. {
  727. get_at_current(0);
  728. return vector_iterator_nothrow(this, 0);
  729. }
  730. vector_iterator_nothrow end()
  731. {
  732. return vector_iterator_nothrow(this, m_size);
  733. }
  734. // Note, the error code is observed in operator!= and operator==, it always
  735. // returns "equal" in the failed state to force the compare to the end
  736. // iterator to return false and stop the loop.
  737. //
  738. // Is this ok for the general case?
  739. void get_at_current(unsigned int i)
  740. {
  741. if (SUCCEEDED(*m_result) && (i < m_size))
  742. {
  743. *m_result = m_v->GetAt(i, m_currentElement.ReleaseAndGetAddressOf());
  744. }
  745. }
  746. private:
  747. VectorType* m_v; // weak, collection must outlive iterators.
  748. unsigned int m_size;
  749. // This state is shared by vector_iterator_nothrow instances. this means
  750. // use of one iterator invalidates the other.
  751. HRESULT* m_result;
  752. HRESULT m_resultStorage = S_OK; // for the case where the caller does not provide the location to store the result
  753. TSmart m_currentElement;
  754. };
  755. #pragma endregion
  756. #pragma region exception and fail fast based IIterable<>
  757. template <typename T, typename err_policy = err_exception_policy>
  758. class iterable_range
  759. {
  760. public:
  761. typedef typename details::MapIteratorResultType<T>::type TResult;
  762. typedef typename details::MapToSmartType<TResult>::type TSmart;
  763. explicit iterable_range(_In_ ABI::Windows::Foundation::Collections::IIterable<T>* iterable)
  764. : m_iterable(iterable)
  765. {
  766. }
  767. class iterable_iterator
  768. {
  769. public:
  770. #ifdef _XUTILITY_
  771. typedef ::std::forward_iterator_tag iterator_category;
  772. #endif
  773. typedef TSmart value_type;
  774. typedef ptrdiff_t difference_type;
  775. typedef const TSmart* pointer;
  776. typedef const TSmart& reference;
  777. iterable_iterator() : m_i(-1) {}
  778. // for begin()
  779. explicit iterable_iterator(_In_ ABI::Windows::Foundation::Collections::IIterable<T>* iterable)
  780. {
  781. err_policy::HResult(iterable->First(&m_iterator));
  782. boolean hasCurrent;
  783. err_policy::HResult(m_iterator->get_HasCurrent(&hasCurrent));
  784. m_i = hasCurrent ? 0 : -1;
  785. }
  786. // for end()
  787. iterable_iterator(int /*currentIndex*/) : m_i(-1)
  788. {
  789. }
  790. iterable_iterator(const iterable_iterator& other)
  791. {
  792. m_iterator = other.m_iterator;
  793. m_i = other.m_i;
  794. err_policy::HResult(other.m_element.CopyTo(m_element.GetAddressOf()));
  795. }
  796. iterable_iterator& operator=(const iterable_iterator& other)
  797. {
  798. m_iterator = other.m_iterator;
  799. m_i = other.m_i;
  800. err_policy::HResult(other.m_element.CopyTo(m_element.ReleaseAndGetAddressOf()));
  801. return *this;
  802. }
  803. bool operator==(iterable_iterator const& other) const
  804. {
  805. return m_i == other.m_i;
  806. }
  807. bool operator!=(iterable_iterator const& other) const
  808. {
  809. return !operator==(other);
  810. }
  811. reference operator*()
  812. {
  813. err_policy::HResult(m_iterator->get_Current(m_element.ReleaseAndGetAddressOf()));
  814. return m_element;
  815. }
  816. pointer operator->()
  817. {
  818. err_policy::HResult(m_iterator->get_Current(m_element.ReleaseAndGetAddressOf()));
  819. return wistd::addressof(m_element);
  820. }
  821. iterable_iterator& operator++()
  822. {
  823. boolean hasCurrent;
  824. err_policy::HResult(m_iterator->MoveNext(&hasCurrent));
  825. if (hasCurrent)
  826. {
  827. m_i++;
  828. }
  829. else
  830. {
  831. m_i = -1;
  832. }
  833. return *this;
  834. }
  835. iterable_iterator operator++(int)
  836. {
  837. iterable_iterator old(*this);
  838. ++*this;
  839. return old;
  840. }
  841. private:
  842. Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IIterator<T>> m_iterator;
  843. int m_i;
  844. TSmart m_element;
  845. };
  846. iterable_iterator begin()
  847. {
  848. return iterable_iterator(m_iterable);
  849. }
  850. iterable_iterator end()
  851. {
  852. return iterable_iterator();
  853. }
  854. private:
  855. // weak, collection must outlive iterators.
  856. ABI::Windows::Foundation::Collections::IIterable<T>* m_iterable;
  857. };
  858. #pragma endregion
  859. #pragma region error code base IIterable<>
  860. template <typename T>
  861. class iterable_range_nothrow
  862. {
  863. public:
  864. typedef typename details::MapIteratorResultType<T>::type TResult;
  865. typedef typename details::MapToSmartType<TResult>::type TSmart;
  866. iterable_range_nothrow() = delete;
  867. iterable_range_nothrow(const iterable_range_nothrow&) = delete;
  868. iterable_range_nothrow& operator=(const iterable_range_nothrow&) = delete;
  869. iterable_range_nothrow& operator=(iterable_range_nothrow &&) = delete;
  870. iterable_range_nothrow(iterable_range_nothrow&& other) :
  871. m_iterator(wistd::move(other.m_iterator)), m_element(wistd::move(other.m_element)),
  872. m_resultStorage(other.m_resultStorage)
  873. {
  874. if (other.m_result == &other.m_resultStorage)
  875. {
  876. m_result = &m_resultStorage;
  877. }
  878. else
  879. {
  880. m_result = other.m_result;
  881. }
  882. }
  883. iterable_range_nothrow(_In_ ABI::Windows::Foundation::Collections::IIterable<T>* iterable, HRESULT* result = nullptr)
  884. : m_result(result ? result : &m_resultStorage)
  885. {
  886. *m_result = iterable->First(&m_iterator);
  887. if (SUCCEEDED(*m_result))
  888. {
  889. boolean hasCurrent;
  890. *m_result = m_iterator->get_HasCurrent(&hasCurrent);
  891. if (SUCCEEDED(*m_result) && hasCurrent)
  892. {
  893. *m_result = m_iterator->get_Current(m_element.ReleaseAndGetAddressOf());
  894. if (FAILED(*m_result))
  895. {
  896. m_iterator = nullptr; // release the iterator if no elements are found
  897. }
  898. }
  899. else
  900. {
  901. m_iterator = nullptr; // release the iterator if no elements are found
  902. }
  903. }
  904. }
  905. class iterable_iterator_nothrow
  906. {
  907. public:
  908. #ifdef _XUTILITY_
  909. // muse be input_iterator_tag as use of one instance invalidates the other.
  910. typedef ::std::input_iterator_tag iterator_category;
  911. #endif
  912. typedef TSmart value_type;
  913. typedef ptrdiff_t difference_type;
  914. typedef const TSmart* pointer;
  915. typedef const TSmart& reference;
  916. iterable_iterator_nothrow(_In_ iterable_range_nothrow* range, int currentIndex) :
  917. m_range(range), m_i(currentIndex)
  918. {
  919. }
  920. bool operator==(iterable_iterator_nothrow const& other) const
  921. {
  922. return FAILED(*m_range->m_result) || (m_i == other.m_i);
  923. }
  924. bool operator!=(iterable_iterator_nothrow const& other) const
  925. {
  926. return !operator==(other);
  927. }
  928. reference operator*() const WI_NOEXCEPT
  929. {
  930. return m_range->m_element;
  931. }
  932. pointer operator->() const WI_NOEXCEPT
  933. {
  934. return wistd::addressof(m_range->m_element);
  935. }
  936. iterable_iterator_nothrow& operator++()
  937. {
  938. boolean hasCurrent;
  939. *m_range->m_result = m_range->m_iterator->MoveNext(&hasCurrent);
  940. if (SUCCEEDED(*m_range->m_result) && hasCurrent)
  941. {
  942. *m_range->m_result = m_range->m_iterator->get_Current(m_range->m_element.ReleaseAndGetAddressOf());
  943. if (SUCCEEDED(*m_range->m_result))
  944. {
  945. m_i++;
  946. }
  947. else
  948. {
  949. m_i = -1;
  950. }
  951. }
  952. else
  953. {
  954. m_i = -1;
  955. }
  956. return *this;
  957. }
  958. iterable_range_nothrow operator++(int)
  959. {
  960. iterable_range_nothrow old(*this);
  961. ++*this;
  962. return old;
  963. }
  964. private:
  965. iterable_range_nothrow* m_range;
  966. int m_i;
  967. };
  968. iterable_iterator_nothrow begin()
  969. {
  970. return iterable_iterator_nothrow(this, this->m_iterator ? 0 : -1);
  971. }
  972. iterable_iterator_nothrow end()
  973. {
  974. return iterable_iterator_nothrow(this, -1);
  975. }
  976. private:
  977. Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IIterator<T>> m_iterator;
  978. // This state is shared by all iterator instances
  979. // so use of one iterator can invalidate another's ability to dereference
  980. // that is allowed for input iterators.
  981. TSmart m_element;
  982. HRESULT* m_result;
  983. HRESULT m_resultStorage = S_OK;
  984. };
  985. #pragma endregion
  986. #ifdef WIL_ENABLE_EXCEPTIONS
  987. template <typename T> vector_range<ABI::Windows::Foundation::Collections::IVector<T>> get_range(ABI::Windows::Foundation::Collections::IVector<T> *v)
  988. {
  989. return vector_range<ABI::Windows::Foundation::Collections::IVector<T>>(v);
  990. }
  991. template <typename T> vector_range<ABI::Windows::Foundation::Collections::IVectorView<T>> get_range(ABI::Windows::Foundation::Collections::IVectorView<T> *v)
  992. {
  993. return vector_range<ABI::Windows::Foundation::Collections::IVectorView<T>>(v);
  994. }
  995. #endif // WIL_ENABLE_EXCEPTIONS
  996. template <typename T> vector_range<ABI::Windows::Foundation::Collections::IVector<T>, err_failfast_policy> get_range_failfast(ABI::Windows::Foundation::Collections::IVector<T> *v)
  997. {
  998. return vector_range<ABI::Windows::Foundation::Collections::IVector<T>, err_failfast_policy>(v);
  999. }
  1000. template <typename T> vector_range<ABI::Windows::Foundation::Collections::IVectorView<T>, err_failfast_policy> get_range_failfast(ABI::Windows::Foundation::Collections::IVectorView<T> *v)
  1001. {
  1002. return vector_range<ABI::Windows::Foundation::Collections::IVectorView<T>, err_failfast_policy>(v);
  1003. }
  1004. template <typename T> vector_range_nothrow<ABI::Windows::Foundation::Collections::IVector<T>> get_range_nothrow(ABI::Windows::Foundation::Collections::IVector<T> *v, HRESULT* result = nullptr)
  1005. {
  1006. return vector_range_nothrow<ABI::Windows::Foundation::Collections::IVector<T>>(v, result);
  1007. }
  1008. template <typename T> vector_range_nothrow<ABI::Windows::Foundation::Collections::IVectorView<T>> get_range_nothrow(ABI::Windows::Foundation::Collections::IVectorView<T> *v, HRESULT* result = nullptr)
  1009. {
  1010. return vector_range_nothrow<ABI::Windows::Foundation::Collections::IVectorView<T>>(v, result);
  1011. }
  1012. #ifdef WIL_ENABLE_EXCEPTIONS
  1013. template <typename T> iterable_range<T> get_range(ABI::Windows::Foundation::Collections::IIterable<T> *v)
  1014. {
  1015. return iterable_range<T>(v);
  1016. }
  1017. #endif // WIL_ENABLE_EXCEPTIONS
  1018. template <typename T> iterable_range<T, err_failfast_policy> get_range_failfast(ABI::Windows::Foundation::Collections::IIterable<T> *v)
  1019. {
  1020. return iterable_range<T, err_failfast_policy>(v);
  1021. }
  1022. template <typename T> iterable_range_nothrow<T> get_range_nothrow(ABI::Windows::Foundation::Collections::IIterable<T> *v, HRESULT* result = nullptr)
  1023. {
  1024. return iterable_range_nothrow<T>(v, result);
  1025. }
  1026. }
  1027. #pragma endregion
  1028. #ifdef WIL_ENABLE_EXCEPTIONS
  1029. #pragma region Global operator functions
  1030. #if defined(MIDL_NS_PREFIX) || defined(____x_ABI_CWindows_CFoundation_CIClosable_FWD_DEFINED__)
  1031. namespace ABI {
  1032. #endif
  1033. namespace Windows {
  1034. namespace Foundation {
  1035. namespace Collections {
  1036. template <typename X> typename wil::vector_range<IVector<X>>::vector_iterator begin(IVector<X>* v)
  1037. {
  1038. return typename wil::vector_range<IVector<X>>::vector_iterator(v, 0);
  1039. }
  1040. template <typename X> typename wil::vector_range<IVector<X>>::vector_iterator end(IVector<X>* v)
  1041. {
  1042. unsigned int size;
  1043. THROW_IF_FAILED(v->get_Size(&size));
  1044. return typename wil::vector_range<IVector<X>>::vector_iterator(v, size);
  1045. }
  1046. template <typename X> typename wil::vector_range<IVectorView<X>>::vector_iterator begin(IVectorView<X>* v)
  1047. {
  1048. return typename wil::vector_range<IVectorView<X>>::vector_iterator(v, 0);
  1049. }
  1050. template <typename X> typename wil::vector_range<IVectorView<X>>::vector_iterator end(IVectorView<X>* v)
  1051. {
  1052. unsigned int size;
  1053. THROW_IF_FAILED(v->get_Size(&size));
  1054. return typename wil::vector_range<IVectorView<X>>::vector_iterator(v, size);
  1055. }
  1056. template <typename X> typename wil::iterable_range<X>::iterable_iterator begin(IIterable<X>* i)
  1057. {
  1058. return typename wil::iterable_range<X>::iterable_iterator(i);
  1059. }
  1060. template <typename X> typename wil::iterable_range<X>::iterable_iterator end(IIterable<X>*)
  1061. {
  1062. return typename wil::iterable_range<X>::iterable_iterator();
  1063. }
  1064. } // namespace Collections
  1065. } // namespace Foundation
  1066. } // namespace Windows
  1067. #if defined(MIDL_NS_PREFIX) || defined(____x_ABI_CWindows_CFoundation_CIClosable_FWD_DEFINED__)
  1068. } // namespace ABI
  1069. #endif
  1070. #endif // WIL_ENABLE_EXCEPTIONS
  1071. #pragma endregion
  1072. namespace wil
  1073. {
  1074. #pragma region WinRT Async API helpers
  1075. /// @cond
  1076. namespace details
  1077. {
  1078. template <typename TResult, typename TFunc, typename ...Args,
  1079. typename wistd::enable_if<wistd::is_same<HRESULT, TResult>::value, int>::type = 0>
  1080. HRESULT CallAndHandleErrorsWithReturnType(TFunc&& func, Args&&... args)
  1081. {
  1082. return wistd::forward<TFunc>(func)(wistd::forward<Args>(args)...);
  1083. }
  1084. #ifdef WIL_ENABLE_EXCEPTIONS
  1085. template <typename TResult, typename TFunc, typename ...Args,
  1086. typename wistd::enable_if<wistd::is_same<void, TResult>::value, int>::type = 0>
  1087. HRESULT CallAndHandleErrorsWithReturnType(TFunc&& func, Args&&... args)
  1088. {
  1089. try
  1090. {
  1091. wistd::forward<TFunc>(func)(wistd::forward<Args>(args)...);
  1092. }
  1093. CATCH_RETURN();
  1094. return S_OK;
  1095. }
  1096. #endif
  1097. template <typename TFunc, typename ...Args>
  1098. HRESULT CallAndHandleErrors(TFunc&& func, Args&&... args)
  1099. {
  1100. return CallAndHandleErrorsWithReturnType<decltype(wistd::forward<TFunc>(func)(wistd::forward<Args>(args)...))>(
  1101. wistd::forward<TFunc>(func), wistd::forward<Args>(args)...);
  1102. }
  1103. // Get the last type of a template parameter pack.
  1104. // usage:
  1105. // LastType<int, bool>::type boolValue;
  1106. template <typename... Ts> struct LastType
  1107. {
  1108. template<typename T, typename... Ts> struct LastTypeOfTs
  1109. {
  1110. typedef typename LastTypeOfTs<Ts...>::type type;
  1111. };
  1112. template<typename T> struct LastTypeOfTs<T>
  1113. {
  1114. typedef T type;
  1115. };
  1116. template<typename... Ts>
  1117. static typename LastTypeOfTs<Ts...>::type LastTypeOfTsFunc() {}
  1118. typedef decltype(LastTypeOfTsFunc<Ts...>()) type;
  1119. };
  1120. // Takes a member function that has an out param like F(..., IAsyncAction**) or F(..., IAsyncOperation<bool>**)
  1121. // and returns IAsyncAction* or IAsyncOperation<bool>*.
  1122. template<typename I, typename ...P>
  1123. typename wistd::remove_pointer<typename LastType<P...>::type>::type GetReturnParamPointerType(HRESULT(STDMETHODCALLTYPE I::*)(P...));
  1124. // Use to determine the result type of the async action/operation interfaces or example
  1125. // decltype(GetAsyncResultType(action.get())) returns void
  1126. void GetAsyncResultType(ABI::Windows::Foundation::IAsyncAction*);
  1127. template <typename P> void GetAsyncResultType(ABI::Windows::Foundation::IAsyncActionWithProgress<P>*);
  1128. template <typename T> typename wil::details::MapAsyncOpResultType<T>::type GetAsyncResultType(ABI::Windows::Foundation::IAsyncOperation<T>*);
  1129. template <typename T, typename P> typename wil::details::MapAsyncOpProgressResultType<T, P>::type GetAsyncResultType(ABI::Windows::Foundation::IAsyncOperationWithProgress<T, P>*);
  1130. // Use to determine the result type of the async action/operation interfaces or example
  1131. // decltype(GetAsyncDelegateType(action.get())) returns void
  1132. ABI::Windows::Foundation::IAsyncActionCompletedHandler* GetAsyncDelegateType(ABI::Windows::Foundation::IAsyncAction*);
  1133. template <typename P> ABI::Windows::Foundation::IAsyncActionWithProgressCompletedHandler<P>* GetAsyncDelegateType(ABI::Windows::Foundation::IAsyncActionWithProgress<P>*);
  1134. template <typename T> ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>* GetAsyncDelegateType(ABI::Windows::Foundation::IAsyncOperation<T>*);
  1135. template <typename T, typename P> ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<T, P>* GetAsyncDelegateType(ABI::Windows::Foundation::IAsyncOperationWithProgress<T, P>*);
  1136. template <typename TBaseAgility, typename TIOperation, typename TFunction>
  1137. HRESULT RunWhenCompleteAction(_In_ TIOperation operation, TFunction&& func) WI_NOEXCEPT
  1138. {
  1139. using namespace Microsoft::WRL;
  1140. typedef wistd::remove_pointer_t<decltype(GetAsyncDelegateType(operation))> TIDelegate;
  1141. auto callback = Callback<Implements<RuntimeClassFlags<ClassicCom>, TIDelegate, TBaseAgility>>(
  1142. [func = wistd::forward<TFunction>(func)](TIOperation operation, ABI::Windows::Foundation::AsyncStatus status) mutable -> HRESULT
  1143. {
  1144. HRESULT hr = S_OK;
  1145. if (status != ABI::Windows::Foundation::AsyncStatus::Completed) // avoid a potentially costly marshaled QI / call if we completed successfully
  1146. {
  1147. ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
  1148. operation->QueryInterface(IID_PPV_ARGS(&asyncInfo)); // All must implement IAsyncInfo
  1149. asyncInfo->get_ErrorCode(&hr);
  1150. }
  1151. return CallAndHandleErrors(func, hr);
  1152. });
  1153. RETURN_IF_NULL_ALLOC(callback);
  1154. return operation->put_Completed(callback.Get());
  1155. }
  1156. template <typename TBaseAgility, typename TIOperation, typename TFunction>
  1157. HRESULT RunWhenComplete(_In_ TIOperation operation, TFunction&& func) WI_NOEXCEPT
  1158. {
  1159. using namespace Microsoft::WRL;
  1160. using namespace ABI::Windows::Foundation::Internal;
  1161. typedef wistd::remove_pointer_t<decltype(GetAsyncDelegateType(operation))> TIDelegate;
  1162. auto callback = Callback<Implements<RuntimeClassFlags<ClassicCom>, TIDelegate, TBaseAgility>>(
  1163. [func = wistd::forward<TFunction>(func)](TIOperation operation, ABI::Windows::Foundation::AsyncStatus status) mutable -> HRESULT
  1164. {
  1165. typename details::MapToSmartType<typename GetAbiType<typename wistd::remove_pointer<TIOperation>::type::TResult_complex>::type>::type result;
  1166. HRESULT hr = S_OK;
  1167. if (status == ABI::Windows::Foundation::AsyncStatus::Completed)
  1168. {
  1169. hr = operation->GetResults(result.GetAddressOf());
  1170. }
  1171. else
  1172. {
  1173. // avoid a potentially costly marshaled QI / call if we completed successfully
  1174. ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
  1175. operation->QueryInterface(IID_PPV_ARGS(&asyncInfo)); // all must implement this
  1176. asyncInfo->get_ErrorCode(&hr);
  1177. }
  1178. return CallAndHandleErrors(func, hr, result.Get());
  1179. });
  1180. RETURN_IF_NULL_ALLOC(callback);
  1181. return operation->put_Completed(callback.Get());
  1182. }
  1183. #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
  1184. template <typename TIOperation>
  1185. HRESULT WaitForCompletion(_In_ TIOperation operation, COWAIT_FLAGS flags, DWORD timeoutValue, _Out_opt_ bool* timedOut) WI_NOEXCEPT
  1186. {
  1187. typedef wistd::remove_pointer_t<decltype(GetAsyncDelegateType(operation))> TIDelegate;
  1188. class CompletionDelegate : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::Delegate>,
  1189. TIDelegate, Microsoft::WRL::FtmBase>
  1190. {
  1191. public:
  1192. HRESULT RuntimeClassInitialize()
  1193. {
  1194. RETURN_HR(m_completedEventHandle.create());
  1195. }
  1196. HRESULT STDMETHODCALLTYPE Invoke(_In_ TIOperation, ABI::Windows::Foundation::AsyncStatus status) override
  1197. {
  1198. m_status = status;
  1199. m_completedEventHandle.SetEvent();
  1200. return S_OK;
  1201. }
  1202. HANDLE GetEvent() const
  1203. {
  1204. return m_completedEventHandle.get();
  1205. }
  1206. ABI::Windows::Foundation::AsyncStatus GetStatus() const
  1207. {
  1208. return m_status;
  1209. }
  1210. private:
  1211. volatile ABI::Windows::Foundation::AsyncStatus m_status = ABI::Windows::Foundation::AsyncStatus::Started;
  1212. wil::unique_event_nothrow m_completedEventHandle;
  1213. };
  1214. WI_ASSERT(timedOut || (timeoutValue == INFINITE));
  1215. assign_to_opt_param(timedOut, false);
  1216. Microsoft::WRL::ComPtr<CompletionDelegate> completedDelegate;
  1217. RETURN_IF_FAILED(Microsoft::WRL::MakeAndInitialize<CompletionDelegate>(&completedDelegate));
  1218. RETURN_IF_FAILED(operation->put_Completed(completedDelegate.Get()));
  1219. HANDLE handles[] = { completedDelegate->GetEvent() };
  1220. DWORD dwHandleIndex;
  1221. HRESULT hr = CoWaitForMultipleHandles(flags, timeoutValue, ARRAYSIZE(handles), handles, &dwHandleIndex);
  1222. // If the caller is listening for timedOut, and we actually timed out, set the bool and return S_OK. Otherwise, fail.
  1223. if (timedOut && (hr == RPC_S_CALLPENDING))
  1224. {
  1225. *timedOut = true;
  1226. return S_OK;
  1227. }
  1228. RETURN_IF_FAILED(hr);
  1229. if (completedDelegate->GetStatus() != ABI::Windows::Foundation::AsyncStatus::Completed)
  1230. {
  1231. Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
  1232. operation->QueryInterface(IID_PPV_ARGS(&asyncInfo)); // all must implement this
  1233. hr = E_UNEXPECTED;
  1234. asyncInfo->get_ErrorCode(&hr); // error return ignored, ok?
  1235. return hr; // leave it to the caller to log failures.
  1236. }
  1237. return S_OK;
  1238. }
  1239. template <typename TIOperation, typename TIResults>
  1240. HRESULT WaitForCompletion(_In_ TIOperation operation, _Out_ TIResults result, COWAIT_FLAGS flags,
  1241. DWORD timeoutValue, _Out_opt_ bool* timedOut) WI_NOEXCEPT
  1242. {
  1243. RETURN_IF_FAILED_EXPECTED(details::WaitForCompletion(operation, flags, timeoutValue, timedOut));
  1244. return operation->GetResults(result);
  1245. }
  1246. #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
  1247. }
  1248. /// @endcond
  1249. /** Set the completion callback for an async operation to run a caller provided function.
  1250. Once complete the function is called with the error code result of the operation
  1251. and the async operation result (if applicable).
  1252. The function parameter list must be (HRESULT hr) for actions,
  1253. (HRESULT hr, IResultInterface* object) for operations that produce interfaces,
  1254. and (HRESULT hr, TResult value) for operations that produce value types.
  1255. ~~~
  1256. run_when_complete(getFileOp.Get(), [](HRESULT hr, IStorageFile* file) -> void
  1257. {
  1258. });
  1259. ~~~
  1260. for an agile callback use Microsoft::WRL::FtmBase
  1261. ~~~
  1262. run_when_complete<FtmBase>(getFileOp.Get(), [](HRESULT hr, IStorageFile* file) -> void
  1263. {
  1264. });
  1265. ~~~
  1266. Using the non throwing form:
  1267. ~~~
  1268. hr = run_when_complete_nothrow<StorageFile*>(getFileOp.Get(), [](HRESULT hr, IStorageFile* file) -> HRESULT
  1269. {
  1270. });
  1271. ~~~
  1272. */
  1273. //! Run a fuction when an async operation completes. Use Microsoft::WRL::FtmBase for TAgility to make the completion handler agile and run on the async thread.
  1274. template<typename TAgility = IUnknown, typename TFunc>
  1275. HRESULT run_when_complete_nothrow(_In_ ABI::Windows::Foundation::IAsyncAction* operation, TFunc&& func) WI_NOEXCEPT
  1276. {
  1277. return details::RunWhenCompleteAction<TAgility>(operation, wistd::forward<TFunc>(func));
  1278. }
  1279. template<typename TAgility = IUnknown, typename TResult, typename TFunc, typename TAsyncResult = typename wil::details::MapAsyncOpResultType<TResult>::type>
  1280. HRESULT run_when_complete_nothrow(_In_ ABI::Windows::Foundation::IAsyncOperation<TResult>* operation, TFunc&& func) WI_NOEXCEPT
  1281. {
  1282. return details::RunWhenComplete<TAgility>(operation, wistd::forward<TFunc>(func));
  1283. }
  1284. template<typename TAgility = IUnknown, typename TResult, typename TProgress, typename TFunc, typename TAsyncResult = typename wil::details::MapAsyncOpProgressResultType<TResult, TProgress>::type>
  1285. HRESULT run_when_complete_nothrow(_In_ ABI::Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress>* operation, TFunc&& func) WI_NOEXCEPT
  1286. {
  1287. return details::RunWhenComplete<TAgility>(operation, wistd::forward<TFunc>(func));
  1288. }
  1289. template<typename TAgility = IUnknown, typename TProgress, typename TFunc>
  1290. HRESULT run_when_complete_nothrow(_In_ ABI::Windows::Foundation::IAsyncActionWithProgress<TProgress>* operation, TFunc&& func) WI_NOEXCEPT
  1291. {
  1292. return details::RunWhenCompleteAction<TAgility>(operation, wistd::forward<TFunc>(func));
  1293. }
  1294. #ifdef WIL_ENABLE_EXCEPTIONS
  1295. //! Run a fuction when an async operation completes. Use Microsoft::WRL::FtmBase for TAgility to make the completion handler agile and run on the async thread.
  1296. template<typename TAgility = IUnknown, typename TFunc>
  1297. void run_when_complete(_In_ ABI::Windows::Foundation::IAsyncAction* operation, TFunc&& func)
  1298. {
  1299. THROW_IF_FAILED((details::RunWhenCompleteAction<TAgility>(operation, wistd::forward<TFunc>(func))));
  1300. }
  1301. template<typename TAgility = IUnknown, typename TResult, typename TFunc, typename TAsyncResult = typename wil::details::MapAsyncOpResultType<TResult>::type>
  1302. void run_when_complete(_In_ ABI::Windows::Foundation::IAsyncOperation<TResult>* operation, TFunc&& func)
  1303. {
  1304. THROW_IF_FAILED((details::RunWhenComplete<TAgility>(operation, wistd::forward<TFunc>(func))));
  1305. }
  1306. template<typename TAgility = IUnknown, typename TResult, typename TProgress, typename TFunc, typename TAsyncResult = typename wil::details::MapAsyncOpProgressResultType<TResult, TProgress>::type>
  1307. void run_when_complete(_In_ ABI::Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress>* operation, TFunc&& func)
  1308. {
  1309. THROW_IF_FAILED((details::RunWhenComplete<TAgility>(operation, wistd::forward<TFunc>(func))));
  1310. }
  1311. template<typename TAgility = IUnknown, typename TProgress, typename TFunc>
  1312. void run_when_complete(_In_ ABI::Windows::Foundation::IAsyncActionWithProgress<TProgress>* operation, TFunc&& func)
  1313. {
  1314. THROW_IF_FAILED((details::RunWhenCompleteAction<TAgility>(operation, wistd::forward<TFunc>(func))));
  1315. }
  1316. #endif
  1317. #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
  1318. /** Wait for an asynchronous operation to complete (or be canceled).
  1319. Use to synchronously wait on async operations on background threads.
  1320. Do not call from UI threads or STA threads as reentrancy will result.
  1321. ~~~
  1322. ComPtr<IAsyncOperation<StorageFile*>> op;
  1323. THROW_IF_FAILED(storageFileStatics->GetFileFromPathAsync(HStringReference(path).Get(), &op));
  1324. auto file = wil::wait_for_completion(op.Get());
  1325. ~~~
  1326. */
  1327. template <typename TAsync = ABI::Windows::Foundation::IAsyncAction>
  1328. inline HRESULT wait_for_completion_nothrow(_In_ TAsync* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) WI_NOEXCEPT
  1329. {
  1330. return details::WaitForCompletion(operation, flags, INFINITE, nullptr);
  1331. }
  1332. // These forms return the result from the async operation
  1333. template <typename TResult>
  1334. HRESULT wait_for_completion_nothrow(_In_ ABI::Windows::Foundation::IAsyncOperation<TResult>* operation,
  1335. _Out_ typename wil::details::MapAsyncOpResultType<TResult>::type* result,
  1336. COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) WI_NOEXCEPT
  1337. {
  1338. return details::WaitForCompletion(operation, result, flags, INFINITE, nullptr);
  1339. }
  1340. template <typename TResult, typename TProgress>
  1341. HRESULT wait_for_completion_nothrow(_In_ ABI::Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress>* operation,
  1342. _Out_ typename wil::details::MapAsyncOpProgressResultType<TResult, TProgress>::type* result,
  1343. COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) WI_NOEXCEPT
  1344. {
  1345. return details::WaitForCompletion(operation, result, flags, INFINITE, nullptr);
  1346. }
  1347. // Same as above, but allows caller to specify a timeout value.
  1348. // On timeout, S_OK is returned, with timedOut set to true.
  1349. template <typename TAsync = ABI::Windows::Foundation::IAsyncAction>
  1350. inline HRESULT wait_for_completion_or_timeout_nothrow(_In_ TAsync* operation,
  1351. DWORD timeoutValue, _Out_ bool* timedOut, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) WI_NOEXCEPT
  1352. {
  1353. return details::WaitForCompletion(operation, flags, timeoutValue, timedOut);
  1354. }
  1355. template <typename TResult>
  1356. HRESULT wait_for_completion_or_timeout_nothrow(_In_ ABI::Windows::Foundation::IAsyncOperation<TResult>* operation,
  1357. _Out_ typename wil::details::MapAsyncOpResultType<TResult>::type* result,
  1358. DWORD timeoutValue, _Out_ bool* timedOut, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) WI_NOEXCEPT
  1359. {
  1360. return details::WaitForCompletion(operation, result, flags, timeoutValue, timedOut);
  1361. }
  1362. template <typename TResult, typename TProgress>
  1363. HRESULT wait_for_completion_or_timeout_nothrow(_In_ ABI::Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress>* operation,
  1364. _Out_ typename wil::details::MapAsyncOpProgressResultType<TResult, TProgress>::type* result,
  1365. DWORD timeoutValue, _Out_ bool* timedOut, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) WI_NOEXCEPT
  1366. {
  1367. return details::WaitForCompletion(operation, result, flags, timeoutValue, timedOut);
  1368. }
  1369. #ifdef WIL_ENABLE_EXCEPTIONS
  1370. //! Wait for an asynchronous operation to complete (or be canceled).
  1371. template <typename TAsync = ABI::Windows::Foundation::IAsyncAction>
  1372. inline void wait_for_completion(_In_ TAsync* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS)
  1373. {
  1374. THROW_IF_FAILED(details::WaitForCompletion(operation, flags, INFINITE, nullptr));
  1375. }
  1376. template <typename TResult, typename TReturn = typename wil::details::MapToSmartType<typename wil::details::MapAsyncOpResultType<TResult>::type>::type>
  1377. TReturn
  1378. wait_for_completion(_In_ ABI::Windows::Foundation::IAsyncOperation<TResult>* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS)
  1379. {
  1380. TReturn result;
  1381. THROW_IF_FAILED(details::WaitForCompletion(operation, result.GetAddressOf(), flags, INFINITE, nullptr));
  1382. return result;
  1383. }
  1384. template <typename TResult, typename TProgress, typename TReturn = typename wil::details::MapToSmartType<typename wil::details::MapAsyncOpProgressResultType<TResult, TProgress>::type>::type>
  1385. TReturn
  1386. wait_for_completion(_In_ ABI::Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress>* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS)
  1387. {
  1388. TReturn result;
  1389. THROW_IF_FAILED(details::WaitForCompletion(operation, result.GetAddressOf(), flags, INFINITE, nullptr));
  1390. return result;
  1391. }
  1392. /** Similar to WaitForCompletion but this function encapsulates the creation of the async operation
  1393. making usage simpler.
  1394. ~~~
  1395. ComPtr<ILauncherStatics> launcher; // inited somewhere
  1396. auto result = call_and_wait_for_completion(launcher.Get(), &ILauncherStatics::LaunchUriAsync, uri.Get());
  1397. ~~~
  1398. */
  1399. template<typename I, typename ...P, typename ...Args>
  1400. auto call_and_wait_for_completion(I* object, HRESULT(STDMETHODCALLTYPE I::*func)(P...), Args&&... args)
  1401. {
  1402. Microsoft::WRL::ComPtr<typename wistd::remove_pointer<typename wistd::remove_pointer<typename details::LastType<P...>::type>::type>::type> op;
  1403. THROW_IF_FAILED((object->*func)(wistd::forward<Args>(args)..., &op));
  1404. return wil::wait_for_completion(op.Get());
  1405. }
  1406. #endif
  1407. #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
  1408. #pragma endregion
  1409. #pragma region WinRT object construction
  1410. #ifdef WIL_ENABLE_EXCEPTIONS
  1411. //! Get a WinRT activation factory object, usually using a IXXXStatics interface.
  1412. template <typename TInterface>
  1413. com_ptr<TInterface> GetActivationFactory(PCWSTR runtimeClass)
  1414. {
  1415. com_ptr<TInterface> result;
  1416. THROW_IF_FAILED(RoGetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(runtimeClass).Get(), IID_PPV_ARGS(&result)));
  1417. return result;
  1418. }
  1419. //! Get a WinRT object.
  1420. template <typename TInterface>
  1421. com_ptr<TInterface> ActivateInstance(PCWSTR runtimeClass)
  1422. {
  1423. com_ptr<IInspectable> result;
  1424. THROW_IF_FAILED(RoActivateInstance(Microsoft::WRL::Wrappers::HStringReference(runtimeClass).Get(), &result));
  1425. return result.query<TInterface>();
  1426. }
  1427. #endif
  1428. #pragma endregion
  1429. #pragma region Async production helpers
  1430. /// @cond
  1431. namespace details
  1432. {
  1433. template <typename TResult>
  1434. class SyncAsyncOp WrlFinal : public Microsoft::WRL::RuntimeClass<ABI::Windows::Foundation::IAsyncOperation<TResult>,
  1435. Microsoft::WRL::AsyncBase<ABI::Windows::Foundation::IAsyncOperationCompletedHandler<TResult>>>
  1436. {
  1437. // typedef typename MapToSmartType<TResult>::type TSmart;
  1438. using RuntimeClassT = typename SyncAsyncOp::RuntimeClassT;
  1439. InspectableClass(__super::z_get_rc_name_impl(), TrustLevel::BaseTrust);
  1440. public:
  1441. HRESULT RuntimeClassInitialize(const TResult& op)
  1442. {
  1443. m_result = op;
  1444. return S_OK;
  1445. }
  1446. IFACEMETHODIMP put_Completed(ABI::Windows::Foundation::IAsyncOperationCompletedHandler<TResult>* competed) override
  1447. {
  1448. competed->Invoke(this, ABI::Windows::Foundation::AsyncStatus::Completed);
  1449. return S_OK;
  1450. }
  1451. IFACEMETHODIMP get_Completed(ABI::Windows::Foundation::IAsyncOperationCompletedHandler<TResult>** competed) override
  1452. {
  1453. *competed = nullptr;
  1454. return S_OK;
  1455. }
  1456. IFACEMETHODIMP GetResults(TResult* result) override
  1457. {
  1458. *result = m_result;
  1459. return S_OK;
  1460. }
  1461. HRESULT OnStart() override { return S_OK; }
  1462. void OnClose() override { }
  1463. void OnCancel() override { }
  1464. private:
  1465. // needs to be MapToSmartType<TResult>::type to hold non trial types
  1466. TResult m_result;
  1467. };
  1468. extern const __declspec(selectany) wchar_t SyncAsyncActionName[] = L"SyncActionAction";
  1469. class SyncAsyncActionOp WrlFinal : public Microsoft::WRL::RuntimeClass<ABI::Windows::Foundation::IAsyncAction,
  1470. Microsoft::WRL::AsyncBase<ABI::Windows::Foundation::IAsyncActionCompletedHandler,
  1471. Microsoft::WRL::Details::Nil,
  1472. Microsoft::WRL::AsyncResultType::SingleResult
  1473. #ifndef _WRL_DISABLE_CAUSALITY_
  1474. ,Microsoft::WRL::AsyncCausalityOptions<SyncAsyncActionName>
  1475. #endif
  1476. >>
  1477. {
  1478. InspectableClass(InterfaceName_Windows_Foundation_IAsyncAction, TrustLevel::BaseTrust);
  1479. public:
  1480. IFACEMETHODIMP put_Completed(ABI::Windows::Foundation::IAsyncActionCompletedHandler* competed) override
  1481. {
  1482. competed->Invoke(this, ABI::Windows::Foundation::AsyncStatus::Completed);
  1483. return S_OK;
  1484. }
  1485. IFACEMETHODIMP get_Completed(ABI::Windows::Foundation::IAsyncActionCompletedHandler** competed) override
  1486. {
  1487. *competed = nullptr;
  1488. return S_OK;
  1489. }
  1490. IFACEMETHODIMP GetResults() override
  1491. {
  1492. return S_OK;
  1493. }
  1494. HRESULT OnStart() override { return S_OK; }
  1495. void OnClose() override { }
  1496. void OnCancel() override { }
  1497. };
  1498. }
  1499. /// @endcond
  1500. //! Creates a WinRT async operation object that implements IAsyncOperation<TResult>. Use mostly for testing and for mocking APIs.
  1501. template <typename TResult>
  1502. HRESULT make_synchronous_async_operation_nothrow(ABI::Windows::Foundation::IAsyncOperation<TResult>** result, const TResult& value)
  1503. {
  1504. return Microsoft::WRL::MakeAndInitialize<details::SyncAsyncOp<TResult>>(result, value);
  1505. }
  1506. //! Creates a WinRT async operation object that implements IAsyncAction. Use mostly for testing and for mocking APIs.
  1507. inline HRESULT make_synchronous_async_action_nothrow(ABI::Windows::Foundation::IAsyncAction** result)
  1508. {
  1509. return Microsoft::WRL::MakeAndInitialize<details::SyncAsyncActionOp>(result);
  1510. }
  1511. #ifdef WIL_ENABLE_EXCEPTIONS
  1512. //! Creates a WinRT async operation object that implements IAsyncOperation<TResult>. Use mostly for testing and for mocking APIs.
  1513. // TODO: map TRealResult and TSmartResult into SyncAsyncOp.
  1514. template <typename TResult, typename TRealResult = typename details::MapAsyncOpResultType<TResult>::type, typename TSmartResult = typename details::MapToSmartType<TRealResult>::type>
  1515. void make_synchronous_async_operation(ABI::Windows::Foundation::IAsyncOperation<TResult>** result, const TResult& value)
  1516. {
  1517. THROW_IF_FAILED((Microsoft::WRL::MakeAndInitialize<details::SyncAsyncOp<TResult>>(result, value)));
  1518. }
  1519. //! Creates a WinRT async operation object that implements IAsyncAction. Use mostly for testing and for mocking APIs.
  1520. inline void make_synchronous_async_action(ABI::Windows::Foundation::IAsyncAction** result)
  1521. {
  1522. THROW_IF_FAILED((Microsoft::WRL::MakeAndInitialize<details::SyncAsyncActionOp>(result)));
  1523. }
  1524. #endif
  1525. #pragma endregion
  1526. #pragma region EventRegistrationToken RAII wrapper
  1527. // unique_winrt_event_token[_cx] is an RAII wrapper around EventRegistrationToken. When the unique_winrt_event_token[_cx] is
  1528. // destroyed, the event is automatically unregistered. Declare a wil::unique_winrt_event_token[_cx]<T> at the scope the event
  1529. // should be registered for (often they are tied to object lifetime), where T is the type of the event sender
  1530. // wil::unique_winrt_event_token_cx<Windows::UI::Xaml::Controls::Button> m_token;
  1531. //
  1532. // Macros have been defined to register for handling the event and then returning an unique_winrt_event_token[_cx]. These
  1533. // macros simply hide the function references for adding and removing the event.
  1534. // C++/CX m_token = WI_MakeUniqueWinRtEventTokenCx(ExampleEventName, sender, handler);
  1535. // ABI m_token = WI_MakeUniqueWinRtEventToken(ExampleEventName, sender, handler, &m_token); // Exception and failfast
  1536. // ABI RETURN_IF_FAILED(WI_MakeUniqueWinRtEventTokenNoThrow(ExampleEventName, sender, handler, &m_token)); // No throw variant
  1537. //
  1538. // When the wrapper is destroyed, the handler will be unregistered. You can explicitly unregister the handler prior.
  1539. // m_token.reset();
  1540. //
  1541. // You can release the EventRegistrationToken from being managed by the wrapper by calling .release()
  1542. // m_token.release(); // DANGER: no longer being managed
  1543. //
  1544. // If you just need the value of the EventRegistrationToken you can call .get()
  1545. // m_token.get();
  1546. //
  1547. // See "onecore\shell\tests\wil\UniqueWinRTEventTokenTests.cpp" for more examples of usage in ABI and C++/CX.
  1548. #ifdef __cplusplus_winrt
  1549. namespace details
  1550. {
  1551. template<typename T> struct remove_reference { typedef T type; };
  1552. template<typename T> struct remove_reference<T^> { typedef T type; };
  1553. }
  1554. template<typename T>
  1555. class unique_winrt_event_token_cx
  1556. {
  1557. using removal_func = void(T::*)(Windows::Foundation::EventRegistrationToken);
  1558. using static_removal_func = void(__cdecl *)(Windows::Foundation::EventRegistrationToken);
  1559. public:
  1560. unique_winrt_event_token_cx() = default;
  1561. unique_winrt_event_token_cx(Windows::Foundation::EventRegistrationToken token, T^ sender, removal_func removalFunction) WI_NOEXCEPT :
  1562. m_token(token),
  1563. m_weakSender(sender),
  1564. m_removalFunction(removalFunction)
  1565. {}
  1566. unique_winrt_event_token_cx(Windows::Foundation::EventRegistrationToken token, static_removal_func removalFunction) WI_NOEXCEPT :
  1567. m_token(token),
  1568. m_staticRemovalFunction(removalFunction)
  1569. {}
  1570. unique_winrt_event_token_cx(const unique_winrt_event_token_cx&) = delete;
  1571. unique_winrt_event_token_cx& operator=(const unique_winrt_event_token_cx&) = delete;
  1572. unique_winrt_event_token_cx(unique_winrt_event_token_cx&& other) WI_NOEXCEPT :
  1573. m_token(other.m_token),
  1574. m_weakSender(wistd::move(other.m_weakSender)),
  1575. m_removalFunction(other.m_removalFunction),
  1576. m_staticRemovalFunction(other.m_staticRemovalFunction)
  1577. {
  1578. other.m_token = {};
  1579. other.m_weakSender = nullptr;
  1580. other.m_removalFunction = nullptr;
  1581. other.m_staticRemovalFunction = nullptr;
  1582. }
  1583. unique_winrt_event_token_cx& operator=(unique_winrt_event_token_cx&& other) WI_NOEXCEPT
  1584. {
  1585. if (this != wistd::addressof(other))
  1586. {
  1587. reset();
  1588. wistd::swap_wil(m_token, other.m_token);
  1589. wistd::swap_wil(m_weakSender, other.m_weakSender);
  1590. wistd::swap_wil(m_removalFunction, other.m_removalFunction);
  1591. wistd::swap_wil(m_staticRemovalFunction, other.m_staticRemovalFunction);
  1592. }
  1593. return *this;
  1594. }
  1595. ~unique_winrt_event_token_cx() WI_NOEXCEPT
  1596. {
  1597. reset();
  1598. }
  1599. explicit operator bool() const WI_NOEXCEPT
  1600. {
  1601. return (m_token.Value != 0);
  1602. }
  1603. Windows::Foundation::EventRegistrationToken get() const WI_NOEXCEPT
  1604. {
  1605. return m_token;
  1606. }
  1607. void reset() noexcept
  1608. {
  1609. if (m_token.Value != 0)
  1610. {
  1611. if (m_staticRemovalFunction)
  1612. {
  1613. (*m_staticRemovalFunction)(m_token);
  1614. }
  1615. else
  1616. {
  1617. auto resolvedSender = m_weakSender.Resolve<T>();
  1618. if (resolvedSender)
  1619. {
  1620. (resolvedSender->*m_removalFunction)(m_token);
  1621. }
  1622. }
  1623. release();
  1624. }
  1625. }
  1626. // Stops the wrapper from managing resource and returns the EventRegistrationToken.
  1627. Windows::Foundation::EventRegistrationToken release() WI_NOEXCEPT
  1628. {
  1629. auto token = m_token;
  1630. m_token = {};
  1631. m_weakSender = nullptr;
  1632. m_removalFunction = nullptr;
  1633. m_staticRemovalFunction = nullptr;
  1634. return token;
  1635. }
  1636. private:
  1637. Windows::Foundation::EventRegistrationToken m_token = {};
  1638. Platform::WeakReference m_weakSender;
  1639. removal_func m_removalFunction = nullptr;
  1640. static_removal_func m_staticRemovalFunction = nullptr;
  1641. };
  1642. #endif
  1643. template<typename T>
  1644. class unique_winrt_event_token
  1645. {
  1646. using removal_func = HRESULT(__stdcall T::*)(::EventRegistrationToken);
  1647. public:
  1648. unique_winrt_event_token() = default;
  1649. unique_winrt_event_token(::EventRegistrationToken token, T* sender, removal_func removalFunction) WI_NOEXCEPT :
  1650. m_token(token),
  1651. m_removalFunction(removalFunction)
  1652. {
  1653. m_weakSender = wil::com_weak_query_failfast(sender);
  1654. }
  1655. unique_winrt_event_token(const unique_winrt_event_token&) = delete;
  1656. unique_winrt_event_token& operator=(const unique_winrt_event_token&) = delete;
  1657. unique_winrt_event_token(unique_winrt_event_token&& other) WI_NOEXCEPT :
  1658. m_token(other.m_token),
  1659. m_weakSender(wistd::move(other.m_weakSender)),
  1660. m_removalFunction(other.m_removalFunction)
  1661. {
  1662. other.m_token = {};
  1663. other.m_removalFunction = nullptr;
  1664. }
  1665. unique_winrt_event_token& operator=(unique_winrt_event_token&& other) WI_NOEXCEPT
  1666. {
  1667. if (this != wistd::addressof(other))
  1668. {
  1669. reset();
  1670. wistd::swap_wil(m_token, other.m_token);
  1671. wistd::swap_wil(m_weakSender, other.m_weakSender);
  1672. wistd::swap_wil(m_removalFunction, other.m_removalFunction);
  1673. }
  1674. return *this;
  1675. }
  1676. ~unique_winrt_event_token() WI_NOEXCEPT
  1677. {
  1678. reset();
  1679. }
  1680. explicit operator bool() const WI_NOEXCEPT
  1681. {
  1682. return (m_token.value != 0);
  1683. }
  1684. ::EventRegistrationToken get() const WI_NOEXCEPT
  1685. {
  1686. return m_token;
  1687. }
  1688. void reset() WI_NOEXCEPT
  1689. {
  1690. if (m_token.value != 0)
  1691. {
  1692. // If T cannot be QI'ed from the weak object then T is not a COM interface.
  1693. auto resolvedSender = m_weakSender.try_query<T>();
  1694. if (resolvedSender)
  1695. {
  1696. FAIL_FAST_IF_FAILED((resolvedSender.get()->*m_removalFunction)(m_token));
  1697. }
  1698. release();
  1699. }
  1700. }
  1701. // Stops the wrapper from managing resource and returns the EventRegistrationToken.
  1702. ::EventRegistrationToken release() WI_NOEXCEPT
  1703. {
  1704. auto token = m_token;
  1705. m_token = {};
  1706. m_weakSender = nullptr;
  1707. m_removalFunction = nullptr;
  1708. return token;
  1709. }
  1710. private:
  1711. ::EventRegistrationToken m_token = {};
  1712. wil::com_weak_ref_failfast m_weakSender;
  1713. removal_func m_removalFunction = nullptr;
  1714. };
  1715. namespace details
  1716. {
  1717. #ifdef __cplusplus_winrt
  1718. // Handles registration of the event handler to the subscribing object and then wraps the EventRegistrationToken in unique_winrt_event_token.
  1719. // Not intended to be directly called. Use the WI_MakeUniqueWinRtEventTokenCx macro to abstract away specifying the functions that handle addition and removal.
  1720. template<typename T, typename addition_func, typename removal_func, typename handler>
  1721. inline wil::unique_winrt_event_token_cx<T> make_unique_winrt_event_token_cx(T^ sender, addition_func additionFunc, removal_func removalFunc, handler^ h)
  1722. {
  1723. auto rawToken = (sender->*additionFunc)(h);
  1724. wil::unique_winrt_event_token_cx<T> temp(rawToken, sender, removalFunc);
  1725. return temp;
  1726. }
  1727. template<typename T, typename addition_func, typename removal_func, typename handler>
  1728. inline wil::unique_winrt_event_token_cx<T> make_unique_winrt_static_event_token_cx(addition_func additionFunc, removal_func removalFunc, handler^ h)
  1729. {
  1730. auto rawToken = (*additionFunc)(h);
  1731. wil::unique_winrt_event_token_cx<T> temp(rawToken, removalFunc);
  1732. return temp;
  1733. }
  1734. #endif // __cplusplus_winrt
  1735. // Handles registration of the event handler to the subscribing object and then wraps the EventRegistrationToken in unique_winrt_event_token.
  1736. // Not intended to be directly called. Use the WI_MakeUniqueWinRtEventToken macro to abstract away specifying the functions that handle addition and removal.
  1737. template<typename err_policy = wil::err_returncode_policy, typename T, typename addition_func, typename removal_func, typename handler>
  1738. inline auto make_unique_winrt_event_token(T* sender, addition_func additionFunc, removal_func removalFunc, handler h, wil::unique_winrt_event_token<T>* token_reference)
  1739. {
  1740. ::EventRegistrationToken rawToken;
  1741. err_policy::HResult((sender->*additionFunc)(h, &rawToken));
  1742. *token_reference = wil::unique_winrt_event_token<T>(rawToken, sender, removalFunc);
  1743. return err_policy::OK();
  1744. }
  1745. // Overload make function to allow for returning the constructed object when not using HRESULT based code.
  1746. template<typename err_policy = wil::err_returncode_policy, typename T, typename addition_func, typename removal_func, typename handler>
  1747. inline typename wistd::enable_if<!wistd::is_same<err_policy, wil::err_returncode_policy>::value, wil::unique_winrt_event_token<T>>::type
  1748. make_unique_winrt_event_token(T* sender, addition_func additionFunc, removal_func removalFunc, handler h)
  1749. {
  1750. ::EventRegistrationToken rawToken;
  1751. err_policy::HResult((sender->*additionFunc)(h, &rawToken));
  1752. return wil::unique_winrt_event_token<T>(rawToken, sender, removalFunc);
  1753. }
  1754. } // namespace details
  1755. // Helper macros to abstract function names for event addition and removal.
  1756. #ifdef __cplusplus_winrt
  1757. #define WI_MakeUniqueWinRtEventTokenCx(_event, _object, _handler) \
  1758. wil::details::make_unique_winrt_event_token_cx( \
  1759. _object, \
  1760. &wil::details::remove_reference<decltype(_object)>::type::##_event##::add, \
  1761. &wil::details::remove_reference<decltype(_object)>::type::##_event##::remove, \
  1762. _handler)
  1763. #define WI_MakeUniqueWinRtStaticEventTokenCx(_event, _baseType, _handler) \
  1764. wil::details::make_unique_winrt_static_event_token_cx<_baseType>( \
  1765. &##_baseType##::##_event##::add, \
  1766. &##_baseType##::##_event##::remove, \
  1767. _handler)
  1768. #endif // __cplusplus_winrt
  1769. #ifdef WIL_ENABLE_EXCEPTIONS
  1770. #define WI_MakeUniqueWinRtEventToken(_event, _object, _handler) \
  1771. wil::details::make_unique_winrt_event_token<wil::err_exception_policy>( \
  1772. _object, \
  1773. &wistd::remove_pointer<decltype(_object)>::type::add_##_event, \
  1774. &wistd::remove_pointer<decltype(_object)>::type::remove_##_event, \
  1775. _handler)
  1776. #endif // WIL_ENABLE_EXCEPTIONS
  1777. #define WI_MakeUniqueWinRtEventTokenNoThrow(_event, _object, _handler, _token_reference) \
  1778. wil::details::make_unique_winrt_event_token( \
  1779. _object, \
  1780. &wistd::remove_pointer<decltype(_object)>::type::add_##_event, \
  1781. &wistd::remove_pointer<decltype(_object)>::type::remove_##_event, \
  1782. _handler, \
  1783. _token_reference)
  1784. #define WI_MakeUniqueWinRtEventTokenFailFast(_event, _object, _handler) \
  1785. wil::details::make_unique_winrt_event_token<wil::err_failfast_policy>( \
  1786. _object, \
  1787. &wistd::remove_pointer<decltype(_object)>::type::add_##_event, \
  1788. &wistd::remove_pointer<decltype(_object)>::type::remove_##_event, \
  1789. _handler)
  1790. #pragma endregion // EventRegistrationToken RAII wrapper
  1791. } // namespace wil
  1792. #if (NTDDI_VERSION >= NTDDI_WINBLUE)
  1793. template <>
  1794. struct ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Foundation::IAsyncAction*> :
  1795. ABI::Windows::Foundation::IAsyncOperation_impl<ABI::Windows::Foundation::IAsyncAction*>
  1796. {
  1797. static const wchar_t* z_get_rc_name_impl()
  1798. {
  1799. return L"IAsyncOperation<IAsyncAction*>";
  1800. }
  1801. };
  1802. template <typename P>
  1803. struct ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Foundation::IAsyncAction*,P> :
  1804. ABI::Windows::Foundation::IAsyncOperationWithProgress_impl<ABI::Windows::Foundation::IAsyncAction*, P>
  1805. {
  1806. static const wchar_t* z_get_rc_name_impl()
  1807. {
  1808. return L"IAsyncOperationWithProgress<IAsyncAction*,P>";
  1809. }
  1810. };
  1811. template <typename T>
  1812. struct ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Foundation::IAsyncOperation<T>*> :
  1813. ABI::Windows::Foundation::IAsyncOperation_impl<ABI::Windows::Foundation::IAsyncOperation<T>*>
  1814. {
  1815. static const wchar_t* z_get_rc_name_impl()
  1816. {
  1817. return L"IAsyncOperation<IAsyncOperation<T>*>";
  1818. }
  1819. };
  1820. template <typename T, typename P>
  1821. struct ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Foundation::IAsyncOperation<T>*, P> :
  1822. ABI::Windows::Foundation::IAsyncOperationWithProgress_impl<ABI::Windows::Foundation::IAsyncOperation<T>*, P>
  1823. {
  1824. static const wchar_t* z_get_rc_name_impl()
  1825. {
  1826. return L"IAsyncOperationWithProgress<IAsyncOperation<T>*,P>";
  1827. }
  1828. };
  1829. template <typename T, typename P>
  1830. struct ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Foundation::IAsyncOperationWithProgress<T, P>*> :
  1831. ABI::Windows::Foundation::IAsyncOperation_impl<ABI::Windows::Foundation::IAsyncOperationWithProgress<T, P>*>
  1832. {
  1833. static const wchar_t* z_get_rc_name_impl()
  1834. {
  1835. return L"IAsyncOperation<IAsyncOperationWithProgress<T,P>*>";
  1836. }
  1837. };
  1838. template <typename T, typename P, typename Z>
  1839. struct ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Foundation::IAsyncOperationWithProgress<T,P>*, Z> :
  1840. ABI::Windows::Foundation::IAsyncOperationWithProgress_impl<ABI::Windows::Foundation::IAsyncOperationWithProgress<T,P>*, Z>
  1841. {
  1842. static const wchar_t* z_get_rc_name_impl()
  1843. {
  1844. return L"IAsyncOperationWithProgress<IAsyncOperationWithProgress<T,P>*,Z>";
  1845. }
  1846. };
  1847. template <>
  1848. struct ABI::Windows::Foundation::IAsyncOperationCompletedHandler<ABI::Windows::Foundation::IAsyncAction*> :
  1849. ABI::Windows::Foundation::IAsyncOperationCompletedHandler_impl<ABI::Windows::Foundation::IAsyncAction*>
  1850. {
  1851. static const wchar_t* z_get_rc_name_impl()
  1852. {
  1853. return L"IAsyncOperationCompletedHandler<IAsyncAction*>";
  1854. }
  1855. };
  1856. template <typename P>
  1857. struct ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<ABI::Windows::Foundation::IAsyncAction*, P> :
  1858. ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler_impl<ABI::Windows::Foundation::IAsyncAction*, P>
  1859. {
  1860. static const wchar_t* z_get_rc_name_impl()
  1861. {
  1862. return L"IAsyncOperationWithProgressCompletedHandler<IAsyncAction*,P>";
  1863. }
  1864. };
  1865. template <typename T>
  1866. struct ABI::Windows::Foundation::IAsyncOperationCompletedHandler<ABI::Windows::Foundation::IAsyncOperation<T>*> :
  1867. ABI::Windows::Foundation::IAsyncOperationCompletedHandler_impl<ABI::Windows::Foundation::IAsyncOperation<T>*>
  1868. {
  1869. static const wchar_t* z_get_rc_name_impl()
  1870. {
  1871. return L"IAsyncOperationCompletedHandler<IAsyncOperation<T>*>";
  1872. }
  1873. };
  1874. template <typename T, typename P>
  1875. struct ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<ABI::Windows::Foundation::IAsyncOperation<T>*, P> :
  1876. ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler_impl<ABI::Windows::Foundation::IAsyncOperation<T>*, P>
  1877. {
  1878. static const wchar_t* z_get_rc_name_impl()
  1879. {
  1880. return L"IAsyncOperationWithProgressCompletedHandler<IAsyncOperation<T>*,P>";
  1881. }
  1882. };
  1883. template <typename T, typename P>
  1884. struct ABI::Windows::Foundation::IAsyncOperationCompletedHandler<ABI::Windows::Foundation::IAsyncOperationWithProgress<T, P>*> :
  1885. ABI::Windows::Foundation::IAsyncOperationCompletedHandler_impl<ABI::Windows::Foundation::IAsyncOperationWithProgress<T, P>*>
  1886. {
  1887. static const wchar_t* z_get_rc_name_impl()
  1888. {
  1889. return L"IAsyncOperationCompletedHandler<IAsyncOperationWithProgress<T>*>";
  1890. }
  1891. };
  1892. template <typename T, typename P, typename Z>
  1893. struct ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<ABI::Windows::Foundation::IAsyncOperationWithProgress<T, P>*, Z> :
  1894. ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler_impl<ABI::Windows::Foundation::IAsyncOperationWithProgress<T, P>*, Z>
  1895. {
  1896. static const wchar_t* z_get_rc_name_impl()
  1897. {
  1898. return L"IAsyncOperationWithProgressCompletedHandler<IAsyncOperationWithProgress<T,P>*,Z>";
  1899. }
  1900. };
  1901. #endif // NTDDI_VERSION >= NTDDI_WINBLUE
  1902. #if !defined(MIDL_NS_PREFIX) && !defined(____x_ABI_CWindows_CFoundation_CIClosable_FWD_DEFINED__)
  1903. // Internal .idl files use the namespace without the ABI prefix. Macro out ABI for that case
  1904. #pragma pop_macro("ABI")
  1905. #endif
  1906. #ifdef WIL_ENABLE_EXCEPTIONS
  1907. namespace std
  1908. {
  1909. //! Specialization of `std::less` for `Microsoft::WRL::Wrappers::HString` that uses `hstring_less` for the
  1910. //! comparison function object.
  1911. template <>
  1912. struct less<Microsoft::WRL::Wrappers::HString> :
  1913. public wil::hstring_less
  1914. {
  1915. };
  1916. //! Specialization of `std::less` for `wil::unique_hstring` that uses `hstring_less` for the comparison function
  1917. //! object.
  1918. template <>
  1919. struct less<wil::unique_hstring> :
  1920. public wil::hstring_less
  1921. {
  1922. };
  1923. }
  1924. #endif
  1925. #endif // __WIL_WINRT_INCLUDED