]> rtime.felk.cvut.cz Git - orte.git/blob - orte/manager/service.c
new version 0.2.3
[orte.git] / orte / manager / service.c
1 #include "orte_all.h"
2
3 HANDLE                         killServiceEvent = NULL;
4 static SERVICE_STATUS          ssStatus;       // current status of the service
5 static SERVICE_STATUS_HANDLE   sshStatusHandle;
6 static DWORD                   dwErr = 0;
7 static char                    szErr[1024] = "";
8
9 char                           *name_service="ortemanager";
10 char                           *name_service_disp="ortemanager";
11
12 int managerInit(void);         //forward declaration
13 int managerStart(void);        //forward declaration
14 int managerStop(void);         //forward declaration
15
16 static void AddToMessageLog(char *lpszMsg) {
17   char    szMsg[2048];
18   HANDLE  hEventSource;
19   char *  lpszStrings[2];
20
21   dwErr = GetLastError();
22   hEventSource = RegisterEventSource(NULL, name_service);
23   sprintf(szMsg, "%s error: %li", name_service, dwErr);
24   lpszStrings[0] = szMsg;
25   lpszStrings[1] = lpszMsg;
26   if(hEventSource != NULL) {
27     ReportEvent(hEventSource, // handle of event source
28                 EVENTLOG_ERROR_TYPE,  // event type
29                 0,                    // event category
30                 0,                    // event ID
31                 NULL,                 // current user's SID
32                 2,                    // strings in lpszStrings
33                 0,                    // no bytes of raw data
34                 (LPCSTR*)lpszStrings, // array of error strings
35                 NULL);                // no raw data
36     DeregisterEventSource(hEventSource);
37   }
38 }
39
40 BOOL ReportStatusToSCMgr(DWORD dwCurrentState,DWORD dwWin32ExitCode,
41                          DWORD dwWaitHint) {
42   static DWORD dwCheckPoint = 1;
43   BOOL fResult = TRUE;
44
45   if(dwCurrentState == SERVICE_START_PENDING) ssStatus.dwControlsAccepted = 0;
46   else ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
47   ssStatus.dwCurrentState = dwCurrentState;
48   ssStatus.dwWin32ExitCode = dwWin32ExitCode;
49   ssStatus.dwWaitHint = dwWaitHint;
50   if((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED)) ssStatus.dwCheckPoint = 0;
51   else ssStatus.dwCheckPoint = dwCheckPoint++;
52   if(!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus))) {
53     AddToMessageLog("SetServiceStatus");
54   }
55   return fResult;
56 }
57
58 void WINAPI service_ctrl(DWORD dwCtrlCode) {
59   switch(dwCtrlCode) {
60     case SERVICE_CONTROL_STOP:
61       ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
62       managerStop();
63       SetEvent(killServiceEvent);
64       break;
65     case SERVICE_CONTROL_INTERROGATE:
66       break;
67     default:
68       break;
69   }
70   ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
71 }
72
73 void WINAPI service_main(DWORD dwArgc, char **lpszArgv) {
74   int       err;
75   sshStatusHandle = RegisterServiceCtrlHandler(name_service, service_ctrl);
76   if(sshStatusHandle) {
77     ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
78     ssStatus.dwServiceSpecificExitCode = 0;
79     killServiceEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
80     if (!killServiceEvent) goto cleanup;
81     if(!ReportStatusToSCMgr(SERVICE_START_PENDING,NO_ERROR,3000)) goto cleanup;
82     err=managerInit();
83     if (err<0) {
84       AddToMessageLog("Starting communication");
85       dwErr=NO_ERROR;
86       goto cleanup;
87     }
88     managerStart();
89     if(!ReportStatusToSCMgr(SERVICE_RUNNING,NO_ERROR, 0 )) goto cleanup;
90     WaitForSingleObject(killServiceEvent,INFINITE);
91     CloseHandle(killServiceEvent);
92   }
93 cleanup:
94   if(sshStatusHandle) {
95     ReportStatusToSCMgr(SERVICE_STOP_PENDING,dwErr,0);
96     ReportStatusToSCMgr(SERVICE_STOPPED,dwErr,0);
97   }
98 }
99
100 void serviceDispatchTable(void) {
101   SERVICE_TABLE_ENTRY dispatchTable[] = {
102       { name_service, (LPSERVICE_MAIN_FUNCTION)service_main },
103       { NULL, NULL }
104   };
105   if(!StartServiceCtrlDispatcher(dispatchTable)) {
106     AddToMessageLog("StartServiceCtrlDispatcher failed.");
107   }
108 }
109
110 char *GetLastErrorText( char *lpszBuf, DWORD dwSize ) {
111   DWORD dwRet;
112   char *lpszTemp = NULL;
113
114   dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
115                         NULL,
116                         GetLastError(),
117                         LANG_NEUTRAL,
118                         (char *)&lpszTemp,
119                         0,
120                         NULL);
121   // supplied buffer is not long enough
122   if(!dwRet || ((long)dwSize < (long)dwRet+14)) {
123     lpszBuf[0] = '\0';
124   } else {
125     lpszTemp[lstrlen(lpszTemp)-2] = '\0';  //remove cr and newline character
126     sprintf(lpszBuf, "%s (%li)", lpszTemp, GetLastError());
127   }
128   if(lpszTemp) LocalFree((HLOCAL) lpszTemp );
129   return lpszBuf;
130 }
131
132 void installService(void) {
133   SC_HANDLE   schService;
134   SC_HANDLE   schSCManager;
135   TCHAR       szPath[512];
136
137   if(GetModuleFileName( NULL, szPath, sizeof(szPath) - 1) == 0) {
138      printf("Unable to install %s - %s\n",
139              name_service,
140              GetLastErrorText(szErr, sizeof(szErr)));
141      return;
142   }
143   strcat(szPath," -s");
144   schSCManager = OpenSCManager(NULL,  // machine (NULL == local)
145                                NULL,  // database (NULL == default)
146                                SC_MANAGER_ALL_ACCESS);   // access required
147   if(schSCManager) {
148     schService = CreateService(schSCManager,               // SCManager database
149                                name_service,               // name of service
150                                name_service_disp,          // name to display
151                                SERVICE_ALL_ACCESS,         // desired access
152                                SERVICE_WIN32_OWN_PROCESS,  // service type
153                                SERVICE_AUTO_START,         // start type
154                                SERVICE_ERROR_NORMAL,       // error control type
155                                szPath,                     // service's binary
156                                NULL,                       // no load ordering group
157                                NULL,                       // no tag identifier
158                                NULL,                       // dependencies
159                                NULL,                       // LocalSystem account
160                                NULL);                      // no password
161     if(schService) {
162       CloseServiceHandle(schSCManager);
163       printf("Service name (%s) instaled!\n",name_service);
164     } else {
165        printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
166     }
167   }
168 }
169
170 void removeService(void) {
171   SC_HANDLE   schService;
172   SC_HANDLE   schSCManager;
173
174   schSCManager = OpenSCManager(NULL,          // machine (NULL == local)
175                                NULL,          // database (NULL == default)
176                                SC_MANAGER_ALL_ACCESS );  // access required
177   if(schSCManager) {
178     schService = OpenService(schSCManager, name_service, SERVICE_ALL_ACCESS);
179     if(schService) {
180       // try to stop the service
181       if(ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus )) {
182         printf("Stopping %s.", name_service);
183         Sleep(100);
184         while(QueryServiceStatus(schService, &ssStatus )) {
185           if(ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
186             printf(".");
187             Sleep(100);
188           } else {
189              break;
190           }
191         }
192         if(ssStatus.dwCurrentState == SERVICE_STOPPED) {
193           printf("\n%s stopped.\n", name_service);
194         } else {
195           printf("\n%s failed to stop.\n", name_service);
196         }
197       }
198       // now remove the service
199       if(DeleteService(schService)) {
200         printf("%s removed.\n", name_service);
201       } else {
202         printf("DeleteService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
203       }
204       CloseServiceHandle(schService);
205     } else {
206       printf("OpenService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
207     }
208     CloseServiceHandle(schSCManager);
209   } else {
210     printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
211   }
212 }
213