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