如何使用提升的权限运行时正确检测网络驱动器

时间:2017-03-13 15:36:31

标签: c++ windows winapi

我正在开发一个需要正确检测Windows上所有已用驱动器号的应用程序。我使用GetLogicalDrives()函数。当用户使用提升的权限启动我的应用程序时,此功能可正常工作(即,使用帐户登录的用户属于'管理员'组并通过选择&#34启动我的应用程序;以管理员身份运行&#34 ; 选项)。在这种情况下,GetLogicalDrives()无法检测到计算机上的映射网络驱动器。

问题的根本原因似乎是在这种情况下,Windows并行运行2个用户会话。我的应用程序运行在"提升的权限"会话,而驱动器映射在"非提升"会话:

https://support.microsoft.com/en-us/help/3035277/mapped-drives-are-not-available-from-an-elevated-prompt-when-uac-is-configured-to-prompt-for-credentials-in-windows

此问题是否有任何编程解决方法?我试图重新启动我的应用程序" non-elevated"会议,但不知道如何(或甚至可能)。我尝试过的是使用限制令牌重新启动我的应用程序(使用带有CreateRestrictedToken选项的DISABLE_MAX_PRIVILEGE),希望Windows能够以某种方式弄清楚它现在可以重新启动我的应用程序。升高"会话,但它没有用。

1 个答案:

答案 0 :(得分:4)

为此您可以临时模拟链接令牌 - 因此获取自己的链接令牌(如果存在),将其设置为线程,调用GetLogicalDrives()并返回进程令牌(链接令牌具有{{3} } == SecurityIdentification因此可以非常限制地使用

#define BOOL_TO_ERR(b) ((b) ? NOERROR : GetLastError())

ULONG GetLogicalDrivesEx(PULONG pDrives)
{
    HANDLE hToken;

    ULONG err = BOOL_TO_ERR(OpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &hToken));

    if (err != NOERROR)
    {
        return err;
    }

    union {
        TOKEN_ELEVATION_TYPE tet;
        TOKEN_LINKED_TOKEN tlt;
    };

    ULONG rcb;

    err = BOOL_TO_ERR(GetTokenInformation(hToken, TokenElevationType, &tet, sizeof(tet), &rcb));

    if (err == NOERROR)
    {
        if (tet == TokenElevationTypeFull)
        {
            err = BOOL_TO_ERR(GetTokenInformation(hToken, TokenLinkedToken, &tlt, sizeof(tlt), &rcb));

            if (err == NOERROR)
            {
                if (NOERROR == (err = BOOL_TO_ERR(SetThreadToken(0, tlt.LinkedToken))))
                {
                    err = (rcb = GetLogicalDrives()) ? NOERROR : GetLastError();
                    SetThreadToken(0, 0);
                }

                CloseHandle(tlt.LinkedToken);
            }
        }
        else
        {
            err = (rcb = GetLogicalDrives()) ? NOERROR : GetLastError();
        }
    }

    *pDrives = rcb;
    return err;
}

void test()
{
    ULONG Drives, Drives0 = GetLogicalDrives();
    GetLogicalDrivesEx(&Drives);
    WCHAR sz[32];
    swprintf(sz, L"%08x %08x", Drives0, Drives);
    MessageBoxW(0, sz, L"", MB_OK);

}

如果没有错误(GetLogicalDrivesEx返回NOERROR),则Drives是未提升会话的逻辑驱动器,而当驱动器0 - 用于提升(当然,如果您以提升方式运行)