News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

WTS Structure Wrong?

Started by AgentSmithers, September 02, 2011, 02:25:37 AM

Previous topic - Next topic

AgentSmithers

.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\Ws2_32.inc
include \masm32\include\advapi32.inc
include \masm32\include\wtsapi32.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\Ws2_32.lib
includelib \masm32\lib\advapi32.lib
includelib \masm32\lib\wtsapi32.lib

include \masm32\include\masm32.inc
include \masm32\include\debug.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\debug.lib

TokenPrimary = 1
SecurityImpersonation = 2

WTS_SESSION_INFO STRUCT
  SessionId             DD      ?
  pWinStationName       BYTE    1 dup(?)
  State                 DD      ?
WTS_SESSION_INFO ENDS

.data

ServerName db "LOCALHOST", 0


.data?

ServerHandle dd ?
Count dd ?
ppSessionInfo dd ?
StructureArray WTS_SESSION_INFO 20 dup(<?>)



.code

start:

invoke WTSOpenServerA, NULL
mov ServerHandle, EAX
invoke WTSEnumerateSessions, EAX, 0, 1, OFFSET ppSessionInfo, ADDR Count
.IF EAX != 0
    PrintDec Count
    mov EAX, [ppSessionInfo]
    assume eax:ptr WTS_SESSION_INFO
    lea ebx, [EAX].pWinStationName
    PrintStringByAddr ebx
.ENDIF


end start


Hi Everyone, I'm not sure what I have wrong here but My goal is to cycle through the Structure array and print out all the SessionNames. For some reason EAX+4 is being referenced but "CONSOLE" in memory lays in EAX-4. Is there a problem with the way I formatted my structure?

drizz

LPTSTR is a pointer.

LP - Long Pointer
T - TCHAR
STR - STRing

...
pWinStationName       LPTSTR     ?
...

mov ebx, [EAX].pWinStationName


make sure PrintDec  and PrintStringByAddr preserve all registers(EAX).
The truth cannot be learned ... it can only be recognized.

ToutEnMasm


I have not the same with ready to use sdk
There is NO BYTE
Quote
;/*=====================================================================
;==   WTS_SESSION_INFO - returned by WTSEnumerateSessions (version 1)
;=====================================================================*/
;/*
; *  WTSEnumerateSessions() returns data in a similar format to the above
; *  WTSEnumerateServers().  It returns two variables: pSessionInfo and
; *  Count.  The latter is the number of WTS_SESSION_INFO structures
; *  contained in the former.  Iteration is similar, except that there
; *  are three parts to each entry, so it would look like this:
; *
; *  for ( i=0; i < Count; i++ ) {
; *      _tprintf( TEXT("%-5u  %-20s  %u\n"),
;                  pSessionInfo.SessionId,
; *                pSessionInfo.pWinStationName,
; *                pSessionInfo.State );
; *  }
; *
; *  The memory returned is also segmented as the above, with all the
; *  structures allocated at the start and the string data at the end.
; *  We'll use S for the SessionId, P for the pWinStationName pointer
; *  and D for the string data, and C for the connect State:
; *
; *  S1 P1 C1 S2 P2 C2 S3 P3 C3 S4 P4 C4 ... Sn Pn Cn D1 D2 D3 D4 ... Dn
; *
; *  As above, this makes it easier to iterate the sessions.
; */

WTS_SESSION_INFOW   STRUCT
   SessionId DWORD ? ; session id
   pWinStationName DWORD ? ; name of WinStation this session is
   State DWORD ? ; connection state (see enum)
WTS_SESSION_INFOW      ENDS



AgentSmithers

Quote from: ToutEnMasm on September 02, 2011, 12:19:13 PM

I have not the same with ready to use sdk
There is NO BYTE
Quote
;/*=====================================================================
;==   WTS_SESSION_INFO - returned by WTSEnumerateSessions (version 1)
;=====================================================================*/
;/*
; *  WTSEnumerateSessions() returns data in a similar format to the above
; *  WTSEnumerateServers().  It returns two variables: pSessionInfo and
; *  Count.  The latter is the number of WTS_SESSION_INFO structures
; *  contained in the former.  Iteration is similar, except that there
; *  are three parts to each entry, so it would look like this:
; *
; *  for ( i=0; i < Count; i++ ) {
; *      _tprintf( TEXT("%-5u  %-20s  %u\n"),
;                  pSessionInfo.SessionId,
; *                pSessionInfo.pWinStationName,
; *                pSessionInfo.State );
; *  }
; *
; *  The memory returned is also segmented as the above, with all the
; *  structures allocated at the start and the string data at the end.
; *  We'll use S for the SessionId, P for the pWinStationName pointer
; *  and D for the string data, and C for the connect State:
; *
; *  S1 P1 C1 S2 P2 C2 S3 P3 C3 S4 P4 C4 ... Sn Pn Cn D1 D2 D3 D4 ... Dn
; *
; *  As above, this makes it easier to iterate the sessions.
; */

WTS_SESSION_INFOW   STRUCT
   SessionId DWORD ? ; session id
   pWinStationName DWORD ? ; name of WinStation this session is
   State DWORD ? ; connection state (see enum)
WTS_SESSION_INFOW      ENDS



I don't understand your post.?

ToutEnMasm

Quote
WTS_SESSION_INFO STRUCT
  SessionId             DD      ?
  pWinStationName       BYTE    1 dup(?)      ;<<<<<<<<<<<<   DD  ? <<<<<<<<<<<<<<<<<<<<< ERROR HERE
  State                 DD      ?
WTS_SESSION_INFO ENDS


AgentSmithers

Thanks!
So its not a LPTSTR?

WTS_SESSION_INFO STRUCT
  SessionId             DWORD      ?
  pWinStationName       LPTSTR     ?
  State                 DWORD      ?
WTS_SESSION_INFO ENDS

.data

ServerName db "MyHost", 0

StructureArray WTS_SESSION_INFO<>

.data?

ServerHandle dd ?
Count dd ?
ppSessionInfo dd ?


.code

start:

invoke    WTSOpenServerA, ADDR ServerName
mov   ServerHandle, EAX
invoke   WTSEnumerateSessions, EAX, 0, 1, ADDR StructureArray, ADDR Count   <--- Load it into a structure? ***CHANGED****
.IF EAX != 0
    PrintDec Count
    mov EAX, StructureArray.pWinStationName
    PrintStringByAddr eax
.ENDIF

ToutEnMasm

Quote
LPTSTR = DWORD ; MAPIDefS.h
It is  LPTSTR. LP mean Low Pointer and  pointer is always (99%) a dword

qWord

Quote from: ToutEnMasm on September 02, 2011, 03:38:47 PMIt is  LPTSTR. LP mean Low Pointer and  pointer is always (99%) a dword
LP = long pointer = simply a pointer (long pointer = far pointer; the name has historically reasons).
pointers are allways DWORDs on x86-32.
FPU in a trice: SmplMath
It's that simple!

ToutEnMasm


You can begin a variable by LP and made this variable a QWORD ,there is no rule here.It's just a good usage.

qWord

Quote from: ToutEnMasm on September 02, 2011, 05:13:58 PM

You can begin a variable by LP and made this variable a QWORD ,there is no rule here.It's just a good usage.

you can use a QWORD to store the pointer, but this is waste of memory, because the upper DWORD will never be used (x86-32)  :8)
FPU in a trice: SmplMath
It's that simple!

ToutEnMasm


AgentSmithers

Quote from: AgentSmithers on September 02, 2011, 03:32:23 PM
Thanks!
So its not a LPTSTR?

WTS_SESSION_INFO STRUCT
  SessionId             DWORD      ?
  pWinStationName       LPTSTR     ?
  State                 DWORD      ?
WTS_SESSION_INFO ENDS

.data

ServerName db "MyHost", 0

StructureArray WTS_SESSION_INFO<>

.data?

ServerHandle dd ?
Count dd ?
ppSessionInfo dd ?


.code

start:

invoke    WTSOpenServerA, ADDR ServerName
mov   ServerHandle, EAX
invoke   WTSEnumerateSessions, EAX, 0, 1, ADDR StructureArray, ADDR Count   <--- Load it into a structure? ***CHANGED****
.IF EAX != 0
    PrintDec Count
    mov EAX, StructureArray.pWinStationName
    PrintStringByAddr eax
.ENDIF

This code is still not outputting "Console" :(

dedndave

.data?

StructureArray WTS_SESSION_INFO 20 dup(<?>)


you are not responsible for allocating this array
the function wants a pointer to a variable (dword) that receives the address of the array
- not a pointer to an array

....RTM

MichaelW

#13
It's not necessary to change the size of the fields of the structure, just change the alignment specified in the structure declaration. The default alignment is 1 so the structure as declared will be byte-packed, and the offsets of the fields will be 0,4,5 and the size of the structure will be 9 bytes. The fields are supposed to be stored at their "natural" alignment, which for the DWORD fields is a multiple of 4, so the offsets of the fields should be 0,4,8 and the structure size should be 12 bytes (verified using the PSDK structure declaration and the Microsoft VC2003 compiler). This declaration will produce the correct alignment (tested with ML 6.15 only):

EDIT: I'm asleep at the wheel again, there is no byte, only DWORDs so the default alignment of 1 is no problem. Where is the "Duh" smiley?


WTS_SESSION_INFO STRUCT
  SessionId         DWORD ?
  pWinStationName   DWORD ?
  State             DWORD ?
WTS_SESSION_INFO ENDS

eschew obfuscation

AgentSmithers

Quote from: MichaelW on September 02, 2011, 08:49:31 PM
It's not necessary to change the size of the fields of the structure, just change the alignment specified in the structure declaration. The default alignment is 1 so the structure as declared will be byte-packed, and the offsets of the fields will be 0,4,5 and the size of the structure will be 9 bytes. The fields are supposed to be stored at their "natural" alignment, which for the DWORD fields is a multiple of 4, so the offsets of the fields should be 0,4,8 and the structure size should be 12 bytes (verified using the PSDK structure declaration and the Microsoft VC2003 compiler). This declaration will produce the correct alignment (tested with ML 6.15 only):

WTS_SESSION_INFO STRUCT DWORD
  SessionId         DWORD ?
  pWinStationName   BYTE  ?
  State             DWORD ?
WTS_SESSION_INFO ENDS


That does make sense, I will give that a shot :)