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

tru*_*ong 3 c++ windows winapi

我正在开发一个需要正确检测 Windows 上所有使用的驱动器号的应用程序。我用这个GetLogicalDrives()函数来实现这个目的。除非用户使用提升的权限启动我的应用程序(即,使用属于“管理员”组的帐户登录并通过选择“以管理员身份运行”选项启动我的应用程序),否则此功能工作正常。在这种情况下,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- Windows 中的凭据

这个问题有任何程序化的解决方法吗?我尝试在“非提升”会话中重新启动我的应用程序,但不知道如何(或者是否可能)。我已经尝试过使用受限令牌(使用CreateRestrictedTokenwithDISABLE_MAX_PRIVILEGE选项)重新启动我的应用程序,希望 Windows 能够以某种方式发现它现在可以在“非提升”会话中重新启动我的应用程序,但它不起作用。

RbM*_*bMm 5

为此,您可以临时模拟链接令牌 - 因此获取自己的链接令牌,如果存在,将其设置为线程,调用GetLogicalDrives()并返回进程令牌(链接令牌具有SECURITY_IMPERSONATION_LEVEL==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);

}
Run Code Online (Sandbox Code Playgroud)

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