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