Thread: SetWindowLong nIndex argument

  1. #1
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99

    SetWindowLong nIndex argument

    I am a bit puzzled by the SetWindowLong function, as described here:

    SetWindowLong function

    Specifically, I cannot make sense of the offsets given for the argument nIndex. For example, GWL_USERDATA is -21 and GWL_EXSTYLE is -20. Since dwNewLong, the value being set, is long in each case, I would have expected the offsets all to be spaced at intervals of 4 bytes (-4, -8, -12 etc.). As it is, it seems to me that any value set with GWL_USERDATA is going to overwrite the first three bytes of a value set with GWL_EXSTYLE.

    Also, is it possible to find a definition somewhere for the structure (WND?) these offsets refer to?

    Thanks.

  2. #2
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Y'know what... you don't actually care what the numerical values are... just use the constants.

    For example:
    Code:
    SetWindowLong(gMainWind, GWL_STYLE, WS_OVERLAPPED);
    There's nothing hidden or undisclosed that would be of any use to you...

  3. #3
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99
    I know in practice it's not important to know the numerical values; I'm just really, really curious because it looks so wrong to me.

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Only positive values are treated as indexes into the window's "cbWndExtra" byte array.
    Code:
        SetWindowLong(hwnd, 0, 0x1234abcd);
        SetWindowLong(hwnd, 2, 0x77777777);
        LONG n = GetWindowLong(hwnd, 0);
        // n == 0x7777abcd on a 32bit OS
    Ideally, one would use SetWindowLongPtr/GetWindowLongPtr and the index value is incremented by sizeof(void*) for each "slot". Or use Window Properties.

    gg

  5. #5
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by DL1 View Post
    I know in practice it's not important to know the numerical values; I'm just really, really curious because it looks so wrong to me.
    Why? The numerical values are offsets from some internal point in the window struct... It's probably just pointer arithmetic.

  6. #6
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    ^ What Codeplug said as I was typing

    Maybe at one point the negative values were offsets from something or other, but the exact numbers could now be anything in any order. They're only use is in a switch statement.

    As for the WND struct, there's pretty much no point. You can't easily get at it from user mode (you need the user32.dll symbols and the dbghelp Sym* functions since @ValidateHwnd@4 isn't exported), and all the data is in kernel space anyway so you'd need a driver or kernel debugger to see what it contains.

    The layout is simpler to get at. Compile this (it comes with Visual Studio if you have that), grab the symbols for the platform of choice (either Vista/Server 2008/7), then run
    dia2dump -t C:\Path\To\win32k.pdb > win32ktypes.txt
    The definition for many User32 types are in the resulting text file. Or you can just look in the one I made earlier. Not sure what use it'll be though. Search for ": tagWND" without quotes to find it.
    Last edited by adeyblue; 10-13-2011 at 03:19 PM.

  7. #7
    Registered User
    Join Date
    Jun 2008
    Location
    Somewhere in Europe
    Posts
    99
    Quote Originally Posted by CommonTater View Post
    Why? The numerical values are offsets from some internal point in the window struct... It's probably just pointer arithmetic.
    That was what I was assuming. However, assuming that to be correct, adapting Codeplug's example gives:

    Code:
    SetWindowLong(hwnd, GWL_USERDATA, 0x1234abcd); // GWL_USERDATA = -21
    SetWindowLong(hwnd, GWL_EXSTYLE, 0x77777777); // GWL_EXSTYLE = -20
    LONG n = GetWindowLong(hwnd, GWL_USERDATA);
    // n == 0x7777ab77 on a 32bit OS? Something wrong here?!!
    If, however, as Codeplug and adeyblue say, only the positive values are treated as offsets, that would explain why the above does not occur.

  8. #8
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Naaaa... it's a block of dwords... stored in the createstruct for the window. GWL_EXSTYLE probably starts 20 bytes before the end of the block or maybe 20 dwords... giving a worst case offset of -80 bytes. The last dword value is just that... the value that gets dumped into that location. If you need to see it as code, it's probably something like....
    Code:
    *(Marker - GWL_USERDATA) = NewLong
    Marker is quite likely some key point in the struct... Also consider: What is 20 - -20?

    (At best all we can do is theorize because that code is not exactly given out.)

  9. #9
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Quote Originally Posted by CommonTater View Post
    (At best all we can do is theorize because that code is not exactly given out.)
    It's on your hard drive. The call chain to where they are used in the kernel is about 5 functions deep, in xxxSetWindowData:
    Code:
    mov     eax, [ebp+arg_4] ; where the index argument is on the stack
    cmp     eax, 0FFFFFFEBh ; GWLP_USERDATA
    jz      loc_BF8B42F8
    cmp     eax, 0FFFFFFECh ; GWL_EXSTYLE
    jz      loc_BF8B42E9
    cmp     eax, 0FFFFFFF0h ; GWL_STYLE
    jz      loc_BF8B42E9
    cmp     eax, 0FFFFFFF4h ; GWLP_ID
    jz      loc_BF8B4291
    cmp     eax, 0FFFFFFF8h ; GWLP_HWNDPARENT
    jz      loc_BF8B4185
    cmp     eax, 0FFFFFFFAh ; GWLP_HINSTANCE
    jz      loc_BF8B4174
    cmp     eax, 0FFFFFFFCh ; GWLP_WNDPROC
    jz      short loc_BF8B3F64
    ; and this for everything else
    push    eax
    push    offset aSetwindowlongI ; "SetWindowLong: Invalid index 0x%x"
    push    ebx
    push    378h
    push    edi
    push    2000000h
    call    _VRipOutput
    If they were used as offsets, you wouldn't check for each one individually.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Template Argument inside the Argument of a Function Declaration
    By manasij7479 in forum C++ Programming
    Replies: 3
    Last Post: 06-11-2011, 05:53 AM
  2. SetWindowLong
    By vopo in forum Windows Programming
    Replies: 3
    Last Post: 09-17-2007, 05:16 AM
  3. Optional argument
    By Probose in forum C++ Programming
    Replies: 3
    Last Post: 09-23-2006, 11:22 AM
  4. mode argument
    By prlove71 in forum C++ Programming
    Replies: 1
    Last Post: 03-09-2002, 11:43 AM
  5. Problems using SetWindowLong and GWL_USERDATA
    By xds4lx in forum Windows Programming
    Replies: 1
    Last Post: 02-25-2002, 12:47 AM