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