Здравствуйте, есть небольшая проблемка.
Есть три бинарника: инсталлятор(И), рабочая программа(РП), служебная утилита(СУ).
1. Инсталлер устанавливает РП и СУ в рабочую папку, естессно работает с повышенными привилегиями.
2. По окончании работы запускает РП с пониженными привилениями (CreateRestrictedToken — CreateProcessAsUser — medium level). В основном для того, чтобы работад драг-н-дроп. Ну и вообще, не нужны программе права админа.
3. Запущенной рабочей программе периодически требуется выполнять функции с повышенными привилегиями, для чего она вызывает СУ через ShellExecuteEx ("runas").
4. Служебная утилита может выполнять различные функции, некоторые из которых не требуют повышенных прав, поэтому в манифесте не указывается прямо, что она требует админских прав. Т.е. РП может иногда запускать СУ и просто, без runas.
Понижение привилегий РП инсталлером (CreateRestrictedToken — CreateProcessAsUser) добавилось недавно, и тут же выяснилось, что после этих изменений РП не может запустить СУ с повышенными привилегиями. Т.е. код ShellExecuteEx ("runas") не инициирует UAC и СУ не получает админстких прав, и естессно отваливается.
Подскажите плз, как решить проблему? Код запуска РП ниже. При этом, я пробовал запускать РП через Process Explorer — Run as limited user. Эффект тот же, хотя в процесс эксплорер запускает процесс с low interrity level (наш инсталлер запускает с medium level).
ATL используется в основном для снижения писанины, в принципе это тот же WINAPI
BOOL CreateLowProcess (wchar_t * pProcessPathWithParams, bool bMediumLevelNotLow /*= true*/, bool bWait /*= false*/, DWORD * pdwRetCode /*= NULL*/)
{
const wchar_t * pIntegritySid = (bMediumLevelNotLow ? L"S-1-16-8192" : L"S-1-16-4096");
PSID pSid = NULL;
if (!ConvertStringSidToSid(pIntegritySid, &pSid))
return false;
ATL::CSid sid (*(SID *)pSid);
LocalFree (pSid);
ATL::CAccessToken hToken;
bool ret = hToken.GetProcessToken (TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY);
if (!ret)
return false;
ATL::CTokenGroups restrSids;
ATL::CTokenGroups disSids;
disSids.Add (ATL::Sids::Admins (), 0);
ATL::CTokenPrivileges delPrivs;
ret = hToken.GetPrivileges (&delPrivs);
if (!ret)
return false;
delPrivs.Delete (SE_CHANGE_NOTIFY_NAME);
ATL::CAccessToken hNewToken;
ret = hToken.CreateRestrictedToken (&hNewToken, disSids, restrSids, delPrivs);
if (!ret)
return false;
TOKEN_MANDATORY_LABEL tml = {};
tml.Label.Attributes = SE_GROUP_INTEGRITY;
tml.Label.Sid = (PSID)sid.GetPSID ();
ret = SetTokenInformation (hNewToken.GetHandle (), TokenIntegrityLevel, &tml, sizeof (TOKEN_MANDATORY_LABEL) + GetLengthSid ((PSID)sid.GetPSID ()));
if (!ret)
return false;
PROCESS_INFORMATION pi = {};
STARTUPINFO si = {};
si.cb = sizeof (STARTUPINFO);
ret = CreateProcessAsUser (hNewToken.GetHandle (), NULL, pProcessPathWithParams, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (ret && bWait)
{
::WaitForSingleObject (pi.hProcess, INFINITE);
if (pdwRetCode != NULL)
::GetExitCodeProcess (pi.hProcess, pdwRetCode);
}
if (pi.hProcess != NULL)
CloseHandle (pi.hProcess);
if (pi.hThread != NULL)
CloseHandle(pi.hThread);
return ret;
}
Спасибо.
Та же проблема. Вам не удалось её решить?