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
This commit is contained in:
@ -46,6 +46,7 @@
|
||||
"logonui",
|
||||
"Lysytsia",
|
||||
"macdeployqt",
|
||||
"mojibake",
|
||||
"msvc",
|
||||
"noquote",
|
||||
"NOSONAR",
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -6,19 +6,22 @@
|
||||
*/
|
||||
|
||||
#include "arch/ArchDaemonNone.h"
|
||||
#include <QString>
|
||||
|
||||
//
|
||||
// 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 {};
|
||||
}
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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 <climits>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
|
||||
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<int>(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<int>(mblen);
|
||||
n -= static_cast<int>(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<int>(mblen);
|
||||
n -= static_cast<int>(mblen);
|
||||
break;
|
||||
}
|
||||
++dst;
|
||||
}
|
||||
len = dst - dst0;
|
||||
}
|
||||
|
||||
return static_cast<int>(len);
|
||||
}
|
||||
@ -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 <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//! 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;
|
||||
|
||||
//@}
|
||||
};
|
||||
@ -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()
|
||||
|
||||
@ -8,8 +8,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
//! Interface for architecture dependent daemonizing
|
||||
/*!
|
||||
@ -53,7 +53,7 @@ public:
|
||||
\c ArchMiscWindows::daemonFailed() to indicate startup failure.
|
||||
</ul>
|
||||
*/
|
||||
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;
|
||||
|
||||
//@}
|
||||
};
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
#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;
|
||||
//@}
|
||||
};
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <QString>
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -7,15 +7,15 @@
|
||||
|
||||
#include "arch/unix/ArchLogUnix.h"
|
||||
|
||||
#include <QString>
|
||||
#include <syslog.h>
|
||||
|
||||
//
|
||||
// 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));
|
||||
}
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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<char *>(name);
|
||||
entry[0].lpServiceName = const_cast<wchar_t *>(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<LPCTSTR>;
|
||||
using Arguments = std::vector<std::string>;
|
||||
const char **argv = const_cast<const char **>(argvIn);
|
||||
using ArgList = std::vector<LPWSTR>;
|
||||
using Arguments = std::vector<std::wstring>;
|
||||
const wchar_t **argv = const_cast<const wchar_t **>(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<const wchar_t **>(&myArgv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
m_commandLine = commandLine;
|
||||
m_commandLine = QString::fromStdWString(commandLine);
|
||||
|
||||
try {
|
||||
// invoke daemon function
|
||||
m_daemonResult = m_daemonFunc(static_cast<int>(argc), argv);
|
||||
m_daemonResult = m_daemonFunc(static_cast<int>(argc), reinterpret_cast<const char **>(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);
|
||||
|
||||
@ -15,7 +15,8 @@
|
||||
#include <tchar.h>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include <QString>
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#include "arch/win32/ArchLogWindows.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <QString>
|
||||
|
||||
//
|
||||
// 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<WORD>(level),
|
||||
0, // event ID
|
||||
nullptr, 0,
|
||||
(DWORD)strlen(msg) + 1, // raw data size
|
||||
(DWORD)(msg.length()) + 1, // raw data size
|
||||
nullptr,
|
||||
const_cast<char *>(msg)
|
||||
const_cast<char *>(qPrintable(msg))
|
||||
); // raw data
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -196,29 +196,29 @@ void ArchMiscWindows::setValue(HKEY key, const TCHAR *name, DWORD value)
|
||||
RegSetValueEx(key, name, 0, REG_DWORD, reinterpret_cast<CONST BYTE *>(&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<BYTE *>(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<STES_t>(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<STES_t>(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<const char *, 2> moduleName
|
||||
}
|
||||
|
||||
for (const auto &moduleName : moduleNames) {
|
||||
if (_stricmp(loadedModuleName.data(), moduleName) == 0) {
|
||||
if (_stricmp((loadedModuleName.data()), moduleName) == 0) {
|
||||
return hModules[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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;
|
||||
|
||||
//@}
|
||||
};
|
||||
|
||||
@ -8,19 +8,20 @@
|
||||
|
||||
#include "base/LogOutputters.h"
|
||||
#include "arch/Arch.h"
|
||||
#include "base/Path.h"
|
||||
#include "base/String.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <QFile>
|
||||
#include <QString>
|
||||
#include <QTextStream>
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "base/ILogOutputter.h"
|
||||
#include "mt/Thread.h"
|
||||
|
||||
#include <QString>
|
||||
//! 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();
|
||||
|
||||
@ -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<const uint8_t *>(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<const uint8_t *>(src), size, errors);
|
||||
|
||||
case kUCS4:
|
||||
return doUCS4ToUTF8(reinterpret_cast<const uint8_t *>(src), size, errors);
|
||||
|
||||
case kUTF16:
|
||||
return doUTF16ToUTF8(reinterpret_cast<const uint8_t *>(src), size, errors);
|
||||
|
||||
case kUTF32:
|
||||
return doUTF32ToUTF8(reinterpret_cast<const uint8_t *>(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
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arch/ArchString.h"
|
||||
#include "common/Common.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@ -6,10 +6,10 @@
|
||||
*/
|
||||
|
||||
#if WINAPI_XWINDOWS
|
||||
#include "base/Log.h"
|
||||
#include <memory>
|
||||
|
||||
#include "DeskflowXkbKeyboard.h"
|
||||
#include "base/Log.h"
|
||||
#include "DeskflowXkbKeyboard.h" // Include last due to X11 use
|
||||
|
||||
namespace deskflow::linux {
|
||||
|
||||
|
||||
@ -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()));
|
||||
|
||||
@ -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()) {
|
||||
|
||||
@ -14,3 +14,5 @@ add_library(io STATIC
|
||||
StreamFilter.cpp
|
||||
StreamFilter.h
|
||||
)
|
||||
|
||||
target_link_libraries(io PUBLIC common)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
MSWindowsClipboardHTMLConverter::MSWindowsClipboardHTMLConverter()
|
||||
{
|
||||
m_format = RegisterClipboardFormat("HTML Format");
|
||||
m_format = RegisterClipboardFormat(L"HTML Format");
|
||||
}
|
||||
|
||||
IClipboard::Format MSWindowsClipboardHTMLConverter::getFormat() const
|
||||
|
||||
@ -9,6 +9,8 @@
|
||||
|
||||
#include "base/Unicode.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
//
|
||||
// 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();
|
||||
}
|
||||
|
||||
@ -9,9 +9,10 @@
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
|
||||
void MSWindowsDebugOutputter::open(const char *title)
|
||||
#include <QString>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
};
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<std::string, Desk *>;
|
||||
using Desks = std::map<std::wstring, Desk *>;
|
||||
|
||||
// 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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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<LPARAM>(&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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<std::string> nameList;
|
||||
std::list<std::wstring> 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<std::string>::iterator it = nameList.begin(); it != nameList.end(); it++) {
|
||||
std::wstring nameListJoin;
|
||||
for (std::list<std::wstring>::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());
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -23,44 +23,23 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <shlobj.h>
|
||||
#include <string.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#include <QStringDecoder>
|
||||
|
||||
//
|
||||
// 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<const char *>(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);
|
||||
|
||||
@ -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<deskflow::platform::MSWindowsProcess> m_process;
|
||||
std::optional<double> 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;
|
||||
};
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#include "deskflow/ClipboardTypes.h"
|
||||
#include "deskflow/IClipboard.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#include "platform/XWindowsClipboardTextConverter.h"
|
||||
|
||||
#include "base/Unicode.h"
|
||||
#include <QString>
|
||||
|
||||
//
|
||||
// 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();
|
||||
}
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
class XWindowsClipboard;
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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 <X11/Xatom.h>
|
||||
#define XK_APL
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
|
||||
* 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)
|
||||
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Deskflow -- mouse and keyboard sharing utility
|
||||
* SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello <sithlord48@gmail.com>
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include "base/Log.h"
|
||||
|
||||
#include <QTest>
|
||||
|
||||
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;
|
||||
};
|
||||
@ -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"
|
||||
)
|
||||
@ -4,10 +4,10 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||
*/
|
||||
|
||||
#include <QTest>
|
||||
|
||||
#include "base/Log.h"
|
||||
|
||||
#include <QTest>
|
||||
|
||||
class LogTests : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -15,8 +15,6 @@ private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void UTF32ToUTF8();
|
||||
void UTF16ToUTF8();
|
||||
void UCS2ToUTF8_kUCS2();
|
||||
void UCS2ToUTF8();
|
||||
|
||||
private:
|
||||
Arch m_arch;
|
||||
|
||||
Reference in New Issue
Block a user