summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2009-03-26 17:26:00 +0100
committerAndreas Baumann <abaumann@yahoo.com>2009-03-26 17:26:00 +0100
commita92ee231c47556681311ae27fdfdb5e36d3e2582 (patch)
tree31c067d164b43d5c641aeaffd731473cf34777df /src
parentcbc6aaca6dd7ac57a6115b3512a85045e51303dd (diff)
downloadwolfbones-a92ee231c47556681311ae27fdfdb5e36d3e2582.tar.gz
wolfbones-a92ee231c47556681311ae27fdfdb5e36d3e2582.tar.bz2
code moved, works again somehow, now cleanup in the service
Diffstat (limited to 'src')
-rw-r--r--src/service/service.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/src/service/service.c b/src/service/service.c
index 0b7bbfa..1252c52 100644
--- a/src/service/service.c
+++ b/src/service/service.c
@@ -7,6 +7,12 @@
#include <WinSvc.h> /* for service functions */
+SERVICE_STATUS_HANDLE service_status_handle;
+SERVICE_STATUS service_status;
+HANDLE service_stop_event = NULL;
+
+#define SERVICE_NAME "testservice"
+
wolf_error_t wolf_service_install( wolf_service_params_t params ) {
SC_HANDLE scm;
SC_HANDLE service;
@@ -138,3 +144,199 @@ wolf_error_t wolf_service_remove( LPCTSTR service_name ) {
return WOLF_OK;
}
+
+/* constants and values from WinSvc.h: */
+static const char *wolf_service_state_to_str( DWORD current_state ) {
+ switch( current_state ) {
+ case SERVICE_STOPPED: return "SERVICE_STOPPED";
+ case SERVICE_START_PENDING: return "SERVICE_START_PENDING";
+ case SERVICE_STOP_PENDING: return "SERVICE_STOP_PENDING";
+ case SERVICE_RUNNING: return "SERVICE_RUNNING";
+ case SERVICE_CONTINUE_PENDING: return "SERVICE_CONTINUE_PENDING";
+ case SERVICE_PAUSE_PENDING: return "SERVICE_PAUSE_PENDING";
+ case SERVICE_PAUSED: return "SERVICE_PAUSED";
+ default: return "<unknown service state>";
+ }
+}
+
+/* constants and values from WinSvc.h: */
+static const char *wolf_service_control_to_str( DWORD control ) {
+ switch( control ) {
+ case SERVICE_CONTROL_STOP: return "SERVICE_CONTROL_STOP";
+ case SERVICE_CONTROL_PAUSE: return "SERVICE_CONTROL_PAUSE";
+ case SERVICE_CONTROL_CONTINUE: return "SERVICE_CONTROL_CONTINUE";
+ case SERVICE_CONTROL_INTERROGATE: return "SERVICE_CONTROL_INTERROGATE";
+ case SERVICE_CONTROL_SHUTDOWN: return "SERVICE_CONTROL_SHUTDOWN";
+ case SERVICE_CONTROL_PARAMCHANGE: return "SERVICE_CONTROL_PARAMCHANGE";
+ case SERVICE_CONTROL_NETBINDADD: return "SERVICE_CONTROL_NETBINDADD";
+ case SERVICE_CONTROL_NETBINDREMOVE: return "SERVICE_CONTROL_NETBINDREMOVE";
+ case SERVICE_CONTROL_NETBINDENABLE: return "SERVICE_CONTROL_NETBINDENABLE";
+ case SERVICE_CONTROL_NETBINDDISABLE: return "SERVICE_CONTROL_NETBINDDISABLE";
+ case SERVICE_CONTROL_DEVICEEVENT: return "SERVICE_CONTROL_DEVICEEVENT";
+ case SERVICE_CONTROL_HARDWAREPROFILECHANGE: return "SERVICE_CONTROL_HARDWAREPROFILECHANGE";
+ case SERVICE_CONTROL_POWEREVENT: return "SERVICE_CONTROL_POWEREVENT";
+ case SERVICE_CONTROL_SESSIONCHANGE: return "SERVICE_CONTROL_SESSIONCHANGE";
+ default: return "<unknown service control>";
+ }
+}
+
+static void wolf_service_report_status( DWORD current_state,
+ DWORD exit_code,
+ DWORD wait_hint ) {
+ BOOL res;
+ char errbuf[512];
+
+ wolf_log( WOLF_LOG_DEBUG, WOLF_CATEGORY_SERVICE, WOLF_MSG_SERVICE_REPORT_STATUS,
+ _( "reporting status with new state '%s' (%d) (currently in state '%s' (%d))" ),
+ wolf_service_state_to_str( current_state ), current_state,
+ wolf_service_state_to_str( service_status.dwCurrentState ), service_status.dwCurrentState );
+
+ service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ service_status.dwCurrentState = current_state;
+ service_status.dwWin32ExitCode = exit_code;
+ service_status.dwServiceSpecificExitCode = 0;
+ service_status.dwWaitHint = wait_hint;
+ service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+
+ switch( current_state ) {
+ case SERVICE_START_PENDING:
+ /* during startup we should not accept events, otherwise our
+ * state machine could get troubled!
+ */
+ service_status.dwControlsAccepted = 0;
+ service_status.dwCheckPoint++;
+ break;
+
+ case SERVICE_RUNNING:
+ case SERVICE_STOPPED:
+ /* reset checkpoint for status bar in final states */
+ service_status.dwCheckPoint = 0;
+ break;
+
+ default:
+ /* increate the tick for transient states */
+ service_status.dwCheckPoint++;
+ break;
+ }
+
+ res = SetServiceStatus( service_status_handle, &service_status );
+ if( !res ) {
+ WOLF_LOG_GET_LAST_ERROR( GetLastError( ), errbuf, 512 );
+ wolf_log( WOLF_LOG_ERR, WOLF_CATEGORY_SERVICE, WOLF_MSG_SERVICE_CANT_REPORT_STATUS,
+ _( "Unable to report state '%s' (%d) of service '%s' to SCM '%s (%d)" ),
+ wolf_service_state_to_str( current_state ), current_state,
+ SERVICE_NAME, errbuf, GetLastError( ) );
+ return;
+ }
+}
+
+/* we get called here by the system and the service control manager,
+ * be as short as possible, report states and trigger new events at
+ * most!
+ */
+void WINAPI wolf_service_ctrl_handler( DWORD control ) {
+ char errbuf[512];
+ BOOL res;
+
+ wolf_log( WOLF_LOG_DEBUG, WOLF_CATEGORY_SERVICE, WOLF_MSG_SERVICE_HANDLING_EVENT,
+ _( "service handler received status change '%s' (%d)" ),
+ wolf_service_control_to_str( control ),
+ control );
+
+ switch( control ) {
+ case SERVICE_CONTROL_STOP:
+ wolf_service_report_status( SERVICE_STOP_PENDING, NO_ERROR, 1000 );
+ SetEvent( service_stop_event );
+ break;
+
+ case SERVICE_CONTROL_INTERROGATE:
+ /* fall through to send current status */
+ break;
+ }
+
+ /* report current state */
+ wolf_service_report_status( service_status.dwCurrentState, NO_ERROR, 1000 );
+}
+
+void WINAPI wolf_service_main( DWORD argc, LPTSTR *argv ) {
+ char errbuf[512];
+ BOOL res;
+
+ /* all other loggers make no sense: a service is not supposed
+ * to have a logfile or interaction with the user in any way!
+ */
+ wolf_log_openlogtoeventlog( NULL, "Application", "testservice",
+ "C:\\Temp\\testservicemsg.dll", WOLF_LAST_INTERNAL_CATEGORY+1, WOLF_LOG_DEBUG );
+
+ /* register the event callback where we get called by the service
+ * manager and the system
+ */
+ service_status_handle = RegisterServiceCtrlHandler(
+ SERVICE_NAME, wolf_service_ctrl_handler );
+
+ if( service_status_handle == 0 ) {
+ WOLF_LOG_GET_LAST_ERROR( GetLastError( ), errbuf, 512 );
+ wolf_log( WOLF_LOG_ERR, WOLF_CATEGORY_SERVICE, WOLF_MSG_SERVICE_CANT_REGISTER_SERVICE_CTRL_HANDLER,
+ _( "Unable to register service control handler function for service '%s': %s (%d)" ),
+ SERVICE_NAME, errbuf, GetLastError( ) );
+ return;
+ }
+
+ /* signal that we are now up and running */
+ wolf_service_report_status( SERVICE_START_PENDING, NO_ERROR, 3000 );
+
+ /* register a stop event, the service control handler will send
+ * the event. From now on we have a service event handler installed,
+ * so if something goes wrong we can set the service state to
+ * SERVICE_STOPPED and terminate gracefully.
+ */
+ service_stop_event = CreateEvent(
+ NULL, /* default security attributes */
+ TRUE, /* manual reset event */
+ FALSE, /* not signalled */
+ NULL ); /* no name */
+ if( service_stop_event == NULL ) {
+ WOLF_LOG_GET_LAST_ERROR( GetLastError( ), errbuf, 512 );
+ wolf_log( WOLF_LOG_ERR, WOLF_CATEGORY_SERVICE, WOLF_MSG_SERVICE_CANT_CREATE_STOP_EVENT,
+ _( "Unable to create the stop event for service '%s': %s (%d)" ),
+ SERVICE_NAME, errbuf, GetLastError( ) );
+ wolf_service_report_status( SERVICE_STOPPED, NO_ERROR, 1000 );
+ }
+
+ wolf_service_report_status( SERVICE_RUNNING, NO_ERROR, 1000 );
+ wolf_log( WOLF_LOG_NOTICE, WOLF_CATEGORY_SERVICE, WOLF_MSG_SERVICE_STARTED_SERVICE,
+ _( "Started %s service" ), SERVICE_NAME );
+
+ /* main loop */
+ while( 1 ) {
+ DWORD r;
+ r = WaitForSingleObject( service_stop_event, 1000 );
+ switch( r ) {
+ case WAIT_OBJECT_0:
+ /* stop signal received */
+ goto SERVICE_END;
+
+ case WAIT_TIMEOUT:
+ /* we can do periodic things here */
+ break;
+
+ default:
+ WOLF_LOG_GET_LAST_ERROR( GetLastError( ), errbuf, 512 );
+ wolf_log( WOLF_LOG_ERR, WOLF_CATEGORY_SERVICE, WOLF_MSG_SERVICE_WAIT_FOR_OBJECT_FAILED,
+ _( "Waiting for the stop event for service '%s' failed: %s (%d)" ),
+ SERVICE_NAME, errbuf, GetLastError( ) );
+ wolf_service_report_status( SERVICE_STOPPED, NO_ERROR, 1000 );
+ return;
+ }
+ }
+
+SERVICE_END:
+ wolf_log( WOLF_LOG_NOTICE, WOLF_CATEGORY_SERVICE, WOLF_MSG_SERVICE_STOPPED_SERVICE,
+ _( "Stopped %s service" ), SERVICE_NAME );
+
+ wolf_service_report_status( SERVICE_STOPPED, NO_ERROR, 1000 );
+
+ wolf_log_closelogtoeventlog( );
+
+ return;
+}