diff options
Diffstat (limited to 'lib/libnt/service.c')
-rw-r--r-- | lib/libnt/service.c | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/lib/libnt/service.c b/lib/libnt/service.c new file mode 100644 index 00000000..1bfc5a5e --- /dev/null +++ b/lib/libnt/service.c @@ -0,0 +1,375 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +#include <windows.h> +#include "nt/ntos.h" + +#define SERVRET_ERROR 0 +#define SERVRET_INSTALLED 1 +#define SERVRET_STARTING 2 +#define SERVRET_STARTED 3 +#define SERVRET_STOPPING 4 +#define SERVRET_REMOVED 5 + + +DWORD NS_WINAPI +SERVICE_GetNTServiceStatus(LPCTSTR szServiceName, LPDWORD lpLastError ) +{ + SERVICE_STATUS ServiceStatus; + SC_HANDLE schService = NULL; + SC_HANDLE schSCManager = NULL; + DWORD lastError = 0; + int ret = 0; + + //ereport(LOG_INFORM, "open SC Manager"); + if ((schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + )) == NULL ) { + lastError = GetLastError(); + ret = SERVRET_ERROR; + goto finish; + } + + schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS); + + if (schService == NULL ) { + lastError = GetLastError(); + if (lastError == ERROR_SERVICE_DOES_NOT_EXIST) { + lastError = 0; + ret = SERVRET_REMOVED; + } else + ret = SERVRET_ERROR; + goto finish; + } + + ret = ControlService(schService, SERVICE_CONTROL_INTERROGATE, &ServiceStatus); + + if ( !ret ) { + lastError = GetLastError(); + if ( lastError == ERROR_SERVICE_NOT_ACTIVE ) { + lastError = 0; + ret = SERVRET_INSTALLED; + } else + ret = SERVRET_ERROR; + goto finish; + } + + switch ( ServiceStatus.dwCurrentState ) { + case SERVICE_STOPPED: ret = SERVRET_INSTALLED; break; + case SERVICE_START_PENDING: ret = SERVRET_STARTING; break; + case SERVICE_STOP_PENDING: ret = SERVRET_STOPPING; break; + case SERVICE_RUNNING: ret = SERVRET_STARTED; break; + case SERVICE_CONTINUE_PENDING: ret = SERVRET_STARTED; break; + case SERVICE_PAUSE_PENDING: ret = SERVRET_STARTED; break; + case SERVICE_PAUSED: ret = SERVRET_STARTED; break; + default: ret = SERVRET_ERROR; break; + } + +finish: + if ( schService) + CloseServiceHandle(schService); + if ( schSCManager) + CloseServiceHandle(schSCManager); + if ( lpLastError ) + *lpLastError = lastError; + return ret; +} + +DWORD NS_WINAPI +SERVICE_InstallNTService(LPCTSTR szServiceName, LPCTSTR szServiceDisplayName, LPCTSTR szServiceExe ) +{ + LPCTSTR lpszBinaryPathName = szServiceExe; + SC_HANDLE schService = NULL; + SC_HANDLE schSCManager = NULL; + int lastError = 0; + int ret = 0; + + + //ereport(LOG_INFORM, "open SC Manager"); + if ((schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + )) == NULL ) { + lastError = GetLastError(); + goto finish; + } + + /* check if service already exists */ + schService = OpenService( schSCManager, + szServiceName, + SERVICE_ALL_ACCESS + ); + if (schService) { + lastError = ERROR_SERVICE_EXISTS; + goto finish; + } + + schService = CreateService( + schSCManager, // SCManager database + szServiceName, // name of service + szServiceDisplayName, // name to display + SERVICE_ALL_ACCESS, // desired access + SERVICE_WIN32_OWN_PROCESS | + SERVICE_INTERACTIVE_PROCESS, // service type + SERVICE_AUTO_START, //SERVICE_DEMAND_START, // start type + SERVICE_ERROR_NORMAL, // error control type + lpszBinaryPathName, // service's binary + NULL, // no load ordering group + NULL, // no tag identifier + NULL, // no dependencies + NULL, // LocalSystem account + NULL); // no password + + if (schService == NULL) { + lastError = GetLastError(); + } + + // successfully installed service + +finish: + if ( schService) + CloseServiceHandle(schService); + if ( schSCManager) + CloseServiceHandle(schSCManager); + return lastError; +} + + +DWORD NS_WINAPI +SERVICE_RemoveNTService(LPCTSTR szServiceName) +{ + SC_HANDLE schService = NULL; + SC_HANDLE schSCManager = NULL; + int lastError = 0; + int ret = 0; + + //ereport(LOG_INFORM, "open SC Manager"); + if ((schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + )) == NULL ) { + lastError = GetLastError(); + goto finish; + } + + schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS); + + if (schService == NULL ) { + lastError = GetLastError(); + goto finish; + } + + ret = DeleteService(schService); + + if ( !ret) { + lastError = GetLastError(); + goto finish; + } + + // successfully removed service + +finish: + if ( schService) + CloseServiceHandle(schService); + if ( schSCManager) + CloseServiceHandle(schSCManager); + return lastError; +} + +DWORD NS_WINAPI +SERVICE_StartNTService(LPCTSTR szServiceName) +{ + SC_HANDLE schService = NULL; + SC_HANDLE schSCManager = NULL; + int lastError = 0; + int ret = 0; + + //ereport(LOG_INFORM, "open SC Manager"); + if ((schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + )) == NULL ) { + lastError = GetLastError(); + goto finish; + } + + schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS); + + if (schService == NULL ) { + lastError = GetLastError(); + goto finish; + } + + ret = StartService(schService, 0, NULL); + + if ( !ret ) { + lastError = GetLastError(); + goto finish; + } + + // successfully started service + + +finish: + if ( schService) + CloseServiceHandle(schService); + if ( schSCManager) + CloseServiceHandle(schSCManager); + return lastError; +} + +DWORD NS_WINAPI +SERVICE_StartNTServiceAndWait(LPCTSTR szServiceName, LPDWORD lpdwLastError) +{ + DWORD dwLastError; + DWORD dwStatus; + int i; + + /* check if service is running */ + dwStatus = SERVICE_GetNTServiceStatus( szServiceName, &dwLastError ); + if ( dwStatus == SERVRET_STARTED ) + return TRUE; + + dwLastError = SERVICE_StartNTService( szServiceName ); + if ( dwLastError != 0 ) { + goto errorExit; + } + + for ( i=0; i<5; i++ ) { + // make sure the service got installed + dwStatus = SERVICE_GetNTServiceStatus( szServiceName, &dwLastError ); + if ( dwStatus == SERVRET_ERROR) { + if ( dwLastError != ERROR_SERVICE_CANNOT_ACCEPT_CTRL ) + goto errorExit; + } else if ( dwStatus == SERVRET_STARTED ) + return TRUE; + + Sleep ( 1000 ); + } + + dwLastError = 0; + +errorExit: + if ( lpdwLastError ) + *lpdwLastError = dwLastError; + return FALSE; +} + +DWORD NS_WINAPI +SERVICE_StopNTService(LPCTSTR szServiceName) +{ + SC_HANDLE schService = NULL; + SC_HANDLE schSCManager = NULL; + int lastError = 0; + int ret = 0; + SERVICE_STATUS ServiceStatus; + + //ereport(LOG_INFORM, "open SC Manager"); + if ((schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + )) == NULL ) { + lastError = GetLastError(); + goto finish; + } + + schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS); + + if (schService == NULL ) { + lastError = GetLastError(); + goto finish; + } + + ret = ControlService(schService, SERVICE_CONTROL_STOP, &ServiceStatus); + + if ( !ret ) { + lastError = GetLastError(); + goto finish; + } + + // server is stopping + +finish: + if ( schService) + CloseServiceHandle(schService); + if ( schSCManager) + CloseServiceHandle(schSCManager); + return lastError; +} + +DWORD NS_WINAPI +SERVICE_StopNTServiceAndWait(LPCTSTR szServiceName, LPDWORD lpdwLastError) +{ + DWORD dwLastError; + DWORD dwStatus; + int i; + + /* check if service is running */ + dwStatus = SERVICE_GetNTServiceStatus( szServiceName, &dwLastError ); + if ( dwStatus != SERVRET_STARTED ) + return TRUE; + + for ( i=0; i<30; i++ ) { + dwLastError = SERVICE_StopNTService( szServiceName ); + Sleep ( 1000 ); + + // make sure the service is stoppped and just installed + dwStatus = SERVICE_GetNTServiceStatus( szServiceName, &dwLastError ); + Sleep ( 1000 ); + if ( dwStatus == SERVRET_INSTALLED ) { + Sleep ( 1000 ); + return TRUE; + } + } + + if ( lpdwLastError ) + *lpdwLastError = dwLastError; + return FALSE; +} + +DWORD NS_WINAPI +SERVICE_ReinstallNTService(LPCTSTR szServiceName, LPCTSTR szServiceDisplayName, LPCTSTR szServiceExe ) +{ + DWORD dwLastError; + DWORD dwStatus; + int i; + + for ( i=0; i< 5; i++ ) { + + /* if service is running, stop it */ + dwStatus = SERVICE_GetNTServiceStatus( szServiceName, &dwLastError ); + if ( dwStatus == SERVRET_STARTED ) + SERVICE_StopNTServiceAndWait( szServiceName, &dwLastError ); + + /* if service is installed, remove it */ + dwStatus = SERVICE_GetNTServiceStatus( szServiceName, &dwLastError ); + if ( dwStatus == SERVRET_INSTALLED ) + SERVICE_RemoveNTService( szServiceName ); + + /* try and install the service again */ + dwStatus = SERVICE_GetNTServiceStatus( szServiceName, &dwLastError ); + if ( dwStatus == SERVRET_REMOVED ) + SERVICE_InstallNTService( szServiceName, szServiceDisplayName, szServiceExe ); + + /* try and start the service again */ + dwStatus = SERVICE_GetNTServiceStatus( szServiceName, &dwLastError ); + if ( dwStatus == SERVRET_INSTALLED ) { + return NO_ERROR; + } + } + + /* if no error reported, force an error */ + if ( dwLastError == NO_ERROR ) + dwLastError = (DWORD)-1; + + return dwLastError; +} + |