Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
460 views
in Technique[技术] by (71.8m points)

c++ - How to correctly detect Network drive when running with elevated privileges

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.

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:

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

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 CreateRestrictedTokenwith 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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);

}

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)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...