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