Ronald Ruijs
Ronald Ruijs

Reputation: 67

Delphi 11.2: CreateWindowEx fails thread on x64

I'm using Peter Below's PBThreadedSplashForm to display a splash window during application startup.

This component worked great for 10 years, but, since updating my Delphi to 11.2, I get an AV on the CreateWindowEx call.

This happens on Win64 platform only, on problems on Win32.

Anyone who knows what can be the cause of this?

Upvotes: 2

Views: 386

Answers (1)

Andreas Rejbrand
Andreas Rejbrand

Reputation: 109003

This is one of the many issues that have surfaced in 11.2 due to the new default ASLR settings in the compiler and linker.

After a very quick glance at the source code I see this:

SetWindowLong( wnd, GWL_WNDPROC, Integer( thread.FCallstub ));

thread.FCallstub is defined as Pointer.

Just as I thought.

You see, pointers are of native size, so in 32-bit applications, pointers are 32 bits wide, while in 64-bit applications, pointers are 64 bits wide.

It was very common in the 32-bit world that pointer values were temporarily saved in Integers. This worked because a 32-bit pointer fits in a 32-bit Integer.

But in a 64-bit application, this is an obvious bug, since a 64-bit pointer doesn't fit in a 32-bit Integer. It's like taking a phone number like 5362417812 and truncating it to 17812, hoping that it will still "work".

Of course, in general, this causes bugs such as AVs and memory corruption.

However, until recently, there was a rather high probability that a pointer in a 64-bit Delphi application by "chance" didn't use its 32 upper bits (so it was like maybe $0000000000A3BE41, and so truncating it to $00A3BE41 didn't have any effect). So it seemed to work most of the time, but only by accident.

Now, recent versions of the Delphi compiler and linker enables ASLR, making such accidents much less likely.

And this is a good thing: If you have a serious bug in your code, it is better if you discover it right away and not "randomly" at your customers.

So, to fix the issue, you need to go through the code and make sure you never store a pointer in a 32-bit Integer. Instead, use a native-sized NativeInt, Pointer, LPARAM, or whatever is semantically appropriate.

(Disabling ASLR will also make it work in "many" cases by accident again, but this is a very bad approach. Your software still has a very serious bug that may manifest itself at any time.)


In your code, there is also

Integer( Pchar( FStatusMessage ))
Integer( Pchar( msg ))

Upvotes: 9

Related Questions