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