2 * 16-bit messaging support
4 * Copyright 2001 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
28 #include "wine/winuser16.h"
33 #include "user_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msg);
39 DWORD USER16_AlertableWait = 0;
41 static struct wow_handlers32 wow_handlers32;
43 static LRESULT cwp_hook_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
44 LRESULT *result, void *arg )
53 return HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp, FALSE );
56 static LRESULT send_message_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
57 LRESULT *result, void *arg )
59 *result = SendMessageA( hwnd, msg, wp, lp );
63 static LRESULT post_message_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
64 LRESULT *result, void *arg )
67 return PostMessageA( hwnd, msg, wp, lp );
70 static LRESULT post_thread_message_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
71 LRESULT *result, void *arg )
73 DWORD_PTR tid = (DWORD_PTR)arg;
75 return PostThreadMessageA( tid, msg, wp, lp );
78 static LRESULT get_message_callback( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp,
79 LRESULT *result, void *arg )
91 static LRESULT defdlg_proc_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
92 LRESULT *result, void *arg )
94 *result = DefDlgProcA( hwnd, msg, wp, lp );
98 static LRESULT call_window_proc_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
99 LRESULT *result, void *arg )
102 *result = CallWindowProcA( proc, hwnd, msg, wp, lp );
107 /**********************************************************************
108 * Support for window procedure thunks
111 #include "pshpack1.h"
114 BYTE popl_eax; /* popl %eax (return address) */
115 BYTE pushl_func; /* pushl $proc */
117 BYTE pushl_eax; /* pushl %eax */
118 BYTE ljmp; /* ljmp relay*/
119 DWORD relay_offset; /* __wine_call_wndproc */
124 #define WINPROC_HANDLE (~0u >> 16)
125 #define MAX_WINPROCS32 4096
126 #define MAX_WINPROCS16 1024
128 static WNDPROC16 winproc16_array[MAX_WINPROCS16];
129 static unsigned int winproc16_used;
131 static WINPROC_THUNK *thunk_array;
132 static UINT thunk_selector;
134 /* return the window proc index for a given handle, or -1 for an invalid handle
135 * indices 0 .. MAX_WINPROCS32-1 are for 32-bit procs,
136 * indices MAX_WINPROCS32 .. MAX_WINPROCS32+MAX_WINPROCS16-1 for 16-bit procs */
137 static int winproc_to_index( WNDPROC16 handle )
141 if (HIWORD(handle) == thunk_selector)
143 index = LOWORD(handle) / sizeof(WINPROC_THUNK);
144 /* check alignment */
145 if (index * sizeof(WINPROC_THUNK) != LOWORD(handle)) return -1;
146 /* check array limits */
147 if (index >= MAX_WINPROCS32) return -1;
151 index = LOWORD(handle);
152 if ((ULONG_PTR)handle >> 16 != WINPROC_HANDLE) return -1;
153 /* check array limits */
154 if (index >= winproc16_used + MAX_WINPROCS32) return -1;
159 /* allocate a 16-bit thunk for an existing window proc */
160 static WNDPROC16 alloc_win16_thunk( WNDPROC handle )
162 static FARPROC16 relay;
163 WINPROC_THUNK *thunk;
164 UINT index = LOWORD( handle );
166 if (index >= MAX_WINPROCS32) return (WNDPROC16)handle; /* already a 16-bit proc */
168 if (!thunk_array) /* allocate the array and its selector */
172 assert( MAX_WINPROCS16 * sizeof(WINPROC_THUNK) <= 0x10000 );
174 if (!(thunk_selector = wine_ldt_alloc_entries(1))) return NULL;
175 if (!(thunk_array = VirtualAlloc( NULL, MAX_WINPROCS16 * sizeof(WINPROC_THUNK), MEM_COMMIT,
176 PAGE_EXECUTE_READWRITE ))) return NULL;
177 wine_ldt_set_base( &entry, thunk_array );
178 wine_ldt_set_limit( &entry, MAX_WINPROCS16 * sizeof(WINPROC_THUNK) - 1 );
179 wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
180 wine_ldt_set_entry( thunk_selector, &entry );
181 relay = GetProcAddress16( GetModuleHandle16("user"), "__wine_call_wndproc" );
184 thunk = &thunk_array[index];
185 thunk->popl_eax = 0x58; /* popl %eax */
186 thunk->pushl_func = 0x68; /* pushl $proc */
187 thunk->proc = handle;
188 thunk->pushl_eax = 0x50; /* pushl %eax */
189 thunk->ljmp = 0xea; /* ljmp relay*/
190 thunk->relay_offset = OFFSETOF(relay);
191 thunk->relay_sel = SELECTOROF(relay);
192 return (WNDPROC16)MAKESEGPTR( thunk_selector, index * sizeof(WINPROC_THUNK) );
195 /**********************************************************************
196 * WINPROC_AllocProc16
198 WNDPROC WINPROC_AllocProc16( WNDPROC16 func )
203 if (!func) return NULL;
205 /* check if the function is already a win proc */
206 if ((index = winproc_to_index( func )) != -1)
207 return (WNDPROC)(ULONG_PTR)(index | (WINPROC_HANDLE << 16));
209 /* then check if we already have a winproc for that function */
210 for (index = 0; index < winproc16_used; index++)
211 if (winproc16_array[index] == func) goto done;
213 if (winproc16_used >= MAX_WINPROCS16)
215 FIXME( "too many winprocs, cannot allocate one for 16-bit %p\n", func );
218 winproc16_array[winproc16_used++] = func;
221 ret = (WNDPROC)(ULONG_PTR)((index + MAX_WINPROCS32) | (WINPROC_HANDLE << 16));
222 TRACE( "returning %p for %p/16-bit (%d/%d used)\n",
223 ret, func, winproc16_used, MAX_WINPROCS16 );
227 /**********************************************************************
230 * Get a window procedure pointer that can be passed to the Windows program.
232 WNDPROC16 WINPROC_GetProc16( WNDPROC proc, BOOL unicode )
236 if (unicode) winproc = wow_handlers32.alloc_winproc( NULL, proc );
237 else winproc = wow_handlers32.alloc_winproc( proc, NULL );
239 if ((ULONG_PTR)winproc >> 16 != WINPROC_HANDLE) return (WNDPROC16)winproc;
240 return alloc_win16_thunk( winproc );
243 /* call a 16-bit window procedure */
244 static LRESULT call_window_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
245 LRESULT *result, void *arg )
247 WNDPROC16 func = arg;
248 int index = winproc_to_index( func );
257 DRAWITEMSTRUCT16 dis16;
258 COMPAREITEMSTRUCT16 cis16;
264 if (index >= MAX_WINPROCS32) func = winproc16_array[index - MAX_WINPROCS32];
266 /* Window procedures want ax = hInstance, ds = es = ss */
268 memset(&context, 0, sizeof(context));
269 context.SegDs = context.SegEs = SELECTOROF(NtCurrentTeb()->WOW32Reserved);
270 context.SegFs = wine_get_fs();
271 context.SegGs = wine_get_gs();
272 if (!(context.Eax = GetWindowWord( HWND_32(hwnd), GWLP_HINSTANCE ))) context.Eax = context.SegDs;
273 context.SegCs = SELECTOROF(func);
274 context.Eip = OFFSETOF(func);
275 context.Ebp = OFFSETOF(NtCurrentTeb()->WOW32Reserved) + FIELD_OFFSET(STACK16FRAME, bp);
279 /* Some programs (eg. the "Undocumented Windows" examples, JWP) only
280 work if structures passed in lParam are placed in the stack/data
281 segment. Programmers easily make the mistake of converting lParam
282 to a near rather than a far pointer, since Windows apparently
283 allows this. We copy the structures to the 16 bit stack; this is
284 ugly but makes these programs work. */
289 size = sizeof(CREATESTRUCT16); break;
291 size = sizeof(DRAWITEMSTRUCT16); break;
293 size = sizeof(COMPAREITEMSTRUCT16); break;
297 memcpy( &args.u, MapSL(lParam), size );
298 lParam = PtrToUlong(NtCurrentTeb()->WOW32Reserved) - size;
302 args.params[4] = hwnd;
303 args.params[3] = msg;
304 args.params[2] = wParam;
305 args.params[1] = HIWORD(lParam);
306 args.params[0] = LOWORD(lParam);
307 WOWCallback16Ex( 0, WCB16_REGS, sizeof(args.params) + size, &args, (DWORD *)&context );
308 *result = MAKELONG( LOWORD(context.Eax), LOWORD(context.Edx) );
312 static LRESULT call_dialog_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp,
313 LRESULT *result, void *arg )
315 LRESULT ret = call_window_proc16( hwnd, msg, wp, lp, result, arg );
316 *result = GetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT );
320 static LRESULT call_window_proc_Ato16( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
321 LRESULT *result, void *arg )
323 return WINPROC_CallProc32ATo16( call_window_proc16, hwnd, msg, wp, lp, result, arg );
326 static LRESULT call_dialog_proc_Ato16( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
327 LRESULT *result, void *arg )
329 return WINPROC_CallProc32ATo16( call_dialog_proc16, hwnd, msg, wp, lp, result, arg );
334 /**********************************************************************
335 * Support for Edit word break proc thunks
338 #define MAX_THUNKS 32
340 #include <pshpack1.h>
341 static struct word_break_thunk
343 BYTE popl_eax; /* popl %eax (return address) */
344 BYTE pushl_proc16; /* pushl proc16 */
345 EDITWORDBREAKPROC16 proc16;
346 BYTE pushl_eax; /* pushl %eax */
347 BYTE jmp; /* ljmp call_word_break_proc16 */
349 } *word_break_thunks;
352 /**********************************************************************
353 * call_word_break_proc16
355 static INT16 CALLBACK call_word_break_proc16( SEGPTR proc16, LPSTR text, INT index, INT count, INT action )
361 segptr = MapLS( text );
362 args[4] = SELECTOROF(segptr);
363 args[3] = OFFSETOF(segptr);
367 WOWCallback16Ex( proc16, WCB16_PASCAL, sizeof(args), args, &result );
369 return LOWORD(result);
372 /******************************************************************
373 * add_word_break_thunk
375 static struct word_break_thunk *add_word_break_thunk( EDITWORDBREAKPROC16 proc16 )
377 struct word_break_thunk *thunk;
379 if (!word_break_thunks)
381 word_break_thunks = VirtualAlloc( NULL, MAX_THUNKS * sizeof(*thunk),
382 MEM_COMMIT, PAGE_EXECUTE_READWRITE );
383 if (!word_break_thunks) return NULL;
385 for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++)
387 thunk->popl_eax = 0x58; /* popl %eax */
388 thunk->pushl_proc16 = 0x68; /* pushl proc16 */
389 thunk->pushl_eax = 0x50; /* pushl %eax */
390 thunk->jmp = 0xe9; /* jmp call_word_break_proc16 */
391 thunk->callback = (char *)call_word_break_proc16 - (char *)(&thunk->callback + 1);
394 for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++)
395 if (thunk->proc16 == proc16) return thunk;
397 for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++)
399 if (thunk->proc16) continue;
400 thunk->proc16 = proc16;
403 FIXME("Out of word break thunks\n");
407 /******************************************************************
408 * get_word_break_thunk
410 static EDITWORDBREAKPROC16 get_word_break_thunk( EDITWORDBREAKPROCA proc )
412 struct word_break_thunk *thunk = (struct word_break_thunk *)proc;
413 if (word_break_thunks && thunk >= word_break_thunks && thunk < &word_break_thunks[MAX_THUNKS])
414 return thunk->proc16;
419 /***********************************************************************
420 * Support for 16<->32 message mapping
423 static inline void *get_buffer( void *static_buffer, size_t size, size_t need )
425 if (size >= need) return static_buffer;
426 return HeapAlloc( GetProcessHeap(), 0, need );
429 static inline void free_buffer( void *static_buffer, void *buffer )
431 if (buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer );
434 static void RECT16to32( const RECT16 *from, RECT *to )
436 to->left = from->left;
438 to->right = from->right;
439 to->bottom = from->bottom;
442 static void RECT32to16( const RECT *from, RECT16 *to )
444 to->left = from->left;
446 to->right = from->right;
447 to->bottom = from->bottom;
450 static void MINMAXINFO32to16( const MINMAXINFO *from, MINMAXINFO16 *to )
452 to->ptReserved.x = from->ptReserved.x;
453 to->ptReserved.y = from->ptReserved.y;
454 to->ptMaxSize.x = from->ptMaxSize.x;
455 to->ptMaxSize.y = from->ptMaxSize.y;
456 to->ptMaxPosition.x = from->ptMaxPosition.x;
457 to->ptMaxPosition.y = from->ptMaxPosition.y;
458 to->ptMinTrackSize.x = from->ptMinTrackSize.x;
459 to->ptMinTrackSize.y = from->ptMinTrackSize.y;
460 to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
461 to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
464 static void MINMAXINFO16to32( const MINMAXINFO16 *from, MINMAXINFO *to )
466 to->ptReserved.x = from->ptReserved.x;
467 to->ptReserved.y = from->ptReserved.y;
468 to->ptMaxSize.x = from->ptMaxSize.x;
469 to->ptMaxSize.y = from->ptMaxSize.y;
470 to->ptMaxPosition.x = from->ptMaxPosition.x;
471 to->ptMaxPosition.y = from->ptMaxPosition.y;
472 to->ptMinTrackSize.x = from->ptMinTrackSize.x;
473 to->ptMinTrackSize.y = from->ptMinTrackSize.y;
474 to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
475 to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
478 static void WINDOWPOS32to16( const WINDOWPOS* from, WINDOWPOS16* to )
480 to->hwnd = HWND_16(from->hwnd);
481 to->hwndInsertAfter = HWND_16(from->hwndInsertAfter);
486 to->flags = from->flags;
489 static void WINDOWPOS16to32( const WINDOWPOS16* from, WINDOWPOS* to )
491 to->hwnd = WIN_Handle32(from->hwnd);
492 to->hwndInsertAfter = (from->hwndInsertAfter == (HWND16)-1) ?
493 HWND_TOPMOST : WIN_Handle32(from->hwndInsertAfter);
498 to->flags = from->flags;
501 /* The strings are not copied */
502 static void CREATESTRUCT32Ato16( const CREATESTRUCTA* from, CREATESTRUCT16* to )
504 to->lpCreateParams = (SEGPTR)from->lpCreateParams;
505 to->hInstance = HINSTANCE_16(from->hInstance);
506 to->hMenu = HMENU_16(from->hMenu);
507 to->hwndParent = HWND_16(from->hwndParent);
512 to->style = from->style;
513 to->dwExStyle = from->dwExStyle;
516 static void CREATESTRUCT16to32A( const CREATESTRUCT16* from, CREATESTRUCTA *to )
519 to->lpCreateParams = (LPVOID)from->lpCreateParams;
520 to->hInstance = HINSTANCE_32(from->hInstance);
521 to->hMenu = HMENU_32(from->hMenu);
522 to->hwndParent = WIN_Handle32(from->hwndParent);
527 to->style = from->style;
528 to->dwExStyle = from->dwExStyle;
529 to->lpszName = MapSL(from->lpszName);
530 to->lpszClass = MapSL(from->lpszClass);
533 /* The strings are not copied */
534 static void MDICREATESTRUCT32Ato16( const MDICREATESTRUCTA* from, MDICREATESTRUCT16* to )
536 to->hOwner = HINSTANCE_16(from->hOwner);
541 to->style = from->style;
542 to->lParam = from->lParam;
545 static void MDICREATESTRUCT16to32A( const MDICREATESTRUCT16* from, MDICREATESTRUCTA *to )
547 to->hOwner = HINSTANCE_32(from->hOwner);
552 to->style = from->style;
553 to->lParam = from->lParam;
554 to->szTitle = MapSL(from->szTitle);
555 to->szClass = MapSL(from->szClass);
558 static UINT_PTR convert_handle_16_to_32(HANDLE16 src, unsigned int flags)
561 UINT sz = GlobalSize16(src);
564 if (!(dst = GlobalAlloc(flags, sz)))
566 ptr16 = GlobalLock16(src);
567 ptr32 = GlobalLock(dst);
568 if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr32, ptr16, sz);
572 return (UINT_PTR)dst;
575 static HANDLE16 convert_handle_32_to_16(UINT_PTR src, unsigned int flags)
578 UINT sz = GlobalSize((HANDLE)src);
581 if (!(dst = GlobalAlloc16(flags, sz)))
583 ptr32 = GlobalLock((HANDLE)src);
584 ptr16 = GlobalLock16(dst);
585 if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr16, ptr32, sz);
586 GlobalUnlock((HANDLE)src);
592 /**********************************************************************
593 * WINPROC_CallProc16To32A
595 LRESULT WINPROC_CallProc16To32A( winproc_callback_t callback, HWND16 hwnd, UINT16 msg,
596 WPARAM16 wParam, LPARAM lParam, LRESULT *result, void *arg )
599 HWND hwnd32 = WIN_Handle32( hwnd );
601 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
602 hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
609 CREATESTRUCT16 *cs16 = MapSL(lParam);
611 MDICREATESTRUCTA mdi_cs;
613 CREATESTRUCT16to32A( cs16, &cs );
614 if (GetWindowLongW(hwnd32, GWL_EXSTYLE) & WS_EX_MDICHILD)
616 MDICREATESTRUCT16 *mdi_cs16 = MapSL(cs16->lpCreateParams);
617 MDICREATESTRUCT16to32A(mdi_cs16, &mdi_cs);
618 cs.lpCreateParams = &mdi_cs;
620 ret = callback( hwnd32, msg, wParam, (LPARAM)&cs, result, arg );
621 CREATESTRUCT32Ato16( &cs, cs16 );
626 MDICREATESTRUCT16 *cs16 = MapSL(lParam);
629 MDICREATESTRUCT16to32A( cs16, &cs );
630 ret = callback( hwnd32, msg, wParam, (LPARAM)&cs, result, arg );
631 MDICREATESTRUCT32Ato16( &cs, cs16 );
636 ret = callback( hwnd32, msg, (WPARAM)WIN_Handle32( HIWORD(lParam) ),
637 (LPARAM)WIN_Handle32( LOWORD(lParam) ), result, arg );
638 else /* message sent to MDI client */
639 ret = callback( hwnd32, msg, wParam, lParam, result, arg );
641 case WM_MDIGETACTIVE:
643 BOOL maximized = FALSE;
644 ret = callback( hwnd32, msg, wParam, (LPARAM)&maximized, result, arg );
645 *result = MAKELRESULT( LOWORD(*result), maximized );
649 ret = callback( hwnd32, wParam ? WM_MDIREFRESHMENU : WM_MDISETMENU,
650 (WPARAM)HMENU_32(LOWORD(lParam)), (LPARAM)HMENU_32(HIWORD(lParam)),
653 case WM_GETMINMAXINFO:
655 MINMAXINFO16 *mmi16 = MapSL(lParam);
658 MINMAXINFO16to32( mmi16, &mmi );
659 ret = callback( hwnd32, msg, wParam, (LPARAM)&mmi, result, arg );
660 MINMAXINFO32to16( &mmi, mmi16 );
663 case WM_WINDOWPOSCHANGING:
664 case WM_WINDOWPOSCHANGED:
666 WINDOWPOS16 *winpos16 = MapSL(lParam);
669 WINDOWPOS16to32( winpos16, &winpos );
670 ret = callback( hwnd32, msg, wParam, (LPARAM)&winpos, result, arg );
671 WINDOWPOS32to16( &winpos, winpos16 );
676 NCCALCSIZE_PARAMS16 *nc16 = MapSL(lParam);
677 NCCALCSIZE_PARAMS nc;
680 RECT16to32( &nc16->rgrc[0], &nc.rgrc[0] );
683 RECT16to32( &nc16->rgrc[1], &nc.rgrc[1] );
684 RECT16to32( &nc16->rgrc[2], &nc.rgrc[2] );
685 WINDOWPOS16to32( MapSL(nc16->lppos), &winpos );
688 ret = callback( hwnd32, msg, wParam, (LPARAM)&nc, result, arg );
689 RECT32to16( &nc.rgrc[0], &nc16->rgrc[0] );
692 RECT32to16( &nc.rgrc[1], &nc16->rgrc[1] );
693 RECT32to16( &nc.rgrc[2], &nc16->rgrc[2] );
694 WINDOWPOS32to16( &winpos, MapSL(nc16->lppos) );
700 COMPAREITEMSTRUCT16* cis16 = MapSL(lParam);
701 COMPAREITEMSTRUCT cis;
702 cis.CtlType = cis16->CtlType;
703 cis.CtlID = cis16->CtlID;
704 cis.hwndItem = WIN_Handle32( cis16->hwndItem );
705 cis.itemID1 = cis16->itemID1;
706 cis.itemData1 = cis16->itemData1;
707 cis.itemID2 = cis16->itemID2;
708 cis.itemData2 = cis16->itemData2;
709 cis.dwLocaleId = 0; /* FIXME */
710 ret = callback( hwnd32, msg, wParam, (LPARAM)&cis, result, arg );
715 DELETEITEMSTRUCT16* dis16 = MapSL(lParam);
716 DELETEITEMSTRUCT dis;
717 dis.CtlType = dis16->CtlType;
718 dis.CtlID = dis16->CtlID;
719 dis.hwndItem = WIN_Handle32( dis16->hwndItem );
720 dis.itemData = dis16->itemData;
721 ret = callback( hwnd32, msg, wParam, (LPARAM)&dis, result, arg );
726 MEASUREITEMSTRUCT16* mis16 = MapSL(lParam);
727 MEASUREITEMSTRUCT mis;
728 mis.CtlType = mis16->CtlType;
729 mis.CtlID = mis16->CtlID;
730 mis.itemID = mis16->itemID;
731 mis.itemWidth = mis16->itemWidth;
732 mis.itemHeight = mis16->itemHeight;
733 mis.itemData = mis16->itemData;
734 ret = callback( hwnd32, msg, wParam, (LPARAM)&mis, result, arg );
735 mis16->itemWidth = (UINT16)mis.itemWidth;
736 mis16->itemHeight = (UINT16)mis.itemHeight;
741 DRAWITEMSTRUCT16* dis16 = MapSL(lParam);
743 dis.CtlType = dis16->CtlType;
744 dis.CtlID = dis16->CtlID;
745 dis.itemID = dis16->itemID;
746 dis.itemAction = dis16->itemAction;
747 dis.itemState = dis16->itemState;
748 dis.hwndItem = (dis.CtlType == ODT_MENU) ? (HWND)HMENU_32(dis16->hwndItem)
749 : WIN_Handle32( dis16->hwndItem );
750 dis.hDC = HDC_32(dis16->hDC);
751 dis.itemData = dis16->itemData;
752 dis.rcItem.left = dis16->rcItem.left;
753 dis.rcItem.top = dis16->rcItem.top;
754 dis.rcItem.right = dis16->rcItem.right;
755 dis.rcItem.bottom = dis16->rcItem.bottom;
756 ret = callback( hwnd32, msg, wParam, (LPARAM)&dis, result, arg );
761 COPYDATASTRUCT16 *cds16 = MapSL(lParam);
763 cds.dwData = cds16->dwData;
764 cds.cbData = cds16->cbData;
765 cds.lpData = MapSL(cds16->lpData);
766 ret = callback( hwnd32, msg, wParam, (LPARAM)&cds, result, arg );
772 MSG16 *msg16 = MapSL(lParam);
774 msg32.hwnd = WIN_Handle32( msg16->hwnd );
775 msg32.message = msg16->message;
776 msg32.wParam = msg16->wParam;
777 msg32.lParam = msg16->lParam;
778 msg32.time = msg16->time;
779 msg32.pt.x = msg16->pt.x;
780 msg32.pt.y = msg16->pt.y;
781 ret = callback( hwnd32, msg, wParam, (LPARAM)&msg32, result, arg );
784 ret = callback( hwnd32, msg, wParam, lParam, result, arg );
789 next.hmenuIn = (HMENU)lParam;
792 ret = callback( hwnd32, msg, wParam, (LPARAM)&next, result, arg );
793 *result = MAKELONG( HMENU_16(next.hmenuNext), HWND_16(next.hwndNext) );
800 ret = callback( hwnd32, msg, MAKEWPARAM( wParam, HIWORD(lParam) ),
801 (LPARAM)WIN_Handle32( LOWORD(lParam) ), result, arg );
805 ret = callback( hwnd32, msg, MAKEWPARAM( wParam, LOWORD(lParam) ),
806 (LPARAM)WIN_Handle32( HIWORD(lParam) ), result, arg );
809 if (HIWORD(lParam) <= CTLCOLOR_STATIC)
810 ret = callback( hwnd32, WM_CTLCOLORMSGBOX + HIWORD(lParam),
811 (WPARAM)HDC_32(wParam), (LPARAM)WIN_Handle32( LOWORD(lParam) ),
816 case WM_WININICHANGE:
817 case WM_DEVMODECHANGE:
818 case WM_ASKCBFORMATNAME:
820 ret = callback( hwnd32, msg, wParam, (LPARAM)MapSL(lParam), result, arg );
823 ret = callback( hwnd32, msg, MAKEWPARAM( wParam, LOWORD(lParam) ),
824 (LPARAM)HMENU_32(HIWORD(lParam)), result, arg );
827 if((LOWORD(lParam) & MF_POPUP) && (LOWORD(lParam) != 0xFFFF))
829 HMENU hmenu = HMENU_32(HIWORD(lParam));
830 UINT pos = MENU_FindSubMenu( &hmenu, HMENU_32(wParam) );
831 if (pos == 0xffff) pos = 0; /* NO_SELECTED_ITEM */
834 ret = callback( hwnd32, msg, MAKEWPARAM( wParam, LOWORD(lParam) ),
835 (LPARAM)HMENU_32(HIWORD(lParam)), result, arg );
837 case WM_PARENTNOTIFY:
838 if ((wParam == WM_CREATE) || (wParam == WM_DESTROY))
839 ret = callback( hwnd32, msg, MAKEWPARAM( wParam, HIWORD(lParam) ),
840 (LPARAM)WIN_Handle32( LOWORD(lParam) ), result, arg );
842 ret = callback( hwnd32, msg, wParam, lParam, result, arg );
845 /* We need this when SetActiveWindow sends a Sendmessage16() to
846 * a 32-bit window. Might be superfluous with 32-bit interprocess
848 if (lParam) lParam = HTASK_32(lParam);
849 ret = callback( hwnd32, msg, wParam, lParam, result, arg );
851 case WM_DDE_INITIATE:
852 case WM_DDE_TERMINATE:
853 case WM_DDE_UNADVISE:
855 ret = callback( hwnd32, msg, (WPARAM)WIN_Handle32(wParam), lParam, result, arg );
861 HANDLE16 lo16 = LOWORD(lParam);
863 if (lo16 && !(lo32 = convert_handle_16_to_32(lo16, GMEM_DDESHARE))) break;
864 lParam = PackDDElParam( msg, lo32, HIWORD(lParam) );
865 ret = callback( hwnd32, msg, (WPARAM)WIN_Handle32(wParam), lParam, result, arg );
867 break; /* FIXME don't know how to free allocated memory (handle) !! */
870 UINT_PTR lo = LOWORD(lParam);
871 UINT_PTR hi = HIWORD(lParam);
875 if (GlobalGetAtomNameA(hi, buf, 2) > 0) flag |= 1;
876 if (GlobalSize16(hi) != 0) flag |= 2;
882 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
887 break; /* atom, nothing to do */
889 MESSAGE("DDE_ACK: %lx both atom and handle... choosing handle\n", hi);
892 hi = convert_handle_16_to_32(hi, GMEM_DDESHARE);
895 lParam = PackDDElParam( WM_DDE_ACK, lo, hi );
896 ret = callback( hwnd32, msg, (WPARAM)WIN_Handle32(wParam), lParam, result, arg );
898 break; /* FIXME don't know how to free allocated memory (handle) !! */
900 lParam = convert_handle_16_to_32( lParam, GMEM_DDESHARE );
901 ret = callback( hwnd32, msg, wParam, lParam, result, arg );
902 break; /* FIXME don't know how to free allocated memory (handle) !! */
903 case WM_PAINTCLIPBOARD:
904 case WM_SIZECLIPBOARD:
905 FIXME_(msg)( "message %04x needs translation\n", msg );
908 ret = callback( hwnd32, msg, wParam, lParam, result, arg );
915 /**********************************************************************
916 * WINPROC_CallProc32ATo16
918 * Call a 16-bit window procedure, translating the 32-bit args.
920 LRESULT WINPROC_CallProc32ATo16( winproc_callback16_t callback, HWND hwnd, UINT msg,
921 WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg )
925 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08lx,lp=%08lx)\n",
926 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
933 CREATESTRUCTA *cs32 = (CREATESTRUCTA *)lParam;
935 MDICREATESTRUCT16 mdi_cs16;
936 BOOL mdi_child = (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD);
938 CREATESTRUCT32Ato16( cs32, &cs );
939 cs.lpszName = MapLS( cs32->lpszName );
940 cs.lpszClass = MapLS( cs32->lpszClass );
944 MDICREATESTRUCTA *mdi_cs = cs32->lpCreateParams;
945 MDICREATESTRUCT32Ato16( mdi_cs, &mdi_cs16 );
946 mdi_cs16.szTitle = MapLS( mdi_cs->szTitle );
947 mdi_cs16.szClass = MapLS( mdi_cs->szClass );
948 cs.lpCreateParams = MapLS( &mdi_cs16 );
950 lParam = MapLS( &cs );
951 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
953 UnMapLS( cs.lpszName );
954 UnMapLS( cs.lpszClass );
957 UnMapLS( cs.lpCreateParams );
958 UnMapLS( mdi_cs16.szTitle );
959 UnMapLS( mdi_cs16.szClass );
965 MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)lParam;
966 MDICREATESTRUCT16 cs;
968 MDICREATESTRUCT32Ato16( cs32, &cs );
969 cs.szTitle = MapLS( cs32->szTitle );
970 cs.szClass = MapLS( cs32->szClass );
971 lParam = MapLS( &cs );
972 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
974 UnMapLS( cs.szTitle );
975 UnMapLS( cs.szClass );
979 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
980 ret = callback( HWND_16(hwnd), msg, ((HWND)lParam == hwnd),
981 MAKELPARAM( LOWORD(lParam), LOWORD(wParam) ), result, arg );
983 ret = callback( HWND_16(hwnd), msg, HWND_16( wParam ), 0, result, arg );
985 case WM_MDIGETACTIVE:
986 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
987 if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(*result);
988 *result = (LRESULT)WIN_Handle32( LOWORD(*result) );
991 ret = callback( HWND_16(hwnd), msg, (lParam == 0),
992 MAKELPARAM( LOWORD(wParam), LOWORD(lParam) ), result, arg );
994 case WM_GETMINMAXINFO:
996 MINMAXINFO *mmi32 = (MINMAXINFO *)lParam;
999 MINMAXINFO32to16( mmi32, &mmi );
1000 lParam = MapLS( &mmi );
1001 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1003 MINMAXINFO16to32( &mmi, mmi32 );
1008 NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)lParam;
1009 NCCALCSIZE_PARAMS16 nc;
1012 RECT32to16( &nc32->rgrc[0], &nc.rgrc[0] );
1015 RECT32to16( &nc32->rgrc[1], &nc.rgrc[1] );
1016 RECT32to16( &nc32->rgrc[2], &nc.rgrc[2] );
1017 WINDOWPOS32to16( nc32->lppos, &winpos );
1018 nc.lppos = MapLS( &winpos );
1020 lParam = MapLS( &nc );
1021 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1023 RECT16to32( &nc.rgrc[0], &nc32->rgrc[0] );
1026 RECT16to32( &nc.rgrc[1], &nc32->rgrc[1] );
1027 RECT16to32( &nc.rgrc[2], &nc32->rgrc[2] );
1028 WINDOWPOS16to32( &winpos, nc32->lppos );
1029 UnMapLS( nc.lppos );
1033 case WM_WINDOWPOSCHANGING:
1034 case WM_WINDOWPOSCHANGED:
1036 WINDOWPOS *winpos32 = (WINDOWPOS *)lParam;
1039 WINDOWPOS32to16( winpos32, &winpos );
1040 lParam = MapLS( &winpos );
1041 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1043 WINDOWPOS16to32( &winpos, winpos32 );
1046 case WM_COMPAREITEM:
1048 COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)lParam;
1049 COMPAREITEMSTRUCT16 cis;
1050 cis.CtlType = cis32->CtlType;
1051 cis.CtlID = cis32->CtlID;
1052 cis.hwndItem = HWND_16( cis32->hwndItem );
1053 cis.itemID1 = cis32->itemID1;
1054 cis.itemData1 = cis32->itemData1;
1055 cis.itemID2 = cis32->itemID2;
1056 cis.itemData2 = cis32->itemData2;
1057 lParam = MapLS( &cis );
1058 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1064 DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)lParam;
1065 DELETEITEMSTRUCT16 dis;
1066 dis.CtlType = dis32->CtlType;
1067 dis.CtlID = dis32->CtlID;
1068 dis.itemID = dis32->itemID;
1069 dis.hwndItem = (dis.CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem)
1070 : HWND_16( dis32->hwndItem );
1071 dis.itemData = dis32->itemData;
1072 lParam = MapLS( &dis );
1073 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1079 DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)lParam;
1080 DRAWITEMSTRUCT16 dis;
1081 dis.CtlType = dis32->CtlType;
1082 dis.CtlID = dis32->CtlID;
1083 dis.itemID = dis32->itemID;
1084 dis.itemAction = dis32->itemAction;
1085 dis.itemState = dis32->itemState;
1086 dis.hwndItem = HWND_16( dis32->hwndItem );
1087 dis.hDC = HDC_16(dis32->hDC);
1088 dis.itemData = dis32->itemData;
1089 dis.rcItem.left = dis32->rcItem.left;
1090 dis.rcItem.top = dis32->rcItem.top;
1091 dis.rcItem.right = dis32->rcItem.right;
1092 dis.rcItem.bottom = dis32->rcItem.bottom;
1093 lParam = MapLS( &dis );
1094 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1098 case WM_MEASUREITEM:
1100 MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)lParam;
1101 MEASUREITEMSTRUCT16 mis;
1102 mis.CtlType = mis32->CtlType;
1103 mis.CtlID = mis32->CtlID;
1104 mis.itemID = mis32->itemID;
1105 mis.itemWidth = mis32->itemWidth;
1106 mis.itemHeight = mis32->itemHeight;
1107 mis.itemData = mis32->itemData;
1108 lParam = MapLS( &mis );
1109 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1111 mis32->itemWidth = mis.itemWidth;
1112 mis32->itemHeight = mis.itemHeight;
1117 COPYDATASTRUCT *cds32 = (COPYDATASTRUCT *)lParam;
1118 COPYDATASTRUCT16 cds;
1120 cds.dwData = cds32->dwData;
1121 cds.cbData = cds32->cbData;
1122 cds.lpData = MapLS( cds32->lpData );
1123 lParam = MapLS( &cds );
1124 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1126 UnMapLS( cds.lpData );
1132 MSG *msg32 = (MSG *)lParam;
1135 msg16.hwnd = HWND_16( msg32->hwnd );
1136 msg16.message = msg32->message;
1137 msg16.wParam = msg32->wParam;
1138 msg16.lParam = msg32->lParam;
1139 msg16.time = msg32->time;
1140 msg16.pt.x = msg32->pt.x;
1141 msg16.pt.y = msg32->pt.y;
1142 lParam = MapLS( &msg16 );
1143 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1147 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1151 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
1152 ret = callback( HWND_16(hwnd), msg, wParam, (LPARAM)next->hmenuIn, result, arg );
1153 next->hmenuNext = HMENU_32( LOWORD(*result) );
1154 next->hwndNext = WIN_Handle32( HIWORD(*result) );
1159 case WM_ASKCBFORMATNAME:
1160 wParam = min( wParam, 0xff80 ); /* Must be < 64K */
1164 case WM_WININICHANGE:
1165 case WM_DEVMODECHANGE:
1166 lParam = MapLS( (void *)lParam );
1167 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1174 ret = callback( HWND_16(hwnd), msg, wParam, MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ),
1179 ret = callback( HWND_16(hwnd), msg, wParam, MAKELPARAM( HIWORD(wParam), (HWND16)lParam ),
1182 case WM_CTLCOLORMSGBOX:
1183 case WM_CTLCOLOREDIT:
1184 case WM_CTLCOLORLISTBOX:
1185 case WM_CTLCOLORBTN:
1186 case WM_CTLCOLORDLG:
1187 case WM_CTLCOLORSCROLLBAR:
1188 case WM_CTLCOLORSTATIC:
1189 ret = callback( HWND_16(hwnd), WM_CTLCOLOR, wParam,
1190 MAKELPARAM( (HWND16)lParam, msg - WM_CTLCOLORMSGBOX ), result, arg );
1193 if(HIWORD(wParam) & MF_POPUP)
1196 if ((HIWORD(wParam) != 0xffff) || lParam)
1198 if ((hmenu = GetSubMenu( (HMENU)lParam, LOWORD(wParam) )))
1200 ret = callback( HWND_16(hwnd), msg, HMENU_16(hmenu),
1201 MAKELPARAM( HIWORD(wParam), (HMENU16)lParam ), result, arg );
1208 ret = callback( HWND_16(hwnd), msg, wParam,
1209 MAKELPARAM( HIWORD(wParam), (HMENU16)lParam ), result, arg );
1211 case WM_PARENTNOTIFY:
1212 if ((LOWORD(wParam) == WM_CREATE) || (LOWORD(wParam) == WM_DESTROY))
1213 ret = callback( HWND_16(hwnd), msg, wParam,
1214 MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ), result, arg );
1216 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1218 case WM_ACTIVATEAPP:
1219 ret = callback( HWND_16(hwnd), msg, wParam, HTASK_16( lParam ), result, arg );
1222 if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON ))
1223 ret = callback( HWND_16(hwnd), WM_PAINTICON, 1, lParam, result, arg );
1225 ret = callback( HWND_16(hwnd), WM_PAINT, wParam, lParam, result, arg );
1228 if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON )) msg = WM_ICONERASEBKGND;
1229 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1231 case WM_DDE_INITIATE:
1232 case WM_DDE_TERMINATE:
1233 case WM_DDE_UNADVISE:
1234 case WM_DDE_REQUEST:
1235 ret = callback( HWND_16(hwnd), msg, HWND_16(wParam), lParam, result, arg );
1244 UnpackDDElParam( msg, lParam, &lo32, &hi );
1245 if (lo32 && !(lo16 = convert_handle_32_to_16(lo32, GMEM_DDESHARE))) break;
1246 ret = callback( HWND_16(hwnd), msg, HWND_16(wParam),
1247 MAKELPARAM(lo16, hi), result, arg );
1249 break; /* FIXME don't know how to free allocated memory (handle) !! */
1256 UnpackDDElParam( msg, lParam, &lo, &hi );
1258 if (GlobalGetAtomNameA((ATOM)hi, buf, sizeof(buf)) > 0) flag |= 1;
1259 if (GlobalSize((HANDLE)hi) != 0) flag |= 2;
1265 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1270 break; /* atom, nothing to do */
1272 MESSAGE("DDE_ACK: %lx both atom and handle... choosing handle\n", hi);
1275 hi = convert_handle_32_to_16(hi, GMEM_DDESHARE);
1278 ret = callback( HWND_16(hwnd), msg, HWND_16(wParam),
1279 MAKELPARAM(lo, hi), result, arg );
1281 break; /* FIXME don't know how to free allocated memory (handle) !! */
1282 case WM_DDE_EXECUTE:
1283 lParam = convert_handle_32_to_16(lParam, GMEM_DDESHARE);
1284 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1285 break; /* FIXME don't know how to free allocated memory (handle) !! */
1287 ret = callback( HWND_16(hwnd), SBM_SETRANGE16, 0, MAKELPARAM(wParam, lParam), result, arg );
1290 ret = callback( HWND_16(hwnd), SBM_GETRANGE16, wParam, lParam, result, arg );
1291 *(LPINT)wParam = LOWORD(*result);
1292 *(LPINT)lParam = HIWORD(*result);
1299 ret = callback( HWND_16(hwnd), msg + BM_GETCHECK16 - BM_GETCHECK, wParam, lParam, result, arg );
1307 case EM_SCROLLCARET:
1310 case EM_GETLINECOUNT:
1322 case EM_LINEFROMCHAR:
1323 case EM_SETTABSTOPS:
1324 case EM_SETPASSWORDCHAR:
1325 case EM_EMPTYUNDOBUFFER:
1326 case EM_GETFIRSTVISIBLELINE:
1327 case EM_SETREADONLY:
1328 case EM_SETWORDBREAKPROC:
1329 case EM_GETWORDBREAKPROC:
1330 case EM_GETPASSWORDCHAR:
1331 ret = callback( HWND_16(hwnd), msg + EM_GETSEL16 - EM_GETSEL, wParam, lParam, result, arg );
1334 ret = callback( HWND_16(hwnd), EM_SETSEL16, 0, MAKELPARAM( wParam, lParam ), result, arg );
1338 case LB_DELETESTRING:
1339 case LB_GETANCHORINDEX:
1340 case LB_GETCARETINDEX:
1343 case LB_GETHORIZONTALEXTENT:
1344 case LB_GETITEMDATA:
1345 case LB_GETITEMHEIGHT:
1347 case LB_GETSELCOUNT:
1349 case LB_GETTOPINDEX:
1350 case LB_RESETCONTENT:
1351 case LB_SELITEMRANGE:
1352 case LB_SELITEMRANGEEX:
1353 case LB_SETANCHORINDEX:
1354 case LB_SETCARETINDEX:
1355 case LB_SETCOLUMNWIDTH:
1357 case LB_SETHORIZONTALEXTENT:
1358 case LB_SETITEMDATA:
1359 case LB_SETITEMHEIGHT:
1361 case LB_SETTOPINDEX:
1362 ret = callback( HWND_16(hwnd), msg + LB_ADDSTRING16 - LB_ADDSTRING, wParam, lParam, result, arg );
1366 case LB_FINDSTRINGEXACT:
1367 case LB_INSERTSTRING:
1368 case LB_SELECTSTRING:
1372 lParam = MapLS( (LPSTR)lParam );
1373 ret = callback( HWND_16(hwnd), msg + LB_ADDSTRING16 - LB_ADDSTRING, wParam, lParam, result, arg );
1376 case LB_GETSELITEMS:
1378 INT *items32 = (INT *)lParam;
1379 INT16 *items, buffer[512];
1382 wParam = min( wParam, 0x7f80 ); /* Must be < 64K */
1383 if (!(items = get_buffer( buffer, sizeof(buffer), wParam * sizeof(INT16) ))) break;
1384 lParam = MapLS( items );
1385 ret = callback( HWND_16(hwnd), LB_GETSELITEMS16, wParam, lParam, result, arg );
1387 for (i = 0; i < wParam; i++) items32[i] = items[i];
1388 free_buffer( buffer, items );
1391 case LB_SETTABSTOPS:
1394 INT *stops32 = (INT *)lParam;
1395 INT16 *stops, buffer[512];
1398 wParam = min( wParam, 0x7f80 ); /* Must be < 64K */
1399 if (!(stops = get_buffer( buffer, sizeof(buffer), wParam * sizeof(INT16) ))) break;
1400 for (i = 0; i < wParam; i++) stops[i] = stops32[i];
1401 lParam = MapLS( stops );
1402 ret = callback( HWND_16(hwnd), LB_SETTABSTOPS16, wParam, lParam, result, arg );
1404 free_buffer( buffer, stops );
1406 else ret = callback( HWND_16(hwnd), LB_SETTABSTOPS16, wParam, lParam, result, arg );
1408 case CB_DELETESTRING:
1410 case CB_GETLBTEXTLEN:
1412 case CB_RESETCONTENT:
1416 case CB_SHOWDROPDOWN:
1417 case CB_SETITEMDATA:
1418 case CB_SETITEMHEIGHT:
1419 case CB_GETITEMHEIGHT:
1420 case CB_SETEXTENDEDUI:
1421 case CB_GETEXTENDEDUI:
1422 case CB_GETDROPPEDSTATE:
1423 ret = callback( HWND_16(hwnd), msg + CB_GETEDITSEL16 - CB_GETEDITSEL, wParam, lParam, result, arg );
1426 ret = callback( HWND_16(hwnd), CB_GETEDITSEL16, wParam, lParam, result, arg );
1427 if (wParam) *((PUINT)(wParam)) = LOWORD(*result);
1428 if (lParam) *((PUINT)(lParam)) = HIWORD(*result); /* FIXME: substract 1? */
1432 case CB_FINDSTRINGEXACT:
1433 case CB_INSERTSTRING:
1434 case CB_SELECTSTRING:
1437 lParam = MapLS( (LPSTR)lParam );
1438 ret = callback( HWND_16(hwnd), msg + CB_GETEDITSEL16 - CB_GETEDITSEL, wParam, lParam, result, arg );
1441 case LB_GETITEMRECT:
1442 case CB_GETDROPPEDCONTROLRECT:
1444 RECT *r32 = (RECT *)lParam;
1446 lParam = MapLS( &rect );
1447 ret = callback( HWND_16(hwnd),
1448 (msg == LB_GETITEMRECT) ? LB_GETITEMRECT16 : CB_GETDROPPEDCONTROLRECT16,
1449 wParam, lParam, result, arg );
1451 RECT16to32( &rect, r32 );
1454 case WM_PAINTCLIPBOARD:
1455 case WM_SIZECLIPBOARD:
1456 FIXME_(msg)( "message %04x needs translation\n", msg );
1458 /* the following messages should not be sent to 16-bit apps */
1461 case WM_CAPTURECHANGED:
1462 case WM_STYLECHANGING:
1463 case WM_STYLECHANGED:
1466 ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1473 /***********************************************************************
1474 * SendMessage (USER.111)
1476 LRESULT WINAPI SendMessage16( HWND16 hwnd16, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
1479 HWND hwnd = WIN_Handle32( hwnd16 );
1481 if (hwnd != HWND_BROADCAST && WIN_IsCurrentThread(hwnd))
1483 /* call 16-bit window proc directly */
1486 /* first the WH_CALLWNDPROC hook */
1487 if (HOOK_IsHooked( WH_CALLWNDPROC ))
1488 WINPROC_CallProc16To32A( cwp_hook_callback, hwnd16, msg, wparam, lparam, &result, NULL );
1490 if (!(winproc = (WNDPROC16)GetWindowLong16( hwnd16, GWLP_WNDPROC ))) return 0;
1492 SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wparam, lparam );
1493 result = CallWindowProc16( winproc, hwnd16, msg, wparam, lparam );
1494 SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, result, wparam, lparam );
1496 else /* map to 32-bit unicode for inter-thread/process message */
1498 WINPROC_CallProc16To32A( send_message_callback, hwnd16, msg, wparam, lparam, &result, NULL );
1504 /***********************************************************************
1505 * PostMessage (USER.110)
1507 BOOL16 WINAPI PostMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
1510 return WINPROC_CallProc16To32A( post_message_callback, hwnd, msg, wparam, lparam, &unused, NULL );
1514 /***********************************************************************
1515 * PostAppMessage (USER.116)
1517 BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
1520 DWORD_PTR tid = HTASK_32( hTask );
1522 if (!tid) return FALSE;
1523 return WINPROC_CallProc16To32A( post_thread_message_callback, 0, msg, wparam, lparam,
1524 &unused, (void *)tid );
1528 /**********************************************************************
1529 * CallWindowProc (USER.122)
1531 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
1532 WPARAM16 wParam, LPARAM lParam )
1534 int index = winproc_to_index( func );
1537 if (!func) return 0;
1539 if (index == -1 || index >= MAX_WINPROCS32)
1540 call_window_proc16( hwnd, msg, wParam, lParam, &result, func );
1542 WINPROC_CallProc16To32A( call_window_proc_callback, hwnd, msg, wParam, lParam, &result,
1543 thunk_array[index].proc );
1548 /**********************************************************************
1549 * __wine_call_wndproc (USER.1010)
1551 LRESULT WINAPI __wine_call_wndproc( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam, WNDPROC proc )
1554 WINPROC_CallProc16To32A( call_window_proc_callback, hwnd, msg, wParam, lParam, &result, proc );
1559 /***********************************************************************
1560 * InSendMessage (USER.192)
1562 BOOL16 WINAPI InSendMessage16(void)
1564 return InSendMessage();
1568 /***********************************************************************
1569 * ReplyMessage (USER.115)
1571 void WINAPI ReplyMessage16( LRESULT result )
1573 ReplyMessage( result );
1577 /***********************************************************************
1578 * PeekMessage32 (USER.819)
1580 BOOL16 WINAPI PeekMessage32_16( MSG32_16 *msg16, HWND16 hwnd16,
1581 UINT16 first, UINT16 last, UINT16 flags,
1582 BOOL16 wHaveParamHigh )
1586 HWND hwnd = WIN_Handle32( hwnd16 );
1588 if(USER16_AlertableWait)
1589 MsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, MWMO_ALERTABLE );
1590 if (!PeekMessageA( &msg, hwnd, first, last, flags )) return FALSE;
1592 msg16->msg.time = msg.time;
1593 msg16->msg.pt.x = (INT16)msg.pt.x;
1594 msg16->msg.pt.y = (INT16)msg.pt.y;
1595 if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
1596 WINPROC_CallProc32ATo16( get_message_callback, msg.hwnd, msg.message, msg.wParam, msg.lParam,
1597 &unused, &msg16->msg );
1602 /***********************************************************************
1603 * DefWindowProc (USER.107)
1605 LRESULT WINAPI DefWindowProc16( HWND16 hwnd16, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
1608 HWND hwnd = WIN_Handle32( hwnd16 );
1610 SPY_EnterMessage( SPY_DEFWNDPROC16, hwnd, msg, wParam, lParam );
1616 CREATESTRUCT16 *cs16 = MapSL(lParam);
1619 cs32.lpCreateParams = ULongToPtr(cs16->lpCreateParams);
1620 cs32.hInstance = HINSTANCE_32(cs16->hInstance);
1621 cs32.hMenu = HMENU_32(cs16->hMenu);
1622 cs32.hwndParent = WIN_Handle32(cs16->hwndParent);
1627 cs32.style = cs16->style;
1628 cs32.dwExStyle = cs16->dwExStyle;
1629 cs32.lpszName = MapSL(cs16->lpszName);
1630 cs32.lpszClass = MapSL(cs16->lpszClass);
1631 result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&cs32 );
1637 RECT16 *rect16 = MapSL(lParam);
1640 rect32.left = rect16->left;
1641 rect32.top = rect16->top;
1642 rect32.right = rect16->right;
1643 rect32.bottom = rect16->bottom;
1645 result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&rect32 );
1647 rect16->left = rect32.left;
1648 rect16->top = rect32.top;
1649 rect16->right = rect32.right;
1650 rect16->bottom = rect32.bottom;
1654 case WM_WINDOWPOSCHANGING:
1655 case WM_WINDOWPOSCHANGED:
1657 WINDOWPOS16 *pos16 = MapSL(lParam);
1660 pos32.hwnd = WIN_Handle32(pos16->hwnd);
1661 pos32.hwndInsertAfter = WIN_Handle32(pos16->hwndInsertAfter);
1664 pos32.cx = pos16->cx;
1665 pos32.cy = pos16->cy;
1666 pos32.flags = pos16->flags;
1668 result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&pos32 );
1670 pos16->hwnd = HWND_16(pos32.hwnd);
1671 pos16->hwndInsertAfter = HWND_16(pos32.hwndInsertAfter);
1674 pos16->cx = pos32.cx;
1675 pos16->cy = pos32.cy;
1676 pos16->flags = pos32.flags;
1682 result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)MapSL(lParam) );
1686 result = DefWindowProcA( hwnd, msg, wParam, lParam );
1690 SPY_ExitMessage( SPY_RESULT_DEFWND16, hwnd, msg, result, wParam, lParam );
1695 /***********************************************************************
1696 * DefDlgProc (USER.308)
1698 LRESULT WINAPI DefDlgProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
1701 WINPROC_CallProc16To32A( defdlg_proc_callback, hwnd, msg, wParam, lParam, &result, 0 );
1706 /***********************************************************************
1707 * PeekMessage (USER.109)
1709 BOOL16 WINAPI PeekMessage16( MSG16 *msg, HWND16 hwnd,
1710 UINT16 first, UINT16 last, UINT16 flags )
1712 return PeekMessage32_16( (MSG32_16 *)msg, hwnd, first, last, flags, FALSE );
1716 /***********************************************************************
1717 * GetMessage32 (USER.820)
1719 BOOL16 WINAPI GetMessage32_16( MSG32_16 *msg16, HWND16 hwnd16, UINT16 first,
1720 UINT16 last, BOOL16 wHaveParamHigh )
1724 HWND hwnd = WIN_Handle32( hwnd16 );
1726 if(USER16_AlertableWait)
1727 MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, 0, MWMO_ALERTABLE );
1728 GetMessageA( &msg, hwnd, first, last );
1729 msg16->msg.time = msg.time;
1730 msg16->msg.pt.x = (INT16)msg.pt.x;
1731 msg16->msg.pt.y = (INT16)msg.pt.y;
1732 if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
1733 WINPROC_CallProc32ATo16( get_message_callback, msg.hwnd, msg.message, msg.wParam, msg.lParam,
1734 &unused, &msg16->msg );
1736 TRACE( "message %04x, hwnd %p, filter(%04x - %04x)\n",
1737 msg16->msg.message, hwnd, first, last );
1739 return msg16->msg.message != WM_QUIT;
1743 /***********************************************************************
1744 * GetMessage (USER.108)
1746 BOOL16 WINAPI GetMessage16( MSG16 *msg, HWND16 hwnd, UINT16 first, UINT16 last )
1748 return GetMessage32_16( (MSG32_16 *)msg, hwnd, first, last, FALSE );
1752 /***********************************************************************
1753 * TranslateMessage32 (USER.821)
1755 BOOL16 WINAPI TranslateMessage32_16( const MSG32_16 *msg, BOOL16 wHaveParamHigh )
1759 msg32.hwnd = WIN_Handle32( msg->msg.hwnd );
1760 msg32.message = msg->msg.message;
1761 msg32.wParam = MAKEWPARAM( msg->msg.wParam, wHaveParamHigh ? msg->wParamHigh : 0 );
1762 msg32.lParam = msg->msg.lParam;
1763 return TranslateMessage( &msg32 );
1767 /***********************************************************************
1768 * TranslateMessage (USER.113)
1770 BOOL16 WINAPI TranslateMessage16( const MSG16 *msg )
1772 return TranslateMessage32_16( (const MSG32_16 *)msg, FALSE );
1776 /***********************************************************************
1777 * DispatchMessage (USER.114)
1779 LONG WINAPI DispatchMessage16( const MSG16* msg )
1784 HWND hwnd = WIN_Handle32( msg->hwnd );
1786 /* Process timer messages */
1787 if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
1790 return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
1791 msg->message, msg->wParam, GetTickCount() );
1794 if (!(wndPtr = WIN_GetPtr( hwnd )))
1796 if (msg->hwnd) SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1799 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1801 if (IsWindow( hwnd )) SetLastError( ERROR_MESSAGE_SYNC_ONLY );
1802 else SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1805 winproc = WINPROC_GetProc16( wndPtr->winproc, wndPtr->flags & WIN_ISUNICODE );
1806 WIN_ReleasePtr( wndPtr );
1808 SPY_EnterMessage( SPY_DISPATCHMESSAGE16, hwnd, msg->message, msg->wParam, msg->lParam );
1809 retval = CallWindowProc16( winproc, msg->hwnd, msg->message, msg->wParam, msg->lParam );
1810 SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg->message, retval, msg->wParam, msg->lParam );
1816 /***********************************************************************
1817 * DispatchMessage32 (USER.822)
1819 LONG WINAPI DispatchMessage32_16( const MSG32_16 *msg16, BOOL16 wHaveParamHigh )
1821 if (wHaveParamHigh == FALSE)
1822 return DispatchMessage16( &msg16->msg );
1827 msg.hwnd = WIN_Handle32( msg16->msg.hwnd );
1828 msg.message = msg16->msg.message;
1829 msg.wParam = MAKEWPARAM( msg16->msg.wParam, msg16->wParamHigh );
1830 msg.lParam = msg16->msg.lParam;
1831 msg.time = msg16->msg.time;
1832 msg.pt.x = msg16->msg.pt.x;
1833 msg.pt.y = msg16->msg.pt.y;
1834 return DispatchMessageA( &msg );
1839 /***********************************************************************
1840 * IsDialogMessage (USER.90)
1842 BOOL16 WINAPI IsDialogMessage16( HWND16 hwndDlg, MSG16 *msg16 )
1847 msg.hwnd = WIN_Handle32(msg16->hwnd);
1848 hwndDlg32 = WIN_Handle32(hwndDlg);
1850 switch(msg16->message)
1855 msg.message = msg16->message;
1856 msg.wParam = msg16->wParam;
1857 msg.lParam = msg16->lParam;
1858 return IsDialogMessageA( hwndDlg32, &msg );
1861 if ((hwndDlg32 != msg.hwnd) && !IsChild( hwndDlg32, msg.hwnd )) return FALSE;
1862 TranslateMessage16( msg16 );
1863 DispatchMessage16( msg16 );
1868 /***********************************************************************
1869 * MsgWaitForMultipleObjects (USER.640)
1871 DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
1872 BOOL wait_all, DWORD timeout, DWORD mask )
1874 return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
1875 wait_all ? MWMO_WAITALL : 0 );
1879 /**********************************************************************
1880 * SetDoubleClickTime (USER.20)
1882 void WINAPI SetDoubleClickTime16( UINT16 interval )
1884 SetDoubleClickTime( interval );
1888 /**********************************************************************
1889 * GetDoubleClickTime (USER.21)
1891 UINT16 WINAPI GetDoubleClickTime16(void)
1893 return GetDoubleClickTime();
1897 /***********************************************************************
1898 * PostQuitMessage (USER.6)
1900 void WINAPI PostQuitMessage16( INT16 exitCode )
1902 PostQuitMessage( exitCode );
1906 /**********************************************************************
1907 * GetKeyState (USER.106)
1909 INT16 WINAPI GetKeyState16(INT16 vkey)
1911 return GetKeyState(vkey);
1915 /**********************************************************************
1916 * GetKeyboardState (USER.222)
1918 BOOL WINAPI GetKeyboardState16( LPBYTE state )
1920 return GetKeyboardState( state );
1924 /**********************************************************************
1925 * SetKeyboardState (USER.223)
1927 BOOL WINAPI SetKeyboardState16( LPBYTE state )
1929 return SetKeyboardState( state );
1933 /***********************************************************************
1934 * SetMessageQueue (USER.266)
1936 BOOL16 WINAPI SetMessageQueue16( INT16 size )
1938 return SetMessageQueue( size );
1942 /***********************************************************************
1943 * UserYield (USER.332)
1945 void WINAPI UserYield16(void)
1948 PeekMessageW( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE );
1952 /***********************************************************************
1953 * GetQueueStatus (USER.334)
1955 DWORD WINAPI GetQueueStatus16( UINT16 flags )
1957 return GetQueueStatus( flags );
1961 /***********************************************************************
1962 * GetInputState (USER.335)
1964 BOOL16 WINAPI GetInputState16(void)
1966 return GetInputState();
1970 /**********************************************************************
1971 * TranslateAccelerator (USER.178)
1973 INT16 WINAPI TranslateAccelerator16( HWND16 hwnd, HACCEL16 hAccel, LPMSG16 msg )
1978 msg32.message = msg->message;
1979 /* msg32.hwnd not used */
1980 msg32.wParam = msg->wParam;
1981 msg32.lParam = msg->lParam;
1982 return TranslateAcceleratorW( WIN_Handle32(hwnd), HACCEL_32(hAccel), &msg32 );
1986 /**********************************************************************
1987 * TranslateMDISysAccel (USER.451)
1989 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
1991 if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
1994 msg32.hwnd = WIN_Handle32(msg->hwnd);
1995 msg32.message = msg->message;
1996 msg32.wParam = msg->wParam;
1997 msg32.lParam = msg->lParam;
1998 /* MDICLIENTINFO is still the same for win32 and win16 ... */
1999 return TranslateMDISysAccel( WIN_Handle32(hwndClient), &msg32 );
2005 /***********************************************************************
2006 * CreateWindowEx (USER.452)
2008 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
2009 LPCSTR windowName, DWORD style, INT16 x,
2010 INT16 y, INT16 width, INT16 height,
2011 HWND16 parent, HMENU16 menu,
2012 HINSTANCE16 instance, LPVOID data )
2018 /* Fix the coordinates */
2020 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
2021 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
2022 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
2023 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
2025 /* Create the window */
2027 cs.lpCreateParams = data;
2028 cs.hInstance = HINSTANCE_32(instance);
2029 cs.hMenu = HMENU_32(menu);
2030 cs.hwndParent = WIN_Handle32( parent );
2032 cs.lpszName = windowName;
2033 cs.lpszClass = className;
2034 cs.dwExStyle = exStyle;
2036 /* map to module handle */
2037 if (instance) instance = GetExePtr( instance );
2040 if (!menu && (style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
2044 if (GetClassInfoA( HINSTANCE_32(instance), className, &class ))
2045 cs.hMenu = HMENU_32( LoadMenu16( instance, class.lpszMenuName ));
2048 if (!IS_INTRESOURCE(className))
2052 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
2054 hwnd = wow_handlers32.create_window( (CREATESTRUCTW *)&cs, bufferW,
2055 HINSTANCE_32(instance), 0 );
2059 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
2061 ERR( "bad atom %x\n", LOWORD(className));
2064 cs.lpszClass = buffer;
2065 hwnd = wow_handlers32.create_window( (CREATESTRUCTW *)&cs, (LPCWSTR)className,
2066 HINSTANCE_32(instance), 0 );
2068 return HWND_16( hwnd );
2072 /***********************************************************************
2075 static LRESULT button_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2077 static const UINT msg16_offset = BM_GETCHECK16 - BM_GETCHECK;
2086 return wow_handlers32.button_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE );
2088 return wow_handlers32.button_proc( hwnd, msg, wParam, lParam, unicode );
2093 /***********************************************************************
2096 static LRESULT combo_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2098 static const UINT msg16_offset = CB_GETEDITSEL16 - CB_GETEDITSEL;
2102 case CB_INSERTSTRING16:
2103 case CB_SELECTSTRING16:
2104 case CB_FINDSTRING16:
2105 case CB_FINDSTRINGEXACT16:
2106 wParam = (INT)(INT16)wParam;
2108 case CB_ADDSTRING16:
2109 if (GetWindowLongW( hwnd, GWL_STYLE ) & CBS_HASSTRINGS) lParam = (LPARAM)MapSL(lParam);
2110 msg -= msg16_offset;
2112 case CB_SETITEMHEIGHT16:
2113 case CB_GETITEMHEIGHT16:
2114 case CB_SETCURSEL16:
2115 case CB_GETLBTEXTLEN16:
2116 case CB_GETITEMDATA16:
2117 case CB_SETITEMDATA16:
2118 wParam = (INT)(INT16)wParam; /* signed integer */
2119 msg -= msg16_offset;
2121 case CB_GETDROPPEDCONTROLRECT16:
2122 lParam = (LPARAM)MapSL(lParam);
2126 RECT16 *r16 = (RECT16 *)lParam;
2127 wow_handlers32.combo_proc( hwnd, CB_GETDROPPEDCONTROLRECT, wParam, (LPARAM)&r, FALSE );
2130 r16->right = r.right;
2131 r16->bottom = r.bottom;
2135 if (wParam & DDL_DRIVES) wParam |= DDL_EXCLUSIVE;
2136 lParam = (LPARAM)MapSL(lParam);
2137 msg -= msg16_offset;
2139 case CB_GETLBTEXT16:
2140 wParam = (INT)(INT16)wParam;
2141 lParam = (LPARAM)MapSL(lParam);
2142 msg -= msg16_offset;
2144 case CB_GETEDITSEL16:
2145 wParam = lParam = 0; /* just in case */
2146 msg -= msg16_offset;
2148 case CB_LIMITTEXT16:
2149 case CB_SETEDITSEL16:
2150 case CB_DELETESTRING16:
2151 case CB_RESETCONTENT16:
2152 case CB_GETDROPPEDSTATE16:
2153 case CB_SHOWDROPDOWN16:
2155 case CB_GETCURSEL16:
2156 case CB_SETEXTENDEDUI16:
2157 case CB_GETEXTENDEDUI16:
2158 msg -= msg16_offset;
2161 return wow_handlers32.combo_proc( hwnd, msg, wParam, lParam, unicode );
2163 return wow_handlers32.combo_proc( hwnd, msg, wParam, lParam, FALSE );
2167 #define GWW_HANDLE16 sizeof(void*)
2169 static void edit_lock_buffer( HWND hwnd )
2171 STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved));
2172 HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 );
2177 if (!hloc16) return;
2178 if (!(hloc32 = (HLOCAL)wow_handlers32.edit_proc( hwnd, EM_GETHANDLE, 0, 0, FALSE ))) return;
2180 oldDS = stack16->ds;
2181 stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
2182 size = LocalSize16(hloc16);
2183 if (LocalReAlloc( hloc32, size, LMEM_MOVEABLE ))
2185 char *text = MapSL( LocalLock16( hloc16 ));
2186 char *dest = LocalLock( hloc32 );
2187 memcpy( dest, text, size );
2188 LocalUnlock( hloc32 );
2189 LocalUnlock16( hloc16 );
2191 stack16->ds = oldDS;
2195 static void edit_unlock_buffer( HWND hwnd )
2197 STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved));
2198 HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 );
2203 if (!hloc16) return;
2204 if (!(hloc32 = (HLOCAL)wow_handlers32.edit_proc( hwnd, EM_GETHANDLE, 0, 0, FALSE ))) return;
2205 size = LocalSize( hloc32 );
2207 oldDS = stack16->ds;
2208 stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
2209 if (LocalReAlloc16( hloc16, size, LMEM_MOVEABLE ))
2211 char *text = LocalLock( hloc32 );
2212 char *dest = MapSL( LocalLock16( hloc16 ));
2213 memcpy( dest, text, size );
2214 LocalUnlock( hloc32 );
2215 LocalUnlock16( hloc16 );
2217 stack16->ds = oldDS;
2220 static HLOCAL16 edit_get_handle( HWND hwnd )
2225 STACK16FRAME* stack16;
2227 HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 );
2229 if (hloc16) return hloc16;
2231 if (!(hloc = (HLOCAL)wow_handlers32.edit_proc( hwnd, EM_GETHANDLE, 0, 0, FALSE ))) return 0;
2232 alloc_size = LocalSize( hloc );
2234 stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved));
2235 oldDS = stack16->ds;
2236 stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
2238 if (!LocalHeapSize16())
2240 if (!LocalInit16(stack16->ds, 0, GlobalSize16(stack16->ds)))
2242 ERR("could not initialize local heap\n");
2247 if (!(hloc16 = LocalAlloc16(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size)))
2249 ERR("could not allocate new 16 bit buffer\n");
2253 if (!(textA = MapSL(LocalLock16( hloc16))))
2255 ERR("could not lock new 16 bit buffer\n");
2256 LocalFree16(hloc16);
2260 memcpy( textA, LocalLock( hloc ), alloc_size );
2261 LocalUnlock( hloc );
2262 LocalUnlock16( hloc16 );
2263 SetWindowWord( hwnd, GWW_HANDLE16, hloc16 );
2266 stack16->ds = oldDS;
2270 static void edit_set_handle( HWND hwnd, HLOCAL16 hloc16 )
2272 STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved));
2273 HINSTANCE16 hInstance = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
2274 HANDLE16 oldDS = stack16->ds;
2279 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & ES_MULTILINE)) return;
2280 if (!hloc16) return;
2282 stack16->ds = hInstance;
2283 count = LocalSize16(hloc16);
2284 text = MapSL(LocalLock16(hloc16));
2285 if ((hloc32 = LocalAlloc(LMEM_MOVEABLE, count)))
2287 memcpy( LocalLock(hloc32), text, count );
2288 LocalUnlock(hloc32);
2289 LocalUnlock16(hloc16);
2290 SetWindowWord( hwnd, GWW_HANDLE16, hloc16 );
2292 stack16->ds = oldDS;
2294 if (hloc32) wow_handlers32.edit_proc( hwnd, EM_SETHANDLE, (WPARAM)hloc32, 0, FALSE );
2297 static void edit_destroy_handle( HWND hwnd )
2299 HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 );
2302 STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved));
2303 HANDLE16 oldDS = stack16->ds;
2305 stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
2306 while (LocalUnlock16(hloc16)) ;
2307 LocalFree16(hloc16);
2308 stack16->ds = oldDS;
2309 SetWindowWord( hwnd, GWW_HANDLE16, 0 );
2313 /*********************************************************************
2316 static LRESULT edit_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2318 static const UINT msg16_offset = EM_GETSEL16 - EM_GETSEL;
2321 edit_lock_buffer( hwnd );
2325 case EM_SCROLLCARET16:
2326 case EM_GETMODIFY16:
2327 case EM_SETMODIFY16:
2328 case EM_GETLINECOUNT16:
2330 case EM_LINELENGTH16:
2331 case EM_LIMITTEXT16:
2335 case EM_LINEFROMCHAR16:
2336 case EM_SETPASSWORDCHAR16:
2337 case EM_EMPTYUNDOBUFFER16:
2338 case EM_SETREADONLY16:
2339 case EM_GETPASSWORDCHAR16:
2340 /* these messages missing from specs */
2345 result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE );
2348 result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, 0, 0, FALSE );
2350 case EM_REPLACESEL16:
2352 result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, (LPARAM)MapSL(lParam), FALSE );
2354 case EM_LINESCROLL16:
2355 result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, (INT)(SHORT)HIWORD(lParam),
2356 (INT)(SHORT)LOWORD(lParam), FALSE );
2358 case EM_LINEINDEX16:
2359 if ((INT16)wParam == -1) wParam = (WPARAM)-1;
2360 result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE );
2363 if ((short)LOWORD(lParam) == -1)
2370 wParam = LOWORD(lParam);
2371 lParam = HIWORD(lParam);
2373 result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE );
2379 RECT16 *r16 = MapSL(lParam);
2380 wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, (LPARAM)&rect, FALSE );
2381 r16->left = rect.left;
2382 r16->top = rect.top;
2383 r16->right = rect.right;
2384 r16->bottom = rect.bottom;
2388 case EM_SETRECTNP16:
2392 RECT16 *r16 = MapSL(lParam);
2393 rect.left = r16->left;
2394 rect.top = r16->top;
2395 rect.right = r16->right;
2396 rect.bottom = r16->bottom;
2397 wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, (LPARAM)&rect, FALSE );
2400 case EM_SETHANDLE16:
2401 edit_set_handle( hwnd, (HLOCAL16)wParam );
2403 case EM_GETHANDLE16:
2404 result = edit_get_handle( hwnd );
2406 case EM_SETTABSTOPS16:
2408 INT16 *tabs16 = MapSL(lParam);
2409 INT i, count = wParam, *tabs = NULL;
2412 if (!(tabs = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*tabs) ))) return 0;
2413 for (i = 0; i < count; i++) tabs[i] = tabs16[i];
2415 result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, count, (LPARAM)tabs, FALSE );
2416 HeapFree( GetProcessHeap(), 0, tabs );
2419 case EM_GETFIRSTVISIBLELINE16:
2420 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & ES_MULTILINE)) break;
2421 result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE );
2423 case EM_SETWORDBREAKPROC16:
2425 struct word_break_thunk *thunk = add_word_break_thunk( (EDITWORDBREAKPROC16)lParam );
2426 result = wow_handlers32.edit_proc( hwnd, EM_SETWORDBREAKPROC, wParam, (LPARAM)thunk, FALSE );
2429 case EM_GETWORDBREAKPROC16:
2430 result = wow_handlers32.edit_proc( hwnd, EM_GETWORDBREAKPROC, wParam, lParam, FALSE );
2431 result = (LRESULT)get_word_break_thunk( (EDITWORDBREAKPROCA)result );
2434 edit_destroy_handle( hwnd );
2435 return wow_handlers32.edit_proc( hwnd, msg, wParam, lParam, unicode ); /* no unlock on destroy */
2438 if (LOWORD(wParam) == EM_GETTHUMB16 || LOWORD(wParam) == EM_LINESCROLL16) wParam -= msg16_offset;
2439 result = wow_handlers32.edit_proc( hwnd, msg, wParam, lParam, unicode );
2442 result = wow_handlers32.edit_proc( hwnd, msg, wParam, lParam, unicode );
2445 edit_unlock_buffer( hwnd );
2450 /***********************************************************************
2453 static LRESULT listbox_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2455 static const UINT msg16_offset = LB_ADDSTRING16 - LB_ADDSTRING;
2460 case LB_RESETCONTENT16:
2461 case LB_DELETESTRING16:
2462 case LB_GETITEMDATA16:
2463 case LB_SETITEMDATA16:
2465 case LB_GETTEXTLEN16:
2466 case LB_GETCURSEL16:
2467 case LB_GETTOPINDEX16:
2468 case LB_GETITEMHEIGHT16:
2469 case LB_SETCARETINDEX16:
2470 case LB_GETCARETINDEX16:
2471 case LB_SETTOPINDEX16:
2472 case LB_SETCOLUMNWIDTH16:
2473 case LB_GETSELCOUNT16:
2474 case LB_SELITEMRANGE16:
2475 case LB_SELITEMRANGEEX16:
2476 case LB_GETHORIZONTALEXTENT16:
2477 case LB_SETHORIZONTALEXTENT16:
2478 case LB_GETANCHORINDEX16:
2481 msg -= msg16_offset;
2485 case LB_SETCURSEL16:
2486 case LB_SETANCHORINDEX16:
2487 wParam = (INT)(INT16)wParam;
2488 msg -= msg16_offset;
2490 case LB_INSERTSTRING16:
2491 case LB_FINDSTRING16:
2492 case LB_FINDSTRINGEXACT16:
2493 case LB_SELECTSTRING16:
2494 wParam = (INT)(INT16)wParam;
2496 case LB_ADDSTRING16:
2499 DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
2500 if ((style & LBS_HASSTRINGS) || !(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)))
2501 lParam = (LPARAM)MapSL(lParam);
2502 msg -= msg16_offset;
2506 lParam = (LPARAM)MapSL(lParam);
2507 msg -= msg16_offset;
2509 case LB_SETITEMHEIGHT16:
2510 lParam = LOWORD(lParam);
2511 msg -= msg16_offset;
2513 case LB_GETITEMRECT16:
2516 RECT16 *r16 = MapSL(lParam);
2517 ret = wow_handlers32.listbox_proc( hwnd, LB_GETITEMRECT, (INT16)wParam, (LPARAM)&rect, FALSE );
2518 r16->left = rect.left;
2519 r16->top = rect.top;
2520 r16->right = rect.right;
2521 r16->bottom = rect.bottom;
2524 case LB_GETSELITEMS16:
2526 INT16 *array16 = MapSL( lParam );
2527 INT i, count = (INT16)wParam, *array;
2528 if (!(array = HeapAlloc( GetProcessHeap(), 0, wParam * sizeof(*array) ))) return LB_ERRSPACE;
2529 ret = wow_handlers32.listbox_proc( hwnd, LB_GETSELITEMS, count, (LPARAM)array, FALSE );
2530 for (i = 0; i < ret; i++) array16[i] = array[i];
2531 HeapFree( GetProcessHeap(), 0, array );
2535 /* according to Win16 docs, DDL_DRIVES should make DDL_EXCLUSIVE
2536 * be set automatically (this is different in Win32) */
2537 if (wParam & DDL_DRIVES) wParam |= DDL_EXCLUSIVE;
2538 lParam = (LPARAM)MapSL(lParam);
2539 msg -= msg16_offset;
2541 case LB_SETTABSTOPS16:
2543 INT i, count, *tabs = NULL;
2544 INT16 *tabs16 = MapSL( lParam );
2546 if ((count = (INT16)wParam) > 0)
2548 if (!(tabs = HeapAlloc( GetProcessHeap(), 0, wParam * sizeof(*tabs) ))) return LB_ERRSPACE;
2549 for (i = 0; i < count; i++) tabs[i] = tabs16[i] << 1; /* FIXME */
2551 ret = wow_handlers32.listbox_proc( hwnd, LB_SETTABSTOPS, count, (LPARAM)tabs, FALSE );
2552 HeapFree( GetProcessHeap(), 0, tabs );
2556 return wow_handlers32.listbox_proc( hwnd, msg, wParam, lParam, unicode );
2558 return wow_handlers32.listbox_proc( hwnd, msg, wParam, lParam, FALSE );
2562 /***********************************************************************
2565 static LRESULT mdiclient_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2567 if (msg == WM_CREATE)
2569 LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
2573 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2574 is_win32 = (win == WND_OTHER_PROCESS || win == WND_DESKTOP || (win->flags & WIN_ISWIN32));
2575 WIN_ReleasePtr( win );
2577 /* Translation layer doesn't know what's in the cs->lpCreateParams
2578 * so we have to keep track of what environment we're in. */
2581 void *orig = cs->lpCreateParams;
2583 CLIENTCREATESTRUCT ccs;
2584 CLIENTCREATESTRUCT16 *ccs16 = MapSL( PtrToUlong( orig ));
2586 ccs.hWindowMenu = HMENU_32(ccs16->hWindowMenu);
2587 ccs.idFirstChild = ccs16->idFirstChild;
2588 cs->lpCreateParams = &ccs;
2589 ret = wow_handlers32.mdiclient_proc( hwnd, msg, wParam, lParam, unicode );
2590 cs->lpCreateParams = orig;
2594 return wow_handlers32.mdiclient_proc( hwnd, msg, wParam, lParam, unicode );
2598 /***********************************************************************
2601 static LRESULT scrollbar_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2603 static const UINT msg16_offset = SBM_SETPOS16 - SBM_SETPOS;
2609 case SBM_ENABLE_ARROWS16:
2610 msg -= msg16_offset;
2612 case SBM_SETRANGE16:
2613 msg = wParam ? SBM_SETRANGEREDRAW : SBM_SETRANGE;
2614 wParam = LOWORD(lParam);
2615 lParam = HIWORD(lParam);
2617 case SBM_GETRANGE16:
2620 wow_handlers32.scrollbar_proc( hwnd, SBM_GETRANGE, (WPARAM)&min, (LPARAM)&max, FALSE );
2621 return MAKELRESULT(min, max);
2624 return wow_handlers32.scrollbar_proc( hwnd, msg, wParam, lParam, unicode );
2626 return wow_handlers32.scrollbar_proc( hwnd, msg, wParam, lParam, FALSE );
2630 /***********************************************************************
2633 static LRESULT static_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2638 wParam = (WPARAM)HICON_32( (HICON16)wParam );
2639 return wow_handlers32.static_proc( hwnd, STM_SETICON, wParam, lParam, FALSE );
2641 return HICON_16( wow_handlers32.static_proc( hwnd, STM_GETICON, wParam, lParam, FALSE ));
2643 return wow_handlers32.static_proc( hwnd, msg, wParam, lParam, unicode );
2648 void register_wow_handlers(void)
2650 static const struct wow_handlers16 handlers16 =
2659 call_window_proc_Ato16,
2660 call_dialog_proc_Ato16
2663 UserRegisterWowHandlers( &handlers16, &wow_handlers32 );