これはシステムサービスです。 ImpersonateLoggedOnUser()
の後、私はCreateProcessAsUser()
を正常に呼び出すことができます。しかし、それは1つのWindows APIを呼び出すことができませんSetDisplayConfig()
。エラーは5です(ERROR_ACCESS_DENIED)。以下のコードをご覧ください。ImpersonateLoggedOnUser()の後、なぜWindows API SetDisplayConfig()を呼び出すことができませんでしたか?
// This function is called in a System service.
void SetDisplayToExtendMode()
{
DWORD dwSessionId = WTSGetActiveConsoleSessionId();
if (dwSessionId == 0xFFFFFFFF)
{
qCritical() << "Failed to get active console session Id when setting extend mode for display!";
}
HANDLE hUserToken = NULL;
if (WTSQueryUserToken(dwSessionId, &hUserToken) == FALSE)
{
qCritical() << "Failed to query user token when setting extend mode for display!";
}
HANDLE hTheToken = NULL;
if (DuplicateTokenEx(hUserToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &hTheToken) == TRUE)
{
if (ImpersonateLoggedOnUser(hTheToken) == TRUE)
{
DWORD dwCreationFlags = HIGH_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
LPVOID pEnv = NULL;
if (CreateEnvironmentBlock(&pEnv, hTheToken, TRUE) == TRUE)
{
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
}
// Way 1: Call Windows API directly.
// Fail. Error code is ERROR_ACCESS_DENIED
LONG errCode = SetDisplayConfig(0, NULL, 0, NULL, SDC_TOPOLOGY_EXTEND | SDC_APPLY);
if (errCode != ERROR_SUCCESS)
{
qCritical() << "Failed to set Windows Display to Extended mode! Error is " << errCode;
if (errCode == ERROR_ACCESS_DENIED)
{
qCritical() << "ACCESS denied!";
}
}
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES Security1 = { sizeof(Security1) };
SECURITY_ATTRIBUTES Security2 = { sizeof(Security2) };
std::wstring command = L"C:\\Users\\SomeUser\\Desktop\\QT_Projects\\build\\release\\TestSetDisplay.exe";
TCHAR commandLine[MAX_PATH];
_tcscpy_s(commandLine, MAX_PATH, command.c_str());
// Way 2: This way can be successful.
BOOL bResult = CreateProcessAsUser(
hTheToken,
NULL, // (LPWSTR)(path),
(LPWSTR)(commandLine),
&Security1,
&Security2,
FALSE,
dwCreationFlags,
pEnv,
NULL,
&si,
&pi
);
if (!bResult)
{
qCritical() << "Failed to CreateProcessAsUser()";
}
RevertToSelf();
if (pEnv)
{
DestroyEnvironmentBlock(pEnv);
}
}
CloseHandle(hTheToken);
}
CloseHandle(hUserToken);
}
ので、ImpersonateLoggedOnUser()
後、どのように呼び出すためのWindows API SetDisplayConfig()
に成功?
また、1つのシステムサービスで、1つのWindows APIをユーザーとして呼び出す方法はありますか? (このケースでは、SetDisplayConfig()
を呼び出すの目的は、モードを拡張するための表示モードを設定することである。この表示モードは、ユーザごとに設定されている。だから、システムサービスとして、それは最初impersonateLoggedOnUser()
する必要があるかもしれません。)
おそらく、偽装されたユーザーがサービスのレジストリ(HKEY_CURRENT_USERが指しているもの、おそらくSetDisplayConfigがユーザーごとの設定を保存しているもの)にアクセスできないためです。 –