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