Я работаю со службой, которая должна олицетворять вошедшего в систему пользователя.
Мой код до сих пор с базовой обработкой ошибок:
// 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). Если службе, которая выдает себя за пользователя, необходимо прочитать или записать файл реестра пользователя, используйте этот дескриптор вместо HKEY_CURRENT_USER. Не закрывайте дескриптор hProfile. Вместо этого передайте его функции UnloadUserProfile.
Если я использую свой код, как сейчас, то он работает. Однако это немного странно, потому что сначала я должен олицетворять вошедшего в систему пользователя, а затем завершать олицетворение, чтобы загрузить профиль пользователя. Если я не завершу олицетворение, то LoadUserProfile завершится с ошибкой 5 (отказано в доступе). И после того, как LoadUserProfile преуспел, я должен снова выдать себя за пользователя?
Так вот у меня вопрос, так и должно быть, или я что-то не так делаю? Другой вопрос заключается в том, что если LoadUserProfile преуспеет, я смогу использовать hProfile в качестве дескриптора для реестра зарегистрированных пользователей. Вопрос как? Потому что для использования RegOpenKeyEy и RegSetValueEx мне нужно передать HKEY, а не HANDLE. Итак, как я могу использовать эту ручку?
Благодарить!