Merge the MDI and common window creation code. Change the way MDI
[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             MultiByteToWideChar(CP_ACP, 0, ch, 2, &wch, 1);
801             *pwparam = MAKEWPARAM( wch, HIWORD(*pwparam) );
802         }
803         return 0;
804
805     case WM_PAINTCLIPBOARD:
806     case WM_SIZECLIPBOARD:
807         FIXME_(msg)("message %s (0x%x) needs translation, please report\n", SPY_GetMsgName(msg, hwnd), msg );
808         return -1;
809     default:  /* No translation needed */
810         return 0;
811     }
812 }
813
814
815 /**********************************************************************
816  *           WINPROC_UnmapMsg32ATo32W
817  *
818  * Unmap a message that was mapped from Ansi to Unicode.
819  */
820 LRESULT WINPROC_UnmapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
821                                   LRESULT result )
822 {
823     switch(msg)
824     {
825     case WM_GETTEXT:
826     case WM_ASKCBFORMATNAME:
827         {
828             LPARAM *ptr = (LPARAM *)lParam - 1;
829             if (wParam > 0 && !WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
830                                                     (LPSTR)*ptr, wParam, NULL, NULL ))
831                 ((LPSTR)*ptr)[wParam-1] = 0;
832             HeapFree( GetProcessHeap(), 0, ptr );
833         }
834         break;
835     case WM_GETTEXTLENGTH:
836     case CB_GETLBTEXTLEN:
837     case LB_GETTEXTLEN:
838         /* there may be one DBCS char for each Unicode char */
839         return result * 2;
840     case WM_NCCREATE:
841     case WM_CREATE:
842         {
843             struct s
844             { CREATESTRUCTW cs;         /* new structure */
845               LPWSTR lpszName;          /* allocated Name */
846               LPWSTR lpszClass;         /* allocated Class */
847             };
848             struct s *xs = (struct s *)lParam;
849             if (xs->lpszName)  HeapFree( GetProcessHeap(), 0, xs->lpszName );
850             if (xs->lpszClass) HeapFree( GetProcessHeap(), 0, xs->lpszClass );
851
852             if (GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
853             {
854                 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)xs->cs.lpCreateParams;
855                 if (HIWORD(mdi_cs->szTitle))
856                     HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szTitle);
857                 if (HIWORD(mdi_cs->szClass))
858                     HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szClass);
859                 HeapFree(GetProcessHeap(), 0, mdi_cs);
860             }
861             HeapFree( GetProcessHeap(), 0, xs );
862         }
863         break;
864
865     case WM_MDICREATE:
866         {
867             MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
868             if (HIWORD(cs->szTitle))
869                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
870             if (HIWORD(cs->szClass))
871                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
872             HeapFree( GetProcessHeap(), 0, cs );
873         }
874         break;
875
876     case WM_SETTEXT:
877     case WM_WININICHANGE:
878     case WM_DEVMODECHANGE:
879     case CB_DIR:
880     case LB_DIR:
881     case LB_ADDFILE:
882     case EM_REPLACESEL:
883         HeapFree( GetProcessHeap(), 0, (void *)lParam );
884         break;
885
886 /* Listbox */
887     case LB_ADDSTRING:
888     case LB_INSERTSTRING:
889     case LB_FINDSTRING:
890     case LB_FINDSTRINGEXACT:
891     case LB_SELECTSTRING:
892         if ( WINPROC_TestLBForStr( hwnd ))
893           HeapFree( GetProcessHeap(), 0, (void *)lParam );
894         break;
895
896     case LB_GETTEXT:
897         { if ( WINPROC_TestLBForStr( hwnd ))
898           { LPARAM *ptr = (LPARAM *)lParam - 1;
899             WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1, (LPSTR)*ptr, 0x7fffffff, NULL, NULL );
900             HeapFree( GetProcessHeap(), 0, ptr );
901           }
902         }
903         break;
904
905 /* Combobox */
906     case CB_ADDSTRING:
907     case CB_INSERTSTRING:
908     case CB_FINDSTRING:
909     case CB_FINDSTRINGEXACT:
910     case CB_SELECTSTRING:
911         if ( WINPROC_TestCBForStr( hwnd ))
912           HeapFree( GetProcessHeap(), 0, (void *)lParam );
913         break;
914
915     case CB_GETLBTEXT:
916         { if ( WINPROC_TestCBForStr( hwnd ))
917           { LPARAM *ptr = (LPARAM *)lParam - 1;
918             WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1, (LPSTR)*ptr, 0x7fffffff, NULL, NULL );
919             HeapFree( GetProcessHeap(), 0, ptr );
920           }
921         }
922         break;
923
924 /* Multiline edit */
925     case EM_GETLINE:
926         { LPARAM * ptr = (LPARAM *)lParam - 1;  /* get the old lParam */
927           WORD len = *(WORD *) lParam;
928           if (len > 0 && !WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
929                                                (LPSTR)*ptr, len, NULL, NULL ))
930               ((LPSTR)*ptr)[len-1] = 0;
931           HeapFree( GetProcessHeap(), 0, ptr );
932         }
933         break;
934     }
935     return result;
936 }
937
938
939 /**********************************************************************
940  *           WINPROC_MapMsg32WTo32A
941  *
942  * Map a message from Unicode to Ansi.
943  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
944  */
945 INT WINPROC_MapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
946 {
947     switch(msg)
948     {
949     case WM_GETTEXT:
950     case WM_ASKCBFORMATNAME:
951         {
952             LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
953                                                *pwparam + sizeof(LPARAM) );
954             if (!ptr) return -1;
955             *ptr++ = *plparam;  /* Store previous lParam */
956             *plparam = (LPARAM)ptr;
957         }
958         return 1;
959
960     case WM_SETTEXT:
961     case WM_WININICHANGE:
962     case WM_DEVMODECHANGE:
963     case CB_DIR:
964     case LB_DIR:
965     case LB_ADDFILE:
966     case EM_REPLACESEL:
967         if(!*plparam) return 0;
968         *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
969         return (*plparam ? 1 : -1);
970
971     case WM_NCCREATE:
972     case WM_CREATE:
973         {
974             CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
975                                                                 sizeof(*cs) );
976             if (!cs) return -1;
977             *cs = *(CREATESTRUCTA *)*plparam;
978             if (HIWORD(cs->lpszName))
979                 cs->lpszName  = HEAP_strdupWtoA( GetProcessHeap(), 0,
980                                                  (LPCWSTR)cs->lpszName );
981             if (HIWORD(cs->lpszClass))
982                 cs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
983                                                  (LPCWSTR)cs->lpszClass);
984
985             if (GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
986             {
987                 MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)HeapAlloc(GetProcessHeap(), 0,
988                                                                          sizeof(*mdi_cs));
989                 if (!mdi_cs)
990                 {
991                     HeapFree(GetProcessHeap(), 0, cs);
992                     return -1;
993                 }
994                 *mdi_cs = *(MDICREATESTRUCTA *)cs->lpCreateParams;
995                 if (HIWORD(mdi_cs->szTitle))
996                     mdi_cs->szTitle = HEAP_strdupWtoA(GetProcessHeap(), 0,
997                                                       (LPCWSTR)mdi_cs->szTitle);
998                 if (HIWORD(mdi_cs->szClass))
999                     mdi_cs->szClass = HEAP_strdupWtoA(GetProcessHeap(), 0,
1000                                                       (LPCWSTR)mdi_cs->szClass);
1001                 cs->lpCreateParams = (LPVOID)mdi_cs;
1002             }
1003             *plparam = (LPARAM)cs;
1004         }
1005         return 1;
1006     case WM_MDICREATE:
1007         {
1008             MDICREATESTRUCTA *cs =
1009                 (MDICREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
1010             if (!cs) return -1;
1011             *cs = *(MDICREATESTRUCTA *)*plparam;
1012             if (HIWORD(cs->szTitle))
1013                 cs->szTitle = HEAP_strdupWtoA( GetProcessHeap(), 0,
1014                                                (LPCWSTR)cs->szTitle );
1015             if (HIWORD(cs->szClass))
1016                 cs->szClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
1017                                                (LPCWSTR)cs->szClass );
1018             *plparam = (LPARAM)cs;
1019         }
1020         return 1;
1021
1022 /* Listbox */
1023     case LB_ADDSTRING:
1024     case LB_INSERTSTRING:
1025     case LB_FINDSTRING:
1026     case LB_FINDSTRINGEXACT:
1027     case LB_SELECTSTRING:
1028         if(!*plparam) return 0;
1029         if ( WINPROC_TestLBForStr( hwnd ))
1030           *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
1031         return (*plparam ? 1 : -1);
1032
1033     case LB_GETTEXT:                    /* FIXME: fixed sized buffer */
1034         { if ( WINPROC_TestLBForStr( hwnd ))
1035           { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
1036             if (!ptr) return -1;
1037             *ptr++ = *plparam;  /* Store previous lParam */
1038             *plparam = (LPARAM)ptr;
1039           }
1040         }
1041         return 1;
1042
1043 /* Combobox */
1044     case CB_ADDSTRING:
1045     case CB_INSERTSTRING:
1046     case CB_FINDSTRING:
1047     case CB_FINDSTRINGEXACT:
1048     case CB_SELECTSTRING:
1049         if(!*plparam) return 0;
1050         if ( WINPROC_TestCBForStr( hwnd ))
1051           *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
1052         return (*plparam ? 1 : -1);
1053
1054     case CB_GETLBTEXT:          /* FIXME: fixed sized buffer */
1055         { if ( WINPROC_TestCBForStr( hwnd ))
1056           { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
1057             if (!ptr) return -1;
1058             *ptr++ = *plparam;  /* Store previous lParam */
1059             *plparam = (LPARAM)ptr;
1060           }
1061         }
1062         return 1;
1063
1064 /* Multiline edit */
1065     case EM_GETLINE:
1066         { WORD len = (WORD)*plparam;
1067           LPARAM *ptr = (LPARAM *) HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(CHAR) );
1068           if (!ptr) return -1;
1069           *ptr++ = *plparam;  /* Store previous lParam */
1070           *((WORD *) ptr) = len;   /* Store the length */
1071           *plparam = (LPARAM)ptr;
1072         }
1073         return 1;
1074
1075     case WM_CHARTOITEM:
1076     case WM_MENUCHAR:
1077     case WM_CHAR:
1078     case WM_DEADCHAR:
1079     case WM_SYSCHAR:
1080     case WM_SYSDEADCHAR:
1081     case EM_SETPASSWORDCHAR:
1082         {
1083             WCHAR wch = LOWORD(*pwparam);
1084             BYTE ch;
1085             WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL );
1086             *pwparam = MAKEWPARAM( ch, HIWORD(*pwparam) );
1087         }
1088         return 0;
1089
1090     case WM_IME_CHAR:
1091         {
1092             WCHAR wch = LOWORD(*pwparam);
1093             BYTE ch[2];
1094
1095             ch[1] = 0;
1096             WideCharToMultiByte( CP_ACP, 0, &wch, 1, ch, 2, NULL, NULL );
1097             *pwparam = MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(*pwparam) );
1098         }
1099         return 0;
1100
1101     case WM_PAINTCLIPBOARD:
1102     case WM_SIZECLIPBOARD:
1103         FIXME_(msg)("message %s (%04x) needs translation, please report\n",SPY_GetMsgName(msg, hwnd),msg );
1104         return -1;
1105     default:  /* No translation needed */
1106         return 0;
1107     }
1108 }
1109
1110
1111 /**********************************************************************
1112  *           WINPROC_UnmapMsg32WTo32A
1113  *
1114  * Unmap a message that was mapped from Unicode to Ansi.
1115  */
1116 void WINPROC_UnmapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
1117 {
1118     switch(msg)
1119     {
1120     case WM_GETTEXT:
1121     case WM_ASKCBFORMATNAME:
1122         {
1123             LPARAM *ptr = (LPARAM *)lParam - 1;
1124             if (wParam)
1125             {
1126                 if (!MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, wParam ))
1127                     ((LPWSTR)*ptr)[wParam-1] = 0;
1128             }
1129             HeapFree( GetProcessHeap(), 0, ptr );
1130         }
1131         break;
1132
1133     case WM_SETTEXT:
1134     case WM_WININICHANGE:
1135     case WM_DEVMODECHANGE:
1136     case CB_DIR:
1137     case LB_DIR:
1138     case LB_ADDFILE:
1139     case EM_REPLACESEL:
1140         HeapFree( GetProcessHeap(), 0, (void *)lParam );
1141         break;
1142
1143     case WM_NCCREATE:
1144     case WM_CREATE:
1145         {
1146             CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1147             if (HIWORD(cs->lpszName))
1148                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
1149             if (HIWORD(cs->lpszClass))
1150                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
1151             if (GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1152             {
1153                 MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs->lpCreateParams;
1154                 if (HIWORD(mdi_cs->szTitle))
1155                     HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szTitle);
1156                 if (HIWORD(mdi_cs->szClass))
1157                     HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szClass);
1158                 HeapFree(GetProcessHeap(), 0, mdi_cs);
1159             }
1160             HeapFree( GetProcessHeap(), 0, cs );
1161         }
1162         break;
1163
1164     case WM_MDICREATE:
1165         {
1166             MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1167             if (HIWORD(cs->szTitle))
1168                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
1169             if (HIWORD(cs->szClass))
1170                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
1171             HeapFree( GetProcessHeap(), 0, cs );
1172         }
1173         break;
1174
1175 /* Listbox */
1176     case LB_ADDSTRING:
1177     case LB_INSERTSTRING:
1178     case LB_FINDSTRING:
1179     case LB_FINDSTRINGEXACT:
1180     case LB_SELECTSTRING:
1181         if ( WINPROC_TestLBForStr( hwnd ))
1182           HeapFree( GetProcessHeap(), 0, (void *)lParam );
1183         break;
1184
1185     case LB_GETTEXT:
1186         if ( WINPROC_TestLBForStr( hwnd ))
1187         {
1188             LPARAM *ptr = (LPARAM *)lParam - 1;
1189             MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, 0x7fffffff );
1190             HeapFree( GetProcessHeap(), 0, ptr );
1191         }
1192         break;
1193
1194 /* Combobox */
1195     case CB_ADDSTRING:
1196     case CB_INSERTSTRING:
1197     case CB_FINDSTRING:
1198     case CB_FINDSTRINGEXACT:
1199     case CB_SELECTSTRING:
1200         if ( WINPROC_TestCBForStr( hwnd ))
1201           HeapFree( GetProcessHeap(), 0, (void *)lParam );
1202         break;
1203
1204     case CB_GETLBTEXT:
1205         if ( WINPROC_TestCBForStr( hwnd ))
1206         {
1207             LPARAM *ptr = (LPARAM *)lParam - 1;
1208             MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, 0x7fffffff );
1209             HeapFree( GetProcessHeap(), 0, ptr );
1210         }
1211         break;
1212
1213 /* Multiline edit */
1214     case EM_GETLINE:
1215         { LPARAM * ptr = (LPARAM *)lParam - 1;  /* get the old lparam */
1216           WORD len = *(WORD *)ptr;
1217           if (len)
1218           {
1219               if (!MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, len ))
1220                   ((LPWSTR)*ptr)[len-1] = 0;
1221           }
1222           HeapFree( GetProcessHeap(), 0, ptr );
1223         }
1224         break;
1225     }
1226 }
1227
1228 static UINT convert_handle_16_to_32(HANDLE16 src, unsigned int flags)
1229 {
1230     HANDLE      dst;
1231     UINT        sz = GlobalSize16(src);
1232     LPSTR       ptr16, ptr32;
1233
1234     if (!(dst = GlobalAlloc(flags, sz)))
1235         return 0;
1236     ptr16 = GlobalLock16(src);
1237     ptr32 = GlobalLock(dst);
1238     if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr32, ptr16, sz);
1239     GlobalUnlock16(src);
1240     GlobalUnlock(dst);
1241
1242     return (UINT)dst;
1243 }
1244
1245 /**********************************************************************
1246  *           WINPROC_MapMsg16To32A
1247  *
1248  * Map a message from 16- to 32-bit Ansi.
1249  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1250  */
1251 INT WINPROC_MapMsg16To32A( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1252                              WPARAM *pwparam32, LPARAM *plparam )
1253 {
1254     *pmsg32 = (UINT)msg16;
1255     *pwparam32 = (WPARAM)wParam16;
1256     switch(msg16)
1257     {
1258     case WM_ACTIVATE:
1259     case WM_CHARTOITEM:
1260     case WM_COMMAND:
1261     case WM_VKEYTOITEM:
1262         *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1263         *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1264         return 0;
1265     case WM_HSCROLL:
1266     case WM_VSCROLL:
1267         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1268         *plparam   = (LPARAM)WIN_Handle32( HIWORD(*plparam) );
1269         return 0;
1270     case WM_CTLCOLOR:
1271         if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
1272         *pmsg32    = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
1273         *pwparam32 = (WPARAM)HDC_32(wParam16);
1274         *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1275         return 0;
1276     case WM_COMPAREITEM:
1277         {
1278             COMPAREITEMSTRUCT16* cis16 = MapSL(*plparam);
1279             COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)
1280                                         HeapAlloc(GetProcessHeap(), 0, sizeof(*cis));
1281             if (!cis) return -1;
1282             cis->CtlType    = cis16->CtlType;
1283             cis->CtlID      = cis16->CtlID;
1284             cis->hwndItem   = WIN_Handle32( cis16->hwndItem );
1285             cis->itemID1    = cis16->itemID1;
1286             cis->itemData1  = cis16->itemData1;
1287             cis->itemID2    = cis16->itemID2;
1288             cis->itemData2  = cis16->itemData2;
1289             cis->dwLocaleId = 0;  /* FIXME */
1290             *plparam = (LPARAM)cis;
1291         }
1292         return 1;
1293     case WM_DELETEITEM:
1294         {
1295             DELETEITEMSTRUCT16* dis16 = MapSL(*plparam);
1296             DELETEITEMSTRUCT *dis = (DELETEITEMSTRUCT *)
1297                                         HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
1298             if (!dis) return -1;
1299             dis->CtlType  = dis16->CtlType;
1300             dis->CtlID    = dis16->CtlID;
1301             dis->hwndItem = WIN_Handle32( dis16->hwndItem );
1302             dis->itemData = dis16->itemData;
1303             *plparam = (LPARAM)dis;
1304         }
1305         return 1;
1306     case WM_MEASUREITEM:
1307         {
1308             MEASUREITEMSTRUCT16* mis16 = MapSL(*plparam);
1309             MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)
1310                                         HeapAlloc(GetProcessHeap(), 0,
1311                                                 sizeof(*mis) + sizeof(LPARAM));
1312             if (!mis) return -1;
1313             mis->CtlType    = mis16->CtlType;
1314             mis->CtlID      = mis16->CtlID;
1315             mis->itemID     = mis16->itemID;
1316             mis->itemWidth  = mis16->itemWidth;
1317             mis->itemHeight = mis16->itemHeight;
1318             mis->itemData   = mis16->itemData;
1319             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
1320             *plparam = (LPARAM)mis;
1321         }
1322         return 1;
1323     case WM_DRAWITEM:
1324         {
1325             DRAWITEMSTRUCT16* dis16 = MapSL(*plparam);
1326             DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT*)HeapAlloc(GetProcessHeap(), 0,
1327                                                                  sizeof(*dis));
1328             if (!dis) return -1;
1329             dis->CtlType    = dis16->CtlType;
1330             dis->CtlID      = dis16->CtlID;
1331             dis->itemID     = dis16->itemID;
1332             dis->itemAction = dis16->itemAction;
1333             dis->itemState  = dis16->itemState;
1334             dis->hwndItem   = (dis->CtlType == ODT_MENU) ? (HWND)HMENU_32(dis16->hwndItem)
1335                                                          : WIN_Handle32( dis16->hwndItem );
1336             dis->hDC        = HDC_32(dis16->hDC);
1337             dis->itemData   = dis16->itemData;
1338             CONV_RECT16TO32( &dis16->rcItem, &dis->rcItem );
1339             *plparam = (LPARAM)dis;
1340         }
1341         return 1;
1342     case WM_GETMINMAXINFO:
1343         {
1344             MINMAXINFO *mmi = (MINMAXINFO *)HeapAlloc( GetProcessHeap(), 0,
1345                                                 sizeof(*mmi) + sizeof(LPARAM));
1346             if (!mmi) return -1;
1347             STRUCT32_MINMAXINFO16to32( MapSL(*plparam), mmi );
1348             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
1349             *plparam = (LPARAM)mmi;
1350         }
1351         return 1;
1352     case WM_GETTEXT:
1353     case WM_SETTEXT:
1354     case WM_WININICHANGE:
1355     case WM_DEVMODECHANGE:
1356     case WM_ASKCBFORMATNAME:
1357         *plparam = (LPARAM)MapSL(*plparam);
1358         return 0;
1359     case WM_MDICREATE:
1360         {
1361             MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1362             MDICREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1363             if (!cs) return -1;
1364             STRUCT32_MDICREATESTRUCT16to32A( cs16, cs );
1365             cs->szTitle = MapSL(cs16->szTitle);
1366             cs->szClass = MapSL(cs16->szClass);
1367             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1368             *plparam = (LPARAM)cs;
1369         }
1370         return 1;
1371     case WM_MDIGETACTIVE:
1372         *plparam = (LPARAM)HeapAlloc( GetProcessHeap(), 0, sizeof(BOOL) );
1373         *(BOOL*)(*plparam) = 0;
1374         return 1;
1375     case WM_MDISETMENU:
1376         if(wParam16==TRUE)
1377            *pmsg32=WM_MDIREFRESHMENU;
1378         *pwparam32 = (WPARAM)HMENU_32(LOWORD(*plparam));
1379         *plparam   = (LPARAM)HMENU_32(HIWORD(*plparam));
1380         return 0;
1381     case WM_MENUCHAR:
1382         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1383         *plparam   = (LPARAM)HMENU_32(HIWORD(*plparam));
1384         return 0;
1385     case WM_MENUSELECT:
1386         if((LOWORD(*plparam) & MF_POPUP) && (LOWORD(*plparam) != 0xFFFF))
1387         {
1388             HMENU hmenu=HMENU_32(HIWORD(*plparam));
1389             UINT Pos=MENU_FindSubMenu( &hmenu, HMENU_32(wParam16));
1390             if(Pos==0xFFFF) Pos=0; /* NO_SELECTED_ITEM */
1391             *pwparam32 = MAKEWPARAM( Pos, LOWORD(*plparam) );
1392         }
1393         else *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1394         *plparam   = (LPARAM)HMENU_32(HIWORD(*plparam));
1395         return 0;
1396     case WM_MDIACTIVATE:
1397         if( *plparam )
1398         {
1399             *pwparam32 = (WPARAM)WIN_Handle32( HIWORD(*plparam) );
1400             *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1401         }
1402         else /* message sent to MDI client */
1403             *pwparam32 = wParam16;
1404         return 0;
1405     case WM_NCCALCSIZE:
1406         {
1407             NCCALCSIZE_PARAMS16 *nc16;
1408             NCCALCSIZE_PARAMS *nc;
1409
1410             nc = (NCCALCSIZE_PARAMS *)HeapAlloc( GetProcessHeap(), 0,
1411                                                 sizeof(*nc) + sizeof(LPARAM) );
1412             if (!nc) return -1;
1413             nc16 = MapSL(*plparam);
1414             CONV_RECT16TO32( &nc16->rgrc[0], &nc->rgrc[0] );
1415             if (wParam16)
1416             {
1417                 nc->lppos = (WINDOWPOS *)HeapAlloc( GetProcessHeap(), 0,
1418                                                       sizeof(*nc->lppos) );
1419                 CONV_RECT16TO32( &nc16->rgrc[1], &nc->rgrc[1] );
1420                 CONV_RECT16TO32( &nc16->rgrc[2], &nc->rgrc[2] );
1421                 if (nc->lppos) STRUCT32_WINDOWPOS16to32( MapSL(nc16->lppos), nc->lppos );
1422             }
1423             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
1424             *plparam = (LPARAM)nc;
1425         }
1426         return 1;
1427     case WM_NCCREATE:
1428     case WM_CREATE:
1429         {
1430             CREATESTRUCT16 *cs16 = MapSL(*plparam);
1431             CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
1432                                                 sizeof(*cs) + sizeof(LPARAM) );
1433             if (!cs) return -1;
1434             STRUCT32_CREATESTRUCT16to32A( cs16, cs );
1435             cs->lpszName  = MapSL(cs16->lpszName);
1436             cs->lpszClass = MapSL(cs16->lpszClass);
1437             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1438             *plparam = (LPARAM)cs;
1439         }
1440         return 1;
1441     case WM_PARENTNOTIFY:
1442         if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
1443         {
1444             *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1445             *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1446         }
1447         return 0;
1448     case WM_WINDOWPOSCHANGING:
1449     case WM_WINDOWPOSCHANGED:
1450         {
1451             WINDOWPOS *wp = (WINDOWPOS *)HeapAlloc( GetProcessHeap(), 0,
1452                                                 sizeof(*wp) + sizeof(LPARAM) );
1453             if (!wp) return -1;
1454             STRUCT32_WINDOWPOS16to32( MapSL(*plparam), wp );
1455             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
1456             *plparam = (LPARAM)wp;
1457         }
1458         return 1;
1459     case WM_GETDLGCODE:
1460         if (*plparam)
1461         {
1462             LPMSG16 msg16 = MapSL(*plparam);
1463             LPMSG msg32 = (LPMSG)HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1464
1465             if (!msg32) return -1;
1466             msg32->hwnd = WIN_Handle32( msg16->hwnd );
1467             msg32->lParam = msg16->lParam;
1468             msg32->time = msg16->time;
1469             CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1470             /* this is right, right? */
1471             if (WINPROC_MapMsg16To32A( msg32->hwnd, msg16->message,msg16->wParam,
1472                                      &msg32->message,&msg32->wParam,
1473                                      &msg32->lParam)<0) {
1474                 HeapFree( GetProcessHeap(), 0, msg32 );
1475                 return -1;
1476             }
1477             *plparam = (LPARAM)msg32;
1478             return 1;
1479         }
1480         else return 0;
1481     case WM_NOTIFY:
1482         *plparam = (LPARAM)MapSL(*plparam);
1483         return 0;
1484     case WM_ACTIVATEAPP:
1485         /* We need this when SetActiveWindow sends a Sendmessage16() to
1486          * a 32bit window. Might be superflous with 32bit interprocess
1487          * message queues. */
1488         if (*plparam) *plparam = HTASK_32( *plparam );
1489         return 0;
1490     case WM_NEXTMENU:
1491         {
1492             MDINEXTMENU *next = HeapAlloc( GetProcessHeap(), 0, sizeof(*next) );
1493             if (!next) return -1;
1494             next->hmenuIn = (HMENU)*plparam;
1495             next->hmenuNext = 0;
1496             next->hwndNext = 0;
1497             *plparam = (LPARAM)next;
1498             return 1;
1499         }
1500     case WM_PAINTCLIPBOARD:
1501     case WM_SIZECLIPBOARD:
1502         FIXME_(msg)("message %04x needs translation\n",msg16 );
1503         return -1;
1504     case WM_DDE_INITIATE:
1505     case WM_DDE_TERMINATE:
1506     case WM_DDE_UNADVISE:
1507     case WM_DDE_REQUEST:
1508         *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1509         return 0;
1510     case WM_DDE_ADVISE:
1511     case WM_DDE_DATA:
1512     case WM_DDE_POKE:
1513         {
1514             HANDLE16    lo16;
1515             ATOM        hi;
1516             UINT lo32 = 0;
1517
1518             *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1519             lo16 = LOWORD(*plparam);
1520             hi = HIWORD(*plparam);
1521             if (lo16 && !(lo32 = convert_handle_16_to_32(lo16, GMEM_DDESHARE)))
1522                 return -1;
1523             *plparam = PackDDElParam(msg16, lo32, hi);
1524         }
1525         return 0; /* FIXME don't know how to free allocated memory (handle)  !! */
1526     case WM_DDE_ACK:
1527         {
1528             UINT        lo, hi;
1529             int         flag = 0;
1530             char        buf[2];
1531
1532             *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1533
1534             lo = LOWORD(*plparam);
1535             hi = HIWORD(*plparam);
1536
1537             if (GlobalGetAtomNameA(hi, buf, 2) > 0) flag |= 1;
1538             if (GlobalSize16(hi) != 0) flag |= 2;
1539             switch (flag)
1540             {
1541             case 0:
1542                 if (hi)
1543                 {
1544                     MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1545                     hi = 0;
1546                 }
1547                 break;
1548             case 1:
1549                 break; /* atom, nothing to do */
1550             case 3:
1551                 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
1552                 /* fall thru */
1553             case 2:
1554                 hi = convert_handle_16_to_32(hi, GMEM_DDESHARE);
1555                 break;
1556             }
1557             *plparam = PackDDElParam(WM_DDE_ACK, lo, hi);
1558         }
1559         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1560     case WM_DDE_EXECUTE:
1561         *plparam = convert_handle_16_to_32(*plparam, GMEM_DDESHARE);
1562         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1563     default:  /* No translation needed */
1564         return 0;
1565     }
1566 }
1567
1568
1569 /**********************************************************************
1570  *           WINPROC_UnmapMsg16To32A
1571  *
1572  * Unmap a message that was mapped from 16- to 32-bit Ansi.
1573  */
1574 LRESULT WINPROC_UnmapMsg16To32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1575                                  LRESULT result )
1576 {
1577     switch(msg)
1578     {
1579     case WM_COMPAREITEM:
1580     case WM_DELETEITEM:
1581     case WM_DRAWITEM:
1582         HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
1583         break;
1584     case WM_MEASUREITEM:
1585         {
1586             MEASUREITEMSTRUCT16 *mis16;
1587             MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam;
1588             lParam = *(LPARAM *)(mis + 1);
1589             mis16 = MapSL(lParam);
1590             mis16->itemWidth  = (UINT16)mis->itemWidth;
1591             mis16->itemHeight = (UINT16)mis->itemHeight;
1592             HeapFree( GetProcessHeap(), 0, mis );
1593         }
1594         break;
1595     case WM_GETMINMAXINFO:
1596         {
1597             MINMAXINFO *mmi = (MINMAXINFO *)lParam;
1598             lParam = *(LPARAM *)(mmi + 1);
1599             STRUCT32_MINMAXINFO32to16( mmi, MapSL(lParam));
1600             HeapFree( GetProcessHeap(), 0, mmi );
1601         }
1602         break;
1603     case WM_MDICREATE:
1604         {
1605             MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1606             lParam = *(LPARAM *)(cs + 1);
1607             STRUCT32_MDICREATESTRUCT32Ato16( cs, MapSL(lParam) );
1608             HeapFree( GetProcessHeap(), 0, cs );
1609         }
1610         break;
1611     case WM_MDIGETACTIVE:
1612         result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL *)lParam) );
1613         HeapFree( GetProcessHeap(), 0, (BOOL *)lParam );
1614         break;
1615     case WM_NCCALCSIZE:
1616         {
1617             NCCALCSIZE_PARAMS16 *nc16;
1618             NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lParam;
1619             lParam = *(LPARAM *)(nc + 1);
1620             nc16 = MapSL(lParam);
1621             CONV_RECT32TO16( &nc->rgrc[0], &nc16->rgrc[0] );
1622             if (wParam)
1623             {
1624                 CONV_RECT32TO16( &nc->rgrc[1], &nc16->rgrc[1] );
1625                 CONV_RECT32TO16( &nc->rgrc[2], &nc16->rgrc[2] );
1626                 if (nc->lppos)
1627                 {
1628                     STRUCT32_WINDOWPOS32to16( nc->lppos, MapSL(nc16->lppos));
1629                     HeapFree( GetProcessHeap(), 0, nc->lppos );
1630                 }
1631             }
1632             HeapFree( GetProcessHeap(), 0, nc );
1633         }
1634         break;
1635     case WM_NCCREATE:
1636     case WM_CREATE:
1637         {
1638             CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1639             lParam = *(LPARAM *)(cs + 1);
1640             STRUCT32_CREATESTRUCT32Ato16( cs, MapSL(lParam) );
1641             HeapFree( GetProcessHeap(), 0, cs );
1642         }
1643         break;
1644     case WM_WINDOWPOSCHANGING:
1645     case WM_WINDOWPOSCHANGED:
1646         {
1647             WINDOWPOS *wp = (WINDOWPOS *)lParam;
1648             lParam = *(LPARAM *)(wp + 1);
1649             STRUCT32_WINDOWPOS32to16(wp, MapSL(lParam));
1650             HeapFree( GetProcessHeap(), 0, wp );
1651         }
1652         break;
1653     case WM_GETDLGCODE:
1654         if (lParam)
1655         {
1656             LPMSG msg32 = (LPMSG)lParam;
1657
1658             WINPROC_UnmapMsg16To32A( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1659                                      result);
1660             HeapFree( GetProcessHeap(), 0, msg32 );
1661         }
1662         break;
1663     case WM_NEXTMENU:
1664         {
1665             MDINEXTMENU *next = (MDINEXTMENU *)lParam;
1666             result = MAKELONG( HMENU_16(next->hmenuNext), HWND_16(next->hwndNext) );
1667             HeapFree( GetProcessHeap(), 0, next );
1668         }
1669         break;
1670     }
1671     return result;
1672 }
1673
1674
1675 /**********************************************************************
1676  *           WINPROC_MapMsg16To32W
1677  *
1678  * Map a message from 16- to 32-bit Unicode.
1679  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1680  */
1681 INT WINPROC_MapMsg16To32W( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1682                            WPARAM *pwparam32, LPARAM *plparam )
1683 {
1684     BYTE ch;
1685     WCHAR wch;
1686
1687     *pmsg32=(UINT)msg16;
1688     *pwparam32 = (WPARAM)wParam16;
1689     switch(msg16)
1690     {
1691     case WM_GETTEXT:
1692     case WM_SETTEXT:
1693     case WM_WININICHANGE:
1694     case WM_DEVMODECHANGE:
1695     case WM_ASKCBFORMATNAME:
1696         *plparam = (LPARAM)MapSL(*plparam);
1697         return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, pwparam32, plparam );
1698     case WM_GETTEXTLENGTH:
1699     case CB_GETLBTEXTLEN:
1700     case LB_GETTEXTLEN:
1701         return 1;  /* need to map result */
1702     case WM_NCCREATE:
1703     case WM_CREATE:
1704         {
1705             CREATESTRUCT16 *cs16 = MapSL(*plparam);
1706             CREATESTRUCTW *cs = (CREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
1707                                                 sizeof(*cs) + sizeof(LPARAM) );
1708             if (!cs) return -1;
1709             STRUCT32_CREATESTRUCT16to32A( cs16, (CREATESTRUCTA *)cs );
1710             cs->lpszName  = map_str_16_to_32W(cs16->lpszName);
1711             cs->lpszClass = map_str_16_to_32W(cs16->lpszClass);
1712             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1713             *plparam = (LPARAM)cs;
1714         }
1715         return 1;
1716     case WM_MDICREATE:
1717         {
1718             MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1719             MDICREATESTRUCTW *cs =
1720                 (MDICREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
1721                                                 sizeof(*cs) + sizeof(LPARAM) );
1722             if (!cs) return -1;
1723             STRUCT32_MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCTA *)cs );
1724             cs->szTitle = map_str_16_to_32W(cs16->szTitle);
1725             cs->szClass = map_str_16_to_32W(cs16->szClass);
1726             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1727             *plparam = (LPARAM)cs;
1728         }
1729         return 1;
1730     case WM_GETDLGCODE:
1731         if (*plparam)
1732         {
1733             LPMSG16 msg16 = MapSL(*plparam);
1734             LPMSG msg32 = (LPMSG)HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1735
1736             if (!msg32) return -1;
1737             msg32->hwnd = WIN_Handle32( msg16->hwnd );
1738             msg32->lParam = msg16->lParam;
1739             msg32->time = msg16->time;
1740             CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1741             /* this is right, right? */
1742             if (WINPROC_MapMsg16To32W(hwnd, msg16->message,msg16->wParam,
1743                                      &msg32->message,&msg32->wParam,
1744                                      &msg32->lParam)<0) {
1745                 HeapFree( GetProcessHeap(), 0, msg32 );
1746                 return -1;
1747             }
1748             *plparam = (LPARAM)msg32;
1749             return 1;
1750         }
1751         else return 0;
1752
1753     case WM_CHARTOITEM:
1754         ch = wParam16;
1755         MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1756         *pwparam32 = MAKEWPARAM( wch, HIWORD(*plparam) );
1757         *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1758         return 0;
1759     case WM_MENUCHAR:
1760         ch = wParam16;
1761         MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1762         *pwparam32 = MAKEWPARAM( wch, LOWORD(*plparam) );
1763         *plparam   = (LPARAM)HMENU_32(HIWORD(*plparam));
1764         return 0;
1765     case WM_CHAR:
1766     case WM_DEADCHAR:
1767     case WM_SYSCHAR:
1768     case WM_SYSDEADCHAR:
1769         ch = wParam16;
1770         MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1771         *pwparam32 = wch;
1772         return 0;
1773     case WM_IME_CHAR:
1774         {
1775             char ch[2];
1776             ch[0] = (wParam16 >> 8);
1777             ch[1] = wParam16 & 0xff;
1778             MultiByteToWideChar(CP_ACP, 0, ch, 2, &wch, 1);
1779             *pwparam32 = wch;
1780         }
1781         return 0;
1782
1783     default:  /* No Unicode translation needed */
1784         return WINPROC_MapMsg16To32A( hwnd, msg16, wParam16, pmsg32,
1785                                       pwparam32, plparam );
1786     }
1787 }
1788
1789
1790 /**********************************************************************
1791  *           WINPROC_UnmapMsg16To32W
1792  *
1793  * Unmap a message that was mapped from 16- to 32-bit Unicode.
1794  */
1795 LRESULT WINPROC_UnmapMsg16To32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1796                                  LRESULT result )
1797 {
1798     switch(msg)
1799     {
1800     case WM_GETTEXT:
1801     case WM_SETTEXT:
1802     case WM_GETTEXTLENGTH:
1803     case CB_GETLBTEXTLEN:
1804     case LB_GETTEXTLEN:
1805     case WM_ASKCBFORMATNAME:
1806         return WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result );
1807     case WM_NCCREATE:
1808     case WM_CREATE:
1809         {
1810             CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
1811             lParam = *(LPARAM *)(cs + 1);
1812             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs, MapSL(lParam) );
1813             unmap_str_16_to_32W( cs->lpszName );
1814             unmap_str_16_to_32W( cs->lpszClass );
1815             HeapFree( GetProcessHeap(), 0, cs );
1816         }
1817         break;
1818     case WM_MDICREATE:
1819         {
1820             MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
1821             lParam = *(LPARAM *)(cs + 1);
1822             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs, MapSL(lParam) );
1823             unmap_str_16_to_32W( cs->szTitle );
1824             unmap_str_16_to_32W( cs->szClass );
1825             HeapFree( GetProcessHeap(), 0, cs );
1826         }
1827         break;
1828     case WM_GETDLGCODE:
1829         if (lParam)
1830         {
1831             LPMSG msg32 = (LPMSG)lParam;
1832
1833             WINPROC_UnmapMsg16To32W( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1834                                      result);
1835             HeapFree( GetProcessHeap(), 0, msg32 );
1836         }
1837         break;
1838     default:
1839         return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1840     }
1841     return result;
1842 }
1843
1844 static HANDLE16 convert_handle_32_to_16(UINT src, unsigned int flags)
1845 {
1846     HANDLE16    dst;
1847     UINT        sz = GlobalSize((HANDLE)src);
1848     LPSTR       ptr16, ptr32;
1849
1850     if (!(dst = GlobalAlloc16(flags, sz)))
1851         return 0;
1852     ptr32 = GlobalLock((HANDLE)src);
1853     ptr16 = GlobalLock16(dst);
1854     if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr16, ptr32, sz);
1855     GlobalUnlock((HANDLE)src);
1856     GlobalUnlock16(dst);
1857
1858     return dst;
1859 }
1860
1861
1862 /**********************************************************************
1863  *           WINPROC_MapMsg32ATo16
1864  *
1865  * Map a message from 32-bit Ansi to 16-bit.
1866  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1867  */
1868 INT WINPROC_MapMsg32ATo16( HWND hwnd, UINT msg32, WPARAM wParam32,
1869                              UINT16 *pmsg16, WPARAM16 *pwparam16,
1870                              LPARAM *plparam )
1871 {
1872     *pmsg16 = (UINT16)msg32;
1873     *pwparam16 = (WPARAM16)LOWORD(wParam32);
1874     switch(msg32)
1875     {
1876     case BM_GETCHECK:
1877     case BM_SETCHECK:
1878     case BM_GETSTATE:
1879     case BM_SETSTATE:
1880     case BM_SETSTYLE:
1881         *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK);
1882         return 0;
1883
1884     case EM_GETSEL:
1885     case EM_GETRECT:
1886     case EM_SETRECT:
1887     case EM_SETRECTNP:
1888     case EM_SCROLL:
1889     case EM_LINESCROLL:
1890     case EM_SCROLLCARET:
1891     case EM_GETMODIFY:
1892     case EM_SETMODIFY:
1893     case EM_GETLINECOUNT:
1894     case EM_LINEINDEX:
1895     case EM_SETHANDLE:
1896     case EM_GETHANDLE:
1897     case EM_GETTHUMB:
1898     case EM_LINELENGTH:
1899     case EM_REPLACESEL:
1900     case EM_GETLINE:
1901     case EM_LIMITTEXT:
1902     case EM_CANUNDO:
1903     case EM_UNDO:
1904     case EM_FMTLINES:
1905     case EM_LINEFROMCHAR:
1906     case EM_SETTABSTOPS:
1907     case EM_SETPASSWORDCHAR:
1908     case EM_EMPTYUNDOBUFFER:
1909     case EM_GETFIRSTVISIBLELINE:
1910     case EM_SETREADONLY:
1911     case EM_SETWORDBREAKPROC:
1912     case EM_GETWORDBREAKPROC:
1913     case EM_GETPASSWORDCHAR:
1914         *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL);
1915         return 0;
1916
1917     case LB_CARETOFF:
1918     case LB_CARETON:
1919     case LB_DELETESTRING:
1920     case LB_GETANCHORINDEX:
1921     case LB_GETCARETINDEX:
1922     case LB_GETCOUNT:
1923     case LB_GETCURSEL:
1924     case LB_GETHORIZONTALEXTENT:
1925     case LB_GETITEMDATA:
1926     case LB_GETITEMHEIGHT:
1927     case LB_GETSEL:
1928     case LB_GETSELCOUNT:
1929     case LB_GETTEXTLEN:
1930     case LB_GETTOPINDEX:
1931     case LB_RESETCONTENT:
1932     case LB_SELITEMRANGE:
1933     case LB_SELITEMRANGEEX:
1934     case LB_SETANCHORINDEX:
1935     case LB_SETCARETINDEX:
1936     case LB_SETCOLUMNWIDTH:
1937     case LB_SETCURSEL:
1938     case LB_SETHORIZONTALEXTENT:
1939     case LB_SETITEMDATA:
1940     case LB_SETITEMHEIGHT:
1941     case LB_SETSEL:
1942     case LB_SETTOPINDEX:
1943         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1944         return 0;
1945     case CB_DELETESTRING:
1946     case CB_GETCOUNT:
1947     case CB_GETLBTEXTLEN:
1948     case CB_LIMITTEXT:
1949     case CB_RESETCONTENT:
1950     case CB_SETEDITSEL:
1951     case CB_GETCURSEL:
1952     case CB_SETCURSEL:
1953     case CB_SHOWDROPDOWN:
1954     case CB_SETITEMDATA:
1955     case CB_SETITEMHEIGHT:
1956     case CB_GETITEMHEIGHT:
1957     case CB_SETEXTENDEDUI:
1958     case CB_GETEXTENDEDUI:
1959     case CB_GETDROPPEDSTATE:
1960         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1961         return 0;
1962     case CB_GETEDITSEL:
1963         *pmsg16 = CB_GETEDITSEL16;
1964         return 1;
1965
1966     case LB_ADDSTRING:
1967     case LB_FINDSTRING:
1968     case LB_FINDSTRINGEXACT:
1969     case LB_INSERTSTRING:
1970     case LB_SELECTSTRING:
1971     case LB_DIR:
1972     case LB_ADDFILE:
1973         *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1974         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1975         return 1;
1976
1977     case CB_ADDSTRING:
1978     case CB_FINDSTRING:
1979     case CB_FINDSTRINGEXACT:
1980     case CB_INSERTSTRING:
1981     case CB_SELECTSTRING:
1982     case CB_DIR:
1983         *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1984         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1985         return 1;
1986
1987     case LB_GETITEMRECT:
1988         {
1989             RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1990             if (!rect) return -1;
1991             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
1992             *plparam = MapLS( rect );
1993         }
1994         *pmsg16 = LB_GETITEMRECT16;
1995         return 1;
1996     case LB_GETSELITEMS:
1997         {
1998             LPINT16 items;
1999             *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
2000             if (!(items = HeapAlloc( GetProcessHeap(), 0,
2001                                      *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
2002             *((LPARAM *)items)++ = *plparam;  /* Store the previous lParam */
2003             *plparam = MapLS( items );
2004         }
2005         *pmsg16 = LB_GETSELITEMS16;
2006         return 1;
2007     case LB_SETTABSTOPS:
2008         if (wParam32)
2009         {
2010             INT i;
2011             LPINT16 stops;
2012             *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
2013             if (!(stops = HeapAlloc( GetProcessHeap(), 0,
2014                                      *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
2015             for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT)*plparam+i);
2016             *plparam = MapLS( stops );
2017             return 1;
2018         }
2019         *pmsg16 = LB_SETTABSTOPS16;
2020         return 0;
2021
2022     case CB_GETDROPPEDCONTROLRECT:
2023         {
2024             RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
2025             if (!rect) return -1;
2026             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
2027             *plparam = (LPARAM)MapLS(rect);
2028         }
2029         *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
2030         return 1;
2031
2032     case LB_GETTEXT:
2033         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
2034         *pmsg16 = LB_GETTEXT16;
2035         return 1;
2036
2037     case CB_GETLBTEXT:
2038         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
2039         *pmsg16 = CB_GETLBTEXT16;
2040         return 1;
2041
2042     case EM_SETSEL:
2043         *pwparam16 = 0;
2044         *plparam = MAKELONG( (INT16)(INT)wParam32, (INT16)*plparam );
2045         *pmsg16 = EM_SETSEL16;
2046         return 0;
2047
2048     case WM_ACTIVATE:
2049     case WM_CHARTOITEM:
2050     case WM_COMMAND:
2051     case WM_VKEYTOITEM:
2052         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2053         return 0;
2054     case WM_HSCROLL:
2055     case WM_VSCROLL:
2056         *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
2057         return 0;
2058     case WM_CTLCOLORMSGBOX:
2059     case WM_CTLCOLOREDIT:
2060     case WM_CTLCOLORLISTBOX:
2061     case WM_CTLCOLORBTN:
2062     case WM_CTLCOLORDLG:
2063     case WM_CTLCOLORSCROLLBAR:
2064     case WM_CTLCOLORSTATIC:
2065         *pmsg16  = WM_CTLCOLOR;
2066         *plparam = MAKELPARAM( (HWND16)*plparam,
2067                                (WORD)msg32 - WM_CTLCOLORMSGBOX );
2068         return 0;
2069     case WM_COMPAREITEM:
2070         {
2071             COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)*plparam;
2072             COMPAREITEMSTRUCT16 *cis = HeapAlloc( GetProcessHeap(), 0, sizeof(COMPAREITEMSTRUCT16));
2073             if (!cis) return -1;
2074             cis->CtlType    = (UINT16)cis32->CtlType;
2075             cis->CtlID      = (UINT16)cis32->CtlID;
2076             cis->hwndItem   = HWND_16( cis32->hwndItem );
2077             cis->itemID1    = (UINT16)cis32->itemID1;
2078             cis->itemData1  = cis32->itemData1;
2079             cis->itemID2    = (UINT16)cis32->itemID2;
2080             cis->itemData2  = cis32->itemData2;
2081             *plparam = MapLS( cis );
2082         }
2083         return 1;
2084     case WM_DELETEITEM:
2085         {
2086             DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)*plparam;
2087             DELETEITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DELETEITEMSTRUCT16) );
2088             if (!dis) return -1;
2089             dis->CtlType  = (UINT16)dis32->CtlType;
2090             dis->CtlID    = (UINT16)dis32->CtlID;
2091             dis->itemID   = (UINT16)dis32->itemID;
2092             dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem)
2093                                                        : HWND_16( dis32->hwndItem );
2094             dis->itemData = dis32->itemData;
2095             *plparam = MapLS( dis );
2096         }
2097         return 1;
2098     case WM_DRAWITEM:
2099         {
2100             DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)*plparam;
2101             DRAWITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DRAWITEMSTRUCT16) );
2102             if (!dis) return -1;
2103             dis->CtlType    = (UINT16)dis32->CtlType;
2104             dis->CtlID      = (UINT16)dis32->CtlID;
2105             dis->itemID     = (UINT16)dis32->itemID;
2106             dis->itemAction = (UINT16)dis32->itemAction;
2107             dis->itemState  = (UINT16)dis32->itemState;
2108             dis->hwndItem   = HWND_16( dis32->hwndItem );
2109             dis->hDC        = HDC_16(dis32->hDC);
2110             dis->itemData   = dis32->itemData;
2111             CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
2112             *plparam = MapLS( dis );
2113         }
2114         return 1;
2115     case WM_MEASUREITEM:
2116         {
2117             MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)*plparam;
2118             MEASUREITEMSTRUCT16 *mis = HeapAlloc( GetProcessHeap(), 0, sizeof(*mis)+sizeof(LPARAM));
2119             if (!mis) return -1;
2120             mis->CtlType    = (UINT16)mis32->CtlType;
2121             mis->CtlID      = (UINT16)mis32->CtlID;
2122             mis->itemID     = (UINT16)mis32->itemID;
2123             mis->itemWidth  = (UINT16)mis32->itemWidth;
2124             mis->itemHeight = (UINT16)mis32->itemHeight;
2125             mis->itemData   = mis32->itemData;
2126             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
2127             *plparam = MapLS( mis );
2128         }
2129         return 1;
2130     case WM_GETMINMAXINFO:
2131         {
2132             MINMAXINFO16 *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM) );
2133             if (!mmi) return -1;
2134             STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)*plparam, mmi );
2135             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
2136             *plparam = MapLS( mmi );
2137         }
2138         return 1;
2139     case WM_GETTEXT:
2140     case WM_ASKCBFORMATNAME:
2141         {
2142             LPSTR str;
2143             *pwparam16 = (WPARAM16)min( wParam32, 0xff80 ); /* Must be < 64K */
2144             if (!(str = HeapAlloc( GetProcessHeap(), 0, *pwparam16 + sizeof(LPARAM)))) return -1;
2145             *((LPARAM *)str)++ = *plparam;  /* Store the previous lParam */
2146             *plparam = MapLS( str );
2147         }
2148         return 1;
2149     case WM_MDICREATE:
2150         {
2151             MDICREATESTRUCT16 *cs;
2152             MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)*plparam;
2153
2154             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2155             STRUCT32_MDICREATESTRUCT32Ato16( cs32, cs );
2156             cs->szTitle = MapLS( cs32->szTitle );
2157             cs->szClass = MapLS( cs32->szClass );
2158             *plparam = MapLS( cs );
2159         }
2160         return 1;
2161     case WM_MDIGETACTIVE:
2162         return 1;
2163     case WM_MDISETMENU:
2164         *plparam   = MAKELPARAM( (HMENU16)LOWORD(wParam32),
2165                                  (HMENU16)LOWORD(*plparam) );
2166         *pwparam16 = (*plparam == 0);
2167         return 0;
2168     case WM_MENUSELECT:
2169         if(HIWORD(wParam32) & MF_POPUP)
2170         {
2171             HMENU hmenu;
2172             if (((UINT)HIWORD(wParam32) != 0xFFFF) || (*plparam))
2173             {
2174                 if((hmenu = GetSubMenu((HMENU)*plparam, *pwparam16)))
2175                     *pwparam16=HMENU_16(hmenu);
2176             }
2177         }
2178         /* fall through */
2179     case WM_MENUCHAR:
2180         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2181         return 0;
2182     case WM_MDIACTIVATE:
2183         if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
2184         {
2185             *pwparam16 = ((HWND)*plparam == hwnd);
2186             *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
2187                                    (HWND16)LOWORD(wParam32) );
2188         }
2189         else
2190         {
2191             *pwparam16 = HWND_16( (HWND)wParam32 );
2192             *plparam = 0;
2193         }
2194         return 0;
2195     case WM_NCCALCSIZE:
2196         {
2197             NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)*plparam;
2198             NCCALCSIZE_PARAMS16 *nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM));
2199             if (!nc) return -1;
2200
2201             CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
2202             if (wParam32)
2203             {
2204                 WINDOWPOS16 *wp;
2205                 CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
2206                 CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
2207                 if (!(wp = HeapAlloc( GetProcessHeap(), 0, sizeof(WINDOWPOS16) )))
2208                 {
2209                     HeapFree( GetProcessHeap(), 0, nc );
2210                     return -1;
2211                 }
2212                 STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
2213                 nc->lppos = MapLS( wp );
2214             }
2215             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
2216             *plparam = MapLS( nc );
2217         }
2218         return 1;
2219     case WM_NCCREATE:
2220     case WM_CREATE:
2221         {
2222             CREATESTRUCT16 *cs;
2223             CREATESTRUCTA *cs32 = (CREATESTRUCTA *)*plparam;
2224
2225             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2226             STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
2227             cs->lpszName  = MapLS( cs32->lpszName );
2228             cs->lpszClass = MapLS( cs32->lpszClass );
2229             *plparam = MapLS( cs );
2230         }
2231         return 1;
2232     case WM_PARENTNOTIFY:
2233         if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
2234             *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
2235         /* else nothing to do */
2236         return 0;
2237     case WM_NOTIFY:
2238         *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
2239         return 1;
2240     case WM_SETTEXT:
2241     case WM_WININICHANGE:
2242     case WM_DEVMODECHANGE:
2243         *plparam = MapLS( (LPSTR)*plparam );
2244         return 1;
2245     case WM_WINDOWPOSCHANGING:
2246     case WM_WINDOWPOSCHANGED:
2247         {
2248             WINDOWPOS16 *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
2249             if (!wp) return -1;
2250             STRUCT32_WINDOWPOS32to16( (WINDOWPOS *)*plparam, wp );
2251             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
2252             *plparam = MapLS( wp );
2253         }
2254         return 1;
2255     case WM_GETDLGCODE:
2256          if (*plparam) {
2257             LPMSG msg32 = (LPMSG) *plparam;
2258             LPMSG16 msg16 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG16) );
2259
2260             if (!msg16) return -1;
2261             msg16->hwnd = HWND_16( msg32->hwnd );
2262             msg16->lParam = msg32->lParam;
2263             msg16->time = msg32->time;
2264             CONV_POINT32TO16(&msg32->pt,&msg16->pt);
2265             /* this is right, right? */
2266             if (WINPROC_MapMsg32ATo16(msg32->hwnd,msg32->message,msg32->wParam,
2267                          &msg16->message,&msg16->wParam, &msg16->lParam)<0)
2268             {
2269                 HeapFree( GetProcessHeap(), 0, msg16 );
2270                 return -1;
2271             }
2272             *plparam = MapLS( msg16 );
2273             return 1;
2274         }
2275         return 0;
2276
2277     case WM_ACTIVATEAPP:
2278         if (*plparam) *plparam = HTASK_16( (HANDLE)*plparam );
2279         return 0;
2280     case WM_NEXTMENU:
2281         {
2282             MDINEXTMENU *next = (MDINEXTMENU *)*plparam;
2283             *plparam = (LPARAM)next->hmenuIn;
2284             return 1;
2285         }
2286     case WM_PAINTCLIPBOARD:
2287     case WM_SIZECLIPBOARD:
2288         FIXME_(msg)("message %04x needs translation\n", msg32 );
2289         return -1;
2290     /* following messages should not be sent to 16-bit apps */
2291     case WM_SIZING:
2292     case WM_MOVING:
2293     case WM_CAPTURECHANGED:
2294     case WM_STYLECHANGING:
2295     case WM_STYLECHANGED:
2296         return -1;
2297     case WM_DDE_INITIATE:
2298     case WM_DDE_TERMINATE:
2299     case WM_DDE_UNADVISE:
2300     case WM_DDE_REQUEST:
2301         *pwparam16 = HWND_16((HWND)wParam32);
2302         return 0;
2303     case WM_DDE_ADVISE:
2304     case WM_DDE_DATA:
2305     case WM_DDE_POKE:
2306         {
2307             UINT lo32, hi;
2308             HANDLE16    lo16 = 0;
2309
2310             *pwparam16 = HWND_16((HWND)wParam32);
2311             UnpackDDElParam(msg32, *plparam, &lo32, &hi);
2312             if (lo32 && !(lo16 = convert_handle_32_to_16(lo32, GMEM_DDESHARE)))
2313                 return -1;
2314             *plparam = MAKELPARAM(lo16, hi);
2315         }
2316         return 0; /* FIXME don't know how to free allocated memory (handle)  !! */
2317     case WM_DDE_ACK:
2318         {
2319             UINT        lo, hi;
2320             int         flag = 0;
2321             char        buf[2];
2322
2323             *pwparam16 = HWND_16((HWND)wParam32);
2324
2325             UnpackDDElParam(msg32, *plparam, &lo, &hi);
2326
2327             if (GlobalGetAtomNameA((ATOM)hi, buf, sizeof(buf)) > 0) flag |= 1;
2328             if (GlobalSize((HANDLE)hi) != 0) flag |= 2;
2329             switch (flag)
2330             {
2331             case 0:
2332                 if (hi)
2333                 {
2334                     MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
2335                     hi = 0;
2336                 }
2337                 break;
2338             case 1:
2339                 break; /* atom, nothing to do */
2340             case 3:
2341                 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
2342                 /* fall thru */
2343             case 2:
2344                 hi = convert_handle_32_to_16(hi, GMEM_DDESHARE);
2345                 break;
2346             }
2347             *plparam = MAKELPARAM(lo, hi);
2348         }
2349         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2350     case WM_DDE_EXECUTE:
2351         *plparam = convert_handle_32_to_16(*plparam, GMEM_DDESHARE);
2352         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2353     default:  /* No translation needed */
2354         return 0;
2355     }
2356 }
2357
2358
2359 /**********************************************************************
2360  *           WINPROC_UnmapMsg32ATo16
2361  *
2362  * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
2363  */
2364 void WINPROC_UnmapMsg32ATo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2365                               MSGPARAM16* p16 )
2366 {
2367     switch(msg)
2368     {
2369     case LB_ADDFILE:
2370     case LB_ADDSTRING:
2371     case LB_DIR:
2372     case LB_FINDSTRING:
2373     case LB_FINDSTRINGEXACT:
2374     case LB_INSERTSTRING:
2375     case LB_SELECTSTRING:
2376     case LB_GETTEXT:
2377     case CB_ADDSTRING:
2378     case CB_FINDSTRING:
2379     case CB_FINDSTRINGEXACT:
2380     case CB_INSERTSTRING:
2381     case CB_SELECTSTRING:
2382     case CB_DIR:
2383     case CB_GETLBTEXT:
2384     case WM_SETTEXT:
2385     case WM_WININICHANGE:
2386     case WM_DEVMODECHANGE:
2387         UnMapLS( (SEGPTR)p16->lParam );
2388         break;
2389     case LB_SETTABSTOPS:
2390     case WM_COMPAREITEM:
2391     case WM_DELETEITEM:
2392     case WM_DRAWITEM:
2393         {
2394             void *ptr = MapSL( p16->lParam );
2395             UnMapLS( p16->lParam );
2396             HeapFree( GetProcessHeap(), 0, ptr );
2397         }
2398         break;
2399     case CB_GETDROPPEDCONTROLRECT:
2400     case LB_GETITEMRECT:
2401         {
2402             RECT16 *rect = MapSL(p16->lParam);
2403             UnMapLS( p16->lParam );
2404             p16->lParam = *(LPARAM *)(rect + 1);
2405             CONV_RECT16TO32( rect, (RECT *)(p16->lParam));
2406             HeapFree( GetProcessHeap(), 0, rect );
2407         }
2408         break;
2409     case LB_GETSELITEMS:
2410         {
2411             INT i;
2412             LPINT16 items = MapSL(p16->lParam);
2413             UnMapLS( p16->lParam );
2414             p16->lParam = *((LPARAM *)items - 1);
2415             for (i = 0; i < p16->wParam; i++) *((LPINT)(p16->lParam) + i) = items[i];
2416             HeapFree( GetProcessHeap(), 0, (LPARAM *)items - 1 );
2417         }
2418         break;
2419
2420     case CB_GETEDITSEL:
2421         if( wParam )
2422             *((PUINT)(wParam)) = LOWORD(p16->lResult);
2423         if( lParam )
2424             *((PUINT)(lParam)) = HIWORD(p16->lResult);  /* FIXME: substract 1? */
2425         break;
2426
2427     case WM_MEASUREITEM:
2428         {
2429             MEASUREITEMSTRUCT16 *mis = MapSL(p16->lParam);
2430             MEASUREITEMSTRUCT *mis32 = *(MEASUREITEMSTRUCT **)(mis + 1);
2431             mis32->itemWidth  = mis->itemWidth;
2432             mis32->itemHeight = mis->itemHeight;
2433             UnMapLS( p16->lParam );
2434             HeapFree( GetProcessHeap(), 0, mis );
2435         }
2436         break;
2437     case WM_GETMINMAXINFO:
2438         {
2439             MINMAXINFO16 *mmi = MapSL(p16->lParam);
2440             UnMapLS( p16->lParam );
2441             p16->lParam = *(LPARAM *)(mmi + 1);
2442             STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO *)(p16->lParam) );
2443             HeapFree( GetProcessHeap(), 0, mmi );
2444         }
2445         break;
2446     case WM_GETTEXT:
2447     case WM_ASKCBFORMATNAME:
2448         {
2449             LPSTR str = MapSL(p16->lParam);
2450             UnMapLS( p16->lParam );
2451             p16->lParam = *((LPARAM *)str - 1);
2452             lstrcpynA( (LPSTR)(p16->lParam), str, p16->wParam );
2453             HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2454         }
2455         break;
2456     case WM_MDICREATE:
2457         {
2458             MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2459             UnMapLS( cs->szTitle );
2460             UnMapLS( cs->szClass );
2461             UnMapLS( p16->lParam );
2462             HeapFree( GetProcessHeap(), 0, cs );
2463         }
2464         break;
2465     case WM_MDIGETACTIVE:
2466         if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(p16->lResult);
2467         p16->lResult = (LRESULT)WIN_Handle32( LOWORD(p16->lResult) );
2468         break;
2469     case WM_NCCALCSIZE:
2470         {
2471             NCCALCSIZE_PARAMS *nc32;
2472             NCCALCSIZE_PARAMS16 *nc = MapSL(p16->lParam);
2473             UnMapLS( p16->lParam );
2474             p16->lParam = *(LPARAM *)(nc + 1);
2475             nc32 = (NCCALCSIZE_PARAMS *)(p16->lParam);
2476             CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
2477             if (p16->wParam)
2478             {
2479                 WINDOWPOS16 *pos = MapSL(nc->lppos);
2480                 UnMapLS( nc->lppos );
2481                 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
2482                 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
2483                 STRUCT32_WINDOWPOS16to32( pos, nc32->lppos );
2484                 HeapFree( GetProcessHeap(), 0, pos );
2485             }
2486             HeapFree( GetProcessHeap(), 0, nc );
2487         }
2488         break;
2489     case WM_NCCREATE:
2490     case WM_CREATE:
2491         {
2492             CREATESTRUCT16 *cs = MapSL(p16->lParam);
2493             UnMapLS( p16->lParam );
2494             UnMapLS( cs->lpszName );
2495             UnMapLS( cs->lpszClass );
2496             HeapFree( GetProcessHeap(), 0, cs );
2497         }
2498         break;
2499     case WM_WINDOWPOSCHANGING:
2500     case WM_WINDOWPOSCHANGED:
2501         {
2502             WINDOWPOS16 *wp = MapSL(p16->lParam);
2503             UnMapLS( p16->lParam );
2504             p16->lParam = *(LPARAM *)(wp + 1);
2505             STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS *)p16->lParam );
2506             HeapFree( GetProcessHeap(), 0, wp );
2507         }
2508         break;
2509     case WM_NOTIFY:
2510         UnMapLS(p16->lParam);
2511         break;
2512     case WM_GETDLGCODE:
2513         if (p16->lParam)
2514         {
2515             LPMSG16 msg16 = MapSL(p16->lParam);
2516             MSGPARAM16 msgp16;
2517             UnMapLS( p16->lParam );
2518             msgp16.wParam=msg16->wParam;
2519             msgp16.lParam=msg16->lParam;
2520             WINPROC_UnmapMsg32ATo16(((LPMSG)lParam)->hwnd, ((LPMSG)lParam)->message,
2521                     ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam,
2522                     &msgp16 );
2523             HeapFree( GetProcessHeap(), 0, msg16 );
2524         }
2525         break;
2526     case WM_NEXTMENU:
2527         {
2528             MDINEXTMENU *next = (MDINEXTMENU *)lParam;
2529             next->hmenuNext = HMENU_32( LOWORD(p16->lResult) );
2530             next->hwndNext = WIN_Handle32( HIWORD(p16->lResult) );
2531             p16->lResult = 0;
2532         }
2533         break;
2534     }
2535 }
2536
2537
2538 /**********************************************************************
2539  *           WINPROC_MapMsg32WTo16
2540  *
2541  * Map a message from 32-bit Unicode to 16-bit.
2542  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
2543  */
2544 INT WINPROC_MapMsg32WTo16( HWND hwnd, UINT msg32, WPARAM wParam32,
2545                              UINT16 *pmsg16, WPARAM16 *pwparam16,
2546                              LPARAM *plparam )
2547 {
2548     BYTE ch;
2549     WCHAR wch;
2550
2551     *pmsg16    = LOWORD(msg32);
2552     *pwparam16 = LOWORD(wParam32);
2553     switch(msg32)
2554     {
2555     case LB_ADDSTRING:
2556     case LB_FINDSTRING:
2557     case LB_FINDSTRINGEXACT:
2558     case LB_INSERTSTRING:
2559     case LB_SELECTSTRING:
2560     case LB_DIR:
2561     case LB_ADDFILE:
2562         *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2563         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2564         return 1;
2565
2566     case CB_ADDSTRING:
2567     case CB_FINDSTRING:
2568     case CB_FINDSTRINGEXACT:
2569     case CB_INSERTSTRING:
2570     case CB_SELECTSTRING:
2571     case CB_DIR:
2572         *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2573         *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING);
2574         return 1;
2575
2576     case WM_NCCREATE:
2577     case WM_CREATE:
2578         {
2579             CREATESTRUCT16 *cs;
2580             CREATESTRUCTW *cs32 = (CREATESTRUCTW *)*plparam;
2581
2582             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2583             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs32, cs );
2584             cs->lpszName  = map_str_32W_to_16( cs32->lpszName );
2585             cs->lpszClass = map_str_32W_to_16( cs32->lpszClass );
2586             *plparam   = MapLS(cs);
2587         }
2588         return 1;
2589     case WM_MDICREATE:
2590         {
2591             MDICREATESTRUCT16 *cs;
2592             MDICREATESTRUCTW *cs32 = (MDICREATESTRUCTW *)*plparam;
2593
2594             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2595             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs32, cs );
2596             cs->szTitle = map_str_32W_to_16( cs32->szTitle );
2597             cs->szClass = map_str_32W_to_16( cs32->szClass );
2598             *plparam   = MapLS(cs);
2599         }
2600         return 1;
2601     case WM_SETTEXT:
2602     case WM_WININICHANGE:
2603     case WM_DEVMODECHANGE:
2604         *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2605         return 1;
2606     case LB_GETTEXT:
2607     case CB_GETLBTEXT:
2608         if ( WINPROC_TestLBForStr( hwnd ))
2609         {
2610             LPSTR str = HeapAlloc( GetProcessHeap(), 0, 256 ); /* FIXME: fixed sized buffer */
2611             if (!str) return -1;
2612             *pmsg16    = (msg32 == LB_GETTEXT)? LB_GETTEXT16 : CB_GETLBTEXT16;
2613             *plparam   = (LPARAM)MapLS(str);
2614         }
2615         return 1;
2616
2617     case WM_CHARTOITEM:
2618         wch = LOWORD(wParam32);
2619         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2620         *pwparam16 = ch;
2621         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2622         return 0;
2623     case WM_MENUCHAR:
2624         wch = LOWORD(wParam32);
2625         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2626         *pwparam16 = ch;
2627         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2628         return 0;
2629     case WM_CHAR:
2630     case WM_DEADCHAR:
2631     case WM_SYSCHAR:
2632     case WM_SYSDEADCHAR:
2633         wch = wParam32;
2634         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2635         *pwparam16 = ch;
2636         return 0;
2637
2638     case WM_IME_CHAR:
2639         {
2640             BYTE ch[2];
2641
2642             wch = wParam32;
2643             ch[1] = 0;
2644             WideCharToMultiByte( CP_ACP, 0, &wch, 1, ch, 2, NULL, NULL );
2645             *pwparam16 = (ch[0] << 8) | ch[1];
2646         }
2647         return 0;
2648
2649     default:  /* No Unicode translation needed (?) */
2650         return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2651                                       pwparam16, plparam );
2652     }
2653 }
2654
2655
2656 /**********************************************************************
2657  *           WINPROC_UnmapMsg32WTo16
2658  *
2659  * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2660  */
2661 void WINPROC_UnmapMsg32WTo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2662                               MSGPARAM16* p16 )
2663 {
2664     switch(msg)
2665     {
2666     case LB_ADDSTRING:
2667     case LB_FINDSTRING:
2668     case LB_FINDSTRINGEXACT:
2669     case LB_INSERTSTRING:
2670     case LB_SELECTSTRING:
2671     case LB_DIR:
2672     case LB_ADDFILE:
2673     case CB_ADDSTRING:
2674     case CB_FINDSTRING:
2675     case CB_FINDSTRINGEXACT:
2676     case CB_INSERTSTRING:
2677     case CB_SELECTSTRING:
2678     case CB_DIR:
2679     case WM_SETTEXT:
2680     case WM_WININICHANGE:
2681     case WM_DEVMODECHANGE:
2682         unmap_str_32W_to_16( p16->lParam );
2683         break;
2684     case WM_NCCREATE:
2685     case WM_CREATE:
2686         {
2687             CREATESTRUCT16 *cs = MapSL(p16->lParam);
2688             UnMapLS( p16->lParam );
2689             unmap_str_32W_to_16( cs->lpszName );
2690             unmap_str_32W_to_16( cs->lpszClass );
2691             HeapFree( GetProcessHeap(), 0, cs );
2692         }
2693         break;
2694     case WM_MDICREATE:
2695         {
2696             MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2697             UnMapLS( p16->lParam );
2698             unmap_str_32W_to_16( cs->szTitle );
2699             unmap_str_32W_to_16( cs->szClass );
2700             HeapFree( GetProcessHeap(), 0, cs );
2701         }
2702         break;
2703     case WM_GETTEXT:
2704     case WM_ASKCBFORMATNAME:
2705         {
2706             LPSTR str = MapSL(p16->lParam);
2707             UnMapLS( p16->lParam );
2708             p16->lParam = *((LPARAM *)str - 1);
2709             MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)p16->lParam, 0x7fffffff );
2710             HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2711         }
2712         break;
2713     case LB_GETTEXT:
2714     case CB_GETLBTEXT:
2715         if ( WINPROC_TestLBForStr( hwnd ))
2716         {
2717             LPSTR str = MapSL(p16->lParam);
2718             UnMapLS( p16->lParam );
2719             MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff );
2720             HeapFree( GetProcessHeap(), 0, (LPARAM *)str );
2721         }
2722         break;
2723     default:
2724         WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, p16 );
2725         break;
2726     }
2727 }
2728
2729
2730 /**********************************************************************
2731  *           WINPROC_CallProc32ATo32W
2732  *
2733  * Call a window procedure, translating args from Ansi to Unicode.
2734  */
2735 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC func, HWND hwnd,
2736                                          UINT msg, WPARAM wParam,
2737                                          LPARAM lParam )
2738 {
2739     LRESULT result;
2740     int unmap;
2741
2742     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2743         func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2744
2745     if( (unmap = WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam )) == -1) {
2746         ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2747                        SPY_GetMsgName(msg, hwnd), wParam, lParam );
2748         return 0;
2749     }
2750     result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2751     if (unmap) result = WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result );
2752     return result;
2753 }
2754
2755
2756 /**********************************************************************
2757  *           WINPROC_CallProc32WTo32A
2758  *
2759  * Call a window procedure, translating args from Unicode to Ansi.
2760  */
2761 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC func, HWND hwnd,
2762                                          UINT msg, WPARAM wParam,
2763                                          LPARAM lParam )
2764 {
2765     LRESULT result;
2766     int unmap;
2767
2768     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2769         func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2770
2771     if ((unmap = WINPROC_MapMsg32WTo32A( hwnd, msg, &wParam, &lParam )) == -1) {
2772         ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2773                        SPY_GetMsgName(msg, hwnd), wParam, lParam );
2774         return 0;
2775     }
2776     result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2777     if( unmap ) WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam );
2778     return result;
2779 }
2780
2781
2782 /**********************************************************************
2783  *           __wine_call_wndproc_32A   (USER.1010)
2784  */
2785 LRESULT WINAPI __wine_call_wndproc_32A( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2786                                         WNDPROC func )
2787 {
2788     LRESULT result;
2789     UINT msg32;
2790     WPARAM wParam32;
2791     HWND hwnd32 = WIN_Handle32( hwnd );
2792
2793     if (WINPROC_MapMsg16To32A( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2794         return 0;
2795     result = WINPROC_CallWndProc( func, hwnd32, msg32, wParam32, lParam );
2796     return WINPROC_UnmapMsg16To32A( hwnd32, msg32, wParam32, lParam, result );
2797 }
2798
2799
2800 /**********************************************************************
2801  *           __wine_call_wndproc_32W   (USER.1011)
2802  */
2803 LRESULT WINAPI  __wine_call_wndproc_32W( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2804                                          WNDPROC func )
2805 {
2806     LRESULT result;
2807     UINT msg32;
2808     WPARAM wParam32;
2809     HWND hwnd32 = WIN_Handle32( hwnd );
2810
2811     if (WINPROC_MapMsg16To32W( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2812         return 0;
2813     result = WINPROC_CallWndProc( func, hwnd32, msg32, wParam32, lParam );
2814     return WINPROC_UnmapMsg16To32W( hwnd32, msg32, wParam32, lParam, result );
2815 }
2816
2817
2818 /**********************************************************************
2819  *           WINPROC_CallProc32ATo16
2820  *
2821  * Call a 16-bit window procedure, translating the 32-bit args.
2822  */
2823 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd,
2824                                                UINT msg, WPARAM wParam,
2825                                                LPARAM lParam )
2826 {
2827     UINT16 msg16;
2828     MSGPARAM16 mp16;
2829
2830     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2831         func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2832
2833     mp16.lParam = lParam;
2834     if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, &msg16, &mp16.wParam, &mp16.lParam ) == -1)
2835         return 0;
2836     mp16.lResult = WINPROC_CallWndProc16( func, HWND_16(hwnd), msg16,
2837                                           mp16.wParam, mp16.lParam );
2838     WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, &mp16 );
2839     return mp16.lResult;
2840 }
2841
2842
2843 /**********************************************************************
2844  *           WINPROC_CallProc32WTo16
2845  *
2846  * Call a 16-bit window procedure, translating the 32-bit args.
2847  */
2848 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd,
2849                                                UINT msg, WPARAM wParam,
2850                                                LPARAM lParam )
2851 {
2852     UINT16 msg16;
2853     MSGPARAM16 mp16;
2854
2855     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2856         func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2857
2858     mp16.lParam = lParam;
2859     if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &mp16.wParam,
2860                                &mp16.lParam ) == -1)
2861         return 0;
2862     mp16.lResult = WINPROC_CallWndProc16( func, HWND_16(hwnd), msg16,
2863                                           mp16.wParam, mp16.lParam );
2864     WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, &mp16 );
2865     return mp16.lResult;
2866 }
2867
2868
2869 /**********************************************************************
2870  *              CallWindowProc (USER.122)
2871  */
2872 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
2873                                  WPARAM16 wParam, LPARAM lParam )
2874 {
2875     WINDOWPROC *proc;
2876
2877     if (!func) return 0;
2878
2879     if (!(proc = WINPROC_GetPtr( (WNDPROC)func )))
2880         return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
2881
2882 #if testing
2883     func = WINPROC_GetProc( (WNDPROC)proc, WIN_PROC_16 );
2884     return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
2885 #endif
2886
2887     switch(proc->type)
2888     {
2889     case WIN_PROC_16:
2890         if (!proc->thunk.t_from32.proc) return 0;
2891         return WINPROC_CallWndProc16( proc->thunk.t_from32.proc,
2892                                       hwnd, msg, wParam, lParam );
2893     case WIN_PROC_32A:
2894         if (!proc->thunk.t_from16.proc) return 0;
2895         return __wine_call_wndproc_32A( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc );
2896     case WIN_PROC_32W:
2897         if (!proc->thunk.t_from16.proc) return 0;
2898         return __wine_call_wndproc_32W( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc );
2899     default:
2900         WARN_(relay)("Invalid proc %p\n", proc );
2901         return 0;
2902     }
2903 }
2904
2905
2906 /**********************************************************************
2907  *              CallWindowProcA (USER32.@)
2908  *
2909  * The CallWindowProc() function invokes the windows procedure _func_,
2910  * with _hwnd_ as the target window, the message specified by _msg_, and
2911  * the message parameters _wParam_ and _lParam_.
2912  *
2913  * Some kinds of argument conversion may be done, I'm not sure what.
2914  *
2915  * CallWindowProc() may be used for windows subclassing. Use
2916  * SetWindowLong() to set a new windows procedure for windows of the
2917  * subclass, and handle subclassed messages in the new windows
2918  * procedure. The new windows procedure may then use CallWindowProc()
2919  * with _func_ set to the parent class's windows procedure to dispatch
2920  * the message to the superclass.
2921  *
2922  * RETURNS
2923  *
2924  *    The return value is message dependent.
2925  *
2926  * CONFORMANCE
2927  *
2928  *   ECMA-234, Win32
2929  */
2930 LRESULT WINAPI CallWindowProcA(
2931     WNDPROC func,  /* [in] window procedure */
2932     HWND hwnd,     /* [in] target window */
2933     UINT msg,      /* [in] message */
2934     WPARAM wParam, /* [in] message dependent parameter */
2935     LPARAM lParam  /* [in] message dependent parameter */
2936 ) {
2937     WINDOWPROC *proc;
2938
2939     if (!func) return 0;
2940
2941     if (!(proc = WINPROC_GetPtr( func )))
2942         return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2943
2944 #if testing
2945     func = WINPROC_GetProc( (WNDPROC)proc, WIN_PROC_32A );
2946     return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2947 #endif
2948
2949     switch(proc->type)
2950     {
2951     case WIN_PROC_16:
2952         if (!proc->thunk.t_from32.proc) return 0;
2953         return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
2954                                         hwnd, msg, wParam, lParam );
2955     case WIN_PROC_32A:
2956         if (!proc->thunk.t_from16.proc) return 0;
2957         return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
2958                                       hwnd, msg, wParam, lParam );
2959     case WIN_PROC_32W:
2960         if (!proc->thunk.t_from16.proc) return 0;
2961         return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
2962                                          hwnd, msg, wParam, lParam );
2963     default:
2964         WARN_(relay)("Invalid proc %p\n", proc );
2965         return 0;
2966     }
2967 }
2968
2969
2970 /**********************************************************************
2971  *              CallWindowProcW (USER32.@)
2972  */
2973 LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
2974                                   WPARAM wParam, LPARAM lParam )
2975 {
2976     WINDOWPROC *proc;
2977
2978     if (!func) return 0;
2979
2980     if (!(proc = WINPROC_GetPtr( (WNDPROC)func )))
2981         return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2982
2983 #if testing
2984     func = WINPROC_GetProc( (WNDPROC)proc, WIN_PROC_32W );
2985     return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2986 #endif
2987
2988     switch(proc->type)
2989     {
2990     case WIN_PROC_16:
2991         if (!proc->thunk.t_from32.proc) return 0;
2992         return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
2993                                         hwnd, msg, wParam, lParam );
2994     case WIN_PROC_32A:
2995         if (!proc->thunk.t_from16.proc) return 0;
2996         return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
2997                                          hwnd, msg, wParam, lParam );
2998     case WIN_PROC_32W:
2999         if (!proc->thunk.t_from16.proc) return 0;
3000         return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
3001                                       hwnd, msg, wParam, lParam );
3002     default:
3003         WARN_(relay)("Invalid proc %p\n", proc );
3004         return 0;
3005     }
3006 }