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