chore: arch, Remove support for lazy error code to string evaluations

This functionality is not needed because in all code paths the error
code is immediately converted to string without actually using the lazy
evaluation functionality.

based-on: 53dff5b803
ported and expanded by sithlord48
This commit is contained in:
Povilas Kanapickas 2025-05-25 00:38:01 -04:00 committed by Nick Bolton
parent 632c3462ec
commit 314899ac7d
16 changed files with 135 additions and 201 deletions

View file

@ -45,29 +45,10 @@ cleanup but before leaving or returning from the handler.
} catch (...) { \
}
//! Lazy error message string evaluation
/*!
This class encapsulates platform dependent error string lookup.
Platforms subclass this type, taking an appropriate error code
type in the c'tor and overriding eval() to return the error
string for that error code.
*/
class XArchEval
{
public:
XArchEval() = default;
virtual ~XArchEval() noexcept = default;
virtual std::string eval() const = 0;
};
//! Generic exception architecture dependent library
class XArch : public std::runtime_error
{
public:
explicit XArch(XArchEval *adopted) : std::runtime_error(adopted->eval())
{
delete adopted;
}
explicit XArch(const std::string &msg) : std::runtime_error(msg)
{
}
@ -79,9 +60,6 @@ public:
class name_ : public super_ \
{ \
public: \
name_(XArchEval *adoptedEvaluator) : super_(adoptedEvaluator) \
{ \
} \
name_(const std::string &msg) : super_(msg) \
{ \
} \

View file

@ -1,5 +1,6 @@
/*
* 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
@ -7,6 +8,7 @@
#include "arch/unix/ArchDaemonUnix.h"
#include "arch/XArch.h"
#include "arch/unix/XArchUnix.h"
#include "base/Log.h"
@ -56,7 +58,7 @@ int ArchDaemonUnix::daemonize(const char *name, DaemonFunc const &func)
switch (fork()) {
case -1:
// failed
throw XArchDaemonFailed(new XArchEvalUnix(errno));
throw XArchDaemonFailed(errorToString(errno));
case 0:
// child

View file

@ -8,6 +8,7 @@
#include "arch/unix/ArchNetworkBSD.h"
#include "arch/Arch.h"
#include "arch/XArch.h"
#include "arch/unix/ArchMultithreadPosix.h"
#include "arch/unix/XArchUnix.h"
@ -751,11 +752,11 @@ void ArchNetworkBSD::throwError(int err) const
switch (err) {
case EINTR:
ARCH->testCancelThread();
throw XArchNetworkInterrupted(new XArchEvalUnix(err));
throw XArchNetworkInterrupted(errorToString(err));
case EACCES:
case EPERM:
throw XArchNetworkAccess(new XArchEvalUnix(err));
throw XArchNetworkAccess(errorToString(err));
case ENFILE:
case EMFILE:
@ -766,7 +767,7 @@ void ArchNetworkBSD::throwError(int err) const
#if defined(ENOSR)
case ENOSR:
#endif
throw XArchNetworkResource(new XArchEvalUnix(err));
throw XArchNetworkResource(errorToString(err));
case EPROTOTYPE:
case EPROTONOSUPPORT:
@ -780,40 +781,40 @@ void ArchNetworkBSD::throwError(int err) const
#if defined(ENOPKG)
case ENOPKG:
#endif
throw XArchNetworkSupport(new XArchEvalUnix(err));
throw XArchNetworkSupport(errorToString(err));
case EIO:
throw XArchNetworkIO(new XArchEvalUnix(err));
throw XArchNetworkIO(errorToString(err));
case EADDRNOTAVAIL:
throw XArchNetworkNoAddress(new XArchEvalUnix(err));
throw XArchNetworkNoAddress(errorToString(err));
case EADDRINUSE:
throw XArchNetworkAddressInUse(new XArchEvalUnix(err));
throw XArchNetworkAddressInUse(errorToString(err));
case EHOSTUNREACH:
case ENETUNREACH:
throw XArchNetworkNoRoute(new XArchEvalUnix(err));
throw XArchNetworkNoRoute(errorToString(err));
case ENOTCONN:
throw XArchNetworkNotConnected(new XArchEvalUnix(err));
throw XArchNetworkNotConnected(errorToString(err));
case EPIPE:
throw XArchNetworkShutdown(new XArchEvalUnix(err));
throw XArchNetworkShutdown(errorToString(err));
case ECONNABORTED:
case ECONNRESET:
throw XArchNetworkDisconnected(new XArchEvalUnix(err));
throw XArchNetworkDisconnected(errorToString(err));
case ECONNREFUSED:
throw XArchNetworkConnectionRefused(new XArchEvalUnix(err));
throw XArchNetworkConnectionRefused(errorToString(err));
case EHOSTDOWN:
case ETIMEDOUT:
throw XArchNetworkTimedOut(new XArchEvalUnix(err));
throw XArchNetworkTimedOut(errorToString(err));
default:
throw XArchNetwork(new XArchEvalUnix(err));
throw XArchNetwork(errorToString(err));
}
}

View file

@ -1,5 +1,6 @@
/*
* 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
@ -9,12 +10,8 @@
#include <cstring>
//
// XArchEvalUnix
//
std::string XArchEvalUnix::eval() const
std::string errorToString(int error)
{
// FIXME -- not thread safe
return strerror(m_error);
return std::strerror(error);
}

View file

@ -1,5 +1,6 @@
/*
* 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
@ -7,20 +8,6 @@
#pragma once
#include "arch/XArch.h"
#include <string>
//! Lazy error message string evaluation for unix
class XArchEvalUnix : public XArchEval
{
public:
explicit XArchEvalUnix(int error) : m_error(error)
{
// do nothing
}
~XArchEvalUnix() noexcept override = default;
std::string eval() const override;
private:
int m_error;
};
std::string errorToString(int error);

View file

@ -8,6 +8,7 @@
#include "arch/win32/ArchDaemonWindows.h"
#include "arch/Arch.h"
#include "arch/XArch.h"
#include "arch/win32/ArchMiscWindows.h"
#include "arch/win32/XArchWindows.h"
#include "base/Log.h"
@ -61,7 +62,7 @@ void ArchDaemonWindows::installDaemon(
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_WRITE);
if (mgr == nullptr) {
// can't open service manager
throw XArchDaemonInstallFailed(new XArchEvalWindows);
throw XArchDaemonInstallFailed(windowsErrorToString(GetLastError()));
}
// create the service
@ -75,7 +76,7 @@ void ArchDaemonWindows::installDaemon(
DWORD err = GetLastError();
if (err != ERROR_SERVICE_EXISTS) {
CloseServiceHandle(mgr);
throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
throw XArchDaemonInstallFailed(windowsErrorToString(err));
}
} else {
// done with service (but only try to close if not null)
@ -96,7 +97,7 @@ void ArchDaemonWindows::installDaemon(
} catch (...) {
// ignore
}
throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
throw XArchDaemonInstallFailed(windowsErrorToString(err));
}
// set the description
@ -113,7 +114,7 @@ void ArchDaemonWindows::installDaemon(
} catch (...) {
// ignore
}
throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
throw XArchDaemonInstallFailed(windowsErrorToString(err));
}
ArchMiscWindows::setValue(key, _T("CommandLine"), commandLine);
@ -137,7 +138,7 @@ void ArchDaemonWindows::uninstallDaemon(const char *name)
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_WRITE);
if (mgr == nullptr) {
// can't open service manager
throw XArchDaemonUninstallFailed(new XArchEvalWindows);
throw XArchDaemonUninstallFailed(windowsErrorToString(GetLastError()));
}
// open the service. oddly, you must open a service to delete it.
@ -146,9 +147,9 @@ void ArchDaemonWindows::uninstallDaemon(const char *name)
DWORD err = GetLastError();
CloseServiceHandle(mgr);
if (err != ERROR_SERVICE_DOES_NOT_EXIST) {
throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
throw XArchDaemonUninstallFailed(windowsErrorToString(err));
}
throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err));
throw XArchDaemonUninstallNotInstalled(windowsErrorToString(err));
}
// stop the service. we don't care if we fail.
@ -181,9 +182,9 @@ void ArchDaemonWindows::uninstallDaemon(const char *name)
return;
}
if (err != ERROR_SERVICE_MARKED_FOR_DELETE) {
throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
throw XArchDaemonUninstallFailed(windowsErrorToString(err));
}
throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err));
throw XArchDaemonUninstallNotInstalled(windowsErrorToString(err));
}
}
@ -208,7 +209,7 @@ int ArchDaemonWindows::daemonize(const char *name, DaemonFunc const &func)
if (StartServiceCtrlDispatcher(entry) == 0) {
// StartServiceCtrlDispatcher failed
s_daemon = nullptr;
throw XArchDaemonFailed(new XArchEvalWindows);
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
}
s_daemon = nullptr;
@ -557,7 +558,7 @@ void ArchDaemonWindows::start(const char *name)
// open service manager
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_READ);
if (mgr == nullptr) {
throw XArchDaemonFailed(new XArchEvalWindows());
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
}
// open the service
@ -565,12 +566,12 @@ void ArchDaemonWindows::start(const char *name)
if (service == nullptr) {
CloseServiceHandle(mgr);
throw XArchDaemonFailed(new XArchEvalWindows());
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
}
// start the service
if (!StartService(service, 0, nullptr)) {
throw XArchDaemonFailed(new XArchEvalWindows());
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
}
}
@ -579,7 +580,7 @@ void ArchDaemonWindows::stop(const char *name)
// open service manager
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_READ);
if (mgr == nullptr) {
throw XArchDaemonFailed(new XArchEvalWindows());
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
}
// open the service
@ -587,7 +588,7 @@ void ArchDaemonWindows::stop(const char *name)
if (service == nullptr) {
CloseServiceHandle(mgr);
throw XArchDaemonFailed(new XArchEvalWindows());
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
}
// ask the service to stop, asynchronously
@ -595,7 +596,7 @@ void ArchDaemonWindows::stop(const char *name)
if (!ControlService(service, SERVICE_CONTROL_STOP, &ss)) {
DWORD dwErrCode = GetLastError();
if (dwErrCode != ERROR_SERVICE_NOT_ACTIVE) {
throw XArchDaemonFailed(new XArchEvalWindows());
throw XArchDaemonFailed(windowsErrorToString(GetLastError()));
}
}
}

View file

@ -7,6 +7,7 @@
#include "arch/win32/ArchMiscWindows.h"
#include "arch/XArch.h"
#include "arch/win32/ArchDaemonWindows.h"
#include "arch/win32/XArchWindows.h"
#include "base/Log.h"
@ -409,7 +410,7 @@ std::string ArchMiscWindows::getActiveDesktopName()
HDESK desk = OpenInputDesktop(0, TRUE, GENERIC_READ);
if (desk == nullptr) {
LOG((CLOG_ERR "could not open input desktop"));
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
DWORD size;
@ -530,7 +531,7 @@ bool ArchMiscWindows::isProcessElevated()
HANDLE hToken = nullptr;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
TOKEN_ELEVATION elevation;
@ -538,7 +539,7 @@ bool ArchMiscWindows::isProcessElevated()
try {
DWORD dwSize = sizeof(TOKEN_ELEVATION);
if (!GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &dwSize)) {
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
} catch (...) {
CloseHandle(hToken);

View file

@ -8,6 +8,7 @@
#include "arch/win32/ArchNetworkWinsock.h"
#include "arch/Arch.h"
#include "arch/IArchMultithread.h"
#include "arch/XArch.h"
#include "arch/win32/ArchMultithreadWindows.h"
#include "arch/win32/XArchWindows.h"
@ -141,7 +142,7 @@ void ArchNetworkWinsock::initModule(HMODULE module)
WSADATA data;
int err = startup(version, &data);
if (data.wVersion != version) {
throw XArchNetworkSupport(new XArchEvalWinsock(err));
throw XArchNetworkSupport(winsockErrorToString(err));
}
if (err != 0) {
// some other initialization error
@ -851,12 +852,12 @@ void ArchNetworkWinsock::throwError(int err)
{
switch (err) {
case WSAEACCES:
throw XArchNetworkAccess(new XArchEvalWinsock(err));
throw XArchNetworkAccess(winsockErrorToString(err));
case WSAEMFILE:
case WSAENOBUFS:
case WSAENETDOWN:
throw XArchNetworkResource(new XArchEvalWinsock(err));
throw XArchNetworkResource(winsockErrorToString(err));
case WSAEPROTOTYPE:
case WSAEPROTONOSUPPORT:
@ -870,50 +871,50 @@ void ArchNetworkWinsock::throwError(int err)
case WSANOTINITIALISED:
case WSAVERNOTSUPPORTED:
case WSASYSNOTREADY:
throw XArchNetworkSupport(new XArchEvalWinsock(err));
throw XArchNetworkSupport(winsockErrorToString(err));
case WSAEADDRNOTAVAIL:
throw XArchNetworkNoAddress(new XArchEvalWinsock(err));
throw XArchNetworkNoAddress(winsockErrorToString(err));
case WSAEADDRINUSE:
throw XArchNetworkAddressInUse(new XArchEvalWinsock(err));
throw XArchNetworkAddressInUse(winsockErrorToString(err));
case WSAEHOSTUNREACH:
case WSAENETUNREACH:
throw XArchNetworkNoRoute(new XArchEvalWinsock(err));
throw XArchNetworkNoRoute(winsockErrorToString(err));
case WSAENOTCONN:
throw XArchNetworkNotConnected(new XArchEvalWinsock(err));
throw XArchNetworkNotConnected(winsockErrorToString(err));
case WSAEDISCON:
throw XArchNetworkShutdown(new XArchEvalWinsock(err));
throw XArchNetworkShutdown(winsockErrorToString(err));
case WSAENETRESET:
case WSAECONNABORTED:
case WSAECONNRESET:
throw XArchNetworkDisconnected(new XArchEvalWinsock(err));
throw XArchNetworkDisconnected(winsockErrorToString(err));
case WSAECONNREFUSED:
throw XArchNetworkConnectionRefused(new XArchEvalWinsock(err));
throw XArchNetworkConnectionRefused(winsockErrorToString(err));
case WSAEHOSTDOWN:
case WSAETIMEDOUT:
throw XArchNetworkTimedOut(new XArchEvalWinsock(err));
throw XArchNetworkTimedOut(winsockErrorToString(err));
case WSAHOST_NOT_FOUND:
throw XArchNetworkNameUnknown(new XArchEvalWinsock(err));
throw XArchNetworkNameUnknown(winsockErrorToString(err));
case WSANO_DATA:
throw XArchNetworkNameNoAddress(new XArchEvalWinsock(err));
throw XArchNetworkNameNoAddress(winsockErrorToString(err));
case WSANO_RECOVERY:
throw XArchNetworkNameFailure(new XArchEvalWinsock(err));
throw XArchNetworkNameFailure(winsockErrorToString(err));
case WSATRY_AGAIN:
throw XArchNetworkNameUnavailable(new XArchEvalWinsock(err));
throw XArchNetworkNameUnavailable(winsockErrorToString(err));
default:
throw XArchNetwork(new XArchEvalWinsock(err));
throw XArchNetwork(winsockErrorToString(err));
}
}
@ -921,18 +922,18 @@ void ArchNetworkWinsock::throwNameError(int err)
{
switch (err) {
case WSAHOST_NOT_FOUND:
throw XArchNetworkNameUnknown(new XArchEvalWinsock(err));
throw XArchNetworkNameUnknown(winsockErrorToString(err));
case WSANO_DATA:
throw XArchNetworkNameNoAddress(new XArchEvalWinsock(err));
throw XArchNetworkNameNoAddress(winsockErrorToString(err));
case WSANO_RECOVERY:
throw XArchNetworkNameFailure(new XArchEvalWinsock(err));
throw XArchNetworkNameFailure(winsockErrorToString(err));
case WSATRY_AGAIN:
throw XArchNetworkNameUnavailable(new XArchEvalWinsock(err));
throw XArchNetworkNameUnavailable(winsockErrorToString(err));
default:
throw XArchNetworkName(new XArchEvalWinsock(err));
throw XArchNetworkName(winsockErrorToString(err));
}
}

View file

@ -1,5 +1,6 @@
/*
* 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
@ -9,30 +10,22 @@
#include "arch/win32/ArchNetworkWinsock.h"
#include "base/String.h"
//
// XArchEvalWindows
//
std::string XArchEvalWindows::eval() const throw()
std::string windowsErrorToString(DWORD error)
{
char *cmsg;
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, 0, m_error,
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, 0, error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&cmsg, 0, nullptr
) == 0) {
cmsg = nullptr;
return deskflow::string::sprintf("Unknown error, code %d", m_error);
return deskflow::string::sprintf("Unknown error, code %d", error);
}
std::string smsg(cmsg);
LocalFree(cmsg);
return smsg;
}
//
// XArchEvalWinsock
//
std::string XArchEvalWinsock::eval() const throw()
std::string winsockErrorToString(int error)
{
// built-in windows function for looking up error message strings
// may not look up network error messages correctly. we'll have
@ -204,7 +197,7 @@ std::string XArchEvalWinsock::eval() const throw()
};
for (unsigned int i = 0; s_netErrorCodes[i].m_code != 0; ++i) {
if (s_netErrorCodes[i].m_code == m_error) {
if (s_netErrorCodes[i].m_code == error) {
return s_netErrorCodes[i].m_msg;
}
}

View file

@ -1,5 +1,6 @@
/*
* 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
@ -7,40 +8,10 @@
#pragma once
#include "arch/XArch.h"
#include <string>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
//! Lazy error message string evaluation for windows
class XArchEvalWindows : public XArchEval
{
public:
XArchEvalWindows() : m_error(GetLastError())
{
}
XArchEvalWindows(DWORD error) : m_error(error)
{
}
~XArchEvalWindows() override = default;
virtual std::string eval() const throw();
private:
DWORD m_error;
};
//! Lazy error message string evaluation for winsock
class XArchEvalWinsock : public XArchEval
{
public:
XArchEvalWinsock(int error) : m_error(error)
{
}
~XArchEvalWinsock() override = default;
virtual std::string eval() const throw();
private:
int m_error;
};
std::string winsockErrorToString(int error);
std::string windowsErrorToString(DWORD error);

View file

@ -7,6 +7,7 @@
#include "deskflow/win32/AppUtilWindows.h"
#include "arch/XArch.h"
#include "arch/win32/ArchMiscWindows.h"
#include "arch/win32/XArchWindows.h"
#include "base/Event.h"
@ -28,7 +29,7 @@
AppUtilWindows::AppUtilWindows(IEventQueue *events) : m_events(events), m_exitMode(kExitModeNormal)
{
if (SetConsoleCtrlHandler((PHANDLER_ROUTINE)consoleHandler, TRUE) == FALSE) {
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
m_eventThread = std::thread(&AppUtilWindows::eventLoop, this); // NOSONAR - No jthread on Windows
@ -191,7 +192,7 @@ void AppUtilWindows::eventLoop()
HANDLE hCloseEvent = CreateEventA(nullptr, TRUE, FALSE, kCloseEventName);
if (!hCloseEvent) {
LOG_CRIT("failed to create event for windows event loop");
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
LOG_DEBUG("windows event loop running");

View file

@ -767,16 +767,20 @@ bool MSWindowsKeyState::fakeCtrlAltDel()
// 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));
if (!sendSasEvent.get()) {
XArchEvalWindows error;
LOG_ERR("couldn't open SAS event, unable to simulate ctrl+alt+del, error: %s", error.eval().c_str());
LOG_ERR(
"couldn't open SAS event, unable to simulate ctrl+alt+del, error: %s",
windowsErrorToString(GetLastError()).c_str()
);
return false;
}
// Note: We don't directly call SendSAS, but rather we tell the daemon to do it by setting the event.
LOG_DEBUG("setting SAS event to simulate ctrl+alt+del");
if (!SetEvent(sendSasEvent.get())) {
XArchEvalWindows error;
LOG_ERR("failed to set SAS event, unable to simulate ctrl+alt+del, error: %s", error.eval().c_str());
LOG_ERR(
"failed to set SAS event, unable to simulate ctrl+alt+del, error: %s",
windowsErrorToString(GetLastError()).c_str()
);
return false;
}

View file

@ -1,11 +1,13 @@
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2025 Deskflow Developers
* SPDX-FileCopyrightText: (C) 2025 Symless Ltd.
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
*/
#include "MSWindowsProcess.h"
#include "arch/XArch.h"
#include "arch/win32/XArchWindows.h"
#include "base/Log.h"
@ -59,7 +61,7 @@ BOOL MSWindowsProcess::startAsUser(HANDLE userToken, LPSECURITY_ATTRIBUTES sa)
LPVOID environment;
if (!CreateEnvironmentBlock(&environment, userToken, FALSE)) {
LOG((CLOG_ERR "could not create environment block"));
throw XArch(new XArchEvalWindows);
throw XArch(windowsErrorToString(GetLastError()));
}
ZeroMemory(&m_info, sizeof(PROCESS_INFORMATION));
@ -94,13 +96,13 @@ DWORD MSWindowsProcess::waitForExit()
if (WaitForSingleObject(m_info.hProcess, kMaxWaitMilliseconds) != WAIT_OBJECT_0) {
LOG_ERR("process did not exit within the expected time");
TerminateProcess(m_info.hProcess, 1);
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
DWORD exitCode = 0;
if (!GetExitCodeProcess(m_info.hProcess, &exitCode)) {
LOG_ERR("failed to get exit code, error: %lu", GetLastError());
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
if (exitCode != 0) {
@ -151,8 +153,9 @@ void MSWindowsProcess::shutdown(HANDLE handle, DWORD pid, int timeout)
return;
}
} else {
XArchEvalWindows error;
LOG_ERR("failed to get process exit code for process %d, error: %s", pid, error.eval().c_str());
LOG_ERR(
"failed to get process exit code for process %d, error: %s", pid, windowsErrorToString(GetLastError()).c_str()
);
}
// Wait for process to exit gracefully.
@ -160,8 +163,10 @@ void MSWindowsProcess::shutdown(HANDLE handle, DWORD pid, int timeout)
DWORD waitResult = WaitForSingleObject(handle, timeout * 1000);
if (waitResult == WAIT_OBJECT_0) { // NOSONAR - Readability
if (!GetExitCodeProcess(handle, &exitCode)) {
XArchEvalWindows error;
LOG_ERR("failed to get exit code after process exit for process %d, error: %s", pid, error.eval().c_str());
LOG_ERR(
"failed to get exit code after process exit for process %d, error: %s", pid,
windowsErrorToString(GetLastError()).c_str()
);
}
LOG_DEBUG("process %d was shutdown gracefully with exit code %d", pid, exitCode);
@ -170,16 +175,14 @@ void MSWindowsProcess::shutdown(HANDLE handle, DWORD pid, int timeout)
} else if (waitResult == WAIT_TIMEOUT) {
LOG_WARN("process %d did not exit within the expected time", pid);
} else {
XArchEvalWindows error;
LOG_ERR("error waiting for process %d to exit, error: %s", pid, error.eval().c_str());
LOG_ERR("error waiting for process %d to exit, error: %s", pid, windowsErrorToString(GetLastError()).c_str());
}
// Last resort, terminate the process forcefully.
if (TerminateProcess(handle, kExitSuccess)) {
LOG_WARN("forcefully terminated process %d", pid);
} else {
XArchEvalWindows error;
LOG_ERR("failed to terminate process %d, error: %s", pid, error.eval().c_str());
LOG_ERR("failed to terminate process %d, error: %s", pid, windowsErrorToString(GetLastError()).c_str());
}
}
@ -192,22 +195,22 @@ void MSWindowsProcess::createPipes()
if (!CreatePipe(&m_outputPipe, &m_stdOutput, &saAttr, 0)) {
LOG_ERR("could not create output pipe");
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
if (!CreatePipe(&m_errorPipe, &m_stdError, &saAttr, 0)) {
LOG_ERR("could not create error pipe");
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
// Set the pipes to non-blocking mode
DWORD mode = PIPE_NOWAIT;
if (!SetNamedPipeHandleState(m_outputPipe, &mode, nullptr, nullptr)) {
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
if (!SetNamedPipeHandleState(m_errorPipe, &mode, nullptr, nullptr)) {
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
}
@ -233,7 +236,7 @@ std::string MSWindowsProcess::readOutput(HANDLE handle)
// Check if there is data available in the pipe, which prevents `ReadFile` from freezing execution.
if (!PeekNamedPipe(handle, nullptr, 0, nullptr, &totalBytesAvail, &bytesLeftThisMessage)) {
LOG_ERR("could not peek into pipe");
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
if (totalBytesAvail == 0) {
@ -242,7 +245,7 @@ std::string MSWindowsProcess::readOutput(HANDLE handle)
if (!ReadFile(handle, buffer, kOutputBufferSize, &bytesRead, nullptr)) {
LOG_ERR("could not read from pipe");
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
return std::string(buffer, bytesRead);

View file

@ -452,14 +452,12 @@ bool MSWindowsScreen::getThisCursorPos(LPPOINT pos)
{
auto result = GetCursorPos(pos);
if (!result) {
XArchEvalWindows error1;
LOG_DEBUG("could not get cursor pos, error: %s", error1.eval().c_str());
LOG_DEBUG("could not get cursor pos, error: %s", windowsErrorToString(GetLastError()).c_str());
LOG_DEBUG("retrying get cursor pos");
result = GetCursorPos(pos);
if (!result) {
XArchEvalWindows error2;
LOG((CLOG_DEBUG "could not get cursor pos, error: %s", error2.eval().c_str()));
LOG((CLOG_DEBUG "could not get cursor pos, error: %s", windowsErrorToString(GetLastError()).c_str()));
updateDesktopThread();
}
@ -472,14 +470,12 @@ bool MSWindowsScreen::setThisCursorPos(int x, int y)
{
auto result = SetCursorPos(x, y);
if (!result) {
XArchEvalWindows error1;
LOG_DEBUG("could not set cursor pos, error: %s", error1.eval().c_str());
LOG_DEBUG("could not set cursor pos, error: %s", windowsErrorToString(GetLastError()).c_str());
LOG_DEBUG("retrying to set cursor pos");
result = SetCursorPos(x, y);
if (!result) {
XArchEvalWindows error2;
LOG((CLOG_DEBUG "could not set cursor pos, error: %s", error2.eval().c_str()));
LOG((CLOG_DEBUG "could not set cursor pos, error: %s", windowsErrorToString(GetLastError()).c_str()));
updateDesktopThread();
}
@ -494,19 +490,16 @@ void MSWindowsScreen::updateDesktopThread()
HDESK hDesk = OpenInputDesktop(0, true, GENERIC_ALL);
if (hDesk == nullptr) {
XArchEvalWindows error1;
LOG_DEBUG("could not open input desktop, error: %s", error1.eval().c_str());
LOG_DEBUG("could not open input desktop, error: %s", windowsErrorToString(GetLastError()).c_str());
return;
}
if (!SetThreadDesktop(hDesk)) {
XArchEvalWindows error1;
LOG_DEBUG("could not set thread desktop, error: %s", error1.eval().c_str());
LOG_DEBUG("could not set thread desktop, error: %s", windowsErrorToString(GetLastError()).c_str());
}
if (!CloseDesktop(hDesk)) {
XArchEvalWindows error1;
LOG_DEBUG("could not close desktop, error: %s", error1.eval().c_str());
LOG_DEBUG("could not close desktop, error: %s", windowsErrorToString(GetLastError()).c_str());
}
}

View file

@ -6,6 +6,7 @@
#include "platform/MSWindowsSession.h"
#include "arch/XArch.h"
#include "arch/win32/XArchWindows.h"
#include "base/Log.h"
#include "deskflow/XDeskflow.h"
@ -22,7 +23,7 @@ bool MSWindowsSession::isProcessInSession(const char *name, PHANDLE process = nu
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE) {
LOG((CLOG_ERR "could not get process snapshot"));
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
PROCESSENTRY32 entry;
@ -33,7 +34,7 @@ bool MSWindowsSession::isProcessInSession(const char *name, PHANDLE process = nu
BOOL gotEntry = Process32First(snapshot, &entry);
if (!gotEntry) {
LOG((CLOG_ERR "could not get first process entry"));
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
// used to record process names for debug info
@ -105,7 +106,7 @@ MSWindowsSession::getUserToken(LPSECURITY_ATTRIBUTES security)
HANDLE sourceToken;
if (!WTSQueryUserToken(m_activeSessionId, &sourceToken)) {
LOG((CLOG_ERR "could not get token from session %d", m_activeSessionId));
throw XArch(new XArchEvalWindows);
throw XArch(windowsErrorToString(GetLastError()));
}
HANDLE newToken;
@ -114,7 +115,7 @@ MSWindowsSession::getUserToken(LPSECURITY_ATTRIBUTES security)
)) {
LOG((CLOG_ERR "could not duplicate token"));
throw XArch(new XArchEvalWindows);
throw XArch(windowsErrorToString(GetLastError()));
}
LOG((CLOG_DEBUG "duplicated, new token: %i", newToken));
@ -148,7 +149,7 @@ BOOL MSWindowsSession::nextProcessEntry(HANDLE snapshot, LPPROCESSENTRY32 entry)
// files' error then it's probably something serious.
if (err != ERROR_NO_MORE_FILES) {
LOG((CLOG_ERR "could not get next process entry"));
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
}

View file

@ -7,6 +7,7 @@
#include "platform/MSWindowsWatchdog.h"
#include "arch/Arch.h"
#include "arch/XArch.h"
#include "arch/win32/XArchWindows.h"
#include "base/ELevel.h"
#include "base/Log.h"
@ -66,7 +67,7 @@ HANDLE openProcessForKill(const PROCESSENTRY32 &entry)
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID);
if (handle == nullptr) {
LOG_ERR("could not open process handle for kill");
throw XArch(new XArchEvalWindows);
throw XArch(windowsErrorToString(GetLastError()));
}
// only shut down if not current process (daemon is now the same unified binary).
@ -125,7 +126,7 @@ MSWindowsWatchdog::duplicateProcessToken(HANDLE process, LPSECURITY_ATTRIBUTES s
if (!tokenRet) {
LOG_ERR("could not open token, process handle: %d", process);
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
LOG_DEBUG("got token %i, duplicating", sourceToken);
@ -137,7 +138,7 @@ MSWindowsWatchdog::duplicateProcessToken(HANDLE process, LPSECURITY_ATTRIBUTES s
if (!duplicateRet) {
LOG_ERR("could not duplicate token %i", sourceToken);
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
LOG_DEBUG("duplicated, new token: %i", newToken);
@ -303,7 +304,7 @@ void MSWindowsWatchdog::startProcess()
LOG_ERR("daemon failed to run command, exit code: %d", exitCode);
} else {
LOG_ERR("daemon failed to run command, unknown exit code");
throw XArch(new XArchEvalWindows);
throw XArch(windowsErrorToString(GetLastError()));
}
} else {
// Wait for program to fail. This needs to be 1 second, as the process may take some time to fail.
@ -387,7 +388,7 @@ void MSWindowsWatchdog::shutdownExistingProcesses()
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, kAllProcesses);
if (snapshot == INVALID_HANDLE_VALUE) {
LOG_ERR("could not get process snapshot");
throw XArch(new XArchEvalWindows);
throw XArch(windowsErrorToString(GetLastError()));
}
PROCESSENTRY32 entry;
@ -398,7 +399,7 @@ void MSWindowsWatchdog::shutdownExistingProcesses()
BOOL gotEntry = Process32First(snapshot, &entry);
if (!gotEntry) {
LOG_ERR("could not get first process entry");
throw XArch(new XArchEvalWindows);
throw XArch(windowsErrorToString(GetLastError()));
}
// now just iterate until we can find winlogon.exe pid
@ -419,7 +420,7 @@ void MSWindowsWatchdog::shutdownExistingProcesses()
// only worry about error if it's not the end of the snapshot
LOG_ERR("could not get next process entry");
throw XArch(new XArchEvalWindows);
throw XArch(windowsErrorToString(GetLastError()));
}
}
}
@ -481,14 +482,14 @@ void MSWindowsWatchdog::initOutputReadPipe()
if (!CreatePipe(&m_outputReadPipe, &m_outputWritePipe, &saAttr, 0)) {
LOG_ERR("could not create output pipe");
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
// Set the pipe to non-blocking mode, which allows us to stop the output reader thread immediately
// in order to speed up the shutdown process when the Windows service needs to stop.
if (DWORD mode = PIPE_NOWAIT; !SetNamedPipeHandleState(m_outputReadPipe, &mode, nullptr, nullptr)) {
LOG_ERR("could not set pipe to non-blocking mode");
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
}
@ -499,14 +500,14 @@ void MSWindowsWatchdog::initSasFunc()
HINSTANCE sasLib = LoadLibrary("sas.dll");
if (!sasLib) {
LOG_ERR("could not load sas.dll");
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
LOG_DEBUG("loaded sas.dll, used to simulate ctrl-alt-del");
m_sendSasFunc = (SendSas)GetProcAddress(sasLib, "SendSAS");
if (!m_sendSasFunc) {
LOG_ERR("could not find SendSAS function in sas.dll");
throw XArch(new XArchEvalWindows());
throw XArch(windowsErrorToString(GetLastError()));
}
LOG_DEBUG("found SendSAS function in sas.dll");
@ -530,8 +531,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));
if (sendSasEvent.get() == nullptr) {
XArchEvalWindows error;
LOG_ERR("could not create SAS event, error: %s", error.eval().c_str());
LOG_ERR("could not create SAS event, error: %s", windowsErrorToString(GetLastError()).c_str());
ARCH->sleep(1);
continue;
}