我有一个旧的 Windows 服务器服务和(衍生)应用程序,在 XP-64 和 W2K3 中运行良好,但在 W2K8 上失败。我相信这是因为新的“Session 0 isolation”功能。
因此,我正在寻找代码示例/安全设置 mojo,它可以让您从 Windows 服务为 Windows 2008 Server 创建一个新进程,以便我可以恢复(并可能超越)以前的行为。我需要一个解决方案:
Because Session 0 is no longer a user session, services that are running in Session 0 do not have access to the video driver. This means that any attempt that a service makes to render graphics fails. Querying the display resolution and color depth in Session 0 reports the correct results for the system up to a maximum of 1920x1200 at 32 bits per pixel.
我目前停留在第 1 项,尽管有一些类似的帖子讨论了这个问题(如 this 和 this - 它们不是合适的解决方案,因为不能保证用户 session 已经登录到“获取”一个 session ID,我也不是从 LocalSystem 帐户运行(我是从服务的域帐户运行,我可以在合理的范围内调整其权限,尽管我宁愿不必升级优先级以包括 SeTcbPrivileges。)
例如 - 这是一个我认为应该可以工作的 stub ,但在 SetTokenInformation 调用上总是返回错误 1314(即使 AdjustTokenPrivileges 没有返回错误)我也使用了一些涉及“LogonUser”的替代策略(而不是打开现有的进程 token ),但我似乎无法换出 session ID。
我也怀疑在所有情况下都使用 WTSActiveConsoleSessionId(例如,如果没有交互式用户登录) - 尽管在没有登录 session 的情况下运行的服务的快速测试似乎返回了合理的 session 值 (1)。
为了便于阅读,我删除了错误处理(仍然有点困惑 - 道歉)
//Also tried using LogonUser(..) here
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_SESSIONID
| TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY
| TOKEN_DUPLICATE, &hToken)
GetTokenInformation( hToken, TokenSessionId, &logonSessionId, sizeof(DWORD), &dwTokenLength )
DWORD consoleSessionId = WTSGetActiveConsoleSessionId();
/* Can't use this - requires very elevated privileges (LOCAL only, SeTcbPrivileges as well)
if( !WTSQueryUserToken(consoleSessionId, &hToken))
...
*/
DuplicateTokenEx(hToken, (TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_SESSIONID | TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE), NULL, SecurityIdentification, TokenPrimary, &hDupToken))
// Look up the LUID for the TCB Name privilege.
LookupPrivilegeValue(NULL, SE_TCB_NAME, &tp.Privileges[0].Luid))
// Enable the TCB Name privilege in the token.
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hDupToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, 0))
{
DisplayError("AdjustTokenPrivileges");
...
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
DEBUG( "Token does not have the necessary privilege.\n");
} else {
DEBUG( "No error reported from AdjustTokenPrivileges!\n");
} // Never errors here
DEBUG(LM_INFO, "Attempting setting of sessionId to: %d\n", consoleSessionId );
if (!SetTokenInformation(hDupToken, TokenSessionId, &consoleSessionId, sizeof(DWORD)))
*** ALWAYS FAILS WITH 1314 HERE ***
在调用 SetTokenInformation 之前,所有调试输出看起来都很好——我看到 session 0 是我当前的进程 session ,就我而言,它正在尝试设置 session 1(WTSGetActiveConsoleSessionId 的结果)。 (请注意,我是通过 VNC 而不是 RDC 登录到 W2K8 框的)
所以 - 一个问题:
非常感谢任何帮助 - 谢谢!
最佳答案
对于有兴趣解决此问题的任何人:
我与 LogonSDK 团队的 MS Support 讨论了这个问题。似乎不可能以编程方式完全模拟交互式用户,这样您就可以得到一个物理控制台和相关的 GDI 构造,而且我们基本上“很幸运”它一直工作到现在。他们确实确认 session 0 隔离是回归的根本原因。
他们的建议是启用自动登录到交互式 session ,并重构服务以与交互式 session 中的新客户端组件对话。为了解决此问题的安全性缺点,他们建议实现外壳替换,以在登录时将服务器置于“Kiosk”模式(例如,没有适当的凭据就无法访问资源管理器等)
从好的方面来说,这应该可以解决我们在终端服务 session 中遇到的终止硬件加速的问题。
我将向 MS 提交请求,考虑在 future 版本中为“代理用户 session ”支持提供这种“渲染农场”用例,这样服务器就可以生成硬件加速进程,而不会因需要现有客户端用户进程而牺牲安全性在控制台登录。
关于opengl - Windows 2008 渲染农场服务 : CreateProcessAsUser "Session 0 Isolation" and OpenGL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2464182/