microsoft / microsoft/win32metadata

`EnumWindows` is incorrectly translated to `Result<()>`

Open
#2,238 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

question
Dominant language
C++
Stars
1.5k
Forks
149
Avg merge
5d 16h
Merged PRs (30d)
4

Description

Summary

Currently, EnumWindows is translated as

#[inline]
pub unsafe fn EnumWindows(
    lpenumfunc: WNDENUMPROC,
    lparam: super::super::Foundation::LPARAM,
) -> windows_core::Result<()> {
    windows_core::link!("user32.dll" "system" fn EnumWindows(lpenumfunc : WNDENUMPROC, lparam : super::super::Foundation:: LPARAM) -> windows_core::BOOL);
    unsafe { EnumWindows(lpenumfunc, lparam).ok() }
}

However, this is incorrect. The docs state

If EnumWindowsProc returns zero, the return value is also zero. In this case, the callback function should call SetLastError to obtain a meaningful error code to be returned to the caller of EnumWindows.

Which means that if lpenumfunc returns 0, code will see Err(<whatever was in SetLastError>) instead of Ok(()). Ideally, EnumWindows should either return Result<BOOL> and do the dance prescribed by docs, or return BOOL and let the user deal with it.

Crate manifest
[package]
name = "ttb_bindings"
edition = "2024"

[dependencies]
windows-core = "0.62.2"

[build-dependencies]
windows-bindgen = "0.66.0"
Crate code
use std::{env, path::Path};
use windows_bindgen;

fn main() {
    let out_dir = env::var_os("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("bindings.rs");

    windows_bindgen::bindgen([
        "--out",
        dest_path.to_string_lossy().as_ref(),
        "--no-allow",
        "--filter",
        "Windows.Win32.Foundation",
        "Windows.Win32.System.Com",
        "Windows.Win32.System.Console",
        "Windows.Win32.System.Diagnostics.Debug",
        "Windows.Win32.System.LibraryLoader",
        "Windows.Win32.System.ProcessStatus",
        "Windows.Win32.System.Threading",
        "Windows.Win32.UI.Accessibility",
        "Windows.Win32.UI.WindowsAndMessaging",
        "Windows.Win32.UI.Xaml.Diagnostics",
        // These drags in a bunch of HTML/XML stuff
        "!Windows.Win32.System.Com.Urlmon",
        "!Windows.Win32.System.Diagnostics.Debug.Extensions",
        "!Windows.Win32.System.Diagnostics.Debug.WebApp",
        // Drags in OLE
        "!Windows.Win32.System.Diagnostics.Debug.I*",
        "!Windows.Win32.System.Diagnostics.Debug.ActiveScript",
    ])
    .unwrap();

    println!("cargo::rerun-if-changed=build.rs");
}
#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

pub use self::Windows::*;
pub use windows_core as core;

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the build.rs example and the generated bindings.rs output for EnumWindows, then trace how the generator maps its native BOOL return and callback behavior. Confirm the intended API shape with the documented SetLastError semantics, and add or update coverage so generated bindings no longer turn a callback return of zero into an incorrect Result error.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, rust
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.