How to impersonate a user from a service correctly?

橙三吉。 提交于 2019-12-01 06:15:57

You don't need to call ImpersonateLoggedOnUser() since you are passing the user's token to LoadUserProfile(). Call ImpersonateLoggedOnUser() only if you need to call APIs that do not allow you to pass a user token to them.

If you read the rest of the LoadUserProfile() documentation, it says:

The calling process must have the SE_RESTORE_NAME and SE_BACKUP_NAME privileges.

By impersonating the user you are trying to load a profile for, you are likely losing those privileges. So don't impersonate the user.

Update: Try something like this:

// get the active console session ID of the logged on user
DWORD dwSessionID = WTSGetActiveConsoleSessionId();
if ( dwSessionID == 0xFFFFFFFF )
{
    ShowErrorText( "WTSGetActiveConsoleSessionId failed.", GetLastError( ), true );
    return;
}

if ( !WTSQueryUserToken( dwSessionID, &hToken ) )
{
    ShowErrorText( "WTSQueryUserToken failed.", GetLastError( ), true );
    return;
}

// duplicate the token
HANDLE hDuplicated = NULL;
if ( !DuplicateToken( hToken, SecurityImpersonation, &hDuplicated ) )
{
    ShowErrorText( "DuplicateToken failed.", GetLastError( ), true );
    CloseHandle( hToken );
    return;
}

// retrieve the DC name 
if ( !GetPrimaryDC( DC ) )
{
    ShowErrorText( "GetPrimaryDC failed.", 0, true );
    CloseHandle( hDuplicated );
    CloseHandle( hToken );
    return;
}

PROFILEINFO lpProfileInfo;
ZeroMemory( &lpProfileInfo, sizeof( PROFILEINFO ) );
lpProfileInfo.dwSize = sizeof( PROFILEINFO );
lpProfileInfo.lpUserName = CurrentUser;

// get type of profile. roaming, mandatory or temporary
USER_INFO_4 *UserInfo = NULL;
int ret = GetTypeOfProfile();
if ( ret == 2 )
{
    // if roaming profile get the path of it
    if ( NetUserGetInfo( DC, CurrentUser, 4, (LPBYTE*)&UserInfo) != NERR_Success )
    {
        ShowErrorText( "NetUserGetInfo failed.", 0, true );
        CloseHandle( hDuplicated );
        CloseHandle( hToken );
        return;
    }

    lpProfileInfo.lpProfilePath = UserInfo->usri3_profile;
}

if ( !LoadUserProfile( hDuplicated, &lpProfileInfo ) )
{
    ShowErrorText( "LoadUserProfile failed.", GetLastError(), true );
    if ( UserInfo )
        NetApiBufferFree(UserInfo);
    CloseHandle( hDuplicated );
    CloseHandle( hToken );
    return;
}

if ( UserInfo )
    NetApiBufferFree(UserInfo);

ShowErrorText( "LoadUserProfile succeeded.", 0, true );

//do some stuff

if ( !UnloadUserProfile( hDuplicated, lpProfileInfo.hProfile ) )
{
    ShowErrorText( "UnloadUserProfile failed.", GetLastError( ), true );
}
else
{
    ShowErrorText( "UnloadUserProfile succeeded.", 0, true );
}

CloseHandle( hDuplicated );
CloseHandle( hToken );

As for the Registry, the hProfile handle is the opened HKEY for the user's HKEY_CURRENT_USER tree. Simpy type-cast it from HANDLE to HKEY when passing it to Registry API functions. It is already opened, so you do not need to call RegOpenKeyEx() to open that same key again, but you can use it as the root key when creating/opening subkeys, or reading/writing values in the root key.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!