2014-01-10 23:27:44 +00:00
/*
* ZeroTier One - Global Peer to Peer Ethernet
2014-02-16 20:40:22 +00:00
* Copyright ( C ) 2011 - 2014 ZeroTier Networks LLC
2014-01-10 23:27:44 +00:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*
* - -
*
* ZeroTier may be used and distributed under the terms of the GPLv3 , which
* are available at : http : //www.gnu.org/licenses/gpl-3.0.html
*
* If you would like to embed ZeroTier into a commercial application or
* redistribute it in a modified binary form , please contact ZeroTier Networks
* LLC . Start here : http : //www.zerotier.com/
*/
2014-02-28 00:28:55 +00:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2013-11-13 21:50:49 +00:00
# include "mainwindow.h"
2014-01-17 18:36:58 +00:00
# include "installdialog.h"
# include "licensedialog.h"
2013-11-13 21:50:49 +00:00
# include <QApplication>
2014-01-17 18:36:58 +00:00
# include <QDir>
# include <QString>
2014-01-27 06:24:29 +00:00
# include <QFont>
2014-02-28 00:28:55 +00:00
# include <QMessageBox>
# include "../node/Constants.hpp"
# include "../node/Defaults.hpp"
2014-01-27 06:24:29 +00:00
2014-02-28 05:56:57 +00:00
// Uncomment for testing to disable making sure Windows service is running
//#define DISABLE_WINDOWS_SERVICE_MANAGEMENT
2014-01-27 06:24:29 +00:00
# ifdef __WINDOWS__
# include <WinSock2.h>
# include <windows.h>
2014-02-28 00:28:55 +00:00
# include "../windows/ZeroTierOne/ZeroTierOneService.h"
2014-02-28 05:56:57 +00:00
# ifndef DISABLE_WINDOWS_SERVICE_MANAGEMENT
2014-02-28 00:28:55 +00:00
// 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 ;
2014-02-28 05:56:57 +00:00
schService = OpenServiceA ( schSCManager , ZT_SERVICE_NAME , SERVICE_QUERY_STATUS | SERVICE_START ) ;
2014-02-28 00:28:55 +00:00
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 ;
}
2014-02-28 05:56:57 +00:00
StartService ( schService , 0 , NULL ) ;
2014-02-28 00:28:55 +00:00
Sleep ( 500 ) ;
}
CloseServiceHandle ( schService ) ;
CloseServiceHandle ( schSCManager ) ;
return running ;
}
2014-02-28 05:56:57 +00:00
# endif // !DISABLE_WINDOWS_SERVICE_MANAGEMENT
2014-02-28 00:28:55 +00:00
# endif // __WINDOWS__
2014-01-17 18:36:58 +00:00
2014-02-28 00:28:55 +00:00
// Globally visible settings for the app
2014-01-17 18:36:58 +00:00
QSettings * settings = ( QSettings * ) 0 ;
2013-11-13 21:50:49 +00:00
int main ( int argc , char * argv [ ] )
{
QApplication a ( argc , argv ) ;
2014-01-17 18:36:58 +00:00
2014-01-27 06:24:29 +00:00
# ifdef __WINDOWS__
2014-02-28 00:28:55 +00:00
// Start up Winsock2
2014-01-27 06:24:29 +00:00
{
WSADATA wsaData ;
WSAStartup ( MAKEWORD ( 2 , 2 ) , & wsaData ) ;
}
# endif
2014-01-24 21:26:24 +00:00
{
QFile qss ( " :css/stylesheet.css " ) ;
qss . open ( QFile : : ReadOnly ) ;
QString style ( qss . readAll ( ) ) ;
a . setStyleSheet ( style ) ;
}
2014-01-17 18:36:58 +00:00
# ifdef __APPLE__
// If service isn't installed, download and install it
if ( ! QFile : : exists ( " /Library/Application Support/ZeroTier/One/zerotier-one " ) ) {
// InstallDialog is an alternative main window. It will re-launch the app
// when done.
InstallDialog id ;
2014-02-28 00:28:55 +00:00
id . setStyleSheet ( a . styleSheet ( ) ) ;
2014-01-17 18:36:58 +00:00
id . show ( ) ;
return a . exec ( ) ;
}
2014-01-24 21:26:24 +00:00
{
2014-01-25 07:15:14 +00:00
// 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.
2014-01-24 21:26:24 +00:00
QString zt1AppSupport ( QDir : : homePath ( ) + " /Library/Application Support/ZeroTier/One " ) ;
QDir : : root ( ) . mkpath ( zt1AppSupport ) ;
settings = new QSettings ( zt1AppSupport + " /ui.ini " , QSettings : : IniFormat ) ;
}
2014-02-28 00:28:55 +00:00
# else // on non-Apple boxen put it in the standard place using the default format
2014-01-17 18:36:58 +00:00
settings = new QSettings ( " ZeroTier Networks " , " ZeroTier One " ) ;
# endif
if ( ! settings - > value ( " acceptedLicenseV1 " , false ) . toBool ( ) ) {
LicenseDialog ld ;
2014-01-24 21:26:24 +00:00
ld . setStyleSheet ( a . styleSheet ( ) ) ;
2014-01-17 18:36:58 +00:00
ld . exec ( ) ;
}
2014-02-28 05:56:57 +00:00
# if defined(__WINDOWS__) && !defined(DISABLE_WINDOWS_SERVICE_MANAGEMENT)
2014-02-28 00:28:55 +00:00
{
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
2013-11-13 21:50:49 +00:00
MainWindow w ;
w . show ( ) ;
return a . exec ( ) ;
}