mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-29 01:02:44 +08:00
[fix] preserve Unicode device names, fixes #126
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
#include <Winsock2.h>
|
#include <Winsock2.h>
|
||||||
|
#include <Windows.h>
|
||||||
#include <iphlpapi.h>
|
#include <iphlpapi.h>
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
@@ -25,19 +26,38 @@ std::string GetMac() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string GetHostName() {
|
std::string GetHostName() {
|
||||||
WSADATA data = {};
|
// Read Unicode directly; Winsock's narrow hostname is not guaranteed UTF-8.
|
||||||
if (WSAStartup(MAKEWORD(2, 2), &data) != 0) {
|
DWORD size = 0;
|
||||||
LOG_ERROR("WSAStartup failed");
|
if (!GetComputerNameExW(ComputerNameDnsHostname, nullptr, &size) &&
|
||||||
|
GetLastError() != ERROR_MORE_DATA) {
|
||||||
|
LOG_ERROR("GetComputerNameExW size query failed: {}", GetLastError());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
char hostname[256] = {};
|
if (size == 0) return {};
|
||||||
if (gethostname(hostname, sizeof(hostname)) == SOCKET_ERROR) {
|
|
||||||
LOG_ERROR("gethostname failed: {}", WSAGetLastError());
|
std::wstring hostname(size, L'\0');
|
||||||
WSACleanup();
|
if (!GetComputerNameExW(ComputerNameDnsHostname, hostname.data(), &size)) {
|
||||||
|
LOG_ERROR("GetComputerNameExW failed: {}", GetLastError());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
WSACleanup();
|
if (size == 0) return {};
|
||||||
return hostname;
|
|
||||||
|
const int length = static_cast<int>(size);
|
||||||
|
const int utf8_size =
|
||||||
|
WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, hostname.data(),
|
||||||
|
length, nullptr, 0, nullptr, nullptr);
|
||||||
|
if (utf8_size == 0) {
|
||||||
|
LOG_ERROR("Hostname UTF-8 size query failed: {}", GetLastError());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::string utf8_name(utf8_size, '\0');
|
||||||
|
if (WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, hostname.data(),
|
||||||
|
length, utf8_name.data(), utf8_size, nullptr,
|
||||||
|
nullptr) == 0) {
|
||||||
|
LOG_ERROR("Hostname UTF-8 conversion failed: {}", GetLastError());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return utf8_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsWaylandSession() { return false; }
|
bool IsWaylandSession() { return false; }
|
||||||
|
|||||||
@@ -236,10 +236,10 @@ struct HostDisplay {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Builds the host_infomation message advertised on every new connection.
|
// Builds the host_infomation message advertised on every new connection.
|
||||||
// |host_name| is truncated to the wire field size. The display arrays are
|
// |host_name| is UTF-8 and truncated at a character boundary to fit the wire
|
||||||
// heap-allocated with the same layout the decoder produces; release the
|
// field size. The display arrays are heap-allocated with the same layout the
|
||||||
// result with FreeRemoteAction. An allocation failure yields an empty display
|
// decoder produces; release the result with FreeRemoteAction. An allocation
|
||||||
// list rather than a partially filled one.
|
// failure yields an empty display list rather than a partially filled one.
|
||||||
// Missing or oversized app versions are advertised as unknown (empty).
|
// Missing or oversized app versions are advertised as unknown (empty).
|
||||||
RemoteAction MakeHostInformation(const std::string& host_name,
|
RemoteAction MakeHostInformation(const std::string& host_name,
|
||||||
const std::vector<HostDisplay>& displays,
|
const std::vector<HostDisplay>& displays,
|
||||||
|
|||||||
@@ -34,6 +34,19 @@ void ResetHostInfo(HostInfo& info) {
|
|||||||
info.supports_deskhub_bandwidth = false;
|
info.supports_deskhub_bandwidth = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CopyHostName(HostInfo& info, const std::string& host_name) {
|
||||||
|
std::size_t size = std::min(
|
||||||
|
{host_name.size(), host_name.find('\0'), sizeof(info.host_name) - 1});
|
||||||
|
// Keep the fixed-size UTF-8 field from ending inside a multibyte character.
|
||||||
|
while (size > 0 && size < host_name.size() &&
|
||||||
|
(static_cast<unsigned char>(host_name[size]) & 0xC0) == 0x80) {
|
||||||
|
--size;
|
||||||
|
}
|
||||||
|
std::memcpy(info.host_name, host_name.data(), size);
|
||||||
|
info.host_name[size] = '\0';
|
||||||
|
info.host_name_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
bool AllocateHostDisplays(HostInfo& info, std::size_t count) {
|
bool AllocateHostDisplays(HostInfo& info, std::size_t count) {
|
||||||
if (count == 0) return true;
|
if (count == 0) return true;
|
||||||
|
|
||||||
@@ -104,11 +117,7 @@ RemoteAction MakeHostInformation(const std::string& host_name,
|
|||||||
|
|
||||||
action.i.supports_privacy_screen = supports_privacy_screen;
|
action.i.supports_privacy_screen = supports_privacy_screen;
|
||||||
action.i.platform = platform;
|
action.i.platform = platform;
|
||||||
const std::size_t name_size =
|
CopyHostName(action.i, host_name);
|
||||||
std::min(host_name.size(), sizeof(action.i.host_name) - 1);
|
|
||||||
std::memcpy(action.i.host_name, host_name.data(), name_size);
|
|
||||||
action.i.host_name[name_size] = '\0';
|
|
||||||
action.i.host_name_size = name_size;
|
|
||||||
// Never advertise a truncated version as a different, valid release.
|
// Never advertise a truncated version as a different, valid release.
|
||||||
if (app_version.size() < sizeof(action.i.app_version) &&
|
if (app_version.size() < sizeof(action.i.app_version) &&
|
||||||
app_version.find('\0') == std::string::npos) {
|
app_version.find('\0') == std::string::npos) {
|
||||||
@@ -462,10 +471,7 @@ bool RemoteAction::FromJson(const std::string& json_string,
|
|||||||
host_info_object.value("supports_deskhub_bandwidth", false);
|
host_info_object.value("supports_deskhub_bandwidth", false);
|
||||||
const std::string host_name =
|
const std::string host_name =
|
||||||
host_info_object.at("host_name").get<std::string>();
|
host_info_object.at("host_name").get<std::string>();
|
||||||
std::strncpy(output.i.host_name, host_name.c_str(),
|
CopyHostName(output.i, host_name);
|
||||||
sizeof(output.i.host_name) - 1);
|
|
||||||
output.i.host_name[sizeof(output.i.host_name) - 1] = '\0';
|
|
||||||
output.i.host_name_size = std::strlen(output.i.host_name);
|
|
||||||
|
|
||||||
const auto& displays = host_info_object.at("displays");
|
const auto& displays = host_info_object.at("displays");
|
||||||
if (!displays.is_array()) return false;
|
if (!displays.is_array()) return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user