wininskit 0.1.1

Thin checked wrappers over the Win32 an installer needs: elevation, ACLs, services, the Restart Manager, the registry and shortcuts.
//! The bits of a window this process owns that its toolkit does not reach.
//!
//! The wizard draws its own title bar, which means Windows stops drawing the
//! frame, and the rounded corners and the shadow go with it. Both are put back
//! here. Neither is essential; a window without them looks unfinished rather
//! than broken, so a failure is reported and otherwise ignored.

use windows_sys::Win32::{
    Foundation::{HWND, LPARAM},
    Graphics::Dwm::{DWMWA_WINDOW_CORNER_PREFERENCE, DWMWCP_ROUND, DwmSetWindowAttribute},
    System::Threading::GetCurrentProcessId,
    UI::WindowsAndMessaging::{
        EnumWindows, GetWindowLongW, GetWindowThreadProcessId, IsWindowVisible, WS_CHILD,
    },
};

use crate::error::{Error, Result};

/// Rounds the corners of this process's window.
///
/// Windows 10 does not know the attribute and says so; that is not a failure
/// worth reporting, since square corners are what it draws everywhere else.
pub fn round_corners() -> Result<()> {
    let window = main_window().ok_or_else(|| Error::saying("EnumWindows", "no window of ours"))?;
    let preference = DWMWCP_ROUND;
    let status = unsafe {
        DwmSetWindowAttribute(
            window,
            DWMWA_WINDOW_CORNER_PREFERENCE as u32,
            std::ptr::from_ref(&preference).cast(),
            size_of_val(&preference) as u32,
        )
    };
    if status < 0 {
        return Err(Error::hresult("DwmSetWindowAttribute", status));
    }
    Ok(())
}

/// The visible top-level window belonging to this process.
///
/// iced keeps its window handle to itself, so the only way to it is to ask
/// Windows which of them are ours. There is one, so the first is the one.
fn main_window() -> Option<HWND> {
    let mut found: HWND = std::ptr::null_mut();
    unsafe {
        EnumWindows(Some(consider), std::ptr::from_mut(&mut found) as LPARAM);
    }
    (!found.is_null()).then_some(found)
}

/// Called for every top-level window until one of ours is found.
unsafe extern "system" fn consider(window: HWND, out: LPARAM) -> i32 {
    const KEEP_LOOKING: i32 = 1;
    const STOP: i32 = 0;

    unsafe {
        let mut owner = 0u32;
        GetWindowThreadProcessId(window, &mut owner);
        if owner != GetCurrentProcessId() || IsWindowVisible(window) == 0 {
            return KEEP_LOOKING;
        }
        // Tool tips and the like are also ours and also visible.
        if GetWindowLongW(window, GWL_STYLE) & WS_CHILD as i32 != 0 {
            return KEEP_LOOKING;
        }
        *(out as *mut HWND) = window;
    }
    STOP
}

/// GWL_STYLE, which windows-sys files under a name this crate does not import.
const GWL_STYLE: i32 = -16;