XP-64 と W2K3 では正常に動作するレガシー Windows サーバー サービスと (生成された) アプリケーションがありますが、W2K8 では失敗します。これは、新しい「セッション 0 分離」機能によるものだと思います。
そのため、Windows 2008 Server の Windows サービスから新しいプロセスを作成して、以前の動作を復元 (さらにはそれを上回る) できるようにするコード サンプル/セキュリティ設定モジョを探しています。次のようなソリューションが必要です。
- セッション 0 分離制限 (セッション 0 からグラフィックス ハードウェアへのアクセスなし) を回避するために、ゼロ以外のセッションで新しいプロセスを作成します。これに関する公式の MS 行は次のとおりです。
セッション 0 はユーザー セッションではないため、セッション 0 で実行されているサービスはビデオ ドライバーにアクセスできません。これは、サービスがグラフィックをレンダリングしようとしても失敗することを意味します。セッション 0 でディスプレイの解像度と色深度を照会すると、最大 1920x1200 で 32 ビット/ピクセルのシステムの正しい結果が報告されます。
新しいプロセスは、Windows DC の作成に使用できる Windows ステーション/デスクトップ (例: winsta0/default) を取得します。ここでこれに対する解決策(インタラクティブセッションで問題なく起動する)を見つけました:C++でのインタラクティブクライアントプロセスの開始
Windows DC は、 OpenGL DescribePixelFormat 列挙型の基礎として使用される場合、ハードウェア アクセラレーション形式を見つけて使用できます (OpenGL ハードウェアが適切に装備されたシステム上)。ただし、ターミナル サービス セッションが実行されている場合を除きます (VNC は正常に動作します)。また、プロセスが動作するようにする (つまり、ターミナル サービス セッションが開いている場合でも OpenGL ハードウェア アクセラレーションを使用して実行する) ソリューションは、必須ではありませんが、非常に優れています。
私は現在、アイテム#1で立ち往生しています。これについて議論する同様の投稿がいくつかありますが(これ、およびこれなど)、ユーザーセッションがすでにログインして「取る」という保証がないため、適切な解決策ではありませんセッションIDから、また私はLocalSystemアカウントから実行していません(サービスのドメインアカウントから実行しているため、理由の範囲内で特権を調整できますが、優先度をエスカレートして含める必要はありませんSeTcbPrivileges.)
たとえば、これは機能すると思われるスタブですが、SetTokenInformation 呼び出しで常にエラー 1314 を返します (AdjustTokenPrivileges がエラーを返さなかったとしても)。プロセス トークン)、しかし、セッション 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 の結果) を設定しようとしています。(RDCではなくVNC経由でW2K8ボックスにログインしていることに注意してください)
だから - 質問:
- このアプローチは有効ですか、それともサービスによって開始されたすべてのプロセスが意図的にセッション 0 に制限されていますか?
- より良いアプローチはありますか (「ログオン時に起動」とサーバーの自動ログオンを除く)。
- このコードに何か問題がありますか、またはセッション ID を交換して新しいセッションでプロセスを生成したいことを示すことができるプロセス トークンを作成する別の方法はありますか? OpenProcessToken の代わりに LogonUser を使用してみましたが、それもうまくいきませんでした。(この時点で、生成されたすべてのプロセスがゼロ以外の同じセッションを共有しているかどうかは気にしません。)
どんな助けでも大歓迎です-ありがとう!