diff --git a/bazaar/SysExec/ShellLib.cpp b/bazaar/SysExec/ShellLib.cpp index d58c5405f..c3bf9880f 100644 --- a/bazaar/SysExec/ShellLib.cpp +++ b/bazaar/SysExec/ShellLib.cpp @@ -7,6 +7,86 @@ NAMESPACE_UPP + +//////////////////////////////////////////////////////////////////////////////////// +// utility functions to check whether an app is running in elevated mode +static bool IsVistaOrLater(void) +{ + OSVERSIONINFO osvi; + BOOL bIsWindowsXPorLater; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + GetVersionEx(&osvi); + + return (osvi.dwMajorVersion >= 6); +} + +static BOOL IsGroupMember(DWORD dwRelativeID, BOOL bProcessRelative, BOOL* pIsMember) +{ + HANDLE hToken, hDupToken; + PSID pSid = NULL; + SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY; + + if (!pIsMember) + { + SetLastError(ERROR_INVALID_USER_BUFFER); + return FALSE; + } + + if (bProcessRelative || !OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_DUPLICATE, TRUE, &hToken)) + { + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)) + return FALSE; + } + + if (!DuplicateToken(hToken, SecurityIdentification, &hDupToken)) + { + CloseHandle(hToken); + return FALSE; + } + + CloseHandle(hToken); + hToken = hDupToken; + + if (!AllocateAndInitializeSid(&SidAuthority, 2, + SECURITY_BUILTIN_DOMAIN_RID, dwRelativeID, 0, 0, 0, 0, 0, 0, + &pSid)) + { + CloseHandle(hToken); + return FALSE; + } + + if (!CheckTokenMembership(hToken, pSid, pIsMember)) + { + CloseHandle(hToken); + FreeSid(pSid); + + *pIsMember = FALSE; + return FALSE; + } + + CloseHandle(hToken); + FreeSid(pSid); + + return TRUE; +} + +// check if user is running in admin mode +bool IsUserAdministrator(void) +{ + BOOL isAdmin; + + // always an admin for XP and previous versions + if(!IsVistaOrLater()) + return true; + + // check if running in admin mode for Vista or newers + IsGroupMember(DOMAIN_ALIAS_RID_ADMINS, FALSE, &isAdmin); + return isAdmin; +} + //////////////////////////////////////////////////////////////////////////////////// // as I found that ShellExecuteEx don't take environment from current process // but gets it from registry, the only way I found to pass it to spawned process diff --git a/bazaar/SysExec/ShellLib.h b/bazaar/SysExec/ShellLib.h index 22b2bc646..490793b63 100644 --- a/bazaar/SysExec/ShellLib.h +++ b/bazaar/SysExec/ShellLib.h @@ -7,6 +7,9 @@ NAMESPACE_UPP #ifdef PLATFORM_WIN32 +// check if user is running in admin mode +bool IsUserAdministrator(void); + // executes a command via shell "runas" as admin user; // if wait is true, will wait for command end, otherwise executes it in background bool ShellExec(String const &args, VectorMap const &env, bool wait); diff --git a/bazaar/SysExec/SysExec.cpp b/bazaar/SysExec/SysExec.cpp index 609753fef..7510860d7 100644 --- a/bazaar/SysExec/SysExec.cpp +++ b/bazaar/SysExec/SysExec.cpp @@ -237,7 +237,10 @@ bool SysStartAdmin(String const &password, String const &command, String const & return SudoExec("root", password, command + " " + args, Environ, false); #else // on windows, no pass should be needed, it'll display the dialog automatically - return ShellExec(command + " " + args, Environ, false); + if(IsUserAdministrator()) + return SysStart(command, args, Environ); + else + return ShellExec(command + " " + args, Environ, false); #endif } @@ -258,7 +261,10 @@ bool SysExecAdmin(String const &password, String const &command, String const &a return SudoExec("root", password, command + " " + args, Environ, true); #else // on windows, no pass should be needed, it'll display the dialog automatically - return ShellExec(command + " " + args, Environ, true); + if(IsUserAdministrator()) + return SysExec(command, args, Environ); + else + return ShellExec(command + " " + args, Environ, true); #endif }