windows: Implement app_version (#9410)

#### Call `app_version`:

![Screenshot 2024-03-16
011821](https://github.com/zed-industries/zed/assets/14981363/9e618e49-fee2-4e7a-b884-6b0be05a0c95)

#### `Zed.exe` info:

![Screenshot 2024-03-16
011856](https://github.com/zed-industries/zed/assets/14981363/2b17a5df-ad38-42d0-8396-53680d77101d)


Release Notes:

- N/A
This commit is contained in:
张小白 2024-03-20 03:40:57 +08:00 committed by GitHub
parent cfa0fc96f0
commit 85c294da9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 129 additions and 6 deletions

25
Cargo.lock generated
View File

@ -9867,6 +9867,18 @@ dependencies = [
"serde",
]
[[package]]
name = "toml"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit 0.19.15",
]
[[package]]
name = "toml"
version = "0.8.10"
@ -9895,6 +9907,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
"indexmap 2.0.0",
"serde",
"serde_spanned",
"toml_datetime",
"winnow 0.5.15",
]
@ -12030,6 +12044,16 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "winresource"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77e2aaaf8cfa92078c0c0375423d631f82f2f57979c2884fdd5f604a11e45329"
dependencies = [
"toml 0.7.8",
"version_check",
]
[[package]]
name = "winx"
version = "0.36.3"
@ -12584,6 +12608,7 @@ dependencies = [
"uuid",
"vim",
"welcome",
"winresource",
"workspace",
"zed_actions",
]

View File

@ -356,6 +356,7 @@ features = [
"Win32_Security",
"Win32_Security_Credentials",
"Win32_Storage_FileSystem",
"Win32_System_LibraryLoader",
"Win32_System_Com",
"Win32_System_Com_StructuredStorage",
"Win32_System_DataExchange",

View File

@ -30,6 +30,7 @@ use windows::{
Graphics::Gdi::*,
Media::*,
Security::Credentials::*,
Storage::FileSystem::*,
System::{Com::*, LibraryLoader::*, Ole::*, SystemInformation::*, Threading::*, Time::*},
UI::{Input::KeyboardAndMouse::*, Shell::*, WindowsAndMessaging::*},
},
@ -520,11 +521,97 @@ impl Platform for WindowsPlatform {
}
fn app_version(&self) -> Result<SemanticVersion> {
Ok(SemanticVersion {
major: 1,
minor: 0,
patch: 0,
})
let mut file_name_buffer = vec![0u16; MAX_PATH as usize];
let file_name = {
let mut file_name_buffer_capacity = MAX_PATH as usize;
let mut file_name_length;
loop {
file_name_length =
unsafe { GetModuleFileNameW(None, &mut file_name_buffer) } as usize;
if file_name_length < file_name_buffer_capacity {
break;
}
// buffer too small
file_name_buffer_capacity *= 2;
file_name_buffer = vec![0u16; file_name_buffer_capacity];
}
PCWSTR::from_raw(file_name_buffer[0..(file_name_length + 1)].as_ptr())
};
let version_info_block = {
let mut version_handle = 0;
let version_info_size =
unsafe { GetFileVersionInfoSizeW(file_name, Some(&mut version_handle)) } as usize;
if version_info_size == 0 {
log::error!(
"unable to get version info size: {}",
std::io::Error::last_os_error()
);
return Err(anyhow!("unable to get version info size"));
}
let mut version_data = vec![0u8; version_info_size + 2];
unsafe {
GetFileVersionInfoW(
file_name,
version_handle,
version_info_size as u32,
version_data.as_mut_ptr() as _,
)
}
.inspect_err(|_| {
log::error!(
"unable to retrieve version info: {}",
std::io::Error::last_os_error()
)
})?;
version_data
};
let version_info_raw = {
let mut buffer = unsafe { std::mem::zeroed() };
let mut size = 0;
let entry = "\\".encode_utf16().chain(Some(0)).collect_vec();
if !unsafe {
VerQueryValueW(
version_info_block.as_ptr() as _,
PCWSTR::from_raw(entry.as_ptr()),
&mut buffer,
&mut size,
)
}
.as_bool()
{
log::error!(
"unable to query version info data: {}",
std::io::Error::last_os_error()
);
return Err(anyhow!("the specified resource is not valid"));
}
if size == 0 {
log::error!(
"unable to query version info data: {}",
std::io::Error::last_os_error()
);
return Err(anyhow!("no value is available for the specified name"));
}
buffer
};
let version_info = unsafe { &*(version_info_raw as *mut VS_FIXEDFILEINFO) };
// https://learn.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo
if version_info.dwSignature == 0xFEEF04BD {
return Ok(SemanticVersion {
major: ((version_info.dwProductVersionMS >> 16) & 0xFFFF) as usize,
minor: (version_info.dwProductVersionMS & 0xFFFF) as usize,
patch: ((version_info.dwProductVersionLS >> 16) & 0xFFFF) as usize,
});
} else {
log::error!(
"no version info present: {}",
std::io::Error::last_os_error()
);
return Err(anyhow!("no version info present"));
}
}
// todo(windows)

View File

@ -89,6 +89,9 @@ welcome.workspace = true
workspace.workspace = true
zed_actions.workspace = true
[target.'cfg(target_os = "windows")'.build-dependencies]
winresource = "0.1"
[dev-dependencies]
call = { workspace = true, features = ["test-support"] }
editor = { workspace = true, features = ["test-support"] }

View File

@ -44,7 +44,8 @@ fn main() {
}
}
if std::env::var("CARGO_CFG_TARGET_ENV").ok() == Some("msvc".to_string()) {
#[cfg(target_os = "windows")]
{
// todo(windows): This is to avoid stack overflow. Remove it when solved.
println!("cargo:rustc-link-arg=/stack:{}", 8 * 1024 * 1024);
@ -56,5 +57,11 @@ fn main() {
"cargo:rustc-link-arg-bins=/MANIFESTINPUT:{}",
manifest.canonicalize().unwrap().display()
);
let res = winresource::WindowsResource::new();
if let Err(e) = res.compile() {
eprintln!("{}", e);
std::process::exit(1);
}
}
}