diff options
author | William A. Rowe Jr <wrowe@apache.org> | 2008-03-04 20:44:22 +0100 |
---|---|---|
committer | William A. Rowe Jr <wrowe@apache.org> | 2008-03-04 20:44:22 +0100 |
commit | c005b2a1616b8d22f84d8e7019a5c8cc2013512f (patch) | |
tree | 500f24e6ca4298205456d84937cbe975b6c047fb /support/win32 | |
parent | Session cache interface redesign, Part 7: (diff) | |
download | apache2-c005b2a1616b8d22f84d8e7019a5c8cc2013512f.tar.xz apache2-c005b2a1616b8d22f84d8e7019a5c8cc2013512f.zip |
Enable UAC transition from ApacheMonitor running as a vanilla user without priv
into a copy runas administrator with permissions (closing the original monitor),
in response to any start/stop/restart request who's control permissions failed.
This happens to work on Win2000 and later, although it is actually needed in
Win2008 or Vista and later, where by default under UAC, the admin user actually
has no permissions to control services unless the app is run elevated.
We don't want to do this at start time, and assault the user with auth attempts
at login before they have even asked to use the features of the Monitor. Once
we've made the transition, we'll leave the new monitor running elevated. Some
branding with the "security" shield icon is actually recommended by the CUA, but
I'm neglecting this for the moment.
This patch drops the single instance mutex for a search of existing windows of
our window's class & title, which is localized to the current session and just fine
for the purpose of restricting multiple invocations.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@633607 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'support/win32')
-rw-r--r-- | support/win32/ApacheMonitor.c | 102 |
1 files changed, 81 insertions, 21 deletions
diff --git a/support/win32/ApacheMonitor.c b/support/win32/ApacheMonitor.c index 4f4d3d9784..4d925d0f5c 100644 --- a/support/win32/ApacheMonitor.c +++ b/support/win32/ApacheMonitor.c @@ -33,7 +33,6 @@ #if defined(_MSC_VER) && _MSC_VER >= 1400 #define _CRT_SECURE_NO_DEPRECATE -#pragma warning(disable: 4996) #endif #include <windows.h> @@ -227,6 +226,29 @@ void ErrorMessage(LPCTSTR szError, BOOL bFatal) } +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; @@ -777,13 +799,29 @@ BOOL ApacheManageService(LPCTSTR szServiceName, LPCTSTR 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; @@ -900,10 +938,6 @@ BOOL ApacheManageService(LPCTSTR szServiceName, LPCTSTR szImagePath, SetCursor(g_hCursorArrow); return retValue; } - else { - g_bRescanServices = TRUE; - } - CloseServiceHandle(schSCManager); return FALSE; } @@ -1438,7 +1472,7 @@ LRESULT CALLBACK ServiceDlgProc(HWND hDlg, UINT message, case IDC_SMANAGER: if (g_dwOSVersion >= OS_VERSION_WIN2K) { - ShellExecute(NULL, _T("open"), _T("services.msc"), _T("/s"), + ShellExecute(hDlg, _T("open"), _T("services.msc"), _T("/s"), NULL, SW_NORMAL); } else { @@ -1777,19 +1811,21 @@ HWND CreateMainWindow(HINSTANCE hInstance) return hWnd; } -#ifdef UNICODE -int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, - LPWSTR lpCmdLine, int nCmdShow) -#else + +#ifndef UNICODE +/* Borrowed from CRT internal.h for _MBCS argc/argv parsing in this GUI app */ +int __CRTDECL _setargv(void); +#endif + int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) -#endif { 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; @@ -1821,18 +1857,39 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LoadString(hInstance, IDS_APMONITORCLASS, szTmp, MAX_LOADSTRING); g_szWindowClass = _tcsdup(szTmp); - if (_tcsstr(lpCmdLine, _T("--kill")) != NULL) { + 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 = _tstoi(__targv[1])); + if ((dwControl != SERVICE_CONTROL_CONTINUE) && + (dwControl != SERVICE_APACHE_RESTART) && + (dwControl != SERVICE_CONTROL_STOP)) + { + return 1; + } - hMutex = CreateMutex(NULL, FALSE, _T("APSRVMON_MUTEX")); - if ((hMutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS)) + /* 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); - if (hMutex) { - CloseHandle(hMutex); - } return 0; } @@ -1863,6 +1920,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 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); @@ -1872,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); |