【发布时间】:2011-01-28 16:22:16
【问题描述】:
我有一个旧的 Windows 服务器服务和(衍生的)应用程序,在 XP-64 和 W2K3 中运行良好,但在 W2K8 中失败。我相信这是因为新的“Session 0 isolation”功能。
因此,我正在寻找代码示例/安全设置 mojo,它可以让您从 Windows 服务为 Windows 2008 Server 创建一个新进程,以便我可以恢复(并可能超越)以前的行为。我需要一个解决方案:
- 在非零会话中创建新进程以绕过会话 0 隔离限制(无法从会话 0 访问图形硬件) - 官方 MS 行是:
因为会话 0 不再是用户 会话,正在运行的服务 会话 0 无权访问 视频驱动程序。这意味着任何 服务进行渲染的尝试 图形失败。查询显示 Session 中的分辨率和颜色深度 0 报告正确的结果 系统高达 1920x1200 在 每像素 32 位。
新进程获得可用于创建 Windows DC 的 Windows 工作站/桌面(例如 winsta0/default)。我在这里找到了一个解决方案(在交互式会话中启动 OK):Starting an Interactive Client Process in C++
Windows DC 在用作OpenGL DescribePixelFormat enumeration 的基础时,能够找到并使用硬件加速格式(在适当配备 OpenGL 硬件的系统上)。请注意,我们当前的解决方案工作正常在 XP-64 和 W2K3 上,除非终端服务会话正在运行(VNC 工作正常。)一个还允许进程工作的解决方案(即,即使终端服务会话打开,也可以使用 OpenGL 硬件加速运行)将是狂热的,虽然不是必需的。
我目前停留在第 1 项,尽管有一些类似的帖子讨论了这个问题(如 this 和 this - 它们不是合适的解决方案,因为不能保证记录用户会话已经从“获取”会话 ID,也不是从 LocalSystem 帐户运行(我正在从服务的域帐户运行,我可以在合理范围内调整权限,尽管我更愿意不必升级优先级以包含 SeTcbPrivileges。)
例如 - 这是一个我认为应该可以工作的存根,但在调用 SetTokenInformation 时总是返回错误 1314(即使 AdjustTokenPrivileges 没有返回错误)我也使用了一些涉及“LogonUser”的替代策略(而不是打开现有的进程令牌),但我似乎无法换出会话 ID。
我也怀疑在所有情况下都使用 WTSActiveConsoleSessionId(例如,如果没有交互式用户登录) - 尽管在没有登录会话的情况下运行服务的快速测试似乎返回了合理的会话值(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 之前,所有调试输出看起来都很好 - 我看到会话 0 是我当前的进程会话,在我的情况下,它正在尝试设置会话 1(WTSGetActiveConsoleSessionId 的结果)。 (请注意,我是通过 VNC 而非 RDC 登录 W2K8 框的)
所以 - 一个问题:
- 这种方法是否有效,还是所有服务启动的进程都被有意限制在会话 0 中?
- 是否有更好的方法(缺少“登录时启动”和服务器自动登录?)
- 此代码是否有问题,或者创建进程令牌的不同方法,我 可以 换出会话 ID 以指示我想在新会话中生成进程?我确实尝试使用 LogonUser 而不是 OpenProcessToken,但这也不起作用。 (此时我不在乎所有衍生进程是否共享相同的非零会话。)
非常感谢任何帮助 - 谢谢!
【问题讨论】:
标签: opengl windows-services windows-server-2008 createprocessasuser session-0-isolation