]> granicus.if.org Git - apache/blob - support/win32/ApacheMonitor.c
This is a nearly blind commit of an update posted by Mladen Turk just
[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
73 #include <windows.h>
74 #include <windowsx.h>
75 #include <commctrl.h>
76 #include <stdlib.h>
77 #include <stdio.h>
78 #include "ApacheMonitor.h"
79
80
81 #define OS_VERSION_WINNT    1
82 #define OS_VERSION_WIN9X    2
83 #define OS_VERSION_WIN2K    3
84 /* Should be enough */
85 #define MAX_APACHE_SERVICES 128
86
87 #define WM_TRAYMESSAGE         (WM_APP+1)
88 #define WM_UPDATEMESSAGE       (WM_USER+1)
89 #define WM_TIMER_REFRESH       10
90 #define WM_TIMER_RESCAN        11
91 #define SERVICE_APACHE_RESTART 128
92 #define XBITMAP                16
93 #define YBITMAP                16 
94 #define MAX_LOADSTRING         100
95 #define REFRESH_TIME           1000           /* service refresh time (ms) */
96 #define RESCAN_TIME            10000          /* registry rescan time (ms) */
97
98 typedef struct _st_APACHE_SERVICE
99 {
100     LPSTR    szServiceName;
101     LPSTR    szDisplayName;
102     LPSTR    szDescription;
103     LPSTR    szImagePath;
104     DWORD    dwPid;
105 } ST_APACHE_SERVICE;
106
107 /* Global variables */
108 HINSTANCE         ap_hInstance = NULL;
109 HWND              ap_hwndAboutDlg = NULL;
110 TCHAR             szTitle[MAX_LOADSTRING];          /* The title bar text */
111 TCHAR             szWindowClass[MAX_LOADSTRING];    /* Window Class Name  */
112 HICON             ap_icoStop;
113 HICON             ap_icoRun;
114 UINT              ap_uiTaskbarCreated;
115 DWORD             ap_OSVersion;
116 BOOL              dlgAboutOn = FALSE;
117 BOOL              dlgServiceOn = FALSE;
118 BOOL              ap_consoleRun = FALSE;
119 ST_APACHE_SERVICE ap_stServices[MAX_APACHE_SERVICES];
120
121 HBITMAP           hbmpStart, hbmpStop; 
122 HBITMAP           hbmpPicture, hbmpOld; 
123 BOOL              ap_rescanServices;
124 HWND              ap_hServiceDlg;
125 HWND              ap_hMainWnd;
126 HWND              ap_hStdoutWnd;
127 HCURSOR           ap_cHourglass;
128 HCURSOR           ap_cArrow;
129
130 HANDLE            h_stdOutR;
131 HANDLE            h_stdOutW;
132 HANDLE            h_stdInR;
133 HANDLE            h_stdInW;
134 HANDLE            h_stdErr;
135 PROCESS_INFORMATION ap_redirectedPI;
136
137 void ap_ClearServicesSt()
138 {
139     int i;
140     for (i = 0; i < MAX_APACHE_SERVICES; i++)
141     {
142         if (ap_stServices[i].szServiceName)
143             free(ap_stServices[i].szServiceName);
144         if (ap_stServices[i].szDisplayName)
145             free(ap_stServices[i].szDisplayName);
146         if (ap_stServices[i].szDescription)
147             free(ap_stServices[i].szDescription);
148         if (ap_stServices[i].szImagePath)
149             free(ap_stServices[i].szImagePath);
150
151     }
152     ZeroMemory(ap_stServices, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
153
154 }
155
156 void ErrorMessage(DWORD dwError)
157 {
158     LPVOID lpMsgBuf;
159     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
160                   FORMAT_MESSAGE_FROM_SYSTEM |
161                   FORMAT_MESSAGE_IGNORE_INSERTS,
162                   NULL,
163                   dwError == ERROR_SUCCESS ? GetLastError() : dwError,
164                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
165                   (LPTSTR) &lpMsgBuf, 0, NULL);
166     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONERROR);
167     LocalFree(lpMsgBuf);
168
169 }
170
171 LPTSTR GetStringRes(int id)
172 {
173   static TCHAR buffer[MAX_PATH];
174
175   buffer[0] = 0;
176   LoadString(GetModuleHandle (NULL), id, buffer, MAX_PATH);
177   return buffer;
178 }
179
180 BOOL GetSystemOSVersion(LPSTR szVersion, LPDWORD dwVersion)
181 {
182     OSVERSIONINFOEX osvi;
183     BOOL    bOsVersionInfoEx;
184     char    szBuff[256];
185     HKEY    hKey;
186     char    szProductType[80];
187     DWORD   dwBufLen;
188     
189     /* 
190     Try calling GetVersionEx using the OSVERSIONINFOEX structure.
191     If that fails, try using the OSVERSIONINFO structure.
192     */
193     ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
194     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
195     
196     if (!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi)))
197     {
198         /* If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. */        
199         osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
200         if (!GetVersionEx((OSVERSIONINFO *) &osvi)) 
201             return FALSE;
202     }
203     
204     switch (osvi.dwPlatformId)
205     {
206     case VER_PLATFORM_WIN32_NT:        
207         /* Test for the product. */        
208         if (szVersion!= NULL)
209         {
210             if (osvi.dwMajorVersion <= 4)
211                 strcpy(szVersion, "MS Windows NT ");
212             else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
213                 strcpy(szVersion, "MS Windows 2000 ");
214             else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
215                 strcpy(szVersion, "Whistler ");
216             /* Test for product type.*/            
217 #ifdef VER_VORKSTATION_NT
218             if (bOsVersionInfoEx)
219             {
220                 if (osvi.wProductType == VER_NT_WORKSTATION)
221                 {
222 #ifdef VER_SUITE_PERSONAL
223                     if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
224                         strcat(szVersion, "Personal ");
225                     else
226 #endif
227                     strcat(szVersion, "Professional ");
228                 }                
229                 else if (osvi.wProductType == VER_NT_SERVER)
230                 {
231                     if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
232                         strcat(szVersion, "DataCenter Server ");
233                     else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
234                         strcat(szVersion, "Advanced Server ");
235                     else
236                         strcat(szVersion, "Server ");
237                 }
238             }
239             else
240             {
241 #endif                
242                 RegOpenKeyEx(HKEY_LOCAL_MACHINE,
243                     "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
244                     0, KEY_QUERY_VALUE, &hKey);
245                 RegQueryValueEx(hKey, "ProductType", NULL, NULL,
246                     (LPBYTE) szProductType, &dwBufLen);
247                 RegCloseKey(hKey);
248                 if (lstrcmpi("WINNT", szProductType) == 0)
249                     strcat(szVersion, "Workstation ");
250                 if (lstrcmpi("SERVERNT", szProductType) == 0)
251                     strcat(szVersion, "Server ");
252 #ifdef VER_VORKSTATION_NT
253             }            
254 #endif
255             /* Get version, service pack (if any), and build number. */
256             if (osvi.dwMajorVersion <= 4)
257             {
258                 sprintf(szBuff, "version %d.%d %s (Build-%d)\n",
259                         osvi.dwMajorVersion,
260                         osvi.dwMinorVersion,
261                         osvi.szCSDVersion,
262                         osvi.dwBuildNumber & 0xFFFF);
263             }
264             else
265             { 
266                 sprintf(szBuff, "%s (Build-%d)\n",
267                     osvi.szCSDVersion,
268                     osvi.dwBuildNumber & 0xFFFF);
269             }
270             strcat(szVersion, szBuff);
271         }
272         else if (dwVersion != NULL)
273         {
274             if (osvi.dwMajorVersion <= 4)
275                 *dwVersion = OS_VERSION_WINNT;
276             else if (osvi.dwMajorVersion == 5)
277                 *dwVersion = OS_VERSION_WIN2K;
278             else
279                 return FALSE;
280             
281         }
282         break;
283         
284     case VER_PLATFORM_WIN32_WINDOWS:
285         if (szVersion != NULL)
286         {
287             if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
288             {
289                 strcpy(szVersion, "MS Windows 95 ");
290                 if (osvi.szCSDVersion[1] == 'C')
291                     strcat(szVersion, "OSR2 ");
292             } 
293             
294             if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
295             {
296                 strcpy(szVersion, "MS Windows 98 ");
297                 if (osvi.szCSDVersion[1] == 'A')
298                     strcat(szVersion, "SE ");
299             } 
300             
301             if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
302             {
303                 strcpy(szVersion, "MS Windows Me ");
304             }
305         }
306         if (dwVersion != NULL)
307             *dwVersion = OS_VERSION_WIN9X;
308         
309         break;
310         
311     case VER_PLATFORM_WIN32s:
312         if (szVersion != NULL)
313             strcpy(szVersion, "Microsoft Win32s ");
314         if (dwVersion != NULL)
315             *dwVersion = OS_VERSION_WIN9X;
316         break;
317     default:
318         return FALSE;
319         break;
320    }
321    return TRUE; 
322 }
323
324 static VOID ShowNotifyIcon(HWND hWnd, DWORD dwMessage)
325 {
326     
327     NOTIFYICONDATA nid;
328     int  i = 0, n = 0;
329
330     ZeroMemory(&nid,sizeof(nid));
331     nid.cbSize = sizeof(NOTIFYICONDATA);
332     nid.hWnd = hWnd;
333     nid.uID = 0xFF;
334     nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
335     nid.uCallbackMessage = WM_TRAYMESSAGE;
336     
337     while (ap_stServices[i].szServiceName != NULL)
338     {    
339         if (ap_stServices[i].dwPid != 0)
340             ++n;
341         ++i;
342     }
343     if (dwMessage != NIM_DELETE)
344     {
345         if (n)
346             nid.hIcon = ap_icoRun;
347         else
348             nid.hIcon = ap_icoStop;
349     }
350     else
351         nid.hIcon = NULL;
352     if (n == i)
353         lstrcpy(nid.szTip, "Running all Apache services");
354     else if (n)
355         sprintf(nid.szTip, "Running %d from %d Apache services", n, i);
356     else
357         sprintf(nid.szTip, "Running none from %d Apache services", n, i);
358
359     Shell_NotifyIcon(dwMessage, &nid);
360     
361 }
362
363 void appendMenuItem(HMENU hMenu, UINT uMenuId, LPSTR szName, BOOL fDefault)
364 {
365     MENUITEMINFO mii;
366     
367     ZeroMemory(&mii, sizeof(MENUITEMINFO));
368     mii.cbSize = sizeof(MENUITEMINFO);
369     mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
370     if (lstrlen(szName))
371     {
372         mii.fType = MFT_STRING;
373         mii.wID = uMenuId;
374         if (fDefault)
375             mii.fState = MFS_DEFAULT;
376         mii.dwTypeData = szName;
377     }
378     else
379         mii.fType = MFT_SEPARATOR;
380     InsertMenuItem(hMenu, uMenuId, FALSE, &mii);
381 }
382
383 void ShowTryPopupMenu(HWND hWnd)
384 {
385     /* create popup menu */
386     HMENU hMenu = CreatePopupMenu();
387     POINT pt;
388
389     if (hMenu)
390     {
391         appendMenuItem(hMenu,  IDM_ABOUT, "&About...", FALSE);
392         appendMenuItem(hMenu,  IDM_RESTORE, "&Show Services...", TRUE);
393         appendMenuItem(hMenu,  0, "", FALSE);
394         appendMenuItem(hMenu,  IDM_EXIT,  "&Exit...", FALSE);
395
396         GetCursorPos(&pt);
397         SetForegroundWindow(NULL);
398         TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, 0, hWnd, NULL);
399     }
400 }
401
402 BOOL CenterWindow(HWND hwndChild)
403 {
404    RECT    rChild, rWorkArea;
405    int     wChild, hChild;
406    int     xNew, yNew;
407    BOOL    bResult;
408
409    /* Get the Height and Width of the child window */
410    GetWindowRect(hwndChild, &rChild);
411    wChild = rChild.right - rChild.left;
412    hChild = rChild.bottom - rChild.top;
413
414    /* Get the limits of the 'workarea' */
415    bResult = SystemParametersInfo(
416       SPI_GETWORKAREA,
417       sizeof(RECT),
418       &rWorkArea,
419       0);
420    if (!bResult) {
421       rWorkArea.left = rWorkArea.top = 0;
422       rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
423       rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
424    }
425
426    /* Calculate new X and Y position*/
427    xNew = (rWorkArea.right - wChild)/2;
428    yNew = (rWorkArea.bottom - hChild)/2;
429    return SetWindowPos (hwndChild, HWND_TOP, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
430 }
431
432 static void addItem(HWND hDlg, LPSTR lpStr, HBITMAP hBmp) 
433
434     int nItem; 
435  
436     nItem = SendMessage(hDlg, LB_ADDSTRING, 0, (LPARAM)lpStr); 
437     SendMessage(hDlg, LB_SETITEMDATA, nItem, (LPARAM)hBmp); 
438
439
440 static DWORD WINAPI ConsoleOutputThread(LPVOID lpThreadParameter)
441 {
442     static BYTE lpBuffer[513];
443     LPSTR lpBuf = lpBuffer;
444     BYTE  ch;
445     DWORD dwReaded;
446
447     while (ReadFile(h_stdOutR, &ch, 1, &dwReaded, NULL) == TRUE) 
448     {
449         if (dwReaded > 0) 
450         {
451             if (ch == '\n') 
452             {
453                 *lpBuf = '\0';
454                 ListBox_SetCurSel(ap_hStdoutWnd,
455                                   ListBox_AddString(ap_hStdoutWnd, lpBuffer));
456                 lpBuf = lpBuffer;
457             } 
458             else if (ch == '\t') 
459             {
460                 int i, t;
461                 t = ((int)lpBuf - (int)lpBuffer) % 8;
462                 for (i = 0; i < 8 - t; ++i)
463                     *lpBuf++ = ' ';
464             }
465             else if (ch != '\r')
466                 *lpBuf++ = ch;
467         }
468     }
469     CloseHandle(h_stdInW);
470     CloseHandle(h_stdOutR);
471     CloseHandle(h_stdErr);
472     return 0;
473 }
474
475
476 DWORD WINAPI ConsoleWaitingThread(LPVOID lpThreadParameter)
477 {
478     WaitForSingleObject(ap_redirectedPI.hThread, INFINITE);
479     CloseHandle(ap_redirectedPI.hThread);
480     MessageBeep(100);
481     ap_consoleRun = FALSE;
482     SetCursor(ap_cArrow);
483     return 0;
484 }
485
486
487 BOOL RunRedirectedConsole(LPTSTR szCmdLine, LPDWORD nRetValue)
488 {
489     
490     DWORD  dwThreadId;
491     HANDLE hProc;
492     STARTUPINFO stInfo;
493     BOOL bResult;
494     ZeroMemory(&stInfo, sizeof(stInfo));
495     stInfo.cb = sizeof(stInfo);
496     stInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
497     stInfo.wShowWindow = SW_HIDE;
498     
499     hProc = GetCurrentProcess();
500
501     if (!CreatePipe(&h_stdInR, &h_stdInW, NULL, MAX_PATH))
502         ErrorMessage(ERROR_SUCCESS);
503     if (!CreatePipe(&h_stdOutR, &h_stdOutW, NULL, MAX_PATH*8))
504         ErrorMessage(ERROR_SUCCESS);
505         
506     DuplicateHandle(hProc, h_stdInR, hProc, &h_stdInR, 0, TRUE, 
507                     DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
508     DuplicateHandle(hProc, h_stdOutW, hProc, &h_stdOutW, 0, TRUE, 
509                     DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
510     DuplicateHandle(hProc, h_stdOutW, hProc, &h_stdErr, 0, TRUE, 
511                     DUPLICATE_SAME_ACCESS);
512     
513     stInfo.hStdInput  = h_stdInR;
514     stInfo.hStdOutput = h_stdOutW;
515     stInfo.hStdError  = h_stdErr;
516
517     bResult = CreateProcess(NULL,
518         szCmdLine,
519         NULL,
520         NULL,
521         TRUE,
522         CREATE_SUSPENDED,
523         NULL,
524         NULL ,
525         &stInfo,
526         &ap_redirectedPI);
527
528
529     CloseHandle(h_stdInR);
530     CloseHandle(h_stdOutW);
531     CloseHandle(h_stdErr);
532
533     if (!bResult)
534     {     
535         if (nRetValue)
536             *nRetValue = GetLastError();
537         CloseHandle(h_stdInW);
538         CloseHandle(h_stdOutR);
539         CloseHandle(h_stdErr);
540         return FALSE;
541     }
542
543     CloseHandle(CreateThread(NULL, 0, ConsoleOutputThread, 0, 0, &dwThreadId));
544     ResumeThread(ap_redirectedPI.hThread);
545     CloseHandle(CreateThread(NULL, 0, ConsoleWaitingThread, 0, 0, &dwThreadId));
546
547     return TRUE;
548 }
549
550 BOOL RunAndForgetConsole(LPTSTR szCmdLine,
551                          LPDWORD nRetValue,
552                          BOOL  bRedirectConsole)
553 {
554         
555     STARTUPINFO stInfo;
556     PROCESS_INFORMATION prInfo;
557     BOOL bResult;
558     
559     if (bRedirectConsole)
560         return RunRedirectedConsole(szCmdLine, nRetValue);
561
562     
563     ZeroMemory(&stInfo, sizeof(stInfo));
564     stInfo.cb = sizeof(stInfo);
565     stInfo.dwFlags = STARTF_USESHOWWINDOW;
566     stInfo.wShowWindow = SW_HIDE;
567
568     bResult = CreateProcess(NULL,
569         szCmdLine,
570         NULL,
571         NULL,
572         TRUE,
573         CREATE_NEW_CONSOLE,
574         NULL,
575         NULL ,
576         &stInfo,
577         &prInfo);
578
579     if (!bResult)
580     {     
581         if (nRetValue)
582             *nRetValue = GetLastError();
583         return FALSE;
584     }
585     if (ap_OSVersion == OS_VERSION_WIN9X) /* give some time to rescan the status */
586         Sleep(2000);
587     CloseHandle(prInfo.hThread);
588     CloseHandle(prInfo.hProcess);
589     return TRUE;
590 }
591
592 BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, DWORD dwCommand)
593 {
594     
595     CHAR      szBuf[MAX_PATH];
596     CHAR      szMsg[MAX_PATH];
597     LPSTR     sPos;
598     DWORD     retCode;
599     BOOL      retValue;
600     BOOL      serviceFlag = TRUE;
601     SC_HANDLE schService;
602     SC_HANDLE schSCManager;    
603     SERVICE_STATUS schSStatus;
604     LPSTR     *args;
605     int       ticks;
606
607     if (ap_OSVersion == OS_VERSION_WIN9X)
608     {
609         sPos = strstr(szImagePath, "-k start");
610         if (sPos)
611         {
612             lstrcpyn(szBuf, szImagePath, sPos - szImagePath);
613             switch (dwCommand)
614             {
615             case SERVICE_CONTROL_STOP:
616                 lstrcat(szBuf, " -k stop -n ");
617                 break;
618             case SERVICE_CONTROL_CONTINUE:
619                 sprintf(szMsg, "The %s is starting.", szServiceName);
620                 ListBox_SetCurSel(ap_hStdoutWnd,
621                                    ListBox_AddString(ap_hStdoutWnd, szMsg));
622                 lstrcat(szBuf, " -k start -n ");
623                 serviceFlag = FALSE;
624                 break;
625             case SERVICE_APACHE_RESTART:
626                 lstrcat(szBuf, " -k restart -n ");
627                 break;
628             default:
629                 return FALSE;
630             }
631             lstrcat(szBuf, szServiceName);
632         }
633         else
634             return FALSE;
635         ap_consoleRun = TRUE;
636         SetCursor(ap_cHourglass);
637         if (!RunAndForgetConsole(szBuf, &retCode, serviceFlag))
638         {
639             ErrorMessage(retCode);
640             ap_consoleRun = FALSE;
641             SetCursor(ap_cArrow);
642             return FALSE;
643         }
644         else if (!serviceFlag)
645         {
646             sprintf(szMsg, "The %s has started.", szServiceName);
647             ListBox_SetCurSel(ap_hStdoutWnd,
648                               ListBox_AddString(ap_hStdoutWnd, szMsg));
649
650             ap_consoleRun = FALSE;
651             SetCursor(ap_cArrow);
652             return TRUE;
653         }
654     }
655     else
656     {
657         /* Apache 2.0 uses '-k runservice' as cmdline parameter */
658         sPos = strstr(szImagePath, "--ntservice");
659         if (!sPos)
660         {
661             sPos = strstr(szImagePath, "-k runservice");
662             serviceFlag = FALSE;
663         }
664         if (sPos)
665             lstrcpyn(szBuf, szImagePath, sPos - szImagePath);
666         else
667             return FALSE;
668         schSCManager = OpenSCManager(
669             NULL,
670             NULL,
671             SC_MANAGER_ALL_ACCESS
672            );
673         if (!schSCManager)
674             return FALSE;
675         
676         schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);
677         if (schService != NULL)
678         {
679             retValue = FALSE;
680             ap_consoleRun = TRUE;
681             SetCursor(ap_cHourglass);
682             switch (dwCommand)
683             {
684                 case SERVICE_CONTROL_STOP:
685                     sprintf(szMsg, "The %s is stopping.", szServiceName);
686                     ListBox_SetCurSel(ap_hStdoutWnd,
687                                       ListBox_AddString(ap_hStdoutWnd, szMsg));
688                     if(ControlService(schService, SERVICE_CONTROL_STOP, &schSStatus)) 
689                     {
690                         Sleep(1000);
691                         while (QueryServiceStatus(schService, &schSStatus)) 
692                         {
693                             if (schSStatus.dwCurrentState == SERVICE_STOP_PENDING)
694                                 Sleep(1000);
695                             else
696                                 break;
697                         }
698                     }
699                     if (QueryServiceStatus(schService, &schSStatus))
700                     {
701                         if(schSStatus.dwCurrentState == SERVICE_STOPPED)
702                         {
703                             retValue = TRUE;
704                             sprintf(szMsg, "The %s has stopped.", szServiceName);
705                             ListBox_SetCurSel(ap_hStdoutWnd,
706                                               ListBox_AddString(ap_hStdoutWnd, szMsg));
707                         }
708                     }
709                 break;                
710                 case SERVICE_CONTROL_CONTINUE:
711                     sprintf(szMsg, "The %s is starting.", szServiceName);
712                     ListBox_SetCurSel(ap_hStdoutWnd,
713                                       ListBox_AddString(ap_hStdoutWnd, szMsg));
714                     args = (char **)malloc(3 * sizeof(char*));
715                     args[0] = szBuf;
716                     if (serviceFlag)
717                         args[1] = "--ntservice";
718                     else
719                     {
720                         args[1] = "-k";
721                         args[2] = "runservice";
722                     }
723                     if(StartService(schService, serviceFlag ? 2 : 3, args)) 
724                     {
725                         Sleep(1000);
726                         while (QueryServiceStatus(schService, &schSStatus)) 
727                         {
728                             if (schSStatus.dwCurrentState == SERVICE_START_PENDING)
729                                 Sleep(1000);
730                             else
731                                 break;
732                         }
733                     }
734                     if (QueryServiceStatus(schService, &schSStatus))
735                     {
736                         if(schSStatus.dwCurrentState == SERVICE_RUNNING)
737                         {
738                             retValue = TRUE;
739                             sprintf(szMsg, "The %s has started.", szServiceName);
740                             ListBox_SetCurSel(ap_hStdoutWnd,
741                                               ListBox_AddString(ap_hStdoutWnd, szMsg));
742                         }
743                     }
744                     /* is this OK to do? */
745                     free(args);
746                 break;                
747                 case SERVICE_APACHE_RESTART:
748                     sprintf(szMsg, "The %s is restarting.", szServiceName);
749                     ListBox_SetCurSel(ap_hStdoutWnd,
750                                       ListBox_AddString(ap_hStdoutWnd, szMsg));
751                     if(ControlService(schService, SERVICE_APACHE_RESTART, &schSStatus)) 
752                     {
753                         ticks = 60;
754                         while(schSStatus.dwCurrentState == SERVICE_START_PENDING) 
755                         {
756                             Sleep(1000);
757                             if(!QueryServiceStatus(schService, &schSStatus))
758                             {
759                                 CloseServiceHandle(schService);
760                                 CloseServiceHandle(schSCManager);
761                                 ap_consoleRun = FALSE;
762                                 SetCursor(ap_cArrow);
763                                 return FALSE;
764                             }
765                             if (!--ticks)
766                                 break;
767                         }
768                     }
769                     if(schSStatus.dwCurrentState == SERVICE_RUNNING)
770                     {
771                         retValue = TRUE;
772                         sprintf(szMsg, "The %s has restarted.", szServiceName);
773                         ListBox_SetCurSel(ap_hStdoutWnd,
774                                           ListBox_AddString(ap_hStdoutWnd, szMsg));
775                     }
776                 break;                
777             }
778             CloseServiceHandle(schService);
779             CloseServiceHandle(schSCManager);
780             if (!retValue)
781                 ErrorMessage(ERROR_SUCCESS);
782             ap_consoleRun = FALSE;
783             SetCursor(ap_cArrow);
784             return retValue;
785             
786         }
787         else
788             ap_rescanServices = TRUE;
789         
790         CloseServiceHandle(schSCManager);
791         return FALSE;
792     }
793     
794     return FALSE;
795 }
796
797 BOOL IsServiceRunning(LPCSTR szServiceName, LPDWORD lpdwPid)
798 {
799
800     DWORD                   dwPid;
801     HWND                    hWnd;
802     SC_HANDLE               schService;
803     SC_HANDLE               schSCManager;    
804     SERVICE_STATUS          schSStatus;
805
806     if (ap_OSVersion == OS_VERSION_WIN9X)
807     {
808         hWnd = FindWindow("ApacheWin95ServiceMonitor", szServiceName);
809         if (hWnd && GetWindowThreadProcessId(hWnd, &dwPid))
810         {
811             *lpdwPid = 1;
812             return TRUE;
813         }
814         else
815             return FALSE;
816     }
817     else
818     {
819
820         dwPid = 0;
821         schSCManager = OpenSCManager(
822                             NULL,
823                             NULL,
824                             SC_MANAGER_ALL_ACCESS
825                            );
826         if (!schSCManager)
827             return FALSE;
828
829         schService = OpenService(schSCManager, szServiceName, SERVICE_QUERY_STATUS);
830         if (schService != NULL)
831         {
832             if (QueryServiceStatus(schService, &schSStatus))
833             {
834                 
835                 dwPid = schSStatus.dwCurrentState;
836                 if (lpdwPid)
837                     *lpdwPid = 1;
838             }
839             CloseServiceHandle(schService);
840             CloseServiceHandle(schSCManager);
841             return dwPid == SERVICE_RUNNING ? TRUE : FALSE;
842         }
843         else
844             ap_rescanServices = TRUE;
845
846         CloseServiceHandle(schSCManager);
847         return FALSE;
848
849     }
850
851     return FALSE;
852 }
853
854 BOOL FindRunningServices()
855 {
856     int i = 0;
857     DWORD dwPid;
858     BOOL rv = FALSE;
859     while (ap_stServices[i].szServiceName != NULL)
860     {    
861         if (!IsServiceRunning(ap_stServices[i].szServiceName, &dwPid))
862             dwPid = 0;
863         if (ap_stServices[i].dwPid != dwPid)
864             rv = TRUE;
865         ap_stServices[i].dwPid = dwPid;
866         ++i;
867     }                        
868     return rv;
869 }
870
871 BOOL GetApacheServicesStatus()
872 {
873
874     CHAR    szKey[MAX_PATH];
875     CHAR    achKey[MAX_PATH];
876     CHAR    szImagePath[MAX_PATH];
877     CHAR    szBuf[MAX_PATH];
878
879     HKEY    hKey, hSubKey;
880     DWORD   retCode, rv, dwKeyType;
881     DWORD   dwBufLen = MAX_PATH;
882     int     i, stPos = 0;
883
884     ap_rescanServices = FALSE;
885
886     retCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
887                             "System\\CurrentControlSet\\Services\\",
888                             0, KEY_READ, &hKey);
889     if (retCode != ERROR_SUCCESS)
890     {
891         ErrorMessage(retCode);
892         return FALSE;
893     }
894     ap_ClearServicesSt();
895     for (i = 0, retCode = ERROR_SUCCESS; retCode == ERROR_SUCCESS; i++)
896     {
897
898         retCode = RegEnumKey(hKey, i, achKey, MAX_PATH);
899         if (retCode == ERROR_SUCCESS)
900         {
901             lstrcpy(szKey, "System\\CurrentControlSet\\Services\\");
902             lstrcat(szKey, achKey);
903
904             if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, 
905                 KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS)
906             {
907                 dwBufLen = MAX_PATH;
908                 rv = RegQueryValueEx(hSubKey, "ImagePath", NULL,
909                                       &dwKeyType, szImagePath, &dwBufLen);
910
911                 if (rv == ERROR_SUCCESS && (dwKeyType == REG_SZ  || dwKeyType == REG_EXPAND_SZ) && dwBufLen)
912                 {
913                     lstrcpy(szBuf, szImagePath);
914                     CharLower(szBuf);
915                     if (strstr(szBuf, "\\apache.exe") != NULL)
916                     {
917                         ap_stServices[stPos].szServiceName = strdup(achKey);
918                         ap_stServices[stPos].szImagePath = strdup(szImagePath);
919                         dwBufLen = MAX_PATH;
920                         if (RegQueryValueEx(hSubKey, "Description", NULL,
921                                       &dwKeyType, szBuf, &dwBufLen) == ERROR_SUCCESS)
922                             ap_stServices[stPos].szDescription = strdup(szBuf);
923
924                         dwBufLen = MAX_PATH;
925                         if (RegQueryValueEx(hSubKey, "DisplayName", NULL,
926                                       &dwKeyType, szBuf, &dwBufLen) == ERROR_SUCCESS)
927                             ap_stServices[stPos].szDisplayName= strdup(szBuf);
928                         ++stPos;
929                         if (stPos >= MAX_APACHE_SERVICES)
930                             retCode = !ERROR_SUCCESS;
931                     }
932                 }
933                 RegCloseKey(hSubKey);
934             }
935         }
936     }
937     RegCloseKey(hKey);
938     FindRunningServices();
939     return TRUE;
940 }
941
942 LRESULT CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
943 {
944     static  HFONT hfontDlg;    /* Font for dialog text */
945     static  HFONT hFinePrint;  /* Font for 'fine print' in dialog */
946     DWORD   dwVerInfoSize;     /* Size of version information block */
947     LPSTR   lpVersion;         /* String pointer to 'version' text */
948     DWORD   dwVerHnd=0;        /* An 'ignored' parameter, always '0' */
949     UINT    uVersionLen;
950     WORD    wRootLen;
951     BOOL    bRetCode;
952     int     i;
953     char    szFullPath[256];
954     char    szResult[256];
955     char    szGetName[256];
956     char    szVersion[256];
957     DWORD   dwResult;
958     
959     switch (message) {
960     case WM_INITDIALOG:
961         ShowWindow(hDlg, SW_HIDE);
962         ap_hwndAboutDlg = hDlg;
963         
964         hfontDlg = CreateFont(13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
965             VARIABLE_PITCH | FF_SWISS, "");
966         hFinePrint = CreateFont(11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
967             VARIABLE_PITCH | FF_SWISS, "");
968
969         CenterWindow(hDlg);
970         GetModuleFileName(ap_hInstance, szFullPath, sizeof(szFullPath));
971         
972         /* Now lets dive in and pull out the version information: */
973         dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwVerHnd);
974         if (dwVerInfoSize) {
975             LPSTR   lpstrVffInfo;
976             HANDLE  hMem;
977             hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
978             lpstrVffInfo  = GlobalLock(hMem);
979             GetFileVersionInfo(szFullPath, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
980             lstrcpy(szGetName, GetStringRes(IDS_VER_INFO_LANG));
981             
982             wRootLen = lstrlen(szGetName); /* Save this position */
983             
984             /* Set the title of the dialog: */
985             lstrcat(szGetName, "ProductName");
986             bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
987                 (LPSTR)szGetName,
988                 (LPVOID)&lpVersion,
989                 (UINT *)&uVersionLen);
990             
991             /* Notice order of version and string... */
992             lstrcpy(szResult, "About ");
993             lstrcat(szResult, lpVersion);
994             
995             SetWindowText(hDlg, szResult);
996             
997             /* Walk through the dialog items that we want to replace: */
998             for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++) {
999                 GetDlgItemText(hDlg, i, szResult, sizeof(szResult));
1000                 szGetName[wRootLen] = (char)0;
1001                 lstrcat(szGetName, szResult);
1002                 uVersionLen   = 0;
1003                 lpVersion     = NULL;
1004                 bRetCode      =  VerQueryValue((LPVOID)lpstrVffInfo,
1005                     (LPSTR)szGetName,
1006                     (LPVOID)&lpVersion,
1007                     (UINT *)&uVersionLen);
1008                 
1009                 if (bRetCode && uVersionLen && lpVersion) {
1010                     /* Replace dialog item text with version info */
1011                     lstrcpy(szResult, lpVersion);
1012                     SetDlgItemText(hDlg, i, szResult);
1013                 }
1014                 else
1015                 {
1016                     dwResult = GetLastError();
1017                     
1018                     wsprintf(szResult, GetStringRes(IDS_VERSION_ERROR), dwResult);
1019                     SetDlgItemText(hDlg, i, szResult);
1020                 }
1021                 SendMessage(GetDlgItem(hDlg, i), WM_SETFONT,
1022                     (UINT)((i==DLG_VERLAST)?hFinePrint:hfontDlg),
1023                     TRUE);
1024             }
1025             
1026             
1027             GlobalUnlock(hMem);
1028             GlobalFree(hMem);
1029             
1030         } 
1031         
1032         SendMessage(GetDlgItem(hDlg, IDC_LABEL), WM_SETFONT,
1033             (WPARAM)hfontDlg,(LPARAM)TRUE);
1034         if (!GetSystemOSVersion(szVersion, NULL))
1035             strcpy(szVersion, "Unknown Version");
1036         SetWindowText(GetDlgItem(hDlg, IDC_OSVERSION), szVersion);
1037         ShowWindow(hDlg, SW_SHOW);
1038         return (TRUE);
1039         
1040       case WM_COMMAND:
1041           if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
1042               EndDialog(hDlg, TRUE);
1043               DeleteObject(hfontDlg);
1044               DeleteObject(hFinePrint);
1045               return (TRUE);
1046           }
1047           break;
1048    }
1049    
1050    return FALSE;
1051 }
1052
1053 LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1054 {
1055
1056     CHAR        tchBuffer[MAX_PATH]; 
1057     CHAR        tsbBuffer[MAX_PATH];
1058     HWND        hListBox;
1059     static HWND hStatusBar; 
1060     TEXTMETRIC  tm; 
1061     int         i, y; 
1062     HDC         hdcMem; 
1063     RECT        rcBitmap; 
1064     UINT        nItem;
1065     LPMEASUREITEMSTRUCT lpmis; 
1066     LPDRAWITEMSTRUCT    lpdis; 
1067
1068     ZeroMemory(tchBuffer, MAX_PATH);
1069     ZeroMemory(tsbBuffer, MAX_PATH);
1070     switch (message) 
1071     { 
1072  
1073         case WM_INITDIALOG: 
1074             ShowWindow(hDlg, SW_HIDE);
1075             ap_hServiceDlg = hDlg;
1076             hbmpStart = LoadBitmap(ap_hInstance, MAKEINTRESOURCE(IDB_BMPRUN)); 
1077             hbmpStop  = LoadBitmap(ap_hInstance, MAKEINTRESOURCE(IDB_BMPSTOP)); 
1078
1079             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1080             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1081             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1082             hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1083             ap_hStdoutWnd = GetDlgItem(hDlg, IDL_STDOUT);
1084             hStatusBar = CreateStatusWindow(SBT_TOOLTIPS | WS_CHILD | WS_VISIBLE,
1085                                             "", hDlg, IDC_STATBAR);            
1086             if (GetApacheServicesStatus())
1087             {
1088                 i = 0;
1089                 while (ap_stServices[i].szServiceName != NULL)
1090                 {    
1091                     addItem(hListBox, ap_stServices[i].szDisplayName, 
1092                         ap_stServices[i].dwPid == 0 ? hbmpStop : hbmpStart);
1093                     ++i;
1094                 }
1095             }
1096             CenterWindow(hDlg);
1097             ShowWindow(hDlg, SW_SHOW);
1098             SetFocus(hListBox); 
1099             SendMessage(hListBox, LB_SETCURSEL, 0, 0); 
1100             return TRUE;
1101         break;
1102         case WM_UPDATEMESSAGE:
1103             hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1104             SendMessage(hListBox, LB_RESETCONTENT, 0, 0); 
1105             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1106             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1107             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1108             i = 0;
1109             while (ap_stServices[i].szServiceName != NULL)
1110             {    
1111                 addItem(hListBox, ap_stServices[i].szDisplayName, 
1112                     ap_stServices[i].dwPid == 0 ? hbmpStop : hbmpStart);
1113                 ++i;
1114             }
1115             SendMessage(hListBox, LB_SETCURSEL, 0, 0); 
1116             /* Dirty hack to bring the window to the foreground */
1117             SetWindowPos(hDlg, HWND_TOPMOST, 0, 0, 0, 0,
1118                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1119             SetWindowPos(hDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
1120                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1121             SetFocus(hListBox); 
1122             return TRUE;
1123         break;
1124         case WM_MEASUREITEM: 
1125  
1126             lpmis = (LPMEASUREITEMSTRUCT) lParam; 
1127             lpmis->itemHeight = 16; 
1128             return TRUE; 
1129         case WM_SETCURSOR:
1130             if (ap_consoleRun)
1131                 SetCursor(ap_cHourglass);
1132             else
1133                 SetCursor(ap_cArrow);
1134             return TRUE;
1135         case WM_DRAWITEM: 
1136  
1137             lpdis = (LPDRAWITEMSTRUCT) lParam; 
1138             if (lpdis->itemID == -1) 
1139             { 
1140                 break; 
1141             } 
1142             switch (lpdis->itemAction) 
1143             { 
1144                 case ODA_SELECT: 
1145                 case ODA_DRAWENTIRE: 
1146                     hbmpPicture = (HBITMAP)SendMessage(lpdis->hwndItem, 
1147                         LB_GETITEMDATA, lpdis->itemID, (LPARAM) 0); 
1148  
1149                     hdcMem = CreateCompatibleDC(lpdis->hDC); 
1150                     hbmpOld = SelectObject(hdcMem, hbmpPicture); 
1151  
1152                     BitBlt(lpdis->hDC, 
1153                         lpdis->rcItem.left, lpdis->rcItem.top, 
1154                         lpdis->rcItem.right - lpdis->rcItem.left, 
1155                         lpdis->rcItem.bottom - lpdis->rcItem.top, 
1156                         hdcMem, 0, 0, SRCCOPY); 
1157                     SendMessage(lpdis->hwndItem, LB_GETTEXT, 
1158                         lpdis->itemID, (LPARAM) tchBuffer); 
1159  
1160                     GetTextMetrics(lpdis->hDC, &tm);  
1161                     y = (lpdis->rcItem.bottom + lpdis->rcItem.top - 
1162                         tm.tmHeight) / 2; 
1163   
1164                     SelectObject(hdcMem, hbmpOld); 
1165                     DeleteDC(hdcMem); 
1166  
1167                     rcBitmap.left = lpdis->rcItem.left + XBITMAP + 2; 
1168                     rcBitmap.top = lpdis->rcItem.top; 
1169                     rcBitmap.right = lpdis->rcItem.right; 
1170                     rcBitmap.bottom = lpdis->rcItem.top + YBITMAP; 
1171
1172                     if (lpdis->itemState & ODS_SELECTED) 
1173                     { 
1174                         if (hbmpPicture == hbmpStop)
1175                         {
1176                             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
1177                             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1178                             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1179                         }
1180                         else if (hbmpPicture == hbmpStart) 
1181                         {
1182                             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1183                             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
1184                             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
1185                         }
1186                         if (ap_stServices[lpdis->itemID].szDescription)
1187                             lstrcpy(tsbBuffer, ap_stServices[lpdis->itemID].szDescription); 
1188                         SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)tsbBuffer);
1189                         
1190                         SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 
1191                         SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); 
1192                         FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_HIGHLIGHTTEXT)); 
1193                     } 
1194                     else
1195                     {
1196                        SetTextColor(lpdis->hDC, GetSysColor(COLOR_MENUTEXT)); 
1197                        SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW)); 
1198                        FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_WINDOW+1)); 
1199                     }
1200                     TextOut(lpdis->hDC, 
1201                         XBITMAP + 6, 
1202                         y, 
1203                         tchBuffer, 
1204                         strlen(tchBuffer)); 
1205                     break; 
1206  
1207                 case ODA_FOCUS: 
1208                     break; 
1209             } 
1210             return TRUE;  
1211         case WM_COMMAND: 
1212             switch (LOWORD(wParam)) 
1213             { 
1214                 case IDL_SERVICES:
1215                     switch (HIWORD(wParam))
1216                     {
1217                         case LBN_DBLCLK:
1218                             /* if started then stop, if stopped the start the service */
1219                             hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1220                             nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1221                             if (nItem != LB_ERR)
1222                             {
1223                                 hbmpPicture = (HBITMAP)SendMessage(hListBox, LB_GETITEMDATA,
1224                                                                nItem, (LPARAM) 0); 
1225                                 if (hbmpPicture == hbmpStop)
1226                                 {
1227                                     ApacheManageService(ap_stServices[nItem].szServiceName,
1228                                                 ap_stServices[nItem].szImagePath,
1229                                                 SERVICE_CONTROL_CONTINUE);
1230                                 }
1231                                 else
1232                                     ApacheManageService(ap_stServices[nItem].szServiceName,
1233                                                 ap_stServices[nItem].szImagePath,
1234                                                 SERVICE_CONTROL_STOP);
1235
1236                             }
1237                             return TRUE;
1238                         break;
1239                      }
1240                 break;
1241                 case IDOK: 
1242                     EndDialog(hDlg, TRUE); 
1243                     return TRUE; 
1244                 break;
1245                 case IDC_SSTART: 
1246                     Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1247                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1248                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1249                     if (nItem != LB_ERR)
1250                     {
1251                         ApacheManageService(ap_stServices[nItem].szServiceName,
1252                                              ap_stServices[nItem].szImagePath,
1253                                              SERVICE_CONTROL_CONTINUE);
1254                     }
1255                     Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
1256                     return TRUE;
1257                 break;
1258                 case IDC_SSTOP: 
1259                     Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1260                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1261                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1262                     if (nItem != LB_ERR)
1263                     {
1264                         ApacheManageService(ap_stServices[nItem].szServiceName,
1265                                              ap_stServices[nItem].szImagePath,
1266                                              SERVICE_CONTROL_STOP);
1267                     }
1268                     Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
1269                     return TRUE;
1270                 break;
1271                 case IDC_SRESTART: 
1272                     Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1273                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1274                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1275                     if (nItem != LB_ERR)
1276                     {
1277                         ApacheManageService(ap_stServices[nItem].szServiceName,
1278                                              ap_stServices[nItem].szImagePath,
1279                                              SERVICE_APACHE_RESTART);
1280                     }
1281                     Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
1282                     return TRUE;
1283                 break;
1284                 case IDC_SABOUT: 
1285                    if (!dlgAboutOn)
1286                    {
1287                       dlgAboutOn = TRUE;
1288                       DialogBox(ap_hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX),
1289                              ap_hMainWnd, (DLGPROC)AboutDlgProc);
1290                       dlgAboutOn = FALSE;
1291                       ap_hwndAboutDlg = NULL;                      
1292                    }
1293                    else if (ap_hwndAboutDlg)
1294                        SetFocus(ap_hwndAboutDlg);
1295                     return TRUE;
1296                 break;
1297              }
1298         break;
1299         case WM_SIZE:
1300             switch (LOWORD(wParam)) 
1301             { 
1302                 case SIZE_MINIMIZED:
1303                     EndDialog(hDlg, TRUE); 
1304                     return TRUE; 
1305                 break;
1306             }
1307         break;
1308         case WM_CLOSE: 
1309             EndDialog(hDlg, TRUE);
1310             return TRUE;
1311         case WM_DESTROY: 
1312             DeleteObject(hbmpStart); 
1313             DeleteObject(hbmpStop); 
1314             return TRUE; 
1315         default:
1316             return FALSE;
1317     }
1318     return FALSE;
1319 }
1320
1321
1322 VOID CALLBACK MainTimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
1323 {
1324     int nPrev = 0, nNew = 0;
1325     if (idEvent == WM_TIMER_RESCAN)
1326     {
1327         if (FindRunningServices() || ap_rescanServices)
1328         {
1329             ShowNotifyIcon(hWnd, NIM_MODIFY);
1330             if (ap_hServiceDlg)
1331                 PostMessage(ap_hServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1332         }
1333         /* check if services list changed */
1334         while (ap_stServices[nPrev].szServiceName != NULL)
1335             ++nPrev;
1336         GetApacheServicesStatus();
1337         while (ap_stServices[nNew].szServiceName != NULL)
1338             ++nNew;
1339         if (nPrev != nNew)
1340         {
1341             ShowNotifyIcon(hWnd, NIM_MODIFY);
1342             if (ap_hServiceDlg)
1343                 PostMessage(ap_hServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1344         }
1345     }
1346     else if (idEvent == WM_TIMER_REFRESH)
1347     {
1348         if (ap_rescanServices)
1349         {
1350             GetApacheServicesStatus();
1351             ShowNotifyIcon(hWnd, NIM_MODIFY);
1352             if (ap_hServiceDlg)
1353                 PostMessage(ap_hServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1354         }
1355         else if (FindRunningServices())
1356         {
1357             ShowNotifyIcon(hWnd, NIM_MODIFY);
1358             if (ap_hServiceDlg)
1359                 PostMessage(ap_hServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1360         }
1361     }
1362 }
1363
1364
1365 LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
1366                           WPARAM wParam, LPARAM lParam)
1367 {
1368     
1369     if (message == ap_uiTaskbarCreated)
1370     {
1371         /* restore the tray icon on shell restart */
1372         ShowNotifyIcon(hWnd, NIM_ADD);
1373         return DefWindowProc(hWnd, message, wParam, lParam);
1374     }
1375     switch (message) 
1376     {
1377         case WM_CREATE:
1378             GetSystemOSVersion(NULL, &ap_OSVersion);
1379             GetApacheServicesStatus();
1380             ShowNotifyIcon(hWnd, NIM_ADD);
1381             SetTimer(hWnd, WM_TIMER_REFRESH, REFRESH_TIME, (TIMERPROC)MainTimerProc);
1382             SetTimer(hWnd, WM_TIMER_RESCAN,  RESCAN_TIME, (TIMERPROC)MainTimerProc);
1383             ap_hServiceDlg = NULL;                      
1384         break;
1385         case WM_QUIT:
1386             ShowNotifyIcon(hWnd, NIM_DELETE);
1387         break;
1388         case WM_TRAYMESSAGE:
1389             switch(lParam)
1390             {
1391                 case WM_LBUTTONDBLCLK:
1392                    if (!dlgServiceOn)
1393                    {
1394                        dlgServiceOn = TRUE;
1395                        DialogBox(ap_hInstance, MAKEINTRESOURCE(IDD_APSRVMON_DIALOG),
1396                              hWnd, (DLGPROC)ServiceDlgProc);
1397                        dlgServiceOn = FALSE;
1398                        ap_hServiceDlg = NULL;
1399                    }
1400                    else if (ap_hServiceDlg)
1401                    {
1402                        /* Dirty hack to bring the window to the foreground */
1403                        SetWindowPos(ap_hServiceDlg, HWND_TOPMOST, 0, 0, 0, 0,
1404                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1405                        SetWindowPos(ap_hServiceDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
1406                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1407                        SetFocus(ap_hServiceDlg);
1408                    }
1409                 break;
1410                 case WM_RBUTTONUP:
1411                     ShowTryPopupMenu(hWnd);
1412                 break;    
1413             }
1414             break;
1415         case WM_COMMAND:
1416             switch (LOWORD(wParam))
1417             {
1418                case IDM_RESTORE:
1419                    if (!dlgServiceOn)
1420                    {
1421                        dlgServiceOn = TRUE;
1422                        DialogBox(ap_hInstance, MAKEINTRESOURCE(IDD_APSRVMON_DIALOG),
1423                              hWnd, (DLGPROC)ServiceDlgProc);
1424                        dlgServiceOn = FALSE;
1425                        ap_hServiceDlg = NULL;
1426                    }
1427                    else if (ap_hServiceDlg)
1428                        SetFocus(ap_hServiceDlg);
1429                break;
1430                case IDM_ABOUT:
1431                    if (!dlgAboutOn)
1432                    {
1433                       dlgAboutOn = TRUE;
1434                       DialogBox(ap_hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX),
1435                              hWnd, (DLGPROC)AboutDlgProc);
1436                       dlgAboutOn = FALSE;
1437                       ap_hwndAboutDlg = NULL;                      
1438                    }
1439                    else if (ap_hwndAboutDlg)
1440                        SetFocus(ap_hwndAboutDlg);
1441                 break;
1442                 case IDM_EXIT:
1443                     PostQuitMessage(0);
1444                     return TRUE;
1445                 break;
1446             }
1447         default:
1448             return DefWindowProc(hWnd, message, wParam, lParam);
1449     }
1450
1451     return FALSE;
1452 }
1453
1454 /* Create main invisible window */
1455 HWND CreateMainWindow(HINSTANCE hInstance)
1456 {
1457     HWND       hWnd = NULL;
1458     WNDCLASSEX wcex;
1459
1460     wcex.cbSize = sizeof(WNDCLASSEX); 
1461
1462     wcex.style          = CS_HREDRAW | CS_VREDRAW;
1463     wcex.lpfnWndProc    = (WNDPROC)WndProc;
1464     wcex.cbClsExtra     = 0;
1465     wcex.cbWndExtra     = 0;
1466     wcex.hInstance      = hInstance;
1467     wcex.hIcon          = LoadIcon(hInstance, (LPCTSTR)IDI_APSRVMON);
1468     wcex.hCursor        = ap_cArrow;
1469     wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
1470     wcex.lpszMenuName   = (LPCSTR)IDC_APSRVMON;
1471     wcex.lpszClassName  = szWindowClass;
1472     wcex.hIconSm        = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_APSMALL);
1473
1474     if (RegisterClassEx(&wcex))
1475     {
1476         hWnd = CreateWindow(szWindowClass, szTitle,
1477                              0, 0, 0, 0, 0,
1478                              NULL, NULL, hInstance, NULL);
1479     }
1480
1481     return hWnd;
1482
1483 }
1484
1485
1486 int WINAPI WinMain(HINSTANCE hInstance,
1487                     HINSTANCE hPrevInstance,
1488                     LPTSTR lpCmdLine,
1489                     int nCmdShow)
1490 {
1491     MSG     msg;
1492     /* single instance mutex */
1493     HANDLE hMutex = CreateMutex(NULL, FALSE, "APSRVMON_MUTEX");
1494     if((hMutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
1495     {
1496         if (hMutex)
1497             CloseHandle(hMutex);
1498
1499         return 0;
1500     }
1501     InitCommonControls();
1502     ap_hInstance = hInstance;
1503
1504     LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
1505     LoadString(hInstance, IDC_APSRVMON,  szWindowClass, MAX_LOADSTRING);
1506     ap_icoStop  = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICOSTOP));
1507     ap_icoRun   = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICORUN));
1508     ap_cHourglass = LoadCursor(NULL, IDC_WAIT);
1509     ap_cArrow     = LoadCursor(NULL, IDC_ARROW);
1510
1511     ZeroMemory(ap_stServices, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
1512     ap_hMainWnd = CreateMainWindow(hInstance);
1513     if (ap_hMainWnd != NULL)
1514     {
1515         ap_uiTaskbarCreated = RegisterWindowMessage("TaskbarCreated");
1516         while (GetMessage(&msg, NULL, 0, 0) == TRUE) 
1517         {
1518             TranslateMessage(&msg);
1519             DispatchMessage(&msg);
1520         }    
1521         ap_ClearServicesSt();
1522     }
1523     CloseHandle(hMutex);
1524     return 0;
1525 }