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