Skip to content

impl _wmi module#7162

Merged
youknowone merged 2 commits into
RustPython:mainfrom
youknowone:wmi
Feb 15, 2026
Merged

impl _wmi module#7162
youknowone merged 2 commits into
RustPython:mainfrom
youknowone:wmi

Conversation

@youknowone
Copy link
Copy Markdown
Member

@youknowone youknowone commented Feb 15, 2026

Summary by CodeRabbit

  • New Features
    • Added Windows WMI (Windows Management Instrumentation) query functionality, enabling Python code to execute WMI queries and retrieve system information on Windows systems.

CPython Developers and others added 2 commits February 15, 2026 23:44
Implement _wmi.exec_query via COM/WMI using pipe+thread
pattern matching _wmimodule.cpp. Uses raw COM vtable calls
for IWbemLocator, IWbemServices, IEnumWbemClassObject, and
IWbemClassObject interfaces.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 15, 2026

📝 Walkthrough

Walkthrough

A new Windows-specific WMI query module is introduced with PyO3 FFI bindings for COM/Win32 APIs. The module exports a single exec_query function that executes queries by spawning a dedicated thread, managing COM initialization, IPC via pipes, and returning concatenated results as name=value pairs.

Changes

Cohort / File(s) Summary
New WMI Module
crates/vm/src/stdlib/_wmi.rs
Introduces comprehensive WMI integration with FFI bindings for COM/Win32 types, a PyO3-exposed exec_query function, threaded query execution with inter-process communication via pipes, property enumeration, and robust error handling including HRESULT conversion and resource cleanup.
Module Registration
crates/vm/src/stdlib/mod.rs
Adds module declaration and initialization for _wmi under Windows with host_env feature gate, registering it in the multi-phase builtin module definitions.

Sequence Diagram

sequenceDiagram
    participant Python as Python VM
    participant Rust as Rust Module
    participant Thread as WMI Thread
    participant COM as Windows COM
    participant Pipe as Named Pipe
    
    Python->>Rust: exec_query(query_string)
    Rust->>Rust: Validate query (SELECT check)
    Rust->>Thread: Spawn query execution thread
    Rust->>Pipe: Create pipe for results
    
    Thread->>COM: CoInitializeEx()
    Thread->>COM: CoCreateInstance (WbemLocator)
    Thread->>COM: ConnectServer (ROOT\CIMV2)
    Thread->>COM: ExecQuery (WQL)
    Thread->>COM: Enumerate class objects
    
    loop For each WMI object
        Thread->>COM: GetNames (properties)
        Thread->>COM: Get (property values)
        Thread->>Pipe: Write name=value\0
    end
    
    Thread->>COM: Release objects & cleanup
    Rust->>Pipe: Read all results
    Rust->>Python: Return concatenated string
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 Whiskers twitching with delight,
Windows queries now shining bright!
Threads and pipes dance through the night,
WMI magic done just right.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'impl _wmi module' accurately describes the main change: implementing a new WMI module for Windows-specific functionality in the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

[x] test: cpython/Lib/test/test_wmi.py

dependencies:

dependent tests: (no tests depend on wmi)

Legend:

  • [+] path exists in CPython
  • [x] up-to-date, [ ] outdated

@youknowone youknowone marked this pull request as ready for review February 15, 2026 15:21
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@crates/vm/src/stdlib/_wmi.rs`:
- Around line 575-582: The HANDLE variables h_thread, read_pipe, and write_pipe
are initialized with null_mut() and later checked with .is_null(), but
windows-sys 0.61.2 defines HANDLE as an integer (isize), so replace
pointer-specific usage: initialize these HANDLEs to 0 instead of null_mut() and
change any .is_null() checks (e.g., on read_pipe, write_pipe, h_thread) to
comparisons against 0 (== 0); alternatively, you can use
MaybeUninit::<HANDLE>::uninit() for these symbols to avoid direct zeroing—update
code around the HANDLE declarations and all occurrences of .is_null() for HANDLE
values accordingly (refer to h_thread, read_pipe, write_pipe, and any other
HANDLE variables in this file).
- Around line 466-532: The loop leaks prop_name (BSTR) and prop_value (VARIANT)
for system-flavor properties because VariantClear and SysFreeString are only
called inside the flavor-handling block; after object_next returns you must
always free the allocated resources even when (flavor & WBEM_FLAVOR_MASK_ORIGIN)
== WBEM_FLAVOR_ORIGIN_SYSTEM or on non-handled branches. Fix: after each
object_next call (and after using prop_value/prop_name when succeeded), move the
cleanup calls (VariantClear(&mut prop_value) and SysFreeString(prop_name)) out
of the flavor-specific if so they run unconditionally (guarding
SysFreeString(prop_name) for null), and ensure cleanup still happens on early
breaks/errors from object_next; reference variables and functions: object_next,
prop_name, prop_value, flavor, WBEM_FLAVOR_ORIGIN_SYSTEM, VariantClear,
SysFreeString.
🧹 Nitpick comments (1)
crates/vm/src/stdlib/_wmi.rs (1)

671-673: Thread HRESULT exit codes may produce misleading OSError messages.

When the thread returns a failure HRESULT (e.g. 0x80040154 for "class not registered"), it's stored as u32 and eventually passed to std::io::Error::from_raw_os_error(err as i32) at line 688. from_raw_os_error interprets this as a Win32 error code, not an HRESULT, producing an incorrect error message. This matches CPython's behavior, so it's likely intentional, but worth a brief note for future maintainers.

Comment on lines +466 to +532
while succeeded(hr) {
let mut prop_name: *mut u16 = null_mut();
let mut prop_value = VARIANT::zeroed();
let mut flavor: i32 = 0;

hr = object_next(
value,
0,
&mut prop_name,
&mut prop_value,
null_mut(),
&mut flavor,
);

if hr == WBEM_S_NO_MORE_DATA {
hr = 0;
break;
}

if succeeded(hr)
&& (flavor & WBEM_FLAVOR_MASK_ORIGIN) != WBEM_FLAVOR_ORIGIN_SYSTEM
{
let mut prop_str = [0u16; BUFFER_SIZE];
hr =
VariantToString(&prop_value, prop_str.as_mut_ptr(), BUFFER_SIZE as u32);

if succeeded(hr) {
let cb_str1 = (wcslen(prop_name) * 2) as u32;
let cb_str2 = (wcslen(prop_str.as_ptr()) * 2) as u32;

if WriteFile(
write_pipe,
prop_name as *const _,
cb_str1,
&mut written,
null_mut(),
) == 0
|| WriteFile(
write_pipe,
&eq_sign as *const u16 as *const _,
2,
&mut written,
null_mut(),
) == 0
|| WriteFile(
write_pipe,
prop_str.as_ptr() as *const _,
cb_str2,
&mut written,
null_mut(),
) == 0
|| WriteFile(
write_pipe,
&null_sep as *const u16 as *const _,
2,
&mut written,
null_mut(),
) == 0
{
hr = hresult_from_win32(GetLastError());
}
}

VariantClear(&mut prop_value);
SysFreeString(prop_name);
}
}
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Resource leak: prop_name (BSTR) and prop_value (VARIANT) are not freed for system-flavor properties.

object_next allocates prop_name and fills prop_value for every property, but VariantClear/SysFreeString at lines 529-530 are only called inside the if succeeded(hr) && !system_flavor block. When a property has WBEM_FLAVOR_ORIGIN_SYSTEM, the entire block is skipped and both resources leak — once per system property, per WMI object.

🐛 Proposed fix — move cleanup outside the flavor check
-                    if succeeded(hr)
-                        && (flavor & WBEM_FLAVOR_MASK_ORIGIN) != WBEM_FLAVOR_ORIGIN_SYSTEM
-                    {
+                    if succeeded(hr) {
+                     if (flavor & WBEM_FLAVOR_MASK_ORIGIN) != WBEM_FLAVOR_ORIGIN_SYSTEM {
                         let mut prop_str = [0u16; BUFFER_SIZE];
                         hr =
                             VariantToString(&prop_value, prop_str.as_mut_ptr(), BUFFER_SIZE as u32);

                         if succeeded(hr) {
                             let cb_str1 = (wcslen(prop_name) * 2) as u32;
                             let cb_str2 = (wcslen(prop_str.as_ptr()) * 2) as u32;

                             if WriteFile(
                                 write_pipe,
                                 prop_name as *const _,
                                 cb_str1,
                                 &mut written,
                                 null_mut(),
                             ) == 0
                                 || WriteFile(
                                     write_pipe,
                                     &eq_sign as *const u16 as *const _,
                                     2,
                                     &mut written,
                                     null_mut(),
                                 ) == 0
                                 || WriteFile(
                                     write_pipe,
                                     prop_str.as_ptr() as *const _,
                                     cb_str2,
                                     &mut written,
                                     null_mut(),
                                 ) == 0
                                 || WriteFile(
                                     write_pipe,
                                     &null_sep as *const u16 as *const _,
                                     2,
                                     &mut written,
                                     null_mut(),
                                 ) == 0
                             {
                                 hr = hresult_from_win32(GetLastError());
                             }
                         }
+                     }

                         VariantClear(&mut prop_value);
                         SysFreeString(prop_name);
                     }
🤖 Prompt for AI Agents
In `@crates/vm/src/stdlib/_wmi.rs` around lines 466 - 532, The loop leaks
prop_name (BSTR) and prop_value (VARIANT) for system-flavor properties because
VariantClear and SysFreeString are only called inside the flavor-handling block;
after object_next returns you must always free the allocated resources even when
(flavor & WBEM_FLAVOR_MASK_ORIGIN) == WBEM_FLAVOR_ORIGIN_SYSTEM or on
non-handled branches. Fix: after each object_next call (and after using
prop_value/prop_name when succeeded), move the cleanup calls (VariantClear(&mut
prop_value) and SysFreeString(prop_name)) out of the flavor-specific if so they
run unconditionally (guarding SysFreeString(prop_name) for null), and ensure
cleanup still happens on early breaks/errors from object_next; reference
variables and functions: object_next, prop_name, prop_value, flavor,
WBEM_FLAVOR_ORIGIN_SYSTEM, VariantClear, SysFreeString.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intended

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@youknowone, understood. I'll defer to your judgment on this design decision.

Comment thread crates/vm/src/stdlib/_wmi.rs
@youknowone youknowone merged commit 7b1db48 into RustPython:main Feb 15, 2026
14 checks passed
@youknowone youknowone deleted the wmi branch February 15, 2026 15:52
youknowone added a commit to youknowone/RustPython that referenced this pull request Mar 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant