2024-02-15 17:18:14 -08:00

152 lines
6.4 KiB
C++

//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <winrt/Microsoft.UI.h>
namespace ABI::Microsoft::UI
{
using WindowId = winrt::Microsoft::UI::WindowId;
using DisplayId = winrt::Microsoft::UI::DisplayId;
using IconId = winrt::Microsoft::UI::IconId;
}
namespace winrt::Microsoft::UI
{
typedef HRESULT (STDAPICALLTYPE *PfnGetWindowIdFromWindow)(_In_ HWND hwnd, _Out_ ABI::Microsoft::UI::WindowId* windowId);
typedef HRESULT (STDAPICALLTYPE *PfnGetWindowFromWindowId)(_In_ ABI::Microsoft::UI::WindowId windowId, _Out_ HWND* hwnd);
typedef HRESULT (STDAPICALLTYPE *PfnGetDisplayIdFromMonitor)(_In_ HMONITOR hmonitor, _Out_ ABI::Microsoft::UI::DisplayId* displayId);
typedef HRESULT (STDAPICALLTYPE *PfnGetMonitorFromDisplayId)(_In_ ABI::Microsoft::UI::DisplayId displayId, _Out_ HMONITOR* hmonitor);
typedef HRESULT (STDAPICALLTYPE *PfnGetIconIdFromIcon)(_In_ HICON hicon, _Out_ ABI::Microsoft::UI::IconId* iconId);
typedef HRESULT (STDAPICALLTYPE *PfnGetIconFromIconId)(_In_ ABI::Microsoft::UI::IconId iconId, _Out_ HICON* hicon);
typedef struct _InteropImpl
{
PfnGetWindowIdFromWindow pfnGetWindowIdFromWindow;
PfnGetWindowFromWindowId pfnGetWindowFromWindowId;
PfnGetDisplayIdFromMonitor pfnGetDisplayIdFromMonitor;
PfnGetMonitorFromDisplayId pfnGetMonitorFromDisplayId;
PfnGetIconIdFromIcon pfnGetIconIdFromIcon;
PfnGetIconFromIconId pfnGetIconFromIconId;
} InteropImpl;
#pragma warning(push)
#pragma warning(disable:4505) // linker warning: unreferenced local function has been removed
__declspec(selectany) InteropImpl s_impl { nullptr };
__declspec(selectany) HMODULE s_module { nullptr };
// Load the FrameworkUdk library if needed and store pointers to the handle conversion functions.
// We need this approach because third-party apps cannot link to the FrameworkUdk directly.
// Note that in unpackaged apps this will only work after a call to MddBootstrapInitialize().
static void EnsureInteropImplLoaded()
{
if (s_module == nullptr)
{
HMODULE hmod = ::GetModuleHandle(TEXT("Microsoft.Internal.FrameworkUdk.dll"));
if (hmod == nullptr)
{
hmod = ::LoadLibrary(TEXT("Microsoft.Internal.FrameworkUdk.dll"));
}
if (hmod != nullptr)
{
// In case of race conditions, this should be idempotent
*reinterpret_cast<FARPROC*>(&s_impl.pfnGetWindowIdFromWindow) = ::GetProcAddress(hmod, "Windowing_GetWindowIdFromWindow");
*reinterpret_cast<FARPROC*>(&s_impl.pfnGetWindowFromWindowId) = ::GetProcAddress(hmod, "Windowing_GetWindowFromWindowId");
*reinterpret_cast<FARPROC*>(&s_impl.pfnGetDisplayIdFromMonitor) = ::GetProcAddress(hmod, "Windowing_GetDisplayIdFromMonitor");
*reinterpret_cast<FARPROC*>(&s_impl.pfnGetMonitorFromDisplayId) = ::GetProcAddress(hmod, "Windowing_GetMonitorFromDisplayId");
*reinterpret_cast<FARPROC*>(&s_impl.pfnGetIconIdFromIcon) = ::GetProcAddress(hmod, "Windowing_GetIconIdFromIcon");
*reinterpret_cast<FARPROC*>(&s_impl.pfnGetIconFromIconId) = ::GetProcAddress(hmod, "Windowing_GetIconFromIconId");
winrt::check_bool(
(s_impl.pfnGetWindowIdFromWindow != nullptr) &&
(s_impl.pfnGetWindowFromWindowId != nullptr) &&
(s_impl.pfnGetDisplayIdFromMonitor != nullptr) &&
(s_impl.pfnGetMonitorFromDisplayId != nullptr) &&
(s_impl.pfnGetIconIdFromIcon != nullptr) &&
(s_impl.pfnGetIconFromIconId != nullptr));
// Store our HMODULE if none has been set so far
::InterlockedCompareExchangePointer(reinterpret_cast<volatile PVOID*>(&s_module), hmod, nullptr);
// It is possible that due to race conditions the FrameworkUdk dll ends up loaded multiple
// times. The expectation is that the FrameworkUdk dll will remain loaded for the lifetime
// of the process so we won't attempt to mitigate the extra lib refcounts.
}
}
winrt::check_bool(s_module != nullptr);
}
static winrt::Microsoft::UI::WindowId GetWindowIdFromWindow(_In_ const HWND& hwnd)
{
::ABI::Microsoft::UI::WindowId abiWindowId = {};
EnsureInteropImplLoaded();
winrt::check_hresult(s_impl.pfnGetWindowIdFromWindow(hwnd, &abiWindowId));
winrt::Microsoft::UI::WindowId winrtWindowId { abiWindowId.Value };
return winrtWindowId;
}
static HWND GetWindowFromWindowId(_In_ const winrt::Microsoft::UI::WindowId& windowId)
{
HWND hwnd = nullptr;
EnsureInteropImplLoaded();
::ABI::Microsoft::UI::WindowId abiWindowId { windowId.Value };
winrt::check_hresult(s_impl.pfnGetWindowFromWindowId(abiWindowId, &hwnd));
return hwnd;
}
static winrt::Microsoft::UI::DisplayId GetDisplayIdFromMonitor(_In_ const HMONITOR& hmonitor)
{
::ABI::Microsoft::UI::DisplayId abiDisplayId = {};
EnsureInteropImplLoaded();
winrt::check_hresult(s_impl.pfnGetDisplayIdFromMonitor(hmonitor, &abiDisplayId));
winrt::Microsoft::UI::DisplayId winrtDisplayId { abiDisplayId.Value };
return winrtDisplayId;
}
static HMONITOR GetMonitorFromDisplayId(_In_ const winrt::Microsoft::UI::DisplayId& displayId)
{
HMONITOR hmonitor = nullptr;
EnsureInteropImplLoaded();
::ABI::Microsoft::UI::DisplayId abiDisplayId { displayId.Value };
winrt::check_hresult(s_impl.pfnGetMonitorFromDisplayId(abiDisplayId, &hmonitor));
return hmonitor;
}
static winrt::Microsoft::UI::IconId GetIconIdFromIcon(_In_ const HICON& hicon)
{
::ABI::Microsoft::UI::IconId abiIconId = {};
EnsureInteropImplLoaded();
winrt::check_hresult(s_impl.pfnGetIconIdFromIcon(hicon, &abiIconId));
winrt::Microsoft::UI::IconId winrtIconId { abiIconId.Value };
return winrtIconId;
}
static HICON GetIconFromIconId(_In_ const winrt::Microsoft::UI::IconId& iconId)
{
HICON hicon = nullptr;
EnsureInteropImplLoaded();
::ABI::Microsoft::UI::IconId abiIconId { iconId.Value };
winrt::check_hresult(s_impl.pfnGetIconFromIconId(abiIconId, &hicon));
return hicon;
}
#pragma warning(pop)
} // namespace winrt::Microsoft::UI