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