Drag-and-drop from 32 to 64-bit

As the question has been reopened, I can post a proper answer.

This is truly a bug of Windows. In a 64-bit process, wParam is a 64-bit value and is used as is to send a "HDROP", which is in fact a pointer to a pointer to a DROPFILES structure. The tests showed that the shell uses the whole 64 bits, and writes the data into the heap. If a file is dragged from a 32-bit application, the data are still properly written into the heap, even if the latter is located above 4GB. But despite that, in this case, wParam is converted to a 32-bit value, and then sign-extended to 64-bit.

In fact, when we drag a file from a 32-bit application to a 64-bit one, the latter is supposed to crash, because we provide an incorrect pointer to DragQueryFile(). But it does not, because DragQueryFile() handles these exceptions.

Now, the solutions:

  • Use the IDropTarget interface. This is a good solution (and recommended by Microsoft) if you don't care about using OLE and adding about 10KB in your executable only for reading a file name that is already in RAM (it's not my case).

  • Find a way to retrieve the high part of wParam. As explained, this value is a pointer to the heap. The closest value is given by GlobalAlloc(GMEM_MOVEABLE, 0). It usually gives the value of wParam (or the one it is supposed to have) +16. Even if it can be sometimes slightly higher, this is enough to retrieve the lacking high order 32 bits of wParam. To cover the unlikely case where the heap overlaps a 4GB boundary, we can try by adding or removing 1 to the high order 32 bits. Note that GlobalFree() remains required. Otherwise, you consume a few bytes (16 according to my tests) after each call to GlobalAlloc().

  • Disable the High Entropy ASLR. This one requires Windows 8 or later, and that's why this bug rarely occurs on Windows 7 and prior. On Windows 7, the addresses are randomized, but remain under the 4GB limit. That said, you may still have to zero the high order 32 bits, because of the sign extension. And this solution means a security decrease.