/[pkg-mixmaster]/trunk/Mix/Src/service.c
ViewVC logotype

Contents of /trunk/Mix/Src/service.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 332 - (show annotations) (download)
Wed Oct 9 20:53:32 2002 UTC (10 years, 7 months ago) by weaselp
File MIME type: text/plain
File size: 9254 byte(s)
Whitespace cleanup:
for i in *.c; do cp -a $i $i.orig; sed -e 's/^        /<TAB>/' $i.orig > $i; rm $i.orig; done
for i in *.c *.h; do cp -a $i $i.orig; sed -e 's/[ <TAB>]*$//' $i.orig > $i; rm $i.orig; done
1 #ifdef WIN32SERVICE
2
3 #include <windows.h>
4 #include <stdio.h>
5 #include <direct.h>
6 #include <io.h>
7 #include <fcntl.h>
8
9 #include "mix3.h"
10
11 #define SVCNAME "Mixmaster"
12 #define SVCDISPLAYNAME "Mixmaster Service"
13
14
15 /* internal variables */
16 static SERVICE_STATUS ssStatus;
17 static SERVICE_STATUS_HANDLE sshStatusHandle;
18 static BOOL not_service = FALSE;
19
20 static HANDLE hThread = NULL;
21 static HANDLE hMustTerminate = NULL;
22
23 /* internal function prototypes */
24 VOID WINAPI service_ctrl(DWORD ctrl_code);
25 VOID WINAPI service_main(DWORD argc, LPSTR *argv);
26 static DWORD service_run(void);
27 static void service_stop();
28 static int set_stdfiles();
29 static int install_service();
30 static int remove_service();
31 static int run_notservice(int argc, char **argv);
32 BOOL WINAPI console_ctrl_handler(DWORD ctrl_type);
33 static char *GetLastErrorText();
34 static BOOL send_status(DWORD current_state, DWORD exit_code, DWORD wait_hint, DWORD id);
35 static void event_log(DWORD id, char *eventmsg);
36
37 int mix_main(int argc, char *argv[]);
38
39
40 int main(int argc, char *argv[])
41 {
42 SERVICE_TABLE_ENTRY dispatchTable[] = {
43 {SVCNAME, (LPSERVICE_MAIN_FUNCTION)service_main},
44 {NULL, NULL} };
45
46 if ((argc > 1) && ((argv[1][0] == '-') && (argv[1][1] == '-'))) {
47 if (!_stricmp("install-svc", argv[1]+2))
48 return install_service();
49 else if (!_stricmp("remove-svc", argv[1]+2))
50 return remove_service();
51 else if (_stricmp("run-svc", argv[1]+2) && !is_nt_service())
52 return run_notservice(argc, argv);
53 } else if (!is_nt_service()) {
54 return run_notservice(argc, argv);
55 }
56 printf("mix --install-svc install the service\n");
57 printf("mix --remove-svc remove the service\n");
58 printf("mix --run-svc run as a service\n");
59 printf("mix -h view a summary of the command line options.\n");
60
61 printf("\nStartServiceCtrlDispatcher being called.\n" );
62 printf("This may take several seconds. Please wait.\n" );
63 if (!StartServiceCtrlDispatcher(dispatchTable)) {
64 printf("Service not started: StartServiceCtrlDispatcher failed.\n" );
65 event_log(1000, "Service not started: StartServiceCtrlDispatcher failed");
66 }
67 return 0;
68 } /* main */
69
70
71 VOID WINAPI service_main(DWORD argc, LPSTR *argv)
72 {
73 DWORD err = 0;
74
75 if (!(sshStatusHandle = RegisterServiceCtrlHandler(SVCNAME, service_ctrl)))
76 return;
77
78 ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
79 ssStatus.dwServiceSpecificExitCode = 0;
80 if (send_status(SERVICE_START_PENDING, NO_ERROR, 1000, 1020))
81 err = service_run();
82
83 send_status(SERVICE_STOPPED, err, 0, err ? 1030 : 30);
84 } /* service_main */
85
86
87 VOID WINAPI service_ctrl(DWORD ctrl_code)
88 { /* Handle the requested control code. */
89 if (ctrl_code == SERVICE_CONTROL_STOP || ctrl_code == SERVICE_CONTROL_SHUTDOWN)
90 service_stop();
91 else
92 send_status(ssStatus.dwCurrentState, NO_ERROR, 0, 1040 + ctrl_code);
93 } /* service_ctrl */
94
95
96 static DWORD service_run(void)
97 {
98 char filename[_MAX_PATH+1];
99 char home[_MAX_PATH+1], *p;
100 char *svc_argv[2] = {filename, "-D"};
101
102 if (!hMustTerminate)
103 hMustTerminate = CreateEvent(NULL, FALSE, FALSE, NULL);
104 set_nt_exit_event(hMustTerminate);
105 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(),
106 &hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
107
108 GetModuleFileName(NULL , filename, _MAX_PATH);
109 strcpy(home, filename);
110 if (p = strrchr(home, '\\')) {
111 *p = 0;
112 chdir(home);
113 }
114
115 if (!set_stdfiles()) {
116 event_log(1010, "stdin|stdout|stderr not created");
117 return ERROR_SERVICE_NOT_ACTIVE;
118 }
119
120 send_status(SERVICE_RUNNING, NO_ERROR, 0, 1060);
121 event_log(10, "Mixmaster Service started");
122
123 mix_main(2, svc_argv);
124 return 0;
125 } /* service_run */
126
127
128 static void service_stop(void)
129 {
130 send_status(SERVICE_STOP_PENDING, NO_ERROR, 5000, 1070);
131 if (hMustTerminate) {
132 SetEvent(hMustTerminate);
133 if (WaitForSingleObject(hThread, 4500) == WAIT_TIMEOUT) {
134 if (hThread) {
135 TerminateThread(hThread, 0);
136 event_log(1080, "Mixmaster Service terminated forcibly");
137 }
138 } else
139 event_log(20, "Mixmaster Service stopped");
140 CloseHandle(hMustTerminate);
141 hMustTerminate = NULL;
142 } else
143 if (hThread)
144 TerminateThread(hThread, 0);
145 if (hThread)
146 CloseHandle(hThread);
147 hThread = NULL;
148 ssStatus.dwCurrentState = SERVICE_STOPPED;
149 } /* service_stop */
150
151
152 static int set_stdfiles()
153 { /* needed for _popen() */
154 static DWORD std_handles[]={STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE};
155 FILE *stdfile[]={stdin, stdout, stderr};
156 HANDLE hStd;
157 int fh, stf_fileno;
158 FILE *fl;
159
160 AllocConsole();
161 for (stf_fileno=0; stf_fileno<=2; stf_fileno++) {
162 hStd = GetStdHandle(std_handles[stf_fileno]);
163 if (hStd == INVALID_HANDLE_VALUE)
164 return 0;
165 fh = _open_osfhandle((long)std_handles[stf_fileno], (stf_fileno ? _O_WRONLY : _O_RDONLY ) | _O_BINARY);
166 dup2(fh, stf_fileno);
167 fl = _fdopen(stf_fileno, (stf_fileno ? "wcb" : "rcb" ));
168 fflush(stdfile[stf_fileno]);
169 memcpy(stdfile[stf_fileno], fl, sizeof(FILE));
170 }
171 return 1;
172 } /* set_stdfiles */
173
174
175 static BOOL send_status(DWORD current_state, DWORD exit_code, DWORD wait_hint, DWORD id)
176 {
177 static DWORD dwCheckPoint = 1;
178 BOOL ret_val;
179
180 if (not_service)
181 return TRUE;
182
183 ssStatus.dwCurrentState = current_state;
184 ssStatus.dwWin32ExitCode = exit_code;
185 ssStatus.dwWaitHint = wait_hint;
186 ssStatus.dwControlsAccepted = (current_state == SERVICE_START_PENDING) ?
187 0 : SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
188 ssStatus.dwCheckPoint = ((current_state == SERVICE_RUNNING) || (current_state == SERVICE_STOPPED)) ?
189 0 : dwCheckPoint++;
190
191 if (!(ret_val = SetServiceStatus(sshStatusHandle, &ssStatus)))
192 event_log(id, "SetServiceStatus failed");
193 return ret_val;
194 } /* send_status */
195
196
197 static void event_log(DWORD id, char *eventmsg)
198 {
199 HANDLE hEventSource;
200 char *pStrings[2] = {"", eventmsg};
201
202 if (not_service)
203 return;
204
205 if (id > 1000)
206 pStrings[0] = GetLastErrorText();
207
208 if (!(hEventSource = RegisterEventSource(NULL, SVCNAME)))
209 return;
210 ReportEvent(hEventSource, (WORD)((id < 1000) ? EVENTLOG_SUCCESS : EVENTLOG_ERROR_TYPE),
211 0, id, NULL, 2, 0, pStrings, NULL);
212 DeregisterEventSource(hEventSource);
213 } /* event_log */
214
215
216 static int run_notservice(int argc, char ** argv)
217 {
218 not_service = TRUE;
219 return mix_main(argc, argv);
220 } /* run_notservice */
221
222
223 static int install_service()
224 {
225 SC_HANDLE schService, schSCManager;
226 char filename[_MAX_PATH+10];
227
228 if (GetModuleFileName(NULL, filename, _MAX_PATH) == 0) {
229 printf("Unable to install Mixmaster Service: %s\n", GetLastErrorText());
230 return 1;
231 }
232 strcat(filename, " --run-svc");
233
234 if (!(schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) {
235 printf("OpenSCManager failed: %s\n", GetLastErrorText());
236 return 1;
237 }
238 schService = CreateService(schSCManager, SVCNAME, SVCDISPLAYNAME,
239 SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
240 filename, NULL, NULL, NULL, NULL, NULL);
241
242 if (schService) {
243 printf("Mixmaster Service installed.\n");
244 CloseServiceHandle(schService);
245 } else {
246 printf("CreateService failed: %s\n", GetLastErrorText());
247 }
248
249 CloseServiceHandle(schSCManager);
250 return 0;
251 } /* install_service */
252
253
254 static int remove_service()
255 {
256 SC_HANDLE schService, schSCManager;
257 int ret_val = 0;
258
259 if (!(schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) {
260 printf("OpenSCManager failed: %s\n", GetLastErrorText());
261 return 1;
262 }
263 if (!(schService = OpenService(schSCManager, SVCNAME, SERVICE_ALL_ACCESS))) {
264 CloseServiceHandle(schSCManager);
265 printf("OpenService failed: %s\n", GetLastErrorText());
266 return 1;
267 }
268 /* try to stop the service */
269 if (ControlService(schService, SERVICE_CONTROL_STOP, &ssStatus)) {
270 printf("Stopping Mixmaster Service");
271 do {
272 Sleep(1000);
273 printf(".");
274 QueryServiceStatus(schService, &ssStatus);
275 } while (ssStatus.dwCurrentState != SERVICE_STOP_PENDING);
276
277 if (ssStatus.dwCurrentState == SERVICE_STOPPED)
278 printf("\nMixmaster Service stopped.\n");
279 else
280 printf("\n%Mixmaster Service failed to stop.\n");
281 }
282
283 /* now remove the service */
284 if (!DeleteService(schService)) {
285 ret_val = 1;
286 printf("DeleteService failed: %s\n", GetLastErrorText());
287 } else
288 printf("Mixmaster Service removed.\n");
289
290 CloseServiceHandle(schService);
291 CloseServiceHandle(schSCManager);
292 return ret_val;
293 } /* remove_service */
294
295
296 static char *GetLastErrorText()
297 {
298 static char error_buf[256];
299 DWORD dwRet, err;
300 LPSTR lpszTemp = NULL;
301
302 dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
303 NULL, err=GetLastError(), LANG_NEUTRAL, (LPSTR)&lpszTemp, 0, NULL);
304
305 /* supplied buffer is not long enough */
306 if (!dwRet || (256 < (long)dwRet+14))
307 sprintf(error_buf, "Error (0x%x)", err);
308 else {
309 lpszTemp[lstrlen(lpszTemp)-2] = '\0';
310 /* remove cr and newline character */
311 sprintf(error_buf, "%s (0x%x)", lpszTemp, err);
312 }
313
314 if (lpszTemp)
315 LocalFree((HLOCAL)lpszTemp);
316
317 return error_buf;
318 } /* GetLastErrorText */
319
320 #endif /* WIN32SERVICE */

  ViewVC Help
Powered by ViewVC 1.1.5