WTSQuerySessionInformation返回不同的域名

时间:2014-01-23 08:42:00

标签: c# .net windows service pinvoke

我有一个由服务运行的应用程序。应用程序的配置方式只能在单个Windows用户帐户(即安装软件的用户)下运行。处理方式是在安装过程中,应用程序会保存启动安装的用户的用户名/域组合,然后保存服务,具体取决于用户会话是否处于活动状态,决定运行应用程序。

我们的一位客户报告该应用程序未在其帐户上运行,经过进一步调查后,我们发现在查询会话信息时出于某种原因,对于相同的会话ID,返回的域名不同。

这是WTSQuerySessionInformation的pInvoke:

[DllImport("Wtsapi32.dll", SetLastError = true)]
        static extern bool WTSQuerySessionInformation(
            IntPtr hServer,
            uint sessionId,
            WTS_INFO_CLASS wtsInfoClass,
            out IntPtr ppBuffer,
            out uint pBytesReturned
        );

如果用户有活动会话,这就是我们获取服务检查的方式:

WTSEnumerateSessions(IntPtr.Zero, 0, 1, ref pSessionInfo, ref dwCount);

Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));

Int32 current = (int)pSessionInfo;
uint bytes = 0;
for (int i = 0; i < dwCount; i++)
{
     WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO));
     if (WTS_CONNECTSTATE_CLASS.WTSActive == si.State)
     {
         IntPtr userPtr = IntPtr.Zero;
         IntPtr domainPtr = IntPtr.Zero;

        //Check if the active session matches the saved username/domain
        WTSQuerySessionInformation(IntPtr.Zero, (uint)si.SessionID, WTS_INFO_CLASS.WTSUserName, out userPtr, out bytes);

        WTSQuerySessionInformation(IntPtr.Zero, (uint)si.SessionID, WTS_INFO_CLASS.WTSDomainName, out domainPtr, out bytes);

        string sessionUName = Marshal.PtrToStringAnsi(userPtr);
        string sessionDomain = Marshal.PtrToStringAnsi(domainPtr);
    }
}

问题是当服务检测到用户的会话并尝试获取域名时,返回的名称与用户的实际域名不同,即使会话ID对于该特定用户是正确的。

如果它有助于从WTSQuerySessionInformation返回的域名NTLAN_1与完全不同于用户的实际域名。

我想知道WTSQuerySessionInformation的pInvoke或上述代码中的任何调用是否有任何问题。还想知道NTLAN_1域是否与某种服务或任何类型的RDP应用程序相关联。

编辑:

经过多次谈判后,我设法得到LsaEnumerateLogonSessionsLsaGetLogonSessionData的结果,遗憾的是它的结果相同,所列出的会话都没有预期的域名。以下是来自LsaEnumerateLogonSessions

的受尊重信息的会话列表
Session: 0 User: MARK *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 7:34:17 AM
Session: 0 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/4/2014 7:47:11 AM
Session: 0 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 1/27/2014 3:27:33 PM
Session: 0 User: MCMFILE2$ *** Domain: NTLAN_1 *** Login Type: (5) Service *** Login Time: 1/16/2014 3:52:46 PM
Session: 0 User: MCM-LR9-YE91K$ *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:52:40 AM
Session: 0 User: MARK *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:19:39 AM
Session: 0 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 1/20/2014 9:57:57 AM
Session: 0 User: ANONYMOUS LOGON *** Domain: NT AUTHORITY *** Login Type: (3) Network *** Login Time: 1/16/2014 3:53:19 PM
Session: 1 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (2) Interactive *** Login Time: 1/16/2014 3:53:11 PM
Session: 0 User: LOCAL SERVICE *** Domain: NT AUTHORITY *** Login Type: (5) Service *** Login Time: 1/16/2014 3:52:46 PM
Session: 0 User: MARK *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:52:40 AM
Session: 1 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:52:38 AM
Session: 0 User: MARK *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:19:39 AM
Session: 0 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 1/18/2014 6:20:25 PM
Session: 0 User: ANONYMOUS LOGON *** Domain: NT AUTHORITY *** Login Type: (3) Network *** Login Time: 1/16/2014 3:53:19 PM
Session: 0 User: CVSMANAGER_USER *** Domain: MCMFILE2 *** Login Type: (5) Service *** Login Time: 1/16/2014 3:53:09 PM
Session: 0 User: MCM-LR9-YE91K$ *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:52:40 AM
Session: 0 User: MARK *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/6/2014 10:19:39 AM
Session: 0 User: DefaultAppPool *** Domain: IIS APPPOOL *** Login Type: (5) Service *** Login Time: 2/6/2014 8:42:47 AM
Session: 0 User: ADMINISTRATOR *** Domain: NTLAN_1 *** Login Type: (3) Network *** Login Time: 2/4/2014 2:40:40 PM
Session: 0 User: IUSR *** Domain: NT AUTHORITY *** Login Type: (5) Service *** Login Time: 1/16/2014 3:53:09 PM
Session: 0 User: MCMFILE2$ *** Domain: NTLAN_1 *** Login Type: (0) 0 *** Login Time: 1/16/2014 3:52:44 PM

有问题的会话有会话ID = 1.从列表中,它显示域名为NTLAN_1而不是实际域。

现在,我在我的桌面应用程序中发现了一些奇怪的东西,我相信在找到这个问题的解决方案时有一个关键的部分,但我不知道该怎么做。

现在我的桌面应用程序是用.NET编写的,所以我尝试直接运行应用程序来获取用户名和域名。现在有趣的是,如果我使用本机GetUserNameEx函数并将NameUserPrincipal作为NameFormat传递,我可以获得正确的用户名/域组合。但是,这是有趣的部分,当我尝试通过调用Environment使用Environment.UserDomainName类获取域名时,我得到了NTLAN_1的罪魁祸首。请注意,托管和非托管调用都是由同一个应用程序在同一次运行中完成的。

我之前没有遇到过这样的问题,现在看来我有更多的用户报告了同样的问题而且开始真的很烦我。

2 个答案:

答案 0 :(得分:2)

我终于找到了问题,有问题的域实际上是UPN后缀,而不是域名。我仍然认为这是来自MS的错误,因为WTSQuerySessionInformationLsaEnumerateLogonSessions都应该返回域名而不是UPN后缀。

我能够通过依赖帐户SID而不是用户名/域组合来解决问题,幸运的是,无论是使用实际域名还是后缀查询,SID都是相同的。

感谢Harry Johnston关于SID的惊人评论。

答案 1 :(得分:0)

作为评论太大了......希望这有用......

那么......服务是否有效地查询本地或远程服务器?

以下摘自this MSDN link which describes the WTSQuerySessionInformation function

“仅在本地服务器上获取会话信息时指定WTS_CURRENT_SESSION。如果在远程服务器上查询会话信息时指定了WTS_CURRENT_SESSION,则返回的会话信息将不一致。请勿使用返回的数据。”

这是您传入的SessionId参数。此外:

“要在远程桌面服务运行时检索当前会话的会话ID,请调用WTSQuerySessionInformation并为SessionId参数指定WTS_CURRENT_SESSION,为WTSInfoClass参数指定WTSSessionId。会话ID将在ppBuffer参数中返回。”

更新:尝试使用WTSEnumerateSessionsEx通过扩展结构获取更多会话信息 WTS_SESSION_INFO_1,其本身包含域名...

“pDomainName - 指向以null结尾的字符串的指针,该字符串包含登录到会话的用户的域名。如果没有用户登录到该会话,则该字符串包含NULL。 “

如果用户正在影响另一个人,则不确定它是什么。