1
0
mirror of https://github.com/apache/httpd.git synced 2025-11-06 16:49:32 +03:00
Files
apache/support/win32/ApacheMonitor.c
William A. Rowe Jr c005b2a161 Enable UAC transition from ApacheMonitor running as a vanilla user without priv
into a copy runas administrator with permissions (closing the original monitor),
in response to any start/stop/restart request who's control permissions failed.
This happens to work on Win2000 and later, although it is actually needed in 
Win2008 or Vista and later, where by default under UAC, the admin user actually 
has no permissions to control services unless the app is run elevated.  

We don't want to do this at start time, and assault the user with auth attempts
at login before they have even asked to use the features of the Monitor.  Once
we've made the transition, we'll leave the new monitor running elevated.  Some
branding with the "security" shield icon is actually recommended by the CUA, but
I'm neglecting this for the moment.

This patch drops the single instance mutex for a search of existing windows of 
our window's class & title, which is localized to the current session and just fine
for the purpose of restricting multiple invocations.




git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@633607 13f79535-47bb-0310-9956-ffa450edef68
2008-03-04 19:44:22 +00:00

1946 lines
61 KiB
C

/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* ====================================================================
* ApacheMonitor.c Simple program to manage and monitor Apache services.
*
* Contributed by Mladen Turk <mturk mappingsoft.com>
*
* 05 Aug 2001
* ====================================================================
*/
#define _WIN32_WINNT 0x0500
#ifndef STRICT
#define STRICT
#endif
#ifndef OEMRESOURCE
#define OEMRESOURCE
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400
#define _CRT_SECURE_NO_DEPRECATE
#endif
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <objbase.h>
#include <shlobj.h>
#include <stdlib.h>
#include <stdio.h>
#include <WtsApi32.h>
#include <tchar.h>
#include "ApacheMonitor.h"
#ifndef AM_STRINGIFY
/** Properly quote a value as a string in the C preprocessor */
#define AM_STRINGIFY(n) AM_STRINGIFY_HELPER(n)
/** Helper macro for AM_STRINGIFY */
#define AM_STRINGIFY_HELPER(n) #n
#endif
#define OS_VERSION_WIN9X 1
#define OS_VERSION_WINNT 2
#define OS_VERSION_WIN2K 3
/* Should be enough */
#define MAX_APACHE_SERVICES 128
#define MAX_APACHE_COMPUTERS 32
#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 _st_APACHE_SERVICE
{
LPTSTR szServiceName;
LPTSTR szDisplayName;
LPTSTR szDescription;
LPTSTR szImagePath;
LPTSTR szComputerName;
DWORD dwPid;
} ST_APACHE_SERVICE;
typedef struct _st_MONITORED_COMPUTERS
{
LPTSTR szComputerName;
HKEY hRegistry;
} ST_MONITORED_COMP;
/* Global variables */
HINSTANCE g_hInstance = NULL;
TCHAR *g_szTitle; /* The title bar text */
TCHAR *g_szWindowClass; /* Window Class Name */
HICON g_icoStop;
HICON g_icoRun;
UINT g_bUiTaskbarCreated;
DWORD g_dwOSVersion;
BOOL g_bDlgServiceOn = FALSE;
BOOL g_bConsoleRun = FALSE;
ST_APACHE_SERVICE g_stServices[MAX_APACHE_SERVICES];
ST_MONITORED_COMP g_stComputers[MAX_APACHE_COMPUTERS];
HBITMAP g_hBmpStart, g_hBmpStop;
HBITMAP g_hBmpPicture, g_hBmpOld;
BOOL g_bRescanServices;
HWND g_hwndServiceDlg;
HWND g_hwndMain;
HWND g_hwndStdoutList;
HWND g_hwndConnectDlg;
HCURSOR g_hCursorHourglass;
HCURSOR g_hCursorArrow;
HANDLE g_hpipeOutRead;
HANDLE g_hpipeOutWrite;
HANDLE g_hpipeInRead;
HANDLE g_hpipeInWrite;
HANDLE g_hpipeStdError;
LANGID g_LangID;
PROCESS_INFORMATION g_lpRedirectProc;
CRITICAL_SECTION g_stcSection;
LPTSTR g_szLocalHost;
/* locale language support */
static TCHAR *g_lpMsg[IDS_MSG_LAST - IDS_MSG_FIRST + 1];
void am_ClearServicesSt()
{
int i;
for (i = 0; i < MAX_APACHE_SERVICES; i++)
{
if (g_stServices[i].szServiceName) {
free(g_stServices[i].szServiceName);
}
if (g_stServices[i].szDisplayName) {
free(g_stServices[i].szDisplayName);
}
if (g_stServices[i].szDescription) {
free(g_stServices[i].szDescription);
}
if (g_stServices[i].szImagePath) {
free(g_stServices[i].szImagePath);
}
if (g_stServices[i].szComputerName) {
free(g_stServices[i].szComputerName);
}
}
memset(g_stServices, 0, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
}
void am_ClearComputersSt()
{
int i;
for (i = 0; i < MAX_APACHE_COMPUTERS; i++) {
if (g_stComputers[i].szComputerName) {
free(g_stComputers[i].szComputerName);
RegCloseKey(g_stComputers[i].hRegistry);
}
}
memset(g_stComputers, 0, sizeof(ST_MONITORED_COMP) * MAX_APACHE_COMPUTERS);
}
BOOL am_IsComputerConnected(LPTSTR szComputerName)
{
int i = 0;
while (g_stComputers[i].szComputerName != NULL) {
if (_tcscmp(g_stComputers[i].szComputerName, szComputerName) == 0) {
return TRUE;
}
++i;
}
return FALSE;
}
void am_DisconnectComputer(LPTSTR szComputerName)
{
int i = 0, j;
while (g_stComputers[i].szComputerName != NULL) {
if (_tcscmp(g_stComputers[i].szComputerName, szComputerName) == 0) {
break;
}
++i;
}
if (g_stComputers[i].szComputerName != NULL) {
free(g_stComputers[i].szComputerName);
RegCloseKey(g_stComputers[i].hRegistry);
for (j = i; j < MAX_APACHE_COMPUTERS - 1; j++) {
g_stComputers[j].szComputerName= g_stComputers[j+1].szComputerName;
g_stComputers[j].hRegistry = g_stComputers[j+1].hRegistry;
}
g_stComputers[j].szComputerName = NULL;
g_stComputers[j].hRegistry = NULL;
}
}
void ErrorMessage(LPCTSTR szError, BOOL bFatal)
{
LPVOID lpMsgBuf = NULL;
if (szError) {
MessageBox(NULL, szError, g_lpMsg[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_LangID,
(LPTSTR) &lpMsgBuf, 0, NULL);
MessageBox(NULL, (LPCTSTR)lpMsgBuf,
g_lpMsg[IDS_MSG_ERROR - IDS_MSG_FIRST],
MB_OK | (bFatal ? MB_ICONERROR : MB_ICONEXCLAMATION));
LocalFree(lpMsgBuf);
}
if (bFatal) {
PostQuitMessage(0);
}
}
int am_RespawnAsUserAdmin(HWND hwnd, DWORD op, LPCTSTR szService,
LPCTSTR szComputerName)
{
TCHAR args[MAX_PATH + MAX_COMPUTERNAME_LENGTH + 12];
if (g_dwOSVersion < OS_VERSION_WIN2K) {
ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST], FALSE);
return 0;
}
_sntprintf(args, sizeof(args) / sizeof(TCHAR),
_T("%d \"%s\" \"%s\""), op, szService,
szComputerName ? szComputerName : _T(""));
if (!ShellExecute(hwnd, _T("runas"), __targv[0], args, NULL, SW_NORMAL)) {
ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST],
FALSE);
return 0;
}
return 1;
}
BOOL am_ConnectComputer(LPTSTR szComputerName)
{
int i = 0;
HKEY hKeyRemote;
TCHAR szTmp[MAX_PATH];
while (g_stComputers[i].szComputerName != NULL) {
if (_tcscmp(g_stComputers[i].szComputerName, szComputerName) == 0) {
return FALSE;
}
++i;
}
if (i > MAX_APACHE_COMPUTERS - 1) {
return FALSE;
}
if (RegConnectRegistry(szComputerName, HKEY_LOCAL_MACHINE, &hKeyRemote)
!= ERROR_SUCCESS) {
_sntprintf(szTmp, sizeof(szTmp) / sizeof(TCHAR),
g_lpMsg[IDS_MSG_ECONNECT - IDS_MSG_FIRST],
szComputerName);
ErrorMessage(szTmp, FALSE);
return FALSE;
}
else {
g_stComputers[i].szComputerName = _tcsdup(szComputerName);
g_stComputers[i].hRegistry = hKeyRemote;
return TRUE;
}
}
LPTSTR GetStringRes(int id)
{
static TCHAR buffer[MAX_PATH];
buffer[0] = 0;
LoadString(GetModuleHandle(NULL), id, buffer, MAX_PATH);
return buffer;
}
BOOL GetSystemOSVersion(LPDWORD dwVersion)
{
OSVERSIONINFO osvi;
/*
Try calling GetVersionEx using the OSVERSIONINFOEX structure.
If that fails, try using the OSVERSIONINFO structure.
*/
memset(&osvi, 0, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&osvi)) {
return FALSE;
}
switch (osvi.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:
if (osvi.dwMajorVersion >= 5)
*dwVersion = OS_VERSION_WIN2K;
else
*dwVersion = OS_VERSION_WINNT;
break;
case VER_PLATFORM_WIN32_WINDOWS:
*dwVersion = OS_VERSION_WIN9X;
break;
case VER_PLATFORM_WIN32s:
default:
*dwVersion = 0;
return FALSE;
}
return TRUE;
}
static VOID ShowNotifyIcon(HWND hWnd, DWORD dwMessage)
{
NOTIFYICONDATA nid;
int i = 0, n = 0;
memset(&nid, 0, sizeof(nid));
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hWnd;
nid.uID = 0xFF;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uCallbackMessage = WM_TRAYMESSAGE;
while (g_stServices[i].szServiceName != NULL)
{
if (g_stServices[i].dwPid != 0) {
++n;
}
++i;
}
if (dwMessage != NIM_DELETE)
{
if (n) {
nid.hIcon = g_icoRun;
}
else {
nid.hIcon = g_icoStop;
}
}
else {
nid.hIcon = NULL;
}
if (n == i && n > 0) {
_tcscpy(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGALL - IDS_MSG_FIRST]);
}
else if (n) {
_sntprintf(nid.szTip, sizeof(nid.szTip) / sizeof(TCHAR),
g_lpMsg[IDS_MSG_RUNNING - IDS_MSG_FIRST], n, i);
}
else if (i) {
_sntprintf(nid.szTip, sizeof(nid.szTip) / sizeof(TCHAR),
g_lpMsg[IDS_MSG_RUNNINGNONE - IDS_MSG_FIRST], i);
}
else {
_tcscpy(nid.szTip, g_lpMsg[IDS_MSG_NOSERVICES - IDS_MSG_FIRST]);
}
Shell_NotifyIcon(dwMessage, &nid);
}
void appendMenuItem(HMENU hMenu, UINT uMenuId, LPTSTR szName,
BOOL fDefault, BOOL fEnabled)
{
MENUITEMINFO mii;
memset(&mii, 0, sizeof(MENUITEMINFO));
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
if (_tcslen(szName))
{
mii.fType = MFT_STRING;
mii.wID = uMenuId;
if (fDefault) {
mii.fState = MFS_DEFAULT;
}
if (!fEnabled) {
mii.fState |= MFS_DISABLED;
}
mii.dwTypeData = szName;
}
else {
mii.fType = MFT_SEPARATOR;
}
InsertMenuItem(hMenu, uMenuId, FALSE, &mii);
}
void appendServiceMenu(HMENU hMenu, UINT uMenuId,
LPTSTR szServiceName, BOOL fRunning)
{
MENUITEMINFO mii;
HMENU smh;
smh = CreatePopupMenu();
appendMenuItem(smh, IDM_SM_START + uMenuId,
g_lpMsg[IDS_MSG_SSTART - IDS_MSG_FIRST], FALSE, !fRunning);
appendMenuItem(smh, IDM_SM_STOP + uMenuId,
g_lpMsg[IDS_MSG_SSTOP - IDS_MSG_FIRST], FALSE, fRunning);
appendMenuItem(smh, IDM_SM_RESTART + uMenuId,
g_lpMsg[IDS_MSG_SRESTART - IDS_MSG_FIRST], FALSE, fRunning);
memset(&mii, 0, 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_hBmpStart;
mii.hbmpUnchecked = g_hBmpStop;
mii.dwTypeData = szServiceName;
mii.hSubMenu = smh;
mii.fState = fRunning ? MFS_CHECKED : MFS_UNCHECKED;
InsertMenuItem(hMenu, IDM_SM_SERVICE + uMenuId, FALSE, &mii);
}
void ShowTryPopupMenu(HWND hWnd)
{
/* create popup menu */
HMENU hMenu = CreatePopupMenu();
POINT pt;
if (hMenu)
{
appendMenuItem(hMenu, IDM_RESTORE,
g_lpMsg[IDS_MSG_MNUSHOW - IDS_MSG_FIRST],
TRUE, TRUE);
if (g_dwOSVersion >= OS_VERSION_WINNT) {
appendMenuItem(hMenu, IDC_SMANAGER,
g_lpMsg[IDS_MSG_MNUSERVICES - IDS_MSG_FIRST],
FALSE, TRUE);
}
appendMenuItem(hMenu, 0, _T(""), FALSE, TRUE);
appendMenuItem(hMenu, IDM_EXIT,
g_lpMsg[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 ShowTryServicesMenu(HWND hWnd)
{
/* create services list popup menu and submenus */
HMENU hMenu = CreatePopupMenu();
POINT pt;
int i = 0;
if (hMenu)
{
while (g_stServices[i].szServiceName != NULL)
{
appendServiceMenu(hMenu, i, g_stServices[i].szDisplayName,
g_stServices[i].dwPid != 0);
++i;
}
if (i)
{
if (!SetForegroundWindow(hWnd)) {
SetForegroundWindow(NULL);
}
GetCursorPos(&pt);
TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON,
pt.x, pt.y, 0, hWnd, NULL);
DestroyMenu(hMenu);
}
}
}
BOOL CenterWindow(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 addListBoxItem(HWND hDlg, LPTSTR lpStr, HBITMAP hBmp)
{
LRESULT nItem;
nItem = SendMessage(hDlg, LB_ADDSTRING, 0, (LPARAM)lpStr);
SendMessage(hDlg, LB_SETITEMDATA, nItem, (LPARAM)hBmp);
}
static void addListBoxString(HWND hListBox, LPTSTR lpStr)
{
static int nItems = 0;
if (!g_bDlgServiceOn) {
return;
}
++nItems;
if (nItems > MAX_LOADSTRING)
{
SendMessage(hListBox, LB_RESETCONTENT, 0, 0);
nItems = 1;
}
ListBox_SetCurSel(hListBox,
ListBox_AddString(hListBox, lpStr));
}
#ifndef UNICODE
#define addListBoxStringA addListBoxString
#else
static void addListBoxStringA(HWND hListBox, LPSTR lpStr)
{
static int nItems = 0;
TCHAR WStr[16384];
if (!g_bDlgServiceOn) {
return;
}
if (!MultiByteToWideChar(CP_ACP, 0, lpStr, (int)strlen(lpStr) + 1,
WStr, (int) (sizeof(WStr) / sizeof(TCHAR))))
return;
++nItems;
if (nItems > MAX_LOADSTRING)
{
SendMessage(hListBox, LB_RESETCONTENT, 0, 0);
nItems = 1;
}
ListBox_SetCurSel(hListBox,
ListBox_AddString(hListBox, WStr));
}
#endif
static DWORD WINAPI ConsoleOutputThread(LPVOID lpThreadParameter)
{
static BYTE lpBuffer[MAX_PATH+1];
int nPtr = 0;
BYTE ch;
DWORD dwReaded;
while (ReadFile(g_hpipeOutRead, &ch, 1, &dwReaded, NULL) == TRUE)
{
if (dwReaded > 0)
{
if (ch == '\n' || nPtr >= MAX_PATH)
{
lpBuffer[nPtr] = '\0';
addListBoxStringA(g_hwndStdoutList, lpBuffer);
nPtr = 0;
}
else if (ch == '\t' && nPtr < (MAX_PATH - 4))
{
int i;
for (i = 0; i < 4; ++i) {
lpBuffer[nPtr++] = ' ';
}
}
else if (ch != '\r') {
lpBuffer[nPtr++] = ch;
}
}
}
CloseHandle(g_hpipeInWrite);
CloseHandle(g_hpipeOutRead);
CloseHandle(g_hpipeStdError);
return 0;
}
DWORD WINAPI ConsoleWaitingThread(LPVOID lpThreadParameter)
{
WaitForSingleObject(g_lpRedirectProc.hThread, INFINITE);
CloseHandle(g_lpRedirectProc.hThread);
MessageBeep(100);
g_bConsoleRun = FALSE;
SetCursor(g_hCursorArrow);
return 0;
}
BOOL RunRedirectedConsole(LPTSTR szCmdLine)
{
DWORD dwThreadId;
HANDLE hProc;
STARTUPINFO stInfo;
BOOL bResult;
memset(&stInfo, 0, 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)) {
ErrorMessage(NULL, TRUE);
}
if (!CreatePipe(&g_hpipeOutRead, &g_hpipeOutWrite, NULL, MAX_PATH*8)) {
ErrorMessage(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) {
ErrorMessage(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, ConsoleOutputThread,
0, 0, &dwThreadId));
ResumeThread(g_lpRedirectProc.hThread);
CloseHandle(CreateThread(NULL, 0, ConsoleWaitingThread,
0, 0, &dwThreadId));
return TRUE;
}
BOOL RunAndForgetConsole(LPTSTR szCmdLine, BOOL bRedirectConsole)
{
STARTUPINFO stInfo;
PROCESS_INFORMATION prInfo;
BOOL bResult;
if (bRedirectConsole) {
return RunRedirectedConsole(szCmdLine);
}
memset(&stInfo, 0, 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_dwOSVersion == OS_VERSION_WIN9X) {
/* give some time to rescan the status */
Sleep(2000);
}
CloseHandle(prInfo.hThread);
CloseHandle(prInfo.hProcess);
return TRUE;
}
BOOL ApacheManageService(LPCTSTR szServiceName, LPCTSTR szImagePath,
LPTSTR szComputerName, DWORD dwCommand)
{
TCHAR szBuf[MAX_PATH];
TCHAR szMsg[MAX_PATH];
LPTSTR sPos;
BOOL retValue;
BOOL serviceFlag = TRUE;
SC_HANDLE schService;
SC_HANDLE schSCManager;
SERVICE_STATUS schSStatus;
int ticks;
if (g_dwOSVersion == OS_VERSION_WIN9X)
{
sPos = _tcsstr(szImagePath, _T("-k start"));
if (sPos)
{
_tcsncpy(szBuf, szImagePath, (int)(sPos - szImagePath));
switch (dwCommand)
{
case SERVICE_CONTROL_STOP:
_tcscat(szBuf, _T(" -k shutdown -n "));
break;
case SERVICE_CONTROL_CONTINUE:
_sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR),
g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST],
szServiceName);
addListBoxString(g_hwndStdoutList, szMsg);
_tcscat(szBuf, _T(" -k start -n "));
serviceFlag = FALSE;
break;
case SERVICE_APACHE_RESTART:
_tcscat(szBuf, _T(" -k restart -n "));
break;
default:
return FALSE;
}
_tcscat(szBuf, szServiceName);
}
else {
return FALSE;
}
g_bConsoleRun = TRUE;
SetCursor(g_hCursorHourglass);
if (!RunAndForgetConsole(szBuf, serviceFlag))
{
ErrorMessage(NULL, FALSE);
g_bConsoleRun = FALSE;
SetCursor(g_hCursorArrow);
return FALSE;
}
else if (!serviceFlag)
{
_sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR),
g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST],
szServiceName);
addListBoxString(g_hwndStdoutList, szMsg);
g_bConsoleRun = FALSE;
SetCursor(g_hCursorArrow);
return TRUE;
}
}
else
{
schSCManager = OpenSCManager(szComputerName, NULL,
SC_MANAGER_CONNECT);
if (!schSCManager) {
ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST],
FALSE);
return FALSE;
}
schService = OpenService(schSCManager, szServiceName,
SERVICE_QUERY_STATUS | SERVICE_START |
SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL);
if (schService == NULL)
{
/* Avoid recursion of ImagePath NULL (from this Respawn) */
if (szImagePath) {
am_RespawnAsUserAdmin(g_hwndMain, dwCommand,
szServiceName, szComputerName);
}
else {
ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST],
FALSE);
}
CloseServiceHandle(schSCManager);
return FALSE;
}
else
{
retValue = FALSE;
g_bConsoleRun = TRUE;
SetCursor(g_hCursorHourglass);
switch (dwCommand)
{
case SERVICE_CONTROL_STOP:
_sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR),
g_lpMsg[IDS_MSG_SRVSTOP - IDS_MSG_FIRST],
szServiceName);
addListBoxString(g_hwndStdoutList, szMsg);
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)
{
retValue = TRUE;
_sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR),
g_lpMsg[IDS_MSG_SRVSTOPPED - IDS_MSG_FIRST],
szServiceName);
addListBoxString(g_hwndStdoutList, szMsg);
}
}
break;
case SERVICE_CONTROL_CONTINUE:
_sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR),
g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST],
szServiceName);
addListBoxString(g_hwndStdoutList, szMsg);
if (StartService(schService, 0, NULL))
{
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)
{
retValue = TRUE;
_sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR),
g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST],
szServiceName);
addListBoxString(g_hwndStdoutList, szMsg);
}
}
break;
case SERVICE_APACHE_RESTART:
_sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR),
g_lpMsg[IDS_MSG_SRVRESTART - IDS_MSG_FIRST],
szServiceName);
addListBoxString(g_hwndStdoutList, szMsg);
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_hCursorArrow);
return FALSE;
}
if (!--ticks) {
break;
}
}
}
if (schSStatus.dwCurrentState == SERVICE_RUNNING)
{
retValue = TRUE;
_sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR),
g_lpMsg[IDS_MSG_SRVRESTARTED - IDS_MSG_FIRST],
szServiceName);
addListBoxString(g_hwndStdoutList, szMsg);
}
break;
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
if (!retValue) {
ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST],
FALSE);
}
g_bConsoleRun = FALSE;
SetCursor(g_hCursorArrow);
return retValue;
}
return FALSE;
}
return FALSE;
}
BOOL IsServiceRunning(LPCTSTR szServiceName, LPCTSTR szComputerName,
LPDWORD lpdwPid)
{
DWORD dwPid;
HWND hWnd;
SC_HANDLE schService;
SC_HANDLE schSCManager;
SERVICE_STATUS schSStatus;
if (g_dwOSVersion == OS_VERSION_WIN9X)
{
hWnd = FindWindow(_T("ApacheWin95ServiceMonitor"), szServiceName);
if (hWnd && GetWindowThreadProcessId(hWnd, &dwPid))
{
*lpdwPid = 1;
return TRUE;
}
else {
return FALSE;
}
}
else
{
dwPid = 0;
schSCManager = OpenSCManager(szComputerName, NULL,
SC_MANAGER_CONNECT);
if (!schSCManager) {
return FALSE;
}
schService = OpenService(schSCManager, szServiceName,
SERVICE_QUERY_STATUS);
if (schService != NULL)
{
if (QueryServiceStatus(schService, &schSStatus))
{
dwPid = schSStatus.dwCurrentState;
if (lpdwPid) {
*lpdwPid = 1;
}
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return dwPid == SERVICE_RUNNING ? TRUE : FALSE;
}
else {
g_bRescanServices = TRUE;
}
CloseServiceHandle(schSCManager);
return FALSE;
}
return FALSE;
}
BOOL FindRunningServices(void)
{
int i = 0;
DWORD dwPid;
BOOL rv = FALSE;
while (g_stServices[i].szServiceName != NULL)
{
if (!IsServiceRunning(g_stServices[i].szServiceName,
g_stServices[i].szComputerName, &dwPid)) {
dwPid = 0;
}
if (g_stServices[i].dwPid != dwPid) {
rv = TRUE;
}
g_stServices[i].dwPid = dwPid;
++i;
}
return rv;
}
BOOL GetApacheServicesStatus()
{
TCHAR szKey[MAX_PATH];
TCHAR achKey[MAX_PATH];
TCHAR szImagePath[MAX_PATH];
TCHAR szBuf[MAX_PATH];
TCHAR szTmp[MAX_PATH];
HKEY hKey, hSubKey, hKeyRemote;
DWORD retCode, rv, dwKeyType;
DWORD dwBufLen = MAX_PATH;
int i, stPos = 0;
int computers = 0;
g_bRescanServices = FALSE;
am_ClearServicesSt();
while (g_stComputers[computers].szComputerName != NULL) {
hKeyRemote = g_stComputers[computers].hRegistry;
retCode = RegOpenKeyEx(hKeyRemote,
_T("System\\CurrentControlSet\\Services\\"),
0, KEY_READ, &hKey);
if (retCode != ERROR_SUCCESS)
{
ErrorMessage(NULL, FALSE);
return FALSE;
}
for (i = 0, retCode = ERROR_SUCCESS; retCode == ERROR_SUCCESS; i++)
{
retCode = RegEnumKey(hKey, i, achKey, MAX_PATH);
if (retCode == ERROR_SUCCESS)
{
_tcscpy(szKey, _T("System\\CurrentControlSet\\Services\\"));
_tcscat(szKey, achKey);
if (RegOpenKeyEx(hKeyRemote, szKey, 0,
KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS)
{
dwBufLen = MAX_PATH;
rv = RegQueryValueEx(hSubKey, _T("ImagePath"), NULL,
&dwKeyType, (LPBYTE)szImagePath, &dwBufLen);
if (rv == ERROR_SUCCESS
&& (dwKeyType == REG_SZ
|| dwKeyType == REG_EXPAND_SZ)
&& dwBufLen)
{
_tcscpy(szBuf, szImagePath);
CharLower(szBuf);
/* the service name could be httpd*.exe or Apache*.exe */
if (((_tcsstr(szBuf, _T("\\apache")) != NULL)
|| (_tcsstr(szBuf, _T("\\httpd")) != NULL))
&& _tcsstr(szBuf, _T(".exe"))
&& (_tcsstr(szBuf, _T("--ntservice")) != NULL
|| _tcsstr(szBuf, _T("-k ")) != NULL))
{
g_stServices[stPos].szServiceName = _tcsdup(achKey);
g_stServices[stPos].szImagePath = _tcsdup(szImagePath);
g_stServices[stPos].szComputerName =
_tcsdup(g_stComputers[computers].szComputerName);
dwBufLen = MAX_PATH;
if (RegQueryValueEx(hSubKey, _T("Description"), NULL,
&dwKeyType, (LPBYTE)szBuf, &dwBufLen)
== ERROR_SUCCESS) {
g_stServices[stPos].szDescription = _tcsdup(szBuf);
}
dwBufLen = MAX_PATH;
if (RegQueryValueEx(hSubKey, _T("DisplayName"), NULL,
&dwKeyType, (LPBYTE)szBuf, &dwBufLen)
== ERROR_SUCCESS)
{
if (_tcscmp(g_stComputers[computers]
.szComputerName, g_szLocalHost) != 0)
{
_tcscpy(szTmp, g_stComputers[computers]
.szComputerName + 2);
_tcscat(szTmp, _T("@"));
_tcscat(szTmp, szBuf);
}
else {
_tcscpy(szTmp, szBuf);
}
g_stServices[stPos].szDisplayName = _tcsdup(szTmp);
}
++stPos;
if (stPos >= MAX_APACHE_SERVICES) {
retCode = !ERROR_SUCCESS;
}
}
}
RegCloseKey(hSubKey);
}
}
}
++computers;
RegCloseKey(hKey);
}
FindRunningServices();
return TRUE;
}
LRESULT CALLBACK ConnectDlgProc(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
TCHAR szCmp[MAX_COMPUTERNAME_LENGTH+4];
switch (message)
{
case WM_INITDIALOG:
ShowWindow(hDlg, SW_HIDE);
g_hwndConnectDlg = hDlg;
CenterWindow(hDlg);
ShowWindow(hDlg, SW_SHOW);
SetFocus(GetDlgItem(hDlg, IDC_COMPUTER));
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
memset(szCmp, 0, sizeof(szCmp));
_tcscpy(szCmp, _T("\\\\"));
SendMessage(GetDlgItem(hDlg, IDC_COMPUTER), WM_GETTEXT,
(WPARAM) MAX_COMPUTERNAME_LENGTH,
(LPARAM) szCmp+2);
_tcsupr(szCmp);
if (_tcslen(szCmp) < 3) {
EndDialog(hDlg, TRUE);
return TRUE;
}
am_ConnectComputer(szCmp);
SendMessage(g_hwndMain, 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 = _T("ApacheMonitor :\nSelect Network Computer!");
bi.pszDisplayName = szCmp;
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) szCmp);
}
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 ServiceDlgProc(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
TCHAR szBuf[MAX_PATH];
HWND hListBox;
static HWND hStatusBar;
TEXTMETRIC tm;
int i, y;
HDC hdcMem;
RECT rcBitmap;
LRESULT nItem;
LPMEASUREITEMSTRUCT lpmis;
LPDRAWITEMSTRUCT lpdis;
memset(szBuf, 0, sizeof(szBuf));
switch (message)
{
case WM_INITDIALOG:
ShowWindow(hDlg, SW_HIDE);
g_hwndServiceDlg = hDlg;
SetWindowText(hDlg, g_szTitle);
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_lpMsg[IDS_MSG_SSTART - IDS_MSG_FIRST]);
SetWindowText(GetDlgItem(hDlg, IDC_SSTOP),
g_lpMsg[IDS_MSG_SSTOP - IDS_MSG_FIRST]);
SetWindowText(GetDlgItem(hDlg, IDC_SRESTART),
g_lpMsg[IDS_MSG_SRESTART - IDS_MSG_FIRST]);
SetWindowText(GetDlgItem(hDlg, IDC_SMANAGER),
g_lpMsg[IDS_MSG_SERVICES - IDS_MSG_FIRST]);
SetWindowText(GetDlgItem(hDlg, IDC_SCONNECT),
g_lpMsg[IDS_MSG_CONNECT - IDS_MSG_FIRST]);
SetWindowText(GetDlgItem(hDlg, IDC_SEXIT),
g_lpMsg[IDS_MSG_MNUEXIT - IDS_MSG_FIRST]);
if (g_dwOSVersion < 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,
_T(""), hDlg, IDC_STATBAR);
if (GetApacheServicesStatus())
{
i = 0;
while (g_stServices[i].szServiceName != NULL)
{
addListBoxItem(hListBox, g_stServices[i].szDisplayName,
g_stServices[i].dwPid == 0 ? g_hBmpStop
: g_hBmpStart);
++i;
}
}
CenterWindow(hDlg);
ShowWindow(hDlg, SW_SHOW);
SetFocus(hListBox);
SendMessage(hListBox, LB_SETCURSEL, 0, 0);
return TRUE;
break;
case WM_MANAGEMESSAGE:
ApacheManageService(g_stServices[LOWORD(wParam)].szServiceName,
g_stServices[LOWORD(wParam)].szImagePath,
g_stServices[LOWORD(wParam)].szComputerName,
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)_T(""));
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);
i = 0;
while (g_stServices[i].szServiceName != NULL)
{
addListBoxItem(hListBox, g_stServices[i].szDisplayName,
g_stServices[i].dwPid == 0 ? g_hBmpStop : g_hBmpStart);
++i;
}
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_hCursorHourglass);
}
else {
SetCursor(g_hCursorArrow);
}
return TRUE;
case WM_DRAWITEM:
lpdis = (LPDRAWITEMSTRUCT) lParam;
if (lpdis->itemID == -1) {
break;
}
switch (lpdis->itemAction)
{
case ODA_SELECT:
case ODA_DRAWENTIRE:
g_hBmpPicture = (HBITMAP)SendMessage(lpdis->hwndItem,
LB_GETITEMDATA,
lpdis->itemID, (LPARAM) 0);
hdcMem = CreateCompatibleDC(lpdis->hDC);
g_hBmpOld = SelectObject(hdcMem, g_hBmpPicture);
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) szBuf);
GetTextMetrics(lpdis->hDC, &tm);
y = (lpdis->rcItem.bottom + lpdis->rcItem.top - tm.tmHeight) / 2;
SelectObject(hdcMem, g_hBmpOld);
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_hBmpPicture == g_hBmpStop)
{
Button_Enable(GetDlgItem(hDlg, IDC_SSTART), TRUE);
Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE);
Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE);
}
else if (g_hBmpPicture == g_hBmpStart)
{
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 (_tcscmp(g_stServices[lpdis->itemID].szComputerName,
g_szLocalHost) == 0) {
Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), FALSE);
}
else {
Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), TRUE);
}
if (g_stServices[lpdis->itemID].szDescription) {
SendMessage(hStatusBar, SB_SETTEXT, 0,
(LPARAM)g_stServices[lpdis->itemID].szDescription);
}
else {
SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)_T(""));
}
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, szBuf, (int)_tcslen(szBuf));
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 */
hListBox = GetDlgItem(hDlg, IDL_SERVICES);
nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
if (nItem != LB_ERR)
{
g_hBmpPicture = (HBITMAP)SendMessage(hListBox,
LB_GETITEMDATA,
nItem, (LPARAM) 0);
if (g_hBmpPicture == g_hBmpStop) {
SendMessage(hDlg, WM_MANAGEMESSAGE, nItem,
SERVICE_CONTROL_CONTINUE);
}
else {
SendMessage(hDlg, WM_MANAGEMESSAGE, nItem,
SERVICE_CONTROL_STOP);
}
}
return TRUE;
}
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_dwOSVersion >= OS_VERSION_WIN2K) {
ShellExecute(hDlg, _T("open"), _T("services.msc"), _T("/s"),
NULL, SW_NORMAL);
}
else {
WinExec("Control.exe SrvMgr.cpl Services", SW_NORMAL);
}
return TRUE;
case IDC_SEXIT:
EndDialog(hDlg, TRUE);
SendMessage(g_hwndMain, WM_COMMAND, (WPARAM)IDM_EXIT, 0);
return TRUE;
case IDC_SCONNECT:
DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DLGCONNECT),
hDlg, (DLGPROC)ConnectDlgProc);
return TRUE;
case IDC_SDISCONN:
hListBox = GetDlgItem(hDlg, IDL_SERVICES);
nItem = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
if (nItem != LB_ERR) {
am_DisconnectComputer(g_stServices[nItem].szComputerName);
SendMessage(g_hwndMain, 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)
{
if (message == g_bUiTaskbarCreated)
{
/* restore the tray icon on shell restart */
ShowNotifyIcon(hWnd, NIM_ADD);
return DefWindowProc(hWnd, message, wParam, lParam);
}
switch (message)
{
case WM_CREATE:
GetApacheServicesStatus();
ShowNotifyIcon(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 nPrev = 0, nNew = 0;
EnterCriticalSection(&g_stcSection);
if (FindRunningServices() || g_bRescanServices)
{
ShowNotifyIcon(hWnd, NIM_MODIFY);
if (g_hwndServiceDlg)
PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
}
/* check if services list changed */
while (g_stServices[nPrev].szServiceName != NULL)
++nPrev;
GetApacheServicesStatus();
while (g_stServices[nNew].szServiceName != NULL)
++nNew;
if (nPrev != nNew)
{
ShowNotifyIcon(hWnd, NIM_MODIFY);
if (g_hwndServiceDlg) {
PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
}
}
LeaveCriticalSection(&g_stcSection);
break;
}
case WM_TIMER_REFRESH:
{
int nPrev = 0, nNew = 0;
EnterCriticalSection(&g_stcSection);
if (g_bRescanServices)
{
GetApacheServicesStatus();
ShowNotifyIcon(hWnd, NIM_MODIFY);
if (g_hwndServiceDlg) {
PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
}
}
else if (FindRunningServices())
{
ShowNotifyIcon(hWnd, NIM_MODIFY);
if (g_hwndServiceDlg) {
PostMessage(g_hwndServiceDlg, WM_UPDATEMESSAGE, 0, 0);
}
}
LeaveCriticalSection(&g_stcSection);
break;
}
}
break;
case WM_QUIT:
ShowNotifyIcon(hWnd, NIM_DELETE);
break;
case WM_TRAYMESSAGE:
switch (lParam)
{
case WM_LBUTTONDBLCLK:
if (!g_bDlgServiceOn)
{
g_bDlgServiceOn = TRUE;
DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DLGSERVICES),
hWnd, (DLGPROC)ServiceDlgProc);
g_bDlgServiceOn = FALSE;
g_hwndServiceDlg = NULL;
}
else if (IsWindow(g_hwndServiceDlg))
{
/* Dirty hack to bring the window to the foreground */
SetWindowPos(g_hwndServiceDlg, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
SetWindowPos(g_hwndServiceDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
SetFocus(g_hwndServiceDlg);
}
break;
case WM_LBUTTONUP:
ShowTryServicesMenu(hWnd);
break;
case WM_RBUTTONUP:
ShowTryPopupMenu(hWnd);
break;
}
break;
case WM_COMMAND:
if ((LOWORD(wParam) & IDM_SM_START) == IDM_SM_START)
{
ApacheManageService(g_stServices[LOWORD(wParam)
- IDM_SM_START].szServiceName,
g_stServices[LOWORD(wParam)
- IDM_SM_START].szImagePath,
g_stServices[LOWORD(wParam)
- IDM_SM_START].szComputerName,
SERVICE_CONTROL_CONTINUE);
return TRUE;
}
else if ((LOWORD(wParam) & IDM_SM_STOP) == IDM_SM_STOP)
{
ApacheManageService(g_stServices[LOWORD(wParam)
- IDM_SM_STOP].szServiceName,
g_stServices[LOWORD(wParam)
- IDM_SM_STOP].szImagePath,
g_stServices[LOWORD(wParam)
- IDM_SM_STOP].szComputerName,
SERVICE_CONTROL_STOP);
return TRUE;
}
else if ((LOWORD(wParam) & IDM_SM_RESTART) == IDM_SM_RESTART)
{
ApacheManageService(g_stServices[LOWORD(wParam)
- IDM_SM_RESTART].szServiceName,
g_stServices[LOWORD(wParam)
- IDM_SM_RESTART].szImagePath,
g_stServices[LOWORD(wParam)
- IDM_SM_RESTART].szComputerName,
SERVICE_APACHE_RESTART);
return TRUE;
}
switch (LOWORD(wParam))
{
case IDM_RESTORE:
if (!g_bDlgServiceOn)
{
g_bDlgServiceOn = TRUE;
DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DLGSERVICES),
hWnd, (DLGPROC)ServiceDlgProc);
g_bDlgServiceOn = FALSE;
g_hwndServiceDlg = NULL;
}
else if (IsWindow(g_hwndServiceDlg)) {
SetFocus(g_hwndServiceDlg);
}
break;
case IDC_SMANAGER:
if (g_dwOSVersion >= OS_VERSION_WIN2K) {
ShellExecute(NULL, _T("open"), _T("services.msc"), _T("/s"),
NULL, SW_NORMAL);
}
else {
WinExec("Control.exe SrvMgr.cpl Services", SW_NORMAL);
}
return TRUE;
case IDM_EXIT:
ShowNotifyIcon(hWnd, NIM_DELETE);
PostQuitMessage(0);
return TRUE;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return FALSE;
}
static int KillAWindow(HWND appwindow)
{
HANDLE appproc;
DWORD procid;
BOOL postres;
SetLastError(0);
GetWindowThreadProcessId(appwindow, &procid);
if (GetLastError())
return(2);
appproc = OpenProcess(SYNCHRONIZE, 0, procid);
postres = PostMessage(appwindow, WM_COMMAND, IDM_EXIT, 0);
if (appproc && postres) {
if (WaitForSingleObject(appproc, 10 /* seconds */ * 1000)
== WAIT_OBJECT_0) {
CloseHandle(appproc);
return (0);
}
}
if (appproc)
CloseHandle(appproc);
if ((appproc = OpenProcess(PROCESS_TERMINATE, 0, procid)) != NULL) {
if (TerminateProcess(appproc, 0)) {
CloseHandle(appproc);
return (0);
}
CloseHandle(appproc);
}
/* Perhaps we were short of permissions? */
return (2);
}
static int KillAllMonitors(void)
{
HWND appwindow;
int exitcode = 0;
PWTS_PROCESS_INFO tsProcs;
DWORD tsProcCount, i;
DWORD thisProcId;
/* This is graceful, close our own Window, clearing the icon */
if ((appwindow = FindWindow(g_szWindowClass, g_szTitle)) != NULL)
exitcode = KillAWindow(appwindow);
if (g_dwOSVersion < OS_VERSION_WIN2K)
return exitcode;
thisProcId = GetCurrentProcessId();
if (!WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1,
&tsProcs, &tsProcCount))
return exitcode;
/* This is ungraceful; close other Windows, with a lingering icon.
* Since on terminal server it's not possible to post the message
* to exit across sessions, we have to suffer this side effect
* of a taskbar 'icon' which will evaporate the next time that
* the user hovers over it or when the taskbar area is updated.
*/
for (i = 0; i < tsProcCount; ++i) {
if (_tcscmp(tsProcs[i].pProcessName, _T(AM_STRINGIFY(BIN_NAME))) == 0
&& tsProcs[i].ProcessId != thisProcId)
WTSTerminateProcess(WTS_CURRENT_SERVER_HANDLE,
tsProcs[i].ProcessId, 1);
}
WTSFreeMemory(tsProcs);
return exitcode;
}
/* Create main invisible window */
HWND CreateMainWindow(HINSTANCE hInstance)
{
HWND hWnd = NULL;
WNDCLASSEX wcex;
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_hCursorArrow;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = 0;
wcex.lpszClassName = g_szWindowClass;
wcex.hIconSm = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_APSRVMON),
IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
if (RegisterClassEx(&wcex)) {
hWnd = CreateWindow(g_szWindowClass, g_szTitle,
0, 0, 0, 0, 0,
NULL, NULL, hInstance, NULL);
}
return hWnd;
}
#ifndef UNICODE
/* Borrowed from CRT internal.h for _MBCS argc/argv parsing in this GUI app */
int __CRTDECL _setargv(void);
#endif
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
TCHAR szTmp[MAX_LOADSTRING];
TCHAR szCmp[MAX_COMPUTERNAME_LENGTH+4];
MSG msg;
/* existing window */
HWND appwindow;
DWORD dwControl;
int i;
DWORD d;
if (!GetSystemOSVersion(&g_dwOSVersion))
{
ErrorMessage(NULL, TRUE);
return 1;
}
g_LangID = GetUserDefaultLangID();
if ((g_LangID & 0xFF) != LANG_ENGLISH) {
g_LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
}
for (i = IDS_MSG_FIRST; i <= IDS_MSG_LAST; ++i) {
LoadString(hInstance, i, szTmp, MAX_LOADSTRING);
g_lpMsg[i - IDS_MSG_FIRST] = _tcsdup(szTmp);
}
LoadString(hInstance, IDS_APMONITORTITLE, szTmp, MAX_LOADSTRING);
d = MAX_COMPUTERNAME_LENGTH+1;
_tcscpy(szCmp, _T("\\\\"));
GetComputerName(szCmp + 2, &d);
_tcsupr(szCmp);
g_szLocalHost = _tcsdup(szCmp);
memset(g_stComputers, 0, sizeof(ST_MONITORED_COMP) * MAX_APACHE_COMPUTERS);
g_stComputers[0].szComputerName = _tcsdup(szCmp);
g_stComputers[0].hRegistry = HKEY_LOCAL_MACHINE;
g_szTitle = _tcsdup(szTmp);
LoadString(hInstance, IDS_APMONITORCLASS, szTmp, MAX_LOADSTRING);
g_szWindowClass = _tcsdup(szTmp);
appwindow = FindWindow(g_szWindowClass, g_szTitle);
#ifdef UNICODE
__wargv = CommandLineToArgvW(GetCommandLineW(), &__argc);
#else
_setargv();
#endif
if ((__argc == 2) && (_tcscmp(__targv[1], _T("--kill")) == 0))
{
/* Off to chase and close up every ApacheMonitor taskbar window */
return KillAllMonitors();
}
else if ((__argc == 4) && (g_dwOSVersion >= OS_VERSION_WIN2K))
{
dwControl = _tstoi(__targv[1]));
if ((dwControl != SERVICE_CONTROL_CONTINUE) &&
(dwControl != SERVICE_APACHE_RESTART) &&
(dwControl != SERVICE_CONTROL_STOP))
{
return 1;
}
/* Chase down and close up our session's previous window */
if ((appwindow) != NULL)
KillAWindow(appwindow);
}
else if (__argc != 1) {
return 1;
}
else if (appwindow)
{
ErrorMessage(g_lpMsg[IDS_MSG_APPRUNNING - IDS_MSG_FIRST], FALSE);
return 0;
}
g_icoStop = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICOSTOP),
IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
g_icoRun = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICORUN),
IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
g_hCursorHourglass = LoadImage(NULL, MAKEINTRESOURCE(OCR_WAIT),
IMAGE_CURSOR, LR_DEFAULTSIZE,
LR_DEFAULTSIZE, LR_SHARED);
g_hCursorArrow = LoadImage(NULL, MAKEINTRESOURCE(OCR_NORMAL),
IMAGE_CURSOR, LR_DEFAULTSIZE,
LR_DEFAULTSIZE, LR_SHARED);
g_hBmpStart = LoadImage(hInstance, MAKEINTRESOURCE(IDB_BMPRUN),
IMAGE_BITMAP, XBITMAP, YBITMAP,
LR_DEFAULTCOLOR);
g_hBmpStop = LoadImage(hInstance, MAKEINTRESOURCE(IDB_BMPSTOP),
IMAGE_BITMAP, XBITMAP, YBITMAP,
LR_DEFAULTCOLOR);
memset(g_stServices, 0, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES);
CoInitialize(NULL);
InitCommonControls();
g_hInstance = hInstance;
g_hwndMain = CreateMainWindow(hInstance);
g_bUiTaskbarCreated = RegisterWindowMessage(_T("TaskbarCreated"));
InitializeCriticalSection(&g_stcSection);
g_hwndServiceDlg = NULL;
if (g_hwndMain != NULL)
{
/* To avoid recursion, pass ImagePath NULL (a noop on NT and later) */
if ((__argc == 4) && (g_dwOSVersion >= OS_VERSION_WIN2K))
ApacheManageService(__targv[2], NULL, __targv[3], dwControl);
while (GetMessage(&msg, NULL, 0, 0) == TRUE)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
am_ClearServicesSt();
}
am_ClearComputersSt();
DeleteCriticalSection(&g_stcSection);
DestroyIcon(g_icoStop);
DestroyIcon(g_icoRun);
DestroyCursor(g_hCursorHourglass);
DestroyCursor(g_hCursorArrow);
DeleteObject(g_hBmpStart);
DeleteObject(g_hBmpStop);
CoUninitialize();
return 0;
}