Skip to content

Commit 7497552

Browse files
authored
[rust] Replace WMIC commands (deprecated) by WinAPI in Windows (#15363)
* [rust] Replace WMIC commands (to be deprecated) by PowerShell in Windows * [rust] Use multiple command in exec driver test * Revert "[rust] Use multiple command in exec driver test" This reverts commit 802da7a. * [rust] Remove iexplorer exec test * Revert "[rust] Remove iexplorer exec test" This reverts commit 91649aa. * [rust] Use PowerShell only for previous WMIC commands * [rust] Run PS command to discover OS * [rust] Setup PROCESSOR_ARCHITECTURE env for Windows * [rust] Avoid repetition in logic to run powershell or not * Use winapi instead of PowerShell to discover browser version * Update checksum in Cargo.Bazel.lock * Use conditional compilation for winapi logic (only compiled in Windows)
1 parent 2534420 commit 7497552

File tree

6 files changed

+168
-21
lines changed

6 files changed

+168
-21
lines changed

‎rust/Cargo.Bazel.lock

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"checksum": "d2d968dacd2ceab962c18fa28697dc189f31b3991a3554ff21e167836627a3b8",
2+
"checksum": "94dc89c8790518c956fd52cd06689af1557f6c755c7bd1a1414719ef73ac468c",
33
"crates": {
44
"addr2line 0.21.0": {
55
"name": "addr2line",
@@ -13478,6 +13478,10 @@
1347813478
"id": "which 7.0.2",
1347913479
"target": "which"
1348013480
},
13481+
{
13482+
"id": "winapi 0.3.9",
13483+
"target": "winapi"
13484+
},
1348113485
{
1348213486
"id": "xz2 0.1.7",
1348313487
"target": "xz2"
@@ -18838,14 +18842,36 @@
1883818842
],
1883918843
"crate_features": {
1884018844
"common": [
18841-
"fileapi",
18842-
"handleapi",
18843-
"processthreadsapi",
18844-
"std",
18845-
"winbase",
18846-
"winerror"
18845+
"sysinfoapi",
18846+
"winnt",
18847+
"winver"
1884718848
],
18848-
"selects": {}
18849+
"selects": {
18850+
"aarch64-pc-windows-msvc": [
18851+
"fileapi",
18852+
"handleapi",
18853+
"processthreadsapi",
18854+
"std",
18855+
"winbase",
18856+
"winerror"
18857+
],
18858+
"i686-pc-windows-msvc": [
18859+
"fileapi",
18860+
"handleapi",
18861+
"processthreadsapi",
18862+
"std",
18863+
"winbase",
18864+
"winerror"
18865+
],
18866+
"x86_64-pc-windows-msvc": [
18867+
"fileapi",
18868+
"handleapi",
18869+
"processthreadsapi",
18870+
"std",
18871+
"winbase",
18872+
"winerror"
18873+
]
18874+
}
1884918875
},
1885018876
"deps": {
1885118877
"common": [
@@ -21972,6 +21998,7 @@
2197221998
"toml 0.8.20",
2197321999
"walkdir 2.5.0",
2197422000
"which 7.0.2",
22001+
"winapi 0.3.9",
2197522002
"xz2 0.1.7",
2197622003
"zip 2.2.3"
2197722004
],

‎rust/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎rust/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ apple-flat-package = "0.20.0"
3838
which = "7.0.2"
3939
fs2 = "0.4.3"
4040
fs_extra = "1.3.0"
41+
winapi = { version = "0.3.9", features = ["winver", "winnt", "sysinfoapi"] }
4142

4243
[dev-dependencies]
4344
assert_cmd = "2.0.16"

‎rust/src/config.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::{
2121
default_cache_folder, format_one_arg, path_to_string, Command, ENV_PROCESSOR_ARCHITECTURE,
2222
REQUEST_TIMEOUT_SEC, UNAME_COMMAND,
2323
};
24-
use crate::{ARCH_AMD64, ARCH_ARM64, ARCH_X86, TTL_SEC, WMIC_COMMAND_OS};
24+
use crate::{ARCH_AMD64, ARCH_ARM64, ARCH_X86, TTL_SEC};
2525
use anyhow::anyhow;
2626
use anyhow::Error;
2727
use std::cell::RefCell;
@@ -30,6 +30,13 @@ use std::env::consts::OS;
3030
use std::fs::read_to_string;
3131
use std::path::Path;
3232
use toml::Table;
33+
#[cfg(windows)]
34+
use winapi::um::sysinfoapi::{GetNativeSystemInfo, SYSTEM_INFO};
35+
#[cfg(windows)]
36+
use winapi::um::winnt::{
37+
PROCESSOR_ARCHITECTURE_AMD64, PROCESSOR_ARCHITECTURE_ARM, PROCESSOR_ARCHITECTURE_ARM64,
38+
PROCESSOR_ARCHITECTURE_IA64, PROCESSOR_ARCHITECTURE_INTEL,
39+
};
3340

3441
thread_local!(static CACHE_PATH: RefCell<String> = RefCell::new(path_to_string(&default_cache_folder())));
3542

@@ -69,14 +76,16 @@ impl ManagerConfig {
6976

7077
let self_os = OS;
7178
let self_arch = if WINDOWS.is(self_os) {
72-
let mut architecture = env::var(ENV_PROCESSOR_ARCHITECTURE).unwrap_or_default();
73-
if architecture.is_empty() {
74-
let get_os_command = Command::new_single(WMIC_COMMAND_OS.to_string());
75-
architecture = run_shell_command_by_os(self_os, get_os_command).unwrap_or_default();
79+
let mut _architecture = env::var(ENV_PROCESSOR_ARCHITECTURE).unwrap_or_default();
80+
#[cfg(windows)]
81+
{
82+
if _architecture.is_empty() {
83+
_architecture = get_win_os_architecture();
84+
}
7685
}
77-
if architecture.contains("32") {
86+
if _architecture.contains("32") {
7887
ARCH_X86.to_string()
79-
} else if architecture.contains("ARM") {
88+
} else if _architecture.contains("ARM") {
8089
ARCH_ARM64.to_string()
8190
} else {
8291
ARCH_AMD64.to_string()
@@ -297,3 +306,21 @@ fn read_cache_path() -> String {
297306
});
298307
cache_path
299308
}
309+
310+
#[cfg(windows)]
311+
fn get_win_os_architecture() -> String {
312+
unsafe {
313+
let mut system_info: SYSTEM_INFO = std::mem::zeroed();
314+
GetNativeSystemInfo(&mut system_info);
315+
316+
match system_info.u.s() {
317+
si if si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 => "64-bit",
318+
si if si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL => "32-bit",
319+
si if si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM => "ARM",
320+
si if si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64 => "ARM64",
321+
si if si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 => "Itanium-based",
322+
_ => "Unknown",
323+
}
324+
.to_string()
325+
}
326+
}

‎rust/src/files.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,23 @@ use directories::BaseDirs;
2929
use flate2::read::GzDecoder;
3030
use fs_extra::dir::{move_dir, CopyOptions};
3131
use regex::Regex;
32+
#[cfg(windows)]
33+
use std::ffi::OsStr;
3234
use std::fs;
3335
use std::fs::File;
3436
use std::io;
3537
use std::io::{BufReader, Cursor, Read};
38+
#[cfg(windows)]
39+
use std::os::windows::ffi::OsStrExt;
3640
use std::path::{Path, PathBuf};
41+
#[cfg(windows)]
42+
use std::ptr;
3743
use tar::Archive;
3844
use walkdir::{DirEntry, WalkDir};
45+
#[cfg(windows)]
46+
use winapi::shared::minwindef::LPVOID;
47+
#[cfg(windows)]
48+
use winapi::um::winver::{GetFileVersionInfoSizeW, GetFileVersionInfoW, VerQueryValueW};
3949
use xz2::read::XzDecoder;
4050
use zip::ZipArchive;
4151

@@ -594,3 +604,86 @@ pub fn capitalize(s: &str) -> String {
594604
Some(first) => first.to_uppercase().collect::<String>() + chars.as_str(),
595605
}
596606
}
607+
608+
#[cfg(not(windows))]
609+
pub fn get_win_file_version(_file_path: &str) -> Option<String> {
610+
None
611+
}
612+
613+
#[cfg(windows)]
614+
pub fn get_win_file_version(file_path: &str) -> Option<String> {
615+
unsafe {
616+
let wide_path: Vec<u16> = OsStr::new(file_path).encode_wide().chain(Some(0)).collect();
617+
618+
let mut dummy = 0;
619+
let size = GetFileVersionInfoSizeW(wide_path.as_ptr(), &mut dummy);
620+
if size == 0 {
621+
return None;
622+
}
623+
624+
let mut buffer: Vec<u8> = Vec::with_capacity(size as usize);
625+
if GetFileVersionInfoW(wide_path.as_ptr(), 0, size, buffer.as_mut_ptr() as LPVOID) == 0 {
626+
return None;
627+
}
628+
buffer.set_len(size as usize);
629+
630+
let mut lang_and_codepage_ptr: LPVOID = ptr::null_mut();
631+
let mut lang_and_codepage_len: u32 = 0;
632+
633+
if VerQueryValueW(
634+
buffer.as_ptr() as LPVOID,
635+
OsStr::new("\\VarFileInfo\\Translation")
636+
.encode_wide()
637+
.chain(Some(0))
638+
.collect::<Vec<u16>>()
639+
.as_ptr(),
640+
&mut lang_and_codepage_ptr,
641+
&mut lang_and_codepage_len,
642+
) == 0
643+
{
644+
return None;
645+
}
646+
647+
if lang_and_codepage_len == 0 {
648+
return None;
649+
}
650+
651+
let lang_and_codepage_slice = std::slice::from_raw_parts(
652+
lang_and_codepage_ptr as *const u16,
653+
lang_and_codepage_len as usize / 2,
654+
);
655+
let lang = lang_and_codepage_slice[0];
656+
let codepage = lang_and_codepage_slice[1];
657+
658+
let query = format!(
659+
"\\StringFileInfo\\{:04x}{:04x}\\ProductVersion",
660+
lang, codepage
661+
);
662+
let query_wide: Vec<u16> = OsStr::new(&query).encode_wide().chain(Some(0)).collect();
663+
664+
let mut product_version_ptr: LPVOID = ptr::null_mut();
665+
let mut product_version_len: u32 = 0;
666+
667+
if VerQueryValueW(
668+
buffer.as_ptr() as LPVOID,
669+
query_wide.as_ptr(),
670+
&mut product_version_ptr,
671+
&mut product_version_len,
672+
) == 0
673+
{
674+
return None;
675+
}
676+
677+
if product_version_ptr.is_null() {
678+
return None;
679+
}
680+
681+
let product_version_slice = std::slice::from_raw_parts(
682+
product_version_ptr as *const u16,
683+
product_version_len as usize,
684+
);
685+
let product_version = String::from_utf16_lossy(product_version_slice);
686+
687+
Some(product_version.trim_end_matches('\0').to_string())
688+
}
689+
}

‎rust/src/lib.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::config::OS::{MACOS, WINDOWS};
2020
use crate::config::{str_to_os, ManagerConfig};
2121
use crate::downloads::download_to_tmp_folder;
2222
use crate::edge::{EdgeManager, EDGEDRIVER_NAME, EDGE_NAMES, WEBVIEW2_NAME};
23+
use crate::files::get_win_file_version;
2324
use crate::files::{
2425
capitalize, collect_files_from_cache, create_path_if_not_exists, default_cache_folder,
2526
find_latest_from_cache, get_binary_extension, path_to_string,
@@ -75,8 +76,6 @@ pub const DEV: &str = "dev";
7576
pub const CANARY: &str = "canary";
7677
pub const NIGHTLY: &str = "nightly";
7778
pub const ESR: &str = "esr";
78-
pub const WMIC_COMMAND: &str = "wmic datafile where name='{}' get Version /value";
79-
pub const WMIC_COMMAND_OS: &str = "wmic os get osarchitecture";
8079
pub const REG_VERSION_ARG: &str = "version";
8180
pub const REG_CURRENT_VERSION_ARG: &str = "CurrentVersion";
8281
pub const REG_PV_ARG: &str = "pv";
@@ -453,8 +452,9 @@ pub trait SeleniumManager {
453452
driver_version_command,
454453
) {
455454
Ok(out) => out,
456-
Err(_e) => continue,
455+
Err(_) => continue,
457456
};
457+
458458
let full_browser_version = parse_version(output, self.get_logger()).unwrap_or_default();
459459
if full_browser_version.is_empty() {
460460
continue;
@@ -1158,9 +1158,7 @@ pub trait SeleniumManager {
11581158
let mut commands = Vec::new();
11591159
if WINDOWS.is(self.get_os()) {
11601160
if !escaped_browser_path.is_empty() {
1161-
let wmic_command =
1162-
Command::new_single(format_one_arg(WMIC_COMMAND, &escaped_browser_path));
1163-
commands.push(wmic_command);
1161+
return Ok(get_win_file_version(&escaped_browser_path));
11641162
}
11651163
if !self.is_browser_version_unstable() {
11661164
let reg_command =

0 commit comments

Comments
 (0)