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