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