From b5fa0fe08ffea2e208eb0625d85abd287265c8bb Mon Sep 17 00:00:00 2001 From: albertony <12441419+albertony@users.noreply.github.com> Date: Wed, 9 Dec 2020 23:36:34 +0100 Subject: [PATCH] Use ansi codepage for internal multibyte strings on windows (fixes #976, fixes #974, fixes #444) --- src/lib/barrier/win32/DaemonApp.cpp | 9 +++- src/lib/common/win32/DataDirectories.cpp | 28 ++-------- src/lib/common/win32/KnownFolderPaths.cpp | 48 +++++++++++++++++ src/lib/common/win32/KnownFolderPaths.h | 24 +++++++++ src/lib/common/win32/StringConverters.cpp | 66 +++++++++++++++++++++++ src/lib/common/win32/StringConverters.h | 25 +++++++++ src/lib/platform/MSWindowsScreen.cpp | 12 ++--- 7 files changed, 179 insertions(+), 33 deletions(-) create mode 100644 src/lib/common/win32/KnownFolderPaths.cpp create mode 100644 src/lib/common/win32/KnownFolderPaths.h create mode 100644 src/lib/common/win32/StringConverters.cpp create mode 100644 src/lib/common/win32/StringConverters.h diff --git a/src/lib/barrier/win32/DaemonApp.cpp b/src/lib/barrier/win32/DaemonApp.cpp index 88e6b4ef0af..472be156d13 100644 --- a/src/lib/barrier/win32/DaemonApp.cpp +++ b/src/lib/barrier/win32/DaemonApp.cpp @@ -34,6 +34,7 @@ #include "base/log_outputters.h" #include "base/Log.h" #include "common/DataDirectories.h" +#include "common/win32/StringConverters.h" #include "arch/win32/ArchMiscWindows.h" #include "arch/win32/XArchWindows.h" @@ -250,6 +251,12 @@ DaemonApp::logFilename() return logFilename; } +static std::string from_ipc_string(const std::string& msg) +{ + // Client sends UTF-8 encoded narrow strings (QString::toStdString()), convert to ANSI encoding used + return ansi_from_utf8(msg); +} + void DaemonApp::handleIpcMessage(const Event& e, void*) { @@ -257,7 +264,7 @@ DaemonApp::handleIpcMessage(const Event& e, void*) switch (m->type()) { case kIpcCommand: { IpcCommandMessage* cm = static_cast(m); - String command = cm->command(); + String command = from_ipc_string(cm->command()); // if empty quotes, clear. if (command == "\"\"") { diff --git a/src/lib/common/win32/DataDirectories.cpp b/src/lib/common/win32/DataDirectories.cpp index 15cb64e1377..3e86c59b8e8 100644 --- a/src/lib/common/win32/DataDirectories.cpp +++ b/src/lib/common/win32/DataDirectories.cpp @@ -16,34 +16,12 @@ */ #include "../DataDirectories.h" - -#include - -std::string unicode_to_mb(const WCHAR* utfStr) -{ - int utfLength = lstrlenW(utfStr); - int mbLength = WideCharToMultiByte(CP_UTF8, 0, utfStr, utfLength, NULL, 0, NULL, NULL); - std::string mbStr(mbLength, 0); - WideCharToMultiByte(CP_UTF8, 0, utfStr, utfLength, &mbStr[0], mbLength, NULL, NULL); - return mbStr; -} - -std::string known_folder_path(const KNOWNFOLDERID& id) -{ - std::string path; - WCHAR* buffer; - HRESULT result = SHGetKnownFolderPath(id, 0, NULL, &buffer); - if (result == S_OK) { - path = unicode_to_mb(buffer); - CoTaskMemFree(buffer); - } - return path; -} +#include "KnownFolderPaths.h" const std::string& DataDirectories::profile() { if (_profile.empty()) - _profile = known_folder_path(FOLDERID_LocalAppData) + "\\Barrier"; + _profile = localAppDataPath() + "\\Barrier"; return _profile; } const std::string& DataDirectories::profile(const std::string& path) @@ -55,7 +33,7 @@ const std::string& DataDirectories::profile(const std::string& path) const std::string& DataDirectories::global() { if (_global.empty()) - _global = known_folder_path(FOLDERID_ProgramData) + "\\Barrier"; + _global = programDataPath() + "\\Barrier"; return _global; } const std::string& DataDirectories::global(const std::string& path) diff --git a/src/lib/common/win32/KnownFolderPaths.cpp b/src/lib/common/win32/KnownFolderPaths.cpp new file mode 100644 index 00000000000..9f873f66bec --- /dev/null +++ b/src/lib/common/win32/KnownFolderPaths.cpp @@ -0,0 +1,48 @@ +/* +* barrier -- mouse and keyboard sharing utility +* Copyright (C) 2018 Debauchee Open Source Group +* +* This package is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* found in the file LICENSE that should have accompanied this file. +* +* This package is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#include "KnownFolderPaths.h" +#include "StringConverters.h" + +#include + +static std::string known_folder_path(const KNOWNFOLDERID& id) +{ + std::string path; + WCHAR* buffer; + HRESULT result = SHGetKnownFolderPath(id, 0, NULL, &buffer); + if (result == S_OK) { + path = ansi_from_wide(buffer); + CoTaskMemFree(buffer); + } + return path; +} + +std::string desktopPath() +{ + return known_folder_path(FOLDERID_Desktop); +} + +std::string localAppDataPath() +{ + return known_folder_path(FOLDERID_LocalAppData); +} + +std::string programDataPath() +{ + return known_folder_path(FOLDERID_ProgramData); +} diff --git a/src/lib/common/win32/KnownFolderPaths.h b/src/lib/common/win32/KnownFolderPaths.h new file mode 100644 index 00000000000..81b650ec57c --- /dev/null +++ b/src/lib/common/win32/KnownFolderPaths.h @@ -0,0 +1,24 @@ +/* +* barrier -- mouse and keyboard sharing utility +* Copyright (C) 2018 Debauchee Open Source Group +* +* This package is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* found in the file LICENSE that should have accompanied this file. +* +* This package is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#pragma once + +#include + +std::string desktopPath(); +std::string localAppDataPath(); +std::string programDataPath(); diff --git a/src/lib/common/win32/StringConverters.cpp b/src/lib/common/win32/StringConverters.cpp new file mode 100644 index 00000000000..81510d4cb1b --- /dev/null +++ b/src/lib/common/win32/StringConverters.cpp @@ -0,0 +1,66 @@ +/* +* barrier -- mouse and keyboard sharing utility +* Copyright (C) 2018 Debauchee Open Source Group +* +* This package is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* found in the file LICENSE that should have accompanied this file. +* +* This package is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#include "StringConverters.h" + +#define WIN32_LEAN_AND_MEAN +#include + +std::string ansi_from_wide(const wchar_t* wideString) +{ + int wideLength = lstrlenW(wideString); + int ansiLength = WideCharToMultiByte(CP_ACP, 0, wideString, wideLength, NULL, 0, NULL, NULL); + if (ansiLength > 0) { + std::string ansiString(ansiLength, 0); + ansiLength = WideCharToMultiByte(CP_ACP, 0, wideString, wideLength, &ansiString[0], ansiLength, NULL, NULL); + if (ansiLength > 0) { + return ansiString; + } + } + return {}; +} + +std::string ansi_from_wide(const std::wstring& wideString) +{ + int ansiLength = WideCharToMultiByte(CP_ACP, 0, wideString.c_str(), (int)wideString.length(), NULL, 0, NULL, NULL); + if (ansiLength > 0) { + std::string ansiString(ansiLength, 0); + ansiLength = WideCharToMultiByte(CP_ACP, 0, wideString.c_str(), (int)wideString.length(), &ansiString[0], (int)ansiString.length(), NULL, NULL); + if (ansiLength > 0) { + return ansiString; + } + } + return {}; +} + +std::wstring wide_from_utf8(const std::string& utf8String) +{ + int wideLength = MultiByteToWideChar(CP_UTF8, 0, utf8String.c_str(), (int)utf8String.length(), NULL, 0); + if (wideLength > 0) { + std::wstring wideString(wideLength, 0); + wideLength = MultiByteToWideChar(CP_UTF8, 0, utf8String.c_str(), (int)utf8String.length(), &wideString[0], wideLength); + if (wideLength > 0) { + return wideString; + } + } + return {}; +} + +std::string ansi_from_utf8(const std::string& utf8String) +{ + return ansi_from_wide(wide_from_utf8(utf8String)); +} diff --git a/src/lib/common/win32/StringConverters.h b/src/lib/common/win32/StringConverters.h new file mode 100644 index 00000000000..bec785bd8ee --- /dev/null +++ b/src/lib/common/win32/StringConverters.h @@ -0,0 +1,25 @@ +/* +* barrier -- mouse and keyboard sharing utility +* Copyright (C) 2018 Debauchee Open Source Group +* +* This package is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* found in the file LICENSE that should have accompanied this file. +* +* This package is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#pragma once + +#include + +std::string ansi_from_wide(const wchar_t* wideString); +std::string ansi_from_wide(const std::wstring& wideString); +std::wstring wide_from_utf8(const std::string& utf8String); +std::string ansi_from_utf8(const std::string& utf8String); diff --git a/src/lib/platform/MSWindowsScreen.cpp b/src/lib/platform/MSWindowsScreen.cpp index fd494c9878b..352368acc60 100644 --- a/src/lib/platform/MSWindowsScreen.cpp +++ b/src/lib/platform/MSWindowsScreen.cpp @@ -41,9 +41,9 @@ #include "base/IEventQueue.h" #include "base/TMethodEventJob.h" #include "base/TMethodJob.h" +#include "common/win32/KnownFolderPaths.h" #include -#include #include #include @@ -1916,14 +1916,12 @@ const std::string& MSWindowsScreen::getDropTarget() const { if (m_dropTargetPath.empty()) { - // SHGetFolderPath is deprecated in vista, but use it for xp support. - char desktopPath[MAX_PATH]; - if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, 0, desktopPath))) { - m_dropTargetPath = std::string(desktopPath); - LOG((CLOG_INFO "using desktop for drop target: %s", m_dropTargetPath.c_str())); + m_dropTargetPath = desktopPath(); + if (!m_dropTargetPath.empty()) { + LOG((CLOG_DEBUG "using desktop for drop target: %s", m_dropTargetPath.c_str())); } else { - LOG((CLOG_ERR "failed to get desktop path, no drop target available, error=%d", GetLastError())); + LOG((CLOG_ERR "failed to get desktop path, no drop target available")); } } return m_dropTargetPath;