1 /* ====================================================================
2 * The Apache Software License, Version 1.1
4 * Copyright (c) 2000 The Apache Software Foundation. All rights
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. The end-user documentation included with the redistribution,
20 * if any, must include the following acknowledgment:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowledgment may appear in the software itself,
24 * if and wherever such third-party acknowledgments normally appear.
26 * 4. The names "Apache" and "Apache Software Foundation" must
27 * not be used to endorse or promote products derived from this
28 * software without prior written permission. For written
29 * permission, please contact apache@apache.org.
31 * 5. Products derived from this software may not be called "Apache",
32 * nor may "Apache" appear in their name, without prior written
33 * permission of the Apache Software Foundation.
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * ====================================================================
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
54 * Portions of this software are based upon public domain software
55 * originally written at the National Center for Supercomputing Applications,
56 * University of Illinois, Urbana-Champaign.
59 /* ====================================================================
60 * ApacheMonitor.c Simple program to manage and monitor Apache services.
62 * Contributed by Mladen Turk <mturk@mappingsoft.com>
65 * ====================================================================
68 #define _WIN32_WINNT 0x0400
81 #include "ApacheMonitor.h"
84 #define OS_VERSION_WIN9X 1
85 #define OS_VERSION_WINNT 2
86 #define OS_VERSION_WIN2K 3
87 /* Should be enough */
88 #define MAX_APACHE_SERVICES 128
90 #define WM_TRAYMESSAGE (WM_APP+1)
91 #define WM_UPDATEMESSAGE (WM_USER+1)
92 #define WM_TIMER_REFRESH 10
93 #define WM_TIMER_RESCAN 11
94 #define SERVICE_APACHE_RESTART 128
97 #define MAX_LOADSTRING 100
98 #define REFRESH_TIME 2000 /* service refresh time (ms) */
99 #define RESCAN_TIME 20000 /* registry rescan time (ms) */
101 typedef struct _st_APACHE_SERVICE
110 /* Global variables */
111 HINSTANCE g_hInstance = NULL;
112 TCHAR *g_szTitle; /* The title bar text */
113 TCHAR *g_szWindowClass; /* Window Class Name */
116 UINT g_bUiTaskbarCreated;
118 BOOL g_bDlgServiceOn = FALSE;
119 BOOL g_bConsoleRun = FALSE;
120 ST_APACHE_SERVICE g_stServices[MAX_APACHE_SERVICES];
122 HBITMAP g_hBmpStart, g_hBmpStop;
123 HBITMAP g_hBmpPicture, g_hBmpOld;
124 BOOL g_bRescanServices;
125 HWND g_hwndServiceDlg;
127 HWND g_hwndStdoutList;
128 HCURSOR g_hCursorHourglass;
129 HCURSOR g_hCursorArrow;
131 HANDLE g_hpipeOutRead;
132 HANDLE g_hpipeOutWrite;
133 HANDLE g_hpipeInRead;
134 HANDLE g_hpipeInWrite;
135 HANDLE g_hpipeStdError;
137 PROCESS_INFORMATION g_lpRedirectProc;
138 CRITICAL_SECTION g_stcSection;
141 /* locale language support */
142 static CHAR *g_lpMsg[IDS_MSG_LAST - IDS_MSG_FIRST + 1];
144 void am_ClearServicesSt()
147 for (i = 0; i < MAX_APACHE_SERVICES; i++)
149 if (g_stServices[i].szServiceName)
150 free(g_stServices[i].szServiceName);
151 if (g_stServices[i].szDisplayName)
152 free(g_stServices[i].szDisplayName);
153 if (g_stServices[i].szDescription)
154 free(g_stServices[i].szDescription);
155 if (g_stServices[i].szImagePath)
156 free(g_stServices[i].szImagePath);
159 ZeroMemory(g_stServices, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
163 void ErrorMessage(LPCSTR szError, BOOL bFatal)
165 LPVOID lpMsgBuf = NULL;
167 MessageBox(NULL, szError, g_lpMsg[IDS_MSG_ERROR-IDS_MSG_FIRST],
168 MB_OK | (bFatal ? MB_ICONERROR : MB_ICONEXCLAMATION));
171 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
172 FORMAT_MESSAGE_FROM_SYSTEM |
173 FORMAT_MESSAGE_IGNORE_INSERTS,
177 (LPSTR) &lpMsgBuf, 0, NULL);
178 MessageBox(NULL, (LPCSTR)lpMsgBuf, g_lpMsg[IDS_MSG_ERROR-IDS_MSG_FIRST],
179 MB_OK | (bFatal ? MB_ICONERROR : MB_ICONEXCLAMATION));
186 LPSTR GetStringRes(int id)
188 static TCHAR buffer[MAX_PATH];
191 LoadString(GetModuleHandle (NULL), id, buffer, MAX_PATH);
195 BOOL GetSystemOSVersion(LPDWORD dwVersion)
199 Try calling GetVersionEx using the OSVERSIONINFOEX structure.
200 If that fails, try using the OSVERSIONINFO structure.
202 ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
203 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
205 if (!GetVersionEx(&osvi))
208 switch (osvi.dwPlatformId)
210 case VER_PLATFORM_WIN32_NT:
211 if (osvi.dwMajorVersion <= 4)
212 *dwVersion = OS_VERSION_WINNT;
213 else if (osvi.dwMajorVersion == 5)
214 *dwVersion = OS_VERSION_WIN2K;
219 case VER_PLATFORM_WIN32_WINDOWS:
220 *dwVersion = OS_VERSION_WIN9X;
223 case VER_PLATFORM_WIN32s:
233 static VOID ShowNotifyIcon(HWND hWnd, DWORD dwMessage)
239 ZeroMemory(&nid,sizeof(nid));
240 nid.cbSize = sizeof(NOTIFYICONDATA);
243 nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
244 nid.uCallbackMessage = WM_TRAYMESSAGE;
246 while (g_stServices[i].szServiceName != NULL)
248 if (g_stServices[i].dwPid != 0)
252 if (dwMessage != NIM_DELETE)
255 nid.hIcon = g_icoRun;
257 nid.hIcon = g_icoStop;
262 lstrcpy(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGALL-IDS_MSG_FIRST]);
264 sprintf(nid.szTip, g_lpMsg[IDS_MSG_RUNNING-IDS_MSG_FIRST], n, i);
266 sprintf(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGNONE-IDS_MSG_FIRST], i);
268 lstrcpy(nid.szTip, g_lpMsg[IDS_MSG_NOSERVICES-IDS_MSG_FIRST]);
269 Shell_NotifyIcon(dwMessage, &nid);
272 void appendMenuItem(HMENU hMenu, UINT uMenuId, LPSTR szName, BOOL fDefault)
276 ZeroMemory(&mii, sizeof(MENUITEMINFO));
277 mii.cbSize = sizeof(MENUITEMINFO);
278 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
281 mii.fType = MFT_STRING;
284 mii.fState = MFS_DEFAULT;
285 mii.dwTypeData = szName;
288 mii.fType = MFT_SEPARATOR;
289 InsertMenuItem(hMenu, uMenuId, FALSE, &mii);
292 void ShowTryPopupMenu(HWND hWnd)
294 /* create popup menu */
295 HMENU hMenu = CreatePopupMenu();
300 appendMenuItem(hMenu, IDM_RESTORE, g_lpMsg[IDS_MSG_MNUSHOW-IDS_MSG_FIRST], TRUE);
301 if (g_dwOSVersion >= OS_VERSION_WINNT)
302 appendMenuItem(hMenu, IDC_SMANAGER, g_lpMsg[IDS_MSG_MNUSERVICES-IDS_MSG_FIRST], FALSE);
303 appendMenuItem(hMenu, 0, "", FALSE);
304 appendMenuItem(hMenu, IDM_EXIT, g_lpMsg[IDS_MSG_MNUEXIT-IDS_MSG_FIRST], FALSE);
307 SetForegroundWindow(NULL);
308 TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, 0, hWnd, NULL);
312 BOOL CenterWindow(HWND hwndChild)
314 RECT rChild, rWorkArea;
319 /* Get the Height and Width of the child window */
320 GetWindowRect(hwndChild, &rChild);
321 wChild = rChild.right - rChild.left;
322 hChild = rChild.bottom - rChild.top;
324 /* Get the limits of the 'workarea' */
325 bResult = SystemParametersInfo(
331 rWorkArea.left = rWorkArea.top = 0;
332 rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
333 rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
336 /* Calculate new X and Y position*/
337 xNew = (rWorkArea.right - wChild)/2;
338 yNew = (rWorkArea.bottom - hChild)/2;
339 return SetWindowPos (hwndChild, HWND_TOP, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
342 static void addListBoxItem(HWND hDlg, LPSTR lpStr, HBITMAP hBmp)
346 nItem = SendMessage(hDlg, LB_ADDSTRING, 0, (LPARAM)lpStr);
347 SendMessage(hDlg, LB_SETITEMDATA, nItem, (LPARAM)hBmp);
350 static void addListBoxString(HWND hListBox, LPSTR lpStr)
352 static int nItems = 0;
354 if ( nItems > MAX_LOADSTRING)
356 SendMessage(hListBox, LB_RESETCONTENT, 0, 0);
359 ListBox_SetCurSel(hListBox,
360 ListBox_AddString(hListBox, lpStr));
363 static DWORD WINAPI ConsoleOutputThread(LPVOID lpThreadParameter)
365 static BYTE lpBuffer[MAX_PATH+1];
370 while (ReadFile(g_hpipeOutRead, &ch, 1, &dwReaded, NULL) == TRUE)
374 if (ch == '\n' || nPtr >= MAX_PATH)
376 lpBuffer[nPtr] = '\0';
377 addListBoxString(g_hwndStdoutList, lpBuffer);
380 else if (ch == '\t' && nPtr < (MAX_PATH - 4))
383 for (i = 0; i < 4; ++i)
384 lpBuffer[nPtr++] = ' ';
387 lpBuffer[nPtr++] = ch;
390 CloseHandle(g_hpipeInWrite);
391 CloseHandle(g_hpipeOutRead);
392 CloseHandle(g_hpipeStdError);
397 DWORD WINAPI ConsoleWaitingThread(LPVOID lpThreadParameter)
399 WaitForSingleObject(g_lpRedirectProc.hThread, INFINITE);
400 CloseHandle(g_lpRedirectProc.hThread);
402 g_bConsoleRun = FALSE;
403 SetCursor(g_hCursorArrow);
408 BOOL RunRedirectedConsole(LPSTR szCmdLine)
415 ZeroMemory(&stInfo, sizeof(stInfo));
416 stInfo.cb = sizeof(stInfo);
417 stInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
418 stInfo.wShowWindow = SW_HIDE;
420 hProc = GetCurrentProcess();
422 if (!CreatePipe(&g_hpipeInRead, &g_hpipeInWrite, NULL, MAX_PATH))
423 ErrorMessage(NULL, TRUE);
424 if (!CreatePipe(&g_hpipeOutRead, &g_hpipeOutWrite, NULL, MAX_PATH*8))
425 ErrorMessage(NULL, TRUE);
427 DuplicateHandle(hProc, g_hpipeInRead, hProc, &g_hpipeInRead, 0, TRUE,
428 DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
429 DuplicateHandle(hProc, g_hpipeOutWrite, hProc, &g_hpipeOutWrite, 0, TRUE,
430 DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
431 DuplicateHandle(hProc, g_hpipeOutWrite, hProc, &g_hpipeStdError, 0, TRUE,
432 DUPLICATE_SAME_ACCESS);
433 if (!g_hpipeInRead && !g_hpipeOutWrite && !g_hpipeStdError)
434 ErrorMessage(NULL, TRUE);
436 stInfo.hStdInput = g_hpipeInRead;
437 stInfo.hStdOutput = g_hpipeOutWrite;
438 stInfo.hStdError = g_hpipeStdError;
440 bResult = CreateProcess(NULL,
452 CloseHandle(g_hpipeInRead);
453 CloseHandle(g_hpipeOutWrite);
454 CloseHandle(g_hpipeStdError);
458 CloseHandle(g_hpipeInWrite);
459 CloseHandle(g_hpipeOutRead);
460 CloseHandle(g_hpipeStdError);
464 CloseHandle(CreateThread(NULL, 0, ConsoleOutputThread, 0, 0, &dwThreadId));
465 ResumeThread(g_lpRedirectProc.hThread);
466 CloseHandle(CreateThread(NULL, 0, ConsoleWaitingThread, 0, 0, &dwThreadId));
471 BOOL RunAndForgetConsole(LPSTR szCmdLine,
472 BOOL bRedirectConsole)
476 PROCESS_INFORMATION prInfo;
479 if (bRedirectConsole)
480 return RunRedirectedConsole(szCmdLine);
483 ZeroMemory(&stInfo, sizeof(stInfo));
484 stInfo.cb = sizeof(stInfo);
485 stInfo.dwFlags = STARTF_USESHOWWINDOW;
486 stInfo.wShowWindow = SW_HIDE;
488 bResult = CreateProcess(NULL,
503 if (g_dwOSVersion == OS_VERSION_WIN9X) /* give some time to rescan the status */
505 CloseHandle(prInfo.hThread);
506 CloseHandle(prInfo.hProcess);
510 BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, DWORD dwCommand)
513 CHAR szBuf[MAX_PATH];
514 CHAR szMsg[MAX_PATH];
517 BOOL serviceFlag = TRUE;
518 SC_HANDLE schService;
519 SC_HANDLE schSCManager;
520 SERVICE_STATUS schSStatus;
524 if (g_dwOSVersion == OS_VERSION_WIN9X)
526 sPos = strstr(szImagePath, "-k start");
529 lstrcpyn(szBuf, szImagePath, sPos - szImagePath);
532 case SERVICE_CONTROL_STOP:
533 lstrcat(szBuf, " -k stop -n ");
535 case SERVICE_CONTROL_CONTINUE:
536 sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART-IDS_MSG_FIRST], szServiceName);
537 addListBoxString(g_hwndStdoutList, szMsg);
538 lstrcat(szBuf, " -k start -n ");
541 case SERVICE_APACHE_RESTART:
542 lstrcat(szBuf, " -k restart -n ");
547 lstrcat(szBuf, szServiceName);
551 g_bConsoleRun = TRUE;
552 SetCursor(g_hCursorHourglass);
553 if (!RunAndForgetConsole(szBuf, serviceFlag))
555 ErrorMessage(NULL, FALSE);
556 g_bConsoleRun = FALSE;
557 SetCursor(g_hCursorArrow);
560 else if (!serviceFlag)
562 sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTARTED-IDS_MSG_FIRST], szServiceName);
563 addListBoxString(g_hwndStdoutList, szMsg);
564 g_bConsoleRun = FALSE;
565 SetCursor(g_hCursorArrow);
571 /* Apache 2.0 uses '-k runservice' as cmdline parameter */
572 sPos = strstr(szImagePath, "--ntservice");
575 sPos = strstr(szImagePath, "-k runservice");
579 lstrcpyn(szBuf, szImagePath, sPos - szImagePath);
582 schSCManager = OpenSCManager(
585 SC_MANAGER_ALL_ACCESS
590 schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);
591 if (schService != NULL)
594 g_bConsoleRun = TRUE;
595 SetCursor(g_hCursorHourglass);
598 case SERVICE_CONTROL_STOP:
599 sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTOP-IDS_MSG_FIRST], szServiceName);
600 addListBoxString(g_hwndStdoutList, szMsg);
601 if(ControlService(schService, SERVICE_CONTROL_STOP, &schSStatus))
604 while (QueryServiceStatus(schService, &schSStatus))
606 if (schSStatus.dwCurrentState == SERVICE_STOP_PENDING)
612 if (QueryServiceStatus(schService, &schSStatus))
614 if(schSStatus.dwCurrentState == SERVICE_STOPPED)
617 sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTOPPED-IDS_MSG_FIRST], szServiceName);
618 addListBoxString(g_hwndStdoutList, szMsg);
622 case SERVICE_CONTROL_CONTINUE:
623 sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART-IDS_MSG_FIRST], szServiceName);
624 addListBoxString(g_hwndStdoutList, szMsg);
625 args = (char **)malloc(3 * sizeof(char*));
628 args[1] = "--ntservice";
632 args[2] = "runservice";
634 if(StartService(schService, serviceFlag ? 2 : 3, args))
637 while (QueryServiceStatus(schService, &schSStatus))
639 if (schSStatus.dwCurrentState == SERVICE_START_PENDING)
645 if (QueryServiceStatus(schService, &schSStatus))
647 if(schSStatus.dwCurrentState == SERVICE_RUNNING)
650 sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTARTED-IDS_MSG_FIRST], szServiceName);
651 addListBoxString(g_hwndStdoutList, szMsg);
654 /* is this OK to do? */
657 case SERVICE_APACHE_RESTART:
658 sprintf(szMsg, g_lpMsg[IDS_MSG_SRVRESTART-IDS_MSG_FIRST], szServiceName);
659 addListBoxString(g_hwndStdoutList, szMsg);
660 if(ControlService(schService, SERVICE_APACHE_RESTART, &schSStatus))
663 while(schSStatus.dwCurrentState == SERVICE_START_PENDING)
666 if(!QueryServiceStatus(schService, &schSStatus))
668 CloseServiceHandle(schService);
669 CloseServiceHandle(schSCManager);
670 g_bConsoleRun = FALSE;
671 SetCursor(g_hCursorArrow);
678 if(schSStatus.dwCurrentState == SERVICE_RUNNING)
681 sprintf(szMsg, g_lpMsg[IDS_MSG_SRVRESTARTED-IDS_MSG_FIRST], szServiceName);
682 addListBoxString(g_hwndStdoutList, szMsg);
686 CloseServiceHandle(schService);
687 CloseServiceHandle(schSCManager);
689 ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED-IDS_MSG_FIRST], FALSE);
690 g_bConsoleRun = FALSE;
691 SetCursor(g_hCursorArrow);
696 g_bRescanServices = TRUE;
698 CloseServiceHandle(schSCManager);
705 BOOL IsServiceRunning(LPCSTR szServiceName, LPDWORD lpdwPid)
710 SC_HANDLE schService;
711 SC_HANDLE schSCManager;
712 SERVICE_STATUS schSStatus;
714 if (g_dwOSVersion == OS_VERSION_WIN9X)
716 hWnd = FindWindow("ApacheWin95ServiceMonitor", szServiceName);
717 if (hWnd && GetWindowThreadProcessId(hWnd, &dwPid))
729 schSCManager = OpenSCManager(
732 SC_MANAGER_ALL_ACCESS
737 schService = OpenService(schSCManager, szServiceName, SERVICE_QUERY_STATUS);
738 if (schService != NULL)
740 if (QueryServiceStatus(schService, &schSStatus))
743 dwPid = schSStatus.dwCurrentState;
747 CloseServiceHandle(schService);
748 CloseServiceHandle(schSCManager);
749 return dwPid == SERVICE_RUNNING ? TRUE : FALSE;
752 g_bRescanServices = TRUE;
754 CloseServiceHandle(schSCManager);
762 BOOL FindRunningServices()
767 while (g_stServices[i].szServiceName != NULL)
769 if (!IsServiceRunning(g_stServices[i].szServiceName, &dwPid))
771 if (g_stServices[i].dwPid != dwPid)
773 g_stServices[i].dwPid = dwPid;
779 BOOL GetApacheServicesStatus()
782 CHAR szKey[MAX_PATH];
783 CHAR achKey[MAX_PATH];
784 CHAR szImagePath[MAX_PATH];
785 CHAR szBuf[MAX_PATH];
788 DWORD retCode, rv, dwKeyType;
789 DWORD dwBufLen = MAX_PATH;
792 g_bRescanServices = FALSE;
794 retCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
795 "System\\CurrentControlSet\\Services\\",
797 if (retCode != ERROR_SUCCESS)
799 ErrorMessage(NULL, FALSE);
802 am_ClearServicesSt();
803 for (i = 0, retCode = ERROR_SUCCESS; retCode == ERROR_SUCCESS; i++)
806 retCode = RegEnumKey(hKey, i, achKey, MAX_PATH);
807 if (retCode == ERROR_SUCCESS)
809 lstrcpy(szKey, "System\\CurrentControlSet\\Services\\");
810 lstrcat(szKey, achKey);
812 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0,
813 KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS)
816 rv = RegQueryValueEx(hSubKey, "ImagePath", NULL,
817 &dwKeyType, szImagePath, &dwBufLen);
819 if (rv == ERROR_SUCCESS && (dwKeyType == REG_SZ || dwKeyType == REG_EXPAND_SZ) && dwBufLen)
821 lstrcpy(szBuf, szImagePath);
823 /* the service name could be Apache*.exe */
824 if (strstr(szBuf, "\\apache") != NULL && strstr(szBuf, ".exe") &&
825 (strstr(szBuf, "--ntservice") != NULL || strstr(szBuf, "-k ") !=NULL))
827 g_stServices[stPos].szServiceName = strdup(achKey);
828 g_stServices[stPos].szImagePath = strdup(szImagePath);
830 if (RegQueryValueEx(hSubKey, "Description", NULL,
831 &dwKeyType, szBuf, &dwBufLen) == ERROR_SUCCESS)
832 g_stServices[stPos].szDescription = strdup(szBuf);
835 if (RegQueryValueEx(hSubKey, "DisplayName", NULL,
836 &dwKeyType, szBuf, &dwBufLen) == ERROR_SUCCESS)
837 g_stServices[stPos].szDisplayName= strdup(szBuf);
839 if (stPos >= MAX_APACHE_SERVICES)
840 retCode = !ERROR_SUCCESS;
843 RegCloseKey(hSubKey);
848 FindRunningServices();
853 LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
856 CHAR szBuf[MAX_PATH];
858 static HWND hStatusBar;
864 LPMEASUREITEMSTRUCT lpmis;
865 LPDRAWITEMSTRUCT lpdis;
867 ZeroMemory(szBuf, MAX_PATH);
872 ShowWindow(hDlg, SW_HIDE);
873 g_hwndServiceDlg = hDlg;
874 g_hBmpStart = LoadImage(g_hInstance, MAKEINTRESOURCE(IDB_BMPRUN),
875 IMAGE_BITMAP, XBITMAP, YBITMAP, LR_DEFAULTCOLOR);
876 g_hBmpStop = LoadImage(g_hInstance, MAKEINTRESOURCE(IDB_BMPSTOP),
877 IMAGE_BITMAP, XBITMAP, YBITMAP, LR_DEFAULTCOLOR);
879 Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
880 Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
881 Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
883 if (g_dwOSVersion < OS_VERSION_WINNT)
884 ShowWindow(GetDlgItem(hDlg, IDC_SMANAGER), SW_HIDE);
886 hListBox = GetDlgItem(hDlg, IDL_SERVICES);
887 g_hwndStdoutList = GetDlgItem(hDlg, IDL_STDOUT);
888 hStatusBar = CreateStatusWindow(SBT_TOOLTIPS | WS_CHILD | WS_VISIBLE,
889 "", hDlg, IDC_STATBAR);
890 if (GetApacheServicesStatus())
893 while (g_stServices[i].szServiceName != NULL)
895 addListBoxItem(hListBox, g_stServices[i].szDisplayName,
896 g_stServices[i].dwPid == 0 ? g_hBmpStop : g_hBmpStart);
901 ShowWindow(hDlg, SW_SHOW);
903 SendMessage(hListBox, LB_SETCURSEL, 0, 0);
906 case WM_UPDATEMESSAGE:
907 hListBox = GetDlgItem(hDlg, IDL_SERVICES);
908 SendMessage(hListBox, LB_RESETCONTENT, 0, 0);
909 SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"");
910 Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
911 Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
912 Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
914 while (g_stServices[i].szServiceName != NULL)
916 addListBoxItem(hListBox, g_stServices[i].szDisplayName,
917 g_stServices[i].dwPid == 0 ? g_hBmpStop : g_hBmpStart);
920 SendMessage(hListBox, LB_SETCURSEL, 0, 0);
921 /* Dirty hack to bring the window to the foreground */
922 SetWindowPos(hDlg, HWND_TOPMOST, 0, 0, 0, 0,
923 SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
924 SetWindowPos(hDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
925 SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
931 lpmis = (LPMEASUREITEMSTRUCT) lParam;
932 lpmis->itemHeight = YBITMAP;
936 SetCursor(g_hCursorHourglass);
938 SetCursor(g_hCursorArrow);
941 lpdis = (LPDRAWITEMSTRUCT) lParam;
942 if (lpdis->itemID == -1)
946 switch (lpdis->itemAction)
950 g_hBmpPicture = (HBITMAP)SendMessage(lpdis->hwndItem,
951 LB_GETITEMDATA, lpdis->itemID, (LPARAM) 0);
953 hdcMem = CreateCompatibleDC(lpdis->hDC);
954 g_hBmpOld = SelectObject(hdcMem, g_hBmpPicture);
957 lpdis->rcItem.left, lpdis->rcItem.top,
958 lpdis->rcItem.right - lpdis->rcItem.left,
959 lpdis->rcItem.bottom - lpdis->rcItem.top,
960 hdcMem, 0, 0, SRCCOPY);
961 SendMessage(lpdis->hwndItem, LB_GETTEXT,
962 lpdis->itemID, (LPARAM) szBuf);
964 GetTextMetrics(lpdis->hDC, &tm);
965 y = (lpdis->rcItem.bottom + lpdis->rcItem.top -
968 SelectObject(hdcMem, g_hBmpOld);
971 rcBitmap.left = lpdis->rcItem.left + XBITMAP + 2;
972 rcBitmap.top = lpdis->rcItem.top;
973 rcBitmap.right = lpdis->rcItem.right;
974 rcBitmap.bottom = lpdis->rcItem.top + YBITMAP;
976 if (lpdis->itemState & ODS_SELECTED)
978 if (g_hBmpPicture == g_hBmpStop)
980 Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
981 Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
982 Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
984 else if (g_hBmpPicture == g_hBmpStart)
986 Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
987 Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
988 Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
990 if (g_stServices[lpdis->itemID].szDescription)
991 SendMessage(hStatusBar, SB_SETTEXT, 0,
992 (LPARAM)g_stServices[lpdis->itemID].szDescription);
994 SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"");
996 SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
997 SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
998 FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_HIGHLIGHTTEXT));
1002 SetTextColor(lpdis->hDC, GetSysColor(COLOR_MENUTEXT));
1003 SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
1004 FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_WINDOW+1));
1018 switch (LOWORD(wParam))
1021 switch (HIWORD(wParam))
1024 /* if started then stop, if stopped then start the service */
1025 hListBox = GetDlgItem(hDlg, IDL_SERVICES);
1026 nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
1027 if (nItem != LB_ERR)
1029 g_hBmpPicture = (HBITMAP)SendMessage(hListBox, LB_GETITEMDATA,
1031 if (g_hBmpPicture == g_hBmpStop)
1033 ApacheManageService(g_stServices[nItem].szServiceName,
1034 g_stServices[nItem].szImagePath,
1035 SERVICE_CONTROL_CONTINUE);
1038 ApacheManageService(g_stServices[nItem].szServiceName,
1039 g_stServices[nItem].szImagePath,
1040 SERVICE_CONTROL_STOP);
1048 EndDialog(hDlg, TRUE);
1051 Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1052 hListBox = GetDlgItem(hDlg, IDL_SERVICES);
1053 nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
1054 if (nItem != LB_ERR)
1056 ApacheManageService(g_stServices[nItem].szServiceName,
1057 g_stServices[nItem].szImagePath,
1058 SERVICE_CONTROL_CONTINUE);
1060 Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
1063 Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1064 hListBox = GetDlgItem(hDlg, IDL_SERVICES);
1065 nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
1066 if (nItem != LB_ERR)
1068 ApacheManageService(g_stServices[nItem].szServiceName,
1069 g_stServices[nItem].szImagePath,
1070 SERVICE_CONTROL_STOP);
1072 Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
1075 Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1076 hListBox = GetDlgItem(hDlg, IDL_SERVICES);
1077 nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
1078 if (nItem != LB_ERR)
1080 ApacheManageService(g_stServices[nItem].szServiceName,
1081 g_stServices[nItem].szImagePath,
1082 SERVICE_APACHE_RESTART);
1084 Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
1087 if (g_dwOSVersion >= OS_VERSION_WIN2K)
1088 ShellExecute(hDlg, "open", "services.msc", "/s", NULL, SW_NORMAL);
1090 WinExec("Control.exe SrvMgr.cpl Services", SW_NORMAL);
1093 EndDialog( hDlg, TRUE);
1094 SendMessage( g_hwndMain, WM_COMMAND, (WPARAM)IDM_EXIT, 0);
1099 switch (LOWORD(wParam))
1101 case SIZE_MINIMIZED:
1102 EndDialog(hDlg, TRUE);
1109 EndDialog(hDlg, TRUE);
1112 DeleteObject(g_hBmpStart);
1113 DeleteObject(g_hBmpStop);
1122 LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
1123 WPARAM wParam, LPARAM lParam)
1126 if (message == g_bUiTaskbarCreated)
1128 /* restore the tray icon on shell restart */
1129 ShowNotifyIcon(hWnd, NIM_ADD);
1130 return DefWindowProc(hWnd, message, wParam, lParam);
1135 GetApacheServicesStatus();
1136 ShowNotifyIcon(hWnd, NIM_ADD);
1137 SetTimer(hWnd, WM_TIMER_REFRESH, REFRESH_TIME, (TIMERPROC)WndProc);
1138 SetTimer(hWnd, WM_TIMER_RESCAN, RESCAN_TIME, (TIMERPROC)WndProc);
1139 g_hwndServiceDlg = NULL;
1141 case WM_TIMER_RESCAN:
1143 int nPrev = 0, nNew = 0;
1144 EnterCriticalSection(&g_stcSection);
1145 if (FindRunningServices() || g_bRescanServices)
1147 ShowNotifyIcon(hWnd, NIM_MODIFY);
1148 if (g_hwndServiceDlg)
1149 PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1151 /* check if services list changed */
1152 while (g_stServices[nPrev].szServiceName != NULL)
1154 GetApacheServicesStatus();
1155 while (g_stServices[nNew].szServiceName != NULL)
1159 ShowNotifyIcon(hWnd, NIM_MODIFY);
1160 if (g_hwndServiceDlg)
1161 PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1163 LeaveCriticalSection(&g_stcSection);
1166 case WM_TIMER_REFRESH:
1168 int nPrev = 0, nNew = 0;
1169 EnterCriticalSection(&g_stcSection);
1170 if (g_bRescanServices)
1172 GetApacheServicesStatus();
1173 ShowNotifyIcon(hWnd, NIM_MODIFY);
1174 if (g_hwndServiceDlg)
1175 PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1177 else if (FindRunningServices())
1179 ShowNotifyIcon(hWnd, NIM_MODIFY);
1180 if (g_hwndServiceDlg)
1181 PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1183 LeaveCriticalSection(&g_stcSection);
1187 ShowNotifyIcon(hWnd, NIM_DELETE);
1189 case WM_TRAYMESSAGE:
1192 case WM_LBUTTONDBLCLK:
1193 if (!g_bDlgServiceOn)
1195 g_bDlgServiceOn = TRUE;
1196 DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DLGSERVICES),
1197 hWnd, (DLGPROC)ServiceDlgProc);
1198 g_bDlgServiceOn = FALSE;
1199 g_hwndServiceDlg = NULL;
1201 else if (g_hwndServiceDlg)
1203 /* Dirty hack to bring the window to the foreground */
1204 SetWindowPos(g_hwndServiceDlg, HWND_TOPMOST, 0, 0, 0, 0,
1205 SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1206 SetWindowPos(g_hwndServiceDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
1207 SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1208 SetFocus(g_hwndServiceDlg);
1212 ShowTryPopupMenu(hWnd);
1217 switch (LOWORD(wParam))
1220 if (!g_bDlgServiceOn)
1222 g_bDlgServiceOn = TRUE;
1223 DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DLGSERVICES),
1224 hWnd, (DLGPROC)ServiceDlgProc);
1225 g_bDlgServiceOn = FALSE;
1226 g_hwndServiceDlg = NULL;
1228 else if (g_hwndServiceDlg)
1229 SetFocus(g_hwndServiceDlg);
1232 if (g_dwOSVersion >= OS_VERSION_WIN2K)
1233 ShellExecute(NULL, "open", "services.msc", "/s", NULL, SW_NORMAL);
1235 WinExec("Control.exe SrvMgr.cpl Services", SW_NORMAL);
1238 ShowNotifyIcon(hWnd, NIM_DELETE);
1243 return DefWindowProc(hWnd, message, wParam, lParam);
1249 /* Create main invisible window */
1250 HWND CreateMainWindow(HINSTANCE hInstance)
1255 if (!GetSystemOSVersion(&g_dwOSVersion))
1257 ErrorMessage(NULL, TRUE);
1261 wcex.cbSize = sizeof(WNDCLASSEX);
1263 wcex.style = CS_HREDRAW | CS_VREDRAW;
1264 wcex.lpfnWndProc = (WNDPROC)WndProc;
1265 wcex.cbClsExtra = 0;
1266 wcex.cbWndExtra = 0;
1267 wcex.hInstance = hInstance;
1268 wcex.hIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_APSRVMON),
1269 IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
1270 wcex.hCursor = g_hCursorArrow;
1271 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
1272 wcex.lpszMenuName = 0;
1273 wcex.lpszClassName = g_szWindowClass;
1274 wcex.hIconSm = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_APSRVMON),
1275 IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1277 if (RegisterClassEx(&wcex))
1278 hWnd = CreateWindow(g_szWindowClass, g_szTitle,
1280 NULL, NULL, hInstance, NULL);
1287 int WINAPI WinMain(HINSTANCE hInstance,
1288 HINSTANCE hPrevInstance,
1292 TCHAR szTmp[MAX_LOADSTRING];
1294 /* single instance mutex */
1298 g_LangID = GetUserDefaultLangID();
1299 if ((g_LangID & 0xFF) != LANG_ENGLISH)
1300 g_LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
1302 for (i = IDS_MSG_FIRST; i <= IDS_MSG_LAST; ++i) {
1303 LoadString(hInstance, i, szTmp, MAX_LOADSTRING);
1304 g_lpMsg[i - IDS_MSG_FIRST] = strdup(szTmp);
1306 LoadString(hInstance, IDS_APMONITORTITLE, szTmp, MAX_LOADSTRING);
1307 g_szTitle = strdup(szTmp);
1308 LoadString(hInstance, IDS_APMONITORCLASS, szTmp, MAX_LOADSTRING);
1309 g_szWindowClass = strdup(szTmp);
1311 g_icoStop = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICOSTOP),
1312 IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1313 g_icoRun = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICORUN),
1314 IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1315 g_hCursorHourglass = LoadImage(NULL, MAKEINTRESOURCE(OCR_WAIT), IMAGE_CURSOR,
1316 LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED);
1317 g_hCursorArrow = LoadImage(NULL, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR,
1318 LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED);
1320 hMutex = CreateMutex(NULL, FALSE, "APSRVMON_MUTEX");
1321 if((hMutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
1323 ErrorMessage(g_lpMsg[IDS_MSG_APPRUNNING-IDS_MSG_FIRST], FALSE);
1325 CloseHandle(hMutex);
1330 ZeroMemory(g_stServices, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
1331 InitCommonControls();
1332 g_hInstance = hInstance;
1333 g_hwndMain = CreateMainWindow(hInstance);
1334 InitializeCriticalSection(&g_stcSection);
1335 if (g_hwndMain != NULL)
1337 g_bUiTaskbarCreated = RegisterWindowMessage("TaskbarCreated");
1338 while (GetMessage(&msg, NULL, 0, 0) == TRUE)
1340 TranslateMessage(&msg);
1341 DispatchMessage(&msg);
1343 am_ClearServicesSt();
1345 DeleteCriticalSection(&g_stcSection);
1346 CloseHandle(hMutex);
1347 DestroyIcon(g_icoStop);
1348 DestroyIcon(g_icoRun);
1349 DestroyCursor(g_hCursorHourglass);
1350 DestroyCursor(g_hCursorArrow);