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