Sign in to follow this  
Followers 0
francoiste

DllCall and returned pointers?

6 posts in this topic

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

Share this post


Link to post
Share on other sites



$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])

Share this post


Link to post
Share on other sites

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 ...

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

#5 ·  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
1 person likes this

Share this post


Link to post
Share on other sites

thank you so much!!

you are genius!

Share this post


Link to post
Share on other sites

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
Sign in to follow this  
Followers 0