]> granicus.if.org Git - apache/blob - support/win32/ApacheMonitor.c
A bit overboard - this registered window message only needs to be
[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, BOOL fEnabled)
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         if (!fEnabled)
286             mii.fState |= MFS_DISABLED;
287         mii.dwTypeData = szName;
288     }
289     else
290         mii.fType = MFT_SEPARATOR;
291     InsertMenuItem(hMenu, uMenuId, FALSE, &mii);
292 }
293
294 void appendServiceMenu(HMENU hMenu, UINT uMenuId, LPSTR szServiceName, BOOL fRunning)
295 {
296     MENUITEMINFO mii;
297     HMENU        smh;    
298
299     smh = CreatePopupMenu();
300
301     appendMenuItem(smh,  IDM_SM_START + uMenuId, g_lpMsg[IDS_MSG_SSTART-IDS_MSG_FIRST], FALSE, !fRunning);
302     appendMenuItem(smh,  IDM_SM_STOP + uMenuId, g_lpMsg[IDS_MSG_SSTOP-IDS_MSG_FIRST], FALSE, fRunning);
303     appendMenuItem(smh,  IDM_SM_RESTART + uMenuId, g_lpMsg[IDS_MSG_SRESTART-IDS_MSG_FIRST], FALSE, fRunning);
304
305     ZeroMemory(&mii, sizeof(MENUITEMINFO));
306     mii.cbSize = sizeof(MENUITEMINFO);
307     mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU;
308     mii.fType = MFT_STRING;
309     mii.wID = uMenuId;
310     mii.dwTypeData = szServiceName;
311     mii.hSubMenu = smh;
312     InsertMenuItem(hMenu, IDM_SM_SERVICE + uMenuId, FALSE, &mii);
313 }
314
315 void ShowTryPopupMenu(HWND hWnd)
316 {
317     /* create popup menu */
318     HMENU hMenu = CreatePopupMenu();
319     POINT pt;
320
321     if (hMenu)
322     {
323         appendMenuItem(hMenu, IDM_RESTORE, g_lpMsg[IDS_MSG_MNUSHOW-IDS_MSG_FIRST], TRUE, TRUE);
324         if (g_dwOSVersion >= OS_VERSION_WINNT)
325             appendMenuItem(hMenu, IDC_SMANAGER, g_lpMsg[IDS_MSG_MNUSERVICES-IDS_MSG_FIRST], FALSE, TRUE);
326         appendMenuItem(hMenu, 0, "", FALSE, TRUE);
327         appendMenuItem(hMenu, IDM_EXIT,  g_lpMsg[IDS_MSG_MNUEXIT-IDS_MSG_FIRST], FALSE, TRUE);
328
329         GetCursorPos(&pt);
330         SetForegroundWindow(NULL);
331         TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, 0, hWnd, NULL);
332         DestroyMenu(hMenu);
333     }
334 }
335
336 void ShowTryServicesMenu(HWND hWnd)
337 {
338     /* create services list popup menu and submenus */
339     HMENU hMenu = CreatePopupMenu();
340     POINT pt;
341     int i = 0;
342
343     if (hMenu)
344     {
345         while (g_stServices[i].szServiceName != NULL)
346         {   
347             appendServiceMenu(hMenu, i, g_stServices[i].szDisplayName,
348                               g_stServices[i].dwPid != 0);               
349             ++i;
350         }
351         if (i)
352         {
353             GetCursorPos(&pt);
354             SetForegroundWindow(NULL);
355             TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, 0, hWnd, NULL);
356             DestroyMenu(hMenu);
357         }
358     }
359 }
360
361 BOOL CenterWindow(HWND hwndChild)
362 {
363    RECT    rChild, rWorkArea;
364    int     wChild, hChild;
365    int     xNew, yNew;
366    BOOL    bResult;
367
368    /* Get the Height and Width of the child window */
369    GetWindowRect(hwndChild, &rChild);
370    wChild = rChild.right - rChild.left;
371    hChild = rChild.bottom - rChild.top;
372
373    /* Get the limits of the 'workarea' */
374    bResult = SystemParametersInfo(
375       SPI_GETWORKAREA,
376       sizeof(RECT),
377       &rWorkArea,
378       0);
379    if (!bResult) {
380       rWorkArea.left = rWorkArea.top = 0;
381       rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
382       rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
383    }
384
385    /* Calculate new X and Y position*/
386    xNew = (rWorkArea.right - wChild)/2;
387    yNew = (rWorkArea.bottom - hChild)/2;
388    return SetWindowPos (hwndChild, HWND_TOP, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
389 }
390
391 static void addListBoxItem(HWND hDlg, LPSTR lpStr, HBITMAP hBmp) 
392
393     int nItem; 
394  
395     nItem = SendMessage(hDlg, LB_ADDSTRING, 0, (LPARAM)lpStr); 
396     SendMessage(hDlg, LB_SETITEMDATA, nItem, (LPARAM)hBmp); 
397
398
399 static void addListBoxString(HWND hListBox, LPSTR lpStr)
400 {
401     static int nItems = 0;
402     if (!g_bDlgServiceOn)
403         return;
404
405     ++nItems;
406     if ( nItems > MAX_LOADSTRING)
407     {
408         SendMessage(hListBox, LB_RESETCONTENT, 0, 0); 
409         nItems = 1;
410     }
411     ListBox_SetCurSel(hListBox,
412                       ListBox_AddString(hListBox, lpStr));
413
414 }
415 static DWORD WINAPI ConsoleOutputThread(LPVOID lpThreadParameter)
416 {
417     static BYTE lpBuffer[MAX_PATH+1];
418     int nPtr = 0;
419     BYTE  ch;
420     DWORD dwReaded;
421
422     while (ReadFile(g_hpipeOutRead, &ch, 1, &dwReaded, NULL) == TRUE) 
423     {
424         if (dwReaded > 0) 
425         {
426             if (ch == '\n' || nPtr >= MAX_PATH) 
427             {
428                 lpBuffer[nPtr] = '\0';
429                 addListBoxString(g_hwndStdoutList, lpBuffer);
430                 nPtr  = 0;
431             } 
432             else if (ch == '\t' && nPtr < (MAX_PATH - 4)) 
433             {
434                 int i;
435                 for (i = 0; i < 4; ++i)
436                     lpBuffer[nPtr++] = ' ';
437             }
438             else if (ch != '\r')
439                 lpBuffer[nPtr++] = ch;
440         }
441     }
442     CloseHandle(g_hpipeInWrite);
443     CloseHandle(g_hpipeOutRead);
444     CloseHandle(g_hpipeStdError);
445     return 0;
446 }
447
448
449 DWORD WINAPI ConsoleWaitingThread(LPVOID lpThreadParameter)
450 {
451     WaitForSingleObject(g_lpRedirectProc.hThread, INFINITE);
452     CloseHandle(g_lpRedirectProc.hThread);
453     MessageBeep(100);
454     g_bConsoleRun = FALSE;
455     SetCursor(g_hCursorArrow);
456     return 0;
457 }
458
459
460 BOOL RunRedirectedConsole(LPSTR szCmdLine)
461 {
462     
463     DWORD  dwThreadId;
464     HANDLE hProc;
465     STARTUPINFO stInfo;
466     BOOL bResult;
467     ZeroMemory(&stInfo, sizeof(stInfo));
468     stInfo.cb = sizeof(stInfo);
469     stInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
470     stInfo.wShowWindow = SW_HIDE;
471     
472     hProc = GetCurrentProcess();
473
474     if (!CreatePipe(&g_hpipeInRead, &g_hpipeInWrite, NULL, MAX_PATH))
475         ErrorMessage(NULL, TRUE);
476     if (!CreatePipe(&g_hpipeOutRead, &g_hpipeOutWrite, NULL, MAX_PATH*8))
477         ErrorMessage(NULL, TRUE);
478         
479     DuplicateHandle(hProc, g_hpipeInRead, hProc, &g_hpipeInRead, 0, TRUE, 
480                     DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
481     DuplicateHandle(hProc, g_hpipeOutWrite, hProc, &g_hpipeOutWrite, 0, TRUE, 
482                     DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
483     DuplicateHandle(hProc, g_hpipeOutWrite, hProc, &g_hpipeStdError, 0, TRUE, 
484                     DUPLICATE_SAME_ACCESS);
485     if (!g_hpipeInRead && !g_hpipeOutWrite && !g_hpipeStdError)
486         ErrorMessage(NULL, TRUE);
487
488     stInfo.hStdInput  = g_hpipeInRead;
489     stInfo.hStdOutput = g_hpipeOutWrite;
490     stInfo.hStdError  = g_hpipeStdError;
491
492     bResult = CreateProcess(NULL,
493         szCmdLine,
494         NULL,
495         NULL,
496         TRUE,
497         CREATE_SUSPENDED,
498         NULL,
499         NULL ,
500         &stInfo,
501         &g_lpRedirectProc);
502
503
504     CloseHandle(g_hpipeInRead);
505     CloseHandle(g_hpipeOutWrite);
506     CloseHandle(g_hpipeStdError);
507
508     if (!bResult)
509     {     
510         CloseHandle(g_hpipeInWrite);
511         CloseHandle(g_hpipeOutRead);
512         CloseHandle(g_hpipeStdError);
513         return FALSE;
514     }
515
516     CloseHandle(CreateThread(NULL, 0, ConsoleOutputThread, 0, 0, &dwThreadId));
517     ResumeThread(g_lpRedirectProc.hThread);
518     CloseHandle(CreateThread(NULL, 0, ConsoleWaitingThread, 0, 0, &dwThreadId));
519
520     return TRUE;
521 }
522
523 BOOL RunAndForgetConsole(LPSTR szCmdLine,
524                          BOOL  bRedirectConsole)
525 {
526         
527     STARTUPINFO stInfo;
528     PROCESS_INFORMATION prInfo;
529     BOOL bResult;
530     
531     if (bRedirectConsole)
532         return RunRedirectedConsole(szCmdLine);
533
534     
535     ZeroMemory(&stInfo, sizeof(stInfo));
536     stInfo.cb = sizeof(stInfo);
537     stInfo.dwFlags = STARTF_USESHOWWINDOW;
538     stInfo.wShowWindow = SW_HIDE;
539
540     bResult = CreateProcess(NULL,
541         szCmdLine,
542         NULL,
543         NULL,
544         TRUE,
545         CREATE_NEW_CONSOLE,
546         NULL,
547         NULL ,
548         &stInfo,
549         &prInfo);
550
551     if (!bResult)
552     {     
553         return FALSE;
554     }
555     if (g_dwOSVersion == OS_VERSION_WIN9X) /* give some time to rescan the status */
556         Sleep(2000);
557     CloseHandle(prInfo.hThread);
558     CloseHandle(prInfo.hProcess);
559     return TRUE;
560 }
561
562 BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, DWORD dwCommand)
563 {
564     
565     CHAR      szBuf[MAX_PATH];
566     CHAR      szMsg[MAX_PATH];
567     LPSTR     sPos;
568     BOOL      retValue;
569     BOOL      serviceFlag = TRUE;
570     SC_HANDLE schService;
571     SC_HANDLE schSCManager;    
572     SERVICE_STATUS schSStatus;
573     LPSTR     *args;
574     int       ticks;
575
576     if (g_dwOSVersion == OS_VERSION_WIN9X)
577     {
578         sPos = strstr(szImagePath, "-k start");
579         if (sPos)
580         {
581             lstrcpyn(szBuf, szImagePath, sPos - szImagePath);
582             switch (dwCommand)
583             {
584             case SERVICE_CONTROL_STOP:
585                 lstrcat(szBuf, " -k stop -n ");
586                 break;
587             case SERVICE_CONTROL_CONTINUE:
588                 sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART-IDS_MSG_FIRST], szServiceName);
589                 addListBoxString(g_hwndStdoutList, szMsg);
590                 lstrcat(szBuf, " -k start -n ");
591                 serviceFlag = FALSE;
592                 break;
593             case SERVICE_APACHE_RESTART:
594                 lstrcat(szBuf, " -k restart -n ");
595                 break;
596             default:
597                 return FALSE;
598             }
599             lstrcat(szBuf, szServiceName);
600         }
601         else
602             return FALSE;
603         g_bConsoleRun = TRUE;
604         SetCursor(g_hCursorHourglass);
605         if (!RunAndForgetConsole(szBuf, serviceFlag))
606         {
607             ErrorMessage(NULL, FALSE);
608             g_bConsoleRun = FALSE;
609             SetCursor(g_hCursorArrow);
610             return FALSE;
611         }
612         else if (!serviceFlag)
613         {
614             sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTARTED-IDS_MSG_FIRST], szServiceName);
615             addListBoxString(g_hwndStdoutList, szMsg);
616             g_bConsoleRun = FALSE;
617             SetCursor(g_hCursorArrow);
618             return TRUE;
619         }
620     }
621     else
622     {
623         /* Apache 2.0 uses '-k runservice' as cmdline parameter */
624         sPos = strstr(szImagePath, "--ntservice");
625         if (!sPos)
626         {
627             sPos = strstr(szImagePath, "-k runservice");
628             serviceFlag = FALSE;
629         }
630         if (sPos)
631             lstrcpyn(szBuf, szImagePath, sPos - szImagePath);
632         else
633             return FALSE;
634         schSCManager = OpenSCManager(
635             NULL,
636             NULL,
637             SC_MANAGER_ALL_ACCESS
638            );
639         if (!schSCManager)
640             return FALSE;
641         
642         schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);
643         if (schService != NULL)
644         {
645             retValue = FALSE;
646             g_bConsoleRun = TRUE;
647             SetCursor(g_hCursorHourglass);
648             switch (dwCommand)
649             {
650                 case SERVICE_CONTROL_STOP:
651                     sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTOP-IDS_MSG_FIRST], szServiceName);
652                     addListBoxString(g_hwndStdoutList, szMsg);
653                     if(ControlService(schService, SERVICE_CONTROL_STOP, &schSStatus)) 
654                     {
655                         Sleep(1000);
656                         while (QueryServiceStatus(schService, &schSStatus)) 
657                         {
658                             if (schSStatus.dwCurrentState == SERVICE_STOP_PENDING)
659                                 Sleep(1000);
660                             else
661                                 break;
662                         }
663                     }
664                     if (QueryServiceStatus(schService, &schSStatus))
665                     {
666                         if(schSStatus.dwCurrentState == SERVICE_STOPPED)
667                         {
668                             retValue = TRUE;
669                             sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTOPPED-IDS_MSG_FIRST], szServiceName);
670                             addListBoxString(g_hwndStdoutList, szMsg);
671                         }
672                     }
673                 break;                
674                 case SERVICE_CONTROL_CONTINUE:
675                     sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART-IDS_MSG_FIRST], szServiceName);
676                     addListBoxString(g_hwndStdoutList, szMsg);
677                     args = (char **)malloc(3 * sizeof(char*));
678                     args[0] = szBuf;
679                     if (serviceFlag)
680                         args[1] = "--ntservice";
681                     else
682                     {
683                         args[1] = "-k";
684                         args[2] = "runservice";
685                     }
686                     if(StartService(schService, serviceFlag ? 2 : 3, args)) 
687                     {
688                         Sleep(1000);
689                         while (QueryServiceStatus(schService, &schSStatus)) 
690                         {
691                             if (schSStatus.dwCurrentState == SERVICE_START_PENDING)
692                                 Sleep(1000);
693                             else
694                                 break;
695                         }
696                     }
697                     if (QueryServiceStatus(schService, &schSStatus))
698                     {
699                         if(schSStatus.dwCurrentState == SERVICE_RUNNING)
700                         {
701                             retValue = TRUE;
702                             sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTARTED-IDS_MSG_FIRST], szServiceName);
703                             addListBoxString(g_hwndStdoutList, szMsg);
704                         }
705                     }
706                     /* is this OK to do? */
707                     free(args);
708                 break;                
709                 case SERVICE_APACHE_RESTART:
710                     sprintf(szMsg, g_lpMsg[IDS_MSG_SRVRESTART-IDS_MSG_FIRST], szServiceName);
711                     addListBoxString(g_hwndStdoutList, szMsg);
712                     if(ControlService(schService, SERVICE_APACHE_RESTART, &schSStatus)) 
713                     {
714                         ticks = 60;
715                         while(schSStatus.dwCurrentState == SERVICE_START_PENDING) 
716                         {
717                             Sleep(1000);
718                             if(!QueryServiceStatus(schService, &schSStatus))
719                             {
720                                 CloseServiceHandle(schService);
721                                 CloseServiceHandle(schSCManager);
722                                 g_bConsoleRun = FALSE;
723                                 SetCursor(g_hCursorArrow);
724                                 return FALSE;
725                             }
726                             if (!--ticks)
727                                 break;
728                         }
729                     }
730                     if(schSStatus.dwCurrentState == SERVICE_RUNNING)
731                     {
732                         retValue = TRUE;
733                         sprintf(szMsg, g_lpMsg[IDS_MSG_SRVRESTARTED-IDS_MSG_FIRST], szServiceName);
734                         addListBoxString(g_hwndStdoutList, szMsg);
735                     }
736                 break;                
737             }
738             CloseServiceHandle(schService);
739             CloseServiceHandle(schSCManager);
740             if (!retValue)
741                 ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED-IDS_MSG_FIRST], FALSE);
742             g_bConsoleRun = FALSE;
743             SetCursor(g_hCursorArrow);
744             return retValue;
745             
746         }
747         else
748             g_bRescanServices = TRUE;
749         
750         CloseServiceHandle(schSCManager);
751         return FALSE;
752     }
753     
754     return FALSE;
755 }
756
757 BOOL IsServiceRunning(LPCSTR szServiceName, LPDWORD lpdwPid)
758 {
759
760     DWORD                   dwPid;
761     HWND                    hWnd;
762     SC_HANDLE               schService;
763     SC_HANDLE               schSCManager;    
764     SERVICE_STATUS          schSStatus;
765
766     if (g_dwOSVersion == OS_VERSION_WIN9X)
767     {
768         hWnd = FindWindow("ApacheWin95ServiceMonitor", szServiceName);
769         if (hWnd && GetWindowThreadProcessId(hWnd, &dwPid))
770         {
771             *lpdwPid = 1;
772             return TRUE;
773         }
774         else
775             return FALSE;
776     }
777     else
778     {
779
780         dwPid = 0;
781         schSCManager = OpenSCManager(
782                             NULL,
783                             NULL,
784                             SC_MANAGER_ALL_ACCESS
785                            );
786         if (!schSCManager)
787             return FALSE;
788
789         schService = OpenService(schSCManager, szServiceName, SERVICE_QUERY_STATUS);
790         if (schService != NULL)
791         {
792             if (QueryServiceStatus(schService, &schSStatus))
793             {
794                 
795                 dwPid = schSStatus.dwCurrentState;
796                 if (lpdwPid)
797                     *lpdwPid = 1;
798             }
799             CloseServiceHandle(schService);
800             CloseServiceHandle(schSCManager);
801             return dwPid == SERVICE_RUNNING ? TRUE : FALSE;
802         }
803         else
804             g_bRescanServices = TRUE;
805
806         CloseServiceHandle(schSCManager);
807         return FALSE;
808
809     }
810
811     return FALSE;
812 }
813
814 BOOL FindRunningServices()
815 {
816     int i = 0;
817     DWORD dwPid;
818     BOOL rv = FALSE;
819     while (g_stServices[i].szServiceName != NULL)
820     {    
821         if (!IsServiceRunning(g_stServices[i].szServiceName, &dwPid))
822             dwPid = 0;
823         if (g_stServices[i].dwPid != dwPid)
824             rv = TRUE;
825         g_stServices[i].dwPid = dwPid;
826         ++i;
827     }                        
828     return rv;
829 }
830
831 BOOL GetApacheServicesStatus()
832 {
833
834     CHAR    szKey[MAX_PATH];
835     CHAR    achKey[MAX_PATH];
836     CHAR    szImagePath[MAX_PATH];
837     CHAR    szBuf[MAX_PATH];
838
839     HKEY    hKey, hSubKey;
840     DWORD   retCode, rv, dwKeyType;
841     DWORD   dwBufLen = MAX_PATH;
842     int     i, stPos = 0;
843
844     g_bRescanServices = FALSE;
845
846     retCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
847                             "System\\CurrentControlSet\\Services\\",
848                             0, KEY_READ, &hKey);
849     if (retCode != ERROR_SUCCESS)
850     {
851         ErrorMessage(NULL, FALSE);
852         return FALSE;
853     }
854     am_ClearServicesSt();
855     for (i = 0, retCode = ERROR_SUCCESS; retCode == ERROR_SUCCESS; i++)
856     {
857
858         retCode = RegEnumKey(hKey, i, achKey, MAX_PATH);
859         if (retCode == ERROR_SUCCESS)
860         {
861             lstrcpy(szKey, "System\\CurrentControlSet\\Services\\");
862             lstrcat(szKey, achKey);
863
864             if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, 
865                 KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS)
866             {
867                 dwBufLen = MAX_PATH;
868                 rv = RegQueryValueEx(hSubKey, "ImagePath", NULL,
869                                       &dwKeyType, szImagePath, &dwBufLen);
870
871                 if (rv == ERROR_SUCCESS && (dwKeyType == REG_SZ  || dwKeyType == REG_EXPAND_SZ) && dwBufLen)
872                 {
873                     lstrcpy(szBuf, szImagePath);
874                     CharLower(szBuf);
875                     /* the service name could be Apache*.exe */
876                     if (strstr(szBuf, "\\apache") != NULL && strstr(szBuf, ".exe") &&
877                        (strstr(szBuf, "--ntservice") != NULL || strstr(szBuf, "-k ") !=NULL))
878                     {
879                         g_stServices[stPos].szServiceName = strdup(achKey);
880                         g_stServices[stPos].szImagePath = strdup(szImagePath);
881                         dwBufLen = MAX_PATH;
882                         if (RegQueryValueEx(hSubKey, "Description", NULL,
883                                       &dwKeyType, szBuf, &dwBufLen) == ERROR_SUCCESS)
884                             g_stServices[stPos].szDescription = strdup(szBuf);
885
886                         dwBufLen = MAX_PATH;
887                         if (RegQueryValueEx(hSubKey, "DisplayName", NULL,
888                                       &dwKeyType, szBuf, &dwBufLen) == ERROR_SUCCESS)
889                             g_stServices[stPos].szDisplayName= strdup(szBuf);
890                         ++stPos;
891                         if (stPos >= MAX_APACHE_SERVICES)
892                             retCode = !ERROR_SUCCESS;
893                     }
894                 }
895                 RegCloseKey(hSubKey);
896             }
897         }
898     }
899     RegCloseKey(hKey);
900     FindRunningServices();
901     return TRUE;
902 }
903
904
905 LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
906 {
907
908     CHAR        szBuf[MAX_PATH]; 
909     HWND        hListBox;
910     static      HWND  hStatusBar; 
911     TEXTMETRIC  tm; 
912     int         i, y; 
913     HDC         hdcMem; 
914     RECT        rcBitmap; 
915     UINT        nItem;
916     LPMEASUREITEMSTRUCT lpmis; 
917     LPDRAWITEMSTRUCT    lpdis; 
918
919     ZeroMemory(szBuf, MAX_PATH);
920     switch (message) 
921     { 
922  
923         case WM_INITDIALOG: 
924             ShowWindow(hDlg, SW_HIDE);
925             g_hwndServiceDlg = hDlg;
926             g_hBmpStart = LoadImage(g_hInstance, MAKEINTRESOURCE(IDB_BMPRUN),
927                                     IMAGE_BITMAP, XBITMAP, YBITMAP, LR_DEFAULTCOLOR); 
928             g_hBmpStop  = LoadImage(g_hInstance, MAKEINTRESOURCE(IDB_BMPSTOP), 
929                                     IMAGE_BITMAP, XBITMAP, YBITMAP, LR_DEFAULTCOLOR); 
930
931             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
932             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
933             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
934
935             if (g_dwOSVersion < OS_VERSION_WINNT)
936                 ShowWindow(GetDlgItem(hDlg, IDC_SMANAGER), SW_HIDE);
937
938             hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
939             g_hwndStdoutList = GetDlgItem(hDlg, IDL_STDOUT);
940             hStatusBar = CreateStatusWindow(SBT_TOOLTIPS | WS_CHILD | WS_VISIBLE,
941                                             "", hDlg, IDC_STATBAR);            
942             if (GetApacheServicesStatus())
943             {
944                 i = 0;
945                 while (g_stServices[i].szServiceName != NULL)
946                 {    
947                     addListBoxItem(hListBox, g_stServices[i].szDisplayName, 
948                         g_stServices[i].dwPid == 0 ? g_hBmpStop : g_hBmpStart);
949                     ++i;
950                 }
951             }
952             CenterWindow(hDlg);
953             ShowWindow(hDlg, SW_SHOW);
954             SetFocus(hListBox); 
955             SendMessage(hListBox, LB_SETCURSEL, 0, 0); 
956             return TRUE;
957         break;
958         case WM_UPDATEMESSAGE:
959             hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
960             SendMessage(hListBox, LB_RESETCONTENT, 0, 0); 
961             SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"");
962             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
963             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
964             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
965             i = 0;
966             while (g_stServices[i].szServiceName != NULL)
967             {    
968                 addListBoxItem(hListBox, g_stServices[i].szDisplayName, 
969                     g_stServices[i].dwPid == 0 ? g_hBmpStop : g_hBmpStart);
970                 ++i;
971             }
972             SendMessage(hListBox, LB_SETCURSEL, 0, 0); 
973             /* Dirty hack to bring the window to the foreground */
974             SetWindowPos(hDlg, HWND_TOPMOST, 0, 0, 0, 0,
975                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
976             SetWindowPos(hDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
977                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
978             SetFocus(hListBox); 
979             return TRUE;
980         break;
981         case WM_MEASUREITEM: 
982  
983             lpmis = (LPMEASUREITEMSTRUCT) lParam; 
984             lpmis->itemHeight = YBITMAP; 
985             return TRUE; 
986         case WM_SETCURSOR:
987             if (g_bConsoleRun)
988                 SetCursor(g_hCursorHourglass);
989             else
990                 SetCursor(g_hCursorArrow);
991             return TRUE;
992         case WM_DRAWITEM: 
993             lpdis = (LPDRAWITEMSTRUCT) lParam; 
994             if (lpdis->itemID == -1) 
995             { 
996                 break; 
997             } 
998             switch (lpdis->itemAction) 
999             { 
1000                 case ODA_SELECT: 
1001                 case ODA_DRAWENTIRE: 
1002                     g_hBmpPicture = (HBITMAP)SendMessage(lpdis->hwndItem, 
1003                         LB_GETITEMDATA, lpdis->itemID, (LPARAM) 0); 
1004  
1005                     hdcMem = CreateCompatibleDC(lpdis->hDC); 
1006                     g_hBmpOld = SelectObject(hdcMem, g_hBmpPicture); 
1007  
1008                     BitBlt(lpdis->hDC, 
1009                         lpdis->rcItem.left, lpdis->rcItem.top, 
1010                         lpdis->rcItem.right - lpdis->rcItem.left, 
1011                         lpdis->rcItem.bottom - lpdis->rcItem.top, 
1012                         hdcMem, 0, 0, SRCCOPY); 
1013                     SendMessage(lpdis->hwndItem, LB_GETTEXT, 
1014                         lpdis->itemID, (LPARAM) szBuf); 
1015  
1016                     GetTextMetrics(lpdis->hDC, &tm);  
1017                     y = (lpdis->rcItem.bottom + lpdis->rcItem.top - 
1018                         tm.tmHeight) / 2; 
1019   
1020                     SelectObject(hdcMem, g_hBmpOld); 
1021                     DeleteDC(hdcMem); 
1022  
1023                     rcBitmap.left = lpdis->rcItem.left + XBITMAP + 2; 
1024                     rcBitmap.top = lpdis->rcItem.top; 
1025                     rcBitmap.right = lpdis->rcItem.right; 
1026                     rcBitmap.bottom = lpdis->rcItem.top + YBITMAP; 
1027
1028                     if (lpdis->itemState & ODS_SELECTED) 
1029                     { 
1030                         if (g_hBmpPicture == g_hBmpStop)
1031                         {
1032                             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
1033                             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1034                             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1035                         }
1036                         else if (g_hBmpPicture == g_hBmpStart) 
1037                         {
1038                             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1039                             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
1040                             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
1041                         }
1042                         if (g_stServices[lpdis->itemID].szDescription)
1043                             SendMessage(hStatusBar, SB_SETTEXT, 0, 
1044                                         (LPARAM)g_stServices[lpdis->itemID].szDescription);
1045                         else
1046                             SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"");
1047                         
1048                         SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 
1049                         SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); 
1050                         FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_HIGHLIGHTTEXT)); 
1051                     } 
1052                     else
1053                     {
1054                        SetTextColor(lpdis->hDC, GetSysColor(COLOR_MENUTEXT)); 
1055                        SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW)); 
1056                        FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_WINDOW+1)); 
1057                     }
1058                     TextOut(lpdis->hDC, 
1059                         XBITMAP + 6, 
1060                         y, 
1061                         szBuf, 
1062                         strlen(szBuf)); 
1063                     break; 
1064  
1065                 case ODA_FOCUS: 
1066                     break; 
1067             } 
1068             return TRUE;  
1069         case WM_COMMAND: 
1070             switch (LOWORD(wParam)) 
1071             { 
1072                 case IDL_SERVICES:
1073                     switch (HIWORD(wParam))
1074                     {
1075                         case LBN_DBLCLK:
1076                             /* if started then stop, if stopped then start the service */
1077                             hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1078                             nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1079                             if (nItem != LB_ERR)
1080                             {
1081                                 g_hBmpPicture = (HBITMAP)SendMessage(hListBox, LB_GETITEMDATA,
1082                                                                nItem, (LPARAM) 0); 
1083                                 if (g_hBmpPicture == g_hBmpStop)
1084                                 {
1085                                     ApacheManageService(g_stServices[nItem].szServiceName,
1086                                                 g_stServices[nItem].szImagePath,
1087                                                 SERVICE_CONTROL_CONTINUE);
1088                                 }
1089                                 else
1090                                     ApacheManageService(g_stServices[nItem].szServiceName,
1091                                                 g_stServices[nItem].szImagePath,
1092                                                 SERVICE_CONTROL_STOP);
1093
1094                             }
1095                             return TRUE;
1096                         break;
1097                      }
1098                 break;
1099                 case IDOK: 
1100                     EndDialog(hDlg, TRUE); 
1101                     return TRUE; 
1102                 case IDC_SSTART: 
1103                     Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1104                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1105                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1106                     if (nItem != LB_ERR)
1107                     {
1108                         ApacheManageService(g_stServices[nItem].szServiceName,
1109                                              g_stServices[nItem].szImagePath,
1110                                              SERVICE_CONTROL_CONTINUE);
1111                     }
1112                     Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
1113                     return TRUE;
1114                 case IDC_SSTOP: 
1115                     Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1116                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1117                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1118                     if (nItem != LB_ERR)
1119                     {
1120                         ApacheManageService(g_stServices[nItem].szServiceName,
1121                                              g_stServices[nItem].szImagePath,
1122                                              SERVICE_CONTROL_STOP);
1123                     }
1124                     Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
1125                     return TRUE;
1126                 case IDC_SRESTART: 
1127                     Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1128                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1129                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1130                     if (nItem != LB_ERR)
1131                     {
1132                         ApacheManageService(g_stServices[nItem].szServiceName,
1133                                              g_stServices[nItem].szImagePath,
1134                                              SERVICE_APACHE_RESTART);
1135                     }
1136                     Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
1137                     return TRUE;
1138                 case IDC_SMANAGER: 
1139                     if (g_dwOSVersion >= OS_VERSION_WIN2K)
1140                         ShellExecute(hDlg, "open", "services.msc", "/s", NULL, SW_NORMAL);
1141                     else
1142                         WinExec("Control.exe SrvMgr.cpl Services", SW_NORMAL);
1143                     return TRUE;
1144                 case IDC_SEXIT: 
1145                     EndDialog( hDlg, TRUE);
1146                     SendMessage( g_hwndMain, WM_COMMAND, (WPARAM)IDM_EXIT, 0);
1147                     return TRUE;
1148              }
1149         break;
1150         case WM_SIZE:
1151             switch (LOWORD(wParam)) 
1152             { 
1153                 case SIZE_MINIMIZED:
1154                     EndDialog(hDlg, TRUE); 
1155                     return TRUE; 
1156                 break;
1157             }
1158         break;
1159         case WM_QUIT:
1160         case WM_CLOSE: 
1161             EndDialog(hDlg, TRUE);
1162             return TRUE;
1163         case WM_DESTROY: 
1164             DeleteObject(g_hBmpStart); 
1165             DeleteObject(g_hBmpStop); 
1166             return TRUE; 
1167         default:
1168             return FALSE;
1169     }
1170     return FALSE;
1171 }
1172
1173
1174 LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
1175                           WPARAM wParam, LPARAM lParam)
1176 {
1177     if (message == g_bUiTaskbarCreated)
1178     {
1179         /* restore the tray icon on shell restart */
1180         ShowNotifyIcon(hWnd, NIM_ADD);
1181         return DefWindowProc(hWnd, message, wParam, lParam);
1182     }
1183     switch (message) 
1184     {
1185         case WM_CREATE:
1186             GetApacheServicesStatus();
1187             ShowNotifyIcon(hWnd, NIM_ADD);
1188             SetTimer(hWnd, WM_TIMER_REFRESH, REFRESH_TIME, NULL);
1189             SetTimer(hWnd, WM_TIMER_RESCAN,  RESCAN_TIME, NULL);
1190             g_hwndServiceDlg = NULL;                      
1191             break;
1192         case WM_TIMER:
1193             switch (wParam)
1194             {
1195                 case WM_TIMER_RESCAN:
1196                 {
1197                     int nPrev = 0, nNew = 0;
1198                     EnterCriticalSection(&g_stcSection);
1199                     if (FindRunningServices() || g_bRescanServices)
1200                     {
1201                         ShowNotifyIcon(hWnd, NIM_MODIFY);
1202                         if (g_hwndServiceDlg)
1203                             PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1204                     }
1205                     /* check if services list changed */
1206                     while (g_stServices[nPrev].szServiceName != NULL)
1207                         ++nPrev;
1208                     GetApacheServicesStatus();
1209                     while (g_stServices[nNew].szServiceName != NULL)
1210                         ++nNew;
1211                     if (nPrev != nNew)
1212                     {
1213                         ShowNotifyIcon(hWnd, NIM_MODIFY);
1214                         if (g_hwndServiceDlg)
1215                             PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1216                     }
1217                     LeaveCriticalSection(&g_stcSection);
1218                 break;
1219                 }
1220                 case WM_TIMER_REFRESH:
1221                 {
1222                     int nPrev = 0, nNew = 0;
1223                     EnterCriticalSection(&g_stcSection);
1224                     if (g_bRescanServices)
1225                     {       
1226                         GetApacheServicesStatus();
1227                         ShowNotifyIcon(hWnd, NIM_MODIFY);
1228                         if (g_hwndServiceDlg)
1229                             PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1230                     }
1231                     else if (FindRunningServices())
1232                     {
1233                         ShowNotifyIcon(hWnd, NIM_MODIFY);
1234                         if (g_hwndServiceDlg)
1235                             PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1236                     }
1237                     LeaveCriticalSection(&g_stcSection);
1238                     break;
1239                 }
1240             }
1241             break;
1242         case WM_QUIT:
1243             ShowNotifyIcon(hWnd, NIM_DELETE);
1244             break;
1245         case WM_TRAYMESSAGE:
1246             switch(lParam)
1247             {
1248                 case WM_LBUTTONDBLCLK:
1249                    if (!g_bDlgServiceOn)
1250                    {
1251                        g_bDlgServiceOn = TRUE;
1252                        DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DLGSERVICES),
1253                              hWnd, (DLGPROC)ServiceDlgProc);
1254                        g_bDlgServiceOn = FALSE;
1255                        g_hwndServiceDlg = NULL;
1256                    }
1257                    else if (g_hwndServiceDlg)
1258                    {
1259                        /* Dirty hack to bring the window to the foreground */
1260                        SetWindowPos(g_hwndServiceDlg, HWND_TOPMOST, 0, 0, 0, 0,
1261                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1262                        SetWindowPos(g_hwndServiceDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
1263                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1264                        SetFocus(g_hwndServiceDlg);
1265                    }
1266                 break;
1267                 case WM_LBUTTONUP:
1268                     ShowTryServicesMenu(hWnd);
1269                 break;    
1270                 case WM_RBUTTONUP:
1271                     ShowTryPopupMenu(hWnd);
1272                 break;    
1273             }
1274             break;
1275         case WM_COMMAND:
1276             if ((LOWORD(wParam) & IDM_SM_START) == IDM_SM_START)
1277             {
1278                 ApacheManageService(g_stServices[LOWORD(wParam) - IDM_SM_START].szServiceName,
1279                                     g_stServices[LOWORD(wParam) - IDM_SM_START].szImagePath,
1280                                     SERVICE_CONTROL_CONTINUE);                
1281                 return TRUE;
1282             }
1283             else if ((LOWORD(wParam) & IDM_SM_STOP) == IDM_SM_STOP)
1284             {
1285                 ApacheManageService(g_stServices[LOWORD(wParam) - IDM_SM_STOP].szServiceName,
1286                                     g_stServices[LOWORD(wParam) - IDM_SM_STOP].szImagePath,
1287                                     SERVICE_CONTROL_STOP);                
1288                 return TRUE;
1289             }
1290             else if ((LOWORD(wParam) & IDM_SM_RESTART) == IDM_SM_RESTART)
1291             {
1292                 ApacheManageService(g_stServices[LOWORD(wParam) - IDM_SM_RESTART].szServiceName,
1293                                     g_stServices[LOWORD(wParam) - IDM_SM_RESTART].szImagePath,
1294                                     SERVICE_APACHE_RESTART);                
1295                 return TRUE;
1296             }
1297             switch (LOWORD(wParam))
1298             {
1299                case IDM_RESTORE:
1300                    if (!g_bDlgServiceOn)
1301                    {
1302                        g_bDlgServiceOn = TRUE;
1303                        DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DLGSERVICES),
1304                              hWnd, (DLGPROC)ServiceDlgProc);
1305                        g_bDlgServiceOn = FALSE;
1306                        g_hwndServiceDlg = NULL;
1307                    }
1308                    else if (g_hwndServiceDlg)
1309                        SetFocus(g_hwndServiceDlg);
1310                    break;
1311                 case IDC_SMANAGER: 
1312                     if (g_dwOSVersion >= OS_VERSION_WIN2K)
1313                         ShellExecute(NULL, "open", "services.msc", "/s", NULL, SW_NORMAL);
1314                     else
1315                         WinExec("Control.exe SrvMgr.cpl Services", SW_NORMAL);
1316                     return TRUE;
1317                case IDM_EXIT:
1318                    ShowNotifyIcon(hWnd, NIM_DELETE);
1319                    PostQuitMessage(0);
1320                    return TRUE;
1321             }
1322         default:
1323             return DefWindowProc(hWnd, message, wParam, lParam);
1324     }
1325
1326     return FALSE;
1327 }
1328
1329 /* Create main invisible window */
1330 HWND CreateMainWindow(HINSTANCE hInstance)
1331 {
1332     HWND       hWnd = NULL;
1333     WNDCLASSEX wcex;
1334
1335     if (!GetSystemOSVersion(&g_dwOSVersion))
1336     {
1337         ErrorMessage(NULL, TRUE);
1338         return hWnd;
1339     }
1340
1341     wcex.cbSize = sizeof(WNDCLASSEX); 
1342
1343     wcex.style          = CS_HREDRAW | CS_VREDRAW;
1344     wcex.lpfnWndProc    = (WNDPROC)WndProc;
1345     wcex.cbClsExtra     = 0;
1346     wcex.cbWndExtra     = 0;
1347     wcex.hInstance      = hInstance;
1348     wcex.hIcon          = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_APSRVMON),
1349                                            IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
1350     wcex.hCursor        = g_hCursorArrow;
1351     wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
1352     wcex.lpszMenuName   = 0;
1353     wcex.lpszClassName  = g_szWindowClass;
1354     wcex.hIconSm        = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_APSRVMON),
1355                                            IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1356
1357     if (RegisterClassEx(&wcex))
1358         hWnd = CreateWindow(g_szWindowClass, g_szTitle,
1359                              0, 0, 0, 0, 0,
1360                              NULL, NULL, hInstance, NULL);
1361
1362     return hWnd;
1363
1364 }
1365
1366
1367 int WINAPI WinMain(HINSTANCE hInstance,
1368                     HINSTANCE hPrevInstance,
1369                     LPSTR lpCmdLine,
1370                     int nCmdShow)
1371 {
1372     TCHAR szTmp[MAX_LOADSTRING];
1373     MSG     msg;
1374     /* single instance mutex */
1375     HANDLE hMutex;
1376     int i;
1377
1378     g_LangID = GetUserDefaultLangID();
1379     if ((g_LangID & 0xFF) != LANG_ENGLISH)
1380         g_LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
1381     
1382     for (i = IDS_MSG_FIRST; i <= IDS_MSG_LAST; ++i) {
1383         LoadString(hInstance, i, szTmp, MAX_LOADSTRING);
1384         g_lpMsg[i - IDS_MSG_FIRST] = strdup(szTmp);
1385     }
1386     LoadString(hInstance, IDS_APMONITORTITLE, szTmp, MAX_LOADSTRING);
1387     g_szTitle = strdup(szTmp);
1388     LoadString(hInstance, IDS_APMONITORCLASS, szTmp, MAX_LOADSTRING);
1389     g_szWindowClass = strdup(szTmp);
1390
1391     g_icoStop          = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICOSTOP),
1392                                    IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1393     g_icoRun           = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICORUN),
1394                                    IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1395     g_hCursorHourglass = LoadImage(NULL, MAKEINTRESOURCE(OCR_WAIT), IMAGE_CURSOR,
1396                                    LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED);
1397     g_hCursorArrow     = LoadImage(NULL, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR,
1398                                    LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED);
1399
1400     hMutex = CreateMutex(NULL, FALSE, "APSRVMON_MUTEX");
1401     if((hMutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
1402     {
1403         ErrorMessage(g_lpMsg[IDS_MSG_APPRUNNING-IDS_MSG_FIRST], FALSE);
1404         if (hMutex)
1405             CloseHandle(hMutex);
1406
1407         return 0;
1408     }
1409
1410     ZeroMemory(g_stServices, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
1411     InitCommonControls();
1412     g_hInstance = hInstance;
1413     g_hwndMain = CreateMainWindow(hInstance);
1414     g_bUiTaskbarCreated = RegisterWindowMessage("TaskbarCreated");
1415     InitializeCriticalSection(&g_stcSection);
1416     if (g_hwndMain != NULL)
1417     {
1418         while (GetMessage(&msg, NULL, 0, 0) == TRUE) 
1419         {
1420             TranslateMessage(&msg);
1421             DispatchMessage(&msg);
1422         }    
1423         am_ClearServicesSt();
1424     }
1425     DeleteCriticalSection(&g_stcSection);
1426     CloseHandle(hMutex);
1427     DestroyIcon(g_icoStop);
1428     DestroyIcon(g_icoRun);
1429     DestroyCursor(g_hCursorHourglass);
1430     DestroyCursor(g_hCursorArrow);
1431     return 0;
1432 }