Как правильно олицетворять пользователя из сервиса?
работает сервис, который должен выдавать себя за зарегистрированного пользователя.
Мой код до сих пор, с основной обработкой ошибок:
// 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. Так как я могу использовать эту ручку?
Поблагодарить!