Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Problem converting structures to 64-bit


  • Please log in to reply
5 replies to this topic
jballi
  • Members
  • 1029 posts
  • Last active:
  • Joined: 01 Oct 2005
I thought I had what I needed to convert structures for use on a 64-bit box. Handles and pointers use 8 bytes, everything else (WORD, DWORD, INT, UINT, LONG, etc.) remains the same as they have always been. Every article I've read on conversion to 64-bit seems to substantiate this information. Or so I thought...

The following MSDN page has a pretty good definition of most data types:
Windows Data Types

In real life, handles and pointers take 8 bytes as expected but the space allocated for other data types appears to be arbitrary. OK, I haven't figured out the pattern yet.

The following is a map of the CHOOSEFONT structure that I created for the Fnt library. I do not have a x64 box so the x64 information was identified and tested by forum members with a x64 box. Thanks.
 
CHOOSEFONT structure - x32 only
Syntax
                                            Type            Size    Offset  Comment
                                            ----            ----    -----   -------
typedef struct {
  DWORD        lStructSize;                 DWORD (UInt)    4       0
  HWND         hwndOwner;                   Handle          4       4     
  HDC          hDC;                         Handle          4       8   
  LPLOGFONT    lpLogFont;                   Pointer         4       12   
  INT          iPointSize;                  Int             4       16   
  DWORD        Flags;                       DWORD (UInt)    4       20   
  COLORREF     rgbColors;                   DWORD (UInt)    4       24   
  LPARAM       lCustData;                   Pointer         4       28   
  LPCFHOOKPROC lpfnHook;                    Pointer         4       32   
  LPCTSTR      lpTemplateName;              Pointer         4       36   
  HINSTANCE    hInstance;                   Handle          4       40   
  LPTSTR       lpszStyle;                   Pointer         4       44   
  WORD         nFontType;                   WORD (UShort)   2       48   
    Unused and/or missing from the documentation            2       50   
  INT          nSizeMin;                    Int             4       52   
  INT          nSizeMax;                    Int             4       56   
} CHOOSEFONT, *LPCHOOSEFONT;
                                                            ----
                                                            60   


CHOOSEFONT structure - x64 Only
##### Under construction.  This structure works but the offsets for unused
members have not been identified/confirmed.  The offsets for unused member are
currently set to "best guess".

                                            Type            Size    Offset      Comment
                                            ----            ----    ------      -------
typedef struct {
  DWORD        lStructSize;                 DWORD (UInt)    4            0*
    Unused and/or missing from the documentation            4       4
  HWND         hwndOwner;                   Handle          8            8*     
  HDC          hDC;                         Handle          8       16          Not used by ChooseFont API
  LPLOGFONT    lpLogFont;                   Pointer         8           24*
  INT          iPointSize;                  Int             4           32*
  DWORD        Flags;                       DWORD (UInt)    4           36*
  COLORREF     rgbColors;                   DWORD (UInt)    4           40*
  LPARAM       lCustData;                   Pointer         8       44
  LPCFHOOKPROC lpfnHook;                    Pointer         8       52
  LPCTSTR      lpTemplateName;              Pointer         8       60
  HINSTANCE    hInstance;                   Handle          8       68
  LPTSTR       lpszStyle;                   Pointer         8       76
  WORD         nFontType;                   WORD (UShort)   2       84
    Unused and/or missing from the documentation            2       86
    Unused and/or missing from the documentation            4       88
  INT          nSizeMin;                    Int             4           92**
  INT          nSizeMax;                    Int             4           96**
    Unused and/or missing from the documentation            4       100
} CHOOSEFONT, *LPCHOOSEFONT;
                                                            ----
                                                            104***
Notes for x64 structure
-----------------------
Offset values that are indented to the right have been confirmed.

* Identified by maestrith.  Tested and confirmed by okram.

** Identified, tested, and confirmed by okram

*** 103 is the minimum size of the structure.  104 also works.
Note that in the x64 structure, there are at least 3 unexplainable (at least to me) gaps in the structure. There may be more but 8 members were not used by my library and so they were not tested. I've discovered these undocumented gaps in other structures and I assume that I'll find them in many other structures.

Can anyone tell me what the method to the madness is? I would hate to convert to x64 using the trial and error method.

Thanks.

VxE
  • Moderators
  • 3622 posts
  • Last active: Dec 24 2015 02:21 AM
  • Joined: 07 Oct 2006
In 64-bit-land, pointers may be aligned so that their offset is a multiple of 8. In your example, the 'mysterious' 4 bytes between the struct's first and second members is the padding required to align hwndOwner.

I'm not sure if there are actual rules for when this occurs, it may depend on the compiler used to make the dll.

just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

We have to look into CommDlh.h to answer this problem:
 

#if !defined(_WIN64)
#include <pshpack1.h>         /* Assume byte packing throughout */
#endif

Default alignment is turned off for 32-bit environment.
 

typedef struct tagCHOOSEFONTW {
   DWORD           lStructSize;
   HWND            hwndOwner;          // caller's window handle
   HDC             hDC;                // printer DC/IC or NULL
   LPLOGFONTW      lpLogFont;          // ptr. to a LOGFONT struct
   INT             iPointSize;         // 10 * size in points of selected font
   DWORD           Flags;              // enum. type flags
   COLORREF        rgbColors;          // returned text color
   LPARAM          lCustData;          // data passed to hook fn.
   LPCFHOOKPROC    lpfnHook;           // ptr. to hook function
   LPCWSTR         lpTemplateName;     // custom template name
   HINSTANCE       hInstance;          // instance handle of.EXE that
                                       //   contains cust. dlg. template
   LPWSTR          lpszStyle;          // return the style field here
                                       // must be LF_FACESIZE or bigger
   WORD            nFontType;          // same value reported to the EnumFonts
                                       //   call back with the extra FONTTYPE_
                                       //   bits added
   WORD            ___MISSING_ALIGNMENT__;                                
   INT             nSizeMin;           // minimum pt size allowed &
   INT             nSizeMax;           // max pt size allowed if
                                       //   CF_LIMITSIZE is used
} CHOOSEFONTW;

We find an undocumented additional WORD member (___MISSING_ALIGNMENT__) explaining the gap in the 32-bit version.

 

But even using the default alignment rules we would get the same result:

CHOOSEFONT structure - x32 only
Syntax
                                            Type            Size    Offset  Comment
                                            ----            ----    -----   -------
typedef struct {
  DWORD        lStructSize;                 DWORD (UInt)    4       0
  HWND         hwndOwner;                   Handle          4       4
  HDC          hDC;                         Handle          4       8
  LPLOGFONT    lpLogFont;                   Pointer         4       12
  INT          iPointSize;                  Int             4       16
  DWORD        Flags;                       DWORD (UInt)    4       20
  COLORREF     rgbColors;                   DWORD (UInt)    4       24
  LPARAM       lCustData;                   Pointer         4       28
  LPCFHOOKPROC lpfnHook;                    Pointer         4       32
  LPCTSTR      lpTemplateName;              Pointer         4       36
  HINSTANCE    hInstance;                   Handle          4       40
  LPTSTR       lpszStyle;                   Pointer         4       44
  WORD         nFontType;                   WORD (UShort)   2       48
  INT          nSizeMin;                    Int             4 !     52      <<< aligned to 4-byte boundary (50 + 2)
  INT          nSizeMax;                    Int             4       56
} CHOOSEFONT, *LPCHOOSEFONT;
                                                            ----
                                                            60 

 
Now we look at the 64 bit version which uses default alignment:

CHOOSEFONT structure - x64 Only
                                            Type            Size    Offset      Comment
                                            ----            ----    ------      -------
typedef struct {
  DWORD        lStructSize;                 DWORD (UInt)    4       0
  HWND         hwndOwner;                   Handle          8 !     8  *        <<< aligned to 8-byte boundary (4 + 4)
  HDC          hDC;                         Handle          8 !     16          
  LPLOGFONT    lpLogFont;                   Pointer         8 !     24
  INT          iPointSize;                  Int             4       32
  DWORD        Flags;                       DWORD (UInt)    4       36
  COLORREF     rgbColors;                   DWORD (UInt)    4       40
  LPARAM       lCustData;                   Pointer         8 !     48 *        <<< aligned to 8-byte boundary (44 + 4)      
  LPCFHOOKPROC lpfnHook;                    Pointer         8 !     56
  LPCTSTR      lpTemplateName;              Pointer         8 !     64
  HINSTANCE    hInstance;                   Handle          8 !     72
  LPTSTR       lpszStyle;                   Pointer         8 !     80
  WORD         nFontType;                   WORD (UShort)   2       88
  WORD         ___MISSING_ALIGNMENT__;      WORD (UShort)   2       90
  INT          nSizeMin;                    Int             4       92
  INT          nSizeMax;                    Int             4       96
                                                            4       100 *       <<< structure size has to be aligned to a multiple of the largest member (8)
} CHOOSEFONT, *LPCHOOSEFONT;
                                                            ----
                                                            104

Edited by just me, 27 August 2013 - 05:32 AM.

Prefer ahkscript.org for the time being.


jballi
  • Members
  • 1029 posts
  • Last active:
  • Joined: 01 Oct 2005
Data structure alignment. In the words of the incomparable Johnny Carson, "I did not know that." Yes, you do need to read that in Johnny's voice to get the full effect.

Excellent feedback. I still have some research to do but the pieces are starting to fit into place. Thanks.

nepter
  • Members
  • 53 posts
  • Last active: Jun 05 2019 07:59 AM
  • Joined: 29 Jun 2012

This is due to structure alignment.



chaidy
  • Members
  • 57 posts
  • Last active: Oct 21 2015 05:53 PM
  • Joined: 20 Apr 2010
http://www.autohotke...e/?fromsearch=1