I am writing a C program that accepts drag and drop files. When it is compiled into 32-bit, it works anyway. But when it is compiled in 64-bit mode, it only works for files being dragged from a 64-bit application:
- 32-bit -> 32-bit: success
- 64-bit -> 64-bit: success
- 64-bit -> 32-bit: success
- 32-bit β 64-bit: crash
I still get the WM_DROPFILES message, but the DragQueryFile returns nothing (the number of files is 0).
This seems to be a problem for many applications, but I would like to know if there is a workaround.
Edit:
- If I drag a file from a 64-bit executable to my 64-bit application, wParam has a value such as 0x000000F211C000B8 (which indicates there is no problem with casting).
- Then, without closing my application, if I dragged a file from a 32-bit executable, wParam will have something like 0x0000000011C000B8 or 0xFFFFFFFF11C000B8, which means that 32 high-order bits are invalid.
- If I replaced the invalid high order with the valid one from the previous message (in this example, it will be 0x000000F2), then DragQueryFile will work!
So, the data here, somewhere, I just donβt know how to get it (at least without an ugly hack).
Edit 2:
I will not indicate the code, because I assume that those who answer know something about this problem, which affects a large number of programs.
------ EDIT ----------
minimum code that reproduces it
LRESULT WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { WCHAR sz[32]; switch (uMsg) { case WM_DROPFILES: swprintf(sz, L"%p", wParam);// look for wParam MessageBox(0,0,sz,0); break; case WM_NCCREATE: DragAcceptFiles(hwnd, TRUE); break; case WM_NCDESTROY: PostQuitMessage(0); break; } return DefWindowProc(hwnd, uMsg, wParam, lParam); } void minimal() { static WNDCLASS wndcls = { 0, WindowProc, 0, 0, 0, 0, 0, 0, 0, L"testwnd" }; if (RegisterClass(&wndcls)) { if (HWND hwnd = CreateWindowEx(WS_EX_ACCEPTFILES, wndcls.lpszClassName, 0, WS_OVERLAPPEDWINDOW|WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, 0, 0, 0)) { MSG msg; while (0 < GetMessage(&msg, 0, 0, 0)) { if (msg.message == WM_DROPFILES) { // look for msg.wParam returned by GetMessage WCHAR name[256]; DragQueryFile((HDROP)msg.wParam, 0, name, RTL_NUMBER_OF(name)); } DispatchMessage(&msg); } } UnregisterClass(wndcls.lpszClassName, 0); } }
Interestingly, if you call DragAcceptFiles (even just jump to its instruction first), then the high 32 bits of wParam will be equal to 1. If you do not call it, set WS_EX_ACCEPTFILES exstyle yourself - all the most significant bits of wParam will be 0
for verification, you can run a 32-bit notepad, open the "Open file" dialog box and drag any file into our window