You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openvpn-gui/service.c

337 lines
8.8 KiB

/*
* OpenVPN-GUI -- A Windows GUI for OpenVPN.
*
* Copyright (C) 2004 Mathias Sundman <mathias@nilings.se>
*
* 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 2 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 (see the file COPYING included with this
* distribution); if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <windows.h>
#include <stdio.h>
#include "tray.h"
#include "service.h"
#include "openvpn.h"
#include "options.h"
#include "scripts.h"
#include "main.h"
#include "openvpn-gui-res.h"
#include "localization.h"
extern options_t o;
int MyStartService()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
SERVICE_STATUS ssStatus;
DWORD dwOldCheckPoint;
DWORD dwStartTickCount;
DWORD dwWaitTime;
int i;
/* Set Service Status = Connecting */
o.service_state = service_connecting;
SetServiceMenuStatus();
CheckAndSetTrayIcon();
// Open a handle to the SC Manager database.
schSCManager = OpenSCManager(
NULL, // local machine
NULL, // ServicesActive database
SC_MANAGER_CONNECT); // Connect rights
if (NULL == schSCManager) {
/* open SC manager failed */
ShowLocalizedMsg(IDS_ERR_OPEN_SCMGR);
goto failed;
}
schService = OpenService(
schSCManager, // SCM database
_T("OpenVPNService"), // service name
SERVICE_START | SERVICE_QUERY_STATUS);
if (schService == NULL) {
/* can't open VPN service */
ShowLocalizedMsg(IDS_ERR_OPEN_VPN_SERVICE);
goto failed;
}
/* Run Pre-connect script */
for (i=0; i<o.num_configs; i++)
RunPreconnectScript(&o.conn[i]);
if (!StartService(
schService, // handle to service
0, // number of arguments
NULL) ) // no arguments
{
/* can't start */
ShowLocalizedMsg(IDS_ERR_START_SERVICE);
goto failed;
}
else
{
//printf("Service start pending.\n");
}
// Check the status until the service is no longer start pending.
if (!QueryServiceStatus(
schService, // handle to service
&ssStatus) ) // address of status information structure
{
/* query failed */
ShowLocalizedMsg(IDS_ERR_QUERY_SERVICE);
goto failed;
}
// Save the tick count and initial checkpoint.
dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;
while (ssStatus.dwCurrentState == SERVICE_START_PENDING)
{
// Do not wait longer than the wait hint. A good interval is
// one tenth the wait hint, but no less than 1 second and no
// more than 5 seconds.
dwWaitTime = ssStatus.dwWaitHint / 10;
if( dwWaitTime < 1000 )
dwWaitTime = 1000;
else if ( dwWaitTime > 5000 )
dwWaitTime = 5000;
Sleep( dwWaitTime );
// Check the status again.
if (!QueryServiceStatus(
schService, // handle to service
&ssStatus) ) // address of structure
break;
if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
{
// The service is making progress.
dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;
}
else
{
if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
{
// No progress made within the wait hint
break;
}
}
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
if (ssStatus.dwCurrentState != SERVICE_RUNNING)
{
/* service hasn't started */
ShowLocalizedMsg(IDS_ERR_SERVICE_START_FAILED);
goto failed;
}
/* Run Connect script */
for (i=0; i<o.num_configs; i++)
RunConnectScript(&o.conn[i], true);
/* Set Service Status = Connected */
o.service_state = service_connected;
SetServiceMenuStatus();
CheckAndSetTrayIcon();
/* Show "OpenVPN Service Started" Tray Balloon msg */
ShowTrayBalloon(LoadLocalizedString(IDS_NFO_SERVICE_STARTED), _T(""));
return(true);
failed:
/* Set Service Status = Disconnecting */
o.service_state = service_disconnected;
SetServiceMenuStatus();
CheckAndSetTrayIcon();
return(false);
}
int MyStopService()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
SERVICE_STATUS ssStatus;
int i;
// Open a handle to the SC Manager database.
schSCManager = OpenSCManager(
NULL, // local machine
NULL, // ServicesActive database
SC_MANAGER_CONNECT); // Connect rights
if (NULL == schSCManager) {
/* can't open SCManager */
ShowLocalizedMsg(IDS_ERR_OPEN_SCMGR, (int) GetLastError());
return(false);
}
schService = OpenService(
schSCManager, // SCM database
_T("OpenVPNService"), // service name
SERVICE_STOP);
if (schService == NULL) {
/* can't open vpn service */
ShowLocalizedMsg(IDS_ERR_OPEN_VPN_SERVICE);
return(false);
}
/* Run DisConnect script */
for (i=0; i<o.num_configs; i++)
RunDisconnectScript(&o.conn[i], true);
if (!ControlService(
schService, // handle to service
SERVICE_CONTROL_STOP, // control value to send
&ssStatus) ) // address of status info
{
/* stop failed */
ShowLocalizedMsg(IDS_ERR_STOP_SERVICE);
return(false);
}
o.service_state = service_disconnected;
SetServiceMenuStatus();
CheckAndSetTrayIcon();
return(true);
}
int MyReStartService()
{
MyStopService();
Sleep(1000);
if (MyStartService()) {
return(true);
}
return(false);
}
bool
CheckIServiceStatus(BOOL warn)
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
SERVICE_STATUS ssStatus;
// Open a handle to the SC Manager database.
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (NULL == schSCManager)
return(false);
schService = OpenService(schSCManager, _T("OpenVPNServiceInteractive"),
SERVICE_QUERY_STATUS);
if (schService == NULL &&
GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
{
/* warn that iservice is not installed */
if (warn)
ShowLocalizedMsg(IDS_ERR_INSTALL_ISERVICE);
return(false);
}
if (!QueryServiceStatus(schService, &ssStatus))
return(false);
if (ssStatus.dwCurrentState != SERVICE_RUNNING)
{
/* warn that iservice is not started */
if (warn)
ShowLocalizedMsg(IDS_ERR_NOTSTARTED_ISERVICE);
return(false);
}
return true;
}
int CheckServiceStatus()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
SERVICE_STATUS ssStatus;
// Open a handle to the SC Manager database.
schSCManager = OpenSCManager(
NULL, // local machine
NULL, // ServicesActive database
SC_MANAGER_CONNECT); // Connect rights
if (NULL == schSCManager) {
o.service_state = service_noaccess;
SetServiceMenuStatus();
return(false);
}
schService = OpenService(
schSCManager, // SCM database
_T("OpenVPNService"), // service name
SERVICE_QUERY_STATUS);
if (schService == NULL) {
/* open vpn service failed */
ShowLocalizedMsg(IDS_ERR_OPEN_VPN_SERVICE);
o.service_state = service_noaccess;
SetServiceMenuStatus();
return(false);
}
if (!QueryServiceStatus(
schService, // handle to service
&ssStatus) ) // address of status information structure
{
/* query failed */
ShowLocalizedMsg(IDS_ERR_QUERY_SERVICE);
return(false);
}
if (ssStatus.dwCurrentState == SERVICE_RUNNING)
{
o.service_state = service_connected;
SetServiceMenuStatus();
SetTrayIcon(connected);
return(true);
}
else
{
o.service_state = service_disconnected;
SetServiceMenuStatus();
SetTrayIcon(disconnected);
return(false);
}
}