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