//********************************************************* // // Copyright (c) Microsoft. All rights reserved. // This code is licensed under the MIT License. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE AND NONINFRINGEMENT. // //********************************************************* #ifndef __WIL_WINDOWING_INCLUDED #define __WIL_WINDOWING_INCLUDED #include #include #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) namespace wil { namespace details { template struct always_false : wistd::false_type { }; template void DoEnumWindowsNoThrow(TEnumApi&& enumApi, TCallback&& callback) noexcept { auto enumproc = [](HWND hwnd, LPARAM lParam) -> BOOL { auto pCallback = reinterpret_cast(lParam); #ifdef __cpp_if_constexpr using result_t = decltype((*pCallback)(hwnd)); if constexpr (wistd::is_void_v) { (*pCallback)(hwnd); return TRUE; } else if constexpr (wistd::is_same_v) { // NB: this works for both HRESULT and NTSTATUS as both S_OK and ERROR_SUCCESS are 0 return (S_OK == (*pCallback)(hwnd)) ? TRUE : FALSE; } else if constexpr (std::is_same_v) { return (*pCallback)(hwnd) ? TRUE : FALSE; } else { static_assert(details::always_false::value, "Callback must return void, bool, or HRESULT"); } #else return (*pCallback)(hwnd); #endif }; enumApi(enumproc, reinterpret_cast(&callback)); } #ifdef WIL_ENABLE_EXCEPTIONS template void DoEnumWindows(TEnumApi&& enumApi, TCallback&& callback) { struct { std::exception_ptr exception; TCallback* pCallback; } callbackData = {nullptr, &callback}; auto enumproc = [](HWND hwnd, LPARAM lParam) -> BOOL { auto pCallbackData = reinterpret_cast(lParam); try { auto pCallback = pCallbackData->pCallback; #ifdef __cpp_if_constexpr using result_t = decltype((*pCallback)(hwnd)); if constexpr (std::is_void_v) { (*pCallback)(hwnd); return TRUE; } else if constexpr (std::is_same_v) { // NB: this works for both HRESULT and NTSTATUS as both S_OK and ERROR_SUCCESS are 0 return (S_OK == (*pCallback)(hwnd)) ? TRUE : FALSE; } else if constexpr (std::is_same_v) { return (*pCallback)(hwnd) ? TRUE : FALSE; } else { static_assert(details::always_false::value, "Callback must return void, bool, or HRESULT"); } #else return (*pCallback)(hwnd); #endif } catch (...) { pCallbackData->exception = std::current_exception(); return FALSE; } }; enumApi(enumproc, reinterpret_cast(&callbackData)); if (callbackData.exception) { std::rethrow_exception(callbackData.exception); } } #endif } // namespace details template void for_each_window_nothrow(TCallback&& callback) noexcept { details::DoEnumWindowsNoThrow(&EnumWindows, wistd::forward(callback)); } template void for_each_thread_window_nothrow(_In_ DWORD threadId, TCallback&& callback) noexcept { auto boundEnumThreadWindows = [threadId](WNDENUMPROC enumproc, LPARAM lParam) noexcept -> BOOL { return EnumThreadWindows(threadId, enumproc, lParam); }; details::DoEnumWindowsNoThrow(boundEnumThreadWindows, wistd::forward(callback)); } template void for_each_child_window_nothrow(_In_ HWND hwndParent, TCallback&& callback) noexcept { auto boundEnumChildWindows = [hwndParent](WNDENUMPROC enumproc, LPARAM lParam) noexcept -> BOOL { return EnumChildWindows(hwndParent, enumproc, lParam); }; details::DoEnumWindowsNoThrow(boundEnumChildWindows, wistd::forward(callback)); } #ifdef WIL_ENABLE_EXCEPTIONS template void for_each_window(TCallback&& callback) { details::DoEnumWindows(&EnumWindows, wistd::forward(callback)); } template void for_each_thread_window(_In_ DWORD threadId, TCallback&& callback) { auto boundEnumThreadWindows = [threadId](WNDENUMPROC enumproc, LPARAM lParam) noexcept -> BOOL { return EnumThreadWindows(threadId, enumproc, lParam); }; details::DoEnumWindows(boundEnumThreadWindows, wistd::forward(callback)); } template void for_each_child_window(_In_ HWND hwndParent, TCallback&& callback) { auto boundEnumChildWindows = [hwndParent](WNDENUMPROC enumproc, LPARAM lParam) noexcept -> BOOL { return EnumChildWindows(hwndParent, enumproc, lParam); }; details::DoEnumWindows(boundEnumChildWindows, wistd::forward(callback)); } #endif } // namespace wil #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #endif // __WIL_WINDOWING_INCLUDED