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