Hi all,

I've been working on that for some time, and here is some background info on
the subject.

1. To install the Apache you need to execute the apache with something like
"apache.exe -k install -n ApacheRulesTheWeb". Well, running that from some
installation program would popup the console window, just to launch the
apache to install himself.
2. Running apache in the non-service mode also creates the console window.

Well, here is the program that resolves some things about console
applications under WIN32 platform.
The application itself can act depending on command line arguments, and
basically has tree modes:
1. without GUI at all
2. try icon
3. console window dialog (with or without try notification).

So one can for example launch the apache with something like "conwrap -g -t
apache.exe".
The conwrap will launch the apache and put the icon in the try. Right mouse
click on that icon will present the menu option to quit the service, and if
clicked the conwrap will send the apXXXX_shutdown message to the apache, but
only if the command line param was apache.exe.

Other use of conwrap would be typing something like:
conwrap -g -c -s cmd.exe, the conwrap will spawn the command shell and
redirect it through its gui.

The conwrap constantly monitors the status of the child process and exits
when the child exits.
It also has the safe terminate process capability calling CreateRemoteThread
(if running WINNT) to quit the child process.

When called with '-q miliseconds' it will exit after the specified time
frame elapses.

The code itself is less the 30K.

MT.

/* ====================================================================
 * 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.
 */

/* ====================================================================
 * Apache Console wrapper.
 *
 * Contributed by Mladen Turk <[EMAIL PROTECTED]>
 *
 * 13 Jan 2002
 * ==================================================================== 
 */

#define _WIN32_WINNT 0x0400
#ifndef STRICT
#define STRICT
#endif
#ifndef OEMRESOURCE
#define OEMRESOURCE
#endif
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <stdlib.h>
#include <stdio.h>
#include "conwrap.h"

#include "apr.h"
#include "apr_strings.h"
#include "apr_general.h"
#include "apr_pools.h"
#include "apr_getopt.h"
#include "apr_tables.h"
#include "apr_errno.h"

#define WM_TRAYMESSAGE         (WM_APP+1)
#define MAX_LOADSTRING         200
#define WM_TIMER_REFRESH       10
#define REFRESH_TIME           1000           /* chech if running */

#define CONWRAP_SUCCESS        0
#define CONWRAP_ENOARGS        1
#define CONWRAP_EARG           2
#define CONWRAP_EFATAL         3
#define CONWRAP_TIMEOUT        3

#define MAX_SIGNAL_NAME 30
char ac_signal_restart[MAX_SIGNAL_NAME]; 
char ac_signal_shutdown[MAX_SIGNAL_NAME];

apr_pool_t      *ac_pool;
apr_getopt_t    *ac_options;

LANGID          ac_lang_id;
char            *ac_cmdline;
char            *ac_shmem_name;
char            ac_wclass_name[30];
char            ac_wtitle_name[MAX_LOADSTRING] = {0};

HICON           ac_main_icon;
HICON           ac_main_licon;
UINT            ac_taskbar_created;
HWND            ac_main_hwnd;
HWND            ac_list_hwnd;
HWND            ac_edit_hwnd;
HWND            ac_disp_hwnd;
HINSTANCE       ac_instance;
apr_table_t     *ac_stdout_lines;

/* are we running apache? */
int             ac_is_httpd = 0;
/* show icon in the system try */
int             ac_use_try = 0;
/* eneble console stdout/stderr dialog */
int             ac_use_dlg = 0;
/* show the console dialog on startup */
int             ac_use_show = 0;
/* do we have a GUI at all */
int             ac_use_gui = 0;
/* show error message boxes */
int             ac_use_err = 0;
/* client run time */
int             ac_use_rtime = 0;
int             ac_run_time = 0;


PROCESS_INFORMATION ac_child;

/* redirection pipes */

typedef struct ac_stdout_t ac_stdout_t;

struct ac_stdout_t {
    HANDLE  rd;
    HANDLE  wr;
};

ac_stdout_t  ac_handles;

static void ac_error_msgbox(const char *msg, BOOL fatal)
{
    void *buf  = NULL;
    
    if (!ac_use_gui || !ac_use_err)
        return;

    if (msg)
        MessageBox(NULL, msg, "Error",
                    MB_OK | (fatal ? MB_ICONERROR : MB_ICONEXCLAMATION));
    else {
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            GetLastError(),
            ac_lang_id,
            (char *) &buf, 0, NULL);
        MessageBox(NULL, (const char *)buf, "System Error",
                    MB_OK | (fatal ? MB_ICONERROR : MB_ICONEXCLAMATION));
        LocalFree(buf);
    }
    if (fatal)
        PostQuitMessage(0);
}

typedef HANDLE (__stdcall * PFNCREATERTHRD)(HANDLE, LPSECURITY_ATTRIBUTES, DWORD,
                                            LPTHREAD_START_ROUTINE, LPVOID, DWORD,
                                            LPDWORD);


static apr_status_t ac_inject_child_exit(PROCESS_INFORMATION *child) 
{
    PFNCREATERTHRD pfn_CreateRemoteThread;
    UINT exit_code = 2303;
    HANDLE rt = NULL, dup = NULL;
    DWORD  rtid, stat;
    BOOL isok;

    pfn_CreateRemoteThread = (PFNCREATERTHRD)GetProcAddress(
                                             GetModuleHandle("KERNEL32.DLL"),
                                            "CreateRemoteThread");

    isok = DuplicateHandle(GetCurrentProcess(), 
                           child->hProcess, 
                           GetCurrentProcess(), 
                           &dup, 
                           PROCESS_ALL_ACCESS, 
                           FALSE, 0);
    isok = GetExitCodeProcess((isok) ? dup : child->hProcess, &stat);
    if (pfn_CreateRemoteThread) {        
        FARPROC pfnExitProc;
        if (isok && stat == STILL_ACTIVE) { 
           
            pfnExitProc = GetProcAddress(GetModuleHandle("KERNEL32.DLL"),
                                     "ExitProcess");
            rt = pfn_CreateRemoteThread(child->hProcess, 
                                        NULL, 
                                        0, 
                                        (LPTHREAD_START_ROUTINE)pfnExitProc,
                                        (PVOID)exit_code, 0, &rtid);
       }
    }
    else {
        if (isok && stat == STILL_ACTIVE)
            TerminateProcess(child->hProcess, exit_code);
    }

    if (rt) {
        WaitForSingleObject(child->hProcess, INFINITE);
        CloseHandle(rt);
    }
    if (dup)
        CloseHandle(dup);
    return APR_SUCCESS;
}




static void ac_add_list_string(HWND list, char *str, int len)
{
    static int nitems = 0;
    static int nqueue = 0;
    static int nlen = 0, olen = 0;
    int i, n;
    char skey[32];

    itoa( nitems + nqueue, skey, 10);
    apr_table_add(ac_stdout_lines, skey, str);
    ++nqueue;
    nlen = max(nlen, len);
    if (!list) {
        return;
    }

    for (i = 0; i < nqueue; i++) {
        itoa( nitems + i, skey, 10);
        n = ListBox_AddString(list, apr_table_get(ac_stdout_lines, skey));
    }
    if (olen < nlen) {
        olen = nlen;
        SendMessage(ac_list_hwnd, LB_SETHORIZONTALEXTENT, (WPARAM) 10 * olen, (LPARAM) 
0);
    }
    SendMessage(ac_list_hwnd, LB_SETCARETINDEX, (WPARAM)n, (LPARAM)FALSE);

    nitems += nqueue;
    nqueue = 0;
}

static DWORD WINAPI ac_console_stdout_thread(LPVOID lpThreadParameter)
{
    static unsigned char buff[MAX_LOADSTRING+1];
    int n = 0;
    unsigned char  ch;
    DWORD readed;

    while (ac_handles.rd && (ReadFile(ac_handles.rd, &ch, 1, &readed, NULL) == TRUE))  
{
        if (readed) {
            readed = 0;
            if (ch == '\n' || n >= MAX_LOADSTRING) {
                buff[n] = '\0';
                ac_add_list_string(ac_list_hwnd, buff, n);
                n  = 0;
            } 
            else if (ch == '\t' && n < (MAX_LOADSTRING - 4)) {
                int i;
                for (i = 0; i < 4; ++i)
                    buff[n++] = ' ';
            }
            else if (ch != '\r')
                buff[n++] = ch;
            else if (ch != '\b')
                buff[n++] = ' ';
        }
    }
    if (ac_handles.wr != NULL) {
        CloseHandle(ac_handles.wr);
        ac_handles.wr = NULL;
    }
    if (ac_handles.rd != NULL) {
        CloseHandle(ac_handles.rd);
        ac_handles.rd = NULL;
    }

    return 0;
}

DWORD WINAPI ac_console_wait_thread(LPVOID lpThreadParameter)
{
    WaitForSingleObject(ac_child.hThread, INFINITE);
    CloseHandle(ac_child.hThread);
    ac_child.dwProcessId = 0;
    return 0;
}

static apr_status_t ac_redirect_console(char *cmdline)
{

    DWORD  threadid;
    SECURITY_ATTRIBUTES sa;
    STARTUPINFO si;
    BOOL r;
    HANDLE  stdinp_rd, stdinp_tmp;
    HANDLE  stdout_wr, stdout_tmp;
    HANDLE  stdinp_save, stdout_save;

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;
    
    /* redirect stdout */
    stdout_save = GetStdHandle(STD_OUTPUT_HANDLE);

    if (!CreatePipe(&stdout_tmp, &stdout_wr, &sa, 0)) {
        ac_error_msgbox(NULL, TRUE);
        return APR_EBADF;
    }
    SetStdHandle(STD_OUTPUT_HANDLE, stdout_wr);
    
    if (!DuplicateHandle(GetCurrentProcess(), stdout_tmp,
                         GetCurrentProcess(), &ac_handles.rd, 
                         0, FALSE, DUPLICATE_SAME_ACCESS)) {
        ac_error_msgbox(NULL, TRUE);
        return APR_EBADF;
    }
    CloseHandle(stdout_tmp);

    /* redirect stdin */
    stdinp_save = GetStdHandle(STD_INPUT_HANDLE);

    if (!CreatePipe(&stdinp_rd, &stdinp_tmp, &sa, 0)) {
        ac_error_msgbox(NULL, TRUE);
        return APR_EBADF;
    }
    SetStdHandle(STD_INPUT_HANDLE, stdinp_rd);
    
    if (!DuplicateHandle(GetCurrentProcess(), stdinp_tmp,
                         GetCurrentProcess(), &ac_handles.wr, 
                         0, FALSE, DUPLICATE_SAME_ACCESS)) {
        ac_error_msgbox(NULL, TRUE);
        return APR_EBADF;
    }
    CloseHandle(stdinp_tmp);
    
    
    si.hStdOutput = stdout_wr;
    si.hStdError  = stdout_wr;
    si.hStdInput  = stdinp_rd;
    r = CreateProcess(NULL,
            cmdline,
            NULL,
            NULL,
            TRUE,
            CREATE_SUSPENDED | CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
            NULL,
            NULL ,
            &si,
            &ac_child);
    if (!r) {
        ac_error_msgbox(NULL, TRUE);
        return APR_ENOPROC;
    }

    SetStdHandle(STD_OUTPUT_HANDLE, stdout_save);
    SetStdHandle(STD_INPUT_HANDLE, stdinp_save);
    
    CloseHandle(stdout_wr);
    CloseHandle(stdinp_rd);
    if (ac_is_httpd) {
        sprintf(ac_signal_shutdown, "ap%d_shutdown", ac_child.dwProcessId);
        sprintf(ac_signal_restart, "ap%d_restart", ac_child.dwProcessId);
    }
    CloseHandle(CreateThread(NULL, 0, ac_console_stdout_thread, 0, 0, &threadid));
    ResumeThread(ac_child.hThread);
    CloseHandle(CreateThread(NULL, 0, ac_console_wait_thread, 0, 0, &threadid));

    return APR_SUCCESS;
}

static void ac_kill_httpd()
{
    if (ac_child.dwProcessId) {
        HANDLE e;
        int i = 0;
        e = OpenEvent(EVENT_ALL_ACCESS, FALSE, ac_signal_shutdown);
        if (!e) {
            ac_error_msgbox(NULL, FALSE);
            return;
        }
        if (SetEvent(e) == 0) {
            ac_error_msgbox(NULL, FALSE);
            CloseHandle(e);
            return; 
        }
        CloseHandle(e);
        /* wait 5 seconds that apache can bail out */
        while (ac_child.dwProcessId) {
            Sleep(200);
            ++i;
            if (i > 25)
                break;
        }
        if (ac_child.dwProcessId) {
            ac_error_msgbox("HTTPD process is still active after 5 seconds", FALSE); 
            TerminateProcess(ac_child.hProcess, -1);
        }
        ac_child.dwProcessId = 0;
    }
}

static void ac_kill_child()
{
    if (ac_child.dwProcessId) {
        if (ac_is_httpd) {
            ac_kill_httpd();
            return;
        }
        else {
            int i = 0;
            /* try to bail out closing child stdin */
            if (ac_handles.wr) {
                CloseHandle(ac_handles.wr);
                ac_handles.wr = NULL;
                while ( i < 20) {
                    if (!ac_child.dwProcessId)
                        return;
                    Sleep(100);
                    ++i;
                }
            }
            ac_inject_child_exit(&ac_child);
        }
        ac_child.dwProcessId = 0;
    }
}


static void ac_show_try_icon(HWND hwnd, DWORD message, const char *tip)
{
    
    NOTIFYICONDATA nid;
    if (!ac_use_try)
        return;

    ZeroMemory(&nid,sizeof(nid));
    nid.cbSize = sizeof(NOTIFYICONDATA);
    nid.hWnd = hwnd;
    nid.uID = 0xFF;
    nid.uFlags = NIF_ICON | NIF_MESSAGE;
    if (tip)
        nid.uFlags |= NIF_TIP;

    nid.uCallbackMessage = WM_TRAYMESSAGE;
    
    if (message != NIM_DELETE)
        nid.hIcon = ac_main_icon;
    else
        nid.hIcon = NULL;
    if (tip)
        strcpy(nid.szTip, tip);

    Shell_NotifyIcon(message, &nid);
}

static void ac_append_menu_item(HMENU menu, UINT menu_id, char *name, int isdef, int 
enabled)
{
    MENUITEMINFO mii;
    
    ZeroMemory(&mii, sizeof(MENUITEMINFO));
    mii.cbSize = sizeof(MENUITEMINFO);
    mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
    if (strlen(name)) {
        mii.fType = MFT_STRING;
        mii.wID = menu_id;
        if (isdef)
            mii.fState = MFS_DEFAULT;
        if (!enabled)
            mii.fState |= MFS_DISABLED;
        mii.dwTypeData = name;
    }
    else
        mii.fType = MFT_SEPARATOR;
    InsertMenuItem(menu, menu_id, FALSE, &mii);
}

static void ac_show_try_menu(HWND hwnd)
{
    HMENU menu;
    POINT pt;
    char tmp[MAX_LOADSTRING];

    if (!ac_use_try)
        return;
    menu = CreatePopupMenu();
    if (menu) {
        if (ac_use_dlg) {
            ac_append_menu_item(menu, IDM_CONSOLE, "Open Console Monitor", 1, 1);
            ac_append_menu_item(menu, 0, "", 0, 1);
        }
        strcpy(tmp, "Quit ");
        strcat(tmp, ac_wtitle_name);
        ac_append_menu_item(menu, IDM_EXIT,  tmp, 0, 1);

        if (!SetForegroundWindow(hwnd))
            SetForegroundWindow(NULL);
        GetCursorPos(&pt);
        TrackPopupMenu(menu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, 
                       pt.x, pt.y, 0, hwnd, NULL);
        DestroyMenu(menu);
    }
}

static void ac_center_window(HWND hwnd)
{
   RECT    rc, rw;
   int     cw, ch;
   int     x, y;
   if (!ac_use_try)
       return;

   /* Get the Height and Width of the child window */
   GetWindowRect(hwnd, &rc);
   cw = rc.right - rc.left;
   ch = rc.bottom - rc.top;

   /* Get the limits of the 'workarea' */
   if (!SystemParametersInfo(
            SPI_GETWORKAREA,
            sizeof(RECT),
            &rw, 0)) {
      rw.left = rw.top = 0;
      rw.right = GetSystemMetrics(SM_CXSCREEN);
      rw.bottom = GetSystemMetrics(SM_CYSCREEN);
   }

   /* Calculate new X and Y position*/
   x = (rw.right - cw)/2;
   y = (rw.bottom - ch)/2;
   SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
}

LRESULT CALLBACK ac_console_dlg_proc(HWND hdlg, UINT message, WPARAM wparam, LPARAM 
lparam)
{

    RECT r, m;
    static      HWND  status_bar; 
    char    etxt[1024];
    int     elen, i;
    switch (message) {
        case WM_INITDIALOG:
           /* TODO: restore previous window pos */
           SendMessage(hdlg, WM_SETICON, ICON_SMALL, (LPARAM)ac_main_icon);
           SendMessage(hdlg, WM_SETICON, ICON_BIG, (LPARAM)ac_main_licon);
           ac_list_hwnd = GetDlgItem(hdlg, IDL_STDOUT); 
           ac_edit_hwnd = GetDlgItem(hdlg, IDE_STDIN); 
           status_bar = CreateStatusWindow(0x0800 /* SBT_TOOLTIPS */
                                          | WS_CHILD | WS_VISIBLE,
                                            ac_cmdline, hdlg, IDC_STATBAR);
           GetWindowRect(status_bar, &r);
           GetClientRect(hdlg, &m);
           MoveWindow(ac_list_hwnd, 0, 0, m.right - m.left, m.bottom - abs((r.top - 
r.bottom)) - 26, TRUE);
           MoveWindow(ac_edit_hwnd, 0, m.bottom - abs((r.top - r.bottom)) - 24, 
m.right - m.left, 24, TRUE);
           SendMessage(ac_list_hwnd, LB_INITSTORAGE, (WPARAM)MAX_LOADSTRING,
                      (LPARAM)(MAX_LOADSTRING * MAX_LOADSTRING));
           ac_disp_hwnd = hdlg;
           if (!ac_use_try) {
                SetWindowLong(hdlg, GWL_STYLE, DS_3DLOOK | WS_MAXIMIZEBOX | WS_POPUP | 
WS_CAPTION | 
                                    WS_SYSMENU | WS_THICKFRAME);
           }
           break;
        case WM_SIZE:
            switch (LOWORD(wparam)) { 
                case SIZE_MINIMIZED:
                    if (ac_use_try) {
                        EndDialog(hdlg, TRUE); 
                        ac_disp_hwnd = NULL;
                    }
                    return TRUE; 
                break;
                default:
                    GetWindowRect(status_bar, &r);
                    MoveWindow(status_bar, 0, HIWORD(lparam) - (r.top - r.bottom),
                                              LOWORD(lparam), (r.top - r.bottom), 
TRUE);
                    GetClientRect(hdlg, &m);
                    MoveWindow(ac_list_hwnd, 0, 0, LOWORD(lparam), HIWORD(lparam) - 
abs((r.top - r.bottom)) - 26, TRUE);
                    MoveWindow(ac_edit_hwnd, 0, HIWORD(lparam) - abs((r.top - 
r.bottom)) - 24, LOWORD(lparam), 24, TRUE);
                    break;
            }
        break;
        case WM_COMMAND:
            switch (wparam) {
                case IDM_EDIT_COPY:
                    {
                        /* TODO: Copy selected to Clipboad */ 

                    }
                    break;
                case IDM_FILE_SAVE:
                    {
                        /* TODO: Save selected to File */ 

                    }
                    break;
                case IDM_FILE_EXIT:
                    ac_show_try_icon(ac_main_hwnd, NIM_DELETE, NULL);
                    ac_kill_child();
                    EndDialog(hdlg, TRUE);
                    ac_list_hwnd = NULL;
                    ac_disp_hwnd = NULL;
                    PostQuitMessage(0);
                    return TRUE;
                case IDCANCEL:
                    ac_show_try_icon(ac_main_hwnd, NIM_DELETE, NULL);
                    EndDialog(hdlg, TRUE);
                    ac_list_hwnd = NULL;
                    ac_disp_hwnd = NULL;
                    if (!ac_use_try) {
                        ac_kill_child();
                        PostQuitMessage(0);
                    }
                    return TRUE;
                case IDOK:
                    elen = SendMessage(ac_edit_hwnd, EM_GETLINE, 0, (LPARAM)etxt);
                    etxt[elen] = '\n';
                    etxt[elen+1] = '\0';
                    SendMessage(ac_edit_hwnd, WM_SETTEXT, 0, (LPARAM)"");
                    if (ac_handles.wr && 
                        (WriteFile(ac_handles.wr, etxt, elen+1, &i, NULL) != TRUE)) {
                        ac_error_msgbox(ac_handles.wr ? "No stin handles" : NULL, 
FALSE);
                    }
                    else
                        FlushFileBuffers(ac_handles.wr);
                    break;

            }
            break;
        case WM_QUIT:
        case WM_CLOSE: 
            EndDialog(hdlg, TRUE);
            ac_list_hwnd = NULL;
            ac_disp_hwnd = NULL;
            if (!ac_use_try) {
                ac_kill_child();
                PostQuitMessage(0);
            }
            return TRUE;
        default:
            return FALSE;


    }

    return FALSE;
}

LRESULT CALLBACK ac_main_wnd_proc(HWND hwnd, UINT message,
                          WPARAM wparam, LPARAM lparam)
{
    if (message == ac_taskbar_created)
    {
        /* restore the tray icon on shell restart */
        ac_show_try_icon(hwnd, NIM_ADD, ac_wtitle_name);
        return DefWindowProc(hwnd, message, wparam, lparam);
    }
    switch (message) 
    {
        case WM_CREATE:
            ac_child.dwProcessId = 0;
            ac_disp_hwnd = NULL;

            if (ac_redirect_console(ac_cmdline) != APR_SUCCESS) {
                PostQuitMessage(3);
                return FALSE;
            }
            /* set the timer that will monitor the child activity */
            SetTimer(hwnd, WM_TIMER_REFRESH, REFRESH_TIME, NULL);

            if (!ac_use_gui)
                return FALSE;

            ac_show_try_icon(hwnd, NIM_ADD, ac_wtitle_name);
            if (ac_use_show)
                DialogBox(ac_instance, MAKEINTRESOURCE(IDD_DLGCONSOLE),
                       hwnd, (DLGPROC)ac_console_dlg_proc);

            break;
        case WM_DESTROY:
        case WM_QUIT:
            ac_show_try_icon(hwnd, NIM_DELETE, NULL);
            ac_kill_child();
            break;
        case WM_TRAYMESSAGE:
            switch(lparam)
            {
                case WM_LBUTTONDBLCLK:
                    if (ac_disp_hwnd != NULL) {
                       SetWindowPos(ac_disp_hwnd, HWND_TOPMOST, 0, 0, 0, 0,
                                    SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
                       SetWindowPos(ac_disp_hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
                                    SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
                       SetFocus(ac_edit_hwnd);
                    }
                    else if (ac_use_dlg)
                       DialogBox(ac_instance, MAKEINTRESOURCE(IDD_DLGCONSOLE),
                                 hwnd, (DLGPROC)ac_console_dlg_proc);                  
  
                break;
                case WM_RBUTTONUP:
                    ac_show_try_menu(hwnd);
                break;    
            }
            break;
        case WM_COMMAND:
            switch (LOWORD(wparam))
            {
               case IDM_EXIT:
                   ac_show_try_icon(hwnd, NIM_DELETE, NULL);
                   ac_kill_child();
                   PostQuitMessage(CONWRAP_SUCCESS);
                   return TRUE;
                   break;
               case IDM_CONSOLE:
                   DialogBox(ac_instance, MAKEINTRESOURCE(IDD_DLGCONSOLE),
                       hwnd, (DLGPROC)ac_console_dlg_proc);
                   
                   break;
            }
        case WM_TIMER:
            switch (wparam)
            {
                case WM_TIMER_REFRESH:
                {
                    DWORD stat;
                    ac_run_time += REFRESH_TIME;
                    if (!GetExitCodeProcess(ac_child.hProcess, &stat) || 
                        (stat != STILL_ACTIVE)) {
                        ac_child.dwProcessId = 0;
                        PostQuitMessage(5);
                    }
                    else if (ac_use_rtime && ac_run_time > ac_use_rtime) {
                        ac_kill_child();
                        PostQuitMessage(CONWRAP_TIMEOUT);
                    }
                }
                break;
            }
        default:
            return DefWindowProc(hwnd, message, wparam, lparam);
    }

    return FALSE;
}

/* Create main invisible window */
HWND ac_create_main_window(HINSTANCE instance, const char *wclass, const char *title)
{
    HWND       hwnd = NULL;
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX); 

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = ac_main_wnd_proc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = instance;
    wcex.hIcon          = ac_main_icon = (HICON)LoadImage(instance, 
MAKEINTRESOURCE(IDI_ICOCONWRAP),
                                                IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = 0;
    wcex.lpszClassName  = wclass;
    wcex.hIconSm        = ac_main_licon = (HICON)LoadImage(instance, 
MAKEINTRESOURCE(IDI_ICOCONWRAP),
                                                IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);

    if (RegisterClassEx(&wcex))
        hwnd = CreateWindow(wclass, title,
                             0, 0, 0, 0, 0,
                             NULL, NULL, instance, NULL);

    return hwnd;

}

static char *ac_usage = "conwrap [options] commandline\n"
                        "-c              use console interactive window\n"
                        "-e              use error reporting\n"
                        "-g              use GUI\n"
                        "-q <time> set the maximum execution time\n"
                        "-n <title>  set the name for the conwrap\n"
                        "-s              show the console interactive window\n"
                        "-t              put the icon in system try\n\n"
                        "example : conwrap apache.exe -k install -n \"Apache 
Service\"\n";

int WINAPI WinMain(HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine,
                    int nCmdShow)
{

    MSG   msg;
    int   i = 1, name = 0;
    char  *arg, *prg;
    int help = 0;

    /* use the global __argc and __argv by the C runtime startup code.*/
    ac_cmdline = lpCmdLine;

    if (__argc > 1) {
        arg = __argv[i];
        while (arg && *arg == '-') { 
            switch (*(arg + 1)) {
                case 'c':
                    ac_use_dlg = 1;
                    break;
                case 'e':
                    ac_use_err = 1;
                    break;
                case 'g':
                    ac_use_gui = 1;
                    break;
                case 'q':
                    ++i;
                    ac_use_rtime = atoi(__argv[i]);
                    ac_cmdline += strlen(__argv[i]) + 1;
                    break;
                case 'm':
                    ++i;
                    ac_shmem_name = __argv[i];
                    /* the shared mem name must be unescaped! so no \" etc...
                       only spaces are allowed
                    */
                    if (*ac_cmdline == '"')
                        ac_cmdline += 2;
                    ac_cmdline += strlen(ac_shmem_name) + 1;
                case 'n':
                    name = 1;
                    ++i;
                    strcpy(ac_wtitle_name, __argv[i]);
                    /* the title must be unescaped! so no \" etc...
                       only spaces are allowed
                    */
                    if (*ac_cmdline == '"')
                        ac_cmdline += 2;
                    ac_cmdline += strlen(ac_wtitle_name) + 1;
                case 's':
                    ac_use_show = 1;
                    break;
                case 't':
                    ac_use_try = 1;
                    break;
                default:
                    help = 1;
                    break;
            }
            ++i;
            arg = __argv[i];
            ac_cmdline += 3;
        }
    }
    else
        return CONWRAP_ENOARGS;
    
    if (help) {
        MessageBox(NULL, ac_usage, "Apache Console Wrapper", 
                   MB_OK | MB_ICONINFORMATION | MB_SYSTEMMODAL);
        return -1;
    }
    apr_initialize();
    atexit(apr_terminate);
    apr_pool_create(&ac_pool, NULL);

    prg = __argv[i];
    i = strlen(prg) - 1;
    while (i >= 0) {
        if (prg[i] == '\\' || prg[i] == '\\') {
            prg += i + 1;
            break;
        }
        --i;
    }
    if (!stricmp(prg, "apache.exe"))
        ac_is_httpd = 1;
    /* the rest of command line is passed to the child */    
    if (ac_use_gui) {
        ac_lang_id = GetUserDefaultLangID();
        if ((ac_lang_id & 0xFF) != LANG_ENGLISH)
            ac_lang_id = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
        InitCommonControls();
    }
    if (!name)
        LoadString(hInstance, IDS_CONWRAPTITLE, ac_wtitle_name, MAX_LOADSTRING);
    LoadString(hInstance, IDS_CONWRAPCLASS, ac_wclass_name, MAX_LOADSTRING);
    
    ac_instance = hInstance;
    ac_stdout_lines = apr_table_make(ac_pool, MAX_LOADSTRING);
    ac_main_hwnd = ac_create_main_window(hInstance, ac_wclass_name, ac_wtitle_name);
    if (ac_use_try)
        ac_taskbar_created = RegisterWindowMessage("TaskbarCreated");

    if (ac_main_hwnd != NULL) {
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }    
    }

    return CONWRAP_SUCCESS;
}
# Microsoft Developer Studio Project File - Name="conwrap" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **

# TARGTYPE "Win32 (x86) Application" 0x0101

CFG=conwrap - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE 
!MESSAGE NMAKE /f "conwrap.mak".
!MESSAGE 
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE 
!MESSAGE NMAKE /f "conwrap.mak" CFG="conwrap - Win32 Debug"
!MESSAGE 
!MESSAGE Possible choices for configuration are:
!MESSAGE 
!MESSAGE "conwrap - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "conwrap - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE 

# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe

!IF  "$(CFG)" == "conwrap - Win32 Release"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX 
/FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD 
/c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x41a /d "NDEBUG"
# ADD RSC /l 0x41a /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib 
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 
/nologo /subsystem:windows /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib 
shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo 
/subsystem:windows /machine:I386

!ELSEIF  "$(CFG)" == "conwrap - Win32 Debug"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D 
"_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../../srclib/apr/include" /I 
"../srclib/apr-util/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D 
"STRICT" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x41a /d "_DEBUG"
# ADD RSC /l 0x41a /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib 
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 
/nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib 
shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib 
mswsock.lib version.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 
/pdbtype:sept

!ENDIF 

# Begin Target

# Name "conwrap - Win32 Release"
# Name "conwrap - Win32 Debug"
# Begin Group "Source Files"

# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File

SOURCE=.\conwrap.c

!IF  "$(CFG)" == "conwrap - Win32 Release"

!ELSEIF  "$(CFG)" == "conwrap - Win32 Debug"

# ADD CPP /I "./include" /I "./os/win32" /I "./srclib/apr/include" /I 
"./srclib/apr-util/include"

!ENDIF 

# End Source File
# End Group
# Begin Group "Resource Files"

# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# Begin Source File

SOURCE=.\conwrap.rc
# End Source File
# End Group
# End Target
# End Project
#define IDD_DLGCONSOLE                  101
#define IDS_CONWRAPTITLE                102
#define IDS_CONWRAPCLASS                103
#define IDM_CONSOLE                     104
#define IDM_EXIT                        105
#define IDC_STATBAR                     106
#define IDC_SSTATUS                     107
#define IDB_BMPHEADER                   108
#define IDL_STDOUT                      109
#define IDE_STDIN                       110
#define IDR_CMENU                       111
#define IDM_FILE_EXIT                   112
#define IDM_FILE_SAVE                   113

#define IDM_EDIT_COPY                   114

#define IDI_ICOCONWRAP                  200

#define IDC_STATIC                      -1


#include "conwrap.h"
#include <windows.h>
IDI_ICOCONWRAP            ICON    DISCARDABLE     "..\\..\\build\\win32\\apache.ico"

STRINGTABLE DISCARDABLE 
BEGIN
    IDS_CONWRAPTITLE      "Apache Service"
    IDS_CONWRAPCLASS      "ApacheConsoleWrapperClass"
END

IDR_CMENU MENU DISCARDABLE 
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "Save &As",                   IDM_FILE_SAVE
        MENUITEM SEPARATOR
        MENUITEM "E&xit",                      IDM_FILE_EXIT
    END
    POPUP "&Edit"
    BEGIN
        MENUITEM "&Copy",                      IDM_EDIT_COPY
    END
END

IDD_DLGCONSOLE DIALOGEX 0, 0, 480, 240
STYLE DS_3DLOOK | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | 
    WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT
CAPTION "Apache Service Monitor"
MENU IDR_CMENU
FONT 10, "Courier New"
BEGIN
    EDITTEXT        IDE_STDIN,0,202,200,26, ES_AUTOHSCROLL
    LISTBOX         IDL_STDOUT,0,0,200,200,NOT LBS_NOTIFY | LBS_USETABSTOPS | 
                    LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | 
                    NOT WS_BORDER | WS_VSCROLL | 
                    WS_HSCROLL | WS_TABSTOP,WS_EX_CLIENTEDGE
    DEFPUSHBUTTON   "OK",IDOK,0,0,0,0,NOT WS_VISIBLE | WS_GROUP


END

Reply via email to