Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move WSL code to lib/ so we can use it in wrapper #5776

Merged
merged 6 commits into from
Aug 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion client/hostinfo_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1669,9 +1669,14 @@ int HOST_INFO::get_host_info(bool init) {
if (!cc_config.dont_use_wsl) {
OSVERSIONINFOEX osvi;
if (get_OSVERSIONINFO(osvi) && osvi.dwMajorVersion >= 10) {
get_wsl_information(
retval = get_wsl_information(
cc_config.allowed_wsls, wsl_distros, !cc_config.dont_use_docker
);
if (retval) {
msg_printf(0, MSG_INTERNAL_ERROR,
"get_wsl_information(): %s", boincerror(retval)
);
}
}
}
#endif
Expand Down
236 changes: 52 additions & 184 deletions client/hostinfo_wsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,18 @@
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.

#ifdef _WIN64

using std::vector;
using std::string;

#include "boinc_win.h"
#include "win_util.h"

#include "str_replace.h"
#include "client_msgs.h"
#include "hostinfo.h"

// scan the registry to get the list of all distros on this host.
// scan the registry to get the list of all WSL distros on this host.
// See https://patrickwu.space/2020/07/19/wsl-related-registry/
// Return nonzero on error
//
int get_all_distros(WSL_DISTROS& distros) {
const std::string lxss_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Lxss";
Expand Down Expand Up @@ -117,145 +115,6 @@ int get_all_distros(WSL_DISTROS& distros) {
return 0;
}

// we run WSL commands by calling a DLL function,
// and communicating with it through two pipes

typedef HRESULT(WINAPI *PWslLaunch)(PCWSTR, PCWSTR, BOOL, HANDLE, HANDLE, HANDLE, HANDLE*);

// handles for running a WSL command
//
struct WSL_CMD {
HINSTANCE wsl_lib = NULL;
HANDLE in_read = NULL;
HANDLE in_write = NULL;
HANDLE out_read = NULL;
HANDLE out_write = NULL;
PWslLaunch pWslLaunch = NULL;

~WSL_CMD() {
close_handle(in_read);
close_handle(in_write);
close_handle(out_read);
close_handle(out_write);

if (wsl_lib) {
FreeLibrary(wsl_lib);
}
}

int prepare_cmd() {
wsl_lib = NULL;
in_read = NULL;
in_write = NULL;
out_read = NULL;
out_write = NULL;
pWslLaunch = NULL;

wsl_lib = LoadLibrary("wslapi.dll");
if (!wsl_lib) {
return 1;
}

pWslLaunch = (PWslLaunch)GetProcAddress(wsl_lib, "WslLaunch");

if (!pWslLaunch) {
return 1;
}

SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;

if (!CreatePipe(&out_read, &out_write, &sa, 0)) {
return 1;
}
if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) {
return 1;
}
if (!CreatePipe(&in_read, &in_write, &sa, 0)) {
return 1;
}
if (!SetHandleInformation(in_write, HANDLE_FLAG_INHERIT, 0)) {
return 1;
}

return 0;
}

private:
inline void close_handle(HANDLE handle) {
if (handle) {
CloseHandle(handle);
}
}
};

// convert std::string to PCWSTR
// taken from https://stackoverflow.com/questions/27220/how-to-convert-stdstring-to-lpcwstr-in-c-unicode
//
std::wstring s2ws(const std::string& s) {
const int slength = (int)s.length() + 1;
const int len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}

// run a (Linux) command in the given distro,
// using the given pipes.
// Return S_OK on success
//
bool create_wsl_process(
const WSL_CMD& rs, const std::string& wsl_distro_name,
const std::string& command, HANDLE* handle,
bool use_current_work_dir = false
) {
HRESULT ret = rs.pWslLaunch(
s2ws(wsl_distro_name).c_str(), s2ws(command).c_str(),
use_current_work_dir, rs.in_read, rs.out_write, rs.out_write,
handle
);
return (ret == S_OK);
}

#if 0
bool CreateWslProcess(
const HANDLE& out_write, const std::string& wsl_app,
const std::string& command, HANDLE& handle
) {
PROCESS_INFORMATION pi;
STARTUPINFO si;

ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si, sizeof(STARTUPINFO));

si.cb = sizeof(STARTUPINFO);
si.hStdError = out_write;
si.hStdOutput = out_write;
si.hStdInput = NULL;
si.dwFlags |= STARTF_USESTDHANDLES;

const DWORD dwFlags = CREATE_NO_WINDOW;

const std::string cmd = wsl_app + " " + command;

const bool res = (CreateProcess(
NULL, (LPSTR)cmd.c_str(), NULL, NULL, TRUE, dwFlags,
NULL, NULL, &si, &pi
) != FALSE);

if (res) {
handle = pi.hProcess;
CloseHandle(pi.hThread);
}

return res;
}
#endif

// read from the given pipe until the given process exits;
// return the result
//
Expand Down Expand Up @@ -314,7 +173,9 @@ void parse_sysctl_output(

// if either name or version is not already there, add
//
static void update_os(WSL_DISTRO &wd, const char* os_name, const char* os_version) {
static void update_os(
WSL_DISTRO &wd, const char* os_name, const char* os_version
) {
if (wd.os_name.empty() && strlen(os_name)) {
wd.os_name = os_name;
}
Expand All @@ -323,7 +184,7 @@ static void update_os(WSL_DISTRO &wd, const char* os_name, const char* os_versio
}
}

// have both name and version?
// have both OS name and version?
//
static bool got_both(WSL_DISTRO &wd) {
return !wd.os_name.empty() && !wd.os_version.empty();
Expand All @@ -346,7 +207,7 @@ int get_wsl_information(

WSL_CMD rs;

if (rs.prepare_cmd()) {
if (rs.setup()) {
return -1;
}

Expand Down Expand Up @@ -378,48 +239,51 @@ int get_wsl_information(

// try running 'lsbrelease -a'
//
if (!create_wsl_process(rs, wd.distro_name, command_lsbrelease, &proc_handle)) {
continue;
if (!rs.run_command(
wd.distro_name, command_lsbrelease, &proc_handle
)) {
HOST_INFO::parse_linux_os_info(
read_from_pipe(proc_handle, rs.out_read), lsbrelease,
os_name, sizeof(os_name),
os_version, sizeof(os_version)
);
CloseHandle(proc_handle);
update_os(wd, os_name, os_version);
}
HOST_INFO::parse_linux_os_info(
read_from_pipe(proc_handle, rs.out_read), lsbrelease,
os_name, sizeof(os_name),
os_version, sizeof(os_version)
);
CloseHandle(proc_handle);
update_os(wd, os_name, os_version);

// try reading '/etc/os-relese'
//
if (!got_both(wd)) {
const std::string command_osrelease = "cat " + std::string(file_osrelease);
if (!create_wsl_process(rs, wd.distro_name, command_osrelease, &proc_handle)) {
continue;
if (!rs.run_command(
wd.distro_name, command_osrelease, &proc_handle
)) {
HOST_INFO::parse_linux_os_info(
read_from_pipe(proc_handle, rs.out_read),
osrelease,
os_name, sizeof(os_name),
os_version, sizeof(os_version)
);
CloseHandle(proc_handle);
update_os(wd, os_name, os_version);
}
HOST_INFO::parse_linux_os_info(
read_from_pipe(proc_handle, rs.out_read),
osrelease,
os_name, sizeof(os_name),
os_version, sizeof(os_version)
);
CloseHandle(proc_handle);
update_os(wd, os_name, os_version);
}

// try reading '/etc/redhatrelease'
//
if (!got_both(wd)) {
const std::string command_redhatrelease = "cat " + std::string(file_redhatrelease);
if (!create_wsl_process(rs, wd.distro_name, command_redhatrelease, &proc_handle)) {
continue;
if (!rs.run_command(
wd.distro_name, command_redhatrelease, &proc_handle
)) {
HOST_INFO::parse_linux_os_info(
read_from_pipe(proc_handle, rs.out_read),
redhatrelease, os_name, sizeof(os_name),
os_version, sizeof(os_version)
);
CloseHandle(proc_handle);
update_os(wd, os_name, os_version);
}
HOST_INFO::parse_linux_os_info(
read_from_pipe(proc_handle, rs.out_read),
redhatrelease, os_name, sizeof(os_name),
os_version, sizeof(os_version)
);
CloseHandle(proc_handle);
update_os(wd, os_name, os_version);
}

std::string os_name_str = "";
Expand All @@ -429,21 +293,25 @@ int get_wsl_information(
//
if (!got_both(wd)) {
const std::string command_sysctl = "sysctl -a";
if (create_wsl_process(rs, wd.distro_name, command_sysctl, &proc_handle)) {
if (!rs.run_command(
wd.distro_name, command_sysctl, &proc_handle
)) {
parse_sysctl_output(
split(read_from_pipe(proc_handle, rs.out_read), '\n'),
os_name_str, os_version_str
);
CloseHandle(proc_handle);
update_os(wd, os_name_str.c_str(), os_version_str.c_str());
}
update_os(wd, os_name_str.c_str(), os_version_str.c_str());
}

// try running 'uname -s'
//
if (!got_both(wd)) {
const std::string command_uname_s = "uname -s";
if (create_wsl_process(rs, wd.distro_name, command_uname_s, &proc_handle)) {
if (!rs.run_command(
wd.distro_name, command_uname_s, &proc_handle
)) {
os_name_str = read_from_pipe(proc_handle, rs.out_read);
strip_whitespace(os_name_str);
CloseHandle(proc_handle);
Expand All @@ -455,7 +323,9 @@ int get_wsl_information(
//
if (!got_both(wd)) {
const std::string command_uname_r = "uname -r";
if (create_wsl_process(rs, wd.distro_name, command_uname_r ,&proc_handle)) {
if (!rs.run_command(
wd.distro_name, command_uname_r ,&proc_handle
)) {
os_version_str = read_from_pipe(proc_handle, rs.out_read);
strip_whitespace(os_version_str);
CloseHandle(proc_handle);
Expand All @@ -469,8 +339,8 @@ int get_wsl_information(
// see if Docker is installed in the distro
//
if (detect_docker) {
if (create_wsl_process(
rs, wd.distro_name, command_get_docker_version, &proc_handle
if (!rs.run_command(
wd.distro_name, command_get_docker_version, &proc_handle
)) {
std::string raw = read_from_pipe(proc_handle, rs.out_read);
std::string version;
Expand All @@ -480,8 +350,8 @@ int get_wsl_information(
}
CloseHandle(proc_handle);
}
if (create_wsl_process(
rs, wd.distro_name, command_get_docker_compose_version, &proc_handle
if (!rs.run_command(
wd.distro_name, command_get_docker_compose_version, &proc_handle
)) {
std::string raw = read_from_pipe(proc_handle, rs.out_read);
std::string version;
Expand All @@ -498,5 +368,3 @@ int get_wsl_information(

return 0;
}

#endif // _WIN64
1 change: 0 additions & 1 deletion lib/sched_msgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class SCHED_MSG_LOG : public MSG_LOG {
const char* v_format_kind(int kind) const;
bool v_message_wanted(int kind) const;
public:
enum { MSG_CRITICAL=1, MSG_WARNING, MSG_NORMAL, MSG_DEBUG, MSG_DETAIL };
SCHED_MSG_LOG(): MSG_LOG(stderr) { debug_level = MSG_NORMAL; }
void set_file(FILE* f) {output=f;}
void set_debug_level(int new_level) { debug_level = new_level; }
Expand Down
Loading
Loading