opengl - Windows 2008 渲染农场服务 : CreateProcessAsUser "Session 0 Isolation" and OpenGL

标签 opengl windows-services windows-server-2008 createprocessasuser session-0-isolation

我有一个旧的 Windows 服务器服务和(衍生)应用程序,在 XP-64 和 W2K3 中运行良好,但在 W2K8 上失败。我相信这是因为新的“Session 0 isolation”功能。

因此,我正在寻找代码示例/安全设置 mojo,它可以让您从 Windows 服务为 Windows 2008 Server 创建一个新进程,以便我可以恢复(并可能超越)以前的行为。我需要一个解决方案:

  • 在非零 session 中创建新进程以绕过 session 0 隔离限制(无法从 session 0 访问图形硬件) - 官方 MS 行是:

  • 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.


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

  • 我目前停留在第 1 项,尽管有一些类似的帖子讨论了这个问题(如 thisthis - 它们不是合适的解决方案,因为不能保证用户 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 框的)

    所以 - 一个问题:
  • 这种方法是否有效,还是所有服务启动的进程都被有意限制在 session 0 中?
  • 有没有更好的方法(没有“登录时启动”和服务器自动登录?)
  • 这段代码是否有问题,或者创建进程 token 的不同方式,我可以换出 session ID 以指示我想在新 session 中生成进程?我确实尝试使用 LogonUser 而不是 OpenProcessToken,但这也不起作用。 (我不在乎所有衍生进程是否共享相同的非零 session 。)

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

    最佳答案

    对于有兴趣解决此问题的任何人:

    我与 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/

    相关文章:

    c# - Windows 服务到 Azure?

    c# - 如何在远程服务器上安装 C# Windows 服务?

    windows-server-2008 - Windows Server 2008 中缺少 'qedit.dll'?

    c++ - QOpenGLtexture层数

    c++ - 使用 GLEW 和 WGL 的 OpenGL 抗锯齿

    c++ - 在 OpenGL/GLFW 3.2 中在窗口和全屏之间切换

    iis - 间歇性的 ColdFusion 404 错误页面,有时显示连接重置/中断,有时显示错误页面

    macos - 在 Mac 上安装 SDL2

    service - 错误1001.指定的服务已存在

    api - 带有 API 的 Windows Server 2008 防病毒软件