master ohmu/fastfetch-openbsd / src / common / windows / winrt.hpp
ohmu  ·  2026-10-15
  1#pragma once
  2
  3#ifdef __cplusplus
  4
  5extern "C" {
  6    #include "common/FFlist.h"
  7    #include "common/FFstrbuf.h"
  8    #include "common/time.h"
  9    #include "common/windows/com.h"
 10    #include "common/windows/unicode.h"
 11}
 12
 13    #if FF_HAVE_WINRT
 14
 15        #include <roapi.h>
 16        #include <winstring.h>
 17        #include <asyncinfo.h>
 18
 19        #include <winrt/base.h>
 20        #include <winrt/Windows.Foundation.h>
 21        #include <winrt/Windows.Foundation.Collections.h>
 22
 23using winrt::impl::abi_t;
 24
 25// Frees an HSTRING and clears the pointer, so it can be used with [[gnu::cleanup]].
 26static inline void ffDeleteHstring(HSTRING* value) {
 27    if (*value) {
 28        WindowsDeleteString(*value);
 29        *value = nullptr;
 30    }
 31}
 32
 33// Copies an HSTRING into an FFstrbuf, transcoding from UTF-16 to UTF-8.
 34static inline void ffStrbufSetHstring(FFstrbuf* destination, HSTRING value) {
 35    uint32_t length = 0;
 36    const wchar_t* raw = WindowsGetStringRawBuffer(value, &length);
 37    ffStrbufSetNWS(destination, length, raw);
 38}
 39
 40// Wraps `items` in an IVector<hstring> and hands out its IIterable<hstring> view, which is the
 41// parameter shape the FindAllAsync overloads taking additional properties expect. The caller owns
 42// the result.
 43HRESULT ffWinrtCreateHstringIterable(const wchar_t* const* items, uint32_t count, abi_t<winrt::Windows::Foundation::Collections::IIterable<winrt::hstring>>** result);
 44
 45// RoGetActivationFactory() for a WinRT runtime class.
 46//
 47// `Projection` must be the *projection* type -- e.g.
 48// winrt::Windows::Devices.Bluetooth::IBluetoothLEDeviceStatics -- and never abi_t<...>:
 49// winrt::impl::guid_v is only specialized for projection types, and abi_t<T> expands to
 50// impl::abi<T>::type, which is a non-deduced context.
 51template <typename Projection>
 52static inline HRESULT ffGetActivationFactory(const wchar_t* className, abi_t<Projection>** factory) {
 53    HSTRING_HEADER header;
 54    HSTRING runtimeClass;
 55    HRESULT hr = WindowsCreateStringReference(className, (UINT32) ::wcslen(className), &header, &runtimeClass);
 56    if (FAILED(hr)) {
 57        return hr;
 58    }
 59
 60    return RoGetActivationFactory(runtimeClass, winrt::guid_of<Projection>(), reinterpret_cast<void**>(factory));
 61}
 62
 63template <typename TargetProjection, typename SourceAbi>
 64static inline HRESULT ffQueryInterface(SourceAbi* source, abi_t<TargetProjection>** target) {
 65    return source->QueryInterface(winrt::guid_of<TargetProjection>(), reinterpret_cast<void**>(target));
 66}
 67
 68// Spins until `operation` leaves AsyncStatus::Started, then hands its results to `result`.
 69template <typename TOperationAbi, typename TResultAbi>
 70static HRESULT ffWaitForAsyncOperation(TOperationAbi* operation, TResultAbi** result) {
 71    FF_AUTO_RELEASE_COM_OBJECT IAsyncInfo* asyncInfo = nullptr;
 72    HRESULT hr = ffQueryInterface<IAsyncInfo>(operation, &asyncInfo);
 73    if (FAILED(hr)) {
 74        return hr;
 75    }
 76
 77    AsyncStatus status = AsyncStatus::Started;
 78
 79    for (;;) {
 80        hr = asyncInfo->get_Status(&status);
 81        if (FAILED(hr)) {
 82            return hr;
 83        }
 84        if (status == AsyncStatus::Started) {
 85            ffTimeSleep(0);
 86        } else {
 87            break;
 88        }
 89    }
 90
 91    if (status != AsyncStatus::Completed) {
 92        HRESULT errorCode = E_FAIL;
 93        asyncInfo->get_ErrorCode(&errorCode);
 94        return FAILED(errorCode) ? errorCode : E_FAIL;
 95    }
 96
 97    return operation->GetResults((void**) result);
 98}
 99
100template <typename TResultProjection, typename TOperation>
101static HRESULT ffRunAndWait(TOperation&& operation, abi_t<TResultProjection>** result) {
102    *result = nullptr;
103
104    FF_AUTO_RELEASE_COM_OBJECT abi_t<winrt::Windows::Foundation::IAsyncOperation<TResultProjection>>* opResult = nullptr;
105    HRESULT hr = operation(reinterpret_cast<void**>(&opResult));
106    if (FAILED(hr) || !opResult) {
107        return hr;
108    }
109
110    return ffWaitForAsyncOperation(opResult, result);
111}
112
113template <typename TResultProjection, typename TOperation>
114static HRESULT ffRunAndWait2(TOperation&& operation, abi_t<TResultProjection>** result) {
115    *result = nullptr;
116
117    FF_AUTO_RELEASE_COM_OBJECT abi_t<winrt::Windows::Foundation::IAsyncOperationWithProgress<TResultProjection, int32_t>>* opResult = nullptr;
118    HRESULT hr = operation(reinterpret_cast<void**>(&opResult));
119    if (FAILED(hr) || !opResult) {
120        return hr;
121    }
122
123    return ffWaitForAsyncOperation(opResult, result);
124}
125
126    #endif // FF_HAVE_WINRT
127
128#else
129
130    #error Must be included in C++ source file
131
132#endif