From: William A. Rowe Jr Date: Mon, 26 May 2008 15:58:46 +0000 (+0000) Subject: Per discussion on list and based on user feedback, merge ApacheMonitor code X-Git-Tag: 2.2.9~129 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ee1c6cb6231f5b10465602ed9bc8cf05e0a87792;p=thirdparty%2Fapache%2Fhttpd.git Per discussion on list and based on user feedback, merge ApacheMonitor code back to the trunk/ development effort. Provides for internationalized versions of ApacheMonitor, and interoperability under Windows User Access Control (UAC) restrictions. When ApacheMonitor cannot control a service, it will attempt to launch a new version of itself, prompting the user for Admin-rights credentials. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@660221 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/STATUS b/STATUS index 77a5d016f9b..dc7b1890762 100644 --- a/STATUS +++ b/STATUS @@ -180,20 +180,6 @@ PATCHES PROPOSED TO BACKPORT FROM TRUNK: rpluem says: I am missing a minor bump and documentation. niq replies: Done. - * ApacheMonitor (win32); Sync to current trunk/. This would - Introduce the --kill flag, for use by the installer, solve - a leak when using ApacheMonitor against another machine, - update to international service names etc (unicoding it) - and finally will allow Windows 2008 admins, and earlier - versions' users to invoke the start|stop|restart etc with - admin permissions. Trouble is, an Admin under UAC does - not actually launch admin-capable applications without - being show a dialog to do so. We could force this at the - start of ApacheMonitor, but it would be bogus to present - this on every login. - http://svn.apache.org/viewvc/httpd/httpd/trunk/support/win32/ApacheMonitor.c?view=log - +1: wrowe - * suexec: When group is given as a numeric gid, validate it by looking up the actual group name such that the name can be used in log entries. PR 7862 [, Leif W ] diff --git a/support/win32/ApacheMonitor.c b/support/win32/ApacheMonitor.c index fa5a3f8979d..6d97fb7b7fc 100644 --- a/support/win32/ApacheMonitor.c +++ b/support/win32/ApacheMonitor.c @@ -23,7 +23,7 @@ * ==================================================================== */ -#define _WIN32_WINNT 0x0400 +#define _WIN32_WINNT 0x0500 #ifndef STRICT #define STRICT #endif @@ -33,7 +33,6 @@ #if defined(_MSC_VER) && _MSC_VER >= 1400 #define _CRT_SECURE_NO_DEPRECATE -#pragma warning(disable: 4996) #endif #include @@ -43,8 +42,16 @@ #include #include #include +#include +#include #include "ApacheMonitor.h" +#ifndef AM_STRINGIFY +/** Properly quote a value as a string in the C preprocessor */ +#define AM_STRINGIFY(n) AM_STRINGIFY_HELPER(n) +/** Helper macro for AM_STRINGIFY */ +#define AM_STRINGIFY_HELPER(n) #n +#endif #define OS_VERSION_WIN9X 1 #define OS_VERSION_WINNT 2 @@ -68,24 +75,24 @@ typedef struct _st_APACHE_SERVICE { - LPSTR szServiceName; - LPSTR szDisplayName; - LPSTR szDescription; - LPSTR szImagePath; - LPSTR szComputerName; + LPTSTR szServiceName; + LPTSTR szDisplayName; + LPTSTR szDescription; + LPTSTR szImagePath; + LPTSTR szComputerName; DWORD dwPid; } ST_APACHE_SERVICE; typedef struct _st_MONITORED_COMPUTERS { - LPSTR szComputerName; + LPTSTR szComputerName; HKEY hRegistry; } ST_MONITORED_COMP; /* Global variables */ HINSTANCE g_hInstance = NULL; -CHAR *g_szTitle; /* The title bar text */ -CHAR *g_szWindowClass; /* Window Class Name */ +TCHAR *g_szTitle; /* The title bar text */ +TCHAR *g_szWindowClass; /* Window Class Name */ HICON g_icoStop; HICON g_icoRun; UINT g_bUiTaskbarCreated; @@ -113,10 +120,10 @@ HANDLE g_hpipeStdError; LANGID g_LangID; PROCESS_INFORMATION g_lpRedirectProc; CRITICAL_SECTION g_stcSection; -LPSTR g_szLocalHost; +LPTSTR g_szLocalHost; /* locale language support */ -static CHAR *g_lpMsg[IDS_MSG_LAST - IDS_MSG_FIRST + 1]; +static TCHAR *g_lpMsg[IDS_MSG_LAST - IDS_MSG_FIRST + 1]; void am_ClearServicesSt() @@ -160,11 +167,11 @@ void am_ClearComputersSt() } -BOOL am_IsComputerConnected(LPSTR szComputerName) +BOOL am_IsComputerConnected(LPTSTR szComputerName) { int i = 0; while (g_stComputers[i].szComputerName != NULL) { - if (strcmp(g_stComputers[i].szComputerName, szComputerName) == 0) { + if (_tcscmp(g_stComputers[i].szComputerName, szComputerName) == 0) { return TRUE; } ++i; @@ -173,11 +180,11 @@ BOOL am_IsComputerConnected(LPSTR szComputerName) } -void am_DisconnectComputer(LPSTR szComputerName) +void am_DisconnectComputer(LPTSTR szComputerName) { int i = 0, j; while (g_stComputers[i].szComputerName != NULL) { - if (strcmp(g_stComputers[i].szComputerName, szComputerName) == 0) { + if (_tcscmp(g_stComputers[i].szComputerName, szComputerName) == 0) { break; } ++i; @@ -195,7 +202,7 @@ void am_DisconnectComputer(LPSTR szComputerName) } -void ErrorMessage(LPCSTR szError, BOOL bFatal) +void ErrorMessage(LPCTSTR szError, BOOL bFatal) { LPVOID lpMsgBuf = NULL; if (szError) { @@ -207,8 +214,8 @@ void ErrorMessage(LPCSTR szError, BOOL bFatal) FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), g_LangID, - (LPSTR) &lpMsgBuf, 0, NULL); - MessageBox(NULL, (LPCSTR)lpMsgBuf, + (LPTSTR) &lpMsgBuf, 0, NULL); + MessageBox(NULL, (LPCTSTR)lpMsgBuf, g_lpMsg[IDS_MSG_ERROR - IDS_MSG_FIRST], MB_OK | (bFatal ? MB_ICONERROR : MB_ICONEXCLAMATION)); LocalFree(lpMsgBuf); @@ -219,14 +226,37 @@ void ErrorMessage(LPCSTR szError, BOOL bFatal) } -BOOL am_ConnectComputer(LPSTR szComputerName) +int am_RespawnAsUserAdmin(HWND hwnd, DWORD op, LPCTSTR szService, + LPCTSTR szComputerName) +{ + TCHAR args[MAX_PATH + MAX_COMPUTERNAME_LENGTH + 12]; + + if (g_dwOSVersion < OS_VERSION_WIN2K) { + ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST], FALSE); + return 0; + } + + _sntprintf(args, sizeof(args) / sizeof(TCHAR), + _T("%d \"%s\" \"%s\""), op, szService, + szComputerName ? szComputerName : _T("")); + if (!ShellExecute(hwnd, _T("runas"), __targv[0], args, NULL, SW_NORMAL)) { + ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST], + FALSE); + return 0; + } + + return 1; +} + + +BOOL am_ConnectComputer(LPTSTR szComputerName) { int i = 0; HKEY hKeyRemote; - char szTmp[MAX_PATH]; + TCHAR szTmp[MAX_PATH]; while (g_stComputers[i].szComputerName != NULL) { - if (strcmp(g_stComputers[i].szComputerName, szComputerName) == 0) { + if (_tcscmp(g_stComputers[i].szComputerName, szComputerName) == 0) { return FALSE; } ++i; @@ -236,22 +266,23 @@ BOOL am_ConnectComputer(LPSTR szComputerName) } if (RegConnectRegistry(szComputerName, HKEY_LOCAL_MACHINE, &hKeyRemote) != ERROR_SUCCESS) { - sprintf(szTmp, g_lpMsg[IDS_MSG_ECONNECT - IDS_MSG_FIRST], - szComputerName); + _sntprintf(szTmp, sizeof(szTmp) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_ECONNECT - IDS_MSG_FIRST], + szComputerName); ErrorMessage(szTmp, FALSE); return FALSE; } else { - g_stComputers[i].szComputerName = strdup(szComputerName); + g_stComputers[i].szComputerName = _tcsdup(szComputerName); g_stComputers[i].hRegistry = hKeyRemote; return TRUE; } } -LPSTR GetStringRes(int id) +LPTSTR GetStringRes(int id) { - static CHAR buffer[MAX_PATH]; + static TCHAR buffer[MAX_PATH]; buffer[0] = 0; LoadString(GetModuleHandle(NULL), id, buffer, MAX_PATH); @@ -327,22 +358,24 @@ static VOID ShowNotifyIcon(HWND hWnd, DWORD dwMessage) nid.hIcon = NULL; } if (n == i && n > 0) { - lstrcpy(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGALL - IDS_MSG_FIRST]); + _tcscpy(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGALL - IDS_MSG_FIRST]); } else if (n) { - sprintf(nid.szTip, g_lpMsg[IDS_MSG_RUNNING - IDS_MSG_FIRST], n, i); + _sntprintf(nid.szTip, sizeof(nid.szTip) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_RUNNING - IDS_MSG_FIRST], n, i); } else if (i) { - sprintf(nid.szTip, g_lpMsg[IDS_MSG_RUNNINGNONE - IDS_MSG_FIRST], i); + _sntprintf(nid.szTip, sizeof(nid.szTip) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_RUNNINGNONE - IDS_MSG_FIRST], i); } else { - lstrcpy(nid.szTip, g_lpMsg[IDS_MSG_NOSERVICES - IDS_MSG_FIRST]); + _tcscpy(nid.szTip, g_lpMsg[IDS_MSG_NOSERVICES - IDS_MSG_FIRST]); } Shell_NotifyIcon(dwMessage, &nid); } -void appendMenuItem(HMENU hMenu, UINT uMenuId, LPSTR szName, +void appendMenuItem(HMENU hMenu, UINT uMenuId, LPTSTR szName, BOOL fDefault, BOOL fEnabled) { MENUITEMINFO mii; @@ -350,7 +383,7 @@ void appendMenuItem(HMENU hMenu, UINT uMenuId, LPSTR szName, memset(&mii, 0, sizeof(MENUITEMINFO)); mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; - if (lstrlen(szName)) + if (_tcslen(szName)) { mii.fType = MFT_STRING; mii.wID = uMenuId; @@ -370,7 +403,7 @@ void appendMenuItem(HMENU hMenu, UINT uMenuId, LPSTR szName, void appendServiceMenu(HMENU hMenu, UINT uMenuId, - LPSTR szServiceName, BOOL fRunning) + LPTSTR szServiceName, BOOL fRunning) { MENUITEMINFO mii; HMENU smh; @@ -415,7 +448,7 @@ void ShowTryPopupMenu(HWND hWnd) g_lpMsg[IDS_MSG_MNUSERVICES - IDS_MSG_FIRST], FALSE, TRUE); } - appendMenuItem(hMenu, 0, "", FALSE, TRUE); + appendMenuItem(hMenu, 0, _T(""), FALSE, TRUE); appendMenuItem(hMenu, IDM_EXIT, g_lpMsg[IDS_MSG_MNUEXIT - IDS_MSG_FIRST], FALSE, TRUE); @@ -489,7 +522,7 @@ BOOL CenterWindow(HWND hwndChild) } -static void addListBoxItem(HWND hDlg, LPSTR lpStr, HBITMAP hBmp) +static void addListBoxItem(HWND hDlg, LPTSTR lpStr, HBITMAP hBmp) { LRESULT nItem; @@ -498,7 +531,7 @@ static void addListBoxItem(HWND hDlg, LPSTR lpStr, HBITMAP hBmp) } -static void addListBoxString(HWND hListBox, LPSTR lpStr) +static void addListBoxString(HWND hListBox, LPTSTR lpStr) { static int nItems = 0; if (!g_bDlgServiceOn) { @@ -516,6 +549,32 @@ static void addListBoxString(HWND hListBox, LPSTR lpStr) } +#ifndef UNICODE +#define addListBoxStringA addListBoxString +#else +static void addListBoxStringA(HWND hListBox, LPSTR lpStr) +{ + static int nItems = 0; + TCHAR WStr[16384]; + + if (!g_bDlgServiceOn) { + return; + } + if (!MultiByteToWideChar(CP_ACP, 0, lpStr, (int)strlen(lpStr) + 1, + WStr, (int) (sizeof(WStr) / sizeof(TCHAR)))) + return; + ++nItems; + if (nItems > MAX_LOADSTRING) + { + SendMessage(hListBox, LB_RESETCONTENT, 0, 0); + nItems = 1; + } + ListBox_SetCurSel(hListBox, + ListBox_AddString(hListBox, WStr)); +} +#endif + + static DWORD WINAPI ConsoleOutputThread(LPVOID lpThreadParameter) { static BYTE lpBuffer[MAX_PATH+1]; @@ -530,7 +589,7 @@ static DWORD WINAPI ConsoleOutputThread(LPVOID lpThreadParameter) if (ch == '\n' || nPtr >= MAX_PATH) { lpBuffer[nPtr] = '\0'; - addListBoxString(g_hwndStdoutList, lpBuffer); + addListBoxStringA(g_hwndStdoutList, lpBuffer); nPtr = 0; } else if (ch == '\t' && nPtr < (MAX_PATH - 4)) @@ -563,7 +622,7 @@ DWORD WINAPI ConsoleWaitingThread(LPVOID lpThreadParameter) } -BOOL RunRedirectedConsole(LPSTR szCmdLine) +BOOL RunRedirectedConsole(LPTSTR szCmdLine) { DWORD dwThreadId; HANDLE hProc; @@ -630,7 +689,7 @@ BOOL RunRedirectedConsole(LPSTR szCmdLine) } -BOOL RunAndForgetConsole(LPSTR szCmdLine, BOOL bRedirectConsole) +BOOL RunAndForgetConsole(LPTSTR szCmdLine, BOOL bRedirectConsole) { STARTUPINFO stInfo; PROCESS_INFORMATION prInfo; @@ -669,12 +728,12 @@ BOOL RunAndForgetConsole(LPSTR szCmdLine, BOOL bRedirectConsole) } -BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, - LPSTR szComputerName, DWORD dwCommand) +BOOL ApacheManageService(LPCTSTR szServiceName, LPCTSTR szImagePath, + LPTSTR szComputerName, DWORD dwCommand) { - CHAR szBuf[MAX_PATH]; - CHAR szMsg[MAX_PATH]; - LPSTR sPos; + TCHAR szBuf[MAX_PATH]; + TCHAR szMsg[MAX_PATH]; + LPTSTR sPos; BOOL retValue; BOOL serviceFlag = TRUE; SC_HANDLE schService; @@ -684,32 +743,33 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, if (g_dwOSVersion == OS_VERSION_WIN9X) { - sPos = strstr(szImagePath, "-k start"); + sPos = _tcsstr(szImagePath, _T("-k start")); if (sPos) { - lstrcpyn(szBuf, szImagePath, (int)(sPos - szImagePath)); + _tcsncpy(szBuf, szImagePath, (int)(sPos - szImagePath)); switch (dwCommand) { case SERVICE_CONTROL_STOP: - lstrcat(szBuf, " -k shutdown -n "); + _tcscat(szBuf, _T(" -k shutdown -n ")); break; case SERVICE_CONTROL_CONTINUE: - sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); - lstrcat(szBuf, " -k start -n "); + _tcscat(szBuf, _T(" -k start -n ")); serviceFlag = FALSE; break; case SERVICE_APACHE_RESTART: - lstrcat(szBuf, " -k restart -n "); + _tcscat(szBuf, _T(" -k restart -n ")); break; default: return FALSE; } - lstrcat(szBuf, szServiceName); + _tcscat(szBuf, szServiceName); } else { return FALSE; @@ -725,8 +785,9 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, } else if (!serviceFlag) { - sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); g_bConsoleRun = FALSE; SetCursor(g_hCursorArrow); @@ -738,13 +799,29 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, schSCManager = OpenSCManager(szComputerName, NULL, SC_MANAGER_CONNECT); if (!schSCManager) { + ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST], + FALSE); return FALSE; } schService = OpenService(schSCManager, szServiceName, SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL); - if (schService != NULL) + if (schService == NULL) + { + /* Avoid recursion of ImagePath NULL (from this Respawn) */ + if (szImagePath) { + am_RespawnAsUserAdmin(g_hwndMain, dwCommand, + szServiceName, szComputerName); + } + else { + ErrorMessage(g_lpMsg[IDS_MSG_SRVFAILED - IDS_MSG_FIRST], + FALSE); + } + CloseServiceHandle(schSCManager); + return FALSE; + } + else { retValue = FALSE; g_bConsoleRun = TRUE; @@ -752,8 +829,9 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, switch (dwCommand) { case SERVICE_CONTROL_STOP: - sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTOP - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVSTOP - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); if (ControlService(schService, SERVICE_CONTROL_STOP, &schSStatus)) { @@ -774,17 +852,18 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, if (schSStatus.dwCurrentState == SERVICE_STOPPED) { retValue = TRUE; - sprintf(szMsg, - g_lpMsg[IDS_MSG_SRVSTOPPED - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVSTOPPED - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); } } break; case SERVICE_CONTROL_CONTINUE: - sprintf(szMsg, g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVSTART - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); if (StartService(schService, 0, NULL)) @@ -806,17 +885,18 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, if (schSStatus.dwCurrentState == SERVICE_RUNNING) { retValue = TRUE; - sprintf(szMsg, - g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVSTARTED - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); } } break; case SERVICE_APACHE_RESTART: - sprintf(szMsg, g_lpMsg[IDS_MSG_SRVRESTART - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVRESTART - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); if (ControlService(schService, SERVICE_APACHE_RESTART, &schSStatus)) @@ -841,9 +921,9 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, if (schSStatus.dwCurrentState == SERVICE_RUNNING) { retValue = TRUE; - sprintf(szMsg, - g_lpMsg[IDS_MSG_SRVRESTARTED - IDS_MSG_FIRST], - szServiceName); + _sntprintf(szMsg, sizeof(szMsg) / sizeof(TCHAR), + g_lpMsg[IDS_MSG_SRVRESTARTED - IDS_MSG_FIRST], + szServiceName); addListBoxString(g_hwndStdoutList, szMsg); } break; @@ -858,10 +938,6 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, SetCursor(g_hCursorArrow); return retValue; } - else { - g_bRescanServices = TRUE; - } - CloseServiceHandle(schSCManager); return FALSE; } @@ -869,7 +945,7 @@ BOOL ApacheManageService(LPCSTR szServiceName, LPCSTR szImagePath, } -BOOL IsServiceRunning(LPCSTR szServiceName, LPCSTR szComputerName, +BOOL IsServiceRunning(LPCTSTR szServiceName, LPCTSTR szComputerName, LPDWORD lpdwPid) { DWORD dwPid; @@ -880,7 +956,7 @@ BOOL IsServiceRunning(LPCSTR szServiceName, LPCSTR szComputerName, if (g_dwOSVersion == OS_VERSION_WIN9X) { - hWnd = FindWindow("ApacheWin95ServiceMonitor", szServiceName); + hWnd = FindWindow(_T("ApacheWin95ServiceMonitor"), szServiceName); if (hWnd && GetWindowThreadProcessId(hWnd, &dwPid)) { *lpdwPid = 1; @@ -949,11 +1025,11 @@ BOOL FindRunningServices(void) BOOL GetApacheServicesStatus() { - CHAR szKey[MAX_PATH]; - CHAR achKey[MAX_PATH]; - CHAR szImagePath[MAX_PATH]; - CHAR szBuf[MAX_PATH]; - CHAR szTmp[MAX_PATH]; + TCHAR szKey[MAX_PATH]; + TCHAR achKey[MAX_PATH]; + TCHAR szImagePath[MAX_PATH]; + TCHAR szBuf[MAX_PATH]; + TCHAR szTmp[MAX_PATH]; HKEY hKey, hSubKey, hKeyRemote; DWORD retCode, rv, dwKeyType; DWORD dwBufLen = MAX_PATH; @@ -966,7 +1042,7 @@ BOOL GetApacheServicesStatus() while (g_stComputers[computers].szComputerName != NULL) { hKeyRemote = g_stComputers[computers].hRegistry; retCode = RegOpenKeyEx(hKeyRemote, - "System\\CurrentControlSet\\Services\\", + _T("System\\CurrentControlSet\\Services\\"), 0, KEY_READ, &hKey); if (retCode != ERROR_SUCCESS) { @@ -978,60 +1054,57 @@ BOOL GetApacheServicesStatus() retCode = RegEnumKey(hKey, i, achKey, MAX_PATH); if (retCode == ERROR_SUCCESS) { - lstrcpy(szKey, "System\\CurrentControlSet\\Services\\"); - lstrcat(szKey, achKey); + _tcscpy(szKey, _T("System\\CurrentControlSet\\Services\\")); + _tcscat(szKey, achKey); if (RegOpenKeyEx(hKeyRemote, szKey, 0, KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS) { dwBufLen = MAX_PATH; - rv = RegQueryValueEx(hSubKey, "ImagePath", NULL, - &dwKeyType, szImagePath, &dwBufLen); + rv = RegQueryValueEx(hSubKey, _T("ImagePath"), NULL, + &dwKeyType, (LPBYTE)szImagePath, &dwBufLen); if (rv == ERROR_SUCCESS && (dwKeyType == REG_SZ || dwKeyType == REG_EXPAND_SZ) && dwBufLen) { - lstrcpy(szBuf, szImagePath); + _tcscpy(szBuf, szImagePath); CharLower(szBuf); /* the service name could be httpd*.exe or Apache*.exe */ - if (((strstr(szBuf, "\\apache") != NULL) - || (strstr(szBuf, "\\httpd") != NULL)) - && strstr(szBuf, ".exe") - && (strstr(szBuf, "--ntservice") != NULL - || strstr(szBuf, "-k ") != NULL)) + if (((_tcsstr(szBuf, _T("\\apache")) != NULL) + || (_tcsstr(szBuf, _T("\\httpd")) != NULL)) + && _tcsstr(szBuf, _T(".exe")) + && (_tcsstr(szBuf, _T("--ntservice")) != NULL + || _tcsstr(szBuf, _T("-k ")) != NULL)) { - g_stServices[stPos].szServiceName = strdup(achKey); - g_stServices[stPos].szImagePath = - strdup(szImagePath); + g_stServices[stPos].szServiceName = _tcsdup(achKey); + g_stServices[stPos].szImagePath = _tcsdup(szImagePath); g_stServices[stPos].szComputerName = - strdup(g_stComputers[computers].szComputerName); + _tcsdup(g_stComputers[computers].szComputerName); dwBufLen = MAX_PATH; - if (RegQueryValueEx(hSubKey, "Description", NULL, - &dwKeyType, szBuf, &dwBufLen) + if (RegQueryValueEx(hSubKey, _T("Description"), NULL, + &dwKeyType, (LPBYTE)szBuf, &dwBufLen) == ERROR_SUCCESS) { - g_stServices[stPos].szDescription = - strdup(szBuf); + g_stServices[stPos].szDescription = _tcsdup(szBuf); } dwBufLen = MAX_PATH; - if (RegQueryValueEx(hSubKey, "DisplayName", NULL, - &dwKeyType, szBuf, &dwBufLen) + if (RegQueryValueEx(hSubKey, _T("DisplayName"), NULL, + &dwKeyType, (LPBYTE)szBuf, &dwBufLen) == ERROR_SUCCESS) { - if (strcmp(g_stComputers[computers] + if (_tcscmp(g_stComputers[computers] .szComputerName, g_szLocalHost) != 0) { - strcpy(szTmp, g_stComputers[computers] + _tcscpy(szTmp, g_stComputers[computers] .szComputerName + 2); - strcat(szTmp, "@"); - strcat(szTmp, szBuf); + _tcscat(szTmp, _T("@")); + _tcscat(szTmp, szBuf); } else { - strcpy(szTmp, szBuf); + _tcscpy(szTmp, szBuf); } - g_stServices[stPos].szDisplayName - = strdup(szTmp); + g_stServices[stPos].szDisplayName = _tcsdup(szTmp); } ++stPos; @@ -1055,7 +1128,7 @@ BOOL GetApacheServicesStatus() LRESULT CALLBACK ConnectDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { - CHAR szCmp[MAX_COMPUTERNAME_LENGTH+4]; + TCHAR szCmp[MAX_COMPUTERNAME_LENGTH+4]; switch (message) { case WM_INITDIALOG: @@ -1070,14 +1143,14 @@ LRESULT CALLBACK ConnectDlgProc(HWND hDlg, UINT message, switch (LOWORD(wParam)) { case IDOK: - memset(szCmp, 0, MAX_COMPUTERNAME_LENGTH+4); - strcpy(szCmp, "\\\\"); + memset(szCmp, 0, sizeof(szCmp)); + _tcscpy(szCmp, _T("\\\\")); SendMessage(GetDlgItem(hDlg, IDC_COMPUTER), WM_GETTEXT, (WPARAM) MAX_COMPUTERNAME_LENGTH, (LPARAM) szCmp+2); - strupr(szCmp); - if (strlen(szCmp) < 3) { + _tcsupr(szCmp); + if (_tcslen(szCmp) < 3) { EndDialog(hDlg, TRUE); return TRUE; } @@ -1096,7 +1169,7 @@ LRESULT CALLBACK ConnectDlgProc(HWND hDlg, UINT message, memset(&bi, 0, sizeof(BROWSEINFO)); SHGetSpecialFolderLocation(hDlg, CSIDL_NETWORK, &il); - bi.lpszTitle = "ApacheMonitor :\nSelect Network Computer!"; + bi.lpszTitle = _T("ApacheMonitor :\nSelect Network Computer!"); bi.pszDisplayName = szCmp; bi.hwndOwner = hDlg; bi.ulFlags = BIF_BROWSEFORCOMPUTER; @@ -1135,7 +1208,7 @@ LRESULT CALLBACK ConnectDlgProc(HWND hDlg, UINT message, LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { - CHAR szBuf[MAX_PATH]; + TCHAR szBuf[MAX_PATH]; HWND hListBox; static HWND hStatusBar; TEXTMETRIC tm; @@ -1146,7 +1219,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, LPMEASUREITEMSTRUCT lpmis; LPDRAWITEMSTRUCT lpdis; - memset(szBuf, 0, MAX_PATH); + memset(szBuf, 0, sizeof(szBuf)); switch (message) { case WM_INITDIALOG: @@ -1179,7 +1252,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, g_hwndStdoutList = GetDlgItem(hDlg, IDL_STDOUT); hStatusBar = CreateStatusWindow(0x0800 /* SBT_TOOLTIPS */ | WS_CHILD | WS_VISIBLE, - "", hDlg, IDC_STATBAR); + _T(""), hDlg, IDC_STATBAR); if (GetApacheServicesStatus()) { i = 0; @@ -1210,7 +1283,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, case WM_UPDATEMESSAGE: hListBox = GetDlgItem(hDlg, IDL_SERVICES); SendMessage(hListBox, LB_RESETCONTENT, 0, 0); - SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)""); + SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)_T("")); Button_Enable(GetDlgItem(hDlg, IDC_SSTART), FALSE); Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE); Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE); @@ -1299,7 +1372,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, Button_Enable(GetDlgItem(hDlg, IDC_SSTOP), FALSE); Button_Enable(GetDlgItem(hDlg, IDC_SRESTART), FALSE); } - if (strcmp(g_stServices[lpdis->itemID].szComputerName, + if (_tcscmp(g_stServices[lpdis->itemID].szComputerName, g_szLocalHost) == 0) { Button_Enable(GetDlgItem(hDlg, IDC_SDISCONN), FALSE); } @@ -1312,7 +1385,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, (LPARAM)g_stServices[lpdis->itemID].szDescription); } else { - SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)""); + SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)_T("")); } SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); @@ -1324,7 +1397,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW)); FillRect(lpdis->hDC, &rcBitmap, (HBRUSH)(COLOR_WINDOW+1)); } - TextOut(lpdis->hDC, XBITMAP + 6, y, szBuf, (int)strlen(szBuf)); + TextOut(lpdis->hDC, XBITMAP + 6, y, szBuf, (int)_tcslen(szBuf)); break; case ODA_FOCUS: @@ -1399,7 +1472,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, case IDC_SMANAGER: if (g_dwOSVersion >= OS_VERSION_WIN2K) { - ShellExecute(hDlg, "open", "services.msc", "/s", + ShellExecute(hDlg, _T("open"), _T("services.msc"), _T("/s"), NULL, SW_NORMAL); } else { @@ -1612,7 +1685,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, case IDC_SMANAGER: if (g_dwOSVersion >= OS_VERSION_WIN2K) { - ShellExecute(NULL, "open", "services.msc", "/s", + ShellExecute(NULL, _T("open"), _T("services.msc"), _T("/s"), NULL, SW_NORMAL); } else { @@ -1634,18 +1707,86 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, } +static int KillAWindow(HWND appwindow) +{ + HANDLE appproc; + DWORD procid; + BOOL postres; + + SetLastError(0); + GetWindowThreadProcessId(appwindow, &procid); + if (GetLastError()) + return(2); + + appproc = OpenProcess(SYNCHRONIZE, 0, procid); + postres = PostMessage(appwindow, WM_COMMAND, IDM_EXIT, 0); + if (appproc && postres) { + if (WaitForSingleObject(appproc, 10 /* seconds */ * 1000) + == WAIT_OBJECT_0) { + CloseHandle(appproc); + return (0); + } + } + if (appproc) + CloseHandle(appproc); + + if ((appproc = OpenProcess(PROCESS_TERMINATE, 0, procid)) != NULL) { + if (TerminateProcess(appproc, 0)) { + CloseHandle(appproc); + return (0); + } + CloseHandle(appproc); + } + + /* Perhaps we were short of permissions? */ + return (2); +} + + +static int KillAllMonitors(void) +{ + HWND appwindow; + int exitcode = 0; + PWTS_PROCESS_INFO tsProcs; + DWORD tsProcCount, i; + DWORD thisProcId; + + /* This is graceful, close our own Window, clearing the icon */ + if ((appwindow = FindWindow(g_szWindowClass, g_szTitle)) != NULL) + exitcode = KillAWindow(appwindow); + + if (g_dwOSVersion < OS_VERSION_WIN2K) + return exitcode; + + thisProcId = GetCurrentProcessId(); + + if (!WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, + &tsProcs, &tsProcCount)) + return exitcode; + + /* This is ungraceful; close other Windows, with a lingering icon. + * Since on terminal server it's not possible to post the message + * to exit across sessions, we have to suffer this side effect + * of a taskbar 'icon' which will evaporate the next time that + * the user hovers over it or when the taskbar area is updated. + */ + for (i = 0; i < tsProcCount; ++i) { + if (_tcscmp(tsProcs[i].pProcessName, _T(AM_STRINGIFY(BIN_NAME))) == 0 + && tsProcs[i].ProcessId != thisProcId) + WTSTerminateProcess(WTS_CURRENT_SERVER_HANDLE, + tsProcs[i].ProcessId, 1); + } + WTSFreeMemory(tsProcs); + return exitcode; +} + + /* Create main invisible window */ HWND CreateMainWindow(HINSTANCE hInstance) { HWND hWnd = NULL; WNDCLASSEX wcex; - if (!GetSystemOSVersion(&g_dwOSVersion)) - { - ErrorMessage(NULL, TRUE); - return hWnd; - } - wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; @@ -1668,42 +1809,89 @@ HWND CreateMainWindow(HINSTANCE hInstance) NULL, NULL, hInstance, NULL); } return hWnd; - } +#ifndef UNICODE +/* Borrowed from CRT internal.h for _MBCS argc/argv parsing in this GUI app */ +int __cdecl _setargv(void); +#endif + int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { - CHAR szTmp[MAX_LOADSTRING]; - CHAR szCmp[MAX_COMPUTERNAME_LENGTH+4]; + TCHAR szTmp[MAX_LOADSTRING]; + TCHAR szCmp[MAX_COMPUTERNAME_LENGTH+4]; MSG msg; - /* single instance mutex */ - HANDLE hMutex; + /* existing window */ + HWND appwindow; + DWORD dwControl; int i; DWORD d; + if (!GetSystemOSVersion(&g_dwOSVersion)) + { + ErrorMessage(NULL, TRUE); + return 1; + } + g_LangID = GetUserDefaultLangID(); if ((g_LangID & 0xFF) != LANG_ENGLISH) { g_LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); } for (i = IDS_MSG_FIRST; i <= IDS_MSG_LAST; ++i) { LoadString(hInstance, i, szTmp, MAX_LOADSTRING); - g_lpMsg[i - IDS_MSG_FIRST] = strdup(szTmp); + g_lpMsg[i - IDS_MSG_FIRST] = _tcsdup(szTmp); } LoadString(hInstance, IDS_APMONITORTITLE, szTmp, MAX_LOADSTRING); d = MAX_COMPUTERNAME_LENGTH+1; - strcpy(szCmp, "\\\\"); + _tcscpy(szCmp, _T("\\\\")); GetComputerName(szCmp + 2, &d); - strupr(szCmp); - g_szLocalHost = strdup(szCmp); + _tcsupr(szCmp); + g_szLocalHost = _tcsdup(szCmp); memset(g_stComputers, 0, sizeof(ST_MONITORED_COMP) * MAX_APACHE_COMPUTERS); - g_stComputers[0].szComputerName = strdup(szCmp); + g_stComputers[0].szComputerName = _tcsdup(szCmp); g_stComputers[0].hRegistry = HKEY_LOCAL_MACHINE; - g_szTitle = strdup(szTmp); + g_szTitle = _tcsdup(szTmp); LoadString(hInstance, IDS_APMONITORCLASS, szTmp, MAX_LOADSTRING); - g_szWindowClass = strdup(szTmp); + g_szWindowClass = _tcsdup(szTmp); + + appwindow = FindWindow(g_szWindowClass, g_szTitle); + +#ifdef UNICODE + __wargv = CommandLineToArgvW(GetCommandLineW(), &__argc); +#else + _setargv(); +#endif + + if ((__argc == 2) && (_tcscmp(__targv[1], _T("--kill")) == 0)) + { + /* Off to chase and close up every ApacheMonitor taskbar window */ + return KillAllMonitors(); + } + else if ((__argc == 4) && (g_dwOSVersion >= OS_VERSION_WIN2K)) + { + dwControl = _ttoi(__targv[1]); + if ((dwControl != SERVICE_CONTROL_CONTINUE) && + (dwControl != SERVICE_APACHE_RESTART) && + (dwControl != SERVICE_CONTROL_STOP)) + { + return 1; + } + + /* Chase down and close up our session's previous window */ + if ((appwindow) != NULL) + KillAWindow(appwindow); + } + else if (__argc != 1) { + return 1; + } + else if (appwindow) + { + ErrorMessage(g_lpMsg[IDS_MSG_APPRUNNING - IDS_MSG_FIRST], FALSE); + return 0; + } g_icoStop = LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICOSTOP), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); @@ -1722,26 +1910,20 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, IMAGE_BITMAP, XBITMAP, YBITMAP, LR_DEFAULTCOLOR); - hMutex = CreateMutex(NULL, FALSE, "APSRVMON_MUTEX"); - if ((hMutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS)) - { - ErrorMessage(g_lpMsg[IDS_MSG_APPRUNNING - IDS_MSG_FIRST], FALSE); - if (hMutex) { - CloseHandle(hMutex); - } - return 0; - } - memset(g_stServices, 0, sizeof(ST_APACHE_SERVICE) * MAX_APACHE_SERVICES); CoInitialize(NULL); InitCommonControls(); g_hInstance = hInstance; g_hwndMain = CreateMainWindow(hInstance); - g_bUiTaskbarCreated = RegisterWindowMessage("TaskbarCreated"); + g_bUiTaskbarCreated = RegisterWindowMessage(_T("TaskbarCreated")); InitializeCriticalSection(&g_stcSection); g_hwndServiceDlg = NULL; if (g_hwndMain != NULL) { + /* To avoid recursion, pass ImagePath NULL (a noop on NT and later) */ + if ((__argc == 4) && (g_dwOSVersion >= OS_VERSION_WIN2K)) + ApacheManageService(__targv[2], NULL, __targv[3], dwControl); + while (GetMessage(&msg, NULL, 0, 0) == TRUE) { TranslateMessage(&msg); @@ -1751,7 +1933,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, } am_ClearComputersSt(); DeleteCriticalSection(&g_stcSection); - CloseHandle(hMutex); DestroyIcon(g_icoStop); DestroyIcon(g_icoRun); DestroyCursor(g_hCursorHourglass); @@ -1761,3 +1942,4 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, CoUninitialize(); return 0; } + diff --git a/support/win32/ApacheMonitor.dsp b/support/win32/ApacheMonitor.dsp index 853ddbc60cc..84369aaa723 100644 --- a/support/win32/ApacheMonitor.dsp +++ b/support/win32/ApacheMonitor.dsp @@ -52,8 +52,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug /opt:ref +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib wtsapi32.lib /nologo /subsystem:windows +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib wtsapi32.lib /nologo /subsystem:windows /debug /opt:ref # Begin Special Build Tool TargetPath=.\Release\ApacheMonitor.exe SOURCE="$(InputPath)" @@ -84,8 +84,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows /incremental:no /debug +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib wtsapi32.lib /nologo /subsystem:windows /debug +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib wtsapi32.lib /nologo /subsystem:windows /incremental:no /debug # Begin Special Build Tool TargetPath=.\Debug\ApacheMonitor.exe SOURCE="$(InputPath)" diff --git a/support/win32/ApacheMonitor.h b/support/win32/ApacheMonitor.h index 8a64b8704b8..085c45f8dde 100644 --- a/support/win32/ApacheMonitor.h +++ b/support/win32/ApacheMonitor.h @@ -18,6 +18,7 @@ * @file ApacheMonitor.h * @brief Resource definitions for ApacheMonitor.rc and ApacheMonitor.c */ +#define BIN_NAME ApacheMonitor.exe #define IDD_DLGSERVICES 101 #define IDS_APMONITORTITLE 102