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.
2345 lines
77 KiB
2345 lines
77 KiB
#include "stdafx.h"
|
|
#include <winsvc.h>
|
|
#include <winsock2.h>
|
|
#include <nspapi.h>
|
|
#include "w3svc.h"
|
|
#include <inetsvcs.h>
|
|
#include <pwsdata.hxx>
|
|
#include "kill.h"
|
|
#include "svc.h"
|
|
|
|
TCHAR gServicesWhichMustBeRestarted[20][PROCESS_SIZE];
|
|
int gServicesWhichMustBeRestarted_nextuse = 0;
|
|
int gServicesWhichMustBeRestarted_total = 0;
|
|
|
|
extern int g_GlobalDebugLevelFlag;
|
|
|
|
int ServicesRestartList_EntryExists(LPCTSTR szServiceName)
|
|
{
|
|
int iFoundMatch = FALSE;
|
|
|
|
// loop thru the whole list
|
|
for(int i=0; i < gServicesWhichMustBeRestarted_total;i++)
|
|
{
|
|
if (_tcsicmp(gServicesWhichMustBeRestarted[i], szServiceName) == 0)
|
|
{
|
|
iFoundMatch = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return iFoundMatch;
|
|
}
|
|
|
|
|
|
int ServicesRestartList_Add(LPCTSTR szServiceName)
|
|
{
|
|
// check if this value already exists in the globalarary
|
|
if (ServicesRestartList_EntryExists(szServiceName)) {return FALSE;}
|
|
|
|
// move info into global array
|
|
if (gServicesWhichMustBeRestarted_nextuse <= 20)
|
|
{
|
|
_tcscpy(gServicesWhichMustBeRestarted[gServicesWhichMustBeRestarted_nextuse],szServiceName);
|
|
// increment counter to array
|
|
// increment next use space
|
|
++gServicesWhichMustBeRestarted_total;
|
|
++gServicesWhichMustBeRestarted_nextuse;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
int ServicesRestartList_RestartServices(void)
|
|
{
|
|
int iReturn = FALSE;
|
|
INT err = 0;
|
|
|
|
// loop thru the whole list and restart the services in reverse
|
|
// order from how they were entered?
|
|
if (gServicesWhichMustBeRestarted_total >= 1)
|
|
{
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("RestartServices()Start.\n")));
|
|
for(int i=0; i < gServicesWhichMustBeRestarted_total;i++)
|
|
{
|
|
if (CheckifServiceExist(gServicesWhichMustBeRestarted[i]) == 0 )
|
|
{
|
|
err = InetStartService(gServicesWhichMustBeRestarted[i]);
|
|
}
|
|
else
|
|
{
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("RestartServices():%s:Not restarting since it no longer exist.\n"),gServicesWhichMustBeRestarted[i]));
|
|
}
|
|
}
|
|
iisDebugOut_End(_T("RestartServices"));
|
|
}
|
|
|
|
return iReturn;
|
|
}
|
|
|
|
DWORD InetStopExtraWait(LPCTSTR lpServiceName)
|
|
{
|
|
DWORD dwSvcMaxSleep = 180000;
|
|
int iFileExist = FALSE;
|
|
|
|
// Wait. How long should we really wait for this service to actually stop?
|
|
// the iisadmin Service can take a long time if the metabase.bin file is huge.
|
|
// So... if it's the iisadmin service we're trying to stop, then
|
|
// check to see how big the metabase.bin file is, then for each 1meg give it 3 minutes (180000)
|
|
if (_tcsicmp(lpServiceName,_T("IISADMIN")) == 0)
|
|
{
|
|
// look for the metabase.bin file
|
|
TCHAR szTempDir[_MAX_PATH];
|
|
_tcscpy(szTempDir, g_pTheApp->m_csPathInetsrv);
|
|
AddPath(szTempDir, _T("Metabase.bin"));
|
|
if (IsFileExist(szTempDir))
|
|
{
|
|
iFileExist = TRUE;
|
|
}
|
|
else
|
|
{
|
|
_tcscpy(szTempDir, g_pTheApp->m_csPathInetsrv);
|
|
AddPath(szTempDir, _T("Metabase.xml"));
|
|
if (IsFileExist(szTempDir))
|
|
{
|
|
iFileExist = TRUE;
|
|
}
|
|
}
|
|
|
|
if (TRUE == iFileExist)
|
|
{
|
|
// Check to see how big it is.
|
|
DWORD dwFileSize = ReturnFileSize(szTempDir);
|
|
if (dwFileSize != 0xFFFFFFFF)
|
|
{
|
|
int iTime = 1;
|
|
// We were able to get the file size.
|
|
// for each meg for size, give it 3 minutes to save.
|
|
if (dwFileSize > 1000000)
|
|
{
|
|
iTime = (dwFileSize/1000000);
|
|
dwSvcMaxSleep = iTime * 180000;
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("InetStopExtraWait():Metabase.bin is kind of big (>1meg), Lets wait longer for IISADMIN service to stop.maxmilsec=0x%x.\n"),dwSvcMaxSleep));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return dwSvcMaxSleep;
|
|
}
|
|
|
|
// function: IsServiceDisabled
|
|
//
|
|
// Check to see if the service being sent in is disabled
|
|
BOOL
|
|
IsServiceDisabled(LPTSTR szServiceName)
|
|
{
|
|
SC_HANDLE hService;
|
|
SC_HANDLE hSCManager;
|
|
BOOL bRet = FALSE;
|
|
BUFFER buffConfig;
|
|
DWORD dwSizeRequired;
|
|
|
|
hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT | GENERIC_READ );
|
|
|
|
if ( hSCManager == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
hService = OpenService( hSCManager, szServiceName, SERVICE_QUERY_CONFIG );
|
|
|
|
if ( hService == NULL )
|
|
{
|
|
CloseServiceHandle( hSCManager );
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !QueryServiceConfig( hService, NULL, 0, &dwSizeRequired ) &&
|
|
( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) &&
|
|
buffConfig.Resize( dwSizeRequired ) &&
|
|
QueryServiceConfig( hService, (LPQUERY_SERVICE_CONFIG) buffConfig.QueryPtr(), buffConfig.QuerySize(), &dwSizeRequired )
|
|
)
|
|
{
|
|
// Check the service Startup Type
|
|
bRet = ((LPQUERY_SERVICE_CONFIG) buffConfig.QueryPtr())->dwStartType == SERVICE_DISABLED;
|
|
}
|
|
|
|
CloseServiceHandle( hSCManager );
|
|
CloseServiceHandle( hService );
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// function: SetServiceStart
|
|
//
|
|
// Change the service state
|
|
void
|
|
SetServiceStart(LPTSTR szServiceName, DWORD dwServiceStart)
|
|
{
|
|
SC_HANDLE hService;
|
|
SC_HANDLE hSCManager;
|
|
|
|
hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT | GENERIC_READ );
|
|
|
|
if ( hSCManager == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
hService = OpenService( hSCManager, szServiceName, SERVICE_CHANGE_CONFIG );
|
|
|
|
if ( hService == NULL )
|
|
{
|
|
CloseServiceHandle( hSCManager );
|
|
return;
|
|
}
|
|
|
|
ChangeServiceConfig( hService,
|
|
SERVICE_NO_CHANGE, // ServiceType
|
|
dwServiceStart, // Startup
|
|
SERVICE_NO_CHANGE, // Error Control
|
|
NULL, // Binary Path
|
|
NULL, // Load order group
|
|
NULL, // TagId
|
|
NULL, // Dependencies
|
|
NULL, // Service Start Name
|
|
NULL, // Password
|
|
NULL ); // StartName
|
|
|
|
CloseServiceHandle( hSCManager );
|
|
CloseServiceHandle( hService );
|
|
}
|
|
|
|
INT InetDisableService( LPCTSTR lpServiceName )
|
|
{
|
|
INT err = 0;
|
|
const DWORD dwSvcSleepInterval = 500 ;
|
|
DWORD dwSvcMaxSleep = 180000 ;
|
|
DWORD dwSleepTotal;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
// Calculcate if this is a "special" service which we
|
|
// need to give more time to in order to stop.
|
|
dwSvcMaxSleep = InetStopExtraWait(lpServiceName);
|
|
|
|
do {
|
|
if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// if the service is running, stop it
|
|
SERVICE_STATUS svcStatus;
|
|
if ( QueryServiceStatus( hService, &svcStatus ))
|
|
{
|
|
if (( svcStatus.dwCurrentState == SERVICE_RUNNING ))
|
|
{
|
|
if ( !ControlService( hService, SERVICE_CONTROL_STOP, &svcStatus ))
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
for ( dwSleepTotal = 0 ;
|
|
dwSleepTotal < dwSvcMaxSleep
|
|
&& (QueryServiceStatus( hService, & svcStatus ))
|
|
&& svcStatus.dwCurrentState == SERVICE_STOP_PENDING ;
|
|
dwSleepTotal += dwSvcSleepInterval )
|
|
{
|
|
::Sleep( dwSvcSleepInterval ) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !ChangeServiceConfig( hService,
|
|
SERVICE_NO_CHANGE,
|
|
SERVICE_DISABLED,
|
|
SERVICE_NO_CHANGE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL ) )
|
|
{
|
|
err = GetLastError();
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
if (hService){CloseServiceHandle(hService);}
|
|
if (hScManager){CloseServiceHandle(hScManager);}
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("InetDisableService():ServiceName=%s. Return=0x%x\n"), lpServiceName, err));
|
|
return(err);
|
|
}
|
|
|
|
INT InetStartService( LPCTSTR lpServiceName )
|
|
{
|
|
iisDebugOut_Start1(_T("InetStartService"),(LPTSTR) lpServiceName);
|
|
|
|
INT err = 0;
|
|
INT err2 = 0;
|
|
const DWORD dwSvcSleepInterval = 500 ;
|
|
DWORD dwSvcMaxSleep = 180000 ;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
// Calculcate if this is a "special" service which we
|
|
// need to give more time to in order to stop.
|
|
dwSvcMaxSleep = InetStopExtraWait(lpServiceName);
|
|
|
|
do
|
|
{
|
|
// set up the service first
|
|
if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
SERVICE_STATUS svcStatus;
|
|
if ( !QueryServiceStatus( hService, &svcStatus ))
|
|
{
|
|
err = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
if ( svcStatus.dwCurrentState == SERVICE_RUNNING )
|
|
{
|
|
// We will only get this ERROR_SERVICE_MARKED_FOR_DELETE
|
|
// message if the service is already running.
|
|
if ( !::StartService( hService, 0, NULL ))
|
|
{
|
|
err2 = ::GetLastError();
|
|
if (err2 == ERROR_SERVICE_MARKED_FOR_DELETE) {err = err2;}
|
|
}
|
|
break; // service already started and running
|
|
}
|
|
|
|
if ( !::StartService( hService, 0, NULL ))
|
|
{
|
|
err = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Wait for the service to attain "running" status; but
|
|
// wait no more than 3 minute.
|
|
DWORD dwSleepTotal;
|
|
for ( dwSleepTotal = 0 ; dwSleepTotal < dwSvcMaxSleep
|
|
&& (QueryServiceStatus( hService, &svcStatus ))
|
|
&& svcStatus.dwCurrentState == SERVICE_START_PENDING ;
|
|
dwSleepTotal += dwSvcSleepInterval )
|
|
{
|
|
::Sleep( dwSvcSleepInterval ) ;
|
|
}
|
|
|
|
if ( svcStatus.dwCurrentState != SERVICE_RUNNING )
|
|
{
|
|
err = dwSleepTotal > dwSvcMaxSleep ? ERROR_SERVICE_REQUEST_TIMEOUT : svcStatus.dwWin32ExitCode;
|
|
break;
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
if (hService){CloseServiceHandle(hService);}
|
|
if (hScManager){CloseServiceHandle(hScManager);}
|
|
|
|
if (err){iisDebugOut((LOG_TYPE_WARN, _T("InetStartService():ServiceName=%s unable to start WARNING. Err=0x%x.\n"), lpServiceName, err));}
|
|
else{iisDebugOut((LOG_TYPE_TRACE, _T("InetStartService():ServiceName=%s success.\n"), lpServiceName));}
|
|
return(err);
|
|
}
|
|
|
|
DWORD InetQueryServiceStatus( LPCTSTR lpServiceName )
|
|
{
|
|
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetQueryServiceStatus():ServiceName=%s\n"), (LPTSTR) lpServiceName));
|
|
DWORD dwStatus = 0;
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
SERVICE_STATUS svcStatus;
|
|
|
|
do {
|
|
if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
|
|
(hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ||
|
|
!::QueryServiceStatus( hService, &svcStatus ) )
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
dwStatus = svcStatus.dwCurrentState;
|
|
|
|
} while (0);
|
|
|
|
if (hService){CloseServiceHandle(hService);}
|
|
if (hScManager){CloseServiceHandle(hScManager);}
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetQueryServiceStatus():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
|
|
return( dwStatus );
|
|
}
|
|
|
|
INT InetStopService( LPCTSTR lpServiceName )
|
|
{
|
|
INT err = 0;
|
|
const DWORD dwSvcSleepInterval = 500 ;
|
|
DWORD dwSvcMaxSleep = 180000 ;
|
|
DWORD dwSleepTotal;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
// Calculcate if this is a "special" service which we
|
|
// need to give more time to in order to stop.
|
|
dwSvcMaxSleep = InetStopExtraWait(lpServiceName);
|
|
|
|
do {
|
|
if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
|
|
(hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
SERVICE_STATUS svcStatus;
|
|
if ( !QueryServiceStatus( hService, &svcStatus ))
|
|
{
|
|
err = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
if ( svcStatus.dwCurrentState == SERVICE_STOPPED )
|
|
break; // service already stopped
|
|
|
|
if (( svcStatus.dwCurrentState == SERVICE_RUNNING ))
|
|
{
|
|
if ( !ControlService( hService, SERVICE_CONTROL_STOP, &svcStatus ))
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
for ( dwSleepTotal = 0 ;
|
|
dwSleepTotal < dwSvcMaxSleep
|
|
&& (QueryServiceStatus( hService, & svcStatus ))
|
|
&& svcStatus.dwCurrentState == SERVICE_STOP_PENDING ;
|
|
dwSleepTotal += dwSvcSleepInterval )
|
|
{
|
|
::Sleep( dwSvcSleepInterval ) ;
|
|
}
|
|
}
|
|
|
|
if ( svcStatus.dwCurrentState != SERVICE_STOPPED )
|
|
{
|
|
err = dwSleepTotal > dwSvcMaxSleep ?
|
|
ERROR_SERVICE_REQUEST_TIMEOUT :
|
|
svcStatus.dwWin32ExitCode;
|
|
break;
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
if (hService){CloseServiceHandle(hService);}
|
|
if (hScManager){CloseServiceHandle(hScManager);}
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("InetStopService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
|
|
return(err);
|
|
}
|
|
|
|
INT InetDeleteService( LPCTSTR lpServiceName )
|
|
{
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
/*
|
|
The DeleteService function marks a service for deletion from the service control manager database.
|
|
The database entry is not removed until all open handles to the service have been closed by calls
|
|
to the CloseServiceHandle function, and the service is not running. A running service is stopped
|
|
by a call to the ControlService function with the SERVICE_CONTROL_STOP control code.
|
|
If the service cannot be stopped, the database entry is removed when the system is restarted.
|
|
The service control manager deletes the service by deleting the service key and its subkeys from
|
|
the registry.
|
|
*/
|
|
// To delete service immediately, we need to stop service first
|
|
StopServiceAndDependencies(lpServiceName, FALSE);
|
|
|
|
do {
|
|
if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
|
|
(hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL ||
|
|
!::DeleteService( hService ) )
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
} while (0);
|
|
|
|
if (hService){CloseServiceHandle(hService);}
|
|
if (hScManager){CloseServiceHandle(hScManager);}
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("InetDeleteService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
|
|
return(err);
|
|
}
|
|
|
|
INT InetCreateDriver(LPCTSTR lpServiceName, LPCTSTR lpDisplayName, LPCTSTR lpBinaryPathName, DWORD dwStartType)
|
|
{
|
|
iisDebugOut_Start1(_T("InetCreateDriver"),(LPTSTR) lpServiceName);
|
|
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
do {
|
|
if ( (hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL )
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
//
|
|
// if Driver already exits then just change the parameters
|
|
//
|
|
if ( CheckifServiceExist( lpServiceName ) == 0 ) {
|
|
|
|
hService = OpenService( hScManager, lpServiceName, GENERIC_ALL );
|
|
|
|
if ( hService ) {
|
|
if ( ChangeServiceConfig(
|
|
hService, // handle to service
|
|
SERVICE_KERNEL_DRIVER, // type of service
|
|
dwStartType, // when to start service
|
|
SERVICE_ERROR_NORMAL, // severity if service fails to start
|
|
lpBinaryPathName, // pointer to service binary file name
|
|
NULL, // pointer to load ordering group name
|
|
NULL, // pointer to variable to get tag identifier
|
|
NULL, // pointer to array of dependency names
|
|
NULL, // pointer to account name of service
|
|
NULL, // pointer to password for service account
|
|
lpDisplayName // pointer to display name
|
|
) ){
|
|
break;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
hService = ::CreateService( hScManager, lpServiceName, lpDisplayName,
|
|
GENERIC_ALL, SERVICE_KERNEL_DRIVER, dwStartType,
|
|
SERVICE_ERROR_NORMAL, lpBinaryPathName, NULL, NULL,
|
|
NULL, NULL, NULL );
|
|
|
|
if ( hService ) {
|
|
break;
|
|
}
|
|
}
|
|
err = GetLastError();
|
|
|
|
} while ( FALSE );
|
|
|
|
if (hService){CloseServiceHandle(hService);}
|
|
if (hScManager){CloseServiceHandle(hScManager);}
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("InetCreateDriver():Name=%s. Return=0x%x.\n"), lpServiceName, err));
|
|
return(err);
|
|
}
|
|
|
|
INT InetCreateService( LPCTSTR lpServiceName, LPCTSTR lpDisplayName, LPCTSTR lpBinaryPathName, DWORD dwStartType, LPCTSTR lpDependencies)
|
|
{
|
|
iisDebugOut_Start1(_T("InetCreateService"),(LPTSTR) lpServiceName);
|
|
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
do {
|
|
if ( (hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL )
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
hService = ::CreateService( hScManager, lpServiceName, lpDisplayName,
|
|
GENERIC_ALL, SERVICE_WIN32_SHARE_PROCESS, dwStartType,
|
|
SERVICE_ERROR_NORMAL, lpBinaryPathName, NULL, NULL,
|
|
lpDependencies, _T("LocalSystem"), NULL );
|
|
if ( !hService )
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
if (hService){CloseServiceHandle(hService);}
|
|
if (hScManager){CloseServiceHandle(hScManager);}
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("InetCreateService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
|
|
return(err);
|
|
}
|
|
|
|
INT InetConfigService( LPCTSTR lpServiceName, LPCTSTR lpDisplayName, LPCTSTR lpBinaryPathName, LPCTSTR lpDependencies)
|
|
{
|
|
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetConfigService():ServiceName=%s\n"), (LPTSTR) lpServiceName));
|
|
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
do {
|
|
if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
|
|
(hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
err = GetLastError();
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigService():OpenSCManager or OpenService: Service=%s BinPathName=%s Dependencies=%s Err=0x%x FAILED\n"), lpServiceName, lpBinaryPathName, lpDependencies, err));
|
|
break;
|
|
}
|
|
|
|
if ( !::ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, lpBinaryPathName, NULL, NULL, lpDependencies, _T("LocalSystem"), NULL, lpDisplayName) )
|
|
{
|
|
err = GetLastError();
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigService():ChangeServiceConfig: Service=%s BinPathName=%s Dependencies=%s Err=0x%x FAILED\n"), lpServiceName, lpBinaryPathName, lpDependencies, err));
|
|
break;
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
if (hService) {CloseServiceHandle(hService);}
|
|
if (hScManager) {CloseServiceHandle(hScManager);}
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("InetConfigService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
|
|
return(err);
|
|
}
|
|
|
|
INT InetConfigService2( LPCTSTR lpServiceName, LPCTSTR lpDescription)
|
|
{
|
|
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetConfigService2():ServiceName=%s\n"), (LPTSTR) lpServiceName));
|
|
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
SERVICE_DESCRIPTION ServiceDescription;
|
|
|
|
do {
|
|
if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
|
|
(hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
err = GetLastError();
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigService2():OpenSCManager or OpenService: Service=%s Err=0x%x FAILED\n"), lpServiceName, err));
|
|
break;
|
|
}
|
|
|
|
if (lpDescription)
|
|
{
|
|
if (_tcscmp(lpDescription, _T("")) != 0)
|
|
{
|
|
ServiceDescription.lpDescription = (LPTSTR) lpDescription;
|
|
if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, (LPVOID)&ServiceDescription))
|
|
{
|
|
err = GetLastError();
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigService2():ChangeServiceConfig2: Service=%s Err=0x%x FAILED\n"), lpServiceName, err));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
if (hService) {CloseServiceHandle(hService);}
|
|
if (hScManager) {CloseServiceHandle(hScManager);}
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("InetConfigService2():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
|
|
return(err);
|
|
}
|
|
|
|
|
|
# define SetServiceTypeValues( pSvcTypeValue, dwNS, dwType, dwSize, lpValName, lpVal) \
|
|
( pSvcTypeValue)->dwNameSpace = ( dwNS); \
|
|
( pSvcTypeValue)->dwValueType = ( dwType); \
|
|
( pSvcTypeValue)->dwValueSize = ( dwSize); \
|
|
( pSvcTypeValue)->lpValueName = ( lpValName); \
|
|
( pSvcTypeValue)->lpValue = (PVOID ) ( lpVal); \
|
|
|
|
# define SetServiceTypeValuesDword( pSvcTypeValue, dwNS, lpValName, lpVal) \
|
|
SetServiceTypeValues( (pSvcTypeValue), (dwNS), REG_DWORD, sizeof( DWORD), \
|
|
( lpValName), ( lpVal))
|
|
|
|
BOOL InetRegisterService( LPCTSTR pszMachine, LPCTSTR pszServiceName, GUID *pGuid, DWORD SapId, DWORD TcpPort, BOOL fAdd )
|
|
{
|
|
iisDebugOut_Start1(_T("InetRegisterService"),(LPTSTR) pszServiceName);
|
|
int err;
|
|
|
|
WSADATA WsaData;
|
|
|
|
SERVICE_INFO serviceInfo;
|
|
LPSERVICE_TYPE_INFO_ABS lpServiceTypeInfo ;
|
|
LPSERVICE_TYPE_VALUE_ABS lpServiceTypeValues ;
|
|
BYTE serviceTypeInfoBuffer[sizeof(SERVICE_TYPE_INFO) + 1024];
|
|
// Buffer large enough for 3 values ( SERVICE_TYPE_VALUE_ABS)
|
|
|
|
DWORD Value1 = 1 ;
|
|
DWORD SapValue = SapId;
|
|
DWORD TcpPortValue = TcpPort;
|
|
DWORD statusFlags;
|
|
|
|
//
|
|
// Initialize Windows Sockets DLL
|
|
//
|
|
|
|
err = WSAStartup( 0x0101, & WsaData);
|
|
if ( err == SOCKET_ERROR)
|
|
{
|
|
return ( FALSE);
|
|
}
|
|
|
|
|
|
//
|
|
// Setup the service information to be passed to SetService() for adding
|
|
// or deleting this service. Most of the SERVICE_INFO fields are not
|
|
// required for add or delete operation. The main things of interests are
|
|
// GUIDs and ServiceSpecificInfo structure.
|
|
//
|
|
|
|
memset( (PVOID ) & serviceInfo, 0, sizeof( serviceInfo)); //null all fields
|
|
|
|
serviceInfo.lpServiceType = pGuid;
|
|
serviceInfo.lpMachineName = (LPTSTR)pszMachine;
|
|
|
|
//
|
|
// The "Blob" will contain the service specific information.
|
|
// In this case, fill it with a SERVICE_TYPE_INFO_ABS structure
|
|
// and associated information.
|
|
//
|
|
serviceInfo.ServiceSpecificInfo.pBlobData = serviceTypeInfoBuffer;
|
|
serviceInfo.ServiceSpecificInfo.cbSize = sizeof( serviceTypeInfoBuffer);
|
|
|
|
lpServiceTypeInfo = (LPSERVICE_TYPE_INFO_ABS ) serviceTypeInfoBuffer;
|
|
|
|
//
|
|
// There are totally 3 values associated with this service if we're doing
|
|
// both SPX and TCP, there's only one value if TCP.
|
|
//
|
|
|
|
if ( SapId )
|
|
{
|
|
lpServiceTypeInfo->dwValueCount = 3;
|
|
}
|
|
else
|
|
{
|
|
lpServiceTypeInfo->dwValueCount = 1;
|
|
}
|
|
lpServiceTypeInfo->lpTypeName = (LPTSTR)pszServiceName;
|
|
|
|
lpServiceTypeValues = lpServiceTypeInfo->Values;
|
|
|
|
if ( SapId )
|
|
{
|
|
//
|
|
// 1st value: tells the SAP that this is a connection oriented service.
|
|
//
|
|
SetServiceTypeValuesDword( ( lpServiceTypeValues + 0),
|
|
NS_SAP, // Name Space
|
|
SERVICE_TYPE_VALUE_CONN, // ValueName
|
|
&Value1 // actual value
|
|
);
|
|
|
|
//
|
|
// 2nd Value: tells SAP about object type to be used for broadcasting
|
|
// the service name.
|
|
//
|
|
SetServiceTypeValuesDword( ( lpServiceTypeValues + 1),
|
|
NS_SAP,
|
|
SERVICE_TYPE_VALUE_SAPID,
|
|
&SapValue);
|
|
|
|
//
|
|
// 3rd value: tells TCPIP name-space provider about TCP/IP port to be used.
|
|
//
|
|
SetServiceTypeValuesDword( ( lpServiceTypeValues + 2),
|
|
NS_DNS,
|
|
SERVICE_TYPE_VALUE_TCPPORT,
|
|
&TcpPortValue);
|
|
|
|
}
|
|
else
|
|
{
|
|
SetServiceTypeValuesDword( ( lpServiceTypeValues + 0),
|
|
NS_DNS,
|
|
SERVICE_TYPE_VALUE_TCPPORT,
|
|
&TcpPortValue);
|
|
}
|
|
//
|
|
// Finally, call SetService to actually perform the operation.
|
|
//
|
|
err = SetService(
|
|
NS_DEFAULT, // all default name spaces
|
|
( fAdd ) ? SERVICE_ADD_TYPE : SERVICE_DELETE_TYPE, // either ADD or DELETE
|
|
0, // dwFlags not used
|
|
&serviceInfo, // the service info structure
|
|
NULL, // lpServiceAsyncInfo
|
|
&statusFlags // additional status information
|
|
);
|
|
|
|
// for some unknown reason, the SERVICE_DELETE_TYPE never remove the related registry
|
|
// I have to manually clean it here.
|
|
if (!fAdd)
|
|
{
|
|
CRegKey regSvcTypes(HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Control\\ServiceProvider\\ServiceTypes"));
|
|
if ((HKEY)regSvcTypes) {regSvcTypes.DeleteTree(pszServiceName);}
|
|
}
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("InetRegisterService():ServiceName=%s.End.Return=%d.\n"), pszServiceName, err));
|
|
return ( err != NO_ERROR);
|
|
} // InetRegisterService()
|
|
|
|
INT CheckifServiceExistAndDependencies( LPCTSTR lpServiceName )
|
|
{
|
|
INT err = 0;
|
|
INT iReturn = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
|
|
|
|
BYTE ConfigBuffer[4096];
|
|
LPENUM_SERVICE_STATUS ServiceConfigEnum = (LPENUM_SERVICE_STATUS) &ConfigBuffer;
|
|
|
|
if (( hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
// Failed, or more likely the service doesn't exist
|
|
iReturn = GetLastError();
|
|
goto CheckifServiceExistAndDependencies_Exit;
|
|
}
|
|
|
|
// There was no error and the service exists.
|
|
// Then let's make sure the actual file exists!!!
|
|
// The above calls will only return true if the service has been registered, but
|
|
// the call doesn't actually check if the file exists!
|
|
|
|
// Retrieve the service's config for the BinaryPathName
|
|
// if it fails then hey, we don't have a correctly installed service
|
|
// so return error!
|
|
if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
|
|
{
|
|
iReturn = GetLastError();
|
|
goto CheckifServiceExistAndDependencies_Exit;
|
|
}
|
|
if (!ServiceConfig)
|
|
{
|
|
iReturn = GetLastError();
|
|
goto CheckifServiceExistAndDependencies_Exit;
|
|
}
|
|
|
|
if ( (ServiceConfig->dwServiceType & SERVICE_WIN32_OWN_PROCESS) || (ServiceConfig->dwServiceType & SERVICE_WIN32_SHARE_PROCESS))
|
|
{
|
|
if (ServiceConfig->lpBinaryPathName)
|
|
{
|
|
if (IsFileExist(ServiceConfig->lpBinaryPathName))
|
|
{
|
|
// the service exists and the file exists too!
|
|
iReturn = 0;
|
|
}
|
|
else
|
|
{
|
|
iReturn = ERROR_FILE_NOT_FOUND;
|
|
goto CheckifServiceExistAndDependencies_Exit;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
iReturn = 0;
|
|
}
|
|
|
|
|
|
// Get our list of services which we depend upon.
|
|
// let's make sure they are registered and exist.
|
|
|
|
// ServiceConfig->lpDependencies should look something like this
|
|
// service\0service\0\0 double null terminated
|
|
{
|
|
TCHAR * pdest = NULL;
|
|
long RightMostNull = 0;
|
|
|
|
pdest = ServiceConfig->lpDependencies;
|
|
do
|
|
{
|
|
if (*pdest != _T('\0'))
|
|
{
|
|
RightMostNull = RightMostNull + _tcslen(pdest) + 1;
|
|
|
|
// Check if the service exists
|
|
if (0 != CheckifServiceExistAndDependencies(pdest)){iReturn = err;}
|
|
|
|
pdest = _tcschr(pdest, _T('\0'));
|
|
pdest++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
} while (TRUE);
|
|
}
|
|
|
|
CheckifServiceExistAndDependencies_Exit:
|
|
if (ServiceConfig) {free(ServiceConfig);}
|
|
if (hService) {CloseServiceHandle(hService);}
|
|
if (hScManager) {CloseServiceHandle(hScManager);}
|
|
return (iReturn);
|
|
}
|
|
|
|
|
|
|
|
INT CheckifServiceExist( LPCTSTR lpServiceName )
|
|
{
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
if (( hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL
|
|
|| (hService = OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{err = GetLastError();}
|
|
|
|
if (hService) CloseServiceHandle(hService);
|
|
if (hScManager) CloseServiceHandle(hScManager);
|
|
return (err);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------------------
|
|
Routine Description:
|
|
This routine allocates a buffer for the specified service's configuration parameters,
|
|
and retrieves those parameters into the buffer. The caller is responsible for freeing
|
|
the buffer.
|
|
Remarks:
|
|
The pointer whose address is contained in ServiceConfig is guaranteed to be NULL upon
|
|
return if any error occurred.
|
|
-----------------------------------------------------------------------------------------*/
|
|
DWORD RetrieveServiceConfig(IN SC_HANDLE ServiceHandle,OUT LPQUERY_SERVICE_CONFIG *ServiceConfig)
|
|
{
|
|
DWORD ServiceConfigSize = 0, Err;
|
|
if (NULL == ServiceConfig)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
*ServiceConfig = NULL;
|
|
while(TRUE)
|
|
{
|
|
if(QueryServiceConfig(ServiceHandle, *ServiceConfig, ServiceConfigSize, &ServiceConfigSize))
|
|
{
|
|
//assert(*ServiceConfig);
|
|
return NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
Err = GetLastError();
|
|
if(*ServiceConfig)
|
|
{
|
|
free(*ServiceConfig);
|
|
*ServiceConfig=NULL;
|
|
}
|
|
|
|
if(Err == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
// Allocate a larger buffer, and try again.
|
|
*ServiceConfig = (LPQUERY_SERVICE_CONFIG) malloc(ServiceConfigSize);
|
|
|
|
if( !( *ServiceConfig ) )
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*ServiceConfig = NULL;
|
|
return Err;
|
|
}
|
|
}
|
|
} // while (TRUE)
|
|
}
|
|
|
|
|
|
INT CreateDependencyForService( LPCTSTR lpServiceName, LPCTSTR lpDependency )
|
|
{
|
|
iisDebugOut_Start1(_T("CreateDependencyForService"),(LPTSTR) lpServiceName);
|
|
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
|
|
TCHAR szTempDependencies[1024];
|
|
TCHAR * pszTempDependencies = NULL;
|
|
pszTempDependencies = szTempDependencies;
|
|
|
|
do {
|
|
// set up the service first
|
|
if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
|
|
(hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Get the existing Service information
|
|
if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
if(!ServiceConfig)
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
// Check if our service is already in there.
|
|
// ServiceConfig->lpDependencies should look something like this
|
|
// service\0service\0\0 double null terminated
|
|
TCHAR * pdest = NULL;
|
|
int bFoundFlag = FALSE;
|
|
long RightMostNull = 0;
|
|
|
|
pdest = ServiceConfig->lpDependencies;
|
|
do
|
|
{
|
|
if (*pdest != _T('\0'))
|
|
{
|
|
RightMostNull = RightMostNull + _tcslen(pdest) + 1;
|
|
if (_tcsicmp(pdest, lpDependency) == 0)
|
|
{
|
|
bFoundFlag = TRUE;
|
|
break;
|
|
}
|
|
|
|
// copy the entry onto our string which we'll use later.
|
|
_tcscpy(pszTempDependencies,pdest);
|
|
// position pointer to the end
|
|
pszTempDependencies=pszTempDependencies + RightMostNull;
|
|
|
|
pdest = _tcschr(pdest, _T('\0'));
|
|
pdest++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
} while (TRUE);
|
|
|
|
// if the service is already on the dependency list then exit
|
|
if (bFoundFlag == TRUE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// The Service is not there So Let's add it to the end of the list then change the data
|
|
// The pointer should be at the beginning or at the next entry point
|
|
_tcscpy(pszTempDependencies, lpDependency);
|
|
// position pointer to the end
|
|
pszTempDependencies=pszTempDependencies + (_tcslen(pszTempDependencies) + 1);
|
|
// add another null to the end
|
|
*pszTempDependencies = _T('\0');
|
|
|
|
|
|
if(!::ChangeServiceConfig(hService,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,NULL,NULL,NULL,szTempDependencies,NULL,NULL,NULL))
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
if (ServiceConfig) {free(ServiceConfig);}
|
|
if (hService) {CloseServiceHandle(hService);}
|
|
if (hScManager) {CloseServiceHandle(hScManager);}
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("CreateDependencyForService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
|
|
return err;
|
|
}
|
|
|
|
|
|
INT RemoveDependencyForService( LPCTSTR lpServiceName, LPCTSTR lpDependency )
|
|
{
|
|
iisDebugOut_Start1(_T("RemoveDependencyForService"),(LPTSTR) lpServiceName);
|
|
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
|
|
TCHAR szTempDependencies[1024];
|
|
TCHAR * pszTempDependencies = NULL;
|
|
pszTempDependencies = szTempDependencies;
|
|
|
|
do {
|
|
// set up the service first
|
|
if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
|
|
(hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Get the existing Service information
|
|
if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
if(!ServiceConfig)
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Check if our service is already in there.
|
|
// ServiceConfig->lpDependencies should look something like this
|
|
// service\0service\0\0 double null terminated
|
|
|
|
TCHAR * pdest = NULL;
|
|
int bFoundFlag = FALSE;
|
|
long RightMostNull = 0;
|
|
_tcsset(szTempDependencies, _T('\0'));
|
|
pdest = ServiceConfig->lpDependencies;
|
|
do
|
|
{
|
|
if (*pdest != _T('\0'))
|
|
{
|
|
RightMostNull = RightMostNull + _tcslen(pdest) + 1;
|
|
if (_tcsicmp(pdest, lpDependency) == 0)
|
|
{
|
|
bFoundFlag = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// copy the entry onto our string which we'll use later.
|
|
_tcscpy(pszTempDependencies,pdest);
|
|
// position pointer to the end
|
|
pszTempDependencies=pszTempDependencies + RightMostNull;
|
|
*pszTempDependencies = _T('\0');
|
|
|
|
/*
|
|
if (_tcslen(szTempDependencies) == 0)
|
|
memcpy(szTempDependencies, pdest, _tcslen(pdest) + 1);
|
|
else
|
|
memcpy(szTempDependencies + _tcslen(szTempDependencies) + 1, pdest, _tcslen(pdest) + 1);
|
|
*/
|
|
}
|
|
pdest = _tcschr(pdest, _T('\0'));
|
|
pdest++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
} while (TRUE);
|
|
// if the service was in the list.
|
|
// Then let's remove it.
|
|
if (bFoundFlag == FALSE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if(!::ChangeServiceConfig(hService,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,SERVICE_NO_CHANGE,NULL,NULL,NULL,szTempDependencies,NULL,NULL,NULL))
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
if (ServiceConfig) {free(ServiceConfig);}
|
|
if (hService) {CloseServiceHandle(hService);}
|
|
if (hScManager) {CloseServiceHandle(hScManager);}
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("RemoveDependencyForService():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
|
|
return err;
|
|
}
|
|
|
|
INT DisplayDependencyForService( LPCTSTR lpServiceName)
|
|
{
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
|
|
|
|
do {
|
|
// set up the service first
|
|
if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
|
|
(hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Get the existing Service information
|
|
if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
if(!ServiceConfig)
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
// Check if our service is already in there.
|
|
// ServiceConfig->lpDependencies should look something like this
|
|
// service\0service\0\0 double null terminated
|
|
TCHAR * pdest = NULL;
|
|
int bFoundFlag = FALSE;
|
|
long RightMostNull = 0;
|
|
pdest = ServiceConfig->lpDependencies;
|
|
do
|
|
{
|
|
if (*pdest != _T('\0'))
|
|
{
|
|
pdest = _tcschr(pdest, _T('\0'));
|
|
pdest++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
} while (TRUE);
|
|
|
|
|
|
} while ( FALSE );
|
|
|
|
if (ServiceConfig) {free(ServiceConfig);}
|
|
if (hService) {CloseServiceHandle(hService);}
|
|
if (hScManager) {CloseServiceHandle(hScManager);}
|
|
return err;
|
|
}
|
|
|
|
|
|
//
|
|
//Routine Description:
|
|
// Stop the named service and all those services which depend upon it.
|
|
// And if the service is hung and can't be stopped, then kill the darn thing.
|
|
//
|
|
//Arguments:
|
|
// ServiceName (Name of service to stop)
|
|
//
|
|
//Return Status:
|
|
// TRUE - Indicates service successfully stopped
|
|
// FALSE - Timeout occurred.
|
|
//
|
|
int StopServiceAndDependencies(LPCTSTR ServiceName, int AddToRestartList)
|
|
{
|
|
iisDebugOut_Start1(_T("StopServiceAndDependencies"),(LPTSTR) ServiceName);
|
|
|
|
int Err = 0;
|
|
int iBeforeServiceStatus = 0;
|
|
SC_HANDLE ScManagerHandle = NULL;
|
|
SC_HANDLE ServiceHandle = NULL;
|
|
SERVICE_STATUS ServiceStatus;
|
|
DWORD Timeout;
|
|
int iReturn = FALSE;
|
|
DWORD TimeoutMaxSecs = 60;
|
|
DWORD dwSvcMaxSleep = 0;
|
|
|
|
//
|
|
// Open a handle to the Service.
|
|
//
|
|
ScManagerHandle = OpenSCManager(NULL,NULL,SC_MANAGER_CONNECT );
|
|
if (ScManagerHandle == NULL)
|
|
{
|
|
Err = GetLastError();
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies():OpenSCManager: Err on Service %s Err=0x%x FAILED\n"), ServiceName, Err));
|
|
goto Cleanup;
|
|
}
|
|
|
|
ServiceHandle = OpenService(ScManagerHandle,ServiceName,SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_STOP | SERVICE_QUERY_CONFIG );
|
|
if ( ServiceHandle == NULL )
|
|
{
|
|
Err = GetLastError();
|
|
if (Err == ERROR_SERVICE_DOES_NOT_EXIST)
|
|
{
|
|
iReturn = TRUE;
|
|
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("StopServiceAndDependencies():%s Service does not exist.\n"), ServiceName));
|
|
}
|
|
else
|
|
{
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies():OpenService: Err on Service %s Err=0x%x FAILED\n"), ServiceName, Err));
|
|
}
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Get the before service status.
|
|
if (QueryServiceStatus(ServiceHandle, &ServiceStatus))
|
|
{
|
|
iBeforeServiceStatus = ServiceStatus.dwCurrentState;
|
|
}
|
|
|
|
//
|
|
// Ask the service to stop.
|
|
//
|
|
if ( !ControlService( ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus) )
|
|
{
|
|
Err = GetLastError();
|
|
// If there are dependent services running,
|
|
// determine their names and stop them.
|
|
if ( Err == ERROR_DEPENDENT_SERVICES_RUNNING )
|
|
{
|
|
BYTE ConfigBuffer[4096];
|
|
LPENUM_SERVICE_STATUS ServiceConfig = (LPENUM_SERVICE_STATUS) &ConfigBuffer;
|
|
DWORD BytesNeeded;
|
|
DWORD ServiceCount;
|
|
DWORD ServiceIndex;
|
|
|
|
//
|
|
// Get the names of the dependent services.
|
|
//
|
|
if ( !EnumDependentServices( ServiceHandle,SERVICE_ACTIVE,ServiceConfig,sizeof(ConfigBuffer),&BytesNeeded,&ServiceCount ) )
|
|
{
|
|
Err = GetLastError();
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies():EnumDependentServices: Err on Service %s Err=0x%x FAILED\n"), ServiceName, Err));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Stop those services.
|
|
//
|
|
for ( ServiceIndex=0; ServiceIndex<ServiceCount; ServiceIndex++ )
|
|
{
|
|
StopServiceAndDependencies( ServiceConfig[ServiceIndex].lpServiceName, AddToRestartList);
|
|
}
|
|
|
|
//
|
|
// Ask the original service to stop.
|
|
//
|
|
if ( !ControlService( ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus) )
|
|
{
|
|
Err = GetLastError();
|
|
|
|
// check if the service is already stopped..
|
|
if ( Err == ERROR_SERVICE_CANNOT_ACCEPT_CTRL || Err == ERROR_SERVICE_NOT_ACTIVE)
|
|
{
|
|
// check if the service is alread stopped.
|
|
if (QueryServiceStatus( ServiceHandle, &ServiceStatus ))
|
|
{
|
|
if ( ServiceStatus.dwCurrentState == SERVICE_STOPPED || ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
|
|
{
|
|
iReturn = TRUE;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The service must be in a hung mode. Let's kill it.
|
|
iisDebugOut((LOG_TYPE_WARN, _T("StopServiceAndDependencies():'%s' Service must be in a hung mode. Let's kill it.\n"), ServiceName));
|
|
KillService(ServiceHandle);
|
|
goto WaitLoop;
|
|
}
|
|
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// check if the service is already stopped..
|
|
if ( Err == ERROR_SERVICE_CANNOT_ACCEPT_CTRL || Err == ERROR_SERVICE_NOT_ACTIVE)
|
|
{
|
|
// check if the service is alread stopped.
|
|
if (QueryServiceStatus( ServiceHandle, &ServiceStatus ))
|
|
{
|
|
if ( ServiceStatus.dwCurrentState == SERVICE_STOPPED || ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
|
|
{
|
|
Err = ServiceStatus.dwCurrentState;
|
|
iReturn = TRUE;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The service must be in a hung mode. Let's kill it.
|
|
iisDebugOut((LOG_TYPE_WARN, _T("StopServiceAndDependencies():'%s' Service must be in a hung mode. Let's kill it.\n"), ServiceName));
|
|
KillService(ServiceHandle);
|
|
goto WaitLoop;
|
|
}
|
|
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// We successfully asked the service to stop...
|
|
}
|
|
|
|
|
|
WaitLoop:
|
|
// Calculcate if this is a "special" service which we
|
|
// need to give more time to in order to stop.
|
|
dwSvcMaxSleep = InetStopExtraWait(ServiceName);
|
|
// dwSvcMaxSleep returns 3 minute intervals. so default dwSvcMaxSleep will be 180000 (3 minutes)
|
|
// we need to convert this into how many seconds
|
|
TimeoutMaxSecs = (dwSvcMaxSleep/1000);
|
|
|
|
// Loop waiting for the service to stop.
|
|
for ( Timeout=0; Timeout < TimeoutMaxSecs; Timeout++ )
|
|
{
|
|
// Return or continue waiting depending on the state of the service.
|
|
if ( ServiceStatus.dwCurrentState == SERVICE_STOPPED )
|
|
{
|
|
// The service successfully stopped.
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("StopServiceAndDependencies(): %s Service stopped.\n"), ServiceName));
|
|
iReturn = TRUE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Wait a second for the service to finish stopping.
|
|
Sleep( 1000 );
|
|
|
|
// Query the status of the service again.
|
|
if (! QueryServiceStatus( ServiceHandle, &ServiceStatus ))
|
|
{
|
|
Err = GetLastError();
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies():QueryServiceStatus: Err on Service %s Err=0x%x FAILED\n"), ServiceName, Err));
|
|
goto Cleanup;
|
|
}
|
|
|
|
// if the service we are trying to stop is a driver,
|
|
// then heck we should just get out of here..
|
|
if (TRUE == IsThisServiceADriver(ServiceName))
|
|
{
|
|
iisDebugOut((LOG_TYPE_WARN, _T("StopServiceAndDependencies(): %s service is a driver, and can only be removed upon reboot.\n"), ServiceName));
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// if we get here then the service failed to stop.
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("StopServiceAndDependencies(): failed to stop %s service.\n"), ServiceName));
|
|
|
|
Cleanup:
|
|
if ( ScManagerHandle != NULL ) {(VOID) CloseServiceHandle(ScManagerHandle);}
|
|
if ( ServiceHandle != NULL ) {(VOID) CloseServiceHandle(ServiceHandle);}
|
|
|
|
// if we successfully stopped this service, then
|
|
// add it to the restart service list
|
|
if (iReturn == TRUE)
|
|
{
|
|
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("StopServiceAndDependencies(): %s service. success.\n"), ServiceName));
|
|
if (iBeforeServiceStatus == SERVICE_RUNNING)
|
|
{
|
|
if (AddToRestartList) {ServicesRestartList_Add(ServiceName);}
|
|
}
|
|
}
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------
|
|
// The service must be in a hung mode. Let's kill it.
|
|
// Get the binary path name and use that to kill it.
|
|
// Return true on successfull kill. false otherwise.
|
|
// ----------------------------------------------
|
|
int KillService(SC_HANDLE ServiceHandle)
|
|
{
|
|
int iReturn = FALSE;
|
|
LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
|
|
int iFlagPutItBack = FALSE;
|
|
|
|
// Retrieve the service's config for the BinaryPathName
|
|
// if failed then just return
|
|
if(RetrieveServiceConfig(ServiceHandle, &ServiceConfig) != NO_ERROR)
|
|
{
|
|
goto KillService_Exit;
|
|
}
|
|
if(!ServiceConfig)
|
|
{
|
|
goto KillService_Exit;
|
|
}
|
|
|
|
// The Service can be one of these types:
|
|
// SERVICE_WIN32_OWN_PROCESS: A service type flag that indicates a Win32 service that runs in its own process.
|
|
// SERVICE_WIN32_SHARE_PROCESS: A service type flag that indicates a Win32 service that shares a process with other services.
|
|
// SERVICE_KERNEL_DRIVER: A service type flag that indicates a Windows NT device driver.
|
|
// SERVICE_FILE_SYSTEM_DRIVER: A service type flag that indicates a Windows NT file system driver.
|
|
// SERVICE_INTERACTIVE_PROCESS: A flag that indicates a Win32 service process that can interact with the desktop.
|
|
|
|
// Attempt to kill only if it's a process.
|
|
if ( (ServiceConfig->dwServiceType & SERVICE_WIN32_OWN_PROCESS) || (ServiceConfig->dwServiceType & SERVICE_WIN32_SHARE_PROCESS))
|
|
{
|
|
if ( _tcslen(ServiceConfig->lpBinaryPathName) >= MAX_PATH )
|
|
{
|
|
goto KillService_Exit;
|
|
}
|
|
|
|
// parse out the different parts and take only the filename.ext
|
|
TCHAR pfilename_only[ MAX_PATH ];
|
|
TCHAR pextention_only[ MAX_PATH ];
|
|
_tsplitpath( ServiceConfig->lpBinaryPathName, NULL, NULL, pfilename_only, pextention_only);
|
|
if (pextention_only) {_tcscat(pfilename_only,pextention_only);}
|
|
|
|
if ( _tcsicmp( pfilename_only, _T("lsass") ) == 0 )
|
|
{
|
|
// No matter what service it is, lets not kill lsass.exe
|
|
goto KillService_Exit;
|
|
}
|
|
|
|
// Convert it to ansi for our "kill" function
|
|
char szFile[ MAX_PATH ];
|
|
#if defined(UNICODE) || defined(_UNICODE)
|
|
WideCharToMultiByte( CP_ACP, 0, (WCHAR*)pfilename_only, -1, szFile, MAX_PATH, NULL, NULL );
|
|
#else
|
|
_tcscpy(szFile, pfilename_only);
|
|
#endif
|
|
|
|
// Some of these services have some action to do if the service is killed.
|
|
// like IISADMIN has some restart function which will automagically restart the
|
|
// Service if the process is not properly shutdown.
|
|
// We need to disable this deal because We can't have this service just startup by itself again.
|
|
iFlagPutItBack = FALSE;
|
|
if (_tcsicmp(ServiceConfig->lpServiceStartName,_T("IISADMIN")) == 0)
|
|
{
|
|
// Go lookup the registry for "FailureCommands" and save that information.
|
|
// retrieve from registry
|
|
CString csFailureCommand;
|
|
CRegKey regIISADMINParam(HKEY_LOCAL_MACHINE, REG_IISADMIN);
|
|
if ( (HKEY)regIISADMINParam )
|
|
{
|
|
regIISADMINParam.m_iDisplayWarnings = FALSE;
|
|
if (ERROR_SUCCESS == regIISADMINParam.QueryValue(_T("FailureCommands"), csFailureCommand))
|
|
{
|
|
// Kool, we got it.
|
|
// Set it to do nothing.
|
|
regIISADMINParam.SetValue(_T("FailureCommands"), _T(""));
|
|
iFlagPutItBack = TRUE;
|
|
}
|
|
}
|
|
|
|
// kill the service's process
|
|
if (KillProcessNameReturn0(szFile) == 0) {iReturn = TRUE;}
|
|
|
|
if (TRUE == iFlagPutItBack)
|
|
{
|
|
CRegKey regIISADMINParam(HKEY_LOCAL_MACHINE, REG_IISADMIN);
|
|
if ( (HKEY)regIISADMINParam )
|
|
{
|
|
regIISADMINParam.SetValue(_T("FailureCommands"), csFailureCommand);
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (KillProcessNameReturn0(szFile) == 0) {iReturn = TRUE;}
|
|
}
|
|
}
|
|
|
|
KillService_Exit:
|
|
if (ServiceConfig) {free(ServiceConfig);}
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
|
|
INT CheckifServiceMarkedForDeletion( LPCTSTR lpServiceName )
|
|
{
|
|
INT iReturn = FALSE;
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
// set up the service first
|
|
if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
|
|
(hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
err = GetLastError();
|
|
goto CheckifServiceMarkedForDeletion_Exit;
|
|
}
|
|
|
|
SERVICE_STATUS svcStatus;
|
|
if ( !QueryServiceStatus( hService, &svcStatus ))
|
|
{
|
|
err = ::GetLastError();
|
|
goto CheckifServiceMarkedForDeletion_Exit;
|
|
}
|
|
|
|
if ( svcStatus.dwCurrentState == SERVICE_RUNNING )
|
|
{
|
|
// We will only get this ERROR_SERVICE_MARKED_FOR_DELETE
|
|
// message if the service is already running.
|
|
if ( !::StartService( hService, 0, NULL ))
|
|
{
|
|
err = ::GetLastError();
|
|
if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {iReturn = TRUE;}
|
|
goto CheckifServiceMarkedForDeletion_Exit;
|
|
}
|
|
}
|
|
|
|
CheckifServiceMarkedForDeletion_Exit:
|
|
if (hService) CloseServiceHandle(hService);
|
|
if (hScManager) CloseServiceHandle(hScManager);
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
//
|
|
// warning: This will leave the lpServiceToValidate in the started mode upon exit!
|
|
//
|
|
int ValidateDependentService(LPCTSTR lpServiceToValidate, LPCTSTR lpServiceWhichIsDependent)
|
|
{
|
|
iisDebugOut_Start1(_T("ValidateDependentService"),(LPTSTR) lpServiceToValidate);
|
|
|
|
int iReturn = FALSE;
|
|
INT err = 0;
|
|
int iFailFlag = FALSE;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
|
|
|
|
// Let's validate that the lpServiceToValidate is installed fine.
|
|
|
|
// Check if the lpServiceToValidate service EVEN exists
|
|
err = CheckifServiceExistAndDependencies(lpServiceToValidate);
|
|
if ( err != 0 )
|
|
{
|
|
MyMessageBox(NULL, IDS_DEPENDENT_UPON_THIS_SVC_ERR, lpServiceWhichIsDependent,lpServiceWhichIsDependent,err, MB_OK | MB_SETFOREGROUND);
|
|
}
|
|
else
|
|
{
|
|
// Try to start the service
|
|
err = InetStartService(lpServiceToValidate);
|
|
if (err == 0 || err == ERROR_SERVICE_ALREADY_RUNNING)
|
|
{
|
|
err = NERR_Success;
|
|
iReturn = TRUE;
|
|
goto ValidateDependentService_Exit;
|
|
}
|
|
|
|
// Service returned an error when we tried to start it.
|
|
// Check if the error = ERROR_SERVICE_DEPENDENCY_FAIL
|
|
if (err == ERROR_SERVICE_DEPENDENCY_FAIL)
|
|
{
|
|
// Loop thru this services dependencies and try to
|
|
// start them, to find out which one failed to start.
|
|
iFailFlag = FALSE;
|
|
if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = ::OpenService( hScManager, lpServiceToValidate, GENERIC_ALL )) == NULL ) {iFailFlag = TRUE;}
|
|
// Get the existing Service information
|
|
if (iFailFlag != TRUE) {if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR) {iFailFlag = TRUE;}}
|
|
if (iFailFlag != TRUE) {if(!ServiceConfig){iFailFlag = TRUE;}}
|
|
// Get the dependencies
|
|
if (iFailFlag != TRUE)
|
|
{
|
|
TCHAR * pdest = NULL;
|
|
long RightMostNull = 0;
|
|
pdest = ServiceConfig->lpDependencies;
|
|
do
|
|
{
|
|
if (*pdest != _T('\0'))
|
|
{
|
|
RightMostNull = RightMostNull + _tcslen(pdest) + 1;
|
|
|
|
// Try to start the service...
|
|
err = InetStartService(pdest);
|
|
if (err)
|
|
{
|
|
if (err != ERROR_SERVICE_ALREADY_RUNNING)
|
|
{
|
|
// The pdest
|
|
// Service was unable to start because...
|
|
// MyMessageBox(NULL, IDS_UNABLE_TO_START, pdest, err, MB_OK | MB_SETFOREGROUND);
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("ValidateDependentService():Unable to start ServiceName=%s.\n"), pdest));
|
|
}
|
|
}
|
|
pdest = _tcschr(pdest, _T('\0'));
|
|
pdest++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
} while (TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MyMessageBox(NULL, IDS_UNABLE_TO_START, lpServiceToValidate, err, MB_OK | MB_SETFOREGROUND);
|
|
}
|
|
|
|
}
|
|
|
|
ValidateDependentService_Exit:
|
|
if (ServiceConfig) {free(ServiceConfig);}
|
|
if (hService) {CloseServiceHandle(hService);}
|
|
if (hScManager) {CloseServiceHandle(hScManager);}
|
|
iisDebugOut_End1(_T("ValidateDependentService"), lpServiceToValidate, LOG_TYPE_TRACE);
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
|
|
int LogEnumServicesStatus(void)
|
|
{
|
|
int iReturn = FALSE;
|
|
#ifndef _CHICAGO_
|
|
BOOL success = 0;
|
|
SC_HANDLE scm = NULL;
|
|
LPENUM_SERVICE_STATUS status = NULL;
|
|
DWORD numServices=0, sizeNeeded=0, resume=0;
|
|
|
|
// Open a connection to the SCM
|
|
//scm = OpenSCManager(0, 0, GENERIC_ALL);
|
|
scm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
|
|
if (!scm)
|
|
{
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("CallEnumServicesStatus():OpenSCManager. FAILED. err=0x%x\n"), GetLastError()));
|
|
goto CallEnumServicesStatus_Exit;
|
|
}
|
|
|
|
// get the number of bytes to allocate
|
|
// MAKE SURE resume starts at 0
|
|
resume = 0;
|
|
success = EnumServicesStatus(scm, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_ACTIVE | SERVICE_INACTIVE, 0, 0, &sizeNeeded, &numServices, &resume);
|
|
if (GetLastError() != ERROR_MORE_DATA)
|
|
{
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("CallEnumServicesStatus():EnumServicesStatus0. FAILED. err=0x%x\n"), GetLastError()));
|
|
goto CallEnumServicesStatus_Exit;
|
|
}
|
|
|
|
// Allocate space
|
|
status = (LPENUM_SERVICE_STATUS) LocalAlloc(LPTR, sizeNeeded);
|
|
if( status == NULL )
|
|
{
|
|
goto CallEnumServicesStatus_Exit;
|
|
}
|
|
|
|
// Get the status records. Making an assumption
|
|
// here that no new services get added during
|
|
// the allocation (could lock the database to
|
|
// guarantee that...)
|
|
resume = 0;
|
|
success = EnumServicesStatus(scm, SERVICE_WIN32,SERVICE_ACTIVE | SERVICE_INACTIVE,status, sizeNeeded, &sizeNeeded,&numServices, &resume);
|
|
if (!success)
|
|
{
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("CallEnumServicesStatus():EnumServicesStatus. FAILED. err=0x%x\n"), GetLastError()));
|
|
goto CallEnumServicesStatus_Exit;
|
|
}
|
|
|
|
DWORD i;
|
|
for (i=0; i < numServices; i++)
|
|
{
|
|
switch(status[i].ServiceStatus.dwCurrentState)
|
|
{
|
|
case SERVICE_STOPPED:
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_STOPPED [%s].\n"), status[i].lpServiceName));
|
|
break;
|
|
case SERVICE_START_PENDING:
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_START_PENDING [%s].\n"), status[i].lpServiceName));
|
|
break;
|
|
case SERVICE_STOP_PENDING:
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_STOP_PENDING [%s].\n"), status[i].lpServiceName));
|
|
break;
|
|
case SERVICE_RUNNING:
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_RUNNING [%s].\n"), status[i].lpServiceName));
|
|
break;
|
|
case SERVICE_CONTINUE_PENDING:
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_CONTINUE_PENDING [%s].\n"), status[i].lpServiceName));
|
|
break;
|
|
case SERVICE_PAUSE_PENDING:
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_PAUSE_PENDING [%s].\n"), status[i].lpServiceName));
|
|
break;
|
|
case SERVICE_PAUSED:
|
|
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SERVICE_PAUSED [%s].\n"), status[i].lpServiceName));
|
|
break;
|
|
}
|
|
}
|
|
iReturn = TRUE;
|
|
|
|
CallEnumServicesStatus_Exit:
|
|
if (status){LocalFree(status);}
|
|
if (scm) {CloseServiceHandle(scm);}
|
|
#endif
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
int InetIsThisExeAService(LPCTSTR lpFileNameToCheck, LPTSTR lpReturnServiceName)
|
|
{
|
|
int iReturn = FALSE;
|
|
#ifndef _CHICAGO_
|
|
BOOL success = 0;
|
|
SC_HANDLE scm = NULL;
|
|
LPENUM_SERVICE_STATUS status = NULL;
|
|
DWORD numServices=0, sizeNeeded=0, resume=0;
|
|
|
|
_tcscpy(lpReturnServiceName, _T(""));
|
|
|
|
// Open a connection to the SCM
|
|
//scm = OpenSCManager(0, 0, GENERIC_ALL);
|
|
scm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
|
|
if (!scm)
|
|
{
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("InetIsThisExeAService():OpenSCManager. FAILED. err=0x%x\n"), GetLastError()));
|
|
goto InetIsThisExeAService_Exit;
|
|
}
|
|
|
|
// get the number of bytes to allocate
|
|
// MAKE SURE resume starts at 0
|
|
resume = 0;
|
|
success = EnumServicesStatus(scm, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_ACTIVE | SERVICE_INACTIVE, 0, 0, &sizeNeeded, &numServices, &resume);
|
|
if (GetLastError() != ERROR_MORE_DATA)
|
|
{
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("InetIsThisExeAService():EnumServicesStatus0. FAILED. err=0x%x\n"), GetLastError()));
|
|
goto InetIsThisExeAService_Exit;
|
|
}
|
|
|
|
// Allocate space
|
|
status = (LPENUM_SERVICE_STATUS) LocalAlloc(LPTR, sizeNeeded);
|
|
if( status == NULL )
|
|
{
|
|
goto InetIsThisExeAService_Exit;
|
|
}
|
|
|
|
// Get the status records. Making an assumption
|
|
// here that no new services get added during
|
|
// the allocation (could lock the database to
|
|
// guarantee that...)
|
|
resume = 0;
|
|
success = EnumServicesStatus(scm, SERVICE_WIN32,SERVICE_ACTIVE | SERVICE_INACTIVE,status, sizeNeeded, &sizeNeeded,&numServices, &resume);
|
|
if (!success)
|
|
{
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("InetIsThisExeAService():EnumServicesStatus. FAILED. err=0x%x\n"), GetLastError()));
|
|
goto InetIsThisExeAService_Exit;
|
|
}
|
|
|
|
DWORD i;
|
|
for (i=0; i < numServices; i++)
|
|
{
|
|
// Use the status[i].lpServiceName
|
|
// to query the service and find out it's binary filename
|
|
if (TRUE == InetIsThisExeAService_Worker(status[i].lpServiceName, lpFileNameToCheck))
|
|
{
|
|
iReturn = TRUE;
|
|
// copy in the service name into the return string.
|
|
_tcscpy(lpReturnServiceName, status[i].lpServiceName);
|
|
goto InetIsThisExeAService_Exit;
|
|
}
|
|
}
|
|
|
|
InetIsThisExeAService_Exit:
|
|
if (status){LocalFree(status);}
|
|
if (scm) {CloseServiceHandle(scm);}
|
|
#endif
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
int InetIsThisExeAService_Worker(LPCTSTR lpServiceName, LPCTSTR lpFileNameToCheck)
|
|
{
|
|
int iReturn = FALSE;
|
|
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
|
|
|
|
BYTE ConfigBuffer[4096];
|
|
LPENUM_SERVICE_STATUS ServiceConfigEnum = (LPENUM_SERVICE_STATUS) &ConfigBuffer;
|
|
|
|
if (( hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
// Failed, or more likely the service doesn't exist
|
|
//iReturn = GetLastError();
|
|
goto InetIsThisExeAService_Worker_Exit;
|
|
}
|
|
|
|
if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
|
|
{
|
|
//iReturn = GetLastError();
|
|
goto InetIsThisExeAService_Worker_Exit;
|
|
}
|
|
|
|
if(!ServiceConfig)
|
|
{
|
|
goto InetIsThisExeAService_Worker_Exit;
|
|
}
|
|
|
|
if ( (ServiceConfig->dwServiceType & SERVICE_WIN32_OWN_PROCESS) || (ServiceConfig->dwServiceType & SERVICE_WIN32_SHARE_PROCESS))
|
|
{
|
|
if (ServiceConfig->lpBinaryPathName)
|
|
{
|
|
if (_tcsicmp(lpFileNameToCheck, ServiceConfig->lpBinaryPathName) == 0)
|
|
{
|
|
//We found a match!!!!!
|
|
iReturn = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// we did not find a match, based on c:\path\filename and c:\path\filename
|
|
// maybe we try "filename.exe" and "filename.exe"????
|
|
TCHAR szBinaryNameOnly[_MAX_FNAME];
|
|
TCHAR szFileNameToCheckNameOnly[_MAX_FNAME];
|
|
if (TRUE == ReturnFileNameOnly((LPCTSTR) ServiceConfig->lpBinaryPathName, szBinaryNameOnly))
|
|
{
|
|
if (TRUE == ReturnFileNameOnly((LPCTSTR) lpFileNameToCheck, szFileNameToCheckNameOnly))
|
|
{
|
|
if (_tcsicmp(szFileNameToCheckNameOnly, szBinaryNameOnly) == 0)
|
|
{
|
|
//We found a match!!!!!
|
|
iReturn = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
InetIsThisExeAService_Worker_Exit:
|
|
if (ServiceConfig) {free(ServiceConfig);}
|
|
if (hService) {CloseServiceHandle(hService);}
|
|
if (hScManager) {CloseServiceHandle(hScManager);}
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
int IsThisServiceADriver(LPCTSTR lpServiceName)
|
|
{
|
|
int iReturn = FALSE;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
LPQUERY_SERVICE_CONFIG ServiceConfig=NULL;
|
|
|
|
BYTE ConfigBuffer[4096];
|
|
LPENUM_SERVICE_STATUS ServiceConfigEnum = (LPENUM_SERVICE_STATUS) &ConfigBuffer;
|
|
if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL || (hService = OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
// Failed, or more likely the service doesn't exist
|
|
//iReturn = GetLastError();
|
|
goto IsThisServiceADriver_Exit;
|
|
}
|
|
|
|
if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
|
|
{
|
|
//iReturn = GetLastError();
|
|
goto IsThisServiceADriver_Exit;
|
|
}
|
|
|
|
if(!ServiceConfig)
|
|
{
|
|
//iReturn = GetLastError();
|
|
goto IsThisServiceADriver_Exit;
|
|
}
|
|
|
|
if ( (ServiceConfig->dwServiceType & SERVICE_KERNEL_DRIVER) || (ServiceConfig->dwServiceType & SERVICE_FILE_SYSTEM_DRIVER))
|
|
{
|
|
iReturn = TRUE;
|
|
}
|
|
|
|
IsThisServiceADriver_Exit:
|
|
if (ServiceConfig) {free(ServiceConfig);}
|
|
if (hService) {CloseServiceHandle(hService);}
|
|
if (hScManager) {CloseServiceHandle(hScManager);}
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
int CreateDriver(CString csDriverName, CString csDisplayName, CString csFileName)
|
|
{
|
|
DWORD dwReturn = ERROR_SUCCESS;
|
|
CString csBinPath;
|
|
CString csFile;
|
|
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("CreateDriver:%s:%s start.\n"), csDriverName, csFileName));
|
|
|
|
csBinPath = _T("\\SystemRoot\\System32\\drivers\\");
|
|
csBinPath += csFileName;
|
|
|
|
// Check if the file even exists first.
|
|
csFile = g_pTheApp->m_csSysDir;
|
|
csFile += _T("\\Drivers\\");
|
|
csFile += csFileName;
|
|
if (!IsFileExist(csFile))
|
|
{
|
|
dwReturn = ERROR_FILE_NOT_FOUND;
|
|
goto CreateDriver_Exit;
|
|
}
|
|
|
|
//
|
|
// Attempt to create the service, could fail if this is an
|
|
// Refresh Install will leave the driver from the prior
|
|
// Install, becuse if we delete in the remove phase it will
|
|
// get marked for deletion and not get readded now.
|
|
// this could happen in a upgrade as well....
|
|
//
|
|
dwReturn = InetCreateDriver(csDriverName, (LPCTSTR)csDisplayName, (LPCTSTR)csBinPath, SERVICE_DEMAND_START);
|
|
if ( dwReturn != ERROR_SUCCESS )
|
|
{
|
|
if (dwReturn == ERROR_SERVICE_EXISTS)
|
|
{
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("CreateDriver:%s:Service exists.\n"), csDriverName));
|
|
dwReturn = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("CreateDriver:%s:failed to create service Err=0x%x.\n"), csDriverName, dwReturn));
|
|
MyMessageBox(NULL, IDS_UNABLE_TO_CREATE_DRIVER, csDriverName, dwReturn, MB_OK | MB_SETFOREGROUND);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("CreateDriver:%s:Successfully created.\n"), csDriverName));
|
|
}
|
|
|
|
CreateDriver_Exit:
|
|
return dwReturn;
|
|
}
|
|
|
|
|
|
DWORD CreateDriver_Wrap(CString csDriverName, CString csDisplayName, CString csFileName,BOOL bDisplayMsgOnErrFlag)
|
|
{
|
|
int bFinishedFlag = FALSE;
|
|
UINT iMsg = NULL;
|
|
DWORD dwReturn = ERROR_SUCCESS;
|
|
|
|
// Create or Config driver spud.sys, NT Server product onloy!!!
|
|
if (g_pTheApp->m_eOS != OS_W95)
|
|
{
|
|
do
|
|
{
|
|
dwReturn = CreateDriver(csDriverName, csDisplayName, csFileName);
|
|
if (dwReturn == ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (bDisplayMsgOnErrFlag == TRUE)
|
|
{
|
|
iMsg = MyMessageBox( NULL, IDS_RETRY, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND );
|
|
switch ( iMsg )
|
|
{
|
|
case IDIGNORE:
|
|
dwReturn = ERROR_SUCCESS;
|
|
goto CreateDriver_Wrap_Exit;
|
|
case IDABORT:
|
|
dwReturn = ERROR_OPERATION_ABORTED;
|
|
goto CreateDriver_Wrap_Exit;
|
|
case IDRETRY:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// return whatever err happened
|
|
goto CreateDriver_Wrap_Exit;
|
|
}
|
|
|
|
}
|
|
} while (dwReturn != ERROR_SUCCESS);
|
|
}
|
|
|
|
CreateDriver_Wrap_Exit:
|
|
return dwReturn;
|
|
}
|
|
|
|
|
|
INT InetConfigServiceInteractive(LPCTSTR lpServiceName, int AddInteractive)
|
|
{
|
|
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("InetConfigServiceInteractive(%i):ServiceName=%s\n"),AddInteractive,(LPTSTR) lpServiceName));
|
|
|
|
INT err = 0;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
LPQUERY_SERVICE_CONFIG ServiceConfig = NULL;
|
|
DWORD dwNewServiceType = 0;
|
|
BOOL bDoStuff = FALSE;
|
|
|
|
do {
|
|
if ((hScManager = ::OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
|
|
(hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
|
|
{
|
|
err = GetLastError();
|
|
// if error = ERROR_SERVICE_DOES_NOT_EXIST
|
|
if (ERROR_SERVICE_DOES_NOT_EXIST != err)
|
|
{
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigServiceInteractive():OpenSCManager or OpenService: Service=%s Err=0x%x FAILED\n"), lpServiceName,err));
|
|
}
|
|
break;
|
|
}
|
|
|
|
if(RetrieveServiceConfig(hService, &ServiceConfig) != NO_ERROR)
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
if(!ServiceConfig)
|
|
{
|
|
err = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// Interactive flag can only work on own_process or share_process types
|
|
if ( (ServiceConfig->dwServiceType & SERVICE_WIN32_OWN_PROCESS) || (ServiceConfig->dwServiceType & SERVICE_WIN32_SHARE_PROCESS))
|
|
{
|
|
// default it incase someone changes code below and logic gets messed up
|
|
dwNewServiceType = ServiceConfig->dwServiceType;
|
|
|
|
// if the interactive flag is already there
|
|
// then don't do jack, otherwise, add it on
|
|
if (ServiceConfig->dwServiceType & SERVICE_INTERACTIVE_PROCESS)
|
|
{
|
|
// only do stuff if we're asked to remove it!
|
|
if (FALSE == AddInteractive)
|
|
{
|
|
// Remove it from the mask!
|
|
dwNewServiceType = ServiceConfig->dwServiceType & (~SERVICE_INTERACTIVE_PROCESS);
|
|
bDoStuff = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (TRUE == AddInteractive)
|
|
{
|
|
dwNewServiceType = ServiceConfig->dwServiceType | SERVICE_INTERACTIVE_PROCESS;
|
|
bDoStuff = TRUE;
|
|
}
|
|
}
|
|
|
|
if (TRUE == bDoStuff)
|
|
{
|
|
if ( !::ChangeServiceConfig(hService, dwNewServiceType, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL) )
|
|
{
|
|
err = GetLastError();
|
|
iisDebugOut((LOG_TYPE_ERROR, _T("InetConfigServiceInteractive():ChangeServiceConfig: Service=%s Err=0x%x FAILED\n"), lpServiceName, err));
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
} while ( FALSE );
|
|
|
|
if (ServiceConfig) {free(ServiceConfig);}
|
|
if (hService) {CloseServiceHandle(hService);}
|
|
if (hScManager) {CloseServiceHandle(hScManager);}
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("InetConfigServiceInteractive():ServiceName=%s. Return=0x%x.\n"), lpServiceName, err));
|
|
return(err);
|
|
}
|
|
|
|
|
|
// This function trys to create the www service
|
|
int MyCreateService(CString csServiceName, CString csDisplayName, CString csBinPath, CString csDependencies, CString csDescription)
|
|
{
|
|
int iReturn = !ERROR_SUCCESS;
|
|
int err = NERR_Success;
|
|
TSTR strDependencies2( MAX_PATH );
|
|
|
|
iisDebugOut((LOG_TYPE_TRACE, _T("MyCreateService:%s,%s,%s,%s.\n"),csServiceName, csDisplayName, csBinPath, csDependencies));
|
|
|
|
if ( !strDependencies2.Copy( csDependencies.GetBuffer(0) ) ||
|
|
!strDependencies2.Append( _T(":") )
|
|
)
|
|
{
|
|
return iReturn;
|
|
}
|
|
|
|
// make sure it ends with a ":"
|
|
// and then replace all the ":", with a "\0" null....
|
|
TCHAR *p = (LPTSTR) strDependencies2.QueryStr();
|
|
while (*p)
|
|
{
|
|
// change ":" to a null "\0"
|
|
if (*p == _T(':')){*p = _T('\0');}
|
|
p = _tcsinc(p);
|
|
}
|
|
|
|
err = InetCreateService(csServiceName,
|
|
(LPCTSTR)csDisplayName,
|
|
(LPCTSTR)csBinPath,
|
|
SERVICE_AUTO_START,
|
|
strDependencies2.QueryStr());
|
|
|
|
if ( err != NERR_Success )
|
|
{
|
|
// check if the error is because the service already exists...
|
|
if (err == ERROR_SERVICE_EXISTS)
|
|
{
|
|
// Since the service should exist by the time we get here,
|
|
// let's make sure it has the dependency we want it to have.
|
|
err = InetConfigService(csServiceName, (LPCTSTR)csDisplayName, (LPCTSTR)csBinPath, strDependencies2.QueryStr());
|
|
if (err != NERR_Success)
|
|
{
|
|
SetLastError(err);
|
|
goto MyCreateService_Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetLastError(err);
|
|
goto MyCreateService_Exit;
|
|
}
|
|
|
|
}
|
|
|
|
// Use newer api to add the description field.
|
|
err = InetConfigService2(csServiceName, (LPCTSTR)csDescription);
|
|
if (err != NERR_Success)
|
|
{
|
|
SetLastError(err);
|
|
goto MyCreateService_Exit;
|
|
}
|
|
|
|
// there was no error in the InetCreateService call.
|
|
// so everything is hunky dory
|
|
iReturn = ERROR_SUCCESS;
|
|
|
|
MyCreateService_Exit:
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
DWORD CreateService_wrap(CString csServiceName, CString csDisplayName, CString csBinPath, CString csDependencies, CString csDescription, BOOL bDisplayMsgOnErrFlag)
|
|
{
|
|
int bFinishedFlag = FALSE;
|
|
UINT iMsg = NULL;
|
|
DWORD dwReturn = ERROR_SUCCESS;
|
|
|
|
do
|
|
{
|
|
dwReturn = MyCreateService(csServiceName, csDisplayName, csBinPath, csDependencies, csDescription);
|
|
if (dwReturn == ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (bDisplayMsgOnErrFlag == TRUE)
|
|
{
|
|
iMsg = MyMessageBox( NULL, IDS_RETRY, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND );
|
|
switch ( iMsg )
|
|
{
|
|
case IDIGNORE:
|
|
dwReturn = ERROR_SUCCESS;
|
|
goto CreateService_wrap_Exit;
|
|
case IDABORT:
|
|
dwReturn = ERROR_OPERATION_ABORTED;
|
|
goto CreateService_wrap_Exit;
|
|
case IDRETRY:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// return whatever err happened
|
|
goto CreateService_wrap_Exit;
|
|
}
|
|
|
|
}
|
|
} while (dwReturn != ERROR_SUCCESS);
|
|
|
|
CreateService_wrap_Exit:
|
|
return dwReturn;
|
|
}
|
|
|
|
// function: ChangeServiceDepenedency
|
|
//
|
|
// Change the dependency of a particular service, to either add or remove another service name
|
|
// from it
|
|
//
|
|
// ex. ChangeServiceDependency( W3SSL, TRUE, IISADMIN ) - Would make W3SSL dependant on IISADMIN
|
|
//
|
|
// Parameters:
|
|
// szServiceName - The service to modify
|
|
// bAddDependency - Add or remove dependency
|
|
// szDependantService - The service that you wand to add as the depenedency
|
|
//
|
|
BOOL
|
|
ChangeServiceDependency(LPTSTR szServiceName, BOOL bAddDependency, LPTSTR szDependantService)
|
|
{
|
|
SC_HANDLE hService;
|
|
SC_HANDLE hSCManager;
|
|
BOOL bRet = FALSE;
|
|
BOOL bChange = FALSE;
|
|
BUFFER buffConfig;
|
|
DWORD dwSizeRequired;
|
|
TSTR_MSZ mszDependencies;
|
|
|
|
hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT | GENERIC_READ );
|
|
|
|
if ( hSCManager == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
hService = OpenService( hSCManager, szServiceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG );
|
|
|
|
if ( hService == NULL )
|
|
{
|
|
CloseServiceHandle( hSCManager );
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !QueryServiceConfig( hService, NULL, 0, &dwSizeRequired ) &&
|
|
( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) &&
|
|
buffConfig.Resize( dwSizeRequired ) &&
|
|
QueryServiceConfig( hService, (LPQUERY_SERVICE_CONFIG) buffConfig.QueryPtr(), buffConfig.QuerySize(), &dwSizeRequired )
|
|
)
|
|
{
|
|
// We have successfully retrieved the service info, so lets modify it
|
|
if ( mszDependencies.Copy( ((LPQUERY_SERVICE_CONFIG) buffConfig.QueryPtr())->lpDependencies ) )
|
|
{
|
|
if ( bAddDependency )
|
|
{
|
|
if ( !mszDependencies.IsPresent(szDependantService, FALSE) )
|
|
{
|
|
bRet = mszDependencies.Add( szDependantService );
|
|
bChange = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// It is already present, so we don't need to add again
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( mszDependencies.IsPresent(szDependantService, FALSE) )
|
|
{
|
|
bRet = mszDependencies.Remove( szDependantService, FALSE );
|
|
bChange = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Since it is not there, lets not worry about it
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( bRet && bChange )
|
|
{
|
|
bRet = ChangeServiceConfig( hService, // Service Handle
|
|
SERVICE_NO_CHANGE, // Service Type
|
|
SERVICE_NO_CHANGE, // Startup Type
|
|
SERVICE_NO_CHANGE, // Error Control
|
|
NULL, // Binary Path
|
|
NULL, // Load Order Group
|
|
NULL, // TagID
|
|
mszDependencies.QueryMultiSz(), // Dependencies
|
|
NULL, // Service Start Name
|
|
NULL, // Password
|
|
NULL ); // Display Name
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseServiceHandle( hSCManager );
|
|
CloseServiceHandle( hService );
|
|
|
|
return bRet;
|
|
}
|