first draft of daemon control code

pull/1327/head
Rick V 4 years ago
parent d56706b626
commit 7bd3731e98

@ -43,7 +43,7 @@ operator delete(void* ptr, size_t) noexcept
#ifdef _WIN32
#include <setjmp.h>
#include <tchar.h>
#include <strsafe.h>
extern "C" LONG FAR PASCAL
win32_signal_handler(EXCEPTION_POINTERS*);
extern "C" VOID FAR PASCAL
@ -51,7 +51,8 @@ win32_daemon_entry(DWORD, LPTSTR*);
VOID ReportSvcStatus(DWORD,DWORD,DWORD);
jmp_buf svc_entry;
SERVICE_STATUS SvcStatus;
SERVICE_STATUS_HANDLE SvcStatusHandle;
SERVICE_STATUS_HANDLE SvcStatusHandle;
bool start_as_daemon = false;
#endif
std::shared_ptr<llarp::Context> ctx;
@ -92,101 +93,96 @@ handle_signal_win32(DWORD fdwCtrlType)
void install_win32_daemon()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
TCHAR szPath[MAX_PATH];
SC_HANDLE schSCManager;
SC_HANDLE schService;
std::array<char, 1024> szPath{};
if( !GetModuleFileName( nullptr, szPath, MAX_PATH ) )
{
llarp::LogError("Cannot install service ", GetLastError());
return;
}
if( !GetModuleFileName( nullptr, szPath.data(), MAX_PATH ) )
{
llarp::LogError("Cannot install service ", GetLastError());
return;
}
StringCchCat(szPath.data(), 1024, " --win32-daemon");
// Get a handle to the SCM database.
schSCManager = OpenSCManager(
nullptr, // local computer
nullptr, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
// Get a handle to the SCM database.
schSCManager = OpenSCManager(
nullptr, // local computer
nullptr, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (nullptr == schSCManager)
{
llarp::LogError("OpenSCManager failed ", GetLastError());
return;
}
if (nullptr == schSCManager)
{
llarp::LogError("OpenSCManager failed ", GetLastError());
return;
}
// Create the service
schService = CreateService(
schSCManager, // SCM database
"lokinet", // name of service
"Lokinet for Windows", // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
szPath, // path to service's binary
nullptr, // no load ordering group
nullptr, // no tag identifier
nullptr, // no dependencies
nullptr, // LocalSystem account
nullptr); // no password
// Create the service
schService = CreateService(
schSCManager, // SCM database
"lokinet", // name of service
"Lokinet for Windows", // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
szPath.data(), // path to service's binary
nullptr, // no load ordering group
nullptr, // no tag identifier
nullptr, // no dependencies
nullptr, // LocalSystem account
nullptr); // no password
if (schService == nullptr)
{
llarp::LogError("CreateService failed ", GetLastError());
CloseServiceHandle(schSCManager);
return;
}
else llarp::LogInfo("Service installed successfully");
CloseServiceHandle(schService);
if (schService == nullptr)
{
llarp::LogError("CreateService failed ", GetLastError());
CloseServiceHandle(schSCManager);
return;
}
else llarp::LogInfo("Service installed successfully");
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
void uninstall_win32_daemon()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
SERVICE_STATUS ssStatus;
// Get a handle to the SCM database.
SC_HANDLE schSCManager;
SC_HANDLE schService;
// Get a handle to the SCM database.
schSCManager = OpenSCManager(
nullptr, // local computer
nullptr, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
schSCManager = OpenSCManager(
nullptr, // local computer
nullptr, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (nullptr == schSCManager)
{
llarp::LogError("OpenSCManager failed ", GetLastError());
return;
}
// Get a handle to the service.
if (nullptr == schSCManager)
{
llarp::LogError("OpenSCManager failed ", GetLastError());
return;
}
schService = OpenService(
schSCManager, // SCM database
"lokinet", // name of service
0x10000); // need delete access
// Get a handle to the service.
schService = OpenService(
schSCManager, // SCM database
"lokinet", // name of service
0x10000); // need delete access
if (schService == nullptr)
{
llarp::LogError("OpenService failed ", GetLastError());
CloseServiceHandle(schSCManager);
return;
}
if (schService == nullptr)
{
llarp::LogError("OpenService failed ", GetLastError());
CloseServiceHandle(schSCManager);
return;
}
// Delete the service.
if (! DeleteService(schService) )
{
llarp::LogError("DeleteService failed ", GetLastError());
}
else llarp::LogInfo("Service deleted successfully\n");
// Delete the service.
if (! DeleteService(schService) )
{
llarp::LogError("DeleteService failed ", GetLastError());
}
else llarp::LogInfo("Service deleted successfully\n");
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
#endif
@ -246,6 +242,11 @@ main(int argc, char* argv[])
return -1;
SetConsoleCtrlHandler(handle_signal_win32, TRUE);
// SetUnhandledExceptionFilter(win32_signal_handler);
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ "lokinet", (LPSERVICE_MAIN_FUNCTION) win32_daemon_entry },
{ NULL, NULL }
};
#endif
cxxopts::Options options(
"lokinet",
@ -257,6 +258,7 @@ main(int argc, char* argv[])
#ifdef _WIN32
("install", "install win32 daemon to SCM", cxxopts::value<bool>())
("remove", "remove win32 daemon from SCM", cxxopts::value<bool>())
("win32-daemon", "do not use interactively", cxxopts::value<bool>())
#endif
("g,generate", "generate client config", cxxopts::value<bool>())(
"r,relay", "run as relay instead of client", cxxopts::value<bool>())(
@ -302,17 +304,19 @@ main(int argc, char* argv[])
#ifdef _WIN32
if (result.count("install"))
{
// install_win32_daemon();
std::cout << "windows daemon coming soon(tm)" << std::endl;
install_win32_daemon();
return 0;
}
if (result.count("remove"))
{
// uninstall_win32_daemon();
std::cout << "windows daemon coming soon(tm)" << std::endl;
uninstall_win32_daemon();
return 0;
}
if (result.count("win32-daemon"))
{
start_as_daemon = true;
}
#endif
if (result.count("generate") > 0)
{
@ -351,8 +355,13 @@ main(int argc, char* argv[])
}
#ifdef _WIN32
setjmp(svc_entry);
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
if (start_as_daemon)
{
setjmp(svc_entry);
// calling this twice returns a harmless error (daemon already running)
StartServiceCtrlDispatcher(DispatchTable);
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
}
#endif
if (!configFile.empty())
@ -503,6 +512,7 @@ VOID FAR PASCAL SvcCtrlHandler(DWORD dwCtrl)
// The win32 daemon entry point is just a trampoline that returns control
// to the original lokinet entry
// and only gets called if we get --win32-daemon in the command line
VOID FAR PASCAL win32_daemon_entry(DWORD largc, LPTSTR* largv)
{
UNREFERENCED_PARAMETER(largc);

Loading…
Cancel
Save