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