When a client is connected to a Terminal Server Session you can use the Terminal Server API to retrieve the client’s local IP address.

Start by enumerating all sessions with WtsEnumerateSessions and then for each session get the ClientAddress with a call to WTSQuerySessionInformation with the WTSClientAddress parameter. Sound simple, no?

WTSQuerySessionInformation returns a pointer to a WTS_CLIENT_ADDRESS structure. You need to know that the IP address is located at on offset of 2 bytes in the Address member of WTS_CLIENT_ADDRESS.

So here’s a sample:

uses JwaWinType, JwaWtsApi32, JwaWinsock2, ExtCtrls;
type
  PWtsSessionInfoAArray = ^TWtsSessionInfoAArray;
  TWtsSessionInfoAArray = array[0..ANYSIZE_ARRAY-1] of WTS_SESSION_INFOA;

var hServer: THandle;
  SessionInfoPtr: PWtsSessionInfoAArray;
  pCount: Cardinal;
  ClientAddressPtr: PWtsClientAddress;
  dwBytesReturned: Cardinal;
  IPStr: String;
  i: integer;
begin
  if WtsEnumerateSessions(WTS_CURRENT_SERVER, 0, 1, PWTS_SESSION_INFO(SessionInfoPtr),
    pCount) then
  begin

    for i := 0 to pCount – 1 do
    begin
      WTSQuerySessionInformation(WTS_CURRENT_SERVER, SessionInfoPtr^[i].SessionId,
        WTSClientAddress, Pointer(ClientAddressPtr), dwBytesReturned);
      case ClientAddressPtr^.AddressFamily of
        AF_INET:
          IPStr:= Format(‘%d.%d.%d.%d’, [ClientAddressPtr^.Address[2],
            ClientAddressPtr^.Address[3], ClientAddressPtr^.Address[4],
            ClientAddressPtr^.Address[5]]);
          AF_INET6:
            IPStr:= ‘IPv6 address not yet supported’;
          AF_IPX:
            IPStr:= ‘IPX is not supported’;
          AF_NETBIOS:
            IPStr:= ‘NETBIOS is not supported’;
          AF_UNSPEC:
            IPStr:= ‘Unspecified (console and listener session have no address)’;
      end;

      WTSfreeMemory(ClientAddressPtr);
    end;
  end;

  // Don’t close the handle if it’s WTS_CURRENT_SERVER
  WtsFreeMemory(SessionInfoPtr);
end;

Screenshot:
Client IP demo app screenshot
ClientIP.zip (1155)

No related posts.