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
78 #include "ApacheMonitor.h"
81 #define OS_VERSION_WINNT 1
82 #define OS_VERSION_WIN9X 2
83 #define OS_VERSION_WIN2K 3
84 /* Should be enough */
85 #define MAX_APACHE_SERVICES 128
87 #define WM_TRAYMESSAGE (WM_APP+1)
88 #define WM_UPDATEMESSAGE (WM_USER+1)
89 #define WM_TIMER_REFRESH 10
90 #define WM_TIMER_RESCAN 11
91 #define SERVICE_APACHE_RESTART 128
94 #define MAX_LOADSTRING 100
95 #define REFRESH_TIME 1000 /* service refresh time (ms) */
96 #define RESCAN_TIME 10000 /* registry rescan time (ms) */
98 typedef struct _st_APACHE_SERVICE
107 /* Global variables */
108 HINSTANCE ap_hInstance = NULL;
109 HWND ap_hwndAboutDlg = NULL;
110 TCHAR szTitle[MAX_LOADSTRING]; /* The title bar text */
111 TCHAR szWindowClass[MAX_LOADSTRING]; /* Window Class Name */
114 UINT ap_uiTaskbarCreated;
116 BOOL dlgAboutOn = FALSE;
117 BOOL dlgServiceOn = FALSE;
118 BOOL ap_consoleRun = FALSE;
119 ST_APACHE_SERVICE ap_stServices[MAX_APACHE_SERVICES];
121 HBITMAP hbmpStart, hbmpStop;
122 HBITMAP hbmpPicture, hbmpOld;
123 BOOL ap_rescanServices;
127 HCURSOR ap_cHourglass;
135 PROCESS_INFORMATION ap_redirectedPI;
137 void ap_ClearServicesSt()
140 for (i = 0; i < MAX_APACHE_SERVICES; i++)
142 if (ap_stServices[i].szServiceName)
143 free(ap_stServices[i].szServiceName);
144 if (ap_stServices[i].szDisplayName)
145 free(ap_stServices[i].szDisplayName);
146 if (ap_stServices[i].szDescription)
147 free(ap_stServices[i].szDescription);
148 if (ap_stServices[i].szImagePath)
149 free(ap_stServices[i].szImagePath);
152 ZeroMemory(ap_stServices, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
156 void ErrorMessage(DWORD dwError)
159 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
160 FORMAT_MESSAGE_FROM_SYSTEM |
161 FORMAT_MESSAGE_IGNORE_INSERTS,
163 dwError == ERROR_SUCCESS ? GetLastError() : dwError,
164 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
165 (LPTSTR) &lpMsgBuf, 0, NULL);
166 MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONERROR);
171 LPTSTR GetStringRes(int id)
173 static TCHAR buffer[MAX_PATH];
176 LoadString(GetModuleHandle (NULL), id, buffer, MAX_PATH);
180 BOOL GetSystemOSVersion(LPSTR szVersion, LPDWORD dwVersion)
182 OSVERSIONINFOEX osvi;
183 BOOL bOsVersionInfoEx;
186 char szProductType[80];
190 Try calling GetVersionEx using the OSVERSIONINFOEX structure.
191 If that fails, try using the OSVERSIONINFO structure.
193 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
194 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
196 if (!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi)))
198 /* If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. */
199 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
200 if (!GetVersionEx((OSVERSIONINFO *) &osvi))
204 switch (osvi.dwPlatformId)
206 case VER_PLATFORM_WIN32_NT:
207 /* Test for the product. */
208 if (szVersion!= NULL)
210 if (osvi.dwMajorVersion <= 4)
211 strcpy(szVersion, "MS Windows NT ");
212 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
213 strcpy(szVersion, "MS Windows 2000 ");
214 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
215 strcpy(szVersion, "Whistler ");
216 /* Test for product type.*/
217 #ifdef VER_VORKSTATION_NT
218 if (bOsVersionInfoEx)
220 if (osvi.wProductType == VER_NT_WORKSTATION)
222 #ifdef VER_SUITE_PERSONAL
223 if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
224 strcat(szVersion, "Personal ");
227 strcat(szVersion, "Professional ");
229 else if (osvi.wProductType == VER_NT_SERVER)
231 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
232 strcat(szVersion, "DataCenter Server ");
233 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
234 strcat(szVersion, "Advanced Server ");
236 strcat(szVersion, "Server ");
242 RegOpenKeyEx(HKEY_LOCAL_MACHINE,
243 "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
244 0, KEY_QUERY_VALUE, &hKey);
245 RegQueryValueEx(hKey, "ProductType", NULL, NULL,
246 (LPBYTE) szProductType, &dwBufLen);
248 if (lstrcmpi("WINNT", szProductType) == 0)
249 strcat(szVersion, "Workstation ");
250 if (lstrcmpi("SERVERNT", szProductType) == 0)
251 strcat(szVersion, "Server ");
252 #ifdef VER_VORKSTATION_NT
255 /* Get version, service pack (if any), and build number. */
256 if (osvi.dwMajorVersion <= 4)
258 sprintf(szBuff, "version %d.%d %s (Build-%d)\n",
262 osvi.dwBuildNumber & 0xFFFF);
266 sprintf(szBuff, "%s (Build-%d)\n",
268 osvi.dwBuildNumber & 0xFFFF);
270 strcat(szVersion, szBuff);
272 else if (dwVersion != NULL)
274 if (osvi.dwMajorVersion <= 4)
275 *dwVersion = OS_VERSION_WINNT;
276 else if (osvi.dwMajorVersion == 5)
277 *dwVersion = OS_VERSION_WIN2K;
284 case VER_PLATFORM_WIN32_WINDOWS:
285 if (szVersion != NULL)
287 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
289 strcpy(szVersion, "MS Windows 95 ");
290 if (osvi.szCSDVersion[1] == 'C')
291 strcat(szVersion, "OSR2 ");
294 if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
296 strcpy(szVersion, "MS Windows 98 ");
297 if (osvi.szCSDVersion[1] == 'A')
298 strcat(szVersion, "SE ");
301 if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
303 strcpy(szVersion, "MS Windows Me ");
306 if (dwVersion != NULL)
307 *dwVersion = OS_VERSION_WIN9X;
311 case VER_PLATFORM_WIN32s:
312 if (szVersion != NULL)
313 strcpy(szVersion, "Microsoft Win32s ");
314 if (dwVersion != NULL)
315 *dwVersion = OS_VERSION_WIN9X;
324 static VOID ShowNotifyIcon(HWND hWnd, DWORD dwMessage)
330 ZeroMemory(&nid,sizeof(nid));
331 nid.cbSize = sizeof(NOTIFYICONDATA);
334 nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
335 nid.uCallbackMessage = WM_TRAYMESSAGE;
337 while (ap_stServices[i].szServiceName != NULL)
339 if (ap_stServices[i].dwPid != 0)
343 if (dwMessage != NIM_DELETE)
346 nid.hIcon = ap_icoRun;
348 nid.hIcon = ap_icoStop;
353 lstrcpy(nid.szTip, "Running all Apache services");
355 sprintf(nid.szTip, "Running %d from %d Apache services", n, i);
357 sprintf(nid.szTip, "Running none from %d Apache services", n, i);
359 Shell_NotifyIcon(dwMessage, &nid);
363 void appendMenuItem(HMENU hMenu, UINT uMenuId, LPSTR szName, BOOL fDefault)
367 ZeroMemory(&mii, sizeof(MENUITEMINFO));
368 mii.cbSize = sizeof(MENUITEMINFO);
369 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
372 mii.fType = MFT_STRING;
375 mii.fState = MFS_DEFAULT;
376 mii.dwTypeData = szName;
379 mii.fType = MFT_SEPARATOR;
380 InsertMenuItem(hMenu, uMenuId, FALSE, &mii);
383 void ShowTryPopupMenu(HWND hWnd)
385 /* create popup menu */
386 HMENU hMenu = CreatePopupMenu();
391 appendMenuItem(hMenu, IDM_ABOUT, "&About...", FALSE);
392 appendMenuItem(hMenu, IDM_RESTORE, "&Show Services...", TRUE);
393 appendMenuItem(hMenu, 0, "", FALSE);
394 appendMenuItem(hMenu, IDM_EXIT, "&Exit...", FALSE);
397 SetForegroundWindow(NULL);
398 TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, 0, hWnd, NULL);
402 BOOL CenterWindow(HWND hwndChild)
404 RECT rChild, rWorkArea;
409 /* Get the Height and Width of the child window */
410 GetWindowRect(hwndChild, &rChild);
411 wChild = rChild.right - rChild.left;
412 hChild = rChild.bottom - rChild.top;
414 /* Get the limits of the 'workarea' */
415 bResult = SystemParametersInfo(
421 rWorkArea.left = rWorkArea.top = 0;
422 rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
423 rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
426 /* Calculate new X and Y position*/
427 xNew = (rWorkArea.right - wChild)/2;
428 yNew = (rWorkArea.bottom - hChild)/2;
429 return SetWindowPos (hwndChild, HWND_TOP, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
432 static void addItem(HWND hDlg, LPSTR lpStr, HBITMAP hBmp)
436 nItem = SendMessage(hDlg, LB_ADDSTRING, 0, (LPARAM)lpStr);
437 SendMessage(hDlg, LB_SETITEMDATA, nItem, (LPARAM)hBmp);
440 static DWORD WINAPI ConsoleOutputThread(LPVOID lpThreadParameter)
442 static BYTE lpBuffer[513];
443 LPSTR lpBuf = lpBuffer;
447 while (ReadFile(h_stdOutR, &ch, 1, &dwReaded, NULL) == TRUE)
454 ListBox_SetCurSel(ap_hStdoutWnd,
455 ListBox_AddString(ap_hStdoutWnd, lpBuffer));
461 t = ((int)lpBuf - (int)lpBuffer) % 8;
462 for (i = 0; i < 8 - t; ++i)
469 CloseHandle(h_stdInW);
470 CloseHandle(h_stdOutR);
471 CloseHandle(h_stdErr);
476 DWORD WINAPI ConsoleWaitingThread(LPVOID lpThreadParameter)
478 WaitForSingleObject(ap_redirectedPI.hThread, INFINITE);
479 CloseHandle(ap_redirectedPI.hThread);
481 ap_consoleRun = FALSE;
482 SetCursor(ap_cArrow);
487 BOOL RunRedirectedConsole(LPTSTR szCmdLine, LPDWORD nRetValue)
494 ZeroMemory(&stInfo, sizeof(stInfo));
495 stInfo.cb = sizeof(stInfo);
496 stInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
497 stInfo.wShowWindow = SW_HIDE;
499 hProc = GetCurrentProcess();
501 if (!CreatePipe(&h_stdInR, &h_stdInW, NULL, MAX_PATH))
502 ErrorMessage(ERROR_SUCCESS);
503 if (!CreatePipe(&h_stdOutR, &h_stdOutW, NULL, MAX_PATH*8))
504 ErrorMessage(ERROR_SUCCESS);
506 DuplicateHandle(hProc, h_stdInR, hProc, &h_stdInR, 0, TRUE,
507 DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
508 DuplicateHandle(hProc, h_stdOutW, hProc, &h_stdOutW, 0, TRUE,
509 DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
510 DuplicateHandle(hProc, h_stdOutW, hProc, &h_stdErr, 0, TRUE,
511 DUPLICATE_SAME_ACCESS);
513 stInfo.hStdInput = h_stdInR;
514 stInfo.hStdOutput = h_stdOutW;
515 stInfo.hStdError = h_stdErr;
517 bResult = CreateProcess(NULL,
529 CloseHandle(h_stdInR);
530 CloseHandle(h_stdOutW);
531 CloseHandle(h_stdErr);
536 *nRetValue = GetLastError();
537 CloseHandle(h_stdInW);
538 CloseHandle(h_stdOutR);
539 CloseHandle(h_stdErr);
543 CloseHandle(CreateThread(NULL, 0, ConsoleOutputThread, 0, 0, &dwThreadId));
544 ResumeThread(ap_redirectedPI.hThread);
545 CloseHandle(CreateThread(NULL, 0, ConsoleWaitingThread, 0, 0, &dwThreadId));
550 BOOL RunAndForgetConsole(LPTSTR szCmdLine,
552 BOOL bRedirectConsole)
556 PROCESS_INFORMATION prInfo;
559 if (bRedirectConsole)
560 return RunRedirectedConsole(szCmdLine, nRetValue);
563 ZeroMemory(&stInfo, sizeof(stInfo));
564 stInfo.cb = sizeof(stInfo);
565 stInfo.dwFlags = STARTF_USESHOWWINDOW;
566 stInfo.wShowWindow = SW_HIDE;
568 bResult = CreateProcess(NULL,
582 *nRetValue = GetLastError();
585 if (ap_OSVersion == OS_VERSION_WIN9X) /* give some time to rescan the status */
587 CloseHandle(prInfo.hThread);
588 CloseHandle(prInfo.hProcess);
592 BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, DWORD dwCommand)
595 CHAR szBuf[MAX_PATH];
596 CHAR szMsg[MAX_PATH];
600 BOOL serviceFlag = TRUE;
601 SC_HANDLE schService;
602 SC_HANDLE schSCManager;
603 SERVICE_STATUS schSStatus;
607 if (ap_OSVersion == OS_VERSION_WIN9X)
609 sPos = strstr(szImagePath, "-k start");
612 lstrcpyn(szBuf, szImagePath, sPos - szImagePath);
615 case SERVICE_CONTROL_STOP:
616 lstrcat(szBuf, " -k stop -n ");
618 case SERVICE_CONTROL_CONTINUE:
619 sprintf(szMsg, "The %s is starting.", szServiceName);
620 ListBox_SetCurSel(ap_hStdoutWnd,
621 ListBox_AddString(ap_hStdoutWnd, szMsg));
622 lstrcat(szBuf, " -k start -n ");
625 case SERVICE_APACHE_RESTART:
626 lstrcat(szBuf, " -k restart -n ");
631 lstrcat(szBuf, szServiceName);
635 ap_consoleRun = TRUE;
636 SetCursor(ap_cHourglass);
637 if (!RunAndForgetConsole(szBuf, &retCode, serviceFlag))
639 ErrorMessage(retCode);
640 ap_consoleRun = FALSE;
641 SetCursor(ap_cArrow);
644 else if (!serviceFlag)
646 sprintf(szMsg, "The %s has started.", szServiceName);
647 ListBox_SetCurSel(ap_hStdoutWnd,
648 ListBox_AddString(ap_hStdoutWnd, szMsg));
650 ap_consoleRun = FALSE;
651 SetCursor(ap_cArrow);
657 /* Apache 2.0 uses '-k runservice' as cmdline parameter */
658 sPos = strstr(szImagePath, "--ntservice");
661 sPos = strstr(szImagePath, "-k runservice");
665 lstrcpyn(szBuf, szImagePath, sPos - szImagePath);
668 schSCManager = OpenSCManager(
671 SC_MANAGER_ALL_ACCESS
676 schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);
677 if (schService != NULL)
680 ap_consoleRun = TRUE;
681 SetCursor(ap_cHourglass);
684 case SERVICE_CONTROL_STOP:
685 sprintf(szMsg, "The %s is stopping.", szServiceName);
686 ListBox_SetCurSel(ap_hStdoutWnd,
687 ListBox_AddString(ap_hStdoutWnd, szMsg));
688 if(ControlService(schService, SERVICE_CONTROL_STOP, &schSStatus))
691 while (QueryServiceStatus(schService, &schSStatus))
693 if (schSStatus.dwCurrentState == SERVICE_STOP_PENDING)
699 if (QueryServiceStatus(schService, &schSStatus))
701 if(schSStatus.dwCurrentState == SERVICE_STOPPED)
704 sprintf(szMsg, "The %s has stopped.", szServiceName);
705 ListBox_SetCurSel(ap_hStdoutWnd,
706 ListBox_AddString(ap_hStdoutWnd, szMsg));
710 case SERVICE_CONTROL_CONTINUE:
711 sprintf(szMsg, "The %s is starting.", szServiceName);
712 ListBox_SetCurSel(ap_hStdoutWnd,
713 ListBox_AddString(ap_hStdoutWnd, szMsg));
714 args = (char **)malloc(3 * sizeof(char*));
717 args[1] = "--ntservice";
721 args[2] = "runservice";
723 if(StartService(schService, serviceFlag ? 2 : 3, args))
726 while (QueryServiceStatus(schService, &schSStatus))
728 if (schSStatus.dwCurrentState == SERVICE_START_PENDING)
734 if (QueryServiceStatus(schService, &schSStatus))
736 if(schSStatus.dwCurrentState == SERVICE_RUNNING)
739 sprintf(szMsg, "The %s has started.", szServiceName);
740 ListBox_SetCurSel(ap_hStdoutWnd,
741 ListBox_AddString(ap_hStdoutWnd, szMsg));
744 /* is this OK to do? */
747 case SERVICE_APACHE_RESTART:
748 sprintf(szMsg, "The %s is restarting.", szServiceName);
749 ListBox_SetCurSel(ap_hStdoutWnd,
750 ListBox_AddString(ap_hStdoutWnd, szMsg));
751 if(ControlService(schService, SERVICE_APACHE_RESTART, &schSStatus))
754 while(schSStatus.dwCurrentState == SERVICE_START_PENDING)
757 if(!QueryServiceStatus(schService, &schSStatus))
759 CloseServiceHandle(schService);
760 CloseServiceHandle(schSCManager);
761 ap_consoleRun = FALSE;
762 SetCursor(ap_cArrow);
769 if(schSStatus.dwCurrentState == SERVICE_RUNNING)
772 sprintf(szMsg, "The %s has restarted.", szServiceName);
773 ListBox_SetCurSel(ap_hStdoutWnd,
774 ListBox_AddString(ap_hStdoutWnd, szMsg));
778 CloseServiceHandle(schService);
779 CloseServiceHandle(schSCManager);
781 ErrorMessage(ERROR_SUCCESS);
782 ap_consoleRun = FALSE;
783 SetCursor(ap_cArrow);
788 ap_rescanServices = TRUE;
790 CloseServiceHandle(schSCManager);
797 BOOL IsServiceRunning(LPCSTR szServiceName, LPDWORD lpdwPid)
802 SC_HANDLE schService;
803 SC_HANDLE schSCManager;
804 SERVICE_STATUS schSStatus;
806 if (ap_OSVersion == OS_VERSION_WIN9X)
808 hWnd = FindWindow("ApacheWin95ServiceMonitor", szServiceName);
809 if (hWnd && GetWindowThreadProcessId(hWnd, &dwPid))
821 schSCManager = OpenSCManager(
824 SC_MANAGER_ALL_ACCESS
829 schService = OpenService(schSCManager, szServiceName, SERVICE_QUERY_STATUS);
830 if (schService != NULL)
832 if (QueryServiceStatus(schService, &schSStatus))
835 dwPid = schSStatus.dwCurrentState;
839 CloseServiceHandle(schService);
840 CloseServiceHandle(schSCManager);
841 return dwPid == SERVICE_RUNNING ? TRUE : FALSE;
844 ap_rescanServices = TRUE;
846 CloseServiceHandle(schSCManager);
854 BOOL FindRunningServices()
859 while (ap_stServices[i].szServiceName != NULL)
861 if (!IsServiceRunning(ap_stServices[i].szServiceName, &dwPid))
863 if (ap_stServices[i].dwPid != dwPid)
865 ap_stServices[i].dwPid = dwPid;
871 BOOL GetApacheServicesStatus()
874 CHAR szKey[MAX_PATH];
875 CHAR achKey[MAX_PATH];
876 CHAR szImagePath[MAX_PATH];
877 CHAR szBuf[MAX_PATH];
880 DWORD retCode, rv, dwKeyType;
881 DWORD dwBufLen = MAX_PATH;
884 ap_rescanServices = FALSE;
886 retCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
887 "System\\CurrentControlSet\\Services\\",
889 if (retCode != ERROR_SUCCESS)
891 ErrorMessage(retCode);
894 ap_ClearServicesSt();
895 for (i = 0, retCode = ERROR_SUCCESS; retCode == ERROR_SUCCESS; i++)
898 retCode = RegEnumKey(hKey, i, achKey, MAX_PATH);
899 if (retCode == ERROR_SUCCESS)
901 lstrcpy(szKey, "System\\CurrentControlSet\\Services\\");
902 lstrcat(szKey, achKey);
904 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0,
905 KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS)
908 rv = RegQueryValueEx(hSubKey, "ImagePath", NULL,
909 &dwKeyType, szImagePath, &dwBufLen);
911 if (rv == ERROR_SUCCESS && (dwKeyType == REG_SZ || dwKeyType == REG_EXPAND_SZ) && dwBufLen)
913 lstrcpy(szBuf, szImagePath);
915 if (strstr(szBuf, "\\apache.exe") != NULL)
917 ap_stServices[stPos].szServiceName = strdup(achKey);
918 ap_stServices[stPos].szImagePath = strdup(szImagePath);
920 if (RegQueryValueEx(hSubKey, "Description", NULL,
921 &dwKeyType, szBuf, &dwBufLen) == ERROR_SUCCESS)
922 ap_stServices[stPos].szDescription = strdup(szBuf);
925 if (RegQueryValueEx(hSubKey, "DisplayName", NULL,
926 &dwKeyType, szBuf, &dwBufLen) == ERROR_SUCCESS)
927 ap_stServices[stPos].szDisplayName= strdup(szBuf);
929 if (stPos >= MAX_APACHE_SERVICES)
930 retCode = !ERROR_SUCCESS;
933 RegCloseKey(hSubKey);
938 FindRunningServices();
942 LRESULT CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
944 static HFONT hfontDlg; /* Font for dialog text */
945 static HFONT hFinePrint; /* Font for 'fine print' in dialog */
946 DWORD dwVerInfoSize; /* Size of version information block */
947 LPSTR lpVersion; /* String pointer to 'version' text */
948 DWORD dwVerHnd=0; /* An 'ignored' parameter, always '0' */
953 char szFullPath[256];
961 ShowWindow(hDlg, SW_HIDE);
962 ap_hwndAboutDlg = hDlg;
964 hfontDlg = CreateFont(13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
965 VARIABLE_PITCH | FF_SWISS, "");
966 hFinePrint = CreateFont(11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
967 VARIABLE_PITCH | FF_SWISS, "");
970 GetModuleFileName(ap_hInstance, szFullPath, sizeof(szFullPath));
972 /* Now lets dive in and pull out the version information: */
973 dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwVerHnd);
977 hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
978 lpstrVffInfo = GlobalLock(hMem);
979 GetFileVersionInfo(szFullPath, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
980 lstrcpy(szGetName, GetStringRes(IDS_VER_INFO_LANG));
982 wRootLen = lstrlen(szGetName); /* Save this position */
984 /* Set the title of the dialog: */
985 lstrcat(szGetName, "ProductName");
986 bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
989 (UINT *)&uVersionLen);
991 /* Notice order of version and string... */
992 lstrcpy(szResult, "About ");
993 lstrcat(szResult, lpVersion);
995 SetWindowText(hDlg, szResult);
997 /* Walk through the dialog items that we want to replace: */
998 for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++) {
999 GetDlgItemText(hDlg, i, szResult, sizeof(szResult));
1000 szGetName[wRootLen] = (char)0;
1001 lstrcat(szGetName, szResult);
1004 bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
1007 (UINT *)&uVersionLen);
1009 if (bRetCode && uVersionLen && lpVersion) {
1010 /* Replace dialog item text with version info */
1011 lstrcpy(szResult, lpVersion);
1012 SetDlgItemText(hDlg, i, szResult);
1016 dwResult = GetLastError();
1018 wsprintf(szResult, GetStringRes(IDS_VERSION_ERROR), dwResult);
1019 SetDlgItemText(hDlg, i, szResult);
1021 SendMessage(GetDlgItem(hDlg, i), WM_SETFONT,
1022 (UINT)((i==DLG_VERLAST)?hFinePrint:hfontDlg),
1032 SendMessage(GetDlgItem(hDlg, IDC_LABEL), WM_SETFONT,
1033 (WPARAM)hfontDlg,(LPARAM)TRUE);
1034 if (!GetSystemOSVersion(szVersion, NULL))
1035 strcpy(szVersion, "Unknown Version");
1036 SetWindowText(GetDlgItem(hDlg, IDC_OSVERSION), szVersion);
1037 ShowWindow(hDlg, SW_SHOW);
1041 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
1042 EndDialog(hDlg, TRUE);
1043 DeleteObject(hfontDlg);
1044 DeleteObject(hFinePrint);
1053 LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1056 CHAR tchBuffer[MAX_PATH];
1057 CHAR tsbBuffer[MAX_PATH];
1059 static HWND hStatusBar;
1065 LPMEASUREITEMSTRUCT lpmis;
1066 LPDRAWITEMSTRUCT lpdis;
1068 ZeroMemory(tchBuffer, MAX_PATH);
1069 ZeroMemory(tsbBuffer, MAX_PATH);
1074 ShowWindow(hDlg, SW_HIDE);
1075 ap_hServiceDlg = hDlg;
1076 hbmpStart = LoadBitmap(ap_hInstance, MAKEINTRESOURCE(IDB_BMPRUN));
1077 hbmpStop = LoadBitmap(ap_hInstance, MAKEINTRESOURCE(IDB_BMPSTOP));
1079 Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1080 Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1081 Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1082 hListBox = GetDlgItem(hDlg, IDL_SERVICES);
1083 ap_hStdoutWnd = GetDlgItem(hDlg, IDL_STDOUT);
1084 hStatusBar = CreateStatusWindow(SBT_TOOLTIPS | WS_CHILD | WS_VISIBLE,
1085 "", hDlg, IDC_STATBAR);
1086 if (GetApacheServicesStatus())
1089 while (ap_stServices[i].szServiceName != NULL)
1091 addItem(hListBox, ap_stServices[i].szDisplayName,
1092 ap_stServices[i].dwPid == 0 ? hbmpStop : hbmpStart);
1097 ShowWindow(hDlg, SW_SHOW);
1099 SendMessage(hListBox, LB_SETCURSEL, 0, 0);
1102 case WM_UPDATEMESSAGE:
1103 hListBox = GetDlgItem(hDlg, IDL_SERVICES);
1104 SendMessage(hListBox, LB_RESETCONTENT, 0, 0);
1105 Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1106 Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1107 Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1109 while (ap_stServices[i].szServiceName != NULL)
1111 addItem(hListBox, ap_stServices[i].szDisplayName,
1112 ap_stServices[i].dwPid == 0 ? hbmpStop : hbmpStart);
1115 SendMessage(hListBox, LB_SETCURSEL, 0, 0);
1116 /* Dirty hack to bring the window to the foreground */
1117 SetWindowPos(hDlg, HWND_TOPMOST, 0, 0, 0, 0,
1118 SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1119 SetWindowPos(hDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
1120 SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1124 case WM_MEASUREITEM:
1126 lpmis = (LPMEASUREITEMSTRUCT) lParam;
1127 lpmis->itemHeight = 16;
1131 SetCursor(ap_cHourglass);
1133 SetCursor(ap_cArrow);
1137 lpdis = (LPDRAWITEMSTRUCT) lParam;
1138 if (lpdis->itemID == -1)
1142 switch (lpdis->itemAction)
1145 case ODA_DRAWENTIRE:
1146 hbmpPicture = (HBITMAP)SendMessage(lpdis->hwndItem,
1147 LB_GETITEMDATA, lpdis->itemID, (LPARAM) 0);
1149 hdcMem = CreateCompatibleDC(lpdis->hDC);
1150 hbmpOld = SelectObject(hdcMem, hbmpPicture);
1153 lpdis->rcItem.left, lpdis->rcItem.top,
1154 lpdis->rcItem.right - lpdis->rcItem.left,
1155 lpdis->rcItem.bottom - lpdis->rcItem.top,
1156 hdcMem, 0, 0, SRCCOPY);
1157 SendMessage(lpdis->hwndItem, LB_GETTEXT,
1158 lpdis->itemID, (LPARAM) tchBuffer);
1160 GetTextMetrics(lpdis->hDC, &tm);
1161 y = (lpdis->rcItem.bottom + lpdis->rcItem.top -
1164 SelectObject(hdcMem, hbmpOld);
1167 rcBitmap.left = lpdis->rcItem.left + XBITMAP + 2;
1168 rcBitmap.top = lpdis->rcItem.top;
1169 rcBitmap.right = lpdis->rcItem.right;
1170 rcBitmap.bottom = lpdis->rcItem.top + YBITMAP;
1172 if (lpdis->itemState & ODS_SELECTED)
1174 if (hbmpPicture == hbmpStop)
1176 Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
1177 Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1178 Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1180 else if (hbmpPicture == hbmpStart)
1182 Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1183 Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
1184 Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
1186 if (ap_stServices[lpdis->itemID].szDescription)
1187 lstrcpy(tsbBuffer, ap_stServices[lpdis->itemID].szDescription);
1188 SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)tsbBuffer);
1190 SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
1191 SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
1192 FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_HIGHLIGHTTEXT));
1196 SetTextColor(lpdis->hDC, GetSysColor(COLOR_MENUTEXT));
1197 SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
1198 FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_WINDOW+1));
1212 switch (LOWORD(wParam))
1215 switch (HIWORD(wParam))
1218 /* if started then stop, if stopped the start the service */
1219 hListBox = GetDlgItem(hDlg, IDL_SERVICES);
1220 nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
1221 if (nItem != LB_ERR)
1223 hbmpPicture = (HBITMAP)SendMessage(hListBox, LB_GETITEMDATA,
1225 if (hbmpPicture == hbmpStop)
1227 ApacheManageService(ap_stServices[nItem].szServiceName,
1228 ap_stServices[nItem].szImagePath,
1229 SERVICE_CONTROL_CONTINUE);
1232 ApacheManageService(ap_stServices[nItem].szServiceName,
1233 ap_stServices[nItem].szImagePath,
1234 SERVICE_CONTROL_STOP);
1242 EndDialog(hDlg, TRUE);
1246 Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
1247 hListBox = GetDlgItem(hDlg, IDL_SERVICES);
1248 nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
1249 if (nItem != LB_ERR)
1251 ApacheManageService(ap_stServices[nItem].szServiceName,
1252 ap_stServices[nItem].szImagePath,
1253 SERVICE_CONTROL_CONTINUE);
1255 Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
1259 Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
1260 hListBox = GetDlgItem(hDlg, IDL_SERVICES);
1261 nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
1262 if (nItem != LB_ERR)
1264 ApacheManageService(ap_stServices[nItem].szServiceName,
1265 ap_stServices[nItem].szImagePath,
1266 SERVICE_CONTROL_STOP);
1268 Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
1272 Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
1273 hListBox = GetDlgItem(hDlg, IDL_SERVICES);
1274 nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
1275 if (nItem != LB_ERR)
1277 ApacheManageService(ap_stServices[nItem].szServiceName,
1278 ap_stServices[nItem].szImagePath,
1279 SERVICE_APACHE_RESTART);
1281 Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
1288 DialogBox(ap_hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX),
1289 ap_hMainWnd, (DLGPROC)AboutDlgProc);
1291 ap_hwndAboutDlg = NULL;
1293 else if (ap_hwndAboutDlg)
1294 SetFocus(ap_hwndAboutDlg);
1300 switch (LOWORD(wParam))
1302 case SIZE_MINIMIZED:
1303 EndDialog(hDlg, TRUE);
1309 EndDialog(hDlg, TRUE);
1312 DeleteObject(hbmpStart);
1313 DeleteObject(hbmpStop);
1322 VOID CALLBACK MainTimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
1324 int nPrev = 0, nNew = 0;
1325 if (idEvent == WM_TIMER_RESCAN)
1327 if (FindRunningServices() || ap_rescanServices)
1329 ShowNotifyIcon(hWnd, NIM_MODIFY);
1331 PostMessage(ap_hServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1333 /* check if services list changed */
1334 while (ap_stServices[nPrev].szServiceName != NULL)
1336 GetApacheServicesStatus();
1337 while (ap_stServices[nNew].szServiceName != NULL)
1341 ShowNotifyIcon(hWnd, NIM_MODIFY);
1343 PostMessage(ap_hServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1346 else if (idEvent == WM_TIMER_REFRESH)
1348 if (ap_rescanServices)
1350 GetApacheServicesStatus();
1351 ShowNotifyIcon(hWnd, NIM_MODIFY);
1353 PostMessage(ap_hServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1355 else if (FindRunningServices())
1357 ShowNotifyIcon(hWnd, NIM_MODIFY);
1359 PostMessage(ap_hServiceDlg, WM_UPDATEMESSAGE, 0, 0);
1365 LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
1366 WPARAM wParam, LPARAM lParam)
1369 if (message == ap_uiTaskbarCreated)
1371 /* restore the tray icon on shell restart */
1372 ShowNotifyIcon(hWnd, NIM_ADD);
1373 return DefWindowProc(hWnd, message, wParam, lParam);
1378 GetSystemOSVersion(NULL, &ap_OSVersion);
1379 GetApacheServicesStatus();
1380 ShowNotifyIcon(hWnd, NIM_ADD);
1381 SetTimer(hWnd, WM_TIMER_REFRESH, REFRESH_TIME, (TIMERPROC)MainTimerProc);
1382 SetTimer(hWnd, WM_TIMER_RESCAN, RESCAN_TIME, (TIMERPROC)MainTimerProc);
1383 ap_hServiceDlg = NULL;
1386 ShowNotifyIcon(hWnd, NIM_DELETE);
1388 case WM_TRAYMESSAGE:
1391 case WM_LBUTTONDBLCLK:
1394 dlgServiceOn = TRUE;
1395 DialogBox(ap_hInstance, MAKEINTRESOURCE(IDD_APSRVMON_DIALOG),
1396 hWnd, (DLGPROC)ServiceDlgProc);
1397 dlgServiceOn = FALSE;
1398 ap_hServiceDlg = NULL;
1400 else if (ap_hServiceDlg)
1402 /* Dirty hack to bring the window to the foreground */
1403 SetWindowPos(ap_hServiceDlg, HWND_TOPMOST, 0, 0, 0, 0,
1404 SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1405 SetWindowPos(ap_hServiceDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
1406 SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
1407 SetFocus(ap_hServiceDlg);
1411 ShowTryPopupMenu(hWnd);
1416 switch (LOWORD(wParam))
1421 dlgServiceOn = TRUE;
1422 DialogBox(ap_hInstance, MAKEINTRESOURCE(IDD_APSRVMON_DIALOG),
1423 hWnd, (DLGPROC)ServiceDlgProc);
1424 dlgServiceOn = FALSE;
1425 ap_hServiceDlg = NULL;
1427 else if (ap_hServiceDlg)
1428 SetFocus(ap_hServiceDlg);
1434 DialogBox(ap_hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX),
1435 hWnd, (DLGPROC)AboutDlgProc);
1437 ap_hwndAboutDlg = NULL;
1439 else if (ap_hwndAboutDlg)
1440 SetFocus(ap_hwndAboutDlg);
1448 return DefWindowProc(hWnd, message, wParam, lParam);
1454 /* Create main invisible window */
1455 HWND CreateMainWindow(HINSTANCE hInstance)
1460 wcex.cbSize = sizeof(WNDCLASSEX);
1462 wcex.style = CS_HREDRAW | CS_VREDRAW;
1463 wcex.lpfnWndProc = (WNDPROC)WndProc;
1464 wcex.cbClsExtra = 0;
1465 wcex.cbWndExtra = 0;
1466 wcex.hInstance = hInstance;
1467 wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_APSRVMON);
1468 wcex.hCursor = ap_cArrow;
1469 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
1470 wcex.lpszMenuName = (LPCSTR)IDC_APSRVMON;
1471 wcex.lpszClassName = szWindowClass;
1472 wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_APSMALL);
1474 if (RegisterClassEx(&wcex))
1476 hWnd = CreateWindow(szWindowClass, szTitle,
1478 NULL, NULL, hInstance, NULL);
1486 int WINAPI WinMain(HINSTANCE hInstance,
1487 HINSTANCE hPrevInstance,
1492 /* single instance mutex */
1493 HANDLE hMutex = CreateMutex(NULL, FALSE, "APSRVMON_MUTEX");
1494 if((hMutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
1497 CloseHandle(hMutex);
1501 InitCommonControls();
1502 ap_hInstance = hInstance;
1504 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
1505 LoadString(hInstance, IDC_APSRVMON, szWindowClass, MAX_LOADSTRING);
1506 ap_icoStop = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICOSTOP));
1507 ap_icoRun = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICORUN));
1508 ap_cHourglass = LoadCursor(NULL, IDC_WAIT);
1509 ap_cArrow = LoadCursor(NULL, IDC_ARROW);
1511 ZeroMemory(ap_stServices, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
1512 ap_hMainWnd = CreateMainWindow(hInstance);
1513 if (ap_hMainWnd != NULL)
1515 ap_uiTaskbarCreated = RegisterWindowMessage("TaskbarCreated");
1516 while (GetMessage(&msg, NULL, 0, 0) == TRUE)
1518 TranslateMessage(&msg);
1519 DispatchMessage(&msg);
1521 ap_ClearServicesSt();
1523 CloseHandle(hMutex);