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

  ViewVC Help
Powered by ViewVC 1.1.5