Reputation: 4785
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
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
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
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