rodrigocfd / winsafe

Windows API and GUI in safe, idiomatic Rust.
https://crates.io/crates/winsafe
MIT License
520 stars 30 forks source link

RegQueryValueEx returning TRANSACTION_REQUEST_NOT_VALID for valid data #105

Closed funArash closed 11 months ago

funArash commented 1 year ago

RegQueryValueEx returning TRANSACTION_REQUEST_NOT_VALID for what should be valid data in the registry.. no race conditions.

the following code reproduces the failures. using winsafe version 0.0.18 the registry variables such as PROCESSOR_ARCHITECTURE, PROCESSOR_IDENTIFIER, and OS (to list a few) are valid and should not error TRANSACTION_REQUEST_NOT_VALID.

fn main() {
    #[cfg(target_os = "windows")]
    {
        use winsafe::{self as w, co, prelude::*};

        winsafe::GetEnvironmentStrings()
            .unwrap()
            .iter()
            .for_each(|(k, v)| {
                println!("{k}: {v}");
            });

        println!("\n\nLooking at System Environment Variables");
        let hklm = w::HKEY::LOCAL_MACHINE.RegOpenKeyEx(
            Some("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"),
            co::REG_OPTION::default(),
            co::KEY::READ,
        );
        let env = hklm.unwrap();
        let val_enum = env.RegEnumValue().unwrap();
        for val in val_enum {
            let (val_key, reg) = if let Ok((val, reg)) = val {
                (val, reg)
            } else {
                println!("{}", val.unwrap_err());
                continue;
            };

            println!("{}: {}", val_key, reg);
            let val = env.RegQueryValueEx(Some(&val_key));
            let val = if let Ok(val) = val {
                val
            } else {
                println!("{}", val.unwrap_err());
                continue;
            };

            println!("{val_key}: {val}");
            match val {
                w::RegistryValue::Dword(n) => println!("Number u32: {}", n),
                w::RegistryValue::Qword(n) => println!("Number u64: {}", n),
                w::RegistryValue::Sz(s) => println!("String: {}", s),
                w::RegistryValue::ExpandSz(s) => {
                    println!("Env string: {}", w::ExpandEnvironmentStrings(&s).unwrap());
                },
                w::RegistryValue::MultiSz(strs) => {
                println!("Multi string:");
                for s in strs.iter() {
                    print!("[{}] ", s);
                }
                println!();
                },
                w::RegistryValue::Binary(bin) => {
                    println!("Binary:");
                    for b in bin.iter() {
                        print!("{:02x} ", b);
                    }
                    println!();
                },
                w::RegistryValue::None => println!("No value"),
            }
        }
    }
}

output

Looking at System Environment Variables
ChocolateyInstall: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

ComSpec: 0x00000002
ComSpec: [REG_SZ] "%SystemRoot%\system32\cmd.exe"
String: %SystemRoot%\system32\cmd.exe
DriverData: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

GOPRIVATE: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

NugetMachineInstallRoot: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

NUMBER_OF_PROCESSORS: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

ONEAPI_ROOT: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

OS: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

path: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

PATHEXT: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

PROCESSOR_ARCHITECTURE: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

PROCESSOR_IDENTIFIER: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

PROCESSOR_LEVEL: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

PROCESSOR_REVISION: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

PSModulePath: 0x00000002
PSModulePath: [REG_SZ] "%ProgramFiles%\WindowsPowerShell\Modules;%SystemRoot%\system32\WindowsPowerShell\v1.0\Modules"
String: %ProgramFiles%\WindowsPowerShell\Modules;%SystemRoot%\system32\WindowsPowerShell\v1.0\Modules
SYS_TYPE: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

TEMP: 0x00000002
TEMP: [REG_SZ] "%SystemRoot%\TEMP"
String: %SystemRoot%\TEMP
TMP: 0x00000002
TMP: [REG_SZ] "%SystemRoot%\TEMP"
String: %SystemRoot%\TEMP
UATDATA: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

USERNAME: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

VS2022INSTALLDIR: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

VTUNE_PROFILER_2023_DIR: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

windir: 0x00000002
windir: [REG_SZ] "%SystemRoot%"
String: %SystemRoot%
ZES_ENABLE_SYSMAN: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

VBOX_MSI_INSTALL_PATH: 0x00000001
[0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.

CLINK_DIR: 0x00000002
CLINK_DIR: [REG_SZ] "C:\Program Files (x86)\clink"
String: C:\Program Files (x86)\clink
rodrigocfd commented 1 year ago

I tested your code, and it works perfectly for me.

What's your Windows version?

funArash commented 1 year ago

I have two Windows installs and it was reproducable on both x64 OS

Edition Windows 11 Enterprise
Version 22H2
Installed on    ‎3/‎29/‎2023
OS build    22621.2715
Experience  Windows Feature Experience Pack 1000.22677.1000.0

aarch64 OS

Edition Windows 11 Pro
Version 23H2
Installed on    ‎7/‎11/‎2023
OS build    22631.2715
Experience  Windows Feature Experience Pack 1000.22677.1000.0

https://github.com/funArash/winsafe/commit/9332457981fbc0d0bbe288ae811d03ffea652d24 this works.. it is the check of the data_lens that is causing it. no sure what is its root cause

rodrigocfd commented 11 months ago

Will the code below run?

fn main() {
    use winsafe::{self as w, prelude::*, co};

    let hkey = w::HKEY::CURRENT_USER.RegOpenKeyEx(
        Some("Control Panel\\Mouse"),
        co::REG_OPTION::default(),
        co::KEY::READ,
    ).unwrap();

    let val = hkey.RegQueryValueEx(Some("Beep")).unwrap();

    match val {
        w::RegistryValue::Dword(n) => println!("Number u32: {}", n),
        w::RegistryValue::Qword(n) => println!("Number u64: {}", n),
        w::RegistryValue::Sz(s) => println!("String: {}", s),
        w::RegistryValue::ExpandSz(s) => {
            println!("Env string: {}", w::ExpandEnvironmentStrings(&s).unwrap());
        },
        w::RegistryValue::MultiSz(strs) => {
        println!("Multi string:");
        for s in strs.iter() {
            print!("[{}] ", s);
        }
        println!("");
        },
        w::RegistryValue::Binary(bin) => {
            println!("Binary:");
            for b in bin.iter() {
                print!("{:02x} ", b);
            }
            println!("");
        },
        w::RegistryValue::None => println!("No value"),
    }
}
funArash commented 11 months ago

it panics on line with let val = hkey.RegQueryValueEx(Some("Beep")).unwrap();


thread 'main' panicked at src\main.rs:12:50:
called `Result::unwrap()` on an `Err` value: [0x1a2e 6702] The requested operation is not valid on the Transaction object in its current state.```
funArash commented 11 months ago

My bad.. the test above was done against version 0.0.18.. using latest master (16f2119a56) works fine with both my code and yours. looks like this #103 is the fix.

rodrigocfd commented 11 months ago

Dude... this problem was driving me nuts. I was about to send you a Rust code with exposed raw bindings to find out what was wrong.

Good to know it's fine.