C++ 在win xp下,如何在运行时提升流程

C++ 在win xp下,如何在运行时提升流程,c++,windows,security,winapi,C++,Windows,Security,Winapi,我的应用程序需要在运行时执行一些特权操作。例如,当用户第一次运行我的应用程序时,我必须创建并格式化虚拟驱动器。我使用未记录的api formatex来完成匹配工作,但formatex需要管理员权限。如果操作系统是vista或更高版本,我可以用“COM提升名字对象”提示UAC对话框,它可以正常工作。但是在xp上,这种技术不适合,所以我使用模拟方法。 如果应用程序以受限用户身份运行,我将按如下方式进行格式化: CredUIPromptForCredentials() -> prompt to

我的应用程序需要在运行时执行一些特权操作。例如,当用户第一次运行我的应用程序时,我必须创建并格式化虚拟驱动器。我使用未记录的api formatex来完成匹配工作,但formatex需要管理员权限。如果操作系统是vista或更高版本,我可以用“COM提升名字对象”提示UAC对话框,它可以正常工作。但是在xp上,这种技术不适合,所以我使用模拟方法。 如果应用程序以受限用户身份运行,我将按如下方式进行格式化:

CredUIPromptForCredentials() -> prompt to get administrator credentials
LogonUser()
ImpersonateLoggedOnUser()
formatex()
RevertToSelf()
formatex仍然失败。。。 当然,以管理员身份运行我的应用程序是可行的,但这并不好,我的应用程序是按用户安装的,而不是按机器安装的,这应该在当前用户环境下工作,即使用户是 有限用户


如何在运行时正确提升我的应用程序以执行格式化工作?任何帮助?

一种可能的解决方案是使用提升的权限和一些命令行参数重新执行应用程序,这些参数将指示执行实际的格式设置

示例代码:

if (!IsUserAdmin()) {
     RunAsAdmin(hwnd, exeName, "--do-format");
} else {
     DoFormat();
}
...

BOOL RunAsAdmin(HWND hWnd, LPCTSTR lpFile, LPCTSTR lpParameters)
{
    SHELLEXECUTEINFO sei;
    ZeroMemory(&sei, sizeof(sei));

    sei.cbSize          = sizeof(SHELLEXECUTEINFOW);
    sei.hwnd            = hWnd;
    sei.fMask           = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
    sei.lpVerb          = _TEXT("runas");
    sei.lpFile          = lpFile;
    sei.lpParameters    = lpParameters;
    sei.nShow           = SW_SHOWNORMAL;

    if (!ShellExecuteEx(&sei)) {
            return FALSE;
    }
    return TRUE;
}

BOOL IsUserAdmin(VOID)
{
    BOOL b;
    SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };
    PSID AdministratorsGroup;
    b = AllocateAndInitializeSid(
            &NtAuthority,
            2,
            SECURITY_BUILTIN_DOMAIN_RID,
            DOMAIN_ALIAS_RID_ADMINS,
            0, 0, 0, 0, 0, 0,
            &AdministratorsGroup);
    if (b) {
            if (!CheckTokenMembership( NULL, AdministratorsGroup, &b)) {
                    b = FALSE;
            }
            FreeSid(AdministratorsGroup);
    }

    return b;
}

这就是我在我的应用程序中所做的(尽管没有IsUserAdmin()检查-我让Win32 API函数向我报告所需的
ERROR\u ELEVATION\u
),它工作得非常好。感谢dimitri的回答。我最终使用了dimitri提出的方法,但有点不同。我使用CredUIPromptForCredentials()->LogonUser()->IsUserAdmin(我的函数)->CreateProcessWithLogonW循环来确保管理员凭据。现在一切都很顺利。