/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* .
*
* Portions of this software are based upon public domain software
* originally written at the National Center for Supercomputing Applications,
* University of Illinois, Urbana-Champaign.
*/
/* ====================================================================
* ApacheMonitor.c Simple program to manage and monitor Apache services.
*
* Contributed by Mladen Turk
*
* 05 Aug 2001
* ====================================================================
*/
#define _WIN32_WINNT 0x0400
#ifndef STRICT
#define STRICT
#endif
#ifndef OEMRESOURCE
#define OEMRESOURCE
#endif
#include
#include
#include
#include
#include
#include "ApacheMonitor.h"
#include "apr.h"
#include "apr_strings.h"
#include "apr_general.h"
#include "apr_pools.h"
#include "apr_hash.h"
#include "apr_lock.h"
#include "apr_thread_mutex.h"
#define OS_VERSION_WIN9X 1
#define OS_VERSION_WINNT 2
#define OS_VERSION_WIN2K 3
#define WM_TRAYMESSAGE (WM_APP+1)
#define WM_UPDATEMESSAGE (WM_USER+1)
#define WM_MANAGEMESSAGE (WM_USER+2)
#define WM_TIMER_REFRESH 10
#define WM_TIMER_RESCAN 11
#define SERVICE_APACHE_RESTART 128
#define XBITMAP 16
#define YBITMAP 16
#define MAX_LOADSTRING 100
#define REFRESH_TIME 2000 /* service refresh time (ms) */
#define RESCAN_TIME 20000 /* registry rescan time (ms) */
typedef struct am_services_t am_services_t;
struct am_services_t
{
char *name;
char *display;
char *description;
char *path;
const char *computer;
int state;
};
typedef struct am_computers_t am_computers_t;
struct am_computers_t
{
char *computer;
HKEY registry;
};
/* Global variables */
apr_pool_t *g_pool; /* The global APR pool */
apr_pool_t *g_subpool;
apr_hash_t *g_services; /* service hash table */
apr_hash_t *g_computers; /* connected computers */
apr_thread_mutex_t *g_mutex;
apr_uint32_t g_os_version;
char *g_title; /* The title bar text */
char *g_window_class; /* Window Class Name */
HINSTANCE g_instance = NULL;
HICON g_icon_stop;
HICON g_icon_run;
UINT g_taskbar_created;
BOOL g_services_on = FALSE;
BOOL g_bConsoleRun = FALSE;
HBITMAP g_bmp_start, g_bmp_stop;
HBITMAP g_bmp_cur, g_bmp_old;
BOOL g_rescan_services;
HWND g_hwnd_service;
HWND g_hwnd_main;
HWND g_hwndStdoutList;
HWND g_hwndConnectDlg;
HCURSOR g_cursor_hourglass;
HCURSOR g_cursor_arrow;
HANDLE g_hpipeOutRead;
HANDLE g_hpipeOutWrite;
HANDLE g_hpipeInRead;
HANDLE g_hpipeInWrite;
HANDLE g_hpipeStdError;
LANGID g_language_id;
PROCESS_INFORMATION g_lpRedirectProc;
char g_hostname[MAX_COMPUTERNAME_LENGTH+1];
/* locale language support */
static char *g_messages[IDS_MSG_LAST - IDS_MSG_FIRST + 1];
BOOL am_is_connected(const char *computer)
{
if (apr_hash_get(g_computers, computer, APR_HASH_KEY_STRING))
return TRUE;
else
return FALSE;
}
void am_disconnect_computer(const char *computer)
{
HKEY remote = apr_hash_get(g_computers, computer, APR_HASH_KEY_STRING);
/* chech if the remote computer is allready diconnected */
if (remote && strcmp(computer, g_hostname)) {
RegCloseKey(remote);
apr_hash_set(g_computers, computer, APR_HASH_KEY_STRING, NULL);
}
}
void am_display_error(const char * szError, BOOL bFatal)
{
LPVOID lpMsgBuf = NULL;
if (szError)
MessageBox(NULL, szError, g_messages[IDS_MSG_ERROR-IDS_MSG_FIRST],
MB_OK | (bFatal ? MB_ICONERROR : MB_ICONEXCLAMATION));
else {
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
g_language_id,
(char *) &lpMsgBuf, 0, NULL);
MessageBox(NULL, (const char *)lpMsgBuf, g_messages[IDS_MSG_ERROR-IDS_MSG_FIRST],
MB_OK | (bFatal ? MB_ICONERROR : MB_ICONEXCLAMATION));
LocalFree(lpMsgBuf);
}
if ( bFatal)
PostQuitMessage(0);
}
BOOL am_connect_computer(const char *computer)
{
HKEY remote;
/* chech if the remote computer is allready connected */
if (apr_hash_get(g_computers, computer, APR_HASH_KEY_STRING))
return FALSE;
if (RegConnectRegistry(computer, HKEY_LOCAL_MACHINE, &remote) != ERROR_SUCCESS) {
char s[MAX_PATH];
sprintf(s, g_messages[IDS_MSG_ECONNECT-IDS_MSG_FIRST], computer);
am_display_error(s, FALSE);
return FALSE;
}
else {
apr_hash_set(g_computers, apr_pstrdup(g_pool, computer),
APR_HASH_KEY_STRING, remote);
return TRUE;
}
}
BOOL am_get_os(apr_uint32_t *version)
{
OSVERSIONINFO osvi;
/*
Try calling GetVersionEx using the OSVERSIONINFOEX structure.
If that fails, try using the OSVERSIONINFO structure.
*/
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&osvi))
return FALSE;
switch (osvi.dwPlatformId) {
case VER_PLATFORM_WIN32_NT:
if (osvi.dwMajorVersion <= 4)
*version = OS_VERSION_WINNT;
else if (osvi.dwMajorVersion == 5)
*version = OS_VERSION_WIN2K;
else
return FALSE;
break;
case VER_PLATFORM_WIN32_WINDOWS:
*version = OS_VERSION_WIN9X;
break;
case VER_PLATFORM_WIN32s:
*version = 0;
return FALSE;
default:
return FALSE;
break;
}
return TRUE;
}
BOOL am_is_running(const char *service, const char *computer)
{
DWORD dwPid;
HWND hWnd;
SC_HANDLE schService;
SC_HANDLE schSCManager;
SERVICE_STATUS schSStatus;
if (g_os_version == OS_VERSION_WIN9X) {
hWnd = FindWindow("ApacheWin95ServiceMonitor", service);
if (hWnd && GetWindowThreadProcessId(hWnd, &dwPid))
return TRUE;
else
return FALSE;
}
else {
dwPid = 0;
schSCManager = OpenSCManager(
computer,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!schSCManager)
return FALSE;
schService = OpenService(schSCManager, service, SERVICE_QUERY_STATUS);
if (schService != NULL) {
if (QueryServiceStatus(schService, &schSStatus))
dwPid = schSStatus.dwCurrentState;
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return dwPid == SERVICE_RUNNING ? TRUE : FALSE;
}
else
g_rescan_services = TRUE;
CloseServiceHandle(schSCManager);
return FALSE;
}
return FALSE;
}
int am_running_services(void)
{
apr_hash_index_t *hi;
apr_ssize_t len;
const char *name;
am_services_t *service;
int i = 0;
for (hi = apr_hash_first(NULL, g_services); hi; hi = apr_hash_next(hi)) {
apr_hash_this(hi, &name, &len, (void*) &service);
service->state = am_is_running(service->name, service->computer);
i += service->state;
}
return i;
}
int am_changed_services(void)
{
apr_hash_index_t *hi;
apr_ssize_t len;
const char *name;
am_services_t *service;
int i = 0, state;
for (hi = apr_hash_first(NULL, g_services); hi; hi = apr_hash_next(hi)) {
apr_hash_this(hi, &name, &len, (void*) &service);
state = am_is_running(service->name, service->computer);
if (service->state != state)
++i;
}
return i;
}
void am_show_try_icon(HWND hWnd, DWORD dwMessage)
{
NOTIFYICONDATA nid;
int i = 0, n = 0;
ZeroMemory(&nid,sizeof(nid));
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hWnd;
nid.uID = 0xFF;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uCallbackMessage = WM_TRAYMESSAGE;
i = apr_hash_count(g_services);
n = am_running_services();
if (dwMessage != NIM_DELETE) {
if (n)
nid.hIcon = g_icon_run;
else
nid.hIcon = g_icon_stop;
}
else
nid.hIcon = NULL;
if (n == i && n > 0)
lstrcpy(nid.szTip, g_messages[IDS_MSG_RUNNINGALL-IDS_MSG_FIRST]);
else if (n)
sprintf(nid.szTip, g_messages[IDS_MSG_RUNNING-IDS_MSG_FIRST], n, i);
else if (i)
sprintf(nid.szTip, g_messages[IDS_MSG_RUNNINGNONE-IDS_MSG_FIRST], i);
else
lstrcpy(nid.szTip, g_messages[IDS_MSG_NOSERVICES-IDS_MSG_FIRST]);
Shell_NotifyIcon(dwMessage, &nid);
}
void am_append_menuitem(HMENU hMenu, UINT uMenuId, char *name, BOOL fDefault, BOOL fEnabled)
{
MENUITEMINFO mii;
ZeroMemory(&mii, sizeof(MENUITEMINFO));
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
if (lstrlen(name)) {
mii.fType = MFT_STRING;
mii.wID = uMenuId;
if (fDefault)
mii.fState = MFS_DEFAULT;
if (!fEnabled)
mii.fState |= MFS_DISABLED;
mii.dwTypeData = name;
}
else
mii.fType = MFT_SEPARATOR;
InsertMenuItem(hMenu, uMenuId, FALSE, &mii);
}
void am_append_servicemenu(HMENU hMenu, UINT uMenuId, char *service, BOOL fRunning)
{
MENUITEMINFO mii;
HMENU smh;
smh = CreatePopupMenu();
am_append_menuitem(smh, IDM_SM_START + uMenuId, g_messages[IDS_MSG_SSTART-IDS_MSG_FIRST], FALSE, !fRunning);
am_append_menuitem(smh, IDM_SM_STOP + uMenuId, g_messages[IDS_MSG_SSTOP-IDS_MSG_FIRST], FALSE, fRunning);
am_append_menuitem(smh, IDM_SM_RESTART + uMenuId, g_messages[IDS_MSG_SRESTART-IDS_MSG_FIRST], FALSE, fRunning);
ZeroMemory(&mii, sizeof(MENUITEMINFO));
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU | MIIM_CHECKMARKS;
mii.fType = MFT_STRING;
mii.wID = uMenuId;
mii.hbmpChecked = g_bmp_start;
mii.hbmpUnchecked = g_bmp_stop;
mii.dwTypeData = service;
mii.hSubMenu = smh;
mii.fState = fRunning ? MFS_CHECKED : MFS_UNCHECKED;
InsertMenuItem(hMenu, IDM_SM_SERVICE + uMenuId, FALSE, &mii);
}
void am_show_popup_menu(HWND hWnd)
{
/* create popup menu */
HMENU hMenu = CreatePopupMenu();
POINT pt;
if (hMenu) {
am_append_menuitem(hMenu, IDM_RESTORE, g_messages[IDS_MSG_MNUSHOW-IDS_MSG_FIRST], TRUE, TRUE);
if (g_os_version >= OS_VERSION_WINNT)
am_append_menuitem(hMenu, IDC_SMANAGER, g_messages[IDS_MSG_MNUSERVICES-IDS_MSG_FIRST], FALSE, TRUE);
am_append_menuitem(hMenu, 0, "", FALSE, TRUE);
am_append_menuitem(hMenu, IDM_EXIT, g_messages[IDS_MSG_MNUEXIT-IDS_MSG_FIRST], FALSE, TRUE);
if (!SetForegroundWindow(hWnd))
SetForegroundWindow(NULL);
GetCursorPos(&pt);
TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON,
pt.x, pt.y, 0, hWnd, NULL);
DestroyMenu(hMenu);
}
}
void am_show_services_menu(HWND hWnd)
{
/* create services list popup menu and submenus */
HMENU hMenu = CreatePopupMenu();
POINT pt;
int i = 0;
apr_hash_index_t *hi;
apr_ssize_t len;
const char *name;
am_services_t *service;
if (hMenu) {
if (apr_hash_count(g_services)) {
for (hi = apr_hash_first(NULL, g_services); hi; hi = apr_hash_next(hi)) {
apr_hash_this(hi, &name, &len, (void*) &service);
am_append_servicemenu(hMenu, i, service->display, service->state);
++i;
}
if (!SetForegroundWindow(hWnd))
SetForegroundWindow(NULL);
GetCursorPos(&pt);
TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON,
pt.x, pt.y, 0, hWnd, NULL);
DestroyMenu(hMenu);
}
}
}
BOOL am_center_window(HWND hwndChild)
{
RECT rChild, rWorkArea;
int wChild, hChild;
int xNew, yNew;
BOOL bResult;
/* Get the Height and Width of the child window */
GetWindowRect(hwndChild, &rChild);
wChild = rChild.right - rChild.left;
hChild = rChild.bottom - rChild.top;
/* Get the limits of the 'workarea' */
bResult = SystemParametersInfo(
SPI_GETWORKAREA,
sizeof(RECT),
&rWorkArea,
0);
if (!bResult) {
rWorkArea.left = rWorkArea.top = 0;
rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
}
/* Calculate new X and Y position*/
xNew = (rWorkArea.right - wChild)/2;
yNew = (rWorkArea.bottom - hChild)/2;
return SetWindowPos (hwndChild, HWND_TOP, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
}
static void am_add_listitem(HWND hDlg, char * lpStr, HBITMAP hBmp)
{
int nItem;
nItem = SendMessage(hDlg, LB_ADDSTRING, 0, (LPARAM)lpStr);
SendMessage(hDlg, LB_SETITEMDATA, nItem, (LPARAM)hBmp);
}
static void am_add_listtext(HWND hListBox, char * lpStr)
{
static int nItems = 0;
if (!g_services_on)
return;
++nItems;
if ( nItems > MAX_LOADSTRING) {
SendMessage(hListBox, LB_RESETCONTENT, 0, 0);
nItems = 1;
}
ListBox_SetCurSel(hListBox,
ListBox_AddString(hListBox, lpStr));
}
static DWORD WINAPI am_output_thread(LPVOID lpThreadParameter)
{
static char buf[MAX_PATH+1];
int p = 0;
char ch;
DWORD dwReaded;
while (ReadFile(g_hpipeOutRead, &ch, 1, &dwReaded, NULL) == TRUE) {
if (dwReaded > 0) {
if (ch == '\n' || p >= MAX_PATH) {
buf[p] = '\0';
am_add_listtext(g_hwndStdoutList, buf);
p = 0;
}
else if (ch == '\t' && p < (MAX_PATH - 4)) {
int i;
for (i = 0; i < 4; ++i)
buf[p++] = ' ';
}
else if (ch != '\r')
buf[p++] = ch;
}
}
CloseHandle(g_hpipeInWrite);
CloseHandle(g_hpipeOutRead);
CloseHandle(g_hpipeStdError);
return 0;
}
DWORD WINAPI am_wait_thread(LPVOID lpThreadParameter)
{
WaitForSingleObject(g_lpRedirectProc.hThread, INFINITE);
CloseHandle(g_lpRedirectProc.hThread);
MessageBeep(100);
g_bConsoleRun = FALSE;
SetCursor(g_cursor_arrow);
return 0;
}
BOOL am_redirect_console(char * szCmdLine)
{
DWORD dwThreadId;
HANDLE hProc;
STARTUPINFO stInfo;
BOOL bResult;
ZeroMemory(&stInfo, sizeof(stInfo));
stInfo.cb = sizeof(stInfo);
stInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
stInfo.wShowWindow = SW_HIDE;
hProc = GetCurrentProcess();
if (!CreatePipe(&g_hpipeInRead, &g_hpipeInWrite, NULL, MAX_PATH))
am_display_error(NULL, TRUE);
if (!CreatePipe(&g_hpipeOutRead, &g_hpipeOutWrite, NULL, MAX_PATH*8))
am_display_error(NULL, TRUE);
DuplicateHandle(hProc, g_hpipeInRead, hProc, &g_hpipeInRead, 0, TRUE,
DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
DuplicateHandle(hProc, g_hpipeOutWrite, hProc, &g_hpipeOutWrite, 0, TRUE,
DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS);
DuplicateHandle(hProc, g_hpipeOutWrite, hProc, &g_hpipeStdError, 0, TRUE,
DUPLICATE_SAME_ACCESS);
if (!g_hpipeInRead && !g_hpipeOutWrite && !g_hpipeStdError)
am_display_error(NULL, TRUE);
stInfo.hStdInput = g_hpipeInRead;
stInfo.hStdOutput = g_hpipeOutWrite;
stInfo.hStdError = g_hpipeStdError;
bResult = CreateProcess(NULL,
szCmdLine,
NULL,
NULL,
TRUE,
CREATE_SUSPENDED,
NULL,
NULL ,
&stInfo,
&g_lpRedirectProc);
CloseHandle(g_hpipeInRead);
CloseHandle(g_hpipeOutWrite);
CloseHandle(g_hpipeStdError);
if (!bResult) {
CloseHandle(g_hpipeInWrite);
CloseHandle(g_hpipeOutRead);
CloseHandle(g_hpipeStdError);
return FALSE;
}
CloseHandle(CreateThread(NULL, 0, am_output_thread, 0, 0, &dwThreadId));
ResumeThread(g_lpRedirectProc.hThread);
CloseHandle(CreateThread(NULL, 0, am_wait_thread, 0, 0, &dwThreadId));
return TRUE;
}
BOOL am_run_console(char *szCmdLine,
BOOL bRedirectConsole)
{
STARTUPINFO stInfo;
PROCESS_INFORMATION prInfo;
BOOL bResult;
if (bRedirectConsole)
return am_redirect_console(szCmdLine);
ZeroMemory(&stInfo, sizeof(stInfo));
stInfo.cb = sizeof(stInfo);
stInfo.dwFlags = STARTF_USESHOWWINDOW;
stInfo.wShowWindow = SW_HIDE;
bResult = CreateProcess(NULL,
szCmdLine,
NULL,
NULL,
TRUE,
CREATE_NEW_CONSOLE,
NULL,
NULL ,
&stInfo,
&prInfo);
if (!bResult)
return FALSE;
if (g_os_version == OS_VERSION_WIN9X) /* give some time to rescan the status */
Sleep(2000);
CloseHandle(prInfo.hThread);
CloseHandle(prInfo.hProcess);
return TRUE;
}
BOOL am_manage_service(const char *name, DWORD dwCommand)
{
char buf[MAX_PATH];
char msg[MAX_PATH];
char *pos;
BOOL rv;
BOOL serviceFlag = TRUE;
SC_HANDLE schService;
SC_HANDLE schSCManager;
SERVICE_STATUS schSStatus;
char *args[3];
int ticks;
am_services_t *service;
service = apr_hash_get(g_services, name, APR_HASH_KEY_STRING);
if (!service)
return FALSE;
if (g_os_version == OS_VERSION_WIN9X) {
pos = strstr(service->path, "-k start");
if (!pos)
pos = strstr(service->path, "-k runservice");
if (pos) {
lstrcpyn(buf, service->path, pos - service->path);
switch (dwCommand) {
case SERVICE_CONTROL_STOP:
lstrcat(buf, " -k shutdown -n ");
break;
case SERVICE_CONTROL_CONTINUE:
sprintf(msg, g_messages[IDS_MSG_SRVSTART-IDS_MSG_FIRST], name);
am_add_listtext(g_hwndStdoutList, msg);
serviceFlag = FALSE;
lstrcat(buf, " -k start -n ");
break;
case SERVICE_APACHE_RESTART:
lstrcat(buf, " -k restart -n ");
break;
default:
return FALSE;
}
lstrcat(buf, service->name);
}
else
return FALSE;
g_bConsoleRun = TRUE;
SetCursor(g_cursor_hourglass);
if (!am_run_console(buf, serviceFlag)) {
am_display_error(NULL, FALSE);
g_bConsoleRun = FALSE;
SetCursor(g_cursor_arrow);
return FALSE;
}
else if (!serviceFlag) {
sprintf(msg, g_messages[IDS_MSG_SRVSTARTED-IDS_MSG_FIRST], name);
am_add_listtext(g_hwndStdoutList, msg);
g_bConsoleRun = FALSE;
SetCursor(g_cursor_arrow);
return TRUE;
}
}
else
{
/* Apache 2.0 uses '-k runservice' as cmdline parameter */
pos = strstr(service->path, "--ntservice");
if (!pos) {
pos = strstr(service->path, "-k runservice");
serviceFlag = FALSE;
}
if (pos)
lstrcpyn(buf, service->path, pos - service->path);
else
return FALSE;
schSCManager = OpenSCManager(
service->computer,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (!schSCManager)
return FALSE;
schService = OpenService(schSCManager, service->name, SERVICE_ALL_ACCESS);
if (schService != NULL) {
rv = FALSE;
g_bConsoleRun = TRUE;
SetCursor(g_cursor_hourglass);
switch (dwCommand)
{
case SERVICE_CONTROL_STOP:
sprintf(msg, g_messages[IDS_MSG_SRVSTOP-IDS_MSG_FIRST], name);
am_add_listtext(g_hwndStdoutList, msg);
if (ControlService(schService, SERVICE_CONTROL_STOP, &schSStatus)) {
Sleep(1000);
while (QueryServiceStatus(schService, &schSStatus)) {
if (schSStatus.dwCurrentState == SERVICE_STOP_PENDING)
Sleep(1000);
else
break;
}
}
if (QueryServiceStatus(schService, &schSStatus)) {
if (schSStatus.dwCurrentState == SERVICE_STOPPED) {
rv = TRUE;
sprintf(msg, g_messages[IDS_MSG_SRVSTOPPED-IDS_MSG_FIRST], name);
am_add_listtext(g_hwndStdoutList, msg);
}
}
break;
case SERVICE_CONTROL_CONTINUE:
sprintf(msg, g_messages[IDS_MSG_SRVSTART-IDS_MSG_FIRST], name);
am_add_listtext(g_hwndStdoutList, msg);
args[0] = buf;
if (serviceFlag)
args[1] = "--ntservice";
else {
args[1] = "-k";
args[2] = "runservice";
}
if (StartService(schService, serviceFlag ? 2 : 3, args))
{
Sleep(1000);
while (QueryServiceStatus(schService, &schSStatus)) {
if (schSStatus.dwCurrentState == SERVICE_START_PENDING)
Sleep(1000);
else
break;
}
}
if (QueryServiceStatus(schService, &schSStatus)) {
if (schSStatus.dwCurrentState == SERVICE_RUNNING) {
rv = TRUE;
sprintf(msg, g_messages[IDS_MSG_SRVSTARTED-IDS_MSG_FIRST], name);
am_add_listtext(g_hwndStdoutList, msg);
}
}
break;
case SERVICE_APACHE_RESTART:
sprintf(msg, g_messages[IDS_MSG_SRVRESTART-IDS_MSG_FIRST], name);
am_add_listtext(g_hwndStdoutList, msg);
if (ControlService(schService, SERVICE_APACHE_RESTART, &schSStatus)) {
ticks = 60;
while (schSStatus.dwCurrentState == SERVICE_START_PENDING) {
Sleep(1000);
if (!QueryServiceStatus(schService, &schSStatus)) {
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
g_bConsoleRun = FALSE;
SetCursor(g_cursor_arrow);
return FALSE;
}
if (!--ticks)
break;
}
}
if (schSStatus.dwCurrentState == SERVICE_RUNNING) {
rv = TRUE;
sprintf(msg, g_messages[IDS_MSG_SRVRESTARTED-IDS_MSG_FIRST], name);
am_add_listtext(g_hwndStdoutList, msg);
}
break;
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
if (!rv)
am_display_error(g_messages[IDS_MSG_SRVFAILED-IDS_MSG_FIRST], FALSE);
g_bConsoleRun = FALSE;
SetCursor(g_cursor_arrow);
return rv;
}
else
g_rescan_services = TRUE;
CloseServiceHandle(schSCManager);
return FALSE;
}
return FALSE;
}
BOOL am_services_status()
{
char szKey[MAX_PATH];
char achKey[MAX_PATH];
char path[MAX_PATH];
char buf[MAX_PATH];
HKEY hKey, hSubKey;
DWORD rc, rv, type;
spr_ssize_t len = MAX_PATH;
int i;
const char *computer;
HKEY remote;
apr_hash_index_t *hi;
g_rescan_services = FALSE;
apr_pool_destroy(g_subpool);
apr_pool_create(&g_subpool, g_pool);
g_services = apr_hash_make(g_subpool);
for (hi = apr_hash_first(NULL, g_computers); hi; hi = apr_hash_next(hi)) {
apr_hash_this(hi, &computer, &len, (void*) &remote);
rc = RegOpenKeyEx(remote,
"System\\CurrentControlSet\\Services\\",
0, KEY_READ, &hKey);
if (rc != ERROR_SUCCESS) {
am_display_error(NULL, FALSE);
return FALSE;
}
for (i = 0, rc = ERROR_SUCCESS; rc == ERROR_SUCCESS; i++) {
rc = RegEnumKey(hKey, i, achKey, MAX_PATH);
if (rc == ERROR_SUCCESS) {
lstrcpy(szKey, "System\\CurrentControlSet\\Services\\");
lstrcat(szKey, achKey);
if (RegOpenKeyEx(remote, szKey, 0,
KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS) {
len = MAX_PATH;
rv = RegQueryValueEx(hSubKey, "ImagePath", NULL,
&type, path, &len);
if (rv == ERROR_SUCCESS && (type == REG_SZ
|| type == REG_EXPAND_SZ) && len) {
lstrcpy(buf, path);
CharLower(buf);
/* the service name could be Apache*.exe */
if (strstr(buf, "\\apache") != NULL && strstr(buf, ".exe") &&
(strstr(buf, "--ntservice") != NULL || strstr(buf, "-k ") !=NULL)) {
am_services_t *service;
service = apr_pcalloc(g_subpool, sizeof(am_services_t));
service->name = apr_pstrdup(g_subpool, achKey);
service->path = apr_pstrdup(g_subpool, path);
service->computer = computer;
len = MAX_PATH;
if (RegQueryValueEx(hSubKey, "Description", NULL,
&type, buf, &len) == ERROR_SUCCESS)
service->description = apr_pstrdup(g_subpool, buf);
len = MAX_PATH;
if (RegQueryValueEx(hSubKey, "DisplayName", NULL,
&type, buf, &len) == ERROR_SUCCESS) {
if (strcmp(computer, g_hostname))
service->display = apr_pstrcat(g_subpool, computer, "@", buf, NULL);
else
service->display = apr_pstrdup(g_subpool, buf);
}
else
service->display = service->name;
service->state = am_is_running(service->name, computer);
apr_hash_set(g_services, service->display,
APR_HASH_KEY_STRING, service);
}
}
RegCloseKey(hSubKey);
}
}
}
RegCloseKey(hKey);
}
am_running_services();
return TRUE;
}
LRESULT CALLBACK am_connectdlg_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
char buf[MAX_COMPUTERNAME_LENGTH+4];
switch (message) {
case WM_INITDIALOG:
ShowWindow(hDlg, SW_HIDE);
g_hwndConnectDlg = hDlg;
am_center_window(hDlg);
ShowWindow(hDlg, SW_SHOW);
SetFocus(GetDlgItem(hDlg, IDC_COMPUTER));
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
ZeroMemory(buf, MAX_COMPUTERNAME_LENGTH+4);
strcpy(buf, "\\\\");
SendMessage(GetDlgItem(hDlg, IDC_COMPUTER), WM_GETTEXT,
(WPARAM) MAX_COMPUTERNAME_LENGTH, (LPARAM) buf+2);
strupr(buf);
if (strlen(buf) < 3) {
EndDialog(hDlg, TRUE);
return TRUE;
}
am_connect_computer(buf);
SendMessage(g_hwnd_main, WM_TIMER, WM_TIMER_RESCAN, 0);
case IDCANCEL:
EndDialog(hDlg, TRUE);
return TRUE;
case IDC_LBROWSE:
{
BROWSEINFO bi;
ITEMIDLIST *il;
LPMALLOC pMalloc;
memset(&bi, 0, sizeof(BROWSEINFO));
SHGetSpecialFolderLocation(hDlg, CSIDL_NETWORK, &il);
bi.lpszTitle = "ApacheMonitor :\nSelect Network Computer!";
bi.pszDisplayName = buf;
bi.hwndOwner = hDlg;
bi.ulFlags = BIF_BROWSEFORCOMPUTER;
bi.lpfn = NULL;
bi.lParam = 0;
bi.iImage = 0;
bi.pidlRoot = il;
if (SHBrowseForFolder(&bi) != NULL) {
SendMessage(GetDlgItem(hDlg, IDC_COMPUTER), WM_SETTEXT,
(WPARAM) NULL, (LPARAM) buf);
}
if (SHGetMalloc(&pMalloc)) {
pMalloc->lpVtbl->Free(pMalloc, il);
pMalloc->lpVtbl->Release(pMalloc);
}
}
return TRUE;
}
break;
case WM_QUIT:
case WM_CLOSE:
EndDialog(hDlg, TRUE);
return TRUE;
default:
return FALSE;
}
return FALSE;
}
LRESULT CALLBACK am_servicedlg_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
char sname[MAX_PATH] = {0};
HWND hListBox;
static HWND hStatusBar;
TEXTMETRIC tm;
int y;
HDC hdcMem;
RECT rcBitmap;
UINT nItem;
LPMEASUREITEMSTRUCT lpmis;
LPDRAWITEMSTRUCT lpdis;
apr_hash_index_t *hi;
apr_ssize_t len;
const char *name;
am_services_t *service;
switch (message) {
case WM_INITDIALOG:
ShowWindow(hDlg, SW_HIDE);
g_hwnd_service = hDlg;
SetWindowText(hDlg, g_title);
Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), FALSE);
SetWindowText(GetDlgItem(hDlg, IDC_SSTART), g_messages[IDS_MSG_SSTART-IDS_MSG_FIRST]);
SetWindowText(GetDlgItem(hDlg, IDC_SSTOP), g_messages[IDS_MSG_SSTOP-IDS_MSG_FIRST]);
SetWindowText(GetDlgItem(hDlg, IDC_SRESTART), g_messages[IDS_MSG_SRESTART-IDS_MSG_FIRST]);
SetWindowText(GetDlgItem(hDlg, IDC_SMANAGER), g_messages[IDS_MSG_SERVICES-IDS_MSG_FIRST]);
SetWindowText(GetDlgItem(hDlg, IDC_SCONNECT), g_messages[IDS_MSG_CONNECT-IDS_MSG_FIRST]);
SetWindowText(GetDlgItem(hDlg, IDC_SEXIT), g_messages[IDS_MSG_MNUEXIT-IDS_MSG_FIRST]);
if (g_os_version < OS_VERSION_WINNT) {
ShowWindow(GetDlgItem(hDlg, IDC_SMANAGER), SW_HIDE);
ShowWindow(GetDlgItem(hDlg, IDC_SCONNECT), SW_HIDE);
ShowWindow(GetDlgItem(hDlg, IDC_SDISCONN), SW_HIDE);
}
hListBox = GetDlgItem(hDlg, IDL_SERVICES);
g_hwndStdoutList = GetDlgItem(hDlg, IDL_STDOUT);
hStatusBar = CreateStatusWindow(0x0800 /* SBT_TOOLTIPS */
| WS_CHILD | WS_VISIBLE,
"", hDlg, IDC_STATBAR);
if (am_services_status()) {
for (hi = apr_hash_first(NULL, g_services); hi; hi = apr_hash_next(hi)) {
apr_hash_this(hi, &name, &len, (void*) &service);
am_add_listitem(hListBox, service->display,
service->state ? g_bmp_start : g_bmp_stop);
}
}
am_center_window(hDlg);
ShowWindow(hDlg, SW_SHOW);
SetFocus(hListBox);
SendMessage(hListBox, LB_SETCURSEL, 0, 0);
return TRUE;
break;
case WM_MANAGEMESSAGE:
hListBox = GetDlgItem(hDlg, IDL_SERVICES);
SendMessage(hListBox, LB_GETTEXT,
LOWORD(wParam), (LPARAM) sname);
am_manage_service(sname, LOWORD(lParam));
return TRUE;
break;
case WM_UPDATEMESSAGE:
hListBox = GetDlgItem(hDlg, IDL_SERVICES);
SendMessage(hListBox, LB_RESETCONTENT, 0, 0);
SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"");
Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), FALSE);
for (hi = apr_hash_first(NULL, g_services); hi; hi = apr_hash_next(hi)) {
apr_hash_this(hi, &name, &len, (void*) &service);
am_add_listitem(hListBox, service->display,
service->state ? g_bmp_start : g_bmp_stop);
}
SendMessage(hListBox, LB_SETCURSEL, 0, 0);
/* Dirty hack to bring the window to the foreground */
SetWindowPos(hDlg, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
SetWindowPos(hDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
SetFocus(hListBox);
return TRUE;
break;
case WM_MEASUREITEM:
lpmis = (LPMEASUREITEMSTRUCT) lParam;
lpmis->itemHeight = YBITMAP;
return TRUE;
case WM_SETCURSOR:
if (g_bConsoleRun)
SetCursor(g_cursor_hourglass);
else
SetCursor(g_cursor_arrow);
return TRUE;
case WM_DRAWITEM:
lpdis = (LPDRAWITEMSTRUCT) lParam;
if (lpdis->itemID == -1)
break;
switch (lpdis->itemAction) {
case ODA_SELECT:
case ODA_DRAWENTIRE:
g_bmp_cur = (HBITMAP)SendMessage(lpdis->hwndItem,
LB_GETITEMDATA, lpdis->itemID, (LPARAM) 0);
hdcMem = CreateCompatibleDC(lpdis->hDC);
g_bmp_old = SelectObject(hdcMem, g_bmp_cur);
BitBlt(lpdis->hDC,
lpdis->rcItem.left, lpdis->rcItem.top,
lpdis->rcItem.right - lpdis->rcItem.left,
lpdis->rcItem.bottom - lpdis->rcItem.top,
hdcMem, 0, 0, SRCCOPY);
SendMessage(lpdis->hwndItem, LB_GETTEXT,
lpdis->itemID, (LPARAM) sname);
service = apr_hash_get(g_services, sname, APR_HASH_KEY_STRING);
GetTextMetrics(lpdis->hDC, &tm);
y = (lpdis->rcItem.bottom + lpdis->rcItem.top -
tm.tmHeight) / 2;
SelectObject(hdcMem, g_bmp_old);
DeleteDC(hdcMem);
rcBitmap.left = lpdis->rcItem.left + XBITMAP + 2;
rcBitmap.top = lpdis->rcItem.top;
rcBitmap.right = lpdis->rcItem.right;
rcBitmap.bottom = lpdis->rcItem.top + YBITMAP;
if (lpdis->itemState & ODS_SELECTED) {
if (g_bmp_cur == g_bmp_stop) {
Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
}
else if (g_bmp_cur == g_bmp_start) {
Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
}
else {
Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
}
if (!strcmp(service->computer, g_hostname))
Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), FALSE);
else
Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), TRUE);
if (service->description)
SendMessage(hStatusBar, SB_SETTEXT, 0,
(LPARAM)service->description);
else
SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)"");
SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_HIGHLIGHTTEXT));
}
else {
SetTextColor(lpdis->hDC, GetSysColor(COLOR_MENUTEXT));
SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_WINDOW+1));
}
TextOut(lpdis->hDC,
XBITMAP + 6,
y,
sname,
strlen(sname));
break;
case ODA_FOCUS:
break;
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDL_SERVICES:
switch (HIWORD(wParam)) {
case LBN_DBLCLK:
/* if started then stop, if stopped then start the service */
hListBox = GetDlgItem(hDlg, IDL_SERVICES);
nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
if (nItem != LB_ERR) {
g_bmp_cur = (HBITMAP)SendMessage(hListBox, LB_GETITEMDATA,
nItem, (LPARAM) 0);
if (g_bmp_cur == g_bmp_stop)
SendMessage(hDlg, WM_MANAGEMESSAGE, nItem, SERVICE_CONTROL_CONTINUE);
else
SendMessage(hDlg, WM_MANAGEMESSAGE, nItem, SERVICE_CONTROL_STOP);
}
return TRUE;
break;
}
break;
case IDOK:
EndDialog(hDlg, TRUE);
return TRUE;
case IDC_SSTART:
Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE);
hListBox = GetDlgItem(hDlg, IDL_SERVICES);
nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
if (nItem != LB_ERR)
SendMessage(hDlg, WM_MANAGEMESSAGE, nItem, SERVICE_CONTROL_CONTINUE);
Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
return TRUE;
case IDC_SSTOP:
Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
hListBox = GetDlgItem(hDlg, IDL_SERVICES);
nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
if (nItem != LB_ERR)
SendMessage(hDlg, WM_MANAGEMESSAGE, nItem, SERVICE_CONTROL_STOP);
Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), TRUE);
return TRUE;
case IDC_SRESTART:
Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
hListBox = GetDlgItem(hDlg, IDL_SERVICES);
nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
if (nItem != LB_ERR)
SendMessage(hDlg, WM_MANAGEMESSAGE, nItem, SERVICE_APACHE_RESTART);
Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), TRUE);
return TRUE;
case IDC_SMANAGER:
if (g_os_version >= OS_VERSION_WIN2K)
ShellExecute(hDlg, "open", "services.msc", "/s", NULL, SW_NORMAL);
else
WinExec("Control.exe SrvMgr.cpl Services", SW_NORMAL);
return TRUE;
case IDC_SEXIT:
EndDialog( hDlg, TRUE);
SendMessage( g_hwnd_main, WM_COMMAND, (WPARAM)IDM_EXIT, 0);
return TRUE;
case IDC_SCONNECT:
DialogBox(g_instance, MAKEINTRESOURCE(IDD_DLGCONNECT),
hDlg, (DLGPROC)am_connectdlg_proc);
return TRUE;
case IDC_SDISCONN:
hListBox = GetDlgItem(hDlg, IDL_SERVICES);
nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
SendMessage(hListBox, LB_GETTEXT, nItem, (LPARAM) sname);
if (nItem != LB_ERR) {
service = apr_hash_get(g_services, sname, APR_HASH_KEY_STRING);
if (service)
am_disconnect_computer(service->computer);
SendMessage(g_hwnd_main, WM_TIMER, WM_TIMER_RESCAN, 0);
}
return TRUE;
}
break;
case WM_SIZE:
switch (LOWORD(wParam)) {
case SIZE_MINIMIZED:
EndDialog(hDlg, TRUE);
return TRUE;
break;
}
break;
case WM_QUIT:
case WM_CLOSE:
EndDialog(hDlg, TRUE);
return TRUE;
default:
return FALSE;
}
return FALSE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
int i, n, cmd = 0;
apr_hash_index_t *hi;
apr_ssize_t len;
const char *name;
am_services_t *service = NULL;
if (message == g_taskbar_created) {
/* restore the tray icon on shell restart */
am_show_try_icon(hWnd, NIM_ADD);
return DefWindowProc(hWnd, message, wParam, lParam);
}
switch (message) {
case WM_CREATE:
am_services_status();
am_show_try_icon(hWnd, NIM_ADD);
SetTimer(hWnd, WM_TIMER_REFRESH, REFRESH_TIME, NULL);
SetTimer(hWnd, WM_TIMER_RESCAN, RESCAN_TIME, NULL);
break;
case WM_TIMER:
switch (wParam) {
case WM_TIMER_RESCAN:
{
int prun, nrun;
apr_thread_mutex_lock(g_mutex);
if (am_changed_services() || g_rescan_services) {
am_show_try_icon(hWnd, NIM_MODIFY);
if (g_hwnd_service)
PostMessage(g_hwnd_service, WM_UPDATEMESSAGE, 0, 0);
}
/* check if services list changed */
prun = apr_hash_count(g_services);
am_services_status();
nrun = apr_hash_count(g_services);
if (prun != nrun) {
am_show_try_icon(hWnd, NIM_MODIFY);
if (g_hwnd_service)
PostMessage(g_hwnd_service, WM_UPDATEMESSAGE, 0, 0);
}
apr_thread_mutex_unlock(g_mutex);
break;
}
case WM_TIMER_REFRESH:
apr_thread_mutex_lock(g_mutex);
if (g_rescan_services) {
am_services_status();
am_show_try_icon(hWnd, NIM_MODIFY);
if (g_hwnd_service)
PostMessage(g_hwnd_service, WM_UPDATEMESSAGE, 0, 0);
}
else if (am_changed_services()) {
am_show_try_icon(hWnd, NIM_MODIFY);
if (g_hwnd_service)
PostMessage(g_hwnd_service, WM_UPDATEMESSAGE, 0, 0);
}
apr_thread_mutex_unlock(g_mutex);
break;
break;
}
break;
case WM_QUIT:
am_show_try_icon(hWnd, NIM_DELETE);
break;
case WM_TRAYMESSAGE:
switch(lParam) {
case WM_LBUTTONDBLCLK:
if (!g_services_on) {
g_services_on = TRUE;
DialogBox(g_instance, MAKEINTRESOURCE(IDD_DLGSERVICES),
hWnd, (DLGPROC)am_servicedlg_proc);
g_services_on = FALSE;
g_hwnd_service = NULL;
}
else if (IsWindow(g_hwnd_service)) {
/* Dirty hack to bring the window to the foreground */
SetWindowPos(g_hwnd_service, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
SetWindowPos(g_hwnd_service, HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
SetFocus(g_hwnd_service);
}
break;
case WM_LBUTTONUP:
am_show_services_menu(hWnd);
break;
case WM_RBUTTONUP:
am_show_popup_menu(hWnd);
break;
}
break;
case WM_COMMAND:
if ((LOWORD(wParam) & IDM_SM_SERVICE)) {
i = 0;
n = -1;
cmd = 0;
if ((LOWORD(wParam) & IDM_SM_START) == IDM_SM_START) {
n = LOWORD(wParam) - IDM_SM_START;
cmd = SERVICE_CONTROL_CONTINUE;
}
else if ((LOWORD(wParam) & IDM_SM_STOP) == IDM_SM_STOP) {
n = LOWORD(wParam) - IDM_SM_STOP;
cmd = SERVICE_CONTROL_STOP;
}
else if ((LOWORD(wParam) & IDM_SM_RESTART) == IDM_SM_RESTART) {
n = LOWORD(wParam) - IDM_SM_RESTART;
cmd = SERVICE_APACHE_RESTART;
}
for (hi = apr_hash_first(NULL, g_services); hi; hi = apr_hash_next(hi)) {
apr_hash_this(hi, &name, &len, (void*) &service);
if (i == n)
break;
++i;
}
if (cmd && service)
am_manage_service(service->display, cmd);
return TRUE;
}
switch (LOWORD(wParam))
{
case IDM_RESTORE:
if (!g_services_on) {
g_services_on = TRUE;
DialogBox(g_instance, MAKEINTRESOURCE(IDD_DLGSERVICES),
hWnd, (DLGPROC)am_servicedlg_proc);
g_services_on = FALSE;
g_hwnd_service = NULL;
}
else if (IsWindow(g_hwnd_service))
SetFocus(g_hwnd_service);
break;
case IDC_SMANAGER:
if (g_os_version >= OS_VERSION_WIN2K)
ShellExecute(NULL, "open", "services.msc", "/s", NULL, SW_NORMAL);
else
WinExec("Control.exe SrvMgr.cpl Services", SW_NORMAL);
return TRUE;
case IDM_EXIT:
am_show_try_icon(hWnd, NIM_DELETE);
PostQuitMessage(0);
return TRUE;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return FALSE;
}
/* Create main invisible window */
HWND am_create_main_window(HINSTANCE hInstance)
{
HWND hWnd = NULL;
WNDCLASSEX wcex;
if (!am_get_os(&g_os_version)) {
am_display_error(NULL, TRUE);
return hWnd;
}
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_APSRVMON),
IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
wcex.hCursor = g_cursor_arrow;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = 0;
wcex.lpszClassName = g_window_class;
wcex.hIconSm = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_APSRVMON),
IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
if (RegisterClassEx(&wcex))
hWnd = CreateWindow(g_window_class, g_title,
0, 0, 0, 0, 0,
NULL, NULL, hInstance, NULL);
return hWnd;
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
char * lpCmdLine,
int nCmdShow)
{
char tmp[MAX_LOADSTRING];
char buf[MAX_COMPUTERNAME_LENGTH+4];
MSG msg;
/* single instance mutex */
int i;
DWORD d;
HANDLE single_instance = NULL;
apr_status_t stat = APR_SUCCESS;
apr_initialize();
atexit(apr_terminate);
apr_pool_create(&g_pool, NULL);
apr_pool_create(&g_subpool, g_pool);
g_computers = apr_hash_make(g_pool);
g_services = apr_hash_make(g_subpool);
g_language_id = GetUserDefaultLangID();
if ((g_language_id & 0xFF) != LANG_ENGLISH)
g_language_id = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
for (i = IDS_MSG_FIRST; i <= IDS_MSG_LAST; ++i) {
LoadString(hInstance, i, tmp, MAX_LOADSTRING);
g_messages[i - IDS_MSG_FIRST] = strdup(tmp);
}
LoadString(hInstance, IDS_APMONITORTITLE, tmp, MAX_LOADSTRING);
d = MAX_COMPUTERNAME_LENGTH+1;
strcpy(buf, "\\\\");
GetComputerName(buf + 2, &d);
strupr(buf);
strcpy(g_hostname, buf);
apr_hash_set(g_computers, buf, APR_HASH_KEY_STRING, HKEY_LOCAL_MACHINE);
g_title = strdup(tmp);
LoadString(hInstance, IDS_APMONITORCLASS, tmp, MAX_LOADSTRING);
g_window_class = strdup(tmp);
g_icon_stop = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICOSTOP),
IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
g_icon_run = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICORUN),
IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
g_cursor_hourglass = LoadImage(NULL, MAKEINTRESOURCE(OCR_WAIT), IMAGE_CURSOR,
LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED);
g_cursor_arrow = LoadImage(NULL, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR,
LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED);
g_bmp_start = LoadImage(hInstance, MAKEINTRESOURCE(IDB_BMPRUN),
IMAGE_BITMAP, XBITMAP, YBITMAP, LR_DEFAULTCOLOR);
g_bmp_stop = LoadImage(hInstance, MAKEINTRESOURCE(IDB_BMPSTOP),
IMAGE_BITMAP, XBITMAP, YBITMAP, LR_DEFAULTCOLOR);
single_instance = CreateMutex(NULL, FALSE, "APACHEMONITOR_MUTEX");
if ((single_instance == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS)) {
am_display_error(g_messages[IDS_MSG_APPRUNNING-IDS_MSG_FIRST], FALSE);
goto out;
}
if ((stat = apr_thread_mutex_create(&g_mutex,
APR_THREAD_MUTEX_DEFAULT, g_pool)) != APR_SUCCESS)
goto out;
CoInitialize(NULL);
InitCommonControls();
g_instance = hInstance;
g_hwnd_main = am_create_main_window(hInstance);
g_taskbar_created = RegisterWindowMessage("TaskbarCreated");
g_hwnd_service = NULL;
if (g_hwnd_main != NULL) {
while (GetMessage(&msg, NULL, 0, 0) == TRUE) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
/* Free allocated resources */
DestroyIcon(g_icon_stop);
DestroyIcon(g_icon_run);
DestroyCursor(g_cursor_hourglass);
DestroyCursor(g_cursor_arrow);
DeleteObject(g_bmp_start);
DeleteObject(g_bmp_stop);
CoUninitialize();
CloseHandle(single_instance);
apr_terminate();
return 0;
out:
if (single_instance)
CloseHandle(single_instance);
return stat;
}