chore: Remove unused daemon installation and uninstallation methods

This commit is contained in:
Nick Bolton
2025-09-10 12:01:41 +01:00
committed by Chris Rizzitello
parent 539ddcaf48
commit ad383ad9d4
8 changed files with 3 additions and 340 deletions

View File

@ -59,12 +59,6 @@ int main(int argc, char **argv)
const auto foregroundOption = QCommandLineOption({"f", "foreground"}, "Run in the foreground (show console)");
parser.addOption(foregroundOption);
const auto installOption = QCommandLineOption({"i", "install"}, "Install as a Windows service");
parser.addOption(installOption);
const auto uninstallOption = QCommandLineOption({"u", "uninstall"}, "Uninstall the Windows service");
parser.addOption(uninstallOption);
parser.process(app);
if (parser.isSet(foregroundOption)) {
@ -83,7 +77,7 @@ int main(int argc, char **argv)
// Default log level to system setting (found in Registry).
auto logLevel = Settings::value(Settings::Daemon::LogLevel).toString().toStdString();
if (logLevel != "") {
if (!logLevel.empty()) {
CLOG->setFilter(logLevel.c_str());
LOG_DEBUG("log level: %s", logLevel.c_str());
}
@ -97,14 +91,6 @@ int main(int argc, char **argv)
}
#endif
if (parser.isSet(installOption)) {
daemon.install();
return s_exitSuccess;
} else if (parser.isSet(uninstallOption)) {
daemon.uninstall();
return s_exitSuccess;
}
const auto ipcServer = new ipc::DaemonIpcServer(&app, qPrintable(DaemonApp::logFilename())); // NOSONAR - Qt managed
ipcServer->listen();
daemon.connectIpcServer(ipcServer);

View File

@ -11,16 +11,6 @@
// ArchDaemonNone
//
void ArchDaemonNone::installDaemon(const char *, const char *, const char *, const char *, const char *)
{
// do nothing
}
void ArchDaemonNone::uninstallDaemon(const char *)
{
// do nothing
}
int ArchDaemonNone::daemonize(const char *name, DaemonFunc const &func)
{
// simply forward the call to func. obviously, this doesn't
@ -28,26 +18,6 @@ int ArchDaemonNone::daemonize(const char *name, DaemonFunc const &func)
return func(1, &name);
}
bool ArchDaemonNone::canInstallDaemon(const char *)
{
return false;
}
bool ArchDaemonNone::isDaemonInstalled(const char *)
{
return false;
}
void ArchDaemonNone::installDaemon()
{
// do nothing
}
void ArchDaemonNone::uninstallDaemon()
{
// do nothing
}
std::string ArchDaemonNone::commandLine() const
{
return "";

View File

@ -13,9 +13,8 @@
//! Dummy implementation of IArchDaemon
/*!
This class implements IArchDaemon for a platform that does not have
daemons. The install and uninstall functions do nothing, the query
functions return false, and \c daemonize() simply calls the passed
This class implements IArchDaemon for a platform that does not have daemons.
The query functions return false, and \c daemonize() simply calls the passed
function and returns its result.
*/
class ArchDaemonNone : public IArchDaemon
@ -25,14 +24,6 @@ public:
~ArchDaemonNone() override = default;
// IArchDaemon overrides
void installDaemon(
const char *name, const char *description, const char *pathname, const char *commandLine, const char *dependencies
) override;
void uninstallDaemon(const char *name) override;
int daemonize(const char *name, DaemonFunc const &func) override;
bool canInstallDaemon(const char *name) override;
bool isDaemonInstalled(const char *name) override;
void installDaemon() override;
void uninstallDaemon() override;
std::string commandLine() const override;
};

View File

@ -26,41 +26,6 @@ public:
//! @name manipulators
//@{
//! Install daemon
/*!
Install a daemon. \c name is the name of the daemon passed to the
system and \c description is a short human readable description of
the daemon. \c pathname is the path to the daemon executable.
\c commandLine should \b not include the name of program as the
first argument. If \c allUsers is true then the daemon will be
installed to start at boot time, otherwise it will be installed to
start when the current user logs in. If \p dependencies is not nullptr
then it's a concatenation of NUL terminated other daemon names
followed by a NUL; the daemon will be configured to startup after
the listed daemons. Throws an \c ArchDaemonException exception on failure.
*/
virtual void installDaemon(
const char *name, const char *description, const char *pathname, const char *commandLine, const char *dependencies
) = 0;
//! Uninstall daemon
/*!
Uninstall a daemon. Throws an \c ArchDaemonException on failure.
*/
virtual void uninstallDaemon(const char *name) = 0;
//! Install daemon
/*!
Installs the default daemon.
*/
virtual void installDaemon() = 0;
//! Uninstall daemon
/*!
Uninstalls the default daemon.
*/
virtual void uninstallDaemon() = 0;
//! Daemonize the process
/*!
Daemonize. Throw ArchDaemonFailedException on error. \c name is the name
@ -90,22 +55,6 @@ public:
*/
virtual int daemonize(const char *name, DaemonFunc const &func) = 0;
//! Check if user has permission to install the daemon
/*!
Returns true iff the caller has permission to install or
uninstall the daemon. Note that even if this method returns
true it's possible that installing/uninstalling the service
may still fail. This method ignores whether or not the
service is already installed.
*/
virtual bool canInstallDaemon(const char *name) = 0;
//! Check if the daemon is installed
/*!
Returns true iff the daemon is installed.
*/
virtual bool isDaemonInstalled(const char *name) = 0;
//@}
//! Get the command line

View File

@ -12,9 +12,7 @@
#include "arch/win32/ArchMiscWindows.h"
#include "arch/win32/XArchWindows.h"
#include "base/Log.h"
#include "common/Constants.h"
inline static const auto kDefaultDaemonName = _T(kAppName);
//
// ArchDaemonWindows
//
@ -54,142 +52,6 @@ void ArchDaemonWindows::daemonFailed(int result)
throw ArchDaemonRunException(result);
}
void ArchDaemonWindows::installDaemon(
const char *name, const char *description, const char *pathname, const char *commandLine, const char *dependencies
)
{
LOG_DEBUG("installing windows service: %s", name);
// open service manager
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_WRITE);
if (mgr == nullptr) {
// can't open service manager
throw ArchDaemonInstallException(windowsErrorToString(GetLastError()));
}
// create the service
SC_HANDLE service = CreateService(
mgr, name, name, 0, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL, pathname, nullptr, nullptr, dependencies, nullptr, nullptr
);
if (service == nullptr) {
// can't create service
DWORD err = GetLastError();
if (err != ERROR_SERVICE_EXISTS) {
CloseServiceHandle(mgr);
throw ArchDaemonInstallException(windowsErrorToString(err));
}
} else {
// done with service (but only try to close if not null)
CloseServiceHandle(service);
}
// done with manager
CloseServiceHandle(mgr);
// open the registry key for this service
HKEY key = openNTServicesKey();
key = ArchMiscWindows::addKey(key, name);
if (key == nullptr) {
// can't open key
DWORD err = GetLastError();
try {
uninstallDaemon(name);
} catch (...) {
// ignore
}
throw ArchDaemonInstallException(windowsErrorToString(err));
}
// set the description
ArchMiscWindows::setValue(key, _T("Description"), description);
// set command line
key = ArchMiscWindows::addKey(key, _T("Parameters"));
if (key == nullptr) {
// can't open key
DWORD err = GetLastError();
ArchMiscWindows::closeKey(key);
try {
uninstallDaemon(name);
} catch (...) {
// ignore
}
throw ArchDaemonInstallException(windowsErrorToString(err));
}
ArchMiscWindows::setValue(key, _T("CommandLine"), commandLine);
// done with registry
ArchMiscWindows::closeKey(key);
}
void ArchDaemonWindows::uninstallDaemon(const char *name)
{
LOG_DEBUG("uninstalling windows service: %s", name);
// remove parameters for this service. ignore failures.
HKEY key = openNTServicesKey();
key = ArchMiscWindows::openKey(key, name);
if (key != nullptr) {
ArchMiscWindows::deleteKey(key, _T("Parameters"));
ArchMiscWindows::closeKey(key);
}
// open service manager
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_WRITE);
if (mgr == nullptr) {
// can't open service manager
throw ArchDaemonUninstallFailedException(windowsErrorToString(GetLastError()));
}
// open the service. oddly, you must open a service to delete it.
SC_HANDLE service = OpenService(mgr, name, DELETE | SERVICE_STOP);
if (service == nullptr) {
DWORD err = GetLastError();
CloseServiceHandle(mgr);
if (err != ERROR_SERVICE_DOES_NOT_EXIST) {
throw ArchDaemonUninstallFailedException(windowsErrorToString(err));
}
throw ArchDaemonUninstallNotInstalledException(windowsErrorToString(err));
}
// stop the service. we don't care if we fail.
SERVICE_STATUS status;
ControlService(service, SERVICE_CONTROL_STOP, &status);
// delete the service
const bool okay = (DeleteService(service) == 0);
const DWORD err = GetLastError();
// clean up
CloseServiceHandle(service);
CloseServiceHandle(mgr);
// give windows a chance to remove the service before we check if it still exists.
// 100ms should be plenty of time.
LOG_DEBUG("waiting for service to be removed");
Arch::sleep(0.1);
// handle failure. ignore error if service isn't installed anymore.
if (!okay && isDaemonInstalled(name)) {
if (err == ERROR_SUCCESS) {
// this seems to occur even though the uninstall was successful.
// it could be a timing issue, i.e., isDaemonInstalled is
// called too soon. i've added a sleep to try and stop this.
return;
}
if (err == ERROR_IO_PENDING) {
// this seems to be a spurious error
return;
}
if (err != ERROR_SERVICE_MARKED_FOR_DELETE) {
throw ArchDaemonUninstallFailedException(windowsErrorToString(err));
}
throw ArchDaemonUninstallNotInstalledException(windowsErrorToString(err));
}
}
int ArchDaemonWindows::daemonize(const char *name, DaemonFunc const &func)
{
assert(name != nullptr);
@ -218,42 +80,6 @@ int ArchDaemonWindows::daemonize(const char *name, DaemonFunc const &func)
return m_daemonResult;
}
bool ArchDaemonWindows::canInstallDaemon(const char * /*name*/)
{
// check if we can open service manager for write
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_WRITE);
if (mgr == nullptr) {
return false;
}
CloseServiceHandle(mgr);
// check if we can open the registry key
HKEY key = openNTServicesKey();
ArchMiscWindows::closeKey(key);
return (key != nullptr);
}
bool ArchDaemonWindows::isDaemonInstalled(const char *name)
{
// open service manager
SC_HANDLE mgr = OpenSCManager(nullptr, nullptr, GENERIC_READ);
if (mgr == nullptr) {
return false;
}
// open the service
SC_HANDLE service = OpenService(mgr, name, GENERIC_READ);
// clean up
if (service != nullptr) {
CloseServiceHandle(service);
}
CloseServiceHandle(mgr);
return (service != nullptr);
}
HKEY ArchDaemonWindows::openNTServicesKey()
{
static const char *s_keyNames[] = {_T("SYSTEM"), _T("CurrentControlSet"), _T("Services"), nullptr};
@ -602,35 +428,3 @@ void ArchDaemonWindows::stop(const char *name)
}
}
}
void ArchDaemonWindows::installDaemon()
{
// install default daemon if not already installed.
if (!isDaemonInstalled(kDefaultDaemonName)) {
char binPath[MAX_PATH];
GetModuleFileName(ArchMiscWindows::instanceWin32(), binPath, MAX_PATH);
// wrap in quotes so a malicious user can't start \Program.exe as admin.
const auto command = "\"" + std::string(binPath) + "\"";
installDaemon(kDefaultDaemonName, DEFAULT_DAEMON_INFO, command.c_str(), "", "");
}
start(kDefaultDaemonName);
}
void ArchDaemonWindows::uninstallDaemon()
{
// remove legacy services if installed.
if (isDaemonInstalled(LEGACY_SERVER_DAEMON_NAME)) {
uninstallDaemon(LEGACY_SERVER_DAEMON_NAME);
}
if (isDaemonInstalled(LEGACY_CLIENT_DAEMON_NAME)) {
uninstallDaemon(LEGACY_CLIENT_DAEMON_NAME);
}
// remove new service if installed.
if (isDaemonInstalled(kDefaultDaemonName)) {
uninstallDaemon(kDefaultDaemonName);
}
}

View File

@ -67,15 +67,7 @@ public:
static UINT getDaemonQuitMessage();
// IArchDaemon overrides
void installDaemon(
const char *name, const char *description, const char *pathname, const char *commandLine, const char *dependencies
) override;
void uninstallDaemon(const char *name) override;
void installDaemon() override;
void uninstallDaemon() override;
int daemonize(const char *name, DaemonFunc const &func) override;
bool canInstallDaemon(const char *name) override;
bool isDaemonInstalled(const char *name) override;
std::string commandLine() const override
{
return m_commandLine;
@ -134,8 +126,3 @@ private:
std::string m_commandLine;
};
#define DEFAULT_DAEMON_INFO _T("Runs the Core process on secure desktops (UAC prompts, login screen, etc).")
#define LEGACY_SERVER_DAEMON_NAME _T("Deskflow Server")
#define LEGACY_CLIENT_DAEMON_NAME _T("Deskflow Client")

View File

@ -122,18 +122,6 @@ void DaemonApp::connectIpcServer(const ipc::DaemonIpcServer *ipcServer) const
);
}
void DaemonApp::install() const
{
LOG_NOTE("installing windows daemon");
ARCH->installDaemon();
}
void DaemonApp::uninstall() const
{
LOG_NOTE("uninstalling windows daemon");
ARCH->uninstallDaemon();
}
void DaemonApp::run(QThread &daemonThread)
{
LOG_NOTE("starting daemon");

View File

@ -48,8 +48,6 @@ public:
~DaemonApp() override;
InitResult init(int argc, char **argv);
void install() const;
void uninstall() const;
void run(QThread &daemonThread);
void setForeground();
void initLogging();