]> granicus.if.org Git - apache/blob - support/win32/ApacheMonitor.c
Reorder OS_VERSION(s) so >= OS_VERSION_WINNT, etc, tests correctly.
[apache] / support / win32 / ApacheMonitor.c
1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000 The Apache Software Foundation.  All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  *    if any, must include the following acknowledgment:
21  *       "This product includes software developed by the
22  *        Apache Software Foundation (http://www.apache.org/)."
23  *    Alternately, this acknowledgment may appear in the software itself,
24  *    if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  *    not be used to endorse or promote products derived from this
28  *    software without prior written permission. For written
29  *    permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  *    nor may "Apache" appear in their name, without prior written
33  *    permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation.  For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  *
54  * Portions of this software are based upon public domain software
55  * originally written at the National Center for Supercomputing Applications,
56  * University of Illinois, Urbana-Champaign.
57  */
58
59 /* ====================================================================
60  * ApacheMonitor.c Simple program to manage and monitor Apache services.
61  *
62  * Contributed by Mladen Turk <mturk@mappingsoft.com>
63  *
64  * 05 Aug 2001
65  * ==================================================================== 
66  */
67
68 #define _WIN32_WINNT 0x0400
69 #ifndef STRICT
70 #define STRICT
71 #endif
72 #ifndef OEMRESOURCE
73 #define OEMRESOURCE
74 #endif
75
76 #include <windows.h>
77 #include <windowsx.h>
78 #include <commctrl.h>
79 #include <stdlib.h>
80 #include <stdio.h>
81 #include "ApacheMonitor.h"
82
83
84 #define OS_VERSION_WIN9X    1
85 #define OS_VERSION_WINNT    2
86 #define OS_VERSION_WIN2K    3
87 /* Should be enough */
88 #define MAX_APACHE_SERVICES 128
89
90 #define WM_TRAYMESSAGE         (WM_APP+1)
91 #define WM_UPDATEMESSAGE       (WM_USER+1)
92 #define WM_TIMER_REFRESH       10
93 #define WM_TIMER_RESCAN        11
94 #define SERVICE_APACHE_RESTART 128
95 #define XBITMAP                16
96 #define YBITMAP                16 
97 #define MAX_LOADSTRING         100
98 #define REFRESH_TIME           2000           /* service refresh time (ms) */
99 #define RESCAN_TIME            20000          /* registry rescan time (ms) */
100
101 typedef struct _st_APACHE_SERVICE
102 {
103     LPSTR    szServiceName;
104     LPSTR    szDisplayName;
105     LPSTR    szDescription;
106     LPSTR    szImagePath;
107     DWORD    dwPid;
108 } ST_APACHE_SERVICE;
109
110 /* Global variables */
111 HINSTANCE         g_hInstance = NULL;
112 TCHAR             *g_szTitle;          /* The title bar text */
113 TCHAR             *g_szWindowClass;    /* Window Class Name  */
114 HICON             g_icoStop;
115 HICON             g_icoRun;
116 UINT              g_bUiTaskbarCreated;
117 DWORD             g_dwOSVersion;
118 BOOL              g_bDlgServiceOn = FALSE;
119 BOOL              g_bConsoleRun = FALSE;
120 ST_APACHE_SERVICE g_stServices[MAX_APACHE_SERVICES];
121
122 HBITMAP           g_hBmpStart, g_hBmpStop; 
123 HBITMAP           g_hBmpPicture, g_hBmpOld; 
124 BOOL              g_bRescanServices;
125 HWND              g_hwndServiceDlg;
126 HWND              g_hwndMain;
127 HWND              g_hwndStdoutList;
128 HCURSOR           g_hCursorHourglass;
129 HCURSOR           g_hCursorArrow;
130
131 HANDLE            g_hpipeOutRead;
132 HANDLE            g_hpipeOutWrite;
133 HANDLE            g_hpipeInRead;
134 HANDLE            g_hpipeInWrite;
135 HANDLE            g_hpipeStdError;
136 LANGID            g_LangID;
137 PROCESS_INFORMATION g_lpRedirectProc;
138 CRITICAL_SECTION    g_stcSection;
139
140
141 /* locale language support */
142 static CHAR *g_lpMsg[IDS_MSG_LAST - IDS_MSG_FIRST + 1];
143
144 void am_ClearServicesSt()
145 {
146     int i;
147     for (i = 0; i < MAX_APACHE_SERVICES; i++)
148     {
149         if (g_stServices[i].szServiceName)
150             free(g_stServices[i].szServiceName);
151         if (g_stServices[i].szDisplayName)
152             free(g_stServices[i].szDisplayName);
153         if (g_stServices[i].szDescription)
154             free(g_stServices[i].szDescription);
155         if (g_stServices[i].szImagePath)
156             free(g_stServices[i].szImagePath);
157
158     }
159     ZeroMemory(g_stServices, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
160
161 }
162
163 void ErrorMessage(LPCSTR szError, BOOL bFatal)
164 {
165     LPVOID lpMsgBuf  = NULL;
166     if (szError)
167         MessageBox(NULL, szError, g_lpMsg[IDS_MSG_ERROR-IDS_MSG_FIRST],
168                     MB_OK | (bFatal ? MB_ICONERROR : MB_ICONEXCLAMATION));
169     else
170     {
171         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
172             FORMAT_MESSAGE_FROM_SYSTEM |
173             FORMAT_MESSAGE_IGNORE_INSERTS,
174             NULL,
175             GetLastError(),
176             g_LangID,
177             (LPSTR) &lpMsgBuf, 0, NULL);
178         MessageBox(NULL, (LPCSTR)lpMsgBuf, g_lpMsg[IDS_MSG_ERROR-IDS_MSG_FIRST],
179                     MB_OK | (bFatal ? MB_ICONERROR : MB_ICONEXCLAMATION));
180         LocalFree(lpMsgBuf);
181     }
182     if( bFatal)
183         PostQuitMessage(0);
184 }
185
186 LPSTR GetStringRes(int id)
187 {
188   static TCHAR buffer[MAX_PATH];
189
190   buffer[0] = 0;
191   LoadString(GetModuleHandle (NULL), id, buffer, MAX_PATH);
192   return buffer;
193 }
194
195 BOOL GetSystemOSVersion(LPDWORD dwVersion)
196 {
197     OSVERSIONINFO osvi;
198     /* 
199     Try calling GetVersionEx using the OSVERSIONINFOEX structure.
200     If that fails, try using the OSVERSIONINFO structure.
201     */
202     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
203     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
204     
205     if (!GetVersionEx(&osvi))
206         return FALSE;
207     
208     switch (osvi.dwPlatformId)
209     {
210     case VER_PLATFORM_WIN32_NT:        
211         if (osvi.dwMajorVersion <= 4)
212             *dwVersion = OS_VERSION_WINNT;
213         else if (osvi.dwMajorVersion == 5)
214             *dwVersion = OS_VERSION_WIN2K;
215         else
216             return FALSE;
217         
218         break;        
219     case VER_PLATFORM_WIN32_WINDOWS:
220             *dwVersion = OS_VERSION_WIN9X;        
221         break;
222         
223     case VER_PLATFORM_WIN32s:
224             *dwVersion = 0;
225         return FALSE;
226     default:
227         return FALSE;
228         break;
229    }
230    return TRUE; 
231 }
232
233 static VOID ShowNotifyIcon(HWND hWnd, DWORD dwMessage)
234 {
235     
236     NOTIFYICONDATA nid;
237     int  i = 0, n = 0;
238
239     ZeroMemory(&nid,sizeof(nid));
240     nid.cbSize = sizeof(NOTIFYICONDATA);
241     nid.hWnd = hWnd;
242     nid.uID = 0xFF;
243     nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
244     nid.uCallbackMessage = WM_TRAYMESSAGE;
245     
246     while (g_stServices[i].szServiceName != NULL)
247     {    
248         if (g_stServices[i].dwPid != 0)
249             ++n;
250         ++i;
251     }
252     if (dwMessage != NIM_DELETE)
253     {
254         if (n)
255             nid.hIcon = g_icoRun;
256         else
257             nid.hIcon = g_icoStop;
258     }
259     else
260         nid.hIcon = NULL;
261     if (n == i && n > 0)
262         lstrcpy(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGALL-IDS_MSG_FIRST]);
263     else if (n)
264         sprintf(nid.szTip, g_lpMsg[IDS_MSG_RUNNING-IDS_MSG_FIRST], n, i);
265     else if (i)
266         sprintf(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGNONE-IDS_MSG_FIRST], i);
267     else
268         lstrcpy(nid.szTip, g_lpMsg[IDS_MSG_NOSERVICES-IDS_MSG_FIRST]);
269     Shell_NotifyIcon(dwMessage, &nid);
270 }
271
272 void appendMenuItem(HMENU hMenu, UINT uMenuId, LPSTR szName, BOOL fDefault)
273 {
274     MENUITEMINFO mii;
275     
276     ZeroMemory(&mii, sizeof(MENUITEMINFO));
277     mii.cbSize = sizeof(MENUITEMINFO);
278     mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
279     if (lstrlen(szName))
280     {
281         mii.fType = MFT_STRING;
282         mii.wID = uMenuId;
283         if (fDefault)
284             mii.fState = MFS_DEFAULT;
285         mii.dwTypeData = szName;
286     }
287     else
288         mii.fType = MFT_SEPARATOR;
289     InsertMenuItem(hMenu, uMenuId, FALSE, &mii);
290 }
291
292 void ShowTryPopupMenu(HWND hWnd)
293 {
294     /* create popup menu */
295     HMENU hMenu = CreatePopupMenu();
296     POINT pt;
297
298     if (hMenu)
299     {
300         appendMenuItem(hMenu, IDM_RESTORE, g_lpMsg[IDS_MSG_MNUSHOW-IDS_MSG_FIRST], TRUE);
301         if (g_dwOSVersion >= OS_VERSION_WINNT)
302             appendMenuItem(hMenu, IDC_SMANAGER, g_lpMsg[IDS_MSG_MNUSERVICES-IDS_MSG_FIRST], FALSE);
303         appendMenuItem(hMenu, 0, "", FALSE);
304         appendMenuItem(hMenu, IDM_EXIT,  g_lpMsg[IDS_MSG_MNUEXIT-IDS_MSG_FIRST], FALSE);
305
306         GetCursorPos(&pt);
307         SetForegroundWindow(NULL);
308         TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, 0, hWnd, NULL);
309     }
310 }
311
312 BOOL CenterWindow(HWND hwndChild)
313 {
314    RECT    rChild, rWorkArea;
315    int     wChild, hChild;
316    int     xNew, yNew;
317    BOOL    bResult;
318
319    /* Get the Height and Width of the child window */
320    GetWindowRect(hwndChild, &rChild);
321    wChild = rChild.right - rChild.left;
322    hChild = rChild.bottom - rChild.top;
323
324    /* Get the limits of the 'workarea' */
325    bResult = SystemParametersInfo(
326       SPI_GETWORKAREA,
327       sizeof(RECT),
328       &rWorkArea,
329       0);
330    if (!bResult) {
331       rWorkArea.left = rWorkArea.top = 0;
332       rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
333       rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
334    }
335
336    /* Calculate new X and Y position*/
337    xNew = (rWorkArea.right - wChild)/2;
338    yNew = (rWorkArea.bottom - hChild)/2;
339    return SetWindowPos (hwndChild, HWND_TOP, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
340 }
341
342 static void addListBoxItem(HWND hDlg, LPSTR lpStr, HBITMAP hBmp) 
343
344     int nItem; 
345  
346     nItem = SendMessage(hDlg, LB_ADDSTRING, 0, (LPARAM)lpStr); 
347     SendMessage(hDlg, LB_SETITEMDATA, nItem, (LPARAM)hBmp); 
348
349
350 static void addListBoxString(HWND hListBox, LPSTR lpStr)
351 {
352     static int nItems = 0;
353     ++nItems;
354     if ( nItems > MAX_LOADSTRING)
355     {
356         SendMessage(hListBox, LB_RESETCONTENT, 0, 0); 
357         nItems = 1;
358     }
359     ListBox_SetCurSel(hListBox,
360                       ListBox_AddString(hListBox, lpStr));
361
362 }
363 static DWORD WINAPI ConsoleOutputThread(LPVOID lpThreadParameter)
364 {
365     static BYTE lpBuffer[MAX_PATH+1];
366     int nPtr = 0;
367     BYTE  ch;
368     DWORD dwReaded;
369
370     while (ReadFile(g_hpipeOutRead, &ch, 1, &dwReaded, NULL) == TRUE) 
371     {
372         if (dwReaded > 0) 
373         {
374             if (ch == '\n' || nPtr >= MAX_PATH) 
375             {
376                 lpBuffer[nPtr] = '\0';
377                 addListBoxString(g_hwndStdoutList, lpBuffer);
378                 nPtr  = 0;
379             } 
380             else if (ch == '\t' && nPtr < (MAX_PATH - 4)) 
381             {
382                 int i;
383                 for (i = 0; i < 4; ++i)
384                     lpBuffer[nPtr++] = ' ';
385             }
386             else if (ch != '\r')
387                 lpBuffer[nPtr++] = ch;
388         }
389     }
390     CloseHandle(g_hpipeInWrite);
391     CloseHandle(g_hpipeOutRead);
392     CloseHandle(g_hpipeStdError);
393     return 0;
394 }
395
396
397 DWORD WINAPI ConsoleWaitingThread(LPVOID lpThreadParameter)
398 {
399     WaitForSingleObject(g_lpRedirectProc.hThread, INFINITE);
400     CloseHandle(g_lpRedirectProc.hThread);
401     MessageBeep(100);
402     g_bConsoleRun = FALSE;
403     SetCursor(g_hCursorArrow);
404     return 0;
405 }
406
407
408 BOOL RunRedirectedConsole(LPSTR szCmdLine)
409 {
410     
411     DWORD  dwThreadId;
412     HANDLE hProc;
413     STARTUPINFO stInfo;
414     BOOL bResult;
415     ZeroMemory(&stInfo, sizeof(stInfo));
416     stInfo.cb = sizeof(stInfo);
417     stInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
418     stInfo.wShowWindow = SW_HIDE;
419     
420     hProc = GetCurrentProcess();
421
422     if (!CreatePipe(&g_hpipeInRead, &g_hpipeInWrite, NULL, MAX_PATH))
423         ErrorMessage(NULL, TRUE);
424     if (!CreatePipe(&g_hpipeOutRead, &g_hpipeOutWrite, NULL, MAX_PATH*8))
425         ErrorMessage(NULL, TRUE);
426         
427     DuplicateHandle(hProc, g_hpipeInRead, hProc, &g_hpipeInRead, 0, TRUE, 
428                     DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
429     DuplicateHandle(hProc, g_hpipeOutWrite, hProc, &g_hpipeOutWrite, 0, TRUE, 
430                     DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
431     DuplicateHandle(hProc, g_hpipeOutWrite, hProc, &g_hpipeStdError, 0, TRUE, 
432                     DUPLICATE_SAME_ACCESS);
433     if (!g_hpipeInRead && !g_hpipeOutWrite && !g_hpipeStdError)
434         ErrorMessage(NULL, TRUE);
435
436     stInfo.hStdInput  = g_hpipeInRead;
437     stInfo.hStdOutput = g_hpipeOutWrite;
438     stInfo.hStdError  = g_hpipeStdError;
439
440     bResult = CreateProcess(NULL,
441         szCmdLine,
442         NULL,
443         NULL,
444         TRUE,
445         CREATE_SUSPENDED,
446         NULL,
447         NULL ,
448         &stInfo,
449         &g_lpRedirectProc);
450
451
452     CloseHandle(g_hpipeInRead);
453     CloseHandle(g_hpipeOutWrite);
454     CloseHandle(g_hpipeStdError);
455
456     if (!bResult)
457     {     
458         CloseHandle(g_hpipeInWrite);
459         CloseHandle(g_hpipeOutRead);
460         CloseHandle(g_hpipeStdError);
461         return FALSE;
462     }
463
464     CloseHandle(CreateThread(NULL, 0, ConsoleOutputThread, 0, 0, &dwThreadId));
465     ResumeThread(g_lpRedirectProc.hThread);
466     CloseHandle(CreateThread(NULL, 0, ConsoleWaitingThread, 0, 0, &dwThreadId));
467
468     return TRUE;
469 }
470
471 BOOL RunAndForgetConsole(LPSTR szCmdLine,
472                          BOOL  bRedirectConsole)
473 {
474         
475     STARTUPINFO stInfo;
476     PROCESS_INFORMATION prInfo;
477     BOOL bResult;
478     
479     if (bRedirectConsole)
480         return RunRedirectedConsole(szCmdLine);
481
482     
483     ZeroMemory(&stInfo, sizeof(stInfo));
484     stInfo.cb = sizeof(stInfo);
485     stInfo.dwFlags = STARTF_USESHOWWINDOW;
486     stInfo.wShowWindow = SW_HIDE;
487
488     bResult = CreateProcess(NULL,
489         szCmdLine,
490         NULL,
491         NULL,
492         TRUE,
493         CREATE_NEW_CONSOLE,
494         NULL,
495         NULL ,
496         &stInfo,
497         &prInfo);
498
499     if (!bResult)
500     {     
501         return FALSE;
502     }
503     if (g_dwOSVersion == OS_VERSION_WIN9X) /* give some time to rescan the status */
504         Sleep(2000);
505     CloseHandle(prInfo.hThread);
506     CloseHandle(prInfo.hProcess);
507     return TRUE;
508 }
509
510 BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, DWORD dwCommand)
511 {
512     
513     CHAR      szBuf[MAX_PATH];
514     CHAR      szMsg[MAX_PATH];
515     LPSTR     sPos;
516     BOOL      retValue;
517     BOOL      serviceFlag = TRUE;
518     SC_HANDLE schService;
519     SC_HANDLE schSCManager;    
520     SERVICE_STATUS schSStatus;
521     LPSTR     *args;
522     int       ticks;
523
524     if (g_dwOSVersion == OS_VERSION_WIN9X)
525     {
526         sPos = strstr(szImagePath, "-k start");
527         if (sPos)
528         {
529             lstrcpyn(szBuf, szImagePath, sPos - szImagePath);
530             switch (dwCommand)
531             {
532             case SERVICE_CONTROL_STOP:
533                 lstrcat(szBuf, " -k stop -n ");
534                 break;
535             case SERVICE_CONTROL_CONTINUE:
536                 sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART-IDS_MSG_FIRST], szServiceName);
537                 addListBoxString(g_hwndStdoutList, szMsg);
538                 lstrcat(szBuf, " -k start -n ");
539                 serviceFlag = FALSE;
540                 break;
541             case SERVICE_APACHE_RESTART:
542                 lstrcat(szBuf, " -k restart -n ");
543                 break;
544             default:
545                 return FALSE;
546             }
547             lstrcat(szBuf, szServiceName);
548         }
549         else
550             return FALSE;
551         g_bConsoleRun = TRUE;
552         SetCursor(g_hCursorHourglass);
553         if (!RunAndForgetConsole(szBuf, serviceFlag))
554         {
555             ErrorMessage(NULL, FALSE);
556             g_bConsoleRun = FALSE;
557             SetCursor(g_hCursorArrow);
558             return FALSE;
559         }
560         else if (!serviceFlag)
561         {
562             sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTARTED-IDS_MSG_FIRST], szServiceName);
563             addListBoxString(g_hwndStdoutList, szMsg);
564             g_bConsoleRun = FALSE;
565             SetCursor(g_hCursorArrow);
566             return TRUE;
567         }
568     }
569     else
570     {
571         /* Apache 2.0 uses '-k runservice' as cmdline parameter */
572         sPos = strstr(szImagePath, "--ntservice");
573         if (!sPos)
574         {
575             sPos = strstr(szImagePath, "-k runservice");
576             serviceFlag = FALSE;
577         }
578         if (sPos)
579             lstrcpyn(szBuf, szImagePath, sPos - szImagePath);
580         else
581             return FALSE;
582         schSCManager = OpenSCManager(
583             NULL,
584             NULL,
585             SC_MANAGER_ALL_ACCESS
586            );
587         if (!schSCManager)
588             return FALSE;
589         
590         schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);
591         if (schService != NULL)
592         {
593             retValue = FALSE;
594             g_bConsoleRun = TRUE;
595             SetCursor(g_hCursorHourglass);
596             switch (dwCommand)
597             {
598                 case SERVICE_CONTROL_STOP:
599                     sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTOP-IDS_MSG_FIRST], szServiceName);
600                     addListBoxString(g_hwndStdoutList, szMsg);
601                     if(ControlService(schService, SERVICE_CONTROL_STOP, &schSStatus)) 
602                     {
603                         Sleep(1000);
604                         while (QueryServiceStatus(schService, &schSStatus)) 
605                         {
606                             if (schSStatus.dwCurrentState == SERVICE_STOP_PENDING)
607                                 Sleep(1000);
608                             else
609                                 break;
610                         }
611                     }
612                     if (QueryServiceStatus(schService, &schSStatus))
613                     {
614                         if(schSStatus.dwCurrentState == SERVICE_STOPPED)
615                         {
616                             retValue = TRUE;
617                             sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTOPPED-IDS_MSG_FIRST], szServiceName);
618                             addListBoxString(g_hwndStdoutList, szMsg);
619                         }
620                     }
621                 break;                
622                 case SERVICE_CONTROL_CONTINUE:
623                     sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART-IDS_MSG_FIRST], szServiceName);
624                     addListBoxString(g_hwndStdoutList, szMsg);
625                     args = (char **)malloc(3 * sizeof(char*));
626                     args[0] = szBuf;
627                     if (serviceFlag)
628                         args[1] = "--ntservice";
629                     else
630                     {
631                         args[1] = "-k";
632                         args[2] = "runservice";
633                     }
634                     if(StartService(schService, serviceFlag ? 2 : 3, args)) 
635                     {
636                         Sleep(1000);
637                         while (QueryServiceStatus(schService, &schSStatus)) 
638                         {
639                             if (schSStatus.dwCurrentState == SERVICE_START_PENDING)
640                                 Sleep(1000);
641                             else
642                                 break;
643                         }
644                     }
645                     if (QueryServiceStatus(schService, &schSStatus))
646                     {
647                         if(schSStatus.dwCurrentState == SERVICE_RUNNING)
648                         {
649                             retValue = TRUE;
650                             sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTARTED-IDS_MSG_FIRST], szServiceName);
651                             addListBoxString(g_hwndStdoutList, szMsg);
652                         }
653                     }
654                     /* is this OK to do? */
655                     free(args);
656                 break;                
657                 case SERVICE_APACHE_RESTART:
658                     sprintf(szMsg, g_lpMsg[IDS_MSG_SRVRESTART-IDS_MSG_FIRST], szServiceName);
659                     addListBoxString(g_hwndStdoutList, szMsg);
660                     if(ControlService(schService, SERVICE_APACHE_RESTART, &schSStatus)) 
661                     {
662                         ticks = 60;
663                         while(schSStatus.dwCurrentState == SERVICE_START_PENDING) 
664                         {
665                             Sleep(1000);
666                             if(!QueryServiceStatus(schService, &schSStatus))
667                             {
668                                 CloseServiceHandle(schService);
669                                 CloseServiceHandle(schSCManager);
670                                 g_bConsoleRun = FALSE;
671                                 SetCursor(g_hCursorArrow);
672                                 return FALSE;
673                             }
674                             if (!--ticks)
675                                 break;
676                         }
677                     }
678                     if(schSStatus.dwCurrentState == SERVICE_RUNNING)
679                     {
680                         retValue = TRUE;
681                         sprintf(szMsg, g_lpMsg[IDS_MSG_SRVRESTARTED-IDS_MSG_FIRST], szServiceName);
682                         addListBoxString(g_hwndStdoutList, szMsg);
683                     }
684                 break;                
685             }
686             CloseServiceHandle(schService);
687             CloseServiceHandle(schSCManager);
688             if (!retValue)
689                 ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED-IDS_MSG_FIRST], FALSE);
690             g_bConsoleRun = FALSE;
691             SetCursor(g_hCursorArrow);
692             return retValue;
693             
694         }
695         else
696             g_bRescanServices = TRUE;
697         
698         CloseServiceHandle(schSCManager);
699         return FALSE;
700     }
701     
702     return FALSE;
703 }
704
705 BOOL IsServiceRunning(LPCSTR szServiceName, LPDWORD lpdwPid)
706 {
707
708     DWORD                   dwPid;
709     HWND                    hWnd;
710     SC_HANDLE               schService;
711     SC_HANDLE               schSCManager;    
712     SERVICE_STATUS          schSStatus;
713
714     if (g_dwOSVersion == OS_VERSION_WIN9X)
715     {
716         hWnd = FindWindow("ApacheWin95ServiceMonitor", szServiceName);
717         if (hWnd && GetWindowThreadProcessId(hWnd, &dwPid))
718         {
719             *lpdwPid = 1;
720             return TRUE;
721         }
722         else
723             return FALSE;
724     }
725     else
726     {
727
728         dwPid = 0;
729         schSCManager = OpenSCManager(
730                             NULL,
731                             NULL,
732                             SC_MANAGER_ALL_ACCESS
733                            );
734         if (!schSCManager)
735             return FALSE;
736
737         schService = OpenService(schSCManager, szServiceName, SERVICE_QUERY_STATUS);
738         if (schService != NULL)
739         {
740             if (QueryServiceStatus(schService, &schSStatus))
741             {
742                 
743                 dwPid = schSStatus.dwCurrentState;
744                 if (lpdwPid)
745                     *lpdwPid = 1;
746             }
747             CloseServiceHandle(schService);
748             CloseServiceHandle(schSCManager);
749             return dwPid == SERVICE_RUNNING ? TRUE : FALSE;
750         }
751         else
752             g_bRescanServices = TRUE;
753
754         CloseServiceHandle(schSCManager);
755         return FALSE;
756
757     }
758
759     return FALSE;
760 }
761
762 BOOL FindRunningServices()
763 {
764     int i = 0;
765     DWORD dwPid;
766     BOOL rv = FALSE;
767     while (g_stServices[i].szServiceName != NULL)
768     {    
769         if (!IsServiceRunning(g_stServices[i].szServiceName, &dwPid))
770             dwPid = 0;
771         if (g_stServices[i].dwPid != dwPid)
772             rv = TRUE;
773         g_stServices[i].dwPid = dwPid;
774         ++i;
775     }                        
776     return rv;
777 }
778
779 BOOL GetApacheServicesStatus()
780 {
781
782     CHAR    szKey[MAX_PATH];
783     CHAR    achKey[MAX_PATH];
784     CHAR    szImagePath[MAX_PATH];
785     CHAR    szBuf[MAX_PATH];
786
787     HKEY    hKey, hSubKey;
788     DWORD   retCode, rv, dwKeyType;
789     DWORD   dwBufLen = MAX_PATH;
790     int     i, stPos = 0;
791
792     g_bRescanServices = FALSE;
793
794     retCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
795                             "System\\CurrentControlSet\\Services\\",
796                             0, KEY_READ, &hKey);
797     if (retCode != ERROR_SUCCESS)
798     {
799         ErrorMessage(NULL, FALSE);
800         return FALSE;
801     }
802     am_ClearServicesSt();
803     for (i = 0, retCode = ERROR_SUCCESS; retCode == ERROR_SUCCESS; i++)
804     {
805
806         retCode = RegEnumKey(hKey, i, achKey, MAX_PATH);
807         if (retCode == ERROR_SUCCESS)
808         {
809             lstrcpy(szKey, "System\\CurrentControlSet\\Services\\");
810             lstrcat(szKey, achKey);
811
812             if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, 
813                 KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS)
814             {
815                 dwBufLen = MAX_PATH;
816                 rv = RegQueryValueEx(hSubKey, "ImagePath", NULL,
817                                       &dwKeyType, szImagePath, &dwBufLen);
818
819                 if (rv == ERROR_SUCCESS && (dwKeyType == REG_SZ  || dwKeyType == REG_EXPAND_SZ) && dwBufLen)
820                 {
821                     lstrcpy(szBuf, szImagePath);
822                     CharLower(szBuf);
823                     /* the service name could be Apache*.exe */
824                     if (strstr(szBuf, "\\apache") != NULL && strstr(szBuf, ".exe") &&
825                        (strstr(szBuf, "--ntservice") != NULL || strstr(szBuf, "-k ") !=NULL))
826                     {
827                         g_stServices[stPos].szServiceName = strdup(achKey);
828                         g_stServices[stPos].szImagePath = strdup(szImagePath);
829                         dwBufLen = MAX_PATH;
830                         if (RegQueryValueEx(hSubKey, "Description", NULL,
831                                       &dwKeyType, szBuf, &dwBufLen) == ERROR_SUCCESS)
832                             g_stServices[stPos].szDescription = strdup(szBuf);
833
834                         dwBufLen = MAX_PATH;
835                         if (RegQueryValueEx(hSubKey, "DisplayName", NULL,
836                                       &dwKeyType, szBuf, &dwBufLen) == ERROR_SUCCESS)
837                             g_stServices[stPos].szDisplayName= strdup(szBuf);
838                         ++stPos;
839                         if (stPos >= MAX_APACHE_SERVICES)
840                             retCode = !ERROR_SUCCESS;
841                     }
842                 }
843                 RegCloseKey(hSubKey);
844             }
845         }
846     }
847     RegCloseKey(hKey);
848     FindRunningServices();
849     return TRUE;
850 }
851
852
853 LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
854 {
855
856     CHAR        szBuf[MAX_PATH]; 
857     HWND        hListBox;
858     static      HWND  hStatusBar; 
859     TEXTMETRIC  tm; 
860     int         i, y; 
861     HDC         hdcMem; 
862     RECT        rcBitmap; 
863     UINT        nItem;
864     LPMEASUREITEMSTRUCT lpmis; 
865     LPDRAWITEMSTRUCT    lpdis; 
866
867     ZeroMemory(szBuf, MAX_PATH);
868     switch (message) 
869     { 
870  
871         case WM_INITDIALOG: 
872             ShowWindow(hDlg, SW_HIDE);
873             g_hwndServiceDlg = hDlg;
874             g_hBmpStart = LoadImage(g_hInstance, MAKEINTRESOURCE(IDB_BMPRUN),
875                                     IMAGE_BITMAP, XBITMAP, YBITMAP, LR_DEFAULTCOLOR); 
876             g_hBmpStop  = LoadImage(g_hInstance, MAKEINTRESOURCE(IDB_BMPSTOP), 
877                                     IMAGE_BITMAP, XBITMAP, YBITMAP, LR_DEFAULTCOLOR); 
878
879             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
880             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
881             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
882
883             if (g_dwOSVersion < OS_VERSION_WINNT)
884                 ShowWindow(GetDlgItem(hDlg, IDC_SMANAGER), SW_HIDE);
885
886             hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
887             g_hwndStdoutList = GetDlgItem(hDlg, IDL_STDOUT);
888             hStatusBar = CreateStatusWindow(SBT_TOOLTIPS | WS_CHILD | WS_VISIBLE,
889                                             "", hDlg, IDC_STATBAR);            
890             if (GetApacheServicesStatus())
891             {
892                 i = 0;
893                 while (g_stServices[i].szServiceName != NULL)
894                 {    
895                     addListBoxItem(hListBox, g_stServices[i].szDisplayName, 
896                         g_stServices[i].dwPid == 0 ? g_hBmpStop : g_hBmpStart);
897                     ++i;
898                 }
899             }
900             CenterWindow(hDlg);
901             ShowWindow(hDlg, SW_SHOW);
902             SetFocus(hListBox); 
903             SendMessage(hListBox, LB_SETCURSEL, 0, 0); 
904             return TRUE;
905         break;
906         case WM_UPDATEMESSAGE:
907             hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
908             SendMessage(hListBox, LB_RESETCONTENT, 0, 0); 
909             SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"");
910             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
911             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
912             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
913             i = 0;
914             while (g_stServices[i].szServiceName != NULL)
915             {    
916                 addListBoxItem(hListBox, g_stServices[i].szDisplayName, 
917                     g_stServices[i].dwPid == 0 ? g_hBmpStop : g_hBmpStart);
918                 ++i;
919             }
920             SendMessage(hListBox, LB_SETCURSEL, 0, 0); 
921             /* Dirty hack to bring the window to the foreground */
922             SetWindowPos(hDlg, HWND_TOPMOST, 0, 0, 0, 0,
923                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
924             SetWindowPos(hDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
925                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
926             SetFocus(hListBox); 
927             return TRUE;
928         break;
929         case WM_MEASUREITEM: 
930  
931             lpmis = (LPMEASUREITEMSTRUCT) lParam; 
932             lpmis->itemHeight = YBITMAP; 
933             return TRUE; 
934         case WM_SETCURSOR:
935             if (g_bConsoleRun)
936                 SetCursor(g_hCursorHourglass);
937             else
938                 SetCursor(g_hCursorArrow);
939             return TRUE;
940         case WM_DRAWITEM: 
941             lpdis = (LPDRAWITEMSTRUCT) lParam; 
942             if (lpdis->itemID == -1) 
943             { 
944                 break; 
945             } 
946             switch (lpdis->itemAction) 
947             { 
948                 case ODA_SELECT: 
949                 case ODA_DRAWENTIRE: 
950                     g_hBmpPicture = (HBITMAP)SendMessage(lpdis->hwndItem, 
951                         LB_GETITEMDATA, lpdis->itemID, (LPARAM) 0); 
952  
953                     hdcMem = CreateCompatibleDC(lpdis->hDC); 
954                     g_hBmpOld = SelectObject(hdcMem, g_hBmpPicture); 
955  
956                     BitBlt(lpdis->hDC, 
957                         lpdis->rcItem.left, lpdis->rcItem.top, 
958                         lpdis->rcItem.right - lpdis->rcItem.left, 
959                         lpdis->rcItem.bottom - lpdis->rcItem.top, 
960                         hdcMem, 0, 0, SRCCOPY); 
961                     SendMessage(lpdis->hwndItem, LB_GETTEXT, 
962                         lpdis->itemID, (LPARAM) szBuf); 
963  
964                     GetTextMetrics(lpdis->hDC, &tm);  
965                     y = (lpdis->rcItem.bottom + lpdis->rcItem.top - 
966                         tm.tmHeight) / 2; 
967   
968                     SelectObject(hdcMem, g_hBmpOld); 
969                     DeleteDC(hdcMem); 
970  
971                     rcBitmap.left = lpdis->rcItem.left + XBITMAP + 2; 
972                     rcBitmap.top = lpdis->rcItem.top; 
973                     rcBitmap.right = lpdis->rcItem.right; 
974                     rcBitmap.bottom = lpdis->rcItem.top + YBITMAP; 
975
976                     if (lpdis->itemState & ODS_SELECTED) 
977                     { 
978                         if (g_hBmpPicture == g_hBmpStop)
979                         {
980                             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
981                             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
982                             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
983                         }
984                         else if (g_hBmpPicture == g_hBmpStart) 
985                         {
986                             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
987                             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
988                             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
989                         }
990                         if (g_stServices[lpdis->itemID].szDescription)
991                             SendMessage(hStatusBar, SB_SETTEXT, 0, 
992                                         (LPARAM)g_stServices[lpdis->itemID].szDescription);
993                         else
994                             SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"");
995                         
996                         SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 
997                         SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); 
998                         FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_HIGHLIGHTTEXT)); 
999                     } 
1000                     else
1001                     {
1002                        SetTextColor(lpdis->hDC, GetSysColor(COLOR_MENUTEXT)); 
1003                        SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW)); 
1004                        FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_WINDOW+1)); 
1005                     }
1006                     TextOut(lpdis->hDC, 
1007                         XBITMAP + 6, 
1008                         y, 
1009                         szBuf, 
1010                         strlen(szBuf)); 
1011                     break; 
1012  
1013                 case ODA_FOCUS: 
1014                     break; 
1015             } 
1016             return TRUE;  
1017         case WM_COMMAND: 
1018             switch (LOWORD(wParam)) 
1019             { 
1020                 case IDL_SERVICES:
1021                     switch (HIWORD(wParam))
1022                     {
1023                         case LBN_DBLCLK:
1024                             /* if started then stop, if stopped then start the service */
1025                             hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1026                             nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1027                             if (nItem != LB_ERR)
1028                             {
1029                                 g_hBmpPicture = (HBITMAP)SendMessage(hListBox, LB_GETITEMDATA,
1030                                                                nItem, (LPARAM) 0); 
1031                                 if (g_hBmpPicture == g_hBmpStop)
1032                                 {
1033                                     ApacheManageService(g_stServices[nItem].szServiceName,
1034                                                 g_stServices[nItem].szImagePath,
1035                                                 SERVICE_CONTROL_CONTINUE);
1036                                 }
1037                                 else
1038                                     ApacheManageService(g_stServices[nItem].szServiceName,
1039                                                 g_stServices[nItem].szImagePath,
1040                                                 SERVICE_CONTROL_STOP);
1041
1042                             }
1043                             return TRUE;
1044                         break;
1045                      }
1046                 break;
1047                 case IDOK: 
1048                     EndDialog(hDlg, TRUE); 
1049                     return TRUE; 
1050                 case IDC_SSTART: 
1051                     Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1052                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1053                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1054                     if (nItem != LB_ERR)
1055                     {
1056                         ApacheManageService(g_stServices[nItem].szServiceName,
1057                                              g_stServices[nItem].szImagePath,
1058                                              SERVICE_CONTROL_CONTINUE);
1059                     }
1060                     Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
1061                     return TRUE;
1062                 case IDC_SSTOP: 
1063                     Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1064                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1065                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1066                     if (nItem != LB_ERR)
1067                     {
1068                         ApacheManageService(g_stServices[nItem].szServiceName,
1069                                              g_stServices[nItem].szImagePath,
1070                                              SERVICE_CONTROL_STOP);
1071                     }
1072                     Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
1073                     return TRUE;
1074                 case IDC_SRESTART: 
1075                     Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1076                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1077                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1078                     if (nItem != LB_ERR)
1079                     {
1080                         ApacheManageService(g_stServices[nItem].szServiceName,
1081                                              g_stServices[nItem].szImagePath,
1082                                              SERVICE_APACHE_RESTART);
1083                     }
1084                     Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
1085                     return TRUE;
1086                 case IDC_SMANAGER: 
1087                     if (g_dwOSVersion >= OS_VERSION_WIN2K)
1088                         ShellExecute(hDlg, "open", "services.msc", "/s", NULL, SW_NORMAL);
1089                     else
1090                         WinExec("Control.exe SrvMgr.cpl Services", SW_NORMAL);
1091                     return TRUE;
1092                 case IDC_SEXIT: 
1093                     EndDialog( hDlg, TRUE);
1094                     SendMessage( g_hwndMain, WM_COMMAND, (WPARAM)IDM_EXIT, 0);
1095                     return TRUE;
1096              }
1097         break;
1098         case WM_SIZE:
1099             switch (LOWORD(wParam)) 
1100             { 
1101                 case SIZE_MINIMIZED:
1102                     EndDialog(hDlg, TRUE); 
1103                     return TRUE; 
1104                 break;
1105             }
1106         break;
1107         case WM_QUIT:
1108         case WM_CLOSE: 
1109             EndDialog(hDlg, TRUE);
1110             return TRUE;
1111         case WM_DESTROY: 
1112             DeleteObject(g_hBmpStart); 
1113             DeleteObject(g_hBmpStop); 
1114             return TRUE; 
1115         default:
1116             return FALSE;
1117     }
1118     return FALSE;
1119 }
1120
1121
1122 LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
1123                           WPARAM wParam, LPARAM lParam)
1124 {
1125     
1126     if (message == g_bUiTaskbarCreated)
1127     {
1128         /* restore the tray icon on shell restart */
1129         ShowNotifyIcon(hWnd, NIM_ADD);
1130         return DefWindowProc(hWnd, message, wParam, lParam);
1131     }
1132     switch (message) 
1133     {
1134         case WM_CREATE:
1135             GetApacheServicesStatus();
1136             ShowNotifyIcon(hWnd, NIM_ADD);
1137             SetTimer(hWnd, WM_TIMER_REFRESH, REFRESH_TIME, (TIMERPROC)WndProc);
1138             SetTimer(hWnd, WM_TIMER_RESCAN,  RESCAN_TIME, (TIMERPROC)WndProc);
1139             g_hwndServiceDlg = NULL;                      
1140             break;
1141         case WM_TIMER_RESCAN:
1142         {
1143             int nPrev = 0, nNew = 0;
1144             EnterCriticalSection(&g_stcSection);
1145             if (FindRunningServices() || g_bRescanServices)
1146             {
1147                 ShowNotifyIcon(hWnd, NIM_MODIFY);
1148                 if (g_hwndServiceDlg)
1149                     PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1150             }
1151             /* check if services list changed */
1152             while (g_stServices[nPrev].szServiceName != NULL)
1153                 ++nPrev;
1154             GetApacheServicesStatus();
1155             while (g_stServices[nNew].szServiceName != NULL)
1156                 ++nNew;
1157             if (nPrev != nNew)
1158             {
1159                 ShowNotifyIcon(hWnd, NIM_MODIFY);
1160                 if (g_hwndServiceDlg)
1161                     PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1162             }
1163             LeaveCriticalSection(&g_stcSection);
1164             break;
1165         }
1166         case WM_TIMER_REFRESH:
1167         {
1168             int nPrev = 0, nNew = 0;
1169             EnterCriticalSection(&g_stcSection);
1170             if (g_bRescanServices)
1171             {
1172                 GetApacheServicesStatus();
1173                 ShowNotifyIcon(hWnd, NIM_MODIFY);
1174                 if (g_hwndServiceDlg)
1175                     PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1176             }
1177             else if (FindRunningServices())
1178             {
1179                 ShowNotifyIcon(hWnd, NIM_MODIFY);
1180                 if (g_hwndServiceDlg)
1181                     PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1182             }
1183             LeaveCriticalSection(&g_stcSection);
1184             break;
1185         }
1186         case WM_QUIT:
1187             ShowNotifyIcon(hWnd, NIM_DELETE);
1188             break;
1189         case WM_TRAYMESSAGE:
1190             switch(lParam)
1191             {
1192                 case WM_LBUTTONDBLCLK:
1193                    if (!g_bDlgServiceOn)
1194                    {
1195                        g_bDlgServiceOn = TRUE;
1196                        DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DLGSERVICES),
1197                              hWnd, (DLGPROC)ServiceDlgProc);
1198                        g_bDlgServiceOn = FALSE;
1199                        g_hwndServiceDlg = NULL;
1200                    }
1201                    else if (g_hwndServiceDlg)
1202                    {
1203                        /* Dirty hack to bring the window to the foreground */
1204                        SetWindowPos(g_hwndServiceDlg, HWND_TOPMOST, 0, 0, 0, 0,
1205                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1206                        SetWindowPos(g_hwndServiceDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
1207                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1208                        SetFocus(g_hwndServiceDlg);
1209                    }
1210                 break;
1211                 case WM_RBUTTONUP:
1212                     ShowTryPopupMenu(hWnd);
1213                 break;    
1214             }
1215             break;
1216         case WM_COMMAND:
1217             switch (LOWORD(wParam))
1218             {
1219                case IDM_RESTORE:
1220                    if (!g_bDlgServiceOn)
1221                    {
1222                        g_bDlgServiceOn = TRUE;
1223                        DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DLGSERVICES),
1224                              hWnd, (DLGPROC)ServiceDlgProc);
1225                        g_bDlgServiceOn = FALSE;
1226                        g_hwndServiceDlg = NULL;
1227                    }
1228                    else if (g_hwndServiceDlg)
1229                        SetFocus(g_hwndServiceDlg);
1230                    break;
1231                 case IDC_SMANAGER: 
1232                     if (g_dwOSVersion >= OS_VERSION_WIN2K)
1233                         ShellExecute(NULL, "open", "services.msc", "/s", NULL, SW_NORMAL);
1234                     else
1235                         WinExec("Control.exe SrvMgr.cpl Services", SW_NORMAL);
1236                     return TRUE;
1237                case IDM_EXIT:
1238                    ShowNotifyIcon(hWnd, NIM_DELETE);
1239                    PostQuitMessage(0);
1240                    return TRUE;
1241             }
1242         default:
1243             return DefWindowProc(hWnd, message, wParam, lParam);
1244     }
1245
1246     return FALSE;
1247 }
1248
1249 /* Create main invisible window */
1250 HWND CreateMainWindow(HINSTANCE hInstance)
1251 {
1252     HWND       hWnd = NULL;
1253     WNDCLASSEX wcex;
1254
1255     if (!GetSystemOSVersion(&g_dwOSVersion))
1256     {
1257         ErrorMessage(NULL, TRUE);
1258         return hWnd;
1259     }
1260
1261     wcex.cbSize = sizeof(WNDCLASSEX); 
1262
1263     wcex.style          = CS_HREDRAW | CS_VREDRAW;
1264     wcex.lpfnWndProc    = (WNDPROC)WndProc;
1265     wcex.cbClsExtra     = 0;
1266     wcex.cbWndExtra     = 0;
1267     wcex.hInstance      = hInstance;
1268     wcex.hIcon          = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_APSRVMON),
1269                                            IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
1270     wcex.hCursor        = g_hCursorArrow;
1271     wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
1272     wcex.lpszMenuName   = 0;
1273     wcex.lpszClassName  = g_szWindowClass;
1274     wcex.hIconSm        = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_APSRVMON),
1275                                            IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1276
1277     if (RegisterClassEx(&wcex))
1278         hWnd = CreateWindow(g_szWindowClass, g_szTitle,
1279                              0, 0, 0, 0, 0,
1280                              NULL, NULL, hInstance, NULL);
1281
1282     return hWnd;
1283
1284 }
1285
1286
1287 int WINAPI WinMain(HINSTANCE hInstance,
1288                     HINSTANCE hPrevInstance,
1289                     LPSTR lpCmdLine,
1290                     int nCmdShow)
1291 {
1292     TCHAR szTmp[MAX_LOADSTRING];
1293     MSG     msg;
1294     /* single instance mutex */
1295     HANDLE hMutex;
1296     int i;
1297
1298     g_LangID = GetUserDefaultLangID();
1299     if ((g_LangID & 0xFF) != LANG_ENGLISH)
1300         g_LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
1301     
1302     for (i = IDS_MSG_FIRST; i <= IDS_MSG_LAST; ++i) {
1303         LoadString(hInstance, i, szTmp, MAX_LOADSTRING);
1304         g_lpMsg[i - IDS_MSG_FIRST] = strdup(szTmp);
1305     }
1306     LoadString(hInstance, IDS_APMONITORTITLE, szTmp, MAX_LOADSTRING);
1307     g_szTitle = strdup(szTmp);
1308     LoadString(hInstance, IDS_APMONITORCLASS, szTmp, MAX_LOADSTRING);
1309     g_szWindowClass = strdup(szTmp);
1310
1311     g_icoStop          = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICOSTOP),
1312                                    IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1313     g_icoRun           = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICORUN),
1314                                    IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1315     g_hCursorHourglass = LoadImage(NULL, MAKEINTRESOURCE(OCR_WAIT), IMAGE_CURSOR,
1316                                    LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED);
1317     g_hCursorArrow     = LoadImage(NULL, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR,
1318                                    LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED);
1319
1320     hMutex = CreateMutex(NULL, FALSE, "APSRVMON_MUTEX");
1321     if((hMutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
1322     {
1323         ErrorMessage(g_lpMsg[IDS_MSG_APPRUNNING-IDS_MSG_FIRST], FALSE);
1324         if (hMutex)
1325             CloseHandle(hMutex);
1326
1327         return 0;
1328     }
1329
1330     ZeroMemory(g_stServices, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
1331     InitCommonControls();
1332     g_hInstance = hInstance;
1333     g_hwndMain = CreateMainWindow(hInstance);
1334     InitializeCriticalSection(&g_stcSection);
1335     if (g_hwndMain != NULL)
1336     {
1337         g_bUiTaskbarCreated = RegisterWindowMessage("TaskbarCreated");
1338         while (GetMessage(&msg, NULL, 0, 0) == TRUE) 
1339         {
1340             TranslateMessage(&msg);
1341             DispatchMessage(&msg);
1342         }    
1343         am_ClearServicesSt();
1344     }
1345     DeleteCriticalSection(&g_stcSection);
1346     CloseHandle(hMutex);
1347     DestroyIcon(g_icoStop);
1348     DestroyIcon(g_icoRun);
1349     DestroyCursor(g_hCursorHourglass);
1350     DestroyCursor(g_hCursorArrow);
1351     return 0;
1352 }