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