123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- #ifdef _WIN32
- #define _CRT_SECURE_NO_WARNINGS // to use freopen
- #endif
- #include "Win32Service.h"
- #include <assert.h>
- #include <strsafe.h>
- #include <windows.h>
- #include "Daemon.h"
- #include "Log.h"
- I2PService *I2PService::s_service = NULL;
- BOOL I2PService::isService()
- {
- BOOL bIsService = FALSE;
- HWINSTA hWinStation = GetProcessWindowStation();
- if (hWinStation != NULL)
- {
- USEROBJECTFLAGS uof = { 0 };
- if (GetUserObjectInformation(hWinStation, UOI_FLAGS, &uof, sizeof(USEROBJECTFLAGS), NULL) && ((uof.dwFlags & WSF_VISIBLE) == 0))
- {
- bIsService = TRUE;
- }
- }
- return bIsService;
- }
- BOOL I2PService::Run(I2PService &service)
- {
- s_service = &service;
- SERVICE_TABLE_ENTRY serviceTable[] =
- {
- { service.m_name, ServiceMain },
- { NULL, NULL }
- };
- return StartServiceCtrlDispatcher(serviceTable);
- }
- void WINAPI I2PService::ServiceMain(DWORD dwArgc, PSTR *pszArgv)
- {
- assert(s_service != NULL);
- s_service->m_statusHandle = RegisterServiceCtrlHandler(
- s_service->m_name, ServiceCtrlHandler);
- if (s_service->m_statusHandle == NULL)
- {
- throw GetLastError();
- }
- s_service->Start(dwArgc, pszArgv);
- }
- void WINAPI I2PService::ServiceCtrlHandler(DWORD dwCtrl)
- {
- switch (dwCtrl)
- {
- case SERVICE_CONTROL_STOP: s_service->Stop(); break;
- case SERVICE_CONTROL_PAUSE: s_service->Pause(); break;
- case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break;
- case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break;
- case SERVICE_CONTROL_INTERROGATE: break;
- default: break;
- }
- }
- I2PService::I2PService(PSTR pszServiceName,
- BOOL fCanStop,
- BOOL fCanShutdown,
- BOOL fCanPauseContinue)
- {
- m_name = (pszServiceName == NULL) ? (PSTR)"" : pszServiceName;
- m_statusHandle = NULL;
- m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- m_status.dwCurrentState = SERVICE_START_PENDING;
- DWORD dwControlsAccepted = 0;
- if (fCanStop)
- dwControlsAccepted |= SERVICE_ACCEPT_STOP;
- if (fCanShutdown)
- dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
- if (fCanPauseContinue)
- dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
- m_status.dwControlsAccepted = dwControlsAccepted;
- m_status.dwWin32ExitCode = NO_ERROR;
- m_status.dwServiceSpecificExitCode = 0;
- m_status.dwCheckPoint = 0;
- m_status.dwWaitHint = 0;
- m_fStopping = FALSE;
- // Create a manual-reset event that is not signaled at first to indicate
- // the stopped signal of the service.
- m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (m_hStoppedEvent == NULL)
- {
- throw GetLastError();
- }
- }
- I2PService::~I2PService(void)
- {
- if (m_hStoppedEvent)
- {
- CloseHandle(m_hStoppedEvent);
- m_hStoppedEvent = NULL;
- }
- }
- void I2PService::Start(DWORD dwArgc, PSTR *pszArgv)
- {
- try
- {
- SetServiceStatus(SERVICE_START_PENDING);
- OnStart(dwArgc, pszArgv);
- SetServiceStatus(SERVICE_RUNNING);
- }
- catch (DWORD dwError)
- {
- LogPrint(eLogError, "Win32Service Start", dwError);
- SetServiceStatus(SERVICE_STOPPED, dwError);
- }
- catch (...)
- {
- LogPrint(eLogError, "Win32Service failed to start.", EVENTLOG_ERROR_TYPE);
- SetServiceStatus(SERVICE_STOPPED);
- }
- }
- void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv)
- {
- LogPrint(eLogInfo, "Win32Service in OnStart", EVENTLOG_INFORMATION_TYPE);
- Daemon.start();
- //i2p::util::config::OptionParser(dwArgc, pszArgv);
- //i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs);
- //i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"),
- // i2p::util::config::GetArg("-port", 17070));
- _worker = new std::thread(std::bind(&I2PService::WorkerThread, this));
- }
- void I2PService::WorkerThread()
- {
- while (!m_fStopping)
- {
- ::Sleep(1000); // Simulate some lengthy operations.
- }
- // Signal the stopped event.
- SetEvent(m_hStoppedEvent);
- }
- void I2PService::Stop()
- {
- DWORD dwOriginalState = m_status.dwCurrentState;
- try
- {
- SetServiceStatus(SERVICE_STOP_PENDING);
- OnStop();
- SetServiceStatus(SERVICE_STOPPED);
- }
- catch (DWORD dwError)
- {
- LogPrint(eLogInfo, "Win32Service Stop", dwError);
- SetServiceStatus(dwOriginalState);
- }
- catch (...)
- {
- LogPrint(eLogError, "Win32Service failed to stop.", EVENTLOG_ERROR_TYPE);
- SetServiceStatus(dwOriginalState);
- }
- }
- void I2PService::OnStop()
- {
- // Log a service stop message to the Application log.
- LogPrint(eLogInfo, "Win32Service in OnStop", EVENTLOG_INFORMATION_TYPE);
- Daemon.stop();
- m_fStopping = TRUE;
- if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
- {
- throw GetLastError();
- }
- _worker->join();
- delete _worker;
- }
- void I2PService::Pause()
- {
- try
- {
- SetServiceStatus(SERVICE_PAUSE_PENDING);
- OnPause();
- SetServiceStatus(SERVICE_PAUSED);
- }
- catch (DWORD dwError)
- {
- LogPrint(eLogError, "Win32Service Pause", dwError);
- SetServiceStatus(SERVICE_RUNNING);
- }
- catch (...)
- {
- LogPrint(eLogError, "Win32Service failed to pause.", EVENTLOG_ERROR_TYPE);
- SetServiceStatus(SERVICE_RUNNING);
- }
- }
- void I2PService::OnPause()
- {
- }
- void I2PService::Continue()
- {
- try
- {
- SetServiceStatus(SERVICE_CONTINUE_PENDING);
- OnContinue();
- SetServiceStatus(SERVICE_RUNNING);
- }
- catch (DWORD dwError)
- {
- LogPrint(eLogError, "Win32Service Continue", dwError);
- SetServiceStatus(SERVICE_PAUSED);
- }
- catch (...)
- {
- LogPrint(eLogError, "Win32Service failed to resume.", EVENTLOG_ERROR_TYPE);
- SetServiceStatus(SERVICE_PAUSED);
- }
- }
- void I2PService::OnContinue()
- {
- }
- void I2PService::Shutdown()
- {
- try
- {
- OnShutdown();
- SetServiceStatus(SERVICE_STOPPED);
- }
- catch (DWORD dwError)
- {
- LogPrint(eLogError, "Win32Service Shutdown", dwError);
- }
- catch (...)
- {
- LogPrint(eLogError, "Win32Service failed to shut down.", EVENTLOG_ERROR_TYPE);
- }
- }
- void I2PService::OnShutdown()
- {
- }
- void I2PService::SetServiceStatus(DWORD dwCurrentState,
- DWORD dwWin32ExitCode,
- DWORD dwWaitHint)
- {
- static DWORD dwCheckPoint = 1;
- m_status.dwCurrentState = dwCurrentState;
- m_status.dwWin32ExitCode = dwWin32ExitCode;
- m_status.dwWaitHint = dwWaitHint;
- m_status.dwCheckPoint =
- ((dwCurrentState == SERVICE_RUNNING) ||
- (dwCurrentState == SERVICE_STOPPED)) ?
- 0 : dwCheckPoint++;
- ::SetServiceStatus(m_statusHandle, &m_status);
- }
- //*****************************************************************************
- void FreeHandles(SC_HANDLE schSCManager, SC_HANDLE schService)
- {
- if (schSCManager)
- {
- CloseServiceHandle(schSCManager);
- schSCManager = NULL;
- }
- if (schService)
- {
- CloseServiceHandle(schService);
- schService = NULL;
- }
- }
- void InstallService(PCSTR pszServiceName, PCSTR pszDisplayName, DWORD dwStartType, PCSTR pszDependencies, PCSTR pszAccount, PCSTR pszPassword)
- {
- printf("Try to install Win32Service (%s).\n", pszServiceName);
- char szPath[MAX_PATH];
- SC_HANDLE schSCManager = NULL;
- SC_HANDLE schService = NULL;
- if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) == 0)
- {
- printf("GetModuleFileName failed w/err 0x%08lx\n", GetLastError());
- FreeHandles(schSCManager, schService);
- return;
- }
- char SvcOpt[] = " --daemon";
- strncat(szPath, SvcOpt, strlen(SvcOpt));
- // Open the local default service control manager database
- schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);
- if (schSCManager == NULL)
- {
- printf("OpenSCManager failed w/err 0x%08lx\n", GetLastError());
- FreeHandles(schSCManager, schService);
- return;
- }
- // Install the service into SCM by calling CreateService
- schService = CreateService(
- schSCManager, // SCManager database
- pszServiceName, // Name of service
- pszDisplayName, // Name to display
- SERVICE_QUERY_STATUS, // Desired access
- SERVICE_WIN32_OWN_PROCESS, // Service type
- dwStartType, // Service start type
- SERVICE_ERROR_NORMAL, // Error control type
- szPath, // Service's binary
- NULL, // No load ordering group
- NULL, // No tag identifier
- pszDependencies, // Dependencies
- pszAccount, // Service running account
- pszPassword // Password of the account
- );
- if (schService == NULL)
- {
- printf("CreateService failed w/err 0x%08lx\n", GetLastError());
- FreeHandles(schSCManager, schService);
- return;
- }
- printf("Win32Service is installed as %s.\n", pszServiceName);
- // Centralized cleanup for all allocated resources.
- FreeHandles(schSCManager, schService);
- }
- void UninstallService(PCSTR pszServiceName)
- {
- printf("Try to uninstall Win32Service (%s).\n", pszServiceName);
- SC_HANDLE schSCManager = NULL;
- SC_HANDLE schService = NULL;
- SERVICE_STATUS ssSvcStatus = {};
- // Open the local default service control manager database
- schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
- if (schSCManager == NULL)
- {
- printf("OpenSCManager failed w/err 0x%08lx\n", GetLastError());
- FreeHandles(schSCManager, schService);
- return;
- }
- // Open the service with delete, stop, and query status permissions
- schService = OpenService(schSCManager, pszServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE);
- if (schService == NULL)
- {
- printf("OpenService failed w/err 0x%08lx\n", GetLastError());
- FreeHandles(schSCManager, schService);
- return;
- }
- // Try to stop the service
- if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus))
- {
- printf("Stopping %s.\n", pszServiceName);
- Sleep(1000);
- while (QueryServiceStatus(schService, &ssSvcStatus))
- {
- if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
- {
- printf(".");
- Sleep(1000);
- }
- else break;
- }
- if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED)
- {
- printf("\n%s is stopped.\n", pszServiceName);
- }
- else
- {
- printf("\n%s failed to stop.\n", pszServiceName);
- }
- }
- // Now remove the service by calling DeleteService.
- if (!DeleteService(schService))
- {
- printf("DeleteService failed w/err 0x%08lx\n", GetLastError());
- FreeHandles(schSCManager, schService);
- return;
- }
- printf("%s is removed.\n", pszServiceName);
- // Centralized cleanup for all allocated resources.
- FreeHandles(schSCManager, schService);
- }
|