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