Moved a couple of 16-bit functions to user16.c.
[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 SBM_SETRANGE:
1880         *pmsg16 = SBM_SETRANGE16;
1881         *plparam = MAKELPARAM(wParam32, *plparam);
1882         *pwparam16 = 0;
1883         return 0;
1884
1885     case SBM_GETRANGE:
1886         *pmsg16 = SBM_GETRANGE16;
1887         return 1;
1888
1889     case BM_GETCHECK:
1890     case BM_SETCHECK:
1891     case BM_GETSTATE:
1892     case BM_SETSTATE:
1893     case BM_SETSTYLE:
1894         *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK);
1895         return 0;
1896
1897     case EM_GETSEL:
1898     case EM_GETRECT:
1899     case EM_SETRECT:
1900     case EM_SETRECTNP:
1901     case EM_SCROLL:
1902     case EM_LINESCROLL:
1903     case EM_SCROLLCARET:
1904     case EM_GETMODIFY:
1905     case EM_SETMODIFY:
1906     case EM_GETLINECOUNT:
1907     case EM_LINEINDEX:
1908     case EM_SETHANDLE:
1909     case EM_GETHANDLE:
1910     case EM_GETTHUMB:
1911     case EM_LINELENGTH:
1912     case EM_REPLACESEL:
1913     case EM_GETLINE:
1914     case EM_LIMITTEXT:
1915     case EM_CANUNDO:
1916     case EM_UNDO:
1917     case EM_FMTLINES:
1918     case EM_LINEFROMCHAR:
1919     case EM_SETTABSTOPS:
1920     case EM_SETPASSWORDCHAR:
1921     case EM_EMPTYUNDOBUFFER:
1922     case EM_GETFIRSTVISIBLELINE:
1923     case EM_SETREADONLY:
1924     case EM_SETWORDBREAKPROC:
1925     case EM_GETWORDBREAKPROC:
1926     case EM_GETPASSWORDCHAR:
1927         *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL);
1928         return 0;
1929
1930     case LB_CARETOFF:
1931     case LB_CARETON:
1932     case LB_DELETESTRING:
1933     case LB_GETANCHORINDEX:
1934     case LB_GETCARETINDEX:
1935     case LB_GETCOUNT:
1936     case LB_GETCURSEL:
1937     case LB_GETHORIZONTALEXTENT:
1938     case LB_GETITEMDATA:
1939     case LB_GETITEMHEIGHT:
1940     case LB_GETSEL:
1941     case LB_GETSELCOUNT:
1942     case LB_GETTEXTLEN:
1943     case LB_GETTOPINDEX:
1944     case LB_RESETCONTENT:
1945     case LB_SELITEMRANGE:
1946     case LB_SELITEMRANGEEX:
1947     case LB_SETANCHORINDEX:
1948     case LB_SETCARETINDEX:
1949     case LB_SETCOLUMNWIDTH:
1950     case LB_SETCURSEL:
1951     case LB_SETHORIZONTALEXTENT:
1952     case LB_SETITEMDATA:
1953     case LB_SETITEMHEIGHT:
1954     case LB_SETSEL:
1955     case LB_SETTOPINDEX:
1956         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1957         return 0;
1958     case CB_DELETESTRING:
1959     case CB_GETCOUNT:
1960     case CB_GETLBTEXTLEN:
1961     case CB_LIMITTEXT:
1962     case CB_RESETCONTENT:
1963     case CB_SETEDITSEL:
1964     case CB_GETCURSEL:
1965     case CB_SETCURSEL:
1966     case CB_SHOWDROPDOWN:
1967     case CB_SETITEMDATA:
1968     case CB_SETITEMHEIGHT:
1969     case CB_GETITEMHEIGHT:
1970     case CB_SETEXTENDEDUI:
1971     case CB_GETEXTENDEDUI:
1972     case CB_GETDROPPEDSTATE:
1973         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1974         return 0;
1975     case CB_GETEDITSEL:
1976         *pmsg16 = CB_GETEDITSEL16;
1977         return 1;
1978
1979     case LB_ADDSTRING:
1980     case LB_FINDSTRING:
1981     case LB_FINDSTRINGEXACT:
1982     case LB_INSERTSTRING:
1983     case LB_SELECTSTRING:
1984     case LB_DIR:
1985     case LB_ADDFILE:
1986         *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1987         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1988         return 1;
1989
1990     case CB_ADDSTRING:
1991     case CB_FINDSTRING:
1992     case CB_FINDSTRINGEXACT:
1993     case CB_INSERTSTRING:
1994     case CB_SELECTSTRING:
1995     case CB_DIR:
1996         *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1997         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1998         return 1;
1999
2000     case LB_GETITEMRECT:
2001         {
2002             RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
2003             if (!rect) return -1;
2004             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
2005             *plparam = MapLS( rect );
2006         }
2007         *pmsg16 = LB_GETITEMRECT16;
2008         return 1;
2009     case LB_GETSELITEMS:
2010         {
2011             LPARAM *items; /* old LPARAM first, then *pwparam16 x INT16 entries */
2012
2013             *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
2014             if (!(items = HeapAlloc( GetProcessHeap(), 0,
2015                                      *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
2016             *items++ = *plparam;  /* Store the previous lParam */
2017             *plparam = MapLS( items );
2018         }
2019         *pmsg16 = LB_GETSELITEMS16;
2020         return 1;
2021     case LB_SETTABSTOPS:
2022         if (wParam32)
2023         {
2024             INT i;
2025             LPINT16 stops;
2026             *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
2027             if (!(stops = HeapAlloc( GetProcessHeap(), 0,
2028                                      *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
2029             for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT)*plparam+i);
2030             *plparam = MapLS( stops );
2031             return 1;
2032         }
2033         *pmsg16 = LB_SETTABSTOPS16;
2034         return 0;
2035
2036     case CB_GETDROPPEDCONTROLRECT:
2037         {
2038             RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
2039             if (!rect) return -1;
2040             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
2041             *plparam = (LPARAM)MapLS(rect);
2042         }
2043         *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
2044         return 1;
2045
2046     case LB_GETTEXT:
2047         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
2048         *pmsg16 = LB_GETTEXT16;
2049         return 1;
2050
2051     case CB_GETLBTEXT:
2052         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
2053         *pmsg16 = CB_GETLBTEXT16;
2054         return 1;
2055
2056     case EM_SETSEL:
2057         *pwparam16 = 0;
2058         *plparam = MAKELONG( (INT16)(INT)wParam32, (INT16)*plparam );
2059         *pmsg16 = EM_SETSEL16;
2060         return 0;
2061
2062     case WM_ACTIVATE:
2063     case WM_CHARTOITEM:
2064     case WM_COMMAND:
2065     case WM_VKEYTOITEM:
2066         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2067         return 0;
2068     case WM_HSCROLL:
2069     case WM_VSCROLL:
2070         *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
2071         return 0;
2072     case WM_CTLCOLORMSGBOX:
2073     case WM_CTLCOLOREDIT:
2074     case WM_CTLCOLORLISTBOX:
2075     case WM_CTLCOLORBTN:
2076     case WM_CTLCOLORDLG:
2077     case WM_CTLCOLORSCROLLBAR:
2078     case WM_CTLCOLORSTATIC:
2079         *pmsg16  = WM_CTLCOLOR;
2080         *plparam = MAKELPARAM( (HWND16)*plparam,
2081                                (WORD)msg32 - WM_CTLCOLORMSGBOX );
2082         return 0;
2083     case WM_COMPAREITEM:
2084         {
2085             COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)*plparam;
2086             COMPAREITEMSTRUCT16 *cis = HeapAlloc( GetProcessHeap(), 0, sizeof(COMPAREITEMSTRUCT16));
2087             if (!cis) return -1;
2088             cis->CtlType    = (UINT16)cis32->CtlType;
2089             cis->CtlID      = (UINT16)cis32->CtlID;
2090             cis->hwndItem   = HWND_16( cis32->hwndItem );
2091             cis->itemID1    = (UINT16)cis32->itemID1;
2092             cis->itemData1  = cis32->itemData1;
2093             cis->itemID2    = (UINT16)cis32->itemID2;
2094             cis->itemData2  = cis32->itemData2;
2095             *plparam = MapLS( cis );
2096         }
2097         return 1;
2098     case WM_DELETEITEM:
2099         {
2100             DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)*plparam;
2101             DELETEITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DELETEITEMSTRUCT16) );
2102             if (!dis) return -1;
2103             dis->CtlType  = (UINT16)dis32->CtlType;
2104             dis->CtlID    = (UINT16)dis32->CtlID;
2105             dis->itemID   = (UINT16)dis32->itemID;
2106             dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem)
2107                                                        : HWND_16( dis32->hwndItem );
2108             dis->itemData = dis32->itemData;
2109             *plparam = MapLS( dis );
2110         }
2111         return 1;
2112     case WM_DRAWITEM:
2113         {
2114             DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)*plparam;
2115             DRAWITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DRAWITEMSTRUCT16) );
2116             if (!dis) return -1;
2117             dis->CtlType    = (UINT16)dis32->CtlType;
2118             dis->CtlID      = (UINT16)dis32->CtlID;
2119             dis->itemID     = (UINT16)dis32->itemID;
2120             dis->itemAction = (UINT16)dis32->itemAction;
2121             dis->itemState  = (UINT16)dis32->itemState;
2122             dis->hwndItem   = HWND_16( dis32->hwndItem );
2123             dis->hDC        = HDC_16(dis32->hDC);
2124             dis->itemData   = dis32->itemData;
2125             CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
2126             *plparam = MapLS( dis );
2127         }
2128         return 1;
2129     case WM_MEASUREITEM:
2130         {
2131             MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)*plparam;
2132             MEASUREITEMSTRUCT16 *mis = HeapAlloc( GetProcessHeap(), 0, sizeof(*mis)+sizeof(LPARAM));
2133             if (!mis) return -1;
2134             mis->CtlType    = (UINT16)mis32->CtlType;
2135             mis->CtlID      = (UINT16)mis32->CtlID;
2136             mis->itemID     = (UINT16)mis32->itemID;
2137             mis->itemWidth  = (UINT16)mis32->itemWidth;
2138             mis->itemHeight = (UINT16)mis32->itemHeight;
2139             mis->itemData   = mis32->itemData;
2140             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
2141             *plparam = MapLS( mis );
2142         }
2143         return 1;
2144     case WM_GETMINMAXINFO:
2145         {
2146             MINMAXINFO16 *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM) );
2147             if (!mmi) return -1;
2148             STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)*plparam, mmi );
2149             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
2150             *plparam = MapLS( mmi );
2151         }
2152         return 1;
2153     case WM_GETTEXT:
2154     case WM_ASKCBFORMATNAME:
2155         {
2156             LPARAM *str; /* store LPARAM, then *pwparam16 char space */
2157             *pwparam16 = (WPARAM16)min( wParam32, 0xff80 ); /* Must be < 64K */
2158             if (!(str = HeapAlloc( GetProcessHeap(), 0, *pwparam16 + sizeof(LPARAM)))) return -1;
2159             *str++ = *plparam;  /* Store the previous lParam */
2160             *plparam = MapLS( str );
2161         }
2162         return 1;
2163     case WM_MDICREATE:
2164         {
2165             MDICREATESTRUCT16 *cs;
2166             MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)*plparam;
2167
2168             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2169             STRUCT32_MDICREATESTRUCT32Ato16( cs32, cs );
2170             cs->szTitle = MapLS( cs32->szTitle );
2171             cs->szClass = MapLS( cs32->szClass );
2172             *plparam = MapLS( cs );
2173         }
2174         return 1;
2175     case WM_MDIGETACTIVE:
2176         return 1;
2177     case WM_MDISETMENU:
2178         *plparam   = MAKELPARAM( (HMENU16)LOWORD(wParam32),
2179                                  (HMENU16)LOWORD(*plparam) );
2180         *pwparam16 = (*plparam == 0);
2181         return 0;
2182     case WM_MENUSELECT:
2183         if(HIWORD(wParam32) & MF_POPUP)
2184         {
2185             HMENU hmenu;
2186             if (((UINT)HIWORD(wParam32) != 0xFFFF) || (*plparam))
2187             {
2188                 if((hmenu = GetSubMenu((HMENU)*plparam, *pwparam16)))
2189                     *pwparam16=HMENU_16(hmenu);
2190             }
2191         }
2192         /* fall through */
2193     case WM_MENUCHAR:
2194         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2195         return 0;
2196     case WM_MDIACTIVATE:
2197         if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
2198         {
2199             *pwparam16 = ((HWND)*plparam == hwnd);
2200             *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
2201                                    (HWND16)LOWORD(wParam32) );
2202         }
2203         else
2204         {
2205             *pwparam16 = HWND_16( (HWND)wParam32 );
2206             *plparam = 0;
2207         }
2208         return 0;
2209     case WM_NCCALCSIZE:
2210         {
2211             NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)*plparam;
2212             NCCALCSIZE_PARAMS16 *nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM));
2213             if (!nc) return -1;
2214
2215             CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
2216             if (wParam32)
2217             {
2218                 WINDOWPOS16 *wp;
2219                 CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
2220                 CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
2221                 if (!(wp = HeapAlloc( GetProcessHeap(), 0, sizeof(WINDOWPOS16) )))
2222                 {
2223                     HeapFree( GetProcessHeap(), 0, nc );
2224                     return -1;
2225                 }
2226                 STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
2227                 nc->lppos = MapLS( wp );
2228             }
2229             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
2230             *plparam = MapLS( nc );
2231         }
2232         return 1;
2233     case WM_NCCREATE:
2234     case WM_CREATE:
2235         {
2236             CREATESTRUCT16 *cs;
2237             CREATESTRUCTA *cs32 = (CREATESTRUCTA *)*plparam;
2238
2239             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2240             STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
2241             cs->lpszName  = MapLS( cs32->lpszName );
2242             cs->lpszClass = MapLS( cs32->lpszClass );
2243
2244             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2245             {
2246                 MDICREATESTRUCT16 *mdi_cs16;
2247                 MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs32->lpCreateParams;
2248                 mdi_cs16 = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs16));
2249                 if (!mdi_cs16)
2250                 {
2251                     HeapFree(GetProcessHeap(), 0, cs);
2252                     return -1;
2253                 }
2254                 STRUCT32_MDICREATESTRUCT32Ato16(mdi_cs, mdi_cs16);
2255                 mdi_cs16->szTitle = MapLS( mdi_cs->szTitle );
2256                 mdi_cs16->szClass = MapLS( mdi_cs->szClass );
2257                 cs->lpCreateParams = MapLS( mdi_cs16 );
2258             }
2259             *plparam = MapLS( cs );
2260         }
2261         return 1;
2262     case WM_PARENTNOTIFY:
2263         if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
2264             *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
2265         /* else nothing to do */
2266         return 0;
2267     case WM_NOTIFY:
2268         *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
2269         return 1;
2270     case WM_SETTEXT:
2271     case WM_WININICHANGE:
2272     case WM_DEVMODECHANGE:
2273         *plparam = MapLS( (LPSTR)*plparam );
2274         return 1;
2275     case WM_WINDOWPOSCHANGING:
2276     case WM_WINDOWPOSCHANGED:
2277         {
2278             WINDOWPOS16 *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
2279             if (!wp) return -1;
2280             STRUCT32_WINDOWPOS32to16( (WINDOWPOS *)*plparam, wp );
2281             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
2282             *plparam = MapLS( wp );
2283         }
2284         return 1;
2285     case WM_GETDLGCODE:
2286          if (*plparam) {
2287             LPMSG msg32 = (LPMSG) *plparam;
2288             LPMSG16 msg16 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG16) );
2289
2290             if (!msg16) return -1;
2291             msg16->hwnd = HWND_16( msg32->hwnd );
2292             msg16->lParam = msg32->lParam;
2293             msg16->time = msg32->time;
2294             CONV_POINT32TO16(&msg32->pt,&msg16->pt);
2295             /* this is right, right? */
2296             if (WINPROC_MapMsg32ATo16(msg32->hwnd,msg32->message,msg32->wParam,
2297                          &msg16->message,&msg16->wParam, &msg16->lParam)<0)
2298             {
2299                 HeapFree( GetProcessHeap(), 0, msg16 );
2300                 return -1;
2301             }
2302             *plparam = MapLS( msg16 );
2303             return 1;
2304         }
2305         return 0;
2306
2307     case WM_ACTIVATEAPP:
2308         if (*plparam) *plparam = HTASK_16( (HANDLE)*plparam );
2309         return 0;
2310     case WM_NEXTMENU:
2311         {
2312             MDINEXTMENU *next = (MDINEXTMENU *)*plparam;
2313             *plparam = (LPARAM)next->hmenuIn;
2314             return 1;
2315         }
2316     case WM_PAINTCLIPBOARD:
2317     case WM_SIZECLIPBOARD:
2318         FIXME_(msg)("message %04x needs translation\n", msg32 );
2319         return -1;
2320     /* following messages should not be sent to 16-bit apps */
2321     case WM_SIZING:
2322     case WM_MOVING:
2323     case WM_CAPTURECHANGED:
2324     case WM_STYLECHANGING:
2325     case WM_STYLECHANGED:
2326         return -1;
2327     case WM_DDE_INITIATE:
2328     case WM_DDE_TERMINATE:
2329     case WM_DDE_UNADVISE:
2330     case WM_DDE_REQUEST:
2331         *pwparam16 = HWND_16((HWND)wParam32);
2332         return 0;
2333     case WM_DDE_ADVISE:
2334     case WM_DDE_DATA:
2335     case WM_DDE_POKE:
2336         {
2337             UINT lo32, hi;
2338             HANDLE16    lo16 = 0;
2339
2340             *pwparam16 = HWND_16((HWND)wParam32);
2341             UnpackDDElParam(msg32, *plparam, &lo32, &hi);
2342             if (lo32 && !(lo16 = convert_handle_32_to_16(lo32, GMEM_DDESHARE)))
2343                 return -1;
2344             *plparam = MAKELPARAM(lo16, hi);
2345         }
2346         return 0; /* FIXME don't know how to free allocated memory (handle)  !! */
2347     case WM_DDE_ACK:
2348         {
2349             UINT        lo, hi;
2350             int         flag = 0;
2351             char        buf[2];
2352
2353             *pwparam16 = HWND_16((HWND)wParam32);
2354
2355             UnpackDDElParam(msg32, *plparam, &lo, &hi);
2356
2357             if (GlobalGetAtomNameA((ATOM)hi, buf, sizeof(buf)) > 0) flag |= 1;
2358             if (GlobalSize((HANDLE)hi) != 0) flag |= 2;
2359             switch (flag)
2360             {
2361             case 0:
2362                 if (hi)
2363                 {
2364                     MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
2365                     hi = 0;
2366                 }
2367                 break;
2368             case 1:
2369                 break; /* atom, nothing to do */
2370             case 3:
2371                 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
2372                 /* fall thru */
2373             case 2:
2374                 hi = convert_handle_32_to_16(hi, GMEM_DDESHARE);
2375                 break;
2376             }
2377             *plparam = MAKELPARAM(lo, hi);
2378         }
2379         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2380     case WM_DDE_EXECUTE:
2381         *plparam = convert_handle_32_to_16(*plparam, GMEM_DDESHARE);
2382         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2383     default:  /* No translation needed */
2384         return 0;
2385     }
2386 }
2387
2388
2389 /**********************************************************************
2390  *           WINPROC_UnmapMsg32ATo16
2391  *
2392  * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
2393  */
2394 void WINPROC_UnmapMsg32ATo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2395                               MSGPARAM16* p16 )
2396 {
2397     switch(msg)
2398     {
2399     case SBM_GETRANGE:
2400         *(LPINT)wParam = LOWORD(p16->lResult);
2401         *(LPINT)lParam = HIWORD(p16->lResult);
2402         break;
2403
2404     case LB_ADDFILE:
2405     case LB_ADDSTRING:
2406     case LB_DIR:
2407     case LB_FINDSTRING:
2408     case LB_FINDSTRINGEXACT:
2409     case LB_INSERTSTRING:
2410     case LB_SELECTSTRING:
2411     case LB_GETTEXT:
2412     case CB_ADDSTRING:
2413     case CB_FINDSTRING:
2414     case CB_FINDSTRINGEXACT:
2415     case CB_INSERTSTRING:
2416     case CB_SELECTSTRING:
2417     case CB_DIR:
2418     case CB_GETLBTEXT:
2419     case WM_SETTEXT:
2420     case WM_WININICHANGE:
2421     case WM_DEVMODECHANGE:
2422         UnMapLS( (SEGPTR)p16->lParam );
2423         break;
2424     case LB_SETTABSTOPS:
2425     case WM_COMPAREITEM:
2426     case WM_DELETEITEM:
2427     case WM_DRAWITEM:
2428         {
2429             void *ptr = MapSL( p16->lParam );
2430             UnMapLS( p16->lParam );
2431             HeapFree( GetProcessHeap(), 0, ptr );
2432         }
2433         break;
2434     case CB_GETDROPPEDCONTROLRECT:
2435     case LB_GETITEMRECT:
2436         {
2437             RECT16 *rect = MapSL(p16->lParam);
2438             UnMapLS( p16->lParam );
2439             p16->lParam = *(LPARAM *)(rect + 1);
2440             CONV_RECT16TO32( rect, (RECT *)(p16->lParam));
2441             HeapFree( GetProcessHeap(), 0, rect );
2442         }
2443         break;
2444     case LB_GETSELITEMS:
2445         {
2446             INT i;
2447             LPINT16 items = MapSL(p16->lParam);
2448             UnMapLS( p16->lParam );
2449             p16->lParam = *((LPARAM *)items - 1);
2450             for (i = 0; i < p16->wParam; i++) *((LPINT)(p16->lParam) + i) = items[i];
2451             HeapFree( GetProcessHeap(), 0, (LPARAM *)items - 1 );
2452         }
2453         break;
2454
2455     case CB_GETEDITSEL:
2456         if( wParam )
2457             *((PUINT)(wParam)) = LOWORD(p16->lResult);
2458         if( lParam )
2459             *((PUINT)(lParam)) = HIWORD(p16->lResult);  /* FIXME: substract 1? */
2460         break;
2461
2462     case WM_MEASUREITEM:
2463         {
2464             MEASUREITEMSTRUCT16 *mis = MapSL(p16->lParam);
2465             MEASUREITEMSTRUCT *mis32 = *(MEASUREITEMSTRUCT **)(mis + 1);
2466             mis32->itemWidth  = mis->itemWidth;
2467             mis32->itemHeight = mis->itemHeight;
2468             UnMapLS( p16->lParam );
2469             HeapFree( GetProcessHeap(), 0, mis );
2470         }
2471         break;
2472     case WM_GETMINMAXINFO:
2473         {
2474             MINMAXINFO16 *mmi = MapSL(p16->lParam);
2475             UnMapLS( p16->lParam );
2476             p16->lParam = *(LPARAM *)(mmi + 1);
2477             STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO *)(p16->lParam) );
2478             HeapFree( GetProcessHeap(), 0, mmi );
2479         }
2480         break;
2481     case WM_GETTEXT:
2482     case WM_ASKCBFORMATNAME:
2483         {
2484             LPSTR str = MapSL(p16->lParam);
2485             UnMapLS( p16->lParam );
2486             p16->lParam = *((LPARAM *)str - 1);
2487             lstrcpynA( (LPSTR)(p16->lParam), str, p16->wParam );
2488             HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2489         }
2490         break;
2491     case WM_MDICREATE:
2492         {
2493             MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2494             UnMapLS( cs->szTitle );
2495             UnMapLS( cs->szClass );
2496             UnMapLS( p16->lParam );
2497             HeapFree( GetProcessHeap(), 0, cs );
2498         }
2499         break;
2500     case WM_MDIGETACTIVE:
2501         if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(p16->lResult);
2502         p16->lResult = (LRESULT)WIN_Handle32( LOWORD(p16->lResult) );
2503         break;
2504     case WM_NCCALCSIZE:
2505         {
2506             NCCALCSIZE_PARAMS *nc32;
2507             NCCALCSIZE_PARAMS16 *nc = MapSL(p16->lParam);
2508             UnMapLS( p16->lParam );
2509             p16->lParam = *(LPARAM *)(nc + 1);
2510             nc32 = (NCCALCSIZE_PARAMS *)(p16->lParam);
2511             CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
2512             if (p16->wParam)
2513             {
2514                 WINDOWPOS16 *pos = MapSL(nc->lppos);
2515                 UnMapLS( nc->lppos );
2516                 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
2517                 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
2518                 STRUCT32_WINDOWPOS16to32( pos, nc32->lppos );
2519                 HeapFree( GetProcessHeap(), 0, pos );
2520             }
2521             HeapFree( GetProcessHeap(), 0, nc );
2522         }
2523         break;
2524     case WM_NCCREATE:
2525     case WM_CREATE:
2526         {
2527             CREATESTRUCT16 *cs = MapSL(p16->lParam);
2528             UnMapLS( p16->lParam );
2529             UnMapLS( cs->lpszName );
2530             UnMapLS( cs->lpszClass );
2531             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2532             {
2533                 MDICREATESTRUCT16 *mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs->lpCreateParams);
2534                 UnMapLS( cs->lpCreateParams );
2535                 UnMapLS( mdi_cs16->szTitle );
2536                 UnMapLS( mdi_cs16->szClass );
2537                 HeapFree(GetProcessHeap(), 0, mdi_cs16);
2538             }
2539             HeapFree( GetProcessHeap(), 0, cs );
2540         }
2541         break;
2542     case WM_WINDOWPOSCHANGING:
2543     case WM_WINDOWPOSCHANGED:
2544         {
2545             WINDOWPOS16 *wp = MapSL(p16->lParam);
2546             UnMapLS( p16->lParam );
2547             p16->lParam = *(LPARAM *)(wp + 1);
2548             STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS *)p16->lParam );
2549             HeapFree( GetProcessHeap(), 0, wp );
2550         }
2551         break;
2552     case WM_NOTIFY:
2553         UnMapLS(p16->lParam);
2554         break;
2555     case WM_GETDLGCODE:
2556         if (p16->lParam)
2557         {
2558             LPMSG16 msg16 = MapSL(p16->lParam);
2559             MSGPARAM16 msgp16;
2560             UnMapLS( p16->lParam );
2561             msgp16.wParam=msg16->wParam;
2562             msgp16.lParam=msg16->lParam;
2563             WINPROC_UnmapMsg32ATo16(((LPMSG)lParam)->hwnd, ((LPMSG)lParam)->message,
2564                     ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam,
2565                     &msgp16 );
2566             HeapFree( GetProcessHeap(), 0, msg16 );
2567         }
2568         break;
2569     case WM_NEXTMENU:
2570         {
2571             MDINEXTMENU *next = (MDINEXTMENU *)lParam;
2572             next->hmenuNext = HMENU_32( LOWORD(p16->lResult) );
2573             next->hwndNext = WIN_Handle32( HIWORD(p16->lResult) );
2574             p16->lResult = 0;
2575         }
2576         break;
2577     }
2578 }
2579
2580
2581 /**********************************************************************
2582  *           WINPROC_MapMsg32WTo16
2583  *
2584  * Map a message from 32-bit Unicode to 16-bit.
2585  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
2586  */
2587 INT WINPROC_MapMsg32WTo16( HWND hwnd, UINT msg32, WPARAM wParam32,
2588                              UINT16 *pmsg16, WPARAM16 *pwparam16,
2589                              LPARAM *plparam )
2590 {
2591     BYTE ch;
2592     WCHAR wch;
2593
2594     *pmsg16    = LOWORD(msg32);
2595     *pwparam16 = LOWORD(wParam32);
2596     switch(msg32)
2597     {
2598     case LB_ADDSTRING:
2599     case LB_FINDSTRING:
2600     case LB_FINDSTRINGEXACT:
2601     case LB_INSERTSTRING:
2602     case LB_SELECTSTRING:
2603     case LB_DIR:
2604     case LB_ADDFILE:
2605         *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2606         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2607         return 1;
2608
2609     case CB_ADDSTRING:
2610     case CB_FINDSTRING:
2611     case CB_FINDSTRINGEXACT:
2612     case CB_INSERTSTRING:
2613     case CB_SELECTSTRING:
2614     case CB_DIR:
2615         *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2616         *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING);
2617         return 1;
2618
2619     case WM_NCCREATE:
2620     case WM_CREATE:
2621         {
2622             CREATESTRUCT16 *cs;
2623             CREATESTRUCTW *cs32 = (CREATESTRUCTW *)*plparam;
2624
2625             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2626             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs32, cs );
2627             cs->lpszName  = map_str_32W_to_16( cs32->lpszName );
2628             cs->lpszClass = map_str_32W_to_16( cs32->lpszClass );
2629
2630             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2631             {
2632                 MDICREATESTRUCT16 *mdi_cs16;
2633                 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)cs32->lpCreateParams;
2634                 mdi_cs16 = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs16));
2635                 if (!mdi_cs16)
2636                 {
2637                     HeapFree(GetProcessHeap(), 0, cs);
2638                     return -1;
2639                 }
2640                 STRUCT32_MDICREATESTRUCT32Ato16((MDICREATESTRUCTA *)mdi_cs, mdi_cs16);
2641                 mdi_cs16->szTitle = map_str_32W_to_16(mdi_cs->szTitle);
2642                 mdi_cs16->szClass = map_str_32W_to_16(mdi_cs->szClass);
2643                 cs->lpCreateParams = MapLS(mdi_cs16);
2644             }
2645             *plparam   = MapLS(cs);
2646         }
2647         return 1;
2648     case WM_MDICREATE:
2649         {
2650             MDICREATESTRUCT16 *cs;
2651             MDICREATESTRUCTW *cs32 = (MDICREATESTRUCTW *)*plparam;
2652
2653             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2654             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs32, cs );
2655             cs->szTitle = map_str_32W_to_16( cs32->szTitle );
2656             cs->szClass = map_str_32W_to_16( cs32->szClass );
2657             *plparam   = MapLS(cs);
2658         }
2659         return 1;
2660     case WM_SETTEXT:
2661     case WM_WININICHANGE:
2662     case WM_DEVMODECHANGE:
2663         *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2664         return 1;
2665     case LB_GETTEXT:
2666         if ( WINPROC_TestLBForStr( hwnd ))
2667         {
2668             LPSTR str = HeapAlloc( GetProcessHeap(), 0, 256 ); /* FIXME: fixed sized buffer */
2669             if (!str) return -1;
2670             *pmsg16    = LB_GETTEXT16;
2671             *plparam   = (LPARAM)MapLS(str);
2672         }
2673         return 1;
2674     case CB_GETLBTEXT:
2675         if ( WINPROC_TestCBForStr( hwnd ))
2676         {
2677             LPSTR str = HeapAlloc( GetProcessHeap(), 0, 256 ); /* FIXME: fixed sized buffer */
2678             if (!str) return -1;
2679             *pmsg16    = CB_GETLBTEXT16;
2680             *plparam   = (LPARAM)MapLS(str);
2681         }
2682         return 1;
2683
2684     case WM_CHARTOITEM:
2685         wch = LOWORD(wParam32);
2686         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2687         *pwparam16 = ch;
2688         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2689         return 0;
2690     case WM_MENUCHAR:
2691         wch = LOWORD(wParam32);
2692         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2693         *pwparam16 = ch;
2694         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2695         return 0;
2696     case WM_CHAR:
2697     case WM_DEADCHAR:
2698     case WM_SYSCHAR:
2699     case WM_SYSDEADCHAR:
2700         wch = wParam32;
2701         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2702         *pwparam16 = ch;
2703         return 0;
2704     case WM_IME_CHAR:
2705         {
2706             BYTE ch[2];
2707
2708             wch = wParam32;
2709             if (WideCharToMultiByte( CP_ACP, 0, &wch, 1, ch, 2, NULL, NULL ) == 2)
2710                 *pwparam16 = (ch[0] << 8) | ch[1];
2711             else
2712                 *pwparam16 = ch[0];
2713         }
2714         return 0;
2715
2716     default:  /* No Unicode translation needed (?) */
2717         return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2718                                       pwparam16, plparam );
2719     }
2720 }
2721
2722
2723 /**********************************************************************
2724  *           WINPROC_UnmapMsg32WTo16
2725  *
2726  * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2727  */
2728 void WINPROC_UnmapMsg32WTo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2729                               MSGPARAM16* p16 )
2730 {
2731     switch(msg)
2732     {
2733     case LB_ADDSTRING:
2734     case LB_FINDSTRING:
2735     case LB_FINDSTRINGEXACT:
2736     case LB_INSERTSTRING:
2737     case LB_SELECTSTRING:
2738     case LB_DIR:
2739     case LB_ADDFILE:
2740     case CB_ADDSTRING:
2741     case CB_FINDSTRING:
2742     case CB_FINDSTRINGEXACT:
2743     case CB_INSERTSTRING:
2744     case CB_SELECTSTRING:
2745     case CB_DIR:
2746     case WM_SETTEXT:
2747     case WM_WININICHANGE:
2748     case WM_DEVMODECHANGE:
2749         unmap_str_32W_to_16( p16->lParam );
2750         break;
2751     case WM_NCCREATE:
2752     case WM_CREATE:
2753         {
2754             CREATESTRUCT16 *cs = MapSL(p16->lParam);
2755             UnMapLS( p16->lParam );
2756             unmap_str_32W_to_16( cs->lpszName );
2757             unmap_str_32W_to_16( cs->lpszClass );
2758
2759             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2760             {
2761                 MDICREATESTRUCT16 *mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs->lpCreateParams);
2762                 UnMapLS( cs->lpCreateParams );
2763                 unmap_str_32W_to_16(mdi_cs16->szTitle);
2764                 unmap_str_32W_to_16(mdi_cs16->szClass);
2765                 HeapFree(GetProcessHeap(), 0, mdi_cs16);
2766             }
2767             HeapFree( GetProcessHeap(), 0, cs );
2768         }
2769         break;
2770     case WM_MDICREATE:
2771         {
2772             MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2773             UnMapLS( p16->lParam );
2774             unmap_str_32W_to_16( cs->szTitle );
2775             unmap_str_32W_to_16( cs->szClass );
2776             HeapFree( GetProcessHeap(), 0, cs );
2777         }
2778         break;
2779     case WM_GETTEXT:
2780     case WM_ASKCBFORMATNAME:
2781         {
2782             LPSTR str = MapSL(p16->lParam);
2783             UnMapLS( p16->lParam );
2784             p16->lParam = *((LPARAM *)str - 1);
2785             MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)p16->lParam, 0x7fffffff );
2786             p16->lResult = strlenW( (LPWSTR)p16->lParam );
2787             HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2788         }
2789         break;
2790     case LB_GETTEXT:
2791         if ( WINPROC_TestLBForStr( hwnd ))
2792         {
2793             LPSTR str = MapSL(p16->lParam);
2794             UnMapLS( p16->lParam );
2795             p16->lResult = MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff ) - 1;
2796             HeapFree( GetProcessHeap(), 0, (LPARAM *)str );
2797         }
2798         break;
2799     case CB_GETLBTEXT:
2800         if ( WINPROC_TestCBForStr( hwnd ))
2801         {
2802             LPSTR str = MapSL(p16->lParam);
2803             UnMapLS( p16->lParam );
2804             p16->lResult = MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff ) - 1;
2805             HeapFree( GetProcessHeap(), 0, (LPARAM *)str );
2806         }
2807         break;
2808     default:
2809         WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, p16 );
2810         break;
2811     }
2812 }
2813
2814
2815 /**********************************************************************
2816  *           WINPROC_CallProc32ATo32W
2817  *
2818  * Call a window procedure, translating args from Ansi to Unicode.
2819  */
2820 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC func, HWND hwnd,
2821                                          UINT msg, WPARAM wParam,
2822                                          LPARAM lParam )
2823 {
2824     LRESULT result;
2825     int unmap;
2826
2827     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2828         func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2829
2830     if( (unmap = WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam )) == -1) {
2831         ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2832                        SPY_GetMsgName(msg, hwnd), wParam, lParam );
2833         return 0;
2834     }
2835     result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2836     if (unmap) result = WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result );
2837     return result;
2838 }
2839
2840
2841 /**********************************************************************
2842  *           WINPROC_CallProc32WTo32A_fast
2843  *
2844  */
2845 static BOOL WINPROC_CallProc32WTo32A_fast( WNDPROC func, HWND hwnd,
2846                                            UINT msg, WPARAM wParam,
2847                                            LPARAM lParam, LRESULT *result )
2848 {
2849     switch(msg)
2850     {
2851     case WM_NCCREATE:
2852     case WM_CREATE:
2853         {   /* csW->lpszName and csW->lpszClass are NOT supposed to be atoms
2854              * at this point.
2855              */
2856             char buffer[1024];
2857             char *cls = buffer, *name;
2858             CREATESTRUCTW *csW = (CREATESTRUCTW *)lParam;
2859             CREATESTRUCTA csA = *(CREATESTRUCTA *)csW;
2860             DWORD name_lenA, name_lenW, class_lenA, class_lenW;
2861
2862             class_lenW = strlenW(csW->lpszClass) * sizeof(WCHAR);
2863             RtlUnicodeToMultiByteSize(&class_lenA, csW->lpszClass, class_lenW);
2864
2865             if (csW->lpszName)
2866             {
2867                 name_lenW = strlenW(csW->lpszName) * sizeof(WCHAR);
2868                 RtlUnicodeToMultiByteSize(&name_lenA, csW->lpszName, name_lenW);
2869             }
2870             else
2871                 name_lenW = name_lenA = 0;
2872
2873             if (class_lenA + name_lenA + 2 > sizeof(buffer))
2874             {
2875                 cls = HeapAlloc(GetProcessHeap(), 0, class_lenA + name_lenA + 2);
2876                 if (!cls) return FALSE;
2877             }
2878
2879             RtlUnicodeToMultiByteN(cls, class_lenA, NULL, csW->lpszClass, class_lenW);
2880             cls[class_lenA] = 0;
2881             csA.lpszClass = cls;
2882
2883             if (csW->lpszName)
2884             {
2885                 name = cls + class_lenA + 1;
2886                 RtlUnicodeToMultiByteN(name, name_lenA, NULL, csW->lpszName, name_lenW);
2887                 name[name_lenA] = 0;
2888                 csA.lpszName = name;
2889             }
2890
2891             if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2892             {
2893                 MDICREATESTRUCTA mdi_cs;
2894
2895                 mdi_cs = *(MDICREATESTRUCTA *)csW->lpCreateParams;
2896                 mdi_cs.szTitle = csA.lpszName;
2897                 mdi_cs.szClass = csA.lpszClass;
2898                 csA.lpCreateParams = &mdi_cs;
2899             }
2900
2901             lParam = (LPARAM)&csA;
2902             *result = WINPROC_CallWndProc(func, hwnd, msg, wParam, lParam);
2903
2904             if (cls != buffer) HeapFree(GetProcessHeap(), 0, cls);
2905         }
2906         return TRUE;
2907
2908     default:
2909         return FALSE;
2910     }
2911 }
2912
2913 /**********************************************************************
2914  *           WINPROC_CallProc32WTo32A
2915  *
2916  * Call a window procedure, translating args from Unicode to Ansi.
2917  */
2918 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC func, HWND hwnd,
2919                                          UINT msg, WPARAM wParam,
2920                                          LPARAM lParam )
2921 {
2922     LRESULT result;
2923     int unmap;
2924
2925     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2926         func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2927
2928     if (WINPROC_CallProc32WTo32A_fast( func, hwnd, msg, wParam, lParam, &result ))
2929         return result;
2930
2931     if ((unmap = WINPROC_MapMsg32WTo32A( hwnd, msg, &wParam, &lParam )) == -1) {
2932         ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2933                        SPY_GetMsgName(msg, hwnd), wParam, lParam );
2934         return 0;
2935     }
2936     result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2937     if( unmap ) result = WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam, result );
2938     return result;
2939 }
2940
2941
2942 /**********************************************************************
2943  *           __wine_call_wndproc_32A   (USER.1010)
2944  */
2945 LRESULT WINAPI __wine_call_wndproc_32A( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2946                                         WNDPROC func )
2947 {
2948     LRESULT result;
2949     UINT msg32;
2950     WPARAM wParam32;
2951     HWND hwnd32 = WIN_Handle32( hwnd );
2952
2953     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2954                  func, hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
2955
2956     if (WINPROC_MapMsg16To32A( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2957         return 0;
2958     result = WINPROC_CallWndProc( func, hwnd32, msg32, wParam32, lParam );
2959     return WINPROC_UnmapMsg16To32A( hwnd32, msg32, wParam32, lParam, result );
2960 }
2961
2962
2963 /**********************************************************************
2964  *           __wine_call_wndproc_32W   (USER.1011)
2965  */
2966 LRESULT WINAPI  __wine_call_wndproc_32W( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2967                                          WNDPROC func )
2968 {
2969     LRESULT result;
2970     UINT msg32;
2971     WPARAM wParam32;
2972     HWND hwnd32 = WIN_Handle32( hwnd );
2973
2974     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2975                  func, hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
2976
2977     if (WINPROC_MapMsg16To32W( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2978         return 0;
2979     result = WINPROC_CallWndProc( func, hwnd32, msg32, wParam32, lParam );
2980     return WINPROC_UnmapMsg16To32W( hwnd32, msg32, wParam32, lParam, result );
2981 }
2982
2983
2984 /**********************************************************************
2985  *           WINPROC_CallProc32ATo16
2986  *
2987  * Call a 16-bit window procedure, translating the 32-bit args.
2988  */
2989 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd,
2990                                                UINT msg, WPARAM wParam,
2991                                                LPARAM lParam )
2992 {
2993     UINT16 msg16;
2994     MSGPARAM16 mp16;
2995
2996     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2997         func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2998
2999     mp16.lParam = lParam;
3000     if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, &msg16, &mp16.wParam, &mp16.lParam ) == -1)
3001         return 0;
3002     mp16.lResult = WINPROC_CallWndProc16( func, HWND_16(hwnd), msg16,
3003                                           mp16.wParam, mp16.lParam );
3004     WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, &mp16 );
3005     return mp16.lResult;
3006 }
3007
3008
3009 /**********************************************************************
3010  *           WINPROC_CallProc32WTo16
3011  *
3012  * Call a 16-bit window procedure, translating the 32-bit args.
3013  */
3014 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd,
3015                                                UINT msg, WPARAM wParam,
3016                                                LPARAM lParam )
3017 {
3018     UINT16 msg16;
3019     MSGPARAM16 mp16;
3020
3021     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
3022         func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
3023
3024     mp16.lParam = lParam;
3025     if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &mp16.wParam,
3026                                &mp16.lParam ) == -1)
3027         return 0;
3028     mp16.lResult = WINPROC_CallWndProc16( func, HWND_16(hwnd), msg16,
3029                                           mp16.wParam, mp16.lParam );
3030     WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, &mp16 );
3031     return mp16.lResult;
3032 }
3033
3034
3035 /**********************************************************************
3036  *              CallWindowProc (USER.122)
3037  */
3038 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
3039                                  WPARAM16 wParam, LPARAM lParam )
3040 {
3041     WINDOWPROC *proc;
3042
3043     if (!func) return 0;
3044
3045     if (!(proc = WINPROC_GetPtr( (WNDPROC)func )))
3046         return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
3047
3048 #if testing
3049     func = WINPROC_GetProc( (WNDPROC)proc, WIN_PROC_16 );
3050     return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
3051 #endif
3052
3053     switch(proc->type)
3054     {
3055     case WIN_PROC_16:
3056         if (!proc->thunk.t_from32.proc) return 0;
3057         return WINPROC_CallWndProc16( proc->thunk.t_from32.proc,
3058                                       hwnd, msg, wParam, lParam );
3059     case WIN_PROC_32A:
3060         if (!proc->thunk.t_from16.proc) return 0;
3061         return __wine_call_wndproc_32A( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc );
3062     case WIN_PROC_32W:
3063         if (!proc->thunk.t_from16.proc) return 0;
3064         return __wine_call_wndproc_32W( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc );
3065     default:
3066         WARN_(relay)("Invalid proc %p\n", proc );
3067         return 0;
3068     }
3069 }
3070
3071
3072 /**********************************************************************
3073  *              CallWindowProcA (USER32.@)
3074  *
3075  * The CallWindowProc() function invokes the windows procedure _func_,
3076  * with _hwnd_ as the target window, the message specified by _msg_, and
3077  * the message parameters _wParam_ and _lParam_.
3078  *
3079  * Some kinds of argument conversion may be done, I'm not sure what.
3080  *
3081  * CallWindowProc() may be used for windows subclassing. Use
3082  * SetWindowLong() to set a new windows procedure for windows of the
3083  * subclass, and handle subclassed messages in the new windows
3084  * procedure. The new windows procedure may then use CallWindowProc()
3085  * with _func_ set to the parent class's windows procedure to dispatch
3086  * the message to the superclass.
3087  *
3088  * RETURNS
3089  *
3090  *    The return value is message dependent.
3091  *
3092  * CONFORMANCE
3093  *
3094  *   ECMA-234, Win32
3095  */
3096 LRESULT WINAPI CallWindowProcA(
3097     WNDPROC func,  /* [in] window procedure */
3098     HWND hwnd,     /* [in] target window */
3099     UINT msg,      /* [in] message */
3100     WPARAM wParam, /* [in] message dependent parameter */
3101     LPARAM lParam  /* [in] message dependent parameter */
3102 ) {
3103     WINDOWPROC *proc;
3104
3105     if (!func) return 0;
3106
3107     if (!(proc = WINPROC_GetPtr( func )))
3108         return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
3109
3110 #if testing
3111     func = WINPROC_GetProc( (WNDPROC)proc, WIN_PROC_32A );
3112     return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
3113 #endif
3114
3115     switch(proc->type)
3116     {
3117     case WIN_PROC_16:
3118         if (!proc->thunk.t_from32.proc) return 0;
3119         return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
3120                                         hwnd, msg, wParam, lParam );
3121     case WIN_PROC_32A:
3122         if (!proc->thunk.t_from16.proc) return 0;
3123         return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
3124                                       hwnd, msg, wParam, lParam );
3125     case WIN_PROC_32W:
3126         if (!proc->thunk.t_from16.proc) return 0;
3127         return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
3128                                          hwnd, msg, wParam, lParam );
3129     default:
3130         WARN_(relay)("Invalid proc %p\n", proc );
3131         return 0;
3132     }
3133 }
3134
3135
3136 /**********************************************************************
3137  *              CallWindowProcW (USER32.@)
3138  */
3139 LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
3140                                   WPARAM wParam, LPARAM lParam )
3141 {
3142     WINDOWPROC *proc;
3143
3144     if (!func) return 0;
3145
3146     if (!(proc = WINPROC_GetPtr( (WNDPROC)func )))
3147         return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
3148
3149 #if testing
3150     func = WINPROC_GetProc( (WNDPROC)proc, WIN_PROC_32W );
3151     return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
3152 #endif
3153
3154     switch(proc->type)
3155     {
3156     case WIN_PROC_16:
3157         if (!proc->thunk.t_from32.proc) return 0;
3158         return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
3159                                         hwnd, msg, wParam, lParam );
3160     case WIN_PROC_32A:
3161         if (!proc->thunk.t_from16.proc) return 0;
3162         return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
3163                                          hwnd, msg, wParam, lParam );
3164     case WIN_PROC_32W:
3165         if (!proc->thunk.t_from16.proc) return 0;
3166         return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
3167                                       hwnd, msg, wParam, lParam );
3168     default:
3169         WARN_(relay)("Invalid proc %p\n", proc );
3170         return 0;
3171     }
3172 }