This question tells me how to detect a remote des开发者_开发百科ktop session.
Do anybody know if it's possible to find out from where the remote connection was initialized?
@Vegar, you can use the WTSEnumerateSessions and WTSQuerySessionInformation functions to retrieve this info.
check this link for an example using the Jedi Api Headers.
check this code.
program ProjectTsInfo;
{$APPTYPE CONSOLE}
Uses
Windows,
JwaWinType,
JwaWtsApi32,
JwaWinsock2,
SysUtils,
TypInfo;
type
PWtsSessionInfoAArray = ^TWtsSessionInfoAArray;
TWtsSessionInfoAArray = array[0..ANYSIZE_ARRAY-1] of WTS_SESSION_INFOA;
//Get the info for all clients connected
procedure GetAll_TSClientsInfo;
var
SessionInfoAArray: PWtsSessionInfoAArray;
ClientAddr : PWtsClientAddress;
ClientName : PAnsiChar;
//ClientInfo : PWTSCLIENT;
RetBytes : Cardinal;
IPAddr : String;
i : integer;
pCount : Cardinal;
SessionId : Cardinal;
begin
if WtsEnumerateSessions(WTS_CURRENT_SERVER, 0, 1, PWTS_SESSION_INFO(SessionInfoAArray), pCount) then
begin
for i := 0 to pCount - 1 do
begin
SessionId:=SessionInfoAArray^[i].SessionId;
WTSQuerySessionInformation(WTS_CURRENT_SERVER, SessionId, WTSClientAddress, Pointer(ClientAddr), RetBytes);
WTSQuerySessionInformation(WTS_CURRENT_SERVER, SessionId, WTSClientName, Pointer(ClientName), RetBytes);
//WTSQuerySessionInformation(WTS_CURRENT_SERVER, SessionId, WTSClientInfo, Pointer(ClientInfo), RetBytes); //This value is supported for Windows Server 2008 and Windows Vista with SP1.
try
case ClientAddr^.AddressFamily of
AF_INET:
IPAddr:= Format('%d.%d.%d.%d', [
ClientAddr^.Address[2],
ClientAddr^.Address[3],
ClientAddr^.Address[4],
ClientAddr^.Address[5]
]);
else
IPAddr:= '<unknow>';
end;
WriteLn(Format('Session Id : %d ', [SessionId]));
WriteLn(Format('Client Name : %s ', [ClientName]));
WriteLn(Format('Station Name: %s ', [SessionInfoAArray^[i].pWinStationName]));
WriteLn(Format('State : %s ', [GetEnumName(TypeInfo(WTS_CONNECTSTATE_CLASS),integer(SessionInfoAArray^[i].State))]));
WriteLn(Format('IP : %s ', [IPAddr]));
//supported for Windows Server 2008 and Windows Vista with SP1.
{
WriteLn(Format('ClientName : %s ', [ClientInfo^.ClientName]));
WriteLn(Format('Domain : %s ', [ClientInfo^.Domain]));
WriteLn(Format('UserName : %s ', [ClientInfo^.UserName]));
WriteLn(Format('WorkDirectory : %s ', [ClientInfo^.WorkDirectory]));
WriteLn(Format('InitialProgram : %s ', [ClientInfo^.InitialProgram]));
WriteLn(Format('EncryptionLevel : %d ', [ClientInfo^.EncryptionLevel]));
WriteLn(Format('HRes : %d ', [ClientInfo^.HRes]));
WriteLn(Format('VRes : %d ', [ClientInfo^.VRes]));
WriteLn(Format('ColorDepth : %d ', [ClientInfo^.ColorDepth]));
WriteLn(Format('ClientDirectory : %s ', [ClientInfo^.ClientDirectory]));
}
Writeln('');
finally
WTSFreeMemory(ClientAddr);
WTSFreeMemory(ClientName);
end;
end;
end;
WtsFreeMemory(SessionInfoAArray);
end;
//Get the ip address of the actual connected client
function GetIpActualClient : string;
var
ClientAddr : PWtsClientAddress;
RetBytes : Cardinal;
IPAddr : String;
SessionId : Cardinal;
begin
SessionId:=WTS_CURRENT_SESSION;
WTSQuerySessionInformation(WTS_CURRENT_SERVER, SessionId, WTSClientAddress, Pointer(ClientAddr), RetBytes);
try
case ClientAddr^.AddressFamily of
AF_INET:
IPAddr:= Format('%d.%d.%d.%d', [
ClientAddr^.Address[2],
ClientAddr^.Address[3],
ClientAddr^.Address[4],
ClientAddr^.Address[5]
]);
else
IPAddr:= '<unknow>';
end;
Result:=IPAddr;
finally
WTSFreeMemory(ClientAddr);
end;
end;
begin
Writeln('IP Actual client '+GetIpActualClient);
Writeln('-----------------------------------');
GetAll_TSClientsInfo;
Readln;
end.
UPDATE
As @Remko says, the WTSQuerySessionInformation function with the WTSClientAddress type, can return the local IP of the client. if you wanna get the real ip you can use the WinStationGetRemoteIPAddress helper function located in the JwaWinSta unit.
Var
Port : Word;
IpAddr : WideString;
Begin
WinStationGetRemoteIPAddress(WTS_CURRENT_SERVER,WTS_CURRENT_SESSION,IpAddr,Port);
End;
For me, this worked, it gets the name of the machine connected.
Environment.GetEnvironmentVariable("CLIENTNAME")
Since it's in windows use netstat to check which machines you are connected to and on which ports and just parse out the address for the one that uses the port that remote desktop uses.
WTSQuerySessionInformation returns the client IP as the client reports it, this will probably be (one) of it's local IP Address. If you want to know the REAL ip address and port that is connected you can use WinStationQueryInformationW with information class WinStationRemoteAddress. You will need my unit JwaWinsta from the Jedi Apilib.
I have provided a simple wrapper in the same unit as well:
function WinStationGetRemoteIPAddress(hServer: HANDLE; SessionId: DWORD;
var RemoteIPAddress: WideString; var Port: WORD): Boolean;
try running qwinsta
If you want to get the remote session ID and get the IP address that connected via Citrix you can use the below. This was designed to run when a user connects to a server via a citrix session and display/create a string for the IP address it is connecting from.
// Prints out ICA or RDP session ID of current user & gets ICA session clientAddress variable
using System;
using Microsoft.Win32;
namespace ViaRegedit
{
class Program03
{
static void Main(string[] args)
{
// Obtain an instance of RegistryKey for the CurrentUser registry
RegistryKey rkCurrentUser = Registry.CurrentUser;
// Obtain the test key (read-only) and display it.
RegistryKey rkTest = rkCurrentUser.OpenSubKey("Remote");
foreach (string valueName in rkTest.GetSubKeyNames())
{
//Getting path to RDP/Citrix session ID
string RDPICApath = "";
if (rkTest.OpenSubKey(valueName) != null && rkTest.OpenSubKey(valueName) != null) { RDPICApath = rkTest.OpenSubKey(valueName).ToString(); }
Console.WriteLine("Getting CurrentUser ICA-RDP path from string = " + RDPICApath);
//Split RDPICApath to get session number
string RDPICAnumber = RDPICApath.Substring(RDPICApath.LastIndexOf('\\') + 1);
Console.WriteLine("Current User RDPICAnumber = " + RDPICAnumber);
//Getting reg local machine info for Citrix based on RDP/Citrix session ID "RDPICAnumber"
string regLocal = @"SOFTWARE\Citrix\Ica\Session\" + RDPICAnumber + @"\Connection";
RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey citrixKey = localKey.OpenSubKey(regLocal);
Console.WriteLine("Registry " + citrixKey + " Does Exist - going to get ClientAddress");
//getting clietAddress var from citrixKey
string clientAddress = "";
if (citrixKey != null && citrixKey.GetValue("clientAddress") != null)
{clientAddress = citrixKey.GetValue("clientAddress").ToString();}
Console.WriteLine("Getting current user clientAddress from string = " + clientAddress);
}
rkTest.Close();
rkCurrentUser.Close();
Console.ReadLine();
}
}
}
精彩评论