mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-13 22:12:56 +00:00
Windows service works now!
This commit is contained in:
parent
cbeb9c5236
commit
9d05897f7a
@ -38,6 +38,8 @@
|
||||
|
||||
#include "../node/Address.hpp"
|
||||
|
||||
// Right now InstallDialog is only used on Mac
|
||||
|
||||
namespace Ui {
|
||||
class InstallDialog;
|
||||
}
|
||||
|
@ -25,6 +25,10 @@
|
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "installdialog.h"
|
||||
#include "licensedialog.h"
|
||||
@ -33,12 +37,62 @@
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include <QFont>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "../node/Constants.hpp"
|
||||
#include "../node/Defaults.hpp"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <WinSock2.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include "../windows/ZeroTierOne/ZeroTierOneService.h"
|
||||
|
||||
// Returns true if started or already running, false if failed or not installed
|
||||
static bool startWindowsService()
|
||||
{
|
||||
SERVICE_STATUS ssSvcStatus;
|
||||
SC_HANDLE schSCManager = NULL;
|
||||
SC_HANDLE schService = NULL;
|
||||
|
||||
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
||||
if (schSCManager == NULL)
|
||||
return false;
|
||||
|
||||
schService = OpenService(schSCManager, ZT_SERVICE_NAME, SERVICE_QUERY_STATUS | SERVICE_START);
|
||||
if (schService == NULL) {
|
||||
CloseServiceHandle(schSCManager);
|
||||
return false;
|
||||
}
|
||||
|
||||
int tries = 0;
|
||||
bool running = true;
|
||||
|
||||
for(;;) {
|
||||
memset(&ssSvcStatus,0,sizeof(ssSvcStatus));
|
||||
if ((++tries > 20)||(!QueryServiceStatus(schService,&ssSvcStatus))) {
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ssSvcStatus.dwCurrentState == SERVICE_RUNNING) {
|
||||
break;
|
||||
} else if (ssSvcStatus.dwCurrentState == SERVICE_START_PENDING) {
|
||||
Sleep(500);
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&ssSvcStatus,0,sizeof(ssSvcStatus));
|
||||
ControlService(schService, SERVICE_CONTROL_START, &ssSvcStatus);
|
||||
Sleep(500);
|
||||
}
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
return running;
|
||||
}
|
||||
#endif // __WINDOWS__
|
||||
|
||||
// Globally visible settings for the app
|
||||
QSettings *settings = (QSettings *)0;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@ -46,6 +100,7 @@ int main(int argc, char *argv[])
|
||||
QApplication a(argc, argv);
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
// Start up Winsock2
|
||||
{
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2,2),&wsaData);
|
||||
@ -65,12 +120,11 @@ int main(int argc, char *argv[])
|
||||
// InstallDialog is an alternative main window. It will re-launch the app
|
||||
// when done.
|
||||
InstallDialog id;
|
||||
id.setStyleSheet(a.styleSheet());
|
||||
id.show();
|
||||
return a.exec();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
{
|
||||
// Put QSettings here because this is one of the writable directories allowed
|
||||
// in Apple's app store sandbox specs. We might end up in app store someday.
|
||||
@ -78,7 +132,7 @@ int main(int argc, char *argv[])
|
||||
QDir::root().mkpath(zt1AppSupport);
|
||||
settings = new QSettings(zt1AppSupport + "/ui.ini",QSettings::IniFormat);
|
||||
}
|
||||
#else
|
||||
#else // on non-Apple boxen put it in the standard place using the default format
|
||||
settings = new QSettings("ZeroTier Networks","ZeroTier One");
|
||||
#endif
|
||||
|
||||
@ -88,6 +142,48 @@ int main(int argc, char *argv[])
|
||||
ld.exec();
|
||||
}
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
{
|
||||
bool winSvcInstalled = false;
|
||||
while (!startWindowsService()) {
|
||||
if (winSvcInstalled) {
|
||||
// Service was installed and subsequently failed to start again, so
|
||||
// something is wrong!
|
||||
QMessageBox::critical((QWidget *)0,"Service Not Available","Unable to locate or start ZeroTier One service. There may be a problem with the installation. Try installing from the .msi file again or e-mail contact@zerotier.com if you cannot install. (Error: service failed to start)",QMessageBox::Ok);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
BOOL is64Bit = TRUE;
|
||||
#else
|
||||
BOOL is64Bit = FALSE;
|
||||
IsWow64Process(GetCurrentProcess(),&is64Bit);
|
||||
#endif
|
||||
std::string exe(ZeroTier::ZT_DEFAULTS.defaultHomePath + "\\zerotier-one_");
|
||||
exe.append((is64Bit == TRUE) ? "x64.exe" : "x86.exe");
|
||||
|
||||
if (QFile::exists(exe.c_str())) {
|
||||
STARTUPINFOA si;
|
||||
PROCESS_INFORMATION pi;
|
||||
memset(&si,0,sizeof(si));
|
||||
memset(&pi,0,sizeof(pi));
|
||||
if (CreateProcessA(NULL,const_cast <LPSTR>((exe + " -I").c_str()),NULL,NULL,FALSE,CREATE_NO_WINDOW|CREATE_NEW_PROCESS_GROUP,NULL,NULL,&si,&pi)) {
|
||||
WaitForSingleObject(pi.hProcess,INFINITE);
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
winSvcInstalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!winSvcInstalled) {
|
||||
// Service failed to install -- installation problem like missing .exe
|
||||
QMessageBox::critical((QWidget *)0,"Service Not Available","Unable to locate or start ZeroTier One service. There may be a problem with the installation. Try installing from the .msi file again or e-mail contact@zerotier.com if you cannot install. (Error: service not installed)",QMessageBox::Ok);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
MainWindow w;
|
||||
w.show();
|
||||
return a.exec();
|
||||
|
@ -38,32 +38,56 @@
|
||||
<ROW Directory="ZeroTier_1_Dir" Directory_Parent="ProgramFilesFolder" DefaultDir="ZeroTier"/>
|
||||
<ROW Directory="ZeroTier_Dir" Directory_Parent="CommonAppDataFolder" DefaultDir="ZeroTier"/>
|
||||
<ROW Directory="networks.d_Dir" Directory_Parent="One_Dir" DefaultDir="networks.d"/>
|
||||
<ROW Directory="platforms_Dir" Directory_Parent="One_1_Dir" DefaultDir="PLATFO~1|platforms"/>
|
||||
<ROW Directory="tapwindows_Dir" Directory_Parent="One_Dir" DefaultDir="TAP-WI~1|tap-windows"/>
|
||||
<ROW Directory="updates.d_Dir" Directory_Parent="One_Dir" DefaultDir="updates.d"/>
|
||||
<ROW Directory="x64_Dir" Directory_Parent="tapwindows_Dir" DefaultDir="x64"/>
|
||||
<ROW Directory="x86_Dir" Directory_Parent="tapwindows_Dir" DefaultDir="x86"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
|
||||
<ROW Component="One" ComponentId="{5CAAC183-3291-4660-9065-438314DC5181}" Directory_="One_1_Dir" Attributes="0"/>
|
||||
<ROW Component="ProductInformation" ComponentId="{DB078D04-EA8E-4A7C-9001-89BAD932F9D9}" Directory_="APPDIR" Attributes="4" KeyPath="Version"/>
|
||||
<ROW Component="Qt5Core.dll" ComponentId="{F6BFD713-0DD7-411C-BE9A-7A5A902814F2}" Directory_="One_1_Dir" Attributes="0" KeyPath="Qt5Core.dll"/>
|
||||
<ROW Component="Qt5Gui.dll" ComponentId="{9005A0ED-9E05-4E7B-8083-AC57131BCF98}" Directory_="One_1_Dir" Attributes="0" KeyPath="Qt5Gui.dll"/>
|
||||
<ROW Component="Qt5Network.dll" ComponentId="{0ECD4DCF-8E1D-4FF7-BB0D-3A9E1629AFC7}" Directory_="One_1_Dir" Attributes="0" KeyPath="Qt5Network.dll"/>
|
||||
<ROW Component="Qt5Widgets.dll" ComponentId="{7B35E61D-D2F2-4605-AE92-9F0E0765831D}" Directory_="One_1_Dir" Attributes="0" KeyPath="Qt5Widgets.dll"/>
|
||||
<ROW Component="WdfCoinstaller01011.dll" ComponentId="{A417293D-AA26-447A-9A16-E0BCB2084CBA}" Directory_="x64_Dir" Attributes="256" KeyPath="WdfCoinstaller01011.dll"/>
|
||||
<ROW Component="WdfCoinstaller01011.dll_1" ComponentId="{C629091A-4845-4BD8-9E49-3A051FDDBEF9}" Directory_="x86_Dir" Attributes="0" KeyPath="WdfCoinstaller01011.dll_1"/>
|
||||
<ROW Component="devcon_x64.exe" ComponentId="{0711ACF9-EEF5-48B0-95D7-8421B74AE314}" Directory_="One_Dir" Attributes="256" KeyPath="devcon_x64.exe"/>
|
||||
<ROW Component="devcon_x86.exe" ComponentId="{335F6945-AC5D-40DD-B671-C9BA9C304623}" Directory_="One_Dir" Attributes="0" KeyPath="devcon_x86.exe"/>
|
||||
<ROW Component="icudt51.dll" ComponentId="{413E1355-FEFE-4767-95A0-8A4B61B77821}" Directory_="One_1_Dir" Attributes="0" KeyPath="icudt51.dll"/>
|
||||
<ROW Component="icuin51.dll" ComponentId="{2BD5EEFC-E613-49B6-9CC7-01E377F2C73C}" Directory_="One_1_Dir" Attributes="0" KeyPath="icuin51.dll"/>
|
||||
<ROW Component="icuuc51.dll" ComponentId="{CCFECFF4-2B24-4A4B-8D77-2C6E6BBEEB2C}" Directory_="One_1_Dir" Attributes="0" KeyPath="icuuc51.dll"/>
|
||||
<ROW Component="libEGL.dll" ComponentId="{D0C896BF-4145-4C0F-8CE1-577283DA7B4A}" Directory_="One_1_Dir" Attributes="0" KeyPath="libEGL.dll"/>
|
||||
<ROW Component="libGLESv2.dll" ComponentId="{C4DD4C75-1EA8-4679-8706-0E4CD2358D3F}" Directory_="One_1_Dir" Attributes="0" KeyPath="libGLESv2.dll"/>
|
||||
<ROW Component="networks.d" ComponentId="{EF54D0DF-889F-41DC-AF5C-4E7F96AB1C8B}" Directory_="networks.d_Dir" Attributes="0"/>
|
||||
<ROW Component="qwindows.dll" ComponentId="{5B31F279-3A03-4BED-B777-05554F7B00EF}" Directory_="platforms_Dir" Attributes="0" KeyPath="qwindows.dll"/>
|
||||
<ROW Component="updates.d" ComponentId="{E07A5480-3942-4529-A976-E7764542274C}" Directory_="updates.d_Dir" Attributes="0"/>
|
||||
<ROW Component="zerotierone_x64.exe" ComponentId="{DFCFB72D-B055-4E60-B6D8-81FF585C2183}" Directory_="One_Dir" Attributes="256" KeyPath="zerotierone_x64.exe"/>
|
||||
<ROW Component="zerotierone_x86.exe" ComponentId="{5D2F3366-4FE1-40A4-A81A-66C49FA11F1C}" Directory_="One_Dir" Attributes="0" KeyPath="zerotierone_x86.exe"/>
|
||||
<ROW Component="zttap200.cat" ComponentId="{CCBE3FBA-1D6E-4486-914D-7444954DE12B}" Directory_="x64_Dir" Attributes="0" KeyPath="zttap200.cat" Type="0"/>
|
||||
<ROW Component="zttap200.cat_1" ComponentId="{BA0FB826-479C-46E8-AB2C-9017D40A99D8}" Directory_="x86_Dir" Attributes="0" KeyPath="zttap200.cat_1" Type="0"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
|
||||
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="One ProductInformation WdfCoinstaller01011.dll WdfCoinstaller01011.dll_1 devcon_x64.exe devcon_x86.exe networks.d updates.d zttap200.cat zttap200.cat_1"/>
|
||||
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="ProductInformation Qt5Core.dll Qt5Gui.dll Qt5Network.dll Qt5Widgets.dll WdfCoinstaller01011.dll WdfCoinstaller01011.dll_1 devcon_x64.exe devcon_x86.exe icudt51.dll icuin51.dll icuuc51.dll libEGL.dll libGLESv2.dll networks.d qwindows.dll updates.d zerotierone_x64.exe zerotierone_x86.exe zttap200.cat zttap200.cat_1"/>
|
||||
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
|
||||
<ROW File="Qt5Core.dll" Component_="Qt5Core.dll" FileName="Qt5Core.dll" Attributes="0" SourcePath="..\..\..\..\..\..\QtWin32Dlls\Qt5Core.dll" SelfReg="false" NextFile="Qt5Gui.dll"/>
|
||||
<ROW File="Qt5Gui.dll" Component_="Qt5Gui.dll" FileName="Qt5Gui.dll" Attributes="0" SourcePath="..\..\..\..\..\..\QtWin32Dlls\Qt5Gui.dll" SelfReg="false" NextFile="Qt5Network.dll"/>
|
||||
<ROW File="Qt5Network.dll" Component_="Qt5Network.dll" FileName="QT5NET~1.DLL|Qt5Network.dll" Attributes="0" SourcePath="..\..\..\..\..\..\QtWin32Dlls\Qt5Network.dll" SelfReg="false" NextFile="Qt5Widgets.dll"/>
|
||||
<ROW File="Qt5Widgets.dll" Component_="Qt5Widgets.dll" FileName="QT5WID~1.DLL|Qt5Widgets.dll" Attributes="0" SourcePath="..\..\..\..\..\..\QtWin32Dlls\Qt5Widgets.dll" SelfReg="false" NextFile="qwindows.dll"/>
|
||||
<ROW File="WdfCoinstaller01011.dll" Component_="WdfCoinstaller01011.dll" FileName="WDFCOI~1.DLL|WdfCoinstaller01011.dll" Attributes="0" SourcePath="..\..\bin\tap-windows\x64\WdfCoinstaller01011.dll" SelfReg="false" NextFile="zttap200.cat"/>
|
||||
<ROW File="WdfCoinstaller01011.dll_1" Component_="WdfCoinstaller01011.dll_1" FileName="WDFCOI~1.DLL|WdfCoinstaller01011.dll" Attributes="0" SourcePath="..\..\bin\tap-windows\x86\WdfCoinstaller01011.dll" SelfReg="false" NextFile="zttap200.cat_1"/>
|
||||
<ROW File="devcon_x64.exe" Component_="devcon_x64.exe" FileName="DEVCON~1.EXE|devcon_x64.exe" Attributes="0" SourcePath="..\..\bin\devcon\devcon_x64.exe" SelfReg="false" NextFile="devcon_x86.exe" DigSign="true"/>
|
||||
<ROW File="devcon_x86.exe" Component_="devcon_x86.exe" FileName="DEVCON~2.EXE|devcon_x86.exe" Attributes="0" SourcePath="..\..\bin\devcon\devcon_x86.exe" SelfReg="false" DigSign="true"/>
|
||||
<ROW File="devcon_x86.exe" Component_="devcon_x86.exe" FileName="DEVCON~2.EXE|devcon_x86.exe" Attributes="0" SourcePath="..\..\bin\devcon\devcon_x86.exe" SelfReg="false" NextFile="icudt51.dll" DigSign="true"/>
|
||||
<ROW File="icudt51.dll" Component_="icudt51.dll" FileName="icudt51.dll" Attributes="0" SourcePath="..\..\..\..\..\..\QtWin32Dlls\icudt51.dll" SelfReg="false" NextFile="icuin51.dll"/>
|
||||
<ROW File="icuin51.dll" Component_="icuin51.dll" FileName="icuin51.dll" Attributes="0" SourcePath="..\..\..\..\..\..\QtWin32Dlls\icuin51.dll" SelfReg="false" NextFile="icuuc51.dll"/>
|
||||
<ROW File="icuuc51.dll" Component_="icuuc51.dll" FileName="icuuc51.dll" Attributes="0" SourcePath="..\..\..\..\..\..\QtWin32Dlls\icuuc51.dll" SelfReg="false" NextFile="libEGL.dll"/>
|
||||
<ROW File="libEGL.dll" Component_="libEGL.dll" FileName="libEGL.dll" Attributes="0" SourcePath="..\..\..\..\..\..\QtWin32Dlls\libEGL.dll" SelfReg="false" NextFile="libGLESv2.dll"/>
|
||||
<ROW File="libGLESv2.dll" Component_="libGLESv2.dll" FileName="LIBGLE~1.DLL|libGLESv2.dll" Attributes="0" SourcePath="..\..\..\..\..\..\QtWin32Dlls\libGLESv2.dll" SelfReg="false" NextFile="Qt5Core.dll"/>
|
||||
<ROW File="qwindows.dll" Component_="qwindows.dll" FileName="qwindows.dll" Attributes="0" SourcePath="..\..\..\..\..\..\QtWin32Dlls\platforms\qwindows.dll" SelfReg="false" NextFile="zerotierone_x86.exe"/>
|
||||
<ROW File="zerotierone_x64.exe" Component_="zerotierone_x64.exe" FileName="ZEROTI~2.EXE|zerotier-one_x64.exe" Attributes="0" SourcePath="..\..\..\windows\Build\x64\Release\zerotier-one_x64.exe" SelfReg="false" DigSign="true"/>
|
||||
<ROW File="zerotierone_x86.exe" Component_="zerotierone_x86.exe" FileName="ZEROTI~1.EXE|zerotier-one_x86.exe" Attributes="0" SourcePath="..\..\..\windows\Build\Win32\Release\zerotier-one_x86.exe" SelfReg="false" NextFile="zerotierone_x64.exe" DigSign="true"/>
|
||||
<ROW File="zttap200.cat" Component_="zttap200.cat" FileName="zttap200.cat" Attributes="0" SourcePath="..\..\bin\tap-windows\x64\zttap200.cat" SelfReg="false" NextFile="zttap200.inf"/>
|
||||
<ROW File="zttap200.cat_1" Component_="zttap200.cat_1" FileName="zttap200.cat" Attributes="0" SourcePath="..\..\bin\tap-windows\x86\zttap200.cat" SelfReg="false" NextFile="zttap200.inf_1"/>
|
||||
<ROW File="zttap200.inf" Component_="zttap200.cat" FileName="zttap200.inf" Attributes="0" SourcePath="..\..\bin\tap-windows\x64\zttap200.inf" SelfReg="false" NextFile="zttap200.sys"/>
|
||||
@ -133,7 +157,6 @@
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiCreateFolderComponent">
|
||||
<ROW Directory_="networks.d_Dir" Component_="networks.d"/>
|
||||
<ROW Directory_="updates.d_Dir" Component_="updates.d"/>
|
||||
<ROW Directory_="One_1_Dir" Component_="One"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
|
||||
<ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/>
|
||||
|
131
main.cpp
131
main.cpp
@ -382,7 +382,7 @@ static void sighandlerQuit(int sig)
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
// Console signal handler routine to allow CTRL+C to work, mostly for testing
|
||||
static BOOL WINAPI _handlerRoutine(DWORD dwCtrlType)
|
||||
static BOOL WINAPI _winConsoleCtrlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
switch(dwCtrlType) {
|
||||
case CTRL_C_EVENT:
|
||||
@ -508,7 +508,6 @@ int main(int argc,char **argv)
|
||||
#ifdef __WINDOWS__
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2,2),&wsaData);
|
||||
SetConsoleCtrlHandler(&_handlerRoutine,TRUE);
|
||||
#endif
|
||||
|
||||
if ((strstr(argv[0],"zerotier-cli"))||(strstr(argv[0],"ZEROTIER-CLI")))
|
||||
@ -580,7 +579,7 @@ int main(int argc,char **argv)
|
||||
}
|
||||
return 0;
|
||||
} break;
|
||||
#endif
|
||||
#endif // __WINDOWS__
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
@ -596,7 +595,6 @@ int main(int argc,char **argv)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!homeDir)||(strlen(homeDir) == 0))
|
||||
homeDir = ZT_DEFAULTS.defaultHomePath.c_str();
|
||||
|
||||
@ -607,6 +605,7 @@ int main(int argc,char **argv)
|
||||
}
|
||||
mkdir(homeDir,0755); // will fail if it already exists
|
||||
{
|
||||
// Write .pid file to home folder
|
||||
char pidpath[4096];
|
||||
Utils::snprintf(pidpath,sizeof(pidpath),"%s/zerotier-one.pid",homeDir);
|
||||
FILE *pf = fopen(pidpath,"w");
|
||||
@ -615,76 +614,78 @@ int main(int argc,char **argv)
|
||||
fclose(pf);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifdef __WINDOWS__
|
||||
if (IsCurrentUserLocalAdministrator() != TRUE) {
|
||||
fprintf(stderr,"%s: must be run as a local administrator."ZT_EOL_S,argv[0]);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
if (!winRunFromCommandLine) {
|
||||
if (winRunFromCommandLine) {
|
||||
// Running in "interactive" mode (mostly for debugging)
|
||||
if (IsCurrentUserLocalAdministrator() != TRUE) {
|
||||
fprintf(stderr,"%s: must be run as a local administrator."ZT_EOL_S,argv[0]);
|
||||
return 1;
|
||||
}
|
||||
SetConsoleCtrlHandler(&_winConsoleCtrlHandler,TRUE);
|
||||
// continues on to ordinary command line execution code below...
|
||||
} else {
|
||||
// Running from service manager
|
||||
ZeroTierOneService zt1Service;
|
||||
if (CServiceBase::Run(zt1Service) == TRUE) {
|
||||
// Normal termination of service process
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr,"%s: unable to start service (try -h for help)"ZT_EOL_S,argv[0]);
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
int exitCode = 0;
|
||||
try {
|
||||
node = new Node(homeDir,port,controlPort);
|
||||
switch(node->run()) {
|
||||
#ifdef __WINDOWS__
|
||||
case Node::NODE_RESTART_FOR_UPGRADE: {
|
||||
const char *upgPath = node->reasonForTermination();
|
||||
if (upgPath) {
|
||||
if (!ZeroTierOneService::doStartUpgrade(std::string(upgPath))) {
|
||||
exitCode = 3;
|
||||
fprintf(stderr,"%s: abnormal termination: unable to execute update at %s (doStartUpgrade failed)\n",argv[0],(upgPath) ? upgPath : "(unknown path)");
|
||||
}
|
||||
} else {
|
||||
exitCode = 3;
|
||||
fprintf(stderr,"%s: abnormal termination: unable to execute update at %s (no upgrade path provided)\n",argv[0],(upgPath) ? upgPath : "(unknown path)");
|
||||
}
|
||||
} break;
|
||||
#else // __UNIX_LIKE__
|
||||
case Node::NODE_RESTART_FOR_UPGRADE: {
|
||||
const char *upgPath = node->reasonForTermination();
|
||||
// On Unix-type OSes we exec() right into the upgrade. This in turn will
|
||||
// end with us being re-launched either via the upgrade itself or something
|
||||
// like OSX's launchd.
|
||||
if (upgPath) {
|
||||
Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
|
||||
::execl(upgPath,upgPath,(char *)0);
|
||||
}
|
||||
exitCode = 3;
|
||||
fprintf(stderr,"%s: abnormal termination: unable to execute update at %s\n",argv[0],(upgPath) ? upgPath : "(unknown path)");
|
||||
} break;
|
||||
#endif
|
||||
case Node::NODE_UNRECOVERABLE_ERROR: {
|
||||
exitCode = 3;
|
||||
const char *termReason = node->reasonForTermination();
|
||||
fprintf(stderr,"%s: abnormal termination: %s\n",argv[0],(termReason) ? termReason : "(unknown reason)");
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
delete node;
|
||||
node = (Node *)0;
|
||||
} catch ( ... ) {
|
||||
fprintf(stderr,"%s: unexpected exception!"ZT_EOL_S,argv[0]);
|
||||
exitCode = 3;
|
||||
}
|
||||
#ifdef __UNIX_LIKE__
|
||||
Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
|
||||
#endif
|
||||
return exitCode;
|
||||
}
|
||||
#endif
|
||||
|
||||
int exitCode = 0;
|
||||
try {
|
||||
node = new Node(homeDir,port,controlPort);
|
||||
switch(node->run()) {
|
||||
#ifdef __WINDOWS__
|
||||
case Node::NODE_RESTART_FOR_UPGRADE: {
|
||||
const char *upgPath = node->reasonForTermination();
|
||||
if (upgPath) {
|
||||
if (!ZeroTierOneService::doStartUpgrade(std::string(upgPath))) {
|
||||
exitCode = 3;
|
||||
fprintf(stderr,"%s: abnormal termination: unable to execute update at %s (doStartUpgrade failed)\n",argv[0],(upgPath) ? upgPath : "(unknown path)");
|
||||
}
|
||||
} else {
|
||||
exitCode = 3;
|
||||
fprintf(stderr,"%s: abnormal termination: unable to execute update at %s (no upgrade path provided)\n",argv[0],(upgPath) ? upgPath : "(unknown path)");
|
||||
}
|
||||
} break;
|
||||
#else // __UNIX_LIKE__
|
||||
case Node::NODE_RESTART_FOR_UPGRADE: {
|
||||
const char *upgPath = node->reasonForTermination();
|
||||
// On Unix-type OSes we exec() right into the upgrade. This in turn will
|
||||
// end with us being re-launched either via the upgrade itself or something
|
||||
// like OSX's launchd.
|
||||
if (upgPath) {
|
||||
Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
|
||||
::execl(upgPath,upgPath,(char *)0);
|
||||
}
|
||||
exitCode = 3;
|
||||
fprintf(stderr,"%s: abnormal termination: unable to execute update at %s\n",argv[0],(upgPath) ? upgPath : "(unknown path)");
|
||||
} break;
|
||||
#endif
|
||||
case Node::NODE_UNRECOVERABLE_ERROR: {
|
||||
exitCode = 3;
|
||||
const char *termReason = node->reasonForTermination();
|
||||
fprintf(stderr,"%s: abnormal termination: %s\n",argv[0],(termReason) ? termReason : "(unknown reason)");
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
delete node;
|
||||
node = (Node *)0;
|
||||
} catch ( ... ) {
|
||||
fprintf(stderr,"%s: unexpected exception!"ZT_EOL_S,argv[0]);
|
||||
exitCode = 3;
|
||||
}
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
|
||||
#endif
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
@ -50,16 +50,19 @@ std::string InstallService(PSTR pszServiceName,
|
||||
PSTR pszPassword)
|
||||
{
|
||||
std::string ret;
|
||||
char szPath[MAX_PATH];
|
||||
char szPathTmp[MAX_PATH],szPath[MAX_PATH];
|
||||
SC_HANDLE schSCManager = NULL;
|
||||
SC_HANDLE schService = NULL;
|
||||
|
||||
if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) == 0)
|
||||
if (GetModuleFileName(NULL, szPathTmp, ARRAYSIZE(szPath)) == 0)
|
||||
{
|
||||
ret = "GetModuleFileName failed, unable to get path to self";
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Quote path in case it contains spaces
|
||||
_snprintf_s(szPath,sizeof(szPath),"\"%s\"",szPathTmp);
|
||||
|
||||
// Open the local default service control manager database
|
||||
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT |
|
||||
SC_MANAGER_CREATE_SERVICE);
|
||||
|
@ -36,19 +36,44 @@
|
||||
#include "../../node/Utils.hpp"
|
||||
#pragma endregion
|
||||
|
||||
#ifdef ZT_DEBUG_SERVICE
|
||||
FILE *SVCDBGfile = (FILE *)0;
|
||||
ZeroTier::Mutex SVCDBGfile_m;
|
||||
#endif
|
||||
|
||||
ZeroTierOneService::ZeroTierOneService() :
|
||||
CServiceBase(ZT_SERVICE_NAME,TRUE,TRUE,FALSE),
|
||||
_node((ZeroTier::Node *)0)
|
||||
{
|
||||
#ifdef ZT_DEBUG_SERVICE
|
||||
SVCDBGfile_m.lock();
|
||||
if (!SVCDBGfile)
|
||||
SVCDBGfile = fopen(ZT_DEBUG_SERVICE,"a");
|
||||
SVCDBGfile_m.unlock();
|
||||
#endif
|
||||
|
||||
ZT_SVCDBG("ZeroTierOneService::ZeroTierOneService()\r\n");
|
||||
}
|
||||
|
||||
ZeroTierOneService::~ZeroTierOneService(void)
|
||||
{
|
||||
ZT_SVCDBG("ZeroTierOneService::~ZeroTierOneService()\r\n");
|
||||
|
||||
#ifdef ZT_DEBUG_SERVICE
|
||||
SVCDBGfile_m.lock();
|
||||
if (SVCDBGfile) {
|
||||
fclose(SVCDBGfile);
|
||||
SVCDBGfile = (FILE *)0;
|
||||
}
|
||||
SVCDBGfile_m.unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ZeroTierOneService::threadMain()
|
||||
throw()
|
||||
{
|
||||
ZT_SVCDBG("ZeroTierOneService::threadMain()\r\n");
|
||||
|
||||
restart_node:
|
||||
try {
|
||||
{
|
||||
@ -144,8 +169,8 @@ bool ZeroTierOneService::doStartUpgrade(const std::string &msiPath)
|
||||
|
||||
void ZeroTierOneService::OnStart(DWORD dwArgc, LPSTR *lpszArgv)
|
||||
{
|
||||
if (_node)
|
||||
return; // sanity check
|
||||
ZT_SVCDBG("ZeroTierOneService::OnStart()\r\n");
|
||||
|
||||
try {
|
||||
_thread = ZeroTier::Thread::start(this);
|
||||
} catch ( ... ) {
|
||||
@ -155,6 +180,8 @@ void ZeroTierOneService::OnStart(DWORD dwArgc, LPSTR *lpszArgv)
|
||||
|
||||
void ZeroTierOneService::OnStop()
|
||||
{
|
||||
ZT_SVCDBG("ZeroTierOneService::OnStop()\r\n");
|
||||
|
||||
_lock.lock();
|
||||
ZeroTier::Node *n = _node;
|
||||
_lock.unlock();
|
||||
@ -166,6 +193,8 @@ void ZeroTierOneService::OnStop()
|
||||
|
||||
void ZeroTierOneService::OnShutdown()
|
||||
{
|
||||
ZT_SVCDBG("ZeroTierOneService::OnShutdown()\r\n");
|
||||
|
||||
// stop thread on system shutdown (if it hasn't happened already)
|
||||
OnStop();
|
||||
}
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ServiceBase.h"
|
||||
|
||||
#include <string>
|
||||
@ -37,11 +39,23 @@
|
||||
#include "../../node/Mutex.hpp"
|
||||
#include "../../node/Utils.hpp"
|
||||
|
||||
// Uncomment to make debugging Windows services suck slightly less hard.
|
||||
//#define ZT_DEBUG_SERVICE "C:\\ZeroTierOneServiceDebugLog.txt"
|
||||
|
||||
#ifdef ZT_DEBUG_SERVICE
|
||||
extern FILE *SVCDBGfile;
|
||||
extern ZeroTier::Mutex SVCDBGfile_m;
|
||||
#define ZT_SVCDBG(f,...) { SVCDBGfile_m.lock(); fprintf(SVCDBGfile,f,##__VA_ARGS__); fflush(SVCDBGfile); SVCDBGfile_m.unlock(); }
|
||||
#else
|
||||
#define ZT_SVCDBG(f,...) {}
|
||||
#endif
|
||||
|
||||
#define ZT_SERVICE_NAME "ZeroTierOneService"
|
||||
#define ZT_SERVICE_DISPLAY_NAME "ZeroTier One"
|
||||
#define ZT_SERVICE_START_TYPE SERVICE_AUTO_START
|
||||
#define ZT_SERVICE_DEPENDENCIES ""
|
||||
#define ZT_SERVICE_ACCOUNT "NT AUTHORITY\\LocalService"
|
||||
//#define ZT_SERVICE_ACCOUNT "NT AUTHORITY\\LocalService"
|
||||
#define ZT_SERVICE_ACCOUNT NULL
|
||||
#define ZT_SERVICE_PASSWORD NULL
|
||||
|
||||
class ZeroTierOneService : public CServiceBase
|
||||
|
Loading…
x
Reference in New Issue
Block a user