Jump to content

Recommended Posts

Posted

hello forum,

i'm currently struggling with reading the return values from DllCall()

Func _CheckIfRemoteSession()
    ;# uses WTSQuerySessionInformation from "Wtsapi32.dll" - see http://msdn.microsoft.com/en-us/library/windows/desktop/aa383838%28v=vs.85%29.aspx
    ;#
    ;# BOOL WTSQuerySessionInformation(
    ;#   __in   HANDLE hServer,
    ;#   __in   DWORD SessionId,
    ;#   __in   WTS_INFO_CLASS WTSInfoClass,
    ;#   __out  LPTSTR *ppBuffer,
    ;#   __out  DWORD *pBytesReturned
    ;# );

    ;# example how to use pinvoke (csharp):
    ;#  [DllImport("Wtsapi32.dll")]
    ;#  public static extern bool WTSQuerySessionInformation(System.IntPtr hServer, int sessionId, WTSInfoClass wtsInfoClass, out System.IntPtr ppBuffer, out uint pBytesReturned);

    Local Const $WTS_CURRENT_SESSION = -1
    Local Const $WTSClientProtocolType = 16
    Local $buffer = -1
    Local $bytesReturned = -1

    Local $retVal = DllCall("Wtsapi32.dll", "int", "WTSQuerySessionInformation", "ptr", 0, "int", $WTS_CURRENT_SESSION, "int", $WTSClientProtocolType, "ptr*", $buffer, "dword*", $bytesReturned)
    If @error Or ($retVal[0] == 0) Then Return (-1)

    MsgBox(0, "DEBUG", "retVal[0]: " & $retVal[0] & ", retVal[4]: " & $retVal[4] & ", retVal[5]: " & $retVal[5] & ", buffer: " & $buffer)

    ;# remote session (RDP) returns "2"
    ;# local sessoin returns "0"
EndFunc

in particular this is what i'm passing in: "ptr*", $buffer

and this is what i'm seeing in the msgbox to display the results:

retVal[0]: - 1 (return value)

retVal[4]: - 0x008F73D0 (the stuff i'm interested in)

retVal[5]: - 2 (BytesReturned)

buffer: -1 (the stuff i'm interested in)

so "0x008F73D0" looks like a pointer ...?

how do i read the value stored at this address?

with pinvoke (csharp) i have seen something like:

value = Marshal.ReadInt32( buffer );

how to achieve the same with autoit? what is it i'm missing?

thanks in advance, francoiste

Posted

$Ret = DllCall("wtsapi32.dll", "int", "WTSQuerySessionInformation", "ptr", 0, "int", -1, "uint", 16, "ptr*", 0, "dword*", 0)
ConsoleWrite(DllStructGetData(DllStructCreate('ushort', $Ret[4]), 1) & @CR)
DllCall("wtsapi32.dll", "none", "WTSFreeMemory", 'ptr', $Ret[4])

Posted

wow, thanks for the super quick response!

your suggested code works like a charm.

i guess all the magic lies in "DllStructGetData(DllStructCreate(...), 1)"

i'll try to do some more reading to fully understand ...

Posted

oh, well. i still don't get it, i'm afraid.

i want to handle scenarios with remote desktop, terminal services, citrix, and alike ...

first step is to gather all user sessions on localhost listing the following attributes:

  • $SessionId
  • $WinStationName
  • $ConnectState
it's all inside "wtsapi32.dll".

so first i need:

BOOL WTSEnumerateSessions(
  __in   HANDLE hServer,
  __in   DWORD Reserved,
  __in   DWORD Version,
  __out  PWTS_SESSION_INFO *ppSessionInfo,
  __out  DWORD *pCount
);

where it says for ppSessionInfo:

A pointer to a variable that receives a pointer to an array of WTS_SESSION_INFO structures. Each structure in the array contains information about a session on the specified RD Session Host server. To free the returned buffer, call the WTSFreeMemory function.

To enumerate a session, you must have "Query Information" permission.

ok, so this structure array consists of:

typedef struct _WTS_SESSION_INFO {
  DWORD               SessionId;
  LPTSTR                 pWinStationName;
  WTS_CONNECTSTATE_CLASS State;
} WTS_SESSION_INFO, *PWTS_SESSION_INFO;

and the WTS_CONNECTSTATE_CLASS is defined as follows:

typedef enum _WTS_CONNECTSTATE_CLASS {
  WTSActive,
  WTSConnected,
  WTSConnectQuery,
  WTSShadow,
  WTSDisconnected,
  WTSIdle,
  WTSListen,
  WTSReset,
  WTSDown,
  WTSInit
} WTS_CONNECTSTATE_CLASS;

i completely don't understand how to wrap those arrays and structures into DllStructGetData(DllStructCreate(...), ...)

i'd very much appreciate if someone could assist me in putting that information into the following array:

Local $avArray[3]
$avArray[0] = $SessionId
$avArray[1] = $WinStationName
$avArray[2] = $ConnectState

thanks in advance, francoiste

Posted (edited)

Global Const $tagWTS_SESSION_INFO = 'dword SessionId;ptr WinStationName;uint State'

$Ret = DllCall('wtsapi32.dll', 'int', 'WTSEnumerateSessionsW', 'ptr', 0, 'dword', 0, 'dword', 1, 'ptr*', 0, 'dword*', 0)

$Offset = 0
For $i = 1 To $Ret[5]
    $tInfo = DllStructCreate($tagWTS_SESSION_INFO, $Ret[4] + $Offset)
    $Offset += DllStructGetSize($tInfo)
    ConsoleWrite('SessionId:      ' & DllStructGetData($tInfo, 'SessionId') & @CR)
    ConsoleWrite('WinStationName: ' & DllStructGetData(DllStructCreate('wchar[1024]', DllStructGetData($tInfo, 'WinStationName')), 1) & @CR)
    ConsoleWrite('State:          ' & DllStructGetData($tInfo, 'State') & @CR)
    ConsoleWrite('--------------' & @CR)
Next

DllCall('wtsapi32.dll', 'none', 'WTSFreeMemory', 'ptr', $Ret[4])

Of course, you need to check for errors but you can do it yourself.

Edited by Yashied
  • 12 years later...

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...