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