chore: Remove unused daemon installation and uninstallation methods
This commit is contained in:
committed by
Chris Rizzitello
parent
539ddcaf48
commit
ad383ad9d4
@ -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);
|
||||
|
||||
@ -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 "";
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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();
|
||||
|
||||
Reference in New Issue
Block a user