システムレベルのWindowsサービスで以下のコードを実行しています。 CreateEnvironmentBlock()とCreateProcessAsUser()をコードに追加すると、そのコードは機能します。しかし、私は "LoadUserProfile()"を使用して、それは "アクセス拒否"を意味する必要がありますエラー5で失敗します。不足しているものを確認してください。私が望むのは、このシステムサービスからユーザーレベルのレジストリ値を取得することです。コード内のコメントは別の方法ですが、ユーザーレベルのレジストリ値を取得することもできませんでした。システムサービスで実行されているこのコードでLoadUserProfile()がエラー5で "失敗アクセス"に失敗しますか?
void GetUserRegistry()
{
#ifdef Q_OS_WIN
DWORD lastError = 0;
DWORD sessionId = WTSGetActiveConsoleSessionId();
qInfo() << "Session ID = " << sessionId;
wchar_t* ppUserName[100];
DWORD sizeOfUserName;
WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, ppUserName, &sizeOfUserName);
qInfo() << "Windows User Name = " << QString::fromWCharArray(*ppUserName);
std::wstring strValueOfBinDir = L"Unknown Value";
// LONG regOpenResult = ERROR_SUCCESS;
HANDLE hUserToken = NULL;
HANDLE hFakeToken = NULL;
if (WTSQueryUserToken(sessionId, &hUserToken))
{
if (DuplicateTokenEx(hUserToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &hFakeToken) == TRUE)
{
qInfo() << "Before ImpersonateLoggedOnUser()......";
if (ImpersonateLoggedOnUser(hFakeToken))
{
HKEY hKey;
// regOpenResult = RegOpenCurrentUser(KEY_READ, &hKey);
PROFILEINFO profileInfo;
ZeroMemory(&profileInfo, sizeof(PROFILEINFO));
profileInfo.dwSize = sizeof(PROFILEINFO);
profileInfo.lpUserName = *ppUserName;
// wchar_t roamingPath[] = L"C:\\Users\\Finix"; // L"C:\\Users\\Finix\\AppData\\Roaming";
// profileInfo.lpProfilePath = roamingPath;
if (LoadUserProfile(hFakeToken, &profileInfo))
{
HANDLE hProfile = profileInfo.hProfile;
RegOpenKeyEx(HKEY_CURRENT_USER,
TEXT("Software\\Baidu\\BaiduYunGuanjia"),
0,
KEY_READ,
&hKey);
GetStringRegKey(hKey, TEXT("installDir"), strValueOfBinDir, TEXT("Unknown"));
UnloadUserProfile(hFakeToken, hProfile);
}
else
{
lastError = GetLastError();
}
RevertToSelf();
}
else
{
qCritical() << "Failed to ImpersonateLoggedOnUser...";
}
CloseHandle(hFakeToken);
}
else
{
qCritical() << "Failed to call DuplicateTokenEx...";
}
CloseHandle(hUserToken);
}
else
{
qCritical() << "Failed to get the user token of session " << sessionId;
}
if (lastError)
{
qCritical() << "Failed to LoadUserProfile(), The ERROR is " << lastError;
}
// if (regOpenResult != ERROR_SUCCESS)
// {
// qCritical() << "Failed to call RegOpenCurrentUser(), Error is " << regOpenResult;
// }
qInfo() << "The value of Registry is " << QString::fromWCharArray(strValueOfBinDir.c_str());
#endif
}
がシンプルであるためには、呼び出しは次のとおりです。()+ WTSQueryUserToken()+ DuplicateTokenEx()+ ImpersonateLoggedOnUser()+ LoadUserProfile()WTSGetActiveConsoleSessionId。 LoadUserProfile()がエラー5で失敗するのはなぜですか? LoadUserProfile()を呼び出す前に、何をする必要がありますか?私は上記のコードを示しています。私は何か見落としてますか? – Finix
文字配列 'wchar_t * ppUserName [100]'へのポインタを宣言しています。 'wchar_t ppUserName [100];'に変更する必要がありますが、他のエラーがあるかもしれません。 –
@BarmakShemirani上記のコードは正しいです。 WTSQuerySessionInformation()の4番目の引数は "LPWSTR *"なので、それはpointorまたはpointorです。そして、私が述べたように、LoadUserProfile()を "CreateEnvironmentBlock()+ CreateProcessAsUser()"に変更すると、このプログラムが動作します。それは残りの部分がすべて正常であることを意味しますが、LoadUserProfile()の呼び出しは失敗します。 – Finix