ohadravid / wmi-rs

WMI crate for rust
Apache License 2.0
80 stars 27 forks source link

Unable to query Win32_Tpm class #63

Closed sn99 closed 1 year ago

sn99 commented 1 year ago

Greetings, I am trying to query Win32_Tpm class but I get the following error Error: HResultError { hres: -2147217385 }

My rust code:

use serde::Deserialize;
use std::collections::HashMap;
use std::time::Duration;
use wmi::{COMLibrary, WMIConnection};
use wmi::{Variant, WMIDateTime};

#[derive(Deserialize, Debug)]
#[serde(rename = "Win32_Tpm")]
#[serde(rename_all = "PascalCase")]
struct Win32Tpm {
    is_activated_initial_value: Option<bool>,
    is_enabled_initial_value: Option<bool>,
    is_owned_initial_value: Option<bool>,
    spec_version: Option<String>,
    manufacturer_version: Option<String>,
    manufacturer_version_info: Option<String>,
    manufacturer_id: Option<u32>,
    physical_presence_version_info: Option<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let com_con = COMLibrary::new()?;
    let wmi_con =
        WMIConnection::with_namespace_path("Root\\CIMV2\\Security\\MicrosoftTpm", com_con)?;

    let results: Vec<Win32Tpm> = wmi_con.query()?; // Error: HResultError { hres: -2147217385 } 

    for tpm in results {
        println!("{:#?}", tpm);
    }

    Ok(())
}

I have trouble understanding where I am going wrong. I am running it in administrative mode. Using something like Get-WmiObject -Namespace "root\CIMV2\Security\MicrosoftTpm" -Class "Win32_Tpm" in powershell works fine.

tance77 commented 1 year ago

I to am getting Error: HResultError { hres: -2147217385 } although on the COMLibrary::new().

Windows 11 running as administrator. Not sure why this would be happening or what the error code means.

There was this closed issue sues/48 but not really sure how they solved the issue. They didn't really go into much detail.

Also this works in my tests but not in a Tauri Command.

This might help you https://github.com/ohadravid/wmi-rs/issues/48#issuecomment-1430406428

sn99 commented 1 year ago

I get the same error as last time using a thread but different error if I use COMLibrary::new() thread '<unnamed>' panicked at 'calledResult::unwrap()on anErrvalue: HResultError { hres: -2147217392 }', src\main.rs:23:54

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let k = std::thread::spawn(|| {
        let com_con = COMLibrary::new().unwrap();
        let wmi_con =
            WMIConnection::new(com_con).unwrap();
        let results: Vec<Win32Tpm> = wmi_con.query().unwrap();

        for tpm in results {
            println!("{:#?}", tpm);
        }
    });

    k.join().unwrap();

    Ok(())
}

I will look into it if I can.

ohadravid commented 1 year ago

Hi @sn99 👋

The problem is that serde will rename a field like is_activated_initial_value to IsOwnedInitialValue, but according to the docs the expected name should be IsOwned_InitialValue.

You can use dbg!(wmi::build_query::<Win32Tpm>(None)) to view the generated query and run it yourself, and you'll get the expected "invalid query" error.

The solution is to rename it manually to the correct name, like this:

#[derive(Deserialize, Debug)]
#[serde(rename = "Win32_Tpm")]
#[serde(rename_all = "PascalCase")]
struct Win32Tpm {
    #[serde(rename = "IsActivated_InitialValue")]
    is_activated_initial_value: Option<bool>,
    /// Same for `IsEnabled_InitialValue` & `IsOwned_InitialValue`
    /// ... rest of the fields can use the default PascalCase renaming
}
sn99 commented 1 year ago

@ohadravid thanks, it worked🥳, I jumped down the wrong rabbit hole thinking I had permission issues 💀

use serde::Deserialize;
use wmi::{COMLibrary, WMIConnection};

#[derive(Deserialize, Debug)]
#[serde(rename = "Win32_Tpm")]
#[serde(rename_all = "PascalCase")]
struct Win32Tpm {
    #[serde(rename = "IsActivated_InitialValue")]
    is_activated_initial_value: Option<bool>,
    #[serde(rename = "IsEnabled_InitialValue")]
    is_enabled_initial_value: Option<bool>,
    #[serde(rename = "IsOwned_InitialValue")]
    is_owned_initial_value: Option<bool>,
    spec_version: Option<String>,
    manufacturer_version: Option<String>,
    manufacturer_version_info: Option<String>,
    manufacturer_id: Option<u32>,
    physical_presence_version_info: Option<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let com_con = COMLibrary::new().unwrap();
    let wmi_con =
        WMIConnection::with_namespace_path("root\\CIMV2\\Security\\MicrosoftTpm", com_con).unwrap();
    let results: Vec<Win32Tpm> = wmi_con.query().unwrap();

    for tpm in results {
        println!("{:#?}", tpm);
    }

    Ok(())
}

@tance77 Thanks for you help too, this works for me now.