ログオンしているユーザーを偽装する必要があるサービスを使用しています。
これまでの私のコード、基本的なエラー処理:
// 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 を呼び出すサービスとアプリケーションは、ユーザーがローミング プロファイルを持っているかどうかを確認する必要があります。ユーザーがローミング プロファイルを持っている場合は、そのパスを PROFILEINFO の lpProfilePath メンバーとして指定します。ユーザーのローミング プロファイル パスを取得するには、情報レベル 3 または 4 を指定して NetUserGetInfo 関数を呼び出します。
正常に返されると、PROFILEINFO の hProfile メンバーは、ユーザーのハイブのルートに対して開かれたレジストリ キー ハンドルになります。フルアクセス (KEY_ALL_ACCESS) で開かれています。ユーザーを偽装しているサービスがユーザーのレジストリ ファイルの読み取りまたは書き込みを行う必要がある場合は、HKEY_CURRENT_USER の代わりにこのハンドルを使用します。hProfile ハンドルを閉じないでください。代わりに、UnloadUserProfile 関数に渡します。
現在のコードをそのまま使用すると、機能します。ただし、最初にログオンしているユーザーを偽装し、次に偽装を終了して、ユーザー プロファイルを読み込む必要があるため、少し奇妙です。偽装を終了しないと、LoadUserProfile はエラー 5 (アクセスが拒否されました) で失敗します。LoadUserProfile が成功した後、ユーザーを再度偽装する必要がありますか?
だから私の質問は、これはこのように行われることを意図したものですか、それとも私は何か間違ったことをしていますか? もう 1 つの質問は、LoadUserProfile が成功した場合、ログオンしているユーザーのレジストリへのハンドルとして hProfile を使用できるということです。質問はどうですか?RegOpenKeyEy と RegSetValueEx を使用するには、HANDLE ではなく HKEY を渡す必要があるためです。では、このハンドルをどのように使用できますか?
感謝!