Jump to content

Recommended Posts

Posted (edited)

..was looking for UserName from SessionID so I put this together

#include <Debug.au3> ; for _DebugArrayDisplay()

; all you can get from _WTSQuerySessionInformation()
Global $i = _WTSQuerySessionInformation(-1, 4) ; current user's SessionId
Global $__a_WTS_INFO_CLASS = StringSplit("WTSInitialProgram,WTSApplicationName,WTSWorkingDirectory,WTSOEMId,WTSSessionId,WTSUserName," & _
"WTSWinStationName,WTSDomainName,WTSConnectState,WTSClientBuildNumber,WTSClientName,WTSClientDirectory,WTSClientProductId,WTSClientHardwareId," & _
"WTSClientAddress,WTSClientDisplay,WTSClientProtocolType,WTSIdleTime,WTSLogonTime,WTSIncomingBytes,WTSOutgoingBytes,WTSIncomingFrames," & _
"WTSOutgoingFrames,WTSClientInfo,WTSSessionInfo,WTSSessionInfoEx,WTSConfigInfo,WTSValidationInfo,WTSSessionAddressV4,WTSIsRemoteSession", ",", 2)
For $n = 0 To UBound($__a_WTS_INFO_CLASS) -1
    ConsoleWrite($n & @TAB & StringLeft($__a_WTS_INFO_CLASS[$n] & ' ________________', 24) & " " & _WTSQuerySessionInformation($i, $n, 1) & @CRLF)
Next

Global $a = ListUserSessions()
_DebugArrayDisplay($a, "ListUserSessions()")

Func ListUserSessions() ; mod. of https://www.autoitscript.com/forum/topic/139774-dllcall-and-returned-pointers/?do=findComment&comment=980850
    Local $_Self_SessionId = _WTSQuerySessionInformation(-1, 4) ; -1 = current user ; 4 = WTSSessionId
    Local Enum $e_IsSelf_SessionId, $e_SessionName, $e_UserName, $e_SessionId, $e_StateName, $e_StateInt, $e_ClientName, $e_ClientIp, $e_Domain, $e_UBound
    Local Const $tagWTS_SESSION_INFO = 'dword SessionId;ptr WinStationName;uint State'
    Local $aResult = DllCall('wtsapi32.dll', 'int', 'WTSEnumerateSessionsW', 'ptr', 0, 'dword', 0, 'dword', 1, 'ptr*', 0, 'dword*', 0)
    If @error Or $aResult[0] = 0 Then Return SetError(1, 0, "") ; https://docs.microsoft.com/en-us/windows/desktop/api/wtsapi32/ne-wtsapi32-_wts_connectstate_class
    Local $aConnectionState = StringSplit("Active,Connected,ConnectQuery,Shadow,Disconnected,Idle,Listen,Reset,Down,Init", ",", 2)
    Local $tInfo, $Offset = 0, $c = 0, $aReturn[$aResult[5] + 1][$e_UBound] ; $e_UBound is the last enumerator, just to determine the size of the array
    $aReturn[0][$e_SessionId] = "ID"
    $aReturn[0][$e_SessionName] = "SessionName"
    $aReturn[0][$e_StateInt] = "StateInt"
    $aReturn[0][$e_StateName] = "State"
    $aReturn[0][$e_UserName] = "UserName"
    $aReturn[0][$e_ClientName] = "ClientName"
    $aReturn[0][$e_ClientIp] = "ClientIp"
    $aReturn[0][$e_Domain] = "Domain"
    For $i = 1 To $aResult[5]
        $tInfo = DllStructCreate($tagWTS_SESSION_INFO, $aResult[4] + $Offset)
        $Offset += DllStructGetSize($tInfo)
        $c += 1
        $aReturn[$c][$e_SessionId] = DllStructGetData($tInfo, 'SessionId')
        $aReturn[$c][$e_SessionName] = DllStructGetData(DllStructCreate('wchar[1024]', DllStructGetData($tInfo, 'WinStationName')), 1)
        $aReturn[$c][$e_StateInt] = DllStructGetData($tInfo, 'State')
        If UBound($aConnectionState) > $aReturn[$c][$e_StateInt] Then $aReturn[$c][$e_StateName] = $aConnectionState[$aReturn[$c][$e_StateInt]]
        $aReturn[$c][$e_UserName] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 5) ; WTSUserName
        $aReturn[$c][$e_ClientName] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 10) ; WTSClientName
        $aReturn[$c][$e_ClientIp] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 14) ; WTSClientAddress
        $aReturn[$c][$e_Domain] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 7) ; WTSDomainName
        $aReturn[0][$e_IsSelf_SessionId] = $c
        If $_Self_SessionId = $aReturn[$c][$e_SessionId] Then
            $aReturn[$c][$e_IsSelf_SessionId] = 1
        Else
            $aReturn[$c][$e_IsSelf_SessionId] = 0
        EndIf
    Next
    DllCall('wtsapi32.dll', 'none', 'WTSFreeMemory', 'ptr', $aResult[4])
    Return $aReturn
EndFunc   ;==>ListUserSessions

Func _WTSQuerySessionInformation($SessionId, $WTSInfoClass = 10, $iReturnAsIs = 0) ; mod. of https://www.autoitscript.com/forum/topic/134679-get-hostname-of-the-client-connected-to-the-terminalserver-session/
    Local $aResult = DllCall("Wtsapi32.dll", "int", "WTSQuerySessionInformation", "Ptr", 0, "int", $SessionId, "int", $WTSInfoClass, "ptr*", 0, "dword*", 0)
    If @error Or $aResult[0] = 0 Then Return SetError(1, 0, "")
    Local $ip = DllStructGetData(DllStructCreate("byte[" & $aResult[5] & "]", $aResult[4]), 1)
    DllCall("Wtsapi32.dll", "int", "WTSFreeMemory", "ptr", $aResult[4])
    If $iReturnAsIs Then Return $ip
    Switch $WTSInfoClass ; https://docs.microsoft.com/en-us/windows/desktop/api/wtsapi32/ns-wtsapi32-_wts_client_address
        Case 4 ; WTSSessionId
            Return Int('0x' & StringTrimRight(StringReverse($ip), 3))

        Case 14 ; WTSClientAddress
            If Not (Int(StringLeft($ip, 4)) = 2) Then ; IPv4
                $ip = ""
            Else
                $ip = Dec(StringMid($ip, 15, 2)) & '.' & Dec(StringMid($ip, 17, 2)) & '.' & Dec(StringMid($ip, 19, 2)) & '.' & Dec(StringMid($ip, 21, 2))
            EndIf

    EndSwitch
    Return StringReplace(BinaryToString($ip), Chr(0), "")
EndFunc   ;==>_GetWTSClientName

 

Edited by argumentum
better code

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

  • 4 months later...
  • Solution
Posted

I just wanted to get the current users SessionID so I pulled just a little out of what you posted.

I also added the 29 to the function to verify that the session you specified is a Remote session or not.

 

The Microsoft link to figure out the WTSInfoClass values was broken but I found them and figured i'd post here in case someone else wants it.

 

;Options for the $SessionID
    Global Static $WTS_CURRENT_SESSION = -1

;Options for the $WTSInfoClass
    Global Static $WTSInitialProgram = 0
    Global Static $WTSApplicationName = 1
    Global Static $WTSWorkingDirectory = 2
    Global Static $WTSOEMId = 3
    Global Static $WTSSessionId = 4
    Global Static $WTSUserName = 5
    Global Static $WTSWinStationName = 6
    Global Static $WTSDomainName = 7
    Global Static $WTSConnectState = 8
    Global Static $WTSClientBuildNumber = 9
    Global Static $WTSClientName = 10
    Global Static $WTSClientDirectory = 11
    Global Static $WTSClientProductId = 12
    Global Static $WTSClientHardwareId = 13
    Global Static $WTSClientAddress = 14
    Global Static $WTSClientDisplay = 15
    Global Static $WTSClientProtocolType = 16
    Global Static $WTSIdleTime = 17
    Global Static $WTSLogonTime = 18
    Global Static $WTSIncomingBytes = 19
    Global Static $WTSOutgoingBytes = 20
    Global Static $WTSIncomingFrames = 21
    Global Static $WTSOutgoingFrames = 22
    Global Static $WTSClientInfo = 23
    Global Static $WTSSessionInfo = 24
    Global Static $WTSSessionInfoEx = 25
    Global Static $WTSConfigInfo = 26
    Global Static $WTSValidationInfo = 27
    Global Static $WTSSessionAddressV4 = 28
    Global Static $WTSIsRemoteSession = 29


$id = _WTSQuerySessionInformation($WTS_CURRENT_SESSION, $WTSSessionId) ;Get the current users SessionId
ConsoleWrite("My Session ID:  " & $id & @CRLF)

$Username = _WTSQuerySessionInformation($WTS_CURRENT_SESSION, $WTSUserName) ;Get the username for the specified session
ConsoleWrite("My Username:  " & $Username & @CRLF)

$Username = _WTSQuerySessionInformation($WTS_CURRENT_SESSION, $WTSIsRemoteSession) ;Can verify that the session is Remote
ConsoleWrite("IsRemote?  " & $Username & @CRLF)



Func _WTSQuerySessionInformation($SessionId = -1, $WTSInfoClass = 10, $iReturnAsIs = 0) ; mod. of https://www.autoitscript.com/forum/topic/134679-get-hostname-of-the-client-connected-to-the-terminalserver-session/
    Local $aResult = DllCall("Wtsapi32.dll", "int", "WTSQuerySessionInformation", "Ptr", 0, "int", $SessionId, "int", $WTSInfoClass, "ptr*", 0, "dword*", 0)
    If @error Or $aResult[0] = 0 Then Return SetError(1, 0, "")
    Local $ip = DllStructGetData(DllStructCreate("byte[" & $aResult[5] & "]", $aResult[4]), 1)
    DllCall("Wtsapi32.dll", "int", "WTSFreeMemory", "ptr", $aResult[4])
    If $iReturnAsIs Then Return $ip
    Switch $WTSInfoClass
        Case 4 ; We want the WTSSessionId
            Return Int('0x' & StringTrimRight(StringReverse($ip), 3))

        Case 29 ; 1 = this is a remote session, 0 means its a physical session  $WTSIsRemoteSession
            Return Int('0x' & StringTrimRight(StringReverse($ip), 3))

        Case 14 ; We want the WTSClientAddress
            If Not (Int(StringLeft($ip, 4)) = 2) Then ; IPv4
                $ip = ""
            Else
                $ip = Dec(StringMid($ip, 15, 2)) & '.' & Dec(StringMid($ip, 17, 2)) & '.' & Dec(StringMid($ip, 19, 2)) & '.' & Dec(StringMid($ip, 21, 2))
            EndIf

    EndSwitch
    Return StringReplace(BinaryToString($ip), Chr(0), "")
EndFunc   ;==>_GetWTSClientName

 

  • 5 months later...
Posted

@argumentum

So I will be the first to admit I don't understand dll structure and converting back to readable data.  I have been toying with your listusersessions array trying to understand it and get it to pull the data I want.   But I need two additional columns of info.  WTSLogonTime & WTSIdleTime.  Here are the changes I have made to your base code but I don't think I am converting things correctly.  If you could help me understand what I am doing wrong and where I can find the different structures for each property.  I believe I want to create an array that list all the properties for all sessions.   I made no changes to the function  _WTSQuerySessionInformation

 

Func ListUserSessions() ; mod. of https://www.autoitscript.com/forum/topic/139774-dllcall-and-returned-pointers/?do=findComment&comment=980850
    Local $_Self_SessionId = _WTSQuerySessionInformation(-1, 4) ; -1 = current user ; 4 = WTSSessionId
    Local Enum $e_IsSelf_SessionId, $e_SessionName, $e_UserName, $e_SessionId, $e_StateName, $e_StateInt, $e_ClientName, $e_ClientIp, $e_Domain, $e_IdleTime, $e_LogonTime, $e_UBound
    Local Const $tagWTS_SESSION_INFO = 'dword SessionId;ptr WinStationName;uint State'
    Local $aResult = DllCall('wtsapi32.dll', 'int', 'WTSEnumerateSessionsW', 'ptr', 0, 'dword', 0, 'dword', 1, 'ptr*', 0, 'dword*', 0)
    If @error Or $aResult[0] = 0 Then Return SetError(1, 0, "") ; https://docs.microsoft.com/en-us/windows/desktop/api/wtsapi32/ne-wtsapi32-_wts_connectstate_class
    Local $aConnectionState = StringSplit("Active,Connected,ConnectQuery,Shadow,Disconnected,Idle,Listen,Reset,Down,Init", ",", 2)
    Local $tInfo, $Offset = 0, $c = 0, $aReturn[$aResult[5] + 1][$e_UBound] ; $e_UBound is the last enumerator, just to determine the size of the array
    $aReturn[0][$e_SessionId] = "ID"
    $aReturn[0][$e_SessionName] = "SessionName"
    $aReturn[0][$e_StateInt] = "StateInt"
    $aReturn[0][$e_StateName] = "State"
    $aReturn[0][$e_UserName] = "UserName"
    $aReturn[0][$e_ClientName] = "ClientName"
    $aReturn[0][$e_ClientIp] = "ClientIp"
    $aReturn[0][$e_Domain] = "Domain"
    $aReturn[0][$e_IdleTime] = "IdleTime"
    $aReturn[0][$e_LogonTime] = "LogonTime"
    For $i = 1 To $aResult[5]
        $tInfo = DllStructCreate($tagWTS_SESSION_INFO, $aResult[4] + $Offset)
        $Offset += DllStructGetSize($tInfo)
        $c += 1
        $aReturn[$c][$e_SessionId] = DllStructGetData($tInfo, 'SessionId')
        $aReturn[$c][$e_SessionName] = DllStructGetData(DllStructCreate('wchar[1024]', DllStructGetData($tInfo, 'WinStationName')), 1)
        $aReturn[$c][$e_StateInt] = DllStructGetData($tInfo, 'State')
        If UBound($aConnectionState) > $aReturn[$c][$e_StateInt] Then $aReturn[$c][$e_StateName] = $aConnectionState[$aReturn[$c][$e_StateInt]]
        $aReturn[$c][$e_UserName] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 5) ; WTSUserName
        $aReturn[$c][$e_ClientName] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 10) ; WTSClientName
        $aReturn[$c][$e_ClientIp] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 14) ; WTSClientAddress
        $aReturn[$c][$e_Domain] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 7) ; WTSDomainName
        $aReturn[$c][$e_IdleTime] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 17) ; WTSIdleTime
        $aReturn[$c][$e_LogonTime] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 18) ; WTSLogonTime
        $aReturn[0][$e_IsSelf_SessionId] = $c
        If $_Self_SessionId = $aReturn[$c][$e_SessionId] Then
            $aReturn[$c][$e_IsSelf_SessionId] = 1
        Else
            $aReturn[$c][$e_IsSelf_SessionId] = 0
        EndIf
    Next
    DllCall('wtsapi32.dll', 'none', 'WTSFreeMemory', 'ptr', $aResult[4])
    Return $aReturn
EndFunc   ;==>ListUserSessions

 

Posted
9 hours ago, Nhardel said:

Bump

Hey @Bump, to tell the truth, I did not code it. The links to the original code should be as comments in the code. I modified it to fit my needs after a long hours of trance like state.
I've got lots of unrelated work to do and can't afford the getting into the request right now, as I too suck at all these DLL stuff.

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

  • 4 years later...
Posted
22 minutes ago, argumentum said:

I didn't know/remember, that there was a problem with it.

The problem reported by @Nhardel about WTSLogonTime & WTSIdleTime but reading your post again I managed how to read it (from WTSSessionInfo [24])

 

I checked your RDPShadow app but I can't find clear information what this app do?
By the way, do you have au3 code for this app?

Posted

..is a mess of code. Didn't code thinking of sharing it, given that the script is an app and the code is all over the forum.
Not all things work as expected. The idle time of the other sessions may not work.**

What the app does is to shadow a session. Instead of using the command line, I made this to "click  click" into a session.
Thought that others may have use for it and shared it.
The ones that do admin know how to set the PC up for it's use, others, I will not enlighten as it could be misused.

** If needed in an "unattended fashion", a script with _WinAPI_GetIdleTime() could provide the admin that info, with an API that loads on every user on login ( we all here can put something like that together in a thousand different ways ) .
But my aim was to give live support to a user and the user would be on the phone, knowing that am shadowing the session to click-click on their behalf as if magic, because some users are really clueless. This solves the problem without a teamviewer/rustDest or what not, that could expose the workstation to unauthorized entry ( due to zero-day, etc. )

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...