From c4c2f7f37fda560bce907951b3c813baa2c48cb2 Mon Sep 17 00:00:00 2001 From: sithlord48 Date: Fri, 30 May 2025 18:26:02 -0400 Subject: [PATCH] feat: begin to use QStrings for strings feat: get windows building with the UNICODE forced by using Qt refactor: remove ARCHString use QString to convert to / from utf8 build: (arch) link to common build: (base) link to arch build: (io) Link to common build: (client) link to common build: (server) link to common fix: Append to log file instead of creating a new one each log line refactor: Trim cipher description for neater log output fix: Update log messages to use wide string format for Unicode support fix: Correct event creation to use wide string for Unicode compatibility refactor: Use QStringDecoder for UTF-8 handling on Windows Daemon child process fix: Use correct wide type for Win32 consts --- cspell.json | 1 + src/lib/arch/Arch.h | 3 +- src/lib/arch/ArchDaemonNone.cpp | 11 +- src/lib/arch/ArchDaemonNone.h | 4 +- src/lib/arch/ArchString.cpp | 163 ------------------ src/lib/arch/ArchString.h | 56 ------ src/lib/arch/CMakeLists.txt | 6 +- src/lib/arch/IArchDaemon.h | 6 +- src/lib/arch/IArchLog.h | 7 +- src/lib/arch/unix/ArchDaemonUnix.cpp | 15 +- src/lib/arch/unix/ArchDaemonUnix.h | 2 +- src/lib/arch/unix/ArchLogUnix.cpp | 10 +- src/lib/arch/unix/ArchLogUnix.h | 4 +- src/lib/arch/win32/ArchDaemonWindows.cpp | 48 +++--- src/lib/arch/win32/ArchDaemonWindows.h | 13 +- src/lib/arch/win32/ArchLogWindows.cpp | 12 +- src/lib/arch/win32/ArchLogWindows.h | 4 +- src/lib/arch/win32/ArchMiscWindows.cpp | 28 +-- src/lib/arch/win32/ArchMiscWindows.h | 8 +- src/lib/arch/win32/ArchNetworkWinsock.cpp | 2 +- src/lib/base/CMakeLists.txt | 2 +- src/lib/base/ILogOutputter.h | 4 +- src/lib/base/LogOutputters.cpp | 59 +++---- src/lib/base/LogOutputters.h | 25 +-- src/lib/base/Unicode.cpp | 107 ------------ src/lib/base/Unicode.h | 33 +--- src/lib/client/CMakeLists.txt | 4 +- src/lib/common/Constants.h.in | 10 +- src/lib/deskflow/unix/DeskflowXkbKeyboard.cpp | 4 +- src/lib/deskflow/win32/AppUtilWindows.cpp | 2 +- src/lib/gui/core/CommandProcess.cpp | 2 +- src/lib/io/CMakeLists.txt | 2 + src/lib/net/SslLogger.cpp | 2 +- .../MSWindowsClipboardHTMLConverter.cpp | 2 +- .../MSWindowsClipboardTextConverter.cpp | 15 +- src/lib/platform/MSWindowsDebugOutputter.cpp | 10 +- src/lib/platform/MSWindowsDebugOutputter.h | 4 +- src/lib/platform/MSWindowsDesks.cpp | 24 +-- src/lib/platform/MSWindowsDesks.h | 12 +- .../platform/MSWindowsEventQueueBuffer.cpp | 2 +- src/lib/platform/MSWindowsKeyState.cpp | 4 +- src/lib/platform/MSWindowsProcess.cpp | 21 +-- src/lib/platform/MSWindowsProcess.h | 10 +- src/lib/platform/MSWindowsScreen.cpp | 6 +- src/lib/platform/MSWindowsScreen.h | 2 +- src/lib/platform/MSWindowsScreenSaver.cpp | 16 +- src/lib/platform/MSWindowsSession.cpp | 12 +- src/lib/platform/MSWindowsSession.h | 4 +- src/lib/platform/MSWindowsWatchdog.cpp | 101 +++++------ src/lib/platform/MSWindowsWatchdog.h | 4 +- src/lib/platform/XWindowsClipboard.h | 2 + .../XWindowsClipboardTextConverter.cpp | 18 +- src/lib/platform/XWindowsScreen.h | 2 + src/lib/platform/XWindowsScreenSaver.cpp | 3 +- src/lib/platform/XWindowsUtil.cpp | 4 +- src/lib/server/CMakeLists.txt | 4 +- src/unittests/CMakeLists.txt | 1 - src/unittests/arch/ArchStringTests.cpp | 58 ------- src/unittests/arch/ArchStringTests.h | 24 --- src/unittests/arch/CMakeLists.txt | 14 -- src/unittests/base/LogTests.h | 4 +- src/unittests/base/UnicodeTests.cpp | 27 --- src/unittests/base/UnicodeTests.h | 2 - 63 files changed, 290 insertions(+), 781 deletions(-) delete mode 100644 src/lib/arch/ArchString.cpp delete mode 100644 src/lib/arch/ArchString.h delete mode 100644 src/unittests/arch/ArchStringTests.cpp delete mode 100644 src/unittests/arch/ArchStringTests.h delete mode 100644 src/unittests/arch/CMakeLists.txt diff --git a/cspell.json b/cspell.json index 771760ad6..c5901b8c1 100644 --- a/cspell.json +++ b/cspell.json @@ -46,6 +46,7 @@ "logonui", "Lysytsia", "macdeployqt", + "mojibake", "msvc", "noquote", "NOSONAR", diff --git a/src/lib/arch/Arch.h b/src/lib/arch/Arch.h index e888d98e4..bd014cf92 100644 --- a/src/lib/arch/Arch.h +++ b/src/lib/arch/Arch.h @@ -25,7 +25,6 @@ #pragma once -#include "arch/ArchString.h" #include "common/Common.h" #if SYSAPI_WIN32 @@ -60,7 +59,7 @@ to each method to those implementations. Clients should use the exactly one of these objects before attempting to call any method, typically at the beginning of \c main(). */ -class Arch : public ARCH_DAEMON, public ARCH_LOG, public ARCH_MULTITHREAD, public ARCH_NETWORK, public ArchString +class Arch : public ARCH_DAEMON, public ARCH_LOG, public ARCH_MULTITHREAD, public ARCH_NETWORK { public: Arch(); diff --git a/src/lib/arch/ArchDaemonNone.cpp b/src/lib/arch/ArchDaemonNone.cpp index c4c293a21..cf0f0c628 100644 --- a/src/lib/arch/ArchDaemonNone.cpp +++ b/src/lib/arch/ArchDaemonNone.cpp @@ -6,19 +6,22 @@ */ #include "arch/ArchDaemonNone.h" +#include // // ArchDaemonNone // -int ArchDaemonNone::daemonize(const char *name, DaemonFunc const &func) +int ArchDaemonNone::daemonize(const QString &name, DaemonFunc const &func) { // simply forward the call to func. obviously, this doesn't // do any daemonizing. - return func(1, &name); + auto t = name.toStdString(); + const char *n = t.c_str(); + return func(1, &n); } -std::string ArchDaemonNone::commandLine() const +QString ArchDaemonNone::commandLine() const { - return ""; + return {}; } diff --git a/src/lib/arch/ArchDaemonNone.h b/src/lib/arch/ArchDaemonNone.h index d6546bdfc..db3674b88 100644 --- a/src/lib/arch/ArchDaemonNone.h +++ b/src/lib/arch/ArchDaemonNone.h @@ -24,6 +24,6 @@ public: ~ArchDaemonNone() override = default; // IArchDaemon overrides - int daemonize(const char *name, DaemonFunc const &func) override; - std::string commandLine() const override; + int daemonize(const QString &name, DaemonFunc const &func) override; + QString commandLine() const override; }; diff --git a/src/lib/arch/ArchString.cpp b/src/lib/arch/ArchString.cpp deleted file mode 100644 index 8487ce8f6..000000000 --- a/src/lib/arch/ArchString.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. - * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman - * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception - */ - -#include "arch/ArchString.h" -#include "common/Common.h" - -#include -#include -#include - -static std::mutex s_mutex; - -// -// use C library non-reentrant multibyte conversion with mutex -// - -int ArchString::convStringWCToMB(char *dst, const wchar_t *src, uint32_t n, bool *errors) const -{ - std::scoped_lock lock{s_mutex}; - ptrdiff_t len = 0; - - bool dummyErrors; - if (errors == nullptr) { - errors = &dummyErrors; - } - *errors = false; - - if (dst == nullptr) { - char dummy[MB_LEN_MAX]; - const wchar_t *scan = src; - for (; n > 0; --n) { - ptrdiff_t mblen = wctomb(dummy, *scan); - if (mblen == -1) { - *errors = true; - mblen = 1; - } - len += mblen; - ++scan; - } - if (ptrdiff_t mblen = wctomb(dummy, L'\0'); mblen != -1) { - len += mblen - 1; - } - } else { - const char *dst0 = dst; - const wchar_t *scan = src; - for (; n > 0; --n) { - if (ptrdiff_t mblen = wctomb(dst, *scan); mblen == -1) { - *errors = true; - *dst++ = '?'; - } else { - dst += mblen; - } - ++scan; - } - if (ptrdiff_t mblen = wctomb(dst, L'\0'); mblen != -1) { - // don't include nul terminator - dst += mblen - 1; - } - len = dst - dst0; - } - - return static_cast(len); -} - -ArchString::EWideCharEncoding ArchString::getWideCharEncoding() const -{ -#ifdef SYSAPI_WIN32 - return EWideCharEncoding::kUTF16; -#else - return EWideCharEncoding::kUCS4; -#endif -} - -int ArchString::convStringMBToWC(wchar_t *dst, const char *src, uint32_t n, bool *errors) const -{ - std::scoped_lock lock{s_mutex}; - ptrdiff_t len = 0; - wchar_t dummy; - - bool dummyErrors; - if (errors == nullptr) { - errors = &dummyErrors; - } - *errors = false; - - if (dst == nullptr) { - const char *scan = src; - while (n > 0) { - switch (ptrdiff_t mblen = mbtowc(&dummy, scan, n); mblen) { - case -2: - // incomplete last character. convert to unknown character. - *errors = true; - len += 1; - n = 0; - break; - - case -1: - // invalid character. count one unknown character and - // start at the next byte. - *errors = true; - len += 1; - scan += 1; - n -= 1; - break; - - case 0: - len += 1; - scan += 1; - n -= 1; - break; - - default: - // normal character - len += 1; - scan += static_cast(mblen); - n -= static_cast(mblen); - break; - } - } - } else { - const wchar_t *dst0 = dst; - const char *scan = src; - while (n > 0) { - switch (ptrdiff_t mblen = mbtowc(dst, scan, n); mblen) { - case -2: - // incomplete character. convert to unknown character. - *errors = true; - *dst = (wchar_t)0xfffd; - n = 0; - break; - - case -1: - // invalid character. count one unknown character and - // start at the next byte. - *errors = true; - *dst = (wchar_t)0xfffd; - scan += 1; - n -= 1; - break; - - case 0: - *dst = (wchar_t)0x0000; - scan += 1; - n -= 1; - break; - - default: - // normal character - scan += static_cast(mblen); - n -= static_cast(mblen); - break; - } - ++dst; - } - len = dst - dst0; - } - - return static_cast(len); -} diff --git a/src/lib/arch/ArchString.h b/src/lib/arch/ArchString.h deleted file mode 100644 index 55fe7f8a0..000000000 --- a/src/lib/arch/ArchString.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers - * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. - * SPDX-FileCopyrightText: (C) 2002 Chris Schoeneman - * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception - */ - -#pragma once - -#include -#include - -//! Interface for architecture dependent string operations -/*! -This interface defines the string operations required by -deskflow. Each architecture must implement this interface. -*/ -class ArchString -{ -public: - ArchString() = default; - ArchString(const ArchString &) = delete; - ArchString(ArchString &&) = delete; - virtual ~ArchString() = default; - - ArchString &operator=(const ArchString &) = delete; - ArchString &operator=(ArchString &&) = delete; - - //! Wide character encodings - /*! - The known wide character encodings - */ - enum class EWideCharEncoding : uint8_t - { - kUCS2, //!< The UCS-2 encoding - kUCS4, //!< The UCS-4 encoding - kUTF16, //!< The UTF-16 encoding - kUTF32, //!< The UTF-32 encoding - kPlatformDetermined - }; - - //! @name manipulators - //@{ - - //! Convert multibyte string to wide character string - int convStringMBToWC(wchar_t *, const char *, uint32_t n, bool *errors) const; - - //! Convert wide character string to multibyte string - int convStringWCToMB(char *, const wchar_t *, uint32_t n, bool *errors) const; - - //! Return the architecture's native wide character encoding - EWideCharEncoding getWideCharEncoding() const; - - //@} -}; diff --git a/src/lib/arch/CMakeLists.txt b/src/lib/arch/CMakeLists.txt index 251db4126..5f8cf3ee4 100644 --- a/src/lib/arch/CMakeLists.txt +++ b/src/lib/arch/CMakeLists.txt @@ -45,10 +45,10 @@ add_library(arch STATIC ${PLATFORM_CODE} IArchLog.h IArchMultithread.h IArchNetwork.h - ArchString.cpp - ArchString.h ) +target_link_libraries (arch PUBLIC common) + if(UNIX) - target_link_libraries(arch ${libs}) + target_link_libraries(arch PUBLIC ${libs}) endif() diff --git a/src/lib/arch/IArchDaemon.h b/src/lib/arch/IArchDaemon.h index 3a2e76441..761479cb9 100644 --- a/src/lib/arch/IArchDaemon.h +++ b/src/lib/arch/IArchDaemon.h @@ -8,8 +8,8 @@ #pragma once +#include #include -#include //! Interface for architecture dependent daemonizing /*! @@ -53,7 +53,7 @@ public: \c ArchMiscWindows::daemonFailed() to indicate startup failure. */ - virtual int daemonize(const char *name, DaemonFunc const &func) = 0; + virtual int daemonize(const QString &name, DaemonFunc const &func) = 0; //@} @@ -61,7 +61,7 @@ public: /*! Gets the command line with which the application was started. */ - virtual std::string commandLine() const = 0; + virtual QString commandLine() const = 0; //@} }; diff --git a/src/lib/arch/IArchLog.h b/src/lib/arch/IArchLog.h index f14119a07..1ed0b8c43 100644 --- a/src/lib/arch/IArchLog.h +++ b/src/lib/arch/IArchLog.h @@ -8,6 +8,8 @@ #pragma once +#include + #include "base/LogLevel.h" //! Interface for architecture dependent logging @@ -27,7 +29,7 @@ public: Opens the log for writing. The log must be opened before being written to. */ - virtual void openLog(const char *name) = 0; + virtual void openLog(const QString &name) = 0; //! Close the log /*! @@ -48,7 +50,6 @@ public: /*! Writes the given string to the log with the given level. */ - virtual void writeLog(LogLevel, const char *) = 0; - + virtual void writeLog(LogLevel, const QString &) = 0; //@} }; diff --git a/src/lib/arch/unix/ArchDaemonUnix.cpp b/src/lib/arch/unix/ArchDaemonUnix.cpp index 2947f40db..2ff746437 100644 --- a/src/lib/arch/unix/ArchDaemonUnix.cpp +++ b/src/lib/arch/unix/ArchDaemonUnix.cpp @@ -19,6 +19,7 @@ #include #include +#include // // ArchDaemonUnix // @@ -46,11 +47,14 @@ bool alreadyDaemonized() #endif -int ArchDaemonUnix::daemonize(const char *name, DaemonFunc const &func) +int ArchDaemonUnix::daemonize(const QString &name, DaemonFunc const &func) { #ifdef __APPLE__ - if (alreadyDaemonized()) - return func(1, &name); + if (alreadyDaemonized()) { + auto t = name.toStdString(); + const char *n = t.c_str(); + return func(1, &n); + } #endif // fork so shell thinks we're done and so we're not a process @@ -104,5 +108,8 @@ int ArchDaemonUnix::daemonize(const char *name, DaemonFunc const &func) #endif // invoke function - return func(1, &name); + + auto t = name.toStdString(); + const char *n = t.c_str(); + return func(1, &n); } diff --git a/src/lib/arch/unix/ArchDaemonUnix.h b/src/lib/arch/unix/ArchDaemonUnix.h index 5384937ff..280154397 100644 --- a/src/lib/arch/unix/ArchDaemonUnix.h +++ b/src/lib/arch/unix/ArchDaemonUnix.h @@ -20,5 +20,5 @@ public: ~ArchDaemonUnix() override = default; // IArchDaemon overrides - int daemonize(const char *name, DaemonFunc const &func) override; + int daemonize(const QString &name, DaemonFunc const &func) override; }; diff --git a/src/lib/arch/unix/ArchLogUnix.cpp b/src/lib/arch/unix/ArchLogUnix.cpp index dc8f81db4..1bab435df 100644 --- a/src/lib/arch/unix/ArchLogUnix.cpp +++ b/src/lib/arch/unix/ArchLogUnix.cpp @@ -7,15 +7,15 @@ #include "arch/unix/ArchLogUnix.h" +#include #include - // // ArchLogUnix // -void ArchLogUnix::openLog(const char *name) +void ArchLogUnix::openLog(const QString &name) { - openlog(name, 0, LOG_DAEMON); + openlog(qPrintable(name), 0, LOG_DAEMON); } void ArchLogUnix::closeLog() @@ -28,7 +28,7 @@ void ArchLogUnix::showLog(bool) // do nothing } -void ArchLogUnix::writeLog(LogLevel level, const char *msg) +void ArchLogUnix::writeLog(LogLevel level, const QString &msg) { // convert level int priority; @@ -56,5 +56,5 @@ void ArchLogUnix::writeLog(LogLevel level, const char *msg) } // log it - syslog(priority, "%s", msg); + syslog(priority, "%s", qPrintable(msg)); } diff --git a/src/lib/arch/unix/ArchLogUnix.h b/src/lib/arch/unix/ArchLogUnix.h index 45c56b500..c8459638a 100644 --- a/src/lib/arch/unix/ArchLogUnix.h +++ b/src/lib/arch/unix/ArchLogUnix.h @@ -19,8 +19,8 @@ public: ~ArchLogUnix() override = default; // IArchLog overrides - void openLog(const char *name) override; + void openLog(const QString &name) override; void closeLog() override; void showLog(bool) override; - void writeLog(LogLevel, const char *) override; + void writeLog(LogLevel, const QString &) override; }; diff --git a/src/lib/arch/win32/ArchDaemonWindows.cpp b/src/lib/arch/win32/ArchDaemonWindows.cpp index 499aba3b2..499fa0ee4 100644 --- a/src/lib/arch/win32/ArchDaemonWindows.cpp +++ b/src/lib/arch/win32/ArchDaemonWindows.cpp @@ -21,7 +21,7 @@ ArchDaemonWindows *ArchDaemonWindows::s_daemon = nullptr; ArchDaemonWindows::ArchDaemonWindows() : m_daemonThreadID(0) { - m_quitMessage = RegisterWindowMessage("DeskflowDaemonExit"); + m_quitMessage = RegisterWindowMessage(L"DeskflowDaemonExit"); } int ArchDaemonWindows::runDaemon(RunFunc runFunc) @@ -52,7 +52,7 @@ void ArchDaemonWindows::daemonFailed(int result) throw ArchDaemonRunException(result); } -int ArchDaemonWindows::daemonize(const char *name, DaemonFunc const &func) +int ArchDaemonWindows::daemonize(const QString &name, DaemonFunc const &func) { assert(name != nullptr); assert(func != nullptr); @@ -62,7 +62,7 @@ int ArchDaemonWindows::daemonize(const char *name, DaemonFunc const &func) // construct the service entry SERVICE_TABLE_ENTRY entry[2]; - entry[0].lpServiceName = const_cast(name); + entry[0].lpServiceName = const_cast(name.toStdWString().c_str()); entry[0].lpServiceProc = &ArchDaemonWindows::serviceMainEntry; entry[1].lpServiceName = nullptr; entry[1].lpServiceProc = nullptr; @@ -82,7 +82,7 @@ int ArchDaemonWindows::daemonize(const char *name, DaemonFunc const &func) HKEY ArchDaemonWindows::openNTServicesKey() { - static const char *s_keyNames[] = {_T("SYSTEM"), _T("CurrentControlSet"), _T("Services"), nullptr}; + static const wchar_t *s_keyNames[] = {_T("SYSTEM"), _T("CurrentControlSet"), _T("Services"), nullptr}; return ArchMiscWindows::addKey(HKEY_LOCAL_MACHINE, s_keyNames); } @@ -204,9 +204,9 @@ void ArchDaemonWindows::setStatusError(DWORD error) void ArchDaemonWindows::serviceMain(DWORD argc, LPTSTR *argvIn) { - using ArgList = std::vector; - using Arguments = std::vector; - const char **argv = const_cast(argvIn); + using ArgList = std::vector; + using Arguments = std::vector; + const wchar_t **argv = const_cast(argvIn); // create synchronization objects m_serviceMutex = ARCH->newMutex(); @@ -226,7 +226,7 @@ void ArchDaemonWindows::serviceMain(DWORD argc, LPTSTR *argvIn) m_serviceState = SERVICE_START_PENDING; setStatus(m_serviceState, 0, 10000); - std::string commandLine; + std::wstring commandLine; // if no arguments supplied then try getting them from the registry. // the first argument doesn't count because it's the service name. @@ -244,17 +244,17 @@ void ArchDaemonWindows::serviceMain(DWORD argc, LPTSTR *argvIn) // if the command line isn't empty then parse and use it if (!commandLine.empty()) { // parse, honoring double quoted substrings - std::string::size_type i = commandLine.find_first_not_of(" \t"); + std::wstring::size_type i = commandLine.find_first_not_of(_T(" \t")); while (i != std::string::npos && i != commandLine.size()) { // find end of string - std::string::size_type e; + std::wstring::size_type e; if (commandLine[i] == '\"') { // quoted. find closing quote. ++i; - e = commandLine.find("\"", i); + e = commandLine.find(_T("\""), i); // whitespace must follow closing quote - if (e == std::string::npos || + if (e == std::wstring::npos || (e + 1 != commandLine.size() && commandLine[e + 1] != ' ' && commandLine[e + 1] != '\t')) { args.clear(); break; @@ -265,8 +265,8 @@ void ArchDaemonWindows::serviceMain(DWORD argc, LPTSTR *argvIn) i = e + 1; } else { // unquoted. find next whitespace. - e = commandLine.find_first_of(" \t", i); - if (e == std::string::npos) { + e = commandLine.find_first_of(_T(" \t"), i); + if (e == std::wstring::npos) { e = commandLine.size(); } @@ -276,28 +276,28 @@ void ArchDaemonWindows::serviceMain(DWORD argc, LPTSTR *argvIn) } // next argument - i = commandLine.find_first_not_of(" \t", i); + i = commandLine.find_first_not_of(_T(" \t"), i); } // service name goes first - myArgv.push_back(argv[0]); + myArgv.push_back(LPWSTR(argv[0])); // get pointers for (size_t j = 0; j < args.size(); ++j) { - myArgv.push_back(args[j].c_str()); + myArgv.push_back(LPWSTR(args[j].c_str())); } // adjust argc/argv argc = (DWORD)myArgv.size(); - argv = &myArgv[0]; + argv = const_cast(&myArgv[0]); } } - m_commandLine = commandLine; + m_commandLine = QString::fromStdWString(commandLine); try { // invoke daemon function - m_daemonResult = m_daemonFunc(static_cast(argc), argv); + m_daemonResult = m_daemonFunc(static_cast(argc), reinterpret_cast(argv)); } catch (ArchDaemonRunException &e) { setStatusError(e.m_result); m_daemonResult = -1; @@ -381,7 +381,7 @@ void WINAPI ArchDaemonWindows::serviceHandlerEntry(DWORD ctrl) s_daemon->serviceHandler(ctrl); } -void ArchDaemonWindows::start(const char *name) +void ArchDaemonWindows::start(const QString &name) { // open service manager SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_READ); @@ -390,7 +390,7 @@ void ArchDaemonWindows::start(const char *name) } // open the service - SC_HANDLE service = OpenService(mgr, name, SERVICE_START); + SC_HANDLE service = OpenService(mgr, name.toStdWString().c_str(), SERVICE_START); if (service == nullptr) { CloseServiceHandle(mgr); @@ -403,7 +403,7 @@ void ArchDaemonWindows::start(const char *name) } } -void ArchDaemonWindows::stop(const char *name) +void ArchDaemonWindows::stop(const QString &name) { // open service manager SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_READ); @@ -412,7 +412,7 @@ void ArchDaemonWindows::stop(const char *name) } // open the service - SC_HANDLE service = OpenService(mgr, name, SERVICE_STOP | SERVICE_QUERY_STATUS); + SC_HANDLE service = OpenService(mgr, name.toStdWString().c_str(), SERVICE_STOP | SERVICE_QUERY_STATUS); if (service == nullptr) { CloseServiceHandle(mgr); diff --git a/src/lib/arch/win32/ArchDaemonWindows.h b/src/lib/arch/win32/ArchDaemonWindows.h index c0711f535..466d8056e 100644 --- a/src/lib/arch/win32/ArchDaemonWindows.h +++ b/src/lib/arch/win32/ArchDaemonWindows.h @@ -15,7 +15,8 @@ #include #include -#include + +#include #define ARCH_DAEMON ArchDaemonWindows @@ -67,8 +68,8 @@ public: static UINT getDaemonQuitMessage(); // IArchDaemon overrides - int daemonize(const char *name, DaemonFunc const &func) override; - std::string commandLine() const override + int daemonize(const QString &name, DaemonFunc const &func) override; + QString commandLine() const override { return m_commandLine; } @@ -92,8 +93,8 @@ private: void serviceHandler(DWORD ctrl); static void WINAPI serviceHandlerEntry(DWORD ctrl); - void start(const char *name); - void stop(const char *name); + void start(const QString &name); + void stop(const QString &name); private: class ArchDaemonRunException @@ -124,5 +125,5 @@ private: UINT m_quitMessage; - std::string m_commandLine; + QString m_commandLine; }; diff --git a/src/lib/arch/win32/ArchLogWindows.cpp b/src/lib/arch/win32/ArchLogWindows.cpp index c49d24e7a..c1bc72a72 100644 --- a/src/lib/arch/win32/ArchLogWindows.cpp +++ b/src/lib/arch/win32/ArchLogWindows.cpp @@ -7,7 +7,7 @@ #include "arch/win32/ArchLogWindows.h" -#include +#include // // ArchLogWindows @@ -18,10 +18,10 @@ ArchLogWindows::ArchLogWindows() : m_eventLog(nullptr) // do nothing } -void ArchLogWindows::openLog(const char *name) +void ArchLogWindows::openLog(const QString &name) { if (m_eventLog == nullptr) { - m_eventLog = RegisterEventSource(nullptr, name); + m_eventLog = RegisterEventSource(nullptr, name.toStdWString().c_str()); } } @@ -38,7 +38,7 @@ void ArchLogWindows::showLog(bool) // do nothing } -void ArchLogWindows::writeLog(LogLevel level, const char *msg) +void ArchLogWindows::writeLog(LogLevel level, const QString &msg) { if (m_eventLog != nullptr) { // convert priority @@ -67,9 +67,9 @@ void ArchLogWindows::writeLog(LogLevel level, const char *msg) m_eventLog, type, static_cast(level), 0, // event ID nullptr, 0, - (DWORD)strlen(msg) + 1, // raw data size + (DWORD)(msg.length()) + 1, // raw data size nullptr, - const_cast(msg) + const_cast(qPrintable(msg)) ); // raw data } } diff --git a/src/lib/arch/win32/ArchLogWindows.h b/src/lib/arch/win32/ArchLogWindows.h index d562c122a..3468f7afe 100644 --- a/src/lib/arch/win32/ArchLogWindows.h +++ b/src/lib/arch/win32/ArchLogWindows.h @@ -22,10 +22,10 @@ public: ~ArchLogWindows() override = default; // IArchLog overrides - void openLog(const char *name) override; + void openLog(const QString &name) override; void closeLog() override; void showLog(bool showIfEmpty) override; - void writeLog(LogLevel, const char *) override; + void writeLog(LogLevel, const QString &) override; private: HANDLE m_eventLog; diff --git a/src/lib/arch/win32/ArchMiscWindows.cpp b/src/lib/arch/win32/ArchMiscWindows.cpp index 073e0478c..bfe4ae40b 100644 --- a/src/lib/arch/win32/ArchMiscWindows.cpp +++ b/src/lib/arch/win32/ArchMiscWindows.cpp @@ -196,29 +196,29 @@ void ArchMiscWindows::setValue(HKEY key, const TCHAR *name, DWORD value) RegSetValueEx(key, name, 0, REG_DWORD, reinterpret_cast(&value), sizeof(DWORD)); } -std::string ArchMiscWindows::readBinaryOrString(HKEY key, const TCHAR *name, DWORD type) +std::wstring ArchMiscWindows::readBinaryOrString(HKEY key, const TCHAR *name, DWORD type) { // get the size of the string DWORD actualType; DWORD size = 0; LONG result = RegQueryValueEx(key, name, 0, &actualType, nullptr, &size); if (result != ERROR_SUCCESS || actualType != type) { - return std::string(); + return std::wstring(); } // if zero size then return empty string if (size == 0) { - return std::string(); + return std::wstring(); } // allocate space - char *buffer = new char[size]; + wchar_t *buffer = new wchar_t[size]; // read it result = RegQueryValueEx(key, name, 0, &actualType, reinterpret_cast(buffer), &size); if (result != ERROR_SUCCESS || actualType != type) { delete[] buffer; - return std::string(); + return std::wstring(); } // clean up and return value @@ -226,12 +226,12 @@ std::string ArchMiscWindows::readBinaryOrString(HKEY key, const TCHAR *name, DWO // don't include terminating nul; std::string will add one. --size; } - std::string value(buffer, size); + std::wstring value(buffer, size); delete[] buffer; return value; } -std::string ArchMiscWindows::readValueString(HKEY key, const TCHAR *name) +std::wstring ArchMiscWindows::readValueString(HKEY key, const TCHAR *name) { return readBinaryOrString(key, name, REG_SZ); } @@ -265,7 +265,7 @@ void ArchMiscWindows::setThreadExecutionState(DWORD busyModes) { // look up function dynamically so we work on older systems if (s_stes == nullptr) { - HINSTANCE kernel = LoadLibrary("kernel32.dll"); + HINSTANCE kernel = LoadLibrary(L"kernel32.dll"); if (kernel != nullptr) { s_stes = reinterpret_cast(GetProcAddress(kernel, "SetThreadExecutionState")); } @@ -303,7 +303,7 @@ void ArchMiscWindows::wakeupDisplay() // ES_CONTINUOUS, which we don't want. if (s_stes == nullptr) { - HINSTANCE kernel = LoadLibrary("kernel32.dll"); + HINSTANCE kernel = LoadLibrary(L"kernel32.dll"); if (kernel != nullptr) { s_stes = reinterpret_cast(GetProcAddress(kernel, "SetThreadExecutionState")); } @@ -320,16 +320,16 @@ void ArchMiscWindows::wakeupDisplay() bool ArchMiscWindows::wasLaunchedAsService() { - std::string name; + std::wstring name; if (!getParentProcessName(name)) { LOG_ERR("cannot determine if process was launched as service"); return false; } - return (name == "services.exe"); + return (name == L"services.exe"); } -bool ArchMiscWindows::getParentProcessName(std::string &name) +bool ArchMiscWindows::getParentProcessName(std::wstring &name) { PROCESSENTRY32 parentEntry; if (!getParentProcessEntry(parentEntry)) { @@ -405,7 +405,7 @@ void ArchMiscWindows::setInstanceWin32(HINSTANCE instance) s_instanceWin32 = instance; } -std::string ArchMiscWindows::getActiveDesktopName() +std::wstring ArchMiscWindows::getActiveDesktopName() { HDESK desk = OpenInputDesktop(0, TRUE, GENERIC_READ); if (desk == nullptr) { @@ -440,7 +440,7 @@ HMODULE ArchMiscWindows::findLoadedModule(std::array moduleName } for (const auto &moduleName : moduleNames) { - if (_stricmp(loadedModuleName.data(), moduleName) == 0) { + if (_stricmp((loadedModuleName.data()), moduleName) == 0) { return hModules[i]; } } diff --git a/src/lib/arch/win32/ArchMiscWindows.h b/src/lib/arch/win32/ArchMiscWindows.h index d3db27465..23c3f621e 100644 --- a/src/lib/arch/win32/ArchMiscWindows.h +++ b/src/lib/arch/win32/ArchMiscWindows.h @@ -92,7 +92,7 @@ public: static void setValue(HKEY key, const TCHAR *name, DWORD value); //! Read a string value from the registry - static std::string readValueString(HKEY, const TCHAR *name); + static std::wstring readValueString(HKEY, const TCHAR *name); //! Read a DWORD value from the registry static DWORD readValueInt(HKEY, const TCHAR *name); @@ -110,7 +110,7 @@ public: static bool wasLaunchedAsService(); //! Returns true if we got the parent process name. - static bool getParentProcessName(std::string &name); + static bool getParentProcessName(std::wstring &name); //! Prevent hard to troubleshoot errors, e.g. access violations. static void guardRuntimeVersion(); @@ -125,7 +125,7 @@ public: static void setInstanceWin32(HINSTANCE instance); //! Get the name of the active input desktop. - static std::string getActiveDesktopName(); + static std::wstring getActiveDesktopName(); //! Returns true if the process is running with elevated privileges (i.e. as admin). static bool isProcessElevated(); @@ -138,7 +138,7 @@ private: static HKEY openKey(HKEY parent, const TCHAR *const *keyPath, bool create); //! Read a string value from the registry - static std::string readBinaryOrString(HKEY, const TCHAR *name, DWORD type); + static std::wstring readBinaryOrString(HKEY, const TCHAR *name, DWORD type); //! Set thread busy state static void setThreadExecutionState(DWORD); diff --git a/src/lib/arch/win32/ArchNetworkWinsock.cpp b/src/lib/arch/win32/ArchNetworkWinsock.cpp index 2ed1084b0..5c8afc558 100644 --- a/src/lib/arch/win32/ArchNetworkWinsock.cpp +++ b/src/lib/arch/win32/ArchNetworkWinsock.cpp @@ -100,7 +100,7 @@ ArchNetworkWinsock::~ArchNetworkWinsock() void ArchNetworkWinsock::init() { - static const char *s_library[] = {"ws2_32.dll"}; + static const wchar_t *s_library[] = {L"ws2_32.dll"}; assert(WSACleanup_winsock == nullptr); assert(s_networkModule == nullptr); diff --git a/src/lib/base/CMakeLists.txt b/src/lib/base/CMakeLists.txt index c473aed32..b8febf3f2 100644 --- a/src/lib/base/CMakeLists.txt +++ b/src/lib/base/CMakeLists.txt @@ -41,7 +41,7 @@ add_library(base STATIC Unicode.h ) -target_link_libraries(base PRIVATE arch) +target_link_libraries(base PUBLIC arch) if (CMAKE_CXX_BYTE_ORDER STREQUAL "BIG_ENDIAN") target_compile_definitions(base PUBLIC WORDS_BIGENDIAN=1) endif() diff --git a/src/lib/base/ILogOutputter.h b/src/lib/base/ILogOutputter.h index a3ea2c489..e46769a2d 100644 --- a/src/lib/base/ILogOutputter.h +++ b/src/lib/base/ILogOutputter.h @@ -30,7 +30,7 @@ public: Opens the outputter for writing. Calling this method on an already open outputter must have no effect. */ - virtual void open(const char *title) = 0; + virtual void open(const QString &title) = 0; //! Close the outputter /*! @@ -55,7 +55,7 @@ public: message to all outputters in the outputter chain, otherwise it continues. Most implementations should return true. */ - virtual bool write(LogLevel level, const char *message) = 0; + virtual bool write(LogLevel level, const QString &message) = 0; //@} }; diff --git a/src/lib/base/LogOutputters.cpp b/src/lib/base/LogOutputters.cpp index 8a588ae1e..1ddb94ea6 100644 --- a/src/lib/base/LogOutputters.cpp +++ b/src/lib/base/LogOutputters.cpp @@ -8,19 +8,20 @@ #include "base/LogOutputters.h" #include "arch/Arch.h" -#include "base/Path.h" -#include "base/String.h" -#include #include +#include +#include +#include + constexpr auto s_logFileSizeLimit = 1024 * 1024; //!< Max Log size before rotating (1Mb) // // StopLogOutputter // -void StopLogOutputter::open(const char *) +void StopLogOutputter::open(const QString &) { // do nothing } @@ -35,7 +36,7 @@ void StopLogOutputter::show(bool) // do nothing } -bool StopLogOutputter::write(LogLevel, const char *) +bool StopLogOutputter::write(LogLevel, const QString &) { return false; } @@ -44,7 +45,7 @@ bool StopLogOutputter::write(LogLevel, const char *) // ConsoleLogOutputter // -void ConsoleLogOutputter::open(const char *title) +void ConsoleLogOutputter::open(const QString &title) { // do nothing } @@ -59,12 +60,12 @@ void ConsoleLogOutputter::show(bool showIfEmpty) // do nothing } -bool ConsoleLogOutputter::write(LogLevel level, const char *msg) +bool ConsoleLogOutputter::write(LogLevel level, const QString &msg) { if ((level >= LogLevel::Fatal) && (level <= LogLevel::Warning)) - std::cerr << msg << std::endl; + std::cerr << qPrintable(msg) << std::endl; else - std::cout << msg << std::endl; + std::cout << qPrintable(msg) << std::endl; std::cout.flush(); return true; } @@ -78,7 +79,7 @@ void ConsoleLogOutputter::flush() const // SystemLogOutputter // -void SystemLogOutputter::open(const char *title) +void SystemLogOutputter::open(const QString &title) { ARCH->openLog(title); } @@ -93,7 +94,7 @@ void SystemLogOutputter::show(bool showIfEmpty) ARCH->showLog(showIfEmpty); } -bool SystemLogOutputter::write(LogLevel level, const char *msg) +bool SystemLogOutputter::write(LogLevel level, const QString &msg) { ARCH->writeLog(level, msg); return true; @@ -103,7 +104,7 @@ bool SystemLogOutputter::write(LogLevel level, const char *msg) // SystemLogger // -SystemLogger::SystemLogger(const char *title, bool blockConsole) +SystemLogger::SystemLogger(const QString &title, bool blockConsole) { // redirect log messages if (blockConsole) { @@ -129,44 +130,36 @@ SystemLogger::~SystemLogger() // FileLogOutputter // -FileLogOutputter::FileLogOutputter(const char *logFile) +FileLogOutputter::FileLogOutputter(const QString &logFile) { setLogFilename(logFile); } -void FileLogOutputter::setLogFilename(const char *logFile) +void FileLogOutputter::setLogFilename(const QString &logFile) { assert(logFile != nullptr); m_fileName = logFile; } -bool FileLogOutputter::write(LogLevel level, const char *message) +bool FileLogOutputter::write(LogLevel level, const QString &message) { - bool moveFile = false; + QFile file(m_fileName); + if (!file.open(QFile::WriteOnly | QFile::Append)) + return false; - std::ofstream m_handle; - m_handle.open(deskflow::filesystem::path(m_fileName), std::fstream::app); - if (m_handle.is_open() && m_handle.fail() != true) { - m_handle << message << std::endl; + QTextStream(&file) << message << Qt::endl; + file.close(); - // when file size exceeds limits, move to 'old log' filename. - size_t p = m_handle.tellp(); - if (p > s_logFileSizeLimit) { - moveFile = true; - } - } - m_handle.close(); - - if (moveFile) { - std::string oldLogFilename = deskflow::string::sprintf("%s.1", m_fileName.c_str()); - remove(oldLogFilename.c_str()); - rename(m_fileName.c_str(), oldLogFilename.c_str()); + if (file.size() > s_logFileSizeLimit) { + const auto oldFile = QStringLiteral("%1.1").arg(m_fileName); + QFile::remove(m_fileName); + file.rename(m_fileName, oldFile); } return true; } -void FileLogOutputter::open(const char *title) +void FileLogOutputter::open(const QString &title) { // do nothing } diff --git a/src/lib/base/LogOutputters.h b/src/lib/base/LogOutputters.h index 03ee1df73..bdce88297 100644 --- a/src/lib/base/LogOutputters.h +++ b/src/lib/base/LogOutputters.h @@ -11,6 +11,7 @@ #include "base/ILogOutputter.h" #include "mt/Thread.h" +#include //! Stop traversing log chain outputter /*! This outputter performs no output and returns false from \c write(), @@ -24,10 +25,10 @@ public: ~StopLogOutputter() override = default; // ILogOutputter overrides - void open(const char *title) override; + void open(const QString &title) override; void close() override; void show(bool showIfEmpty) override; - bool write(LogLevel level, const char *message) override; + bool write(LogLevel level, const QString &message) override; }; //! Write log to console @@ -42,10 +43,10 @@ public: ~ConsoleLogOutputter() override = default; // ILogOutputter overrides - void open(const char *title) override; + void open(const QString &title) override; void close() override; void show(bool showIfEmpty) override; - bool write(LogLevel level, const char *message) override; + bool write(LogLevel level, const QString &message) override; void flush() const; }; @@ -58,19 +59,19 @@ message is ignored. class FileLogOutputter : public ILogOutputter { public: - explicit FileLogOutputter(const char *logFile); + explicit FileLogOutputter(const QString &logFile); ~FileLogOutputter() override = default; // ILogOutputter overrides - void open(const char *title) override; + void open(const QString &title) override; void close() override; void show(bool showIfEmpty) override; - bool write(LogLevel level, const char *message) override; + bool write(LogLevel level, const QString &message) override; - void setLogFilename(const char *title); + void setLogFilename(const QString &title); private: - std::string m_fileName; + QString m_fileName; }; //! Write log to system log @@ -84,10 +85,10 @@ public: ~SystemLogOutputter() override = default; // ILogOutputter overrides - void open(const char *title) override; + void open(const QString &title) override; void close() override; void show(bool showIfEmpty) override; - bool write(LogLevel level, const char *message) override; + bool write(LogLevel level, const QString &message) override; }; //! Write log to system log only @@ -101,7 +102,7 @@ the scope. class SystemLogger { public: - SystemLogger(const char *title, bool blockConsole); + SystemLogger(const QString &title, bool blockConsole); SystemLogger(SystemLogger const &) = delete; SystemLogger(SystemLogger &&) = delete; ~SystemLogger(); diff --git a/src/lib/base/Unicode.cpp b/src/lib/base/Unicode.cpp index 6d293d04d..309c8df7f 100644 --- a/src/lib/base/Unicode.cpp +++ b/src/lib/base/Unicode.cpp @@ -6,9 +6,7 @@ */ #include "base/Unicode.h" -#include "arch/Arch.h" -using enum ArchString::EWideCharEncoding; // // local utility functions // @@ -197,28 +195,6 @@ std::string Unicode::UTF8ToUTF32(const std::string &src, bool *errors) return dst; } -std::string Unicode::UTF8ToText(const std::string &src, bool *errors) -{ - // default to success - resetError(errors); - - // convert to wide char - uint32_t size; - wchar_t *tmp = UTF8ToWideChar(src, size, errors); - - // convert string to multibyte - int len = ARCH->convStringWCToMB(nullptr, tmp, size, errors); - auto *mbs = new char[len + 1]; - ARCH->convStringWCToMB(mbs, tmp, size, errors); - std::string text(mbs, len); - - // clean up - delete[] mbs; - delete[] tmp; - - return text; -} - std::string Unicode::UCS2ToUTF8(const std::string_view &src, bool *errors) { // default to success @@ -259,89 +235,6 @@ std::string Unicode::UTF32ToUTF8(const std::string_view &src, bool *errors) return doUTF32ToUTF8(reinterpret_cast(src.data()), n, errors); } -std::string Unicode::textToUTF8(const std::string &src, bool *errors, ArchString::EWideCharEncoding encoding) -{ - // default to success - resetError(errors); - - // convert string to wide characters - auto n = (uint32_t)src.size(); - int len = ARCH->convStringMBToWC(nullptr, src.c_str(), n, errors); - auto *wcs = new wchar_t[len + 1]; - ARCH->convStringMBToWC(wcs, src.c_str(), n, errors); - - // convert to UTF8 - std::string utf8 = wideCharToUTF8(wcs, len, errors, encoding); - - // clean up - delete[] wcs; - - return utf8; -} - -wchar_t *Unicode::UTF8ToWideChar(const std::string &src, uint32_t &size, bool *errors) -{ - // convert to platform's wide character encoding - std::string tmp; - switch (ARCH->getWideCharEncoding()) { - case kUCS2: - tmp = UTF8ToUCS2(src, errors); - size = (uint32_t)tmp.size() >> 1; - break; - - case kUCS4: - tmp = UTF8ToUCS4(src, errors); - size = (uint32_t)tmp.size() >> 2; - break; - - case kUTF16: - tmp = UTF8ToUTF16(src, errors); - size = (uint32_t)tmp.size() >> 1; - break; - - case kUTF32: - tmp = UTF8ToUTF32(src, errors); - size = (uint32_t)tmp.size() >> 2; - break; - - default: - assert(0 && "unknown wide character encoding"); - } - - // copy to a wchar_t array - auto *dst = new wchar_t[size]; - ::memcpy(dst, tmp.data(), sizeof(wchar_t) * size); - return dst; -} - -std::string -Unicode::wideCharToUTF8(const wchar_t *src, uint32_t size, bool *errors, ArchString::EWideCharEncoding encoding) -{ - if (encoding == kPlatformDetermined) { - encoding = ARCH->getWideCharEncoding(); - } - // convert from platform's wide character encoding. - // note -- this must include a wide nul character (independent of - // the String's nul character). - switch (encoding) { - case kUCS2: - return doUCS2ToUTF8(reinterpret_cast(src), size, errors); - - case kUCS4: - return doUCS4ToUTF8(reinterpret_cast(src), size, errors); - - case kUTF16: - return doUTF16ToUTF8(reinterpret_cast(src), size, errors); - - case kUTF32: - return doUTF32ToUTF8(reinterpret_cast(src), size, errors); - - default: - assert(0 && "unknown wide character encoding"); - return std::string(); - } -} - std::string Unicode::doUCS2ToUTF8(const uint8_t *data, uint32_t n, bool *errors) { // make some space diff --git a/src/lib/base/Unicode.h b/src/lib/base/Unicode.h index edb486feb..9f69a373b 100644 --- a/src/lib/base/Unicode.h +++ b/src/lib/base/Unicode.h @@ -7,7 +7,7 @@ #pragma once -#include "arch/ArchString.h" +#include "common/Common.h" #include @@ -61,14 +61,6 @@ public: */ static std::string UTF8ToUTF32(const std::string &, bool *errors = nullptr); - //! Convert from UTF-8 to the current locale encoding - /*! - Convert from UTF-8 to the current locale encoding. If errors is not - nullptr then *errors is set to true iff any character could not be encoded. - Decoding errors do not set *errors. - */ - static std::string UTF8ToText(const std::string &, bool *errors = nullptr); - //! Convert from UCS-2 to UTF-8 /*! Convert from UCS-2 to UTF-8. If errors is not nullptr then *errors is @@ -97,32 +89,9 @@ public: */ static std::string UTF32ToUTF8(const std::string_view &, bool *errors = nullptr); - //! Convert from the current locale encoding to UTF-8 - /*! - Convert from the current locale encoding to UTF-8. If errors is not - nullptr then *errors is set to true iff any character could not be decoded. - */ - static std::string textToUTF8( - const std::string &, bool *errors = nullptr, - ArchString::EWideCharEncoding encoding = ArchString::EWideCharEncoding::kPlatformDetermined - ); - //@} private: - // convert UTF8 to wchar_t string (using whatever encoding is native - // to the platform). caller must delete[] the returned string. the - // string is *not* nul terminated; the length (in characters) is - // returned in size. - static wchar_t *UTF8ToWideChar(const std::string &, uint32_t &size, bool *errors); - - // convert nul terminated wchar_t string (in platform's native - // encoding) to UTF8. - static std::string wideCharToUTF8( - const wchar_t *, uint32_t size, bool *errors, - ArchString::EWideCharEncoding encoding = ArchString::EWideCharEncoding::kPlatformDetermined - ); - // internal conversion to UTF8 static std::string doUCS2ToUTF8(const uint8_t *src, uint32_t n, bool *errors); static std::string doUCS4ToUTF8(const uint8_t *src, uint32_t n, bool *errors); diff --git a/src/lib/client/CMakeLists.txt b/src/lib/client/CMakeLists.txt index faa7074c7..f6e0519f1 100644 --- a/src/lib/client/CMakeLists.txt +++ b/src/lib/client/CMakeLists.txt @@ -13,6 +13,8 @@ add_library(client STATIC ServerProxy.h ) +target_link_libraries(client PUBLIC common) + if(UNIX) - target_link_libraries(client app io) + target_link_libraries(client PUBLIC app io) endif() diff --git a/src/lib/common/Constants.h.in b/src/lib/common/Constants.h.in index 193495846..cf9f0ef9f 100644 --- a/src/lib/common/Constants.h.in +++ b/src/lib/common/Constants.h.in @@ -21,7 +21,6 @@ const auto kCopyright = // "Copyright (C) 2009-2012 Nick Bolton\n" "Copyright (C) 2002-2009 Chris Schoeneman"; - const auto kCoreBinName = "@CORE_BINARY@"; #ifndef NDEBUG @@ -43,11 +42,8 @@ const auto kWindowsRuntimeMajor = @REQUIRED_MSVC_RUNTIME_MAJOR@; const auto kWindowsRuntimeMinor = @REQUIRED_MSVC_RUNTIME_MINOR@; // clang-format on -const auto kWindowsRegistryKey = "SOFTWARE\\@CMAKE_PROJECT_PROPER_NAME@"; -const auto kCloseEventName = "Global\\@CMAKE_PROJECT_PROPER_NAME@Close"; -const auto kSendSasEventName = "Global\\@CMAKE_PROJECT_PROPER_NAME@SendSAS"; +constexpr auto kWindowsRegistryKey = L"SOFTWARE\\@CMAKE_PROJECT_PROPER_NAME@"; +constexpr auto kCloseEventName = L"Global\\@CMAKE_PROJECT_PROPER_NAME@Close"; +constexpr auto kSendSasEventName = L"Global\\@CMAKE_PROJECT_PROPER_NAME@SendSAS"; #endif - - - diff --git a/src/lib/deskflow/unix/DeskflowXkbKeyboard.cpp b/src/lib/deskflow/unix/DeskflowXkbKeyboard.cpp index 42c5edf04..b04af7138 100644 --- a/src/lib/deskflow/unix/DeskflowXkbKeyboard.cpp +++ b/src/lib/deskflow/unix/DeskflowXkbKeyboard.cpp @@ -6,10 +6,10 @@ */ #if WINAPI_XWINDOWS +#include "base/Log.h" #include -#include "DeskflowXkbKeyboard.h" -#include "base/Log.h" +#include "DeskflowXkbKeyboard.h" // Include last due to X11 use namespace deskflow::linux { diff --git a/src/lib/deskflow/win32/AppUtilWindows.cpp b/src/lib/deskflow/win32/AppUtilWindows.cpp index dbb12b27d..d9d2e484c 100644 --- a/src/lib/deskflow/win32/AppUtilWindows.cpp +++ b/src/lib/deskflow/win32/AppUtilWindows.cpp @@ -189,7 +189,7 @@ HKL AppUtilWindows::getCurrentKeyboardLayout() const void AppUtilWindows::eventLoop() { - HANDLE hCloseEvent = CreateEventA(nullptr, TRUE, FALSE, kCloseEventName); + HANDLE hCloseEvent = CreateEvent(nullptr, TRUE, FALSE, kCloseEventName); if (!hCloseEvent) { LOG_CRIT("failed to create event for windows event loop"); throw std::runtime_error(windowsErrorToString(GetLastError())); diff --git a/src/lib/gui/core/CommandProcess.cpp b/src/lib/gui/core/CommandProcess.cpp index 23f369c49..2533e2bf3 100644 --- a/src/lib/gui/core/CommandProcess.cpp +++ b/src/lib/gui/core/CommandProcess.cpp @@ -27,7 +27,7 @@ QString CommandProcess::run() QString error; if (success) { if (!m_Input.isEmpty()) { - process.write(m_Input.toStdString().c_str()); + process.write(qPrintable(m_Input)); } if (process.waitForFinished()) { diff --git a/src/lib/io/CMakeLists.txt b/src/lib/io/CMakeLists.txt index fa2d6a03d..223bb34d0 100644 --- a/src/lib/io/CMakeLists.txt +++ b/src/lib/io/CMakeLists.txt @@ -14,3 +14,5 @@ add_library(io STATIC StreamFilter.cpp StreamFilter.h ) + +target_link_libraries(io PUBLIC common) diff --git a/src/lib/net/SslLogger.cpp b/src/lib/net/SslLogger.cpp index 124ef9b1f..06bace07e 100644 --- a/src/lib/net/SslLogger.cpp +++ b/src/lib/net/SslLogger.cpp @@ -90,7 +90,7 @@ void SslLogger::logSecureConnectInfo(const SSL *ssl) if (cipher) { char msg[128] = {0}; SSL_CIPHER_description(cipher, msg, sizeof(msg)); - LOG_DEBUG("openssl cipher: %s", msg); + LOG_DEBUG("openssl cipher: %s", QString(msg).trimmed().toStdString().c_str()); // For some reason SSL_get_version is return mismatching information to // SSL_CIPHER_description diff --git a/src/lib/platform/MSWindowsClipboardHTMLConverter.cpp b/src/lib/platform/MSWindowsClipboardHTMLConverter.cpp index cb9ca2cb8..9f55bb070 100644 --- a/src/lib/platform/MSWindowsClipboardHTMLConverter.cpp +++ b/src/lib/platform/MSWindowsClipboardHTMLConverter.cpp @@ -15,7 +15,7 @@ MSWindowsClipboardHTMLConverter::MSWindowsClipboardHTMLConverter() { - m_format = RegisterClipboardFormat("HTML Format"); + m_format = RegisterClipboardFormat(L"HTML Format"); } IClipboard::Format MSWindowsClipboardHTMLConverter::getFormat() const diff --git a/src/lib/platform/MSWindowsClipboardTextConverter.cpp b/src/lib/platform/MSWindowsClipboardTextConverter.cpp index 248556854..1a7e12f5a 100644 --- a/src/lib/platform/MSWindowsClipboardTextConverter.cpp +++ b/src/lib/platform/MSWindowsClipboardTextConverter.cpp @@ -9,6 +9,8 @@ #include "base/Unicode.h" +#include + // // MSWindowsClipboardTextConverter // @@ -20,17 +22,12 @@ UINT MSWindowsClipboardTextConverter::getWin32Format() const std::string MSWindowsClipboardTextConverter::doFromIClipboard(const std::string &data) const { - // convert and add nul terminator - return Unicode::UTF8ToText(data) += '\0'; + return QString::fromStdString(data).toLatin1().toStdString() + '\0'; } std::string MSWindowsClipboardTextConverter::doToIClipboard(const std::string &data) const { - // convert and truncate at first nul terminator - std::string dst = Unicode::textToUTF8(data); - std::string::size_type n = dst.find('\0'); - if (n != std::string::npos) { - dst.erase(n); - } - return dst; + auto q = QString::fromStdString(data); + q.truncate(q.indexOf('\0')); + return q.toStdString(); } diff --git a/src/lib/platform/MSWindowsDebugOutputter.cpp b/src/lib/platform/MSWindowsDebugOutputter.cpp index d70150889..06cb85f41 100644 --- a/src/lib/platform/MSWindowsDebugOutputter.cpp +++ b/src/lib/platform/MSWindowsDebugOutputter.cpp @@ -9,9 +9,10 @@ #define WIN32_LEAN_AND_MEAN #include -#include -void MSWindowsDebugOutputter::open(const char *title) +#include + +void MSWindowsDebugOutputter::open(const QString &title) { // do nothing } @@ -26,9 +27,10 @@ void MSWindowsDebugOutputter::show(bool showIfEmpty) // do nothing } -bool MSWindowsDebugOutputter::write(LogLevel level, const char *msg) +bool MSWindowsDebugOutputter::write(LogLevel level, const QString &msg) { - OutputDebugString((std::string(msg) + "\n").c_str()); + std::wstring out = msg.toStdWString() + L"\n"; + OutputDebugString(out.c_str()); return true; } diff --git a/src/lib/platform/MSWindowsDebugOutputter.h b/src/lib/platform/MSWindowsDebugOutputter.h index f2d65eceb..1bf334790 100644 --- a/src/lib/platform/MSWindowsDebugOutputter.h +++ b/src/lib/platform/MSWindowsDebugOutputter.h @@ -21,9 +21,9 @@ public: ~MSWindowsDebugOutputter() override = default; // ILogOutputter overrides - void open(const char *title) override; + void open(const QString &title) override; void close() override; void show(bool showIfEmpty) override; - bool write(LogLevel level, const char *message) override; + bool write(LogLevel level, const QString &message) override; void flush(); }; diff --git a/src/lib/platform/MSWindowsDesks.cpp b/src/lib/platform/MSWindowsDesks.cpp index 35637e066..c7e38979c 100644 --- a/src/lib/platform/MSWindowsDesks.cpp +++ b/src/lib/platform/MSWindowsDesks.cpp @@ -348,7 +348,7 @@ ATOM MSWindowsDesks::createDeskWindowClass(bool isPrimary) const classInfo.hCursor = m_cursor; classInfo.hbrBackground = nullptr; classInfo.lpszMenuName = nullptr; - classInfo.lpszClassName = "DeskflowDesk"; + classInfo.lpszClassName = L"DeskflowDesk"; classInfo.hIconSm = nullptr; return RegisterClassEx(&classInfo); } @@ -360,7 +360,7 @@ void MSWindowsDesks::destroyClass(ATOM windowClass) const } } -HWND MSWindowsDesks::createWindow(ATOM windowClass, const char *name) const +HWND MSWindowsDesks::createWindow(ATOM windowClass, const wchar_t *name) const { HWND window = CreateWindowEx( WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW, MAKEINTATOM(windowClass), name, WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, @@ -610,11 +610,11 @@ void MSWindowsDesks::deskThread(void *vdesk) // create a window. we use this window to hide the cursor. try { - desk->m_window = createWindow(m_deskClass, "DeskflowDesk"); - LOG_DEBUG("desk %s window is 0x%08x", desk->m_name.c_str(), desk->m_window); + desk->m_window = createWindow(m_deskClass, L"DeskflowDesk"); + LOG_DEBUG("desk %ls window is 0x%08x", desk->m_name.c_str(), desk->m_window); } catch (...) { // ignore - LOG_DEBUG("can't create desk window for %s", desk->m_name.c_str()); + LOG_DEBUG("can't create desk window for %ls", desk->m_name.c_str()); } } @@ -744,7 +744,7 @@ void MSWindowsDesks::deskThread(void *vdesk) } } -MSWindowsDesks::Desk *MSWindowsDesks::addDesk(const std::string &name, HDESK hdesk) +MSWindowsDesks::Desk *MSWindowsDesks::addDesk(const std::wstring &name, HDESK hdesk) { Desk *desk = new Desk; desk->m_name = name; @@ -767,7 +767,7 @@ void MSWindowsDesks::removeDesks() } m_desks.clear(); m_activeDesk = nullptr; - m_activeDeskName = ""; + m_activeDeskName = L""; } void MSWindowsDesks::checkDesk() @@ -775,7 +775,7 @@ void MSWindowsDesks::checkDesk() // get current desktop. if we already know about it then return. Desk *desk; HDESK hdesk = openInputDesktop(); - std::string name = getDesktopName(hdesk); + std::wstring name = getDesktopName(hdesk); Desks::const_iterator index = m_desks.find(name); if (index == m_desks.end()) { desk = addDesk(name, hdesk); @@ -802,7 +802,7 @@ void MSWindowsDesks::checkDesk() // from an inaccessible desktop so when we switch from an // inaccessible desktop to an accessible one we have to // update the keyboard state. - LOG_DEBUG("switched to desk \"%s\"", name.c_str()); + LOG_DEBUG("switched to desk \"%ls\"", name.c_str()); bool syncKeys = false; bool isAccessible = isDeskAccessible(desk); if (isDeskAccessible(m_activeDesk) != isAccessible) { @@ -876,16 +876,16 @@ void MSWindowsDesks::closeDesktop(HDESK desk) } } -std::string MSWindowsDesks::getDesktopName(HDESK desk) +std::wstring MSWindowsDesks::getDesktopName(HDESK desk) { if (desk == nullptr) { - return std::string(); + return std::wstring(); } else { DWORD size; GetUserObjectInformation(desk, UOI_NAME, nullptr, 0, &size); TCHAR *name = (TCHAR *)alloca(size + sizeof(TCHAR)); GetUserObjectInformation(desk, UOI_NAME, name, size, &size); - std::string result(name); + std::wstring result(name); return result; } } diff --git a/src/lib/platform/MSWindowsDesks.h b/src/lib/platform/MSWindowsDesks.h index 423015979..439313b79 100644 --- a/src/lib/platform/MSWindowsDesks.h +++ b/src/lib/platform/MSWindowsDesks.h @@ -179,7 +179,7 @@ private: class Desk { public: - std::string m_name; + std::wstring m_name; Thread *m_thread; DWORD m_threadID; DWORD m_targetID; @@ -188,14 +188,14 @@ private: HWND m_foregroundWindow; bool m_lowLevel; }; - using Desks = std::map; + using Desks = std::map; // initialization and shutdown operations HCURSOR createBlankCursor() const; void destroyCursor(HCURSOR cursor) const; ATOM createDeskWindowClass(bool isPrimary) const; void destroyClass(ATOM windowClass) const; - HWND createWindow(ATOM windowClass, const char *name) const; + HWND createWindow(ATOM windowClass, const wchar_t *name) const; void destroyWindow(HWND) const; // message handlers @@ -206,7 +206,7 @@ private: void deskThread(void *vdesk); // desk switch checking and handling - Desk *addDesk(const std::string &name, HDESK hdesk); + Desk *addDesk(const std::wstring &name, HDESK hdesk); void removeDesks(); void checkDesk(); bool isDeskAccessible(const Desk *desk) const; @@ -222,7 +222,7 @@ private: // desk API wrappers HDESK openInputDesktop(); void closeDesktop(HDESK); - std::string getDesktopName(HDESK); + std::wstring getDesktopName(HDESK); // our desk window procs static LRESULT CALLBACK primaryDeskProc(HWND, UINT, WPARAM, LPARAM); @@ -263,7 +263,7 @@ private: // the current desk and it's name Desk *m_activeDesk = nullptr; - std::string m_activeDeskName; + std::wstring m_activeDeskName; // one desk per desktop and a cond var to communicate with it Mutex m_mutex; diff --git a/src/lib/platform/MSWindowsEventQueueBuffer.cpp b/src/lib/platform/MSWindowsEventQueueBuffer.cpp index 9a71795f4..5178e6603 100644 --- a/src/lib/platform/MSWindowsEventQueueBuffer.cpp +++ b/src/lib/platform/MSWindowsEventQueueBuffer.cpp @@ -29,7 +29,7 @@ MSWindowsEventQueueBuffer::MSWindowsEventQueueBuffer(IEventQueue *events) : m_ev m_thread = GetCurrentThreadId(); // create a message type for custom events - m_userEvent = RegisterWindowMessage("DESKFLOW_USER_EVENT"); + m_userEvent = RegisterWindowMessage(L"DESKFLOW_USER_EVENT"); // get message type for daemon quit m_daemonQuit = ArchMiscWindows::getDaemonQuitMessage(); diff --git a/src/lib/platform/MSWindowsKeyState.cpp b/src/lib/platform/MSWindowsKeyState.cpp index 3d27ad6b6..2312533b1 100644 --- a/src/lib/platform/MSWindowsKeyState.cpp +++ b/src/lib/platform/MSWindowsKeyState.cpp @@ -599,7 +599,7 @@ MSWindowsKeyState::~MSWindowsKeyState() void MSWindowsKeyState::init() { // look up symbol that's available on winNT family but not win95 - HMODULE userModule = GetModuleHandle("user32.dll"); + HMODULE userModule = GetModuleHandle(L"user32.dll"); m_ToUnicodeEx = (ToUnicodeEx_t)GetProcAddress(userModule, "ToUnicodeEx"); } @@ -766,7 +766,7 @@ bool MSWindowsKeyState::fakeCtrlAltDel() { // The daemon creates this event with default permissions, which means this process must be // elevated to be able to open it. If not elevated, an access denied error will be returned. - MSWindowsHandle sendSasEvent(OpenEvent(EVENT_MODIFY_STATE, FALSE, kSendSasEventName)); + MSWindowsHandle sendSasEvent(OpenEvent(EVENT_MODIFY_STATE, FALSE, LPCWSTR(kSendSasEventName))); if (!sendSasEvent.get()) { LOG_ERR( "couldn't open SAS event, unable to simulate ctrl+alt+del, error: %s", diff --git a/src/lib/platform/MSWindowsProcess.cpp b/src/lib/platform/MSWindowsProcess.cpp index bd8b8e989..fff9f84d7 100644 --- a/src/lib/platform/MSWindowsProcess.cpp +++ b/src/lib/platform/MSWindowsProcess.cpp @@ -23,7 +23,7 @@ namespace deskflow::platform { -MSWindowsProcess::MSWindowsProcess(const std::string &command, HANDLE stdOutput, HANDLE stdError) +MSWindowsProcess::MSWindowsProcess(const std::wstring &command, HANDLE stdOutput, HANDLE stdError) : m_command(command), m_stdOutput(stdOutput), m_stdError(stdError) @@ -52,7 +52,7 @@ BOOL MSWindowsProcess::startInForeground() si.wShowWindow = SW_MINIMIZE; m_createProcessResult = - CreateProcess(nullptr, LPSTR(m_command.c_str()), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &m_info); + CreateProcess(nullptr, LPWSTR(m_command.c_str()), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &m_info); return m_createProcessResult; } @@ -70,7 +70,8 @@ BOOL MSWindowsProcess::startAsUser(HANDLE userToken, LPSECURITY_ATTRIBUTES sa) ZeroMemory(&m_info, sizeof(PROCESS_INFORMATION)); const DWORD creationFlags = NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT; m_createProcessResult = CreateProcessAsUser( - userToken, nullptr, LPSTR(m_command.c_str()), sa, nullptr, TRUE, creationFlags, environment, nullptr, &si, &m_info + userToken, nullptr, LPWSTR(m_command.c_str()), sa, nullptr, TRUE, creationFlags, environment, nullptr, &si, + &m_info ); DestroyEnvironmentBlock(environment); @@ -81,7 +82,7 @@ BOOL MSWindowsProcess::startAsUser(HANDLE userToken, LPSECURITY_ATTRIBUTES sa) void MSWindowsProcess::setStartupInfo(STARTUPINFO &si) { - static char g_desktopName[] = "winsta0\\Default"; // NOSONAR -- Idiomatic Win32 + static wchar_t g_desktopName[] = L"winsta0\\Default"; // NOSONAR -- Idiomatic Win32 ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); @@ -217,20 +218,20 @@ void MSWindowsProcess::createPipes() } } -std::string MSWindowsProcess::readStdOutput() +std::wstring MSWindowsProcess::readStdOutput() { return readOutput(m_outputPipe); } -std::string MSWindowsProcess::readStdError() +std::wstring MSWindowsProcess::readStdError() { return readOutput(m_errorPipe); } -std::string MSWindowsProcess::readOutput(HANDLE handle) +std::wstring MSWindowsProcess::readOutput(HANDLE handle) { const auto kOutputBufferSize = 4096; - char buffer[kOutputBufferSize]; // NOSONAR -- Idiomatic Win32 + wchar_t buffer[kOutputBufferSize]; // NOSONAR -- Idiomatic Win32 DWORD bytesRead; DWORD totalBytesAvail; @@ -243,7 +244,7 @@ std::string MSWindowsProcess::readOutput(HANDLE handle) } if (totalBytesAvail == 0) { - return ""; + return {}; } if (!ReadFile(handle, buffer, kOutputBufferSize, &bytesRead, nullptr)) { @@ -251,7 +252,7 @@ std::string MSWindowsProcess::readOutput(HANDLE handle) throw std::runtime_error(windowsErrorToString(GetLastError())); } - return std::string(buffer, bytesRead); + return std::wstring(buffer, bytesRead); } } // namespace deskflow::platform diff --git a/src/lib/platform/MSWindowsProcess.h b/src/lib/platform/MSWindowsProcess.h index 93bc44c46..243dd9a4d 100644 --- a/src/lib/platform/MSWindowsProcess.h +++ b/src/lib/platform/MSWindowsProcess.h @@ -20,7 +20,7 @@ const auto kDefaultShutdownTimeout = 10; class MSWindowsProcess { public: - explicit MSWindowsProcess(const std::string &command, HANDLE stdOutput = nullptr, HANDLE stdError = nullptr); + explicit MSWindowsProcess(const std::wstring &command, HANDLE stdOutput = nullptr, HANDLE stdError = nullptr); ~MSWindowsProcess(); BOOL startInForeground(); @@ -28,8 +28,8 @@ public: void shutdown(int timeout = kDefaultShutdownTimeout); DWORD waitForExit(); void createPipes(); - std::string readStdOutput(); - std::string readStdError(); + std::wstring readStdOutput(); + std::wstring readStdError(); PROCESS_INFORMATION info() const { @@ -41,9 +41,9 @@ public: private: void setStartupInfo(STARTUPINFO &si); - static std::string readOutput(HANDLE handle); + static std::wstring readOutput(HANDLE handle); - std::string m_command; + std::wstring m_command; HANDLE m_stdOutput; HANDLE m_stdError; HANDLE m_outputPipe = nullptr; diff --git a/src/lib/platform/MSWindowsScreen.cpp b/src/lib/platform/MSWindowsScreen.cpp index 54fec4218..2a9891255 100644 --- a/src/lib/platform/MSWindowsScreen.cpp +++ b/src/lib/platform/MSWindowsScreen.cpp @@ -112,7 +112,7 @@ MSWindowsScreen::MSWindowsScreen( updateScreenShape(); m_class = createWindowClass(); - m_window = createWindow(m_class, kAppName); + m_window = createWindow(m_class, LPCWSTR(kAppName)); setupMouseKeys(); LOG_DEBUG("screen shape: %d,%d %dx%d %s", m_x, m_y, m_w, m_h, m_multimon ? "(multi-monitor)" : ""); LOG_DEBUG("window is 0x%08x", m_window); @@ -786,7 +786,7 @@ ATOM MSWindowsScreen::createWindowClass() const classInfo.hCursor = nullptr; classInfo.hbrBackground = nullptr; classInfo.lpszMenuName = nullptr; - classInfo.lpszClassName = kAppName; + classInfo.lpszClassName = LPCWSTR(kAppName); classInfo.hIconSm = nullptr; return RegisterClassEx(&classInfo); } @@ -798,7 +798,7 @@ void MSWindowsScreen::destroyClass(ATOM windowClass) const } } -HWND MSWindowsScreen::createWindow(ATOM windowClass, const char *name) const +HWND MSWindowsScreen::createWindow(ATOM windowClass, const wchar_t *name) const { HWND window = CreateWindowEx( WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW, MAKEINTATOM(windowClass), name, WS_POPUP, 0, 0, 1, 1, diff --git a/src/lib/platform/MSWindowsScreen.h b/src/lib/platform/MSWindowsScreen.h index d04f50a27..c11389e14 100644 --- a/src/lib/platform/MSWindowsScreen.h +++ b/src/lib/platform/MSWindowsScreen.h @@ -142,7 +142,7 @@ private: ATOM createWindowClass() const; ATOM createDeskWindowClass(bool isPrimary) const; void destroyClass(ATOM windowClass) const; - HWND createWindow(ATOM windowClass, const char *name) const; + HWND createWindow(ATOM windowClass, const wchar_t *name) const; void destroyWindow(HWND) const; // convenience function to send events diff --git a/src/lib/platform/MSWindowsScreenSaver.cpp b/src/lib/platform/MSWindowsScreenSaver.cpp index 2f664da27..f86669a76 100644 --- a/src/lib/platform/MSWindowsScreenSaver.cpp +++ b/src/lib/platform/MSWindowsScreenSaver.cpp @@ -21,9 +21,9 @@ #define SPI_GETSCREENSAVERRUNNING 114 #endif -static const TCHAR *g_isSecureNT = "ScreenSaverIsSecure"; -static const TCHAR *g_isSecure9x = "ScreenSaveUsePassword"; -static const TCHAR *const g_pathScreenSaverIsSecure[] = {"Control Panel", "Desktop", nullptr}; +static const TCHAR *g_isSecureNT = L"ScreenSaverIsSecure"; +static const TCHAR *g_isSecure9x = L"ScreenSaveUsePassword"; +static const TCHAR *const g_pathScreenSaverIsSecure[] = {L"Control Panel", L"Desktop", nullptr}; // // MSWindowsScreenSaver @@ -121,7 +121,7 @@ void MSWindowsScreenSaver::deactivate() bool killed = false; // NT runs screen saver in another desktop - HDESK desktop = OpenDesktop("Screen-saver", 0, FALSE, DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS); + HDESK desktop = OpenDesktop(L"Screen-saver", 0, FALSE, DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS); if (desktop != nullptr) { EnumDesktopWindows(desktop, &MSWindowsScreenSaver::killScreenSaverFunc, reinterpret_cast(&killed)); CloseDesktop(desktop); @@ -130,10 +130,10 @@ void MSWindowsScreenSaver::deactivate() // if above failed or wasn't tried, try the windows 95 way if (!killed) { // find screen saver window and close it - HWND hwnd = FindWindow("WindowsScreenSaverClass", nullptr); + HWND hwnd = FindWindow(L"WindowsScreenSaverClass", nullptr); if (hwnd == nullptr) { // win2k may use a different class - hwnd = FindWindow("Default Screen Saver", nullptr); + hwnd = FindWindow(L"Default Screen Saver", nullptr); } if (hwnd != nullptr) { PostMessage(hwnd, WM_CLOSE, 0, 0); @@ -284,9 +284,9 @@ bool MSWindowsScreenSaver::isSecure(bool *wasSecureFlagAnInt) const } case ArchMiscWindows::kSTRING: { - std::string value = ArchMiscWindows::readValueString(hkey, g_isSecureNT); + std::wstring value = ArchMiscWindows::readValueString(hkey, g_isSecureNT); *wasSecureFlagAnInt = false; - result = (value != "0"); + result = (value != L"0"); break; } } diff --git a/src/lib/platform/MSWindowsSession.cpp b/src/lib/platform/MSWindowsSession.cpp index b4d1120cb..f53715301 100644 --- a/src/lib/platform/MSWindowsSession.cpp +++ b/src/lib/platform/MSWindowsSession.cpp @@ -16,7 +16,7 @@ MSWindowsSession::MSWindowsSession() : m_activeSessionId(-1) { } -bool MSWindowsSession::isProcessInSession(const char *name, PHANDLE process = nullptr) +bool MSWindowsSession::isProcessInSession(const wchar_t *name, PHANDLE process = nullptr) { // first we need to take a snapshot of the running processes HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); @@ -37,7 +37,7 @@ bool MSWindowsSession::isProcessInSession(const char *name, PHANDLE process = nu } // used to record process names for debug info - std::list nameList; + std::list nameList; // now just iterate until we can find winlogon.exe pid DWORD pid = 0; @@ -64,7 +64,7 @@ bool MSWindowsSession::isProcessInSession(const char *name, PHANDLE process = nu // store the names so we can record them for debug nameList.push_back(entry.szExeFile); - if (_stricmp(entry.szExeFile, name) == 0) { + if (_wcsicmp(entry.szExeFile, name) == 0) { pid = entry.th32ProcessID; } } @@ -75,10 +75,10 @@ bool MSWindowsSession::isProcessInSession(const char *name, PHANDLE process = nu gotEntry = nextProcessEntry(snapshot, &entry); } - std::string nameListJoin; - for (std::list::iterator it = nameList.begin(); it != nameList.end(); it++) { + std::wstring nameListJoin; + for (std::list::iterator it = nameList.begin(); it != nameList.end(); it++) { nameListJoin.append(*it); - nameListJoin.append(", "); + nameListJoin.append(L", "); } LOG_DEBUG2("processes in session %d: %s", m_activeSessionId, nameListJoin.c_str()); diff --git a/src/lib/platform/MSWindowsSession.h b/src/lib/platform/MSWindowsSession.h index 679690016..f08c875cf 100644 --- a/src/lib/platform/MSWindowsSession.h +++ b/src/lib/platform/MSWindowsSession.h @@ -6,8 +6,6 @@ #pragma once -#include - #define WIN32_LEAN_AND_MEAN #include @@ -25,7 +23,7 @@ public: */ BOOL hasChanged(); - bool isProcessInSession(const char *name, PHANDLE process); + bool isProcessInSession(const wchar_t *name, PHANDLE process); HANDLE getUserToken(LPSECURITY_ATTRIBUTES security); void updateActiveSession(); diff --git a/src/lib/platform/MSWindowsWatchdog.cpp b/src/lib/platform/MSWindowsWatchdog.cpp index 7ee6224b1..3ede7fd7e 100644 --- a/src/lib/platform/MSWindowsWatchdog.cpp +++ b/src/lib/platform/MSWindowsWatchdog.cpp @@ -23,44 +23,23 @@ #define WIN32_LEAN_AND_MEAN #include #include -#include #include +#include + // // Free functions // -std::string trimOutputBuffer(const CHAR *buffer) -{ - // strip out windows \r chars to prevent extra lines in log file. - std::string output(buffer); - if (output.empty()) { - LOG_DEBUG1("output buffer is empty"); - return output; - } - - size_t pos = 0; - while ((pos = output.find("\r", pos)) != std::string::npos) { - output.replace(pos, 1, ""); - } - - // trip ending newline, as file writer will add it's own newline. - if (output[output.length() - 1] == '\n') { - output = output.substr(0, output.length() - 1); - } - - return output; -} - HANDLE openProcessForKill(const PROCESSENTRY32 &entry) { // pid 0 is 'system idle process' if (entry.th32ProcessID == 0) return nullptr; - if (_stricmp(entry.szExeFile, "deskflow-client.exe") != 0 && // - _stricmp(entry.szExeFile, "deskflow-server.exe") != 0 && // - _stricmp(entry.szExeFile, "deskflow-core.exe") != 0) { + if (_wcsicmp(entry.szExeFile, L"deskflow-client.exe") != 0 && // + _wcsicmp(entry.szExeFile, L"deskflow-server.exe") != 0 && // + _wcsicmp(entry.szExeFile, L"deskflow-core.exe") != 0) { return nullptr; } @@ -155,7 +134,7 @@ MSWindowsWatchdog::getUserToken(LPSECURITY_ATTRIBUTES security, bool elevatedTok LOG_DEBUG("getting elevated token"); HANDLE process; - if (!m_session.isProcessInSession("winlogon.exe", &process)) { + if (!m_session.isProcessInSession(L"winlogon.exe", &process)) { throw std::runtime_error("cannot get user token without winlogon.exe"); } @@ -330,7 +309,7 @@ void MSWindowsWatchdog::setProcessConfig(const std::string_view &command, bool e std::scoped_lock lock{m_processStateMutex}; LOG_DEBUG("setting watchdog process config"); - m_command = command; + m_command = std::wstring(command.begin(), command.end()); m_elevateProcess = elevate; if (m_command.empty()) { @@ -345,35 +324,49 @@ void MSWindowsWatchdog::setProcessConfig(const std::string_view &command, bool e void MSWindowsWatchdog::outputLoop(void *) { - const auto kOutputBufferSize = 4096; + static constexpr DWORD kBufSize = 4096; - // +1 char for \0 - CHAR buffer[kOutputBufferSize + 1]; + BYTE raw[kBufSize]; + DWORD bytesRead = 0; + + // Warning: Manual decoding while we still use Win32 APIs for process launching and output reading. + // Using a byte decoder should help to prevent mojibake when we get a partial UTF-8 sequence in a read chunk. + // In future when we move to Qt process APIs, this can all be simplified. + QStringDecoder decoder(QStringDecoder::Utf8); while (m_running) { + const BOOL ok = ::ReadFile(m_outputReadPipe, raw, kBufSize, &bytesRead, nullptr); - DWORD bytesRead; - BOOL success = ReadFile(m_outputReadPipe, buffer, kOutputBufferSize, &bytesRead, nullptr); - - if (!success || bytesRead == 0) { - // Sleep for only 100ms rather than 1 second so that the service can shut down faster. - Arch::sleep(0.1); - } else { - buffer[bytesRead] = '\0'; - - // strip out windows \r chars to prevent extra lines in log file. - std::string output = trimOutputBuffer(buffer); - m_fileLogOutputter.write(LogLevel::Print, output.c_str()); - -#if SYSAPI_WIN32 - if (m_foreground) { - // when in foreground mode (useful for debugging), send the core - // process output to the VS debug output window. - // we could use the MSWindowsDebugOutputter, but it's really fiddly to - // so, and there doesn't seem to be an advantage of doing that. - OutputDebugString(buffer); + if (!ok) { + const DWORD err = ::GetLastError(); + if (err == ERROR_BROKEN_PIPE) { + // It doesn't make sense to keep reading the pipe if the process has exited and closed its end of the pipe. + LOG_DEBUG("output pipe closed, exiting output loop"); + break; } -#endif + + // Retry immediately when we get a transient error like ERROR_NO_DATA (pipe is non-blocking). + continue; + } + + if (bytesRead == 0) { + // Sleep for short moment so we're not busy looping while the Core is quiet (which is the case most of the time). + // Important: Keep the sleep short so the service can shut down fast. + Arch::sleep(0.1); + LOG_DEBUG("no more data to read from output pipe"); + break; + } + + const QString decoded = + decoder.decode(QByteArray::fromRawData(reinterpret_cast(raw), int(bytesRead))); + + // The file log outputter adds its own newlines, so trim the decoded string to avoid double newlines. + const auto trimmed = decoded.trimmed(); + m_fileLogOutputter.write(LogLevel::Print, trimmed); + + if (m_foreground) { + // Doesn't add it's own newlines, so use the original ones from the process output. + ::OutputDebugString(decoded.toStdWString().c_str()); } } } @@ -497,7 +490,7 @@ void MSWindowsWatchdog::initSasFunc() { // the SendSAS function is used to send a sas (secure attention sequence) to the // winlogon process. this is used to switch to the login screen. - HINSTANCE sasLib = LoadLibrary("sas.dll"); + HINSTANCE sasLib = LoadLibrary(L"sas.dll"); if (!sasLib) { LOG_ERR("could not load sas.dll"); throw std::runtime_error(windowsErrorToString(GetLastError())); @@ -529,7 +522,7 @@ void MSWindowsWatchdog::sasLoop(void *) // NOSONAR - Thread entry point signatur } // Create a an event so that other processes can tell the daemon to call the `SendSAS` function. - MSWindowsHandle sendSasEvent(CreateEvent(nullptr, FALSE, FALSE, kSendSasEventName)); + MSWindowsHandle sendSasEvent(CreateEvent(nullptr, FALSE, FALSE, LPCWSTR(kSendSasEventName))); if (sendSasEvent.get() == nullptr) { LOG_ERR("could not create SAS event, error: %s", windowsErrorToString(GetLastError()).c_str()); Arch::sleep(1); diff --git a/src/lib/platform/MSWindowsWatchdog.h b/src/lib/platform/MSWindowsWatchdog.h index c37f989eb..e397bc6b0 100644 --- a/src/lib/platform/MSWindowsWatchdog.h +++ b/src/lib/platform/MSWindowsWatchdog.h @@ -140,11 +140,11 @@ private: int m_startFailures = 0; FileLogOutputter &m_fileLogOutputter; bool m_foreground = false; - std::string m_activeDesktop = ""; + std::wstring m_activeDesktop = {}; std::unique_ptr m_process; std::optional m_nextStartTime = std::nullopt; ProcessState m_processState = ProcessState::Idle; - std::string m_command = ""; + std::wstring m_command = {}; SendSas m_sendSasFunc = nullptr; std::mutex m_processStateMutex; }; diff --git a/src/lib/platform/XWindowsClipboard.h b/src/lib/platform/XWindowsClipboard.h index d9636beb5..6b9f4004e 100644 --- a/src/lib/platform/XWindowsClipboard.h +++ b/src/lib/platform/XWindowsClipboard.h @@ -11,6 +11,8 @@ #include "deskflow/ClipboardTypes.h" #include "deskflow/IClipboard.h" +#include + #include #include #include diff --git a/src/lib/platform/XWindowsClipboardTextConverter.cpp b/src/lib/platform/XWindowsClipboardTextConverter.cpp index 4da412779..630f8a2f6 100644 --- a/src/lib/platform/XWindowsClipboardTextConverter.cpp +++ b/src/lib/platform/XWindowsClipboardTextConverter.cpp @@ -7,7 +7,7 @@ #include "platform/XWindowsClipboardTextConverter.h" -#include "base/Unicode.h" +#include // // XWindowsClipboardTextConverter @@ -36,22 +36,10 @@ int XWindowsClipboardTextConverter::getDataSize() const std::string XWindowsClipboardTextConverter::fromIClipboard(const std::string &data) const { - return Unicode::UTF8ToText(data); + return QString::fromStdString(data).toLatin1().toStdString(); } std::string XWindowsClipboardTextConverter::toIClipboard(const std::string &data) const { - // convert to UTF-8 - bool errors; - std::string utf8 = Unicode::textToUTF8(data, &errors); - - // if there were decoding errors then, to support old applications - // that don't understand UTF-8 but can report the exact binary - // UTF-8 representation, see if the data appears to be UTF-8. if - // so then use it as is. - if (errors && Unicode::isUTF8(data)) { - return data; - } - - return utf8; + return QString::fromLatin1(data).toUtf8().toStdString(); } diff --git a/src/lib/platform/XWindowsScreen.h b/src/lib/platform/XWindowsScreen.h index 81b78e46b..637c5a8ce 100644 --- a/src/lib/platform/XWindowsScreen.h +++ b/src/lib/platform/XWindowsScreen.h @@ -17,6 +17,8 @@ #include #include +#include + #include class XWindowsClipboard; diff --git a/src/lib/platform/XWindowsScreenSaver.cpp b/src/lib/platform/XWindowsScreenSaver.cpp index 84232eeea..50500092e 100644 --- a/src/lib/platform/XWindowsScreenSaver.cpp +++ b/src/lib/platform/XWindowsScreenSaver.cpp @@ -6,11 +6,12 @@ * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ +#include "base/Log.h" // include first Qt... + #include "platform/XWindowsScreenSaver.h" #include "base/Event.h" #include "base/IEventQueue.h" -#include "base/Log.h" #include "deskflow/IPlatformScreen.h" #include "platform/XWindowsUtil.h" diff --git a/src/lib/platform/XWindowsUtil.cpp b/src/lib/platform/XWindowsUtil.cpp index dcbe9adf4..3f0c4d2bf 100644 --- a/src/lib/platform/XWindowsUtil.cpp +++ b/src/lib/platform/XWindowsUtil.cpp @@ -5,12 +5,12 @@ * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ -#include "platform/XWindowsUtil.h" +#include "base/Log.h" //Include First -#include "base/Log.h" #include "base/String.h" #include "deskflow/KeyTypes.h" #include "mt/Thread.h" +#include "platform/XWindowsUtil.h" #include #define XK_APL diff --git a/src/lib/server/CMakeLists.txt b/src/lib/server/CMakeLists.txt index bc1413001..a3dc34c08 100644 --- a/src/lib/server/CMakeLists.txt +++ b/src/lib/server/CMakeLists.txt @@ -40,6 +40,8 @@ add_library(server STATIC Server.h ) +target_link_libraries(server PUBLIC common) + if(UNIX) - target_link_libraries(server app) + target_link_libraries(server PUBLIC app) endif() diff --git a/src/unittests/CMakeLists.txt b/src/unittests/CMakeLists.txt index c5a1a49f6..5169adb39 100644 --- a/src/unittests/CMakeLists.txt +++ b/src/unittests/CMakeLists.txt @@ -56,7 +56,6 @@ endfunction() enable_testing() find_package(Qt6 ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Test) -add_subdirectory(arch) add_subdirectory(base) add_subdirectory(common) add_subdirectory(deskflow) diff --git a/src/unittests/arch/ArchStringTests.cpp b/src/unittests/arch/ArchStringTests.cpp deleted file mode 100644 index f4a75615f..000000000 --- a/src/unittests/arch/ArchStringTests.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello - * SPDX-FileCopyrightText: (C) 2014 - 2016 Symless Ltd. - * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception - */ - -#include "ArchStringTests.h" - -#include "arch/ArchString.h" - -void ArchStringTests::initTestCase() -{ - m_arch.init(); - m_log.setFilter(LogLevel::Debug2); -} - -void ArchStringTests::convertStringWCToMB_buffer() -{ - ArchString as; - char buff[20]; - bool errors; - - auto converted = as.convStringWCToMB(buff, L"Hello", 6, &errors); - - QCOMPARE(converted, 6); - QCOMPARE(buff, "Hello"); - QVERIFY(!errors); -} - -void ArchStringTests::convertStringWCToMB_noBuffer() -{ - ArchString as; - bool errors; - - auto converted = as.convStringWCToMB(nullptr, L"Hello", 6, &errors); - - QCOMPARE(converted, 6); - QVERIFY(!errors); -} - -void ArchStringTests::convertStringMBToWC() -{ - ArchString as; - wchar_t buff[20]; - bool errors; - - auto converted = as.convStringMBToWC(buff, "Hello", 6, &errors); - QCOMPARE(converted, 6); - - auto actual = QString::fromStdWString(buff); - auto expected = QString::fromStdWString(L"Hello"); - - QCOMPARE(actual, expected); - QVERIFY(!errors); -} - -QTEST_MAIN(ArchStringTests) diff --git a/src/unittests/arch/ArchStringTests.h b/src/unittests/arch/ArchStringTests.h deleted file mode 100644 index 1e2adade9..000000000 --- a/src/unittests/arch/ArchStringTests.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Deskflow -- mouse and keyboard sharing utility - * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello - * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception - */ - -#include "base/Log.h" - -#include - -class ArchStringTests : public QObject -{ - Q_OBJECT -private Q_SLOTS: - void initTestCase(); - // Test are run in order top to bottom - void convertStringWCToMB_buffer(); - void convertStringWCToMB_noBuffer(); - void convertStringMBToWC(); - -private: - Arch m_arch; - Log m_log; -}; diff --git a/src/unittests/arch/CMakeLists.txt b/src/unittests/arch/CMakeLists.txt deleted file mode 100644 index 141342ce1..000000000 --- a/src/unittests/arch/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-FileCopyrightText: 2025 Deskflow Developers -# SPDX-License-Identifier: MIT - -if(WIN32) - set(extra_libs version) -endif() - -create_test( - NAME ArchStringTests - DEPENDS arch - LIBS base ${extra_libs} - SOURCE ArchStringTests.cpp - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/arch" -) diff --git a/src/unittests/base/LogTests.h b/src/unittests/base/LogTests.h index 436d9fdf4..fe25f26b7 100644 --- a/src/unittests/base/LogTests.h +++ b/src/unittests/base/LogTests.h @@ -4,10 +4,10 @@ * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ -#include - #include "base/Log.h" +#include + class LogTests : public QObject { Q_OBJECT diff --git a/src/unittests/base/UnicodeTests.cpp b/src/unittests/base/UnicodeTests.cpp index f6fd6bbae..fef1d445e 100644 --- a/src/unittests/base/UnicodeTests.cpp +++ b/src/unittests/base/UnicodeTests.cpp @@ -7,7 +7,6 @@ #include "UnicodeTests.h" -#include "arch/ArchString.h" #include "base/Unicode.h" void UnicodeTests::initTestCase() @@ -34,30 +33,4 @@ void UnicodeTests::UTF16ToUTF8() QCOMPARE(result.c_str(), "hello"); } -void UnicodeTests::UCS2ToUTF8_kUCS2() -{ - bool errors; - auto result = Unicode::textToUTF8("hello", &errors, ArchString::EWideCharEncoding::kUCS2); - - QVERIFY(!errors); -#ifdef _WIN32 - QCOMPARE(result, std::string("hello", 5)); // mixed-platform expected result -#else -#ifdef WORDS_BIGENDIAN - QCOMPARE(result, std::string("\0h\0e\0", 5)); // mixed-platform expected result -#else - QCOMPARE(result, std::string("h\0e\0l", 5)); // mixed-platform expected result -#endif // WORDS_BIGENDIAN -#endif // _WIN32 -} - -void UnicodeTests::UCS2ToUTF8() -{ - bool errors; - auto result = Unicode::textToUTF8("hello", &errors); - - QVERIFY(!errors); - QCOMPARE(result, std::string("hello", 5)); // mixed-platform expected result -} - QTEST_MAIN(UnicodeTests) diff --git a/src/unittests/base/UnicodeTests.h b/src/unittests/base/UnicodeTests.h index 7647f055c..899a39f30 100644 --- a/src/unittests/base/UnicodeTests.h +++ b/src/unittests/base/UnicodeTests.h @@ -15,8 +15,6 @@ private Q_SLOTS: void initTestCase(); void UTF32ToUTF8(); void UTF16ToUTF8(); - void UCS2ToUTF8_kUCS2(); - void UCS2ToUTF8(); private: Arch m_arch;