X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Fliblutil%2Fntservice.c;h=23d1ea6fb195cc8e04e089ac5e2f523b529eb2df;hb=5ce2a2aee611726aa763234469d6849d2113044f;hp=6540bf20797fc0ae8e9063457c1d592b1130299d;hpb=b7af076fee4d363bdfa963dfd458e13ea5e5816e;p=openldap diff --git a/libraries/liblutil/ntservice.c b/libraries/liblutil/ntservice.c index 6540bf2079..23d1ea6fb1 100644 --- a/libraries/liblutil/ntservice.c +++ b/libraries/liblutil/ntservice.c @@ -1,9 +1,22 @@ /* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2012 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + /* - * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + * NT Service manager utilities for OpenLDAP services */ -/* ntservice.c */ + #include "portable.h" #ifdef HAVE_NT_SERVICE_MANAGER @@ -18,13 +31,8 @@ #include -#define ldap_debug slap_debug -extern int slap_debug; - -#include "ldap_log.h" #include "ldap_pvt_thread.h" - #include "ldap_defaults.h" #include "slapdmsg.h" @@ -32,36 +40,38 @@ extern int slap_debug; #define SCM_NOTIFICATION_INTERVAL 5000 #define THIRTY_SECONDS (30 * 1000) -int is_NT_Service = 1; /* assume this is an NT service until determined that */ - /* startup was from the command line */ +int is_NT_Service; /* is this is an NT service? */ -SERVICE_STATUS SLAPDServiceStatus; -SERVICE_STATUS_HANDLE hSLAPDServiceStatus; +SERVICE_STATUS lutil_ServiceStatus; +SERVICE_STATUS_HANDLE hlutil_ServiceStatus; ldap_pvt_thread_cond_t started_event, stopped_event; ldap_pvt_thread_t start_status_tid, stop_status_tid; void (*stopfunc)(int); -/* in nt_err.c */ -char *GetLastErrorString( void ); +static char *GetLastErrorString( void ); -int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) +int lutil_srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszDisplayName, + LPCTSTR lpszBinaryPathName, int auto_start) { HKEY hKey; DWORD dwValue, dwDisposition; SC_HANDLE schSCManager, schService; + char *sp = strchr( lpszBinaryPathName, ' '); + if ( sp ) *sp = '\0'; fprintf( stderr, "The install path is %s.\n", lpszBinaryPathName ); + if ( sp ) *sp = ' '; if ((schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE ) ) != NULL ) { if ((schService = CreateService( schSCManager, lpszServiceName, - TEXT("OpenLDAP Directory Service"), - SC_MANAGER_CREATE_SERVICE, + lpszDisplayName, + SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, - SERVICE_DEMAND_START, + auto_start ? SERVICE_AUTO_START : SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, lpszBinaryPathName, NULL, NULL, NULL, NULL, NULL)) != NULL) @@ -70,7 +80,8 @@ int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) CloseServiceHandle(schService); CloseServiceHandle(schSCManager); - sprintf( regpath, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s", + snprintf( regpath, sizeof regpath, + "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s", lpszServiceName ); /* Create the registry key for event logging to the Windows NT event log. */ if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, @@ -82,6 +93,7 @@ int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) RegCloseKey(hKey); return(0); } + if ( sp ) *sp = '\0'; if ( RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ, lpszBinaryPathName, strlen(lpszBinaryPathName) + 1) != ERROR_SUCCESS) { fprintf( stderr, "RegSetValueEx(EventMessageFile) failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() ); @@ -112,7 +124,7 @@ int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) } -int srv_remove(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) +int lutil_srv_remove(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) { SC_HANDLE schSCManager, schService; @@ -145,6 +157,58 @@ int srv_remove(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName) } +#if 0 /* unused */ +DWORD +svc_installed (LPTSTR lpszServiceName, LPTSTR lpszBinaryPathName) +{ + char buf[256]; + HKEY key; + DWORD rc; + DWORD type; + long len; + + strcpy(buf, TEXT("SYSTEM\\CurrentControlSet\\Services\\")); + strcat(buf, lpszServiceName); + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) + return(-1); + + rc = 0; + if (lpszBinaryPathName) { + len = sizeof(buf); + if (RegQueryValueEx(key, "ImagePath", NULL, &type, buf, &len) == ERROR_SUCCESS) { + if (strcmp(lpszBinaryPathName, buf)) + rc = -1; + } + } + RegCloseKey(key); + return(rc); +} + + +DWORD +svc_running (LPTSTR lpszServiceName) +{ + SC_HANDLE service; + SC_HANDLE scm; + DWORD rc; + SERVICE_STATUS ss; + + if (!(scm = OpenSCManager(NULL, NULL, GENERIC_READ))) + return(GetLastError()); + + rc = 1; + service = OpenService(scm, lpszServiceName, SERVICE_QUERY_STATUS); + if (service) { + if (!QueryServiceStatus(service, &ss)) + rc = GetLastError(); + else if (ss.dwCurrentState != SERVICE_STOPPED) + rc = 0; + CloseServiceHandle(service); + } + CloseServiceHandle(scm); + return(rc); +} +#endif static void *start_status_routine( void *ptr ) { @@ -161,27 +225,27 @@ static void *start_status_routine( void *ptr ) /* the object that we were waiting for has been destroyed (ABANDONED) or * signalled (TIMEOUT_0). We can assume that the startup process is * complete and tell the Service Control Manager that we are now runnng */ - SLAPDServiceStatus.dwCurrentState = SERVICE_RUNNING; - SLAPDServiceStatus.dwWin32ExitCode = NO_ERROR; - SLAPDServiceStatus.dwCheckPoint++; - SLAPDServiceStatus.dwWaitHint = 1000; - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + lutil_ServiceStatus.dwCurrentState = SERVICE_RUNNING; + lutil_ServiceStatus.dwWin32ExitCode = NO_ERROR; + lutil_ServiceStatus.dwCheckPoint++; + lutil_ServiceStatus.dwWaitHint = 1000; + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); done = 1; break; case WAIT_TIMEOUT: /* We've waited for the required time, so send an update to the Service Control * Manager saying to wait again. */ - SLAPDServiceStatus.dwCheckPoint++; - SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + lutil_ServiceStatus.dwCheckPoint++; + lutil_ServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); break; case WAIT_FAILED: /* theres been some problem with WaitForSingleObject so tell the Service * Control Manager to wait 30 seconds before deploying its assasin and * then leave the thread. */ - SLAPDServiceStatus.dwCheckPoint++; - SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS; - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + lutil_ServiceStatus.dwCheckPoint++; + lutil_ServiceStatus.dwWaitHint = THIRTY_SECONDS; + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); done = 1; break; } @@ -213,17 +277,17 @@ static void *stop_status_routine( void *ptr ) case WAIT_TIMEOUT: /* We've waited for the required time, so send an update to the Service Control * Manager saying to wait again. */ - SLAPDServiceStatus.dwCheckPoint++; - SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + lutil_ServiceStatus.dwCheckPoint++; + lutil_ServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); break; case WAIT_FAILED: /* theres been some problem with WaitForSingleObject so tell the Service * Control Manager to wait 30 seconds before deploying its assasin and * then leave the thread. */ - SLAPDServiceStatus.dwCheckPoint++; - SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS; - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + lutil_ServiceStatus.dwCheckPoint++; + lutil_ServiceStatus.dwWaitHint = THIRTY_SECONDS; + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); done = 1; break; } @@ -234,27 +298,26 @@ static void *stop_status_routine( void *ptr ) -void WINAPI SLAPDServiceCtrlHandler( IN DWORD Opcode) +static void WINAPI lutil_ServiceCtrlHandler( IN DWORD Opcode) { switch (Opcode) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: - Debug( LDAP_DEBUG_TRACE, "Service Shutdown ordered\n", 0, 0, 0 ); - SLAPDServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; - SLAPDServiceStatus.dwCheckPoint++; - SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + lutil_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; + lutil_ServiceStatus.dwCheckPoint++; + lutil_ServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); ldap_pvt_thread_cond_init( &stopped_event ); if ( stopped_event == NULL ) { /* the event was not created. We will ask the service control manager for 30 * seconds to shutdown */ - SLAPDServiceStatus.dwCheckPoint++; - SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS; - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + lutil_ServiceStatus.dwCheckPoint++; + lutil_ServiceStatus.dwWaitHint = THIRTY_SECONDS; + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); } else { @@ -269,22 +332,22 @@ void WINAPI SLAPDServiceCtrlHandler( IN DWORD Opcode) * service stopping is proceeding. * tell the Service Control Manager to wait another 30 seconds before deploying its * assasin. */ - SLAPDServiceStatus.dwCheckPoint++; - SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS; - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + lutil_ServiceStatus.dwCheckPoint++; + lutil_ServiceStatus.dwWaitHint = THIRTY_SECONDS; + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); } } stopfunc( -1 ); break; case SERVICE_CONTROL_INTERROGATE: - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); break; } return; } -void *getRegParam( char *svc, char *value ) +void *lutil_getRegParam( char *svc, char *value ) { HKEY hkey; char path[255]; @@ -293,19 +356,17 @@ void *getRegParam( char *svc, char *value ) DWORD valLen = sizeof( vValue ); if ( svc != NULL ) - sprintf ( path, "SOFTWARE\\OpenLDAP\\%s\\Parameters", svc ); + snprintf ( path, sizeof path, "SOFTWARE\\%s", svc ); else - strcpy (path, "SOFTWARE\\OpenLDAP\\Parameters" ); + snprintf ( path, sizeof path, "SOFTWARE\\OpenLDAP\\Parameters" ); if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &hkey ) != ERROR_SUCCESS ) { - /*Debug( LDAP_DEBUG_ANY, "RegOpenKeyEx() %s\n", GetLastErrorString(), 0, 0); */ return NULL; } if ( RegQueryValueEx( hkey, value, NULL, &vType, vValue, &valLen ) != ERROR_SUCCESS ) { - /*Debug( LDAP_DEBUG_ANY, "RegQueryValueEx() %s\n", GetLastErrorString(), 0, 0 );*/ RegCloseKey( hkey ); return NULL; } @@ -322,7 +383,7 @@ void *getRegParam( char *svc, char *value ) return (void*)NULL; } -void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, char *urls ) +void lutil_LogStartedEvent( char *svc, int slap_debug, char *configfile, char *urls ) { char *Inserts[5]; WORD i = 0, j; @@ -332,12 +393,11 @@ void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, char *ur Inserts[i] = (char *)malloc( 20 ); itoa( slap_debug, Inserts[i++], 10 ); - Inserts[i++] = ldap_pvt_strdup( configfile ); - Inserts[i++] = ldap_pvt_strdup( urls ? urls : "ldap:///" ); - Inserts[i++] = ldap_pvt_strdup( is_NT_Service ? "svc" : "cmd" ); + Inserts[i++] = strdup( configfile ); + Inserts[i++] = strdup( urls ? urls : "ldap:///" ); ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0, - MSG_SLAPD_STARTED, NULL, i, 0, (LPCSTR *) Inserts, NULL ); + MSG_SVC_STARTED, NULL, i, 0, (LPCSTR *) Inserts, NULL ); for ( j = 0; j < i; j++ ) ldap_memfree( Inserts[j] ); @@ -346,34 +406,34 @@ void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, char *ur -void LogSlapdStoppedEvent( char *svc ) +void lutil_LogStoppedEvent( char *svc ) { HANDLE hEventLog; hEventLog = RegisterEventSource( NULL, svc ); ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0, - MSG_SLAPD_STOPPED, NULL, 0, 0, NULL, NULL ); + MSG_SVC_STOPPED, NULL, 0, 0, NULL, NULL ); DeregisterEventSource( hEventLog ); } -void CommenceStartupProcessing( LPCTSTR lpszServiceName, +void lutil_CommenceStartupProcessing( char *lpszServiceName, void (*stopper)(int) ) { - hSLAPDServiceStatus = RegisterServiceCtrlHandler( lpszServiceName, (LPHANDLER_FUNCTION)SLAPDServiceCtrlHandler); + hlutil_ServiceStatus = RegisterServiceCtrlHandler( lpszServiceName, (LPHANDLER_FUNCTION)lutil_ServiceCtrlHandler); stopfunc = stopper; /* initialize the Service Status structure */ - SLAPDServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - SLAPDServiceStatus.dwCurrentState = SERVICE_START_PENDING; - SLAPDServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; - SLAPDServiceStatus.dwWin32ExitCode = NO_ERROR; - SLAPDServiceStatus.dwServiceSpecificExitCode = 0; - SLAPDServiceStatus.dwCheckPoint = 1; - SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; + lutil_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + lutil_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; + lutil_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; + lutil_ServiceStatus.dwWin32ExitCode = NO_ERROR; + lutil_ServiceStatus.dwServiceSpecificExitCode = 0; + lutil_ServiceStatus.dwCheckPoint = 1; + lutil_ServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2; - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); /* start up a thread to keep sending SERVICE_START_PENDING to the Service Control Manager * until the slapd listener is completed and listening. Only then should we send @@ -384,9 +444,9 @@ void CommenceStartupProcessing( LPCTSTR lpszServiceName, /* failed to create the event to determine when the startup process is complete so * tell the Service Control Manager to wait another 30 seconds before deploying its * assasin */ - SLAPDServiceStatus.dwCheckPoint++; - SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS; - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + lutil_ServiceStatus.dwCheckPoint++; + lutil_ServiceStatus.dwWaitHint = THIRTY_SECONDS; + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); } else { @@ -401,14 +461,14 @@ void CommenceStartupProcessing( LPCTSTR lpszServiceName, * service startup is proceeding. * tell the Service Control Manager to wait another 30 seconds before deploying its * assasin. */ - SLAPDServiceStatus.dwCheckPoint++; - SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS; - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + lutil_ServiceStatus.dwCheckPoint++; + lutil_ServiceStatus.dwWaitHint = THIRTY_SECONDS; + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); } } } -void ReportSlapdShutdownComplete( ) +void lutil_ReportShutdownComplete( ) { if ( is_NT_Service ) { @@ -421,11 +481,28 @@ void ReportSlapdShutdownComplete( ) if (ldap_pvt_thread_join( stop_status_tid, (void *) NULL ) == -1) ldap_pvt_thread_sleep( SCM_NOTIFICATION_INTERVAL / 2 ); - SLAPDServiceStatus.dwCurrentState = SERVICE_STOPPED; - SLAPDServiceStatus.dwCheckPoint++; - SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL; - SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus); + lutil_ServiceStatus.dwCurrentState = SERVICE_STOPPED; + lutil_ServiceStatus.dwCheckPoint++; + lutil_ServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL; + SetServiceStatus(hlutil_ServiceStatus, &lutil_ServiceStatus); } } +static char *GetErrorString( int err ) +{ + static char msgBuf[1024]; + + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + msgBuf, 1024, NULL ); + + return msgBuf; +} + +static char *GetLastErrorString( void ) +{ + return GetErrorString( GetLastError() ); +} #endif