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