Fixed some issues found by winapi_check.
[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     /* following messages should not be sent to 16-bit apps */
2022     case WM_SIZING:
2023     case WM_CAPTURECHANGED:
2024     case WM_STYLECHANGING:
2025     case WM_STYLECHANGED:
2026         return -1;
2027     default:  /* No translation needed */
2028         return 0;
2029     }
2030 }
2031
2032
2033 /**********************************************************************
2034  *           WINPROC_UnmapMsg32ATo16
2035  *
2036  * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
2037  */
2038 void WINPROC_UnmapMsg32ATo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2039                               MSGPARAM16* p16 ) 
2040 {
2041     switch(msg)
2042     {
2043     case LB_ADDFILE:
2044     case LB_ADDSTRING:
2045     case LB_DIR:
2046     case LB_FINDSTRING:
2047     case LB_FINDSTRINGEXACT:
2048     case LB_INSERTSTRING:
2049     case LB_SELECTSTRING:
2050     case LB_SETTABSTOPS:
2051     case CB_ADDSTRING:
2052     case CB_FINDSTRING:
2053     case CB_FINDSTRINGEXACT:
2054     case CB_INSERTSTRING:
2055     case CB_SELECTSTRING:
2056     case CB_DIR:
2057     case WM_COMPAREITEM:
2058     case WM_DELETEITEM:
2059     case WM_DRAWITEM:
2060     case WM_SETTEXT:
2061         SEGPTR_FREE( MapSL(p16->lParam) );
2062         break;
2063
2064     case CB_GETDROPPEDCONTROLRECT:
2065     case LB_GETITEMRECT:
2066         {
2067             RECT16 *rect = MapSL(p16->lParam);
2068             p16->lParam = *(LPARAM *)(rect + 1);
2069             CONV_RECT16TO32( rect, (RECT *)(p16->lParam));
2070             SEGPTR_FREE( rect );
2071         }
2072         break;
2073     case LB_GETSELITEMS:
2074         {
2075             INT i;
2076             LPINT16 items = MapSL(lParam);
2077             p16->lParam = *((LPARAM *)items - 1);
2078             for (i = 0; i < p16->wParam; i++) *((LPINT)(p16->lParam) + i) = items[i];
2079             SEGPTR_FREE( (LPARAM *)items - 1 );
2080         }
2081         break;
2082
2083     case CB_GETEDITSEL:
2084         if( wParam )
2085             *((LPUINT)(wParam)) = LOWORD(p16->lResult);
2086         if( lParam )
2087             *((LPUINT)(lParam)) = HIWORD(p16->lResult); /* FIXME: substract 1? */
2088         break;
2089
2090     case LB_GETTEXT:
2091     case CB_GETLBTEXT:
2092         UnMapLS( (SEGPTR)(p16->lParam) );
2093         break;
2094
2095     case WM_MEASUREITEM:
2096         {
2097             MEASUREITEMSTRUCT16 *mis = MapSL(p16->lParam);
2098             MEASUREITEMSTRUCT *mis32 = *(MEASUREITEMSTRUCT **)(mis + 1);
2099             mis32->itemWidth  = mis->itemWidth;
2100             mis32->itemHeight = mis->itemHeight;
2101             SEGPTR_FREE(mis);
2102         }
2103         break;
2104     case WM_GETMINMAXINFO:
2105         {
2106             MINMAXINFO16 *mmi = MapSL(p16->lParam);
2107             p16->lParam = *(LPARAM *)(mmi + 1);
2108             STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO *)(p16->lParam) );
2109             SEGPTR_FREE(mmi);
2110         }
2111         break;
2112     case WM_GETTEXT:
2113         {
2114             LPSTR str = MapSL(p16->lParam);
2115             p16->lParam = *((LPARAM *)str - 1);
2116             lstrcpynA( (LPSTR)(p16->lParam), str, p16->wParam );
2117             SEGPTR_FREE( (LPARAM *)str - 1 );
2118         }
2119         break;
2120     case WM_MDICREATE:
2121         {
2122             MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2123             SEGPTR_FREE( MapSL(cs->szTitle) );
2124             SEGPTR_FREE( MapSL(cs->szClass) );
2125             SEGPTR_FREE( cs );
2126         }
2127         break;
2128     case WM_MDIGETACTIVE:
2129         if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(p16->lResult);
2130         p16->lResult = (HWND)LOWORD(p16->lResult);
2131         break;
2132     case WM_NCCALCSIZE:
2133         {
2134             NCCALCSIZE_PARAMS *nc32;
2135             NCCALCSIZE_PARAMS16 *nc = MapSL(p16->lParam);
2136             p16->lParam = *(LPARAM *)(nc + 1);
2137             nc32 = (NCCALCSIZE_PARAMS *)(p16->lParam);
2138             CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
2139             if (p16->wParam)
2140             {
2141                 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
2142                 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
2143                 STRUCT32_WINDOWPOS16to32( MapSL(nc->lppos), nc32->lppos );
2144                 SEGPTR_FREE( MapSL(nc->lppos) );
2145             }
2146             SEGPTR_FREE(nc);
2147         }
2148         break;
2149     case WM_NCCREATE:
2150     case WM_CREATE:
2151         {
2152             CREATESTRUCT16 *cs = MapSL(p16->lParam);
2153             SEGPTR_FREE( MapSL(cs->lpszName) );
2154             SEGPTR_FREE( MapSL(cs->lpszClass) );
2155             SEGPTR_FREE( cs );
2156         }
2157         break;
2158     case WM_WINDOWPOSCHANGING:
2159     case WM_WINDOWPOSCHANGED:
2160         {
2161             WINDOWPOS16 *wp = MapSL(p16->lParam);
2162             p16->lParam = *(LPARAM *)(wp + 1);
2163             STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS *)p16->lParam );
2164             SEGPTR_FREE(wp);
2165         }
2166         break;
2167     case WM_NOTIFY:
2168         UnMapLS(p16->lParam);
2169         break;
2170     case WM_GETDLGCODE:
2171         if (p16->lParam)
2172         {
2173             LPMSG16 msg16 = MapSL(p16->lParam);
2174             MSGPARAM16 msgp16;
2175             msgp16.wParam=msg16->wParam;
2176             msgp16.lParam=msg16->lParam;
2177             WINPROC_UnmapMsg32ATo16(((LPMSG)lParam)->hwnd, ((LPMSG)lParam)->message,
2178                     ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam,
2179                     &msgp16 );
2180             SEGPTR_FREE(msg16);
2181         }
2182         break;
2183     }
2184 }
2185
2186
2187 /**********************************************************************
2188  *           WINPROC_MapMsg32WTo16
2189  *
2190  * Map a message from 32-bit Unicode to 16-bit.
2191  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
2192  */
2193 INT WINPROC_MapMsg32WTo16( HWND hwnd, UINT msg32, WPARAM wParam32,
2194                              UINT16 *pmsg16, WPARAM16 *pwparam16,
2195                              LPARAM *plparam )
2196 {
2197     char ch;
2198     WCHAR wch;
2199
2200     *pmsg16    = LOWORD(msg32);
2201     *pwparam16 = LOWORD(wParam32);
2202     switch(msg32)
2203     {
2204     case LB_ADDSTRING:
2205     case LB_FINDSTRING:
2206     case LB_FINDSTRINGEXACT:
2207     case LB_INSERTSTRING:
2208     case LB_SELECTSTRING:
2209     case LB_DIR:
2210     case LB_ADDFILE:
2211         {
2212             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
2213             if (!str) return -1;
2214             *plparam   = (LPARAM)SEGPTR_GET(str);
2215         }
2216         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2217         return 1;
2218
2219     case CB_ADDSTRING:
2220     case CB_FINDSTRING:
2221     case CB_FINDSTRINGEXACT:
2222     case CB_INSERTSTRING:
2223     case CB_SELECTSTRING:
2224     case CB_DIR:
2225         {
2226             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
2227             if (!str) return -1;
2228             *plparam   = (LPARAM)SEGPTR_GET(str);
2229         }
2230         *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING);
2231         return 1;
2232
2233     case WM_NCCREATE:
2234     case WM_CREATE:
2235         {
2236             CREATESTRUCT16 *cs;
2237             CREATESTRUCTW *cs32 = (CREATESTRUCTW *)*plparam;
2238             LPSTR name, cls;
2239
2240             if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
2241             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs32, cs );
2242             name = SEGPTR_STRDUP_WtoA( cs32->lpszName );
2243             cls  = SEGPTR_STRDUP_WtoA( cs32->lpszClass );
2244             cs->lpszName  = SEGPTR_GET(name);
2245             cs->lpszClass = SEGPTR_GET(cls);
2246             *plparam   = (LPARAM)SEGPTR_GET(cs);
2247         }
2248         return 1;
2249     case WM_MDICREATE:
2250         {
2251             MDICREATESTRUCT16 *cs;
2252             MDICREATESTRUCTW *cs32 = (MDICREATESTRUCTW *)*plparam;
2253             LPSTR name, cls;
2254
2255             if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
2256             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs32, cs );
2257             name = SEGPTR_STRDUP_WtoA( cs32->szTitle );
2258             cls  = SEGPTR_STRDUP_WtoA( cs32->szClass );
2259             cs->szTitle = SEGPTR_GET(name);
2260             cs->szClass = SEGPTR_GET(cls);
2261             *plparam   = (LPARAM)SEGPTR_GET(cs);
2262         }
2263         return 1;
2264     case WM_SETTEXT:
2265         {
2266             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
2267             if (!str) return -1;
2268             *plparam   = (LPARAM)SEGPTR_GET(str);
2269         }
2270         return 1;
2271     case LB_GETTEXT:
2272     case CB_GETLBTEXT:
2273         if ( WINPROC_TestLBForStr( hwnd ))
2274         {
2275             LPSTR str = (LPSTR) SEGPTR_ALLOC( 256 ); /* fixme: fixed sized buffer */
2276             if (!str) return -1;
2277             *pmsg16    = (msg32 == LB_GETTEXT)? LB_GETTEXT16 : CB_GETLBTEXT16;
2278             *plparam   = (LPARAM)SEGPTR_GET(str);
2279         }
2280         return 1;
2281
2282     case WM_CHARTOITEM:
2283         wch = LOWORD(wParam32);
2284         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2285         *pwparam16 = ch;
2286         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2287         return 0;
2288     case WM_MENUCHAR:
2289         wch = LOWORD(wParam32);
2290         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2291         *pwparam16 = ch;
2292         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2293         return 0;
2294     case WM_CHAR:
2295     case WM_DEADCHAR:
2296     case WM_SYSCHAR:
2297     case WM_SYSDEADCHAR:
2298         wch = wParam32;
2299         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2300         *pwparam16 = ch;
2301         return 0;
2302
2303     default:  /* No Unicode translation needed (?) */
2304         return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2305                                       pwparam16, plparam );
2306     }
2307 }
2308
2309
2310 /**********************************************************************
2311  *           WINPROC_UnmapMsg32WTo16
2312  *
2313  * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2314  */
2315 void WINPROC_UnmapMsg32WTo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2316                               MSGPARAM16* p16 )
2317 {
2318     switch(msg)
2319     {
2320     case WM_GETTEXT:
2321         {
2322             LPSTR str = MapSL(p16->lParam);
2323             p16->lParam = *((LPARAM *)str - 1);
2324             MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)p16->lParam, 0x7fffffff );
2325             SEGPTR_FREE( (LPARAM *)str - 1 );
2326         }
2327         break;
2328     case LB_GETTEXT:
2329     case CB_GETLBTEXT:
2330         if ( WINPROC_TestLBForStr( hwnd ))
2331         {
2332             LPSTR str = MapSL(p16->lParam);
2333             MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff );
2334             SEGPTR_FREE( (LPARAM *) str );
2335         }
2336         break;
2337     default:
2338         WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, p16 );
2339         break;
2340     }
2341 }
2342
2343
2344 /**********************************************************************
2345  *           WINPROC_CallProc32ATo32W
2346  *
2347  * Call a window procedure, translating args from Ansi to Unicode.
2348  */
2349 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC func, HWND hwnd,
2350                                          UINT msg, WPARAM wParam,
2351                                          LPARAM lParam )
2352 {
2353     LRESULT result;
2354     int unmap;
2355
2356     if( (unmap = WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam )) == -1) {
2357         ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2358                        SPY_GetMsgName(msg), wParam, lParam );
2359         return 0;
2360     }
2361     result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2362     if( unmap ) WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam );
2363     return result;
2364 }
2365
2366
2367 /**********************************************************************
2368  *           WINPROC_CallProc32WTo32A
2369  *
2370  * Call a window procedure, translating args from Unicode to Ansi.
2371  */
2372 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC func, HWND hwnd,
2373                                          UINT msg, WPARAM wParam,
2374                                          LPARAM lParam )
2375 {
2376     LRESULT result;
2377     int unmap;
2378
2379     if ((unmap = WINPROC_MapMsg32WTo32A( hwnd, msg, &wParam, &lParam )) == -1) {
2380         ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2381                        SPY_GetMsgName(msg), wParam, lParam );
2382         return 0;
2383     }
2384     result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2385     if( unmap ) WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam );
2386     return result;
2387 }
2388
2389
2390 /**********************************************************************
2391  *           WINPROC_CallProc16To32A
2392  *
2393  * Call a 32-bit window procedure, translating the 16-bit args.
2394  */
2395 static LRESULT WINPROC_CallProc16To32A( WNDPROC func, HWND16 hwnd,
2396                                         UINT16 msg, WPARAM16 wParam,
2397                                         LPARAM lParam )
2398 {
2399     LRESULT result;
2400     UINT msg32;
2401     WPARAM wParam32;
2402
2403     if (WINPROC_MapMsg16To32A( msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2404         return 0;
2405     result = WINPROC_CallWndProc( func, hwnd, msg32, wParam32, lParam );
2406     return WINPROC_UnmapMsg16To32A( hwnd, msg32, wParam32, lParam, result );
2407 }
2408
2409 /**********************************************************************
2410  *           WINPROC_Thunk16To32A
2411  */
2412 static LRESULT WINAPI WINPROC_Thunk16To32A( WNDPROC func, LPBYTE args )
2413 {
2414     HWND16   hwnd   = *(HWND16 *)( args+8 );
2415     UINT16   msg    = *(HWND16 *)( args+6 );
2416     WPARAM16 wParam = *(HWND16 *)( args+4 );
2417     LPARAM   lParam = *(LPARAM *)( args+0 );
2418
2419     return WINPROC_CallProc16To32A( func, hwnd, msg, wParam, lParam );
2420 }
2421
2422
2423 /**********************************************************************
2424  *           WINPROC_CallProc16To32W
2425  *
2426  * Call a 32-bit window procedure, translating the 16-bit args.
2427  */
2428 static LRESULT WINPROC_CallProc16To32W( WNDPROC func, HWND16 hwnd,
2429                                         UINT16 msg, WPARAM16 wParam,
2430                                         LPARAM lParam )
2431 {
2432     LRESULT result;
2433     UINT msg32;
2434     WPARAM wParam32;
2435
2436     if (WINPROC_MapMsg16To32W( hwnd, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2437         return 0;
2438
2439     result = WINPROC_CallWndProc( func, hwnd, msg32, wParam32, lParam );
2440     
2441     return WINPROC_UnmapMsg16To32W( hwnd, msg32, wParam32, lParam, result );
2442 }
2443
2444 /**********************************************************************
2445  *           WINPROC_Thunk16To32W
2446  */
2447 static LRESULT WINAPI WINPROC_Thunk16To32W( WNDPROC func, LPBYTE args )
2448 {
2449     HWND16   hwnd   = *(HWND16 *)( args+8 );
2450     UINT16   msg    = *(HWND16 *)( args+6 );
2451     WPARAM16 wParam = *(HWND16 *)( args+4 );
2452     LPARAM   lParam = *(LPARAM *)( args+0 );
2453
2454     return WINPROC_CallProc16To32W( func, hwnd, msg, wParam, lParam );
2455 }
2456
2457 /**********************************************************************
2458  *           WINPROC_CallProc32ATo16
2459  *
2460  * Call a 16-bit window procedure, translating the 32-bit args.
2461  */
2462 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd,
2463                                                UINT msg, WPARAM wParam,
2464                                                LPARAM lParam )
2465 {
2466     UINT16 msg16;
2467     MSGPARAM16 mp16;
2468
2469     mp16.lParam = lParam;
2470     if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, 
2471                                &msg16, &mp16.wParam, &mp16.lParam ) == -1)
2472         return 0;
2473     mp16.lResult = WINPROC_CallWndProc16( func, hwnd, msg16,
2474                                           mp16.wParam, mp16.lParam );
2475     WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, &mp16 );
2476     return mp16.lResult;
2477 }
2478
2479
2480 /**********************************************************************
2481  *           WINPROC_CallProc32WTo16
2482  *
2483  * Call a 16-bit window procedure, translating the 32-bit args.
2484  */
2485 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd,
2486                                                UINT msg, WPARAM wParam,
2487                                                LPARAM lParam )
2488 {
2489     UINT16 msg16;
2490     MSGPARAM16 mp16;
2491
2492     mp16.lParam = lParam;
2493     if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &mp16.wParam,
2494                                &mp16.lParam ) == -1)
2495         return 0;
2496     mp16.lResult = WINPROC_CallWndProc16( func, hwnd, msg16,
2497                                           mp16.wParam, mp16.lParam );
2498     WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, &mp16 );
2499     return mp16.lResult;
2500 }
2501
2502
2503 /**********************************************************************
2504  *              CallWindowProc (USER.122)
2505  *              CallWindowProc16 (USER32.@)
2506  */
2507 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
2508                                  WPARAM16 wParam, LPARAM lParam )
2509 {
2510     WINDOWPROC *proc = WINPROC_GetPtr( func );
2511
2512     if (!proc)
2513         return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
2514
2515 #if testing
2516     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16 );
2517     return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
2518 #endif
2519     
2520     switch(proc->type)
2521     {
2522     case WIN_PROC_16:
2523         if (!proc->thunk.t_from32.proc) return 0;
2524         return WINPROC_CallWndProc16( proc->thunk.t_from32.proc,
2525                                       hwnd, msg, wParam, lParam );
2526     case WIN_PROC_32A:
2527         if (!proc->thunk.t_from16.proc) return 0;
2528         return WINPROC_CallProc16To32A( proc->thunk.t_from16.proc,
2529                                         hwnd, msg, wParam, lParam );
2530     case WIN_PROC_32W:
2531         if (!proc->thunk.t_from16.proc) return 0;
2532         return WINPROC_CallProc16To32W( proc->thunk.t_from16.proc,
2533                                         hwnd, msg, wParam, lParam );
2534     default:
2535         WARN_(relay)("Invalid proc %p\n", proc );
2536         return 0;
2537     }
2538 }
2539
2540
2541 /**********************************************************************
2542  *              CallWindowProcA (USER32.@)
2543  *
2544  * The CallWindowProc() function invokes the windows procedure _func_,
2545  * with _hwnd_ as the target window, the message specified by _msg_, and
2546  * the message parameters _wParam_ and _lParam_.
2547  *
2548  * Some kinds of argument conversion may be done, I'm not sure what.
2549  *
2550  * CallWindowProc() may be used for windows subclassing. Use
2551  * SetWindowLong() to set a new windows procedure for windows of the
2552  * subclass, and handle subclassed messages in the new windows
2553  * procedure. The new windows procedure may then use CallWindowProc()
2554  * with _func_ set to the parent class's windows procedure to dispatch
2555  * the message to the superclass.
2556  *
2557  * RETURNS
2558  *
2559  *    The return value is message dependent.
2560  *
2561  * CONFORMANCE
2562  *
2563  *   ECMA-234, Win32 
2564  */
2565 LRESULT WINAPI CallWindowProcA( 
2566     WNDPROC func,  /* [in] window procedure */
2567     HWND hwnd,     /* [in] target window */
2568     UINT msg,      /* [in] message */
2569     WPARAM wParam, /* [in] message dependent parameter */
2570     LPARAM lParam  /* [in] message dependent parameter */
2571 ) {
2572     WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2573
2574     if (!proc) return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2575
2576 #if testing
2577     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32A );
2578     return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2579 #endif
2580
2581     switch(proc->type)
2582     {
2583     case WIN_PROC_16:
2584         if (!proc->thunk.t_from32.proc) return 0;
2585         return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
2586                                         hwnd, msg, wParam, lParam );
2587     case WIN_PROC_32A:
2588         if (!proc->thunk.t_from16.proc) return 0;
2589         return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
2590                                       hwnd, msg, wParam, lParam );
2591     case WIN_PROC_32W:
2592         if (!proc->thunk.t_from16.proc) return 0;
2593         return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
2594                                          hwnd, msg, wParam, lParam );
2595     default:
2596         WARN_(relay)("Invalid proc %p\n", proc );
2597         return 0;
2598     }
2599 }
2600
2601
2602 /**********************************************************************
2603  *              CallWindowProcW (USER32.@)
2604  */
2605 LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
2606                                   WPARAM wParam, LPARAM lParam )
2607 {
2608     WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2609
2610     if (!proc) return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2611
2612 #if testing
2613     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32W );
2614     return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2615 #endif
2616
2617     switch(proc->type)
2618     {
2619     case WIN_PROC_16:
2620         if (!proc->thunk.t_from32.proc) return 0;
2621         return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
2622                                         hwnd, msg, wParam, lParam );
2623     case WIN_PROC_32A:
2624         if (!proc->thunk.t_from16.proc) return 0;
2625         return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
2626                                          hwnd, msg, wParam, lParam );
2627     case WIN_PROC_32W:
2628         if (!proc->thunk.t_from16.proc) return 0;
2629         return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
2630                                       hwnd, msg, wParam, lParam );
2631     default:
2632         WARN_(relay)("Invalid proc %p\n", proc );
2633         return 0;
2634     }
2635 }