Windows 8 and x64

I fixed a problem with the x64 edition of PngOptimizer on Windows 8: dialog boxes would not open. You can find a new version for x64 only (2.4.2) on the download page.

I don't have any Windows 8 around me so that bug unfortunately leaked. By chance a user kindly reported the problem to me and tested the new version. I hope I'll find a way to test all flavors of Windows for future release.

Now, the reason dialog boxes would not open is interesting.

PngOptimizer uses a C++ layer over the Windows graphical user interface API I have been maintaining for several years. This layer relies on links between Windows GUI objects and their related C++ object. With dialog boxes, the C++ object address is given as the user parameter when the dialog box is created.

To create the dialog box, I call DialogBoxParamW() which declares the user parameter as an integer. As I need to pass a pointer, a cast is needed. A long time ago when I was making the code ready for x64, I removed the pointer to integer cast warning by using the PtrToUlong() function. Unfortunately that was wrong, because the "Ulong" size returned by PtrToUlong is always 32 bits, which may lead to a corrupted pointer on x64 if the pointer value is big enough (greater than 0xFFFFFFFF).

The correct way to cast the pointer is to simply use the type declared for the user parameter by DialogBoxParamW: LPARAM. LPARAM is 32 bits on x86 and 64 bits on x64.

int Dialog::DoModalHelper(HINSTANCE hInstance, int dialogId, HWND hParent)
	INT_PTR ret = DialogBoxParamW(hInstance, 
 	                (DLGPROC) DlgProcStatic,
	                PtrToUlong(this) // Wrong! Should be LPARAM(this)
	return int(ret);

Now the question I have is how did it work reliably on Windows 7 x64 (and I guess, Vista x64). I cannot really prove the exact reason but I'll give my best guess. I think it is related to Address space layout randomization (ASLR).

The Dialog instances of PngOptimizer are always created on the stack. After several tests on Windows 7, I noticed the stack was always located at some low address in the process, and would always fit in a 32 bits integer. On Windows 8, I guess the address randomization works better and puts the stack of the process at higher addresses than 0xFFFFFFFF.