native-dialog 0.9.6

A library to display dialogs. Supports GNU/Linux, BSD Unix, macOS and Windows.
Documentation
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::sync::LazyLock;

use winapi::shared::minwindef::{DWORD, ULONG};
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::libloaderapi::GetModuleHandleW;
use winapi::um::winbase::{ACTCTXW, ActivateActCtx, CreateActCtxW, DeactivateActCtx};
use winapi::um::winnt::HANDLE;
use winapi::um::winuser::MAKEINTRESOURCEW;

const ACTCTX_FLAG_RESOURCE_NAME_VALID: DWORD = 0x008;
const ACTCTX_FLAG_HMODULE_VALID: DWORD = 0x080;

pub struct ActivationContext {
    handle: HANDLE,
}

unsafe impl Send for ActivationContext {}
unsafe impl Sync for ActivationContext {}

impl ActivationContext {
    pub fn with<T>(&self, f: impl Fn() -> T) -> T {
        let mut cookie = 0;
        unsafe { ActivateActCtx(self.handle, &mut cookie) };
        let result = f();
        unsafe { DeactivateActCtx(0, cookie) };

        result
    }

    pub fn get() -> Option<Self> {
        static INSTANCE: LazyLock<ActivationContext> = LazyLock::new(ActivationContext::new);

        let handle = INSTANCE.handle;
        if std::ptr::eq(handle, INVALID_HANDLE_VALUE) {
            return None;
        }

        Some(Self { handle })
    }

    fn new() -> ActivationContext {
        let module_name: Vec<u16> = OsStr::new("shell32.dll")
            .encode_wide()
            .chain(std::iter::once(0))
            .collect();

        let context = ACTCTXW {
            cbSize: std::mem::size_of::<ACTCTXW>() as ULONG,
            hModule: unsafe { GetModuleHandleW(module_name.as_ptr()) },
            lpResourceName: MAKEINTRESOURCEW(124),
            dwFlags: ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID,
            ..unsafe { std::mem::zeroed() }
        };

        ActivationContext {
            handle: unsafe { CreateActCtxW(&context) },
        }
    }
}