This patch makes the ApacheMonitor to use APR.

It uses hash tables to maintain the list of available services and connected
computers

Since the patch is much larger then original I've enclosed the new
ApacheMonitor.c instead.

MT.

Attachment: ApacheMonitor.rc.patch
Description: Binary data

Attachment: Apache.dsw.patch
Description: Binary data

/* ====================================================================
 * 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 [EMAIL PROTECTED]
 *
 * 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
 * <http://www.apache.org/>.
 *
 * 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 <[EMAIL PROTECTED]>
 *
 * 05 Aug 2001
 * ==================================================================== 
 */


#define _WIN32_WINNT 0x0400
#ifndef STRICT
#define STRICT
#endif
#ifndef OEMRESOURCE
#define OEMRESOURCE
#endif

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <objbase.h>
#include <shlobj.h>
#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;

}

Attachment: ApacheMonitor.dsp.patch
Description: Binary data

Reply via email to