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