Only measure child rectangles of visible children when deciding about
[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         {
560             LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
561                                      *pwparam * sizeof(WCHAR) + sizeof(LPARAM) );
562             if (!ptr) return -1;
563             *ptr++ = *plparam;  /* Store previous lParam */
564             *plparam = (LPARAM)ptr;
565         }
566         return 1;
567     /* lparam is string (0-terminated) */
568     case WM_SETTEXT:
569     case WM_WININICHANGE:
570     case CB_DIR:
571     case CB_FINDSTRING:
572     case CB_FINDSTRINGEXACT:
573     case CB_SELECTSTRING:
574     case LB_DIR:
575     case LB_ADDFILE:
576     case LB_FINDSTRING:
577     case LB_FINDSTRINGEXACT:
578     case LB_SELECTSTRING:
579     case EM_REPLACESEL:
580         if(!*plparam) return 0;
581         *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
582         return (*plparam ? 1 : -1);
583
584     case WM_NCCREATE:
585     case WM_CREATE:
586         {
587             struct s 
588             { CREATESTRUCTW cs;         /* new structure */
589               LPCWSTR lpszName;         /* allocated Name */
590               LPCWSTR lpszClass;        /* allocated Class */
591             };
592
593             struct s *xs = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct s));
594             if (!xs) return -1;
595             xs->cs = *(CREATESTRUCTW *)*plparam;
596             if (HIWORD(xs->cs.lpszName))
597                 xs->lpszName = xs->cs.lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
598                                                                   (LPCSTR)xs->cs.lpszName );
599             if (HIWORD(xs->cs.lpszClass))
600                 xs->lpszClass = xs->cs.lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
601                                                                     (LPCSTR)xs->cs.lpszClass );
602             *plparam = (LPARAM)xs;
603         }
604         return 1;
605     case WM_MDICREATE:
606         {
607             MDICREATESTRUCTW *cs =
608                 (MDICREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
609             if (!cs) return -1;
610             *cs = *(MDICREATESTRUCTW *)*plparam;
611             if (HIWORD(cs->szClass))
612                 cs->szClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
613                                                (LPCSTR)cs->szClass );
614             if (HIWORD(cs->szTitle))
615                 cs->szTitle = HEAP_strdupAtoW( GetProcessHeap(), 0,
616                                                (LPCSTR)cs->szTitle );
617             *plparam = (LPARAM)cs;
618         }
619         return 1;
620
621 /* Listbox */
622     case LB_ADDSTRING:
623     case LB_INSERTSTRING:
624         if(!*plparam) return 0;
625         if ( WINPROC_TestLBForStr( hwnd ))
626           *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
627         return (*plparam ? 1 : -1);
628
629     case LB_GETTEXT:                /* fixme: fixed sized buffer */
630         { if ( WINPROC_TestLBForStr( hwnd ))
631           { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
632             if (!ptr) return -1;
633             *ptr++ = *plparam;  /* Store previous lParam */
634             *plparam = (LPARAM)ptr;
635           }
636         }
637         return 1;
638
639 /* Combobox */
640     case CB_ADDSTRING:
641     case CB_INSERTSTRING:
642         if(!*plparam) return 0;
643         if ( WINPROC_TestCBForStr( hwnd ))
644           *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
645         return (*plparam ? 1 : -1);
646
647     case CB_GETLBTEXT:    /* fixme: fixed sized buffer */
648         { if ( WINPROC_TestCBForStr( hwnd ))
649           { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
650             if (!ptr) return -1;
651             *ptr++ = *plparam;  /* Store previous lParam */
652             *plparam = (LPARAM)ptr;
653           }
654         }
655         return 1;
656
657 /* Multiline edit */
658     case EM_GETLINE:
659         { WORD len = (WORD)*plparam;
660           LPARAM *ptr = (LPARAM *) HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
661           if (!ptr) return -1;
662           *ptr++ = *plparam;  /* Store previous lParam */
663           *((WORD *) ptr) = len;   /* Store the length */
664           *plparam = (LPARAM)ptr;
665         }
666         return 1;
667
668     case WM_CHARTOITEM:
669     case WM_MENUCHAR:
670     case WM_CHAR:
671     case WM_DEADCHAR:
672     case WM_SYSCHAR:
673     case WM_SYSDEADCHAR:
674     case EM_SETPASSWORDCHAR:
675         {
676             char ch = LOWORD(*pwparam);
677             WCHAR wch;
678             MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
679             *pwparam = MAKEWPARAM( wch, HIWORD(*pwparam) );
680         }
681         return 0;
682
683     case WM_ASKCBFORMATNAME:
684     case WM_DEVMODECHANGE:
685     case WM_PAINTCLIPBOARD:
686     case WM_SIZECLIPBOARD:
687         FIXME_(msg)("message %s (0x%x) needs translation, please report\n", SPY_GetMsgName(msg), msg );
688         return -1;
689     default:  /* No translation needed */
690         return 0;
691     }
692 }
693
694
695 /**********************************************************************
696  *           WINPROC_UnmapMsg32ATo32W
697  *
698  * Unmap a message that was mapped from Ansi to Unicode.
699  */
700 void WINPROC_UnmapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
701 {
702     switch(msg)
703     {
704     case WM_GETTEXT:
705         {
706             LPARAM *ptr = (LPARAM *)lParam - 1;
707             if (wParam > 0 && !WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
708                                                     (LPSTR)*ptr, wParam, NULL, NULL ))
709                 ((LPSTR)*ptr)[wParam-1] = 0;
710             HeapFree( GetProcessHeap(), 0, ptr );
711         }
712         break;
713
714     case WM_NCCREATE:
715     case WM_CREATE:
716         {
717             struct s 
718             { CREATESTRUCTW cs;         /* new structure */
719               LPWSTR lpszName;          /* allocated Name */
720               LPWSTR lpszClass;         /* allocated Class */
721             };
722             struct s *xs = (struct s *)lParam;
723             if (xs->lpszName)  HeapFree( GetProcessHeap(), 0, xs->lpszName );
724             if (xs->lpszClass) HeapFree( GetProcessHeap(), 0, xs->lpszClass );
725             HeapFree( GetProcessHeap(), 0, xs );
726         }
727         break;
728
729     case WM_MDICREATE:
730         {
731             MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
732             if (HIWORD(cs->szTitle))
733                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
734             if (HIWORD(cs->szClass))
735                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
736             HeapFree( GetProcessHeap(), 0, cs );
737         }
738         break;
739
740     case WM_SETTEXT:
741     case WM_WININICHANGE:
742     case CB_DIR:
743     case CB_FINDSTRING:
744     case CB_FINDSTRINGEXACT:
745     case CB_SELECTSTRING:
746     case LB_DIR:
747     case LB_ADDFILE:
748     case LB_FINDSTRING:
749     case LB_FINDSTRINGEXACT:
750     case LB_SELECTSTRING:
751     case EM_REPLACESEL:
752         HeapFree( GetProcessHeap(), 0, (void *)lParam );
753         break;
754
755 /* Listbox */
756     case LB_ADDSTRING:
757     case LB_INSERTSTRING:
758         if ( WINPROC_TestLBForStr( hwnd ))
759           HeapFree( GetProcessHeap(), 0, (void *)lParam );
760         break;
761
762     case LB_GETTEXT:
763         { if ( WINPROC_TestLBForStr( hwnd ))
764           { LPARAM *ptr = (LPARAM *)lParam - 1;
765             WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1, (LPSTR)*ptr, 0x7fffffff, NULL, NULL );
766             HeapFree( GetProcessHeap(), 0, ptr );
767           }
768         }
769         break;
770
771 /* Combobox */
772     case CB_ADDSTRING:
773     case CB_INSERTSTRING:
774         if ( WINPROC_TestCBForStr( hwnd ))
775           HeapFree( GetProcessHeap(), 0, (void *)lParam );
776         break;
777
778     case CB_GETLBTEXT:
779         { if ( WINPROC_TestCBForStr( hwnd ))
780           { LPARAM *ptr = (LPARAM *)lParam - 1;
781             WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1, (LPSTR)*ptr, 0x7fffffff, NULL, NULL );
782             HeapFree( GetProcessHeap(), 0, ptr );
783           }
784         }
785         break;
786
787 /* Multiline edit */
788     case EM_GETLINE:
789         { LPARAM * ptr = (LPARAM *)lParam - 1;  /* get the old lParam */
790           WORD len = *(WORD *) lParam;
791           if (len > 0 && !WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
792                                                (LPSTR)*ptr, len, NULL, NULL ))
793               ((LPSTR)*ptr)[len-1] = 0;
794           HeapFree( GetProcessHeap(), 0, ptr );
795         }
796         break;
797     }
798 }
799
800
801 /**********************************************************************
802  *           WINPROC_MapMsg32WTo32A
803  *
804  * Map a message from Unicode to Ansi.
805  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
806  */
807 INT WINPROC_MapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
808 {
809     switch(msg)
810     {
811     case WM_GETTEXT:
812         {
813             LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
814                                                *pwparam + sizeof(LPARAM) );
815             if (!ptr) return -1;
816             *ptr++ = *plparam;  /* Store previous lParam */
817             *plparam = (LPARAM)ptr;
818         }
819         return 1;
820
821     case WM_SETTEXT:
822     case WM_WININICHANGE:
823     case CB_DIR:
824     case CB_FINDSTRING:
825     case CB_FINDSTRINGEXACT:
826     case CB_SELECTSTRING:
827     case LB_DIR:
828     case LB_ADDFILE:
829     case LB_FINDSTRING:
830     case LB_FINDSTRINGEXACT:
831     case LB_SELECTSTRING:
832     case EM_REPLACESEL:
833         if(!*plparam) return 0;
834         *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
835         return (*plparam ? 1 : -1);
836
837     case WM_NCCREATE:
838     case WM_CREATE:
839         {
840             CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
841                                                                 sizeof(*cs) );
842             if (!cs) return -1;
843             *cs = *(CREATESTRUCTA *)*plparam;
844             if (HIWORD(cs->lpszName))
845                 cs->lpszName  = HEAP_strdupWtoA( GetProcessHeap(), 0,
846                                                  (LPCWSTR)cs->lpszName );
847             if (HIWORD(cs->lpszClass))
848                 cs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
849                                                  (LPCWSTR)cs->lpszClass);
850             *plparam = (LPARAM)cs;
851         }
852         return 1;
853     case WM_MDICREATE:
854         {
855             MDICREATESTRUCTA *cs =
856                 (MDICREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
857             if (!cs) return -1;
858             *cs = *(MDICREATESTRUCTA *)*plparam;
859             if (HIWORD(cs->szTitle))
860                 cs->szTitle = HEAP_strdupWtoA( GetProcessHeap(), 0,
861                                                (LPCWSTR)cs->szTitle );
862             if (HIWORD(cs->szClass))
863                 cs->szClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
864                                                (LPCWSTR)cs->szClass );
865             *plparam = (LPARAM)cs;
866         }
867         return 1;
868
869 /* Listbox */
870     case LB_ADDSTRING:
871     case LB_INSERTSTRING:
872         if(!*plparam) return 0;
873         if ( WINPROC_TestLBForStr( hwnd ))
874           *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
875         return (*plparam ? 1 : -1);
876
877     case LB_GETTEXT:                    /* fixme: fixed sized buffer */
878         { if ( WINPROC_TestLBForStr( hwnd ))
879           { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
880             if (!ptr) return -1;
881             *ptr++ = *plparam;  /* Store previous lParam */
882             *plparam = (LPARAM)ptr;
883           }
884         }
885         return 1;
886
887 /* Combobox */
888     case CB_ADDSTRING:
889     case CB_INSERTSTRING:
890         if(!*plparam) return 0;
891         if ( WINPROC_TestCBForStr( hwnd ))
892           *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
893         return (*plparam ? 1 : -1);
894
895     case CB_GETLBTEXT:          /* fixme: fixed sized buffer */
896         { if ( WINPROC_TestCBForStr( hwnd ))
897           { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
898             if (!ptr) return -1;
899             *ptr++ = *plparam;  /* Store previous lParam */
900             *plparam = (LPARAM)ptr;
901           }
902         }
903         return 1;
904
905 /* Multiline edit */
906     case EM_GETLINE:
907         { WORD len = (WORD)*plparam;
908           LPARAM *ptr = (LPARAM *) HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(CHAR) );
909           if (!ptr) return -1;
910           *ptr++ = *plparam;  /* Store previous lParam */
911           *((WORD *) ptr) = len;   /* Store the length */
912           *plparam = (LPARAM)ptr;
913         }
914         return 1;
915
916     case WM_CHARTOITEM:
917     case WM_MENUCHAR:
918     case WM_CHAR:
919     case WM_DEADCHAR:
920     case WM_SYSCHAR:
921     case WM_SYSDEADCHAR:
922     case EM_SETPASSWORDCHAR:
923         {
924             WCHAR wch = LOWORD(*pwparam);
925             char ch;
926             WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL );
927             *pwparam = MAKEWPARAM( ch, HIWORD(*pwparam) );
928         }
929         return 0;
930
931     case WM_ASKCBFORMATNAME:
932     case WM_DEVMODECHANGE:
933     case WM_PAINTCLIPBOARD:
934     case WM_SIZECLIPBOARD:
935         FIXME_(msg)("message %s (%04x) needs translation, please report\n",SPY_GetMsgName(msg),msg );
936         return -1;
937     default:  /* No translation needed */
938         return 0;
939     }
940 }
941
942
943 /**********************************************************************
944  *           WINPROC_UnmapMsg32WTo32A
945  *
946  * Unmap a message that was mapped from Unicode to Ansi.
947  */
948 void WINPROC_UnmapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
949 {
950     switch(msg)
951     {
952     case WM_GETTEXT:
953         {
954             LPARAM *ptr = (LPARAM *)lParam - 1;
955             if (wParam)
956             {
957                 if (!MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, wParam ))
958                     ((LPWSTR)*ptr)[wParam-1] = 0;
959             }
960             HeapFree( GetProcessHeap(), 0, ptr );
961         }
962         break;
963
964     case WM_SETTEXT:
965     case WM_WININICHANGE:
966     case CB_DIR:
967     case CB_FINDSTRING:
968     case CB_FINDSTRINGEXACT:
969     case CB_SELECTSTRING:
970     case LB_DIR:
971     case LB_ADDFILE:
972     case LB_FINDSTRING:
973     case LB_FINDSTRINGEXACT:
974     case LB_SELECTSTRING:
975     case EM_REPLACESEL:
976         HeapFree( GetProcessHeap(), 0, (void *)lParam );
977         break;
978
979     case WM_NCCREATE:
980     case WM_CREATE:
981         {
982             CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
983             if (HIWORD(cs->lpszName))
984                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
985             if (HIWORD(cs->lpszClass))
986                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
987             HeapFree( GetProcessHeap(), 0, cs );
988         }
989         break;
990
991     case WM_MDICREATE:
992         {
993             MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
994             if (HIWORD(cs->szTitle))
995                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
996             if (HIWORD(cs->szClass))
997                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
998             HeapFree( GetProcessHeap(), 0, cs );
999         }
1000         break;
1001
1002 /* Listbox */
1003     case LB_ADDSTRING:
1004     case LB_INSERTSTRING:
1005         if ( WINPROC_TestLBForStr( hwnd ))
1006           HeapFree( GetProcessHeap(), 0, (void *)lParam );
1007         break;
1008
1009     case LB_GETTEXT:
1010         if ( WINPROC_TestLBForStr( hwnd ))
1011         {
1012             LPARAM *ptr = (LPARAM *)lParam - 1;
1013             MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, 0x7fffffff );
1014             HeapFree( GetProcessHeap(), 0, ptr );
1015         }
1016         break;
1017
1018 /* Combobox */
1019     case CB_ADDSTRING:
1020     case CB_INSERTSTRING:
1021         if ( WINPROC_TestCBForStr( hwnd ))
1022           HeapFree( GetProcessHeap(), 0, (void *)lParam );
1023         break;
1024
1025     case CB_GETLBTEXT:
1026         if ( WINPROC_TestCBForStr( hwnd ))
1027         {
1028             LPARAM *ptr = (LPARAM *)lParam - 1;
1029             MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, 0x7fffffff );
1030             HeapFree( GetProcessHeap(), 0, ptr );
1031         }
1032         break;
1033
1034 /* Multiline edit */
1035     case EM_GETLINE:
1036         { LPARAM * ptr = (LPARAM *)lParam - 1;  /* get the old lparam */
1037           WORD len = *(WORD *)ptr;
1038           if (len)
1039           {
1040               if (!MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, len ))
1041                   ((LPWSTR)*ptr)[len-1] = 0;
1042           }
1043           HeapFree( GetProcessHeap(), 0, ptr );
1044         }
1045         break;
1046     }
1047 }
1048
1049
1050 /**********************************************************************
1051  *           WINPROC_MapMsg16To32A
1052  *
1053  * Map a message from 16- to 32-bit Ansi.
1054  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1055  */
1056 INT WINPROC_MapMsg16To32A( UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1057                              WPARAM *pwparam32, LPARAM *plparam )
1058 {
1059     *pmsg32 = (UINT)msg16;
1060     *pwparam32 = (WPARAM)wParam16;
1061     switch(msg16)
1062     {
1063     case WM_ACTIVATE:
1064     case WM_CHARTOITEM:
1065     case WM_COMMAND:
1066     case WM_VKEYTOITEM:
1067         *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1068         *plparam   = (LPARAM)(HWND)LOWORD(*plparam);
1069         return 0;
1070     case WM_HSCROLL:
1071     case WM_VSCROLL:
1072         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1073         *plparam   = (LPARAM)(HWND)HIWORD(*plparam);
1074         return 0;
1075     case WM_CTLCOLOR:
1076         if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
1077         *pmsg32    = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
1078         *pwparam32 = (WPARAM)(HDC)wParam16;
1079         *plparam   = (LPARAM)(HWND)LOWORD(*plparam);
1080         return 0;
1081     case WM_COMPAREITEM:
1082         {
1083             COMPAREITEMSTRUCT16* cis16 = MapSL(*plparam);
1084             COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)
1085                                         HeapAlloc(GetProcessHeap(), 0, sizeof(*cis));
1086             if (!cis) return -1;
1087             cis->CtlType    = cis16->CtlType;
1088             cis->CtlID      = cis16->CtlID;
1089             cis->hwndItem   = cis16->hwndItem;
1090             cis->itemID1    = cis16->itemID1;
1091             cis->itemData1  = cis16->itemData1;
1092             cis->itemID2    = cis16->itemID2;
1093             cis->itemData2  = cis16->itemData2;
1094             cis->dwLocaleId = 0;  /* FIXME */
1095             *plparam = (LPARAM)cis;
1096         }
1097         return 1;
1098     case WM_DELETEITEM:
1099         {
1100             DELETEITEMSTRUCT16* dis16 = MapSL(*plparam);
1101             DELETEITEMSTRUCT *dis = (DELETEITEMSTRUCT *)
1102                                         HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
1103             if (!dis) return -1;
1104             dis->CtlType  = dis16->CtlType;
1105             dis->CtlID    = dis16->CtlID;
1106             dis->hwndItem = dis16->hwndItem;
1107             dis->itemData = dis16->itemData;
1108             *plparam = (LPARAM)dis;
1109         }
1110         return 1;
1111     case WM_MEASUREITEM:
1112         {
1113             MEASUREITEMSTRUCT16* mis16 = MapSL(*plparam);
1114             MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)
1115                                         HeapAlloc(GetProcessHeap(), 0,
1116                                                 sizeof(*mis) + sizeof(LPARAM));
1117             if (!mis) return -1;
1118             mis->CtlType    = mis16->CtlType;
1119             mis->CtlID      = mis16->CtlID;
1120             mis->itemID     = mis16->itemID;
1121             mis->itemWidth  = mis16->itemWidth;
1122             mis->itemHeight = mis16->itemHeight;
1123             mis->itemData   = mis16->itemData;
1124             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
1125             *plparam = (LPARAM)mis;
1126         }
1127         return 1;
1128     case WM_DRAWITEM:
1129         {
1130             DRAWITEMSTRUCT16* dis16 = MapSL(*plparam);
1131             DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT*)HeapAlloc(GetProcessHeap(), 0,
1132                                                                  sizeof(*dis));
1133             if (!dis) return -1;
1134             dis->CtlType    = dis16->CtlType;
1135             dis->CtlID      = dis16->CtlID;
1136             dis->itemID     = dis16->itemID;
1137             dis->itemAction = dis16->itemAction;
1138             dis->itemState  = dis16->itemState;
1139             dis->hwndItem   = dis16->hwndItem;
1140             dis->hDC        = dis16->hDC;
1141             dis->itemData   = dis16->itemData;
1142             CONV_RECT16TO32( &dis16->rcItem, &dis->rcItem );
1143             *plparam = (LPARAM)dis;
1144         }
1145         return 1;
1146     case WM_GETMINMAXINFO:
1147         {
1148             MINMAXINFO *mmi = (MINMAXINFO *)HeapAlloc( GetProcessHeap(), 0,
1149                                                 sizeof(*mmi) + sizeof(LPARAM));
1150             if (!mmi) return -1;
1151             STRUCT32_MINMAXINFO16to32( MapSL(*plparam), mmi );
1152             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
1153             *plparam = (LPARAM)mmi;
1154         }
1155         return 1;
1156     case WM_GETTEXT:
1157     case WM_SETTEXT:
1158         *plparam = (LPARAM)MapSL(*plparam);
1159         return 0;
1160     case WM_MDICREATE:
1161         {
1162             MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1163             MDICREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1164             if (!cs) return -1;
1165             STRUCT32_MDICREATESTRUCT16to32A( cs16, cs );
1166             cs->szTitle = MapSL(cs16->szTitle);
1167             cs->szClass = MapSL(cs16->szClass);
1168             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1169             *plparam = (LPARAM)cs;
1170         }
1171         return 1;
1172     case WM_MDIGETACTIVE:
1173         *plparam = (LPARAM)HeapAlloc( GetProcessHeap(), 0, sizeof(BOOL) );
1174         *(BOOL*)(*plparam) = 0;
1175         return 1;
1176     case WM_MDISETMENU:
1177         if(wParam16==TRUE)
1178            *pmsg32=WM_MDIREFRESHMENU;
1179         *pwparam32 = (WPARAM)(HMENU)LOWORD(*plparam);
1180         *plparam   = (LPARAM)(HMENU)HIWORD(*plparam);
1181         return 0;
1182     case WM_MENUCHAR:
1183         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1184         *plparam   = (LPARAM)(HMENU)HIWORD(*plparam);
1185         return 0;
1186     case WM_MENUSELECT:
1187         if((LOWORD(*plparam) & MF_POPUP) && (LOWORD(*plparam) != 0xFFFF))
1188         {
1189             HMENU hmenu=(HMENU)HIWORD(*plparam);
1190             UINT Pos=MENU_FindSubMenu( &hmenu, wParam16);
1191             if(Pos==0xFFFF) Pos=0; /* NO_SELECTED_ITEM */
1192             *pwparam32 = MAKEWPARAM( Pos, LOWORD(*plparam) );
1193         }
1194         else *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1195         *plparam   = (LPARAM)(HMENU)HIWORD(*plparam);
1196         return 0;
1197     case WM_MDIACTIVATE:
1198         if( *plparam )
1199         {
1200             *pwparam32 = (WPARAM)(HWND)HIWORD(*plparam);
1201             *plparam   = (LPARAM)(HWND)LOWORD(*plparam);
1202         }
1203         else /* message sent to MDI client */
1204             *pwparam32 = wParam16;
1205         return 0;
1206     case WM_NCCALCSIZE:
1207         {
1208             NCCALCSIZE_PARAMS16 *nc16;
1209             NCCALCSIZE_PARAMS *nc;
1210
1211             nc = (NCCALCSIZE_PARAMS *)HeapAlloc( GetProcessHeap(), 0,
1212                                                 sizeof(*nc) + sizeof(LPARAM) );
1213             if (!nc) return -1;
1214             nc16 = MapSL(*plparam);
1215             CONV_RECT16TO32( &nc16->rgrc[0], &nc->rgrc[0] );
1216             if (wParam16)
1217             {
1218                 nc->lppos = (WINDOWPOS *)HeapAlloc( GetProcessHeap(), 0,
1219                                                       sizeof(*nc->lppos) );
1220                 CONV_RECT16TO32( &nc16->rgrc[1], &nc->rgrc[1] );
1221                 CONV_RECT16TO32( &nc16->rgrc[2], &nc->rgrc[2] );
1222                 if (nc->lppos) STRUCT32_WINDOWPOS16to32( MapSL(nc16->lppos), nc->lppos );
1223             }
1224             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
1225             *plparam = (LPARAM)nc;
1226         }
1227         return 1;
1228     case WM_NCCREATE:
1229     case WM_CREATE:
1230         {
1231             CREATESTRUCT16 *cs16 = MapSL(*plparam);
1232             CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
1233                                                 sizeof(*cs) + sizeof(LPARAM) );
1234             if (!cs) return -1;
1235             STRUCT32_CREATESTRUCT16to32A( cs16, cs );
1236             cs->lpszName  = MapSL(cs16->lpszName);
1237             cs->lpszClass = MapSL(cs16->lpszClass);
1238             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1239             *plparam = (LPARAM)cs;
1240         }
1241         return 1;
1242     case WM_PARENTNOTIFY:
1243         if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
1244         {
1245             *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1246             *plparam   = (LPARAM)(HWND)LOWORD(*plparam);
1247         }
1248         return 0;
1249     case WM_WINDOWPOSCHANGING:
1250     case WM_WINDOWPOSCHANGED:
1251         {
1252             WINDOWPOS *wp = (WINDOWPOS *)HeapAlloc( GetProcessHeap(), 0,
1253                                                 sizeof(*wp) + sizeof(LPARAM) );
1254             if (!wp) return -1;
1255             STRUCT32_WINDOWPOS16to32( MapSL(*plparam), wp );
1256             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
1257             *plparam = (LPARAM)wp;
1258         }
1259         return 1;
1260     case WM_GETDLGCODE:
1261         if (*plparam)
1262         {
1263             LPMSG16 msg16 = MapSL(*plparam);
1264             LPMSG msg32 = (LPMSG)HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1265
1266             if (!msg32) return -1;
1267             msg32->hwnd = msg16->hwnd;
1268             msg32->lParam = msg16->lParam;
1269             msg32->time = msg16->time;
1270             CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1271             /* this is right, right? */
1272             if (WINPROC_MapMsg16To32A(msg16->message,msg16->wParam,
1273                                      &msg32->message,&msg32->wParam,
1274                                      &msg32->lParam)<0) {
1275                 HeapFree( GetProcessHeap(), 0, msg32 );
1276                 return -1;
1277             }
1278             *plparam = (LPARAM)msg32;
1279             return 1;
1280         }
1281         else return 0;
1282     case WM_NOTIFY:
1283         *plparam = (LPARAM)MapSL(*plparam);
1284         return 1;
1285     case WM_ACTIVATEAPP:
1286         if (*plparam)
1287         { /* We need this when SetActiveWindow sends a Sendmessage16() to
1288              a 32bit window. Might be superflous with 32bit interprocess
1289              message queues.
1290           */
1291           HTASK16 htask = (HTASK16) *plparam;
1292           DWORD idThread = (DWORD)TASK_GetPtr(htask)->teb->tid;
1293           *plparam = (LPARAM) idThread;
1294         }
1295         return 1;
1296     case WM_ASKCBFORMATNAME:
1297     case WM_DEVMODECHANGE:
1298     case WM_PAINTCLIPBOARD:
1299     case WM_SIZECLIPBOARD:
1300     case WM_WININICHANGE:
1301         FIXME_(msg)("message %04x needs translation\n",msg16 );
1302         return -1;
1303
1304     default:  /* No translation needed */
1305         return 0;
1306     }
1307 }
1308
1309
1310 /**********************************************************************
1311  *           WINPROC_UnmapMsg16To32A
1312  *
1313  * Unmap a message that was mapped from 16- to 32-bit Ansi.
1314  */
1315 LRESULT WINPROC_UnmapMsg16To32A( HWND16 hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1316                                  LRESULT result )
1317 {
1318     switch(msg)
1319     {
1320     case WM_COMPAREITEM:
1321     case WM_DELETEITEM:
1322     case WM_DRAWITEM:
1323         HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
1324         break;
1325     case WM_MEASUREITEM:
1326         {
1327             MEASUREITEMSTRUCT16 *mis16;
1328             MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam;
1329             lParam = *(LPARAM *)(mis + 1);
1330             mis16 = MapSL(lParam);
1331             mis16->itemWidth  = (UINT16)mis->itemWidth;
1332             mis16->itemHeight = (UINT16)mis->itemHeight;
1333             HeapFree( GetProcessHeap(), 0, mis );
1334         }
1335         break;
1336     case WM_GETMINMAXINFO:
1337         {
1338             MINMAXINFO *mmi = (MINMAXINFO *)lParam;
1339             lParam = *(LPARAM *)(mmi + 1);
1340             STRUCT32_MINMAXINFO32to16( mmi, MapSL(lParam));
1341             HeapFree( GetProcessHeap(), 0, mmi );
1342         }
1343         break;
1344     case WM_MDICREATE:
1345         {
1346             MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1347             lParam = *(LPARAM *)(cs + 1);
1348             STRUCT32_MDICREATESTRUCT32Ato16( cs, MapSL(lParam) );
1349             HeapFree( GetProcessHeap(), 0, cs );
1350         }
1351         break;
1352     case WM_MDIGETACTIVE:
1353         result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL *)lParam) );
1354         HeapFree( GetProcessHeap(), 0, (BOOL *)lParam );
1355         break;
1356     case WM_NCCALCSIZE:
1357         {
1358             NCCALCSIZE_PARAMS16 *nc16;
1359             NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lParam;
1360             lParam = *(LPARAM *)(nc + 1);
1361             nc16 = MapSL(lParam);
1362             CONV_RECT32TO16( &nc->rgrc[0], &nc16->rgrc[0] );
1363             if (wParam)
1364             {
1365                 CONV_RECT32TO16( &nc->rgrc[1], &nc16->rgrc[1] );
1366                 CONV_RECT32TO16( &nc->rgrc[2], &nc16->rgrc[2] );
1367                 if (nc->lppos)
1368                 {
1369                     STRUCT32_WINDOWPOS32to16( nc->lppos, MapSL(nc16->lppos));
1370                     HeapFree( GetProcessHeap(), 0, nc->lppos );
1371                 }
1372             }
1373             HeapFree( GetProcessHeap(), 0, nc );
1374         }
1375         break;
1376     case WM_NCCREATE:
1377     case WM_CREATE:
1378         {
1379             CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1380             lParam = *(LPARAM *)(cs + 1);
1381             STRUCT32_CREATESTRUCT32Ato16( cs, MapSL(lParam) );
1382             HeapFree( GetProcessHeap(), 0, cs );
1383         }
1384         break;
1385     case WM_WINDOWPOSCHANGING:
1386     case WM_WINDOWPOSCHANGED:
1387         {
1388             WINDOWPOS *wp = (WINDOWPOS *)lParam;
1389             lParam = *(LPARAM *)(wp + 1);
1390             STRUCT32_WINDOWPOS32to16(wp, MapSL(lParam));
1391             HeapFree( GetProcessHeap(), 0, wp );
1392         }
1393         break;
1394     case WM_GETDLGCODE:
1395         if (lParam)
1396         {
1397             LPMSG msg32 = (LPMSG)lParam;
1398
1399             WINPROC_UnmapMsg16To32A( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1400                                      result);
1401             HeapFree( GetProcessHeap(), 0, msg32 );
1402         }
1403         break;
1404     }
1405     return result;
1406 }
1407
1408
1409 /**********************************************************************
1410  *           WINPROC_MapMsg16To32W
1411  *
1412  * Map a message from 16- to 32-bit Unicode.
1413  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1414  */
1415 INT WINPROC_MapMsg16To32W( HWND16 hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1416                              WPARAM *pwparam32, LPARAM *plparam )
1417 {
1418     char ch;
1419     WCHAR wch;
1420
1421     *pmsg32=(UINT)msg16;
1422     *pwparam32 = (WPARAM)wParam16;
1423     switch(msg16)
1424     {
1425     case WM_GETTEXT:
1426     case WM_SETTEXT:
1427         *plparam = (LPARAM)MapSL(*plparam);
1428         return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, pwparam32, plparam );
1429     case WM_NCCREATE:
1430     case WM_CREATE:
1431         {
1432             CREATESTRUCT16 *cs16 = MapSL(*plparam);
1433             CREATESTRUCTW *cs = (CREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
1434                                                 sizeof(*cs) + sizeof(LPARAM) );
1435             if (!cs) return -1;
1436             STRUCT32_CREATESTRUCT16to32A( cs16, (CREATESTRUCTA *)cs );
1437             cs->lpszName  = MapSL(cs16->lpszName);
1438             cs->lpszClass = MapSL(cs16->lpszClass);
1439             if (HIWORD(cs->lpszName))
1440                 cs->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
1441                                                 (LPCSTR)cs->lpszName );
1442             if (HIWORD(cs->lpszClass))
1443                 cs->lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
1444                                                  (LPCSTR)cs->lpszClass );
1445             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1446             *plparam = (LPARAM)cs;
1447         }
1448         return 1;
1449     case WM_MDICREATE:
1450         {
1451             MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1452             MDICREATESTRUCTW *cs =
1453                 (MDICREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
1454                                                 sizeof(*cs) + sizeof(LPARAM) );
1455             if (!cs) return -1;
1456             STRUCT32_MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCTA *)cs );
1457             cs->szTitle = MapSL(cs16->szTitle);
1458             cs->szClass = MapSL(cs16->szClass);
1459             if (HIWORD(cs->szTitle))
1460                 cs->szTitle = HEAP_strdupAtoW( GetProcessHeap(), 0,
1461                                                (LPCSTR)cs->szTitle );
1462             if (HIWORD(cs->szClass))
1463                 cs->szClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
1464                                                (LPCSTR)cs->szClass );
1465             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1466             *plparam = (LPARAM)cs;
1467         }
1468         return 1;
1469     case WM_GETDLGCODE:
1470         if (*plparam)
1471         {
1472             LPMSG16 msg16 = MapSL(*plparam);
1473             LPMSG msg32 = (LPMSG)HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1474
1475             if (!msg32) return -1;
1476             msg32->hwnd = msg16->hwnd;
1477             msg32->lParam = msg16->lParam;
1478             msg32->time = msg16->time;
1479             CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1480             /* this is right, right? */
1481             if (WINPROC_MapMsg16To32W(hwnd, msg16->message,msg16->wParam,
1482                                      &msg32->message,&msg32->wParam,
1483                                      &msg32->lParam)<0) {
1484                 HeapFree( GetProcessHeap(), 0, msg32 );
1485                 return -1;
1486             }
1487             *plparam = (LPARAM)msg32;
1488             return 1;
1489         }
1490         else return 0;
1491
1492     case WM_CHARTOITEM:
1493         ch = wParam16;
1494         MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1495         *pwparam32 = MAKEWPARAM( wch, HIWORD(*plparam) );
1496         *plparam   = (LPARAM)(HWND)LOWORD(*plparam);
1497         return 0;
1498     case WM_MENUCHAR:
1499         ch = wParam16;
1500         MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1501         *pwparam32 = MAKEWPARAM( wch, LOWORD(*plparam) );
1502         *plparam   = (LPARAM)(HMENU)HIWORD(*plparam);
1503         return 0;
1504     case WM_CHAR:
1505     case WM_DEADCHAR:
1506     case WM_SYSCHAR:
1507     case WM_SYSDEADCHAR:
1508         ch = wParam16;
1509         MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1510         *pwparam32 = wch;
1511         return 0;
1512
1513     default:  /* No Unicode translation needed */
1514         return WINPROC_MapMsg16To32A( msg16, wParam16, pmsg32,
1515                                       pwparam32, plparam );
1516     }
1517 }
1518
1519
1520 /**********************************************************************
1521  *           WINPROC_UnmapMsg16To32W
1522  *
1523  * Unmap a message that was mapped from 16- to 32-bit Unicode.
1524  */
1525 LRESULT WINPROC_UnmapMsg16To32W( HWND16 hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1526                                  LRESULT result )
1527 {
1528     switch(msg)
1529     {
1530     case WM_GETTEXT:
1531     case WM_SETTEXT:
1532         WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam );
1533         break;
1534     case WM_NCCREATE:
1535     case WM_CREATE:
1536         {
1537             CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
1538             lParam = *(LPARAM *)(cs + 1);
1539             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs, MapSL(lParam) );
1540             if (HIWORD(cs->lpszName))
1541                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
1542             if (HIWORD(cs->lpszClass))
1543                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
1544             HeapFree( GetProcessHeap(), 0, cs );
1545         }
1546         break;
1547     case WM_MDICREATE:
1548         {
1549             MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
1550             lParam = *(LPARAM *)(cs + 1);
1551             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs, MapSL(lParam) );
1552             if (HIWORD(cs->szTitle))
1553                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
1554             if (HIWORD(cs->szClass))
1555                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
1556             HeapFree( GetProcessHeap(), 0, cs );
1557         }
1558         break;
1559     case WM_GETDLGCODE:
1560         if (lParam)
1561         {
1562             LPMSG msg32 = (LPMSG)lParam;
1563
1564             WINPROC_UnmapMsg16To32W( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1565                                      result);
1566             HeapFree( GetProcessHeap(), 0, msg32 );
1567         }
1568         break;
1569     default:
1570         return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1571     }
1572     return result;
1573 }
1574
1575
1576 /**********************************************************************
1577  *           WINPROC_MapMsg32ATo16
1578  *
1579  * Map a message from 32-bit Ansi to 16-bit.
1580  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1581  */
1582 INT WINPROC_MapMsg32ATo16( HWND hwnd, UINT msg32, WPARAM wParam32,
1583                              UINT16 *pmsg16, WPARAM16 *pwparam16,
1584                              LPARAM *plparam )
1585 {
1586     *pmsg16 = (UINT16)msg32;
1587     *pwparam16 = (WPARAM16)LOWORD(wParam32);
1588     switch(msg32)
1589     {
1590     case BM_GETCHECK:
1591     case BM_SETCHECK:
1592     case BM_GETSTATE:
1593     case BM_SETSTATE:
1594     case BM_SETSTYLE:
1595         *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK);
1596         return 0;
1597
1598     case EM_GETSEL:
1599     case EM_GETRECT:
1600     case EM_SETRECT:
1601     case EM_SETRECTNP:
1602     case EM_SCROLL:
1603     case EM_LINESCROLL:
1604     case EM_SCROLLCARET:
1605     case EM_GETMODIFY:
1606     case EM_SETMODIFY:
1607     case EM_GETLINECOUNT:
1608     case EM_LINEINDEX:
1609     case EM_SETHANDLE:
1610     case EM_GETHANDLE:
1611     case EM_GETTHUMB:
1612     case EM_LINELENGTH:
1613     case EM_REPLACESEL:
1614     case EM_GETLINE:
1615     case EM_LIMITTEXT:
1616     case EM_CANUNDO:
1617     case EM_UNDO:
1618     case EM_FMTLINES:
1619     case EM_LINEFROMCHAR:
1620     case EM_SETTABSTOPS:
1621     case EM_SETPASSWORDCHAR:
1622     case EM_EMPTYUNDOBUFFER:
1623     case EM_GETFIRSTVISIBLELINE:
1624     case EM_SETREADONLY:
1625     case EM_SETWORDBREAKPROC:
1626     case EM_GETWORDBREAKPROC:
1627     case EM_GETPASSWORDCHAR:
1628         *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL);
1629         return 0;
1630
1631     case LB_CARETOFF:
1632     case LB_CARETON:
1633     case LB_DELETESTRING:
1634     case LB_GETANCHORINDEX:
1635     case LB_GETCARETINDEX:
1636     case LB_GETCOUNT:
1637     case LB_GETCURSEL:
1638     case LB_GETHORIZONTALEXTENT:
1639     case LB_GETITEMDATA:
1640     case LB_GETITEMHEIGHT:
1641     case LB_GETSEL:
1642     case LB_GETSELCOUNT:
1643     case LB_GETTEXTLEN:
1644     case LB_GETTOPINDEX:
1645     case LB_RESETCONTENT:
1646     case LB_SELITEMRANGE:
1647     case LB_SELITEMRANGEEX:
1648     case LB_SETANCHORINDEX:
1649     case LB_SETCARETINDEX:
1650     case LB_SETCOLUMNWIDTH:
1651     case LB_SETCURSEL:
1652     case LB_SETHORIZONTALEXTENT:
1653     case LB_SETITEMDATA:
1654     case LB_SETITEMHEIGHT:
1655     case LB_SETSEL:
1656     case LB_SETTOPINDEX:
1657         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1658         return 0;
1659     case CB_DELETESTRING:
1660     case CB_GETCOUNT:
1661     case CB_GETLBTEXTLEN:
1662     case CB_LIMITTEXT:
1663     case CB_RESETCONTENT:
1664     case CB_SETEDITSEL:
1665     case CB_GETCURSEL:
1666     case CB_SETCURSEL:
1667     case CB_SHOWDROPDOWN:
1668     case CB_SETITEMDATA:
1669     case CB_SETITEMHEIGHT:
1670     case CB_GETITEMHEIGHT:
1671     case CB_SETEXTENDEDUI:
1672     case CB_GETEXTENDEDUI:
1673     case CB_GETDROPPEDSTATE:
1674         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1675         return 0;
1676     case CB_GETEDITSEL:
1677         *pmsg16 = CB_GETEDITSEL16;
1678         return 1;
1679
1680     case LB_ADDSTRING:
1681     case LB_FINDSTRING:
1682     case LB_FINDSTRINGEXACT:
1683     case LB_INSERTSTRING:
1684     case LB_SELECTSTRING:
1685     case LB_DIR:
1686     case LB_ADDFILE:
1687         {
1688             LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1689             if (!str) return -1;
1690             *plparam = (LPARAM)SEGPTR_GET(str);
1691         }
1692         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1693         return 1;
1694
1695     case CB_ADDSTRING:
1696     case CB_FINDSTRING:
1697     case CB_FINDSTRINGEXACT:
1698     case CB_INSERTSTRING:
1699     case CB_SELECTSTRING:
1700     case CB_DIR:
1701         {
1702             LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1703             if (!str) return -1;
1704             *plparam = (LPARAM)SEGPTR_GET(str);
1705         }
1706         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1707         return 1;
1708
1709     case LB_GETITEMRECT:
1710         {
1711             RECT16 *rect;
1712             rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
1713             if (!rect) return -1;
1714             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
1715             *plparam = (LPARAM)SEGPTR_GET(rect);
1716         }
1717         *pmsg16 = LB_GETITEMRECT16;
1718         return 1;
1719     case LB_GETSELITEMS:
1720         {
1721             LPINT16 items;
1722             *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1723             if (!(items = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
1724                                         + sizeof(LPARAM)))) return -1;
1725             *((LPARAM *)items)++ = *plparam;  /* Store the previous lParam */
1726             *plparam = (LPARAM)SEGPTR_GET(items);
1727         }
1728         *pmsg16 = LB_GETSELITEMS16;
1729         return 1;
1730     case LB_SETTABSTOPS:
1731         if (wParam32)
1732         {
1733             INT i;
1734             LPINT16 stops;
1735             *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1736             if (!(stops = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
1737                                         + sizeof(LPARAM)))) return -1;
1738             for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT)*plparam+i);
1739             *plparam = (LPARAM)SEGPTR_GET(stops);
1740             return 1;
1741         }
1742         *pmsg16 = LB_SETTABSTOPS16;
1743         return 0;
1744
1745     case CB_GETDROPPEDCONTROLRECT:
1746         {
1747             RECT16 *rect;
1748             rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
1749             if (!rect) return -1;
1750             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
1751             *plparam = (LPARAM)SEGPTR_GET(rect);
1752         }
1753         *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
1754         return 1;
1755
1756     case LB_GETTEXT:
1757         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1758         *pmsg16 = LB_GETTEXT16;
1759         return 1;
1760
1761     case CB_GETLBTEXT:
1762         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1763         *pmsg16 = CB_GETLBTEXT16;
1764         return 1;
1765
1766     case EM_SETSEL:
1767         *pwparam16 = 0;
1768         *plparam = MAKELONG( (INT16)(INT)wParam32, (INT16)*plparam );
1769         *pmsg16 = EM_SETSEL16;
1770         return 0;
1771
1772     case WM_ACTIVATE:
1773     case WM_CHARTOITEM:
1774     case WM_COMMAND:
1775     case WM_VKEYTOITEM:
1776         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
1777         return 0;
1778     case WM_HSCROLL:
1779     case WM_VSCROLL:
1780         *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
1781         return 0;
1782     case WM_CTLCOLORMSGBOX:
1783     case WM_CTLCOLOREDIT:
1784     case WM_CTLCOLORLISTBOX:
1785     case WM_CTLCOLORBTN:
1786     case WM_CTLCOLORDLG:
1787     case WM_CTLCOLORSCROLLBAR:
1788     case WM_CTLCOLORSTATIC:
1789         *pmsg16  = WM_CTLCOLOR;
1790         *plparam = MAKELPARAM( (HWND16)*plparam,
1791                                (WORD)msg32 - WM_CTLCOLORMSGBOX );
1792         return 0;
1793     case WM_COMPAREITEM:
1794         {
1795             COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)*plparam;
1796             COMPAREITEMSTRUCT16 *cis = SEGPTR_NEW(COMPAREITEMSTRUCT16);
1797             if (!cis) return -1;
1798             cis->CtlType    = (UINT16)cis32->CtlType;
1799             cis->CtlID      = (UINT16)cis32->CtlID;
1800             cis->hwndItem   = (HWND16)cis32->hwndItem;
1801             cis->itemID1    = (UINT16)cis32->itemID1;
1802             cis->itemData1  = cis32->itemData1;
1803             cis->itemID2    = (UINT16)cis32->itemID2;
1804             cis->itemData2  = cis32->itemData2;
1805             *plparam = (LPARAM)SEGPTR_GET(cis);
1806         }
1807         return 1;
1808     case WM_DELETEITEM:
1809         {
1810             DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)*plparam;
1811             DELETEITEMSTRUCT16 *dis = SEGPTR_NEW(DELETEITEMSTRUCT16);
1812             if (!dis) return -1;
1813             dis->CtlType  = (UINT16)dis32->CtlType;
1814             dis->CtlID    = (UINT16)dis32->CtlID;
1815             dis->itemID   = (UINT16)dis32->itemID;
1816             dis->hwndItem = (HWND16)dis32->hwndItem;
1817             dis->itemData = dis32->itemData;
1818             *plparam = (LPARAM)SEGPTR_GET(dis);
1819         }
1820         return 1;
1821     case WM_DRAWITEM:
1822         {
1823             DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)*plparam;
1824             DRAWITEMSTRUCT16 *dis = SEGPTR_NEW(DRAWITEMSTRUCT16);
1825             if (!dis) return -1;
1826             dis->CtlType    = (UINT16)dis32->CtlType;
1827             dis->CtlID      = (UINT16)dis32->CtlID;
1828             dis->itemID     = (UINT16)dis32->itemID;
1829             dis->itemAction = (UINT16)dis32->itemAction;
1830             dis->itemState  = (UINT16)dis32->itemState;
1831             dis->hwndItem   = (HWND16)dis32->hwndItem;
1832             dis->hDC        = (HDC16)dis32->hDC;
1833             dis->itemData   = dis32->itemData;
1834             CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
1835             *plparam = (LPARAM)SEGPTR_GET(dis);
1836         }
1837         return 1;
1838     case WM_MEASUREITEM:
1839         {
1840             MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)*plparam;
1841             MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)
1842                                      SEGPTR_ALLOC(sizeof(*mis)+sizeof(LPARAM));
1843             if (!mis) return -1;
1844             mis->CtlType    = (UINT16)mis32->CtlType;
1845             mis->CtlID      = (UINT16)mis32->CtlID;
1846             mis->itemID     = (UINT16)mis32->itemID;
1847             mis->itemWidth  = (UINT16)mis32->itemWidth;
1848             mis->itemHeight = (UINT16)mis32->itemHeight;
1849             mis->itemData   = mis32->itemData;
1850             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
1851             *plparam = (LPARAM)SEGPTR_GET(mis);
1852         }
1853         return 1;
1854     case WM_GETMINMAXINFO:
1855         {
1856             MINMAXINFO16 *mmi = (MINMAXINFO16 *)SEGPTR_ALLOC( sizeof(*mmi) +
1857                                                               sizeof(LPARAM) );
1858             if (!mmi) return -1;
1859             STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)*plparam, mmi );
1860             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
1861             *plparam = (LPARAM)SEGPTR_GET(mmi);
1862         }
1863         return 1;
1864     case WM_GETTEXT:
1865         {
1866             LPSTR str;
1867             *pwparam16 = (WPARAM16)min( wParam32, 0xff80 ); /* Must be < 64K */
1868             if (!(str = SEGPTR_ALLOC(*pwparam16 + sizeof(LPARAM)))) return -1;
1869             *((LPARAM *)str)++ = *plparam;  /* Store the previous lParam */
1870             *plparam = (LPARAM)SEGPTR_GET(str);
1871         }
1872         return 1;
1873     case WM_MDICREATE:
1874         {
1875             MDICREATESTRUCT16 *cs;
1876             MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)*plparam;
1877             LPSTR name, cls;
1878
1879             if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
1880             STRUCT32_MDICREATESTRUCT32Ato16( cs32, cs );
1881             name = SEGPTR_STRDUP( cs32->szTitle );
1882             cls  = SEGPTR_STRDUP( cs32->szClass );
1883             cs->szTitle = SEGPTR_GET(name);
1884             cs->szClass = SEGPTR_GET(cls);
1885             *plparam = (LPARAM)SEGPTR_GET(cs);
1886         }
1887         return 1;
1888     case WM_MDIGETACTIVE:
1889         return 1;
1890     case WM_MDISETMENU:
1891         *plparam   = MAKELPARAM( (HMENU16)LOWORD(wParam32),
1892                                  (HMENU16)LOWORD(*plparam) );
1893         *pwparam16 = (*plparam == 0);
1894         return 0;
1895     case WM_MENUSELECT:
1896         if(HIWORD(wParam32) & MF_POPUP)
1897         {
1898             UINT16 hmenu;
1899             if (((UINT)HIWORD(wParam32) != 0xFFFF) || (*plparam))
1900             {
1901                 if((hmenu = GetSubMenu((HMENU16)*plparam, *pwparam16)))
1902                     *pwparam16=hmenu;
1903             }
1904         }
1905         /* fall through */
1906     case WM_MENUCHAR:
1907         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
1908         return 0;
1909     case WM_MDIACTIVATE:
1910         if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
1911         {
1912             *pwparam16 = ((HWND)*plparam == hwnd);
1913             *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
1914                                    (HWND16)LOWORD(wParam32) );
1915         }
1916         else
1917         {
1918             *pwparam16 = (HWND)wParam32;
1919             *plparam = 0;
1920         }
1921         return 0;
1922     case WM_NCCALCSIZE:
1923         {
1924             NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)*plparam;
1925             NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)SEGPTR_ALLOC( sizeof(*nc) + sizeof(LPARAM) );
1926             if (!nc) return -1;
1927
1928             CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
1929             if (wParam32)
1930             {
1931                 WINDOWPOS16 *wp;
1932                 CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
1933                 CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
1934                 if (!(wp = SEGPTR_NEW(WINDOWPOS16)))
1935                 {
1936                     SEGPTR_FREE(nc);
1937                     return -1;
1938                 }
1939                 STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
1940                 nc->lppos = SEGPTR_GET(wp);
1941             }
1942             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
1943             *plparam = (LPARAM)SEGPTR_GET(nc);
1944         }
1945         return 1;
1946     case WM_NCCREATE:
1947     case WM_CREATE:
1948         {
1949             CREATESTRUCT16 *cs;
1950             CREATESTRUCTA *cs32 = (CREATESTRUCTA *)*plparam;
1951             LPSTR name, cls;
1952
1953             if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
1954             STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
1955             name = SEGPTR_STRDUP( cs32->lpszName );
1956             cls  = SEGPTR_STRDUP( cs32->lpszClass );
1957             cs->lpszName  = SEGPTR_GET(name);
1958             cs->lpszClass = SEGPTR_GET(cls);
1959             *plparam = (LPARAM)SEGPTR_GET(cs);
1960         }
1961         return 1;
1962     case WM_PARENTNOTIFY:
1963         if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
1964             *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
1965         /* else nothing to do */
1966         return 0;
1967     case WM_NOTIFY:
1968         *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
1969         return 1;
1970     case WM_SETTEXT:
1971         {
1972             LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1973             if (!str) return -1;
1974             *plparam = (LPARAM)SEGPTR_GET(str);
1975         }
1976         return 1;
1977     case WM_WINDOWPOSCHANGING:
1978     case WM_WINDOWPOSCHANGED:
1979         {
1980             WINDOWPOS16 *wp = (WINDOWPOS16 *)SEGPTR_ALLOC( sizeof(*wp) +
1981                                                            sizeof(LPARAM) );
1982             if (!wp) return -1;
1983             STRUCT32_WINDOWPOS32to16( (WINDOWPOS *)*plparam, wp );
1984             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
1985             *plparam = (LPARAM)SEGPTR_GET(wp);
1986         }
1987         return 1;
1988     case WM_GETDLGCODE:
1989          if (*plparam) {
1990             LPMSG msg32 = (LPMSG) *plparam;
1991             LPMSG16 msg16 = (LPMSG16) SEGPTR_NEW( MSG16 );
1992
1993             if (!msg16) return -1;
1994             msg16->hwnd = msg32->hwnd;
1995             msg16->lParam = msg32->lParam;
1996             msg16->time = msg32->time;
1997             CONV_POINT32TO16(&msg32->pt,&msg16->pt);
1998             /* this is right, right? */
1999             if (WINPROC_MapMsg32ATo16(msg32->hwnd,msg32->message,msg32->wParam,
2000                          &msg16->message,&msg16->wParam, &msg16->lParam)<0) {
2001                 SEGPTR_FREE( msg16 );
2002                 return -1;
2003             }
2004             *plparam = (LPARAM)SEGPTR_GET(msg16);
2005             return 1;
2006         }
2007         return 0;
2008
2009     case WM_ACTIVATEAPP:
2010         if (*plparam) {
2011         *plparam = (LPARAM)THREAD_IdToTEB((DWORD) *plparam)->htask16;
2012         }
2013         return 1;
2014     case WM_ASKCBFORMATNAME:
2015     case WM_DEVMODECHANGE:
2016     case WM_PAINTCLIPBOARD:
2017     case WM_SIZECLIPBOARD:
2018     case WM_WININICHANGE:
2019         FIXME_(msg)("message %04x needs translation\n", msg32 );
2020         return -1;
2021     case WM_SIZING:  /* should not be send to 16-bit apps */
2022         return -1;
2023     default:  /* No translation needed */
2024         return 0;
2025     }
2026 }
2027
2028
2029 /**********************************************************************
2030  *           WINPROC_UnmapMsg32ATo16
2031  *
2032  * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
2033  */
2034 void WINPROC_UnmapMsg32ATo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2035                               MSGPARAM16* p16 ) 
2036 {
2037     switch(msg)
2038     {
2039     case LB_ADDFILE:
2040     case LB_ADDSTRING:
2041     case LB_DIR:
2042     case LB_FINDSTRING:
2043     case LB_FINDSTRINGEXACT:
2044     case LB_INSERTSTRING:
2045     case LB_SELECTSTRING:
2046     case LB_SETTABSTOPS:
2047     case CB_ADDSTRING:
2048     case CB_FINDSTRING:
2049     case CB_FINDSTRINGEXACT:
2050     case CB_INSERTSTRING:
2051     case CB_SELECTSTRING:
2052     case CB_DIR:
2053     case WM_COMPAREITEM:
2054     case WM_DELETEITEM:
2055     case WM_DRAWITEM:
2056     case WM_SETTEXT:
2057         SEGPTR_FREE( MapSL(p16->lParam) );
2058         break;
2059
2060     case CB_GETDROPPEDCONTROLRECT:
2061     case LB_GETITEMRECT:
2062         {
2063             RECT16 *rect = MapSL(p16->lParam);
2064             p16->lParam = *(LPARAM *)(rect + 1);
2065             CONV_RECT16TO32( rect, (RECT *)(p16->lParam));
2066             SEGPTR_FREE( rect );
2067         }
2068         break;
2069     case LB_GETSELITEMS:
2070         {
2071             INT i;
2072             LPINT16 items = MapSL(lParam);
2073             p16->lParam = *((LPARAM *)items - 1);
2074             for (i = 0; i < p16->wParam; i++) *((LPINT)(p16->lParam) + i) = items[i];
2075             SEGPTR_FREE( (LPARAM *)items - 1 );
2076         }
2077         break;
2078
2079     case CB_GETEDITSEL:
2080         if( wParam )
2081             *((LPUINT)(wParam)) = LOWORD(p16->lResult);
2082         if( lParam )
2083             *((LPUINT)(lParam)) = HIWORD(p16->lResult); /* FIXME: substract 1? */
2084         break;
2085
2086     case LB_GETTEXT:
2087     case CB_GETLBTEXT:
2088         UnMapLS( (SEGPTR)(p16->lParam) );
2089         break;
2090
2091     case WM_MEASUREITEM:
2092         {
2093             MEASUREITEMSTRUCT16 *mis = MapSL(p16->lParam);
2094             MEASUREITEMSTRUCT *mis32 = *(MEASUREITEMSTRUCT **)(mis + 1);
2095             mis32->itemWidth  = mis->itemWidth;
2096             mis32->itemHeight = mis->itemHeight;
2097             SEGPTR_FREE(mis);
2098         }
2099         break;
2100     case WM_GETMINMAXINFO:
2101         {
2102             MINMAXINFO16 *mmi = MapSL(p16->lParam);
2103             p16->lParam = *(LPARAM *)(mmi + 1);
2104             STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO *)(p16->lParam) );
2105             SEGPTR_FREE(mmi);
2106         }
2107         break;
2108     case WM_GETTEXT:
2109         {
2110             LPSTR str = MapSL(p16->lParam);
2111             p16->lParam = *((LPARAM *)str - 1);
2112             lstrcpynA( (LPSTR)(p16->lParam), str, p16->wParam );
2113             SEGPTR_FREE( (LPARAM *)str - 1 );
2114         }
2115         break;
2116     case WM_MDICREATE:
2117         {
2118             MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2119             SEGPTR_FREE( MapSL(cs->szTitle) );
2120             SEGPTR_FREE( MapSL(cs->szClass) );
2121             SEGPTR_FREE( cs );
2122         }
2123         break;
2124     case WM_MDIGETACTIVE:
2125         if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(p16->lResult);
2126         p16->lResult = (HWND)LOWORD(p16->lResult);
2127         break;
2128     case WM_NCCALCSIZE:
2129         {
2130             NCCALCSIZE_PARAMS *nc32;
2131             NCCALCSIZE_PARAMS16 *nc = MapSL(p16->lParam);
2132             p16->lParam = *(LPARAM *)(nc + 1);
2133             nc32 = (NCCALCSIZE_PARAMS *)(p16->lParam);
2134             CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
2135             if (p16->wParam)
2136             {
2137                 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
2138                 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
2139                 STRUCT32_WINDOWPOS16to32( MapSL(nc->lppos), nc32->lppos );
2140                 SEGPTR_FREE( MapSL(nc->lppos) );
2141             }
2142             SEGPTR_FREE(nc);
2143         }
2144         break;
2145     case WM_NCCREATE:
2146     case WM_CREATE:
2147         {
2148             CREATESTRUCT16 *cs = MapSL(p16->lParam);
2149             SEGPTR_FREE( MapSL(cs->lpszName) );
2150             SEGPTR_FREE( MapSL(cs->lpszClass) );
2151             SEGPTR_FREE( cs );
2152         }
2153         break;
2154     case WM_WINDOWPOSCHANGING:
2155     case WM_WINDOWPOSCHANGED:
2156         {
2157             WINDOWPOS16 *wp = MapSL(p16->lParam);
2158             p16->lParam = *(LPARAM *)(wp + 1);
2159             STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS *)p16->lParam );
2160             SEGPTR_FREE(wp);
2161         }
2162         break;
2163     case WM_NOTIFY:
2164         UnMapLS(p16->lParam);
2165         break;
2166     case WM_GETDLGCODE:
2167         if (p16->lParam)
2168         {
2169             LPMSG16 msg16 = MapSL(p16->lParam);
2170             MSGPARAM16 msgp16;
2171             msgp16.wParam=msg16->wParam;
2172             msgp16.lParam=msg16->lParam;
2173             WINPROC_UnmapMsg32ATo16(((LPMSG)lParam)->hwnd, ((LPMSG)lParam)->message,
2174                     ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam,
2175                     &msgp16 );
2176             SEGPTR_FREE(msg16);
2177         }
2178         break;
2179     }
2180 }
2181
2182
2183 /**********************************************************************
2184  *           WINPROC_MapMsg32WTo16
2185  *
2186  * Map a message from 32-bit Unicode to 16-bit.
2187  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
2188  */
2189 INT WINPROC_MapMsg32WTo16( HWND hwnd, UINT msg32, WPARAM wParam32,
2190                              UINT16 *pmsg16, WPARAM16 *pwparam16,
2191                              LPARAM *plparam )
2192 {
2193     char ch;
2194     WCHAR wch;
2195
2196     *pmsg16    = LOWORD(msg32);
2197     *pwparam16 = LOWORD(wParam32);
2198     switch(msg32)
2199     {
2200     case LB_ADDSTRING:
2201     case LB_FINDSTRING:
2202     case LB_FINDSTRINGEXACT:
2203     case LB_INSERTSTRING:
2204     case LB_SELECTSTRING:
2205     case LB_DIR:
2206     case LB_ADDFILE:
2207         {
2208             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
2209             if (!str) return -1;
2210             *plparam   = (LPARAM)SEGPTR_GET(str);
2211         }
2212         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2213         return 1;
2214
2215     case CB_ADDSTRING:
2216     case CB_FINDSTRING:
2217     case CB_FINDSTRINGEXACT:
2218     case CB_INSERTSTRING:
2219     case CB_SELECTSTRING:
2220     case CB_DIR:
2221         {
2222             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
2223             if (!str) return -1;
2224             *plparam   = (LPARAM)SEGPTR_GET(str);
2225         }
2226         *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING);
2227         return 1;
2228
2229     case WM_NCCREATE:
2230     case WM_CREATE:
2231         {
2232             CREATESTRUCT16 *cs;
2233             CREATESTRUCTW *cs32 = (CREATESTRUCTW *)*plparam;
2234             LPSTR name, cls;
2235
2236             if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
2237             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs32, cs );
2238             name = SEGPTR_STRDUP_WtoA( cs32->lpszName );
2239             cls  = SEGPTR_STRDUP_WtoA( cs32->lpszClass );
2240             cs->lpszName  = SEGPTR_GET(name);
2241             cs->lpszClass = SEGPTR_GET(cls);
2242             *plparam   = (LPARAM)SEGPTR_GET(cs);
2243         }
2244         return 1;
2245     case WM_MDICREATE:
2246         {
2247             MDICREATESTRUCT16 *cs;
2248             MDICREATESTRUCTW *cs32 = (MDICREATESTRUCTW *)*plparam;
2249             LPSTR name, cls;
2250
2251             if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
2252             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs32, cs );
2253             name = SEGPTR_STRDUP_WtoA( cs32->szTitle );
2254             cls  = SEGPTR_STRDUP_WtoA( cs32->szClass );
2255             cs->szTitle = SEGPTR_GET(name);
2256             cs->szClass = SEGPTR_GET(cls);
2257             *plparam   = (LPARAM)SEGPTR_GET(cs);
2258         }
2259         return 1;
2260     case WM_SETTEXT:
2261         {
2262             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
2263             if (!str) return -1;
2264             *plparam   = (LPARAM)SEGPTR_GET(str);
2265         }
2266         return 1;
2267     case LB_GETTEXT:
2268     case CB_GETLBTEXT:
2269         if ( WINPROC_TestLBForStr( hwnd ))
2270         {
2271             LPSTR str = (LPSTR) SEGPTR_ALLOC( 256 ); /* fixme: fixed sized buffer */
2272             if (!str) return -1;
2273             *pmsg16    = (msg32 == LB_GETTEXT)? LB_GETTEXT16 : CB_GETLBTEXT16;
2274             *plparam   = (LPARAM)SEGPTR_GET(str);
2275         }
2276         return 1;
2277
2278     case WM_CHARTOITEM:
2279         wch = LOWORD(wParam32);
2280         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2281         *pwparam16 = ch;
2282         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2283         return 0;
2284     case WM_MENUCHAR:
2285         wch = LOWORD(wParam32);
2286         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2287         *pwparam16 = ch;
2288         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2289         return 0;
2290     case WM_CHAR:
2291     case WM_DEADCHAR:
2292     case WM_SYSCHAR:
2293     case WM_SYSDEADCHAR:
2294         wch = wParam32;
2295         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2296         *pwparam16 = ch;
2297         return 0;
2298
2299     default:  /* No Unicode translation needed (?) */
2300         return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2301                                       pwparam16, plparam );
2302     }
2303 }
2304
2305
2306 /**********************************************************************
2307  *           WINPROC_UnmapMsg32WTo16
2308  *
2309  * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2310  */
2311 void WINPROC_UnmapMsg32WTo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2312                               MSGPARAM16* p16 )
2313 {
2314     switch(msg)
2315     {
2316     case WM_GETTEXT:
2317         {
2318             LPSTR str = MapSL(p16->lParam);
2319             p16->lParam = *((LPARAM *)str - 1);
2320             MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)p16->lParam, 0x7fffffff );
2321             SEGPTR_FREE( (LPARAM *)str - 1 );
2322         }
2323         break;
2324     case LB_GETTEXT:
2325     case CB_GETLBTEXT:
2326         if ( WINPROC_TestLBForStr( hwnd ))
2327         {
2328             LPSTR str = MapSL(p16->lParam);
2329             MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff );
2330             SEGPTR_FREE( (LPARAM *) str );
2331         }
2332         break;
2333     default:
2334         WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, p16 );
2335         break;
2336     }
2337 }
2338
2339
2340 /**********************************************************************
2341  *           WINPROC_CallProc32ATo32W
2342  *
2343  * Call a window procedure, translating args from Ansi to Unicode.
2344  */
2345 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC func, HWND hwnd,
2346                                          UINT msg, WPARAM wParam,
2347                                          LPARAM lParam )
2348 {
2349     LRESULT result;
2350     int unmap;
2351
2352     if( (unmap = WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam )) == -1) {
2353         ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2354                        SPY_GetMsgName(msg), wParam, lParam );
2355         return 0;
2356     }
2357     result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2358     if( unmap ) WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam );
2359     return result;
2360 }
2361
2362
2363 /**********************************************************************
2364  *           WINPROC_CallProc32WTo32A
2365  *
2366  * Call a window procedure, translating args from Unicode to Ansi.
2367  */
2368 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC func, HWND hwnd,
2369                                          UINT msg, WPARAM wParam,
2370                                          LPARAM lParam )
2371 {
2372     LRESULT result;
2373     int unmap;
2374
2375     if ((unmap = WINPROC_MapMsg32WTo32A( hwnd, msg, &wParam, &lParam )) == -1) {
2376         ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2377                        SPY_GetMsgName(msg), wParam, lParam );
2378         return 0;
2379     }
2380     result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2381     if( unmap ) WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam );
2382     return result;
2383 }
2384
2385
2386 /**********************************************************************
2387  *           WINPROC_CallProc16To32A
2388  *
2389  * Call a 32-bit window procedure, translating the 16-bit args.
2390  */
2391 static LRESULT WINPROC_CallProc16To32A( WNDPROC func, HWND16 hwnd,
2392                                         UINT16 msg, WPARAM16 wParam,
2393                                         LPARAM lParam )
2394 {
2395     LRESULT result;
2396     UINT msg32;
2397     WPARAM wParam32;
2398
2399     if (WINPROC_MapMsg16To32A( msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2400         return 0;
2401     result = WINPROC_CallWndProc( func, hwnd, msg32, wParam32, lParam );
2402     return WINPROC_UnmapMsg16To32A( hwnd, msg32, wParam32, lParam, result );
2403 }
2404
2405 /**********************************************************************
2406  *           WINPROC_Thunk16To32A
2407  */
2408 static LRESULT WINAPI WINPROC_Thunk16To32A( WNDPROC func, LPBYTE args )
2409 {
2410     HWND16   hwnd   = *(HWND16 *)( args+8 );
2411     UINT16   msg    = *(HWND16 *)( args+6 );
2412     WPARAM16 wParam = *(HWND16 *)( args+4 );
2413     LPARAM   lParam = *(LPARAM *)( args+0 );
2414
2415     return WINPROC_CallProc16To32A( func, hwnd, msg, wParam, lParam );
2416 }
2417
2418
2419 /**********************************************************************
2420  *           WINPROC_CallProc16To32W
2421  *
2422  * Call a 32-bit window procedure, translating the 16-bit args.
2423  */
2424 static LRESULT WINPROC_CallProc16To32W( WNDPROC func, HWND16 hwnd,
2425                                         UINT16 msg, WPARAM16 wParam,
2426                                         LPARAM lParam )
2427 {
2428     LRESULT result;
2429     UINT msg32;
2430     WPARAM wParam32;
2431
2432     if (WINPROC_MapMsg16To32W( hwnd, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2433         return 0;
2434
2435     result = WINPROC_CallWndProc( func, hwnd, msg32, wParam32, lParam );
2436     
2437     return WINPROC_UnmapMsg16To32W( hwnd, msg32, wParam32, lParam, result );
2438 }
2439
2440 /**********************************************************************
2441  *           WINPROC_Thunk16To32W
2442  */
2443 static LRESULT WINAPI WINPROC_Thunk16To32W( WNDPROC func, LPBYTE args )
2444 {
2445     HWND16   hwnd   = *(HWND16 *)( args+8 );
2446     UINT16   msg    = *(HWND16 *)( args+6 );
2447     WPARAM16 wParam = *(HWND16 *)( args+4 );
2448     LPARAM   lParam = *(LPARAM *)( args+0 );
2449
2450     return WINPROC_CallProc16To32W( func, hwnd, msg, wParam, lParam );
2451 }
2452
2453 /**********************************************************************
2454  *           WINPROC_CallProc32ATo16
2455  *
2456  * Call a 16-bit window procedure, translating the 32-bit args.
2457  */
2458 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd,
2459                                                UINT msg, WPARAM wParam,
2460                                                LPARAM lParam )
2461 {
2462     UINT16 msg16;
2463     MSGPARAM16 mp16;
2464
2465     mp16.lParam = lParam;
2466     if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, 
2467                                &msg16, &mp16.wParam, &mp16.lParam ) == -1)
2468         return 0;
2469     mp16.lResult = WINPROC_CallWndProc16( func, hwnd, msg16,
2470                                           mp16.wParam, mp16.lParam );
2471     WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, &mp16 );
2472     return mp16.lResult;
2473 }
2474
2475
2476 /**********************************************************************
2477  *           WINPROC_CallProc32WTo16
2478  *
2479  * Call a 16-bit window procedure, translating the 32-bit args.
2480  */
2481 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd,
2482                                                UINT msg, WPARAM wParam,
2483                                                LPARAM lParam )
2484 {
2485     UINT16 msg16;
2486     MSGPARAM16 mp16;
2487
2488     mp16.lParam = lParam;
2489     if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &mp16.wParam,
2490                                &mp16.lParam ) == -1)
2491         return 0;
2492     mp16.lResult = WINPROC_CallWndProc16( func, hwnd, msg16,
2493                                           mp16.wParam, mp16.lParam );
2494     WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, &mp16 );
2495     return mp16.lResult;
2496 }
2497
2498
2499 /**********************************************************************
2500  *              CallWindowProc (USER.122)
2501  *              CallWindowProc16 (USER32.@)
2502  */
2503 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
2504                                  WPARAM16 wParam, LPARAM lParam )
2505 {
2506     WINDOWPROC *proc = WINPROC_GetPtr( func );
2507
2508     if (!proc)
2509         return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
2510
2511 #if testing
2512     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16 );
2513     return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
2514 #endif
2515     
2516     switch(proc->type)
2517     {
2518     case WIN_PROC_16:
2519         if (!proc->thunk.t_from32.proc) return 0;
2520         return WINPROC_CallWndProc16( proc->thunk.t_from32.proc,
2521                                       hwnd, msg, wParam, lParam );
2522     case WIN_PROC_32A:
2523         if (!proc->thunk.t_from16.proc) return 0;
2524         return WINPROC_CallProc16To32A( proc->thunk.t_from16.proc,
2525                                         hwnd, msg, wParam, lParam );
2526     case WIN_PROC_32W:
2527         if (!proc->thunk.t_from16.proc) return 0;
2528         return WINPROC_CallProc16To32W( proc->thunk.t_from16.proc,
2529                                         hwnd, msg, wParam, lParam );
2530     default:
2531         WARN_(relay)("Invalid proc %p\n", proc );
2532         return 0;
2533     }
2534 }
2535
2536
2537 /**********************************************************************
2538  *              CallWindowProcA (USER32.@)
2539  *
2540  * The CallWindowProc() function invokes the windows procedure _func_,
2541  * with _hwnd_ as the target window, the message specified by _msg_, and
2542  * the message parameters _wParam_ and _lParam_.
2543  *
2544  * Some kinds of argument conversion may be done, I'm not sure what.
2545  *
2546  * CallWindowProc() may be used for windows subclassing. Use
2547  * SetWindowLong() to set a new windows procedure for windows of the
2548  * subclass, and handle subclassed messages in the new windows
2549  * procedure. The new windows procedure may then use CallWindowProc()
2550  * with _func_ set to the parent class's windows procedure to dispatch
2551  * the message to the superclass.
2552  *
2553  * RETURNS
2554  *
2555  *    The return value is message dependent.
2556  *
2557  * CONFORMANCE
2558  *
2559  *   ECMA-234, Win32 
2560  */
2561 LRESULT WINAPI CallWindowProcA( 
2562     WNDPROC func,  /* [in] window procedure */
2563     HWND hwnd,     /* [in] target window */
2564     UINT msg,      /* [in] message */
2565     WPARAM wParam, /* [in] message dependent parameter */
2566     LPARAM lParam  /* [in] message dependent parameter */
2567 ) {
2568     WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2569
2570     if (!proc) return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2571
2572 #if testing
2573     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32A );
2574     return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2575 #endif
2576
2577     switch(proc->type)
2578     {
2579     case WIN_PROC_16:
2580         if (!proc->thunk.t_from32.proc) return 0;
2581         return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
2582                                         hwnd, msg, wParam, lParam );
2583     case WIN_PROC_32A:
2584         if (!proc->thunk.t_from16.proc) return 0;
2585         return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
2586                                       hwnd, msg, wParam, lParam );
2587     case WIN_PROC_32W:
2588         if (!proc->thunk.t_from16.proc) return 0;
2589         return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
2590                                          hwnd, msg, wParam, lParam );
2591     default:
2592         WARN_(relay)("Invalid proc %p\n", proc );
2593         return 0;
2594     }
2595 }
2596
2597
2598 /**********************************************************************
2599  *              CallWindowProcW (USER32.@)
2600  */
2601 LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
2602                                   WPARAM wParam, LPARAM lParam )
2603 {
2604     WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2605
2606     if (!proc) return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2607
2608 #if testing
2609     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32W );
2610     return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2611 #endif
2612
2613     switch(proc->type)
2614     {
2615     case WIN_PROC_16:
2616         if (!proc->thunk.t_from32.proc) return 0;
2617         return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
2618                                         hwnd, msg, wParam, lParam );
2619     case WIN_PROC_32A:
2620         if (!proc->thunk.t_from16.proc) return 0;
2621         return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
2622                                          hwnd, msg, wParam, lParam );
2623     case WIN_PROC_32W:
2624         if (!proc->thunk.t_from16.proc) return 0;
2625         return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
2626                                       hwnd, msg, wParam, lParam );
2627     default:
2628         WARN_(relay)("Invalid proc %p\n", proc );
2629         return 0;
2630     }
2631 }