• Would some throw this together for me?

    From T@21:1/5 to All on Mon Nov 28 22:08:21 2022
    Hi All,

    Windows 11 Pro 22H2

    I program in Raku and can barely read C++

    I pulled this off an M$ Forum. The idea was
    to give you the size of a structure in bytes
    of a structure:


    This is the structure:

    C++
    typedef struct _WTS_SESSION_INFOA {
    DWORD SessionId; # 4 bytes
    LPSTR pWinStationName; # 4 or 8 bytes
    WTS_CONNECTSTATE_CLASS State; # 4 bytes
    } WTS_SESSION_INFOA, *PWTS_SESSION_INFOA;



    This is the result:


    int nSize1 = sizeof WTS_SESSION_INFOA; // 12 in x86, 24 in x64
    // x64

    int nSize1 = sizeof WTS_SESSION_INFOA; // 24
    int nOffset1 = offsetof(WTS_SESSION_INFOA, SessionId); // 0
    int nOffset2 = offsetof(WTS_SESSION_INFOA, pWinStationName); // 8
    int nOffset3 = offsetof(WTS_SESSION_INFOA, State); // 16


    I need these sizes to user Raku's NativeCall.

    Would someone please throw together the C++ code
    so I can duplicate it? (And use it for other
    structure in the future.)

    Also, when you do and if you have access to 32 bit
    Windows, I need those results too (I have no
    32 bit Windows at the moment.)

    Many thanks,
    -T

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Tue Nov 29 08:04:54 2022
    T,

    The idea was to give you the size of a structure in bytes of a structure:
    ...
    I need these sizes to user Raku's NativeCall.

    That won't be possible I'm afraid. "sizeof" and "offsetoff" are pseudo-commands, resolved at compile, not runtime.

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From T@21:1/5 to R.Wieser on Mon Nov 28 23:27:54 2022
    On 11/28/22 23:04, R.Wieser wrote:
    T,

    The idea was to give you the size of a structure in bytes of a structure:
    ...
    I need these sizes to user Raku's NativeCall.

    That won't be possible I'm afraid. "sizeof" and "offsetoff" are pseudo-commands, resolved at compile, not runtime.

    Regards,
    Rudy Wieser



    How'd he come up with them?

    I do not care if the compilers tells me or
    if a running program prints it out. Either
    gives me the information I need.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From T@21:1/5 to R.Wieser on Tue Nov 29 01:12:14 2022
    On 11/29/22 00:46, R.Wieser wrote:
    T,

    How'd he come up with them?

    "Them" ? I'm not sure what you are referring to.

    If you mean the lines you posted as "the result", than you should know its a misnomer. Its not the *result*, its just how you ask for those (already existing!) constants.

    Take a look

    typedef struct _WTS_SESSION_INFOA {
    DWORD SessionId; # 4 bytes
    LPSTR pWinStationName; # 4 or 8 bytes
    WTS_CONNECTSTATE_CLASS State; # 4 bytes
    }

    (assuming that you are on a 32-bit machine that LPSTR is going to be 32 bit too)

    You can go thru the offsets and sizes yourself :

    The first field thats declared is "SessionId", of type DWORD, which is 4 bytes. As its the first field its located at offset 0.

    The second field thats declared is "pWinStationName", of type LPSTR, which
    is (also) 4 bytes. Its offset is the previous fields offset plus its size*, being 0 + 4, so its at offset 4.

    The third field is "State" of type WTS_CONNECTSTATE_CLASS. Now it gets tricky, as you have to find that type back somewhere (in the multitude of
    *.h (header files) ) and figure out what its size is. Lets assume 4 bytes (its just a DWORD in disguise). Its offset is again the previous fields offset plus its size, being 4 + 4, so its at offset 8.

    The size of the whole structure is ofcourse (again) the offset of the last field plus its size, being 8 + 4, so it is 12 bytes long.

    And that matches the comment after the first line in the result : "12 in
    x86"


    But remember that "*" that I tagged onto that "plus its size" ? Yeah, here is the thing: machines are a fussy about where start of its data pieces should be. There is a thing called "alignment".

    Lets again take a look and assume we are now on a 64-bit machine. It
    expects an alignment of 8. The "SessionId" field will still be just 4 bytes. So, how is it that the "pWinStationName" field after it is at
    offset 8 ? Thats where padding comes in : it just fills out the space until the next allowed offset :

    On a 64-bit machine :

    (best viewed with a fixed width font. Copy it into notepad ?)

    typedef struct _WTS_SESSION_INFOA {
    DWORD SessionId; # 4 bytes - padding needed
    DWORD ? // the padding. Unnamed, unused
    LPSTR pWinStationName; # 8 bytes - No padding
    WTS_CONNECTSTATE_CLASS State; # 4 bytes - padding needed
    DWORD ? // the padding. Unnamed, unused
    }

    And now the structure matches the comments in the "result" in its full, including the "24 in x64" remark from the first line. :-)


    Mind you, not all functions expect the data to be aligned. But for those
    who do the above is how it works. And by the way, although it was not relevant to the above structure (it fits just fine) the x86 has an alignment of 4. IOW, if the first field would have been a byte it would be followed by, on an x86 machine, a padding of 3 bytes

    Hope that helps.

    ... but you still need to do all that work by hand - or put the structure in a compiler and let it output those values ofcourse.

    Regards,
    Rudy Wieser

    P.s.
    That alignment also means that your structure-storage needs to be placed at
    a multiple of that alignment value. If you don't the function trying to use will just throw an "bad argument" error. Don't ask me how I know that. :-)



    Thank you!

    I plan on printing out the contents of the structure
    byte by byte and see what I find. I will presalt
    the result with 0xFF and see what agets changed.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Tue Nov 29 09:46:35 2022
    T,

    How'd he come up with them?

    "Them" ? I'm not sure what you are referring to.

    If you mean the lines you posted as "the result", than you should know its a misnomer. Its not the *result*, its just how you ask for those (already existing!) constants.

    Take a look

    typedef struct _WTS_SESSION_INFOA {
    DWORD SessionId; # 4 bytes
    LPSTR pWinStationName; # 4 or 8 bytes
    WTS_CONNECTSTATE_CLASS State; # 4 bytes
    }

    (assuming that you are on a 32-bit machine that LPSTR is going to be 32 bit too)

    You can go thru the offsets and sizes yourself :

    The first field thats declared is "SessionId", of type DWORD, which is 4
    bytes. As its the first field its located at offset 0.

    The second field thats declared is "pWinStationName", of type LPSTR, which
    is (also) 4 bytes. Its offset is the previous fields offset plus its size*, being 0 + 4, so its at offset 4.

    The third field is "State" of type WTS_CONNECTSTATE_CLASS. Now it gets
    tricky, as you have to find that type back somewhere (in the multitude of
    *.h (header files) ) and figure out what its size is. Lets assume 4 bytes
    (its just a DWORD in disguise). Its offset is again the previous fields offset plus its size, being 4 + 4, so its at offset 8.

    The size of the whole structure is ofcourse (again) the offset of the last field plus its size, being 8 + 4, so it is 12 bytes long.

    And that matches the comment after the first line in the result : "12 in
    x86"


    But remember that "*" that I tagged onto that "plus its size" ? Yeah, here
    is the thing: machines are a fussy about where start of its data pieces
    should be. There is a thing called "alignment".

    Lets again take a look and assume we are now on a 64-bit machine. It
    expects an alignment of 8. The "SessionId" field will still be just 4
    bytes. So, how is it that the "pWinStationName" field after it is at
    offset 8 ? Thats where padding comes in : it just fills out the space until the next allowed offset :

    On a 64-bit machine :

    (best viewed with a fixed width font. Copy it into notepad ?)

    typedef struct _WTS_SESSION_INFOA {
    DWORD SessionId; # 4 bytes - padding needed
    DWORD ? // the padding. Unnamed, unused
    LPSTR pWinStationName; # 8 bytes - No padding
    WTS_CONNECTSTATE_CLASS State; # 4 bytes - padding needed
    DWORD ? // the padding. Unnamed, unused
    }

    And now the structure matches the comments in the "result" in its full, including the "24 in x64" remark from the first line. :-)


    Mind you, not all functions expect the data to be aligned. But for those
    who do the above is how it works. And by the way, although it was not
    relevant to the above structure (it fits just fine) the x86 has an alignment
    of 4. IOW, if the first field would have been a byte it would be followed
    by, on an x86 machine, a padding of 3 bytes

    Hope that helps.

    ... but you still need to do all that work by hand - or put the structure in
    a compiler and let it output those values ofcourse.

    Regards,
    Rudy Wieser

    P.s.
    That alignment also means that your structure-storage needs to be placed at
    a multiple of that alignment value. If you don't the function trying to use will just throw an "bad argument" error. Don't ask me how I know that. :-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Tue Nov 29 10:51:17 2022
    T,

    Thank you!

    You're welcome. :-) And I assume that was the information you wher
    missing

    I plan on printing out the contents of the structure
    byte by byte and see what I find. I will presalt
    the result with 0xFF and see what agets changed.

    Good idea.

    A suggestion though : first look at the structures bytes when you have not given the fields a value. If you get anything else than a single byte value back than "memfill" the whole structure with a certain value first, and only than put stuff ito the fields (possibly also memfill-ing each of them, preferrably with a different value. Makes it easier to see where one field ends and the padding or the next field starts).

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From T@21:1/5 to R.Wieser on Tue Nov 29 02:19:40 2022
    On 11/29/22 01:51, R.Wieser wrote:
    T,

    Thank you!

    You're welcome. :-) And I assume that was the information you wher
    missing

    I plan on printing out the contents of the structure
    byte by byte and see what I find. I will presalt
    the result with 0xFF and see what agets changed.

    Good idea.

    A suggestion though : first look at the structures bytes when you have not given the fields a value. If you get anything else than a single byte value back than "memfill" the whole structure with a certain value first, and only than put stuff ito the fields (possibly also memfill-ing each of them, preferrably with a different value. Makes it easier to see where one field ends and the padding or the next field starts).

    Regards,
    Rudy Wieser



    The variable I am sending will be created with
    backfill:

    my $SessionArray = CArray[BYTE].new( 0xFF xx $Length );

    Means $SessionArray will be $Length Bytes long
    and each byte will be filled with 0xFF

    Then I see what gets overwritten.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From T@21:1/5 to R.Wieser on Tue Nov 29 04:33:49 2022
    On 11/29/22 04:30, R.Wieser wrote:
    T,

    The variable I am sending will be created with
    backfill:

    my $SessionArray = CArray[BYTE].new( 0xFF xx $Length );

    Ah yes. You're not creating the structure itself, you create some space for it and than cast that $SessionArray pointer to a WTS_SESSION_INFOA one (so you can access its fields).

    That works too. :-)

    Is that stil C, or Raku ?

    Regards,
    Rudy Wieser




    it is Raku attempting to call a C API

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From R.Wieser@21:1/5 to All on Tue Nov 29 13:30:26 2022
    T,

    The variable I am sending will be created with
    backfill:

    my $SessionArray = CArray[BYTE].new( 0xFF xx $Length );

    Ah yes. You're not creating the structure itself, you create some space for
    it and than cast that $SessionArray pointer to a WTS_SESSION_INFOA one (so
    you can access its fields).

    That works too. :-)

    Is that stil C, or Raku ?

    Regards,
    Rudy Wieser

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)