T
Thomas Eg Jørgensen
Guest
Hi,
I've been searching for at better place to ask this question, but i
wasn't able to find any:-( If you have a better place for this question,
please let me know...
Anyhow, the question is related to developing custom terminal services
administration application...
I need to remote control a specific user(defined by the server+username)
in my software. To be able to remote control a specific user i must know
the sessionid of the user. However, the API in windows does not allow me
to query a server for a single username, i must enumerate ALL users and
thereafter compare EACH enumerated user to see if this user has the
correct username....
First i must enumerate all sessions on the specific server with:
BOOL WTSEnumerateSessions(
__in HANDLE hServer,
__in DWORD Reserved,
__in DWORD Version,
__out PWTS_SESSION_INFO* ppSessionInfo,
__out DWORD* pCount
);
[ http://msdn2.microsoft.com/en-us/library/aa383833(VS.85).aspx ]
....then i must loop all the users(about 200 per server) and query each
of them to verify the username with:
BOOL WTSQuerySessionInformation(
__in HANDLE hServer,
__in DWORD SessionId,
__in WTS_INFO_CLASS WTSInfoClass,
__out LPTSTR* ppBuffer,
__out DWORD* pBytesReturned
);
[ http://msdn2.microsoft.com/en-us/library/aa383838(VS.85).aspx ]
This can't be right, can it? the above procedure is, ofcourse, very
slow. About 1 sec to find a random user on a server with about 200
active sessions...and that is just to find the correct sessionid!
Here is snippet from my application(Pascal language):
//Open the serverhandle for the server in question...
ServerHandle=WTSOpenServerW(PWideChar(ServerName));
try
//Enumerate all users on the server...
if WTSEnumerateSessionsW(ServerHandle,0,1,SessionInfo,nCount) then
begin
//Set the the "CurrentSessionInformation"-pointer to the first
pointer returned by the enumeration...
CurrSessionInfo := SessionInfo;
//Loop as many times as nCount....one for each session...
for a:=1 to nCount do
begin
//Query the session to get the username...
if
WTSQuerySessionInformationW(ServerHandle,CurrSessionInfo^.SessionId,
WTSUserName, ptr, bytesReturned) then
begin
CurrUsername:=PWideChar(ptr);
If LowerCase(CurrUsername)=LowerCase(Username) then
begin
//Hurray! The username was correct, print it on the GUI and
break the loop..
memo1.lines.add('User '+CurrUsername+' found with ID
'+inttostr(CurrSessionInfo^.SessionId)+' on server "'+Servername+'"');
break;
end;
end;
//Increase the pointer to the next in the enumeration...
inc(CurrSessionInfo);
end;
end;
//Memory management....um...we love it! eh..
WTSFreeMemory(SessionInfo);
finally
WTSCloseServer(ServerHandle);
end;
And it works fine...but it ain't pretty!
What am i missing here? Has anyone done anything like this and found a
neat "Username to sessionid" method?
Thanks!
....and again, i'm sorry if this ain't the correct group:-(
/Thomas
I've been searching for at better place to ask this question, but i
wasn't able to find any:-( If you have a better place for this question,
please let me know...
Anyhow, the question is related to developing custom terminal services
administration application...
I need to remote control a specific user(defined by the server+username)
in my software. To be able to remote control a specific user i must know
the sessionid of the user. However, the API in windows does not allow me
to query a server for a single username, i must enumerate ALL users and
thereafter compare EACH enumerated user to see if this user has the
correct username....
First i must enumerate all sessions on the specific server with:
BOOL WTSEnumerateSessions(
__in HANDLE hServer,
__in DWORD Reserved,
__in DWORD Version,
__out PWTS_SESSION_INFO* ppSessionInfo,
__out DWORD* pCount
);
[ http://msdn2.microsoft.com/en-us/library/aa383833(VS.85).aspx ]
....then i must loop all the users(about 200 per server) and query each
of them to verify the username with:
BOOL WTSQuerySessionInformation(
__in HANDLE hServer,
__in DWORD SessionId,
__in WTS_INFO_CLASS WTSInfoClass,
__out LPTSTR* ppBuffer,
__out DWORD* pBytesReturned
);
[ http://msdn2.microsoft.com/en-us/library/aa383838(VS.85).aspx ]
This can't be right, can it? the above procedure is, ofcourse, very
slow. About 1 sec to find a random user on a server with about 200
active sessions...and that is just to find the correct sessionid!
Here is snippet from my application(Pascal language):
//Open the serverhandle for the server in question...
ServerHandle=WTSOpenServerW(PWideChar(ServerName));
try
//Enumerate all users on the server...
if WTSEnumerateSessionsW(ServerHandle,0,1,SessionInfo,nCount) then
begin
//Set the the "CurrentSessionInformation"-pointer to the first
pointer returned by the enumeration...
CurrSessionInfo := SessionInfo;
//Loop as many times as nCount....one for each session...
for a:=1 to nCount do
begin
//Query the session to get the username...
if
WTSQuerySessionInformationW(ServerHandle,CurrSessionInfo^.SessionId,
WTSUserName, ptr, bytesReturned) then
begin
CurrUsername:=PWideChar(ptr);
If LowerCase(CurrUsername)=LowerCase(Username) then
begin
//Hurray! The username was correct, print it on the GUI and
break the loop..
memo1.lines.add('User '+CurrUsername+' found with ID
'+inttostr(CurrSessionInfo^.SessionId)+' on server "'+Servername+'"');
break;
end;
end;
//Increase the pointer to the next in the enumeration...
inc(CurrSessionInfo);
end;
end;
//Memory management....um...we love it! eh..
WTSFreeMemory(SessionInfo);
finally
WTSCloseServer(ServerHandle);
end;
And it works fine...but it ain't pretty!
What am i missing here? Has anyone done anything like this and found a
neat "Username to sessionid" method?
Thanks!
....and again, i'm sorry if this ain't the correct group:-(
/Thomas