Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

5987 lines
238KB

  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. #include "result_macros.h"
  12. #include "wistd_functional.h"
  13. #include "wistd_memory.h"
  14. #pragma warning(push)
  15. #pragma warning(disable:26135 26110) // Missing locking annotation, Caller failing to hold lock
  16. #pragma warning(disable:4714) // __forceinline not honored
  17. #ifndef __WIL_RESOURCE
  18. #define __WIL_RESOURCE
  19. // stdint.h and intsafe.h have conflicting definitions, so it's not safe to include either to pick up our dependencies,
  20. // so the definitions we need are copied below
  21. #ifdef _WIN64
  22. #define __WI_SIZE_MAX 0xffffffffffffffffui64 // UINT64_MAX
  23. #else /* _WIN64 */
  24. #define __WI_SIZE_MAX 0xffffffffui32 // UINT32_MAX
  25. #endif /* _WIN64 */
  26. // Forward declaration
  27. /// @cond
  28. namespace Microsoft
  29. {
  30. namespace WRL
  31. {
  32. template <typename T>
  33. class ComPtr;
  34. }
  35. }
  36. /// @endcond
  37. namespace wil
  38. {
  39. //! This type copies the current value of GetLastError at construction and resets the last error
  40. //! to that value when it is destroyed.
  41. //!
  42. //! This is useful in library code that runs during a value's destructor. If the library code could
  43. //! inadvertantly change the value of GetLastError (by calling a Win32 API or similar), it should
  44. //! instantiate a value of this type before calling the library function in order to preserve the
  45. //! GetLastError value the user would expect.
  46. //!
  47. //! This construct exists to hide kernel mode/user mode differences in wil library code.
  48. //!
  49. //! Example usage:
  50. //!
  51. //! if (!CreateFile(...))
  52. //! {
  53. //! auto lastError = wil::last_error_context();
  54. //! WriteFile(g_hlog, logdata);
  55. //! }
  56. //!
  57. class last_error_context
  58. {
  59. #ifndef WIL_KERNEL_MODE
  60. bool m_dismissed;
  61. DWORD m_error;
  62. public:
  63. last_error_context() WI_NOEXCEPT :
  64. m_dismissed(false),
  65. m_error(::GetLastError())
  66. {
  67. }
  68. last_error_context(last_error_context&& other) WI_NOEXCEPT
  69. {
  70. operator=(wistd::move(other));
  71. }
  72. last_error_context & operator=(last_error_context&& other) WI_NOEXCEPT
  73. {
  74. m_dismissed = other.m_dismissed;
  75. m_error = other.m_error;
  76. other.m_dismissed = true;
  77. return *this;
  78. }
  79. ~last_error_context() WI_NOEXCEPT
  80. {
  81. if (!m_dismissed)
  82. {
  83. ::SetLastError(m_error);
  84. }
  85. }
  86. //! last_error_context doesn't own a concrete resource, so therefore
  87. //! it just disarms its destructor and returns void.
  88. void release() WI_NOEXCEPT
  89. {
  90. WI_ASSERT(!m_dismissed);
  91. m_dismissed = true;
  92. }
  93. #else
  94. public:
  95. void release() WI_NOEXCEPT { }
  96. #endif // WIL_KERNEL_MODE
  97. };
  98. /// @cond
  99. namespace details
  100. {
  101. typedef wistd::integral_constant<size_t, 0> pointer_access_all; // get(), release(), addressof(), and '&' are available
  102. typedef wistd::integral_constant<size_t, 1> pointer_access_noaddress; // get() and release() are available
  103. typedef wistd::integral_constant<size_t, 2> pointer_access_none; // the raw pointer is not available
  104. template <typename pointer, // The handle type
  105. typename close_fn_t, // The handle close function type
  106. close_fn_t close_fn, // * and function pointer
  107. typename pointer_access = pointer_access_all, // all, noaddress or none to control pointer method access
  108. typename pointer_storage = pointer, // The type used to store the handle (usually the same as the handle itself)
  109. typename invalid_t = pointer, // The invalid handle value type
  110. invalid_t invalid = invalid_t(), // * and its value (default ZERO value)
  111. typename pointer_invalid = wistd::nullptr_t> // nullptr_t if the invalid handle value is compatible with nullptr, otherwise pointer
  112. struct resource_policy
  113. {
  114. typedef pointer_storage pointer_storage;
  115. typedef pointer pointer;
  116. typedef pointer_invalid pointer_invalid;
  117. typedef pointer_access pointer_access;
  118. __forceinline static pointer_storage invalid_value() WI_NOEXCEPT { return (pointer)invalid; }
  119. __forceinline static bool is_valid(pointer_storage value) WI_NOEXCEPT { return (static_cast<pointer>(value) != (pointer)invalid); }
  120. __forceinline static void close(pointer_storage value) WI_NOEXCEPT { wistd::invoke(close_fn, value); }
  121. inline static void close_reset(pointer_storage value) WI_NOEXCEPT
  122. {
  123. auto preserveError = last_error_context();
  124. wistd::invoke(close_fn, value);
  125. }
  126. };
  127. // This class provides the pointer storage behind the implementation of unique_any_t utilizing the given
  128. // resource_policy. It is separate from unique_any_t to allow a type-specific specialization class to plug
  129. // into the inheritance chain between unique_any_t and unique_storage. This allows classes like unique_event
  130. // to be a unique_any formed class, but also expose methods like SetEvent directly.
  131. template <typename policy>
  132. class unique_storage
  133. {
  134. protected:
  135. typedef policy policy;
  136. typedef typename policy::pointer_storage pointer_storage;
  137. typedef typename policy::pointer pointer;
  138. typedef unique_storage<policy> base_storage;
  139. unique_storage() WI_NOEXCEPT :
  140. m_ptr(policy::invalid_value())
  141. {
  142. }
  143. explicit unique_storage(pointer_storage ptr) WI_NOEXCEPT :
  144. m_ptr(ptr)
  145. {
  146. }
  147. unique_storage(unique_storage &&other) WI_NOEXCEPT :
  148. m_ptr(wistd::move(other.m_ptr))
  149. {
  150. other.m_ptr = policy::invalid_value();
  151. }
  152. ~unique_storage() WI_NOEXCEPT
  153. {
  154. if (policy::is_valid(m_ptr))
  155. {
  156. policy::close(m_ptr);
  157. }
  158. }
  159. void replace(unique_storage &&other) WI_NOEXCEPT
  160. {
  161. reset(other.m_ptr);
  162. other.m_ptr = policy::invalid_value();
  163. }
  164. public:
  165. bool is_valid() const WI_NOEXCEPT
  166. {
  167. return policy::is_valid(m_ptr);
  168. }
  169. void reset(pointer_storage ptr = policy::invalid_value()) WI_NOEXCEPT
  170. {
  171. if (policy::is_valid(m_ptr))
  172. {
  173. policy::close_reset(m_ptr);
  174. }
  175. m_ptr = ptr;
  176. }
  177. void reset(wistd::nullptr_t) WI_NOEXCEPT
  178. {
  179. static_assert(wistd::is_same<typename policy::pointer_invalid, wistd::nullptr_t>::value, "reset(nullptr): valid only for handle types using nullptr as the invalid value");
  180. reset();
  181. }
  182. pointer get() const WI_NOEXCEPT
  183. {
  184. return static_cast<pointer>(m_ptr);
  185. }
  186. pointer_storage release() WI_NOEXCEPT
  187. {
  188. static_assert(!wistd::is_same<typename policy::pointer_access, pointer_access_none>::value, "release(): the raw handle value is not available for this resource class");
  189. auto ptr = m_ptr;
  190. m_ptr = policy::invalid_value();
  191. return ptr;
  192. }
  193. pointer_storage *addressof() WI_NOEXCEPT
  194. {
  195. static_assert(wistd::is_same<typename policy::pointer_access, pointer_access_all>::value, "addressof(): the address of the raw handle is not available for this resource class");
  196. return &m_ptr;
  197. }
  198. private:
  199. pointer_storage m_ptr;
  200. };
  201. } // details
  202. /// @endcond
  203. // This class when paired with unique_storage and an optional type-specific specialization class implements
  204. // the same interface as STL's unique_ptr<> for resource handle types. It is a non-copyable, yet movable class
  205. // supporting attach (reset), detach (release), retrieval (get()).
  206. template <typename storage_t>
  207. class unique_any_t : public storage_t
  208. {
  209. public:
  210. typedef typename storage_t::policy policy;
  211. typedef typename policy::pointer_storage pointer_storage;
  212. typedef typename policy::pointer pointer;
  213. unique_any_t(unique_any_t const &) = delete;
  214. unique_any_t& operator=(unique_any_t const &) = delete;
  215. // Note that the default constructor really shouldn't be needed (taken care of by the forwarding constructor below), but
  216. // the forwarding constructor causes an internal compiler error when the class is used in a C++ array. Defining the default
  217. // constructor independent of the forwarding constructor removes the compiler limitation.
  218. unique_any_t() = default;
  219. // forwarding constructor: forwards all 'explicit' and multi-arg constructors to the base class
  220. template <typename arg1, typename... args_t>
  221. explicit unique_any_t(arg1 && first, args_t&&... args) : // should not be WI_NOEXCEPT (may forward to a throwing constructor)
  222. storage_t(wistd::forward<arg1>(first), wistd::forward<args_t>(args)...)
  223. {
  224. static_assert(wistd::is_same<typename policy::pointer_access, details::pointer_access_none>::value ||
  225. wistd::is_same<typename policy::pointer_access, details::pointer_access_all>::value ||
  226. wistd::is_same<typename policy::pointer_access, details::pointer_access_noaddress>::value, "pointer_access policy must be a known pointer_access* integral type");
  227. }
  228. unique_any_t(wistd::nullptr_t) WI_NOEXCEPT
  229. {
  230. static_assert(wistd::is_same<typename policy::pointer_invalid, wistd::nullptr_t>::value, "nullptr constructor: valid only for handle types using nullptr as the invalid value");
  231. }
  232. unique_any_t(unique_any_t &&other) WI_NOEXCEPT :
  233. storage_t(wistd::move(other))
  234. {
  235. }
  236. unique_any_t& operator=(unique_any_t &&other) WI_NOEXCEPT
  237. {
  238. if (this != wistd::addressof(other))
  239. {
  240. // cast to base_storage to 'skip' calling the (optional) specialization class that provides handle-specific functionality
  241. storage_t::replace(wistd::move(static_cast<typename storage_t::base_storage &>(other)));
  242. }
  243. return (*this);
  244. }
  245. unique_any_t& operator=(wistd::nullptr_t) WI_NOEXCEPT
  246. {
  247. static_assert(wistd::is_same<typename policy::pointer_invalid, wistd::nullptr_t>::value, "nullptr assignment: valid only for handle types using nullptr as the invalid value");
  248. storage_t::reset();
  249. return (*this);
  250. }
  251. void swap(unique_any_t &other) WI_NOEXCEPT
  252. {
  253. unique_any_t self(wistd::move(*this));
  254. operator=(wistd::move(other));
  255. other = wistd::move(self);
  256. }
  257. explicit operator bool() const WI_NOEXCEPT
  258. {
  259. return storage_t::is_valid();
  260. }
  261. //! ~~~~
  262. //! BOOL OpenOrCreateWaffle(PCWSTR name, HWAFFLE* handle);
  263. //! wil::unique_any<HWAFFLE, decltype(&::CloseWaffle), ::CloseWaffle> waffle;
  264. //! RETURN_IF_WIN32_BOOL_FALSE(OpenOrCreateWaffle(L"tasty.yum", waffle.put()));
  265. //! ~~~~
  266. pointer_storage *put() WI_NOEXCEPT
  267. {
  268. static_assert(wistd::is_same<typename policy::pointer_access, details::pointer_access_all>::value, "operator & is not available for this handle");
  269. storage_t::reset();
  270. return storage_t::addressof();
  271. }
  272. pointer_storage *operator&() WI_NOEXCEPT
  273. {
  274. return put();
  275. }
  276. pointer get() const WI_NOEXCEPT
  277. {
  278. static_assert(!wistd::is_same<typename policy::pointer_access, details::pointer_access_none>::value, "get(): the raw handle value is not available for this resource class");
  279. return storage_t::get();
  280. }
  281. // The following functions are publicly exposed by their inclusion in the unique_storage base class
  282. // explicit unique_any_t(pointer_storage ptr) WI_NOEXCEPT
  283. // void reset(pointer_storage ptr = policy::invalid_value()) WI_NOEXCEPT
  284. // void reset(wistd::nullptr_t) WI_NOEXCEPT
  285. // pointer_storage release() WI_NOEXCEPT // not exposed for some resource types
  286. // pointer_storage *addressof() WI_NOEXCEPT // not exposed for some resource types
  287. };
  288. template <typename policy>
  289. void swap(unique_any_t<policy>& left, unique_any_t<policy>& right) WI_NOEXCEPT
  290. {
  291. left.swap(right);
  292. }
  293. template <typename policy>
  294. bool operator==(const unique_any_t<policy>& left, const unique_any_t<policy>& right) WI_NOEXCEPT
  295. {
  296. return (left.get() == right.get());
  297. }
  298. template <typename policy>
  299. bool operator==(const unique_any_t<policy>& left, wistd::nullptr_t) WI_NOEXCEPT
  300. {
  301. static_assert(wistd::is_same<typename unique_any_t<policy>::policy::pointer_invalid, wistd::nullptr_t>::value, "the resource class does not use nullptr as an invalid value");
  302. return !left;
  303. }
  304. template <typename policy>
  305. bool operator==(wistd::nullptr_t, const unique_any_t<policy>& right) WI_NOEXCEPT
  306. {
  307. static_assert(wistd::is_same<typename unique_any_t<policy>::policy::pointer_invalid, wistd::nullptr_t>::value, "the resource class does not use nullptr as an invalid value");
  308. return !right;
  309. }
  310. template <typename policy>
  311. bool operator!=(const unique_any_t<policy>& left, const unique_any_t<policy>& right) WI_NOEXCEPT
  312. {
  313. return (!(left.get() == right.get()));
  314. }
  315. template <typename policy>
  316. bool operator!=(const unique_any_t<policy>& left, wistd::nullptr_t) WI_NOEXCEPT
  317. {
  318. static_assert(wistd::is_same<typename unique_any_t<policy>::policy::pointer_invalid, wistd::nullptr_t>::value, "the resource class does not use nullptr as an invalid value");
  319. return !!left;
  320. }
  321. template <typename policy>
  322. bool operator!=(wistd::nullptr_t, const unique_any_t<policy>& right) WI_NOEXCEPT
  323. {
  324. static_assert(wistd::is_same<typename unique_any_t<policy>::policy::pointer_invalid, wistd::nullptr_t>::value, "the resource class does not use nullptr as an invalid value");
  325. return !!right;
  326. }
  327. template <typename policy>
  328. bool operator<(const unique_any_t<policy>& left, const unique_any_t<policy>& right) WI_NOEXCEPT
  329. {
  330. return (left.get() < right.get());
  331. }
  332. template <typename policy>
  333. bool operator>=(const unique_any_t<policy>& left, const unique_any_t<policy>& right) WI_NOEXCEPT
  334. {
  335. return (!(left < right));
  336. }
  337. template <typename policy>
  338. bool operator>(const unique_any_t<policy>& left, const unique_any_t<policy>& right) WI_NOEXCEPT
  339. {
  340. return (right < left);
  341. }
  342. template <typename policy>
  343. bool operator<=(const unique_any_t<policy>& left, const unique_any_t<policy>& right) WI_NOEXCEPT
  344. {
  345. return (!(right < left));
  346. }
  347. // unique_any provides a template alias for easily building a unique_any_t from a unique_storage class with the given
  348. // template parameters for resource_policy.
  349. template <typename pointer, // The handle type
  350. typename close_fn_t, // The handle close function type
  351. close_fn_t close_fn, // * and function pointer
  352. typename pointer_access = details::pointer_access_all, // all, noaddress or none to control pointer method access
  353. typename pointer_storage = pointer, // The type used to store the handle (usually the same as the handle itself)
  354. typename invalid_t = pointer, // The invalid handle value type
  355. invalid_t invalid = invalid_t(), // * and its value (default ZERO value)
  356. typename pointer_invalid = wistd::nullptr_t> // nullptr_t if the invalid handle value is compatible with nullptr, otherwise pointer
  357. using unique_any = unique_any_t<details::unique_storage<details::resource_policy<pointer, close_fn_t, close_fn, pointer_access, pointer_storage, invalid_t, invalid, pointer_invalid>>>;
  358. /// @cond
  359. namespace details
  360. {
  361. template <typename TLambda>
  362. class lambda_call
  363. {
  364. public:
  365. lambda_call(const lambda_call&) = delete;
  366. lambda_call& operator=(const lambda_call&) = delete;
  367. lambda_call& operator=(lambda_call&& other) = delete;
  368. explicit lambda_call(TLambda&& lambda) WI_NOEXCEPT : m_lambda(wistd::move(lambda))
  369. {
  370. static_assert(wistd::is_same<decltype(lambda()), void>::value, "scope_exit lambdas must not have a return value");
  371. static_assert(!wistd::is_lvalue_reference<TLambda>::value && !wistd::is_rvalue_reference<TLambda>::value,
  372. "scope_exit should only be directly used with a lambda");
  373. }
  374. lambda_call(lambda_call&& other) WI_NOEXCEPT : m_lambda(wistd::move(other.m_lambda)), m_call(other.m_call)
  375. {
  376. other.m_call = false;
  377. }
  378. ~lambda_call() WI_NOEXCEPT
  379. {
  380. reset();
  381. }
  382. // Ensures the scope_exit lambda will not be called
  383. void release() WI_NOEXCEPT
  384. {
  385. m_call = false;
  386. }
  387. // Executes the scope_exit lambda immediately if not yet run; ensures it will not run again
  388. void reset() WI_NOEXCEPT
  389. {
  390. if (m_call)
  391. {
  392. m_call = false;
  393. m_lambda();
  394. }
  395. }
  396. // Returns true if the scope_exit lambda is still going to be executed
  397. explicit operator bool() const WI_NOEXCEPT
  398. {
  399. return m_call;
  400. }
  401. protected:
  402. TLambda m_lambda;
  403. bool m_call = true;
  404. };
  405. #ifdef WIL_ENABLE_EXCEPTIONS
  406. template <typename TLambda>
  407. class lambda_call_log
  408. {
  409. public:
  410. lambda_call_log(const lambda_call_log&) = delete;
  411. lambda_call_log& operator=(const lambda_call_log&) = delete;
  412. lambda_call_log& operator=(lambda_call_log&& other) = delete;
  413. explicit lambda_call_log(void* address, const DiagnosticsInfo& info, TLambda&& lambda) WI_NOEXCEPT :
  414. m_address(address), m_info(info), m_lambda(wistd::move(lambda))
  415. {
  416. static_assert(wistd::is_same<decltype(lambda()), void>::value, "scope_exit lambdas must return 'void'");
  417. static_assert(!wistd::is_lvalue_reference<TLambda>::value && !wistd::is_rvalue_reference<TLambda>::value,
  418. "scope_exit should only be directly used with a lambda");
  419. }
  420. lambda_call_log(lambda_call_log&& other) WI_NOEXCEPT :
  421. m_address(other.m_address), m_info(other.m_info), m_lambda(wistd::move(other.m_lambda)), m_call(other.m_call)
  422. {
  423. other.m_call = false;
  424. }
  425. ~lambda_call_log() WI_NOEXCEPT
  426. {
  427. reset();
  428. }
  429. // Ensures the scope_exit lambda will not be called
  430. void release() WI_NOEXCEPT
  431. {
  432. m_call = false;
  433. }
  434. // Executes the scope_exit lambda immediately if not yet run; ensures it will not run again
  435. void reset() WI_NOEXCEPT
  436. {
  437. if (m_call)
  438. {
  439. m_call = false;
  440. try
  441. {
  442. m_lambda();
  443. }
  444. catch (...)
  445. {
  446. ReportFailure_CaughtException<FailureType::Log>(__R_DIAGNOSTICS(m_info), m_address);
  447. }
  448. }
  449. }
  450. // Returns true if the scope_exit lambda is still going to be executed
  451. explicit operator bool() const WI_NOEXCEPT
  452. {
  453. return m_call;
  454. }
  455. private:
  456. void* m_address;
  457. DiagnosticsInfo m_info;
  458. TLambda m_lambda;
  459. bool m_call = true;
  460. };
  461. #endif // WIL_ENABLE_EXCEPTIONS
  462. }
  463. /// @endcond
  464. /** Returns an object that executes the given lambda when destroyed.
  465. Capture the object with 'auto'; use reset() to execute the lambda early or release() to avoid
  466. execution. Exceptions thrown in the lambda will fail-fast; use scope_exit_log to avoid. */
  467. template <typename TLambda>
  468. WI_NODISCARD inline auto scope_exit(TLambda&& lambda) WI_NOEXCEPT
  469. {
  470. return details::lambda_call<TLambda>(wistd::forward<TLambda>(lambda));
  471. }
  472. #ifdef WIL_ENABLE_EXCEPTIONS
  473. /** Returns an object that executes the given lambda when destroyed; logs exceptions.
  474. Capture the object with 'auto'; use reset() to execute the lambda early or release() to avoid
  475. execution. Exceptions thrown in the lambda will be caught and logged without being propagated. */
  476. template <typename TLambda>
  477. WI_NODISCARD inline __declspec(noinline) auto scope_exit_log(const DiagnosticsInfo& diagnostics, TLambda&& lambda) WI_NOEXCEPT
  478. {
  479. return details::lambda_call_log<TLambda>(_ReturnAddress(), diagnostics, wistd::forward<TLambda>(lambda));
  480. }
  481. #endif
  482. // Forward declaration...
  483. template <typename T, typename err_policy>
  484. class com_ptr_t;
  485. //! Type traits class that identifies the inner type of any smart pointer.
  486. template <typename Ptr>
  487. struct smart_pointer_details
  488. {
  489. typedef typename Ptr::pointer pointer;
  490. };
  491. /// @cond
  492. template <typename T>
  493. struct smart_pointer_details<Microsoft::WRL::ComPtr<T>>
  494. {
  495. typedef T* pointer;
  496. };
  497. /// @endcond
  498. /** Generically detaches a raw pointer from any smart pointer.
  499. Caller takes ownership of the returned raw pointer; calls the correct release(), detach(),
  500. or Detach() method based on the smart pointer type */
  501. template <typename TSmartPointer>
  502. WI_NODISCARD typename TSmartPointer::pointer detach_from_smart_pointer(TSmartPointer& smartPtr)
  503. {
  504. return smartPtr.release();
  505. }
  506. /// @cond
  507. // Generically detaches a raw pointer from any smart pointer
  508. template <typename T, typename err>
  509. WI_NODISCARD T* detach_from_smart_pointer(wil::com_ptr_t<T, err>& smartPtr)
  510. {
  511. return smartPtr.detach();
  512. }
  513. // Generically detaches a raw pointer from any smart pointer
  514. template <typename T>
  515. WI_NODISCARD T* detach_from_smart_pointer(Microsoft::WRL::ComPtr<T>& smartPtr)
  516. {
  517. return smartPtr.Detach();
  518. }
  519. template<typename T, typename err> class com_ptr_t; // forward
  520. namespace details
  521. {
  522. // The first two attach_to_smart_pointer() overloads are ambiguous when passed a com_ptr_t.
  523. // To solve that use this functions return type to elminate the reset form for com_ptr_t.
  524. template <typename T, typename err> wistd::false_type use_reset(wil::com_ptr_t<T, err>*) { return wistd::false_type(); }
  525. template <typename T> wistd::true_type use_reset(T*) { return wistd::true_type(); }
  526. }
  527. /// @endcond
  528. /** Generically attach a raw pointer to a compatible smart pointer.
  529. Calls the correct reset(), attach(), or Attach() method based on samrt pointer type. */
  530. template <typename TSmartPointer, typename EnableResetForm = wistd::enable_if_t<decltype(details::use_reset(static_cast<TSmartPointer*>(nullptr)))::value>>
  531. void attach_to_smart_pointer(TSmartPointer& smartPtr, typename TSmartPointer::pointer rawPtr)
  532. {
  533. smartPtr.reset(rawPtr);
  534. }
  535. /// @cond
  536. // Generically attach a raw pointer to a compatible smart pointer.
  537. template <typename T, typename err>
  538. void attach_to_smart_pointer(wil::com_ptr_t<T, err>& smartPtr, T* rawPtr)
  539. {
  540. smartPtr.attach(rawPtr);
  541. }
  542. // Generically attach a raw pointer to a compatible smart pointer.
  543. template <typename T>
  544. void attach_to_smart_pointer(Microsoft::WRL::ComPtr<T>& smartPtr, T* rawPtr)
  545. {
  546. smartPtr.Attach(rawPtr);
  547. }
  548. /// @endcond
  549. //! @ingroup outparam
  550. /** Detach a smart pointer resource to an optional output pointer parameter.
  551. Avoids cluttering code with nullptr tests; works generically for any smart pointer */
  552. template <typename T, typename TSmartPointer>
  553. inline void detach_to_opt_param(_Out_opt_ T* outParam, TSmartPointer&& smartPtr)
  554. {
  555. if (outParam)
  556. {
  557. *outParam = detach_from_smart_pointer(smartPtr);
  558. }
  559. }
  560. /// @cond
  561. namespace details
  562. {
  563. template <typename T>
  564. struct out_param_t
  565. {
  566. typedef typename wil::smart_pointer_details<T>::pointer pointer;
  567. T &wrapper;
  568. pointer pRaw;
  569. bool replace = true;
  570. out_param_t(_Inout_ T &output) :
  571. wrapper(output),
  572. pRaw(nullptr)
  573. {
  574. }
  575. out_param_t(out_param_t&& other) :
  576. wrapper(other.wrapper),
  577. pRaw(other.pRaw)
  578. {
  579. WI_ASSERT(other.replace);
  580. other.replace = false;
  581. }
  582. operator pointer*()
  583. {
  584. WI_ASSERT(replace);
  585. return &pRaw;
  586. }
  587. ~out_param_t()
  588. {
  589. if (replace)
  590. {
  591. attach_to_smart_pointer(wrapper, pRaw);
  592. }
  593. }
  594. out_param_t(out_param_t const &other) = delete;
  595. out_param_t &operator=(out_param_t const &other) = delete;
  596. };
  597. template <typename Tcast, typename T>
  598. struct out_param_ptr_t
  599. {
  600. typedef typename wil::smart_pointer_details<T>::pointer pointer;
  601. T &wrapper;
  602. pointer pRaw;
  603. bool replace = true;
  604. out_param_ptr_t(_Inout_ T &output) :
  605. wrapper(output),
  606. pRaw(nullptr)
  607. {
  608. }
  609. out_param_ptr_t(out_param_ptr_t&& other) :
  610. wrapper(other.wrapper),
  611. pRaw(other.pRaw)
  612. {
  613. WI_ASSERT(other.replace);
  614. other.replace = false;
  615. }
  616. operator Tcast()
  617. {
  618. WI_ASSERT(replace);
  619. return reinterpret_cast<Tcast>(&pRaw);
  620. }
  621. ~out_param_ptr_t()
  622. {
  623. if (replace)
  624. {
  625. attach_to_smart_pointer(wrapper, pRaw);
  626. }
  627. }
  628. out_param_ptr_t(out_param_ptr_t const &other) = delete;
  629. out_param_ptr_t &operator=(out_param_ptr_t const &other) = delete;
  630. };
  631. } // details
  632. /// @endcond
  633. /** Use to retrieve raw out parameter pointers into smart pointers that do not support the '&' operator.
  634. This avoids multi-step handling of a raw resource to establish the smart pointer.
  635. Example: `GetFoo(out_param(foo));` */
  636. template <typename T>
  637. details::out_param_t<T> out_param(T& p)
  638. {
  639. return details::out_param_t<T>(p);
  640. }
  641. /** Use to retrieve raw out parameter pointers (with a required cast) into smart pointers that do not support the '&' operator.
  642. Use only when the smart pointer's &handle is not equal to the output type a function requries, necessitating a cast.
  643. Example: `wil::out_param_ptr<PSECURITY_DESCRIPTOR*>(securityDescriptor)` */
  644. template <typename Tcast, typename T>
  645. details::out_param_ptr_t<Tcast, T> out_param_ptr(T& p)
  646. {
  647. return details::out_param_ptr_t<Tcast, T>(p);
  648. }
  649. /** Use unique_struct to define an RAII type for a trivial struct that references resources that must be cleaned up.
  650. Unique_struct wraps a trivial struct using a custom clean up function and, optionally, custom initializer function. If no custom initialier function is defined in the template
  651. then ZeroMemory is used.
  652. Unique_struct is modeled off of std::unique_ptr. However, unique_struct inherits from the defined type instead of managing the struct through a private member variable.
  653. If the type you're wrapping is a system type, you can share the code by declaring it in this file (Resource.h). Send requests to wildisc.
  654. Otherwise, if the type is local to your project, declare it locally.
  655. @tparam struct_t The struct you want to manage
  656. @tparam close_fn_t The type of the function to clean up the struct. Takes one parameter: a pointer of struct_t. Return values are ignored.
  657. @tparam close_fn The function of type close_fn_t. This is called in the destructor and reset functions.
  658. @tparam init_fn_t Optional:The type of the function to initialize the struct. Takes one parameter: a pointer of struct_t. Return values are ignored.
  659. @tparam init_fn Optional:The function of type init_fn_t. This is called in the constructor, reset, and release functions. The default is ZeroMemory to initialize the struct.
  660. Defined using the default zero memory initializer
  661. ~~~
  662. typedef wil::unique_struct<PROPVARIANT, decltype(&::PropVariantClear), ::PropVariantClear> unique_prop_variant_default_init;
  663. unique_prop_variant propvariant;
  664. SomeFunction(&propvariant);
  665. ~~~
  666. Defined using a custom initializer
  667. ~~~
  668. typedef wil::unique_struct<PROPVARIANT, decltype(&::PropVariantClear), ::PropVariantClear, decltype(&::PropVariantInit), ::PropVariantInit> unique_prop_variant;
  669. unique_prop_variant propvariant;
  670. SomeFunction(&propvariant);
  671. ~~~
  672. */
  673. template <typename struct_t, typename close_fn_t, close_fn_t close_fn, typename init_fn_t = wistd::nullptr_t, init_fn_t init_fn = wistd::nullptr_t()>
  674. class unique_struct : public struct_t
  675. {
  676. public:
  677. //! Initializes the managed struct using the user-provided initialization function, or ZeroMemory if no function is specified
  678. unique_struct()
  679. {
  680. call_init(use_default_init_fn());
  681. }
  682. //! Takes ownership of the struct by doing a shallow copy. Must explicitly be type struct_t
  683. explicit unique_struct(const struct_t& other) WI_NOEXCEPT :
  684. struct_t(other)
  685. {}
  686. //! Initializes the managed struct by taking the ownership of the other managed struct
  687. //! Then resets the other managed struct by calling the custom close function
  688. unique_struct(unique_struct&& other) WI_NOEXCEPT :
  689. struct_t(other.release())
  690. {}
  691. //! Resets this managed struct by calling the custom close function and takes ownership of the other managed struct
  692. //! Then resets the other managed struct by calling the custom close function
  693. unique_struct & operator=(unique_struct&& other) WI_NOEXCEPT
  694. {
  695. if (this != wistd::addressof(other))
  696. {
  697. reset(other.release());
  698. }
  699. return *this;
  700. }
  701. //! Calls the custom close function
  702. ~unique_struct() WI_NOEXCEPT
  703. {
  704. wistd::invoke(close_fn, this);
  705. }
  706. void reset(const unique_struct&) = delete;
  707. //! Resets this managed struct by calling the custom close function and begins management of the other struct
  708. void reset(const struct_t& other) WI_NOEXCEPT
  709. {
  710. {
  711. auto preserveError = last_error_context();
  712. wistd::invoke(close_fn, this);
  713. }
  714. struct_t::operator=(other);
  715. }
  716. //! Resets this managed struct by calling the custom close function
  717. //! Then initializes this managed struct using the user-provided initialization function, or ZeroMemory if no function is specified
  718. void reset() WI_NOEXCEPT
  719. {
  720. wistd::invoke(close_fn, this);
  721. call_init(use_default_init_fn());
  722. }
  723. void swap(struct_t&) = delete;
  724. //! Swaps the managed structs
  725. void swap(unique_struct& other) WI_NOEXCEPT
  726. {
  727. struct_t self(*this);
  728. struct_t::operator=(other);
  729. *(other.addressof()) = self;
  730. }
  731. //! Returns the managed struct
  732. //! Then initializes this managed struct using the user-provided initialization function, or ZeroMemory if no function is specified
  733. struct_t release() WI_NOEXCEPT
  734. {
  735. struct_t value(*this);
  736. call_init(use_default_init_fn());
  737. return value;
  738. }
  739. //! Returns address of the managed struct
  740. struct_t * addressof() WI_NOEXCEPT
  741. {
  742. return this;
  743. }
  744. //! Resets this managed struct by calling the custom close function
  745. //! Then initializes this managed struct using the user-provided initialization function, or ZeroMemory if no function is specified
  746. //! Returns address of the managed struct
  747. struct_t * reset_and_addressof() WI_NOEXCEPT
  748. {
  749. reset();
  750. return this;
  751. }
  752. unique_struct(const unique_struct&) = delete;
  753. unique_struct& operator=(const unique_struct&) = delete;
  754. unique_struct& operator=(const struct_t&) = delete;
  755. private:
  756. typedef typename wistd::is_same<init_fn_t, wistd::nullptr_t>::type use_default_init_fn;
  757. void call_init(wistd::true_type)
  758. {
  759. RtlZeroMemory(this, sizeof(*this));
  760. }
  761. void call_init(wistd::false_type)
  762. {
  763. init_fn(this);
  764. }
  765. };
  766. struct empty_deleter
  767. {
  768. template <typename T>
  769. void operator()(_Pre_opt_valid_ _Frees_ptr_opt_ T) const
  770. {
  771. }
  772. };
  773. /** unique_any_array_ptr is a RAII type for managing conformant arrays that need to be freed and have elements that may need to be freed.
  774. The intented use for this RAII type would be to capture out params from API like IPropertyValue::GetStringArray.
  775. This class also maintains the size of the array, so it can iterate over the members and deallocate them before it deallocates the base array pointer.
  776. If the type you're wrapping is a system type, you can share the code by declaring it in this file (Resource.h). Send requests to wildisc.
  777. Otherwise, if the type is local to your project, declare it locally.
  778. @tparam ValueType: The type of array you want to manage.
  779. @tparam ArrayDeleter: The type of the function to clean up the array. Takes one parameter of type T[] or T*. Return values are ignored. This is called in the destructor and reset functions.
  780. @tparam ElementDeleter: The type of the function to clean up the array elements. Takes one parameter of type T. Return values are ignored. This is called in the destructor and reset functions.
  781. ~~~
  782. void GetSomeArray(_Out_ size_t*, _Out_ NOTMYTYPE**);
  783. struct not_my_deleter
  784. {
  785. void operator()(NOTMYTYPE p) const
  786. {
  787. destroy(p);
  788. }
  789. };
  790. wil::unique_any_array_ptr<NOTMYTYPE, ::CoTaskMemFree, not_my_deleter> myArray;
  791. GetSomeArray(myArray.size_address(), &myArray);
  792. ~~~ */
  793. template <typename ValueType, typename ArrayDeleter, typename ElementDeleter = empty_deleter>
  794. class unique_any_array_ptr
  795. {
  796. public:
  797. typedef ValueType value_type;
  798. typedef size_t size_type;
  799. typedef ptrdiff_t difference_type;
  800. typedef ValueType *pointer;
  801. typedef const ValueType *const_pointer;
  802. typedef ValueType& reference;
  803. typedef const ValueType& const_reference;
  804. typedef ValueType* iterator;
  805. typedef const ValueType* const_iterator;
  806. unique_any_array_ptr() = default;
  807. unique_any_array_ptr(const unique_any_array_ptr&) = delete;
  808. unique_any_array_ptr& operator=(const unique_any_array_ptr&) = delete;
  809. unique_any_array_ptr(wistd::nullptr_t) WI_NOEXCEPT
  810. {
  811. }
  812. unique_any_array_ptr& operator=(wistd::nullptr_t) WI_NOEXCEPT
  813. {
  814. reset();
  815. return *this;
  816. }
  817. unique_any_array_ptr(pointer ptr, size_t size) WI_NOEXCEPT : m_ptr(ptr), m_size(size)
  818. {
  819. }
  820. unique_any_array_ptr(unique_any_array_ptr&& other) WI_NOEXCEPT : m_ptr(other.m_ptr), m_size(other.m_size)
  821. {
  822. other.m_ptr = nullptr;
  823. other.m_size = size_type{};
  824. }
  825. unique_any_array_ptr& operator=(unique_any_array_ptr&& other) WI_NOEXCEPT
  826. {
  827. if (this != wistd::addressof(other))
  828. {
  829. reset();
  830. swap(other);
  831. }
  832. return *this;
  833. }
  834. ~unique_any_array_ptr() WI_NOEXCEPT
  835. {
  836. reset();
  837. }
  838. void swap(unique_any_array_ptr& other) WI_NOEXCEPT
  839. {
  840. auto ptr = m_ptr;
  841. auto size = m_size;
  842. m_ptr = other.m_ptr;
  843. m_size = other.m_size;
  844. other.m_ptr = ptr;
  845. other.m_size = size;
  846. }
  847. iterator begin() WI_NOEXCEPT
  848. {
  849. return (iterator(m_ptr));
  850. }
  851. const_iterator begin() const WI_NOEXCEPT
  852. {
  853. return (const_iterator(m_ptr));
  854. }
  855. iterator end() WI_NOEXCEPT
  856. {
  857. return (iterator(m_ptr + m_size));
  858. }
  859. const_iterator end() const WI_NOEXCEPT
  860. {
  861. return (const_iterator(m_ptr + m_size));
  862. }
  863. const_iterator cbegin() const WI_NOEXCEPT
  864. {
  865. return (begin());
  866. }
  867. const_iterator cend() const WI_NOEXCEPT
  868. {
  869. return (end());
  870. }
  871. size_type size() const WI_NOEXCEPT
  872. {
  873. return (m_size);
  874. }
  875. bool empty() const WI_NOEXCEPT
  876. {
  877. return (size() == size_type{});
  878. }
  879. reference operator[](size_type position)
  880. {
  881. WI_ASSERT(position < m_size);
  882. _Analysis_assume_(position < m_size);
  883. return (m_ptr[position]);
  884. }
  885. const_reference operator[](size_type position) const
  886. {
  887. WI_ASSERT(position < m_size);
  888. _Analysis_assume_(position < m_size);
  889. return (m_ptr[position]);
  890. }
  891. reference front()
  892. {
  893. WI_ASSERT(!empty());
  894. return (m_ptr[0]);
  895. }
  896. const_reference front() const
  897. {
  898. WI_ASSERT(!empty());
  899. return (m_ptr[0]);
  900. }
  901. reference back()
  902. {
  903. WI_ASSERT(!empty());
  904. return (m_ptr[m_size - 1]);
  905. }
  906. const_reference back() const
  907. {
  908. WI_ASSERT(!empty());
  909. return (m_ptr[m_size - 1]);
  910. }
  911. ValueType* data() WI_NOEXCEPT
  912. {
  913. return (m_ptr);
  914. }
  915. const ValueType* data() const WI_NOEXCEPT
  916. {
  917. return (m_ptr);
  918. }
  919. pointer get() const WI_NOEXCEPT
  920. {
  921. return m_ptr;
  922. }
  923. explicit operator bool() const WI_NOEXCEPT
  924. {
  925. return (m_ptr != pointer());
  926. }
  927. pointer release() WI_NOEXCEPT
  928. {
  929. auto result = m_ptr;
  930. m_ptr = nullptr;
  931. m_size = size_type{};
  932. return result;
  933. }
  934. void reset() WI_NOEXCEPT
  935. {
  936. if (m_ptr)
  937. {
  938. reset_array(ElementDeleter());
  939. ArrayDeleter()(m_ptr);
  940. m_ptr = nullptr;
  941. m_size = size_type{};
  942. }
  943. }
  944. void reset(pointer ptr, size_t size) WI_NOEXCEPT
  945. {
  946. reset();
  947. m_ptr = ptr;
  948. m_size = size;
  949. }
  950. pointer* addressof() WI_NOEXCEPT
  951. {
  952. return &m_ptr;
  953. }
  954. pointer* put() WI_NOEXCEPT
  955. {
  956. reset();
  957. return addressof();
  958. }
  959. pointer* operator&() WI_NOEXCEPT
  960. {
  961. return put();
  962. }
  963. size_type* size_address() WI_NOEXCEPT
  964. {
  965. return &m_size;
  966. }
  967. template <typename TSize>
  968. struct size_address_ptr
  969. {
  970. unique_any_array_ptr& wrapper;
  971. TSize size{};
  972. bool replace = true;
  973. size_address_ptr(_Inout_ unique_any_array_ptr& output) :
  974. wrapper(output)
  975. {
  976. }
  977. size_address_ptr(size_address_ptr&& other) :
  978. wrapper(other.wrapper),
  979. size(other.size)
  980. {
  981. WI_ASSERT(other.replace);
  982. other.replace = false;
  983. }
  984. operator TSize*()
  985. {
  986. WI_ASSERT(replace);
  987. return &size;
  988. }
  989. ~size_address_ptr()
  990. {
  991. if (replace)
  992. {
  993. *wrapper.size_address() = static_cast<size_type>(size);
  994. }
  995. }
  996. size_address_ptr(size_address_ptr const &other) = delete;
  997. size_address_ptr &operator=(size_address_ptr const &other) = delete;
  998. };
  999. template <typename T>
  1000. size_address_ptr<T> size_address() WI_NOEXCEPT
  1001. {
  1002. return size_address_ptr<T>(*this);
  1003. }
  1004. private:
  1005. pointer m_ptr = nullptr;
  1006. size_type m_size{};
  1007. void reset_array(const empty_deleter&)
  1008. {
  1009. }
  1010. template <typename T>
  1011. void reset_array(const T& deleter)
  1012. {
  1013. for (auto& element : make_range(m_ptr, m_size))
  1014. {
  1015. deleter(element);
  1016. }
  1017. }
  1018. };
  1019. // forward declaration
  1020. template <typename T, typename err_policy>
  1021. class com_ptr_t;
  1022. /// @cond
  1023. namespace details
  1024. {
  1025. template <typename UniqueAnyType>
  1026. struct unique_any_array_deleter
  1027. {
  1028. template <typename T>
  1029. void operator()(_Pre_opt_valid_ _Frees_ptr_opt_ T* p) const
  1030. {
  1031. UniqueAnyType::policy::close_reset(p);
  1032. }
  1033. };
  1034. template <typename close_fn_t, close_fn_t close_fn>
  1035. struct unique_struct_array_deleter
  1036. {
  1037. template <typename T>
  1038. void operator()(_Pre_opt_valid_ _Frees_ptr_opt_ T& p) const
  1039. {
  1040. wistd::invoke(close_fn, &p);
  1041. }
  1042. };
  1043. struct com_unknown_deleter
  1044. {
  1045. template <typename T>
  1046. void operator()(_Pre_opt_valid_ _Frees_ptr_opt_ T* p) const
  1047. {
  1048. if (p)
  1049. {
  1050. p->Release();
  1051. }
  1052. }
  1053. };
  1054. template <class T>
  1055. struct element_traits
  1056. {
  1057. typedef empty_deleter deleter;
  1058. typedef T type;
  1059. };
  1060. template <typename storage_t>
  1061. struct element_traits<unique_any_t<storage_t>>
  1062. {
  1063. typedef unique_any_array_deleter<unique_any_t<storage_t>> deleter;
  1064. typedef typename unique_any_t<storage_t>::pointer type;
  1065. };
  1066. template <typename T, typename err_policy>
  1067. struct element_traits<com_ptr_t<T, err_policy>>
  1068. {
  1069. typedef com_unknown_deleter deleter;
  1070. typedef T* type;
  1071. };
  1072. template <typename struct_t, typename close_fn_t, close_fn_t close_fn, typename init_fn_t, init_fn_t init_fn>
  1073. struct element_traits<unique_struct<struct_t, close_fn_t, close_fn, init_fn_t, init_fn>>
  1074. {
  1075. typedef unique_struct_array_deleter<close_fn_t, close_fn> deleter;
  1076. typedef struct_t type;
  1077. };
  1078. }
  1079. /// @endcond
  1080. template <typename T, typename ArrayDeleter>
  1081. using unique_array_ptr = unique_any_array_ptr<typename details::element_traits<T>::type, ArrayDeleter, typename details::element_traits<T>::deleter>;
  1082. /** Adapter for single-parameter 'free memory' for `wistd::unique_ptr`.
  1083. This struct provides a standard wrapper for calling a platform function to deallocate memory held by a
  1084. `wistd::unique_ptr`, making declaring them as easy as declaring wil::unique_any<>.
  1085. Consider this adapter in preference to `wil::unique_any<>` when the returned type is really a pointer or an
  1086. array of items; `wistd::unique_ptr<>` exposes `operator->()` and `operator[]` for array-typed things safely.
  1087. ~~~~
  1088. EXTERN_C VOID WINAPI MyDllFreeMemory(void* p);
  1089. EXTERN_C HRESULT MyDllGetString(_Outptr_ PWSTR* pString);
  1090. EXTERN_C HRESULT MyDllGetThing(_In_ PCWSTR pString, _Outptr_ PMYSTRUCT* ppThing);
  1091. template<typename T>
  1092. using unique_mydll_ptr = wistd::unique_ptr<T, wil::function_deleter<decltype(&MyDllFreeMemory), MyDllFreeMemory>>;
  1093. HRESULT Test()
  1094. {
  1095. unique_mydll_ptr<WCHAR[]> dllString;
  1096. unique_mydll_ptr<MYSTRUCT> thing;
  1097. RETURN_IF_FAILED(MyDllGetString(wil::out_param(dllString)));
  1098. RETURN_IF_FAILED(MyDllGetThing(dllString.get(), wil::out_param(thing)));
  1099. if (thing->Member)
  1100. {
  1101. // ...
  1102. }
  1103. return S_OK;
  1104. }
  1105. ~~~~ */
  1106. template<typename Q, Q TDeleter> struct function_deleter
  1107. {
  1108. template<typename T> void operator()(_Frees_ptr_opt_ T* toFree) const
  1109. {
  1110. TDeleter(toFree);
  1111. }
  1112. };
  1113. /** Use unique_com_token to define an RAII type for a token-based resource that is managed by a COM interface.
  1114. By comparison, unique_any_t has the requirement that the close function must be static. This works for functions
  1115. such as CloseHandle(), but for any resource cleanup function that relies on a more complex interface,
  1116. unique_com_token can be used.
  1117. @tparam interface_t A COM interface pointer that will manage this resource type.
  1118. @tparam token_t The token type that relates to the COM interface management functions.
  1119. @tparam close_fn_t The type of the function that is called when the resource is destroyed.
  1120. @tparam close_fn The function used to destroy the associated resource. This function should have the signature void(interface_t* source, token_t token).
  1121. @tparam invalid_token Optional:An invalid token value. Defaults to default-constructed token_t().
  1122. Example
  1123. ~~~
  1124. void __stdcall MyInterfaceCloseFunction(IMyInterface* source, DWORD token)
  1125. {
  1126. source->MyCloseFunction(token);
  1127. }
  1128. using unique_my_interface_token = wil::unique_com_token<IMyInterface, DWORD, decltype(MyInterfaceCloseFunction), MyInterfaceCloseFunction, 0xFFFFFFFF>;
  1129. ~~~ */
  1130. template <typename interface_t, typename token_t, typename close_fn_t, close_fn_t close_fn, token_t invalid_token = token_t()>
  1131. class unique_com_token
  1132. {
  1133. public:
  1134. unique_com_token() = default;
  1135. unique_com_token(_In_opt_ interface_t* source, token_t token = invalid_token) WI_NOEXCEPT
  1136. {
  1137. reset(source, token);
  1138. }
  1139. unique_com_token(unique_com_token&& other) WI_NOEXCEPT : m_source(other.m_source), m_token(other.m_token)
  1140. {
  1141. other.m_source = nullptr;
  1142. other.m_token = invalid_token;
  1143. }
  1144. unique_com_token& operator=(unique_com_token&& other) WI_NOEXCEPT
  1145. {
  1146. if (this != wistd::addressof(other))
  1147. {
  1148. reset();
  1149. m_source = other.m_source;
  1150. m_token = other.m_token;
  1151. other.m_source = nullptr;
  1152. other.m_token = invalid_token;
  1153. }
  1154. return *this;
  1155. }
  1156. ~unique_com_token() WI_NOEXCEPT
  1157. {
  1158. reset();
  1159. }
  1160. //! Determine if the underlying source and token are valid
  1161. explicit operator bool() const WI_NOEXCEPT
  1162. {
  1163. return (m_token != invalid_token) && m_source;
  1164. }
  1165. //! Associates a new source and releases the existing token if valid
  1166. void associate(_In_opt_ interface_t* source) WI_NOEXCEPT
  1167. {
  1168. reset(source, invalid_token);
  1169. }
  1170. //! Assigns a new source and token
  1171. void reset(_In_opt_ interface_t* source, token_t token) WI_NOEXCEPT
  1172. {
  1173. WI_ASSERT(source || (token == invalid_token));
  1174. // Determine if we need to call the close function on our previous token.
  1175. if (m_token != invalid_token)
  1176. {
  1177. if ((m_source != source) || (m_token != token))
  1178. {
  1179. wistd::invoke(close_fn, m_source, m_token);
  1180. }
  1181. }
  1182. m_token = token;
  1183. // Assign our new source and manage the reference counts
  1184. if (m_source != source)
  1185. {
  1186. auto oldSource = m_source;
  1187. m_source = source;
  1188. if (m_source)
  1189. {
  1190. m_source->AddRef();
  1191. }
  1192. if (oldSource)
  1193. {
  1194. oldSource->Release();
  1195. }
  1196. }
  1197. }
  1198. //! Assigns a new token without modifying the source; associate must be called first
  1199. void reset(token_t token) WI_NOEXCEPT
  1200. {
  1201. reset(m_source, token);
  1202. }
  1203. //! Closes the token and the releases the reference to the source
  1204. void reset() WI_NOEXCEPT
  1205. {
  1206. reset(nullptr, invalid_token);
  1207. }
  1208. //! Exchanges values with another managed token
  1209. void swap(unique_com_token& other) WI_NOEXCEPT
  1210. {
  1211. wistd::swap_wil(m_source, other.m_source);
  1212. wistd::swap_wil(m_token, other.m_token);
  1213. }
  1214. //! Releases the held token to the caller without closing it and releases the reference to the source.
  1215. //! Requires that the associated COM interface be kept alive externally or the released token may be invalidated
  1216. token_t release() WI_NOEXCEPT
  1217. {
  1218. auto token = m_token;
  1219. m_token = invalid_token;
  1220. reset();
  1221. return token;
  1222. }
  1223. //! Returns address of the managed token; associate must be called first
  1224. token_t* addressof() WI_NOEXCEPT
  1225. {
  1226. WI_ASSERT(m_source);
  1227. return &m_token;
  1228. }
  1229. //! Releases the held token and allows attaching a new token; associate must be called first
  1230. token_t* put() WI_NOEXCEPT
  1231. {
  1232. reset(invalid_token);
  1233. return addressof();
  1234. }
  1235. //! Releases the held token and allows attaching a new token; associate must be called first
  1236. token_t* operator&() WI_NOEXCEPT
  1237. {
  1238. return put();
  1239. }
  1240. //! Retrieves the token
  1241. token_t get() const WI_NOEXCEPT
  1242. {
  1243. return m_token;
  1244. }
  1245. unique_com_token(const unique_com_token&) = delete;
  1246. unique_com_token& operator=(const unique_com_token&) = delete;
  1247. private:
  1248. interface_t* m_source = nullptr;
  1249. token_t m_token = invalid_token;
  1250. };
  1251. /** Use unique_com_call to define an RAII type that demands a particular parameter-less method be called on a COM interface.
  1252. This allows implementing an RAII type that can call a Close() method (think IClosable) or a SetSite(nullptr)
  1253. method (think IObjectWithSite) or some other method when a basic interface call is required as part of the RAII contract.
  1254. see wil::com_set_site in wil\com.h for the IObjectWithSite support.
  1255. @tparam interface_t A COM interface pointer that provides context to make the call.
  1256. @tparam close_fn_t The type of the function that is called to invoke the method.
  1257. @tparam close_fn The function used to invoke the interface method. This function should have the signature void(interface_t* source).
  1258. Example
  1259. ~~~
  1260. void __stdcall CloseIClosable(IClosable* source)
  1261. {
  1262. source->Close();
  1263. }
  1264. using unique_closable_call = wil::unique_com_call<IClosable, decltype(CloseIClosable), CloseIClosable>;
  1265. ~~~ */
  1266. template <typename interface_t, typename close_fn_t, close_fn_t close_fn>
  1267. class unique_com_call
  1268. {
  1269. public:
  1270. unique_com_call() = default;
  1271. explicit unique_com_call(_In_opt_ interface_t* ptr) WI_NOEXCEPT
  1272. {
  1273. reset(ptr);
  1274. }
  1275. unique_com_call(unique_com_call&& other) WI_NOEXCEPT
  1276. {
  1277. m_ptr = other.m_ptr;
  1278. other.m_ptr = nullptr;
  1279. }
  1280. unique_com_call& operator=(unique_com_call&& other) WI_NOEXCEPT
  1281. {
  1282. if (this != wistd::addressof(other))
  1283. {
  1284. reset();
  1285. m_ptr = other.m_ptr;
  1286. other.m_ptr = nullptr;
  1287. }
  1288. return *this;
  1289. }
  1290. ~unique_com_call() WI_NOEXCEPT
  1291. {
  1292. reset();
  1293. }
  1294. //! Assigns an interface to make a given call on
  1295. void reset(_In_opt_ interface_t* ptr = nullptr) WI_NOEXCEPT
  1296. {
  1297. if (ptr != m_ptr)
  1298. {
  1299. auto oldSource = m_ptr;
  1300. m_ptr = ptr;
  1301. if (m_ptr)
  1302. {
  1303. m_ptr->AddRef();
  1304. }
  1305. if (oldSource)
  1306. {
  1307. wistd::invoke(close_fn, oldSource);
  1308. oldSource->Release();
  1309. }
  1310. }
  1311. }
  1312. //! Exchanges values with another class
  1313. void swap(unique_com_call& other) WI_NOEXCEPT
  1314. {
  1315. wistd::swap_wil(m_ptr, other.m_ptr);
  1316. }
  1317. //! Cancel the interface call that this class was expected to make
  1318. void release() WI_NOEXCEPT
  1319. {
  1320. auto ptr = m_ptr;
  1321. m_ptr = nullptr;
  1322. if (ptr)
  1323. {
  1324. ptr->Release();
  1325. }
  1326. }
  1327. //! Returns true if the call this class was expected to make is still outstanding
  1328. explicit operator bool() const WI_NOEXCEPT
  1329. {
  1330. return (m_ptr != nullptr);
  1331. }
  1332. //! Returns address of the internal interface
  1333. interface_t** addressof() WI_NOEXCEPT
  1334. {
  1335. return &m_ptr;
  1336. }
  1337. //! Releases the held interface (first performing the interface call if required)
  1338. //! and allows attaching a new interface
  1339. interface_t** put() WI_NOEXCEPT
  1340. {
  1341. reset();
  1342. return addressof();
  1343. }
  1344. //! Releases the held interface (first performing the interface call if required)
  1345. //! and allows attaching a new interface
  1346. interface_t** operator&() WI_NOEXCEPT
  1347. {
  1348. return put();
  1349. }
  1350. unique_com_call(const unique_com_call&) = delete;
  1351. unique_com_call& operator=(const unique_com_call&) = delete;
  1352. private:
  1353. interface_t* m_ptr = nullptr;
  1354. };
  1355. /** Use unique_call to define an RAII type that demands a particular parameter-less global function be called.
  1356. This allows implementing a RAII types that can call methods like CoUninitialize.
  1357. @tparam close_fn_t The type of the function that is called to invoke the call.
  1358. @tparam close_fn The function used to invoke the call. This function should have the signature void().
  1359. @tparam default_value Determines whether the unique_call is active or inactive when default-constructed or reset.
  1360. Example
  1361. ~~~
  1362. void __stdcall CoUninitializeFunction()
  1363. {
  1364. ::CoUninitialize();
  1365. }
  1366. using unique_couninitialize_call = wil::unique_call<decltype(CoUninitializeFunction), CoUninitializeFunction>;
  1367. ~~~ */
  1368. template <typename close_fn_t, close_fn_t close_fn, bool default_value = true>
  1369. class unique_call
  1370. {
  1371. public:
  1372. unique_call() = default;
  1373. explicit unique_call(bool call) WI_NOEXCEPT : m_call(call)
  1374. {
  1375. }
  1376. unique_call(unique_call&& other) WI_NOEXCEPT
  1377. {
  1378. m_call = other.m_call;
  1379. other.m_call = false;
  1380. }
  1381. unique_call& operator=(unique_call&& other) WI_NOEXCEPT
  1382. {
  1383. if (this != wistd::addressof(other))
  1384. {
  1385. reset();
  1386. m_call = other.m_call;
  1387. other.m_call = false;
  1388. }
  1389. return *this;
  1390. }
  1391. ~unique_call() WI_NOEXCEPT
  1392. {
  1393. reset();
  1394. }
  1395. //! Assigns a new ptr and token
  1396. void reset() WI_NOEXCEPT
  1397. {
  1398. auto call = m_call;
  1399. m_call = false;
  1400. if (call)
  1401. {
  1402. wistd::invoke(close_fn);
  1403. }
  1404. }
  1405. //! Exchanges values with raii class
  1406. void swap(unique_call& other) WI_NOEXCEPT
  1407. {
  1408. wistd::swap_wil(m_call, other.m_call);
  1409. }
  1410. //! Make the interface call that was expected of this class
  1411. void activate() WI_NOEXCEPT
  1412. {
  1413. m_call = true;
  1414. }
  1415. //! Do not make the interface call that was expected of this class
  1416. void release() WI_NOEXCEPT
  1417. {
  1418. m_call = false;
  1419. }
  1420. //! Returns true if the call that was expected is still outstanding
  1421. explicit operator bool() const WI_NOEXCEPT
  1422. {
  1423. return m_call;
  1424. }
  1425. unique_call(const unique_call&) = delete;
  1426. unique_call& operator=(const unique_call&) = delete;
  1427. private:
  1428. bool m_call = default_value;
  1429. };
  1430. // str_raw_ptr is an overloaded function that retrieves a const pointer to the first character in a string's buffer.
  1431. // Overloads in this file support any string that is implicitly convertible to a PCWSTR, HSTRING, and any unique_any_t
  1432. // that points to any other supported type (this covers unique_hstring, unique_cotaskmem_string, and similar).
  1433. // An overload for std::wstring is available in stl.h.
  1434. inline PCWSTR str_raw_ptr(PCWSTR str)
  1435. {
  1436. return str;
  1437. }
  1438. template <typename T>
  1439. PCWSTR str_raw_ptr(const unique_any_t<T>& ua)
  1440. {
  1441. return str_raw_ptr(ua.get());
  1442. }
  1443. namespace details
  1444. {
  1445. // Forward declaration
  1446. template<typename string_type> struct string_maker;
  1447. // Concatenate any number of strings together and store it in an automatically allocated string. If a string is present
  1448. // in the input buffer, it is overwritten.
  1449. template <typename string_type>
  1450. HRESULT str_build_nothrow(string_type& result, _In_reads_(strCount) PCWSTR* strList, size_t strCount)
  1451. {
  1452. size_t lengthRequiredWithoutNull{};
  1453. for (auto& string : make_range(strList, strCount))
  1454. {
  1455. lengthRequiredWithoutNull += string ? wcslen(string) : 0;
  1456. }
  1457. details::string_maker<string_type> maker;
  1458. RETURN_IF_FAILED(maker.make(nullptr, lengthRequiredWithoutNull));
  1459. auto buffer = maker.buffer();
  1460. auto bufferEnd = buffer + lengthRequiredWithoutNull + 1;
  1461. for (auto& string : make_range(strList, strCount))
  1462. {
  1463. if (string)
  1464. {
  1465. RETURN_IF_FAILED(StringCchCopyExW(buffer, (bufferEnd - buffer), string, &buffer, nullptr, STRSAFE_IGNORE_NULLS));
  1466. }
  1467. }
  1468. result = maker.release();
  1469. return S_OK;
  1470. }
  1471. // NOTE: 'Strings' must all be PCWSTR, or convertible to PCWSTR, but C++ doesn't allow us to express that cleanly
  1472. template <typename string_type, typename... Strings>
  1473. HRESULT str_build_nothrow(string_type& result, Strings... strings)
  1474. {
  1475. PCWSTR localStrings[] = { strings... };
  1476. return str_build_nothrow(result, localStrings, sizeof...(Strings));
  1477. }
  1478. }
  1479. // Concatenate any number of strings together and store it in an automatically allocated string. If a string is present
  1480. // in the input buffer, the remaining strings are appended to it.
  1481. template <typename string_type, typename... strings>
  1482. HRESULT str_concat_nothrow(string_type& buffer, const strings&... str)
  1483. {
  1484. static_assert(sizeof...(str) > 0, "attempting to concatenate no strings");
  1485. return details::str_build_nothrow(buffer, details::string_maker<string_type>::get(buffer), str_raw_ptr(str)...);
  1486. }
  1487. #ifdef WIL_ENABLE_EXCEPTIONS
  1488. // Concatenate any number of strings together and store it in an automatically allocated string.
  1489. template <typename string_type, typename... arguments>
  1490. string_type str_concat(arguments&&... args)
  1491. {
  1492. string_type result;
  1493. THROW_IF_FAILED(str_concat_nothrow(result, wistd::forward<arguments>(args)...));
  1494. return result;
  1495. }
  1496. #endif // WIL_ENABLE_EXCEPTIONS
  1497. // Concatenate any number of strings together and store it in an automatically allocated string.
  1498. template <typename string_type, typename... arguments>
  1499. string_type str_concat_failfast(arguments&&... args)
  1500. {
  1501. string_type result;
  1502. FAIL_FAST_IF_FAILED(str_concat_nothrow(result, wistd::forward<arguments>(args)...));
  1503. return result;
  1504. }
  1505. namespace details
  1506. {
  1507. // Wraps StringCchPrintFExW and stores it in an automatically allocated string. Takes a buffer followed by the same format arguments
  1508. // that StringCchPrintfExW takes.
  1509. template <typename string_type>
  1510. HRESULT str_vprintf_nothrow(string_type& result, _Printf_format_string_ PCWSTR pszFormat, va_list& argsVL)
  1511. {
  1512. size_t lengthRequiredWithoutNull = _vscwprintf(pszFormat, argsVL);
  1513. string_maker<string_type> maker;
  1514. RETURN_IF_FAILED(maker.make(nullptr, lengthRequiredWithoutNull));
  1515. auto buffer = maker.buffer();
  1516. RETURN_IF_FAILED(::StringCchVPrintfExW(buffer, lengthRequiredWithoutNull + 1, nullptr, nullptr, STRSAFE_NULL_ON_FAILURE, pszFormat, argsVL));
  1517. result = maker.release();
  1518. return S_OK;
  1519. }
  1520. }
  1521. // Wraps StringCchPrintFExW and stores it in an automatically allocated string. Takes a buffer followed by the same format arguments
  1522. // that StringCchPrintfExW takes.
  1523. template <typename string_type>
  1524. HRESULT str_printf_nothrow(string_type& result, _Printf_format_string_ PCWSTR pszFormat, _In_ ...)
  1525. {
  1526. va_list argsVL;
  1527. va_start(argsVL, pszFormat);
  1528. auto hr = details::str_vprintf_nothrow(result, pszFormat, argsVL);
  1529. va_end(argsVL);
  1530. return hr;
  1531. }
  1532. #ifdef WIL_ENABLE_EXCEPTIONS
  1533. // Wraps StringCchPrintFExW and stores it in an automatically allocated string. Takes a buffer followed by the same format arguments
  1534. // that StringCchPrintfExW takes.
  1535. template <typename string_type>
  1536. string_type str_printf(_Printf_format_string_ PCWSTR pszFormat, _In_ ...)
  1537. {
  1538. string_type result;
  1539. va_list argsVL;
  1540. va_start(argsVL, pszFormat);
  1541. auto hr = details::str_vprintf_nothrow(result, pszFormat, argsVL);
  1542. va_end(argsVL);
  1543. THROW_IF_FAILED(hr);
  1544. return result;
  1545. }
  1546. #endif // WIL_ENABLE_EXCEPTIONS
  1547. // Wraps StringCchPrintFExW and stores it in an automatically allocated string. Takes a buffer followed by the same format arguments
  1548. // that StringCchPrintfExW takes.
  1549. template <typename string_type>
  1550. string_type str_printf_failfast(_Printf_format_string_ PCWSTR pszFormat, _In_ ...)
  1551. {
  1552. string_type result;
  1553. va_list argsVL;
  1554. va_start(argsVL, pszFormat);
  1555. auto hr = details::str_vprintf_nothrow(result, pszFormat, argsVL);
  1556. va_end(argsVL);
  1557. FAIL_FAST_IF_FAILED(hr);
  1558. return result;
  1559. }
  1560. } // namespace wil
  1561. #endif // __WIL_RESOURCE
  1562. // Hash deferral function for unique_any_t
  1563. #if (defined(_UNORDERED_SET_) || defined(_UNORDERED_MAP_)) && !defined(__WIL_RESOURCE_UNIQUE_HASH)
  1564. #define __WIL_RESOURCE_UNIQUE_HASH
  1565. namespace std
  1566. {
  1567. template <typename storage_t>
  1568. struct hash<wil::unique_any_t<storage_t>>
  1569. {
  1570. size_t operator()(wil::unique_any_t<storage_t> const &val) const
  1571. {
  1572. return (hash<typename wil::unique_any_t<storage_t>::pointer>()(val.get()));
  1573. }
  1574. };
  1575. }
  1576. #endif
  1577. // shared_any and weak_any implementation using <memory> STL header
  1578. #if defined(_MEMORY_) && defined(WIL_ENABLE_EXCEPTIONS) && !defined(WIL_RESOURCE_STL) && !defined(RESOURCE_SUPPRESS_STL)
  1579. #define WIL_RESOURCE_STL
  1580. namespace wil {
  1581. template <typename storage_t>
  1582. class weak_any;
  1583. /// @cond
  1584. namespace details
  1585. {
  1586. // This class provides the pointer storage behind the implementation of shared_any_t utilizing the given
  1587. // resource_policy. It is separate from shared_any_t to allow a type-specific specialization class to plug
  1588. // into the inheritance chain between shared_any_t and shared_storage. This allows classes like shared_event
  1589. // to be a shared_any formed class, but also expose methods like SetEvent directly.
  1590. template <typename unique_t>
  1591. class shared_storage
  1592. {
  1593. protected:
  1594. typedef unique_t unique_t;
  1595. typedef typename unique_t::policy policy;
  1596. typedef typename policy::pointer_storage pointer_storage;
  1597. typedef typename policy::pointer pointer;
  1598. typedef shared_storage<unique_t> base_storage;
  1599. shared_storage() = default;
  1600. explicit shared_storage(pointer_storage ptr)
  1601. {
  1602. if (policy::is_valid(ptr))
  1603. {
  1604. m_ptr = std::make_shared<unique_t>(unique_t(ptr)); // unique_t on the stack to prevent leak on throw
  1605. }
  1606. }
  1607. shared_storage(unique_t &&other)
  1608. {
  1609. if (other)
  1610. {
  1611. m_ptr = std::make_shared<unique_t>(wistd::move(other));
  1612. }
  1613. }
  1614. shared_storage(const shared_storage &other) WI_NOEXCEPT :
  1615. m_ptr(other.m_ptr)
  1616. {
  1617. }
  1618. shared_storage& operator=(const shared_storage &other) WI_NOEXCEPT
  1619. {
  1620. m_ptr = other.m_ptr;
  1621. return *this;
  1622. }
  1623. shared_storage(shared_storage &&other) WI_NOEXCEPT :
  1624. m_ptr(wistd::move(other.m_ptr))
  1625. {
  1626. }
  1627. shared_storage(std::shared_ptr<unique_t> const &ptr) :
  1628. m_ptr(ptr)
  1629. {
  1630. }
  1631. void replace(shared_storage &&other) WI_NOEXCEPT
  1632. {
  1633. m_ptr = wistd::move(other.m_ptr);
  1634. }
  1635. public:
  1636. bool is_valid() const WI_NOEXCEPT
  1637. {
  1638. return (m_ptr && m_ptr->is_valid());
  1639. }
  1640. void reset(pointer_storage ptr = policy::invalid_value())
  1641. {
  1642. if (policy::is_valid(ptr))
  1643. {
  1644. m_ptr = std::make_shared<unique_t>(unique_t(ptr)); // unique_t on the stack to prevent leak on throw
  1645. }
  1646. else
  1647. {
  1648. m_ptr = nullptr;
  1649. }
  1650. }
  1651. void reset(unique_t &&other)
  1652. {
  1653. m_ptr = std::make_shared<unique_t>(wistd::move(other));
  1654. }
  1655. void reset(wistd::nullptr_t) WI_NOEXCEPT
  1656. {
  1657. static_assert(wistd::is_same<typename policy::pointer_invalid, wistd::nullptr_t>::value, "reset(nullptr): valid only for handle types using nullptr as the invalid value");
  1658. reset();
  1659. }
  1660. template <typename allow_t = typename policy::pointer_access, typename wistd::enable_if<!wistd::is_same<allow_t, details::pointer_access_none>::value, int>::type = 0>
  1661. pointer get() const WI_NOEXCEPT
  1662. {
  1663. return (m_ptr ? m_ptr->get() : policy::invalid_value());
  1664. }
  1665. template <typename allow_t = typename policy::pointer_access, typename wistd::enable_if<wistd::is_same<allow_t, details::pointer_access_all>::value, int>::type = 0>
  1666. pointer_storage *addressof()
  1667. {
  1668. if (!m_ptr)
  1669. {
  1670. m_ptr = std::make_shared<unique_t>();
  1671. }
  1672. return m_ptr->addressof();
  1673. }
  1674. long int use_count() const WI_NOEXCEPT
  1675. {
  1676. return m_ptr.use_count();
  1677. }
  1678. private:
  1679. template <typename storage_t>
  1680. friend class ::wil::weak_any;
  1681. std::shared_ptr<unique_t> m_ptr;
  1682. };
  1683. }
  1684. /// @endcond
  1685. // This class when paired with shared_storage and an optional type-specific specialization class implements
  1686. // the same interface as STL's shared_ptr<> for resource handle types. It is both copyable and movable, supporting
  1687. // weak references and automatic closure of the handle upon release of the last shared_any.
  1688. template <typename storage_t>
  1689. class shared_any_t : public storage_t
  1690. {
  1691. public:
  1692. typedef typename storage_t::policy policy;
  1693. typedef typename policy::pointer_storage pointer_storage;
  1694. typedef typename policy::pointer pointer;
  1695. typedef typename storage_t::unique_t unique_t;
  1696. // default and forwarding constructor: forwards default, all 'explicit' and multi-arg constructors to the base class
  1697. template <typename... args_t>
  1698. explicit shared_any_t(args_t&&... args) : // should not be WI_NOEXCEPT (may forward to a throwing constructor)
  1699. storage_t(wistd::forward<args_t>(args)...)
  1700. {
  1701. }
  1702. shared_any_t(wistd::nullptr_t) WI_NOEXCEPT
  1703. {
  1704. static_assert(wistd::is_same<typename policy::pointer_invalid, wistd::nullptr_t>::value, "nullptr constructor: valid only for handle types using nullptr as the invalid value");
  1705. }
  1706. shared_any_t(shared_any_t &&other) WI_NOEXCEPT :
  1707. storage_t(wistd::move(other))
  1708. {
  1709. }
  1710. shared_any_t(const shared_any_t &other) WI_NOEXCEPT :
  1711. storage_t(other)
  1712. {
  1713. }
  1714. shared_any_t& operator=(shared_any_t &&other) WI_NOEXCEPT
  1715. {
  1716. if (this != wistd::addressof(other))
  1717. {
  1718. storage_t::replace(wistd::move(static_cast<typename storage_t::base_storage &>(other)));
  1719. }
  1720. return (*this);
  1721. }
  1722. shared_any_t& operator=(const shared_any_t& other) WI_NOEXCEPT
  1723. {
  1724. storage_t::operator=(other);
  1725. return (*this);
  1726. }
  1727. shared_any_t(unique_t &&other) :
  1728. storage_t(wistd::move(other))
  1729. {
  1730. }
  1731. shared_any_t& operator=(unique_t &&other)
  1732. {
  1733. storage_t::reset(wistd::move(other));
  1734. return (*this);
  1735. }
  1736. shared_any_t& operator=(wistd::nullptr_t) WI_NOEXCEPT
  1737. {
  1738. static_assert(wistd::is_same<typename policy::pointer_invalid, wistd::nullptr_t>::value, "nullptr assignment: valid only for handle types using nullptr as the invalid value");
  1739. storage_t::reset();
  1740. return (*this);
  1741. }
  1742. void swap(shared_any_t &other) WI_NOEXCEPT
  1743. {
  1744. shared_any_t self(wistd::move(*this));
  1745. operator=(wistd::move(other));
  1746. other = wistd::move(self);
  1747. }
  1748. explicit operator bool() const WI_NOEXCEPT
  1749. {
  1750. return storage_t::is_valid();
  1751. }
  1752. pointer_storage *put()
  1753. {
  1754. static_assert(wistd::is_same<typename policy::pointer_access, details::pointer_access_all>::value, "operator & is not available for this handle");
  1755. storage_t::reset();
  1756. return storage_t::addressof();
  1757. }
  1758. pointer_storage *operator&()
  1759. {
  1760. return put();
  1761. }
  1762. pointer get() const WI_NOEXCEPT
  1763. {
  1764. static_assert(!wistd::is_same<typename policy::pointer_access, details::pointer_access_none>::value, "get(): the raw handle value is not available for this resource class");
  1765. return storage_t::get();
  1766. }
  1767. // The following functions are publicly exposed by their inclusion in the base class
  1768. // void reset(pointer_storage ptr = policy::invalid_value()) WI_NOEXCEPT
  1769. // void reset(wistd::nullptr_t) WI_NOEXCEPT
  1770. // pointer_storage *addressof() WI_NOEXCEPT // (note: not exposed for opaque resource types)
  1771. };
  1772. template <typename unique_t>
  1773. void swap(shared_any_t<unique_t>& left, shared_any_t<unique_t>& right) WI_NOEXCEPT
  1774. {
  1775. left.swap(right);
  1776. }
  1777. template <typename unique_t>
  1778. bool operator==(const shared_any_t<unique_t>& left, const shared_any_t<unique_t>& right) WI_NOEXCEPT
  1779. {
  1780. return (left.get() == right.get());
  1781. }
  1782. template <typename unique_t>
  1783. bool operator==(const shared_any_t<unique_t>& left, wistd::nullptr_t) WI_NOEXCEPT
  1784. {
  1785. static_assert(wistd::is_same<typename shared_any_t<unique_t>::policy::pointer_invalid, wistd::nullptr_t>::value, "the resource class does not use nullptr as an invalid value");
  1786. return !left;
  1787. }
  1788. template <typename unique_t>
  1789. bool operator==(wistd::nullptr_t, const shared_any_t<unique_t>& right) WI_NOEXCEPT
  1790. {
  1791. static_assert(wistd::is_same<typename shared_any_t<unique_t>::policy::pointer_invalid, wistd::nullptr_t>::value, "the resource class does not use nullptr as an invalid value");
  1792. return !right;
  1793. }
  1794. template <typename unique_t>
  1795. bool operator!=(const shared_any_t<unique_t>& left, const shared_any_t<unique_t>& right) WI_NOEXCEPT
  1796. {
  1797. return (!(left.get() == right.get()));
  1798. }
  1799. template <typename unique_t>
  1800. bool operator!=(const shared_any_t<unique_t>& left, wistd::nullptr_t) WI_NOEXCEPT
  1801. {
  1802. static_assert(wistd::is_same<typename shared_any_t<unique_t>::policy::pointer_invalid, wistd::nullptr_t>::value, "the resource class does not use nullptr as an invalid value");
  1803. return !!left;
  1804. }
  1805. template <typename unique_t>
  1806. bool operator!=(wistd::nullptr_t, const shared_any_t<unique_t>& right) WI_NOEXCEPT
  1807. {
  1808. static_assert(wistd::is_same<typename shared_any_t<unique_t>::policy::pointer_invalid, wistd::nullptr_t>::value, "the resource class does not use nullptr as an invalid value");
  1809. return !!right;
  1810. }
  1811. template <typename unique_t>
  1812. bool operator<(const shared_any_t<unique_t>& left, const shared_any_t<unique_t>& right) WI_NOEXCEPT
  1813. {
  1814. return (left.get() < right.get());
  1815. }
  1816. template <typename unique_t>
  1817. bool operator>=(const shared_any_t<unique_t>& left, const shared_any_t<unique_t>& right) WI_NOEXCEPT
  1818. {
  1819. return (!(left < right));
  1820. }
  1821. template <typename unique_t>
  1822. bool operator>(const shared_any_t<unique_t>& left, const shared_any_t<unique_t>& right) WI_NOEXCEPT
  1823. {
  1824. return (right < left);
  1825. }
  1826. template <typename unique_t>
  1827. bool operator<=(const shared_any_t<unique_t>& left, const shared_any_t<unique_t>& right) WI_NOEXCEPT
  1828. {
  1829. return (!(right < left));
  1830. }
  1831. // This class provides weak_ptr<> support for shared_any<>, bringing the same weak reference counting and lock() acquire semantics
  1832. // to shared_any.
  1833. template <typename shared_t>
  1834. class weak_any
  1835. {
  1836. public:
  1837. typedef shared_t shared_t;
  1838. weak_any() WI_NOEXCEPT
  1839. {
  1840. }
  1841. weak_any(const shared_t &other) WI_NOEXCEPT :
  1842. m_weakPtr(other.m_ptr)
  1843. {
  1844. }
  1845. weak_any(const weak_any &other) WI_NOEXCEPT :
  1846. m_weakPtr(other.m_weakPtr)
  1847. {
  1848. }
  1849. weak_any& operator=(const weak_any &right) WI_NOEXCEPT
  1850. {
  1851. m_weakPtr = right.m_weakPtr;
  1852. return (*this);
  1853. }
  1854. weak_any& operator=(const shared_t &right) WI_NOEXCEPT
  1855. {
  1856. m_weakPtr = right.m_ptr;
  1857. return (*this);
  1858. }
  1859. void reset() WI_NOEXCEPT
  1860. {
  1861. m_weakPtr.reset();
  1862. }
  1863. void swap(weak_any &other) WI_NOEXCEPT
  1864. {
  1865. m_weakPtr.swap(other.m_weakPtr);
  1866. }
  1867. bool expired() const WI_NOEXCEPT
  1868. {
  1869. return m_weakPtr.expired();
  1870. }
  1871. shared_t lock() const WI_NOEXCEPT
  1872. {
  1873. return shared_t(m_weakPtr.lock());
  1874. }
  1875. private:
  1876. std::weak_ptr<typename shared_t::unique_t> m_weakPtr;
  1877. };
  1878. template <typename shared_t>
  1879. void swap(weak_any<shared_t>& left, weak_any<shared_t>& right) WI_NOEXCEPT
  1880. {
  1881. left.swap(right);
  1882. }
  1883. template <typename unique_t>
  1884. using shared_any = shared_any_t<details::shared_storage<unique_t>>;
  1885. } // namespace wil
  1886. #endif
  1887. #if defined(WIL_RESOURCE_STL) && (defined(_UNORDERED_SET_) || defined(_UNORDERED_MAP_)) && !defined(__WIL_RESOURCE_SHARED_HASH)
  1888. #define __WIL_RESOURCE_SHARED_HASH
  1889. namespace std
  1890. {
  1891. template <typename storage_t>
  1892. struct hash<wil::shared_any_t<storage_t>>
  1893. {
  1894. size_t operator()(wil::shared_any_t<storage_t> const &val) const
  1895. {
  1896. return (hash<typename wil::shared_any_t<storage_t>::pointer>()(val.get()));
  1897. }
  1898. };
  1899. }
  1900. #endif
  1901. namespace wil
  1902. {
  1903. #if defined(__NOTHROW_T_DEFINED) && !defined(__WIL__NOTHROW_T_DEFINED)
  1904. #define __WIL__NOTHROW_T_DEFINED
  1905. /** Provides `std::make_unique()` semantics for resources allocated in a context that may not throw upon allocation failure.
  1906. `wil::make_unique_nothrow()` is identical to `std::make_unique()` except for the following:
  1907. * It returns `wistd::unique_ptr`, rather than `std::unique_ptr`
  1908. * It returns an empty (null) `wistd::unique_ptr` upon allocation failure, rather than throwing an exception
  1909. Note that `wil::make_unique_nothrow()` is not marked WI_NOEXCEPT as it may be used to create an exception-based class that may throw in its constructor.
  1910. ~~~
  1911. auto foo = wil::make_unique_nothrow<Foo>(fooConstructorParam1, fooConstructorParam2);
  1912. if (foo)
  1913. {
  1914. foo->Bar();
  1915. }
  1916. ~~~
  1917. */
  1918. template <class _Ty, class... _Types>
  1919. inline typename wistd::enable_if<!wistd::is_array<_Ty>::value, wistd::unique_ptr<_Ty> >::type make_unique_nothrow(_Types&&... _Args)
  1920. {
  1921. return (wistd::unique_ptr<_Ty>(new(std::nothrow) _Ty(wistd::forward<_Types>(_Args)...)));
  1922. }
  1923. /** Provides `std::make_unique()` semantics for array resources allocated in a context that may not throw upon allocation failure.
  1924. See the overload of `wil::make_unique_nothrow()` for non-array types for more details.
  1925. ~~~
  1926. const size_t size = 42;
  1927. auto foos = wil::make_unique_nothrow<Foo[]>(size); // the default constructor will be called on each Foo object
  1928. if (foos)
  1929. {
  1930. for (auto& elem : wil::make_range(foos.get(), size))
  1931. {
  1932. elem.Bar();
  1933. }
  1934. }
  1935. ~~~
  1936. */
  1937. template <class _Ty>
  1938. inline typename wistd::enable_if<wistd::is_array<_Ty>::value && wistd::extent<_Ty>::value == 0, wistd::unique_ptr<_Ty> >::type make_unique_nothrow(size_t _Size)
  1939. {
  1940. typedef typename wistd::remove_extent<_Ty>::type _Elem;
  1941. return (wistd::unique_ptr<_Ty>(new(std::nothrow) _Elem[_Size]()));
  1942. }
  1943. template <class _Ty, class... _Types>
  1944. typename wistd::enable_if<wistd::extent<_Ty>::value != 0, void>::type make_unique_nothrow(_Types&&...) = delete;
  1945. #if !defined(__WIL_MIN_KERNEL) && !defined(WIL_KERNEL_MODE)
  1946. /** Provides `std::make_unique()` semantics for resources allocated in a context that must fail fast upon allocation failure.
  1947. See the overload of `wil::make_unique_nothrow()` for non-array types for more details.
  1948. ~~~
  1949. auto foo = wil::make_unique_failfast<Foo>(fooConstructorParam1, fooConstructorParam2);
  1950. foo->Bar();
  1951. ~~~
  1952. */
  1953. template <class _Ty, class... _Types>
  1954. inline typename wistd::enable_if<!wistd::is_array<_Ty>::value, wistd::unique_ptr<_Ty> >::type make_unique_failfast(_Types&&... _Args)
  1955. {
  1956. #pragma warning(suppress: 28193) // temporary must be inspected (it is within the called function)
  1957. return (wistd::unique_ptr<_Ty>(FAIL_FAST_IF_NULL_ALLOC(new(std::nothrow) _Ty(wistd::forward<_Types>(_Args)...))));
  1958. }
  1959. /** Provides `std::make_unique()` semantics for array resources allocated in a context that must fail fast upon allocation failure.
  1960. See the overload of `wil::make_unique_nothrow()` for non-array types for more details.
  1961. ~~~
  1962. const size_t size = 42;
  1963. auto foos = wil::make_unique_nothrow<Foo[]>(size); // the default constructor will be called on each Foo object
  1964. for (auto& elem : wil::make_range(foos.get(), size))
  1965. {
  1966. elem.Bar();
  1967. }
  1968. ~~~
  1969. */
  1970. template <class _Ty>
  1971. inline typename wistd::enable_if<wistd::is_array<_Ty>::value && wistd::extent<_Ty>::value == 0, wistd::unique_ptr<_Ty> >::type make_unique_failfast(size_t _Size)
  1972. {
  1973. typedef typename wistd::remove_extent<_Ty>::type _Elem;
  1974. #pragma warning(suppress: 28193) // temporary must be inspected (it is within the called function)
  1975. return (wistd::unique_ptr<_Ty>(FAIL_FAST_IF_NULL_ALLOC(new(std::nothrow) _Elem[_Size]())));
  1976. }
  1977. template <class _Ty, class... _Types>
  1978. typename wistd::enable_if<wistd::extent<_Ty>::value != 0, void>::type make_unique_failfast(_Types&&...) = delete;
  1979. #endif // !defined(__WIL_MIN_KERNEL) && !defined(WIL_KERNEL_MODE)
  1980. #endif // __WIL__NOTHROW_T_DEFINED
  1981. #if defined(_WINBASE_) && !defined(__WIL_WINBASE_) && !defined(WIL_KERNEL_MODE)
  1982. #define __WIL_WINBASE_
  1983. /// @cond
  1984. namespace details
  1985. {
  1986. inline void __stdcall SetEvent(HANDLE h) WI_NOEXCEPT
  1987. {
  1988. __FAIL_FAST_ASSERT_WIN32_BOOL_FALSE__(::SetEvent(h));
  1989. }
  1990. inline void __stdcall ResetEvent(HANDLE h) WI_NOEXCEPT
  1991. {
  1992. __FAIL_FAST_ASSERT_WIN32_BOOL_FALSE__(::ResetEvent(h));
  1993. }
  1994. inline void __stdcall CloseHandle(HANDLE h) WI_NOEXCEPT
  1995. {
  1996. __FAIL_FAST_ASSERT_WIN32_BOOL_FALSE__(::CloseHandle(h));
  1997. }
  1998. inline void __stdcall ReleaseSemaphore(_In_ HANDLE h) WI_NOEXCEPT
  1999. {
  2000. __FAIL_FAST_ASSERT_WIN32_BOOL_FALSE__(::ReleaseSemaphore(h, 1, nullptr));
  2001. }
  2002. inline void __stdcall ReleaseMutex(_In_ HANDLE h) WI_NOEXCEPT
  2003. {
  2004. __FAIL_FAST_ASSERT_WIN32_BOOL_FALSE__(::ReleaseMutex(h));
  2005. }
  2006. inline void __stdcall CloseTokenLinkedToken(_In_ TOKEN_LINKED_TOKEN* linkedToken) WI_NOEXCEPT
  2007. {
  2008. if (linkedToken->LinkedToken && (linkedToken->LinkedToken != INVALID_HANDLE_VALUE))
  2009. {
  2010. __FAIL_FAST_ASSERT_WIN32_BOOL_FALSE__(::CloseHandle(linkedToken->LinkedToken));
  2011. }
  2012. }
  2013. enum class PendingCallbackCancellationBehavior
  2014. {
  2015. Cancel,
  2016. Wait,
  2017. NoWait,
  2018. };
  2019. template <PendingCallbackCancellationBehavior cancellationBehavior>
  2020. struct DestroyThreadPoolWait
  2021. {
  2022. static void Destroy(_In_ PTP_WAIT threadPoolWait) WI_NOEXCEPT
  2023. {
  2024. ::SetThreadpoolWait(threadPoolWait, nullptr, nullptr);
  2025. ::WaitForThreadpoolWaitCallbacks(threadPoolWait, (cancellationBehavior == PendingCallbackCancellationBehavior::Cancel));
  2026. ::CloseThreadpoolWait(threadPoolWait);
  2027. }
  2028. };
  2029. template <>
  2030. struct DestroyThreadPoolWait<PendingCallbackCancellationBehavior::NoWait>
  2031. {
  2032. static void Destroy(_In_ PTP_WAIT threadPoolWait) WI_NOEXCEPT
  2033. {
  2034. ::CloseThreadpoolWait(threadPoolWait);
  2035. }
  2036. };
  2037. template <PendingCallbackCancellationBehavior cancellationBehavior>
  2038. struct DestroyThreadPoolWork
  2039. {
  2040. static void Destroy(_In_ PTP_WORK threadpoolWork) WI_NOEXCEPT
  2041. {
  2042. ::WaitForThreadpoolWorkCallbacks(threadpoolWork, (cancellationBehavior == PendingCallbackCancellationBehavior::Cancel));
  2043. ::CloseThreadpoolWork(threadpoolWork);
  2044. }
  2045. };
  2046. template <>
  2047. struct DestroyThreadPoolWork<PendingCallbackCancellationBehavior::NoWait>
  2048. {
  2049. static void Destroy(_In_ PTP_WORK threadpoolWork) WI_NOEXCEPT
  2050. {
  2051. ::CloseThreadpoolWork(threadpoolWork);
  2052. }
  2053. };
  2054. // Non-RTL implementation for threadpool_t parameter of DestroyThreadPoolTimer<>
  2055. struct SystemThreadPoolMethods
  2056. {
  2057. static void WINAPI SetThreadpoolTimer(_Inout_ PTP_TIMER Timer, _In_opt_ PFILETIME DueTime, _In_ DWORD Period, _In_opt_ DWORD WindowLength) WI_NOEXCEPT
  2058. {
  2059. ::SetThreadpoolTimer(Timer, DueTime, Period, WindowLength);
  2060. }
  2061. static void WaitForThreadpoolTimerCallbacks(_Inout_ PTP_TIMER Timer, _In_ BOOL CancelPendingCallbacks) WI_NOEXCEPT
  2062. {
  2063. ::WaitForThreadpoolTimerCallbacks(Timer, CancelPendingCallbacks);
  2064. }
  2065. static void CloseThreadpoolTimer(_Inout_ PTP_TIMER Timer) WI_NOEXCEPT
  2066. {
  2067. ::CloseThreadpoolTimer(Timer);
  2068. }
  2069. };
  2070. // SetThreadpoolTimer(timer, nullptr, 0, 0) will cancel any pending callbacks,
  2071. // then CloseThreadpoolTimer will asynchronusly close the timer if a callback is running.
  2072. template <typename threadpool_t, PendingCallbackCancellationBehavior cancellationBehavior>
  2073. struct DestroyThreadPoolTimer
  2074. {
  2075. static void Destroy(_In_ PTP_TIMER threadpoolTimer) WI_NOEXCEPT
  2076. {
  2077. threadpool_t::SetThreadpoolTimer(threadpoolTimer, nullptr, 0, 0);
  2078. #pragma warning(suppress:4127) // conditional expression is constant
  2079. if (cancellationBehavior != PendingCallbackCancellationBehavior::NoWait)
  2080. {
  2081. threadpool_t::WaitForThreadpoolTimerCallbacks(threadpoolTimer, (cancellationBehavior == PendingCallbackCancellationBehavior::Cancel));
  2082. }
  2083. threadpool_t::CloseThreadpoolTimer(threadpoolTimer);
  2084. }
  2085. };
  2086. // PendingCallbackCancellationBehavior::NoWait explicitly does not block waiting for
  2087. // callbacks when destructing.
  2088. template <typename threadpool_t>
  2089. struct DestroyThreadPoolTimer<threadpool_t, PendingCallbackCancellationBehavior::NoWait>
  2090. {
  2091. static void Destroy(_In_ PTP_TIMER threadpoolTimer) WI_NOEXCEPT
  2092. {
  2093. threadpool_t::CloseThreadpoolTimer(threadpoolTimer);
  2094. }
  2095. };
  2096. template <PendingCallbackCancellationBehavior cancellationBehavior>
  2097. struct DestroyThreadPoolIo
  2098. {
  2099. static void Destroy(_In_ PTP_IO threadpoolIo) WI_NOEXCEPT
  2100. {
  2101. ::WaitForThreadpoolIoCallbacks(threadpoolIo, (cancellationBehavior == PendingCallbackCancellationBehavior::Cancel));
  2102. ::CloseThreadpoolIo(threadpoolIo);
  2103. }
  2104. };
  2105. template <>
  2106. struct DestroyThreadPoolIo<PendingCallbackCancellationBehavior::NoWait>
  2107. {
  2108. static void Destroy(_In_ PTP_IO threadpoolIo) WI_NOEXCEPT
  2109. {
  2110. ::CloseThreadpoolIo(threadpoolIo);
  2111. }
  2112. };
  2113. template <typename close_fn_t, close_fn_t close_fn>
  2114. struct handle_invalid_resource_policy : resource_policy<HANDLE, close_fn_t, close_fn, details::pointer_access_all, HANDLE, INT_PTR, -1, HANDLE>
  2115. {
  2116. __forceinline static bool is_valid(HANDLE ptr) WI_NOEXCEPT { return ((ptr != INVALID_HANDLE_VALUE) && (ptr != nullptr)); }
  2117. };
  2118. template <typename close_fn_t, close_fn_t close_fn>
  2119. struct handle_null_resource_policy : resource_policy<HANDLE, close_fn_t, close_fn>
  2120. {
  2121. __forceinline static bool is_valid(HANDLE ptr) WI_NOEXCEPT { return ((ptr != nullptr) && (ptr != INVALID_HANDLE_VALUE)); }
  2122. };
  2123. template <typename close_fn_t, close_fn_t close_fn>
  2124. struct handle_null_only_resource_policy : resource_policy<HANDLE, close_fn_t, close_fn>
  2125. {
  2126. __forceinline static bool is_valid(HANDLE ptr) WI_NOEXCEPT { return (ptr != nullptr); }
  2127. };
  2128. typedef resource_policy<HANDLE, decltype(&details::CloseHandle), details::CloseHandle, details::pointer_access_all> handle_resource_policy;
  2129. }
  2130. /// @endcond
  2131. template <typename close_fn_t, close_fn_t close_fn>
  2132. using unique_any_handle_invalid = unique_any_t<details::unique_storage<details::handle_invalid_resource_policy<close_fn_t, close_fn>>>;
  2133. template <typename close_fn_t, close_fn_t close_fn>
  2134. using unique_any_handle_null = unique_any_t<details::unique_storage<details::handle_null_resource_policy<close_fn_t, close_fn>>>;
  2135. template <typename close_fn_t, close_fn_t close_fn>
  2136. using unique_any_handle_null_only = unique_any_t<details::unique_storage<details::handle_null_only_resource_policy<close_fn_t, close_fn>>>;
  2137. typedef unique_any_handle_invalid<decltype(&::CloseHandle), ::CloseHandle> unique_hfile;
  2138. typedef unique_any_handle_null<decltype(&::CloseHandle), ::CloseHandle> unique_handle;
  2139. typedef unique_any_handle_invalid<decltype(&::FindClose), ::FindClose> unique_hfind;
  2140. typedef unique_any<HMODULE, decltype(&::FreeLibrary), ::FreeLibrary> unique_hmodule;
  2141. typedef unique_any_handle_null_only<decltype(&::CloseHandle), ::CloseHandle> unique_process_handle;
  2142. typedef unique_struct<TOKEN_LINKED_TOKEN, decltype(&details::CloseTokenLinkedToken), details::CloseTokenLinkedToken> unique_token_linked_token;
  2143. #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
  2144. typedef unique_any<PSID, decltype(&::FreeSid), ::FreeSid> unique_sid;
  2145. #endif
  2146. using unique_tool_help_snapshot = unique_hfile;
  2147. typedef unique_any<PTP_WAIT, void(*)(PTP_WAIT), details::DestroyThreadPoolWait<details::PendingCallbackCancellationBehavior::Cancel>::Destroy> unique_threadpool_wait;
  2148. typedef unique_any<PTP_WAIT, void(*)(PTP_WAIT), details::DestroyThreadPoolWait<details::PendingCallbackCancellationBehavior::Wait>::Destroy> unique_threadpool_wait_nocancel;
  2149. typedef unique_any<PTP_WAIT, void(*)(PTP_WAIT), details::DestroyThreadPoolWait<details::PendingCallbackCancellationBehavior::NoWait>::Destroy> unique_threadpool_wait_nowait;
  2150. typedef unique_any<PTP_WORK, void(*)(PTP_WORK), details::DestroyThreadPoolWork<details::PendingCallbackCancellationBehavior::Cancel>::Destroy> unique_threadpool_work;
  2151. typedef unique_any<PTP_WORK, void(*)(PTP_WORK), details::DestroyThreadPoolWork<details::PendingCallbackCancellationBehavior::Wait>::Destroy> unique_threadpool_work_nocancel;
  2152. typedef unique_any<PTP_WORK, void(*)(PTP_WORK), details::DestroyThreadPoolWork<details::PendingCallbackCancellationBehavior::NoWait>::Destroy> unique_threadpool_work_nowait;
  2153. typedef unique_any<PTP_TIMER, void(*)(PTP_TIMER), details::DestroyThreadPoolTimer<details::SystemThreadPoolMethods, details::PendingCallbackCancellationBehavior::Cancel>::Destroy> unique_threadpool_timer;
  2154. typedef unique_any<PTP_TIMER, void(*)(PTP_TIMER), details::DestroyThreadPoolTimer<details::SystemThreadPoolMethods, details::PendingCallbackCancellationBehavior::Wait>::Destroy> unique_threadpool_timer_nocancel;
  2155. typedef unique_any<PTP_TIMER, void(*)(PTP_TIMER), details::DestroyThreadPoolTimer<details::SystemThreadPoolMethods, details::PendingCallbackCancellationBehavior::NoWait>::Destroy> unique_threadpool_timer_nowait;
  2156. typedef unique_any<PTP_IO, void(*)(PTP_IO), details::DestroyThreadPoolIo<details::PendingCallbackCancellationBehavior::Cancel>::Destroy> unique_threadpool_io;
  2157. typedef unique_any<PTP_IO, void(*)(PTP_IO), details::DestroyThreadPoolIo<details::PendingCallbackCancellationBehavior::Wait>::Destroy> unique_threadpool_io_nocancel;
  2158. typedef unique_any<PTP_IO, void(*)(PTP_IO), details::DestroyThreadPoolIo<details::PendingCallbackCancellationBehavior::NoWait>::Destroy> unique_threadpool_io_nowait;
  2159. #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  2160. typedef unique_any_handle_invalid<decltype(&::FindCloseChangeNotification), ::FindCloseChangeNotification> unique_hfind_change;
  2161. #endif
  2162. typedef unique_any<HANDLE, decltype(&details::SetEvent), details::SetEvent, details::pointer_access_noaddress> event_set_scope_exit;
  2163. typedef unique_any<HANDLE, decltype(&details::ResetEvent), details::ResetEvent, details::pointer_access_noaddress> event_reset_scope_exit;
  2164. // Guarantees a SetEvent on the given event handle when the returned object goes out of scope
  2165. // Note: call SetEvent early with the reset() method on the returned object or abort the call with the release() method
  2166. WI_NODISCARD inline event_set_scope_exit SetEvent_scope_exit(HANDLE hEvent) WI_NOEXCEPT
  2167. {
  2168. __FAIL_FAST_ASSERT__(hEvent != nullptr);
  2169. return event_set_scope_exit(hEvent);
  2170. }
  2171. // Guarantees a ResetEvent on the given event handle when the returned object goes out of scope
  2172. // Note: call ResetEvent early with the reset() method on the returned object or abort the call with the release() method
  2173. WI_NODISCARD inline event_reset_scope_exit ResetEvent_scope_exit(HANDLE hEvent) WI_NOEXCEPT
  2174. {
  2175. __FAIL_FAST_ASSERT__(hEvent != nullptr);
  2176. return event_reset_scope_exit(hEvent);
  2177. }
  2178. // Checks to see if the given *manual reset* event is currently signaled. The event must not be an auto-reset event.
  2179. // Use when the event will only be set once (cancellation-style) or will only be reset by the polling thread
  2180. inline bool event_is_signaled(HANDLE hEvent) WI_NOEXCEPT
  2181. {
  2182. auto status = ::WaitForSingleObjectEx(hEvent, 0, FALSE);
  2183. // Fast fail will trip for wait failures, auto-reset events, or when the event is being both Set and Reset
  2184. // from a thread other than the polling thread (use event_wait directly for those cases).
  2185. __FAIL_FAST_ASSERT__((status == WAIT_TIMEOUT) || ((status == WAIT_OBJECT_0) && (WAIT_OBJECT_0 == ::WaitForSingleObjectEx(hEvent, 0, FALSE))));
  2186. return (status == WAIT_OBJECT_0);
  2187. }
  2188. // Waits on the given handle for the specified duration
  2189. inline bool handle_wait(HANDLE hEvent, DWORD dwMilliseconds = INFINITE) WI_NOEXCEPT
  2190. {
  2191. DWORD status = ::WaitForSingleObjectEx(hEvent, dwMilliseconds, FALSE);
  2192. __FAIL_FAST_ASSERT__((status == WAIT_TIMEOUT) || (status == WAIT_OBJECT_0));
  2193. return (status == WAIT_OBJECT_0);
  2194. }
  2195. enum class EventOptions
  2196. {
  2197. None = 0x0,
  2198. ManualReset = 0x1,
  2199. Signaled = 0x2
  2200. };
  2201. DEFINE_ENUM_FLAG_OPERATORS(EventOptions);
  2202. template <typename storage_t, typename err_policy = err_exception_policy>
  2203. class event_t : public storage_t
  2204. {
  2205. public:
  2206. // forward all base class constructors...
  2207. template <typename... args_t>
  2208. explicit event_t(args_t&&... args) WI_NOEXCEPT : storage_t(wistd::forward<args_t>(args)...) {}
  2209. // HRESULT or void error handling...
  2210. typedef typename err_policy::result result;
  2211. // Exception-based constructor to create an unnamed event
  2212. event_t(EventOptions options)
  2213. {
  2214. static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions or fail fast; use the create method");
  2215. create(options);
  2216. }
  2217. void ResetEvent() const WI_NOEXCEPT
  2218. {
  2219. details::ResetEvent(storage_t::get());
  2220. }
  2221. void SetEvent() const WI_NOEXCEPT
  2222. {
  2223. details::SetEvent(storage_t::get());
  2224. }
  2225. // Guarantees a SetEvent on the given event handle when the returned object goes out of scope
  2226. // Note: call SetEvent early with the reset() method on the returned object or abort the call with the release() method
  2227. WI_NODISCARD event_set_scope_exit SetEvent_scope_exit() const WI_NOEXCEPT
  2228. {
  2229. return wil::SetEvent_scope_exit(storage_t::get());
  2230. }
  2231. // Guarantees a ResetEvent on the given event handle when the returned object goes out of scope
  2232. // Note: call ResetEvent early with the reset() method on the returned object or abort the call with the release() method
  2233. WI_NODISCARD event_reset_scope_exit ResetEvent_scope_exit() const WI_NOEXCEPT
  2234. {
  2235. return wil::ResetEvent_scope_exit(storage_t::get());
  2236. }
  2237. // Checks if a *manual reset* event is currently signaled. The event must not be an auto-reset event.
  2238. // Use when the event will only be set once (cancellation-style) or will only be reset by the polling thread
  2239. bool is_signaled() const WI_NOEXCEPT
  2240. {
  2241. return wil::event_is_signaled(storage_t::get());
  2242. }
  2243. // Basic WaitForSingleObject on the event handle with the given timeout
  2244. bool wait(DWORD dwMilliseconds = INFINITE) const WI_NOEXCEPT
  2245. {
  2246. return wil::handle_wait(storage_t::get(), dwMilliseconds);
  2247. }
  2248. // Tries to create a named event -- returns false if unable to do so (gle may still be inspected with return=false)
  2249. bool try_create(EventOptions options, PCWSTR name, _In_opt_ LPSECURITY_ATTRIBUTES pSecurity = nullptr, _Out_opt_ bool *pAlreadyExists = nullptr)
  2250. {
  2251. auto handle = ::CreateEventExW(pSecurity, name, (WI_IsFlagSet(options, EventOptions::ManualReset) ? CREATE_EVENT_MANUAL_RESET : 0) | (WI_IsFlagSet(options, EventOptions::Signaled) ? CREATE_EVENT_INITIAL_SET : 0), EVENT_ALL_ACCESS);
  2252. if (!handle)
  2253. {
  2254. assign_to_opt_param(pAlreadyExists, false);
  2255. return false;
  2256. }
  2257. assign_to_opt_param(pAlreadyExists, (::GetLastError() == ERROR_ALREADY_EXISTS));
  2258. storage_t::reset(handle);
  2259. return true;
  2260. }
  2261. // Returns HRESULT for unique_event_nothrow, void with exceptions for shared_event and unique_event
  2262. result create(EventOptions options = EventOptions::None, PCWSTR name = nullptr, _In_opt_ LPSECURITY_ATTRIBUTES pSecurity = nullptr, _Out_opt_ bool *pAlreadyExists = nullptr)
  2263. {
  2264. return err_policy::LastErrorIfFalse(try_create(options, name, pSecurity, pAlreadyExists));
  2265. }
  2266. // Tries to open the named event -- returns false if unable to do so (gle may still be inspected with return=false)
  2267. bool try_open(_In_ PCWSTR name, DWORD desiredAccess = SYNCHRONIZE | EVENT_MODIFY_STATE, bool inheritHandle = false)
  2268. {
  2269. auto handle = ::OpenEventW(desiredAccess, inheritHandle, name);
  2270. if (handle == nullptr)
  2271. {
  2272. return false;
  2273. }
  2274. storage_t::reset(handle);
  2275. return true;
  2276. }
  2277. // Returns HRESULT for unique_event_nothrow, void with exceptions for shared_event and unique_event
  2278. result open(_In_ PCWSTR name, DWORD desiredAccess = SYNCHRONIZE | EVENT_MODIFY_STATE, bool inheritHandle = false)
  2279. {
  2280. return err_policy::LastErrorIfFalse(try_open(name, desiredAccess, inheritHandle));
  2281. }
  2282. };
  2283. typedef unique_any_t<event_t<details::unique_storage<details::handle_resource_policy>, err_returncode_policy>> unique_event_nothrow;
  2284. typedef unique_any_t<event_t<details::unique_storage<details::handle_resource_policy>, err_failfast_policy>> unique_event_failfast;
  2285. #ifdef WIL_ENABLE_EXCEPTIONS
  2286. typedef unique_any_t<event_t<details::unique_storage<details::handle_resource_policy>, err_exception_policy>> unique_event;
  2287. #endif
  2288. #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  2289. enum class SlimEventType
  2290. {
  2291. AutoReset,
  2292. ManualReset,
  2293. };
  2294. /** A lean and mean event class.
  2295. This class provides a very similar API to `wil::unique_event` but doesn't require a kernel object.
  2296. The two variants of this class are:
  2297. - `wil::slim_event_auto_reset`
  2298. - `wil::slim_event_manual_reset`
  2299. In addition, `wil::slim_event_auto_reset` has the alias `wil::slim_event`.
  2300. Some key differences to `wil::unique_event` include:
  2301. - There is no 'create()' function, as initialization occurs in the constructor and can't fail.
  2302. - The move functions have been deleted.
  2303. - For auto-reset events, the `is_signaled()` function doesn't reset the event. (Use `ResetEvent()` instead.)
  2304. - The `ResetEvent()` function returns the previous state of the event.
  2305. - To create a manual reset event, use `wil::slim_event_manual_reset'.
  2306. ~~~~
  2307. wil::slim_event finished;
  2308. std::thread doStuff([&finished] () {
  2309. Sleep(10);
  2310. finished.SetEvent();
  2311. });
  2312. finished.wait();
  2313. std::shared_ptr<wil::slim_event> CreateSharedEvent(bool startSignaled)
  2314. {
  2315. return std::make_shared<wil::slim_event>(startSignaled);
  2316. }
  2317. ~~~~ */
  2318. template <SlimEventType Type>
  2319. class slim_event_t
  2320. {
  2321. public:
  2322. slim_event_t() WI_NOEXCEPT = default;
  2323. slim_event_t(bool isSignaled) WI_NOEXCEPT :
  2324. m_isSignaled(isSignaled ? TRUE : FALSE)
  2325. {
  2326. }
  2327. // Cannot change memory location.
  2328. slim_event_t(const slim_event_t&) = delete;
  2329. slim_event_t(slim_event_t&&) = delete;
  2330. slim_event_t& operator=(const slim_event_t&) = delete;
  2331. slim_event_t& operator=(slim_event_t&&) = delete;
  2332. // Returns the previous state of the event.
  2333. bool ResetEvent() WI_NOEXCEPT
  2334. {
  2335. return !!InterlockedExchange(&m_isSignaled, FALSE);
  2336. }
  2337. void SetEvent() WI_NOEXCEPT
  2338. {
  2339. // FYI: 'WakeByAddress*' invokes a full memory barrier.
  2340. WriteRelease(&m_isSignaled, TRUE);
  2341. #pragma warning(suppress:4127) // conditional expression is constant
  2342. if (Type == SlimEventType::AutoReset)
  2343. {
  2344. WakeByAddressSingle(&m_isSignaled);
  2345. }
  2346. else
  2347. {
  2348. WakeByAddressAll(&m_isSignaled);
  2349. }
  2350. }
  2351. // Checks if the event is currently signaled.
  2352. // Note: Unlike Win32 auto-reset event objects, this will not reset the event.
  2353. bool is_signaled() const WI_NOEXCEPT
  2354. {
  2355. return !!ReadAcquire(&m_isSignaled);
  2356. }
  2357. bool wait(DWORD timeoutMiliseconds) WI_NOEXCEPT
  2358. {
  2359. if (timeoutMiliseconds == 0)
  2360. {
  2361. return TryAcquireEvent();
  2362. }
  2363. else if (timeoutMiliseconds == INFINITE)
  2364. {
  2365. return wait();
  2366. }
  2367. UINT64 startTime;
  2368. QueryUnbiasedInterruptTime(&startTime);
  2369. UINT64 elapsedTimeMilliseconds = 0;
  2370. while (!TryAcquireEvent())
  2371. {
  2372. if (elapsedTimeMilliseconds >= timeoutMiliseconds)
  2373. {
  2374. return false;
  2375. }
  2376. DWORD newTimeout = static_cast<DWORD>(timeoutMiliseconds - elapsedTimeMilliseconds);
  2377. if (!WaitForSignal(newTimeout))
  2378. {
  2379. return false;
  2380. }
  2381. UINT64 currTime;
  2382. QueryUnbiasedInterruptTime(&currTime);
  2383. elapsedTimeMilliseconds = (currTime - startTime) / (10 * 1000);
  2384. }
  2385. return true;
  2386. }
  2387. bool wait() WI_NOEXCEPT
  2388. {
  2389. while (!TryAcquireEvent())
  2390. {
  2391. if (!WaitForSignal(INFINITE))
  2392. {
  2393. return false;
  2394. }
  2395. }
  2396. return true;
  2397. }
  2398. private:
  2399. bool TryAcquireEvent() WI_NOEXCEPT
  2400. {
  2401. #pragma warning(suppress:4127) // conditional expression is constant
  2402. if (Type == SlimEventType::AutoReset)
  2403. {
  2404. return ResetEvent();
  2405. }
  2406. else
  2407. {
  2408. return is_signaled();
  2409. }
  2410. }
  2411. bool WaitForSignal(DWORD timeoutMiliseconds) WI_NOEXCEPT
  2412. {
  2413. LONG falseValue = FALSE;
  2414. BOOL waitResult = WaitOnAddress(&m_isSignaled, &falseValue, sizeof(m_isSignaled), timeoutMiliseconds);
  2415. __FAIL_FAST_ASSERT__(waitResult || ::GetLastError() == ERROR_TIMEOUT);
  2416. return !!waitResult;
  2417. }
  2418. LONG m_isSignaled = FALSE;
  2419. };
  2420. /** An event object that will atomically revert to an unsignaled state anytime a `wait()` call succeeds (i.e. returns true). */
  2421. using slim_event_auto_reset = slim_event_t<SlimEventType::AutoReset>;
  2422. /** An event object that once signaled remains that way forever, unless `ResetEvent()` is called. */
  2423. using slim_event_manual_reset = slim_event_t<SlimEventType::ManualReset>;
  2424. /** An alias for `wil::slim_event_auto_reset`. */
  2425. using slim_event = slim_event_auto_reset;
  2426. #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  2427. typedef unique_any<HANDLE, decltype(&details::ReleaseMutex), details::ReleaseMutex, details::pointer_access_none> mutex_release_scope_exit;
  2428. WI_NODISCARD inline mutex_release_scope_exit ReleaseMutex_scope_exit(_In_ HANDLE hMutex) WI_NOEXCEPT
  2429. {
  2430. __FAIL_FAST_ASSERT__(hMutex != nullptr);
  2431. return mutex_release_scope_exit(hMutex);
  2432. }
  2433. // For efficiency, avoid using mutexes when an srwlock or condition variable will do.
  2434. template <typename storage_t, typename err_policy = err_exception_policy>
  2435. class mutex_t : public storage_t
  2436. {
  2437. public:
  2438. // forward all base class constructors...
  2439. template <typename... args_t>
  2440. explicit mutex_t(args_t&&... args) WI_NOEXCEPT : storage_t(wistd::forward<args_t>(args)...) {}
  2441. // HRESULT or void error handling...
  2442. typedef typename err_policy::result result;
  2443. // Exception-based constructor to create a mutex (prefer unnamed (nullptr) for the name)
  2444. mutex_t(_In_opt_ PCWSTR name)
  2445. {
  2446. static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions or fail fast; use the create method");
  2447. create(name);
  2448. }
  2449. void ReleaseMutex() const WI_NOEXCEPT
  2450. {
  2451. details::ReleaseMutex(storage_t::get());
  2452. }
  2453. WI_NODISCARD mutex_release_scope_exit ReleaseMutex_scope_exit() const WI_NOEXCEPT
  2454. {
  2455. return wil::ReleaseMutex_scope_exit(storage_t::get());
  2456. }
  2457. WI_NODISCARD mutex_release_scope_exit acquire(_Out_opt_ DWORD *pStatus = nullptr, DWORD dwMilliseconds = INFINITE, BOOL bAlertable = FALSE) const WI_NOEXCEPT
  2458. {
  2459. auto handle = storage_t::get();
  2460. DWORD status = ::WaitForSingleObjectEx(handle, dwMilliseconds, bAlertable);
  2461. assign_to_opt_param(pStatus, status);
  2462. __FAIL_FAST_ASSERT__((status == WAIT_TIMEOUT) || (status == WAIT_OBJECT_0) || (status == WAIT_ABANDONED) || (bAlertable && (status == WAIT_IO_COMPLETION)));
  2463. return mutex_release_scope_exit(((status == WAIT_OBJECT_0) || (status == WAIT_ABANDONED)) ? handle : nullptr);
  2464. }
  2465. // Tries to create a named mutex -- returns false if unable to do so (gle may still be inspected with return=false)
  2466. bool try_create(_In_opt_ PCWSTR name, DWORD dwFlags = 0, DWORD desiredAccess = MUTEX_ALL_ACCESS, _In_opt_ PSECURITY_ATTRIBUTES pMutexAttributes = nullptr)
  2467. {
  2468. auto handle = ::CreateMutexExW(pMutexAttributes, name, dwFlags, desiredAccess);
  2469. if (handle == nullptr)
  2470. {
  2471. return false;
  2472. }
  2473. storage_t::reset(handle);
  2474. return true;
  2475. }
  2476. // Returns HRESULT for unique_mutex_nothrow, void with exceptions for shared_mutex and unique_mutex
  2477. result create(_In_opt_ PCWSTR name = nullptr, DWORD dwFlags = 0, DWORD desiredAccess = MUTEX_ALL_ACCESS, _In_opt_ PSECURITY_ATTRIBUTES pMutexAttributes = nullptr)
  2478. {
  2479. return err_policy::LastErrorIfFalse(try_create(name, dwFlags, desiredAccess, pMutexAttributes));
  2480. }
  2481. // Tries to open a named mutex -- returns false if unable to do so (gle may still be inspected with return=false)
  2482. bool try_open(_In_ PCWSTR name, DWORD desiredAccess = SYNCHRONIZE | MUTEX_MODIFY_STATE, bool inheritHandle = false)
  2483. {
  2484. auto handle = ::OpenMutexW(desiredAccess, inheritHandle, name);
  2485. if (handle == nullptr)
  2486. {
  2487. return false;
  2488. }
  2489. storage_t::reset(handle);
  2490. return true;
  2491. }
  2492. // Returns HRESULT for unique_mutex_nothrow, void with exceptions for shared_mutex and unique_mutex
  2493. result open(_In_ PCWSTR name, DWORD desiredAccess = SYNCHRONIZE | MUTEX_MODIFY_STATE, bool inheritHandle = false)
  2494. {
  2495. return err_policy::LastErrorIfFalse(try_open(name, desiredAccess, inheritHandle));
  2496. }
  2497. };
  2498. typedef unique_any_t<mutex_t<details::unique_storage<details::handle_resource_policy>, err_returncode_policy>> unique_mutex_nothrow;
  2499. typedef unique_any_t<mutex_t<details::unique_storage<details::handle_resource_policy>, err_failfast_policy>> unique_mutex_failfast;
  2500. #ifdef WIL_ENABLE_EXCEPTIONS
  2501. typedef unique_any_t<mutex_t<details::unique_storage<details::handle_resource_policy>, err_exception_policy>> unique_mutex;
  2502. #endif
  2503. typedef unique_any<HANDLE, decltype(&details::ReleaseSemaphore), details::ReleaseSemaphore, details::pointer_access_none> semaphore_release_scope_exit;
  2504. WI_NODISCARD inline semaphore_release_scope_exit ReleaseSemaphore_scope_exit(_In_ HANDLE hSemaphore) WI_NOEXCEPT
  2505. {
  2506. __FAIL_FAST_ASSERT__(hSemaphore != nullptr);
  2507. return semaphore_release_scope_exit(hSemaphore);
  2508. }
  2509. template <typename storage_t, typename err_policy = err_exception_policy>
  2510. class semaphore_t : public storage_t
  2511. {
  2512. public:
  2513. // forward all base class constructors...
  2514. template <typename... args_t>
  2515. explicit semaphore_t(args_t&&... args) WI_NOEXCEPT : storage_t(wistd::forward<args_t>(args)...) {}
  2516. // HRESULT or void error handling...
  2517. typedef typename err_policy::result result;
  2518. // Note that for custom-constructors the type given the constructor has to match exactly as not all implicit conversions will make it through the
  2519. // forwarding constructor. This constructor, for example, uses 'int' instead of 'LONG' as the count to ease that particular issue (const numbers are int by default).
  2520. explicit semaphore_t(int initialCount, int maximumCount, _In_opt_ PCWSTR name = nullptr, DWORD desiredAccess = SEMAPHORE_ALL_ACCESS, _In_opt_ PSECURITY_ATTRIBUTES pSemaphoreAttributes = nullptr)
  2521. {
  2522. static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions or fail fast; use the create method");
  2523. create(initialCount, maximumCount, name, desiredAccess, pSemaphoreAttributes);
  2524. }
  2525. void ReleaseSemaphore(long nReleaseCount = 1, _In_opt_ long *pnPreviousCount = nullptr) WI_NOEXCEPT
  2526. {
  2527. long nPreviousCount = 0;
  2528. __FAIL_FAST_ASSERT__(::ReleaseSemaphore(storage_t::get(), nReleaseCount, &nPreviousCount));
  2529. assign_to_opt_param(pnPreviousCount, nPreviousCount);
  2530. }
  2531. WI_NODISCARD semaphore_release_scope_exit ReleaseSemaphore_scope_exit() WI_NOEXCEPT
  2532. {
  2533. return wil::ReleaseSemaphore_scope_exit(storage_t::get());
  2534. }
  2535. WI_NODISCARD semaphore_release_scope_exit acquire(_Out_opt_ DWORD *pStatus = nullptr, DWORD dwMilliseconds = INFINITE, BOOL bAlertable = FALSE) WI_NOEXCEPT
  2536. {
  2537. auto handle = storage_t::get();
  2538. DWORD status = ::WaitForSingleObjectEx(handle, dwMilliseconds, bAlertable);
  2539. assign_to_opt_param(pStatus, status);
  2540. __FAIL_FAST_ASSERT__((status == WAIT_TIMEOUT) || (status == WAIT_OBJECT_0) || (bAlertable && (status == WAIT_IO_COMPLETION)));
  2541. return semaphore_release_scope_exit((status == WAIT_OBJECT_0) ? handle : nullptr);
  2542. }
  2543. // Tries to create a named event -- returns false if unable to do so (gle may still be inspected with return=false)
  2544. bool try_create(LONG lInitialCount, LONG lMaximumCount, _In_opt_ PCWSTR name, DWORD desiredAccess = SEMAPHORE_ALL_ACCESS, _In_opt_ PSECURITY_ATTRIBUTES pSemaphoreAttributes = nullptr)
  2545. {
  2546. auto handle = ::CreateSemaphoreExW(pSemaphoreAttributes, lInitialCount, lMaximumCount, name, 0, desiredAccess);
  2547. if (handle == nullptr)
  2548. {
  2549. return false;
  2550. }
  2551. storage_t::reset(handle);
  2552. return true;
  2553. }
  2554. // Returns HRESULT for unique_semaphore_nothrow, void with exceptions for shared_event and unique_event
  2555. result create(LONG lInitialCount, LONG lMaximumCount, _In_opt_ PCWSTR name = nullptr, DWORD desiredAccess = SEMAPHORE_ALL_ACCESS, _In_opt_ PSECURITY_ATTRIBUTES pSemaphoreAttributes = nullptr)
  2556. {
  2557. return err_policy::LastErrorIfFalse(try_create(lInitialCount, lMaximumCount, name, desiredAccess, pSemaphoreAttributes));
  2558. }
  2559. // Tries to open the named semaphore -- returns false if unable to do so (gle may still be inspected with return=false)
  2560. bool try_open(_In_ PCWSTR name, DWORD desiredAccess = SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, bool inheritHandle = false)
  2561. {
  2562. auto handle = ::OpenSemaphoreW(desiredAccess, inheritHandle, name);
  2563. if (handle == nullptr)
  2564. {
  2565. return false;
  2566. }
  2567. storage_t::reset(handle);
  2568. return true;
  2569. }
  2570. // Returns HRESULT for unique_semaphore_nothrow, void with exceptions for shared_semaphore and unique_semaphore
  2571. result open(_In_ PCWSTR name, DWORD desiredAccess = SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, bool inheritHandle = false)
  2572. {
  2573. return err_policy::LastErrorIfFalse(try_open(name, desiredAccess, inheritHandle));
  2574. }
  2575. };
  2576. typedef unique_any_t<semaphore_t<details::unique_storage<details::handle_resource_policy>, err_returncode_policy>> unique_semaphore_nothrow;
  2577. typedef unique_any_t<semaphore_t<details::unique_storage<details::handle_resource_policy>, err_failfast_policy>> unique_semaphore_failfast;
  2578. #ifdef WIL_ENABLE_EXCEPTIONS
  2579. typedef unique_any_t<semaphore_t<details::unique_storage<details::handle_resource_policy>, err_exception_policy>> unique_semaphore;
  2580. #endif
  2581. typedef unique_any<SRWLOCK *, decltype(&::ReleaseSRWLockExclusive), ::ReleaseSRWLockExclusive, details::pointer_access_noaddress> rwlock_release_exclusive_scope_exit;
  2582. typedef unique_any<SRWLOCK *, decltype(&::ReleaseSRWLockShared), ::ReleaseSRWLockShared, details::pointer_access_noaddress> rwlock_release_shared_scope_exit;
  2583. WI_NODISCARD inline rwlock_release_exclusive_scope_exit AcquireSRWLockExclusive(_Inout_ SRWLOCK *plock) WI_NOEXCEPT
  2584. {
  2585. ::AcquireSRWLockExclusive(plock);
  2586. return rwlock_release_exclusive_scope_exit(plock);
  2587. }
  2588. WI_NODISCARD inline rwlock_release_shared_scope_exit AcquireSRWLockShared(_Inout_ SRWLOCK *plock) WI_NOEXCEPT
  2589. {
  2590. ::AcquireSRWLockShared(plock);
  2591. return rwlock_release_shared_scope_exit(plock);
  2592. }
  2593. WI_NODISCARD inline rwlock_release_exclusive_scope_exit TryAcquireSRWLockExclusive(_Inout_ SRWLOCK *plock) WI_NOEXCEPT
  2594. {
  2595. return rwlock_release_exclusive_scope_exit(::TryAcquireSRWLockExclusive(plock) ? plock : nullptr);
  2596. }
  2597. WI_NODISCARD inline rwlock_release_shared_scope_exit TryAcquireSRWLockShared(_Inout_ SRWLOCK *plock) WI_NOEXCEPT
  2598. {
  2599. return rwlock_release_shared_scope_exit(::TryAcquireSRWLockShared(plock) ? plock : nullptr);
  2600. }
  2601. class srwlock
  2602. {
  2603. public:
  2604. srwlock(const srwlock&) = delete;
  2605. srwlock(srwlock&&) = delete;
  2606. srwlock& operator=(const srwlock&) = delete;
  2607. srwlock& operator=(srwlock&&) = delete;
  2608. srwlock() = default;
  2609. WI_NODISCARD rwlock_release_exclusive_scope_exit lock_exclusive() WI_NOEXCEPT
  2610. {
  2611. return wil::AcquireSRWLockExclusive(&m_lock);
  2612. }
  2613. WI_NODISCARD rwlock_release_exclusive_scope_exit try_lock_exclusive() WI_NOEXCEPT
  2614. {
  2615. return wil::TryAcquireSRWLockExclusive(&m_lock);
  2616. }
  2617. WI_NODISCARD rwlock_release_shared_scope_exit lock_shared() WI_NOEXCEPT
  2618. {
  2619. return wil::AcquireSRWLockShared(&m_lock);
  2620. }
  2621. WI_NODISCARD rwlock_release_shared_scope_exit try_lock_shared() WI_NOEXCEPT
  2622. {
  2623. return wil::TryAcquireSRWLockShared(&m_lock);
  2624. }
  2625. private:
  2626. SRWLOCK m_lock = SRWLOCK_INIT;
  2627. };
  2628. typedef unique_any<CRITICAL_SECTION *, decltype(&::LeaveCriticalSection), ::LeaveCriticalSection, details::pointer_access_noaddress> cs_leave_scope_exit;
  2629. WI_NODISCARD inline cs_leave_scope_exit EnterCriticalSection(_Inout_ CRITICAL_SECTION *pcs) WI_NOEXCEPT
  2630. {
  2631. ::EnterCriticalSection(pcs);
  2632. return cs_leave_scope_exit(pcs);
  2633. }
  2634. WI_NODISCARD inline cs_leave_scope_exit TryEnterCriticalSection(_Inout_ CRITICAL_SECTION *pcs) WI_NOEXCEPT
  2635. {
  2636. return cs_leave_scope_exit(::TryEnterCriticalSection(pcs) ? pcs : nullptr);
  2637. }
  2638. // Critical sections are worse than srwlocks in performance and memory usage (their only unique attribute
  2639. // being recursive acquisition). Prefer srwlocks over critical sections when you don't need recursive acquisition.
  2640. class critical_section
  2641. {
  2642. public:
  2643. critical_section(const critical_section&) = delete;
  2644. critical_section(critical_section&&) = delete;
  2645. critical_section& operator=(const critical_section&) = delete;
  2646. critical_section& operator=(critical_section&&) = delete;
  2647. critical_section(ULONG spincount = 0) WI_NOEXCEPT
  2648. {
  2649. // Initialization will not fail without invalid params...
  2650. ::InitializeCriticalSectionEx(&m_cs, spincount, 0);
  2651. }
  2652. ~critical_section() WI_NOEXCEPT
  2653. {
  2654. ::DeleteCriticalSection(&m_cs);
  2655. }
  2656. WI_NODISCARD cs_leave_scope_exit lock() WI_NOEXCEPT
  2657. {
  2658. return wil::EnterCriticalSection(&m_cs);
  2659. }
  2660. WI_NODISCARD cs_leave_scope_exit try_lock() WI_NOEXCEPT
  2661. {
  2662. return wil::TryEnterCriticalSection(&m_cs);
  2663. }
  2664. private:
  2665. CRITICAL_SECTION m_cs;
  2666. };
  2667. class condition_variable
  2668. {
  2669. public:
  2670. condition_variable(const condition_variable&) = delete;
  2671. condition_variable(condition_variable&&) = delete;
  2672. condition_variable& operator=(const condition_variable&) = delete;
  2673. condition_variable& operator=(condition_variable&&) = delete;
  2674. condition_variable() = default;
  2675. void notify_one() WI_NOEXCEPT
  2676. {
  2677. ::WakeConditionVariable(&m_cv);
  2678. }
  2679. void notify_all() WI_NOEXCEPT
  2680. {
  2681. ::WakeAllConditionVariable(&m_cv);
  2682. }
  2683. void wait(const cs_leave_scope_exit& lock) WI_NOEXCEPT
  2684. {
  2685. wait_for(lock, INFINITE);
  2686. }
  2687. void wait(const rwlock_release_exclusive_scope_exit& lock) WI_NOEXCEPT
  2688. {
  2689. wait_for(lock, INFINITE);
  2690. }
  2691. void wait(const rwlock_release_shared_scope_exit& lock) WI_NOEXCEPT
  2692. {
  2693. wait_for(lock, INFINITE);
  2694. }
  2695. bool wait_for(const cs_leave_scope_exit& lock, DWORD timeoutMs) WI_NOEXCEPT
  2696. {
  2697. bool result = !!::SleepConditionVariableCS(&m_cv, lock.get(), timeoutMs);
  2698. __FAIL_FAST_ASSERT__(result || ::GetLastError() == ERROR_TIMEOUT);
  2699. return result;
  2700. }
  2701. bool wait_for(const rwlock_release_exclusive_scope_exit& lock, DWORD timeoutMs) WI_NOEXCEPT
  2702. {
  2703. bool result = !!::SleepConditionVariableSRW(&m_cv, lock.get(), timeoutMs, 0);
  2704. __FAIL_FAST_ASSERT__(result || ::GetLastError() == ERROR_TIMEOUT);
  2705. return result;
  2706. }
  2707. bool wait_for(const rwlock_release_shared_scope_exit& lock, DWORD timeoutMs) WI_NOEXCEPT
  2708. {
  2709. bool result = !!::SleepConditionVariableSRW(&m_cv, lock.get(), timeoutMs, CONDITION_VARIABLE_LOCKMODE_SHARED);
  2710. __FAIL_FAST_ASSERT__(result || ::GetLastError() == ERROR_TIMEOUT);
  2711. return result;
  2712. }
  2713. private:
  2714. CONDITION_VARIABLE m_cv = CONDITION_VARIABLE_INIT;
  2715. };
  2716. /// @cond
  2717. namespace details
  2718. {
  2719. template<typename string_class> struct string_allocator
  2720. {
  2721. static void* allocate(size_t /*size*/) WI_NOEXCEPT
  2722. {
  2723. static_assert(!wistd::is_same<string_class, string_class>::value, "This type did not provide a string_allocator, add a specialization of string_allocator to support your type.");
  2724. return nullptr;
  2725. }
  2726. };
  2727. }
  2728. /// @endcond
  2729. // This string helper does not support the ansi wil string helpers
  2730. template<typename string_type>
  2731. PCWSTR string_get_not_null(const string_type& string)
  2732. {
  2733. return string ? string.get() : L"";
  2734. }
  2735. #ifndef MAKE_UNIQUE_STRING_MAX_CCH
  2736. #define MAKE_UNIQUE_STRING_MAX_CCH 2147483647 // max buffer size, in characters, that we support (same as INT_MAX)
  2737. #endif
  2738. /** Copies a string (up to the given length) into memory allocated with a specified allocator returning null on failure.
  2739. Use `wil::make_unique_string_nothrow()` for string resources returned from APIs that must satisfy a memory allocation contract
  2740. that requires use of a specific allocator and free function (CoTaskMemAlloc/CoTaskMemFree, LocalAlloc/LocalFree, GlobalAlloc/GlobalFree, etc.).
  2741. ~~~
  2742. auto str = wil::make_unique_string_nothrow<wil::unique_cotaskmem_string>(L"a string of words", 8);
  2743. RETURN_IF_NULL_ALLOC(str);
  2744. std::wcout << L"This is " << str.get() << std::endl; // prints "This is a string"
  2745. auto str = wil::make_unique_string_nothrow<unique_hlocal_string>(L"a string");
  2746. RETURN_IF_NULL_ALLOC(str);
  2747. std::wcout << L"This is " << str.get() << std::endl; // prints "This is a string"
  2748. NOTE: If source is not null terminated, then length MUST be equal to or less than the size
  2749. of the buffer pointed to by source.
  2750. ~~~
  2751. */
  2752. template<typename string_type> string_type make_unique_string_nothrow(
  2753. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  2754. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  2755. const wchar_t* source, size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
  2756. {
  2757. // guard against invalid parameters (null source with -1 length)
  2758. FAIL_FAST_IF(!source && (length == static_cast<size_t>(-1)));
  2759. // When the source string exists, calculate the number of characters to copy up to either
  2760. // 1) the length that is given
  2761. // 2) the length of the source string. When the source does not exist, use the given length
  2762. // for calculating both the size of allocated buffer and the number of characters to copy.
  2763. size_t lengthToCopy = length;
  2764. if (source)
  2765. {
  2766. size_t maxLength = length < MAKE_UNIQUE_STRING_MAX_CCH ? length : MAKE_UNIQUE_STRING_MAX_CCH;
  2767. PCWSTR endOfSource = source;
  2768. while (maxLength && (*endOfSource != L'\0'))
  2769. {
  2770. endOfSource++;
  2771. maxLength--;
  2772. }
  2773. lengthToCopy = endOfSource - source;
  2774. }
  2775. if (length == static_cast<size_t>(-1))
  2776. {
  2777. length = lengthToCopy;
  2778. }
  2779. const size_t allocatedBytes = (length + 1) * sizeof(*source);
  2780. auto result = static_cast<PWSTR>(details::string_allocator<string_type>::allocate(allocatedBytes));
  2781. if (result)
  2782. {
  2783. if (source)
  2784. {
  2785. const size_t bytesToCopy = lengthToCopy * sizeof(*source);
  2786. memcpy_s(result, allocatedBytes, source, bytesToCopy);
  2787. result[lengthToCopy] = L'\0'; // ensure the copied string is zero terminated
  2788. }
  2789. else
  2790. {
  2791. *result = L'\0'; // ensure null terminated in the "reserve space" use case.
  2792. }
  2793. result[length] = L'\0'; // ensure the final char of the buffer is zero terminated
  2794. }
  2795. return string_type(result);
  2796. }
  2797. #ifndef WIL_NO_ANSI_STRINGS
  2798. template<typename string_type> string_type make_unique_ansistring_nothrow(
  2799. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  2800. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  2801. PCSTR source, size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
  2802. {
  2803. // guard against invalid parameters (null source with -1 length)
  2804. FAIL_FAST_IF(!source && (length == static_cast<size_t>(-1)));
  2805. if (length == static_cast<size_t>(-1))
  2806. {
  2807. length = strlen(source);
  2808. }
  2809. const size_t cb = (length + 1) * sizeof(*source);
  2810. auto result = static_cast<PSTR>(details::string_allocator<string_type>::allocate(cb));
  2811. if (result)
  2812. {
  2813. if (source)
  2814. {
  2815. memcpy_s(result, cb, source, cb - sizeof(*source));
  2816. }
  2817. else
  2818. {
  2819. *result = '\0'; // ensure null terminated in the "reserve space" use case.
  2820. }
  2821. result[length] = '\0'; // ensure zero terminated
  2822. }
  2823. return string_type(result);
  2824. }
  2825. #endif // WIL_NO_ANSI_STRINGS
  2826. /** Copies a given string into memory allocated with a specified allocator that will fail fast on failure.
  2827. The use of variadic templates parameters supports the 2 forms of make_unique_string, see those for more details.
  2828. */
  2829. template<typename string_type> string_type make_unique_string_failfast(
  2830. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  2831. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  2832. PCWSTR source, size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
  2833. {
  2834. auto result(make_unique_string_nothrow<string_type>(source, length));
  2835. FAIL_FAST_IF_NULL_ALLOC(result);
  2836. return result;
  2837. }
  2838. #ifndef WIL_NO_ANSI_STRINGS
  2839. template<typename string_type> string_type make_unique_ansistring_failfast(
  2840. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  2841. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  2842. PCSTR source, size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
  2843. {
  2844. auto result(make_unique_ansistring_nothrow<string_type>(source, length));
  2845. FAIL_FAST_IF_NULL_ALLOC(result);
  2846. return result;
  2847. }
  2848. #endif // WIL_NO_ANSI_STRINGS
  2849. #ifdef WIL_ENABLE_EXCEPTIONS
  2850. /** Copies a given string into memory allocated with a specified allocator that will throw on failure.
  2851. The use of variadic templates parameters supports the 2 forms of make_unique_string, see those for more details.
  2852. */
  2853. template<typename string_type> string_type make_unique_string(
  2854. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  2855. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  2856. PCWSTR source, size_t length = static_cast<size_t>(-1))
  2857. {
  2858. auto result(make_unique_string_nothrow<string_type>(source, length));
  2859. THROW_IF_NULL_ALLOC(result);
  2860. return result;
  2861. }
  2862. #ifndef WIL_NO_ANSI_STRINGS
  2863. template<typename string_type> string_type make_unique_ansistring(
  2864. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  2865. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  2866. PCSTR source, size_t length = static_cast<size_t>(-1))
  2867. {
  2868. auto result(make_unique_ansistring_nothrow<string_type>(source, length));
  2869. THROW_IF_NULL_ALLOC(result);
  2870. return result;
  2871. }
  2872. #endif // WIL_NO_ANSI_STRINGS
  2873. #endif // WIL_ENABLE_EXCEPTIONS
  2874. /// @cond
  2875. namespace details
  2876. {
  2877. // string_maker abstracts creating a string for common string types. This form supports the
  2878. // wil::unique_xxx_string types. Specializations of other types like HSTRING and std::wstring
  2879. // are found in wil\winrt.h and wil\stl.h.
  2880. // This design supports creating the string in a single step or using two phase construction.
  2881. template<typename string_type> struct string_maker
  2882. {
  2883. HRESULT make(
  2884. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  2885. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  2886. const wchar_t* source,
  2887. size_t length)
  2888. {
  2889. m_value = make_unique_string_nothrow<string_type>(source, length);
  2890. return m_value ? S_OK : E_OUTOFMEMORY;
  2891. }
  2892. wchar_t* buffer() { WI_ASSERT(m_value.get()); return m_value.get(); }
  2893. string_type release() { return wistd::move(m_value); }
  2894. // Utility to abstract access to the null terminated m_value of all string types.
  2895. static PCWSTR get(const string_type& value) { return value.get(); }
  2896. private:
  2897. string_type m_value; // a wil::unique_xxx_string type.
  2898. };
  2899. struct SecureZeroData
  2900. {
  2901. void *pointer;
  2902. size_t sizeBytes;
  2903. SecureZeroData(void *pointer_, size_t sizeBytes_ = 0) WI_NOEXCEPT { pointer = pointer_; sizeBytes = sizeBytes_; }
  2904. operator void *() const WI_NOEXCEPT { return pointer; }
  2905. static void Close(SecureZeroData data) WI_NOEXCEPT { ::SecureZeroMemory(data.pointer, data.sizeBytes); }
  2906. };
  2907. }
  2908. /// @endcond
  2909. typedef unique_any<void*, decltype(&details::SecureZeroData::Close), details::SecureZeroData::Close, details::pointer_access_all, details::SecureZeroData> secure_zero_memory_scope_exit;
  2910. WI_NODISCARD inline secure_zero_memory_scope_exit SecureZeroMemory_scope_exit(_In_reads_bytes_(sizeBytes) void* pSource, size_t sizeBytes)
  2911. {
  2912. return secure_zero_memory_scope_exit(details::SecureZeroData(pSource, sizeBytes));
  2913. }
  2914. WI_NODISCARD inline secure_zero_memory_scope_exit SecureZeroMemory_scope_exit(_In_ PWSTR initializedString)
  2915. {
  2916. return SecureZeroMemory_scope_exit(static_cast<void*>(initializedString), wcslen(initializedString) * sizeof(initializedString[0]));
  2917. }
  2918. /// @cond
  2919. namespace details
  2920. {
  2921. inline void __stdcall FreeProcessHeap(_Pre_opt_valid_ _Frees_ptr_opt_ void* p)
  2922. {
  2923. ::HeapFree(::GetProcessHeap(), 0, p);
  2924. }
  2925. }
  2926. /// @endcond
  2927. struct process_heap_deleter
  2928. {
  2929. template <typename T>
  2930. void operator()(_Pre_opt_valid_ _Frees_ptr_opt_ T* p) const
  2931. {
  2932. details::FreeProcessHeap(p);
  2933. }
  2934. };
  2935. struct virtualalloc_deleter
  2936. {
  2937. template<typename T>
  2938. void operator()(_Pre_opt_valid_ _Frees_ptr_opt_ T* p) const
  2939. {
  2940. ::VirtualFree(p, 0, MEM_RELEASE);
  2941. }
  2942. };
  2943. struct mapview_deleter
  2944. {
  2945. template<typename T>
  2946. void operator()(_Pre_opt_valid_ _Frees_ptr_opt_ T* p) const
  2947. {
  2948. ::UnmapViewOfFile(p);
  2949. }
  2950. };
  2951. template <typename T = void>
  2952. using unique_process_heap_ptr = wistd::unique_ptr<T, process_heap_deleter>;
  2953. typedef unique_any<PWSTR, decltype(&details::FreeProcessHeap), details::FreeProcessHeap> unique_process_heap_string;
  2954. /// @cond
  2955. namespace details
  2956. {
  2957. template<> struct string_allocator<unique_process_heap_string>
  2958. {
  2959. static _Ret_opt_bytecap_(size) void* allocate(size_t size) WI_NOEXCEPT
  2960. {
  2961. return ::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, size);
  2962. }
  2963. };
  2964. }
  2965. /// @endcond
  2966. /** Manages a typed pointer allocated with VirtualAlloc
  2967. A specialization of wistd::unique_ptr<> that frees via VirtualFree(p, 0, MEM_RELEASE).
  2968. */
  2969. template<typename T = void>
  2970. using unique_virtualalloc_ptr = wistd::unique_ptr<T, virtualalloc_deleter>;
  2971. /** Manages a typed pointer allocated with MapViewOfFile
  2972. A specialization of wistd::unique_ptr<> that frees via UnmapViewOfFile(p).
  2973. */
  2974. template<typename T>
  2975. using unique_mapview_ptr = wistd::unique_ptr<T, mapview_deleter>;
  2976. #endif // __WIL_WINBASE_
  2977. #if defined(__WIL_WINBASE_) && defined(__NOTHROW_T_DEFINED) && !defined(__WIL_WINBASE_NOTHROW_T_DEFINED)
  2978. #define __WIL_WINBASE_NOTHROW_T_DEFINED
  2979. // unique_event_watcher, unique_event_watcher_nothrow, unique_event_watcher_failfast
  2980. //
  2981. // Clients must include <new> or <new.h> to enable use of this class as it uses new(std::nothrow).
  2982. // This is to avoid the dependency on those headers that some clients can't tolerate.
  2983. //
  2984. // These classes makes it easy to execute a provided function when an event
  2985. // is signaled. It will create the event handle for you, take ownership of one
  2986. // or duplicate a handle provided. It supports the ability to signal the
  2987. // event using SetEvent() and SetEvent_scope_exit();
  2988. //
  2989. // This can be used to support producer-consumer pattern
  2990. // where a producer updates some state then signals the event when done.
  2991. // The consumer will consume that state in the callback provided to unique_event_watcher.
  2992. //
  2993. // Note, multiple signals may coalesce into a single callback.
  2994. //
  2995. // Example use of throwing version:
  2996. // auto globalStateWatcher = wil::make_event_watcher([]
  2997. // {
  2998. // currentState = GetGlobalState();
  2999. // });
  3000. //
  3001. // UpdateGlobalState(value);
  3002. // globalStateWatcher.SetEvent(); // signal observers so they can update
  3003. //
  3004. // Example use of non-throwing version:
  3005. // auto globalStateWatcher = wil::make_event_watcher_nothrow([]
  3006. // {
  3007. // currentState = GetGlobalState();
  3008. // });
  3009. // RETURN_IF_NULL_ALLOC(globalStateWatcher);
  3010. //
  3011. // UpdateGlobalState(value);
  3012. // globalStateWatcher.SetEvent(); // signal observers so they can update
  3013. /// @cond
  3014. namespace details
  3015. {
  3016. struct event_watcher_state
  3017. {
  3018. event_watcher_state(unique_event_nothrow &&eventHandle, wistd::function<void()> &&callback)
  3019. : m_callback(wistd::move(callback)), m_event(wistd::move(eventHandle))
  3020. {
  3021. }
  3022. wistd::function<void()> m_callback;
  3023. unique_event_nothrow m_event;
  3024. // The thread pool must be last to ensure that the other members are valid
  3025. // when it is destructed as it will reference them.
  3026. unique_threadpool_wait m_threadPoolWait;
  3027. };
  3028. inline void delete_event_watcher_state(_In_opt_ event_watcher_state *watcherStorage) { delete watcherStorage; }
  3029. typedef resource_policy<event_watcher_state *, decltype(&delete_event_watcher_state),
  3030. delete_event_watcher_state, details::pointer_access_none> event_watcher_state_resource_policy;
  3031. }
  3032. /// @endcond
  3033. template <typename storage_t, typename err_policy = err_exception_policy>
  3034. class event_watcher_t : public storage_t
  3035. {
  3036. public:
  3037. // forward all base class constructors...
  3038. template <typename... args_t>
  3039. explicit event_watcher_t(args_t&&... args) WI_NOEXCEPT : storage_t(wistd::forward<args_t>(args)...) {}
  3040. // HRESULT or void error handling...
  3041. typedef typename err_policy::result result;
  3042. // Exception-based constructors
  3043. template <typename err_policy>
  3044. event_watcher_t(unique_any_t<event_t<details::unique_storage<details::handle_resource_policy>, err_policy>> &&eventHandle, wistd::function<void()> &&callback)
  3045. {
  3046. static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions or fail fast; use the create method");
  3047. create(wistd::move(eventHandle), wistd::move(callback));
  3048. }
  3049. event_watcher_t(_In_ HANDLE eventHandle, wistd::function<void()> &&callback)
  3050. {
  3051. static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions or fail fast; use the create method");
  3052. create(eventHandle, wistd::move(callback));
  3053. }
  3054. event_watcher_t(wistd::function<void()> &&callback)
  3055. {
  3056. static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions or fail fast; use the create method");
  3057. create(wistd::move(callback));
  3058. }
  3059. template <typename event_err_policy>
  3060. result create(unique_any_t<event_t<details::unique_storage<details::handle_resource_policy>, event_err_policy>> &&eventHandle,
  3061. wistd::function<void()> &&callback)
  3062. {
  3063. return err_policy::HResult(create_take_hevent_ownership(eventHandle.release(), wistd::move(callback)));
  3064. }
  3065. // Creates the event that you will be watching.
  3066. result create(wistd::function<void()> &&callback)
  3067. {
  3068. unique_event_nothrow eventHandle;
  3069. HRESULT hr = eventHandle.create(EventOptions::ManualReset); // auto-reset is supported too.
  3070. if (FAILED(hr))
  3071. {
  3072. return err_policy::HResult(hr);
  3073. }
  3074. return err_policy::HResult(create_take_hevent_ownership(eventHandle.release(), wistd::move(callback)));
  3075. }
  3076. // Input is an event handler that is duplicated into this class.
  3077. result create(_In_ HANDLE eventHandle, wistd::function<void()> &&callback)
  3078. {
  3079. unique_event_nothrow ownedHandle;
  3080. if (!DuplicateHandle(GetCurrentProcess(), eventHandle, GetCurrentProcess(), &ownedHandle, 0, FALSE, DUPLICATE_SAME_ACCESS))
  3081. {
  3082. return err_policy::LastError();
  3083. }
  3084. return err_policy::HResult(create_take_hevent_ownership(ownedHandle.release(), wistd::move(callback)));
  3085. }
  3086. // Provide access to the inner event and the very common SetEvent() method on it.
  3087. unique_event_nothrow const& get_event() const WI_NOEXCEPT { return storage_t::get()->m_event; }
  3088. void SetEvent() const WI_NOEXCEPT { storage_t::get()->m_event.SetEvent(); }
  3089. private:
  3090. // Had to move this from a Lambda so it would compile in C++/CLI (which thought the Lambda should be a managed function for some reason).
  3091. static void CALLBACK wait_callback(PTP_CALLBACK_INSTANCE, void *context, TP_WAIT *pThreadPoolWait, TP_WAIT_RESULT)
  3092. {
  3093. auto pThis = static_cast<details::event_watcher_state *>(context);
  3094. // Manual events must be re-set to avoid missing the last notification.
  3095. pThis->m_event.ResetEvent();
  3096. // Call the client before re-arming to ensure that multiple callbacks don't
  3097. // run concurrently.
  3098. pThis->m_callback();
  3099. SetThreadpoolWait(pThreadPoolWait, pThis->m_event.get(), nullptr); // valid params ensure success
  3100. }
  3101. // To avoid template expansion (if unique_event/unique_event_nothrow forms were used) this base
  3102. // create function takes a raw handle and assumes its ownership, even on failure.
  3103. HRESULT create_take_hevent_ownership(_In_ HANDLE rawHandleOwnershipTaken, wistd::function<void()> &&callback)
  3104. {
  3105. __FAIL_FAST_ASSERT__(rawHandleOwnershipTaken != nullptr); // invalid parameter
  3106. unique_event_nothrow eventHandle(rawHandleOwnershipTaken);
  3107. wistd::unique_ptr<details::event_watcher_state> watcherState(new(std::nothrow) details::event_watcher_state(wistd::move(eventHandle), wistd::move(callback)));
  3108. RETURN_IF_NULL_ALLOC(watcherState);
  3109. watcherState->m_threadPoolWait.reset(CreateThreadpoolWait(wait_callback, watcherState.get(), nullptr));
  3110. RETURN_LAST_ERROR_IF(!watcherState->m_threadPoolWait);
  3111. storage_t::reset(watcherState.release()); // no more failures after this, pass ownership
  3112. SetThreadpoolWait(storage_t::get()->m_threadPoolWait.get(), storage_t::get()->m_event.get(), nullptr);
  3113. return S_OK;
  3114. }
  3115. };
  3116. typedef unique_any_t<event_watcher_t<details::unique_storage<details::event_watcher_state_resource_policy>, err_returncode_policy>> unique_event_watcher_nothrow;
  3117. typedef unique_any_t<event_watcher_t<details::unique_storage<details::event_watcher_state_resource_policy>, err_failfast_policy>> unique_event_watcher_failfast;
  3118. template <typename err_policy>
  3119. unique_event_watcher_nothrow make_event_watcher_nothrow(unique_any_t<event_t<details::unique_storage<details::handle_resource_policy>, err_policy>> &&eventHandle, wistd::function<void()> &&callback) WI_NOEXCEPT
  3120. {
  3121. unique_event_watcher_nothrow watcher;
  3122. watcher.create(wistd::move(eventHandle), wistd::move(callback));
  3123. return watcher; // caller must test for success using if (watcher)
  3124. }
  3125. inline unique_event_watcher_nothrow make_event_watcher_nothrow(_In_ HANDLE eventHandle, wistd::function<void()> &&callback) WI_NOEXCEPT
  3126. {
  3127. unique_event_watcher_nothrow watcher;
  3128. watcher.create(eventHandle, wistd::move(callback));
  3129. return watcher; // caller must test for success using if (watcher)
  3130. }
  3131. inline unique_event_watcher_nothrow make_event_watcher_nothrow(wistd::function<void()> &&callback) WI_NOEXCEPT
  3132. {
  3133. unique_event_watcher_nothrow watcher;
  3134. watcher.create(wistd::move(callback));
  3135. return watcher; // caller must test for success using if (watcher)
  3136. }
  3137. template <typename err_policy>
  3138. unique_event_watcher_failfast make_event_watcher_failfast(unique_any_t<event_t<details::unique_storage<details::handle_resource_policy>, err_policy>> &&eventHandle, wistd::function<void()> &&callback)
  3139. {
  3140. return unique_event_watcher_failfast(wistd::move(eventHandle), wistd::move(callback));
  3141. }
  3142. inline unique_event_watcher_failfast make_event_watcher_failfast(_In_ HANDLE eventHandle, wistd::function<void()> &&callback)
  3143. {
  3144. return unique_event_watcher_failfast(eventHandle, wistd::move(callback));
  3145. }
  3146. inline unique_event_watcher_failfast make_event_watcher_failfast(wistd::function<void()> &&callback)
  3147. {
  3148. return unique_event_watcher_failfast(wistd::move(callback));
  3149. }
  3150. #ifdef WIL_ENABLE_EXCEPTIONS
  3151. typedef unique_any_t<event_watcher_t<details::unique_storage<details::event_watcher_state_resource_policy>, err_exception_policy>> unique_event_watcher;
  3152. template <typename err_policy>
  3153. unique_event_watcher make_event_watcher(unique_any_t<event_t<details::unique_storage<details::handle_resource_policy>, err_policy>> &&eventHandle, wistd::function<void()> &&callback)
  3154. {
  3155. return unique_event_watcher(wistd::move(eventHandle), wistd::move(callback));
  3156. }
  3157. inline unique_event_watcher make_event_watcher(_In_ HANDLE eventHandle, wistd::function<void()> &&callback)
  3158. {
  3159. return unique_event_watcher(eventHandle, wistd::move(callback));
  3160. }
  3161. inline unique_event_watcher make_event_watcher(wistd::function<void()> &&callback)
  3162. {
  3163. return unique_event_watcher(wistd::move(callback));
  3164. }
  3165. #endif // WIL_ENABLE_EXCEPTIONS
  3166. #endif // __WIL_WINBASE_NOTHROW_T_DEFINED
  3167. #if defined(__WIL_WINBASE_) && !defined(__WIL_WINBASE_STL) && defined(WIL_RESOURCE_STL)
  3168. #define __WIL_WINBASE_STL
  3169. typedef shared_any_t<event_t<details::shared_storage<unique_event>>> shared_event;
  3170. typedef shared_any_t<mutex_t<details::shared_storage<unique_mutex>>> shared_mutex;
  3171. typedef shared_any_t<semaphore_t<details::shared_storage<unique_semaphore>>> shared_semaphore;
  3172. typedef shared_any<unique_hfile> shared_hfile;
  3173. typedef shared_any<unique_handle> shared_handle;
  3174. typedef shared_any<unique_hfind> shared_hfind;
  3175. typedef shared_any<unique_hmodule> shared_hmodule;
  3176. #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  3177. typedef shared_any<unique_threadpool_wait> shared_threadpool_wait;
  3178. typedef shared_any<unique_threadpool_wait_nocancel> shared_threadpool_wait_nocancel;
  3179. typedef shared_any<unique_threadpool_work> shared_threadpool_work;
  3180. typedef shared_any<unique_threadpool_work_nocancel> shared_threadpool_work_nocancel;
  3181. typedef shared_any<unique_hfind_change> shared_hfind_change;
  3182. #endif
  3183. typedef weak_any<shared_event> weak_event;
  3184. typedef weak_any<shared_mutex> weak_mutex;
  3185. typedef weak_any<shared_semaphore> weak_semaphore;
  3186. typedef weak_any<shared_hfile> weak_hfile;
  3187. typedef weak_any<shared_handle> weak_handle;
  3188. typedef weak_any<shared_hfind> weak_hfind;
  3189. typedef weak_any<shared_hmodule> weak_hmodule;
  3190. #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  3191. typedef weak_any<shared_threadpool_wait> weak_threadpool_wait;
  3192. typedef weak_any<shared_threadpool_wait_nocancel> weak_threadpool_wait_nocancel;
  3193. typedef weak_any<shared_threadpool_work> weak_threadpool_work;
  3194. typedef weak_any<shared_threadpool_work_nocancel> weak_threadpool_work_nocancel;
  3195. typedef weak_any<shared_hfind_change> weak_hfind_change;
  3196. #endif
  3197. #endif // __WIL_WINBASE_STL
  3198. #if defined(__WIL_WINBASE_) && defined(__NOTHROW_T_DEFINED) && !defined(__WIL_WINBASE_NOTHROW_T_DEFINED_STL) && defined(WIL_RESOURCE_STL) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  3199. #define __WIL_WINBASE_NOTHROW_T_DEFINED_STL
  3200. typedef shared_any_t<event_watcher_t<details::shared_storage<unique_event_watcher>>> shared_event_watcher;
  3201. typedef weak_any<shared_event_watcher> weak_event_watcher;
  3202. #endif // __WIL_WINBASE_NOTHROW_T_DEFINED_STL
  3203. #if defined(__WIL_WINBASE_) && !defined(__WIL_WINBASE_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  3204. #define __WIL_WINBASE_DESKTOP
  3205. /// @cond
  3206. namespace details
  3207. {
  3208. inline void __stdcall DestroyPrivateObjectSecurity(_Pre_opt_valid_ _Frees_ptr_opt_ PSECURITY_DESCRIPTOR pObjectDescriptor) WI_NOEXCEPT
  3209. {
  3210. ::DestroyPrivateObjectSecurity(&pObjectDescriptor);
  3211. }
  3212. }
  3213. /// @endcond
  3214. using hlocal_deleter = function_deleter<decltype(&::LocalFree), LocalFree>;
  3215. template <typename T = void>
  3216. using unique_hlocal_ptr = wistd::unique_ptr<T, hlocal_deleter>;
  3217. /** Provides `std::make_unique()` semantics for resources allocated with `LocalAlloc()` in a context that may not throw upon allocation failure.
  3218. Use `wil::make_unique_hlocal_nothrow()` for resources returned from APIs that must satisfy a memory allocation contract that requires the use of `LocalAlloc()` / `LocalFree()`.
  3219. Use `wil::make_unique_nothrow()` when `LocalAlloc()` is not required.
  3220. Allocations are initialized with placement new and will call constructors (if present), but this does not guarantee initialization.
  3221. Note that `wil::make_unique_hlocal_nothrow()` is not marked WI_NOEXCEPT as it may be used to create an exception-based class that may throw in its constructor.
  3222. ~~~
  3223. auto foo = wil::make_unique_hlocal_nothrow<Foo>();
  3224. if (foo)
  3225. {
  3226. // initialize allocated Foo object as appropriate
  3227. }
  3228. ~~~
  3229. */
  3230. template <typename T, typename... Args>
  3231. inline typename wistd::enable_if<!wistd::is_array<T>::value, unique_hlocal_ptr<T>>::type make_unique_hlocal_nothrow(Args&&... args)
  3232. {
  3233. static_assert(wistd::is_trivially_destructible<T>::value, "T has a destructor that won't be run when used with this function; use make_unique instead");
  3234. unique_hlocal_ptr<T> sp(static_cast<T*>(::LocalAlloc(LMEM_FIXED, sizeof(T))));
  3235. if (sp)
  3236. {
  3237. // use placement new to initialize memory from the previous allocation
  3238. new (sp.get()) T(wistd::forward<Args>(args)...);
  3239. }
  3240. return sp;
  3241. }
  3242. /** Provides `std::make_unique()` semantics for array resources allocated with `LocalAlloc()` in a context that may not throw upon allocation failure.
  3243. See the overload of `wil::make_unique_hlocal_nothrow()` for non-array types for more details.
  3244. ~~~
  3245. const size_t size = 42;
  3246. auto foos = wil::make_unique_hlocal_nothrow<Foo[]>(size);
  3247. if (foos)
  3248. {
  3249. for (auto& elem : wil::make_range(foos.get(), size))
  3250. {
  3251. // initialize allocated Foo objects as appropriate
  3252. }
  3253. }
  3254. ~~~
  3255. */
  3256. template <typename T>
  3257. inline typename wistd::enable_if<wistd::is_array<T>::value && wistd::extent<T>::value == 0, unique_hlocal_ptr<T>>::type make_unique_hlocal_nothrow(size_t size)
  3258. {
  3259. typedef typename wistd::remove_extent<T>::type E;
  3260. static_assert(wistd::is_trivially_destructible<E>::value, "E has a destructor that won't be run when used with this function; use make_unique instead");
  3261. FAIL_FAST_IF((__WI_SIZE_MAX / sizeof(E)) < size);
  3262. size_t allocSize = sizeof(E) * size;
  3263. unique_hlocal_ptr<T> sp(static_cast<E*>(::LocalAlloc(LMEM_FIXED, allocSize)));
  3264. if (sp)
  3265. {
  3266. // use placement new to initialize memory from the previous allocation;
  3267. // note that array placement new cannot be used as the standard allows for operator new[]
  3268. // to consume overhead in the allocation for internal bookkeeping
  3269. for (auto& elem : make_range(static_cast<E*>(sp.get()), size))
  3270. {
  3271. new (&elem) E();
  3272. }
  3273. }
  3274. return sp;
  3275. }
  3276. /** Provides `std::make_unique()` semantics for resources allocated with `LocalAlloc()` in a context that must fail fast upon allocation failure.
  3277. See the overload of `wil::make_unique_hlocal_nothrow()` for non-array types for more details.
  3278. ~~~
  3279. auto foo = wil::make_unique_hlocal_failfast<Foo>();
  3280. // initialize allocated Foo object as appropriate
  3281. ~~~
  3282. */
  3283. template <typename T, typename... Args>
  3284. inline typename wistd::enable_if<!wistd::is_array<T>::value, unique_hlocal_ptr<T>>::type make_unique_hlocal_failfast(Args&&... args)
  3285. {
  3286. unique_hlocal_ptr<T> result(make_unique_hlocal_nothrow<T>(wistd::forward<Args>(args)...));
  3287. FAIL_FAST_IF_NULL_ALLOC(result);
  3288. return result;
  3289. }
  3290. /** Provides `std::make_unique()` semantics for array resources allocated with `LocalAlloc()` in a context that must fail fast upon allocation failure.
  3291. See the overload of `wil::make_unique_hlocal_nothrow()` for non-array types for more details.
  3292. ~~~
  3293. const size_t size = 42;
  3294. auto foos = wil::make_unique_hlocal_failfast<Foo[]>(size);
  3295. for (auto& elem : wil::make_range(foos.get(), size))
  3296. {
  3297. // initialize allocated Foo objects as appropriate
  3298. }
  3299. ~~~
  3300. */
  3301. template <typename T>
  3302. inline typename wistd::enable_if<wistd::is_array<T>::value && wistd::extent<T>::value == 0, unique_hlocal_ptr<T>>::type make_unique_hlocal_failfast(size_t size)
  3303. {
  3304. unique_hlocal_ptr<T> result(make_unique_hlocal_nothrow<T>(size));
  3305. FAIL_FAST_IF_NULL_ALLOC(result);
  3306. return result;
  3307. }
  3308. #ifdef WIL_ENABLE_EXCEPTIONS
  3309. /** Provides `std::make_unique()` semantics for resources allocated with `LocalAlloc()`.
  3310. See the overload of `wil::make_unique_hlocal_nothrow()` for non-array types for more details.
  3311. ~~~
  3312. auto foo = wil::make_unique_hlocal<Foo>();
  3313. // initialize allocated Foo object as appropriate
  3314. ~~~
  3315. */
  3316. template <typename T, typename... Args>
  3317. inline typename wistd::enable_if<!wistd::is_array<T>::value, unique_hlocal_ptr<T>>::type make_unique_hlocal(Args&&... args)
  3318. {
  3319. unique_hlocal_ptr<T> result(make_unique_hlocal_nothrow<T>(wistd::forward<Args>(args)...));
  3320. THROW_IF_NULL_ALLOC(result);
  3321. return result;
  3322. }
  3323. /** Provides `std::make_unique()` semantics for array resources allocated with `LocalAlloc()`.
  3324. See the overload of `wil::make_unique_hlocal_nothrow()` for non-array types for more details.
  3325. ~~~
  3326. const size_t size = 42;
  3327. auto foos = wil::make_unique_hlocal<Foo[]>(size);
  3328. for (auto& elem : wil::make_range(foos.get(), size))
  3329. {
  3330. // initialize allocated Foo objects as appropriate
  3331. }
  3332. ~~~
  3333. */
  3334. template <typename T>
  3335. inline typename wistd::enable_if<wistd::is_array<T>::value && wistd::extent<T>::value == 0, unique_hlocal_ptr<T>>::type make_unique_hlocal(size_t size)
  3336. {
  3337. unique_hlocal_ptr<T> result(make_unique_hlocal_nothrow<T>(size));
  3338. THROW_IF_NULL_ALLOC(result);
  3339. return result;
  3340. }
  3341. #endif // WIL_ENABLE_EXCEPTIONS
  3342. typedef unique_any<HLOCAL, decltype(&::LocalFree), ::LocalFree> unique_hlocal;
  3343. typedef unique_any<PWSTR, decltype(&::LocalFree), ::LocalFree> unique_hlocal_string;
  3344. #ifndef WIL_NO_ANSI_STRINGS
  3345. typedef unique_any<PSTR, decltype(&::LocalFree), ::LocalFree> unique_hlocal_ansistring;
  3346. #endif // WIL_NO_ANSI_STRINGS
  3347. /// @cond
  3348. namespace details
  3349. {
  3350. struct localalloc_allocator
  3351. {
  3352. static _Ret_opt_bytecap_(size) void* allocate(size_t size) WI_NOEXCEPT
  3353. {
  3354. return ::LocalAlloc(LMEM_FIXED, size);
  3355. }
  3356. };
  3357. template<> struct string_allocator<unique_hlocal_string> : localalloc_allocator {};
  3358. #ifndef WIL_NO_ANSI_STRINGS
  3359. template<> struct string_allocator<unique_hlocal_ansistring> : localalloc_allocator {};
  3360. #endif // WIL_NO_ANSI_STRINGS
  3361. }
  3362. /// @endcond
  3363. inline auto make_hlocal_string_nothrow(
  3364. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  3365. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  3366. PCWSTR source, size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
  3367. {
  3368. return make_unique_string_nothrow<unique_hlocal_string>(source, length);
  3369. }
  3370. inline auto make_hlocal_string_failfast(
  3371. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  3372. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  3373. PCWSTR source, size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
  3374. {
  3375. return make_unique_string_failfast<unique_hlocal_string>(source, length);
  3376. }
  3377. #ifndef WIL_NO_ANSI_STRINGS
  3378. inline auto make_hlocal_ansistring_nothrow(
  3379. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  3380. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  3381. PCSTR source, size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
  3382. {
  3383. return make_unique_ansistring_nothrow<unique_hlocal_ansistring>(source, length);
  3384. }
  3385. inline auto make_hlocal_ansistring_failfast(
  3386. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  3387. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  3388. PCSTR source, size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
  3389. {
  3390. return make_unique_ansistring_failfast<unique_hlocal_ansistring>(source, length);
  3391. }
  3392. #endif
  3393. #ifdef WIL_ENABLE_EXCEPTIONS
  3394. inline auto make_hlocal_string(
  3395. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  3396. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  3397. PCWSTR source, size_t length = static_cast<size_t>(-1))
  3398. {
  3399. return make_unique_string<unique_hlocal_string>(source, length);
  3400. }
  3401. #ifndef WIL_NO_ANSI_STRINGS
  3402. inline auto make_hlocal_ansistring(
  3403. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  3404. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  3405. PCSTR source, size_t length = static_cast<size_t>(-1))
  3406. {
  3407. return make_unique_ansistring<unique_hlocal_ansistring>(source, length);
  3408. }
  3409. #endif // WIL_NO_ANSI_STRINGS
  3410. #endif // WIL_ENABLE_EXCEPTIONS
  3411. struct hlocal_secure_deleter
  3412. {
  3413. template <typename T>
  3414. void operator()(_Pre_opt_valid_ _Frees_ptr_opt_ T* p) const
  3415. {
  3416. if (p)
  3417. {
  3418. #pragma warning(suppress: 26006 26007) // LocalSize() ensures proper buffer length
  3419. ::SecureZeroMemory(p, ::LocalSize(p)); // this is safe since LocalSize() returns 0 on failure
  3420. ::LocalFree(p);
  3421. }
  3422. }
  3423. };
  3424. template <typename T = void>
  3425. using unique_hlocal_secure_ptr = wistd::unique_ptr<T, hlocal_secure_deleter>;
  3426. /** Provides `std::make_unique()` semantics for secure resources allocated with `LocalAlloc()` in a context that may not throw upon allocation failure.
  3427. See the overload of `wil::make_unique_hlocal_nothrow()` for non-array types for more details.
  3428. ~~~
  3429. auto foo = wil::make_unique_hlocal_secure_nothrow<Foo>();
  3430. if (foo)
  3431. {
  3432. // initialize allocated Foo object as appropriate
  3433. }
  3434. ~~~
  3435. */
  3436. template <typename T, typename... Args>
  3437. inline typename wistd::enable_if<!wistd::is_array<T>::value, unique_hlocal_secure_ptr<T>>::type make_unique_hlocal_secure_nothrow(Args&&... args)
  3438. {
  3439. return unique_hlocal_secure_ptr<T>(make_unique_hlocal_nothrow<T>(wistd::forward<Args>(args)...).release());
  3440. }
  3441. /** Provides `std::make_unique()` semantics for secure array resources allocated with `LocalAlloc()` in a context that may not throw upon allocation failure.
  3442. See the overload of `wil::make_unique_hlocal_nothrow()` for non-array types for more details.
  3443. ~~~
  3444. const size_t size = 42;
  3445. auto foos = wil::make_unique_hlocal_secure_nothrow<Foo[]>(size);
  3446. if (foos)
  3447. {
  3448. for (auto& elem : wil::make_range(foos.get(), size))
  3449. {
  3450. // initialize allocated Foo objects as appropriate
  3451. }
  3452. }
  3453. ~~~
  3454. */
  3455. template <typename T>
  3456. inline typename wistd::enable_if<wistd::is_array<T>::value && wistd::extent<T>::value == 0, unique_hlocal_secure_ptr<T>>::type make_unique_hlocal_secure_nothrow(size_t size)
  3457. {
  3458. return unique_hlocal_secure_ptr<T>(make_unique_hlocal_nothrow<T>(size).release());
  3459. }
  3460. /** Provides `std::make_unique()` semantics for secure resources allocated with `LocalAlloc()` in a context that must fail fast upon allocation failure.
  3461. See the overload of `wil::make_unique_hlocal_nothrow()` for non-array types for more details.
  3462. ~~~
  3463. auto foo = wil::make_unique_hlocal_secure_failfast<Foo>();
  3464. // initialize allocated Foo object as appropriate
  3465. ~~~
  3466. */
  3467. template <typename T, typename... Args>
  3468. inline typename wistd::enable_if<!wistd::is_array<T>::value, unique_hlocal_secure_ptr<T>>::type make_unique_hlocal_secure_failfast(Args&&... args)
  3469. {
  3470. unique_hlocal_secure_ptr<T> result(make_unique_hlocal_secure_nothrow<T>(wistd::forward<Args>(args)...));
  3471. FAIL_FAST_IF_NULL_ALLOC(result);
  3472. return result;
  3473. }
  3474. /** Provides `std::make_unique()` semantics for secure array resources allocated with `LocalAlloc()` in a context that must fail fast upon allocation failure.
  3475. See the overload of `wil::make_unique_hlocal_nothrow()` for non-array types for more details.
  3476. ~~~
  3477. const size_t size = 42;
  3478. auto foos = wil::make_unique_hlocal_secure_failfast<Foo[]>(size);
  3479. for (auto& elem : wil::make_range(foos.get(), size))
  3480. {
  3481. // initialize allocated Foo objects as appropriate
  3482. }
  3483. ~~~
  3484. */
  3485. template <typename T>
  3486. inline typename wistd::enable_if<wistd::is_array<T>::value && wistd::extent<T>::value == 0, unique_hlocal_secure_ptr<T>>::type make_unique_hlocal_secure_failfast(size_t size)
  3487. {
  3488. unique_hlocal_secure_ptr<T> result(make_unique_hlocal_secure_nothrow<T>(size));
  3489. FAIL_FAST_IF_NULL_ALLOC(result);
  3490. return result;
  3491. }
  3492. #ifdef WIL_ENABLE_EXCEPTIONS
  3493. /** Provides `std::make_unique()` semantics for secure resources allocated with `LocalAlloc()`.
  3494. See the overload of `wil::make_unique_hlocal_nothrow()` for non-array types for more details.
  3495. ~~~
  3496. auto foo = wil::make_unique_hlocal_secure<Foo>();
  3497. // initialize allocated Foo object as appropriate
  3498. ~~~
  3499. */
  3500. template <typename T, typename... Args>
  3501. inline typename wistd::enable_if<!wistd::is_array<T>::value, unique_hlocal_secure_ptr<T>>::type make_unique_hlocal_secure(Args&&... args)
  3502. {
  3503. unique_hlocal_secure_ptr<T> result(make_unique_hlocal_secure_nothrow<T>(wistd::forward<Args>(args)...));
  3504. THROW_IF_NULL_ALLOC(result);
  3505. return result;
  3506. }
  3507. /** Provides `std::make_unique()` semantics for secure array resources allocated with `LocalAlloc()`.
  3508. See the overload of `wil::make_unique_hlocal_nothrow()` for non-array types for more details.
  3509. ~~~
  3510. const size_t size = 42;
  3511. auto foos = wil::make_unique_hlocal_secure<Foo[]>(size);
  3512. for (auto& elem : wil::make_range(foos.get(), size))
  3513. {
  3514. // initialize allocated Foo objects as appropriate
  3515. }
  3516. ~~~
  3517. */
  3518. template <typename T>
  3519. inline typename wistd::enable_if<wistd::is_array<T>::value && wistd::extent<T>::value == 0, unique_hlocal_secure_ptr<T>>::type make_unique_hlocal_secure(size_t size)
  3520. {
  3521. unique_hlocal_secure_ptr<T> result(make_unique_hlocal_secure_nothrow<T>(size));
  3522. THROW_IF_NULL_ALLOC(result);
  3523. return result;
  3524. }
  3525. #endif // WIL_ENABLE_EXCEPTIONS
  3526. typedef unique_hlocal_secure_ptr<wchar_t[]> unique_hlocal_string_secure;
  3527. /** Copies a given string into secure memory allocated with `LocalAlloc()` in a context that may not throw upon allocation failure.
  3528. See the overload of `wil::make_hlocal_string_nothrow()` with supplied length for more details.
  3529. ~~~
  3530. auto str = wil::make_hlocal_string_secure_nothrow(L"a string");
  3531. RETURN_IF_NULL_ALLOC(str);
  3532. std::wcout << L"This is " << str.get() << std::endl; // prints "This is a string"
  3533. ~~~
  3534. */
  3535. inline auto make_hlocal_string_secure_nothrow(_In_ PCWSTR source) WI_NOEXCEPT
  3536. {
  3537. return unique_hlocal_string_secure(make_hlocal_string_nothrow(source).release());
  3538. }
  3539. /** Copies a given string into secure memory allocated with `LocalAlloc()` in a context that must fail fast upon allocation failure.
  3540. See the overload of `wil::make_hlocal_string_nothrow()` with supplied length for more details.
  3541. ~~~
  3542. auto str = wil::make_hlocal_string_secure_failfast(L"a string");
  3543. std::wcout << L"This is " << str.get() << std::endl; // prints "This is a string"
  3544. ~~~
  3545. */
  3546. inline auto make_hlocal_string_secure_failfast(_In_ PCWSTR source) WI_NOEXCEPT
  3547. {
  3548. unique_hlocal_string_secure result(make_hlocal_string_secure_nothrow(source));
  3549. FAIL_FAST_IF_NULL_ALLOC(result);
  3550. return result;
  3551. }
  3552. #ifdef WIL_ENABLE_EXCEPTIONS
  3553. /** Copies a given string into secure memory allocated with `LocalAlloc()`.
  3554. See the overload of `wil::make_hlocal_string_nothrow()` with supplied length for more details.
  3555. ~~~
  3556. auto str = wil::make_hlocal_string_secure(L"a string");
  3557. std::wcout << L"This is " << str.get() << std::endl; // prints "This is a string"
  3558. ~~~
  3559. */
  3560. inline auto make_hlocal_string_secure(_In_ PCWSTR source)
  3561. {
  3562. unique_hlocal_string_secure result(make_hlocal_string_secure_nothrow(source));
  3563. THROW_IF_NULL_ALLOC(result);
  3564. return result;
  3565. }
  3566. #endif
  3567. using hglobal_deleter = function_deleter<decltype(&::GlobalFree), ::GlobalFree>;
  3568. template <typename T = void>
  3569. using unique_hglobal_ptr = wistd::unique_ptr<T, hglobal_deleter>;
  3570. typedef unique_any<HGLOBAL, decltype(&::GlobalFree), ::GlobalFree> unique_hglobal;
  3571. typedef unique_any<PWSTR, decltype(&::GlobalFree), ::GlobalFree> unique_hglobal_string;
  3572. #ifndef WIL_NO_ANSI_STRINGS
  3573. typedef unique_any<PSTR, decltype(&::GlobalFree), ::GlobalFree> unique_hglobal_ansistring;
  3574. #endif // WIL_NO_ANSI_STRINGS
  3575. /// @cond
  3576. namespace details
  3577. {
  3578. template<> struct string_allocator<unique_hglobal_string>
  3579. {
  3580. static _Ret_opt_bytecap_(size) void* allocate(size_t size) WI_NOEXCEPT
  3581. {
  3582. return ::GlobalAlloc(GPTR, size);
  3583. }
  3584. };
  3585. }
  3586. /// @endcond
  3587. inline auto make_process_heap_string_nothrow(
  3588. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  3589. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  3590. PCWSTR source, size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
  3591. {
  3592. return make_unique_string_nothrow<unique_process_heap_string>(source, length);
  3593. }
  3594. inline auto make_process_heap_string_failfast(
  3595. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  3596. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  3597. PCWSTR source, size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
  3598. {
  3599. return make_unique_string_failfast<unique_process_heap_string>(source, length);
  3600. }
  3601. #ifdef WIL_ENABLE_EXCEPTIONS
  3602. inline auto make_process_heap_string(
  3603. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  3604. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  3605. PCWSTR source, size_t length = static_cast<size_t>(-1))
  3606. {
  3607. return make_unique_string<unique_process_heap_string>(source, length);
  3608. }
  3609. #endif // WIL_ENABLE_EXCEPTIONS
  3610. typedef unique_any_handle_null<decltype(&::HeapDestroy), ::HeapDestroy> unique_hheap;
  3611. typedef unique_any<DWORD, decltype(&::TlsFree), ::TlsFree, details::pointer_access_all, DWORD, DWORD, TLS_OUT_OF_INDEXES, DWORD> unique_tls;
  3612. typedef unique_any<PSECURITY_DESCRIPTOR, decltype(&::LocalFree), ::LocalFree> unique_hlocal_security_descriptor;
  3613. typedef unique_any<PSECURITY_DESCRIPTOR, decltype(&details::DestroyPrivateObjectSecurity), details::DestroyPrivateObjectSecurity> unique_private_security_descriptor;
  3614. #if defined(_WINUSER_) && !defined(__WIL__WINUSER_)
  3615. #define __WIL__WINUSER_
  3616. typedef unique_any<HACCEL, decltype(&::DestroyAcceleratorTable), ::DestroyAcceleratorTable> unique_haccel;
  3617. typedef unique_any<HCURSOR, decltype(&::DestroyCursor), ::DestroyCursor> unique_hcursor;
  3618. typedef unique_any<HWND, decltype(&::DestroyWindow), ::DestroyWindow> unique_hwnd;
  3619. #if !defined(NOUSER) && !defined(NOWH)
  3620. typedef unique_any<HHOOK, decltype(&::UnhookWindowsHookEx), ::UnhookWindowsHookEx> unique_hhook;
  3621. #endif
  3622. #if !defined(NOWINABLE)
  3623. typedef unique_any<HWINEVENTHOOK, decltype(&::UnhookWinEvent), ::UnhookWinEvent> unique_hwineventhook;
  3624. #endif
  3625. #endif // __WIL__WINUSER_
  3626. #if !defined(NOGDI) && !defined(NODESKTOP)
  3627. typedef unique_any<HDESK, decltype(&::CloseDesktop), ::CloseDesktop> unique_hdesk;
  3628. typedef unique_any<HWINSTA, decltype(&::CloseWindowStation), ::CloseWindowStation> unique_hwinsta;
  3629. #endif // !defined(NOGDI) && !defined(NODESKTOP)
  3630. #endif
  3631. #if defined(__WIL_WINBASE_DESKTOP) && !defined(__WIL_WINBASE_DESKTOP_STL) && defined(WIL_RESOURCE_STL)
  3632. #define __WIL_WINBASE_DESKTOP_STL
  3633. typedef shared_any<unique_hheap> shared_hheap;
  3634. typedef shared_any<unique_hlocal> shared_hlocal;
  3635. typedef shared_any<unique_tls> shared_tls;
  3636. typedef shared_any<unique_hlocal_security_descriptor> shared_hlocal_security_descriptor;
  3637. typedef shared_any<unique_private_security_descriptor> shared_private_security_descriptor;
  3638. typedef shared_any<unique_haccel> shared_haccel;
  3639. typedef shared_any<unique_hcursor> shared_hcursor;
  3640. #if !defined(NOGDI) && !defined(NODESKTOP)
  3641. typedef shared_any<unique_hdesk> shared_hdesk;
  3642. typedef shared_any<unique_hwinsta> shared_hwinsta;
  3643. #endif // !defined(NOGDI) && !defined(NODESKTOP)
  3644. typedef shared_any<unique_hwnd> shared_hwnd;
  3645. #if !defined(NOUSER) && !defined(NOWH)
  3646. typedef shared_any<unique_hhook> shared_hhook;
  3647. #endif
  3648. #if !defined(NOWINABLE)
  3649. typedef shared_any<unique_hwineventhook> shared_hwineventhook;
  3650. #endif
  3651. typedef weak_any<shared_hheap> weak_hheap;
  3652. typedef weak_any<shared_hlocal> weak_hlocal;
  3653. typedef weak_any<shared_tls> weak_tls;
  3654. typedef weak_any<shared_hlocal_security_descriptor> weak_hlocal_security_descriptor;
  3655. typedef weak_any<shared_private_security_descriptor> weak_private_security_descriptor;
  3656. typedef weak_any<shared_haccel> weak_haccel;
  3657. typedef weak_any<shared_hcursor> weak_hcursor;
  3658. #if !defined(NOGDI) && !defined(NODESKTOP)
  3659. typedef weak_any<shared_hdesk> weak_hdesk;
  3660. typedef weak_any<shared_hwinsta> weak_hwinsta;
  3661. #endif // !defined(NOGDI) && !defined(NODESKTOP)
  3662. typedef weak_any<shared_hwnd> weak_hwnd;
  3663. #if !defined(NOUSER) && !defined(NOWH)
  3664. typedef weak_any<shared_hhook> weak_hhook;
  3665. #endif
  3666. #if !defined(NOWINABLE)
  3667. typedef weak_any<shared_hwineventhook> weak_hwineventhook;
  3668. #endif
  3669. #endif // __WIL_WINBASE_DESKTOP_STL
  3670. #if defined(_COMBASEAPI_H_) && !defined(__WIL__COMBASEAPI_H_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) && !defined(WIL_KERNEL_MODE)
  3671. #define __WIL__COMBASEAPI_H_
  3672. #if (NTDDI_VERSION >= NTDDI_WIN8)
  3673. typedef unique_any<CO_MTA_USAGE_COOKIE, decltype(&::CoDecrementMTAUsage), ::CoDecrementMTAUsage> unique_mta_usage_cookie;
  3674. #endif
  3675. typedef unique_any<DWORD, decltype(&::CoRevokeClassObject), ::CoRevokeClassObject> unique_com_class_object_cookie;
  3676. /// @cond
  3677. namespace details
  3678. {
  3679. inline void __stdcall MultiQiCleanup(_In_ MULTI_QI* multiQi)
  3680. {
  3681. if (multiQi->pItf)
  3682. {
  3683. multiQi->pItf->Release();
  3684. multiQi->pItf = nullptr;
  3685. }
  3686. }
  3687. }
  3688. /// @endcond
  3689. //! A type that calls CoRevertToSelf on destruction (or reset()).
  3690. using unique_coreverttoself_call = unique_call<decltype(&::CoRevertToSelf), ::CoRevertToSelf>;
  3691. //! Calls CoImpersonateClient and fail-fasts if it fails; returns an RAII object that reverts
  3692. WI_NODISCARD inline unique_coreverttoself_call CoImpersonateClient_failfast()
  3693. {
  3694. FAIL_FAST_IF_FAILED(::CoImpersonateClient());
  3695. return unique_coreverttoself_call();
  3696. }
  3697. typedef unique_struct<MULTI_QI, decltype(&details::MultiQiCleanup), details::MultiQiCleanup> unique_multi_qi;
  3698. #endif // __WIL__COMBASEAPI_H_
  3699. #if defined(__WIL__COMBASEAPI_H_) && defined(WIL_ENABLE_EXCEPTIONS) && !defined(__WIL__COMBASEAPI_H_EXCEPTIONAL)
  3700. #define __WIL__COMBASEAPI_H_EXCEPTIONAL
  3701. WI_NODISCARD inline unique_coreverttoself_call CoImpersonateClient()
  3702. {
  3703. THROW_IF_FAILED(::CoImpersonateClient());
  3704. return unique_coreverttoself_call();
  3705. }
  3706. #endif
  3707. #if defined(__WIL__COMBASEAPI_H_) && !defined(__WIL__COMBASEAPI_H__STL) && defined(WIL_RESOURCE_STL) && (NTDDI_VERSION >= NTDDI_WIN8)
  3708. #define __WIL__COMBASEAPI_H__STL
  3709. typedef shared_any<unique_mta_usage_cookie> shared_mta_usage_cookie;
  3710. typedef weak_any<shared_mta_usage_cookie> weak_mta_usage_cookie;
  3711. #endif // __WIL__COMBASEAPI_H__STL
  3712. #if defined(_COMBASEAPI_H_) && !defined(__WIL__COMBASEAPI_H_APP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) && !defined(WIL_KERNEL_MODE)
  3713. #define __WIL__COMBASEAPI_H_APP
  3714. //! A type that calls CoUninitialize on destruction (or reset()).
  3715. using unique_couninitialize_call = unique_call<decltype(&::CoUninitialize), ::CoUninitialize>;
  3716. //! Calls CoInitializeEx and fail-fasts if it fails; returns an RAII object that reverts
  3717. WI_NODISCARD inline unique_couninitialize_call CoInitializeEx_failfast(DWORD coinitFlags = 0 /*COINIT_MULTITHREADED*/)
  3718. {
  3719. FAIL_FAST_IF_FAILED(::CoInitializeEx(nullptr, coinitFlags));
  3720. return unique_couninitialize_call();
  3721. }
  3722. #endif // __WIL__COMBASEAPI_H_APP
  3723. #if defined(__WIL__COMBASEAPI_H_APP) && defined(WIL_ENABLE_EXCEPTIONS) && !defined(__WIL__COMBASEAPI_H_APPEXCEPTIONAL)
  3724. #define __WIL__COMBASEAPI_H_APPEXCEPTIONAL
  3725. WI_NODISCARD inline unique_couninitialize_call CoInitializeEx(DWORD coinitFlags = 0 /*COINIT_MULTITHREADED*/)
  3726. {
  3727. THROW_IF_FAILED(::CoInitializeEx(nullptr, coinitFlags));
  3728. return unique_couninitialize_call();
  3729. }
  3730. #endif
  3731. #if defined(__ROAPI_H_) && !defined(__WIL__ROAPI_H_APP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) && (NTDDI_VERSION >= NTDDI_WIN8)
  3732. #define __WIL__ROAPI_H_APP
  3733. typedef unique_any<RO_REGISTRATION_COOKIE, decltype(&::RoRevokeActivationFactories), ::RoRevokeActivationFactories> unique_ro_registration_cookie;
  3734. //! A type that calls RoUninitialize on destruction (or reset()).
  3735. //! Use as a replacement for Windows::Foundation::Uninitialize.
  3736. using unique_rouninitialize_call = unique_call<decltype(&::RoUninitialize), ::RoUninitialize>;
  3737. //! Calls RoInitialize and fail-fasts if it fails; returns an RAII object that reverts
  3738. //! Use as a replacement for Windows::Foundation::Initialize
  3739. WI_NODISCARD inline unique_rouninitialize_call RoInitialize_failfast(RO_INIT_TYPE initType = RO_INIT_MULTITHREADED)
  3740. {
  3741. FAIL_FAST_IF_FAILED(::RoInitialize(initType));
  3742. return unique_rouninitialize_call();
  3743. }
  3744. #endif // __WIL__ROAPI_H_APP
  3745. #if defined(__WIL__ROAPI_H_APP) && defined(WIL_ENABLE_EXCEPTIONS) && !defined(__WIL__ROAPI_H_APPEXCEPTIONAL)
  3746. #define __WIL__ROAPI_H_APPEXCEPTIONAL
  3747. //! Calls RoInitialize and throws an exception if it fails; returns an RAII object that reverts
  3748. //! Use as a replacement for Windows::Foundation::Initialize
  3749. WI_NODISCARD inline unique_rouninitialize_call RoInitialize(RO_INIT_TYPE initType = RO_INIT_MULTITHREADED)
  3750. {
  3751. THROW_IF_FAILED(::RoInitialize(initType));
  3752. return unique_rouninitialize_call();
  3753. }
  3754. #endif
  3755. #if defined(__WINSTRING_H_) && !defined(__WIL__WINSTRING_H_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
  3756. #define __WIL__WINSTRING_H_
  3757. typedef unique_any<HSTRING, decltype(&::WindowsDeleteString), ::WindowsDeleteString> unique_hstring;
  3758. template<> inline unique_hstring make_unique_string_nothrow<unique_hstring>(
  3759. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  3760. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  3761. PCWSTR source, size_t length) WI_NOEXCEPT
  3762. {
  3763. WI_ASSERT(source != nullptr); // the HSTRING version of this function does not suport this case
  3764. if (length == static_cast<size_t>(-1))
  3765. {
  3766. length = wcslen(source);
  3767. }
  3768. unique_hstring result;
  3769. ::WindowsCreateString(source, static_cast<UINT32>(length), &result);
  3770. return result;
  3771. }
  3772. typedef unique_any<HSTRING_BUFFER, decltype(&::WindowsDeleteStringBuffer), ::WindowsDeleteStringBuffer> unique_hstring_buffer;
  3773. /** Promotes an hstring_buffer to an HSTRING.
  3774. When an HSTRING_BUFFER object is promoted to a real string it must not be passed to WindowsDeleteString. The caller owns the
  3775. HSTRING afterwards.
  3776. ~~~
  3777. HRESULT Type::MakePath(_Out_ HSTRING* path)
  3778. {
  3779. wchar_t* bufferStorage = nullptr;
  3780. wil::unique_hstring_buffer theBuffer;
  3781. RETURN_IF_FAILED(::WindowsPreallocateStringBuffer(65, &bufferStorage, &theBuffer));
  3782. RETURN_IF_FAILED(::PathCchCombine(bufferStorage, 65, m_foo, m_bar));
  3783. RETURN_IF_FAILED(wil::make_hstring_from_buffer_nothrow(wistd::move(theBuffer), path)));
  3784. return S_OK;
  3785. }
  3786. ~~~
  3787. */
  3788. inline HRESULT make_hstring_from_buffer_nothrow(unique_hstring_buffer&& source, _Out_ HSTRING* promoted)
  3789. {
  3790. HRESULT hr = ::WindowsPromoteStringBuffer(source.get(), promoted);
  3791. if (SUCCEEDED(hr))
  3792. {
  3793. source.release();
  3794. }
  3795. return hr;
  3796. }
  3797. //! A fail-fast variant of `make_hstring_from_buffer_nothrow`
  3798. inline unique_hstring make_hstring_from_buffer_failfast(unique_hstring_buffer&& source)
  3799. {
  3800. unique_hstring result;
  3801. FAIL_FAST_IF_FAILED(make_hstring_from_buffer_nothrow(wistd::move(source), &result));
  3802. return result;
  3803. }
  3804. #if defined WIL_ENABLE_EXCEPTIONS
  3805. /** Promotes an hstring_buffer to an HSTRING.
  3806. When an HSTRING_BUFFER object is promoted to a real string it must not be passed to WindowsDeleteString. The caller owns the
  3807. HSTRING afterwards.
  3808. ~~~
  3809. wil::unique_hstring Type::Make()
  3810. {
  3811. wchar_t* bufferStorage = nullptr;
  3812. wil::unique_hstring_buffer theBuffer;
  3813. THROW_IF_FAILED(::WindowsPreallocateStringBuffer(65, &bufferStorage, &theBuffer));
  3814. THROW_IF_FAILED(::PathCchCombine(bufferStorage, 65, m_foo, m_bar));
  3815. return wil::make_hstring_from_buffer(wistd::move(theBuffer));
  3816. }
  3817. ~~~
  3818. */
  3819. inline unique_hstring make_hstring_from_buffer(unique_hstring_buffer&& source)
  3820. {
  3821. unique_hstring result;
  3822. THROW_IF_FAILED(make_hstring_from_buffer_nothrow(wistd::move(source), &result));
  3823. return result;
  3824. }
  3825. #endif
  3826. /// @cond
  3827. namespace details
  3828. {
  3829. template<> struct string_maker<unique_hstring>
  3830. {
  3831. string_maker() = default;
  3832. string_maker(const string_maker&) = delete;
  3833. void operator=(const string_maker&) = delete;
  3834. string_maker& operator=(string_maker&& source) WI_NOEXCEPT
  3835. {
  3836. m_value = wistd::move(source.m_value);
  3837. m_bufferHandle = wistd::move(source.m_bufferHandle);
  3838. m_charBuffer = source.m_charBuffer;
  3839. source.m_charBuffer = nullptr;
  3840. return *this;
  3841. }
  3842. HRESULT make(
  3843. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  3844. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  3845. const wchar_t* source,
  3846. size_t length)
  3847. {
  3848. if (source)
  3849. {
  3850. RETURN_IF_FAILED(WindowsCreateString(source, static_cast<UINT32>(length), &m_value));
  3851. }
  3852. else
  3853. {
  3854. // Need to set it to the empty string to support the empty string case.
  3855. m_value.reset();
  3856. RETURN_IF_FAILED(WindowsPreallocateStringBuffer(static_cast<UINT32>(length), &m_charBuffer, &m_bufferHandle));
  3857. }
  3858. return S_OK;
  3859. }
  3860. wchar_t* buffer() { WI_ASSERT(m_charBuffer != nullptr); return m_charBuffer; }
  3861. const wchar_t* buffer() const { return m_charBuffer; }
  3862. unique_hstring release()
  3863. {
  3864. m_charBuffer = nullptr;
  3865. if (m_bufferHandle)
  3866. {
  3867. return make_hstring_from_buffer_failfast(wistd::move(m_bufferHandle));
  3868. }
  3869. return wistd::move(m_value);
  3870. }
  3871. static PCWSTR get(const wil::unique_hstring& value) { return WindowsGetStringRawBuffer(value.get(), nullptr); }
  3872. private:
  3873. unique_hstring m_value;
  3874. unique_hstring_buffer m_bufferHandle;
  3875. wchar_t* m_charBuffer = nullptr;
  3876. };
  3877. }
  3878. /// @endcond
  3879. // str_raw_ptr is an overloaded function that retrieves a const pointer to the first character in a string's buffer.
  3880. // This is the overload for HSTRING. Other overloads available above.
  3881. inline PCWSTR str_raw_ptr(HSTRING str)
  3882. {
  3883. return WindowsGetStringRawBuffer(str, nullptr);
  3884. }
  3885. inline PCWSTR str_raw_ptr(const unique_hstring& str)
  3886. {
  3887. return str_raw_ptr(str.get());
  3888. }
  3889. #endif // __WIL__WINSTRING_H_
  3890. #if defined(__WIL__WINSTRING_H_) && !defined(__WIL__WINSTRING_H_STL) && defined(WIL_RESOURCE_STL)
  3891. #define __WIL__WINSTRING_H_STL
  3892. typedef shared_any<unique_hstring> shared_hstring;
  3893. typedef shared_any<unique_hstring_buffer> shared_hstring_buffer;
  3894. typedef weak_any<shared_hstring> weak_hstring;
  3895. typedef weak_any<shared_hstring_buffer> weak_hstring_buffer;
  3896. #endif // __WIL__WINSTRING_H_STL
  3897. #if defined(_WINREG_) && !defined(__WIL_WINREG_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && !defined(WIL_KERNEL_MODE)
  3898. #define __WIL_WINREG_
  3899. typedef unique_any<HKEY, decltype(&::RegCloseKey), ::RegCloseKey> unique_hkey;
  3900. #endif // __WIL_WINREG_
  3901. #if defined(__WIL_WINREG_) && !defined(__WIL_WINREG_STL) && defined(WIL_RESOURCE_STL)
  3902. #define __WIL_WINREG_STL
  3903. typedef shared_any<unique_hkey> shared_hkey;
  3904. typedef weak_any<shared_hkey> weak_hkey;
  3905. #endif // __WIL_WINREG_STL
  3906. #if defined(__propidl_h__) && !defined(_WIL__propidl_h__) && !defined(WIL_KERNEL_MODE)
  3907. #define _WIL__propidl_h__
  3908. using unique_prop_variant = wil::unique_struct<PROPVARIANT, decltype(&::PropVariantClear), ::PropVariantClear, decltype(&::PropVariantInit), ::PropVariantInit>;
  3909. #endif // _WIL__propidl_h__
  3910. #if defined(_OLEAUTO_H_) && !defined(__WIL_OLEAUTO_H_) && !defined(WIL_KERNEL_MODE) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
  3911. #define __WIL_OLEAUTO_H_
  3912. using unique_variant = wil::unique_struct<VARIANT, decltype(&::VariantClear), ::VariantClear, decltype(&::VariantInit), ::VariantInit>;
  3913. typedef unique_any<BSTR, decltype(&::SysFreeString), ::SysFreeString> unique_bstr;
  3914. inline wil::unique_bstr make_bstr_nothrow(PCWSTR source) WI_NOEXCEPT
  3915. {
  3916. return wil::unique_bstr(::SysAllocString(source));
  3917. }
  3918. inline wil::unique_bstr make_bstr_failfast(PCWSTR source) WI_NOEXCEPT
  3919. {
  3920. return wil::unique_bstr(FAIL_FAST_IF_NULL_ALLOC(::SysAllocString(source)));
  3921. }
  3922. #ifdef WIL_ENABLE_EXCEPTIONS
  3923. inline wil::unique_bstr make_bstr(PCWSTR source)
  3924. {
  3925. wil::unique_bstr result(make_bstr_nothrow(source));
  3926. THROW_IF_NULL_ALLOC(result);
  3927. return result;
  3928. }
  3929. #endif // WIL_ENABLE_EXCEPTIONS
  3930. #endif // __WIL_OLEAUTO_H_
  3931. #if defined(__WIL_OLEAUTO_H_) && !defined(__WIL_OLEAUTO_H_STL) && defined(WIL_RESOURCE_STL)
  3932. #define __WIL_OLEAUTO_H_STL
  3933. typedef shared_any<unique_bstr> shared_bstr;
  3934. typedef weak_any<shared_bstr> weak_bstr;
  3935. #endif // __WIL_OLEAUTO_H_STL
  3936. #if (defined(_WININET_) || defined(_DUBINET_)) && !defined(__WIL_WININET_)
  3937. #define __WIL_WININET_
  3938. typedef unique_any<HINTERNET, decltype(&::InternetCloseHandle), ::InternetCloseHandle> unique_hinternet;
  3939. #endif // __WIL_WININET_
  3940. #if defined(__WIL_WININET_) && !defined(__WIL_WININET_STL) && defined(WIL_RESOURCE_STL)
  3941. #define __WIL_WININET_STL
  3942. typedef shared_any<unique_hinternet> shared_hinternet;
  3943. typedef weak_any<shared_hinternet> weak_hinternet;
  3944. #endif // __WIL_WININET_STL
  3945. #if defined(_WINHTTPX_) && !defined(__WIL_WINHTTP_)
  3946. #define __WIL_WINHTTP_
  3947. typedef unique_any<HINTERNET, decltype(&::WinHttpCloseHandle), ::WinHttpCloseHandle> unique_winhttp_hinternet;
  3948. #endif // __WIL_WINHTTP_
  3949. #if defined(__WIL_WINHTTP_) && !defined(__WIL_WINHTTP_STL) && defined(WIL_RESOURCE_STL)
  3950. #define __WIL_WINHTTP_STL
  3951. typedef shared_any<unique_winhttp_hinternet> shared_winhttp_hinternet;
  3952. typedef weak_any<shared_winhttp_hinternet> weak_winhttp_hinternet;
  3953. #endif // __WIL_WINHTTP_STL
  3954. #if defined(_WINSOCKAPI_) && !defined(__WIL_WINSOCKAPI_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  3955. #define __WIL_WINSOCKAPI_
  3956. typedef unique_any<SOCKET, int (WINAPI*)(SOCKET), ::closesocket, details::pointer_access_all, SOCKET, SOCKET, INVALID_SOCKET, SOCKET> unique_socket;
  3957. #endif // __WIL_WINSOCKAPI_
  3958. #if defined(__WIL_WINSOCKAPI_) && !defined(__WIL_WINSOCKAPI_STL) && defined(WIL_RESOURCE_STL)
  3959. #define __WIL_WINSOCKAPI_STL
  3960. typedef shared_any<unique_socket> shared_socket;
  3961. typedef weak_any<shared_socket> weak_socket;
  3962. #endif // __WIL_WINSOCKAPI_STL
  3963. #if defined(_WINGDI_) && !defined(__WIL_WINGDI_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && !defined(NOGDI) && !defined(WIL_KERNEL_MODE)
  3964. #define __WIL_WINGDI_
  3965. struct window_dc
  3966. {
  3967. HDC dc;
  3968. HWND hwnd;
  3969. window_dc(HDC dc_, HWND hwnd_ = nullptr) WI_NOEXCEPT { dc = dc_; hwnd = hwnd_; }
  3970. operator HDC() const WI_NOEXCEPT { return dc; }
  3971. static void close(window_dc wdc) WI_NOEXCEPT { ::ReleaseDC(wdc.hwnd, wdc.dc); }
  3972. };
  3973. typedef unique_any<HDC, decltype(&window_dc::close), window_dc::close, details::pointer_access_all, window_dc> unique_hdc_window;
  3974. struct paint_dc
  3975. {
  3976. HWND hwnd;
  3977. PAINTSTRUCT ps;
  3978. paint_dc(HDC hdc = nullptr) { ::ZeroMemory(this, sizeof(*this)); ps.hdc = hdc; }
  3979. operator HDC() const WI_NOEXCEPT { return ps.hdc; }
  3980. static void close(paint_dc pdc) WI_NOEXCEPT { ::EndPaint(pdc.hwnd, &pdc.ps); }
  3981. };
  3982. typedef unique_any<HDC, decltype(&paint_dc::close), paint_dc::close, details::pointer_access_all, paint_dc> unique_hdc_paint;
  3983. struct select_result
  3984. {
  3985. HGDIOBJ hgdi;
  3986. HDC hdc;
  3987. select_result(HGDIOBJ hgdi_, HDC hdc_ = nullptr) WI_NOEXCEPT { hgdi = hgdi_; hdc = hdc_; }
  3988. operator HGDIOBJ() const WI_NOEXCEPT { return hgdi; }
  3989. static void close(select_result sr) WI_NOEXCEPT { ::SelectObject(sr.hdc, sr.hgdi); }
  3990. };
  3991. typedef unique_any<HGDIOBJ, decltype(&select_result::close), select_result::close, details::pointer_access_all, select_result> unique_select_object;
  3992. inline unique_hdc_window GetDC(HWND hwnd) WI_NOEXCEPT
  3993. {
  3994. return unique_hdc_window(window_dc(::GetDC(hwnd), hwnd));
  3995. }
  3996. inline unique_hdc_window GetWindowDC(HWND hwnd) WI_NOEXCEPT
  3997. {
  3998. return unique_hdc_window(window_dc(::GetWindowDC(hwnd), hwnd));
  3999. }
  4000. inline unique_hdc_paint BeginPaint(HWND hwnd, _Out_opt_ PPAINTSTRUCT pPaintStruct = nullptr) WI_NOEXCEPT
  4001. {
  4002. paint_dc pdc;
  4003. HDC hdc = ::BeginPaint(hwnd, &pdc.ps);
  4004. assign_to_opt_param(pPaintStruct, pdc.ps);
  4005. return (hdc == nullptr) ? unique_hdc_paint() : unique_hdc_paint(pdc);
  4006. }
  4007. inline unique_select_object SelectObject(HDC hdc, HGDIOBJ gdiobj) WI_NOEXCEPT
  4008. {
  4009. return unique_select_object(select_result(::SelectObject(hdc, gdiobj), hdc));
  4010. }
  4011. typedef unique_any<HGDIOBJ, decltype(&::DeleteObject), ::DeleteObject> unique_hgdiobj;
  4012. typedef unique_any<HPEN, decltype(&::DeleteObject), ::DeleteObject> unique_hpen;
  4013. typedef unique_any<HBRUSH, decltype(&::DeleteObject), ::DeleteObject> unique_hbrush;
  4014. typedef unique_any<HFONT, decltype(&::DeleteObject), ::DeleteObject> unique_hfont;
  4015. typedef unique_any<HBITMAP, decltype(&::DeleteObject), ::DeleteObject> unique_hbitmap;
  4016. typedef unique_any<HRGN, decltype(&::DeleteObject), ::DeleteObject> unique_hrgn;
  4017. typedef unique_any<HPALETTE, decltype(&::DeleteObject), ::DeleteObject> unique_hpalette;
  4018. typedef unique_any<HDC, decltype(&::DeleteDC), ::DeleteDC> unique_hdc;
  4019. typedef unique_any<HICON, decltype(&::DestroyIcon), ::DestroyIcon> unique_hicon;
  4020. #if !defined(NOMENUS)
  4021. typedef unique_any<HMENU, decltype(&::DestroyMenu), ::DestroyMenu> unique_hmenu;
  4022. #endif // !defined(NOMENUS)
  4023. #endif // __WIL_WINGDI_
  4024. #if defined(__WIL_WINGDI_) && !defined(__WIL_WINGDI_STL) && defined(WIL_RESOURCE_STL)
  4025. #define __WIL_WINGDI_STL
  4026. typedef shared_any<unique_hgdiobj> shared_hgdiobj;
  4027. typedef shared_any<unique_hpen> shared_hpen;
  4028. typedef shared_any<unique_hbrush> shared_hbrush;
  4029. typedef shared_any<unique_hfont> shared_hfont;
  4030. typedef shared_any<unique_hbitmap> shared_hbitmap;
  4031. typedef shared_any<unique_hrgn> shared_hrgn;
  4032. typedef shared_any<unique_hpalette> shared_hpalette;
  4033. typedef shared_any<unique_hdc> shared_hdc;
  4034. typedef shared_any<unique_hicon> shared_hicon;
  4035. #if !defined(NOMENUS)
  4036. typedef shared_any<unique_hmenu> shared_hmenu;
  4037. #endif // !defined(NOMENUS)
  4038. typedef weak_any<shared_hgdiobj> weak_hgdiobj;
  4039. typedef weak_any<shared_hpen> weak_hpen;
  4040. typedef weak_any<shared_hbrush> weak_hbrush;
  4041. typedef weak_any<shared_hfont> weak_hfont;
  4042. typedef weak_any<shared_hbitmap> weak_hbitmap;
  4043. typedef weak_any<shared_hrgn> weak_hrgn;
  4044. typedef weak_any<shared_hpalette> weak_hpalette;
  4045. typedef weak_any<shared_hdc> weak_hdc;
  4046. typedef weak_any<shared_hicon> weak_hicon;
  4047. #if !defined(NOMENUS)
  4048. typedef weak_any<shared_hmenu> weak_hmenu;
  4049. #endif // !defined(NOMENUS)
  4050. #endif // __WIL_WINGDI_STL
  4051. #if defined(_INC_WTSAPI) && !defined(__WIL_WTSAPI)
  4052. #define __WIL_WTSAPI
  4053. template<typename T>
  4054. using unique_wtsmem_ptr = wistd::unique_ptr<T, function_deleter<decltype(&WTSFreeMemory), WTSFreeMemory>>;
  4055. #endif // __WIL_WTSAPI
  4056. #if defined(_WINSCARD_H_) && !defined(__WIL_WINSCARD_H_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4057. #define __WIL_WINSCARD_H_
  4058. typedef unique_any<SCARDCONTEXT, decltype(&::SCardReleaseContext), ::SCardReleaseContext> unique_scardctx;
  4059. #endif // __WIL_WINSCARD_H_
  4060. #if defined(__WIL_WINSCARD_H_) && !defined(__WIL_WINSCARD_H_STL) && defined(WIL_RESOURCE_STL)
  4061. #define __WIL_WINSCARD_H_STL
  4062. typedef shared_any<unique_scardctx> shared_scardctx;
  4063. typedef weak_any<shared_scardctx> weak_scardctx;
  4064. #endif // __WIL_WINSCARD_H_STL
  4065. #if defined(__WINCRYPT_H__) && !defined(__WIL__WINCRYPT_H__) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4066. #define __WIL__WINCRYPT_H__
  4067. /// @cond
  4068. namespace details
  4069. {
  4070. inline void __stdcall CertCloseStoreNoParam(_Pre_opt_valid_ _Frees_ptr_opt_ HCERTSTORE hCertStore) WI_NOEXCEPT
  4071. {
  4072. ::CertCloseStore(hCertStore, 0);
  4073. }
  4074. inline void __stdcall CryptReleaseContextNoParam(_Pre_opt_valid_ _Frees_ptr_opt_ HCRYPTPROV hCryptCtx) WI_NOEXCEPT
  4075. {
  4076. ::CryptReleaseContext(hCryptCtx, 0);
  4077. }
  4078. }
  4079. /// @endcond
  4080. typedef unique_any<PCCERT_CONTEXT, decltype(&::CertFreeCertificateContext), ::CertFreeCertificateContext> unique_cert_context;
  4081. typedef unique_any<PCCERT_CHAIN_CONTEXT, decltype(&::CertFreeCertificateChain), ::CertFreeCertificateChain> unique_cert_chain_context;
  4082. typedef unique_any<HCERTSTORE, decltype(&details::CertCloseStoreNoParam), details::CertCloseStoreNoParam> unique_hcertstore;
  4083. typedef unique_any<HCRYPTPROV, decltype(&details::CryptReleaseContextNoParam), details::CryptReleaseContextNoParam> unique_hcryptprov;
  4084. typedef unique_any<HCRYPTKEY, decltype(&::CryptDestroyKey), ::CryptDestroyKey> unique_hcryptkey;
  4085. typedef unique_any<HCRYPTHASH, decltype(&::CryptDestroyHash), ::CryptDestroyHash> unique_hcrypthash;
  4086. #endif // __WIL__WINCRYPT_H__
  4087. #if defined(__WIL__WINCRYPT_H__) && !defined(__WIL__WINCRYPT_H__STL) && defined(WIL_RESOURCE_STL)
  4088. #define __WIL__WINCRYPT_H__STL
  4089. typedef shared_any<unique_cert_context> shared_cert_context;
  4090. typedef shared_any<unique_cert_chain_context> shared_cert_chain_context;
  4091. typedef shared_any<unique_hcertstore> shared_hcertstore;
  4092. typedef shared_any<unique_hcryptprov> shared_hcryptprov;
  4093. typedef shared_any<unique_hcryptkey> shared_hcryptkey;
  4094. typedef shared_any<unique_hcrypthash> shared_hcrypthash;
  4095. typedef weak_any<shared_cert_context> weak_cert_context;
  4096. typedef weak_any<shared_cert_chain_context> weak_cert_chain_context;
  4097. typedef weak_any<shared_hcertstore> weak_hcertstore;
  4098. typedef weak_any<shared_hcryptprov> weak_hcryptprov;
  4099. typedef weak_any<shared_hcryptkey> weak_hcryptkey;
  4100. typedef weak_any<shared_hcrypthash> weak_hcrypthash;
  4101. #endif // __WIL__WINCRYPT_H__STL
  4102. #if defined(__NCRYPT_H__) && !defined(__WIL_NCRYPT_H__) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4103. #define __WIL_NCRYPT_H__
  4104. using ncrypt_deleter = function_deleter<decltype(&::NCryptFreeBuffer), NCryptFreeBuffer>;
  4105. template <typename T>
  4106. using unique_ncrypt_ptr = wistd::unique_ptr<T, ncrypt_deleter>;
  4107. typedef unique_any<NCRYPT_PROV_HANDLE, decltype(&::NCryptFreeObject), ::NCryptFreeObject> unique_ncrypt_prov;
  4108. typedef unique_any<NCRYPT_KEY_HANDLE, decltype(&::NCryptFreeObject), ::NCryptFreeObject> unique_ncrypt_key;
  4109. typedef unique_any<NCRYPT_SECRET_HANDLE, decltype(&::NCryptFreeObject), ::NCryptFreeObject> unique_ncrypt_secret;
  4110. #endif // __WIL_NCRYPT_H__
  4111. #if defined(__WIL_NCRYPT_H__) && !defined(__WIL_NCRYPT_H_STL) && defined(WIL_RESOURCE_STL)
  4112. #define __WIL_NCRYPT_H_STL
  4113. typedef shared_any<unique_ncrypt_prov> shared_ncrypt_prov;
  4114. typedef shared_any<unique_ncrypt_key> shared_ncrypt_key;
  4115. typedef shared_any<unique_ncrypt_secret> shared_ncrypt_secret;
  4116. typedef weak_any<shared_ncrypt_prov> weak_ncrypt_prov;
  4117. typedef weak_any<shared_ncrypt_key> weak_ncrypt_key;
  4118. typedef weak_any<shared_ncrypt_secret> weak_ncrypt_secret;
  4119. #endif // __WIL_NCRYPT_H_STL
  4120. #if defined(__BCRYPT_H__) && !defined(__WIL_BCRYPT_H__) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4121. #define __WIL_BCRYPT_H__
  4122. /// @cond
  4123. namespace details
  4124. {
  4125. inline void __stdcall BCryptCloseAlgorithmProviderNoFlags(_Pre_opt_valid_ _Frees_ptr_opt_ BCRYPT_ALG_HANDLE hAlgorithm) WI_NOEXCEPT
  4126. {
  4127. if (hAlgorithm)
  4128. {
  4129. ::BCryptCloseAlgorithmProvider(hAlgorithm, 0);
  4130. }
  4131. }
  4132. }
  4133. /// @endcond
  4134. using bcrypt_deleter = function_deleter<decltype(&::BCryptFreeBuffer), BCryptFreeBuffer>;
  4135. template <typename T>
  4136. using unique_bcrypt_ptr = wistd::unique_ptr<T, bcrypt_deleter>;
  4137. typedef unique_any<BCRYPT_ALG_HANDLE, decltype(&details::BCryptCloseAlgorithmProviderNoFlags), details::BCryptCloseAlgorithmProviderNoFlags> unique_bcrypt_algorithm;
  4138. typedef unique_any<BCRYPT_HASH_HANDLE, decltype(&::BCryptDestroyHash), ::BCryptDestroyHash> unique_bcrypt_hash;
  4139. typedef unique_any<BCRYPT_KEY_HANDLE, decltype(&::BCryptDestroyKey), ::BCryptDestroyKey> unique_bcrypt_key;
  4140. typedef unique_any<BCRYPT_SECRET_HANDLE, decltype(&::BCryptDestroySecret), ::BCryptDestroySecret> unique_bcrypt_secret;
  4141. #endif // __WIL_BCRYPT_H__
  4142. #if defined(__WIL_BCRYPT_H__) && !defined(__WIL_BCRYPT_H_STL) && defined(WIL_RESOURCE_STL)
  4143. #define __WIL_BCRYPT_H_STL
  4144. typedef shared_any<unique_bcrypt_algorithm> shared_bcrypt_algorithm;
  4145. typedef shared_any<unique_bcrypt_hash> shared_bcrypt_hash;
  4146. typedef shared_any<unique_bcrypt_key> shared_bcrypt_key;
  4147. typedef shared_any<unique_bcrypt_secret> shared_bcrypt_secret;
  4148. typedef weak_any<shared_bcrypt_algorithm> weak_bcrypt_algorithm;
  4149. typedef weak_any<shared_bcrypt_hash> weak_bcrypt_hash;
  4150. typedef weak_any<unique_bcrypt_key> weak_bcrypt_key;
  4151. typedef weak_any<shared_bcrypt_secret> weak_bcrypt_secret;
  4152. #endif // __WIL_BCRYPT_H_STL
  4153. #if defined(__RPCNDR_H__) && !defined(__WIL__RPCNDR_H__) && !defined(WIL_KERNEL_MODE)
  4154. #define __WIL__RPCNDR_H__
  4155. //! Function deleter for use with pointers allocated by MIDL_user_allocate
  4156. using midl_deleter = function_deleter<decltype(&::MIDL_user_free), MIDL_user_free>;
  4157. //! Unique-ptr holding a type allocated by MIDL_user_alloc or returned from an RPC invocation
  4158. template<typename T = void> using unique_midl_ptr = wistd::unique_ptr<T, midl_deleter>;
  4159. //! Unique-ptr for strings allocated by MIDL_user_alloc
  4160. using unique_midl_string = unique_midl_ptr<wchar_t>;
  4161. #ifndef WIL_NO_ANSI_STRINGS
  4162. using unique_midl_ansistring = unique_midl_ptr<char>;
  4163. #endif
  4164. namespace details
  4165. {
  4166. struct midl_allocator
  4167. {
  4168. static _Ret_opt_bytecap_(size) void* allocate(size_t size) WI_NOEXCEPT
  4169. {
  4170. return ::MIDL_user_allocate(size);
  4171. }
  4172. };
  4173. // Specialization to support construction of unique_midl_string instances
  4174. template<> struct string_allocator<unique_midl_string> : midl_allocator {};
  4175. #ifndef WIL_NO_ANSI_STRINGS
  4176. template<> struct string_allocator<unique_midl_ansistring> : midl_allocator {};
  4177. #endif
  4178. }
  4179. #endif // __WIL__RPCNDR_H__
  4180. #if defined(_OBJBASE_H_) && !defined(__WIL_OBJBASE_H_) && !defined(WIL_KERNEL_MODE)
  4181. #define __WIL_OBJBASE_H_
  4182. using cotaskmem_deleter = function_deleter<decltype(&::CoTaskMemFree), ::CoTaskMemFree>;
  4183. template <typename T = void>
  4184. using unique_cotaskmem_ptr = wistd::unique_ptr<T, cotaskmem_deleter>;
  4185. template <typename T>
  4186. using unique_cotaskmem_array_ptr = unique_array_ptr<T, cotaskmem_deleter>;
  4187. /** Provides `std::make_unique()` semantics for resources allocated with `CoTaskMemAlloc()` in a context that may not throw upon allocation failure.
  4188. Use `wil::make_unique_cotaskmem_nothrow()` for resources returned from APIs that must satisfy a memory allocation contract that requires the use of `CoTaskMemAlloc()` / `CoTaskMemFree()`.
  4189. Use `wil::make_unique_nothrow()` when `CoTaskMemAlloc()` is not required.
  4190. Allocations are initialized with placement new and will call constructors (if present), but this does not guarantee initialization.
  4191. Note that `wil::make_unique_cotaskmem_nothrow()` is not marked WI_NOEXCEPT as it may be used to create an exception-based class that may throw in its constructor.
  4192. ~~~
  4193. auto foo = wil::make_unique_cotaskmem_nothrow<Foo>();
  4194. if (foo)
  4195. {
  4196. // initialize allocated Foo object as appropriate
  4197. }
  4198. ~~~
  4199. */
  4200. template <typename T, typename... Args>
  4201. inline typename wistd::enable_if<!wistd::is_array<T>::value, unique_cotaskmem_ptr<T>>::type make_unique_cotaskmem_nothrow(Args&&... args)
  4202. {
  4203. static_assert(wistd::is_trivially_destructible<T>::value, "T has a destructor that won't be run when used with this function; use make_unique instead");
  4204. unique_cotaskmem_ptr<T> sp(static_cast<T*>(::CoTaskMemAlloc(sizeof(T))));
  4205. if (sp)
  4206. {
  4207. // use placement new to initialize memory from the previous allocation
  4208. new (sp.get()) T(wistd::forward<Args>(args)...);
  4209. }
  4210. return sp;
  4211. }
  4212. /** Provides `std::make_unique()` semantics for array resources allocated with `CoTaskMemAlloc()` in a context that may not throw upon allocation failure.
  4213. See the overload of `wil::make_unique_cotaskmem_nothrow()` for non-array types for more details.
  4214. ~~~
  4215. const size_t size = 42;
  4216. auto foos = wil::make_unique_cotaskmem_nothrow<Foo[]>(size);
  4217. if (foos)
  4218. {
  4219. for (auto& elem : wil::make_range(foos.get(), size))
  4220. {
  4221. // initialize allocated Foo objects as appropriate
  4222. }
  4223. }
  4224. ~~~
  4225. */
  4226. template <typename T>
  4227. inline typename wistd::enable_if<wistd::is_array<T>::value && wistd::extent<T>::value == 0, unique_cotaskmem_ptr<T>>::type make_unique_cotaskmem_nothrow(size_t size)
  4228. {
  4229. typedef typename wistd::remove_extent<T>::type E;
  4230. static_assert(wistd::is_trivially_destructible<E>::value, "E has a destructor that won't be run when used with this function; use make_unique instead");
  4231. FAIL_FAST_IF((__WI_SIZE_MAX / sizeof(E)) < size);
  4232. size_t allocSize = sizeof(E) * size;
  4233. unique_cotaskmem_ptr<T> sp(static_cast<E*>(::CoTaskMemAlloc(allocSize)));
  4234. if (sp)
  4235. {
  4236. // use placement new to initialize memory from the previous allocation;
  4237. // note that array placement new cannot be used as the standard allows for operator new[]
  4238. // to consume overhead in the allocation for internal bookkeeping
  4239. for (auto& elem : make_range(static_cast<E*>(sp.get()), size))
  4240. {
  4241. new (&elem) E();
  4242. }
  4243. }
  4244. return sp;
  4245. }
  4246. /** Provides `std::make_unique()` semantics for resources allocated with `CoTaskMemAlloc()` in a context that must fail fast upon allocation failure.
  4247. See the overload of `wil::make_unique_cotaskmem_nothrow()` for non-array types for more details.
  4248. ~~~
  4249. auto foo = wil::make_unique_cotaskmem_failfast<Foo>();
  4250. // initialize allocated Foo object as appropriate
  4251. ~~~
  4252. */
  4253. template <typename T, typename... Args>
  4254. inline typename wistd::enable_if<!wistd::is_array<T>::value, unique_cotaskmem_ptr<T>>::type make_unique_cotaskmem_failfast(Args&&... args)
  4255. {
  4256. unique_cotaskmem_ptr<T> result(make_unique_cotaskmem_nothrow<T>(wistd::forward<Args>(args)...));
  4257. FAIL_FAST_IF_NULL_ALLOC(result);
  4258. return result;
  4259. }
  4260. /** Provides `std::make_unique()` semantics for array resources allocated with `CoTaskMemAlloc()` in a context that must fail fast upon allocation failure.
  4261. See the overload of `wil::make_unique_cotaskmem_nothrow()` for non-array types for more details.
  4262. ~~~
  4263. const size_t size = 42;
  4264. auto foos = wil::make_unique_cotaskmem_failfast<Foo[]>(size);
  4265. for (auto& elem : wil::make_range(foos.get(), size))
  4266. {
  4267. // initialize allocated Foo objects as appropriate
  4268. }
  4269. ~~~
  4270. */
  4271. template <typename T>
  4272. inline typename wistd::enable_if<wistd::is_array<T>::value && wistd::extent<T>::value == 0, unique_cotaskmem_ptr<T>>::type make_unique_cotaskmem_failfast(size_t size)
  4273. {
  4274. unique_cotaskmem_ptr<T> result(make_unique_cotaskmem_nothrow<T>(size));
  4275. FAIL_FAST_IF_NULL_ALLOC(result);
  4276. return result;
  4277. }
  4278. #ifdef WIL_ENABLE_EXCEPTIONS
  4279. /** Provides `std::make_unique()` semantics for resources allocated with `CoTaskMemAlloc()`.
  4280. See the overload of `wil::make_unique_cotaskmem_nothrow()` for non-array types for more details.
  4281. ~~~
  4282. auto foo = wil::make_unique_cotaskmem<Foo>();
  4283. // initialize allocated Foo object as appropriate
  4284. ~~~
  4285. */
  4286. template <typename T, typename... Args>
  4287. inline typename wistd::enable_if<!wistd::is_array<T>::value, unique_cotaskmem_ptr<T>>::type make_unique_cotaskmem(Args&&... args)
  4288. {
  4289. unique_cotaskmem_ptr<T> result(make_unique_cotaskmem_nothrow<T>(wistd::forward<Args>(args)...));
  4290. THROW_IF_NULL_ALLOC(result);
  4291. return result;
  4292. }
  4293. /** Provides `std::make_unique()` semantics for array resources allocated with `CoTaskMemAlloc()`.
  4294. See the overload of `wil::make_unique_cotaskmem_nothrow()` for non-array types for more details.
  4295. ~~~
  4296. const size_t size = 42;
  4297. auto foos = wil::make_unique_cotaskmem<Foo[]>(size);
  4298. for (auto& elem : wil::make_range(foos.get(), size))
  4299. {
  4300. // initialize allocated Foo objects as appropriate
  4301. }
  4302. ~~~
  4303. */
  4304. template <typename T>
  4305. inline typename wistd::enable_if<wistd::is_array<T>::value && wistd::extent<T>::value == 0, unique_cotaskmem_ptr<T>>::type make_unique_cotaskmem(size_t size)
  4306. {
  4307. unique_cotaskmem_ptr<T> result(make_unique_cotaskmem_nothrow<T>(size));
  4308. THROW_IF_NULL_ALLOC(result);
  4309. return result;
  4310. }
  4311. #endif // WIL_ENABLE_EXCEPTIONS
  4312. typedef unique_any<void*, decltype(&::CoTaskMemFree), ::CoTaskMemFree> unique_cotaskmem;
  4313. typedef unique_any<PWSTR, decltype(&::CoTaskMemFree), ::CoTaskMemFree> unique_cotaskmem_string;
  4314. #ifndef WIL_NO_ANSI_STRINGS
  4315. typedef unique_any<PSTR, decltype(&::CoTaskMemFree), ::CoTaskMemFree> unique_cotaskmem_ansistring;
  4316. #endif // WIL_NO_ANSI_STRINGS
  4317. /// @cond
  4318. namespace details
  4319. {
  4320. struct cotaskmem_allocator
  4321. {
  4322. static _Ret_opt_bytecap_(size) void* allocate(size_t size) WI_NOEXCEPT
  4323. {
  4324. return ::CoTaskMemAlloc(size);
  4325. }
  4326. };
  4327. template<> struct string_allocator<unique_cotaskmem_string> : cotaskmem_allocator {};
  4328. #ifndef WIL_NO_ANSI_STRINGS
  4329. template<> struct string_allocator<unique_cotaskmem_ansistring> : cotaskmem_allocator {};
  4330. #endif // WIL_NO_ANSI_STRINGS
  4331. }
  4332. /// @endcond
  4333. inline auto make_cotaskmem_string_nothrow(
  4334. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  4335. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  4336. PCWSTR source, size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
  4337. {
  4338. return make_unique_string_nothrow<unique_cotaskmem_string>(source, length);
  4339. }
  4340. inline auto make_cotaskmem_string_failfast(
  4341. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  4342. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  4343. PCWSTR source, size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
  4344. {
  4345. return make_unique_string_failfast<unique_cotaskmem_string>(source, length);
  4346. }
  4347. #ifdef WIL_ENABLE_EXCEPTIONS
  4348. inline auto make_cotaskmem_string(
  4349. _When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
  4350. _When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_)
  4351. PCWSTR source, size_t length = static_cast<size_t>(-1))
  4352. {
  4353. return make_unique_string<unique_cotaskmem_string>(source, length);
  4354. }
  4355. #endif // WIL_ENABLE_EXCEPTIONS
  4356. #endif // __WIL_OBJBASE_H_
  4357. #if defined(__WIL_OBJBASE_H_) && !defined(__WIL_OBJBASE_H_STL) && defined(WIL_RESOURCE_STL)
  4358. #define __WIL_OBJBASE_H_STL
  4359. typedef shared_any<unique_cotaskmem> shared_cotaskmem;
  4360. typedef weak_any<shared_cotaskmem> weak_cotaskmem;
  4361. typedef shared_any<unique_cotaskmem_string> shared_cotaskmem_string;
  4362. typedef weak_any<shared_cotaskmem_string> weak_cotaskmem_string;
  4363. #endif // __WIL_OBJBASE_H_STL
  4364. #if defined(__WIL_OBJBASE_H_) && defined(__WIL_WINBASE_) && !defined(__WIL_OBJBASE_AND_WINBASE_H_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4365. #define __WIL_OBJBASE_AND_WINBASE_H_
  4366. struct cotaskmem_secure_deleter
  4367. {
  4368. template <typename T>
  4369. void operator()(_Pre_opt_valid_ _Frees_ptr_opt_ T* p) const
  4370. {
  4371. if (p)
  4372. {
  4373. IMalloc* malloc;
  4374. if (SUCCEEDED(::CoGetMalloc(1, &malloc)))
  4375. {
  4376. size_t const size = malloc->GetSize(p);
  4377. if (size != static_cast<size_t>(-1))
  4378. {
  4379. ::SecureZeroMemory(p, size);
  4380. }
  4381. malloc->Release();
  4382. }
  4383. ::CoTaskMemFree(p);
  4384. }
  4385. }
  4386. };
  4387. template <typename T = void>
  4388. using unique_cotaskmem_secure_ptr = wistd::unique_ptr<T, cotaskmem_secure_deleter>;
  4389. /** Provides `std::make_unique()` semantics for secure resources allocated with `CoTaskMemAlloc()` in a context that may not throw upon allocation failure.
  4390. See the overload of `wil::make_unique_cotaskmem_nothrow()` for non-array types for more details.
  4391. ~~~
  4392. auto foo = wil::make_unique_cotaskmem_secure_nothrow<Foo>();
  4393. if (foo)
  4394. {
  4395. // initialize allocated Foo object as appropriate
  4396. }
  4397. ~~~
  4398. */
  4399. template <typename T, typename... Args>
  4400. inline typename wistd::enable_if<!wistd::is_array<T>::value, unique_cotaskmem_secure_ptr<T>>::type make_unique_cotaskmem_secure_nothrow(Args&&... args)
  4401. {
  4402. return unique_cotaskmem_secure_ptr<T>(make_unique_cotaskmem_nothrow<T>(wistd::forward<Args>(args)...).release());
  4403. }
  4404. /** Provides `std::make_unique()` semantics for secure array resources allocated with `CoTaskMemAlloc()` in a context that may not throw upon allocation failure.
  4405. See the overload of `wil::make_unique_cotaskmem_nothrow()` for non-array types for more details.
  4406. ~~~
  4407. const size_t size = 42;
  4408. auto foos = wil::make_unique_cotaskmem_secure_nothrow<Foo[]>(size);
  4409. if (foos)
  4410. {
  4411. for (auto& elem : wil::make_range(foos.get(), size))
  4412. {
  4413. // initialize allocated Foo objects as appropriate
  4414. }
  4415. }
  4416. ~~~
  4417. */
  4418. template <typename T>
  4419. inline typename wistd::enable_if<wistd::is_array<T>::value && wistd::extent<T>::value == 0, unique_cotaskmem_secure_ptr<T>>::type make_unique_cotaskmem_secure_nothrow(size_t size)
  4420. {
  4421. return unique_cotaskmem_secure_ptr<T>(make_unique_cotaskmem_nothrow<T>(size).release());
  4422. }
  4423. /** Provides `std::make_unique()` semantics for secure resources allocated with `CoTaskMemAlloc()` in a context that must fail fast upon allocation failure.
  4424. See the overload of `wil::make_unique_cotaskmem_nothrow()` for non-array types for more details.
  4425. ~~~
  4426. auto foo = wil::make_unique_cotaskmem_secure_failfast<Foo>();
  4427. // initialize allocated Foo object as appropriate
  4428. ~~~
  4429. */
  4430. template <typename T, typename... Args>
  4431. inline typename wistd::enable_if<!wistd::is_array<T>::value, unique_cotaskmem_secure_ptr<T>>::type make_unique_cotaskmem_secure_failfast(Args&&... args)
  4432. {
  4433. unique_cotaskmem_secure_ptr<T> result(make_unique_cotaskmem_secure_nothrow<T>(wistd::forward<Args>(args)...));
  4434. FAIL_FAST_IF_NULL_ALLOC(result);
  4435. return result;
  4436. }
  4437. /** Provides `std::make_unique()` semantics for secure array resources allocated with `CoTaskMemAlloc()` in a context that must fail fast upon allocation failure.
  4438. See the overload of `wil::make_unique_cotaskmem_nothrow()` for non-array types for more details.
  4439. ~~~
  4440. const size_t size = 42;
  4441. auto foos = wil::make_unique_cotaskmem_secure_failfast<Foo[]>(size);
  4442. for (auto& elem : wil::make_range(foos.get(), size))
  4443. {
  4444. // initialize allocated Foo objects as appropriate
  4445. }
  4446. ~~~
  4447. */
  4448. template <typename T>
  4449. inline typename wistd::enable_if<wistd::is_array<T>::value && wistd::extent<T>::value == 0, unique_cotaskmem_secure_ptr<T>>::type make_unique_cotaskmem_secure_failfast(size_t size)
  4450. {
  4451. unique_cotaskmem_secure_ptr<T> result(make_unique_cotaskmem_secure_nothrow<T>(size));
  4452. FAIL_FAST_IF_NULL_ALLOC(result);
  4453. return result;
  4454. }
  4455. #ifdef WIL_ENABLE_EXCEPTIONS
  4456. /** Provides `std::make_unique()` semantics for secure resources allocated with `CoTaskMemAlloc()`.
  4457. See the overload of `wil::make_unique_cotaskmem_nothrow()` for non-array types for more details.
  4458. ~~~
  4459. auto foo = wil::make_unique_cotaskmem_secure<Foo>();
  4460. // initialize allocated Foo object as appropriate
  4461. ~~~
  4462. */
  4463. template <typename T, typename... Args>
  4464. inline typename wistd::enable_if<!wistd::is_array<T>::value, unique_cotaskmem_secure_ptr<T>>::type make_unique_cotaskmem_secure(Args&&... args)
  4465. {
  4466. unique_cotaskmem_secure_ptr<T> result(make_unique_cotaskmem_secure_nothrow<T>(wistd::forward<Args>(args)...));
  4467. THROW_IF_NULL_ALLOC(result);
  4468. return result;
  4469. }
  4470. /** Provides `std::make_unique()` semantics for secure array resources allocated with `CoTaskMemAlloc()`.
  4471. See the overload of `wil::make_unique_cotaskmem_nothrow()` for non-array types for more details.
  4472. ~~~
  4473. const size_t size = 42;
  4474. auto foos = wil::make_unique_cotaskmem_secure<Foo[]>(size);
  4475. for (auto& elem : wil::make_range(foos.get(), size))
  4476. {
  4477. // initialize allocated Foo objects as appropriate
  4478. }
  4479. ~~~
  4480. */
  4481. template <typename T>
  4482. inline typename wistd::enable_if<wistd::is_array<T>::value && wistd::extent<T>::value == 0, unique_cotaskmem_secure_ptr<T>>::type make_unique_cotaskmem_secure(size_t size)
  4483. {
  4484. unique_cotaskmem_secure_ptr<T> result(make_unique_cotaskmem_secure_nothrow<T>(size));
  4485. THROW_IF_NULL_ALLOC(result);
  4486. return result;
  4487. }
  4488. #endif // WIL_ENABLE_EXCEPTIONS
  4489. typedef unique_cotaskmem_secure_ptr<wchar_t[]> unique_cotaskmem_string_secure;
  4490. /** Copies a given string into secure memory allocated with `CoTaskMemAlloc()` in a context that may not throw upon allocation failure.
  4491. See the overload of `wil::make_cotaskmem_string_nothrow()` with supplied length for more details.
  4492. ~~~
  4493. auto str = wil::make_cotaskmem_string_secure_nothrow(L"a string");
  4494. if (str)
  4495. {
  4496. std::wcout << L"This is " << str.get() << std::endl; // prints "This is a string"
  4497. }
  4498. ~~~
  4499. */
  4500. inline unique_cotaskmem_string_secure make_cotaskmem_string_secure_nothrow(_In_ PCWSTR source) WI_NOEXCEPT
  4501. {
  4502. return unique_cotaskmem_string_secure(make_cotaskmem_string_nothrow(source).release());
  4503. }
  4504. /** Copies a given string into secure memory allocated with `CoTaskMemAlloc()` in a context that must fail fast upon allocation failure.
  4505. See the overload of `wil::make_cotaskmem_string_nothrow()` with supplied length for more details.
  4506. ~~~
  4507. auto str = wil::make_cotaskmem_string_secure_failfast(L"a string");
  4508. std::wcout << L"This is " << str.get() << std::endl; // prints "This is a string"
  4509. ~~~
  4510. */
  4511. inline unique_cotaskmem_string_secure make_cotaskmem_string_secure_failfast(_In_ PCWSTR source) WI_NOEXCEPT
  4512. {
  4513. unique_cotaskmem_string_secure result(make_cotaskmem_string_secure_nothrow(source));
  4514. FAIL_FAST_IF_NULL_ALLOC(result);
  4515. return result;
  4516. }
  4517. #ifdef WIL_ENABLE_EXCEPTIONS
  4518. /** Copies a given string into secure memory allocated with `CoTaskMemAlloc()`.
  4519. See the overload of `wil::make_cotaskmem_string_nothrow()` with supplied length for more details.
  4520. ~~~
  4521. auto str = wil::make_cotaskmem_string_secure(L"a string");
  4522. std::wcout << L"This is " << str.get() << std::endl; // prints "This is a string"
  4523. ~~~
  4524. */
  4525. inline unique_cotaskmem_string_secure make_cotaskmem_string_secure(_In_ PCWSTR source)
  4526. {
  4527. unique_cotaskmem_string_secure result(make_cotaskmem_string_secure_nothrow(source));
  4528. THROW_IF_NULL_ALLOC(result);
  4529. return result;
  4530. }
  4531. #endif
  4532. #endif // __WIL_OBJBASE_AND_WINBASE_H_
  4533. #if defined(_OLE2_H_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && !defined(__WIL_OLE2_H_) && !defined(WIL_KERNEL_MODE)
  4534. #define __WIL_OLE2_H_
  4535. typedef unique_struct<STGMEDIUM, decltype(&::ReleaseStgMedium), ::ReleaseStgMedium> unique_stg_medium;
  4536. struct unique_hglobal_locked : public unique_any<void*, decltype(&::GlobalUnlock), ::GlobalUnlock>
  4537. {
  4538. unique_hglobal_locked() = delete;
  4539. explicit unique_hglobal_locked(HGLOBAL global) : unique_any<void*, decltype(&::GlobalUnlock), ::GlobalUnlock>(global)
  4540. {
  4541. // GlobalLock returns a pointer to the associated global memory block and that's what callers care about.
  4542. m_globalMemory = GlobalLock(global);
  4543. if (!m_globalMemory)
  4544. {
  4545. release();
  4546. }
  4547. }
  4548. explicit unique_hglobal_locked(unique_hglobal& global) : unique_hglobal_locked(global.get())
  4549. {
  4550. }
  4551. explicit unique_hglobal_locked(STGMEDIUM& medium) : unique_hglobal_locked(medium.hGlobal)
  4552. {
  4553. }
  4554. pointer get() const
  4555. {
  4556. return m_globalMemory;
  4557. }
  4558. private:
  4559. pointer m_globalMemory;
  4560. };
  4561. //! A type that calls OleUninitialize on destruction (or reset()).
  4562. //! Use as a replacement for Windows::Foundation::Uninitialize.
  4563. using unique_oleuninitialize_call = unique_call<decltype(&::OleUninitialize), ::OleUninitialize>;
  4564. //! Calls RoInitialize and fail-fasts if it fails; returns an RAII object that reverts
  4565. //! Use as a replacement for Windows::Foundation::Initialize
  4566. _Check_return_ inline unique_oleuninitialize_call OleInitialize_failfast()
  4567. {
  4568. FAIL_FAST_IF_FAILED(::OleInitialize(nullptr));
  4569. return unique_oleuninitialize_call();
  4570. }
  4571. #endif // __WIL_OLE2_H_
  4572. #if defined(__WIL_OLE2_H_) && defined(WIL_ENABLE_EXCEPTIONS) && !defined(__WIL_OLE2_H_EXCEPTIONAL)
  4573. #define __WIL_OLE2_H_EXCEPTIONAL
  4574. //! Calls RoInitialize and throws an exception if it fails; returns an RAII object that reverts
  4575. //! Use as a replacement for Windows::Foundation::Initialize
  4576. _Check_return_ inline unique_oleuninitialize_call OleInitialize()
  4577. {
  4578. THROW_IF_FAILED(::OleInitialize(nullptr));
  4579. return unique_oleuninitialize_call();
  4580. }
  4581. #endif
  4582. #if defined(_INC_COMMCTRL) && !defined(__WIL_INC_COMMCTRL) && !defined(WIL_KERNEL_MODE)
  4583. #define __WIL_INC_COMMCTRL
  4584. typedef unique_any<HIMAGELIST, decltype(&::ImageList_Destroy), ::ImageList_Destroy> unique_himagelist;
  4585. #endif // __WIL_INC_COMMCTRL
  4586. #if defined(__WIL_INC_COMMCTRL) && !defined(__WIL_INC_COMMCTRL_STL) && defined(WIL_RESOURCE_STL)
  4587. #define __WIL_INC_COMMCTRL_STL
  4588. typedef shared_any<unique_himagelist> shared_himagelist;
  4589. typedef weak_any<shared_himagelist> weak_himagelist;
  4590. #endif // __WIL_INC_COMMCTRL_STL
  4591. #if defined(_UXTHEME_H_) && !defined(__WIL_INC_UXTHEME) && !defined(WIL_KERNEL_MODE)
  4592. #define __WIL_INC_UXTHEME
  4593. typedef unique_any<HTHEME, decltype(&::CloseThemeData), ::CloseThemeData> unique_htheme;
  4594. #endif // __WIL_INC_UXTHEME
  4595. #if defined(_WINSVC_) && !defined(__WIL_HANDLE_H_WINSVC) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && !defined(WIL_KERNEL_MODE)
  4596. #define __WIL_HANDLE_H_WINSVC
  4597. typedef unique_any<SC_HANDLE, decltype(&::CloseServiceHandle), ::CloseServiceHandle> unique_schandle;
  4598. #endif // __WIL_HANDLE_H_WINSVC
  4599. #if defined(__WIL_HANDLE_H_WINSVC) && !defined(__WIL_HANDLE_H_WINSVC_STL) && defined(WIL_RESOURCE_STL)
  4600. #define __WIL_HANDLE_H_WINSVC_STL
  4601. typedef shared_any<unique_schandle> shared_schandle;
  4602. typedef weak_any<shared_schandle> weak_schandle;
  4603. #endif // __WIL_HANDLE_H_WINSVC_STL
  4604. #if defined(_INC_STDIO) && !defined(__WIL_INC_STDIO) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && !defined(WIL_KERNEL_MODE)
  4605. #define __WIL_INC_STDIO
  4606. typedef unique_any<FILE*, decltype(&::_pclose), ::_pclose> unique_pipe;
  4607. typedef unique_any<FILE*, decltype(&::fclose), ::fclose> unique_file;
  4608. #endif // __WIL_INC_STDIO
  4609. #if defined(__WIL_INC_STDIO) && !defined(__WIL__INC_STDIO_STL) && defined(WIL_RESOURCE_STL)
  4610. #define __WIL__INC_STDIO_STL
  4611. typedef shared_any<unique_pipe> shared_pipe;
  4612. typedef weak_any<shared_pipe> weak_pipe;
  4613. typedef shared_any<unique_file> shared_file;
  4614. typedef weak_any<unique_file> weak_file;
  4615. #endif // __WIL__INC_STDIO_STL
  4616. #if defined(_NTLSA_) && !defined(__WIL_NTLSA_) && !defined(WIL_KERNEL_MODE)
  4617. #define __WIL_NTLSA_
  4618. typedef unique_any<LSA_HANDLE, decltype(&::LsaClose), ::LsaClose> unique_hlsa;
  4619. using lsa_freemem_deleter = function_deleter<decltype(&::LsaFreeMemory), LsaFreeMemory>;
  4620. template <typename T>
  4621. using unique_lsamem_ptr = wistd::unique_ptr<T, lsa_freemem_deleter>;
  4622. #endif // _NTLSA_
  4623. #if defined(_NTLSA_) && !defined(__WIL_NTLSA_STL) && defined(WIL_RESOURCE_STL)
  4624. #define __WIL_NTLSA_STL
  4625. typedef shared_any<unique_hlsa> shared_hlsa;
  4626. typedef weak_any<shared_hlsa> weak_hlsa;
  4627. #endif // _NTLSA_
  4628. #if defined(_LSALOOKUP_) && !defined(__WIL_LSALOOKUP_)
  4629. #define __WIL_LSALOOKUP_
  4630. typedef unique_any<LSA_HANDLE, decltype(&::LsaLookupClose), ::LsaLookupClose> unique_hlsalookup;
  4631. using lsalookup_freemem_deleter = function_deleter<decltype(&::LsaLookupFreeMemory), LsaLookupFreeMemory>;
  4632. template <typename T>
  4633. using unique_lsalookupmem_ptr = wistd::unique_ptr<T, lsalookup_freemem_deleter>;
  4634. #endif // _LSALOOKUP_
  4635. #if defined(_LSALOOKUP_) && !defined(__WIL_LSALOOKUP_STL) && defined(WIL_RESOURCE_STL)
  4636. #define __WIL_LSALOOKUP_STL
  4637. typedef shared_any<unique_hlsalookup> shared_hlsalookup;
  4638. typedef weak_any<shared_hlsalookup> weak_hlsalookup;
  4639. #endif // _LSALOOKUP_
  4640. #if defined(_NTLSA_IFS_) && !defined(__WIL_HANDLE_H_NTLSA_IFS_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4641. #define __WIL_HANDLE_H_NTLSA_IFS_
  4642. using lsa_deleter = function_deleter<decltype(&::LsaFreeReturnBuffer), LsaFreeReturnBuffer>;
  4643. template <typename T>
  4644. using unique_lsa_ptr = wistd::unique_ptr<T, lsa_deleter>;
  4645. #endif // __WIL_HANDLE_H_NTLSA_IFS_
  4646. #if defined(__WERAPI_H__) && !defined(__WIL_WERAPI_H__) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4647. #define __WIL_WERAPI_H__
  4648. typedef unique_any<HREPORT, decltype(&WerReportCloseHandle), WerReportCloseHandle> unique_wer_report;
  4649. #endif
  4650. #if defined(__MIDLES_H__) && !defined(__WIL_MIDLES_H__) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4651. #define __WIL_MIDLES_H__
  4652. typedef unique_any<handle_t, decltype(&::MesHandleFree), ::MesHandleFree> unique_rpc_pickle;
  4653. #endif
  4654. #if defined(__WIL_MIDLES_H__) && !defined(__WIL_MIDLES_H_STL) && defined(WIL_RESOURCE_STL)
  4655. #define __WIL_MIDLES_H_STL
  4656. typedef shared_any<unique_rpc_pickle> shared_rpc_pickle;
  4657. typedef weak_any<shared_rpc_pickle> weak_rpc_pickle;
  4658. #endif
  4659. #if defined(__RPCDCE_H__) && !defined(__WIL_RPCDCE_H__) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4660. #define __WIL_RPCDCE_H__
  4661. /// @cond
  4662. namespace details
  4663. {
  4664. inline void __stdcall WpRpcBindingFree(_Pre_opt_valid_ _Frees_ptr_opt_ RPC_BINDING_HANDLE binding)
  4665. {
  4666. ::RpcBindingFree(&binding);
  4667. }
  4668. inline void __stdcall WpRpcBindingVectorFree(_Pre_opt_valid_ _Frees_ptr_opt_ RPC_BINDING_VECTOR* bindingVector)
  4669. {
  4670. ::RpcBindingVectorFree(&bindingVector);
  4671. }
  4672. inline void __stdcall WpRpcStringFree(_Pre_opt_valid_ _Frees_ptr_opt_ RPC_WSTR wstr)
  4673. {
  4674. ::RpcStringFreeW(&wstr);
  4675. }
  4676. }
  4677. /// @endcond
  4678. typedef unique_any<RPC_BINDING_HANDLE, decltype(&details::WpRpcBindingFree), details::WpRpcBindingFree> unique_rpc_binding;
  4679. typedef unique_any<RPC_BINDING_VECTOR*, decltype(&details::WpRpcBindingVectorFree), details::WpRpcBindingVectorFree> unique_rpc_binding_vector;
  4680. typedef unique_any<RPC_WSTR, decltype(&details::WpRpcStringFree), details::WpRpcStringFree> unique_rpc_wstr;
  4681. #endif
  4682. #if defined(__WIL_RPCDCE_H__) && !defined(__WIL_RPCDCE_H_STL) && defined(WIL_RESOURCE_STL)
  4683. #define __WIL_RPCDCE_H_STL
  4684. typedef shared_any<unique_rpc_binding> shared_rpc_binding;
  4685. typedef weak_any<shared_rpc_binding> weak_rpc_binding;
  4686. typedef shared_any<unique_rpc_binding_vector> shared_rpc_binding_vector;
  4687. typedef weak_any<shared_rpc_binding_vector> weak_rpc_binding_vector;
  4688. typedef shared_any<unique_rpc_wstr> shared_rpc_wstr;
  4689. typedef weak_any<unique_rpc_wstr> weak_rpc_wstr;
  4690. #endif
  4691. #if defined(_WCMAPI_H) && !defined(__WIL_WCMAPI_H_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4692. #define __WIL_WCMAPI_H_
  4693. using wcm_deleter = function_deleter<decltype(&::WcmFreeMemory), WcmFreeMemory>;
  4694. template<typename T>
  4695. using unique_wcm_ptr = wistd::unique_ptr<T, wcm_deleter>;
  4696. #endif
  4697. #if defined(_NETIOAPI_H_) && defined(_WS2IPDEF_) && defined(MIB_INVALID_TEREDO_PORT_NUMBER) && !defined(__WIL_NETIOAPI_H_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4698. #define __WIL_NETIOAPI_H_
  4699. typedef unique_any<PMIB_IF_TABLE2, decltype(&::FreeMibTable), ::FreeMibTable> unique_mib_iftable;
  4700. #endif
  4701. #if defined(__WIL_NETIOAPI_H_) && !defined(__WIL_NETIOAPI_H_STL) && defined(WIL_RESOURCE_STL)
  4702. #define __WIL_NETIOAPI_H_STL
  4703. typedef shared_any<unique_mib_iftable> shared_mib_iftable;
  4704. typedef weak_any<shared_mib_iftable> weak_mib_iftable;
  4705. #endif
  4706. #if defined(_WLAN_WLANAPI_H) && !defined(__WIL_WLAN_WLANAPI_H) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4707. #define __WIL_WLAN_WLANAPI_H
  4708. using wlan_deleter = function_deleter<decltype(&::WlanFreeMemory), ::WlanFreeMemory>;
  4709. template<typename T>
  4710. using unique_wlan_ptr = wistd::unique_ptr < T, wlan_deleter >;
  4711. /// @cond
  4712. namespace details
  4713. {
  4714. inline void __stdcall CloseWlanHandle(_Frees_ptr_ HANDLE hClientHandle)
  4715. {
  4716. ::WlanCloseHandle(hClientHandle, nullptr);
  4717. }
  4718. }
  4719. /// @endcond
  4720. typedef unique_any<HANDLE, decltype(&details::CloseWlanHandle), details::CloseWlanHandle, details::pointer_access_all, HANDLE, INT_PTR, -1> unique_wlan_handle;
  4721. #endif
  4722. #if defined(__WIL_WLAN_WLANAPI_H) && !defined(__WIL_WLAN_WLANAPI_H_STL) && defined(WIL_RESOURCE_STL)
  4723. #define __WIL_WLAN_WLANAPI_H_STL
  4724. typedef shared_any<unique_wlan_handle> shared_wlan_handle;
  4725. typedef weak_any<shared_wlan_handle> weak_wlan_handle;
  4726. #endif
  4727. #if defined(_HPOWERNOTIFY_DEF_) && !defined(__WIL_HPOWERNOTIFY_DEF_H_) && !defined(WIL_KERNEL_MODE)
  4728. #define __WIL_HPOWERNOTIFY_DEF_H_
  4729. typedef unique_any<HPOWERNOTIFY, decltype(&::UnregisterPowerSettingNotification), ::UnregisterPowerSettingNotification> unique_hpowernotify;
  4730. #endif
  4731. #if defined(__WIL_WINBASE_DESKTOP) && defined(SID_DEFINED) && !defined(__WIL_PSID_DEF_H_)
  4732. #define __WIL_PSID_DEF_H_
  4733. typedef unique_any<PSID, decltype(&::LocalFree), ::LocalFree> unique_any_psid;
  4734. #if defined(_OBJBASE_H_)
  4735. typedef unique_any<PSID, decltype(&::CoTaskMemFree), ::CoTaskMemFree> unique_cotaskmem_psid;
  4736. #endif
  4737. #endif
  4738. #if defined(_PROCESSTHREADSAPI_H_) && !defined(__WIL_PROCESSTHREADSAPI_H_DESK_SYS) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) && !defined(WIL_KERNEL_MODE)
  4739. #define __WIL_PROCESSTHREADSAPI_H_DESK_SYS
  4740. /// @cond
  4741. namespace details
  4742. {
  4743. inline void __stdcall CloseProcessInformation(_In_ PROCESS_INFORMATION* p)
  4744. {
  4745. if (p->hProcess)
  4746. {
  4747. CloseHandle(p->hProcess);
  4748. }
  4749. if (p->hThread)
  4750. {
  4751. CloseHandle(p->hThread);
  4752. }
  4753. }
  4754. }
  4755. /// @endcond
  4756. /** Manages the outbound parameter containing handles returned by `CreateProcess()` and related methods.
  4757. ~~~
  4758. unique_process_information process;
  4759. CreateProcessW(..., CREATE_SUSPENDED, ..., &process);
  4760. THROW_IF_WIN32_BOOL_FALSE(ResumeThread(process.hThread));
  4761. THROW_LAST_ERROR_IF(WaitForSingleObject(process.hProcess, INFINITE) != WAIT_OBJECT_0);
  4762. ~~~
  4763. */
  4764. using unique_process_information = unique_struct<PROCESS_INFORMATION, decltype(&details::CloseProcessInformation), details::CloseProcessInformation>;
  4765. #endif
  4766. #if defined(_PROCESSENV_) && !defined(__WIL__PROCESSENV_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
  4767. #define __WIL__PROCESSENV_
  4768. /** Manages lifecycle of an environment-strings block
  4769. ~~~
  4770. wil::unique_environstrings_ptr env { ::GetEnvironmentStringsW() };
  4771. const wchar_t *nextVar = env.get();
  4772. while (nextVar && *nextVar)
  4773. {
  4774. // consume 'nextVar'
  4775. nextVar += wcslen(nextVar) + 1;
  4776. }
  4777. ~~~
  4778. */
  4779. using unique_environstrings_ptr = wistd::unique_ptr<wchar_t, function_deleter<decltype(&::FreeEnvironmentStringsW), FreeEnvironmentStringsW>>;
  4780. #ifndef WIL_NO_ANSI_STRINGS
  4781. //! ANSI equivalent to unique_environstrings_ptr;
  4782. using unique_environansistrings_ptr = wistd::unique_ptr<char, function_deleter<decltype(&::FreeEnvironmentStringsA), FreeEnvironmentStringsA>>;
  4783. #endif
  4784. #endif
  4785. #if defined(_APPMODEL_H_) && !defined(__WIL_APPMODEL_H_) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  4786. #define __WIL_APPMODEL_H_
  4787. typedef unique_any<PACKAGE_INFO_REFERENCE, decltype(&::ClosePackageInfo), ::ClosePackageInfo> unique_package_info_reference;
  4788. #endif // __WIL_APPMODEL_H_
  4789. #if defined(__WIL_APPMODEL_H_) && !defined(__WIL_APPMODEL_H_STL) && defined(WIL_RESOURCE_STL)
  4790. #define __WIL_APPMODEL_H_STL
  4791. typedef shared_any<unique_package_info_reference> shared_package_info_reference;
  4792. typedef weak_any<shared_package_info_reference> weak_package_info_reference;
  4793. #endif // __WIL_APPMODEL_H_STL
  4794. #if defined(WDFAPI) && !defined(__WIL_WDFAPI)
  4795. #define __WIL_WDFAPI
  4796. namespace details
  4797. {
  4798. template<typename TWDFOBJECT>
  4799. using wdf_object_resource_policy = resource_policy<TWDFOBJECT, decltype(&::WdfObjectDelete), &::WdfObjectDelete>;
  4800. }
  4801. template<typename TWDFOBJECT>
  4802. using unique_wdf_any = unique_any_t<details::unique_storage<details::wdf_object_resource_policy<TWDFOBJECT>>>;
  4803. using unique_wdf_object = unique_wdf_any<WDFOBJECT>;
  4804. using unique_wdf_timer = unique_wdf_any<WDFTIMER>;
  4805. using unique_wdf_work_item = unique_wdf_any<WDFWORKITEM>;
  4806. using unique_wdf_memory = unique_wdf_any<WDFMEMORY>;
  4807. using unique_wdf_dma_enabler = unique_wdf_any<WDFDMAENABLER>;
  4808. using unique_wdf_dma_transaction = unique_wdf_any<WDFDMATRANSACTION>;
  4809. using unique_wdf_common_buffer = unique_wdf_any<WDFCOMMONBUFFER>;
  4810. using unique_wdf_key = unique_wdf_any<WDFKEY>;
  4811. using unique_wdf_string = unique_wdf_any<WDFSTRING>;
  4812. using unique_wdf_collection = unique_wdf_any<WDFCOLLECTION>;
  4813. using wdf_wait_lock_release_scope_exit =
  4814. unique_any<
  4815. WDFWAITLOCK,
  4816. decltype(&::WdfWaitLockRelease),
  4817. ::WdfWaitLockRelease,
  4818. details::pointer_access_none>;
  4819. inline
  4820. WI_NODISCARD
  4821. _IRQL_requires_max_(PASSIVE_LEVEL)
  4822. _Acquires_lock_(lock)
  4823. wdf_wait_lock_release_scope_exit
  4824. acquire_wdf_wait_lock(WDFWAITLOCK lock) WI_NOEXCEPT
  4825. {
  4826. ::WdfWaitLockAcquire(lock, nullptr);
  4827. return wdf_wait_lock_release_scope_exit(lock);
  4828. }
  4829. inline
  4830. WI_NODISCARD
  4831. _IRQL_requires_max_(APC_LEVEL)
  4832. _When_(return, _Acquires_lock_(lock))
  4833. wdf_wait_lock_release_scope_exit
  4834. try_acquire_wdf_wait_lock(WDFWAITLOCK lock) WI_NOEXCEPT
  4835. {
  4836. LONGLONG timeout = 0;
  4837. NTSTATUS status = ::WdfWaitLockAcquire(lock, &timeout);
  4838. if (status == STATUS_SUCCESS)
  4839. {
  4840. return wdf_wait_lock_release_scope_exit(lock);
  4841. }
  4842. else
  4843. {
  4844. return wdf_wait_lock_release_scope_exit();
  4845. }
  4846. }
  4847. using wdf_spin_lock_release_scope_exit =
  4848. unique_any<
  4849. WDFSPINLOCK,
  4850. decltype(&::WdfSpinLockRelease),
  4851. ::WdfSpinLockRelease,
  4852. details::pointer_access_none>;
  4853. inline
  4854. WI_NODISCARD
  4855. _IRQL_requires_max_(DISPATCH_LEVEL)
  4856. _IRQL_raises_(DISPATCH_LEVEL)
  4857. _Acquires_lock_(lock)
  4858. wdf_spin_lock_release_scope_exit
  4859. acquire_wdf_spin_lock(WDFSPINLOCK lock) WI_NOEXCEPT
  4860. {
  4861. ::WdfSpinLockAcquire(lock);
  4862. return wdf_spin_lock_release_scope_exit(lock);
  4863. }
  4864. namespace details
  4865. {
  4866. template<typename TWDFLOCK>
  4867. using unique_wdf_lock_storage = unique_storage<wdf_object_resource_policy<TWDFLOCK>>;
  4868. class unique_wdf_spin_lock_storage : public unique_wdf_lock_storage<WDFSPINLOCK>
  4869. {
  4870. using wdf_lock_storage_t = unique_wdf_lock_storage<WDFSPINLOCK>;
  4871. public:
  4872. using pointer = wdf_lock_storage_t::pointer;
  4873. // Forward all base class constructors, but have it be explicit.
  4874. template <typename... args_t>
  4875. explicit unique_wdf_spin_lock_storage(args_t&& ... args) WI_NOEXCEPT : wdf_lock_storage_t(wistd::forward<args_t>(args)...) {}
  4876. NTSTATUS create(_In_opt_ WDF_OBJECT_ATTRIBUTES* attributes = WDF_NO_OBJECT_ATTRIBUTES)
  4877. {
  4878. return ::WdfSpinLockCreate(attributes, out_param(*this));
  4879. }
  4880. WI_NODISCARD
  4881. _IRQL_requires_max_(DISPATCH_LEVEL)
  4882. _IRQL_raises_(DISPATCH_LEVEL)
  4883. wdf_spin_lock_release_scope_exit acquire() WI_NOEXCEPT
  4884. {
  4885. return wil::acquire_wdf_spin_lock(wdf_lock_storage_t::get());
  4886. }
  4887. };
  4888. class unique_wdf_wait_lock_storage : public unique_wdf_lock_storage<WDFWAITLOCK>
  4889. {
  4890. using wdf_lock_storage_t = unique_wdf_lock_storage<WDFWAITLOCK>;
  4891. public:
  4892. using pointer = wdf_lock_storage_t::pointer;
  4893. // Forward all base class constructors, but have it be explicit.
  4894. template <typename... args_t>
  4895. explicit unique_wdf_wait_lock_storage(args_t&& ... args) WI_NOEXCEPT : wdf_lock_storage_t(wistd::forward<args_t>(args)...) {}
  4896. NTSTATUS create(_In_opt_ WDF_OBJECT_ATTRIBUTES* attributes = WDF_NO_OBJECT_ATTRIBUTES)
  4897. {
  4898. return ::WdfWaitLockCreate(attributes, out_param(*this));
  4899. }
  4900. WI_NODISCARD
  4901. _IRQL_requires_max_(PASSIVE_LEVEL)
  4902. wdf_wait_lock_release_scope_exit acquire() WI_NOEXCEPT
  4903. {
  4904. return wil::acquire_wdf_wait_lock(wdf_lock_storage_t::get());
  4905. }
  4906. WI_NODISCARD
  4907. _IRQL_requires_max_(APC_LEVEL)
  4908. wdf_wait_lock_release_scope_exit try_acquire() WI_NOEXCEPT
  4909. {
  4910. return wil::try_acquire_wdf_wait_lock(wdf_lock_storage_t::get());
  4911. }
  4912. };
  4913. }
  4914. using unique_wdf_wait_lock = unique_any_t<details::unique_wdf_wait_lock_storage>;
  4915. using unique_wdf_spin_lock = unique_any_t<details::unique_wdf_spin_lock_storage>;
  4916. template<typename TWDFOBJECT>
  4917. struct wdf_object_reference
  4918. {
  4919. TWDFOBJECT wdfObject = WDF_NO_HANDLE;
  4920. PVOID tag = nullptr;
  4921. wdf_object_reference() WI_NOEXCEPT = default;
  4922. wdf_object_reference(TWDFOBJECT wdfObject, PVOID tag = nullptr) WI_NOEXCEPT
  4923. : wdfObject(wdfObject), tag(tag)
  4924. {
  4925. }
  4926. operator TWDFOBJECT() const WI_NOEXCEPT
  4927. {
  4928. return wdfObject;
  4929. }
  4930. static void close(const wdf_object_reference& wdfObjectReference) WI_NOEXCEPT
  4931. {
  4932. // We don't use WdfObjectDereferenceActual because there is no way to provide the
  4933. // correct __LINE__ and __FILE__, but if you use RAII all the way, you shouldn't have to
  4934. // worry about where it was released, only where it was acquired.
  4935. WdfObjectDereferenceWithTag(wdfObjectReference.wdfObject, wdfObjectReference.tag);
  4936. }
  4937. };
  4938. template<typename TWDFOBJECT>
  4939. using unique_wdf_object_reference = unique_any<TWDFOBJECT, decltype(wdf_object_reference<TWDFOBJECT>::close),
  4940. &wdf_object_reference<TWDFOBJECT>::close, details::pointer_access_noaddress, wdf_object_reference<TWDFOBJECT>>;
  4941. // Increment the ref-count on a WDF object a unique_wdf_object_reference for it. Use
  4942. // WI_WdfObjectReferenceIncrement to automatically use the call-site source location. Use this
  4943. // function only if the call-site source location is obtained from elsewhere (i.e., plumbed
  4944. // through other abstractions).
  4945. template<typename TWDFOBJECT>
  4946. inline WI_NODISCARD unique_wdf_object_reference<TWDFOBJECT> wdf_object_reference_increment(
  4947. TWDFOBJECT wdfObject, PVOID tag, LONG lineNumber, PCSTR fileName) WI_NOEXCEPT
  4948. {
  4949. // Parameter is incorrectly marked as non-const, so the const-cast is required.
  4950. ::WdfObjectReferenceActual(wdfObject, tag, lineNumber, const_cast<char*>(fileName));
  4951. return unique_wdf_object_reference<TWDFOBJECT>{ wdf_object_reference<TWDFOBJECT>{ wdfObject, tag } };
  4952. }
  4953. // A macro so that we can capture __LINE__ and __FILE__.
  4954. #define WI_WdfObjectReferenceIncrement(wdfObject, tag) \
  4955. wil::wdf_object_reference_increment(wdfObject, tag, __LINE__, __FILE__)
  4956. #endif
  4957. #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) && \
  4958. defined(_CFGMGR32_H_) && \
  4959. (WINVER >= _WIN32_WINNT_WIN8) && \
  4960. !defined(__WIL_CFGMGR32_H_)
  4961. #define __WIL_CFGMGR32_H_
  4962. typedef unique_any<HCMNOTIFICATION, decltype(&::CM_Unregister_Notification), ::CM_Unregister_Notification> unique_hcmnotification;
  4963. #endif
  4964. #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) && \
  4965. defined(_SWDEVICE_H_) && \
  4966. (WINVER >= _WIN32_WINNT_WIN8) && \
  4967. !defined(__WIL_SWDEVICE_H_)
  4968. #define __WIL_SWDEVICE_H_
  4969. typedef unique_any<HSWDEVICE, decltype(&::SwDeviceClose), ::SwDeviceClose> unique_hswdevice;
  4970. #endif
  4971. #if defined(WIL_KERNEL_MODE) && (defined(_WDMDDK_) || defined(_NTDDK_)) && !defined(__WIL_RESOURCE_WDM)
  4972. #define __WIL_RESOURCE_WDM
  4973. namespace details
  4974. {
  4975. struct kspin_lock_saved_irql
  4976. {
  4977. PKSPIN_LOCK spinLock = nullptr;
  4978. KIRQL savedIrql = PASSIVE_LEVEL;
  4979. kspin_lock_saved_irql() = default;
  4980. kspin_lock_saved_irql(PKSPIN_LOCK /* spinLock */)
  4981. {
  4982. // This constructor exists simply to allow conversion of the pointer type to
  4983. // pointer_storage type when constructing an invalid instance. The spinLock pointer
  4984. // is expected to be nullptr.
  4985. }
  4986. // Exists to satisfy the interconvertibility requirement for pointer_storage and
  4987. // pointer.
  4988. explicit operator PKSPIN_LOCK() const
  4989. {
  4990. return spinLock;
  4991. }
  4992. _IRQL_requires_(DISPATCH_LEVEL)
  4993. static
  4994. void Release(_In_ _IRQL_restores_ const kspin_lock_saved_irql& spinLockSavedIrql)
  4995. {
  4996. KeReleaseSpinLock(spinLockSavedIrql.spinLock, spinLockSavedIrql.savedIrql);
  4997. }
  4998. };
  4999. // On some architectures KeReleaseSpinLockFromDpcLevel is a macro, and we need a thunk
  5000. // function we can take the address of.
  5001. inline
  5002. _IRQL_requires_min_(DISPATCH_LEVEL)
  5003. void __stdcall ReleaseSpinLockFromDpcLevel(_Inout_ PKSPIN_LOCK spinLock) WI_NOEXCEPT
  5004. {
  5005. KeReleaseSpinLockFromDpcLevel(spinLock);
  5006. }
  5007. }
  5008. using kspin_lock_guard = unique_any<PKSPIN_LOCK, decltype(details::kspin_lock_saved_irql::Release), &details::kspin_lock_saved_irql::Release,
  5009. details::pointer_access_none, details::kspin_lock_saved_irql>;
  5010. using kspin_lock_at_dpc_guard = unique_any<PKSPIN_LOCK, decltype(details::ReleaseSpinLockFromDpcLevel), &details::ReleaseSpinLockFromDpcLevel,
  5011. details::pointer_access_none>;
  5012. inline
  5013. WI_NODISCARD
  5014. _IRQL_requires_max_(DISPATCH_LEVEL)
  5015. _IRQL_saves_
  5016. _IRQL_raises_(DISPATCH_LEVEL)
  5017. kspin_lock_guard
  5018. acquire_kspin_lock(_In_ PKSPIN_LOCK spinLock)
  5019. {
  5020. details::kspin_lock_saved_irql spinLockSavedIrql;
  5021. KeAcquireSpinLock(spinLock, &spinLockSavedIrql.savedIrql);
  5022. spinLockSavedIrql.spinLock = spinLock;
  5023. return kspin_lock_guard(spinLockSavedIrql);
  5024. }
  5025. inline
  5026. WI_NODISCARD
  5027. _IRQL_requires_min_(DISPATCH_LEVEL)
  5028. kspin_lock_at_dpc_guard
  5029. acquire_kspin_lock_at_dpc(_In_ PKSPIN_LOCK spinLock)
  5030. {
  5031. KeAcquireSpinLockAtDpcLevel(spinLock);
  5032. return kspin_lock_at_dpc_guard(spinLock);
  5033. }
  5034. class kernel_spin_lock
  5035. {
  5036. public:
  5037. kernel_spin_lock() WI_NOEXCEPT
  5038. {
  5039. ::KeInitializeSpinLock(&m_kSpinLock);
  5040. }
  5041. ~kernel_spin_lock() = default;
  5042. // Cannot change memory location.
  5043. kernel_spin_lock(const kernel_spin_lock&) = delete;
  5044. kernel_spin_lock& operator=(const kernel_spin_lock&) = delete;
  5045. kernel_spin_lock(kernel_spin_lock&&) = delete;
  5046. kernel_spin_lock& operator=(kernel_spin_lock&&) = delete;
  5047. WI_NODISCARD
  5048. _IRQL_requires_max_(DISPATCH_LEVEL)
  5049. _IRQL_saves_
  5050. _IRQL_raises_(DISPATCH_LEVEL)
  5051. kspin_lock_guard acquire() WI_NOEXCEPT
  5052. {
  5053. return acquire_kspin_lock(&m_kSpinLock);
  5054. }
  5055. WI_NODISCARD
  5056. _IRQL_requires_min_(DISPATCH_LEVEL)
  5057. kspin_lock_at_dpc_guard acquire_at_dpc() WI_NOEXCEPT
  5058. {
  5059. return acquire_kspin_lock_at_dpc(&m_kSpinLock);
  5060. }
  5061. private:
  5062. KSPIN_LOCK m_kSpinLock;
  5063. };
  5064. namespace details
  5065. {
  5066. template <EVENT_TYPE eventType>
  5067. class kernel_event_t
  5068. {
  5069. public:
  5070. explicit kernel_event_t(bool isSignaled = false) WI_NOEXCEPT
  5071. {
  5072. ::KeInitializeEvent(&m_kernelEvent, static_cast<EVENT_TYPE>(eventType), isSignaled ? TRUE : FALSE);
  5073. }
  5074. // Cannot change memory location.
  5075. kernel_event_t(const kernel_event_t&) = delete;
  5076. kernel_event_t(kernel_event_t&&) = delete;
  5077. kernel_event_t& operator=(const kernel_event_t&) = delete;
  5078. kernel_event_t& operator=(kernel_event_t&&) = delete;
  5079. // Get the underlying KEVENT structure for more advanced usages like
  5080. // KeWaitForMultipleObjects or KeWaitForSingleObject with non-default parameters.
  5081. PRKEVENT get() WI_NOEXCEPT
  5082. {
  5083. return &m_kernelEvent;
  5084. }
  5085. void clear() WI_NOEXCEPT
  5086. {
  5087. // The most common use-case is to clear the event with no interest in its previous
  5088. // value. Hence, that is the functionality we provide by default. If the previous
  5089. // value is required, one may .get() the underlying event object and call
  5090. // ::KeResetEvent().
  5091. ::KeClearEvent(&m_kernelEvent);
  5092. }
  5093. // Returns the previous state of the event.
  5094. bool set(KPRIORITY increment = IO_NO_INCREMENT) WI_NOEXCEPT
  5095. {
  5096. return ::KeSetEvent(&m_kernelEvent, increment, FALSE) ? true : false;
  5097. }
  5098. // Checks if the event is currently signaled. Does not change the state of the event.
  5099. bool is_signaled() const WI_NOEXCEPT
  5100. {
  5101. return ::KeReadStateEvent(const_cast<PRKEVENT>(&m_kernelEvent)) ? true : false;
  5102. }
  5103. // Return true if the wait was satisfied. Time is specified in 100ns units, relative
  5104. // (negative) or absolute (positive). For more details, see the documentation of
  5105. // KeWaitForSingleObject.
  5106. bool wait(LONGLONG waitTime) WI_NOEXCEPT
  5107. {
  5108. LARGE_INTEGER duration;
  5109. duration.QuadPart = waitTime;
  5110. return wait_for_single_object(&duration);
  5111. }
  5112. // Waits indefinitely for the event to be signaled.
  5113. void wait() WI_NOEXCEPT
  5114. {
  5115. wait_for_single_object(nullptr);
  5116. }
  5117. private:
  5118. bool wait_for_single_object(_In_opt_ LARGE_INTEGER* waitDuration) WI_NOEXCEPT
  5119. {
  5120. auto status = ::KeWaitForSingleObject(&m_kernelEvent, Executive, KernelMode, FALSE, waitDuration);
  5121. // We specified Executive and non-alertable, which means some of the return values are
  5122. // not possible.
  5123. WI_ASSERT((status == STATUS_SUCCESS) || (status == STATUS_TIMEOUT));
  5124. return (status == STATUS_SUCCESS);
  5125. }
  5126. KEVENT m_kernelEvent;
  5127. };
  5128. }
  5129. using kernel_event_auto_reset = details::kernel_event_t<SynchronizationEvent>;
  5130. using kernel_event_manual_reset = details::kernel_event_t<NotificationEvent>;
  5131. using kernel_event = kernel_event_auto_reset; // For parity with the default for other WIL event types.
  5132. namespace details
  5133. {
  5134. // Define a templated type for pool functions in order to satisfy overload resolution below
  5135. template <typename pointer, ULONG tag>
  5136. struct pool_helpers
  5137. {
  5138. static inline
  5139. _IRQL_requires_max_(DISPATCH_LEVEL)
  5140. void __stdcall FreePoolWithTag(pointer value) WI_NOEXCEPT
  5141. {
  5142. if (value)
  5143. {
  5144. ExFreePoolWithTag(value, tag);
  5145. }
  5146. }
  5147. };
  5148. }
  5149. template <typename pointer, ULONG tag = 0>
  5150. using unique_tagged_pool_ptr = unique_any<pointer, decltype(details::pool_helpers<pointer, tag>::FreePoolWithTag), &details::pool_helpers<pointer, tag>::FreePoolWithTag>;
  5151. // For use with IRPs that need to be IoFreeIrp'ed when done, typically allocated using IoAllocateIrp.
  5152. using unique_allocated_irp = wil::unique_any<PIRP, decltype(&::IoFreeIrp), ::IoFreeIrp, details::pointer_access_noaddress>;
  5153. using unique_io_workitem = wil::unique_any<PIO_WORKITEM, decltype(&::IoFreeWorkItem), ::IoFreeWorkItem, details::pointer_access_noaddress>;
  5154. #endif // __WIL_RESOURCE_WDM
  5155. #if defined(WIL_KERNEL_MODE) && (defined(_WDMDDK_) || defined(_ZWAPI_)) && !defined(__WIL_RESOURCE_ZWAPI)
  5156. #define __WIL_RESOURCE_ZWAPI
  5157. using unique_kernel_handle = wil::unique_any<HANDLE, decltype(&::ZwClose), ::ZwClose>;
  5158. #endif // __WIL_RESOURCE_ZWAPI
  5159. } // namespace wil
  5160. #pragma warning(pop)