Is there a known issue with calling CreateWindowExA on Windows 8 (64-bit) for a 64-bit application?
Context: I'm using the FOX Toolkit (FOX STABLE 1.6.46). When compling and running the most trivial Hello World sample ("hello"), the call to CreateWindowExA
in file FXWindow.cpp:1345 returns a zero HWND handle (but GetLastError()
doesn't report an error). This only happens in one specific configuration:
OS | OS Platform | App compiled for | CreateWindowExA succeeds? |
Windows 7 | 32-bit | 32-bit | YES |
Windows 7 | 64-bit | 32-bit | YES |
Windows 7 | 64-bit | 64-bit | YES |
Windows 8 | 64-bit | 32-bit | YES |
Windows 8 | 64-bit | 64-bit | NO! (returns NULL) |
Is there anything different about CreateWindowExA
with the last configuration. Please note that the window procedure is the same in all cases, and that the messages it receives are the following, in that order:
WM_GETMINMAXINFO
(forwarded to DefWindowProc
)WM_NCCREATE
(forwarded to DefWindowProc
)In the last configuration, it goes on with WM_NCDESTROY
and then CreateWindowExA
returns NULL.
In all other configurations, WM_NCCALCSIZE
is sent and finally WM_CREATE
.
I've found the source problem: FOX incorrectly defines the function signature of the window procedure as
long CALLBACK wndproc(FXID hwnd,unsigned iMsg,unsigned int wParam,long lParam);
(with FXID
typedef'd to void*
), so on 64-bit Windows, wParam
and lParam
are only 32-bit wide, whereas they should be 64-bit. The correct function signature (using FOX types) is:
FXival CALLBACK wndproc(FXID hwnd,unsigned int iMsg,FXuval wParam,FXival lParam);
So why did it work in 64-bit Windows up to Windows 7? As MSDN says:
The
lParam
ofWM_NCCREATE
contains a pointer to the CREATESTRUCT structure that contains information about the window being created. The members of CREATESTRUCT are identical to the parameters of the CreateWindowEx function.
It so happens that on Windows 7 (64-bit) and below, that structure was always allocated in memory below 4GB, and even though the pointer value was truncated to 32-bit, it still pointed to the correct location. As of Windows 8, that structure is allocated anywhere in the 64-bit memory range, and truncating it is likely to produce an incorrect pointer.
There is just one thing I'm unsure about: CALLBACK
being __stdcall
, arguments are pushed onto the stack from right to left. So, given the incorrect declaration of the windproc
, is it still retrieving the correct iMsg
and hwnd
parameters?