在使用高架特权运行时,如何正确检测网络驱动器

How to correctly detect Network drive when running with elevated privileges

本文关键字:何正确 检测 网络 驱动器 运行时 高架 特权      更新时间:2023-10-16

我正在处理一个需要正确检测Windows上所有使用过的驱动器字母的应用程序。我为此使用GetLogicalDrives()函数。此功能正常工作,除了用户启动具有提升特权的应用程序时(即,用帐户登录的用户属于"管理员"组,并通过选择"作为管理员"选项来启动我的应用程序。在这种情况下,GetLogicalDrives()无法检测到机器上的映射网络驱动器。

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

https://support.microsoft.com/en-us/help/3035277/mapped-drives-drives-are-not-available-from-an-ey-man-ey-eyvated-prompt-when-uac-uac-uac-uac-is-is-is-is-in-conconconcured--for-credentials-in-windows

这个问题有任何程序化解决方法吗?我试图在"非高级"会话中重新启动我的应用程序,但不知道如何(或是否可能)。我已经尝试的是使用受限的令牌重新启动我的应用程序(使用DISABLE_MAX_PRIVILEGE带有CC_4选项),希望Windows可以以某种方式确定它现在可以在"非高级"会话中重新启动我的应用程序,但它不起作用。<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<</p>

为此,您可以暂时模仿链接的令牌 - 因此,如果存在,请获得自己的链接令牌(如果存在),将其设置为线程,调用GetLogicalDrives()并返回process token(链接的token token拥有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);
}

如果没有错误(GetLogicalDrivesEx返回NOERRORDrives是逻辑驱动器,用于未提升的会话,当drives0-升级时(如果您以升高为单位)