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