You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2229 lines
86KB

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