Zaid Amir
Zaid Amir

Reputation: 4785

Get the full windows domain name from a session id

I am working on service application that needs to monitor windows session changes and automatically start an application if a specific user logged on to.

Here is how it works, I have a file with a list of Windows usernames stored in a user principal name format ([email protected]). My service will monitor any session changes and will take certain actions once one of those users gets logged on.

List<string> _UsersList;
 object _sessionCheckLock = new object();
        void OnCheckSession(int nSessionId, bool bIsLoggIn)
        {
            lock(_sessionCheckLock)
            {
                try
                {
                    string sUserName = string.Empty;
                    string sDomain = string.Empty;

                    IntPtr pUserName = IntPtr.Zero;
                    uint nBytesReturned = 0;
                    if (WTSQuerySessionInformation(IntPtr.Zero, (uint)nSessionId, WTS_INFO_CLASS.WTSUserName, out pUserName, out nBytesReturned) && (pUserName != IntPtr.Zero))
                    {
                        sUserName = Marshal.PtrToStringAnsi(pUserName);

                        WTSFreeMemory(pUserName);

                        IntPtr pDomain = IntPtr.Zero;
                        if(WTSQuerySessionInformation(IntPtr.Zero, (uint)nSessionId, WTS_INFO_CLASS.WTSDomainName, out pDomain, out nBytesReturned) && (pDomain != IntPtr.Zero))
                        {
                            sDomain = Marshal.PtrToStringAnsi(pDomain);
                            WTSFreeMemory(pDomain);
                        }
                        else
                        {

                        }

                        if (!string.IsNullOrEmpty(sUserName))
                        {
                          if(!string.IsNullOrEmpty(sDomain)
                          {
                              sUserName += "@" + sDomain;
                          }

                            foreach(string username in _UsersList)
                            {
                               if(string.Compare(sUsername, username, true)==0)
                               {
                                //Do a couple of things
                                return;
                               }
                            }

                        }
                    }
                    else
                    {
                        return;
                    }
                }
                catch (System.Exception ex)
                {

                }
            }
        }

The above code is the function I call whenever a new logon event is raised. The _UsersList is a list of strings that contains all the usernames that the service is allowed to work with. The problem here is that WTSQuerySessionInformation when used with WTS_INFO_CLASS.WTSDomainName does not return the full name of the domain and therefore the comparison fails.For example if a username called ([email protected]) exists in the list of user and logs on, when querying for the domain name of the session, it returns only (DOMAIN) without the .LOCAL appendix. I need to find a way to get the full domain name to match the one in my list.

Can someone help please

Upvotes: 0

Views: 1774

Answers (3)

rifaco
rifaco

Reputation: 746

Red Serpent, did Cassia really help? I had the same problem as you, but Cassia seems to use the same WTSQuerySessionInformation call underneath, so I was still only getting the short domain name.

On this page I found a reference to the DsGetDcName function which I was able to use to get the FQDN using the short domain name that WTSQuerySessionInformation gave me. Here's my example that works for me:

std::wstring GetSessionDomainName(DWORD sessionId)
{
    std::wstring domainName;
    LPWSTR buffer = NULL;
    DWORD bufferSize = 0;

    if(WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSDomainName, &buffer, &bufferSize))
    {
        PDOMAIN_CONTROLLER_INFOW domainControllerInfo = NULL;
        DWORD retVal = DsGetDcNameW(NULL, buffer, NULL, NULL, DS_IS_FLAT_NAME | DS_RETURN_DNS_NAME, &domainControllerInfo);
        if (retVal == 0)
            domainName = domainControllerInfo->DnsForestName;

        WTSFreeMemory(buffer);
        NetApiBufferFree(domainControllerInfo);
    }

    return domainName;
}

Upvotes: 1

Dino Rondelly
Dino Rondelly

Reputation: 138

Look into Cassia.Net, this is a very useful.

You can download the source code, i used this for a project where i had to get all the users that were logged on to a server.

cassia .NET Windows Terminal Services / Remote Desktop Services Library

http://code.google.com/p/cassia/

hope that helps

Upvotes: 2

slipsec
slipsec

Reputation: 3062

WTSDomainName shows the domain a user is a member of-- I cannot find any explicit documentation, but I would assume that it is getting the netBios name, not the FQDN. You should be able to use the two environmental variable USERDNSDOMAIN USERDOMAIN hold these values.

You can also use ADSI to do a more detailed lookup, have a look at the thread here

But this all said, unless you have an INCREDIBLY complex forest structure, with users logging in from many different domains in the tree... it will probably be much faster to just hard-code the conversions into your app. They are not something that often changes, and users logging in from a new domain should also be rare.

Upvotes: 1

Related Questions