# HG changeset patch # User Jiri Vanek # Date 1551971624 -3600 # Node ID ec35c20b529b8e9f2316d35011ba992e80958165 # Parent 2d7fe876a14c67098665a9bc58aec1337c9d997c Native launchers now iterate through various keys of jre/jdk in registry * rust-launcher/src/os_access.rs: introduced RegQueryInfoKeyW and RegEnumKeyExW to enable registry query jdk_registry_path renamed to java_registry_path. jdk_registry_path now iterates over several keys * rust-launcher/src/utils.rs: adapted, and if jdk is found, its jre is used. diff -r 2d7fe876a14c -r ec35c20b529b ChangeLog --- a/ChangeLog Thu Mar 07 14:01:56 2019 +0100 +++ b/ChangeLog Thu Mar 07 16:13:44 2019 +0100 @@ -1,3 +1,10 @@ +2019-03-07 Lars Herschke + + Native launchers now iterate through various keys of jre/jdk in registry + * rust-launcher/src/os_access.rs: introduced RegQueryInfoKeyW and RegEnumKeyExW to enable registry query + jdk_registry_path renamed to java_registry_path. jdk_registry_path now iterates over several keys + * rust-launcher/src/utils.rs: adapted, and if jdk is found, its jre is used. + 2019-03-06 Jiri Vanek Lars Herschke diff -r 2d7fe876a14c -r ec35c20b529b rust-launcher/src/os_access.rs --- a/rust-launcher/src/os_access.rs Thu Mar 07 14:01:56 2019 +0100 +++ b/rust-launcher/src/os_access.rs Thu Mar 07 16:13:44 2019 +0100 @@ -37,7 +37,7 @@ fn info(&self, s: &str); fn important(&self, s: &str); fn system_log(&self, s: &str); - fn get_registry_jdk(&self) -> Option; + fn get_registry_java(&self) -> Option; // next to system and home cfg dir, there is also by-jre config dir, but that do not need to be handled os-specific way // https://docs.oracle.com/javase/7/docs/technotes/guides/jweb/jcp/properties.html fn get_system_config_javadir(&self) -> Option; @@ -119,7 +119,7 @@ log_helper::log_impl(0,self, s); } - fn get_registry_jdk(&self) -> Option { + fn get_registry_java(&self) -> Option { None } @@ -226,10 +226,12 @@ return self.verbose; } - fn get_registry_jdk(&self) -> Option { + fn get_registry_java(&self) -> Option { std::panic::catch_unwind(|| { - let path = win::jdk_registry_path(); - Some(std::path::PathBuf::from(path)) + match win::java_registry_path() { + Ok(path) => Some(std::path::PathBuf::from(path)), + Err(_) => None, + } }).unwrap_or_else(|_e| { // show_error_message(errloc_msg(&e)); None @@ -414,6 +416,32 @@ phkResult: *mut *mut c_void ) -> c_long; + fn RegQueryInfoKeyW( + hKey: *mut c_void, + lpClass: *mut c_ushort, + lpcchClass: *mut c_ulong, + lpReserved: *mut c_ulong, + lpcSubKeys: *mut c_ulong, + lpcbMaxSubKeyLen: *mut c_ulong, + lpcbMaxClassLen: *mut c_ulong, + lpcValues: *mut c_ulong, + lpcbMaxValueNameLen: *mut c_ulong, + lpcbMaxValueLen: *mut c_ulong, + lpcbSecurityDescriptor: *mut c_ulong, + lpftLastWriteTime: *mut c_void + ) -> c_long; + + fn RegEnumKeyExW( + hKey: *mut c_void, + dwIndex: c_ulong, + lpName: *mut c_ushort, + lpcchName: *mut c_ulong, + lpReserved: *mut c_ulong, + lpClass: *mut c_ushort, + lpcchClass: *mut c_ulong, + lpftLastWriteTime: *mut c_void + ) -> c_long; + fn RegCloseKey( hKey: *mut c_void ) -> c_long; @@ -536,32 +564,109 @@ } } - pub fn jdk_registry_path() -> String { - let jdk_key_name = "SOFTWARE\\JavaSoft\\Java Development Kit\\1.8"; - let wjdk_key_name = widen(jdk_key_name); + /* + try to get with the following preference: + - JRE 1.8 + - JDK 1.8 + - max JDK >= 9 + - max JRE >= 9 (only 9 or 10 possible) + - max JDK < 1.8 + - max JRE < 1.8 + */ + pub fn java_registry_path() -> Result { + let mut java_key_name = String::new(); + let jskeys = vec!["Java Runtime Environment", + "Java Development Kit", "JDK", "JRE"]; + for jskey in jskeys.iter() { + let reg_key_name = r"SOFTWARE\JavaSoft\".to_string() + jskey; + let wreg_key_name = widen(®_key_name); + unsafe { + // open regkey + let mut reg_key = null_mut::(); + let err_java = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + wreg_key_name.as_ptr(), + 0, + KEY_READ | KEY_ENUMERATE_SUB_KEYS, + &mut reg_key) as u32; + if ERROR_SUCCESS != err_java { + continue; + } + defer!({ + RegCloseKey(reg_key); + }); + + // get subkey count + let mut sub_cnt: c_ulong = 0; + let err_cnt = RegQueryInfoKeyW( + reg_key, + null_mut::(), + null_mut::(), + null_mut::(), + &mut sub_cnt, + null_mut::(), + null_mut::(), + null_mut::(), + null_mut::(), + null_mut::(), + null_mut::(), + null_mut::()) as u32; + if ERROR_SUCCESS != err_cnt || !(sub_cnt > 0) { + continue; + } + + // get last subkey + let mut sub_key = Vec::with_capacity(256); + let mut sub_len = sub_key.capacity() as u32; + let err_sub = RegEnumKeyExW( + reg_key, + sub_cnt-1, + sub_key.as_mut_ptr(), + &mut sub_len, + null_mut::(), + null_mut::(), + null_mut::(), + null_mut::()) as u32; + if ERROR_SUCCESS != err_sub { + continue; + } + sub_key.set_len(sub_len as usize); + let slice = std::slice::from_raw_parts(sub_key.as_ptr(), sub_key.len() as usize); + let jpath = narrow(slice); + java_key_name = reg_key_name + r"\" + &jpath; + if jpath.starts_with("1.8") || jskey.len() == 3 { + break; + } + } + } + + if java_key_name.len() == 0 { + return Err(2); + } + + let wjava_key_name = widen(&java_key_name); let java_home = "JavaHome"; let wjava_home = widen("JavaHome"); unsafe { // open root - let mut jdk_key = null_mut::(); - let err_jdk = RegOpenKeyExW( + let mut java_key = null_mut::(); + let err_java = RegOpenKeyExW( HKEY_LOCAL_MACHINE, - wjdk_key_name.as_ptr(), + wjava_key_name.as_ptr(), 0, KEY_READ | KEY_ENUMERATE_SUB_KEYS, - &mut jdk_key) as u32; - if ERROR_SUCCESS != err_jdk { - panic!(format!("Error opening registry key, \ - name: [{}], message: [{}]", jdk_key_name, errcode_to_string(err_jdk))); + &mut java_key) as u32; + if ERROR_SUCCESS != err_java { + return Err(err_java); } defer!({ - RegCloseKey(jdk_key); + RegCloseKey(java_key); }); // find out value len let mut value_len: c_ulong = 0; let mut value_type: c_ulong = 0; let err_len = RegQueryValueExW( - jdk_key, + java_key, wjava_home.as_ptr(), null_mut::(), &mut value_type, @@ -569,13 +674,13 @@ &mut value_len) as u32; if ERROR_SUCCESS != err_len || !(value_len > 0) || REG_SZ != value_type { panic!(format!("Error opening registry value len, \ - key: [{}], value: [{}], message: [{}]", jdk_key_name, java_home, errcode_to_string(err_len))); + key: [{}], value: [{}], message: [{}]", java_key_name, java_home, errcode_to_string(err_len))); } // get value let mut wvalue: Vec = Vec::new(); wvalue.resize((value_len as usize) / std::mem::size_of::(), 0); let err_val = RegQueryValueExW( - jdk_key, + java_key, wjava_home.as_ptr(), null_mut::(), null_mut::(), @@ -583,16 +688,15 @@ &mut value_len) as u32; if ERROR_SUCCESS != err_val { panic!(format!("Error opening registry value, \ - key: [{}], value: [{}], message: [{}]", jdk_key_name, java_home, errcode_to_string(err_val))); + key: [{}], value: [{}], message: [{}]", java_key_name, java_home, errcode_to_string(err_val))); } // format and return path let slice = std::slice::from_raw_parts(wvalue.as_ptr(), wvalue.len() - 1 as usize); - let jpath_badslash = narrow(slice); - let mut jpath = jpath_badslash.replace("\\", "/"); - if '/' as u8 != jpath.as_bytes()[jpath.len() - 1] { - jpath.push('/'); + let mut jpath = narrow(slice); + if '\\' as u8 != jpath.as_bytes()[jpath.len() - 1] { + jpath.push('\\'); } - return jpath; + return Ok(jpath); } } diff -r 2d7fe876a14c -r ec35c20b529b rust-launcher/src/utils.rs --- a/rust-launcher/src/utils.rs Thu Mar 07 14:01:56 2019 +0100 +++ b/rust-launcher/src/utils.rs Thu Mar 07 16:13:44 2019 +0100 @@ -23,12 +23,19 @@ match env::var("JAVA_HOME") { Ok(war) => { os.log("itw-rust-debug: found and using"); - return std::path::PathBuf::from(war); + let java_home = std::path::PathBuf::from(war); + let mut jre_dir = java_home.clone(); + jre_dir.push("jre"); + jre_dir.push(""); + if jre_dir.exists() { + return jre_dir; + } + return java_home; } Err(_e) => { os.log("itw-rust-debug: nothing"); os.log("itw-rust-debug: trying jdk from registry"); - match os.get_registry_jdk() { + match os.get_registry_java() { Some(path) => { os.log("itw-rust-debug: found and using"); return path; @@ -39,6 +46,12 @@ match get_jdk_from_path_conditionally(os) { Some(path) => { os.log("itw-rust-debug: found and using"); + let mut jre_dir = path.clone(); + jre_dir.push("jre"); + jre_dir.push(""); + if jre_dir.exists() { + return jre_dir; + } return path; } None => { @@ -243,7 +256,7 @@ self.vec.borrow_mut().push(ss); } - fn get_registry_jdk(&self) -> Option { + fn get_registry_java(&self) -> Option { None }