user32: Reimplement 16-bit clipboard functions on top of the 32-bit ones.
[wine] / dlls / user32 / msg16.c
1 /*
2  * 16-bit messaging support
3  *
4  * Copyright 2001 Alexandre Julliard
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <string.h>
27
28 #include "wine/winuser16.h"
29 #include "wownt32.h"
30 #include "winerror.h"
31 #include "win.h"
32 #include "dde.h"
33 #include "user_private.h"
34 #include "controls.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(msg);
38
39 DWORD USER16_AlertableWait = 0;
40
41 static struct wow_handlers32 wow_handlers32;
42
43 static LRESULT cwp_hook_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
44                                   LRESULT *result, void *arg )
45 {
46     CWPSTRUCT cwp;
47
48     cwp.hwnd    = hwnd;
49     cwp.message = msg;
50     cwp.wParam  = wp;
51     cwp.lParam  = lp;
52     *result = 0;
53     return HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp, FALSE );
54 }
55
56 static LRESULT send_message_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
57                                       LRESULT *result, void *arg )
58 {
59     *result = SendMessageA( hwnd, msg, wp, lp );
60     return *result;
61 }
62
63 static LRESULT post_message_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
64                                       LRESULT *result, void *arg )
65 {
66     *result = 0;
67     return PostMessageA( hwnd, msg, wp, lp );
68 }
69
70 static LRESULT post_thread_message_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
71                                              LRESULT *result, void *arg )
72 {
73     DWORD_PTR tid = (DWORD_PTR)arg;
74     *result = 0;
75     return PostThreadMessageA( tid, msg, wp, lp );
76 }
77
78 static LRESULT get_message_callback( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp,
79                                      LRESULT *result, void *arg )
80 {
81     MSG16 *msg16 = arg;
82
83     msg16->hwnd    = hwnd;
84     msg16->message = msg;
85     msg16->wParam  = wp;
86     msg16->lParam  = lp;
87     *result = 0;
88     return 0;
89 }
90
91 static LRESULT defdlg_proc_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
92                                      LRESULT *result, void *arg )
93 {
94     *result = DefDlgProcA( hwnd, msg, wp, lp );
95     return *result;
96 }
97
98 static LRESULT call_window_proc_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
99                                           LRESULT *result, void *arg )
100 {
101     WNDPROC proc = arg;
102     *result = CallWindowProcA( proc, hwnd, msg, wp, lp );
103     return *result;
104 }
105
106
107 /**********************************************************************
108  * Support for window procedure thunks
109  */
110
111 #include "pshpack1.h"
112 typedef struct
113 {
114     BYTE        popl_eax;        /* popl  %eax (return address) */
115     BYTE        pushl_func;      /* pushl $proc */
116     WNDPROC     proc;
117     BYTE        pushl_eax;       /* pushl %eax */
118     BYTE        ljmp;            /* ljmp relay*/
119     DWORD       relay_offset;    /* __wine_call_wndproc */
120     WORD        relay_sel;
121 } WINPROC_THUNK;
122 #include "poppack.h"
123
124 #define WINPROC_HANDLE (~0u >> 16)
125 #define MAX_WINPROCS32 4096
126 #define MAX_WINPROCS16 1024
127
128 static WNDPROC16 winproc16_array[MAX_WINPROCS16];
129 static unsigned int winproc16_used;
130
131 static WINPROC_THUNK *thunk_array;
132 static UINT thunk_selector;
133
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 )
138 {
139     unsigned int index;
140
141     if (HIWORD(handle) == thunk_selector)
142     {
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;
148     }
149     else
150     {
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;
155     }
156     return index;
157 }
158
159 /* allocate a 16-bit thunk for an existing window proc */
160 static WNDPROC16 alloc_win16_thunk( WNDPROC handle )
161 {
162     static FARPROC16 relay;
163     WINPROC_THUNK *thunk;
164     UINT index = LOWORD( handle );
165
166     if (index >= MAX_WINPROCS32)  /* already a 16-bit proc */
167         return winproc16_array[index - MAX_WINPROCS32];
168
169     if (!thunk_array)  /* allocate the array and its selector */
170     {
171         LDT_ENTRY entry;
172
173         assert( MAX_WINPROCS16 * sizeof(WINPROC_THUNK) <= 0x10000 );
174
175         if (!(thunk_selector = wine_ldt_alloc_entries(1))) return NULL;
176         if (!(thunk_array = VirtualAlloc( NULL, MAX_WINPROCS16 * sizeof(WINPROC_THUNK), MEM_COMMIT,
177                                           PAGE_EXECUTE_READWRITE ))) return NULL;
178         wine_ldt_set_base( &entry, thunk_array );
179         wine_ldt_set_limit( &entry, MAX_WINPROCS16 * sizeof(WINPROC_THUNK) - 1 );
180         wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
181         wine_ldt_set_entry( thunk_selector, &entry );
182         relay = GetProcAddress16( GetModuleHandle16("user"), "__wine_call_wndproc" );
183     }
184
185     thunk = &thunk_array[index];
186     thunk->popl_eax     = 0x58;   /* popl  %eax */
187     thunk->pushl_func   = 0x68;   /* pushl $proc */
188     thunk->proc         = handle;
189     thunk->pushl_eax    = 0x50;   /* pushl %eax */
190     thunk->ljmp         = 0xea;   /* ljmp   relay*/
191     thunk->relay_offset = OFFSETOF(relay);
192     thunk->relay_sel    = SELECTOROF(relay);
193     return (WNDPROC16)MAKESEGPTR( thunk_selector, index * sizeof(WINPROC_THUNK) );
194 }
195
196 /**********************************************************************
197  *           WINPROC_AllocProc16
198  */
199 WNDPROC WINPROC_AllocProc16( WNDPROC16 func )
200 {
201     int index;
202     WNDPROC ret;
203
204     if (!func) return NULL;
205
206     /* check if the function is already a win proc */
207     if ((index = winproc_to_index( func )) != -1)
208         return (WNDPROC)(ULONG_PTR)(index | (WINPROC_HANDLE << 16));
209
210     /* then check if we already have a winproc for that function */
211     for (index = 0; index < winproc16_used; index++)
212         if (winproc16_array[index] == func) goto done;
213
214     if (winproc16_used >= MAX_WINPROCS16)
215     {
216         FIXME( "too many winprocs, cannot allocate one for 16-bit %p\n", func );
217         return NULL;
218     }
219     winproc16_array[winproc16_used++] = func;
220
221 done:
222     ret = (WNDPROC)(ULONG_PTR)((index + MAX_WINPROCS32) | (WINPROC_HANDLE << 16));
223     TRACE( "returning %p for %p/16-bit (%d/%d used)\n",
224            ret, func, winproc16_used, MAX_WINPROCS16 );
225     return ret;
226 }
227
228 /**********************************************************************
229  *           WINPROC_GetProc16
230  *
231  * Get a window procedure pointer that can be passed to the Windows program.
232  */
233 WNDPROC16 WINPROC_GetProc16( WNDPROC proc, BOOL unicode )
234 {
235     WNDPROC winproc = wow_handlers32.alloc_winproc( proc, unicode );
236
237     if ((ULONG_PTR)winproc >> 16 != WINPROC_HANDLE) return (WNDPROC16)winproc;
238     return alloc_win16_thunk( winproc );
239 }
240
241 /* call a 16-bit window procedure */
242 static LRESULT call_window_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
243                                    LRESULT *result, void *arg )
244 {
245     WNDPROC16 func = arg;
246     int index = winproc_to_index( func );
247     CONTEXT86 context;
248     size_t size = 0;
249     struct
250     {
251         WORD params[5];
252         union
253         {
254             CREATESTRUCT16 cs16;
255             DRAWITEMSTRUCT16 dis16;
256             COMPAREITEMSTRUCT16 cis16;
257         } u;
258     } args;
259
260     USER_CheckNotLock();
261
262     if (index >= MAX_WINPROCS32) func = winproc16_array[index - MAX_WINPROCS32];
263
264     /* Window procedures want ax = hInstance, ds = es = ss */
265
266     memset(&context, 0, sizeof(context));
267     context.SegDs = context.SegEs = SELECTOROF(NtCurrentTeb()->WOW32Reserved);
268     context.SegFs = wine_get_fs();
269     context.SegGs = wine_get_gs();
270     if (!(context.Eax = GetWindowWord( HWND_32(hwnd), GWLP_HINSTANCE ))) context.Eax = context.SegDs;
271     context.SegCs = SELECTOROF(func);
272     context.Eip   = OFFSETOF(func);
273     context.Ebp   = OFFSETOF(NtCurrentTeb()->WOW32Reserved) + FIELD_OFFSET(STACK16FRAME, bp);
274
275     if (lParam)
276     {
277         /* Some programs (eg. the "Undocumented Windows" examples, JWP) only
278            work if structures passed in lParam are placed in the stack/data
279            segment. Programmers easily make the mistake of converting lParam
280            to a near rather than a far pointer, since Windows apparently
281            allows this. We copy the structures to the 16 bit stack; this is
282            ugly but makes these programs work. */
283         switch (msg)
284         {
285           case WM_CREATE:
286           case WM_NCCREATE:
287             size = sizeof(CREATESTRUCT16); break;
288           case WM_DRAWITEM:
289             size = sizeof(DRAWITEMSTRUCT16); break;
290           case WM_COMPAREITEM:
291             size = sizeof(COMPAREITEMSTRUCT16); break;
292         }
293         if (size)
294         {
295             memcpy( &args.u, MapSL(lParam), size );
296             lParam = PtrToUlong(NtCurrentTeb()->WOW32Reserved) - size;
297         }
298     }
299
300     args.params[4] = hwnd;
301     args.params[3] = msg;
302     args.params[2] = wParam;
303     args.params[1] = HIWORD(lParam);
304     args.params[0] = LOWORD(lParam);
305     WOWCallback16Ex( 0, WCB16_REGS, sizeof(args.params) + size, &args, (DWORD *)&context );
306     *result = MAKELONG( LOWORD(context.Eax), LOWORD(context.Edx) );
307     return *result;
308 }
309
310 static LRESULT call_dialog_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp,
311                                    LRESULT *result, void *arg )
312 {
313     LRESULT ret = call_window_proc16( hwnd, msg, wp, lp, result, arg );
314     *result = GetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT );
315     return LOWORD(ret);
316 }
317
318 static LRESULT call_window_proc_Ato16( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
319                                        LRESULT *result, void *arg )
320 {
321     return WINPROC_CallProc32ATo16( call_window_proc16, hwnd, msg, wp, lp, result, arg );
322 }
323
324 static LRESULT call_dialog_proc_Ato16( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
325                                        LRESULT *result, void *arg )
326 {
327     return WINPROC_CallProc32ATo16( call_dialog_proc16, hwnd, msg, wp, lp, result, arg );
328 }
329
330
331
332 /**********************************************************************
333  * Support for Edit word break proc thunks
334  */
335
336 #define MAX_THUNKS 32
337
338 #include <pshpack1.h>
339 static struct word_break_thunk
340 {
341     BYTE                popl_eax;       /* popl  %eax (return address) */
342     BYTE                pushl_proc16;   /* pushl proc16 */
343     EDITWORDBREAKPROC16 proc16;
344     BYTE                pushl_eax;      /* pushl %eax */
345     BYTE                jmp;            /* ljmp call_word_break_proc16 */
346     DWORD               callback;
347 } *word_break_thunks;
348 #include <poppack.h>
349
350 /**********************************************************************
351  *           call_word_break_proc16
352  */
353 static INT16 CALLBACK call_word_break_proc16( SEGPTR proc16, LPSTR text, INT index, INT count, INT action )
354 {
355     SEGPTR segptr;
356     WORD args[5];
357     DWORD result;
358
359     segptr = MapLS( text );
360     args[4] = SELECTOROF(segptr);
361     args[3] = OFFSETOF(segptr);
362     args[2] = index;
363     args[1] = count;
364     args[0] = action;
365     WOWCallback16Ex( proc16, WCB16_PASCAL, sizeof(args), args, &result );
366     UnMapLS( segptr );
367     return LOWORD(result);
368 }
369
370 /******************************************************************
371  *              add_word_break_thunk
372  */
373 static struct word_break_thunk *add_word_break_thunk( EDITWORDBREAKPROC16 proc16 )
374 {
375     struct word_break_thunk *thunk;
376
377     if (!word_break_thunks)
378     {
379         word_break_thunks = VirtualAlloc( NULL, MAX_THUNKS * sizeof(*thunk),
380                                           MEM_COMMIT, PAGE_EXECUTE_READWRITE );
381         if (!word_break_thunks) return NULL;
382
383         for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++)
384         {
385             thunk->popl_eax     = 0x58;   /* popl  %eax */
386             thunk->pushl_proc16 = 0x68;   /* pushl proc16 */
387             thunk->pushl_eax    = 0x50;   /* pushl %eax */
388             thunk->jmp          = 0xe9;   /* jmp call_word_break_proc16 */
389             thunk->callback     = (char *)call_word_break_proc16 - (char *)(&thunk->callback + 1);
390         }
391     }
392     for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++)
393         if (thunk->proc16 == proc16) return thunk;
394
395     for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++)
396     {
397         if (thunk->proc16) continue;
398         thunk->proc16 = proc16;
399         return thunk;
400     }
401     FIXME("Out of word break thunks\n");
402     return NULL;
403 }
404
405 /******************************************************************
406  *              get_word_break_thunk
407  */
408 static EDITWORDBREAKPROC16 get_word_break_thunk( EDITWORDBREAKPROCA proc )
409 {
410     struct word_break_thunk *thunk = (struct word_break_thunk *)proc;
411     if (word_break_thunks && thunk >= word_break_thunks && thunk < &word_break_thunks[MAX_THUNKS])
412         return thunk->proc16;
413     return NULL;
414 }
415
416
417 /***********************************************************************
418  * Support for 16<->32 message mapping
419  */
420
421 static inline void *get_buffer( void *static_buffer, size_t size, size_t need )
422 {
423     if (size >= need) return static_buffer;
424     return HeapAlloc( GetProcessHeap(), 0, need );
425 }
426
427 static inline void free_buffer( void *static_buffer, void *buffer )
428 {
429     if (buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer );
430 }
431
432 static void RECT16to32( const RECT16 *from, RECT *to )
433 {
434     to->left   = from->left;
435     to->top    = from->top;
436     to->right  = from->right;
437     to->bottom = from->bottom;
438 }
439
440 static void RECT32to16( const RECT *from, RECT16 *to )
441 {
442     to->left   = from->left;
443     to->top    = from->top;
444     to->right  = from->right;
445     to->bottom = from->bottom;
446 }
447
448 static void MINMAXINFO32to16( const MINMAXINFO *from, MINMAXINFO16 *to )
449 {
450     to->ptReserved.x     = from->ptReserved.x;
451     to->ptReserved.y     = from->ptReserved.y;
452     to->ptMaxSize.x      = from->ptMaxSize.x;
453     to->ptMaxSize.y      = from->ptMaxSize.y;
454     to->ptMaxPosition.x  = from->ptMaxPosition.x;
455     to->ptMaxPosition.y  = from->ptMaxPosition.y;
456     to->ptMinTrackSize.x = from->ptMinTrackSize.x;
457     to->ptMinTrackSize.y = from->ptMinTrackSize.y;
458     to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
459     to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
460 }
461
462 static void MINMAXINFO16to32( const MINMAXINFO16 *from, MINMAXINFO *to )
463 {
464     to->ptReserved.x     = from->ptReserved.x;
465     to->ptReserved.y     = from->ptReserved.y;
466     to->ptMaxSize.x      = from->ptMaxSize.x;
467     to->ptMaxSize.y      = from->ptMaxSize.y;
468     to->ptMaxPosition.x  = from->ptMaxPosition.x;
469     to->ptMaxPosition.y  = from->ptMaxPosition.y;
470     to->ptMinTrackSize.x = from->ptMinTrackSize.x;
471     to->ptMinTrackSize.y = from->ptMinTrackSize.y;
472     to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
473     to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
474 }
475
476 static void WINDOWPOS32to16( const WINDOWPOS* from, WINDOWPOS16* to )
477 {
478     to->hwnd            = HWND_16(from->hwnd);
479     to->hwndInsertAfter = HWND_16(from->hwndInsertAfter);
480     to->x               = from->x;
481     to->y               = from->y;
482     to->cx              = from->cx;
483     to->cy              = from->cy;
484     to->flags           = from->flags;
485 }
486
487 static void WINDOWPOS16to32( const WINDOWPOS16* from, WINDOWPOS* to )
488 {
489     to->hwnd            = WIN_Handle32(from->hwnd);
490     to->hwndInsertAfter = (from->hwndInsertAfter == (HWND16)-1) ?
491                            HWND_TOPMOST : WIN_Handle32(from->hwndInsertAfter);
492     to->x               = from->x;
493     to->y               = from->y;
494     to->cx              = from->cx;
495     to->cy              = from->cy;
496     to->flags           = from->flags;
497 }
498
499 /* The strings are not copied */
500 static void CREATESTRUCT32Ato16( const CREATESTRUCTA* from, CREATESTRUCT16* to )
501 {
502     to->lpCreateParams = (SEGPTR)from->lpCreateParams;
503     to->hInstance      = HINSTANCE_16(from->hInstance);
504     to->hMenu          = HMENU_16(from->hMenu);
505     to->hwndParent     = HWND_16(from->hwndParent);
506     to->cy             = from->cy;
507     to->cx             = from->cx;
508     to->y              = from->y;
509     to->x              = from->x;
510     to->style          = from->style;
511     to->dwExStyle      = from->dwExStyle;
512 }
513
514 static void CREATESTRUCT16to32A( const CREATESTRUCT16* from, CREATESTRUCTA *to )
515
516 {
517     to->lpCreateParams = (LPVOID)from->lpCreateParams;
518     to->hInstance      = HINSTANCE_32(from->hInstance);
519     to->hMenu          = HMENU_32(from->hMenu);
520     to->hwndParent     = WIN_Handle32(from->hwndParent);
521     to->cy             = from->cy;
522     to->cx             = from->cx;
523     to->y              = from->y;
524     to->x              = from->x;
525     to->style          = from->style;
526     to->dwExStyle      = from->dwExStyle;
527     to->lpszName       = MapSL(from->lpszName);
528     to->lpszClass      = MapSL(from->lpszClass);
529 }
530
531 /* The strings are not copied */
532 static void MDICREATESTRUCT32Ato16( const MDICREATESTRUCTA* from, MDICREATESTRUCT16* to )
533 {
534     to->hOwner = HINSTANCE_16(from->hOwner);
535     to->x      = from->x;
536     to->y      = from->y;
537     to->cx     = from->cx;
538     to->cy     = from->cy;
539     to->style  = from->style;
540     to->lParam = from->lParam;
541 }
542
543 static void MDICREATESTRUCT16to32A( const MDICREATESTRUCT16* from, MDICREATESTRUCTA *to )
544 {
545     to->hOwner = HINSTANCE_32(from->hOwner);
546     to->x      = from->x;
547     to->y      = from->y;
548     to->cx     = from->cx;
549     to->cy     = from->cy;
550     to->style  = from->style;
551     to->lParam = from->lParam;
552     to->szTitle = MapSL(from->szTitle);
553     to->szClass = MapSL(from->szClass);
554 }
555
556 static UINT_PTR convert_handle_16_to_32(HANDLE16 src, unsigned int flags)
557 {
558     HANDLE      dst;
559     UINT        sz = GlobalSize16(src);
560     LPSTR       ptr16, ptr32;
561
562     if (!(dst = GlobalAlloc(flags, sz)))
563         return 0;
564     ptr16 = GlobalLock16(src);
565     ptr32 = GlobalLock(dst);
566     if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr32, ptr16, sz);
567     GlobalUnlock16(src);
568     GlobalUnlock(dst);
569
570     return (UINT_PTR)dst;
571 }
572
573 static HANDLE16 convert_handle_32_to_16(UINT_PTR src, unsigned int flags)
574 {
575     HANDLE16    dst;
576     UINT        sz = GlobalSize((HANDLE)src);
577     LPSTR       ptr16, ptr32;
578
579     if (!(dst = GlobalAlloc16(flags, sz)))
580         return 0;
581     ptr32 = GlobalLock((HANDLE)src);
582     ptr16 = GlobalLock16(dst);
583     if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr16, ptr32, sz);
584     GlobalUnlock((HANDLE)src);
585     GlobalUnlock16(dst);
586
587     return dst;
588 }
589
590 static int find_sub_menu( HMENU *hmenu, HMENU16 target )
591 {
592     int i, pos, count = GetMenuItemCount( *hmenu );
593
594     for (i = 0; i < count; i++)
595     {
596         HMENU sub = GetSubMenu( *hmenu, i );
597         if (!sub) continue;
598         if (HMENU_16(sub) == target) return i;
599         if ((pos = find_sub_menu( &sub, target )) != -1)
600         {
601             *hmenu = sub;
602             return pos;
603         }
604     }
605     return -1;
606 }
607
608 /**********************************************************************
609  *           WINPROC_CallProc16To32A
610  */
611 LRESULT WINPROC_CallProc16To32A( winproc_callback_t callback, HWND16 hwnd, UINT16 msg,
612                                  WPARAM16 wParam, LPARAM lParam, LRESULT *result, void *arg )
613 {
614     LRESULT ret = 0;
615     HWND hwnd32 = WIN_Handle32( hwnd );
616
617     TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
618                  hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
619
620     switch(msg)
621     {
622     case WM_NCCREATE:
623     case WM_CREATE:
624         {
625             CREATESTRUCT16 *cs16 = MapSL(lParam);
626             CREATESTRUCTA cs;
627             MDICREATESTRUCTA mdi_cs;
628
629             CREATESTRUCT16to32A( cs16, &cs );
630             if (GetWindowLongW(hwnd32, GWL_EXSTYLE) & WS_EX_MDICHILD)
631             {
632                 MDICREATESTRUCT16 *mdi_cs16 = MapSL(cs16->lpCreateParams);
633                 MDICREATESTRUCT16to32A(mdi_cs16, &mdi_cs);
634                 cs.lpCreateParams = &mdi_cs;
635             }
636             ret = callback( hwnd32, msg, wParam, (LPARAM)&cs, result, arg );
637             CREATESTRUCT32Ato16( &cs, cs16 );
638         }
639         break;
640     case WM_MDICREATE:
641         {
642             MDICREATESTRUCT16 *cs16 = MapSL(lParam);
643             MDICREATESTRUCTA cs;
644
645             MDICREATESTRUCT16to32A( cs16, &cs );
646             ret = callback( hwnd32, msg, wParam, (LPARAM)&cs, result, arg );
647             MDICREATESTRUCT32Ato16( &cs, cs16 );
648         }
649         break;
650     case WM_MDIACTIVATE:
651         if (lParam)
652             ret = callback( hwnd32, msg, (WPARAM)WIN_Handle32( HIWORD(lParam) ),
653                             (LPARAM)WIN_Handle32( LOWORD(lParam) ), result, arg );
654         else /* message sent to MDI client */
655             ret = callback( hwnd32, msg, wParam, lParam, result, arg );
656         break;
657     case WM_MDIGETACTIVE:
658         {
659             BOOL maximized = FALSE;
660             ret = callback( hwnd32, msg, wParam, (LPARAM)&maximized, result, arg );
661             *result = MAKELRESULT( LOWORD(*result), maximized );
662         }
663         break;
664     case WM_MDISETMENU:
665         ret = callback( hwnd32, wParam ? WM_MDIREFRESHMENU : WM_MDISETMENU,
666                         (WPARAM)HMENU_32(LOWORD(lParam)), (LPARAM)HMENU_32(HIWORD(lParam)),
667                         result, arg );
668         break;
669     case WM_GETMINMAXINFO:
670         {
671             MINMAXINFO16 *mmi16 = MapSL(lParam);
672             MINMAXINFO mmi;
673
674             MINMAXINFO16to32( mmi16, &mmi );
675             ret = callback( hwnd32, msg, wParam, (LPARAM)&mmi, result, arg );
676             MINMAXINFO32to16( &mmi, mmi16 );
677         }
678         break;
679     case WM_WINDOWPOSCHANGING:
680     case WM_WINDOWPOSCHANGED:
681         {
682             WINDOWPOS16 *winpos16 = MapSL(lParam);
683             WINDOWPOS winpos;
684
685             WINDOWPOS16to32( winpos16, &winpos );
686             ret = callback( hwnd32, msg, wParam, (LPARAM)&winpos, result, arg );
687             WINDOWPOS32to16( &winpos, winpos16 );
688         }
689         break;
690     case WM_NCCALCSIZE:
691         {
692             NCCALCSIZE_PARAMS16 *nc16 = MapSL(lParam);
693             NCCALCSIZE_PARAMS nc;
694             WINDOWPOS winpos;
695
696             RECT16to32( &nc16->rgrc[0], &nc.rgrc[0] );
697             if (wParam)
698             {
699                 RECT16to32( &nc16->rgrc[1], &nc.rgrc[1] );
700                 RECT16to32( &nc16->rgrc[2], &nc.rgrc[2] );
701                 WINDOWPOS16to32( MapSL(nc16->lppos), &winpos );
702                 nc.lppos = &winpos;
703             }
704             ret = callback( hwnd32, msg, wParam, (LPARAM)&nc, result, arg );
705             RECT32to16( &nc.rgrc[0], &nc16->rgrc[0] );
706             if (wParam)
707             {
708                 RECT32to16( &nc.rgrc[1], &nc16->rgrc[1] );
709                 RECT32to16( &nc.rgrc[2], &nc16->rgrc[2] );
710                 WINDOWPOS32to16( &winpos, MapSL(nc16->lppos) );
711             }
712         }
713         break;
714     case WM_COMPAREITEM:
715         {
716             COMPAREITEMSTRUCT16* cis16 = MapSL(lParam);
717             COMPAREITEMSTRUCT cis;
718             cis.CtlType    = cis16->CtlType;
719             cis.CtlID      = cis16->CtlID;
720             cis.hwndItem   = WIN_Handle32( cis16->hwndItem );
721             cis.itemID1    = cis16->itemID1;
722             cis.itemData1  = cis16->itemData1;
723             cis.itemID2    = cis16->itemID2;
724             cis.itemData2  = cis16->itemData2;
725             cis.dwLocaleId = 0;  /* FIXME */
726             ret = callback( hwnd32, msg, wParam, (LPARAM)&cis, result, arg );
727         }
728         break;
729     case WM_DELETEITEM:
730         {
731             DELETEITEMSTRUCT16* dis16 = MapSL(lParam);
732             DELETEITEMSTRUCT dis;
733             dis.CtlType  = dis16->CtlType;
734             dis.CtlID    = dis16->CtlID;
735             dis.hwndItem = WIN_Handle32( dis16->hwndItem );
736             dis.itemData = dis16->itemData;
737             ret = callback( hwnd32, msg, wParam, (LPARAM)&dis, result, arg );
738         }
739         break;
740     case WM_MEASUREITEM:
741         {
742             MEASUREITEMSTRUCT16* mis16 = MapSL(lParam);
743             MEASUREITEMSTRUCT mis;
744             mis.CtlType    = mis16->CtlType;
745             mis.CtlID      = mis16->CtlID;
746             mis.itemID     = mis16->itemID;
747             mis.itemWidth  = mis16->itemWidth;
748             mis.itemHeight = mis16->itemHeight;
749             mis.itemData   = mis16->itemData;
750             ret = callback( hwnd32, msg, wParam, (LPARAM)&mis, result, arg );
751             mis16->itemWidth  = (UINT16)mis.itemWidth;
752             mis16->itemHeight = (UINT16)mis.itemHeight;
753         }
754         break;
755     case WM_DRAWITEM:
756         {
757             DRAWITEMSTRUCT16* dis16 = MapSL(lParam);
758             DRAWITEMSTRUCT dis;
759             dis.CtlType       = dis16->CtlType;
760             dis.CtlID         = dis16->CtlID;
761             dis.itemID        = dis16->itemID;
762             dis.itemAction    = dis16->itemAction;
763             dis.itemState     = dis16->itemState;
764             dis.hwndItem      = (dis.CtlType == ODT_MENU) ? (HWND)HMENU_32(dis16->hwndItem)
765                                                           : WIN_Handle32( dis16->hwndItem );
766             dis.hDC           = HDC_32(dis16->hDC);
767             dis.itemData      = dis16->itemData;
768             dis.rcItem.left   = dis16->rcItem.left;
769             dis.rcItem.top    = dis16->rcItem.top;
770             dis.rcItem.right  = dis16->rcItem.right;
771             dis.rcItem.bottom = dis16->rcItem.bottom;
772             ret = callback( hwnd32, msg, wParam, (LPARAM)&dis, result, arg );
773         }
774         break;
775     case WM_COPYDATA:
776         {
777             COPYDATASTRUCT16 *cds16 = MapSL(lParam);
778             COPYDATASTRUCT cds;
779             cds.dwData = cds16->dwData;
780             cds.cbData = cds16->cbData;
781             cds.lpData = MapSL(cds16->lpData);
782             ret = callback( hwnd32, msg, wParam, (LPARAM)&cds, result, arg );
783         }
784         break;
785     case WM_GETDLGCODE:
786         if (lParam)
787         {
788             MSG16 *msg16 = MapSL(lParam);
789             MSG msg32;
790             msg32.hwnd    = WIN_Handle32( msg16->hwnd );
791             msg32.message = msg16->message;
792             msg32.wParam  = msg16->wParam;
793             msg32.lParam  = msg16->lParam;
794             msg32.time    = msg16->time;
795             msg32.pt.x    = msg16->pt.x;
796             msg32.pt.y    = msg16->pt.y;
797             ret = callback( hwnd32, msg, wParam, (LPARAM)&msg32, result, arg );
798         }
799         else
800             ret = callback( hwnd32, msg, wParam, lParam, result, arg );
801         break;
802     case WM_NEXTMENU:
803         {
804             MDINEXTMENU next;
805             next.hmenuIn   = (HMENU)lParam;
806             next.hmenuNext = 0;
807             next.hwndNext  = 0;
808             ret = callback( hwnd32, msg, wParam, (LPARAM)&next, result, arg );
809             *result = MAKELONG( HMENU_16(next.hmenuNext), HWND_16(next.hwndNext) );
810         }
811         break;
812     case WM_ACTIVATE:
813     case WM_CHARTOITEM:
814     case WM_COMMAND:
815     case WM_VKEYTOITEM:
816         ret = callback( hwnd32, msg, MAKEWPARAM( wParam, HIWORD(lParam) ),
817                         (LPARAM)WIN_Handle32( LOWORD(lParam) ), result, arg );
818         break;
819     case WM_HSCROLL:
820     case WM_VSCROLL:
821         ret = callback( hwnd32, msg, MAKEWPARAM( wParam, LOWORD(lParam) ),
822                         (LPARAM)WIN_Handle32( HIWORD(lParam) ), result, arg );
823         break;
824     case WM_CTLCOLOR:
825         if (HIWORD(lParam) <= CTLCOLOR_STATIC)
826             ret = callback( hwnd32, WM_CTLCOLORMSGBOX + HIWORD(lParam),
827                             (WPARAM)HDC_32(wParam), (LPARAM)WIN_Handle32( LOWORD(lParam) ),
828                             result, arg );
829         break;
830     case WM_GETTEXT:
831     case WM_SETTEXT:
832     case WM_WININICHANGE:
833     case WM_DEVMODECHANGE:
834     case WM_ASKCBFORMATNAME:
835     case WM_NOTIFY:
836         ret = callback( hwnd32, msg, wParam, (LPARAM)MapSL(lParam), result, arg );
837         break;
838     case WM_MENUCHAR:
839         ret = callback( hwnd32, msg, MAKEWPARAM( wParam, LOWORD(lParam) ),
840                         (LPARAM)HMENU_32(HIWORD(lParam)), result, arg );
841         break;
842     case WM_MENUSELECT:
843         if((LOWORD(lParam) & MF_POPUP) && (LOWORD(lParam) != 0xFFFF))
844         {
845             HMENU hmenu = HMENU_32(HIWORD(lParam));
846             int pos = find_sub_menu( &hmenu, wParam );
847             if (pos == -1) pos = 0;
848             wParam = pos;
849         }
850         ret = callback( hwnd32, msg, MAKEWPARAM( wParam, LOWORD(lParam) ),
851                         (LPARAM)HMENU_32(HIWORD(lParam)), result, arg );
852         break;
853     case WM_PARENTNOTIFY:
854         if ((wParam == WM_CREATE) || (wParam == WM_DESTROY))
855             ret = callback( hwnd32, msg, MAKEWPARAM( wParam, HIWORD(lParam) ),
856                             (LPARAM)WIN_Handle32( LOWORD(lParam) ), result, arg );
857         else
858             ret = callback( hwnd32, msg, wParam, lParam, result, arg );
859         break;
860     case WM_ACTIVATEAPP:
861         /* We need this when SetActiveWindow sends a Sendmessage16() to
862          * a 32-bit window. Might be superfluous with 32-bit interprocess
863          * message queues. */
864         if (lParam) lParam = HTASK_32(lParam);
865         ret = callback( hwnd32, msg, wParam, lParam, result, arg );
866         break;
867     case WM_DDE_INITIATE:
868     case WM_DDE_TERMINATE:
869     case WM_DDE_UNADVISE:
870     case WM_DDE_REQUEST:
871         ret = callback( hwnd32, msg, (WPARAM)WIN_Handle32(wParam), lParam, result, arg );
872         break;
873     case WM_DDE_ADVISE:
874     case WM_DDE_DATA:
875     case WM_DDE_POKE:
876         {
877             HANDLE16 lo16 = LOWORD(lParam);
878             UINT_PTR lo32 = 0;
879             if (lo16 && !(lo32 = convert_handle_16_to_32(lo16, GMEM_DDESHARE))) break;
880             lParam = PackDDElParam( msg, lo32, HIWORD(lParam) );
881             ret = callback( hwnd32, msg, (WPARAM)WIN_Handle32(wParam), lParam, result, arg );
882         }
883         break; /* FIXME don't know how to free allocated memory (handle)  !! */
884     case WM_DDE_ACK:
885         {
886             UINT_PTR lo = LOWORD(lParam);
887             UINT_PTR hi = HIWORD(lParam);
888             int flag = 0;
889             char buf[2];
890
891             if (GlobalGetAtomNameA(hi, buf, 2) > 0) flag |= 1;
892             if (GlobalSize16(hi) != 0) flag |= 2;
893             switch (flag)
894             {
895             case 0:
896                 if (hi)
897                 {
898                     MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
899                     hi = 0;
900                 }
901                 break;
902             case 1:
903                 break; /* atom, nothing to do */
904             case 3:
905                 MESSAGE("DDE_ACK: %lx both atom and handle... choosing handle\n", hi);
906                 /* fall thru */
907             case 2:
908                 hi = convert_handle_16_to_32(hi, GMEM_DDESHARE);
909                 break;
910             }
911             lParam = PackDDElParam( WM_DDE_ACK, lo, hi );
912             ret = callback( hwnd32, msg, (WPARAM)WIN_Handle32(wParam), lParam, result, arg );
913         }
914         break; /* FIXME don't know how to free allocated memory (handle) !! */
915     case WM_DDE_EXECUTE:
916         lParam = convert_handle_16_to_32( lParam, GMEM_DDESHARE );
917         ret = callback( hwnd32, msg, wParam, lParam, result, arg );
918         break; /* FIXME don't know how to free allocated memory (handle) !! */
919     case WM_PAINTCLIPBOARD:
920     case WM_SIZECLIPBOARD:
921         FIXME_(msg)( "message %04x needs translation\n", msg );
922         break;
923     default:
924         ret = callback( hwnd32, msg, wParam, lParam, result, arg );
925         break;
926     }
927     return ret;
928 }
929
930
931 /**********************************************************************
932  *           WINPROC_CallProc32ATo16
933  *
934  * Call a 16-bit window procedure, translating the 32-bit args.
935  */
936 LRESULT WINPROC_CallProc32ATo16( winproc_callback16_t callback, HWND hwnd, UINT msg,
937                                  WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg )
938 {
939     LRESULT ret = 0;
940
941     TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08lx,lp=%08lx)\n",
942                 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
943
944     switch(msg)
945     {
946     case WM_NCCREATE:
947     case WM_CREATE:
948         {
949             CREATESTRUCTA *cs32 = (CREATESTRUCTA *)lParam;
950             CREATESTRUCT16 cs;
951             MDICREATESTRUCT16 mdi_cs16;
952             BOOL mdi_child = (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD);
953
954             CREATESTRUCT32Ato16( cs32, &cs );
955             cs.lpszName  = MapLS( cs32->lpszName );
956             cs.lpszClass = MapLS( cs32->lpszClass );
957
958             if (mdi_child)
959             {
960                 MDICREATESTRUCTA *mdi_cs = cs32->lpCreateParams;
961                 MDICREATESTRUCT32Ato16( mdi_cs, &mdi_cs16 );
962                 mdi_cs16.szTitle = MapLS( mdi_cs->szTitle );
963                 mdi_cs16.szClass = MapLS( mdi_cs->szClass );
964                 cs.lpCreateParams = MapLS( &mdi_cs16 );
965             }
966             lParam = MapLS( &cs );
967             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
968             UnMapLS( lParam );
969             UnMapLS( cs.lpszName );
970             UnMapLS( cs.lpszClass );
971             if (mdi_child)
972             {
973                 UnMapLS( cs.lpCreateParams );
974                 UnMapLS( mdi_cs16.szTitle );
975                 UnMapLS( mdi_cs16.szClass );
976             }
977         }
978         break;
979     case WM_MDICREATE:
980         {
981             MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)lParam;
982             MDICREATESTRUCT16 cs;
983
984             MDICREATESTRUCT32Ato16( cs32, &cs );
985             cs.szTitle = MapLS( cs32->szTitle );
986             cs.szClass = MapLS( cs32->szClass );
987             lParam = MapLS( &cs );
988             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
989             UnMapLS( lParam );
990             UnMapLS( cs.szTitle );
991             UnMapLS( cs.szClass );
992         }
993         break;
994     case WM_MDIACTIVATE:
995         if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
996             ret = callback( HWND_16(hwnd), msg, ((HWND)lParam == hwnd),
997                             MAKELPARAM( LOWORD(lParam), LOWORD(wParam) ), result, arg );
998         else
999             ret = callback( HWND_16(hwnd), msg, HWND_16( wParam ), 0, result, arg );
1000         break;
1001     case WM_MDIGETACTIVE:
1002         ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1003         if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(*result);
1004         *result = (LRESULT)WIN_Handle32( LOWORD(*result) );
1005         break;
1006     case WM_MDISETMENU:
1007         ret = callback( HWND_16(hwnd), msg, (lParam == 0),
1008                         MAKELPARAM( LOWORD(wParam), LOWORD(lParam) ), result, arg );
1009         break;
1010     case WM_GETMINMAXINFO:
1011         {
1012             MINMAXINFO *mmi32 = (MINMAXINFO *)lParam;
1013             MINMAXINFO16 mmi;
1014
1015             MINMAXINFO32to16( mmi32, &mmi );
1016             lParam = MapLS( &mmi );
1017             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1018             UnMapLS( lParam );
1019             MINMAXINFO16to32( &mmi, mmi32 );
1020         }
1021         break;
1022     case WM_NCCALCSIZE:
1023         {
1024             NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)lParam;
1025             NCCALCSIZE_PARAMS16 nc;
1026             WINDOWPOS16 winpos;
1027
1028             RECT32to16( &nc32->rgrc[0], &nc.rgrc[0] );
1029             if (wParam)
1030             {
1031                 RECT32to16( &nc32->rgrc[1], &nc.rgrc[1] );
1032                 RECT32to16( &nc32->rgrc[2], &nc.rgrc[2] );
1033                 WINDOWPOS32to16( nc32->lppos, &winpos );
1034                 nc.lppos = MapLS( &winpos );
1035             }
1036             lParam = MapLS( &nc );
1037             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1038             UnMapLS( lParam );
1039             RECT16to32( &nc.rgrc[0], &nc32->rgrc[0] );
1040             if (wParam)
1041             {
1042                 RECT16to32( &nc.rgrc[1], &nc32->rgrc[1] );
1043                 RECT16to32( &nc.rgrc[2], &nc32->rgrc[2] );
1044                 WINDOWPOS16to32( &winpos, nc32->lppos );
1045                 UnMapLS( nc.lppos );
1046             }
1047         }
1048         break;
1049     case WM_WINDOWPOSCHANGING:
1050     case WM_WINDOWPOSCHANGED:
1051         {
1052             WINDOWPOS *winpos32 = (WINDOWPOS *)lParam;
1053             WINDOWPOS16 winpos;
1054
1055             WINDOWPOS32to16( winpos32, &winpos );
1056             lParam = MapLS( &winpos );
1057             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1058             UnMapLS( lParam );
1059             WINDOWPOS16to32( &winpos, winpos32 );
1060         }
1061         break;
1062     case WM_COMPAREITEM:
1063         {
1064             COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)lParam;
1065             COMPAREITEMSTRUCT16 cis;
1066             cis.CtlType    = cis32->CtlType;
1067             cis.CtlID      = cis32->CtlID;
1068             cis.hwndItem   = HWND_16( cis32->hwndItem );
1069             cis.itemID1    = cis32->itemID1;
1070             cis.itemData1  = cis32->itemData1;
1071             cis.itemID2    = cis32->itemID2;
1072             cis.itemData2  = cis32->itemData2;
1073             lParam = MapLS( &cis );
1074             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1075             UnMapLS( lParam );
1076         }
1077         break;
1078     case WM_DELETEITEM:
1079         {
1080             DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)lParam;
1081             DELETEITEMSTRUCT16 dis;
1082             dis.CtlType  = dis32->CtlType;
1083             dis.CtlID    = dis32->CtlID;
1084             dis.itemID   = dis32->itemID;
1085             dis.hwndItem = (dis.CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem)
1086                                                      : HWND_16( dis32->hwndItem );
1087             dis.itemData = dis32->itemData;
1088             lParam = MapLS( &dis );
1089             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1090             UnMapLS( lParam );
1091         }
1092         break;
1093     case WM_DRAWITEM:
1094         {
1095             DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)lParam;
1096             DRAWITEMSTRUCT16 dis;
1097             dis.CtlType       = dis32->CtlType;
1098             dis.CtlID         = dis32->CtlID;
1099             dis.itemID        = dis32->itemID;
1100             dis.itemAction    = dis32->itemAction;
1101             dis.itemState     = dis32->itemState;
1102             dis.hwndItem      = HWND_16( dis32->hwndItem );
1103             dis.hDC           = HDC_16(dis32->hDC);
1104             dis.itemData      = dis32->itemData;
1105             dis.rcItem.left   = dis32->rcItem.left;
1106             dis.rcItem.top    = dis32->rcItem.top;
1107             dis.rcItem.right  = dis32->rcItem.right;
1108             dis.rcItem.bottom = dis32->rcItem.bottom;
1109             lParam = MapLS( &dis );
1110             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1111             UnMapLS( lParam );
1112         }
1113         break;
1114     case WM_MEASUREITEM:
1115         {
1116             MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)lParam;
1117             MEASUREITEMSTRUCT16 mis;
1118             mis.CtlType    = mis32->CtlType;
1119             mis.CtlID      = mis32->CtlID;
1120             mis.itemID     = mis32->itemID;
1121             mis.itemWidth  = mis32->itemWidth;
1122             mis.itemHeight = mis32->itemHeight;
1123             mis.itemData   = mis32->itemData;
1124             lParam = MapLS( &mis );
1125             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1126             UnMapLS( lParam );
1127             mis32->itemWidth  = mis.itemWidth;
1128             mis32->itemHeight = mis.itemHeight;
1129         }
1130         break;
1131     case WM_COPYDATA:
1132         {
1133             COPYDATASTRUCT *cds32 = (COPYDATASTRUCT *)lParam;
1134             COPYDATASTRUCT16 cds;
1135
1136             cds.dwData = cds32->dwData;
1137             cds.cbData = cds32->cbData;
1138             cds.lpData = MapLS( cds32->lpData );
1139             lParam = MapLS( &cds );
1140             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1141             UnMapLS( lParam );
1142             UnMapLS( cds.lpData );
1143         }
1144         break;
1145     case WM_GETDLGCODE:
1146         if (lParam)
1147         {
1148             MSG *msg32 = (MSG *)lParam;
1149             MSG16 msg16;
1150
1151             msg16.hwnd    = HWND_16( msg32->hwnd );
1152             msg16.message = msg32->message;
1153             msg16.wParam  = msg32->wParam;
1154             msg16.lParam  = msg32->lParam;
1155             msg16.time    = msg32->time;
1156             msg16.pt.x    = msg32->pt.x;
1157             msg16.pt.y    = msg32->pt.y;
1158             lParam = MapLS( &msg16 );
1159             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1160             UnMapLS( lParam );
1161         }
1162         else
1163             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1164         break;
1165     case WM_NEXTMENU:
1166         {
1167             MDINEXTMENU *next = (MDINEXTMENU *)lParam;
1168             ret = callback( HWND_16(hwnd), msg, wParam, (LPARAM)next->hmenuIn, result, arg );
1169             next->hmenuNext = HMENU_32( LOWORD(*result) );
1170             next->hwndNext  = WIN_Handle32( HIWORD(*result) );
1171             *result = 0;
1172         }
1173         break;
1174     case WM_GETTEXT:
1175     case WM_ASKCBFORMATNAME:
1176         wParam = min( wParam, 0xff80 ); /* Must be < 64K */
1177         /* fall through */
1178     case WM_NOTIFY:
1179     case WM_SETTEXT:
1180     case WM_WININICHANGE:
1181     case WM_DEVMODECHANGE:
1182         lParam = MapLS( (void *)lParam );
1183         ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1184         UnMapLS( lParam );
1185         break;
1186     case WM_ACTIVATE:
1187     case WM_CHARTOITEM:
1188     case WM_COMMAND:
1189     case WM_VKEYTOITEM:
1190         ret = callback( HWND_16(hwnd), msg, wParam, MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ),
1191                         result, arg );
1192         break;
1193     case WM_HSCROLL:
1194     case WM_VSCROLL:
1195         ret = callback( HWND_16(hwnd), msg, wParam, MAKELPARAM( HIWORD(wParam), (HWND16)lParam ),
1196                         result, arg );
1197         break;
1198     case WM_CTLCOLORMSGBOX:
1199     case WM_CTLCOLOREDIT:
1200     case WM_CTLCOLORLISTBOX:
1201     case WM_CTLCOLORBTN:
1202     case WM_CTLCOLORDLG:
1203     case WM_CTLCOLORSCROLLBAR:
1204     case WM_CTLCOLORSTATIC:
1205         ret = callback( HWND_16(hwnd), WM_CTLCOLOR, wParam,
1206                         MAKELPARAM( (HWND16)lParam, msg - WM_CTLCOLORMSGBOX ), result, arg );
1207         break;
1208     case WM_MENUSELECT:
1209         if(HIWORD(wParam) & MF_POPUP)
1210         {
1211             HMENU hmenu;
1212             if ((HIWORD(wParam) != 0xffff) || lParam)
1213             {
1214                 if ((hmenu = GetSubMenu( (HMENU)lParam, LOWORD(wParam) )))
1215                 {
1216                     ret = callback( HWND_16(hwnd), msg, HMENU_16(hmenu),
1217                                     MAKELPARAM( HIWORD(wParam), (HMENU16)lParam ), result, arg );
1218                     break;
1219                 }
1220             }
1221         }
1222         /* fall through */
1223     case WM_MENUCHAR:
1224         ret = callback( HWND_16(hwnd), msg, wParam,
1225                         MAKELPARAM( HIWORD(wParam), (HMENU16)lParam ), result, arg );
1226         break;
1227     case WM_PARENTNOTIFY:
1228         if ((LOWORD(wParam) == WM_CREATE) || (LOWORD(wParam) == WM_DESTROY))
1229             ret = callback( HWND_16(hwnd), msg, wParam,
1230                             MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ), result, arg );
1231         else
1232             ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1233         break;
1234     case WM_ACTIVATEAPP:
1235         ret = callback( HWND_16(hwnd), msg, wParam, HTASK_16( lParam ), result, arg );
1236         break;
1237     case WM_PAINT:
1238         if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON ))
1239             ret = callback( HWND_16(hwnd), WM_PAINTICON, 1, lParam, result, arg );
1240         else
1241             ret = callback( HWND_16(hwnd), WM_PAINT, wParam, lParam, result, arg );
1242         break;
1243     case WM_ERASEBKGND:
1244         if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON )) msg = WM_ICONERASEBKGND;
1245         ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1246         break;
1247     case WM_DDE_INITIATE:
1248     case WM_DDE_TERMINATE:
1249     case WM_DDE_UNADVISE:
1250     case WM_DDE_REQUEST:
1251         ret = callback( HWND_16(hwnd), msg, HWND_16(wParam), lParam, result, arg );
1252         break;
1253     case WM_DDE_ADVISE:
1254     case WM_DDE_DATA:
1255     case WM_DDE_POKE:
1256         {
1257             UINT_PTR lo32, hi;
1258             HANDLE16 lo16 = 0;
1259
1260             UnpackDDElParam( msg, lParam, &lo32, &hi );
1261             if (lo32 && !(lo16 = convert_handle_32_to_16(lo32, GMEM_DDESHARE))) break;
1262             ret = callback( HWND_16(hwnd), msg, HWND_16(wParam),
1263                             MAKELPARAM(lo16, hi), result, arg );
1264         }
1265         break; /* FIXME don't know how to free allocated memory (handle)  !! */
1266     case WM_DDE_ACK:
1267         {
1268             UINT_PTR lo, hi;
1269             int flag = 0;
1270             char buf[2];
1271
1272             UnpackDDElParam( msg, lParam, &lo, &hi );
1273
1274             if (GlobalGetAtomNameA((ATOM)hi, buf, sizeof(buf)) > 0) flag |= 1;
1275             if (GlobalSize((HANDLE)hi) != 0) flag |= 2;
1276             switch (flag)
1277             {
1278             case 0:
1279                 if (hi)
1280                 {
1281                     MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1282                     hi = 0;
1283                 }
1284                 break;
1285             case 1:
1286                 break; /* atom, nothing to do */
1287             case 3:
1288                 MESSAGE("DDE_ACK: %lx both atom and handle... choosing handle\n", hi);
1289                 /* fall thru */
1290             case 2:
1291                 hi = convert_handle_32_to_16(hi, GMEM_DDESHARE);
1292                 break;
1293             }
1294             ret = callback( HWND_16(hwnd), msg, HWND_16(wParam),
1295                             MAKELPARAM(lo, hi), result, arg );
1296         }
1297         break; /* FIXME don't know how to free allocated memory (handle) !! */
1298     case WM_DDE_EXECUTE:
1299         lParam = convert_handle_32_to_16(lParam, GMEM_DDESHARE);
1300         ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1301         break; /* FIXME don't know how to free allocated memory (handle) !! */
1302     case SBM_SETRANGE:
1303         ret = callback( HWND_16(hwnd), SBM_SETRANGE16, 0, MAKELPARAM(wParam, lParam), result, arg );
1304         break;
1305     case SBM_GETRANGE:
1306         ret = callback( HWND_16(hwnd), SBM_GETRANGE16, wParam, lParam, result, arg );
1307         *(LPINT)wParam = LOWORD(*result);
1308         *(LPINT)lParam = HIWORD(*result);
1309         break;
1310     case BM_GETCHECK:
1311     case BM_SETCHECK:
1312     case BM_GETSTATE:
1313     case BM_SETSTATE:
1314     case BM_SETSTYLE:
1315         ret = callback( HWND_16(hwnd), msg + BM_GETCHECK16 - BM_GETCHECK, wParam, lParam, result, arg );
1316         break;
1317     case EM_GETSEL:
1318     case EM_GETRECT:
1319     case EM_SETRECT:
1320     case EM_SETRECTNP:
1321     case EM_SCROLL:
1322     case EM_LINESCROLL:
1323     case EM_SCROLLCARET:
1324     case EM_GETMODIFY:
1325     case EM_SETMODIFY:
1326     case EM_GETLINECOUNT:
1327     case EM_LINEINDEX:
1328     case EM_SETHANDLE:
1329     case EM_GETHANDLE:
1330     case EM_GETTHUMB:
1331     case EM_LINELENGTH:
1332     case EM_REPLACESEL:
1333     case EM_GETLINE:
1334     case EM_LIMITTEXT:
1335     case EM_CANUNDO:
1336     case EM_UNDO:
1337     case EM_FMTLINES:
1338     case EM_LINEFROMCHAR:
1339     case EM_SETTABSTOPS:
1340     case EM_SETPASSWORDCHAR:
1341     case EM_EMPTYUNDOBUFFER:
1342     case EM_GETFIRSTVISIBLELINE:
1343     case EM_SETREADONLY:
1344     case EM_SETWORDBREAKPROC:
1345     case EM_GETWORDBREAKPROC:
1346     case EM_GETPASSWORDCHAR:
1347         ret = callback( HWND_16(hwnd), msg + EM_GETSEL16 - EM_GETSEL, wParam, lParam, result, arg );
1348         break;
1349     case EM_SETSEL:
1350         ret = callback( HWND_16(hwnd), EM_SETSEL16, 0, MAKELPARAM( wParam, lParam ), result, arg );
1351         break;
1352     case LB_CARETOFF:
1353     case LB_CARETON:
1354     case LB_DELETESTRING:
1355     case LB_GETANCHORINDEX:
1356     case LB_GETCARETINDEX:
1357     case LB_GETCOUNT:
1358     case LB_GETCURSEL:
1359     case LB_GETHORIZONTALEXTENT:
1360     case LB_GETITEMDATA:
1361     case LB_GETITEMHEIGHT:
1362     case LB_GETSEL:
1363     case LB_GETSELCOUNT:
1364     case LB_GETTEXTLEN:
1365     case LB_GETTOPINDEX:
1366     case LB_RESETCONTENT:
1367     case LB_SELITEMRANGE:
1368     case LB_SELITEMRANGEEX:
1369     case LB_SETANCHORINDEX:
1370     case LB_SETCARETINDEX:
1371     case LB_SETCOLUMNWIDTH:
1372     case LB_SETCURSEL:
1373     case LB_SETHORIZONTALEXTENT:
1374     case LB_SETITEMDATA:
1375     case LB_SETITEMHEIGHT:
1376     case LB_SETSEL:
1377     case LB_SETTOPINDEX:
1378         ret = callback( HWND_16(hwnd), msg + LB_ADDSTRING16 - LB_ADDSTRING, wParam, lParam, result, arg );
1379         break;
1380     case LB_ADDSTRING:
1381     case LB_FINDSTRING:
1382     case LB_FINDSTRINGEXACT:
1383     case LB_INSERTSTRING:
1384     case LB_SELECTSTRING:
1385     case LB_GETTEXT:
1386     case LB_DIR:
1387     case LB_ADDFILE:
1388         lParam = MapLS( (LPSTR)lParam );
1389         ret = callback( HWND_16(hwnd), msg + LB_ADDSTRING16 - LB_ADDSTRING, wParam, lParam, result, arg );
1390         UnMapLS( lParam );
1391         break;
1392     case LB_GETSELITEMS:
1393         {
1394             INT *items32 = (INT *)lParam;
1395             INT16 *items, buffer[512];
1396             unsigned int i;
1397
1398             wParam = min( wParam, 0x7f80 ); /* Must be < 64K */
1399             if (!(items = get_buffer( buffer, sizeof(buffer), wParam * sizeof(INT16) ))) break;
1400             lParam = MapLS( items );
1401             ret = callback( HWND_16(hwnd), LB_GETSELITEMS16, wParam, lParam, result, arg );
1402             UnMapLS( lParam );
1403             for (i = 0; i < wParam; i++) items32[i] = items[i];
1404             free_buffer( buffer, items );
1405         }
1406         break;
1407     case LB_SETTABSTOPS:
1408         if (wParam)
1409         {
1410             INT *stops32 = (INT *)lParam;
1411             INT16 *stops, buffer[512];
1412             unsigned int i;
1413
1414             wParam = min( wParam, 0x7f80 ); /* Must be < 64K */
1415             if (!(stops = get_buffer( buffer, sizeof(buffer), wParam * sizeof(INT16) ))) break;
1416             for (i = 0; i < wParam; i++) stops[i] = stops32[i];
1417             lParam = MapLS( stops );
1418             ret = callback( HWND_16(hwnd), LB_SETTABSTOPS16, wParam, lParam, result, arg );
1419             UnMapLS( lParam );
1420             free_buffer( buffer, stops );
1421         }
1422         else ret = callback( HWND_16(hwnd), LB_SETTABSTOPS16, wParam, lParam, result, arg );
1423         break;
1424     case CB_DELETESTRING:
1425     case CB_GETCOUNT:
1426     case CB_GETLBTEXTLEN:
1427     case CB_LIMITTEXT:
1428     case CB_RESETCONTENT:
1429     case CB_SETEDITSEL:
1430     case CB_GETCURSEL:
1431     case CB_SETCURSEL:
1432     case CB_SHOWDROPDOWN:
1433     case CB_SETITEMDATA:
1434     case CB_SETITEMHEIGHT:
1435     case CB_GETITEMHEIGHT:
1436     case CB_SETEXTENDEDUI:
1437     case CB_GETEXTENDEDUI:
1438     case CB_GETDROPPEDSTATE:
1439         ret = callback( HWND_16(hwnd), msg + CB_GETEDITSEL16 - CB_GETEDITSEL, wParam, lParam, result, arg );
1440         break;
1441     case CB_GETEDITSEL:
1442         ret = callback( HWND_16(hwnd), CB_GETEDITSEL16, wParam, lParam, result, arg );
1443         if (wParam) *((PUINT)(wParam)) = LOWORD(*result);
1444         if (lParam) *((PUINT)(lParam)) = HIWORD(*result);  /* FIXME: substract 1? */
1445         break;
1446     case CB_ADDSTRING:
1447     case CB_FINDSTRING:
1448     case CB_FINDSTRINGEXACT:
1449     case CB_INSERTSTRING:
1450     case CB_SELECTSTRING:
1451     case CB_DIR:
1452     case CB_GETLBTEXT:
1453         lParam = MapLS( (LPSTR)lParam );
1454         ret = callback( HWND_16(hwnd), msg + CB_GETEDITSEL16 - CB_GETEDITSEL, wParam, lParam, result, arg );
1455         UnMapLS( lParam );
1456         break;
1457     case LB_GETITEMRECT:
1458     case CB_GETDROPPEDCONTROLRECT:
1459         {
1460             RECT *r32 = (RECT *)lParam;
1461             RECT16 rect;
1462             lParam = MapLS( &rect );
1463             ret = callback( HWND_16(hwnd),
1464                             (msg == LB_GETITEMRECT) ? LB_GETITEMRECT16 : CB_GETDROPPEDCONTROLRECT16,
1465                             wParam, lParam, result, arg );
1466             UnMapLS( lParam );
1467             RECT16to32( &rect, r32 );
1468         }
1469         break;
1470     case WM_PAINTCLIPBOARD:
1471     case WM_SIZECLIPBOARD:
1472         FIXME_(msg)( "message %04x needs translation\n", msg );
1473         break;
1474     /* the following messages should not be sent to 16-bit apps */
1475     case WM_SIZING:
1476     case WM_MOVING:
1477     case WM_CAPTURECHANGED:
1478     case WM_STYLECHANGING:
1479     case WM_STYLECHANGED:
1480         break;
1481     default:
1482         ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
1483         break;
1484     }
1485     return ret;
1486 }
1487
1488
1489 /***********************************************************************
1490  *              SendMessage  (USER.111)
1491  */
1492 LRESULT WINAPI SendMessage16( HWND16 hwnd16, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
1493 {
1494     LRESULT result;
1495     HWND hwnd = WIN_Handle32( hwnd16 );
1496
1497     if (hwnd != HWND_BROADCAST && WIN_IsCurrentThread(hwnd))
1498     {
1499         /* call 16-bit window proc directly */
1500         WNDPROC16 winproc;
1501
1502         /* first the WH_CALLWNDPROC hook */
1503         if (HOOK_IsHooked( WH_CALLWNDPROC ))
1504             WINPROC_CallProc16To32A( cwp_hook_callback, hwnd16, msg, wparam, lparam, &result, NULL );
1505
1506         if (!(winproc = (WNDPROC16)GetWindowLong16( hwnd16, GWLP_WNDPROC ))) return 0;
1507
1508         SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wparam, lparam );
1509         result = CallWindowProc16( winproc, hwnd16, msg, wparam, lparam );
1510         SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, result, wparam, lparam );
1511     }
1512     else  /* map to 32-bit unicode for inter-thread/process message */
1513     {
1514         WINPROC_CallProc16To32A( send_message_callback, hwnd16, msg, wparam, lparam, &result, NULL );
1515     }
1516     return result;
1517 }
1518
1519
1520 /***********************************************************************
1521  *              PostMessage  (USER.110)
1522  */
1523 BOOL16 WINAPI PostMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
1524 {
1525     LRESULT unused;
1526     return WINPROC_CallProc16To32A( post_message_callback, hwnd, msg, wparam, lparam, &unused, NULL );
1527 }
1528
1529
1530 /***********************************************************************
1531  *              PostAppMessage (USER.116)
1532  */
1533 BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
1534 {
1535     LRESULT unused;
1536     DWORD_PTR tid = HTASK_32( hTask );
1537
1538     if (!tid) return FALSE;
1539     return WINPROC_CallProc16To32A( post_thread_message_callback, 0, msg, wparam, lparam,
1540                                     &unused, (void *)tid );
1541 }
1542
1543
1544 /**********************************************************************
1545  *              CallWindowProc (USER.122)
1546  */
1547 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
1548                                  WPARAM16 wParam, LPARAM lParam )
1549 {
1550     int index = winproc_to_index( func );
1551     LRESULT result;
1552
1553     if (!func) return 0;
1554
1555     if (index == -1 || index >= MAX_WINPROCS32)
1556         call_window_proc16( hwnd, msg, wParam, lParam, &result, func );
1557     else
1558     {
1559         WNDPROC proc = (WNDPROC)func;
1560         if (thunk_array && thunk_array[index].proc) proc = thunk_array[index].proc;
1561         WINPROC_CallProc16To32A( call_window_proc_callback, hwnd, msg, wParam, lParam, &result, proc );
1562     }
1563     return result;
1564 }
1565
1566
1567 /**********************************************************************
1568  *           __wine_call_wndproc   (USER.1010)
1569  */
1570 LRESULT WINAPI __wine_call_wndproc( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam, WNDPROC proc )
1571 {
1572     LRESULT result;
1573     WINPROC_CallProc16To32A( call_window_proc_callback, hwnd, msg, wParam, lParam, &result, proc );
1574     return result;
1575 }
1576
1577
1578 /***********************************************************************
1579  *              InSendMessage  (USER.192)
1580  */
1581 BOOL16 WINAPI InSendMessage16(void)
1582 {
1583     return InSendMessage();
1584 }
1585
1586
1587 /***********************************************************************
1588  *              ReplyMessage  (USER.115)
1589  */
1590 void WINAPI ReplyMessage16( LRESULT result )
1591 {
1592     ReplyMessage( result );
1593 }
1594
1595
1596 /***********************************************************************
1597  *              PeekMessage32 (USER.819)
1598  */
1599 BOOL16 WINAPI PeekMessage32_16( MSG32_16 *msg16, HWND16 hwnd16,
1600                                 UINT16 first, UINT16 last, UINT16 flags,
1601                                 BOOL16 wHaveParamHigh )
1602 {
1603     MSG msg;
1604     LRESULT unused;
1605     HWND hwnd = WIN_Handle32( hwnd16 );
1606
1607     if(USER16_AlertableWait)
1608         MsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, MWMO_ALERTABLE );
1609     if (!PeekMessageA( &msg, hwnd, first, last, flags )) return FALSE;
1610
1611     msg16->msg.time    = msg.time;
1612     msg16->msg.pt.x    = (INT16)msg.pt.x;
1613     msg16->msg.pt.y    = (INT16)msg.pt.y;
1614     if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
1615     WINPROC_CallProc32ATo16( get_message_callback, msg.hwnd, msg.message, msg.wParam, msg.lParam,
1616                              &unused, &msg16->msg );
1617     return TRUE;
1618 }
1619
1620
1621 /***********************************************************************
1622  *              DefWindowProc (USER.107)
1623  */
1624 LRESULT WINAPI DefWindowProc16( HWND16 hwnd16, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
1625 {
1626     LRESULT result;
1627     HWND hwnd = WIN_Handle32( hwnd16 );
1628
1629     SPY_EnterMessage( SPY_DEFWNDPROC16, hwnd, msg, wParam, lParam );
1630
1631     switch(msg)
1632     {
1633     case WM_NCCREATE:
1634         {
1635             CREATESTRUCT16 *cs16 = MapSL(lParam);
1636             CREATESTRUCTA cs32;
1637
1638             cs32.lpCreateParams = ULongToPtr(cs16->lpCreateParams);
1639             cs32.hInstance      = HINSTANCE_32(cs16->hInstance);
1640             cs32.hMenu          = HMENU_32(cs16->hMenu);
1641             cs32.hwndParent     = WIN_Handle32(cs16->hwndParent);
1642             cs32.cy             = cs16->cy;
1643             cs32.cx             = cs16->cx;
1644             cs32.y              = cs16->y;
1645             cs32.x              = cs16->x;
1646             cs32.style          = cs16->style;
1647             cs32.dwExStyle      = cs16->dwExStyle;
1648             cs32.lpszName       = MapSL(cs16->lpszName);
1649             cs32.lpszClass      = MapSL(cs16->lpszClass);
1650             result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&cs32 );
1651         }
1652         break;
1653
1654     case WM_NCCALCSIZE:
1655         {
1656             RECT16 *rect16 = MapSL(lParam);
1657             RECT rect32;
1658
1659             rect32.left    = rect16->left;
1660             rect32.top     = rect16->top;
1661             rect32.right   = rect16->right;
1662             rect32.bottom  = rect16->bottom;
1663
1664             result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&rect32 );
1665
1666             rect16->left   = rect32.left;
1667             rect16->top    = rect32.top;
1668             rect16->right  = rect32.right;
1669             rect16->bottom = rect32.bottom;
1670         }
1671         break;
1672
1673     case WM_WINDOWPOSCHANGING:
1674     case WM_WINDOWPOSCHANGED:
1675         {
1676             WINDOWPOS16 *pos16 = MapSL(lParam);
1677             WINDOWPOS pos32;
1678
1679             pos32.hwnd             = WIN_Handle32(pos16->hwnd);
1680             pos32.hwndInsertAfter  = WIN_Handle32(pos16->hwndInsertAfter);
1681             pos32.x                = pos16->x;
1682             pos32.y                = pos16->y;
1683             pos32.cx               = pos16->cx;
1684             pos32.cy               = pos16->cy;
1685             pos32.flags            = pos16->flags;
1686
1687             result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&pos32 );
1688
1689             pos16->hwnd            = HWND_16(pos32.hwnd);
1690             pos16->hwndInsertAfter = HWND_16(pos32.hwndInsertAfter);
1691             pos16->x               = pos32.x;
1692             pos16->y               = pos32.y;
1693             pos16->cx              = pos32.cx;
1694             pos16->cy              = pos32.cy;
1695             pos16->flags           = pos32.flags;
1696         }
1697         break;
1698
1699     case WM_GETTEXT:
1700     case WM_SETTEXT:
1701         result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)MapSL(lParam) );
1702         break;
1703
1704     default:
1705         result = DefWindowProcA( hwnd, msg, wParam, lParam );
1706         break;
1707     }
1708
1709     SPY_ExitMessage( SPY_RESULT_DEFWND16, hwnd, msg, result, wParam, lParam );
1710     return result;
1711 }
1712
1713
1714 /***********************************************************************
1715  *              DefDlgProc (USER.308)
1716  */
1717 LRESULT WINAPI DefDlgProc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
1718 {
1719     LRESULT result;
1720     WINPROC_CallProc16To32A( defdlg_proc_callback, hwnd, msg, wParam, lParam, &result, 0 );
1721     return result;
1722 }
1723
1724
1725 /***********************************************************************
1726  *              PeekMessage  (USER.109)
1727  */
1728 BOOL16 WINAPI PeekMessage16( MSG16 *msg, HWND16 hwnd,
1729                              UINT16 first, UINT16 last, UINT16 flags )
1730 {
1731     return PeekMessage32_16( (MSG32_16 *)msg, hwnd, first, last, flags, FALSE );
1732 }
1733
1734
1735 /***********************************************************************
1736  *              GetMessage32  (USER.820)
1737  */
1738 BOOL16 WINAPI GetMessage32_16( MSG32_16 *msg16, HWND16 hwnd16, UINT16 first,
1739                                UINT16 last, BOOL16 wHaveParamHigh )
1740 {
1741     MSG msg;
1742     LRESULT unused;
1743     HWND hwnd = WIN_Handle32( hwnd16 );
1744
1745     if(USER16_AlertableWait)
1746         MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, 0, MWMO_ALERTABLE );
1747     GetMessageA( &msg, hwnd, first, last );
1748     msg16->msg.time    = msg.time;
1749     msg16->msg.pt.x    = (INT16)msg.pt.x;
1750     msg16->msg.pt.y    = (INT16)msg.pt.y;
1751     if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
1752     WINPROC_CallProc32ATo16( get_message_callback, msg.hwnd, msg.message, msg.wParam, msg.lParam,
1753                              &unused, &msg16->msg );
1754
1755     TRACE( "message %04x, hwnd %p, filter(%04x - %04x)\n",
1756            msg16->msg.message, hwnd, first, last );
1757
1758     return msg16->msg.message != WM_QUIT;
1759 }
1760
1761
1762 /***********************************************************************
1763  *              GetMessage  (USER.108)
1764  */
1765 BOOL16 WINAPI GetMessage16( MSG16 *msg, HWND16 hwnd, UINT16 first, UINT16 last )
1766 {
1767     return GetMessage32_16( (MSG32_16 *)msg, hwnd, first, last, FALSE );
1768 }
1769
1770
1771 /***********************************************************************
1772  *              TranslateMessage32 (USER.821)
1773  */
1774 BOOL16 WINAPI TranslateMessage32_16( const MSG32_16 *msg, BOOL16 wHaveParamHigh )
1775 {
1776     MSG msg32;
1777
1778     msg32.hwnd    = WIN_Handle32( msg->msg.hwnd );
1779     msg32.message = msg->msg.message;
1780     msg32.wParam  = MAKEWPARAM( msg->msg.wParam, wHaveParamHigh ? msg->wParamHigh : 0 );
1781     msg32.lParam  = msg->msg.lParam;
1782     return TranslateMessage( &msg32 );
1783 }
1784
1785
1786 /***********************************************************************
1787  *              TranslateMessage (USER.113)
1788  */
1789 BOOL16 WINAPI TranslateMessage16( const MSG16 *msg )
1790 {
1791     return TranslateMessage32_16( (const MSG32_16 *)msg, FALSE );
1792 }
1793
1794
1795 /***********************************************************************
1796  *              DispatchMessage (USER.114)
1797  */
1798 LONG WINAPI DispatchMessage16( const MSG16* msg )
1799 {
1800     WNDPROC16 winproc;
1801     LONG retval;
1802     HWND hwnd = WIN_Handle32( msg->hwnd );
1803
1804       /* Process timer messages */
1805     if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
1806     {
1807         if (msg->lParam)
1808             return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
1809                                      msg->message, msg->wParam, GetTickCount() );
1810     }
1811
1812     if (!(winproc = (WNDPROC16)GetWindowLong16( msg->hwnd, GWLP_WNDPROC )))
1813     {
1814         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1815         return 0;
1816     }
1817     SPY_EnterMessage( SPY_DISPATCHMESSAGE16, hwnd, msg->message, msg->wParam, msg->lParam );
1818     retval = CallWindowProc16( winproc, msg->hwnd, msg->message, msg->wParam, msg->lParam );
1819     SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg->message, retval, msg->wParam, msg->lParam );
1820
1821     return retval;
1822 }
1823
1824
1825 /***********************************************************************
1826  *              DispatchMessage32 (USER.822)
1827  */
1828 LONG WINAPI DispatchMessage32_16( const MSG32_16 *msg16, BOOL16 wHaveParamHigh )
1829 {
1830     if (wHaveParamHigh == FALSE)
1831         return DispatchMessage16( &msg16->msg );
1832     else
1833     {
1834         MSG msg;
1835
1836         msg.hwnd    = WIN_Handle32( msg16->msg.hwnd );
1837         msg.message = msg16->msg.message;
1838         msg.wParam  = MAKEWPARAM( msg16->msg.wParam, msg16->wParamHigh );
1839         msg.lParam  = msg16->msg.lParam;
1840         msg.time    = msg16->msg.time;
1841         msg.pt.x    = msg16->msg.pt.x;
1842         msg.pt.y    = msg16->msg.pt.y;
1843         return DispatchMessageA( &msg );
1844     }
1845 }
1846
1847
1848 /***********************************************************************
1849  *              IsDialogMessage (USER.90)
1850  */
1851 BOOL16 WINAPI IsDialogMessage16( HWND16 hwndDlg, MSG16 *msg16 )
1852 {
1853     MSG msg;
1854     HWND hwndDlg32;
1855
1856     msg.hwnd  = WIN_Handle32(msg16->hwnd);
1857     hwndDlg32 = WIN_Handle32(hwndDlg);
1858
1859     switch(msg16->message)
1860     {
1861     case WM_KEYDOWN:
1862     case WM_CHAR:
1863     case WM_SYSCHAR:
1864         msg.message = msg16->message;
1865         msg.wParam  = msg16->wParam;
1866         msg.lParam  = msg16->lParam;
1867         return IsDialogMessageA( hwndDlg32, &msg );
1868     }
1869
1870     if ((hwndDlg32 != msg.hwnd) && !IsChild( hwndDlg32, msg.hwnd )) return FALSE;
1871     TranslateMessage16( msg16 );
1872     DispatchMessage16( msg16 );
1873     return TRUE;
1874 }
1875
1876
1877 /***********************************************************************
1878  *              MsgWaitForMultipleObjects  (USER.640)
1879  */
1880 DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
1881                                           BOOL wait_all, DWORD timeout, DWORD mask )
1882 {
1883     return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
1884                                         wait_all ? MWMO_WAITALL : 0 );
1885 }
1886
1887
1888 /**********************************************************************
1889  *              SetDoubleClickTime (USER.20)
1890  */
1891 void WINAPI SetDoubleClickTime16( UINT16 interval )
1892 {
1893     SetDoubleClickTime( interval );
1894 }
1895
1896
1897 /**********************************************************************
1898  *              GetDoubleClickTime (USER.21)
1899  */
1900 UINT16 WINAPI GetDoubleClickTime16(void)
1901 {
1902     return GetDoubleClickTime();
1903 }
1904
1905
1906 /***********************************************************************
1907  *              PostQuitMessage (USER.6)
1908  */
1909 void WINAPI PostQuitMessage16( INT16 exitCode )
1910 {
1911     PostQuitMessage( exitCode );
1912 }
1913
1914
1915 /**********************************************************************
1916  *              GetKeyState (USER.106)
1917  */
1918 INT16 WINAPI GetKeyState16(INT16 vkey)
1919 {
1920     return GetKeyState(vkey);
1921 }
1922
1923
1924 /**********************************************************************
1925  *              GetKeyboardState (USER.222)
1926  */
1927 BOOL WINAPI GetKeyboardState16( LPBYTE state )
1928 {
1929     return GetKeyboardState( state );
1930 }
1931
1932
1933 /**********************************************************************
1934  *              SetKeyboardState (USER.223)
1935  */
1936 BOOL WINAPI SetKeyboardState16( LPBYTE state )
1937 {
1938     return SetKeyboardState( state );
1939 }
1940
1941
1942 /***********************************************************************
1943  *              SetMessageQueue (USER.266)
1944  */
1945 BOOL16 WINAPI SetMessageQueue16( INT16 size )
1946 {
1947     return SetMessageQueue( size );
1948 }
1949
1950
1951 /***********************************************************************
1952  *              UserYield (USER.332)
1953  */
1954 void WINAPI UserYield16(void)
1955 {
1956     MSG msg;
1957     PeekMessageW( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE );
1958 }
1959
1960
1961 /***********************************************************************
1962  *              GetQueueStatus (USER.334)
1963  */
1964 DWORD WINAPI GetQueueStatus16( UINT16 flags )
1965 {
1966     return GetQueueStatus( flags );
1967 }
1968
1969
1970 /***********************************************************************
1971  *              GetInputState (USER.335)
1972  */
1973 BOOL16 WINAPI GetInputState16(void)
1974 {
1975     return GetInputState();
1976 }
1977
1978
1979 /**********************************************************************
1980  *           TranslateAccelerator      (USER.178)
1981  */
1982 INT16 WINAPI TranslateAccelerator16( HWND16 hwnd, HACCEL16 hAccel, LPMSG16 msg )
1983 {
1984     MSG msg32;
1985
1986     if (!msg) return 0;
1987     msg32.message = msg->message;
1988     /* msg32.hwnd not used */
1989     msg32.wParam  = msg->wParam;
1990     msg32.lParam  = msg->lParam;
1991     return TranslateAcceleratorW( WIN_Handle32(hwnd), HACCEL_32(hAccel), &msg32 );
1992 }
1993
1994
1995 /**********************************************************************
1996  *              TranslateMDISysAccel (USER.451)
1997  */
1998 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
1999 {
2000     if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
2001     {
2002         MSG msg32;
2003         msg32.hwnd    = WIN_Handle32(msg->hwnd);
2004         msg32.message = msg->message;
2005         msg32.wParam  = msg->wParam;
2006         msg32.lParam  = msg->lParam;
2007         /* MDICLIENTINFO is still the same for win32 and win16 ... */
2008         return TranslateMDISysAccel( WIN_Handle32(hwndClient), &msg32 );
2009     }
2010     return 0;
2011 }
2012
2013
2014 /***********************************************************************
2015  *           button_proc16
2016  */
2017 static LRESULT button_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2018 {
2019     static const UINT msg16_offset = BM_GETCHECK16 - BM_GETCHECK;
2020
2021     switch (msg)
2022     {
2023     case BM_GETCHECK16:
2024     case BM_SETCHECK16:
2025     case BM_GETSTATE16:
2026     case BM_SETSTATE16:
2027     case BM_SETSTYLE16:
2028         return wow_handlers32.button_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE );
2029     default:
2030         return wow_handlers32.button_proc( hwnd, msg, wParam, lParam, unicode );
2031     }
2032 }
2033
2034
2035 /***********************************************************************
2036  *           combo_proc16
2037  */
2038 static LRESULT combo_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2039 {
2040     static const UINT msg16_offset = CB_GETEDITSEL16 - CB_GETEDITSEL;
2041
2042     switch (msg)
2043     {
2044     case CB_INSERTSTRING16:
2045     case CB_SELECTSTRING16:
2046     case CB_FINDSTRING16:
2047     case CB_FINDSTRINGEXACT16:
2048         wParam = (INT)(INT16)wParam;
2049         /* fall through */
2050     case CB_ADDSTRING16:
2051     {
2052         DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
2053         if ((style & CBS_HASSTRINGS) || !(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)))
2054            lParam = (LPARAM)MapSL(lParam);
2055         msg -= msg16_offset;
2056         break;
2057     }
2058     case CB_SETITEMHEIGHT16:
2059     case CB_GETITEMHEIGHT16:
2060     case CB_SETCURSEL16:
2061     case CB_GETLBTEXTLEN16:
2062     case CB_GETITEMDATA16:
2063     case CB_SETITEMDATA16:
2064         wParam = (INT)(INT16)wParam;    /* signed integer */
2065         msg -= msg16_offset;
2066         break;
2067     case CB_GETDROPPEDCONTROLRECT16:
2068         lParam = (LPARAM)MapSL(lParam);
2069         if (lParam)
2070         {
2071             RECT r;
2072             RECT16 *r16 = (RECT16 *)lParam;
2073             wow_handlers32.combo_proc( hwnd, CB_GETDROPPEDCONTROLRECT, wParam, (LPARAM)&r, FALSE );
2074             r16->left   = r.left;
2075             r16->top    = r.top;
2076             r16->right  = r.right;
2077             r16->bottom = r.bottom;
2078         }
2079         return CB_OKAY;
2080     case CB_DIR16:
2081         if (wParam & DDL_DRIVES) wParam |= DDL_EXCLUSIVE;
2082         lParam = (LPARAM)MapSL(lParam);
2083         msg -= msg16_offset;
2084         break;
2085     case CB_GETLBTEXT16:
2086         wParam = (INT)(INT16)wParam;
2087         lParam = (LPARAM)MapSL(lParam);
2088         msg -= msg16_offset;
2089         break;
2090     case CB_GETEDITSEL16:
2091         wParam = lParam = 0;   /* just in case */
2092         msg -= msg16_offset;
2093         break;
2094     case CB_LIMITTEXT16:
2095     case CB_SETEDITSEL16:
2096     case CB_DELETESTRING16:
2097     case CB_RESETCONTENT16:
2098     case CB_GETDROPPEDSTATE16:
2099     case CB_SHOWDROPDOWN16:
2100     case CB_GETCOUNT16:
2101     case CB_GETCURSEL16:
2102     case CB_SETEXTENDEDUI16:
2103     case CB_GETEXTENDEDUI16:
2104         msg -= msg16_offset;
2105         break;
2106     default:
2107         return wow_handlers32.combo_proc( hwnd, msg, wParam, lParam, unicode );
2108     }
2109     return wow_handlers32.combo_proc( hwnd, msg, wParam, lParam, FALSE );
2110 }
2111
2112
2113 #define GWW_HANDLE16 sizeof(void*)
2114
2115 static void edit_lock_buffer( HWND hwnd )
2116 {
2117     STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved));
2118     HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 );
2119     HANDLE16 oldDS;
2120     HLOCAL hloc32;
2121     UINT size;
2122
2123     if (!hloc16) return;
2124     if (!(hloc32 = (HLOCAL)wow_handlers32.edit_proc( hwnd, EM_GETHANDLE, 0, 0, FALSE ))) return;
2125
2126     oldDS = stack16->ds;
2127     stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
2128     size = LocalSize16(hloc16);
2129     if (LocalReAlloc( hloc32, size, LMEM_MOVEABLE ))
2130     {
2131         char *text = MapSL( LocalLock16( hloc16 ));
2132         char *dest = LocalLock( hloc32 );
2133         memcpy( dest, text, size );
2134         LocalUnlock( hloc32 );
2135         LocalUnlock16( hloc16 );
2136     }
2137     stack16->ds = oldDS;
2138
2139 }
2140
2141 static void edit_unlock_buffer( HWND hwnd )
2142 {
2143     STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved));
2144     HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 );
2145     HANDLE16 oldDS;
2146     HLOCAL hloc32;
2147     UINT size;
2148
2149     if (!hloc16) return;
2150     if (!(hloc32 = (HLOCAL)wow_handlers32.edit_proc( hwnd, EM_GETHANDLE, 0, 0, FALSE ))) return;
2151     size = LocalSize( hloc32 );
2152
2153     oldDS = stack16->ds;
2154     stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
2155     if (LocalReAlloc16( hloc16, size, LMEM_MOVEABLE ))
2156     {
2157         char *text = LocalLock( hloc32 );
2158         char *dest = MapSL( LocalLock16( hloc16 ));
2159         memcpy( dest, text, size );
2160         LocalUnlock( hloc32 );
2161         LocalUnlock16( hloc16 );
2162     }
2163     stack16->ds = oldDS;
2164 }
2165
2166 static HLOCAL16 edit_get_handle( HWND hwnd )
2167 {
2168     CHAR *textA;
2169     UINT alloc_size;
2170     HLOCAL hloc;
2171     STACK16FRAME* stack16;
2172     HANDLE16 oldDS;
2173     HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 );
2174
2175     if (hloc16) return hloc16;
2176
2177     if (!(hloc = (HLOCAL)wow_handlers32.edit_proc( hwnd, EM_GETHANDLE, 0, 0, FALSE ))) return 0;
2178     alloc_size = LocalSize( hloc );
2179
2180     stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved));
2181     oldDS = stack16->ds;
2182     stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
2183
2184     if (!LocalHeapSize16())
2185     {
2186         if (!LocalInit16(stack16->ds, 0, GlobalSize16(stack16->ds)))
2187         {
2188             ERR("could not initialize local heap\n");
2189             goto done;
2190         }
2191     }
2192
2193     if (!(hloc16 = LocalAlloc16(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size)))
2194     {
2195         ERR("could not allocate new 16 bit buffer\n");
2196         goto done;
2197     }
2198
2199     if (!(textA = MapSL(LocalLock16( hloc16))))
2200     {
2201         ERR("could not lock new 16 bit buffer\n");
2202         LocalFree16(hloc16);
2203         hloc16 = 0;
2204         goto done;
2205     }
2206     memcpy( textA, LocalLock( hloc ), alloc_size );
2207     LocalUnlock( hloc );
2208     LocalUnlock16( hloc16 );
2209     SetWindowWord( hwnd, GWW_HANDLE16, hloc16 );
2210
2211 done:
2212     stack16->ds = oldDS;
2213     return hloc16;
2214 }
2215
2216 static void edit_set_handle( HWND hwnd, HLOCAL16 hloc16 )
2217 {
2218     STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved));
2219     HINSTANCE16 hInstance = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
2220     HANDLE16 oldDS = stack16->ds;
2221     HLOCAL hloc32;
2222     INT count;
2223     CHAR *text;
2224
2225     if (!(GetWindowLongW( hwnd, GWL_STYLE ) & ES_MULTILINE)) return;
2226     if (!hloc16) return;
2227
2228     stack16->ds = hInstance;
2229     count = LocalSize16(hloc16);
2230     text = MapSL(LocalLock16(hloc16));
2231     if ((hloc32 = LocalAlloc(LMEM_MOVEABLE, count)))
2232     {
2233         memcpy( LocalLock(hloc32), text, count );
2234         LocalUnlock(hloc32);
2235         LocalUnlock16(hloc16);
2236         SetWindowWord( hwnd, GWW_HANDLE16, hloc16 );
2237     }
2238     stack16->ds = oldDS;
2239
2240     if (hloc32) wow_handlers32.edit_proc( hwnd, EM_SETHANDLE, (WPARAM)hloc32, 0, FALSE );
2241 }
2242
2243 static void edit_destroy_handle( HWND hwnd )
2244 {
2245     HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 );
2246     if (hloc16)
2247     {
2248         STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved));
2249         HANDLE16 oldDS = stack16->ds;
2250
2251         stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
2252         while (LocalUnlock16(hloc16)) ;
2253         LocalFree16(hloc16);
2254         stack16->ds = oldDS;
2255         SetWindowWord( hwnd, GWW_HANDLE16, 0 );
2256     }
2257 }
2258
2259 /*********************************************************************
2260  *      edit_proc16
2261  */
2262 static LRESULT edit_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2263 {
2264     static const UINT msg16_offset = EM_GETSEL16 - EM_GETSEL;
2265     LRESULT result = 0;
2266
2267     edit_lock_buffer( hwnd );
2268     switch (msg)
2269     {
2270     case EM_SCROLL16:
2271     case EM_SCROLLCARET16:
2272     case EM_GETMODIFY16:
2273     case EM_SETMODIFY16:
2274     case EM_GETLINECOUNT16:
2275     case EM_GETTHUMB16:
2276     case EM_LINELENGTH16:
2277     case EM_LIMITTEXT16:
2278     case EM_CANUNDO16:
2279     case EM_UNDO16:
2280     case EM_FMTLINES16:
2281     case EM_LINEFROMCHAR16:
2282     case EM_SETPASSWORDCHAR16:
2283     case EM_EMPTYUNDOBUFFER16:
2284     case EM_SETREADONLY16:
2285     case EM_GETPASSWORDCHAR16:
2286         /* these messages missing from specs */
2287     case WM_USER+15:
2288     case WM_USER+16:
2289     case WM_USER+19:
2290     case WM_USER+26:
2291         result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE );
2292         break;
2293     case EM_GETSEL16:
2294         result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, 0, 0, FALSE );
2295         break;
2296     case EM_REPLACESEL16:
2297     case EM_GETLINE16:
2298         result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, (LPARAM)MapSL(lParam), FALSE );
2299         break;
2300     case EM_LINESCROLL16:
2301         result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, (INT)(SHORT)HIWORD(lParam),
2302                                            (INT)(SHORT)LOWORD(lParam), FALSE );
2303         break;
2304     case EM_LINEINDEX16:
2305         if ((INT16)wParam == -1) wParam = (WPARAM)-1;
2306         result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE );
2307         break;
2308     case EM_SETSEL16:
2309         if ((short)LOWORD(lParam) == -1)
2310         {
2311             wParam = -1;
2312             lParam = 0;
2313         }
2314         else
2315         {
2316             wParam = LOWORD(lParam);
2317             lParam = HIWORD(lParam);
2318         }
2319         result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE );
2320         break;
2321     case EM_GETRECT16:
2322         if (lParam)
2323         {
2324             RECT rect;
2325             RECT16 *r16 = MapSL(lParam);
2326             wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, (LPARAM)&rect, FALSE );
2327             r16->left   = rect.left;
2328             r16->top    = rect.top;
2329             r16->right  = rect.right;
2330             r16->bottom = rect.bottom;
2331         }
2332         break;
2333     case EM_SETRECT16:
2334     case EM_SETRECTNP16:
2335         if (lParam)
2336         {
2337             RECT rect;
2338             RECT16 *r16 = MapSL(lParam);
2339             rect.left   = r16->left;
2340             rect.top    = r16->top;
2341             rect.right  = r16->right;
2342             rect.bottom = r16->bottom;
2343             wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, (LPARAM)&rect, FALSE );
2344         }
2345         break;
2346     case EM_SETHANDLE16:
2347         edit_set_handle( hwnd, (HLOCAL16)wParam );
2348         break;
2349     case EM_GETHANDLE16:
2350         result = edit_get_handle( hwnd );
2351         break;
2352     case EM_SETTABSTOPS16:
2353     {
2354         INT16 *tabs16 = MapSL(lParam);
2355         INT i, count = wParam, *tabs = NULL;
2356         if (count > 0)
2357         {
2358             if (!(tabs = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*tabs) ))) return 0;
2359             for (i = 0; i < count; i++) tabs[i] = tabs16[i];
2360         }
2361         result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, count, (LPARAM)tabs, FALSE );
2362         HeapFree( GetProcessHeap(), 0, tabs );
2363         break;
2364     }
2365     case EM_GETFIRSTVISIBLELINE16:
2366         if (!(GetWindowLongW( hwnd, GWL_STYLE ) & ES_MULTILINE)) break;
2367         result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE );
2368         break;
2369     case EM_SETWORDBREAKPROC16:
2370     {
2371         struct word_break_thunk *thunk = add_word_break_thunk( (EDITWORDBREAKPROC16)lParam );
2372         result = wow_handlers32.edit_proc( hwnd, EM_SETWORDBREAKPROC, wParam, (LPARAM)thunk, FALSE );
2373         break;
2374     }
2375     case EM_GETWORDBREAKPROC16:
2376         result = wow_handlers32.edit_proc( hwnd, EM_GETWORDBREAKPROC, wParam, lParam, FALSE );
2377         result = (LRESULT)get_word_break_thunk( (EDITWORDBREAKPROCA)result );
2378         break;
2379     case WM_NCDESTROY:
2380         edit_destroy_handle( hwnd );
2381         return wow_handlers32.edit_proc( hwnd, msg, wParam, lParam, unicode );  /* no unlock on destroy */
2382     case WM_HSCROLL:
2383     case WM_VSCROLL:
2384         if (LOWORD(wParam) == EM_GETTHUMB16 || LOWORD(wParam) == EM_LINESCROLL16) wParam -= msg16_offset;
2385         result = wow_handlers32.edit_proc( hwnd, msg, wParam, lParam, unicode );
2386         break;
2387     default:
2388         result = wow_handlers32.edit_proc( hwnd, msg, wParam, lParam, unicode );
2389         break;
2390     }
2391     edit_unlock_buffer( hwnd );
2392     return result;
2393 }
2394
2395
2396 /***********************************************************************
2397  *           listbox_proc16
2398  */
2399 static LRESULT listbox_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2400 {
2401     static const UINT msg16_offset = LB_ADDSTRING16 - LB_ADDSTRING;
2402     LRESULT ret;
2403
2404     switch (msg)
2405     {
2406     case LB_RESETCONTENT16:
2407     case LB_DELETESTRING16:
2408     case LB_GETITEMDATA16:
2409     case LB_SETITEMDATA16:
2410     case LB_GETCOUNT16:
2411     case LB_GETTEXTLEN16:
2412     case LB_GETCURSEL16:
2413     case LB_GETTOPINDEX16:
2414     case LB_GETITEMHEIGHT16:
2415     case LB_SETCARETINDEX16:
2416     case LB_GETCARETINDEX16:
2417     case LB_SETTOPINDEX16:
2418     case LB_SETCOLUMNWIDTH16:
2419     case LB_GETSELCOUNT16:
2420     case LB_SELITEMRANGE16:
2421     case LB_SELITEMRANGEEX16:
2422     case LB_GETHORIZONTALEXTENT16:
2423     case LB_SETHORIZONTALEXTENT16:
2424     case LB_GETANCHORINDEX16:
2425     case LB_CARETON16:
2426     case LB_CARETOFF16:
2427         msg -= msg16_offset;
2428         break;
2429     case LB_GETSEL16:
2430     case LB_SETSEL16:
2431     case LB_SETCURSEL16:
2432     case LB_SETANCHORINDEX16:
2433         wParam = (INT)(INT16)wParam;
2434         msg -= msg16_offset;
2435         break;
2436     case LB_INSERTSTRING16:
2437     case LB_FINDSTRING16:
2438     case LB_FINDSTRINGEXACT16:
2439     case LB_SELECTSTRING16:
2440         wParam = (INT)(INT16)wParam;
2441         /* fall through */
2442     case LB_ADDSTRING16:
2443     case LB_ADDFILE16:
2444     {
2445         DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
2446         if ((style & LBS_HASSTRINGS) || !(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)))
2447             lParam = (LPARAM)MapSL(lParam);
2448         msg -= msg16_offset;
2449         break;
2450     }
2451     case LB_GETTEXT16:
2452         lParam = (LPARAM)MapSL(lParam);
2453         msg -= msg16_offset;
2454         break;
2455     case LB_SETITEMHEIGHT16:
2456         lParam = LOWORD(lParam);
2457         msg -= msg16_offset;
2458         break;
2459     case LB_GETITEMRECT16:
2460         {
2461             RECT rect;
2462             RECT16 *r16 = MapSL(lParam);
2463             ret = wow_handlers32.listbox_proc( hwnd, LB_GETITEMRECT, (INT16)wParam, (LPARAM)&rect, FALSE );
2464             r16->left   = rect.left;
2465             r16->top    = rect.top;
2466             r16->right  = rect.right;
2467             r16->bottom = rect.bottom;
2468             return ret;
2469         }
2470     case LB_GETSELITEMS16:
2471     {
2472         INT16 *array16 = MapSL( lParam );
2473         INT i, count = (INT16)wParam, *array;
2474         if (!(array = HeapAlloc( GetProcessHeap(), 0, wParam * sizeof(*array) ))) return LB_ERRSPACE;
2475         ret = wow_handlers32.listbox_proc( hwnd, LB_GETSELITEMS, count, (LPARAM)array, FALSE );
2476         for (i = 0; i < ret; i++) array16[i] = array[i];
2477         HeapFree( GetProcessHeap(), 0, array );
2478         return ret;
2479     }
2480     case LB_DIR16:
2481         /* according to Win16 docs, DDL_DRIVES should make DDL_EXCLUSIVE
2482          * be set automatically (this is different in Win32) */
2483         if (wParam & DDL_DRIVES) wParam |= DDL_EXCLUSIVE;
2484         lParam = (LPARAM)MapSL(lParam);
2485         msg -= msg16_offset;
2486         break;
2487     case LB_SETTABSTOPS16:
2488     {
2489         INT i, count, *tabs = NULL;
2490         INT16 *tabs16 = MapSL( lParam );
2491
2492         if ((count = (INT16)wParam) > 0)
2493         {
2494             if (!(tabs = HeapAlloc( GetProcessHeap(), 0, wParam * sizeof(*tabs) ))) return LB_ERRSPACE;
2495             for (i = 0; i < count; i++) tabs[i] = tabs16[i] << 1; /* FIXME */
2496         }
2497         ret = wow_handlers32.listbox_proc( hwnd, LB_SETTABSTOPS, count, (LPARAM)tabs, FALSE );
2498         HeapFree( GetProcessHeap(), 0, tabs );
2499         return ret;
2500     }
2501     default:
2502         return wow_handlers32.listbox_proc( hwnd, msg, wParam, lParam, unicode );
2503     }
2504     return wow_handlers32.listbox_proc( hwnd, msg, wParam, lParam, FALSE );
2505 }
2506
2507
2508 /***********************************************************************
2509  *           mdiclient_proc16
2510  */
2511 static LRESULT mdiclient_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2512 {
2513     if (msg == WM_CREATE)
2514     {
2515         LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
2516         WND *win;
2517         BOOL is_win32;
2518
2519         if (!(win = WIN_GetPtr( hwnd ))) return 0;
2520         is_win32 = (win == WND_OTHER_PROCESS || win == WND_DESKTOP || (win->flags & WIN_ISWIN32));
2521         WIN_ReleasePtr( win );
2522
2523         /* Translation layer doesn't know what's in the cs->lpCreateParams
2524          * so we have to keep track of what environment we're in. */
2525         if (!is_win32)
2526         {
2527             void *orig = cs->lpCreateParams;
2528             LRESULT ret;
2529             CLIENTCREATESTRUCT ccs;
2530             CLIENTCREATESTRUCT16 *ccs16 = MapSL( PtrToUlong( orig ));
2531
2532             ccs.hWindowMenu  = HMENU_32(ccs16->hWindowMenu);
2533             ccs.idFirstChild = ccs16->idFirstChild;
2534             cs->lpCreateParams = &ccs;
2535             ret = wow_handlers32.mdiclient_proc( hwnd, msg, wParam, lParam, unicode );
2536             cs->lpCreateParams = orig;
2537             return ret;
2538         }
2539     }
2540     return wow_handlers32.mdiclient_proc( hwnd, msg, wParam, lParam, unicode );
2541 }
2542
2543
2544 /***********************************************************************
2545  *           scrollbar_proc16
2546  */
2547 static LRESULT scrollbar_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2548 {
2549     static const UINT msg16_offset = SBM_SETPOS16 - SBM_SETPOS;
2550
2551     switch (msg)
2552     {
2553     case SBM_SETPOS16:
2554     case SBM_GETPOS16:
2555     case SBM_ENABLE_ARROWS16:
2556         msg -= msg16_offset;
2557         break;
2558     case SBM_SETRANGE16:
2559         msg = wParam ? SBM_SETRANGEREDRAW : SBM_SETRANGE;
2560         wParam = LOWORD(lParam);
2561         lParam = HIWORD(lParam);
2562         break;
2563     case SBM_GETRANGE16:
2564     {
2565         INT min, max;
2566         wow_handlers32.scrollbar_proc( hwnd, SBM_GETRANGE, (WPARAM)&min, (LPARAM)&max, FALSE );
2567         return MAKELRESULT(min, max);
2568     }
2569     default:
2570         return wow_handlers32.scrollbar_proc( hwnd, msg, wParam, lParam, unicode );
2571     }
2572     return wow_handlers32.scrollbar_proc( hwnd, msg, wParam, lParam, FALSE );
2573 }
2574
2575
2576 /***********************************************************************
2577  *           static_proc16
2578  */
2579 static LRESULT static_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode )
2580 {
2581     switch (msg)
2582     {
2583     case STM_SETICON16:
2584         wParam = (WPARAM)HICON_32( (HICON16)wParam );
2585         return wow_handlers32.static_proc( hwnd, STM_SETICON, wParam, lParam, FALSE );
2586     case STM_GETICON16:
2587         return HICON_16( wow_handlers32.static_proc( hwnd, STM_GETICON, wParam, lParam, FALSE ));
2588     default:
2589         return wow_handlers32.static_proc( hwnd, msg, wParam, lParam, unicode );
2590     }
2591 }
2592
2593
2594 /***********************************************************************
2595  *           create_window16
2596  */
2597 HWND create_window16( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE instance, UINT flags )
2598 {
2599     /* map to module handle */
2600     if (instance && !((ULONG_PTR)instance >> 16))
2601         instance = HINSTANCE_32( GetExePtr( HINSTANCE_16(instance) ));
2602
2603     return wow_handlers32.create_window( cs, className, instance, flags );
2604 }
2605
2606
2607 /***********************************************************************
2608  * cursor/icon handles
2609  */
2610
2611 static HICON alloc_icon_handle( unsigned int size )
2612 {
2613     HGLOBAL16 handle = GlobalAlloc16( GMEM_MOVEABLE, size );
2614     FarSetOwner16( handle, 0 );
2615     return HICON_32( handle );
2616 }
2617
2618 static struct tagCURSORICONINFO *get_icon_ptr( HICON handle )
2619 {
2620     return GlobalLock16( HICON_16(handle) );
2621 }
2622
2623 static void release_icon_ptr( HICON handle, struct tagCURSORICONINFO *ptr )
2624 {
2625     GlobalUnlock16( HICON_16(handle) );
2626 }
2627
2628 static int free_icon_handle( HICON handle )
2629 {
2630     return GlobalFree16( HICON_16(handle) );
2631 }
2632
2633
2634 void register_wow_handlers(void)
2635 {
2636     static const struct wow_handlers16 handlers16 =
2637     {
2638         button_proc16,
2639         combo_proc16,
2640         edit_proc16,
2641         listbox_proc16,
2642         mdiclient_proc16,
2643         scrollbar_proc16,
2644         static_proc16,
2645         create_window16,
2646         call_window_proc_Ato16,
2647         call_dialog_proc_Ato16,
2648         alloc_icon_handle,
2649         get_icon_ptr,
2650         release_icon_ptr,
2651         free_icon_handle
2652     };
2653
2654     UserRegisterWowHandlers( &handlers16, &wow_handlers32 );
2655 }