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