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