From e02ba3c2b9fc2418975b9153fb6a78f6b0818e6d Mon Sep 17 00:00:00 2001 From: Vitalii Koshura Date: Sun, 11 Aug 2024 03:32:30 +0200 Subject: [PATCH] [Windows] Detect WSL version of enabled distros. In the most cases, WSL2 (currently the latest) is the recommended version, but there are some cases when WSL1 is more suitable. For example, WSL1 is faster in some cases (e.g. file operations), and it is the only option for Windows 10 Home users. More details here: https://docs.microsoft.com/en-us/windows/wsl/compare-versions Signed-off-by: Vitalii Koshura --- client/client_state.cpp | 8 ++++---- client/hostinfo_wsl.cpp | 35 ++++++++++++++++++++--------------- lib/wslinfo.cpp | 26 +++++++++++++++----------- lib/wslinfo.h | 15 +++++++++++---- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/client/client_state.cpp b/client/client_state.cpp index 2ce90391d3..d371aa7741 100644 --- a/client/client_state.cpp +++ b/client/client_state.cpp @@ -1,6 +1,6 @@ // This file is part of BOINC. -// http://boinc.berkeley.edu -// Copyright (C) 2022 University of California +// https://boinc.berkeley.edu +// Copyright (C) 2024 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License @@ -253,11 +253,11 @@ void CLIENT_STATE::show_host_info() { const WSL& wsl = host_info.wsls.wsls[i]; if (wsl.is_default) { msg_printf(NULL, MSG_INFO, - " [%s] (default): %s (%s)", wsl.distro_name.c_str(), wsl.name.c_str(), wsl.version.c_str() + " [%s] (default): %s (%s)", wsl.distro_name.c_str(), wsl.wsl_version.c_str(), wsl.os_name.c_str(), wsl.os_version.c_str() ); } else { msg_printf(NULL, MSG_INFO, - " [%s]: %s (%s)", wsl.distro_name.c_str(), wsl.name.c_str(), wsl.version.c_str() + " [%s] : %s (%s)", wsl.distro_name.c_str(), wsl.wsl_version.c_str(), wsl.os_name.c_str(), wsl.os_version.c_str() ); } } diff --git a/client/hostinfo_wsl.cpp b/client/hostinfo_wsl.cpp index 211c45fbb0..7c11597754 100644 --- a/client/hostinfo_wsl.cpp +++ b/client/hostinfo_wsl.cpp @@ -1,6 +1,6 @@ // This file is part of BOINC. -// http://boinc.berkeley.edu -// Copyright (C) 2018 University of California +// https://boinc.berkeley.edu +// Copyright (C) 2024 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License @@ -23,7 +23,7 @@ #include "hostinfo.h" -bool get_available_wsls(std::vector& wsls, std::string& default_wsl) { +bool get_available_wsls(std::vector>& wsls, std::string& default_wsl) { const std::string lxss_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Lxss"; HKEY hKey; @@ -65,20 +65,24 @@ bool get_available_wsls(std::vector& wsls, std::string& default_wsl break; } - char wsl_name[buf_len]; - DWORD wsl_name_len = sizeof(wsl_name); DWORD wsl_state = 0; DWORD wsl_state_len = sizeof(wsl_state); - ret = RegQueryValueEx(hSubKey, "State", NULL, NULL, (LPBYTE)&wsl_state, &wsl_state_len); if (ret != ERROR_SUCCESS || wsl_state != 1) { continue; } + DWORD wsl_version = 1; + DWORD wsl_version_len = sizeof(wsl_version); + // there might be no version key, so we ignore the return value + RegQueryValueEx(hSubKey, "Version", NULL, NULL, (LPBYTE)&wsl_version, &wsl_version_len); + + char wsl_name[buf_len]; + DWORD wsl_name_len = sizeof(wsl_name); ret = RegQueryValueEx(hSubKey, "DistributionName", NULL, NULL, (LPBYTE)wsl_name, &wsl_name_len); if ((ret == ERROR_SUCCESS) && (wsl_name_len < buf_len)) { - wsls.push_back(wsl_name); + wsls.push_back(std::make_pair(wsl_name, wsl_version)); if (std::string(wsl_guid) == std::string(default_wsl_guid)) { default_wsl = wsl_name; } @@ -117,8 +121,8 @@ std::wstring s2ws(const std::string& s) return r; } -bool create_wsl_process(const std::string& wsl_distro_name, const std::string& command, HANDLE* handle) { - return (pWslLaunch(s2ws(wsl_distro_name).c_str(), s2ws(command).c_str(), FALSE, in_read, out_write, out_write, handle) == S_OK); +bool create_wsl_process(const std::string& wsl_distro_name, const std::string& command, HANDLE* handle, bool use_current_work_dir = false) { + return (pWslLaunch(s2ws(wsl_distro_name).c_str(), s2ws(command).c_str(), use_current_work_dir, in_read, out_write, out_write, handle) == S_OK); } bool CreateWslProcess(const std::string& wsl_app, const std::string& command, HANDLE& handle) { @@ -226,7 +230,7 @@ int get_wsl_information(bool& wsl_available, WSLS& wsls) { out_write = NULL; pWslLaunch = NULL; - std::vector distros; + std::vector> distros; std::string default_distro; if (!get_available_wsls(distros, default_distro)) { @@ -270,7 +274,7 @@ int get_wsl_information(bool& wsl_available, WSLS& wsls) { char wsl_dist_name[256]; char wsl_dist_version[256]; - const std::string& distro = distros[i]; + const std::string& distro = distros[i].first; WSL wsl; wsl.distro_name = distro; if (distro == default_distro) { @@ -278,6 +282,7 @@ int get_wsl_information(bool& wsl_available, WSLS& wsls) { } else { wsl.is_default = false; } + wsl.wsl_version = std::to_string(distros[i].second); // lsbrelease if (!create_wsl_process(distro, command_lsbrelease, &handle)) { @@ -344,16 +349,16 @@ int get_wsl_information(bool& wsl_available, WSLS& wsls) { } if (!os_name.empty()) { - wsl.name = os_name + " " + wsl_dist_name; + wsl.os_name = os_name + " " + wsl_dist_name; } else { - wsl.name = wsl_dist_name; + wsl.os_name = wsl_dist_name; } if (!os_version_extra.empty()) { - wsl.version = std::string(wsl_dist_version) + " [" + os_version_extra + "]"; + wsl.os_version = std::string(wsl_dist_version) + " [" + os_version_extra + "]"; } else { - wsl.version = wsl_dist_version; + wsl.os_version = wsl_dist_version; } wsls.wsls.push_back(wsl); } diff --git a/lib/wslinfo.cpp b/lib/wslinfo.cpp index 77d2c3d6e0..f39091e619 100644 --- a/lib/wslinfo.cpp +++ b/lib/wslinfo.cpp @@ -1,6 +1,6 @@ // This file is part of BOINC. -// http://boinc.berkeley.edu -// Copyright (C) 2018 University of California +// https://boinc.berkeley.edu +// Copyright (C) 2024 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License @@ -23,27 +23,30 @@ WSL::WSL() { void WSL::clear() { distro_name = ""; - name = ""; - version = ""; + os_name = ""; + os_version = ""; is_default = false; + wsl_version = "1"; } void WSL::write_xml(MIOFILE& f) { char dn[256], n[256], v[256]; xml_escape(distro_name.c_str(), dn, sizeof(dn)); - xml_escape(name.c_str(), n, sizeof(n)); - xml_escape(version.c_str(), v, sizeof(v)); + xml_escape(os_name.c_str(), n, sizeof(n)); + xml_escape(os_version.c_str(), v, sizeof(v)); f.printf( " \n" " %s\n" - " %s\n" - " %s\n" + " %s\n" + " %s\n" " %d\n" + " %s\n" " \n", dn, n, v, - is_default ? 1 : 0 + is_default ? 1 : 0, + wsl_version.c_str() ); } @@ -54,9 +57,10 @@ int WSL::parse(XML_PARSER& xp) { return 0; } if (xp.parse_string("distro_name", distro_name)) continue; - if (xp.parse_string("name", name)) continue; - if (xp.parse_string("version", version)) continue; + if (xp.parse_string("os_name", os_name)) continue; + if (xp.parse_string("os_version", os_version)) continue; if (xp.parse_bool("is_default", is_default)) continue; + if (xp.parse_string("wsl_version", wsl_version)) continue; } return ERR_XML_PARSE; } diff --git a/lib/wslinfo.h b/lib/wslinfo.h index 1076c271e2..734070c882 100644 --- a/lib/wslinfo.h +++ b/lib/wslinfo.h @@ -1,6 +1,6 @@ // This file is part of BOINC. -// http://boinc.berkeley.edu -// Copyright (C) 2018 University of California +// https://boinc.berkeley.edu +// Copyright (C) 2024 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License @@ -23,10 +23,17 @@ #include "miofile.h" #include "parse.h" +// this structure describes the information about every WSL (Windows Subsystem for Linux) installation enabled on the host struct WSL { + // unique identifier of installed WSL distribution std::string distro_name; - std::string name; - std::string version; + // name of the operating system + std::string os_name; + // version of the operating system + std::string os_version; + // version of WSL (currently 1 or 2) + std::string wsl_version; + // flag indicating whether this is the default WSL distribution bool is_default; WSL();