首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Windows 2008 RenderFarm服务: CreateProcessAsUser“会话0隔离”和OpenGL

Windows 2008 RenderFarm服务: CreateProcessAsUser“会话0隔离”和OpenGL
EN

Stack Overflow用户
提问于 2010-03-17 16:53:32
回答 3查看 11.7K关注 0票数 10

我有一个遗留的Windows服务和(衍生的)应用程序,它在XP-64和W2K3中运行良好,但在W2K8上失败。我相信这是因为新的“会话0隔离(http://msdn.microsoft.com/en-us/library/bb203962(VS.85%29.aspx))”特性。

因此,我正在寻找代码示例/安全设置mojo,它允许您从windows 2008 Server的Windows服务中创建一个新进程,这样我就可以恢复(并可能超过)以前的行为。我需要一个解决办法:

  1. 在非零会话中创建新进程,以绕过session-0隔离限制(不能从会话0访问图形硬件)--这方面的正式MS行是:

因为会话0不再是用户会话,所以在会话0中运行的服务无法访问视频驱动程序。这意味着服务呈现图形的任何尝试都将失败。在会话0中查询显示分辨率和颜色深度会报告系统的正确结果,以每像素32位为单位,最高可达1920x1200。

  1. 新进程获得一个windows站点/桌面(例如winsta0/default),可用于创建windows DC。我在这里找到了一个解决方案(在交互会话中启动OK ):在C++中启动交互式客户端进程
  2. windows作为OpenGL DescribePixelFormat枚举的基础时,能够找到并使用硬件加速格式(在配备了OpenGL硬件的系统上)。请注意,我们的当前解决方案在XP-64和W2K3上正常工作,除非终端服务会话正在运行(VNC工作正常)。一个也允许进程工作的解决方案(即,即使在终端服务会话打开时也使用OpenGL硬件加速运行)将是狂热的,尽管不是必需的。

目前我还停留在第1项,尽管有一些类似的帖子讨论这个问题(比如 --它们不是合适的解决方案,因为无法保证已经登录的用户会话可以“从”LocalSystem帐户“获取”会话id,也不能从LocalSystem帐户运行(我是从服务的域帐户运行的,我可以在合理的情况下调整服务的特权,尽管我不希望升级优先级以包含SeTcbPrivileges)。

例如,这里有一个我认为应该有效的存根,但是总是在SetTokenInformation调用上返回一个错误1314 (尽管AdjustTokenPrivileges没有返回错误),我也使用了一些涉及"LogonUser“的替代策略(而不是打开现有的进程令牌),但是我似乎无法交换会话id。

我也怀疑在所有情况下是否使用WTSActiveConsoleSessionId (例如,如果没有交互式用户登录)--尽管对没有登录会话的服务运行的快速测试似乎返回了一个合理的会话值(1)。

为了便于阅读,我删除了错误处理(还是有点混乱--抱歉)

代码语言:javascript
复制
    //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登录到W2K8框的,而不是RDC)

所以-A问题:

  1. 这种方法有效吗?还是所有服务启动的进程都被有意地限制在会话0上?
  2. 是否有更好的方法(除了“启动登录”和服务器自动登录之外)?
  3. 这段代码有什么问题吗?还是用另一种方法来创建一个进程令牌,在这里我可以交换会话id,以指示我要在一个新会话中生成进程?我确实尝试过使用LogonUser而不是OpenProcessToken,但这也不起作用。(我不在乎所有产生的进程在此时是否共享相同的非零会话。)

任何帮助都非常感谢--谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-03-18 23:17:16

对于任何对解决这一问题感兴趣的人:

我与MS支持的LogonSDK团队讨论了这个问题。看起来,不可能完全以编程方式模拟交互式用户,因此您可以得到一个物理控制台和相关的GDI构造,而且我们实际上“只是幸运地”,直到现在它才能正常工作。他们确实确认,会话0隔离是回归的根本原因。

他们的建议是启用交互式会话的自动登录,并重构服务以与交互式会话中的新客户端组件对话。为了解决这方面的安全缺陷,他们建议实现shell替换,将服务器置于"Kiosk“模式登录(例如,没有适当凭据的资源管理器访问,等等)。

从好的方面来说,这应该解决我们在终端服务会话中遇到的问题,这些问题扼杀了硬件的加速。

我将向MS提交一个请求,考虑这种“呈现场”用例,以便在将来的版本中支持“代理用户会话”,这样服务器就可以生成硬件加速的进程,而不需要在控制台上登录现有的客户端用户进程。

票数 9
EN

Stack Overflow用户

发布于 2013-05-01 14:30:17

我还没有完成培训课程,但我在Microsoft站点上找到了“会话0隔离解决方案”教程:

unit.aspx

在计划的任务中,我有相同的会话-0-隔离问题。

票数 0
EN

Stack Overflow用户

发布于 2013-08-13 23:57:58

farmComm将启动您选择的应用程序到会话0,没有图形用户界面可见,但可以访问图形硬件,无论用户是否登录。它还响应任何会话中的用户活动(包括会话0或“安全桌面”,而这是活动会话)。它旨在因此在用户空闲时启动应用程序,并在用户从空闲恢复时终止应用程序,但这些运行条件可以很容易地在源AutoHotkey脚本中更改。

https://github.com/r-alex-hall/farmComm

它在会话0中生成“不可见”的应用程序,但它可以很容易地被修改(将值为“隐藏”的变量更改为“显示”),使派生进程的GUI可见(如果它们有GUI)。但是,如果它们是可见的,则它们可能触发Windows挂起以查看会话0中的“消息”,和/或只能从会话0中看到(它似乎包括“安全桌面”可见的任何时候--例如,当工作站被锁定,或断开与用户会话的连接,或没有用户登录时)。

在本文中,如果在farmComm运行过程中启动任何远程桌面( RDP )会话,farmComm将终止这些进程并尝试重新启动它们以响应RDP会话,如果它们是试图访问图形硬件的应用程序,则可能导致它们崩溃(因为RDP限制对图形硬件的访问)。也许这个RDP问题也可以解决。。。或者您可以调整源,使其永远不会终止进程,也不会迁移到其他会话。(注意:一种可能的计划更改是使您能够编写farmComm是否和何时终止、不终止、挂起或恢复进程-或者在用户从空闲状态恢复时,用脚本运行完全不同的进程)。

脚本可以编译成可执行文件,在我的发行版中,它们是可执行的。

此工具集的核心是特定版本的paexec (它将应用程序启动到会话0)、AutoHotkey对用户活动的非常可靠的响应(或缺少响应),以及检索有关会话的系统信息。启动进程“隐藏”(没有GUI可见)的选项也是通过AutoHotkey进行的。

公开:我编写了脚本(或编码) farmComm,并将其发布到公共域。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2464182

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档