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