Detailed changes
@@ -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",
]
@@ -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",
@@ -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)
@@ -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"] }
@@ -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);
+ }
}
}