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