Как правильно олицетворять пользователя из сервиса?

работает сервис, который должен выдавать себя за зарегистрированного пользователя.

Мой код до сих пор, с основной обработкой ошибок:

 // get the active console session ID of the logged on user
if ( !WTSQueryUserToken( WTSGetActiveConsoleSessionId(), &hToken ) )
{
    ShowErrorText( "WTSQueryUserToken failed.", GetLastError( ), true );
    return;
}

HANDLE hDuplicated;

// duplicate the token
if ( !DuplicateToken( hToken, SecurityImpersonation, &hDuplicated ) )
{
    ShowErrorText( "DuplicateToken failed.", GetLastError( ), true );
}
else 
{
    ShowErrorText( "DuplicateToken succeeded.", 0, true );
}

// impersonate the logged on user
if ( !ImpersonateLoggedOnUser( hToken ) )
{
    ShowErrorText( "ImpersonateLoggedOnUser failed.", GetLastError(), true );
    return;
}

// retrieve the DC name 
if ( !GetPrimaryDC( DC ) )
{
    ShowErrorText( "GetPrimaryDC failed.", 0, true );
}
PROFILEINFO lpProfileInfo;

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

// get type of profile. roaming, mandatory or temporary
int ret = GetTypeOfProfile();
if ( ret == 2 )
{
    // if roaming profile get the path of it
    if ( !GetRoamingProfilePath( DC, CurrentUser, RoamingProfilePath ) )
    {
        ShowErrorText( "Failed to retrieve roaming profile path.", GetLastError(), true );
    }
}
if ( RevertToSelf( ) )
{
    ShowErrorText( "Impersonation ended successfully.", 0, true );
}

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

   //do some stuff


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

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

По данным MSDN:

Когда пользователь входит в систему в интерактивном режиме, система автоматически загружает пользователяпрофиль. Если служба или приложение олицетворяет пользователя, система не загружает пользователя.профиль. Поэтому служба или приложение должны загружать пользователяс профилем LoadUserProfile.

Службы и приложения, которые вызывают LoadUserProfile, должны проверить, есть ли у пользователя профиль в роуминге. Если у пользователя есть перемещаемый профиль, укажите его путь в качестве члена lpProfilePath в PROFILEINFO. Чтобы получить пользователяПуть к перемещаемому профилю, вы можете вызвать функцию NetUserGetInfo, указав уровень информации 3 или 4.

При успешном возвращении член hProfile в PROFILEINFO является дескриптором ключа реестра, открытым для корня пользователя.улей. Он был открыт с полным доступом (KEY_ALL_ACCESS). Если служба, которая олицетворяет пользователя, должна читать или писать пользователю 's файл реестра, используйте этот дескриптор вместо HKEY_CURRENT_USER. Не закрывайте ручку hProfile. Вместо этого передайте его в функцию UnloadUserProfile.

Если я использую свой код, как сейчас, то он работает. Однако это немного странно, потому что сначала я должен выдать себя за зарегистрированного пользователя, а затем закончить олицетворение, чтобы загрузить профиль пользователя. Если я неПосле завершения олицетворения LoadUserProfile завершится с ошибкой 5 (доступ запрещен). И после успешного завершения LoadUserProfile я должен снова выдать себя за пользователя?

Итак, мой вопрос, это должно быть сделано таким образом, или я делаю что-то не так? Другой вопрос заключается в том, что если LoadUserProfile преуспел, я мог бы использовать hProfile в качестве дескриптора для реестра пользователей, вошедших в систему. Вопрос как? Потому что для использования RegOpenKeyEy и RegSetValueEx мне нужно передать HKEY, а не HANDLE. Так как я могу использовать эту ручку?

Поблагодарить!

Ответы на вопрос(1)

Ваш ответ на вопрос