user: Get rid of the MSGPARAMS16 structure.
[wine] / dlls / user / winproc.c
1 /*
2  * Window procedure callbacks
3  *
4  * Copyright 1995 Martin von Loewis
5  * Copyright 1996 Alexandre Julliard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <string.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "wownt32.h"
33 #include "wine/winbase16.h"
34 #include "wine/winuser16.h"
35 #include "controls.h"
36 #include "win.h"
37 #include "winproc.h"
38 #include "user_private.h"
39 #include "dde.h"
40 #include "winternl.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
43
44 WINE_DECLARE_DEBUG_CHANNEL(msg);
45 WINE_DECLARE_DEBUG_CHANNEL(relay);
46 WINE_DEFAULT_DEBUG_CHANNEL(win);
47
48 typedef struct tagWINDOWPROC
49 {
50     WNDPROC16      proc16;   /* 16-bit window proc */
51     WNDPROC        procA;    /* ASCII window proc */
52     WNDPROC        procW;    /* Unicode window proc */
53 } WINDOWPROC;
54
55 #define WINPROC_HANDLE (~0UL >> 16)
56 #define MAX_WINPROCS  8192
57
58 static WINDOWPROC winproc_array[MAX_WINPROCS];
59 static UINT winproc_used;
60
61 static CRITICAL_SECTION winproc_cs;
62 static CRITICAL_SECTION_DEBUG critsect_debug =
63 {
64     0, 0, &winproc_cs,
65     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
66       0, 0, { (DWORD_PTR)(__FILE__ ": winproc_cs") }
67 };
68 static CRITICAL_SECTION winproc_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
69
70 /* map a Unicode string to a 16-bit pointer */
71 inline static SEGPTR map_str_32W_to_16( LPCWSTR str )
72 {
73     LPSTR ret;
74     INT len;
75
76     if (!HIWORD(str)) return (SEGPTR)LOWORD(str);
77     len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
78     if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
79         WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
80     return MapLS(ret);
81 }
82
83 /* unmap a Unicode string that was converted to a 16-bit pointer */
84 inline static void unmap_str_32W_to_16( SEGPTR str )
85 {
86     if (!HIWORD(str)) return;
87     HeapFree( GetProcessHeap(), 0, MapSL(str) );
88     UnMapLS( str );
89 }
90
91 /* map a 16-bit pointer to a Unicode string */
92 inline static LPWSTR map_str_16_to_32W( SEGPTR str )
93 {
94     LPWSTR ret;
95     INT len;
96
97     if (!HIWORD(str)) return (LPWSTR)(ULONG_PTR)LOWORD(str);
98     len = MultiByteToWideChar( CP_ACP, 0, MapSL(str), -1, NULL, 0 );
99     if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
100         MultiByteToWideChar( CP_ACP, 0, MapSL(str), -1, ret, len );
101     return ret;
102 }
103
104 /* unmap a 16-bit pointer that was converted to a Unicode string */
105 inline static void unmap_str_16_to_32W( LPCWSTR str )
106 {
107     if (HIWORD(str)) HeapFree( GetProcessHeap(), 0, (void *)str );
108 }
109
110 /* find an existing winproc for a given 16-bit function and type */
111 /* FIXME: probably should do something more clever than a linear search */
112 static inline WINDOWPROC *find_winproc16( WNDPROC16 func )
113 {
114     unsigned int i;
115
116     for (i = 0; i < winproc_used; i++)
117     {
118         if (winproc_array[i].proc16 == func) return &winproc_array[i];
119     }
120     return NULL;
121 }
122
123 /* find an existing winproc for a given function and type */
124 /* FIXME: probably should do something more clever than a linear search */
125 static inline WINDOWPROC *find_winproc( WNDPROC funcA, WNDPROC funcW )
126 {
127     unsigned int i;
128
129     for (i = 0; i < winproc_used; i++)
130     {
131         if (funcA && winproc_array[i].procA != funcA) continue;
132         if (funcW && winproc_array[i].procW != funcW) continue;
133         return &winproc_array[i];
134     }
135     return NULL;
136 }
137
138 /* return the window proc for a given handle, or NULL for an invalid handle */
139 static inline WINDOWPROC *handle_to_proc( WNDPROC handle )
140 {
141     UINT index = LOWORD(handle);
142     if ((ULONG_PTR)handle >> 16 != WINPROC_HANDLE) return NULL;
143     if (index >= winproc_used) return NULL;
144     return &winproc_array[index];
145 }
146
147 /* create a handle for a given window proc */
148 static inline WNDPROC proc_to_handle( WINDOWPROC *proc )
149 {
150     return (WNDPROC)(ULONG_PTR)((proc - winproc_array) | (WINPROC_HANDLE << 16));
151 }
152
153 /* allocate and initialize a new winproc */
154 static inline WINDOWPROC *alloc_winproc( WNDPROC funcA, WNDPROC funcW )
155 {
156     WINDOWPROC *proc;
157
158     /* check if the function is already a win proc */
159     if (funcA && (proc = handle_to_proc( funcA ))) return proc;
160     if (funcW && (proc = handle_to_proc( funcW ))) return proc;
161     if (!funcA && !funcW) return NULL;
162
163     EnterCriticalSection( &winproc_cs );
164
165     /* check if we already have a winproc for that function */
166     if (!(proc = find_winproc( funcA, funcW )))
167     {
168         if (winproc_used < MAX_WINPROCS)
169         {
170             proc = &winproc_array[winproc_used++];
171             proc->procA = funcA;
172             proc->procW = funcW;
173             TRACE( "allocated %p for %p/%p (%d/%d used)\n",
174                    proc_to_handle(proc), funcA, funcW, winproc_used, MAX_WINPROCS );
175         }
176         else FIXME( "too many winprocs, cannot allocate one for %p/%p\n", funcA, funcW );
177     }
178     else TRACE( "reusing %p for %p/%p\n", proc_to_handle(proc), funcA, funcW );
179
180     LeaveCriticalSection( &winproc_cs );
181     return proc;
182 }
183
184
185 #ifdef __i386__
186
187 #include "pshpack1.h"
188
189 /* Window procedure 16-to-32-bit thunk */
190 typedef struct
191 {
192     BYTE        popl_eax;        /* popl  %eax (return address) */
193     BYTE        pushl_func;      /* pushl $proc */
194     WINDOWPROC *proc;
195     BYTE        pushl_eax;       /* pushl %eax */
196     BYTE        ljmp;            /* ljmp relay*/
197     DWORD       relay_offset;    /* __wine_call_wndproc */
198     WORD        relay_sel;
199 } WINPROC_THUNK;
200
201 #include "poppack.h"
202
203 #define MAX_THUNKS  (0x10000 / sizeof(WINPROC_THUNK))
204
205 static WINPROC_THUNK *thunk_array;
206 static UINT thunk_selector;
207 static UINT thunk_used;
208
209 /* return the window proc for a given handle, or NULL for an invalid handle */
210 static inline WINDOWPROC *handle16_to_proc( WNDPROC16 handle )
211 {
212     if (HIWORD(handle) == thunk_selector)
213     {
214         UINT index = LOWORD(handle) / sizeof(WINPROC_THUNK);
215         /* check alignment */
216         if (index * sizeof(WINPROC_THUNK) != LOWORD(handle)) return NULL;
217         /* check array limits */
218         if (index >= thunk_used) return NULL;
219         return thunk_array[index].proc;
220     }
221     return handle_to_proc( (WNDPROC)handle );
222 }
223
224 /* allocate a 16-bit thunk for an existing window proc */
225 static WNDPROC16 alloc_win16_thunk( WINDOWPROC *proc )
226 {
227     static FARPROC16 relay;
228     UINT i;
229
230     if (proc->proc16) return proc->proc16;
231
232     EnterCriticalSection( &winproc_cs );
233
234     if (!thunk_array)  /* allocate the array and its selector */
235     {
236         LDT_ENTRY entry;
237
238         if (!(thunk_selector = wine_ldt_alloc_entries(1))) goto done;
239         if (!(thunk_array = VirtualAlloc( NULL, MAX_THUNKS * sizeof(WINPROC_THUNK), MEM_COMMIT,
240                                           PAGE_EXECUTE_READWRITE ))) goto done;
241         wine_ldt_set_base( &entry, thunk_array );
242         wine_ldt_set_limit( &entry, MAX_THUNKS * sizeof(WINPROC_THUNK) - 1 );
243         wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
244         wine_ldt_set_entry( thunk_selector, &entry );
245         relay = GetProcAddress16( GetModuleHandle16("user"), "__wine_call_wndproc" );
246     }
247
248     /* check if it already exists */
249     for (i = 0; i < thunk_used; i++) if (thunk_array[i].proc == proc) break;
250
251     if (i == thunk_used)  /* create a new one */
252     {
253         WINPROC_THUNK *thunk;
254
255         if (thunk_used >= MAX_THUNKS) goto done;
256         thunk = &thunk_array[thunk_used++];
257         thunk->popl_eax     = 0x58;   /* popl  %eax */
258         thunk->pushl_func   = 0x68;   /* pushl $proc */
259         thunk->proc         = proc;
260         thunk->pushl_eax    = 0x50;   /* pushl %eax */
261         thunk->ljmp         = 0xea;   /* ljmp   relay*/
262         thunk->relay_offset = OFFSETOF(relay);
263         thunk->relay_sel    = SELECTOROF(relay);
264     }
265     proc->proc16 = (WNDPROC16)MAKESEGPTR( thunk_selector, i * sizeof(WINPROC_THUNK) );
266 done:
267     LeaveCriticalSection( &winproc_cs );
268     return proc->proc16;
269 }
270
271 #else  /* __i386__ */
272
273 static inline WINDOWPROC *handle16_to_proc( WNDPROC16 handle )
274 {
275     return handle_to_proc( (WNDPROC)handle );
276 }
277
278 static inline WNDPROC16 alloc_win16_thunk( WINDOWPROC *proc )
279 {
280     return 0;
281 }
282
283 #endif  /* __i386__ */
284
285
286 #ifdef __i386__
287 /* Some window procedures modify register they shouldn't, or are not
288  * properly declared stdcall; so we need a small assembly wrapper to
289  * call them. */
290 extern LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
291                                 WPARAM wParam, LPARAM lParam );
292 __ASM_GLOBAL_FUNC( WINPROC_wrapper,
293                    "pushl %ebp\n\t"
294                    "movl %esp,%ebp\n\t"
295                    "pushl %edi\n\t"
296                    "pushl %esi\n\t"
297                    "pushl %ebx\n\t"
298                    "subl $12,%esp\n\t"
299                    "pushl 24(%ebp)\n\t"
300                    "pushl 20(%ebp)\n\t"
301                    "pushl 16(%ebp)\n\t"
302                    "pushl 12(%ebp)\n\t"
303                    "movl 8(%ebp),%eax\n\t"
304                    "call *%eax\n\t"
305                    "leal -12(%ebp),%esp\n\t"
306                    "popl %ebx\n\t"
307                    "popl %esi\n\t"
308                    "popl %edi\n\t"
309                    "leave\n\t"
310                    "ret" );
311 #else
312 static inline LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
313                                        WPARAM wParam, LPARAM lParam )
314 {
315     return proc( hwnd, msg, wParam, lParam );
316 }
317 #endif  /* __i386__ */
318
319
320 static void MINMAXINFO32to16( const MINMAXINFO *from, MINMAXINFO16 *to )
321 {
322     to->ptReserved.x     = from->ptReserved.x;
323     to->ptReserved.y     = from->ptReserved.y;
324     to->ptMaxSize.x      = from->ptMaxSize.x;
325     to->ptMaxSize.y      = from->ptMaxSize.y;
326     to->ptMaxPosition.x  = from->ptMaxPosition.x;
327     to->ptMaxPosition.y  = from->ptMaxPosition.y;
328     to->ptMinTrackSize.x = from->ptMinTrackSize.x;
329     to->ptMinTrackSize.y = from->ptMinTrackSize.y;
330     to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
331     to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
332 }
333
334 static void MINMAXINFO16to32( const MINMAXINFO16 *from, MINMAXINFO *to )
335 {
336     to->ptReserved.x     = from->ptReserved.x;
337     to->ptReserved.y     = from->ptReserved.y;
338     to->ptMaxSize.x      = from->ptMaxSize.x;
339     to->ptMaxSize.y      = from->ptMaxSize.y;
340     to->ptMaxPosition.x  = from->ptMaxPosition.x;
341     to->ptMaxPosition.y  = from->ptMaxPosition.y;
342     to->ptMinTrackSize.x = from->ptMinTrackSize.x;
343     to->ptMinTrackSize.y = from->ptMinTrackSize.y;
344     to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
345     to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
346 }
347
348 static void WINDOWPOS32to16( const WINDOWPOS* from, WINDOWPOS16* to )
349 {
350     to->hwnd            = HWND_16(from->hwnd);
351     to->hwndInsertAfter = HWND_16(from->hwndInsertAfter);
352     to->x               = from->x;
353     to->y               = from->y;
354     to->cx              = from->cx;
355     to->cy              = from->cy;
356     to->flags           = from->flags;
357 }
358
359 static void WINDOWPOS16to32( const WINDOWPOS16* from, WINDOWPOS* to )
360 {
361     to->hwnd            = WIN_Handle32(from->hwnd);
362     to->hwndInsertAfter = (from->hwndInsertAfter == (HWND16)-1) ?
363                            HWND_TOPMOST : WIN_Handle32(from->hwndInsertAfter);
364     to->x               = from->x;
365     to->y               = from->y;
366     to->cx              = from->cx;
367     to->cy              = from->cy;
368     to->flags           = from->flags;
369 }
370
371 /* The strings are not copied */
372 static void CREATESTRUCT32Ato16( const CREATESTRUCTA* from, CREATESTRUCT16* to )
373 {
374     to->lpCreateParams = (SEGPTR)from->lpCreateParams;
375     to->hInstance      = HINSTANCE_16(from->hInstance);
376     to->hMenu          = HMENU_16(from->hMenu);
377     to->hwndParent     = HWND_16(from->hwndParent);
378     to->cy             = from->cy;
379     to->cx             = from->cx;
380     to->y              = from->y;
381     to->x              = from->x;
382     to->style          = from->style;
383     to->dwExStyle      = from->dwExStyle;
384 }
385
386 static void CREATESTRUCT16to32A( const CREATESTRUCT16* from, CREATESTRUCTA *to )
387
388 {
389     to->lpCreateParams = (LPVOID)from->lpCreateParams;
390     to->hInstance      = HINSTANCE_32(from->hInstance);
391     to->hMenu          = HMENU_32(from->hMenu);
392     to->hwndParent     = WIN_Handle32(from->hwndParent);
393     to->cy             = from->cy;
394     to->cx             = from->cx;
395     to->y              = from->y;
396     to->x              = from->x;
397     to->style          = from->style;
398     to->dwExStyle      = from->dwExStyle;
399 }
400
401 /* The strings are not copied */
402 static void MDICREATESTRUCT32Ato16( const MDICREATESTRUCTA* from, MDICREATESTRUCT16* to )
403 {
404     to->hOwner = HINSTANCE_16(from->hOwner);
405     to->x      = from->x;
406     to->y      = from->y;
407     to->cx     = from->cx;
408     to->cy     = from->cy;
409     to->style  = from->style;
410     to->lParam = from->lParam;
411 }
412
413 static void MDICREATESTRUCT16to32A( const MDICREATESTRUCT16* from, MDICREATESTRUCTA *to )
414 {
415     to->hOwner = HINSTANCE_32(from->hOwner);
416     to->x      = from->x;
417     to->y      = from->y;
418     to->cx     = from->cx;
419     to->cy     = from->cy;
420     to->style  = from->style;
421     to->lParam = from->lParam;
422 }
423
424 static WPARAM map_wparam_char_AtoW( WPARAM wParam, DWORD len )
425 {
426     CHAR ch[2];
427     WCHAR wch;
428
429     ch[0] = (wParam >> 8);
430     ch[1] = wParam & 0xff;
431     if (len > 1 && ch[0])
432         RtlMultiByteToUnicodeN( &wch, sizeof(wch), NULL, ch, 2 );
433     else
434         RtlMultiByteToUnicodeN( &wch, sizeof(wch), NULL, ch + 1, 1 );
435     return MAKEWPARAM( wch, HIWORD(wParam) );
436 }
437
438 static WPARAM map_wparam_char_WtoA( WPARAM wParam, DWORD len )
439 {
440     WCHAR wch = wParam;
441     BYTE ch[2];
442
443     RtlUnicodeToMultiByteN( (LPSTR)ch, len, &len, &wch, sizeof(wch) );
444     if (len == 2)
445         return MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(wParam) );
446     else
447         return MAKEWPARAM( ch[0], HIWORD(wParam) );
448 }
449
450 /* call a 32-bit window procedure */
451 static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result, void *arg )
452 {
453     WNDPROC proc = arg;
454
455     USER_CheckNotLock();
456
457     hwnd = WIN_GetFullHandle( hwnd );
458     if (TRACE_ON(relay))
459         DPRINTF( "%04lx:Call window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
460                  GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp );
461
462     *result = WINPROC_wrapper( proc, hwnd, msg, wp, lp );
463
464     if (TRACE_ON(relay))
465         DPRINTF( "%04lx:Ret  window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx\n",
466                  GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp, *result );
467     return *result;
468 }
469
470 /* call a 32-bit dialog procedure */
471 static LRESULT call_dialog_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result, void *arg )
472 {
473     WNDPROC proc = arg;
474     LRESULT ret;
475
476     USER_CheckNotLock();
477
478     hwnd = WIN_GetFullHandle( hwnd );
479     if (TRACE_ON(relay))
480         DPRINTF( "%04lx:Call dialog proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
481                  GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp );
482
483     ret = WINPROC_wrapper( proc, hwnd, msg, wp, lp );
484     *result = GetWindowLongPtrW( hwnd, DWLP_MSGRESULT );
485
486     if (TRACE_ON(relay))
487         DPRINTF( "%04lx:Ret  dialog proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx result=%08lx\n",
488                  GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp, ret, *result );
489     return ret;
490 }
491
492 /**********************************************************************
493  *           WINPROC_CallWndProc32
494  *
495  * Call a 32-bit WndProc.
496  */
497 static LRESULT WINPROC_CallWndProc( WNDPROC proc, HWND hwnd, UINT msg,
498                                       WPARAM wParam, LPARAM lParam )
499 {
500     LRESULT retvalue;
501
502     USER_CheckNotLock();
503
504     hwnd = WIN_GetFullHandle( hwnd );
505     if (TRACE_ON(relay))
506         DPRINTF( "%04lx:Call window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
507                  GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
508
509     retvalue = WINPROC_wrapper( proc, hwnd, msg, wParam, lParam );
510
511     if (TRACE_ON(relay))
512         DPRINTF( "%04lx:Ret  window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx\n",
513                  GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam, retvalue );
514     return retvalue;
515 }
516
517 /* call a 16-bit window procedure */
518 static LRESULT call_window_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
519                                    LRESULT *result, void *arg )
520 {
521     WNDPROC16 proc = arg;
522     CONTEXT86 context;
523     size_t size = 0;
524     struct
525     {
526         WORD params[5];
527         union
528         {
529             CREATESTRUCT16 cs16;
530             DRAWITEMSTRUCT16 dis16;
531             COMPAREITEMSTRUCT16 cis16;
532         } u;
533     } args;
534
535     USER_CheckNotLock();
536
537     /* Window procedures want ax = hInstance, ds = es = ss */
538
539     memset(&context, 0, sizeof(context));
540     context.SegDs = context.SegEs = SELECTOROF(NtCurrentTeb()->WOW32Reserved);
541     context.SegFs = wine_get_fs();
542     context.SegGs = wine_get_gs();
543     if (!(context.Eax = GetWindowWord( HWND_32(hwnd), GWLP_HINSTANCE ))) context.Eax = context.SegDs;
544     context.SegCs = SELECTOROF(proc);
545     context.Eip   = OFFSETOF(proc);
546     context.Ebp   = OFFSETOF(NtCurrentTeb()->WOW32Reserved) + (WORD)&((STACK16FRAME*)0)->bp;
547
548     if (lParam)
549     {
550         /* Some programs (eg. the "Undocumented Windows" examples, JWP) only
551            work if structures passed in lParam are placed in the stack/data
552            segment. Programmers easily make the mistake of converting lParam
553            to a near rather than a far pointer, since Windows apparently
554            allows this. We copy the structures to the 16 bit stack; this is
555            ugly but makes these programs work. */
556         switch (msg)
557         {
558           case WM_CREATE:
559           case WM_NCCREATE:
560             size = sizeof(CREATESTRUCT16); break;
561           case WM_DRAWITEM:
562             size = sizeof(DRAWITEMSTRUCT16); break;
563           case WM_COMPAREITEM:
564             size = sizeof(COMPAREITEMSTRUCT16); break;
565         }
566         if (size)
567         {
568             memcpy( &args.u, MapSL(lParam), size );
569             lParam = (SEGPTR)NtCurrentTeb()->WOW32Reserved - size;
570         }
571     }
572
573     args.params[4] = hwnd;
574     args.params[3] = msg;
575     args.params[2] = wParam;
576     args.params[1] = HIWORD(lParam);
577     args.params[0] = LOWORD(lParam);
578     WOWCallback16Ex( 0, WCB16_REGS, sizeof(args.params) + size, &args, (DWORD *)&context );
579     *result = MAKELONG( LOWORD(context.Eax), LOWORD(context.Edx) );
580     return *result;
581 }
582
583 /* call a 16-bit dialog procedure */
584 static LRESULT call_dialog_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp,
585                                    LRESULT *result, void *arg )
586 {
587     LRESULT ret = call_window_proc16( hwnd, msg, wp, lp, result, arg );
588     *result = GetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT );
589     return LOWORD(ret);
590 }
591
592
593 /**********************************************************************
594  *           WINPROC_GetProc16
595  *
596  * Get a window procedure pointer that can be passed to the Windows program.
597  */
598 WNDPROC16 WINPROC_GetProc16( WNDPROC proc, BOOL unicode )
599 {
600     WINDOWPROC *ptr;
601
602     if (unicode) ptr = alloc_winproc( NULL, proc );
603     else ptr = alloc_winproc( proc, NULL );
604
605     if (!ptr) return 0;
606     return alloc_win16_thunk( ptr );
607 }
608
609
610 /**********************************************************************
611  *           WINPROC_GetProc
612  *
613  * Get a window procedure pointer that can be passed to the Windows program.
614  */
615 WNDPROC WINPROC_GetProc( WNDPROC proc, BOOL unicode )
616 {
617     WINDOWPROC *ptr = handle_to_proc( proc );
618
619     if (!ptr) return proc;
620     if (unicode)
621     {
622         if (ptr->procW) return ptr->procW;
623         return proc;
624     }
625     else
626     {
627         if (ptr->procA) return ptr->procA;
628         return proc;
629     }
630 }
631
632
633 /**********************************************************************
634  *           WINPROC_AllocProc16
635  *
636  * Allocate a window procedure for a window or class.
637  *
638  * Note that allocated winprocs are never freed; the idea is that even if an app creates a
639  * lot of windows, it will usually only have a limited number of window procedures, so the
640  * array won't grow too large, and this way we avoid the need to track allocations per window.
641  */
642 WNDPROC WINPROC_AllocProc16( WNDPROC16 func )
643 {
644     WINDOWPROC *proc;
645
646     if (!func) return NULL;
647
648     /* check if the function is already a win proc */
649     if (!(proc = handle16_to_proc( func )))
650     {
651         EnterCriticalSection( &winproc_cs );
652
653         /* then check if we already have a winproc for that function */
654         if (!(proc = find_winproc16( func )))
655         {
656             if (winproc_used < MAX_WINPROCS)
657             {
658                 proc = &winproc_array[winproc_used++];
659                 proc->proc16 = func;
660                 TRACE( "allocated %p for %p/16-bit (%d/%d used)\n",
661                        proc_to_handle(proc), func, winproc_used, MAX_WINPROCS );
662             }
663             else FIXME( "too many winprocs, cannot allocate one for 16-bit %p\n", func );
664         }
665         else TRACE( "reusing %p for %p/16-bit\n", proc_to_handle(proc), func );
666
667         LeaveCriticalSection( &winproc_cs );
668     }
669     return proc_to_handle( proc );
670 }
671
672
673 /**********************************************************************
674  *           WINPROC_AllocProc
675  *
676  * Allocate a window procedure for a window or class.
677  *
678  * Note that allocated winprocs are never freed; the idea is that even if an app creates a
679  * lot of windows, it will usually only have a limited number of window procedures, so the
680  * array won't grow too large, and this way we avoid the need to track allocations per window.
681  */
682 WNDPROC WINPROC_AllocProc( WNDPROC funcA, WNDPROC funcW )
683 {
684     WINDOWPROC *proc;
685
686     if (!(proc = alloc_winproc( funcA, funcW ))) return NULL;
687     return proc_to_handle( proc );
688 }
689
690
691 /**********************************************************************
692  *           WINPROC_IsUnicode
693  *
694  * Return the window procedure type, or the default value if not a winproc handle.
695  */
696 BOOL WINPROC_IsUnicode( WNDPROC proc, BOOL def_val )
697 {
698     WINDOWPROC *ptr = handle_to_proc( proc );
699
700     if (!ptr) return def_val;
701     if (ptr->procA && ptr->procW) return def_val;  /* can be both */
702     return (ptr->procW != NULL);
703 }
704
705
706 /**********************************************************************
707  *           WINPROC_TestLBForStr
708  *
709  * Return TRUE if the lparam is a string
710  */
711 inline static BOOL WINPROC_TestLBForStr( HWND hwnd, UINT msg )
712 {
713     DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
714     if (msg <= CB_MSGMAX)
715         return (!(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) || (style & CBS_HASSTRINGS));
716     else
717         return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS));
718
719 }
720 /**********************************************************************
721  *           WINPROC_MapMsg32ATo32W
722  *
723  * Map a message from Ansi to Unicode.
724  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
725  *
726  * FIXME:
727  *  WM_GETTEXT/WM_SETTEXT and static control with SS_ICON style:
728  *  the first four bytes are the handle of the icon
729  *  when the WM_SETTEXT message has been used to set the icon
730  */
731 static INT WINPROC_MapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
732 {
733     switch(msg)
734     {
735     case WM_GETTEXT:
736     case WM_ASKCBFORMATNAME:
737         {
738             LPARAM *ptr = HeapAlloc( GetProcessHeap(), 0,
739                                      *pwparam * sizeof(WCHAR) + sizeof(LPARAM) );
740             if (!ptr) return -1;
741             *ptr++ = *plparam;  /* Store previous lParam */
742             *plparam = (LPARAM)ptr;
743         }
744         return 1;
745     /* lparam is string (0-terminated) */
746     case WM_SETTEXT:
747     case WM_WININICHANGE:
748     case WM_DEVMODECHANGE:
749     case CB_DIR:
750     case LB_DIR:
751     case LB_ADDFILE:
752     case EM_REPLACESEL:
753         if (!*plparam) return 0;
754         else
755         {
756             DWORD len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*plparam, -1, NULL, 0);
757             WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
758             MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*plparam, -1, buf, len);
759             *plparam = (LPARAM)buf;
760             return (*plparam ? 1 : -1);
761         }
762     case WM_GETTEXTLENGTH:
763     case CB_GETLBTEXTLEN:
764     case LB_GETTEXTLEN:
765         return 1;  /* need to map result */
766     case WM_NCCREATE:
767     case WM_CREATE:
768         {
769             UNICODE_STRING usBuffer;
770             struct s
771             { CREATESTRUCTW cs;         /* new structure */
772               LPCWSTR lpszName;         /* allocated Name */
773               LPCWSTR lpszClass;        /* allocated Class */
774             };
775
776             struct s *xs = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct s));
777             if (!xs) return -1;
778             xs->cs = *(CREATESTRUCTW *)*plparam;
779             if (HIWORD(xs->cs.lpszName))
780             {
781                 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)xs->cs.lpszName);
782                 xs->lpszName = xs->cs.lpszName = usBuffer.Buffer;
783             }
784             if (HIWORD(xs->cs.lpszClass))
785             {
786                 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)xs->cs.lpszClass);
787                 xs->lpszClass = xs->cs.lpszClass = usBuffer.Buffer;
788             }
789
790             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
791             {
792                 MDICREATESTRUCTW *mdi_cs = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs));
793                 *mdi_cs = *(MDICREATESTRUCTW *)xs->cs.lpCreateParams;
794                 if (HIWORD(mdi_cs->szTitle))
795                 {
796                     RtlCreateUnicodeStringFromAsciiz(&usBuffer, (LPCSTR)mdi_cs->szTitle);
797                     mdi_cs->szTitle = usBuffer.Buffer;
798                 }
799                 if (HIWORD(mdi_cs->szClass))
800                 {
801                     RtlCreateUnicodeStringFromAsciiz(&usBuffer, (LPCSTR)mdi_cs->szClass);
802                     mdi_cs->szClass = usBuffer.Buffer;
803                 }
804                 xs->cs.lpCreateParams = mdi_cs;
805             }
806
807             *plparam = (LPARAM)xs;
808         }
809         return 1;
810     case WM_MDICREATE:
811         {
812             MDICREATESTRUCTW *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
813             if (!cs) return -1;
814             *cs = *(MDICREATESTRUCTW *)*plparam;
815             if (HIWORD(cs->szClass))
816             {
817                 UNICODE_STRING usBuffer;
818                 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)cs->szClass);
819                 cs->szClass = usBuffer.Buffer;
820             }
821             if (HIWORD(cs->szTitle))
822             {
823                 UNICODE_STRING usBuffer;
824                 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)cs->szTitle);
825                 cs->szTitle = usBuffer.Buffer;
826             }
827             *plparam = (LPARAM)cs;
828         }
829         return 1;
830
831 /* Listbox / Combobox */
832     case LB_ADDSTRING:
833     case LB_INSERTSTRING:
834     case LB_FINDSTRING:
835     case LB_FINDSTRINGEXACT:
836     case LB_SELECTSTRING:
837     case CB_ADDSTRING:
838     case CB_INSERTSTRING:
839     case CB_FINDSTRINGEXACT:
840     case CB_FINDSTRING:
841     case CB_SELECTSTRING:
842         if(!*plparam) return 0;
843         if ( WINPROC_TestLBForStr( hwnd, msg ))
844         {
845             UNICODE_STRING usBuffer;
846             RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)*plparam);
847             *plparam = (LPARAM)usBuffer.Buffer;
848         }
849         return (*plparam ? 1 : -1);
850
851     case LB_GETTEXT:                /* FIXME: fixed sized buffer */
852     case CB_GETLBTEXT:
853         if ( WINPROC_TestLBForStr( hwnd, msg ))
854         {
855             LPARAM *ptr = HeapAlloc( GetProcessHeap(), 0, 512 * sizeof(WCHAR) + sizeof(LPARAM) );
856             if (!ptr) return -1;
857             *ptr++ = *plparam;  /* Store previous lParam */
858             *plparam = (LPARAM)ptr;
859         }
860         return 1;
861
862 /* Multiline edit */
863     case EM_GETLINE:
864         { WORD len = (WORD)*plparam;
865           LPARAM *ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
866           if (!ptr) return -1;
867           *ptr++ = *plparam;  /* Store previous lParam */
868           *((WORD *) ptr) = len;   /* Store the length */
869           *plparam = (LPARAM)ptr;
870         }
871         return 1;
872
873     case WM_CHARTOITEM:
874     case WM_MENUCHAR:
875     case WM_CHAR:
876     case WM_DEADCHAR:
877     case WM_SYSCHAR:
878     case WM_SYSDEADCHAR:
879     case EM_SETPASSWORDCHAR:
880         *pwparam = map_wparam_char_AtoW( *pwparam, 1 );
881         return 0;
882
883     case WM_IME_CHAR:
884         *pwparam = map_wparam_char_AtoW( *pwparam, 2 );
885         return 0;
886
887     case WM_PAINTCLIPBOARD:
888     case WM_SIZECLIPBOARD:
889         FIXME_(msg)("message %s (0x%x) needs translation, please report\n", SPY_GetMsgName(msg, hwnd), msg );
890         return -1;
891     default:  /* No translation needed */
892         return 0;
893     }
894 }
895
896
897 /**********************************************************************
898  *           WINPROC_UnmapMsg32ATo32W
899  *
900  * Unmap a message that was mapped from Ansi to Unicode.
901  */
902 static LRESULT WINPROC_UnmapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
903                                          LRESULT result, WNDPROC dispatch )
904 {
905     switch(msg)
906     {
907     case WM_GETTEXT:
908     case WM_ASKCBFORMATNAME:
909         {
910             LPARAM *ptr = (LPARAM *)lParam - 1;
911             if (!wParam) result = 0;
912             else if (!(result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
913                                                     (LPSTR)*ptr, wParam, NULL, NULL )))
914             {
915                 ((LPSTR)*ptr)[wParam-1] = 0;
916                 result = wParam - 1;
917             }
918             else result--;  /* do not count terminating null */
919             HeapFree( GetProcessHeap(), 0, ptr );
920         }
921         break;
922     case WM_GETTEXTLENGTH:
923     case CB_GETLBTEXTLEN:
924     case LB_GETTEXTLEN:
925         if (result >= 0)
926         {
927             /* Determine respective GETTEXT message */
928             UINT msgGetText =
929               (msg == WM_GETTEXTLENGTH) ? WM_GETTEXT :
930               ((msg == CB_GETLBTEXTLEN) ? CB_GETLBTEXT : LB_GETTEXT);
931             /* wParam differs between the messages */
932             WPARAM wp = (msg == WM_GETTEXTLENGTH) ? (WPARAM)(result + 1) : wParam;
933
934             WCHAR* p = HeapAlloc (GetProcessHeap(), 0, (result + 1) * sizeof(WCHAR));
935
936             if (p)
937             {
938                 LRESULT n;
939
940                 if (dispatch)
941                     n = WINPROC_CallWndProc(dispatch, hwnd, msgGetText, wp, (LPARAM)p);
942                 else
943                     n = SendMessageW (hwnd, msgGetText, wp, (LPARAM)p);
944
945                 result = WideCharToMultiByte( CP_ACP, 0, p, n, NULL, 0, 0, NULL );
946                 HeapFree (GetProcessHeap(), 0, p);
947             }
948         }
949         break;
950     case WM_NCCREATE:
951     case WM_CREATE:
952         {
953             struct s
954             { CREATESTRUCTW cs;         /* new structure */
955               LPWSTR lpszName;          /* allocated Name */
956               LPWSTR lpszClass;         /* allocated Class */
957             };
958             struct s *xs = (struct s *)lParam;
959             HeapFree( GetProcessHeap(), 0, xs->lpszName );
960             HeapFree( GetProcessHeap(), 0, xs->lpszClass );
961
962             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
963             {
964                 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)xs->cs.lpCreateParams;
965                 if (HIWORD(mdi_cs->szTitle))
966                     HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szTitle);
967                 if (HIWORD(mdi_cs->szClass))
968                     HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szClass);
969                 HeapFree(GetProcessHeap(), 0, mdi_cs);
970             }
971             HeapFree( GetProcessHeap(), 0, xs );
972         }
973         break;
974
975     case WM_MDICREATE:
976         {
977             MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
978             if (HIWORD(cs->szTitle))
979                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
980             if (HIWORD(cs->szClass))
981                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
982             HeapFree( GetProcessHeap(), 0, cs );
983         }
984         break;
985
986     case WM_SETTEXT:
987     case WM_WININICHANGE:
988     case WM_DEVMODECHANGE:
989     case CB_DIR:
990     case LB_DIR:
991     case LB_ADDFILE:
992     case EM_REPLACESEL:
993         HeapFree( GetProcessHeap(), 0, (void *)lParam );
994         break;
995
996 /* Listbox / Combobox */
997     case LB_ADDSTRING:
998     case LB_INSERTSTRING:
999     case LB_FINDSTRING:
1000     case LB_FINDSTRINGEXACT:
1001     case LB_SELECTSTRING:
1002     case CB_ADDSTRING:
1003     case CB_INSERTSTRING:
1004     case CB_FINDSTRING:
1005     case CB_FINDSTRINGEXACT:
1006     case CB_SELECTSTRING:
1007         if ( WINPROC_TestLBForStr( hwnd, msg ))
1008           HeapFree( GetProcessHeap(), 0, (void *)lParam );
1009         break;
1010
1011     case LB_GETTEXT:
1012     case CB_GETLBTEXT:
1013         if ( WINPROC_TestLBForStr( hwnd, msg ))
1014         {
1015             LPARAM *ptr = (LPARAM *)lParam - 1;
1016             if (result >= 0)
1017                 result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
1018                                               (LPSTR)*ptr, 0x7fffffff, NULL, NULL ) - 1;
1019             HeapFree( GetProcessHeap(), 0, ptr );
1020         }
1021         break;
1022
1023 /* Multiline edit */
1024     case EM_GETLINE:
1025         {
1026             LPARAM * ptr = (LPARAM *)lParam - 1;  /* get the old lParam */
1027             WORD len = *(WORD *) lParam;
1028             result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, result,
1029                                           (LPSTR)*ptr, len, NULL, NULL );
1030             if (result < len) ((LPSTR)*ptr)[result] = 0;
1031             HeapFree( GetProcessHeap(), 0, ptr );
1032         }
1033         break;
1034     }
1035     return result;
1036 }
1037
1038
1039 static UINT convert_handle_16_to_32(HANDLE16 src, unsigned int flags)
1040 {
1041     HANDLE      dst;
1042     UINT        sz = GlobalSize16(src);
1043     LPSTR       ptr16, ptr32;
1044
1045     if (!(dst = GlobalAlloc(flags, sz)))
1046         return 0;
1047     ptr16 = GlobalLock16(src);
1048     ptr32 = GlobalLock(dst);
1049     if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr32, ptr16, sz);
1050     GlobalUnlock16(src);
1051     GlobalUnlock(dst);
1052
1053     return (UINT)dst;
1054 }
1055
1056 /**********************************************************************
1057  *           WINPROC_MapMsg16To32A
1058  *
1059  * Map a message from 16- to 32-bit Ansi.
1060  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1061  */
1062 INT WINPROC_MapMsg16To32A( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1063                              WPARAM *pwparam32, LPARAM *plparam )
1064 {
1065     *pmsg32 = (UINT)msg16;
1066     *pwparam32 = (WPARAM)wParam16;
1067     switch(msg16)
1068     {
1069     case WM_ACTIVATE:
1070     case WM_CHARTOITEM:
1071     case WM_COMMAND:
1072     case WM_VKEYTOITEM:
1073         *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1074         *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1075         return 0;
1076     case WM_HSCROLL:
1077     case WM_VSCROLL:
1078         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1079         *plparam   = (LPARAM)WIN_Handle32( HIWORD(*plparam) );
1080         return 0;
1081     case WM_CTLCOLOR:
1082         if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
1083         *pmsg32    = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
1084         *pwparam32 = (WPARAM)HDC_32(wParam16);
1085         *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1086         return 0;
1087     case WM_COMPAREITEM:
1088         {
1089             COMPAREITEMSTRUCT16* cis16 = MapSL(*plparam);
1090             COMPAREITEMSTRUCT *cis = HeapAlloc(GetProcessHeap(), 0, sizeof(*cis));
1091             if (!cis) return -1;
1092             cis->CtlType    = cis16->CtlType;
1093             cis->CtlID      = cis16->CtlID;
1094             cis->hwndItem   = WIN_Handle32( cis16->hwndItem );
1095             cis->itemID1    = cis16->itemID1;
1096             cis->itemData1  = cis16->itemData1;
1097             cis->itemID2    = cis16->itemID2;
1098             cis->itemData2  = cis16->itemData2;
1099             cis->dwLocaleId = 0;  /* FIXME */
1100             *plparam = (LPARAM)cis;
1101         }
1102         return 1;
1103     case WM_COPYDATA:
1104         {
1105             PCOPYDATASTRUCT16 pcds16 =  MapSL(*plparam);
1106             PCOPYDATASTRUCT pcds = HeapAlloc ( GetProcessHeap(), 0, sizeof(*pcds));
1107             pcds->dwData = pcds16->dwData;
1108             pcds->cbData = pcds16->cbData;
1109             pcds->lpData = MapSL( pcds16->lpData);
1110             *plparam = (LPARAM)pcds;
1111         }
1112         return 1;
1113     case WM_DELETEITEM:
1114         {
1115             DELETEITEMSTRUCT16* dis16 = MapSL(*plparam);
1116             DELETEITEMSTRUCT *dis = HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
1117             if (!dis) return -1;
1118             dis->CtlType  = dis16->CtlType;
1119             dis->CtlID    = dis16->CtlID;
1120             dis->hwndItem = WIN_Handle32( dis16->hwndItem );
1121             dis->itemData = dis16->itemData;
1122             *plparam = (LPARAM)dis;
1123         }
1124         return 1;
1125     case WM_MEASUREITEM:
1126         {
1127             MEASUREITEMSTRUCT16* mis16 = MapSL(*plparam);
1128             MEASUREITEMSTRUCT *mis = HeapAlloc(GetProcessHeap(), 0,
1129                                                 sizeof(*mis) + sizeof(LPARAM));
1130             if (!mis) return -1;
1131             mis->CtlType    = mis16->CtlType;
1132             mis->CtlID      = mis16->CtlID;
1133             mis->itemID     = mis16->itemID;
1134             mis->itemWidth  = mis16->itemWidth;
1135             mis->itemHeight = mis16->itemHeight;
1136             mis->itemData   = mis16->itemData;
1137             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
1138             *plparam = (LPARAM)mis;
1139         }
1140         return 1;
1141     case WM_DRAWITEM:
1142         {
1143             DRAWITEMSTRUCT16* dis16 = MapSL(*plparam);
1144             DRAWITEMSTRUCT *dis = HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
1145             if (!dis) return -1;
1146             dis->CtlType       = dis16->CtlType;
1147             dis->CtlID         = dis16->CtlID;
1148             dis->itemID        = dis16->itemID;
1149             dis->itemAction    = dis16->itemAction;
1150             dis->itemState     = dis16->itemState;
1151             dis->hwndItem      = (dis->CtlType == ODT_MENU) ? (HWND)HMENU_32(dis16->hwndItem)
1152                                                             : WIN_Handle32( dis16->hwndItem );
1153             dis->hDC           = HDC_32(dis16->hDC);
1154             dis->itemData      = dis16->itemData;
1155             dis->rcItem.left   = dis16->rcItem.left;
1156             dis->rcItem.top    = dis16->rcItem.top;
1157             dis->rcItem.right  = dis16->rcItem.right;
1158             dis->rcItem.bottom = dis16->rcItem.bottom;
1159             *plparam = (LPARAM)dis;
1160         }
1161         return 1;
1162     case WM_GETMINMAXINFO:
1163         {
1164             MINMAXINFO *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM));
1165             if (!mmi) return -1;
1166             MINMAXINFO16to32( MapSL(*plparam), mmi );
1167             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
1168             *plparam = (LPARAM)mmi;
1169         }
1170         return 1;
1171     case WM_GETTEXT:
1172     case WM_SETTEXT:
1173     case WM_WININICHANGE:
1174     case WM_DEVMODECHANGE:
1175     case WM_ASKCBFORMATNAME:
1176         *plparam = (LPARAM)MapSL(*plparam);
1177         return 0;
1178     case WM_MDICREATE:
1179         {
1180             MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1181             MDICREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1182             if (!cs) return -1;
1183             MDICREATESTRUCT16to32A( cs16, cs );
1184             cs->szTitle = MapSL(cs16->szTitle);
1185             cs->szClass = MapSL(cs16->szClass);
1186             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1187             *plparam = (LPARAM)cs;
1188         }
1189         return 1;
1190     case WM_MDIGETACTIVE:
1191         *plparam = (LPARAM)HeapAlloc( GetProcessHeap(), 0, sizeof(BOOL) );
1192         *(BOOL*)(*plparam) = 0;
1193         return 1;
1194     case WM_MDISETMENU:
1195         if(wParam16) *pmsg32=WM_MDIREFRESHMENU;
1196         *pwparam32 = (WPARAM)HMENU_32(LOWORD(*plparam));
1197         *plparam   = (LPARAM)HMENU_32(HIWORD(*plparam));
1198         return 0;
1199     case WM_MENUCHAR:
1200         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1201         *plparam   = (LPARAM)HMENU_32(HIWORD(*plparam));
1202         return 0;
1203     case WM_MENUSELECT:
1204         if((LOWORD(*plparam) & MF_POPUP) && (LOWORD(*plparam) != 0xFFFF))
1205         {
1206             HMENU hmenu=HMENU_32(HIWORD(*plparam));
1207             UINT Pos=MENU_FindSubMenu( &hmenu, HMENU_32(wParam16));
1208             if(Pos==0xFFFF) Pos=0; /* NO_SELECTED_ITEM */
1209             *pwparam32 = MAKEWPARAM( Pos, LOWORD(*plparam) );
1210         }
1211         else *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1212         *plparam   = (LPARAM)HMENU_32(HIWORD(*plparam));
1213         return 0;
1214     case WM_MDIACTIVATE:
1215         if( *plparam )
1216         {
1217             *pwparam32 = (WPARAM)WIN_Handle32( HIWORD(*plparam) );
1218             *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1219         }
1220         else /* message sent to MDI client */
1221             *pwparam32 = wParam16;
1222         return 0;
1223     case WM_NCCALCSIZE:
1224         {
1225             NCCALCSIZE_PARAMS16 *nc16;
1226             NCCALCSIZE_PARAMS *nc;
1227
1228             nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM) );
1229             if (!nc) return -1;
1230             nc16 = MapSL(*plparam);
1231             nc->rgrc[0].left   = nc16->rgrc[0].left;
1232             nc->rgrc[0].top    = nc16->rgrc[0].top;
1233             nc->rgrc[0].right  = nc16->rgrc[0].right;
1234             nc->rgrc[0].bottom = nc16->rgrc[0].bottom;
1235             if (wParam16)
1236             {
1237                 nc->lppos = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc->lppos) );
1238                 nc->rgrc[1].left   = nc16->rgrc[1].left;
1239                 nc->rgrc[1].top    = nc16->rgrc[1].top;
1240                 nc->rgrc[1].right  = nc16->rgrc[1].right;
1241                 nc->rgrc[1].bottom = nc16->rgrc[1].bottom;
1242                 nc->rgrc[2].left   = nc16->rgrc[2].left;
1243                 nc->rgrc[2].top    = nc16->rgrc[2].top;
1244                 nc->rgrc[2].right  = nc16->rgrc[2].right;
1245                 nc->rgrc[2].bottom = nc16->rgrc[2].bottom;
1246                 if (nc->lppos) WINDOWPOS16to32( MapSL(nc16->lppos), nc->lppos );
1247             }
1248             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
1249             *plparam = (LPARAM)nc;
1250         }
1251         return 1;
1252     case WM_NCCREATE:
1253     case WM_CREATE:
1254         {
1255             CREATESTRUCT16 *cs16 = MapSL(*plparam);
1256             CREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1257             if (!cs) return -1;
1258             CREATESTRUCT16to32A( cs16, cs );
1259             cs->lpszName  = MapSL(cs16->lpszName);
1260             cs->lpszClass = MapSL(cs16->lpszClass);
1261
1262             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1263             {
1264                 MDICREATESTRUCT16 *mdi_cs16;
1265                 MDICREATESTRUCTA *mdi_cs = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs));
1266                 if (!mdi_cs)
1267                 {
1268                     HeapFree(GetProcessHeap(), 0, cs);
1269                     return -1;
1270                 }
1271                 mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs16->lpCreateParams);
1272                 MDICREATESTRUCT16to32A(mdi_cs16, mdi_cs);
1273                 mdi_cs->szTitle = MapSL(mdi_cs16->szTitle);
1274                 mdi_cs->szClass = MapSL(mdi_cs16->szClass);
1275
1276                 cs->lpCreateParams = mdi_cs;
1277             }
1278             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1279             *plparam = (LPARAM)cs;
1280         }
1281         return 1;
1282     case WM_PARENTNOTIFY:
1283         if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
1284         {
1285             *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1286             *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1287         }
1288         return 0;
1289     case WM_WINDOWPOSCHANGING:
1290     case WM_WINDOWPOSCHANGED:
1291         {
1292             WINDOWPOS *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
1293             if (!wp) return -1;
1294             WINDOWPOS16to32( MapSL(*plparam), wp );
1295             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
1296             *plparam = (LPARAM)wp;
1297         }
1298         return 1;
1299     case WM_GETDLGCODE:
1300         if (*plparam)
1301         {
1302             LPMSG16 msg16 = MapSL(*plparam);
1303             LPMSG msg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1304
1305             if (!msg32) return -1;
1306             msg32->hwnd = WIN_Handle32( msg16->hwnd );
1307             msg32->message = msg16->message;
1308             msg32->wParam = msg16->wParam;
1309             msg32->lParam = msg16->lParam;
1310             msg32->time = msg16->time;
1311             msg32->pt.x = msg16->pt.x;
1312             msg32->pt.y = msg16->pt.y;
1313             *plparam = (LPARAM)msg32;
1314             return 1;
1315         }
1316         else return 0;
1317     case WM_NOTIFY:
1318         *plparam = (LPARAM)MapSL(*plparam);
1319         return 0;
1320     case WM_ACTIVATEAPP:
1321         /* We need this when SetActiveWindow sends a Sendmessage16() to
1322          * a 32bit window. Might be superflous with 32bit interprocess
1323          * message queues. */
1324         if (*plparam) *plparam = HTASK_32( *plparam );
1325         return 0;
1326     case WM_NEXTMENU:
1327         {
1328             MDINEXTMENU *next = HeapAlloc( GetProcessHeap(), 0, sizeof(*next) );
1329             if (!next) return -1;
1330             next->hmenuIn = (HMENU)*plparam;
1331             next->hmenuNext = 0;
1332             next->hwndNext = 0;
1333             *plparam = (LPARAM)next;
1334             return 1;
1335         }
1336     case WM_PAINTCLIPBOARD:
1337     case WM_SIZECLIPBOARD:
1338         FIXME_(msg)("message %04x needs translation\n",msg16 );
1339         return -1;
1340     case WM_DDE_INITIATE:
1341     case WM_DDE_TERMINATE:
1342     case WM_DDE_UNADVISE:
1343     case WM_DDE_REQUEST:
1344         *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1345         return 0;
1346     case WM_DDE_ADVISE:
1347     case WM_DDE_DATA:
1348     case WM_DDE_POKE:
1349         {
1350             HANDLE16    lo16;
1351             ATOM        hi;
1352             UINT lo32 = 0;
1353
1354             *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1355             lo16 = LOWORD(*plparam);
1356             hi = HIWORD(*plparam);
1357             if (lo16 && !(lo32 = convert_handle_16_to_32(lo16, GMEM_DDESHARE)))
1358                 return -1;
1359             *plparam = PackDDElParam(msg16, lo32, hi);
1360         }
1361         return 0; /* FIXME don't know how to free allocated memory (handle)  !! */
1362     case WM_DDE_ACK:
1363         {
1364             UINT        lo, hi;
1365             int         flag = 0;
1366             char        buf[2];
1367
1368             *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1369
1370             lo = LOWORD(*plparam);
1371             hi = HIWORD(*plparam);
1372
1373             if (GlobalGetAtomNameA(hi, buf, 2) > 0) flag |= 1;
1374             if (GlobalSize16(hi) != 0) flag |= 2;
1375             switch (flag)
1376             {
1377             case 0:
1378                 if (hi)
1379                 {
1380                     MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1381                     hi = 0;
1382                 }
1383                 break;
1384             case 1:
1385                 break; /* atom, nothing to do */
1386             case 3:
1387                 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
1388                 /* fall thru */
1389             case 2:
1390                 hi = convert_handle_16_to_32(hi, GMEM_DDESHARE);
1391                 break;
1392             }
1393             *plparam = PackDDElParam(WM_DDE_ACK, lo, hi);
1394         }
1395         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1396     case WM_DDE_EXECUTE:
1397         *plparam = convert_handle_16_to_32(*plparam, GMEM_DDESHARE);
1398         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1399     default:  /* No translation needed */
1400         return 0;
1401     }
1402 }
1403
1404
1405 /**********************************************************************
1406  *           WINPROC_UnmapMsg16To32A
1407  *
1408  * Unmap a message that was mapped from 16- to 32-bit Ansi.
1409  */
1410 static LRESULT WINPROC_UnmapMsg16To32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1411                                         LRESULT result )
1412 {
1413     switch(msg)
1414     {
1415     case WM_COMPAREITEM:
1416     case WM_DELETEITEM:
1417     case WM_DRAWITEM:
1418     case WM_COPYDATA:
1419         HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
1420         break;
1421     case WM_MEASUREITEM:
1422         {
1423             MEASUREITEMSTRUCT16 *mis16;
1424             MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam;
1425             lParam = *(LPARAM *)(mis + 1);
1426             mis16 = MapSL(lParam);
1427             mis16->itemWidth  = (UINT16)mis->itemWidth;
1428             mis16->itemHeight = (UINT16)mis->itemHeight;
1429             HeapFree( GetProcessHeap(), 0, mis );
1430         }
1431         break;
1432     case WM_GETMINMAXINFO:
1433         {
1434             MINMAXINFO *mmi = (MINMAXINFO *)lParam;
1435             lParam = *(LPARAM *)(mmi + 1);
1436             MINMAXINFO32to16( mmi, MapSL(lParam));
1437             HeapFree( GetProcessHeap(), 0, mmi );
1438         }
1439         break;
1440     case WM_MDICREATE:
1441         {
1442             MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1443             lParam = *(LPARAM *)(cs + 1);
1444             MDICREATESTRUCT32Ato16( cs, MapSL(lParam) );
1445             HeapFree( GetProcessHeap(), 0, cs );
1446         }
1447         break;
1448     case WM_MDIGETACTIVE:
1449         result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL *)lParam) );
1450         HeapFree( GetProcessHeap(), 0, (BOOL *)lParam );
1451         break;
1452     case WM_NCCALCSIZE:
1453         {
1454             NCCALCSIZE_PARAMS16 *nc16;
1455             NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lParam;
1456             lParam = *(LPARAM *)(nc + 1);
1457             nc16 = MapSL(lParam);
1458             nc16->rgrc[0].left   = nc->rgrc[0].left;
1459             nc16->rgrc[0].top    = nc->rgrc[0].top;
1460             nc16->rgrc[0].right  = nc->rgrc[0].right;
1461             nc16->rgrc[0].bottom = nc->rgrc[0].bottom;
1462             if (wParam)
1463             {
1464                 nc16->rgrc[1].left   = nc->rgrc[1].left;
1465                 nc16->rgrc[1].top    = nc->rgrc[1].top;
1466                 nc16->rgrc[1].right  = nc->rgrc[1].right;
1467                 nc16->rgrc[1].bottom = nc->rgrc[1].bottom;
1468                 nc16->rgrc[2].left   = nc->rgrc[2].left;
1469                 nc16->rgrc[2].top    = nc->rgrc[2].top;
1470                 nc16->rgrc[2].right  = nc->rgrc[2].right;
1471                 nc16->rgrc[2].bottom = nc->rgrc[2].bottom;
1472                 if (nc->lppos)
1473                 {
1474                     WINDOWPOS32to16( nc->lppos, MapSL(nc16->lppos));
1475                     HeapFree( GetProcessHeap(), 0, nc->lppos );
1476                 }
1477             }
1478             HeapFree( GetProcessHeap(), 0, nc );
1479         }
1480         break;
1481     case WM_NCCREATE:
1482     case WM_CREATE:
1483         {
1484             CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1485             lParam = *(LPARAM *)(cs + 1);
1486             CREATESTRUCT32Ato16( cs, MapSL(lParam) );
1487
1488             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1489                 HeapFree(GetProcessHeap(), 0, cs->lpCreateParams);
1490
1491             HeapFree( GetProcessHeap(), 0, cs );
1492         }
1493         break;
1494     case WM_WINDOWPOSCHANGING:
1495     case WM_WINDOWPOSCHANGED:
1496         {
1497             WINDOWPOS *wp = (WINDOWPOS *)lParam;
1498             lParam = *(LPARAM *)(wp + 1);
1499             WINDOWPOS32to16(wp, MapSL(lParam));
1500             HeapFree( GetProcessHeap(), 0, wp );
1501         }
1502         break;
1503     case WM_GETDLGCODE:
1504         if (lParam)
1505         {
1506             LPMSG msg32 = (LPMSG)lParam;
1507             HeapFree( GetProcessHeap(), 0, msg32 );
1508         }
1509         break;
1510     case WM_NEXTMENU:
1511         {
1512             MDINEXTMENU *next = (MDINEXTMENU *)lParam;
1513             result = MAKELONG( HMENU_16(next->hmenuNext), HWND_16(next->hwndNext) );
1514             HeapFree( GetProcessHeap(), 0, next );
1515         }
1516         break;
1517     }
1518     return result;
1519 }
1520
1521
1522 /**********************************************************************
1523  *           WINPROC_MapMsg16To32W
1524  *
1525  * Map a message from 16- to 32-bit Unicode.
1526  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1527  */
1528 static INT WINPROC_MapMsg16To32W( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1529                                   WPARAM *pwparam32, LPARAM *plparam )
1530 {
1531     *pmsg32=(UINT)msg16;
1532     *pwparam32 = (WPARAM)wParam16;
1533     switch(msg16)
1534     {
1535     case WM_GETTEXT:
1536     case WM_SETTEXT:
1537     case WM_WININICHANGE:
1538     case WM_DEVMODECHANGE:
1539     case WM_ASKCBFORMATNAME:
1540         *plparam = (LPARAM)MapSL(*plparam);
1541         return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, pwparam32, plparam );
1542     case WM_GETTEXTLENGTH:
1543     case CB_GETLBTEXTLEN:
1544     case LB_GETTEXTLEN:
1545         return 1;  /* need to map result */
1546     case WM_NCCREATE:
1547     case WM_CREATE:
1548         {
1549             CREATESTRUCT16 *cs16 = MapSL(*plparam);
1550             CREATESTRUCTW *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1551             if (!cs) return -1;
1552             CREATESTRUCT16to32A( cs16, (CREATESTRUCTA *)cs );
1553             cs->lpszName  = map_str_16_to_32W(cs16->lpszName);
1554             cs->lpszClass = map_str_16_to_32W(cs16->lpszClass);
1555
1556             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1557             {
1558                 MDICREATESTRUCT16 *mdi_cs16;
1559                 MDICREATESTRUCTW *mdi_cs = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs));
1560                 if (!mdi_cs)
1561                 {
1562                     HeapFree(GetProcessHeap(), 0, cs);
1563                     return -1;
1564                 }
1565                 mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs16->lpCreateParams);
1566                 MDICREATESTRUCT16to32A(mdi_cs16, (MDICREATESTRUCTA *)mdi_cs);
1567                 mdi_cs->szTitle = map_str_16_to_32W(mdi_cs16->szTitle);
1568                 mdi_cs->szClass = map_str_16_to_32W(mdi_cs16->szClass);
1569
1570                 cs->lpCreateParams = mdi_cs;
1571             }
1572             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1573             *plparam = (LPARAM)cs;
1574         }
1575         return 1;
1576     case WM_MDICREATE:
1577         {
1578             MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1579             MDICREATESTRUCTW *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1580             if (!cs) return -1;
1581             MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCTA *)cs );
1582             cs->szTitle = map_str_16_to_32W(cs16->szTitle);
1583             cs->szClass = map_str_16_to_32W(cs16->szClass);
1584             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1585             *plparam = (LPARAM)cs;
1586         }
1587         return 1;
1588     case WM_GETDLGCODE:
1589         if (*plparam)
1590         {
1591             LPMSG16 msg16 = MapSL(*plparam);
1592             LPMSG msg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1593
1594             if (!msg32) return -1;
1595             msg32->hwnd = WIN_Handle32( msg16->hwnd );
1596             msg32->message = msg16->message;
1597             msg32->wParam = msg16->wParam;
1598             msg32->lParam = msg16->lParam;
1599             msg32->time = msg16->time;
1600             msg32->pt.x = msg16->pt.x;
1601             msg32->pt.y = msg16->pt.y;
1602             switch(msg32->message)
1603             {
1604             case WM_CHAR:
1605             case WM_DEADCHAR:
1606             case WM_SYSCHAR:
1607             case WM_SYSDEADCHAR:
1608                 msg32->wParam = map_wparam_char_AtoW( msg16->wParam, 1 );
1609                 break;
1610             }
1611             *plparam = (LPARAM)msg32;
1612             return 1;
1613         }
1614         else return 0;
1615
1616     case WM_CHARTOITEM:
1617         *pwparam32 = MAKEWPARAM( map_wparam_char_AtoW( wParam16, 1 ), HIWORD(*plparam) );
1618         *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1619         return 0;
1620     case WM_MENUCHAR:
1621         *pwparam32 = MAKEWPARAM( map_wparam_char_AtoW( wParam16, 1 ), LOWORD(*plparam) );
1622         *plparam   = (LPARAM)HMENU_32(HIWORD(*plparam));
1623         return 0;
1624     case WM_CHAR:
1625     case WM_DEADCHAR:
1626     case WM_SYSCHAR:
1627     case WM_SYSDEADCHAR:
1628         *pwparam32 = map_wparam_char_AtoW( wParam16, 1 );
1629         return 0;
1630     case WM_IME_CHAR:
1631         *pwparam32 = map_wparam_char_AtoW( wParam16, 2 );
1632         return 0;
1633
1634     default:  /* No Unicode translation needed */
1635         return WINPROC_MapMsg16To32A( hwnd, msg16, wParam16, pmsg32,
1636                                       pwparam32, plparam );
1637     }
1638 }
1639
1640
1641 /**********************************************************************
1642  *           WINPROC_UnmapMsg16To32W
1643  *
1644  * Unmap a message that was mapped from 16- to 32-bit Unicode.
1645  */
1646 static LRESULT WINPROC_UnmapMsg16To32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1647                                         LRESULT result, WNDPROC dispatch )
1648 {
1649     switch(msg)
1650     {
1651     case WM_GETTEXT:
1652     case WM_SETTEXT:
1653     case WM_GETTEXTLENGTH:
1654     case CB_GETLBTEXTLEN:
1655     case LB_GETTEXTLEN:
1656     case WM_ASKCBFORMATNAME:
1657         return WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result, dispatch );
1658     case WM_NCCREATE:
1659     case WM_CREATE:
1660         {
1661             CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
1662             lParam = *(LPARAM *)(cs + 1);
1663             CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs, MapSL(lParam) );
1664             unmap_str_16_to_32W( cs->lpszName );
1665             unmap_str_16_to_32W( cs->lpszClass );
1666
1667             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1668             {
1669                 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)cs->lpCreateParams;
1670                 unmap_str_16_to_32W( mdi_cs->szTitle );
1671                 unmap_str_16_to_32W( mdi_cs->szClass );
1672                 HeapFree(GetProcessHeap(), 0, cs->lpCreateParams);
1673             }
1674             HeapFree( GetProcessHeap(), 0, cs );
1675         }
1676         break;
1677     case WM_MDICREATE:
1678         {
1679             MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
1680             lParam = *(LPARAM *)(cs + 1);
1681             MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs, MapSL(lParam) );
1682             unmap_str_16_to_32W( cs->szTitle );
1683             unmap_str_16_to_32W( cs->szClass );
1684             HeapFree( GetProcessHeap(), 0, cs );
1685         }
1686         break;
1687     case WM_GETDLGCODE:
1688         if (lParam)
1689         {
1690             LPMSG msg32 = (LPMSG)lParam;
1691             HeapFree( GetProcessHeap(), 0, msg32 );
1692         }
1693         break;
1694     default:
1695         return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1696     }
1697     return result;
1698 }
1699
1700 static HANDLE16 convert_handle_32_to_16(UINT src, unsigned int flags)
1701 {
1702     HANDLE16    dst;
1703     UINT        sz = GlobalSize((HANDLE)src);
1704     LPSTR       ptr16, ptr32;
1705
1706     if (!(dst = GlobalAlloc16(flags, sz)))
1707         return 0;
1708     ptr32 = GlobalLock((HANDLE)src);
1709     ptr16 = GlobalLock16(dst);
1710     if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr16, ptr32, sz);
1711     GlobalUnlock((HANDLE)src);
1712     GlobalUnlock16(dst);
1713
1714     return dst;
1715 }
1716
1717
1718 /**********************************************************************
1719  *           WINPROC_MapMsg32ATo16
1720  *
1721  * Map a message from 32-bit Ansi to 16-bit.
1722  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1723  */
1724 INT WINPROC_MapMsg32ATo16( HWND hwnd, UINT msg32, WPARAM wParam32,
1725                              UINT16 *pmsg16, WPARAM16 *pwparam16,
1726                              LPARAM *plparam )
1727 {
1728     *pmsg16 = (UINT16)msg32;
1729     *pwparam16 = (WPARAM16)LOWORD(wParam32);
1730     switch(msg32)
1731     {
1732     case SBM_SETRANGE:
1733         *pmsg16 = SBM_SETRANGE16;
1734         *plparam = MAKELPARAM(wParam32, *plparam);
1735         *pwparam16 = 0;
1736         return 0;
1737
1738     case SBM_GETRANGE:
1739         *pmsg16 = SBM_GETRANGE16;
1740         return 1;
1741
1742     case BM_GETCHECK:
1743     case BM_SETCHECK:
1744     case BM_GETSTATE:
1745     case BM_SETSTATE:
1746     case BM_SETSTYLE:
1747         *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK);
1748         return 0;
1749
1750     case EM_GETSEL:
1751     case EM_GETRECT:
1752     case EM_SETRECT:
1753     case EM_SETRECTNP:
1754     case EM_SCROLL:
1755     case EM_LINESCROLL:
1756     case EM_SCROLLCARET:
1757     case EM_GETMODIFY:
1758     case EM_SETMODIFY:
1759     case EM_GETLINECOUNT:
1760     case EM_LINEINDEX:
1761     case EM_SETHANDLE:
1762     case EM_GETHANDLE:
1763     case EM_GETTHUMB:
1764     case EM_LINELENGTH:
1765     case EM_REPLACESEL:
1766     case EM_GETLINE:
1767     case EM_LIMITTEXT:
1768     case EM_CANUNDO:
1769     case EM_UNDO:
1770     case EM_FMTLINES:
1771     case EM_LINEFROMCHAR:
1772     case EM_SETTABSTOPS:
1773     case EM_SETPASSWORDCHAR:
1774     case EM_EMPTYUNDOBUFFER:
1775     case EM_GETFIRSTVISIBLELINE:
1776     case EM_SETREADONLY:
1777     case EM_SETWORDBREAKPROC:
1778     case EM_GETWORDBREAKPROC:
1779     case EM_GETPASSWORDCHAR:
1780         *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL);
1781         return 0;
1782
1783     case LB_CARETOFF:
1784     case LB_CARETON:
1785     case LB_DELETESTRING:
1786     case LB_GETANCHORINDEX:
1787     case LB_GETCARETINDEX:
1788     case LB_GETCOUNT:
1789     case LB_GETCURSEL:
1790     case LB_GETHORIZONTALEXTENT:
1791     case LB_GETITEMDATA:
1792     case LB_GETITEMHEIGHT:
1793     case LB_GETSEL:
1794     case LB_GETSELCOUNT:
1795     case LB_GETTEXTLEN:
1796     case LB_GETTOPINDEX:
1797     case LB_RESETCONTENT:
1798     case LB_SELITEMRANGE:
1799     case LB_SELITEMRANGEEX:
1800     case LB_SETANCHORINDEX:
1801     case LB_SETCARETINDEX:
1802     case LB_SETCOLUMNWIDTH:
1803     case LB_SETCURSEL:
1804     case LB_SETHORIZONTALEXTENT:
1805     case LB_SETITEMDATA:
1806     case LB_SETITEMHEIGHT:
1807     case LB_SETSEL:
1808     case LB_SETTOPINDEX:
1809         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1810         return 0;
1811     case CB_DELETESTRING:
1812     case CB_GETCOUNT:
1813     case CB_GETLBTEXTLEN:
1814     case CB_LIMITTEXT:
1815     case CB_RESETCONTENT:
1816     case CB_SETEDITSEL:
1817     case CB_GETCURSEL:
1818     case CB_SETCURSEL:
1819     case CB_SHOWDROPDOWN:
1820     case CB_SETITEMDATA:
1821     case CB_SETITEMHEIGHT:
1822     case CB_GETITEMHEIGHT:
1823     case CB_SETEXTENDEDUI:
1824     case CB_GETEXTENDEDUI:
1825     case CB_GETDROPPEDSTATE:
1826         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1827         return 0;
1828     case CB_GETEDITSEL:
1829         *pmsg16 = CB_GETEDITSEL16;
1830         return 1;
1831
1832     case LB_ADDSTRING:
1833     case LB_FINDSTRING:
1834     case LB_FINDSTRINGEXACT:
1835     case LB_INSERTSTRING:
1836     case LB_SELECTSTRING:
1837     case LB_DIR:
1838     case LB_ADDFILE:
1839         *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1840         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1841         return 1;
1842
1843     case CB_ADDSTRING:
1844     case CB_FINDSTRING:
1845     case CB_FINDSTRINGEXACT:
1846     case CB_INSERTSTRING:
1847     case CB_SELECTSTRING:
1848     case CB_DIR:
1849         *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1850         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1851         return 1;
1852
1853     case LB_GETITEMRECT:
1854         {
1855             RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1856             if (!rect) return -1;
1857             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
1858             *plparam = MapLS( rect );
1859         }
1860         *pmsg16 = LB_GETITEMRECT16;
1861         return 1;
1862     case LB_GETSELITEMS:
1863         {
1864             LPARAM *items; /* old LPARAM first, then *pwparam16 x INT16 entries */
1865
1866             *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1867             if (!(items = HeapAlloc( GetProcessHeap(), 0,
1868                                      *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
1869             *items++ = *plparam;  /* Store the previous lParam */
1870             *plparam = MapLS( items );
1871         }
1872         *pmsg16 = LB_GETSELITEMS16;
1873         return 1;
1874     case LB_SETTABSTOPS:
1875         if (wParam32)
1876         {
1877             INT i;
1878             LPINT16 stops;
1879             *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1880             if (!(stops = HeapAlloc( GetProcessHeap(), 0,
1881                                      *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
1882             for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT)*plparam+i);
1883             *plparam = MapLS( stops );
1884             return 1;
1885         }
1886         *pmsg16 = LB_SETTABSTOPS16;
1887         return 0;
1888
1889     case CB_GETDROPPEDCONTROLRECT:
1890         {
1891             RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1892             if (!rect) return -1;
1893             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
1894             *plparam = (LPARAM)MapLS(rect);
1895         }
1896         *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
1897         return 1;
1898
1899     case LB_GETTEXT:
1900         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1901         *pmsg16 = LB_GETTEXT16;
1902         return 1;
1903
1904     case CB_GETLBTEXT:
1905         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1906         *pmsg16 = CB_GETLBTEXT16;
1907         return 1;
1908
1909     case EM_SETSEL:
1910         *pwparam16 = 0;
1911         *plparam = MAKELONG( (INT16)(INT)wParam32, (INT16)*plparam );
1912         *pmsg16 = EM_SETSEL16;
1913         return 0;
1914
1915     case WM_ACTIVATE:
1916     case WM_CHARTOITEM:
1917     case WM_COMMAND:
1918     case WM_VKEYTOITEM:
1919         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
1920         return 0;
1921     case WM_HSCROLL:
1922     case WM_VSCROLL:
1923         *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
1924         return 0;
1925     case WM_COPYDATA:
1926         {
1927             PCOPYDATASTRUCT pcds32 = (PCOPYDATASTRUCT) *plparam;
1928             PCOPYDATASTRUCT16 pcds = HeapAlloc( GetProcessHeap(), 0, sizeof( *pcds));
1929             pcds->dwData = pcds32->dwData;
1930             pcds->cbData = pcds32->cbData;
1931             pcds->lpData = MapLS( pcds32->lpData);
1932             *plparam = MapLS( pcds );
1933         }
1934         return 1;
1935     case WM_CTLCOLORMSGBOX:
1936     case WM_CTLCOLOREDIT:
1937     case WM_CTLCOLORLISTBOX:
1938     case WM_CTLCOLORBTN:
1939     case WM_CTLCOLORDLG:
1940     case WM_CTLCOLORSCROLLBAR:
1941     case WM_CTLCOLORSTATIC:
1942         *pmsg16  = WM_CTLCOLOR;
1943         *plparam = MAKELPARAM( (HWND16)*plparam,
1944                                (WORD)msg32 - WM_CTLCOLORMSGBOX );
1945         return 0;
1946     case WM_COMPAREITEM:
1947         {
1948             COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)*plparam;
1949             COMPAREITEMSTRUCT16 *cis = HeapAlloc( GetProcessHeap(), 0, sizeof(COMPAREITEMSTRUCT16));
1950             if (!cis) return -1;
1951             cis->CtlType    = (UINT16)cis32->CtlType;
1952             cis->CtlID      = (UINT16)cis32->CtlID;
1953             cis->hwndItem   = HWND_16( cis32->hwndItem );
1954             cis->itemID1    = (UINT16)cis32->itemID1;
1955             cis->itemData1  = cis32->itemData1;
1956             cis->itemID2    = (UINT16)cis32->itemID2;
1957             cis->itemData2  = cis32->itemData2;
1958             *plparam = MapLS( cis );
1959         }
1960         return 1;
1961     case WM_DELETEITEM:
1962         {
1963             DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)*plparam;
1964             DELETEITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DELETEITEMSTRUCT16) );
1965             if (!dis) return -1;
1966             dis->CtlType  = (UINT16)dis32->CtlType;
1967             dis->CtlID    = (UINT16)dis32->CtlID;
1968             dis->itemID   = (UINT16)dis32->itemID;
1969             dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem)
1970                                                        : HWND_16( dis32->hwndItem );
1971             dis->itemData = dis32->itemData;
1972             *plparam = MapLS( dis );
1973         }
1974         return 1;
1975     case WM_DRAWITEM:
1976         {
1977             DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)*plparam;
1978             DRAWITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DRAWITEMSTRUCT16) );
1979             if (!dis) return -1;
1980             dis->CtlType       = (UINT16)dis32->CtlType;
1981             dis->CtlID         = (UINT16)dis32->CtlID;
1982             dis->itemID        = (UINT16)dis32->itemID;
1983             dis->itemAction    = (UINT16)dis32->itemAction;
1984             dis->itemState     = (UINT16)dis32->itemState;
1985             dis->hwndItem      = HWND_16( dis32->hwndItem );
1986             dis->hDC           = HDC_16(dis32->hDC);
1987             dis->itemData      = dis32->itemData;
1988             dis->rcItem.left   = dis32->rcItem.left;
1989             dis->rcItem.top    = dis32->rcItem.top;
1990             dis->rcItem.right  = dis32->rcItem.right;
1991             dis->rcItem.bottom = dis32->rcItem.bottom;
1992             *plparam = MapLS( dis );
1993         }
1994         return 1;
1995     case WM_MEASUREITEM:
1996         {
1997             MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)*plparam;
1998             MEASUREITEMSTRUCT16 *mis = HeapAlloc( GetProcessHeap(), 0, sizeof(*mis)+sizeof(LPARAM));
1999             if (!mis) return -1;
2000             mis->CtlType    = (UINT16)mis32->CtlType;
2001             mis->CtlID      = (UINT16)mis32->CtlID;
2002             mis->itemID     = (UINT16)mis32->itemID;
2003             mis->itemWidth  = (UINT16)mis32->itemWidth;
2004             mis->itemHeight = (UINT16)mis32->itemHeight;
2005             mis->itemData   = mis32->itemData;
2006             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
2007             *plparam = MapLS( mis );
2008         }
2009         return 1;
2010     case WM_GETMINMAXINFO:
2011         {
2012             MINMAXINFO16 *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM) );
2013             if (!mmi) return -1;
2014             MINMAXINFO32to16( (MINMAXINFO *)*plparam, mmi );
2015             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
2016             *plparam = MapLS( mmi );
2017         }
2018         return 1;
2019     case WM_GETTEXT:
2020     case WM_ASKCBFORMATNAME:
2021         {
2022             LPARAM *str; /* store LPARAM, then *pwparam16 char space */
2023             *pwparam16 = (WPARAM16)min( wParam32, 0xff80 ); /* Must be < 64K */
2024             if (!(str = HeapAlloc( GetProcessHeap(), 0, *pwparam16 + sizeof(LPARAM)))) return -1;
2025             *str++ = *plparam;  /* Store the previous lParam */
2026             *plparam = MapLS( str );
2027         }
2028         return 1;
2029     case WM_MDICREATE:
2030         {
2031             MDICREATESTRUCT16 *cs;
2032             MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)*plparam;
2033
2034             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2035             MDICREATESTRUCT32Ato16( cs32, cs );
2036             cs->szTitle = MapLS( cs32->szTitle );
2037             cs->szClass = MapLS( cs32->szClass );
2038             *plparam = MapLS( cs );
2039         }
2040         return 1;
2041     case WM_MDIGETACTIVE:
2042         return 1;
2043     case WM_MDISETMENU:
2044         *plparam   = MAKELPARAM( (HMENU16)LOWORD(wParam32),
2045                                  (HMENU16)LOWORD(*plparam) );
2046         *pwparam16 = (*plparam == 0);
2047         return 0;
2048     case WM_MENUSELECT:
2049         if(HIWORD(wParam32) & MF_POPUP)
2050         {
2051             HMENU hmenu;
2052             if (((UINT)HIWORD(wParam32) != 0xFFFF) || (*plparam))
2053             {
2054                 if((hmenu = GetSubMenu((HMENU)*plparam, *pwparam16)))
2055                     *pwparam16=HMENU_16(hmenu);
2056             }
2057         }
2058         /* fall through */
2059     case WM_MENUCHAR:
2060         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2061         return 0;
2062     case WM_MDIACTIVATE:
2063         if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
2064         {
2065             *pwparam16 = ((HWND)*plparam == hwnd);
2066             *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
2067                                    (HWND16)LOWORD(wParam32) );
2068         }
2069         else
2070         {
2071             *pwparam16 = HWND_16( (HWND)wParam32 );
2072             *plparam = 0;
2073         }
2074         return 0;
2075     case WM_NCCALCSIZE:
2076         {
2077             NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)*plparam;
2078             NCCALCSIZE_PARAMS16 *nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM));
2079             if (!nc) return -1;
2080
2081             nc->rgrc[0].left   = nc32->rgrc[0].left;
2082             nc->rgrc[0].top    = nc32->rgrc[0].top;
2083             nc->rgrc[0].right  = nc32->rgrc[0].right;
2084             nc->rgrc[0].bottom = nc32->rgrc[0].bottom;
2085             if (wParam32)
2086             {
2087                 WINDOWPOS16 *wp;
2088                 nc->rgrc[1].left   = nc32->rgrc[1].left;
2089                 nc->rgrc[1].top    = nc32->rgrc[1].top;
2090                 nc->rgrc[1].right  = nc32->rgrc[1].right;
2091                 nc->rgrc[1].bottom = nc32->rgrc[1].bottom;
2092                 nc->rgrc[2].left   = nc32->rgrc[2].left;
2093                 nc->rgrc[2].top    = nc32->rgrc[2].top;
2094                 nc->rgrc[2].right  = nc32->rgrc[2].right;
2095                 nc->rgrc[2].bottom = nc32->rgrc[2].bottom;
2096                 if (!(wp = HeapAlloc( GetProcessHeap(), 0, sizeof(WINDOWPOS16) )))
2097                 {
2098                     HeapFree( GetProcessHeap(), 0, nc );
2099                     return -1;
2100                 }
2101                 WINDOWPOS32to16( nc32->lppos, wp );
2102                 nc->lppos = MapLS( wp );
2103             }
2104             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
2105             *plparam = MapLS( nc );
2106         }
2107         return 1;
2108     case WM_NCCREATE:
2109     case WM_CREATE:
2110         {
2111             CREATESTRUCT16 *cs;
2112             CREATESTRUCTA *cs32 = (CREATESTRUCTA *)*plparam;
2113
2114             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2115             CREATESTRUCT32Ato16( cs32, cs );
2116             cs->lpszName  = MapLS( cs32->lpszName );
2117             cs->lpszClass = MapLS( cs32->lpszClass );
2118
2119             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2120             {
2121                 MDICREATESTRUCT16 *mdi_cs16;
2122                 MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs32->lpCreateParams;
2123                 mdi_cs16 = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs16));
2124                 if (!mdi_cs16)
2125                 {
2126                     HeapFree(GetProcessHeap(), 0, cs);
2127                     return -1;
2128                 }
2129                 MDICREATESTRUCT32Ato16(mdi_cs, mdi_cs16);
2130                 mdi_cs16->szTitle = MapLS( mdi_cs->szTitle );
2131                 mdi_cs16->szClass = MapLS( mdi_cs->szClass );
2132                 cs->lpCreateParams = MapLS( mdi_cs16 );
2133             }
2134             *plparam = MapLS( cs );
2135         }
2136         return 1;
2137     case WM_PARENTNOTIFY:
2138         if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
2139             *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
2140         /* else nothing to do */
2141         return 0;
2142     case WM_NOTIFY:
2143         *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
2144         return 1;
2145     case WM_SETTEXT:
2146     case WM_WININICHANGE:
2147     case WM_DEVMODECHANGE:
2148         *plparam = MapLS( (LPSTR)*plparam );
2149         return 1;
2150     case WM_WINDOWPOSCHANGING:
2151     case WM_WINDOWPOSCHANGED:
2152         {
2153             WINDOWPOS16 *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
2154             if (!wp) return -1;
2155             WINDOWPOS32to16( (WINDOWPOS *)*plparam, wp );
2156             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
2157             *plparam = MapLS( wp );
2158         }
2159         return 1;
2160     case WM_GETDLGCODE:
2161          if (*plparam) {
2162             LPMSG msg32 = (LPMSG) *plparam;
2163             LPMSG16 msg16 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG16) );
2164
2165             if (!msg16) return -1;
2166             msg16->hwnd = HWND_16( msg32->hwnd );
2167             msg16->message = msg32->message;
2168             msg16->wParam = msg32->wParam;
2169             msg16->lParam = msg32->lParam;
2170             msg16->time = msg32->time;
2171             msg16->pt.x = msg32->pt.x;
2172             msg16->pt.y = msg32->pt.y;
2173             *plparam = MapLS( msg16 );
2174             return 1;
2175         }
2176         return 0;
2177
2178     case WM_ACTIVATEAPP:
2179         if (*plparam) *plparam = HTASK_16( (HANDLE)*plparam );
2180         return 0;
2181     case WM_NEXTMENU:
2182         {
2183             MDINEXTMENU *next = (MDINEXTMENU *)*plparam;
2184             *plparam = (LPARAM)next->hmenuIn;
2185             return 1;
2186         }
2187     case WM_PAINT:
2188         if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON ))
2189         {
2190             *pmsg16 = WM_PAINTICON;
2191             *pwparam16 = 1;
2192         }
2193         return 0;
2194     case WM_ERASEBKGND:
2195         if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON ))
2196             *pmsg16 = WM_ICONERASEBKGND;
2197         return 0;
2198     case WM_PAINTCLIPBOARD:
2199     case WM_SIZECLIPBOARD:
2200         FIXME_(msg)("message %04x needs translation\n", msg32 );
2201         return -1;
2202     /* following messages should not be sent to 16-bit apps */
2203     case WM_SIZING:
2204     case WM_MOVING:
2205     case WM_CAPTURECHANGED:
2206     case WM_STYLECHANGING:
2207     case WM_STYLECHANGED:
2208         return -1;
2209     case WM_DDE_INITIATE:
2210     case WM_DDE_TERMINATE:
2211     case WM_DDE_UNADVISE:
2212     case WM_DDE_REQUEST:
2213         *pwparam16 = HWND_16((HWND)wParam32);
2214         return 0;
2215     case WM_DDE_ADVISE:
2216     case WM_DDE_DATA:
2217     case WM_DDE_POKE:
2218         {
2219             UINT_PTR lo32, hi;
2220             HANDLE16    lo16 = 0;
2221
2222             *pwparam16 = HWND_16((HWND)wParam32);
2223             UnpackDDElParam(msg32, *plparam, &lo32, &hi);
2224             if (lo32 && !(lo16 = convert_handle_32_to_16(lo32, GMEM_DDESHARE)))
2225                 return -1;
2226             *plparam = MAKELPARAM(lo16, hi);
2227         }
2228         return 0; /* FIXME don't know how to free allocated memory (handle)  !! */
2229     case WM_DDE_ACK:
2230         {
2231             UINT_PTR    lo, hi;
2232             int         flag = 0;
2233             char        buf[2];
2234
2235             *pwparam16 = HWND_16((HWND)wParam32);
2236
2237             UnpackDDElParam(msg32, *plparam, &lo, &hi);
2238
2239             if (GlobalGetAtomNameA((ATOM)hi, buf, sizeof(buf)) > 0) flag |= 1;
2240             if (GlobalSize((HANDLE)hi) != 0) flag |= 2;
2241             switch (flag)
2242             {
2243             case 0:
2244                 if (hi)
2245                 {
2246                     MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
2247                     hi = 0;
2248                 }
2249                 break;
2250             case 1:
2251                 break; /* atom, nothing to do */
2252             case 3:
2253                 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
2254                 /* fall thru */
2255             case 2:
2256                 hi = convert_handle_32_to_16(hi, GMEM_DDESHARE);
2257                 break;
2258             }
2259             *plparam = MAKELPARAM(lo, hi);
2260         }
2261         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2262     case WM_DDE_EXECUTE:
2263         *plparam = convert_handle_32_to_16(*plparam, GMEM_DDESHARE);
2264         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2265     default:  /* No translation needed */
2266         return 0;
2267     }
2268 }
2269
2270
2271 /**********************************************************************
2272  *           WINPROC_UnmapMsg32ATo16
2273  *
2274  * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
2275  */
2276 static void WINPROC_UnmapMsg32ATo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2277                                      WPARAM16 wParam16, LPARAM lParam16, LRESULT *result )
2278 {
2279     switch(msg)
2280     {
2281     case SBM_GETRANGE:
2282         *(LPINT)wParam = LOWORD(*result);
2283         *(LPINT)lParam = HIWORD(*result);
2284         break;
2285
2286     case LB_ADDFILE:
2287     case LB_ADDSTRING:
2288     case LB_DIR:
2289     case LB_FINDSTRING:
2290     case LB_FINDSTRINGEXACT:
2291     case LB_INSERTSTRING:
2292     case LB_SELECTSTRING:
2293     case LB_GETTEXT:
2294     case CB_ADDSTRING:
2295     case CB_FINDSTRING:
2296     case CB_FINDSTRINGEXACT:
2297     case CB_INSERTSTRING:
2298     case CB_SELECTSTRING:
2299     case CB_DIR:
2300     case CB_GETLBTEXT:
2301     case WM_SETTEXT:
2302     case WM_WININICHANGE:
2303     case WM_DEVMODECHANGE:
2304         UnMapLS( (SEGPTR)lParam16 );
2305         break;
2306     case LB_SETTABSTOPS:
2307     case WM_COMPAREITEM:
2308     case WM_DELETEITEM:
2309     case WM_DRAWITEM:
2310         {
2311             void *ptr = MapSL( lParam16 );
2312             UnMapLS( lParam16 );
2313             HeapFree( GetProcessHeap(), 0, ptr );
2314         }
2315         break;
2316     case WM_COPYDATA:
2317         {
2318             PCOPYDATASTRUCT16 pcds = MapSL( lParam16 );
2319             UnMapLS( lParam16 );
2320             UnMapLS( pcds->lpData );
2321             HeapFree( GetProcessHeap(), 0, pcds );
2322         }
2323         break;
2324     case CB_GETDROPPEDCONTROLRECT:
2325     case LB_GETITEMRECT:
2326         {
2327             RECT *r32;
2328             RECT16 *rect = MapSL(lParam16);
2329             UnMapLS( lParam16 );
2330             lParam16 = *(LPARAM *)(rect + 1);
2331             r32 = (RECT *)lParam16;
2332             r32->left   = rect->left;
2333             r32->top    = rect->top;
2334             r32->right  = rect->right;
2335             r32->bottom = rect->bottom;
2336             HeapFree( GetProcessHeap(), 0, rect );
2337         }
2338         break;
2339     case LB_GETSELITEMS:
2340         {
2341             INT i;
2342             LPINT16 items = MapSL(lParam16);
2343             UnMapLS( lParam16 );
2344             lParam16 = *((LPARAM *)items - 1);
2345             for (i = 0; i < wParam16; i++) *((LPINT)lParam16 + i) = items[i];
2346             HeapFree( GetProcessHeap(), 0, (LPARAM *)items - 1 );
2347         }
2348         break;
2349
2350     case CB_GETEDITSEL:
2351         if( wParam )
2352             *((PUINT)(wParam)) = LOWORD(*result);
2353         if( lParam )
2354             *((PUINT)(lParam)) = HIWORD(*result);  /* FIXME: substract 1? */
2355         break;
2356
2357     case WM_MEASUREITEM:
2358         {
2359             MEASUREITEMSTRUCT16 *mis = MapSL(lParam16);
2360             MEASUREITEMSTRUCT *mis32 = *(MEASUREITEMSTRUCT **)(mis + 1);
2361             mis32->itemWidth  = mis->itemWidth;
2362             mis32->itemHeight = mis->itemHeight;
2363             UnMapLS( lParam16 );
2364             HeapFree( GetProcessHeap(), 0, mis );
2365         }
2366         break;
2367     case WM_GETMINMAXINFO:
2368         {
2369             MINMAXINFO16 *mmi = MapSL(lParam16);
2370             UnMapLS( lParam16 );
2371             lParam16 = *(LPARAM *)(mmi + 1);
2372             MINMAXINFO16to32( mmi, (MINMAXINFO *)lParam16 );
2373             HeapFree( GetProcessHeap(), 0, mmi );
2374         }
2375         break;
2376     case WM_GETTEXT:
2377     case WM_ASKCBFORMATNAME:
2378         {
2379             LPSTR str = MapSL(lParam16);
2380             UnMapLS( lParam16 );
2381             lParam16 = *((LPARAM *)str - 1);
2382             lstrcpynA( (LPSTR)lParam16, str, wParam16 );
2383             HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2384         }
2385         break;
2386     case WM_MDICREATE:
2387         {
2388             MDICREATESTRUCT16 *cs = MapSL(lParam16);
2389             UnMapLS( cs->szTitle );
2390             UnMapLS( cs->szClass );
2391             UnMapLS( lParam16 );
2392             HeapFree( GetProcessHeap(), 0, cs );
2393         }
2394         break;
2395     case WM_MDIGETACTIVE:
2396         if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(*result);
2397         *result = (LRESULT)WIN_Handle32( LOWORD(*result) );
2398         break;
2399     case WM_NCCALCSIZE:
2400         {
2401             NCCALCSIZE_PARAMS *nc32;
2402             NCCALCSIZE_PARAMS16 *nc = MapSL(lParam16);
2403             UnMapLS( lParam16 );
2404             lParam16 = *(LPARAM *)(nc + 1);
2405             nc32 = (NCCALCSIZE_PARAMS *)lParam16;
2406             nc32->rgrc[0].left   = nc->rgrc[0].left;
2407             nc32->rgrc[0].top    = nc->rgrc[0].top;
2408             nc32->rgrc[0].right  = nc->rgrc[0].right;
2409             nc32->rgrc[0].bottom = nc->rgrc[0].bottom;
2410             if (wParam16)
2411             {
2412                 WINDOWPOS16 *pos = MapSL(nc->lppos);
2413                 UnMapLS( nc->lppos );
2414                 nc32->rgrc[1].left   = nc->rgrc[1].left;
2415                 nc32->rgrc[1].top    = nc->rgrc[1].top;
2416                 nc32->rgrc[1].right  = nc->rgrc[1].right;
2417                 nc32->rgrc[1].bottom = nc->rgrc[1].bottom;
2418                 nc32->rgrc[2].left   = nc->rgrc[2].left;
2419                 nc32->rgrc[2].top    = nc->rgrc[2].top;
2420                 nc32->rgrc[2].right  = nc->rgrc[2].right;
2421                 nc32->rgrc[2].bottom = nc->rgrc[2].bottom;
2422                 WINDOWPOS16to32( pos, nc32->lppos );
2423                 HeapFree( GetProcessHeap(), 0, pos );
2424             }
2425             HeapFree( GetProcessHeap(), 0, nc );
2426         }
2427         break;
2428     case WM_NCCREATE:
2429     case WM_CREATE:
2430         {
2431             CREATESTRUCT16 *cs = MapSL(lParam16);
2432             UnMapLS( lParam16 );
2433             UnMapLS( cs->lpszName );
2434             UnMapLS( cs->lpszClass );
2435             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2436             {
2437                 MDICREATESTRUCT16 *mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs->lpCreateParams);
2438                 UnMapLS( cs->lpCreateParams );
2439                 UnMapLS( mdi_cs16->szTitle );
2440                 UnMapLS( mdi_cs16->szClass );
2441                 HeapFree(GetProcessHeap(), 0, mdi_cs16);
2442             }
2443             HeapFree( GetProcessHeap(), 0, cs );
2444         }
2445         break;
2446     case WM_WINDOWPOSCHANGING:
2447     case WM_WINDOWPOSCHANGED:
2448         {
2449             WINDOWPOS16 *wp = MapSL(lParam16);
2450             UnMapLS( lParam16 );
2451             lParam16 = *(LPARAM *)(wp + 1);
2452             WINDOWPOS16to32( wp, (WINDOWPOS *)lParam16 );
2453             HeapFree( GetProcessHeap(), 0, wp );
2454         }
2455         break;
2456     case WM_NOTIFY:
2457         UnMapLS(lParam16);
2458         break;
2459     case WM_GETDLGCODE:
2460         if (lParam16)
2461         {
2462             LPMSG16 msg16 = MapSL(lParam16);
2463             UnMapLS( lParam16 );
2464             HeapFree( GetProcessHeap(), 0, msg16 );
2465         }
2466         break;
2467     case WM_NEXTMENU:
2468         {
2469             MDINEXTMENU *next = (MDINEXTMENU *)lParam;
2470             next->hmenuNext = HMENU_32( LOWORD(*result) );
2471             next->hwndNext = WIN_Handle32( HIWORD(*result) );
2472             *result = 0;
2473         }
2474         break;
2475     }
2476 }
2477
2478
2479 /**********************************************************************
2480  *           WINPROC_MapMsg32WTo16
2481  *
2482  * Map a message from 32-bit Unicode to 16-bit.
2483  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
2484  */
2485 static INT WINPROC_MapMsg32WTo16( HWND hwnd, UINT msg32, WPARAM wParam32,
2486                                   UINT16 *pmsg16, WPARAM16 *pwparam16, LPARAM *plparam )
2487 {
2488     *pmsg16    = LOWORD(msg32);
2489     *pwparam16 = LOWORD(wParam32);
2490     switch(msg32)
2491     {
2492     case LB_ADDSTRING:
2493     case LB_FINDSTRING:
2494     case LB_FINDSTRINGEXACT:
2495     case LB_INSERTSTRING:
2496     case LB_SELECTSTRING:
2497     case LB_DIR:
2498     case LB_ADDFILE:
2499         *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2500         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2501         return 1;
2502
2503     case CB_ADDSTRING:
2504     case CB_FINDSTRING:
2505     case CB_FINDSTRINGEXACT:
2506     case CB_INSERTSTRING:
2507     case CB_SELECTSTRING:
2508     case CB_DIR:
2509         *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2510         *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING);
2511         return 1;
2512
2513     case WM_NCCREATE:
2514     case WM_CREATE:
2515         {
2516             CREATESTRUCT16 *cs;
2517             CREATESTRUCTW *cs32 = (CREATESTRUCTW *)*plparam;
2518
2519             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2520             CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs32, cs );
2521             cs->lpszName  = map_str_32W_to_16( cs32->lpszName );
2522             cs->lpszClass = map_str_32W_to_16( cs32->lpszClass );
2523
2524             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2525             {
2526                 MDICREATESTRUCT16 *mdi_cs16;
2527                 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)cs32->lpCreateParams;
2528                 mdi_cs16 = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs16));
2529                 if (!mdi_cs16)
2530                 {
2531                     HeapFree(GetProcessHeap(), 0, cs);
2532                     return -1;
2533                 }
2534                 MDICREATESTRUCT32Ato16((MDICREATESTRUCTA *)mdi_cs, mdi_cs16);
2535                 mdi_cs16->szTitle = map_str_32W_to_16(mdi_cs->szTitle);
2536                 mdi_cs16->szClass = map_str_32W_to_16(mdi_cs->szClass);
2537                 cs->lpCreateParams = MapLS(mdi_cs16);
2538             }
2539             *plparam   = MapLS(cs);
2540         }
2541         return 1;
2542     case WM_MDICREATE:
2543         {
2544             MDICREATESTRUCT16 *cs;
2545             MDICREATESTRUCTW *cs32 = (MDICREATESTRUCTW *)*plparam;
2546
2547             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2548             MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs32, cs );
2549             cs->szTitle = map_str_32W_to_16( cs32->szTitle );
2550             cs->szClass = map_str_32W_to_16( cs32->szClass );
2551             *plparam   = MapLS(cs);
2552         }
2553         return 1;
2554     case WM_SETTEXT:
2555     case WM_WININICHANGE:
2556     case WM_DEVMODECHANGE:
2557         *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2558         return 1;
2559     case LB_GETTEXT:
2560     case CB_GETLBTEXT:
2561         if ( WINPROC_TestLBForStr( hwnd, msg32 ))
2562         {
2563             LPSTR str = HeapAlloc( GetProcessHeap(), 0, 512 ); /* FIXME: fixed sized buffer */
2564             if (!str) return -1;
2565             *pmsg16    = (msg32 == LB_GETTEXT) ? LB_GETTEXT16 : CB_GETLBTEXT16;
2566             *plparam   = (LPARAM)MapLS(str);
2567         }
2568         return 1;
2569
2570     case WM_CHARTOITEM:
2571         *pwparam16 = map_wparam_char_WtoA( wParam32, 1 );
2572         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2573         return 0;
2574     case WM_MENUCHAR:
2575         *pwparam16 = map_wparam_char_WtoA( wParam32, 1 );
2576         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2577         return 0;
2578     case WM_CHAR:
2579     case WM_DEADCHAR:
2580     case WM_SYSCHAR:
2581     case WM_SYSDEADCHAR:
2582         *pwparam16 = map_wparam_char_WtoA( wParam32, 1 );
2583         return 0;
2584     case WM_IME_CHAR:
2585         *pwparam16 = map_wparam_char_WtoA( wParam32, 2 );
2586         return 0;
2587
2588     default:  /* No Unicode translation needed (?) */
2589         return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2590                                       pwparam16, plparam );
2591     }
2592 }
2593
2594
2595 /**********************************************************************
2596  *           WINPROC_UnmapMsg32WTo16
2597  *
2598  * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2599  */
2600 static void WINPROC_UnmapMsg32WTo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2601                                      WPARAM16 wParam16, LPARAM lParam16, LRESULT *result )
2602 {
2603     switch(msg)
2604     {
2605     case LB_ADDSTRING:
2606     case LB_FINDSTRING:
2607     case LB_FINDSTRINGEXACT:
2608     case LB_INSERTSTRING:
2609     case LB_SELECTSTRING:
2610     case LB_DIR:
2611     case LB_ADDFILE:
2612     case CB_ADDSTRING:
2613     case CB_FINDSTRING:
2614     case CB_FINDSTRINGEXACT:
2615     case CB_INSERTSTRING:
2616     case CB_SELECTSTRING:
2617     case CB_DIR:
2618     case WM_SETTEXT:
2619     case WM_WININICHANGE:
2620     case WM_DEVMODECHANGE:
2621         unmap_str_32W_to_16( lParam16 );
2622         break;
2623     case WM_NCCREATE:
2624     case WM_CREATE:
2625         {
2626             CREATESTRUCT16 *cs = MapSL(lParam16);
2627             UnMapLS( lParam16 );
2628             unmap_str_32W_to_16( cs->lpszName );
2629             unmap_str_32W_to_16( cs->lpszClass );
2630
2631             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2632             {
2633                 MDICREATESTRUCT16 *mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs->lpCreateParams);
2634                 UnMapLS( cs->lpCreateParams );
2635                 unmap_str_32W_to_16(mdi_cs16->szTitle);
2636                 unmap_str_32W_to_16(mdi_cs16->szClass);
2637                 HeapFree(GetProcessHeap(), 0, mdi_cs16);
2638             }
2639             HeapFree( GetProcessHeap(), 0, cs );
2640         }
2641         break;
2642     case WM_MDICREATE:
2643         {
2644             MDICREATESTRUCT16 *cs = MapSL(lParam16);
2645             UnMapLS( lParam16 );
2646             unmap_str_32W_to_16( cs->szTitle );
2647             unmap_str_32W_to_16( cs->szClass );
2648             HeapFree( GetProcessHeap(), 0, cs );
2649         }
2650         break;
2651     case WM_GETTEXT:
2652     case WM_ASKCBFORMATNAME:
2653         {
2654             LPSTR str = MapSL(lParam16);
2655             UnMapLS( lParam16 );
2656             lParam16 = *((LPARAM *)str - 1);
2657             MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam16, 0x7fffffff );
2658             *result = strlenW( (LPWSTR)lParam16 );
2659             HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2660         }
2661         break;
2662     case LB_GETTEXT:
2663     case CB_GETLBTEXT:
2664         if ( WINPROC_TestLBForStr( hwnd, msg ))
2665         {
2666             LPSTR str = MapSL(lParam16);
2667             UnMapLS( lParam16 );
2668             *result = MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff ) - 1;
2669             HeapFree( GetProcessHeap(), 0, (LPARAM *)str );
2670         }
2671         break;
2672     default:
2673         WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, wParam16, lParam16, result );
2674         break;
2675     }
2676 }
2677
2678
2679 /**********************************************************************
2680  *           WINPROC_CallProcAtoW
2681  *
2682  * Call a window procedure, translating args from Ansi to Unicode.
2683  */
2684 LRESULT WINPROC_CallProcAtoW( winproc_callback_t callback, HWND hwnd, UINT msg, WPARAM wParam,
2685                               LPARAM lParam, LRESULT *result, void *arg )
2686 {
2687     LRESULT ret;
2688     int unmap;
2689
2690     TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2691                 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2692
2693     if( (unmap = WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam )) == -1) {
2694         ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2695                        SPY_GetMsgName(msg, hwnd), wParam, lParam );
2696         return 0;
2697     }
2698     ret = callback( hwnd, msg, wParam, lParam, result, arg );
2699     if (unmap)
2700         *result = WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, *result,
2701                                             (callback == call_window_proc) ? arg : NULL  /*FIXME: hack*/ );
2702     return ret;
2703 }
2704
2705
2706 static inline void *get_buffer( void *static_buffer, size_t size, size_t need )
2707 {
2708     if (size >= need) return static_buffer;
2709     return HeapAlloc( GetProcessHeap(), 0, need );
2710 }
2711
2712 static inline void free_buffer( void *static_buffer, void *buffer )
2713 {
2714     if (buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer );
2715 }
2716
2717 /**********************************************************************
2718  *           WINPROC_CallProcWtoA
2719  *
2720  * Call a window procedure, translating args from Unicode to Ansi.
2721  */
2722 static LRESULT WINPROC_CallProcWtoA( winproc_callback_t callback, HWND hwnd, UINT msg, WPARAM wParam,
2723                                      LPARAM lParam, LRESULT *result, void *arg )
2724 {
2725     LRESULT ret = 0;
2726
2727     TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2728                 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2729
2730     switch(msg)
2731     {
2732     case WM_NCCREATE:
2733     case WM_CREATE:
2734         {   /* csW->lpszName and csW->lpszClass are NOT supposed to be atoms
2735              * at this point.
2736              */
2737             char buffer[1024], *cls, *name;
2738             CREATESTRUCTW *csW = (CREATESTRUCTW *)lParam;
2739             CREATESTRUCTA csA = *(CREATESTRUCTA *)csW;
2740             MDICREATESTRUCTA mdi_cs;
2741             DWORD name_lenA, name_lenW, class_lenA, class_lenW;
2742
2743             class_lenW = strlenW(csW->lpszClass) * sizeof(WCHAR);
2744             RtlUnicodeToMultiByteSize(&class_lenA, csW->lpszClass, class_lenW);
2745
2746             if (csW->lpszName)
2747             {
2748                 name_lenW = strlenW(csW->lpszName) * sizeof(WCHAR);
2749                 RtlUnicodeToMultiByteSize(&name_lenA, csW->lpszName, name_lenW);
2750             }
2751             else
2752                 name_lenW = name_lenA = 0;
2753
2754             if (!(cls = get_buffer( buffer, sizeof(buffer), class_lenA + name_lenA + 2 ))) break;
2755
2756             RtlUnicodeToMultiByteN(cls, class_lenA, NULL, csW->lpszClass, class_lenW);
2757             cls[class_lenA] = 0;
2758             csA.lpszClass = cls;
2759
2760             if (csW->lpszName)
2761             {
2762                 name = cls + class_lenA + 1;
2763                 RtlUnicodeToMultiByteN(name, name_lenA, NULL, csW->lpszName, name_lenW);
2764                 name[name_lenA] = 0;
2765                 csA.lpszName = name;
2766             }
2767
2768             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2769             {
2770                 mdi_cs = *(MDICREATESTRUCTA *)csW->lpCreateParams;
2771                 mdi_cs.szTitle = csA.lpszName;
2772                 mdi_cs.szClass = csA.lpszClass;
2773                 csA.lpCreateParams = &mdi_cs;
2774             }
2775
2776             ret = callback( hwnd, msg, wParam, (LPARAM)&csA, result, arg );
2777             free_buffer( buffer, cls );
2778         }
2779         break;
2780
2781     case WM_GETTEXT:
2782     case WM_ASKCBFORMATNAME:
2783         {
2784             char *ptr, buffer[512];
2785             DWORD len = wParam * 2;
2786
2787             if (!(ptr = get_buffer( buffer, sizeof(buffer), len ))) break;
2788             ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2789             if (*result && len)
2790             {
2791                 RtlMultiByteToUnicodeN( (LPWSTR)lParam, wParam*sizeof(WCHAR), &len, ptr, strlen(ptr)+1 );
2792                 *result = len/sizeof(WCHAR) - 1;  /* do not count terminating null */
2793                 ((LPWSTR)lParam)[*result] = 0;
2794             }
2795             free_buffer( buffer, ptr );
2796         }
2797         break;
2798
2799     case LB_ADDSTRING:
2800     case LB_INSERTSTRING:
2801     case LB_FINDSTRING:
2802     case LB_FINDSTRINGEXACT:
2803     case LB_SELECTSTRING:
2804     case CB_ADDSTRING:
2805     case CB_INSERTSTRING:
2806     case CB_FINDSTRING:
2807     case CB_FINDSTRINGEXACT:
2808     case CB_SELECTSTRING:
2809         if (!lParam || !WINPROC_TestLBForStr( hwnd, msg ))
2810         {
2811             ret = callback( hwnd, msg, wParam, lParam, result, arg );
2812             break;
2813         }
2814         /* fall through */
2815     case WM_SETTEXT:
2816     case WM_WININICHANGE:
2817     case WM_DEVMODECHANGE:
2818     case CB_DIR:
2819     case LB_DIR:
2820     case LB_ADDFILE:
2821     case EM_REPLACESEL:
2822         if (!lParam) ret = callback( hwnd, msg, wParam, lParam, result, arg );
2823         else
2824         {
2825             char *ptr, buffer[512];
2826             LPCWSTR strW = (LPCWSTR)lParam;
2827             DWORD lenA, lenW = (strlenW(strW) + 1) * sizeof(WCHAR);
2828
2829             RtlUnicodeToMultiByteSize( &lenA, strW, lenW );
2830             if ((ptr = get_buffer( buffer, sizeof(buffer), lenA )))
2831             {
2832                 RtlUnicodeToMultiByteN( ptr, lenA, NULL, strW, lenW );
2833                 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2834                 free_buffer( buffer, ptr );
2835             }
2836         }
2837         break;
2838
2839     case WM_MDICREATE:
2840         {
2841             char *ptr, buffer[1024];
2842             DWORD title_lenA = 0, title_lenW = 0, class_lenA = 0, class_lenW = 0;
2843             MDICREATESTRUCTW *csW = (MDICREATESTRUCTW *)lParam;
2844             MDICREATESTRUCTA csA;
2845
2846             memcpy( &csA, csW, sizeof(csA) );
2847
2848             if (HIWORD(csW->szTitle))
2849             {
2850                 title_lenW = (strlenW(csW->szTitle) + 1) * sizeof(WCHAR);
2851                 RtlUnicodeToMultiByteSize( &title_lenA, csW->szTitle, title_lenW );
2852             }
2853             if (HIWORD(csW->szClass))
2854             {
2855                 class_lenW = (strlenW(csW->szClass) + 1) * sizeof(WCHAR);
2856                 RtlUnicodeToMultiByteSize( &class_lenA, csW->szClass, class_lenW );
2857             }
2858
2859             if (!(ptr = get_buffer( buffer, sizeof(buffer), title_lenA + class_lenA ))) break;
2860
2861             if (title_lenA)
2862             {
2863                 RtlUnicodeToMultiByteN( ptr, title_lenA, NULL, csW->szTitle, title_lenW );
2864                 csA.szTitle = ptr;
2865             }
2866             if (class_lenA)
2867             {
2868                 RtlUnicodeToMultiByteN( ptr + title_lenA, class_lenA, NULL, csW->szClass, class_lenW );
2869                 csA.szClass = ptr + title_lenA;
2870             }
2871             ret = callback( hwnd, msg, wParam, (LPARAM)&csA, result, arg );
2872             free_buffer( buffer, ptr );
2873         }
2874         break;
2875
2876     case LB_GETTEXT:
2877     case CB_GETLBTEXT:
2878         if (lParam && WINPROC_TestLBForStr( hwnd, msg ))
2879         {
2880             char buffer[512];  /* FIXME: fixed sized buffer */
2881
2882             ret = callback( hwnd, msg, wParam, (LPARAM)buffer, result, arg );
2883             if (*result >= 0)
2884             {
2885                 DWORD len;
2886                 RtlMultiByteToUnicodeN( (LPWSTR)lParam, ~0u, &len, buffer, strlen(buffer) + 1 );
2887                 *result = len / sizeof(WCHAR) - 1;
2888             }
2889         }
2890         else ret = callback( hwnd, msg, wParam, lParam, result, arg );
2891         break;
2892
2893     case EM_GETLINE:
2894         {
2895             char *ptr, buffer[512];
2896             WORD len = *(WORD *)lParam;
2897
2898             if (!(ptr = get_buffer( buffer, sizeof(buffer), len * 2 ))) break;
2899             *((WORD *)ptr) = len * 2;   /* store the length */
2900             ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2901             if (*result)
2902             {
2903                 DWORD reslen;
2904                 RtlMultiByteToUnicodeN( (LPWSTR)lParam, len*sizeof(WCHAR), &reslen, buffer, *result );
2905                 *result = reslen / sizeof(WCHAR);
2906                 if (*result < len) ((LPWSTR)lParam)[*result] = 0;
2907             }
2908             free_buffer( buffer, ptr );
2909         }
2910         break;
2911
2912     case WM_CHARTOITEM:
2913     case WM_MENUCHAR:
2914     case WM_CHAR:
2915     case WM_DEADCHAR:
2916     case WM_SYSCHAR:
2917     case WM_SYSDEADCHAR:
2918     case EM_SETPASSWORDCHAR:
2919         ret = callback( hwnd, msg, map_wparam_char_WtoA(wParam,1), lParam, result, arg );
2920         break;
2921
2922     case WM_IME_CHAR:
2923         ret = callback( hwnd, msg, map_wparam_char_WtoA(wParam,2), lParam, result, arg );
2924         break;
2925
2926     case WM_PAINTCLIPBOARD:
2927     case WM_SIZECLIPBOARD:
2928         FIXME_(msg)( "message %s (%04x) needs translation, please report\n",
2929                      SPY_GetMsgName(msg, hwnd), msg );
2930         break;
2931
2932     default:
2933         ret = callback( hwnd, msg, wParam, lParam, result, arg );
2934         break;
2935     }
2936
2937     return ret;
2938 }
2939
2940
2941 /**********************************************************************
2942  *           WINPROC_CallProc16To32A
2943  */
2944 LRESULT WINPROC_CallProc16To32A( winproc_callback_t callback, HWND16 hwnd, UINT16 msg,
2945                                  WPARAM16 wParam, LPARAM lParam, LRESULT *result, void *arg )
2946 {
2947     LRESULT ret;
2948     UINT msg32;
2949     WPARAM wParam32;
2950     HWND hwnd32 = WIN_Handle32( hwnd );
2951
2952     TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2953                  hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
2954
2955     if (WINPROC_MapMsg16To32A( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2956         return 0;
2957
2958     ret = callback( hwnd32, msg32, wParam32, lParam, result, arg );
2959     *result = WINPROC_UnmapMsg16To32A( hwnd32, msg32, wParam32, lParam, *result );
2960     return ret;
2961 }
2962
2963
2964 /**********************************************************************
2965  *           WINPROC_CallProc16To32W
2966  */
2967 static LRESULT WINPROC_CallProc16To32W( winproc_callback_t callback, HWND16 hwnd, UINT16 msg,
2968                                         WPARAM16 wParam, LPARAM lParam, LRESULT *result, void *arg )
2969 {
2970     LRESULT ret;
2971     UINT msg32;
2972     WPARAM wParam32;
2973     HWND hwnd32 = WIN_Handle32( hwnd );
2974
2975     TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2976                  hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
2977
2978     if (WINPROC_MapMsg16To32W( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2979         return 0;
2980
2981     ret = callback( hwnd32, msg32, wParam32, lParam, result, arg );
2982     *result = WINPROC_UnmapMsg16To32W( hwnd32, msg32, wParam32, lParam, *result,
2983                                        (callback == call_window_proc) ? arg : NULL  /*FIXME: hack*/ );
2984     return ret;
2985 }
2986
2987
2988 /**********************************************************************
2989  *           __wine_call_wndproc   (USER.1010)
2990  */
2991 LRESULT WINAPI __wine_call_wndproc( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2992                                     WINDOWPROC *proc )
2993 {
2994     LRESULT result;
2995
2996     if (proc->procA)
2997         WINPROC_CallProc16To32A( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
2998     else
2999         WINPROC_CallProc16To32W( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3000     return result;
3001 }
3002
3003
3004 /**********************************************************************
3005  *           WINPROC_CallProc32ATo16
3006  *
3007  * Call a 16-bit window procedure, translating the 32-bit args.
3008  */
3009 LRESULT WINPROC_CallProc32ATo16( winproc_callback16_t callback, HWND hwnd, UINT msg,
3010                                  WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg )
3011 {
3012     LRESULT ret;
3013     UINT16 msg16;
3014     WPARAM16 wParam16;
3015     LPARAM lParam16;
3016
3017     TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
3018                 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
3019
3020     lParam16 = lParam;
3021     if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, &msg16, &wParam16, &lParam16 ) == -1)
3022         return 0;
3023     ret = callback( HWND_16(hwnd), msg16, wParam16, lParam16, result, arg );
3024     WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, wParam16, lParam16, result );
3025     return ret;
3026 }
3027
3028
3029 /**********************************************************************
3030  *           WINPROC_CallProc32WTo16
3031  *
3032  * Call a 16-bit window procedure, translating the 32-bit args.
3033  */
3034 static LRESULT WINPROC_CallProc32WTo16( winproc_callback16_t callback, HWND hwnd, UINT msg,
3035                                         WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg )
3036 {
3037     LRESULT ret;
3038     UINT16 msg16;
3039     WPARAM16 wParam16;
3040     LPARAM lParam16;
3041
3042     TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
3043                 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
3044
3045     lParam16 = lParam;
3046     if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &wParam16, &lParam16 ) == -1)
3047         return 0;
3048     ret = callback( HWND_16(hwnd), msg16, wParam16, lParam16, result, arg );
3049     WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, wParam16, lParam16, result );
3050     return ret;
3051 }
3052
3053
3054 /**********************************************************************
3055  *              CallWindowProc (USER.122)
3056  */
3057 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
3058                                  WPARAM16 wParam, LPARAM lParam )
3059 {
3060     WINDOWPROC *proc;
3061     LRESULT result;
3062
3063     if (!func) return 0;
3064
3065     if (!(proc = handle16_to_proc( func )))
3066         call_window_proc16( hwnd, msg, wParam, lParam, &result, func );
3067     else if (proc->procA)
3068         WINPROC_CallProc16To32A( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
3069     else if (proc->procW)
3070         WINPROC_CallProc16To32W( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3071     else
3072         call_window_proc16( hwnd, msg, wParam, lParam, &result, proc->proc16 );
3073
3074     return result;
3075 }
3076
3077
3078 /**********************************************************************
3079  *              CallWindowProcA (USER32.@)
3080  *
3081  * The CallWindowProc() function invokes the windows procedure _func_,
3082  * with _hwnd_ as the target window, the message specified by _msg_, and
3083  * the message parameters _wParam_ and _lParam_.
3084  *
3085  * Some kinds of argument conversion may be done, I'm not sure what.
3086  *
3087  * CallWindowProc() may be used for windows subclassing. Use
3088  * SetWindowLong() to set a new windows procedure for windows of the
3089  * subclass, and handle subclassed messages in the new windows
3090  * procedure. The new windows procedure may then use CallWindowProc()
3091  * with _func_ set to the parent class's windows procedure to dispatch
3092  * the message to the superclass.
3093  *
3094  * RETURNS
3095  *
3096  *    The return value is message dependent.
3097  *
3098  * CONFORMANCE
3099  *
3100  *   ECMA-234, Win32
3101  */
3102 LRESULT WINAPI CallWindowProcA(
3103     WNDPROC func,  /* [in] window procedure */
3104     HWND hwnd,     /* [in] target window */
3105     UINT msg,      /* [in] message */
3106     WPARAM wParam, /* [in] message dependent parameter */
3107     LPARAM lParam  /* [in] message dependent parameter */
3108 ) {
3109     WINDOWPROC *proc;
3110     LRESULT result;
3111
3112     if (!func) return 0;
3113
3114     if (!(proc = handle_to_proc( func )))
3115         call_window_proc( hwnd, msg, wParam, lParam, &result, func );
3116     else if (proc->procA)
3117         call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
3118     else if (proc->procW)
3119         WINPROC_CallProcAtoW( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3120     else
3121         WINPROC_CallProc32ATo16( call_window_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3122     return result;
3123 }
3124
3125
3126 /**********************************************************************
3127  *              CallWindowProcW (USER32.@)
3128  *
3129  * See CallWindowProcA.
3130  */
3131 LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
3132                                   WPARAM wParam, LPARAM lParam )
3133 {
3134     WINDOWPROC *proc;
3135     LRESULT result;
3136
3137     if (!func) return 0;
3138
3139     if (!(proc = handle_to_proc( func )))
3140         call_window_proc( hwnd, msg, wParam, lParam, &result, func );
3141     else if (proc->procW)
3142         call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
3143     else if (proc->procA)
3144         WINPROC_CallProcWtoA( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
3145     else
3146         WINPROC_CallProc32WTo16( call_window_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3147     return result;
3148 }
3149
3150
3151 /**********************************************************************
3152  *              WINPROC_CallDlgProc16
3153  */
3154 INT_PTR WINPROC_CallDlgProc16( DLGPROC16 func, HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
3155 {
3156     WINDOWPROC *proc;
3157     LRESULT result;
3158     INT_PTR ret;
3159
3160     if (!func) return 0;
3161
3162     if (!(proc = handle16_to_proc( (WNDPROC16)func )))
3163     {
3164         ret = call_dialog_proc16( hwnd, msg, wParam, lParam, &result, func );
3165     }
3166     else if (proc->procA)
3167     {
3168         ret = WINPROC_CallProc16To32A( call_dialog_proc, hwnd, msg, wParam, lParam,
3169                                        &result, proc->procA );
3170         SetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT, result );
3171     }
3172     else if (proc->procW)
3173     {
3174         ret = WINPROC_CallProc16To32W( call_dialog_proc, hwnd, msg, wParam, lParam,
3175                                        &result, proc->procW );
3176         SetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT, result );
3177     }
3178     else
3179     {
3180         ret = call_dialog_proc16( hwnd, msg, wParam, lParam, &result, proc->proc16 );
3181     }
3182     return ret;
3183 }
3184
3185
3186 /**********************************************************************
3187  *              WINPROC_CallDlgProcA
3188  */
3189 INT_PTR WINPROC_CallDlgProcA( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
3190 {
3191     WINDOWPROC *proc;
3192     LRESULT result;
3193     INT_PTR ret;
3194
3195     if (!func) return 0;
3196
3197     if (!(proc = handle_to_proc( (WNDPROC)func )))
3198         ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, func );
3199     else if (proc->procA)
3200         ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
3201     else if (proc->procW)
3202     {
3203         ret = WINPROC_CallProcAtoW( call_dialog_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3204         SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3205     }
3206     else
3207     {
3208         ret = WINPROC_CallProc32ATo16( call_dialog_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3209         SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3210     }
3211     return ret;
3212 }
3213
3214
3215 /**********************************************************************
3216  *              WINPROC_CallDlgProcW
3217  */
3218 INT_PTR WINPROC_CallDlgProcW( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
3219 {
3220     WINDOWPROC *proc;
3221     LRESULT result;
3222     INT_PTR ret;
3223
3224     if (!func) return 0;
3225
3226     if (!(proc = handle_to_proc( (WNDPROC)func )))
3227         ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, func );
3228     else if (proc->procW)
3229         ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
3230     else if (proc->procA)
3231     {
3232         ret = WINPROC_CallProcWtoA( call_dialog_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
3233         SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3234     }
3235     else
3236     {
3237         ret = WINPROC_CallProc32WTo16( call_dialog_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3238         SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3239     }
3240     return ret;
3241 }