summaryrefslogtreecommitdiffstats
path: root/lib/libnt/service.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libnt/service.c')
-rw-r--r--lib/libnt/service.c375
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;
+}
+