title: WTSQuerySessionInformation returns a different domain name
body: <p>I have an application that is run by a service. The application is configured in a way that it only runs under a single Windows user account, i.e. the user who installed the software. The way this is handled is during installation, the application saves the username/domain combination of the user who initiated the installation and then the service, depending on whether or not the user session is active decides to run the application.</p>
  
  <p>One of our customers reported that the application was not running on his account and after further investigation we discovered that for some reason when querying the session information, the domain name returned is different for the same session id.</p>
  
  <p>This is the pInvoke for WTSQuerySessionInformation:</p>
  
  <pre><code>[DllImport("Wtsapi32.dll", SetLastError = true)]
          static extern bool WTSQuerySessionInformation(
              IntPtr hServer,
              uint sessionId,
              WTS_INFO_CLASS wtsInfoClass,
              out IntPtr ppBuffer,
              out uint pBytesReturned
          );
  </code></pre>
  
  <p>and this is how we get the service checks if the user has an active session :</p>
  
  <pre><code>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 &lt; 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);
      }
  }
  </code></pre>
  
  <p>The problem is when the service detects the user's session and tries to get the domain name, the name returned is different than the actual domain name of the user even though the session ID is correct for that particular user.</p>
  
  <p>If it helps the domain name returned from <code>WTSQuerySessionInformation</code> is <code>NTLAN_1</code> which is totally different from the actual domain of the user.</p>
  
  <p>I would like to know if there is anything wrong with the pInvoke of <code>WTSQuerySessionInformation</code> or any of the calls in the above code. Also would like to know if the <code>NTLAN_1</code> domain is associated with some service or RDP application of any sort.</p>
  
  <p>EDIT:</p>
  
  <p>After much negotiations I managed to get the result for <code>LsaEnumerateLogonSessions</code> and <code>LsaGetLogonSessionData</code>, sadly it's the same result and none of the listed sessions has the expected domain name. Here is the list of sessions with their respected info from the <code>LsaEnumerateLogonSessions</code>:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>The session in question is have session id = 1. And from the list it shows the domain name to be NTLAN_1 instead of the actual domain.</p>
  
  <p>Now, I caught something strange in my desktop application which I believe have a crucial part in finding the solution for this issue but I'm not sure what to make of it.</p>
  
  <p>Now my desktop application is written in .NET, so I tried getting the username and domain by running the application directly. Now the funny thing is if I use the native <code>GetUserNameEx</code> function and passing <code>NameUserPrincipal</code> as the NameFormat, I am able to get the correct username/domain combination. However, and this is the funny part, when I try getting the domain name using the <code>Environment</code> class by calling <code>Environment.UserDomainName</code> I get the NTLAN_1 culprit. note that both managed and unmanaged calls were done by the same application in the same run.</p>
  
  <p>I haven't had such an issue before and it seems now I have a couple more users who reported the same issue and it started to really bother me.</p>