]> granicus.if.org Git - apache/blob - support/win32/ApacheMonitor.c
Fix Restart and Stop from the service taskbar list.
[apache] / support / win32 / ApacheMonitor.c
1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000-2002 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 <objbase.h>
80 #include <shlobj.h>
81 #include <stdlib.h>
82 #include <stdio.h>
83 #include "ApacheMonitor.h"
84
85
86 #define OS_VERSION_WIN9X    1
87 #define OS_VERSION_WINNT    2
88 #define OS_VERSION_WIN2K    3
89 /* Should be enough */
90 #define MAX_APACHE_SERVICES 128
91 #define MAX_APACHE_COMPUTERS 32
92
93 #define WM_TRAYMESSAGE         (WM_APP+1)
94 #define WM_UPDATEMESSAGE       (WM_USER+1)
95 #define WM_MANAGEMESSAGE       (WM_USER+2)
96 #define WM_TIMER_REFRESH       10
97 #define WM_TIMER_RESCAN        11
98 #define SERVICE_APACHE_RESTART 128
99 #define XBITMAP                16
100 #define YBITMAP                16 
101 #define MAX_LOADSTRING         100
102 #define REFRESH_TIME           2000           /* service refresh time (ms) */
103 #define RESCAN_TIME            20000          /* registry rescan time (ms) */
104
105 typedef struct _st_APACHE_SERVICE
106 {
107     LPSTR    szServiceName;
108     LPSTR    szDisplayName;
109     LPSTR    szDescription;
110     LPSTR    szImagePath;
111     LPSTR    szComputerName;
112     DWORD    dwPid;
113 } ST_APACHE_SERVICE;
114
115 typedef struct _st_MONITORED_COMPUTERS
116 {
117     LPSTR   szComputerName;
118     HKEY    hRegistry;
119 } ST_MONITORED_COMP;
120
121 /* Global variables */
122 HINSTANCE         g_hInstance = NULL;
123 CHAR              *g_szTitle;          /* The title bar text */
124 CHAR              *g_szWindowClass;    /* Window Class Name  */
125 HICON             g_icoStop;
126 HICON             g_icoRun;
127 UINT              g_bUiTaskbarCreated;
128 DWORD             g_dwOSVersion;
129 BOOL              g_bDlgServiceOn = FALSE;
130 BOOL              g_bConsoleRun = FALSE;
131 ST_APACHE_SERVICE g_stServices[MAX_APACHE_SERVICES];
132 ST_MONITORED_COMP g_stComputers[MAX_APACHE_COMPUTERS];
133
134 HBITMAP           g_hBmpStart, g_hBmpStop; 
135 HBITMAP           g_hBmpPicture, g_hBmpOld; 
136 BOOL              g_bRescanServices;
137 HWND              g_hwndServiceDlg;
138 HWND              g_hwndMain;
139 HWND              g_hwndStdoutList;
140 HWND              g_hwndConnectDlg;
141 HCURSOR           g_hCursorHourglass;
142 HCURSOR           g_hCursorArrow;
143
144 HANDLE            g_hpipeOutRead;
145 HANDLE            g_hpipeOutWrite;
146 HANDLE            g_hpipeInRead;
147 HANDLE            g_hpipeInWrite;
148 HANDLE            g_hpipeStdError;
149 LANGID            g_LangID;
150 PROCESS_INFORMATION g_lpRedirectProc;
151 CRITICAL_SECTION    g_stcSection;
152 LPSTR             g_szLocalHost;
153
154 /* locale language support */
155 static CHAR *g_lpMsg[IDS_MSG_LAST - IDS_MSG_FIRST + 1];
156
157 void am_ClearServicesSt()
158 {
159     int i;
160     for (i = 0; i < MAX_APACHE_SERVICES; i++)
161     {
162         if (g_stServices[i].szServiceName)
163             free(g_stServices[i].szServiceName);
164         if (g_stServices[i].szDisplayName)
165             free(g_stServices[i].szDisplayName);
166         if (g_stServices[i].szDescription)
167             free(g_stServices[i].szDescription);
168         if (g_stServices[i].szImagePath)
169             free(g_stServices[i].szImagePath);
170         if (g_stServices[i].szComputerName)
171             free(g_stServices[i].szComputerName);
172
173     }
174     ZeroMemory(g_stServices, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
175
176 }
177
178 void am_ClearComputersSt()
179 {
180     int i;
181     for (i = 0; i < MAX_APACHE_COMPUTERS; i++)
182     {
183         if (g_stComputers[i].szComputerName) {
184             free(g_stComputers[i].szComputerName);
185             RegCloseKey(g_stComputers[i].hRegistry);
186         }
187     }
188     ZeroMemory(g_stComputers, sizeof(ST_MONITORED_COMP) * MAX_APACHE_COMPUTERS);
189
190 }
191
192 BOOL am_IsComputerConnected( LPSTR szComputerName)
193 {
194     int i = 0;
195     while (g_stComputers[i].szComputerName != NULL) {
196         if (strcmp(g_stComputers[i].szComputerName, szComputerName) == 0)
197             return TRUE;
198         ++i;
199     }
200     return FALSE;
201 }
202
203 void am_DisconnectComputer( LPSTR szComputerName)
204 {
205     int i = 0, j;
206     while (g_stComputers[i].szComputerName != NULL) {
207         if (strcmp(g_stComputers[i].szComputerName, szComputerName) == 0)
208             break;
209         ++i;
210     }
211     if (g_stComputers[i].szComputerName != NULL) {
212         free(g_stComputers[i].szComputerName);
213         RegCloseKey(g_stComputers[i].hRegistry);
214         for( j = i; j < MAX_APACHE_COMPUTERS - 1; j++) {
215             g_stComputers[i].szComputerName = g_stComputers[i+1].szComputerName;
216             g_stComputers[i].hRegistry = g_stComputers[i+1].hRegistry;
217         }
218         for( i = j; i < MAX_APACHE_COMPUTERS; i++) {
219             g_stComputers[i].szComputerName = NULL;
220             g_stComputers[i].hRegistry = NULL;
221         }
222     } 
223
224 }
225
226 void ErrorMessage(LPCSTR szError, BOOL bFatal)
227 {
228     LPVOID lpMsgBuf  = NULL;
229     if (szError)
230         MessageBox(NULL, szError, g_lpMsg[IDS_MSG_ERROR-IDS_MSG_FIRST],
231                     MB_OK | (bFatal ? MB_ICONERROR : MB_ICONEXCLAMATION));
232     else
233     {
234         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
235             FORMAT_MESSAGE_FROM_SYSTEM |
236             FORMAT_MESSAGE_IGNORE_INSERTS,
237             NULL,
238             GetLastError(),
239             g_LangID,
240             (LPSTR) &lpMsgBuf, 0, NULL);
241         MessageBox(NULL, (LPCSTR)lpMsgBuf, g_lpMsg[IDS_MSG_ERROR-IDS_MSG_FIRST],
242                     MB_OK | (bFatal ? MB_ICONERROR : MB_ICONEXCLAMATION));
243         LocalFree(lpMsgBuf);
244     }
245     if ( bFatal)
246         PostQuitMessage(0);
247 }
248
249 BOOL am_ConnectComputer(LPSTR szComputerName)
250 {
251     int i = 0;
252     HKEY hKeyRemote;
253     char szTmp[MAX_PATH];
254
255     while (g_stComputers[i].szComputerName != NULL) {
256         if (strcmp(g_stComputers[i].szComputerName, szComputerName) == 0)
257             return FALSE;
258         ++i;
259     }
260     if (i > MAX_APACHE_COMPUTERS - 1)
261         return FALSE;
262     if (RegConnectRegistry(szComputerName, HKEY_LOCAL_MACHINE, &hKeyRemote) != ERROR_SUCCESS)
263     {
264         sprintf(szTmp, g_lpMsg[IDS_MSG_ECONNECT-IDS_MSG_FIRST], szComputerName);
265         ErrorMessage(szTmp, FALSE);
266         return FALSE;
267     }
268     else 
269     {
270         g_stComputers[i].szComputerName = strdup(szComputerName);
271         g_stComputers[i].hRegistry = hKeyRemote;
272         return TRUE;
273     }
274
275
276 LPSTR GetStringRes(int id)
277 {
278   static CHAR buffer[MAX_PATH];
279
280   buffer[0] = 0;
281   LoadString(GetModuleHandle (NULL), id, buffer, MAX_PATH);
282   return buffer;
283 }
284
285 BOOL GetSystemOSVersion(LPDWORD dwVersion)
286 {
287     OSVERSIONINFO osvi;
288     /* 
289     Try calling GetVersionEx using the OSVERSIONINFOEX structure.
290     If that fails, try using the OSVERSIONINFO structure.
291     */
292     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
293     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
294     
295     if (!GetVersionEx(&osvi))
296         return FALSE;
297     
298     switch (osvi.dwPlatformId)
299     {
300     case VER_PLATFORM_WIN32_NT:        
301         if (osvi.dwMajorVersion <= 4)
302             *dwVersion = OS_VERSION_WINNT;
303         else if (osvi.dwMajorVersion == 5)
304             *dwVersion = OS_VERSION_WIN2K;
305         else
306             return FALSE;
307         
308         break;        
309     case VER_PLATFORM_WIN32_WINDOWS:
310             *dwVersion = OS_VERSION_WIN9X;        
311         break;
312         
313     case VER_PLATFORM_WIN32s:
314             *dwVersion = 0;
315         return FALSE;
316     default:
317         return FALSE;
318         break;
319    }
320    return TRUE; 
321 }
322
323 static VOID ShowNotifyIcon(HWND hWnd, DWORD dwMessage)
324 {
325     
326     NOTIFYICONDATA nid;
327     int  i = 0, n = 0;
328
329     ZeroMemory(&nid,sizeof(nid));
330     nid.cbSize = sizeof(NOTIFYICONDATA);
331     nid.hWnd = hWnd;
332     nid.uID = 0xFF;
333     nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
334     nid.uCallbackMessage = WM_TRAYMESSAGE;
335     
336     while (g_stServices[i].szServiceName != NULL)
337     {    
338         if (g_stServices[i].dwPid != 0)
339             ++n;
340         ++i;
341     }
342     if (dwMessage != NIM_DELETE)
343     {
344         if (n)
345             nid.hIcon = g_icoRun;
346         else
347             nid.hIcon = g_icoStop;
348     }
349     else
350         nid.hIcon = NULL;
351     if (n == i && n > 0)
352         lstrcpy(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGALL-IDS_MSG_FIRST]);
353     else if (n)
354         sprintf(nid.szTip, g_lpMsg[IDS_MSG_RUNNING-IDS_MSG_FIRST], n, i);
355     else if (i)
356         sprintf(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGNONE-IDS_MSG_FIRST], i);
357     else
358         lstrcpy(nid.szTip, g_lpMsg[IDS_MSG_NOSERVICES-IDS_MSG_FIRST]);
359     Shell_NotifyIcon(dwMessage, &nid);
360 }
361
362 void appendMenuItem(HMENU hMenu, UINT uMenuId, LPSTR szName, BOOL fDefault, BOOL fEnabled)
363 {
364     MENUITEMINFO mii;
365     
366     ZeroMemory(&mii, sizeof(MENUITEMINFO));
367     mii.cbSize = sizeof(MENUITEMINFO);
368     mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
369     if (lstrlen(szName))
370     {
371         mii.fType = MFT_STRING;
372         mii.wID = uMenuId;
373         if (fDefault)
374             mii.fState = MFS_DEFAULT;
375         if (!fEnabled)
376             mii.fState |= MFS_DISABLED;
377         mii.dwTypeData = szName;
378     }
379     else
380         mii.fType = MFT_SEPARATOR;
381     InsertMenuItem(hMenu, uMenuId, FALSE, &mii);
382 }
383
384 void appendServiceMenu(HMENU hMenu, UINT uMenuId, LPSTR szServiceName, BOOL fRunning)
385 {
386     MENUITEMINFO mii;
387     HMENU        smh;    
388
389     smh = CreatePopupMenu();
390
391     appendMenuItem(smh,  IDM_SM_START + uMenuId, g_lpMsg[IDS_MSG_SSTART-IDS_MSG_FIRST], FALSE, !fRunning);
392     appendMenuItem(smh,  IDM_SM_STOP + uMenuId, g_lpMsg[IDS_MSG_SSTOP-IDS_MSG_FIRST], FALSE, fRunning);
393     appendMenuItem(smh,  IDM_SM_RESTART + uMenuId, g_lpMsg[IDS_MSG_SRESTART-IDS_MSG_FIRST], FALSE, fRunning);
394
395     ZeroMemory(&mii, sizeof(MENUITEMINFO));
396     mii.cbSize = sizeof(MENUITEMINFO);
397     mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU | MIIM_CHECKMARKS;
398     mii.fType = MFT_STRING;
399     mii.wID = uMenuId;
400     mii.hbmpChecked = g_hBmpStart;
401     mii.hbmpUnchecked = g_hBmpStop;
402     mii.dwTypeData = szServiceName;
403     mii.hSubMenu = smh;
404     mii.fState = fRunning ? MFS_CHECKED : MFS_UNCHECKED;
405     InsertMenuItem(hMenu, IDM_SM_SERVICE + uMenuId, FALSE, &mii);
406 }
407
408 void ShowTryPopupMenu(HWND hWnd)
409 {
410     /* create popup menu */
411     HMENU hMenu = CreatePopupMenu();
412     POINT pt;
413
414     if (hMenu)
415     {
416         appendMenuItem(hMenu, IDM_RESTORE, g_lpMsg[IDS_MSG_MNUSHOW-IDS_MSG_FIRST], TRUE, TRUE);
417         if (g_dwOSVersion >= OS_VERSION_WINNT)
418             appendMenuItem(hMenu, IDC_SMANAGER, g_lpMsg[IDS_MSG_MNUSERVICES-IDS_MSG_FIRST], FALSE, TRUE);
419         appendMenuItem(hMenu, 0, "", FALSE, TRUE);
420         appendMenuItem(hMenu, IDM_EXIT,  g_lpMsg[IDS_MSG_MNUEXIT-IDS_MSG_FIRST], FALSE, TRUE);
421
422         if (!SetForegroundWindow(hWnd))
423             SetForegroundWindow(NULL);
424         GetCursorPos(&pt);
425         TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, 
426                        pt.x, pt.y, 0, hWnd, NULL);
427         DestroyMenu(hMenu);
428     }
429 }
430
431 void ShowTryServicesMenu(HWND hWnd)
432 {
433     /* create services list popup menu and submenus */
434     HMENU hMenu = CreatePopupMenu();
435     POINT pt;
436     int i = 0;
437
438     if (hMenu)
439     {
440         while (g_stServices[i].szServiceName != NULL)
441         {   
442             appendServiceMenu(hMenu, i, g_stServices[i].szDisplayName,
443                               g_stServices[i].dwPid != 0);               
444             ++i;
445         }
446         if (i)
447         {
448             if (!SetForegroundWindow(hWnd))
449                 SetForegroundWindow(NULL);
450             GetCursorPos(&pt);
451             TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, 
452                            pt.x, pt.y, 0, hWnd, NULL);
453             DestroyMenu(hMenu);
454         }
455     }
456 }
457
458 BOOL CenterWindow(HWND hwndChild)
459 {
460    RECT    rChild, rWorkArea;
461    int     wChild, hChild;
462    int     xNew, yNew;
463    BOOL    bResult;
464
465    /* Get the Height and Width of the child window */
466    GetWindowRect(hwndChild, &rChild);
467    wChild = rChild.right - rChild.left;
468    hChild = rChild.bottom - rChild.top;
469
470    /* Get the limits of the 'workarea' */
471    bResult = SystemParametersInfo(
472       SPI_GETWORKAREA,
473       sizeof(RECT),
474       &rWorkArea,
475       0);
476    if (!bResult) {
477       rWorkArea.left = rWorkArea.top = 0;
478       rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
479       rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
480    }
481
482    /* Calculate new X and Y position*/
483    xNew = (rWorkArea.right - wChild)/2;
484    yNew = (rWorkArea.bottom - hChild)/2;
485    return SetWindowPos (hwndChild, HWND_TOP, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
486 }
487
488 static void addListBoxItem(HWND hDlg, LPSTR lpStr, HBITMAP hBmp) 
489
490     int nItem; 
491  
492     nItem = SendMessage(hDlg, LB_ADDSTRING, 0, (LPARAM)lpStr); 
493     SendMessage(hDlg, LB_SETITEMDATA, nItem, (LPARAM)hBmp); 
494
495
496 static void addListBoxString(HWND hListBox, LPSTR lpStr)
497 {
498     static int nItems = 0;
499     if (!g_bDlgServiceOn)
500         return;
501
502     ++nItems;
503     if ( nItems > MAX_LOADSTRING)
504     {
505         SendMessage(hListBox, LB_RESETCONTENT, 0, 0); 
506         nItems = 1;
507     }
508     ListBox_SetCurSel(hListBox,
509                       ListBox_AddString(hListBox, lpStr));
510
511 }
512 static DWORD WINAPI ConsoleOutputThread(LPVOID lpThreadParameter)
513 {
514     static BYTE lpBuffer[MAX_PATH+1];
515     int nPtr = 0;
516     BYTE  ch;
517     DWORD dwReaded;
518
519     while (ReadFile(g_hpipeOutRead, &ch, 1, &dwReaded, NULL) == TRUE) 
520     {
521         if (dwReaded > 0) 
522         {
523             if (ch == '\n' || nPtr >= MAX_PATH) 
524             {
525                 lpBuffer[nPtr] = '\0';
526                 addListBoxString(g_hwndStdoutList, lpBuffer);
527                 nPtr  = 0;
528             } 
529             else if (ch == '\t' && nPtr < (MAX_PATH - 4)) 
530             {
531                 int i;
532                 for (i = 0; i < 4; ++i)
533                     lpBuffer[nPtr++] = ' ';
534             }
535             else if (ch != '\r')
536                 lpBuffer[nPtr++] = ch;
537         }
538     }
539     CloseHandle(g_hpipeInWrite);
540     CloseHandle(g_hpipeOutRead);
541     CloseHandle(g_hpipeStdError);
542     return 0;
543 }
544
545
546 DWORD WINAPI ConsoleWaitingThread(LPVOID lpThreadParameter)
547 {
548     WaitForSingleObject(g_lpRedirectProc.hThread, INFINITE);
549     CloseHandle(g_lpRedirectProc.hThread);
550     MessageBeep(100);
551     g_bConsoleRun = FALSE;
552     SetCursor(g_hCursorArrow);
553     return 0;
554 }
555
556
557 BOOL RunRedirectedConsole(LPSTR szCmdLine)
558 {
559     
560     DWORD  dwThreadId;
561     HANDLE hProc;
562     STARTUPINFO stInfo;
563     BOOL bResult;
564     ZeroMemory(&stInfo, sizeof(stInfo));
565     stInfo.cb = sizeof(stInfo);
566     stInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
567     stInfo.wShowWindow = SW_HIDE;
568     
569     hProc = GetCurrentProcess();
570
571     if (!CreatePipe(&g_hpipeInRead, &g_hpipeInWrite, NULL, MAX_PATH))
572         ErrorMessage(NULL, TRUE);
573     if (!CreatePipe(&g_hpipeOutRead, &g_hpipeOutWrite, NULL, MAX_PATH*8))
574         ErrorMessage(NULL, TRUE);
575         
576     DuplicateHandle(hProc, g_hpipeInRead, hProc, &g_hpipeInRead, 0, TRUE, 
577                     DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
578     DuplicateHandle(hProc, g_hpipeOutWrite, hProc, &g_hpipeOutWrite, 0, TRUE, 
579                     DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
580     DuplicateHandle(hProc, g_hpipeOutWrite, hProc, &g_hpipeStdError, 0, TRUE, 
581                     DUPLICATE_SAME_ACCESS);
582     if (!g_hpipeInRead && !g_hpipeOutWrite && !g_hpipeStdError)
583         ErrorMessage(NULL, TRUE);
584
585     stInfo.hStdInput  = g_hpipeInRead;
586     stInfo.hStdOutput = g_hpipeOutWrite;
587     stInfo.hStdError  = g_hpipeStdError;
588
589     bResult = CreateProcess(NULL,
590         szCmdLine,
591         NULL,
592         NULL,
593         TRUE,
594         CREATE_SUSPENDED,
595         NULL,
596         NULL ,
597         &stInfo,
598         &g_lpRedirectProc);
599
600
601     CloseHandle(g_hpipeInRead);
602     CloseHandle(g_hpipeOutWrite);
603     CloseHandle(g_hpipeStdError);
604
605     if (!bResult)
606     {     
607         CloseHandle(g_hpipeInWrite);
608         CloseHandle(g_hpipeOutRead);
609         CloseHandle(g_hpipeStdError);
610         return FALSE;
611     }
612
613     CloseHandle(CreateThread(NULL, 0, ConsoleOutputThread, 0, 0, &dwThreadId));
614     ResumeThread(g_lpRedirectProc.hThread);
615     CloseHandle(CreateThread(NULL, 0, ConsoleWaitingThread, 0, 0, &dwThreadId));
616
617     return TRUE;
618 }
619
620 BOOL RunAndForgetConsole(LPSTR szCmdLine,
621                          BOOL  bRedirectConsole)
622 {
623         
624     STARTUPINFO stInfo;
625     PROCESS_INFORMATION prInfo;
626     BOOL bResult;
627     
628     if (bRedirectConsole)
629         return RunRedirectedConsole(szCmdLine);
630
631     
632     ZeroMemory(&stInfo, sizeof(stInfo));
633     stInfo.cb = sizeof(stInfo);
634     stInfo.dwFlags = STARTF_USESHOWWINDOW;
635     stInfo.wShowWindow = SW_HIDE;
636
637     bResult = CreateProcess(NULL,
638         szCmdLine,
639         NULL,
640         NULL,
641         TRUE,
642         CREATE_NEW_CONSOLE,
643         NULL,
644         NULL ,
645         &stInfo,
646         &prInfo);
647
648     if (!bResult)
649     {     
650         return FALSE;
651     }
652     if (g_dwOSVersion == OS_VERSION_WIN9X) /* give some time to rescan the status */
653         Sleep(2000);
654     CloseHandle(prInfo.hThread);
655     CloseHandle(prInfo.hProcess);
656     return TRUE;
657 }
658
659 BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, LPSTR szComputerName, DWORD dwCommand)
660 {
661     
662     CHAR      szBuf[MAX_PATH];
663     CHAR      szMsg[MAX_PATH];
664     LPSTR     sPos;
665     BOOL      retValue;
666     BOOL      serviceFlag = TRUE;
667     SC_HANDLE schService;
668     SC_HANDLE schSCManager;    
669     SERVICE_STATUS schSStatus;
670     LPSTR     *args;
671     int       ticks;
672
673     if (g_dwOSVersion == OS_VERSION_WIN9X)
674     {
675         sPos = strstr(szImagePath, "-k start");
676         if (sPos)
677         {
678             lstrcpyn(szBuf, szImagePath, sPos - szImagePath);
679             switch (dwCommand)
680             {
681             case SERVICE_CONTROL_STOP:
682                 lstrcat(szBuf, " -k shutdown -n ");
683                 break;
684             case SERVICE_CONTROL_CONTINUE:
685                 sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART-IDS_MSG_FIRST], szServiceName);
686                 addListBoxString(g_hwndStdoutList, szMsg);
687                 lstrcat(szBuf, " -k start -n ");
688                 serviceFlag = FALSE;
689                 break;
690             case SERVICE_APACHE_RESTART:
691                 lstrcat(szBuf, " -k restart -n ");
692                 break;
693             default:
694                 return FALSE;
695             }
696             lstrcat(szBuf, szServiceName);
697         }
698         else
699             return FALSE;
700         g_bConsoleRun = TRUE;
701         SetCursor(g_hCursorHourglass);
702         if (!RunAndForgetConsole(szBuf, serviceFlag))
703         {
704             ErrorMessage(NULL, FALSE);
705             g_bConsoleRun = FALSE;
706             SetCursor(g_hCursorArrow);
707             return FALSE;
708         }
709         else if (!serviceFlag)
710         {
711             sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTARTED-IDS_MSG_FIRST], szServiceName);
712             addListBoxString(g_hwndStdoutList, szMsg);
713             g_bConsoleRun = FALSE;
714             SetCursor(g_hCursorArrow);
715             return TRUE;
716         }
717     }
718     else
719     {
720         /* Apache 2.0 uses '-k runservice' as cmdline parameter */
721         sPos = strstr(szImagePath, "--ntservice");
722         if (!sPos)
723         {
724             sPos = strstr(szImagePath, "-k runservice");
725             serviceFlag = FALSE;
726         }
727         if (sPos)
728             lstrcpyn(szBuf, szImagePath, sPos - szImagePath);
729         else
730             return FALSE;
731         schSCManager = OpenSCManager(
732             szComputerName,
733             NULL,
734             SC_MANAGER_ALL_ACCESS
735            );
736         if (!schSCManager)
737             return FALSE;
738         
739         schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);
740         if (schService != NULL)
741         {
742             retValue = FALSE;
743             g_bConsoleRun = TRUE;
744             SetCursor(g_hCursorHourglass);
745             switch (dwCommand)
746             {
747                 case SERVICE_CONTROL_STOP:
748                     sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTOP-IDS_MSG_FIRST], szServiceName);
749                     addListBoxString(g_hwndStdoutList, szMsg);
750                     if (ControlService(schService, SERVICE_CONTROL_STOP, &schSStatus)) 
751                     {
752                         Sleep(1000);
753                         while (QueryServiceStatus(schService, &schSStatus)) 
754                         {
755                             if (schSStatus.dwCurrentState == SERVICE_STOP_PENDING)
756                                 Sleep(1000);
757                             else
758                                 break;
759                         }
760                     }
761                     if (QueryServiceStatus(schService, &schSStatus))
762                     {
763                         if (schSStatus.dwCurrentState == SERVICE_STOPPED)
764                         {
765                             retValue = TRUE;
766                             sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTOPPED-IDS_MSG_FIRST], szServiceName);
767                             addListBoxString(g_hwndStdoutList, szMsg);
768                         }
769                     }
770                 break;                
771                 case SERVICE_CONTROL_CONTINUE:
772                     sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART-IDS_MSG_FIRST], szServiceName);
773                     addListBoxString(g_hwndStdoutList, szMsg);
774                     args = (char **)malloc(3 * sizeof(char*));
775                     args[0] = szBuf;
776                     if (serviceFlag)
777                         args[1] = "--ntservice";
778                     else
779                     {
780                         args[1] = "-k";
781                         args[2] = "runservice";
782                     }
783                     if (StartService(schService, serviceFlag ? 2 : 3, args)) 
784                     {
785                         Sleep(1000);
786                         while (QueryServiceStatus(schService, &schSStatus)) 
787                         {
788                             if (schSStatus.dwCurrentState == SERVICE_START_PENDING)
789                                 Sleep(1000);
790                             else
791                                 break;
792                         }
793                     }
794                     if (QueryServiceStatus(schService, &schSStatus))
795                     {
796                         if (schSStatus.dwCurrentState == SERVICE_RUNNING)
797                         {
798                             retValue = TRUE;
799                             sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTARTED-IDS_MSG_FIRST], szServiceName);
800                             addListBoxString(g_hwndStdoutList, szMsg);
801                         }
802                     }
803                     /* is this OK to do? */
804                     free(args);
805                 break;                
806                 case SERVICE_APACHE_RESTART:
807                     sprintf(szMsg, g_lpMsg[IDS_MSG_SRVRESTART-IDS_MSG_FIRST], szServiceName);
808                     addListBoxString(g_hwndStdoutList, szMsg);
809                     if (ControlService(schService, SERVICE_APACHE_RESTART, &schSStatus)) 
810                     {
811                         ticks = 60;
812                         while (schSStatus.dwCurrentState == SERVICE_START_PENDING) 
813                         {
814                             Sleep(1000);
815                             if (!QueryServiceStatus(schService, &schSStatus))
816                             {
817                                 CloseServiceHandle(schService);
818                                 CloseServiceHandle(schSCManager);
819                                 g_bConsoleRun = FALSE;
820                                 SetCursor(g_hCursorArrow);
821                                 return FALSE;
822                             }
823                             if (!--ticks)
824                                 break;
825                         }
826                     }
827                     if (schSStatus.dwCurrentState == SERVICE_RUNNING)
828                     {
829                         retValue = TRUE;
830                         sprintf(szMsg, g_lpMsg[IDS_MSG_SRVRESTARTED-IDS_MSG_FIRST], szServiceName);
831                         addListBoxString(g_hwndStdoutList, szMsg);
832                     }
833                 break;                
834             }
835             CloseServiceHandle(schService);
836             CloseServiceHandle(schSCManager);
837             if (!retValue)
838                 ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED-IDS_MSG_FIRST], FALSE);
839             g_bConsoleRun = FALSE;
840             SetCursor(g_hCursorArrow);
841             return retValue;
842             
843         }
844         else
845             g_bRescanServices = TRUE;
846         
847         CloseServiceHandle(schSCManager);
848         return FALSE;
849     }
850     
851     return FALSE;
852 }
853
854 BOOL IsServiceRunning(LPCSTR szServiceName, LPCSTR szComputerName, LPDWORD lpdwPid)
855 {
856
857     DWORD                   dwPid;
858     HWND                    hWnd;
859     SC_HANDLE               schService;
860     SC_HANDLE               schSCManager;    
861     SERVICE_STATUS          schSStatus;
862
863     if (g_dwOSVersion == OS_VERSION_WIN9X)
864     {
865         hWnd = FindWindow("ApacheWin95ServiceMonitor", szServiceName);
866         if (hWnd && GetWindowThreadProcessId(hWnd, &dwPid))
867         {
868             *lpdwPid = 1;
869             return TRUE;
870         }
871         else
872             return FALSE;
873     }
874     else
875     {
876
877         dwPid = 0;
878         schSCManager = OpenSCManager(
879                             szComputerName,
880                             NULL,
881                             SC_MANAGER_ALL_ACCESS
882                            );
883         if (!schSCManager)
884             return FALSE;
885
886         schService = OpenService(schSCManager, szServiceName, SERVICE_QUERY_STATUS);
887         if (schService != NULL)
888         {
889             if (QueryServiceStatus(schService, &schSStatus))
890             {
891                 
892                 dwPid = schSStatus.dwCurrentState;
893                 if (lpdwPid)
894                     *lpdwPid = 1;
895             }
896             CloseServiceHandle(schService);
897             CloseServiceHandle(schSCManager);
898             return dwPid == SERVICE_RUNNING ? TRUE : FALSE;
899         }
900         else
901             g_bRescanServices = TRUE;
902
903         CloseServiceHandle(schSCManager);
904         return FALSE;
905
906     }
907
908     return FALSE;
909 }
910
911 BOOL FindRunningServices(void)
912 {
913     int i = 0;
914     DWORD dwPid;
915     BOOL rv = FALSE;
916     while (g_stServices[i].szServiceName != NULL)
917     {    
918         if (!IsServiceRunning(g_stServices[i].szServiceName, g_stServices[i].szComputerName, &dwPid))
919             dwPid = 0;
920         if (g_stServices[i].dwPid != dwPid)
921             rv = TRUE;
922         g_stServices[i].dwPid = dwPid;
923         ++i;
924     }                        
925     return rv;
926 }
927
928 BOOL GetApacheServicesStatus()
929 {
930
931     CHAR    szKey[MAX_PATH];
932     CHAR    achKey[MAX_PATH];
933     CHAR    szImagePath[MAX_PATH];
934     CHAR    szBuf[MAX_PATH];
935     CHAR    szTmp[MAX_PATH];
936
937     HKEY    hKey, hSubKey, hKeyRemote;
938     DWORD   retCode, rv, dwKeyType;
939     DWORD   dwBufLen = MAX_PATH;
940     int     i, stPos = 0;
941     int     computers = 0;
942
943     g_bRescanServices = FALSE;
944
945     
946     am_ClearServicesSt();
947     while (g_stComputers[computers].szComputerName != NULL) {
948         hKeyRemote = g_stComputers[computers].hRegistry;
949         retCode = RegOpenKeyEx(hKeyRemote,
950                                 "System\\CurrentControlSet\\Services\\",
951                                 0, KEY_READ, &hKey);
952         if (retCode != ERROR_SUCCESS)
953         {
954             ErrorMessage(NULL, FALSE);
955             return FALSE;
956         }
957         for (i = 0, retCode = ERROR_SUCCESS; retCode == ERROR_SUCCESS; i++)
958         {
959
960             retCode = RegEnumKey(hKey, i, achKey, MAX_PATH);
961             if (retCode == ERROR_SUCCESS)
962             {
963                 lstrcpy(szKey, "System\\CurrentControlSet\\Services\\");
964                 lstrcat(szKey, achKey);
965
966                 if (RegOpenKeyEx(hKeyRemote, szKey, 0, 
967                     KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS)
968                 {
969                     dwBufLen = MAX_PATH;
970                     rv = RegQueryValueEx(hSubKey, "ImagePath", NULL,
971                                           &dwKeyType, szImagePath, &dwBufLen);
972
973                     if (rv == ERROR_SUCCESS && (dwKeyType == REG_SZ  || dwKeyType == REG_EXPAND_SZ) && dwBufLen)
974                     {
975                         lstrcpy(szBuf, szImagePath);
976                         CharLower(szBuf);
977                         /* the service name could be Apache*.exe */
978                         if (strstr(szBuf, "\\apache") != NULL && strstr(szBuf, ".exe") &&
979                         (strstr(szBuf, "--ntservice") != NULL || strstr(szBuf, "-k ") !=NULL))
980                         {
981                             g_stServices[stPos].szServiceName = strdup(achKey);
982                             g_stServices[stPos].szImagePath = strdup(szImagePath);
983                             g_stServices[stPos].szComputerName = strdup(g_stComputers[computers].szComputerName);
984                             dwBufLen = MAX_PATH;
985                             if (RegQueryValueEx(hSubKey, "Description", NULL,
986                                           &dwKeyType, szBuf, &dwBufLen) == ERROR_SUCCESS)
987                                 g_stServices[stPos].szDescription = strdup(szBuf);
988
989                             dwBufLen = MAX_PATH;
990                             if (RegQueryValueEx(hSubKey, "DisplayName", NULL,
991                                           &dwKeyType, szBuf, &dwBufLen) == ERROR_SUCCESS) {
992                                 if (strcmp(g_stComputers[computers].szComputerName, g_szLocalHost) != 0) { 
993                                     strcpy(szTmp, g_stComputers[computers].szComputerName + 2);
994                                     strcat(szTmp, "@");
995                                     strcat(szTmp, szBuf);
996                                 }
997                                 else
998                                     strcpy( szTmp, szBuf);
999                                 g_stServices[stPos].szDisplayName= strdup(szTmp);
1000
1001                             }
1002                             ++stPos;
1003                             if (stPos >= MAX_APACHE_SERVICES)
1004                                 retCode = !ERROR_SUCCESS;
1005                         }
1006                     }
1007                     RegCloseKey(hSubKey);
1008                 }
1009             }
1010         }
1011         ++computers;
1012     }
1013     RegCloseKey(hKey);
1014     FindRunningServices();
1015     return TRUE;
1016 }
1017
1018 LRESULT CALLBACK ConnectDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1019 {
1020     CHAR szCmp[MAX_COMPUTERNAME_LENGTH+4];
1021     switch (message) 
1022     { 
1023  
1024         case WM_INITDIALOG: 
1025             ShowWindow(hDlg, SW_HIDE);
1026             g_hwndConnectDlg = hDlg;
1027             CenterWindow(hDlg);
1028             ShowWindow(hDlg, SW_SHOW);
1029             SetFocus(GetDlgItem(hDlg, IDC_COMPUTER));
1030             return TRUE;
1031         case WM_COMMAND: 
1032             switch (LOWORD(wParam)) 
1033             { 
1034                 case IDOK: 
1035                     ZeroMemory(szCmp, MAX_COMPUTERNAME_LENGTH+4);
1036                     strcpy(szCmp, "\\\\");
1037                     SendMessage(GetDlgItem(hDlg, IDC_COMPUTER), WM_GETTEXT, 
1038                         (WPARAM) MAX_COMPUTERNAME_LENGTH, (LPARAM) szCmp+2); 
1039
1040                     strupr(szCmp);
1041                     if (strlen(szCmp) < 3) {
1042                         EndDialog(hDlg, TRUE); 
1043                         return TRUE;
1044                     }
1045                     am_ConnectComputer(szCmp);
1046                     SendMessage(g_hwndMain, WM_TIMER, WM_TIMER_RESCAN, 0);                        
1047                 case IDCANCEL:
1048                     EndDialog(hDlg, TRUE); 
1049                     return TRUE; 
1050                 case IDC_LBROWSE:
1051                     {
1052                         BROWSEINFO      bi;
1053                         ITEMIDLIST      *il;
1054                         LPMALLOC        pMalloc;
1055                         memset(&bi, 0, sizeof(BROWSEINFO));
1056                         SHGetSpecialFolderLocation(hDlg, CSIDL_NETWORK, &il);
1057
1058                         bi.lpszTitle      = "ApacheMonitor :\nSelect Network Computer!";
1059                         bi.pszDisplayName = szCmp;
1060                         bi.hwndOwner =      hDlg;
1061                         bi.ulFlags =        BIF_BROWSEFORCOMPUTER;
1062                         bi.lpfn =           NULL;
1063                         bi.lParam =         0;
1064                         bi.iImage =         0;
1065                         bi.pidlRoot =       il;
1066                         
1067                         if (SHBrowseForFolder(&bi) != NULL) {                     
1068                                 SendMessage(GetDlgItem(hDlg, IDC_COMPUTER), WM_SETTEXT, 
1069                                     (WPARAM) NULL, (LPARAM) szCmp); 
1070                         }
1071                         if (SHGetMalloc(&pMalloc)) {
1072                             pMalloc->lpVtbl->Free(pMalloc, il);
1073                             pMalloc->lpVtbl->Release(pMalloc);
1074                         }
1075                     }
1076                     return TRUE;
1077             }
1078         break;
1079         case WM_QUIT:
1080         case WM_CLOSE: 
1081             EndDialog(hDlg, TRUE);
1082             return TRUE;
1083         default:
1084             return FALSE;
1085     }
1086     return FALSE;
1087
1088 }
1089
1090 LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1091 {
1092
1093     CHAR        szBuf[MAX_PATH]; 
1094     HWND        hListBox;
1095     static      HWND  hStatusBar; 
1096     TEXTMETRIC  tm; 
1097     int         i, y; 
1098     HDC         hdcMem; 
1099     RECT        rcBitmap; 
1100     UINT        nItem;
1101     LPMEASUREITEMSTRUCT lpmis; 
1102     LPDRAWITEMSTRUCT    lpdis; 
1103
1104     ZeroMemory(szBuf, MAX_PATH);
1105     switch (message) 
1106     { 
1107  
1108         case WM_INITDIALOG: 
1109             ShowWindow(hDlg, SW_HIDE);
1110             g_hwndServiceDlg = hDlg;
1111             SetWindowText(hDlg, g_szTitle);
1112             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1113             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1114             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1115             Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), FALSE);
1116             SetWindowText(GetDlgItem(hDlg, IDC_SSTART), g_lpMsg[IDS_MSG_SSTART-IDS_MSG_FIRST]);
1117             SetWindowText(GetDlgItem(hDlg, IDC_SSTOP), g_lpMsg[IDS_MSG_SSTOP-IDS_MSG_FIRST]);
1118             SetWindowText(GetDlgItem(hDlg, IDC_SRESTART), g_lpMsg[IDS_MSG_SRESTART-IDS_MSG_FIRST]);
1119             SetWindowText(GetDlgItem(hDlg, IDC_SMANAGER), g_lpMsg[IDS_MSG_SERVICES-IDS_MSG_FIRST]);
1120             SetWindowText(GetDlgItem(hDlg, IDC_SCONNECT), g_lpMsg[IDS_MSG_CONNECT-IDS_MSG_FIRST]);
1121             SetWindowText(GetDlgItem(hDlg, IDC_SEXIT), g_lpMsg[IDS_MSG_MNUEXIT-IDS_MSG_FIRST]);
1122             if (g_dwOSVersion < OS_VERSION_WINNT)
1123             {
1124                 ShowWindow(GetDlgItem(hDlg, IDC_SMANAGER), SW_HIDE);
1125                 ShowWindow(GetDlgItem(hDlg, IDC_SCONNECT), SW_HIDE);
1126                 ShowWindow(GetDlgItem(hDlg, IDC_SDISCONN), SW_HIDE);
1127             }
1128             hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1129             g_hwndStdoutList = GetDlgItem(hDlg, IDL_STDOUT);
1130             hStatusBar = CreateStatusWindow(0x0800 /* SBT_TOOLTIPS */
1131                                           | WS_CHILD | WS_VISIBLE,
1132                                             "", hDlg, IDC_STATBAR);            
1133             if (GetApacheServicesStatus())
1134             {
1135                 i = 0;
1136                 while (g_stServices[i].szServiceName != NULL)
1137                 {    
1138                     addListBoxItem(hListBox, g_stServices[i].szDisplayName,
1139                         g_stServices[i].dwPid == 0 ? g_hBmpStop : g_hBmpStart);
1140                     ++i;
1141                 }
1142             }
1143             CenterWindow(hDlg);
1144             ShowWindow(hDlg, SW_SHOW);
1145             SetFocus(hListBox); 
1146             SendMessage(hListBox, LB_SETCURSEL, 0, 0); 
1147             return TRUE;
1148         break;
1149         case WM_MANAGEMESSAGE:
1150             ApacheManageService(g_stServices[LOWORD(wParam)].szServiceName,
1151                         g_stServices[LOWORD(wParam)].szImagePath,
1152                         g_stServices[LOWORD(wParam)].szComputerName,
1153                         LOWORD(lParam));
1154     
1155             return TRUE;
1156         break;
1157         case WM_UPDATEMESSAGE:
1158             hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1159             SendMessage(hListBox, LB_RESETCONTENT, 0, 0); 
1160             SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"");
1161             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1162             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1163             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1164             Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), FALSE);
1165             i = 0;
1166             while (g_stServices[i].szServiceName != NULL)
1167             {    
1168                 addListBoxItem(hListBox, g_stServices[i].szDisplayName, 
1169                     g_stServices[i].dwPid == 0 ? g_hBmpStop : g_hBmpStart);
1170                 ++i;
1171             }
1172             SendMessage(hListBox, LB_SETCURSEL, 0, 0); 
1173             /* Dirty hack to bring the window to the foreground */
1174             SetWindowPos(hDlg, HWND_TOPMOST, 0, 0, 0, 0,
1175                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1176             SetWindowPos(hDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
1177                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1178             SetFocus(hListBox); 
1179             return TRUE;
1180         break;
1181         case WM_MEASUREITEM: 
1182  
1183             lpmis = (LPMEASUREITEMSTRUCT) lParam; 
1184             lpmis->itemHeight = YBITMAP; 
1185             return TRUE; 
1186         case WM_SETCURSOR:
1187             if (g_bConsoleRun)
1188                 SetCursor(g_hCursorHourglass);
1189             else
1190                 SetCursor(g_hCursorArrow);
1191             return TRUE;
1192         case WM_DRAWITEM: 
1193             lpdis = (LPDRAWITEMSTRUCT) lParam; 
1194             if (lpdis->itemID == -1) 
1195             { 
1196                 break; 
1197             } 
1198             switch (lpdis->itemAction) 
1199             { 
1200                 case ODA_SELECT: 
1201                 case ODA_DRAWENTIRE: 
1202                     g_hBmpPicture = (HBITMAP)SendMessage(lpdis->hwndItem, 
1203                         LB_GETITEMDATA, lpdis->itemID, (LPARAM) 0); 
1204                         
1205                     hdcMem = CreateCompatibleDC(lpdis->hDC); 
1206                     g_hBmpOld = SelectObject(hdcMem, g_hBmpPicture); 
1207  
1208                     BitBlt(lpdis->hDC, 
1209                         lpdis->rcItem.left, lpdis->rcItem.top, 
1210                         lpdis->rcItem.right - lpdis->rcItem.left, 
1211                         lpdis->rcItem.bottom - lpdis->rcItem.top, 
1212                         hdcMem, 0, 0, SRCCOPY); 
1213                     SendMessage(lpdis->hwndItem, LB_GETTEXT, 
1214                         lpdis->itemID, (LPARAM) szBuf); 
1215  
1216                     GetTextMetrics(lpdis->hDC, &tm);  
1217                     y = (lpdis->rcItem.bottom + lpdis->rcItem.top - 
1218                         tm.tmHeight) / 2; 
1219   
1220                     SelectObject(hdcMem, g_hBmpOld); 
1221                     DeleteDC(hdcMem); 
1222  
1223                     rcBitmap.left = lpdis->rcItem.left + XBITMAP + 2; 
1224                     rcBitmap.top = lpdis->rcItem.top; 
1225                     rcBitmap.right = lpdis->rcItem.right; 
1226                     rcBitmap.bottom = lpdis->rcItem.top + YBITMAP; 
1227
1228                     if (lpdis->itemState & ODS_SELECTED) 
1229                     { 
1230                         if (g_hBmpPicture == g_hBmpStop)
1231                         {
1232                             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
1233                             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1234                             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1235                         }
1236                         else if (g_hBmpPicture == g_hBmpStart) 
1237                         {
1238                             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1239                             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
1240                             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
1241                         }
1242                         else {
1243                             Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1244                             Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1245                             Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1246                         }
1247                         if (strcmp(g_stServices[lpdis->itemID].szComputerName, g_szLocalHost) == 0)
1248                             Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), FALSE);
1249                         else
1250                             Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), TRUE);
1251
1252                         if (g_stServices[lpdis->itemID].szDescription)
1253                             SendMessage(hStatusBar, SB_SETTEXT, 0, 
1254                                         (LPARAM)g_stServices[lpdis->itemID].szDescription);
1255                         else
1256                             SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"");
1257                         
1258                         SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 
1259                         SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); 
1260                         FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_HIGHLIGHTTEXT)); 
1261                     } 
1262                     else
1263                     {
1264                        SetTextColor(lpdis->hDC, GetSysColor(COLOR_MENUTEXT)); 
1265                        SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW)); 
1266                        FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_WINDOW+1)); 
1267                     }
1268                     TextOut(lpdis->hDC, 
1269                         XBITMAP + 6, 
1270                         y, 
1271                         szBuf, 
1272                         strlen(szBuf)); 
1273                     break; 
1274  
1275                 case ODA_FOCUS: 
1276                     break; 
1277             } 
1278             return TRUE;  
1279         case WM_COMMAND: 
1280             switch (LOWORD(wParam)) 
1281             { 
1282                 case IDL_SERVICES:
1283                     switch (HIWORD(wParam))
1284                     {
1285                         case LBN_DBLCLK:
1286                             /* if started then stop, if stopped then start the service */
1287                             hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1288                             nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1289                             if (nItem != LB_ERR)
1290                             {
1291                                 g_hBmpPicture = (HBITMAP)SendMessage(hListBox, LB_GETITEMDATA,
1292                                                                nItem, (LPARAM) 0); 
1293                                 if (g_hBmpPicture == g_hBmpStop)
1294                                 {
1295                                     SendMessage(hDlg, WM_MANAGEMESSAGE, nItem, SERVICE_CONTROL_CONTINUE);                                    
1296                                 }
1297                                 else
1298                                     SendMessage(hDlg, WM_MANAGEMESSAGE, nItem, SERVICE_CONTROL_STOP);                                    
1299
1300                             }
1301                             return TRUE;
1302                         break;
1303                      }
1304                 break;
1305                 case IDOK: 
1306                     EndDialog(hDlg, TRUE); 
1307                     return TRUE; 
1308                 case IDC_SSTART: 
1309                     Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1310                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1311                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1312                     if (nItem != LB_ERR)
1313                     {
1314                         SendMessage(hDlg, WM_MANAGEMESSAGE, nItem, SERVICE_CONTROL_CONTINUE);                                    
1315                     }
1316                     Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
1317                     return TRUE;
1318                 case IDC_SSTOP: 
1319                     Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1320                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1321                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1322                     if (nItem != LB_ERR)
1323                     {
1324                         SendMessage(hDlg, WM_MANAGEMESSAGE, nItem, SERVICE_CONTROL_STOP);                                    
1325                     }
1326                     Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
1327                     return TRUE;
1328                 case IDC_SRESTART: 
1329                     Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1330                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1331                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1332                     if (nItem != LB_ERR)
1333                     {
1334                         SendMessage(hDlg, WM_MANAGEMESSAGE, nItem, SERVICE_APACHE_RESTART);                                    
1335                     }
1336                     Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
1337                     return TRUE;
1338                 case IDC_SMANAGER: 
1339                     if (g_dwOSVersion >= OS_VERSION_WIN2K)
1340                         ShellExecute(hDlg, "open", "services.msc", "/s", NULL, SW_NORMAL);
1341                     else
1342                         WinExec("Control.exe SrvMgr.cpl Services", SW_NORMAL);
1343                     return TRUE;
1344                 case IDC_SEXIT: 
1345                     EndDialog( hDlg, TRUE);
1346                     SendMessage( g_hwndMain, WM_COMMAND, (WPARAM)IDM_EXIT, 0);
1347                     return TRUE;
1348                 case IDC_SCONNECT: 
1349                     DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DLGCONNECT),
1350                                     hDlg, (DLGPROC)ConnectDlgProc);
1351                     return TRUE;
1352                 case IDC_SDISCONN: 
1353                     hListBox = GetDlgItem(hDlg, IDL_SERVICES); 
1354                     nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0); 
1355                     if (nItem != LB_ERR) {
1356                         am_DisconnectComputer(g_stServices[nItem].szComputerName);
1357                         SendMessage(g_hwndMain, WM_TIMER, WM_TIMER_RESCAN, 0);                        
1358                     }
1359                     return TRUE;
1360              }
1361         break;
1362         case WM_SIZE:
1363             switch (LOWORD(wParam)) 
1364             { 
1365                 case SIZE_MINIMIZED:
1366                     EndDialog(hDlg, TRUE); 
1367                     return TRUE; 
1368                 break;
1369             }
1370         break;
1371         case WM_QUIT:
1372         case WM_CLOSE: 
1373             EndDialog(hDlg, TRUE);
1374             return TRUE;
1375         default:
1376             return FALSE;
1377     }
1378     return FALSE;
1379 }
1380
1381
1382 LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
1383                           WPARAM wParam, LPARAM lParam)
1384 {
1385     if (message == g_bUiTaskbarCreated)
1386     {
1387         /* restore the tray icon on shell restart */
1388         ShowNotifyIcon(hWnd, NIM_ADD);
1389         return DefWindowProc(hWnd, message, wParam, lParam);
1390     }
1391     switch (message) 
1392     {
1393         case WM_CREATE:
1394             GetApacheServicesStatus();
1395             ShowNotifyIcon(hWnd, NIM_ADD);
1396             SetTimer(hWnd, WM_TIMER_REFRESH, REFRESH_TIME, NULL);
1397             SetTimer(hWnd, WM_TIMER_RESCAN,  RESCAN_TIME, NULL);
1398             break;
1399         case WM_TIMER:
1400             switch (wParam)
1401             {
1402                 case WM_TIMER_RESCAN:
1403                 {
1404                     int nPrev = 0, nNew = 0;
1405                     EnterCriticalSection(&g_stcSection);
1406                     if (FindRunningServices() || g_bRescanServices)
1407                     {
1408                         ShowNotifyIcon(hWnd, NIM_MODIFY);
1409                         if (g_hwndServiceDlg)
1410                             PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1411                     }
1412                     /* check if services list changed */
1413                     while (g_stServices[nPrev].szServiceName != NULL)
1414                         ++nPrev;
1415                     GetApacheServicesStatus();
1416                     while (g_stServices[nNew].szServiceName != NULL)
1417                         ++nNew;
1418                     if (nPrev != nNew)
1419                     {
1420                         ShowNotifyIcon(hWnd, NIM_MODIFY);
1421                         if (g_hwndServiceDlg)
1422                             PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1423                     }
1424                     LeaveCriticalSection(&g_stcSection);
1425                 break;
1426                 }
1427                 case WM_TIMER_REFRESH:
1428                 {
1429                     int nPrev = 0, nNew = 0;
1430                     EnterCriticalSection(&g_stcSection);
1431                     if (g_bRescanServices)
1432                     {       
1433                         GetApacheServicesStatus();
1434                         ShowNotifyIcon(hWnd, NIM_MODIFY);
1435                         if (g_hwndServiceDlg)
1436                             PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1437                     }
1438                     else if (FindRunningServices())
1439                     {
1440                         ShowNotifyIcon(hWnd, NIM_MODIFY);
1441                         if (g_hwndServiceDlg)
1442                             PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1443                     }
1444                     LeaveCriticalSection(&g_stcSection);
1445                     break;
1446                 }
1447             }
1448             break;
1449         case WM_QUIT:
1450             ShowNotifyIcon(hWnd, NIM_DELETE);
1451             break;
1452         case WM_TRAYMESSAGE:
1453             switch(lParam)
1454             {
1455                 case WM_LBUTTONDBLCLK:
1456                    if (!g_bDlgServiceOn)
1457                    {
1458                        g_bDlgServiceOn = TRUE;
1459                        DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DLGSERVICES),
1460                              hWnd, (DLGPROC)ServiceDlgProc);
1461                        g_bDlgServiceOn = FALSE;
1462                        g_hwndServiceDlg = NULL;
1463                    }
1464                    else if (IsWindow(g_hwndServiceDlg))
1465                    {
1466                        /* Dirty hack to bring the window to the foreground */
1467                        SetWindowPos(g_hwndServiceDlg, HWND_TOPMOST, 0, 0, 0, 0,
1468                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1469                        SetWindowPos(g_hwndServiceDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
1470                                     SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1471                        SetFocus(g_hwndServiceDlg);
1472                    }
1473                 break;
1474                 case WM_LBUTTONUP:
1475                     ShowTryServicesMenu(hWnd);
1476                 break;    
1477                 case WM_RBUTTONUP:
1478                     ShowTryPopupMenu(hWnd);
1479                 break;    
1480             }
1481             break;
1482         case WM_COMMAND:
1483             if ((LOWORD(wParam) & IDM_SM_START) == IDM_SM_START)
1484             {
1485                 ApacheManageService(g_stServices[LOWORD(wParam) - IDM_SM_START].szServiceName,
1486                                     g_stServices[LOWORD(wParam) - IDM_SM_START].szImagePath,
1487                                     g_stServices[LOWORD(wParam) - IDM_SM_START].szComputerName,
1488                                     SERVICE_CONTROL_CONTINUE);                
1489                 return TRUE;
1490             }
1491             else if ((LOWORD(wParam) & IDM_SM_STOP) == IDM_SM_STOP)
1492             {
1493                 ApacheManageService(g_stServices[LOWORD(wParam) - IDM_SM_STOP].szServiceName,
1494                                     g_stServices[LOWORD(wParam) - IDM_SM_STOP].szImagePath,
1495                                     g_stServices[LOWORD(wParam) - IDM_SM_STOP].szComputerName,
1496                                     SERVICE_CONTROL_STOP);                
1497                 return TRUE;
1498             }
1499             else if ((LOWORD(wParam) & IDM_SM_RESTART) == IDM_SM_RESTART)
1500             {
1501                 ApacheManageService(g_stServices[LOWORD(wParam) - IDM_SM_RESTART].szServiceName,
1502                                     g_stServices[LOWORD(wParam) - IDM_SM_RESTART].szImagePath,
1503                                     g_stServices[LOWORD(wParam) - IDM_SM_RESTART].szComputerName,
1504                                     SERVICE_APACHE_RESTART);                
1505                 return TRUE;
1506             }
1507             switch (LOWORD(wParam))
1508             {
1509                case IDM_RESTORE:
1510                    if (!g_bDlgServiceOn)
1511                    {
1512                        g_bDlgServiceOn = TRUE;
1513                        DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DLGSERVICES),
1514                              hWnd, (DLGPROC)ServiceDlgProc);
1515                        g_bDlgServiceOn = FALSE;
1516                        g_hwndServiceDlg = NULL;
1517                    }
1518                    else if (IsWindow(g_hwndServiceDlg))
1519                        SetFocus(g_hwndServiceDlg);
1520                    break;
1521                 case IDC_SMANAGER: 
1522                     if (g_dwOSVersion >= OS_VERSION_WIN2K)
1523                         ShellExecute(NULL, "open", "services.msc", "/s", NULL, SW_NORMAL);
1524                     else
1525                         WinExec("Control.exe SrvMgr.cpl Services", SW_NORMAL);
1526                     return TRUE;
1527                case IDM_EXIT:
1528                    ShowNotifyIcon(hWnd, NIM_DELETE);
1529                    PostQuitMessage(0);
1530                    return TRUE;
1531             }
1532         default:
1533             return DefWindowProc(hWnd, message, wParam, lParam);
1534     }
1535
1536     return FALSE;
1537 }
1538
1539 /* Create main invisible window */
1540 HWND CreateMainWindow(HINSTANCE hInstance)
1541 {
1542     HWND       hWnd = NULL;
1543     WNDCLASSEX wcex;
1544
1545     if (!GetSystemOSVersion(&g_dwOSVersion))
1546     {
1547         ErrorMessage(NULL, TRUE);
1548         return hWnd;
1549     }
1550
1551     wcex.cbSize = sizeof(WNDCLASSEX); 
1552
1553     wcex.style          = CS_HREDRAW | CS_VREDRAW;
1554     wcex.lpfnWndProc    = (WNDPROC)WndProc;
1555     wcex.cbClsExtra     = 0;
1556     wcex.cbWndExtra     = 0;
1557     wcex.hInstance      = hInstance;
1558     wcex.hIcon          = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_APSRVMON),
1559                                            IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
1560     wcex.hCursor        = g_hCursorArrow;
1561     wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
1562     wcex.lpszMenuName   = 0;
1563     wcex.lpszClassName  = g_szWindowClass;
1564     wcex.hIconSm        = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_APSRVMON),
1565                                            IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1566
1567     if (RegisterClassEx(&wcex))
1568         hWnd = CreateWindow(g_szWindowClass, g_szTitle,
1569                              0, 0, 0, 0, 0,
1570                              NULL, NULL, hInstance, NULL);
1571
1572     return hWnd;
1573
1574 }
1575
1576
1577 int WINAPI WinMain(HINSTANCE hInstance,
1578                     HINSTANCE hPrevInstance,
1579                     LPSTR lpCmdLine,
1580                     int nCmdShow)
1581 {
1582     CHAR szTmp[MAX_LOADSTRING];
1583     CHAR szCmp[MAX_COMPUTERNAME_LENGTH+4];
1584     MSG     msg;
1585     /* single instance mutex */
1586     HANDLE hMutex;
1587     int i;
1588     DWORD d;
1589
1590     g_LangID = GetUserDefaultLangID();
1591     if ((g_LangID & 0xFF) != LANG_ENGLISH)
1592         g_LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
1593     
1594     for (i = IDS_MSG_FIRST; i <= IDS_MSG_LAST; ++i) {
1595         LoadString(hInstance, i, szTmp, MAX_LOADSTRING);
1596         g_lpMsg[i - IDS_MSG_FIRST] = strdup(szTmp);
1597     }
1598     LoadString(hInstance, IDS_APMONITORTITLE, szTmp, MAX_LOADSTRING);
1599     d = MAX_COMPUTERNAME_LENGTH+1;
1600     strcpy(szCmp, "\\\\");
1601     GetComputerName(szCmp + 2, &d);
1602     strupr(szCmp);
1603     g_szLocalHost = strdup(szCmp);
1604
1605     ZeroMemory(g_stComputers, sizeof(ST_MONITORED_COMP) * MAX_APACHE_COMPUTERS);
1606     g_stComputers[0].szComputerName = strdup(szCmp);
1607     g_stComputers[0].hRegistry = HKEY_LOCAL_MACHINE;
1608     g_szTitle = strdup(szTmp);
1609     LoadString(hInstance, IDS_APMONITORCLASS, szTmp, MAX_LOADSTRING);
1610     g_szWindowClass = strdup(szTmp);
1611
1612     g_icoStop          = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICOSTOP),
1613                                    IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1614     g_icoRun           = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICORUN),
1615                                    IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1616     g_hCursorHourglass = LoadImage(NULL, MAKEINTRESOURCE(OCR_WAIT), IMAGE_CURSOR,
1617                                    LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED);
1618     g_hCursorArrow     = LoadImage(NULL, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR,
1619                                    LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED);
1620     g_hBmpStart        = LoadImage(hInstance, MAKEINTRESOURCE(IDB_BMPRUN),
1621                                    IMAGE_BITMAP, XBITMAP, YBITMAP, LR_DEFAULTCOLOR);
1622     g_hBmpStop         = LoadImage(hInstance, MAKEINTRESOURCE(IDB_BMPSTOP),
1623                                    IMAGE_BITMAP, XBITMAP, YBITMAP, LR_DEFAULTCOLOR);
1624
1625     hMutex = CreateMutex(NULL, FALSE, "APSRVMON_MUTEX");
1626     if ((hMutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
1627     {
1628         ErrorMessage(g_lpMsg[IDS_MSG_APPRUNNING-IDS_MSG_FIRST], FALSE);
1629         if (hMutex)
1630             CloseHandle(hMutex);
1631
1632         return 0;
1633     }
1634
1635     ZeroMemory(g_stServices, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
1636     CoInitialize(NULL);
1637     InitCommonControls();
1638     g_hInstance = hInstance;
1639     g_hwndMain = CreateMainWindow(hInstance);
1640     g_bUiTaskbarCreated = RegisterWindowMessage("TaskbarCreated");
1641     InitializeCriticalSection(&g_stcSection);
1642     g_hwndServiceDlg = NULL;                      
1643     if (g_hwndMain != NULL)
1644     {
1645         while (GetMessage(&msg, NULL, 0, 0) == TRUE) 
1646         {
1647             TranslateMessage(&msg);
1648             DispatchMessage(&msg);
1649         }    
1650         am_ClearServicesSt();
1651     }
1652     am_ClearComputersSt();
1653     DeleteCriticalSection(&g_stcSection);
1654     CloseHandle(hMutex);
1655     DestroyIcon(g_icoStop);
1656     DestroyIcon(g_icoRun);
1657     DestroyCursor(g_hCursorHourglass);
1658     DestroyCursor(g_hCursorArrow);
1659     DeleteObject(g_hBmpStart); 
1660     DeleteObject(g_hBmpStop); 
1661     CoUninitialize();
1662     return 0;
1663 }