问题描述
我正在开发一个需要正确检测Windows上所有已用驱动器号的应用程序。我为此使用 GetLogicalDrives()
函数。除了用户以提升的特权启动我的应用程序(即使用帐户登录的用户属于管理员组并通过选择以管理员身份运行选项启动我的应用程序)外,此功能非常有效。在这种情况下, GetLogicalDrives()
无法检测到计算机上的映射网络驱动器。
I am working on an application that needs to correctly detect all used drive letters on Windows. And I use the GetLogicalDrives()
function for that. This function works just fine excepts when users launch my application with elevated privileges (i.e., the user logged in with an account belongs to 'Administrators' group and launch my application by choosing "Run as administrator" option). In this case, GetLogicalDrives()
fails to detect mapped network drives on the machine.
问题的原因是在这种情况下Windows并行运行2个用户会话。我的应用程序在高特权会话中运行,而驱动器在非高特权会话中映射:
It seems that the root cause of the problem is that in this scenario Windows runs 2 user sessions in parallel. My application runs in the "elevated privileges" session, while the drive is mapped in the "non-elevated" session:
是否存在针对此问题的编程解决方法?我尝试在非高架会话中重新启动我的应用程序,但不知道如何(甚至可能)。我已经尝试过使用受限令牌重新启动应用程序(使用 CreateRestrictedToken
和 DISABLE_MAX_PRIVILEGE
选项),希望Windows能够莫名其妙地发现它现在可以在非高架会话中重新启动我的应用程序,但是它不起作用。
Is there any programmatic workaround for this problem? I tried to relaunch my application in the "non-elevated" session, but don't know how (or if it is even possible). What I tried already is relaunching my application with a restricted token (using CreateRestrictedToken
with DISABLE_MAX_PRIVILEGE
option), hoping that Windows will somehow figure out that it could now relaunch my application in a "non-elevated" session, but it did not work.
推荐答案
为此,您可以临时模拟链接令牌-因此,获取自己的链接令牌(如果存在),将其设置为线程,调用 GetLogicalDrives()
并返回到处理令牌(链接的令牌具有 == SecurityIdentification
结果可以非常严格地使用它)
for this you can temporary impersonate with Linked token - so get own linked token, if it exist, set it to thread, call GetLogicalDrives()
and return to process token (Linked token have SECURITY_IMPERSONATION_LEVEL
== SecurityIdentification
as result it can be used very restrict )
#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
返回无错误
),驱动器
是用于非提升会话的逻辑驱动器,当Drives0-表示高架(如果您当然以高架运行)
if no errors (GetLogicalDrivesEx
return NOERROR
) the Drives
is logical drives for not-elevated session, when Drives0 - for elevated (if of course you run as elevated)
这篇关于使用提升的特权运行时如何正确检测网络驱动器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!