2015-08-05 3 views
5

Мое приложение должно записывать файл в \ ProgramData, который можно защитить. Это происходит только один раз после установки.Есть ли вызов API для запроса пользователя для повышения UAC?

Есть ли функция API, которая принимает информацию ACL и запрашивает у пользователя авторизацию приложения для доступа к файлу? Другими словами, приложение предложит Windows запросить у пользователя подтверждение и авторизацию. Это должно произойти в интерактивном режиме и разрешить приложению возобновить выполнение после авторизации доступа к файлу. Приложение работает как стандартный пользователь, не требует прав администратора.

Файл открывается с помощью CreateFile().

Редактировать: Есть тонкая разница между моим запросом и другими словами, которые дублируются. Я прошу разрешения на доступ к одному конкретному объекту, файлу. Другие просят возвысить привилегии всего процесса. Во всяком случае, я благодарен за все ответы, которые включают решение.

+0

Но ... не некоторая комбинация GetNamedSecurityInfo, AllocateAndInitializeSid, SetEntriesInAcl, SetNamedSecurityInfo и т.д., что позволило бы мне доступ только этот один файл? Я не хочу, чтобы весь процесс запускался как Admin. CreateFile() ссылается на вещь SECURITY_ATTRIBUTES. Кажется, что я мог бы получить объект SECURITY_ATTRIBUTES, передать его CreateFile и presto! – Pierre

+0

В документации '' CreateFile() '(https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx):" * Указатель на структуру SECURITY_ATTRIBUTES, которая содержит два отдельных, но связанных с данными: необязательный дескриптор безопасности и логическое значение, определяющее, может ли возвращенный дескриптор наследоваться дочерними процессами ... ** CreateFile игнорирует член lpSecurityDescriptor при открытии существующего файла ** или устройства, но продолжает использовать член bInheritHandle. * « –

+0

Нет никакой разницы. Это обман много раз. Если вы не согласны, вы все равно не понимаете ОАК. Повторное открытие избирателей явно не понимает этого. –

ответ

11

Если вы не хотите, чтобы поднять все приложение, у вас есть несколько вариантов:

  1. икру отдельного возвышенный процесс только для доступа к файлу. Используйте ShellExecute/Ex() с глаголом runas или CreateProcessElevated(), чтобы запустить вторую копию вашего приложения или другое вспомогательное приложение с параметрами командной строки, чтобы сообщить, что делать. Основной процесс может ждать выхода второго процесса, если это необходимо.

  2. создать COM-объект для доступа к файлу, а затем использовать COM Elevation Moniker для запуска COM-объекта в повышенном состоянии.

  3. приглашение пользователю ввести учетные данные с помощью CredUIPromptForCredentials() или CredUIPromptForWindowsCredentials() (см Asking the User for Credentials для более подробной информации), а затем войти на указанный счет, используя LogonUser(), чтобы получить маркер, выдавать себя за этот маркер с помощью ImpersonateLoggedOnUser(), получить доступ к файлу по мере необходимости, а затем остановить выдавая себя за использование RevertToSelf() и закройте токен CloseHandle().

+0

# 3 очень изобретательно, но если я правильно понимаю, приложение должно знать пароль администратора? Я боюсь, что большинство пользователей не согласится на это. Я попробую # 2. (Мой COM рудиментарный, это займет некоторое время). Спасибо. – Pierre

+0

# 1 проще реализовать, так как все может оставаться в одном exe. Для # 3 пользователь должен знать пароль администратора, так как в диалоговом окне будет запрашиваться имя пользователя и пароль, которое ваше приложение затем будет использовать для входа в эту учетную запись. Не сильно отличается от повышения UAC, предлагая стандартного пользователя для учетных данных администратора. Если администратор запускает ваше приложение, они, вероятно, уже имеют доступ к файлу. Итак, вы должны попытаться получить доступ к файлу один раз, а затем попросить учетные данные и повторите попытку, только если вы получите код ошибки, например, «ERROR_ACCESS_DENIED» или «ERROR_ELEVATION_REQUIRED». –

+0

Думаю, я попробую # 1, потому что это самый простой. Огромное спасибо. – Pierre

4

Процессы могут запускаться только с повышенным токеном, они не могут получить его после факта. Таким образом, вы можете либо заново запустить приложение с помощью аргумента командной строки, рассказывая ему, что делать (простое решение), либо реализовать COM-сервер внепроцессного кода, который вы можете создать над ним и передать ему инструкции (сложнее).

Третьим решением является использование встроенной поддержки UAC интерфейса IFileOperation, но это не позволяет вам читать/писать, копировать. Таким образом, вы можете сделать копию файла, который вам нужно изменить, изменить копию, а затем использовать IFileOperation, чтобы скопировать временный текст над оригиналом.

4

Благодаря @Remy для предложения ShellExecuteEx, вот некоторые подробности о грязных деталях. Обратите внимание на использование «cmd» и двойной команды, поэтому пользователю нужно ответить только один раз. Кроме того, [1] должен ждать завершения процесса, иначе вы могли бы создать файл перед его удалением, а [2] не дождались процесса, если он не сработал.

// delete file with Admin privilege 
// 'file_name' is path of file to be deleted 
SHELLEXECUTEINFO shex; 
char param[512]; 
char *cmd = "/C \"attrib -H \"%s\" && del /F /Q \"%s\"\""; // double command 

_snprintf(param, sizeof(param), cmd, file_name, file_name); 
ZeroMemory(&shex, sizeof(shex)); 
shex.cbSize = sizeof(shex); 
shex.lpVerb = "runas"; // runas, open 
shex.lpFile = "cmd"; // not 'del' 
shex.lpParameters = param; 
shex.nShow = SW_HIDE; 
shex.fMask = SEE_MASK_NOCLOSEPROCESS; 
BOOL retshx = ShellExecuteEx(&shex); 
// wait otherwise could return before completed 
if(retshx) 
{ time_t st = clock(); 
    DWORD exitCode; 
    do 
    { if(!GetExitCodeProcess(shex.hProcess, &exitCode)) 
      break; 
     if(clock() - st > CLOCKS_PER_SEC * 5)  // max 5 seconds 
      break; 
    } while(exitCode != STATUS_WAIT_0); // STILL_ACTIVE 
    CloseHandle(shex.hProcess); 
} 
+0

Почему «-1»? Для этого кода потребовалось несколько часов. Я хотел бы, чтобы кто-то написал что-то подобное, когда я искал ответ. Надеюсь, это поможет тем, у кого есть такая же проблема. Как «-1» помогает сообществу? – Pierre