我正在处理一个需要在Windows上正确检测所有使用的驱动器号的应用程序。 我使用GetLogicalDrives()
函数。 此function工作得很好,除非用户使用提升的权限启动我的应用程序(即用户使用属于“pipe理员”组login的用户,并通过select“以pipe理员身份运行”选项启动我的应用程序)。 在这种情况下, GetLogicalDrives()
无法检测到计算机上映射的networking驱动器。
看来问题的根本原因是在这种情况下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-凭据,在窗口
有没有针对这个问题的程序化解决方法? 我尝试在“非升级”会话中重新启动我的应用程序,但不知道如何(或甚至可能)。 我已经试过的是用限制令牌重新启动我的应用程序(使用带有DISABLE_MAX_PRIVILEGE
选项的CreateRestrictedToken
),希望Windows能以某种方式发现它现在可以在“非升级”会话中重新启动我的应用程序,但是它不起作用。
为此,您可以使用链接标记进行临时模拟 – 因此,获取自己的链接标记(如果存在),将其设置为线程,调用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); }
如果没有错误( GetLogicalDrivesEx
返回NOERROR
), Drives
是未升级会话的逻辑驱动器,当驱动器0 – 对于提升(如果当然你运行提升)