Added WM_GETDLGCODE handling in (Un)MapMsg32Ato16.
[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 "windows.h"
9 #include "callback.h"
10 #include "heap.h"
11 #include "selectors.h"
12 #include "struct32.h"
13 #include "win.h"
14 #include "winproc.h"
15 #include "debug.h"
16 #include "spy.h"
17 #include "commctrl.h"
18
19 /* Window procedure 16-to-32-bit thunk,
20  * see BuildSpec16Files() in tools/build.c */
21
22 typedef struct
23 {
24     BYTE       popl_eax;             /* popl  %eax (return address) */
25     BYTE       pushl_func;           /* pushl $proc */
26     WNDPROC32  proc WINE_PACKED;
27     BYTE       pushl_eax;            /* pushl %eax */
28     WORD       pushw_bp WINE_PACKED; /* pushw %bp */
29     BYTE       pushl_thunk;          /* pushl $thunkfrom16 */
30     void     (*thunk32)() WINE_PACKED;
31     BYTE       lcall;                /* lcall cs:relay */
32     void     (*relay)() WINE_PACKED; /* WINPROC_CallProc16To32A/W() */
33     WORD       cs WINE_PACKED;
34 } WINPROC_THUNK_FROM16;
35
36 /* Window procedure 32-to-16-bit thunk,
37  * see BuildSpec32Files() in tools/build.c */
38
39 typedef struct
40 {
41     BYTE       popl_eax;             /* popl  %eax (return address) */
42     BYTE       pushl_func;           /* pushl $proc */
43     WNDPROC16  proc WINE_PACKED;
44     BYTE       pushl_eax;            /* pushl %eax */
45     BYTE       jmp;                  /* jmp   relay (relative jump)*/
46     void     (*relay)() WINE_PACKED; /* WINPROC_CallProc32ATo16() */
47 } WINPROC_THUNK_FROM32;
48
49 /* Simple jmp to call 32-bit procedure directly */
50 typedef struct
51 {
52     BYTE       jmp;                  /* jmp  proc (relative jump) */
53     WNDPROC32  proc WINE_PACKED;
54 } WINPROC_JUMP;
55
56 typedef union
57 {
58     WINPROC_THUNK_FROM16  t_from16;
59     WINPROC_THUNK_FROM32  t_from32;
60 } WINPROC_THUNK;
61
62 typedef struct tagWINDOWPROC
63 {
64     WINPROC_THUNK         thunk;    /* Thunk */
65     WINPROC_JUMP          jmp;      /* Jump */
66     struct tagWINDOWPROC *next;     /* Next window proc */
67     UINT32                magic;    /* Magic number */
68     WINDOWPROCTYPE        type;     /* Function type */
69     WINDOWPROCUSER        user;     /* Function user */
70 } WINDOWPROC;
71
72 #define WINPROC_MAGIC  ('W' | ('P' << 8) | ('R' << 16) | ('C' << 24))
73
74 #define WINPROC_THUNKPROC(pproc) \
75     (((pproc)->type == WIN_PROC_16) ? \
76           (WNDPROC16)((pproc)->thunk.t_from32.proc) : \
77           (WNDPROC16)((pproc)->thunk.t_from16.proc))
78
79 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND32 hwnd,
80                                                UINT32 msg, WPARAM32 wParam,
81                                                LPARAM lParam );
82 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND32 hwnd,
83                                                UINT32 msg, WPARAM32 wParam,
84                                                LPARAM lParam );
85 static LRESULT WINPROC_CallProc16To32A( HWND16 hwnd, UINT16 msg,
86                                         WPARAM16 wParam, LPARAM lParam,
87                                         WNDPROC32 func );
88 static LRESULT WINPROC_CallProc16To32W( HWND16 hwnd, UINT16 msg,
89                                         WPARAM16 wParam, LPARAM lParam,
90                                         WNDPROC32 func );
91
92 static HANDLE32 WinProcHeap;
93
94
95 /**********************************************************************
96  *           WINPROC_Init
97  */
98 BOOL32 WINPROC_Init(void)
99 {
100     WinProcHeap = HeapCreate( HEAP_WINE_SEGPTR | HEAP_WINE_CODESEG, 0, 0 );
101     if (!WinProcHeap)
102     {
103         WARN(relay, "Unable to create winproc heap\n" );
104         return FALSE;
105     }
106     return TRUE;
107 }
108
109
110 /**********************************************************************
111  *           WINPROC_CallWndProc32
112  *
113  * Call a 32-bit WndProc.
114  */
115 static LRESULT WINPROC_CallWndProc32( WNDPROC32 proc, HWND32 hwnd, UINT32 msg,
116                                       WPARAM32 wParam, LPARAM lParam )
117 {
118     TRACE(relay, "(wndproc=%p,hwnd=%08x,msg=%s,wp=%08x,lp=%08lx)\n",
119                    proc, hwnd, SPY_GetMsgName(msg), wParam, lParam );
120     return proc( hwnd, msg, wParam, lParam );
121 }
122
123
124 /**********************************************************************
125  *           WINPROC_GetPtr
126  *
127  * Return a pointer to the win proc.
128  */
129 static WINDOWPROC *WINPROC_GetPtr( WNDPROC16 handle )
130 {
131     BYTE *ptr;
132     WINDOWPROC *proc;
133
134     /* Check for a linear pointer */
135
136     if (HEAP_IsInsideHeap( WinProcHeap, 0, (LPVOID)handle ))
137     {
138         ptr = (BYTE *)handle;
139         /* First check if it is the jmp address */
140         if (*ptr == 0xe9 /* jmp */) ptr -= (int)&((WINDOWPROC *)0)->jmp -
141                                            (int)&((WINDOWPROC *)0)->thunk;
142         /* Now it must be the thunk address */
143         if (*ptr == 0x58 /* popl eax */) ptr -= (int)&((WINDOWPROC *)0)->thunk;
144         /* Now we have a pointer to the WINDOWPROC struct */
145         if (((WINDOWPROC *)ptr)->magic == WINPROC_MAGIC)
146             return (WINDOWPROC *)ptr;
147     }
148
149     /* Check for a segmented pointer */
150
151     if (!IsBadReadPtr16((SEGPTR)handle,sizeof(WINDOWPROC)-sizeof(proc->thunk)))
152     {
153         ptr = (BYTE *)PTR_SEG_TO_LIN(handle);
154         if (!HEAP_IsInsideHeap( WinProcHeap, 0, ptr )) return NULL;
155         /* It must be the thunk address */
156         if (*ptr == 0x58 /* popl eax */) ptr -= (int)&((WINDOWPROC *)0)->thunk;
157         /* Now we have a pointer to the WINDOWPROC struct */
158         if (((WINDOWPROC *)ptr)->magic == WINPROC_MAGIC)
159             return (WINDOWPROC *)ptr;
160     }
161
162     return NULL;
163 }
164
165
166 /**********************************************************************
167  *           WINPROC_AllocWinProc
168  *
169  * Allocate a new window procedure.
170  */
171 static WINDOWPROC *WINPROC_AllocWinProc( WNDPROC16 func, WINDOWPROCTYPE type,
172                                          WINDOWPROCUSER user )
173 {
174     WINDOWPROC *proc, *oldproc;
175
176     /* Allocate a window procedure */
177
178     if (!(proc = HeapAlloc( WinProcHeap, 0, sizeof(WINDOWPROC) ))) return 0;
179
180     /* Check if the function is already a win proc */
181
182     if ((oldproc = WINPROC_GetPtr( func )))
183     {
184         *proc = *oldproc;
185     }
186     else
187     {
188         switch(type)
189         {
190         case WIN_PROC_16:
191             proc->thunk.t_from32.popl_eax    = 0x58;   /* popl  %eax */
192             proc->thunk.t_from32.pushl_func  = 0x68;   /* pushl $proc */
193             proc->thunk.t_from32.proc        = func;
194             proc->thunk.t_from32.pushl_eax   = 0x50;   /* pushl %eax */
195             proc->thunk.t_from32.jmp         = 0xe9;   /* jmp   relay*/
196             proc->thunk.t_from32.relay =  /* relative jump */
197                 (void(*)())((DWORD)WINPROC_CallProc32ATo16 -
198                                      (DWORD)(&proc->thunk.t_from32.relay + 1));
199             break;
200         case WIN_PROC_32A:
201         case WIN_PROC_32W:
202             proc->thunk.t_from16.popl_eax    = 0x58;   /* popl  %eax */
203             proc->thunk.t_from16.pushl_func  = 0x68;   /* pushl $proc */
204             proc->thunk.t_from16.proc        = (FARPROC32)func;
205             proc->thunk.t_from16.pushl_eax   = 0x50;   /* pushl %eax */
206             proc->thunk.t_from16.pushw_bp    = 0x5566; /* pushw %bp */
207             proc->thunk.t_from16.pushl_thunk = 0x68;   /* pushl $thunkfrom16 */
208             proc->thunk.t_from16.thunk32     = (type == WIN_PROC_32A) ?
209                                            (void(*)())WINPROC_CallProc16To32A :
210                                            (void(*)())WINPROC_CallProc16To32W;
211             proc->thunk.t_from16.lcall       = 0x9a;   /* lcall cs:relay */
212             proc->thunk.t_from16.relay       = Callbacks->CallFrom16WndProc;
213             GET_CS(proc->thunk.t_from16.cs);
214             proc->jmp.jmp  = 0xe9;
215             /* Fixup relative jump */
216             proc->jmp.proc = (WNDPROC32)((DWORD)func -
217                                                  (DWORD)(&proc->jmp.proc + 1));
218             break;
219         default:
220             /* Should not happen */
221             break;
222         }
223         proc->magic = WINPROC_MAGIC;
224         proc->type  = type;
225         proc->user  = user;
226     }
227     proc->next  = NULL;
228     TRACE(win, "(%08x,%d): returning %08x\n",
229                  (UINT32)func, type, (UINT32)proc );
230     return proc;
231 }
232
233
234 /**********************************************************************
235  *           WINPROC_GetProc
236  *
237  * Get a window procedure pointer that can be passed to the Windows program.
238  */
239 WNDPROC16 WINPROC_GetProc( HWINDOWPROC proc, WINDOWPROCTYPE type )
240 {
241     if (!proc) return NULL;
242     if (type == WIN_PROC_16)  /* We want a 16:16 address */
243     {
244         if (((WINDOWPROC *)proc)->type == WIN_PROC_16)
245             return ((WINDOWPROC *)proc)->thunk.t_from32.proc;
246         else
247             return (WNDPROC16)HEAP_GetSegptr( WinProcHeap, 0,
248                                               &((WINDOWPROC *)proc)->thunk );
249     }
250     else  /* We want a 32-bit address */
251     {
252         if (((WINDOWPROC *)proc)->type == WIN_PROC_16)
253             return (WNDPROC16)&((WINDOWPROC *)proc)->thunk;
254         else if (type != ((WINDOWPROC *)proc)->type)
255             /* Have to return the jmp address if types don't match */
256             return (WNDPROC16)&((WINDOWPROC *)proc)->jmp;
257         else
258             /* Some Win16 programs want to get back the proc they set */
259             return (WNDPROC16)((WINDOWPROC *)proc)->thunk.t_from16.proc;
260     }
261 }
262
263
264 /**********************************************************************
265  *           WINPROC_SetProc
266  *
267  * Set the window procedure for a window or class. There are
268  * three tree classes of winproc callbacks:
269  *
270  * 1) class  -> wp                      -       not subclassed
271  *    class  -> wp -> wp -> wp -> wp    -       SetClassLong()
272  *             /           /
273  * 2) window -'           /             -       not subclassed
274  *    window -> wp -> wp '              -       SetWindowLong()
275  *
276  * 3) timer  -> wp                      -       SetTimer()
277  *
278  * Initially, winproc of the window points to the current winproc 
279  * thunk of its class. Subclassing prepends a new thunk to the 
280  * window winproc chain at the head of the list. Thus, window thunk 
281  * list includes class thunks and the latter are preserved when the 
282  * window is destroyed.
283  *
284  */
285 BOOL32 WINPROC_SetProc( HWINDOWPROC *pFirst, WNDPROC16 func,
286                         WINDOWPROCTYPE type, WINDOWPROCUSER user )
287 {
288     BOOL32 bRecycle = FALSE;
289     WINDOWPROC *proc, **ppPrev;
290
291     /* Check if function is already in the list */
292
293     ppPrev = (WINDOWPROC **)pFirst;
294     proc = WINPROC_GetPtr( func );
295     while (*ppPrev)
296     {
297         if (proc)
298         {
299             if (*ppPrev == proc)
300             {
301                 if ((*ppPrev)->user != user)
302                 {
303                     /* terminal thunk is being restored */
304
305                     WINPROC_FreeProc( *pFirst, (*ppPrev)->user );
306                     *(WINDOWPROC **)pFirst = *ppPrev;
307                     return TRUE;
308                 }
309                 bRecycle = TRUE;
310                 break;
311             }
312         }
313         else
314         {
315             if (((*ppPrev)->type == type) &&
316                 (func == WINPROC_THUNKPROC(*ppPrev)))
317             {
318                 bRecycle = TRUE;
319                 break;
320             }
321         }
322             
323         /* WPF_CLASS thunk terminates window thunk list */
324         if ((*ppPrev)->user != user) break;
325         ppPrev = &(*ppPrev)->next;
326     }
327
328     if (bRecycle)
329     {
330         /* Extract this thunk from the list */
331         proc = *ppPrev;
332         *ppPrev = proc->next;
333     }
334     else  /* Allocate a new one */
335     {
336         if (proc)  /* Was already a win proc */
337         {
338             type = proc->type;
339             func = WINPROC_THUNKPROC(proc);
340         }
341         proc = WINPROC_AllocWinProc( func, type, user );
342         if (!proc) return FALSE;
343     }
344
345     /* Add the win proc at the head of the list */
346
347     TRACE(win, "(%08x,%08x,%d): res=%08x\n",
348                  (UINT32)*pFirst, (UINT32)func, type, (UINT32)proc );
349     proc->next  = *(WINDOWPROC **)pFirst;
350     *(WINDOWPROC **)pFirst = proc;
351     return TRUE;
352 }
353
354
355 /**********************************************************************
356  *           WINPROC_FreeProc
357  *
358  * Free a list of win procs.
359  */
360 void WINPROC_FreeProc( HWINDOWPROC proc, WINDOWPROCUSER user )
361 {
362     while (proc)
363     {
364         WINDOWPROC *next = ((WINDOWPROC *)proc)->next;
365         if (((WINDOWPROC *)proc)->user != user) break;
366         TRACE(win, "freeing %08x\n", (UINT32)proc);
367         HeapFree( WinProcHeap, 0, proc );
368         proc = next;
369     }
370 }
371
372
373 /**********************************************************************
374  *           WINPROC_GetProcType
375  *
376  * Return the window procedure type.
377  */
378 WINDOWPROCTYPE WINPROC_GetProcType( HWINDOWPROC proc )
379 {
380     if (!proc ||
381         (((WINDOWPROC *)proc)->magic != WINPROC_MAGIC))
382         return WIN_PROC_INVALID;
383     return ((WINDOWPROC *)proc)->type;
384 }
385
386
387 /**********************************************************************
388  *           WINPROC_MapMsg32ATo32W
389  *
390  * Map a message from Ansi to Unicode.
391  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
392  * fixme WM_CHAR, WM_CHARTOITEM, WM_DEADCHAR, WM_MENUCHAR, WM_SYSCHAR,
393  * WM_SYSDEADCHAR ???
394  */
395 INT32 WINPROC_MapMsg32ATo32W( UINT32 msg, WPARAM32 wParam, LPARAM *plparam )
396 {
397     switch(msg)
398     {
399     case WM_GETTEXT:
400         {
401             LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
402                                      wParam * sizeof(WCHAR) + sizeof(LPARAM) );
403             if (!ptr) return -1;
404             *ptr++ = *plparam;  /* Store previous lParam */
405             *plparam = (LPARAM)ptr;
406         }
407         return 1;
408     case LB_GETTEXT32:
409     case CB_GETLBTEXT32:
410     /* fixme: fixed sized buffer */
411         {
412             LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
413                                      256 * sizeof(WCHAR) + sizeof(LPARAM) );
414             if (!ptr) return -1;
415             *ptr++ = *plparam;  /* Store previous lParam */
416             *plparam = (LPARAM)ptr;
417         }
418         return 1;
419     case WM_SETTEXT:
420     case CB_ADDSTRING32:
421     case CB_DIR32:
422     case CB_FINDSTRING32:
423     case CB_FINDSTRINGEXACT32:
424     case CB_INSERTSTRING32:
425     case CB_SELECTSTRING32:
426     case LB_ADDSTRING32:
427     case LB_INSERTSTRING32:
428         *plparam = (LPARAM)HEAP_strdupAtoW( SystemHeap, 0, (LPCSTR)*plparam );
429         return (*plparam ? 1 : -1);
430     case WM_NCCREATE:
431     case WM_CREATE:
432         {
433             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
434                                                                 sizeof(*cs) );
435             if (!cs) return -1;
436             *cs = *(CREATESTRUCT32W *)*plparam;
437             if (HIWORD(cs->lpszName))
438                 cs->lpszName = HEAP_strdupAtoW( SystemHeap, 0,
439                                                 (LPCSTR)cs->lpszName );
440             if (HIWORD(cs->lpszClass))
441                 cs->lpszClass = HEAP_strdupAtoW( SystemHeap, 0,
442                                                  (LPCSTR)cs->lpszClass );
443             *plparam = (LPARAM)cs;
444         }
445         return 1;
446     case WM_MDICREATE:
447         {
448             MDICREATESTRUCT32W *cs =
449                 (MDICREATESTRUCT32W *)HeapAlloc( SystemHeap, 0, sizeof(*cs) );
450             if (!cs) return -1;
451             *cs = *(MDICREATESTRUCT32W *)*plparam;
452             if (HIWORD(cs->szClass))
453                 cs->szClass = HEAP_strdupAtoW( SystemHeap, 0,
454                                                (LPCSTR)cs->szClass );
455             if (HIWORD(cs->szTitle))
456                 cs->szTitle = HEAP_strdupAtoW( SystemHeap, 0,
457                                                (LPCSTR)cs->szTitle );
458             *plparam = (LPARAM)cs;
459         }
460         return 1;
461     case WM_ASKCBFORMATNAME:
462     case WM_DEVMODECHANGE:
463     case WM_PAINTCLIPBOARD:
464     case WM_SIZECLIPBOARD:
465     case WM_WININICHANGE:
466     case EM_GETLINE32:
467     case EM_REPLACESEL32:
468     case EM_SETPASSWORDCHAR32:
469     case LB_ADDFILE32:
470     case LB_DIR32:
471     case LB_FINDSTRING32:
472     case LB_SELECTSTRING32:
473         FIXME(msg, "message %s (0x%x) needs translation\n", SPY_GetMsgName(msg), msg );
474         return -1;
475     default:  /* No translation needed */
476         return 0;
477     }
478 }
479
480
481 /**********************************************************************
482  *           WINPROC_UnmapMsg32ATo32W
483  *
484  * Unmap a message that was mapped from Ansi to Unicode.
485  */
486 void WINPROC_UnmapMsg32ATo32W( UINT32 msg, WPARAM32 wParam, LPARAM lParam )
487 {
488     switch(msg)
489     {
490     case WM_GETTEXT:
491         {
492             LPARAM *ptr = (LPARAM *)lParam - 1;
493             lstrcpynWtoA( (LPSTR)*ptr, (LPWSTR)(ptr + 1), wParam );
494             HeapFree( SystemHeap, 0, ptr );
495         }
496         break;
497     case LB_GETTEXT32:
498     case CB_GETLBTEXT32:
499         {
500             LPARAM *ptr = (LPARAM *)lParam - 1;
501             lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(ptr + 1) );
502             HeapFree( SystemHeap, 0, ptr );
503         }
504         break;
505
506     case LB_ADDSTRING32:
507     case LB_INSERTSTRING32:
508     case CB_ADDSTRING32:
509     case CB_DIR32:
510     case CB_FINDSTRING32:
511     case CB_FINDSTRINGEXACT32:
512     case CB_INSERTSTRING32:
513     case CB_SELECTSTRING32:
514     case WM_SETTEXT:
515         HeapFree( SystemHeap, 0, (void *)lParam );
516         break;
517     case WM_NCCREATE:
518     case WM_CREATE:
519         {
520             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
521             if (HIWORD(cs->lpszName))
522                 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszName );
523             if (HIWORD(cs->lpszClass))
524                 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszClass );
525             HeapFree( SystemHeap, 0, cs );
526         }
527         break;
528     case WM_MDICREATE:
529         {
530             MDICREATESTRUCT32W *cs = (MDICREATESTRUCT32W *)lParam;
531             if (HIWORD(cs->szTitle))
532                 HeapFree( SystemHeap, 0, (LPVOID)cs->szTitle );
533             if (HIWORD(cs->szClass))
534                 HeapFree( SystemHeap, 0, (LPVOID)cs->szClass );
535             HeapFree( SystemHeap, 0, cs );
536         }
537         break;
538     }
539 }
540
541
542 /**********************************************************************
543  *           WINPROC_MapMsg32WTo32A
544  *
545  * Map a message from Unicode to Ansi.
546  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
547  */
548 INT32 WINPROC_MapMsg32WTo32A( UINT32 msg, WPARAM32 wParam, LPARAM *plparam )
549 {
550     switch(msg)
551     {
552     case WM_GETTEXT:
553         {
554             LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
555                                                wParam + sizeof(LPARAM) );
556             if (!ptr) return -1;
557             *ptr++ = *plparam;  /* Store previous lParam */
558             *plparam = (LPARAM)ptr;
559         }
560         return 1;
561
562     case LB_GETTEXT32:
563     case CB_GETLBTEXT32:
564         /* fixme: fixed sized buffer */
565         {
566             LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
567                                                256 + sizeof(LPARAM) );
568             if (!ptr) return -1;
569             *ptr++ = *plparam;  /* Store previous lParam */
570             *plparam = (LPARAM)ptr;
571         }
572         return 1;
573
574     case LB_ADDSTRING32:
575     case LB_INSERTSTRING32:
576     case CB_ADDSTRING32:
577     case CB_DIR32:
578     case CB_FINDSTRING32:
579     case CB_FINDSTRINGEXACT32:
580     case CB_INSERTSTRING32:
581     case CB_SELECTSTRING32:
582     case WM_SETTEXT:
583         *plparam = (LPARAM)HEAP_strdupWtoA( SystemHeap, 0, (LPCWSTR)*plparam );
584         return (*plparam ? 1 : -1);
585     case WM_NCCREATE:
586     case WM_CREATE:
587         {
588             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
589                                                                 sizeof(*cs) );
590             if (!cs) return -1;
591             *cs = *(CREATESTRUCT32A *)*plparam;
592             if (HIWORD(cs->lpszName))
593                 cs->lpszName  = HEAP_strdupWtoA( SystemHeap, 0,
594                                                  (LPCWSTR)cs->lpszName );
595             if (HIWORD(cs->lpszClass))
596                 cs->lpszClass = HEAP_strdupWtoA( SystemHeap, 0,
597                                                  (LPCWSTR)cs->lpszClass);
598             *plparam = (LPARAM)cs;
599         }
600         return 1;
601     case WM_MDICREATE:
602         {
603             MDICREATESTRUCT32A *cs =
604                 (MDICREATESTRUCT32A *)HeapAlloc( SystemHeap, 0, sizeof(*cs) );
605             if (!cs) return -1;
606             *cs = *(MDICREATESTRUCT32A *)*plparam;
607             if (HIWORD(cs->szTitle))
608                 cs->szTitle = HEAP_strdupWtoA( SystemHeap, 0,
609                                                (LPCWSTR)cs->szTitle );
610             if (HIWORD(cs->szClass))
611                 cs->szClass = HEAP_strdupWtoA( SystemHeap, 0,
612                                                (LPCWSTR)cs->szClass );
613             *plparam = (LPARAM)cs;
614         }
615         return 1;
616     case WM_ASKCBFORMATNAME:
617     case WM_DEVMODECHANGE:
618     case WM_PAINTCLIPBOARD:
619     case WM_SIZECLIPBOARD:
620     case WM_WININICHANGE:
621     case EM_GETLINE32:
622     case EM_REPLACESEL32:
623     case EM_SETPASSWORDCHAR32:
624     case LB_ADDFILE32:
625     case LB_DIR32:
626     case LB_FINDSTRING32:
627     case LB_SELECTSTRING32:
628         FIXME(msg, "message %04x needs translation\n",msg );
629         return -1;
630     default:  /* No translation needed */
631         return 0;
632     }
633 }
634
635
636 /**********************************************************************
637  *           WINPROC_UnmapMsg32WTo32A
638  *
639  * Unmap a message that was mapped from Unicode to Ansi.
640  */
641 void WINPROC_UnmapMsg32WTo32A( UINT32 msg, WPARAM32 wParam, LPARAM lParam )
642 {
643     switch(msg)
644     {
645     case WM_GETTEXT:
646         {
647             LPARAM *ptr = (LPARAM *)lParam - 1;
648             lstrcpynAtoW( (LPWSTR)*ptr, (LPSTR)(ptr + 1), wParam );
649             HeapFree( SystemHeap, 0, ptr );
650         }
651         break;
652     case LB_GETTEXT32:
653     case CB_GETLBTEXT32:
654         {
655             LPARAM *ptr = (LPARAM *)lParam - 1;
656             lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(ptr + 1) );
657             HeapFree( SystemHeap, 0, ptr );
658         }
659         break;
660     case LB_ADDSTRING32:
661     case LB_INSERTSTRING32:
662     case CB_ADDSTRING32:
663     case CB_DIR32:
664     case CB_FINDSTRING32:
665     case CB_FINDSTRINGEXACT32:
666     case CB_INSERTSTRING32:
667     case CB_SELECTSTRING32:
668     case WM_SETTEXT:
669         HeapFree( SystemHeap, 0, (void *)lParam );
670         break;
671     case WM_NCCREATE:
672     case WM_CREATE:
673         {
674             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
675             if (HIWORD(cs->lpszName))
676                 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszName );
677             if (HIWORD(cs->lpszClass))
678                 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszClass );
679             HeapFree( SystemHeap, 0, cs );
680         }
681         break;
682     case WM_MDICREATE:
683         {
684             MDICREATESTRUCT32A *cs = (MDICREATESTRUCT32A *)lParam;
685             if (HIWORD(cs->szTitle))
686                 HeapFree( SystemHeap, 0, (LPVOID)cs->szTitle );
687             if (HIWORD(cs->szClass))
688                 HeapFree( SystemHeap, 0, (LPVOID)cs->szClass );
689             HeapFree( SystemHeap, 0, cs );
690         }
691         break;
692     }
693 }
694
695
696 /**********************************************************************
697  *           WINPROC_MapMsg16To32A
698  *
699  * Map a message from 16- to 32-bit Ansi.
700  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
701  */
702 INT32 WINPROC_MapMsg16To32A( UINT16 msg16, WPARAM16 wParam16, UINT32 *pmsg32,
703                              WPARAM32 *pwparam32, LPARAM *plparam )
704 {
705     *pmsg32 = (UINT32)msg16;
706     *pwparam32 = (WPARAM32)wParam16;
707     switch(msg16)
708     {
709     case WM_ACTIVATE:
710     case WM_CHARTOITEM:
711     case WM_COMMAND:
712     case WM_VKEYTOITEM:
713         *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
714         *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
715         return 0;
716     case WM_HSCROLL:
717     case WM_VSCROLL:
718         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
719         *plparam   = (LPARAM)(HWND32)HIWORD(*plparam);
720         return 0;
721     case WM_CTLCOLOR:
722         *pmsg32    = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
723         *pwparam32 = (WPARAM32)(HDC32)wParam16;
724         *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
725         return 0;
726     case WM_COMPAREITEM:
727         {
728             COMPAREITEMSTRUCT16* cis16 = (COMPAREITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
729             COMPAREITEMSTRUCT32 *cis = (COMPAREITEMSTRUCT32 *)
730                                         HeapAlloc(SystemHeap, 0, sizeof(*cis));
731             if (!cis) return -1;
732             cis->CtlType    = cis16->CtlType;
733             cis->CtlID      = cis16->CtlID;
734             cis->hwndItem   = cis16->hwndItem;
735             cis->itemID1    = cis16->itemID1;
736             cis->itemData1  = cis16->itemData1;
737             cis->itemID2    = cis16->itemID2;
738             cis->itemData2  = cis16->itemData2;
739             cis->dwLocaleId = 0;  /* FIXME */
740             *plparam = (LPARAM)cis;
741         }
742         return 1;
743     case WM_DELETEITEM:
744         {
745             DELETEITEMSTRUCT16* dis16 = (DELETEITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
746             DELETEITEMSTRUCT32 *dis = (DELETEITEMSTRUCT32 *)
747                                         HeapAlloc(SystemHeap, 0, sizeof(*dis));
748             if (!dis) return -1;
749             dis->CtlType  = dis16->CtlType;
750             dis->CtlID    = dis16->CtlID;
751             dis->hwndItem = dis16->hwndItem;
752             dis->itemData = dis16->itemData;
753             *plparam = (LPARAM)dis;
754         }
755         return 1;
756     case WM_MEASUREITEM:
757         {
758             MEASUREITEMSTRUCT16* mis16 = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
759             MEASUREITEMSTRUCT32 *mis = (MEASUREITEMSTRUCT32 *)
760                                         HeapAlloc(SystemHeap, 0,
761                                                 sizeof(*mis) + sizeof(LPARAM));
762             if (!mis) return -1;
763             mis->CtlType    = mis16->CtlType;
764             mis->CtlID      = mis16->CtlID;
765             mis->itemID     = mis16->itemID;
766             mis->itemWidth  = mis16->itemWidth;
767             mis->itemHeight = mis16->itemHeight;
768             mis->itemData   = mis16->itemData;
769             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
770             *plparam = (LPARAM)mis;
771         }
772         return 1;
773     case WM_DRAWITEM:
774         {
775             DRAWITEMSTRUCT16* dis16 = (DRAWITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
776             DRAWITEMSTRUCT32 *dis = (DRAWITEMSTRUCT32*)HeapAlloc(SystemHeap, 0,
777                                                                  sizeof(*dis));
778             if (!dis) return -1;
779             dis->CtlType    = dis16->CtlType;
780             dis->CtlID      = dis16->CtlID;
781             dis->itemID     = dis16->itemID;
782             dis->itemAction = dis16->itemAction;
783             dis->itemState  = dis16->itemState;
784             dis->hwndItem   = dis16->hwndItem;
785             dis->hDC        = dis16->hDC;
786             dis->itemData   = dis16->itemData;
787             CONV_RECT16TO32( &dis16->rcItem, &dis->rcItem );
788             *plparam = (LPARAM)dis;
789         }
790         return 1;
791     case WM_GETMINMAXINFO:
792         {
793             MINMAXINFO32 *mmi = (MINMAXINFO32 *)HeapAlloc( SystemHeap, 0,
794                                                 sizeof(*mmi) + sizeof(LPARAM));
795             if (!mmi) return -1;
796             STRUCT32_MINMAXINFO16to32( (MINMAXINFO16*)PTR_SEG_TO_LIN(*plparam),
797                                        mmi );
798             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
799             *plparam = (LPARAM)mmi;
800         }
801         return 1;
802     case WM_GETTEXT:
803     case WM_SETTEXT:
804         *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
805         return 0;
806     case WM_MDICREATE:
807         {
808             MDICREATESTRUCT16 *cs16 =
809                 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
810             MDICREATESTRUCT32A *cs =
811                 (MDICREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
812                                                 sizeof(*cs) + sizeof(LPARAM) );
813             if (!cs) return -1;
814             STRUCT32_MDICREATESTRUCT16to32A( cs16, cs );
815             cs->szTitle = (LPCSTR)PTR_SEG_TO_LIN(cs16->szTitle);
816             cs->szClass = (LPCSTR)PTR_SEG_TO_LIN(cs16->szClass);
817             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
818             *plparam = (LPARAM)cs;
819         }
820         return 1;
821     case WM_MDIGETACTIVE:
822         *plparam = (LPARAM)HeapAlloc( SystemHeap, 0, sizeof(BOOL32) );
823         return 1;
824     case WM_MDISETMENU:
825         if(wParam16==TRUE)
826            *pmsg32=WM_MDIREFRESHMENU;
827         *pwparam32 = (WPARAM32)(HMENU32)LOWORD(*plparam);
828         *plparam   = (LPARAM)(HMENU32)HIWORD(*plparam);
829         return 0;
830     case WM_MENUCHAR:
831     case WM_MENUSELECT:
832         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
833         *plparam   = (LPARAM)(HMENU32)HIWORD(*plparam);
834         return 0;
835     case WM_MDIACTIVATE:
836         if( *plparam )
837         {
838             *pwparam32 = (WPARAM32)(HWND32)HIWORD(*plparam);
839             *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
840         }
841         else /* message sent to MDI client */
842             *pwparam32 = wParam16;
843         return 0;
844     case WM_NCCALCSIZE:
845         {
846             NCCALCSIZE_PARAMS16 *nc16;
847             NCCALCSIZE_PARAMS32 *nc;
848
849             nc = (NCCALCSIZE_PARAMS32 *)HeapAlloc( SystemHeap, 0,
850                                                 sizeof(*nc) + sizeof(LPARAM) );
851             if (!nc) return -1;
852             nc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(*plparam);
853             CONV_RECT16TO32( &nc16->rgrc[0], &nc->rgrc[0] );
854             if (wParam16)
855             {
856                 nc->lppos = (WINDOWPOS32 *)HeapAlloc( SystemHeap, 0,
857                                                       sizeof(*nc->lppos) );
858                 CONV_RECT16TO32( &nc16->rgrc[1], &nc->rgrc[1] );
859                 CONV_RECT16TO32( &nc16->rgrc[2], &nc->rgrc[2] );
860                 if (nc->lppos) STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc16->lppos), nc->lppos );
861             }
862             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
863             *plparam = (LPARAM)nc;
864         }
865         return 1;
866     case WM_NCCREATE:
867     case WM_CREATE:
868         {
869             CREATESTRUCT16 *cs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
870             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
871                                                 sizeof(*cs) + sizeof(LPARAM) );
872             if (!cs) return -1;
873             STRUCT32_CREATESTRUCT16to32A( cs16, cs );
874             cs->lpszName  = (LPCSTR)PTR_SEG_TO_LIN(cs16->lpszName);
875             cs->lpszClass = (LPCSTR)PTR_SEG_TO_LIN(cs16->lpszClass);
876             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
877             *plparam = (LPARAM)cs;
878         }
879         return 1;
880     case WM_PARENTNOTIFY:
881         if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
882         {
883             *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
884             *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
885         }
886         return 0;
887     case WM_WINDOWPOSCHANGING:
888     case WM_WINDOWPOSCHANGED:
889         {
890             WINDOWPOS32 *wp = (WINDOWPOS32 *)HeapAlloc( SystemHeap, 0,
891                                                 sizeof(*wp) + sizeof(LPARAM) );
892             if (!wp) return -1;
893             STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(*plparam),
894                                       wp );
895             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
896             *plparam = (LPARAM)wp;
897         }
898         return 1;
899     case WM_GETDLGCODE:
900         if (*plparam)
901         {
902             LPMSG16 msg16 = (LPMSG16)PTR_SEG_TO_LIN(*plparam);
903             LPMSG32 msg32 = (LPMSG32)HeapAlloc( SystemHeap, 0, sizeof(MSG32) );
904
905             if (!msg32) return -1;
906             msg32->hwnd = msg16->hwnd;
907             msg32->lParam = msg16->lParam;
908             msg32->time = msg16->time;
909             CONV_POINT16TO32(&msg16->pt,&msg32->pt);
910             /* this is right, right? */
911             if (WINPROC_MapMsg16To32A(msg16->message,msg16->wParam,
912                                      &msg32->message,&msg32->wParam,
913                                      &msg32->lParam)<0) {
914                 HeapFree( SystemHeap, 0, msg32 );
915                 return -1;
916             }
917             *plparam = (LPARAM)msg32;
918             return 1;
919         }
920         else return 0;
921     case WM_NOTIFY:
922         *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
923         return 1;
924     case WM_ASKCBFORMATNAME:
925     case WM_DEVMODECHANGE:
926     case WM_PAINTCLIPBOARD:
927     case WM_SIZECLIPBOARD:
928     case WM_WININICHANGE:
929         FIXME( msg, "message %04x needs translation\n",msg16 );
930         return -1;
931
932     default:  /* No translation needed */
933         return 0;
934     }
935 }
936
937
938 /**********************************************************************
939  *           WINPROC_UnmapMsg16To32A
940  *
941  * Unmap a message that was mapped from 16- to 32-bit Ansi.
942  */
943 LRESULT WINPROC_UnmapMsg16To32A( UINT32 msg, WPARAM32 wParam, LPARAM lParam,
944                                  LRESULT result )
945 {
946     switch(msg)
947     {
948     case WM_COMPAREITEM:
949     case WM_DELETEITEM:
950     case WM_DRAWITEM:
951         HeapFree( SystemHeap, 0, (LPVOID)lParam );
952         break;
953     case WM_MEASUREITEM:
954         {
955             MEASUREITEMSTRUCT16 *mis16;
956             MEASUREITEMSTRUCT32 *mis = (MEASUREITEMSTRUCT32 *)lParam;
957             lParam = *(LPARAM *)(mis + 1);
958             mis16 = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(lParam);
959             mis16->itemWidth  = (UINT16)mis->itemWidth;
960             mis16->itemHeight = (UINT16)mis->itemHeight;
961             HeapFree( SystemHeap, 0, mis );
962         }
963         break;
964     case WM_GETMINMAXINFO:
965         {
966             MINMAXINFO32 *mmi = (MINMAXINFO32 *)lParam;
967             lParam = *(LPARAM *)(mmi + 1);
968             STRUCT32_MINMAXINFO32to16( mmi,
969                                        (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam));
970             HeapFree( SystemHeap, 0, mmi );
971         }
972         break;
973     case WM_MDICREATE:
974         {
975             MDICREATESTRUCT32A *cs = (MDICREATESTRUCT32A *)lParam;
976             lParam = *(LPARAM *)(cs + 1);
977             STRUCT32_MDICREATESTRUCT32Ato16( cs,
978                                  (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
979             HeapFree( SystemHeap, 0, cs );
980         }
981         break;
982     case WM_MDIGETACTIVE:
983         result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL32 *)lParam) );
984         HeapFree( SystemHeap, 0, (BOOL32 *)lParam );
985         break;
986     case WM_NCCALCSIZE:
987         {
988             NCCALCSIZE_PARAMS16 *nc16;
989             NCCALCSIZE_PARAMS32 *nc = (NCCALCSIZE_PARAMS32 *)lParam;
990             lParam = *(LPARAM *)(nc + 1);
991             nc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam);
992             CONV_RECT32TO16( &nc->rgrc[0], &nc16->rgrc[0] );
993             if (wParam)
994             {
995                 CONV_RECT32TO16( &nc->rgrc[1], &nc16->rgrc[1] );
996                 CONV_RECT32TO16( &nc->rgrc[2], &nc16->rgrc[2] );
997                 if (nc->lppos)
998                 {
999                     STRUCT32_WINDOWPOS32to16( nc->lppos,
1000                                    (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc16->lppos));
1001                     HeapFree( SystemHeap, 0, nc->lppos );
1002                 }
1003             }
1004             HeapFree( SystemHeap, 0, nc );
1005         }
1006         break;
1007     case WM_NCCREATE:
1008     case WM_CREATE:
1009         {
1010             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
1011             lParam = *(LPARAM *)(cs + 1);
1012             STRUCT32_CREATESTRUCT32Ato16( cs,
1013                                     (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1014             HeapFree( SystemHeap, 0, cs );
1015         }
1016         break;
1017     case WM_WINDOWPOSCHANGING:
1018     case WM_WINDOWPOSCHANGED:
1019         {
1020             WINDOWPOS32 *wp = (WINDOWPOS32 *)lParam;
1021             lParam = *(LPARAM *)(wp + 1);
1022             STRUCT32_WINDOWPOS32to16(wp,(WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam));
1023             HeapFree( SystemHeap, 0, wp );
1024         }
1025         break;
1026     case WM_GETDLGCODE:
1027         if (lParam)
1028         {
1029             LPMSG32 msg32 = (LPMSG32)lParam;
1030
1031             WINPROC_UnmapMsg16To32A( msg32->message, msg32->wParam, msg32->lParam,
1032                                      result);
1033             HeapFree( SystemHeap, 0, msg32 );
1034         }
1035         break;
1036     }
1037     return result;
1038 }
1039
1040
1041 /**********************************************************************
1042  *           WINPROC_MapMsg16To32W
1043  *
1044  * Map a message from 16- to 32-bit Unicode.
1045  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1046  */
1047 INT32 WINPROC_MapMsg16To32W( UINT16 msg16, WPARAM16 wParam16, UINT32 *pmsg32,
1048                              WPARAM32 *pwparam32, LPARAM *plparam )
1049 {
1050     switch(msg16)
1051     {
1052     case WM_GETTEXT:
1053     case WM_SETTEXT:
1054         *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
1055         return WINPROC_MapMsg32ATo32W( *pmsg32, *pwparam32, plparam );
1056     case WM_NCCREATE:
1057     case WM_CREATE:
1058         {
1059             CREATESTRUCT16 *cs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
1060             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
1061                                                 sizeof(*cs) + sizeof(LPARAM) );
1062             if (!cs) return -1;
1063             STRUCT32_CREATESTRUCT16to32A( cs16, (CREATESTRUCT32A *)cs );
1064             cs->lpszName  = (LPCWSTR)PTR_SEG_TO_LIN(cs16->lpszName);
1065             cs->lpszClass = (LPCWSTR)PTR_SEG_TO_LIN(cs16->lpszClass);
1066             if (HIWORD(cs->lpszName))
1067                 cs->lpszName = HEAP_strdupAtoW( SystemHeap, 0,
1068                                                 (LPCSTR)cs->lpszName );
1069             if (HIWORD(cs->lpszClass))
1070                 cs->lpszClass = HEAP_strdupAtoW( SystemHeap, 0,
1071                                                  (LPCSTR)cs->lpszClass );
1072             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1073             *plparam = (LPARAM)cs;
1074         }
1075         return 1;
1076     case WM_MDICREATE:
1077         {
1078             MDICREATESTRUCT16 *cs16 =
1079                 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
1080             MDICREATESTRUCT32W *cs =
1081                 (MDICREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
1082                                                 sizeof(*cs) + sizeof(LPARAM) );
1083             if (!cs) return -1;
1084             STRUCT32_MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCT32A *)cs );
1085             cs->szTitle = (LPCWSTR)PTR_SEG_TO_LIN(cs16->szTitle);
1086             cs->szClass = (LPCWSTR)PTR_SEG_TO_LIN(cs16->szClass);
1087             if (HIWORD(cs->szTitle))
1088                 cs->szTitle = HEAP_strdupAtoW( SystemHeap, 0,
1089                                                (LPCSTR)cs->szTitle );
1090             if (HIWORD(cs->szClass))
1091                 cs->szClass = HEAP_strdupAtoW( SystemHeap, 0,
1092                                                (LPCSTR)cs->szClass );
1093             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1094             *plparam = (LPARAM)cs;
1095         }
1096         return 1;
1097     case WM_GETDLGCODE:
1098         if (*plparam)
1099         {
1100             LPMSG16 msg16 = (LPMSG16)PTR_SEG_TO_LIN(*plparam);
1101             LPMSG32 msg32 = (LPMSG32)HeapAlloc( SystemHeap, 0, sizeof(MSG32) );
1102
1103             if (!msg32) return -1;
1104             msg32->hwnd = msg16->hwnd;
1105             msg32->lParam = msg16->lParam;
1106             msg32->time = msg16->time;
1107             CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1108             /* this is right, right? */
1109             if (WINPROC_MapMsg16To32W(msg16->message,msg16->wParam,
1110                                      &msg32->message,&msg32->wParam,
1111                                      &msg32->lParam)<0) {
1112                 HeapFree( SystemHeap, 0, msg32 );
1113                 return -1;
1114             }
1115             *plparam = (LPARAM)msg32;
1116             return 1;
1117         }
1118         else return 0;
1119     default:  /* No Unicode translation needed */
1120         return WINPROC_MapMsg16To32A( msg16, wParam16, pmsg32,
1121                                       pwparam32, plparam );
1122     }
1123 }
1124
1125
1126 /**********************************************************************
1127  *           WINPROC_UnmapMsg16To32W
1128  *
1129  * Unmap a message that was mapped from 16- to 32-bit Unicode.
1130  */
1131 LRESULT WINPROC_UnmapMsg16To32W( UINT32 msg, WPARAM32 wParam, LPARAM lParam,
1132                                  LRESULT result )
1133 {
1134     switch(msg)
1135     {
1136     case WM_GETTEXT:
1137     case WM_SETTEXT:
1138         WINPROC_UnmapMsg32ATo32W( msg, wParam, lParam );
1139         break;
1140     case WM_NCCREATE:
1141     case WM_CREATE:
1142         {
1143             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
1144             lParam = *(LPARAM *)(cs + 1);
1145             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCT32A *)cs,
1146                                     (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1147             if (HIWORD(cs->lpszName))
1148                 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszName );
1149             if (HIWORD(cs->lpszClass))
1150                 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszClass );
1151             HeapFree( SystemHeap, 0, cs );
1152         }
1153         break;
1154     case WM_MDICREATE:
1155         {
1156             MDICREATESTRUCT32W *cs = (MDICREATESTRUCT32W *)lParam;
1157             lParam = *(LPARAM *)(cs + 1);
1158             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCT32A *)cs,
1159                                  (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1160             if (HIWORD(cs->szTitle))
1161                 HeapFree( SystemHeap, 0, (LPVOID)cs->szTitle );
1162             if (HIWORD(cs->szClass))
1163                 HeapFree( SystemHeap, 0, (LPVOID)cs->szClass );
1164             HeapFree( SystemHeap, 0, cs );
1165         }
1166         break;
1167     case WM_GETDLGCODE:
1168         if (lParam)
1169         {
1170             LPMSG32 msg32 = (LPMSG32)lParam;
1171
1172             WINPROC_UnmapMsg16To32W( msg32->message, msg32->wParam, msg32->lParam,
1173                                      result);
1174             HeapFree( SystemHeap, 0, msg32 );
1175         }
1176         break;
1177     default:
1178         return WINPROC_UnmapMsg16To32A( msg, wParam, lParam, result );
1179     }
1180     return result;
1181 }
1182
1183
1184 /**********************************************************************
1185  *           WINPROC_MapMsg32ATo16
1186  *
1187  * Map a message from 32-bit Ansi to 16-bit.
1188  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1189  */
1190 INT32 WINPROC_MapMsg32ATo16( HWND32 hwnd, UINT32 msg32, WPARAM32 wParam32,
1191                              UINT16 *pmsg16, WPARAM16 *pwparam16,
1192                              LPARAM *plparam )
1193 {
1194     *pmsg16 = (UINT16)msg32;
1195     *pwparam16 = (WPARAM16)LOWORD(wParam32);
1196     switch(msg32)
1197     {
1198     case BM_GETCHECK32:
1199     case BM_SETCHECK32:
1200     case BM_GETSTATE32:
1201     case BM_SETSTATE32:
1202     case BM_SETSTYLE32:
1203         *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK32);
1204         return 0;
1205
1206     case EM_GETSEL32:
1207     case EM_GETRECT32:
1208     case EM_SETRECT32:
1209     case EM_SETRECTNP32:
1210     case EM_SCROLL32:
1211     case EM_LINESCROLL32:
1212     case EM_SCROLLCARET32:
1213     case EM_GETMODIFY32:
1214     case EM_SETMODIFY32:
1215     case EM_GETLINECOUNT32:
1216     case EM_LINEINDEX32:
1217     case EM_SETHANDLE32:
1218     case EM_GETHANDLE32:
1219     case EM_GETTHUMB32:
1220     case EM_LINELENGTH32:
1221     case EM_REPLACESEL32:
1222     case EM_GETLINE32:
1223     case EM_LIMITTEXT32:
1224     case EM_CANUNDO32:
1225     case EM_UNDO32:
1226     case EM_FMTLINES32:
1227     case EM_LINEFROMCHAR32:
1228     case EM_SETTABSTOPS32:
1229     case EM_SETPASSWORDCHAR32:
1230     case EM_EMPTYUNDOBUFFER32:
1231     case EM_GETFIRSTVISIBLELINE32:
1232     case EM_SETREADONLY32:
1233     case EM_SETWORDBREAKPROC32:
1234     case EM_GETWORDBREAKPROC32:
1235     case EM_GETPASSWORDCHAR32:
1236         *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL32);
1237         return 0;
1238
1239     case LB_CARETOFF32:
1240     case LB_CARETON32:
1241     case LB_DELETESTRING32:
1242     case LB_GETANCHORINDEX32:
1243     case LB_GETCARETINDEX32:
1244     case LB_GETCOUNT32:
1245     case LB_GETCURSEL32:
1246     case LB_GETHORIZONTALEXTENT32:
1247     case LB_GETITEMDATA32:
1248     case LB_GETITEMHEIGHT32:
1249     case LB_GETSEL32:
1250     case LB_GETSELCOUNT32:
1251     case LB_GETTEXTLEN32:
1252     case LB_GETTOPINDEX32:
1253     case LB_RESETCONTENT32:
1254     case LB_SELITEMRANGE32:
1255     case LB_SELITEMRANGEEX32:
1256     case LB_SETANCHORINDEX32:
1257     case LB_SETCARETINDEX32:
1258     case LB_SETCOLUMNWIDTH32:
1259     case LB_SETCURSEL32:
1260     case LB_SETHORIZONTALEXTENT32:
1261     case LB_SETITEMDATA32:
1262     case LB_SETITEMHEIGHT32:
1263     case LB_SETSEL32:
1264     case LB_SETTOPINDEX32:
1265         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
1266         return 0;
1267     case CB_DELETESTRING32:
1268     case CB_GETCOUNT32:
1269     case CB_GETLBTEXTLEN32:
1270     case CB_LIMITTEXT32:
1271     case CB_RESETCONTENT32:
1272     case CB_SETEDITSEL32:
1273     case CB_GETCURSEL32:
1274     case CB_SETCURSEL32:
1275     case CB_SHOWDROPDOWN32:
1276     case CB_SETITEMDATA32:
1277     case CB_SETITEMHEIGHT32:
1278     case CB_GETITEMHEIGHT32:
1279     case CB_SETEXTENDEDUI32:
1280     case CB_GETEXTENDEDUI32:
1281     case CB_GETDROPPEDSTATE32:
1282         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL32);
1283         return 0;
1284     case CB_GETEDITSEL32:
1285         *pmsg16 = CB_GETEDITSEL16;
1286         return 1;
1287
1288     case LB_ADDSTRING32:
1289     case LB_FINDSTRING32:
1290     case LB_FINDSTRINGEXACT32:
1291     case LB_INSERTSTRING32:
1292     case LB_SELECTSTRING32:
1293     case LB_DIR32:
1294     case LB_ADDFILE32:
1295         {
1296             LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1297             if (!str) return -1;
1298             *plparam = (LPARAM)SEGPTR_GET(str);
1299         }
1300         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
1301         return 1;
1302
1303     case CB_ADDSTRING32:
1304     case CB_FINDSTRING32:
1305     case CB_FINDSTRINGEXACT32:
1306     case CB_INSERTSTRING32:
1307     case CB_SELECTSTRING32:
1308     case CB_DIR32:
1309         {
1310             LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1311             if (!str) return -1;
1312             *plparam = (LPARAM)SEGPTR_GET(str);
1313         }
1314         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL32);
1315         return 1;
1316
1317     case LB_GETITEMRECT32:
1318         {
1319             RECT16 *rect;
1320             rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
1321             if (!rect) return -1;
1322             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
1323             *plparam = (LPARAM)SEGPTR_GET(rect);
1324         }
1325         *pmsg16 = LB_GETITEMRECT16;
1326         return 1;
1327     case LB_GETSELITEMS32:
1328         {
1329             LPINT16 items;
1330             *pwparam16 = (WPARAM16)MIN( wParam32, 0x7f80 ); /* Must be < 64K */
1331             if (!(items = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
1332                                         + sizeof(LPARAM)))) return -1;
1333             *((LPARAM *)items)++ = *plparam;  /* Store the previous lParam */
1334             *plparam = (LPARAM)SEGPTR_GET(items);
1335         }
1336         *pmsg16 = LB_GETSELITEMS16;
1337         return 1;
1338     case LB_SETTABSTOPS32:
1339         if (wParam32)
1340         {
1341             INT32 i;
1342             LPINT16 stops;
1343             *pwparam16 = (WPARAM16)MIN( wParam32, 0x7f80 ); /* Must be < 64K */
1344             if (!(stops = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
1345                                         + sizeof(LPARAM)))) return -1;
1346             for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT32)*plparam+i);
1347             *plparam = (LPARAM)SEGPTR_GET(stops);
1348             return 1;
1349         }
1350         *pmsg16 = LB_SETTABSTOPS16;
1351         return 0;
1352
1353     case CB_GETDROPPEDCONTROLRECT32:
1354         {
1355             RECT16 *rect;
1356             rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
1357             if (!rect) return -1;
1358             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
1359             *plparam = (LPARAM)SEGPTR_GET(rect);
1360         }
1361         *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
1362         return 1;
1363
1364     case LB_GETTEXT32:
1365         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1366         *pmsg16 = LB_GETTEXT16;
1367         return 1;
1368
1369     case CB_GETLBTEXT32:
1370         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1371         *pmsg16 = CB_GETLBTEXT16;
1372         return 1;
1373
1374     case EM_SETSEL32:
1375         *pwparam16 = 0;
1376         *plparam = MAKELONG( (INT16)(INT32)wParam32, (INT16)*plparam );
1377         *pmsg16 = EM_SETSEL16;
1378         return 0;
1379
1380     case WM_ACTIVATE:
1381     case WM_CHARTOITEM:
1382     case WM_COMMAND:
1383     case WM_VKEYTOITEM:
1384         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
1385         return 0;
1386     case WM_HSCROLL:
1387     case WM_VSCROLL:
1388         *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
1389         return 0;
1390     case WM_CTLCOLORMSGBOX:
1391     case WM_CTLCOLOREDIT:
1392     case WM_CTLCOLORLISTBOX:
1393     case WM_CTLCOLORBTN:
1394     case WM_CTLCOLORDLG:
1395     case WM_CTLCOLORSCROLLBAR:
1396     case WM_CTLCOLORSTATIC:
1397         *pmsg16  = WM_CTLCOLOR;
1398         *plparam = MAKELPARAM( (HWND16)*plparam,
1399                                (WORD)msg32 - WM_CTLCOLORMSGBOX );
1400         return 0;
1401     case WM_COMPAREITEM:
1402         {
1403             COMPAREITEMSTRUCT32 *cis32 = (COMPAREITEMSTRUCT32 *)*plparam;
1404             COMPAREITEMSTRUCT16 *cis = SEGPTR_NEW(COMPAREITEMSTRUCT16);
1405             if (!cis) return -1;
1406             cis->CtlType    = (UINT16)cis32->CtlType;
1407             cis->CtlID      = (UINT16)cis32->CtlID;
1408             cis->hwndItem   = (HWND16)cis32->hwndItem;
1409             cis->itemID1    = (UINT16)cis32->itemID1;
1410             cis->itemData1  = cis32->itemData1;
1411             cis->itemID2    = (UINT16)cis32->itemID2;
1412             cis->itemData2  = cis32->itemData2;
1413             *plparam = (LPARAM)SEGPTR_GET(cis);
1414         }
1415         return 1;
1416     case WM_DELETEITEM:
1417         {
1418             DELETEITEMSTRUCT32 *dis32 = (DELETEITEMSTRUCT32 *)*plparam;
1419             DELETEITEMSTRUCT16 *dis = SEGPTR_NEW(DELETEITEMSTRUCT16);
1420             if (!dis) return -1;
1421             dis->CtlType  = (UINT16)dis32->CtlType;
1422             dis->CtlID    = (UINT16)dis32->CtlID;
1423             dis->itemID   = (UINT16)dis32->itemID;
1424             dis->hwndItem = (HWND16)dis32->hwndItem;
1425             dis->itemData = dis32->itemData;
1426             *plparam = (LPARAM)SEGPTR_GET(dis);
1427         }
1428         return 1;
1429     case WM_DRAWITEM:
1430         {
1431             DRAWITEMSTRUCT32 *dis32 = (DRAWITEMSTRUCT32 *)*plparam;
1432             DRAWITEMSTRUCT16 *dis = SEGPTR_NEW(DRAWITEMSTRUCT16);
1433             if (!dis) return -1;
1434             dis->CtlType    = (UINT16)dis32->CtlType;
1435             dis->CtlID      = (UINT16)dis32->CtlID;
1436             dis->itemID     = (UINT16)dis32->itemID;
1437             dis->itemAction = (UINT16)dis32->itemAction;
1438             dis->itemState  = (UINT16)dis32->itemState;
1439             dis->hwndItem   = (HWND16)dis32->hwndItem;
1440             dis->hDC        = (HDC16)dis32->hDC;
1441             dis->itemData   = dis32->itemData;
1442             CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
1443             *plparam = (LPARAM)SEGPTR_GET(dis);
1444         }
1445         return 1;
1446     case WM_MEASUREITEM:
1447         {
1448             MEASUREITEMSTRUCT32 *mis32 = (MEASUREITEMSTRUCT32 *)*plparam;
1449             MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)
1450                                      SEGPTR_ALLOC(sizeof(*mis)+sizeof(LPARAM));
1451             if (!mis) return -1;
1452             mis->CtlType    = (UINT16)mis32->CtlType;
1453             mis->CtlID      = (UINT16)mis32->CtlID;
1454             mis->itemID     = (UINT16)mis32->itemID;
1455             mis->itemWidth  = (UINT16)mis32->itemWidth;
1456             mis->itemHeight = (UINT16)mis32->itemHeight;
1457             mis->itemData   = mis32->itemData;
1458             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
1459             *plparam = (LPARAM)SEGPTR_GET(mis);
1460         }
1461         return 1;
1462     case WM_GETMINMAXINFO:
1463         {
1464             MINMAXINFO16 *mmi = (MINMAXINFO16 *)SEGPTR_ALLOC( sizeof(*mmi) +
1465                                                               sizeof(LPARAM) );
1466             if (!mmi) return -1;
1467             STRUCT32_MINMAXINFO32to16( (MINMAXINFO32 *)*plparam, mmi );
1468             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
1469             *plparam = (LPARAM)SEGPTR_GET(mmi);
1470         }
1471         return 1;
1472     case WM_GETTEXT:
1473         {
1474             LPSTR str;
1475             *pwparam16 = (WPARAM16)MIN( wParam32, 0xff80 ); /* Must be < 64K */
1476             if (!(str = SEGPTR_ALLOC(*pwparam16 + sizeof(LPARAM)))) return -1;
1477             *((LPARAM *)str)++ = *plparam;  /* Store the previous lParam */
1478             *plparam = (LPARAM)SEGPTR_GET(str);
1479         }
1480         return 1;
1481     case WM_MDICREATE:
1482         {
1483             MDICREATESTRUCT16 *cs;
1484             MDICREATESTRUCT32A *cs32 = (MDICREATESTRUCT32A *)*plparam;
1485             LPSTR name, cls;
1486
1487             if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
1488             STRUCT32_MDICREATESTRUCT32Ato16( cs32, cs );
1489             name = SEGPTR_STRDUP( cs32->szTitle );
1490             cls  = SEGPTR_STRDUP( cs32->szClass );
1491             cs->szTitle = SEGPTR_GET(name);
1492             cs->szClass = SEGPTR_GET(cls);
1493             *plparam = (LPARAM)SEGPTR_GET(cs);
1494         }
1495         return 1;
1496     case WM_MDIGETACTIVE:
1497         return 1;
1498     case WM_MDISETMENU:
1499         *plparam   = MAKELPARAM( (HMENU16)LOWORD(wParam32),
1500                                  (HMENU16)LOWORD(*plparam) );
1501         *pwparam16 = (*plparam == 0);
1502         return 0;
1503     case WM_MENUCHAR:
1504     case WM_MENUSELECT:
1505         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
1506         return 0;
1507     case WM_MDIACTIVATE:
1508         if( WIDGETS_IsControl32(WIN_FindWndPtr(hwnd), BIC32_MDICLIENT) )
1509         {
1510             *pwparam16 = (HWND32)wParam32;
1511             *plparam = 0;
1512         }
1513         else
1514         {
1515             *pwparam16 = ((HWND32)*plparam == hwnd);
1516             *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
1517                                    (HWND16)LOWORD(wParam32) );
1518         }
1519         return 0;
1520     case WM_NCCALCSIZE:
1521         {
1522             NCCALCSIZE_PARAMS32 *nc32 = (NCCALCSIZE_PARAMS32 *)*plparam;
1523             NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)SEGPTR_ALLOC( sizeof(*nc) + sizeof(LPARAM) );
1524             if (!nc) return -1;
1525
1526             CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
1527             if (wParam32)
1528             {
1529                 WINDOWPOS16 *wp;
1530                 CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
1531                 CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
1532                 if (!(wp = SEGPTR_NEW(WINDOWPOS16)))
1533                 {
1534                     SEGPTR_FREE(nc);
1535                     return -1;
1536                 }
1537                 STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
1538                 nc->lppos = SEGPTR_GET(wp);
1539             }
1540             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
1541             *plparam = (LPARAM)SEGPTR_GET(nc);
1542         }
1543         return 1;
1544     case WM_NCCREATE:
1545     case WM_CREATE:
1546         {
1547             CREATESTRUCT16 *cs;
1548             CREATESTRUCT32A *cs32 = (CREATESTRUCT32A *)*plparam;
1549             LPSTR name, cls;
1550
1551             if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
1552             STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
1553             name = SEGPTR_STRDUP( cs32->lpszName );
1554             cls  = SEGPTR_STRDUP( cs32->lpszClass );
1555             cs->lpszName  = SEGPTR_GET(name);
1556             cs->lpszClass = SEGPTR_GET(cls);
1557             *plparam = (LPARAM)SEGPTR_GET(cs);
1558         }
1559         return 1;
1560     case WM_PARENTNOTIFY:
1561         if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
1562             *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
1563         /* else nothing to do */
1564         return 0;
1565     case WM_NOTIFY:
1566         *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
1567         return 1;
1568     case WM_SETTEXT:
1569         {
1570             LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1571             if (!str) return -1;
1572             *plparam = (LPARAM)SEGPTR_GET(str);
1573         }
1574         return 1;
1575     case WM_WINDOWPOSCHANGING:
1576     case WM_WINDOWPOSCHANGED:
1577         {
1578             WINDOWPOS16 *wp = (WINDOWPOS16 *)SEGPTR_ALLOC( sizeof(*wp) +
1579                                                            sizeof(LPARAM) );
1580             if (!wp) return -1;
1581             STRUCT32_WINDOWPOS32to16( (WINDOWPOS32 *)*plparam, wp );
1582             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
1583             *plparam = (LPARAM)SEGPTR_GET(wp);
1584         }
1585         return 1;
1586     case WM_GETDLGCODE:
1587          if (*plparam) {
1588             LPMSG32 msg32 = (LPMSG32) *plparam;
1589             LPMSG16 msg16 = (LPMSG16) SEGPTR_NEW( MSG16 );
1590
1591             if (!msg16) return -1;
1592             msg16->hwnd = msg32->hwnd;
1593             msg16->lParam = msg32->lParam;
1594             msg16->time = msg32->time;
1595             CONV_POINT32TO16(&msg32->pt,&msg16->pt);
1596             /* this is right, right? */
1597             if (WINPROC_MapMsg32ATo16(msg32->hwnd,msg32->message,msg32->wParam,
1598                          &msg16->message,&msg16->wParam, &msg16->lParam)<0) {
1599                 SEGPTR_FREE( msg16 );
1600                 return -1;
1601             }
1602             *plparam = (LPARAM)SEGPTR_GET(msg16);
1603             return 1;
1604         }
1605         return 0;
1606
1607     case WM_ASKCBFORMATNAME:
1608     case WM_DEVMODECHANGE:
1609     case WM_PAINTCLIPBOARD:
1610     case WM_SIZECLIPBOARD:
1611     case WM_WININICHANGE:
1612         FIXME( msg, "message %04x needs translation\n", msg32 );
1613         return -1;
1614     default:  /* No translation needed */
1615         return 0;
1616     }
1617 }
1618
1619
1620 /**********************************************************************
1621  *           WINPROC_UnmapMsg32ATo16
1622  *
1623  * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
1624  */
1625 void WINPROC_UnmapMsg32ATo16( UINT32 msg, WPARAM32 wParam, LPARAM lParam,
1626                               MSGPARAM16* p16 ) 
1627 {
1628     switch(msg)
1629     {
1630     case LB_ADDFILE32:
1631     case LB_ADDSTRING32:
1632     case LB_DIR32:
1633     case LB_FINDSTRING32:
1634     case LB_FINDSTRINGEXACT32:
1635     case LB_INSERTSTRING32:
1636     case LB_SELECTSTRING32:
1637     case LB_SETTABSTOPS32:
1638     case CB_ADDSTRING32:
1639     case CB_FINDSTRING32:
1640     case CB_FINDSTRINGEXACT32:
1641     case CB_INSERTSTRING32:
1642     case CB_SELECTSTRING32:
1643     case CB_DIR32:
1644     case WM_COMPAREITEM:
1645     case WM_DELETEITEM:
1646     case WM_DRAWITEM:
1647     case WM_SETTEXT:
1648         SEGPTR_FREE( PTR_SEG_TO_LIN(p16->lParam) );
1649         break;
1650
1651     case CB_GETDROPPEDCONTROLRECT32:
1652     case LB_GETITEMRECT32:
1653         {
1654             RECT16 *rect = (RECT16 *)PTR_SEG_TO_LIN(p16->lParam);
1655             p16->lParam = *(LPARAM *)(rect + 1);
1656             CONV_RECT16TO32( rect, (RECT32 *)(p16->lParam));
1657             SEGPTR_FREE( rect );
1658         }
1659         break;
1660     case LB_GETSELITEMS32:
1661         {
1662             INT32 i;
1663             LPINT16 items = (LPINT16)PTR_SEG_TO_LIN(lParam);
1664             p16->lParam = *((LPARAM *)items - 1);
1665             for (i = 0; i < p16->wParam; i++) *((LPINT32)(p16->lParam) + i) = items[i];
1666             SEGPTR_FREE( (LPARAM *)items - 1 );
1667         }
1668         break;
1669
1670     case CB_GETEDITSEL32:
1671         if( wParam )
1672             *((LPUINT32)(wParam)) = LOWORD(p16->lResult);
1673         if( lParam )
1674             *((LPUINT32)(lParam)) = HIWORD(p16->lResult);       /* FIXME: substract 1? */
1675         break;
1676
1677     case LB_GETTEXT32:
1678     case CB_GETLBTEXT32:
1679         UnMapLS( (SEGPTR)(p16->lParam) );
1680         break;
1681
1682     case WM_MEASUREITEM:
1683         {
1684             MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(p16->lParam);
1685             MEASUREITEMSTRUCT32 *mis32 = *(MEASUREITEMSTRUCT32 **)(mis + 1);
1686             mis32->itemWidth  = mis->itemWidth;
1687             mis32->itemHeight = mis->itemHeight;
1688             SEGPTR_FREE(mis);
1689         }
1690         break;
1691     case WM_GETMINMAXINFO:
1692         {
1693             MINMAXINFO16 *mmi = (MINMAXINFO16 *)PTR_SEG_TO_LIN(p16->lParam);
1694             p16->lParam = *(LPARAM *)(mmi + 1);
1695             STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO32 *)(p16->lParam) );
1696             SEGPTR_FREE(mmi);
1697         }
1698         break;
1699     case WM_GETTEXT:
1700         {
1701             LPSTR str = (LPSTR)PTR_SEG_TO_LIN(p16->lParam);
1702             p16->lParam = *((LPARAM *)str - 1);
1703             lstrcpyn32A( (LPSTR)(p16->lParam), str, p16->wParam );
1704             SEGPTR_FREE( (LPARAM *)str - 1 );
1705         }
1706         break;
1707     case WM_MDICREATE:
1708         {
1709             MDICREATESTRUCT16 *cs = (MDICREATESTRUCT16*)PTR_SEG_TO_LIN(p16->lParam);
1710             SEGPTR_FREE( PTR_SEG_TO_LIN(cs->szTitle) );
1711             SEGPTR_FREE( PTR_SEG_TO_LIN(cs->szClass) );
1712             SEGPTR_FREE( cs );
1713         }
1714         break;
1715     case WM_MDIGETACTIVE:
1716         if (lParam) *(BOOL32 *)lParam = (BOOL16)HIWORD(p16->lResult);
1717         p16->lResult = (HWND32)LOWORD(p16->lResult);
1718         break;
1719     case WM_NCCALCSIZE:
1720         {
1721             NCCALCSIZE_PARAMS32 *nc32;
1722             NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(p16->lParam);
1723             p16->lParam = *(LPARAM *)(nc + 1);
1724             nc32 = (NCCALCSIZE_PARAMS32 *)(p16->lParam);
1725             CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
1726             if (p16->wParam)
1727             {
1728                 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
1729                 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
1730                 STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc->lppos),
1731                                           nc32->lppos );
1732                 SEGPTR_FREE( PTR_SEG_TO_LIN(nc->lppos) );
1733             }
1734             SEGPTR_FREE(nc);
1735         }
1736         break;
1737     case WM_NCCREATE:
1738     case WM_CREATE:
1739         {
1740             CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(p16->lParam);
1741             SEGPTR_FREE( PTR_SEG_TO_LIN(cs->lpszName) );
1742             SEGPTR_FREE( PTR_SEG_TO_LIN(cs->lpszClass) );
1743             SEGPTR_FREE( cs );
1744         }
1745         break;
1746     case WM_WINDOWPOSCHANGING:
1747     case WM_WINDOWPOSCHANGED:
1748         {
1749             WINDOWPOS16 *wp = (WINDOWPOS16 *)PTR_SEG_TO_LIN(p16->lParam);
1750             p16->lParam = *(LPARAM *)(wp + 1);
1751             STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS32 *)p16->lParam );
1752             SEGPTR_FREE(wp);
1753         }
1754         break;
1755     case WM_NOTIFY:
1756         UnMapLS(p16->lParam);
1757         break;
1758     case WM_GETDLGCODE:
1759         if (p16->lParam)
1760         {
1761             LPMSG16 msg16 = (LPMSG16)PTR_SEG_TO_LIN(p16->lParam);
1762             MSGPARAM16 msgp16;
1763             msgp16.wParam=msg16->wParam;
1764             msgp16.lParam=msg16->lParam;
1765             WINPROC_UnmapMsg32ATo16(((LPMSG32)lParam)->message,
1766                     ((LPMSG32)lParam)->wParam, ((LPMSG32)lParam)->lParam,
1767                     &msgp16 );
1768             SEGPTR_FREE(msg16);
1769         }
1770         break;
1771     }
1772 }
1773
1774
1775 /**********************************************************************
1776  *           WINPROC_MapMsg32WTo16
1777  *
1778  * Map a message from 32-bit Unicode to 16-bit.
1779  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1780  */
1781 INT32 WINPROC_MapMsg32WTo16( HWND32 hwnd, UINT32 msg32, WPARAM32 wParam32,
1782                              UINT16 *pmsg16, WPARAM16 *pwparam16,
1783                              LPARAM *plparam )
1784 {
1785     switch(msg32)
1786     {
1787     case LB_ADDSTRING32:
1788     case LB_FINDSTRING32:
1789     case LB_FINDSTRINGEXACT32:
1790     case LB_INSERTSTRING32:
1791     case LB_SELECTSTRING32:
1792     case LB_DIR32:
1793     case LB_ADDFILE32:
1794         {
1795             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
1796             if (!str) return -1;
1797             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1798             *plparam   = (LPARAM)SEGPTR_GET(str);
1799         }
1800         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
1801         return 1;
1802
1803     case CB_ADDSTRING32:
1804     case CB_FINDSTRING32:
1805     case CB_FINDSTRINGEXACT32:
1806     case CB_INSERTSTRING32:
1807     case CB_SELECTSTRING32:
1808     case CB_DIR32:
1809         {
1810             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
1811             if (!str) return -1;
1812             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1813             *plparam   = (LPARAM)SEGPTR_GET(str);
1814         }
1815         *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING32);
1816         return 1;
1817
1818     case WM_NCCREATE:
1819     case WM_CREATE:
1820         {
1821             CREATESTRUCT16 *cs;
1822             CREATESTRUCT32W *cs32 = (CREATESTRUCT32W *)*plparam;
1823             LPSTR name, cls;
1824
1825             if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
1826             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCT32A *)cs32, cs );
1827             name = SEGPTR_STRDUP_WtoA( cs32->lpszName );
1828             cls  = SEGPTR_STRDUP_WtoA( cs32->lpszClass );
1829             cs->lpszName  = SEGPTR_GET(name);
1830             cs->lpszClass = SEGPTR_GET(cls);
1831             *pmsg16    = (UINT16)msg32;
1832             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1833             *plparam   = (LPARAM)SEGPTR_GET(cs);
1834         }
1835         return 1;
1836     case WM_MDICREATE:
1837         {
1838             MDICREATESTRUCT16 *cs;
1839             MDICREATESTRUCT32W *cs32 = (MDICREATESTRUCT32W *)*plparam;
1840             LPSTR name, cls;
1841
1842             if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
1843             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCT32A *)cs32, cs );
1844             name = SEGPTR_STRDUP_WtoA( cs32->szTitle );
1845             cls  = SEGPTR_STRDUP_WtoA( cs32->szClass );
1846             cs->szTitle = SEGPTR_GET(name);
1847             cs->szClass = SEGPTR_GET(cls);
1848             *pmsg16    = (UINT16)msg32;
1849             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1850             *plparam   = (LPARAM)SEGPTR_GET(cs);
1851         }
1852         return 1;
1853     case WM_SETTEXT:
1854         {
1855             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
1856             if (!str) return -1;
1857             *pmsg16    = (UINT16)msg32;
1858             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1859             *plparam   = (LPARAM)SEGPTR_GET(str);
1860         }
1861         return 1;
1862     default:  /* No Unicode translation needed */
1863         return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
1864                                       pwparam16, plparam );
1865     }
1866 }
1867
1868
1869 /**********************************************************************
1870  *           WINPROC_UnmapMsg32WTo16
1871  *
1872  * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
1873  */
1874 void WINPROC_UnmapMsg32WTo16( UINT32 msg, WPARAM32 wParam, LPARAM lParam,
1875                               MSGPARAM16* p16 )
1876 {
1877     switch(msg)
1878     {
1879     case WM_GETTEXT:
1880         {
1881             LPSTR str = (LPSTR)PTR_SEG_TO_LIN(p16->lParam);
1882             p16->lParam = *((LPARAM *)str - 1);
1883             lstrcpyAtoW( (LPWSTR)(p16->lParam), str );
1884             SEGPTR_FREE( (LPARAM *)str - 1 );
1885         }
1886         break;
1887     default:
1888         WINPROC_UnmapMsg32ATo16( msg, wParam, lParam, p16 );
1889         break;
1890     }
1891 }
1892
1893
1894 /**********************************************************************
1895  *           WINPROC_CallProc32ATo32W
1896  *
1897  * Call a window procedure, translating args from Ansi to Unicode.
1898  */
1899 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC32 func, HWND32 hwnd,
1900                                          UINT32 msg, WPARAM32 wParam,
1901                                          LPARAM lParam )
1902 {
1903     LRESULT result;
1904
1905     if (WINPROC_MapMsg32ATo32W( msg, wParam, &lParam ) == -1) return 0;
1906     result = WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
1907     WINPROC_UnmapMsg32ATo32W( msg, wParam, lParam );
1908     return result;
1909 }
1910
1911
1912 /**********************************************************************
1913  *           WINPROC_CallProc32WTo32A
1914  *
1915  * Call a window procedure, translating args from Unicode to Ansi.
1916  */
1917 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC32 func, HWND32 hwnd,
1918                                          UINT32 msg, WPARAM32 wParam,
1919                                          LPARAM lParam )
1920 {
1921     LRESULT result;
1922
1923     if (WINPROC_MapMsg32WTo32A( msg, wParam, &lParam ) == -1) return 0;
1924     result = WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
1925     WINPROC_UnmapMsg32WTo32A( msg, wParam, lParam );
1926     return result;
1927 }
1928
1929
1930 /**********************************************************************
1931  *           WINPROC_CallProc16To32A
1932  *
1933  * Call a 32-bit window procedure, translating the 16-bit args.
1934  */
1935 LRESULT WINPROC_CallProc16To32A( HWND16 hwnd, UINT16 msg,
1936                                  WPARAM16 wParam, LPARAM lParam,
1937                                  WNDPROC32 func )
1938 {
1939     LRESULT result;
1940     UINT32 msg32;
1941     WPARAM32 wParam32;
1942
1943     if (WINPROC_MapMsg16To32A( msg, wParam, &msg32, &wParam32, &lParam ) == -1)
1944         return 0;
1945     result = WINPROC_CallWndProc32( func, hwnd, msg32, wParam32, lParam );
1946     return WINPROC_UnmapMsg16To32A( msg32, wParam32, lParam, result );
1947 }
1948
1949
1950 /**********************************************************************
1951  *           WINPROC_CallProc16To32W
1952  *
1953  * Call a 32-bit window procedure, translating the 16-bit args.
1954  */
1955 LRESULT WINPROC_CallProc16To32W( HWND16 hwnd, UINT16 msg,
1956                                  WPARAM16 wParam, LPARAM lParam,
1957                                  WNDPROC32 func )
1958 {
1959     LRESULT result;
1960     UINT32 msg32;
1961     WPARAM32 wParam32;
1962
1963     if (WINPROC_MapMsg16To32W( msg, wParam, &msg32, &wParam32, &lParam ) == -1)
1964         return 0;
1965     result = WINPROC_CallWndProc32( func, hwnd, msg32, wParam32, lParam );
1966     return WINPROC_UnmapMsg16To32W( msg32, wParam32, lParam, result );
1967 }
1968
1969
1970 /**********************************************************************
1971  *           WINPROC_CallProc32ATo16
1972  *
1973  * Call a 16-bit window procedure, translating the 32-bit args.
1974  */
1975 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND32 hwnd,
1976                                                UINT32 msg, WPARAM32 wParam,
1977                                                LPARAM lParam )
1978 {
1979     UINT16 msg16;
1980     MSGPARAM16 mp16;
1981
1982     mp16.lParam = lParam;
1983     if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, 
1984                                &msg16, &mp16.wParam, &mp16.lParam ) == -1)
1985         return 0;
1986     mp16.lResult = Callbacks->CallWndProc( func, hwnd, msg16,
1987                                            mp16.wParam, mp16.lParam );
1988     WINPROC_UnmapMsg32ATo16( msg, wParam, lParam, &mp16 );
1989     return mp16.lResult;
1990 }
1991
1992
1993 /**********************************************************************
1994  *           WINPROC_CallProc32WTo16
1995  *
1996  * Call a 16-bit window procedure, translating the 32-bit args.
1997  */
1998 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND32 hwnd,
1999                                                UINT32 msg, WPARAM32 wParam,
2000                                                LPARAM lParam )
2001 {
2002     UINT16 msg16;
2003     MSGPARAM16 mp16;
2004
2005     mp16.lParam = lParam;
2006     if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &mp16.wParam,
2007                                &mp16.lParam ) == -1)
2008         return 0;
2009     mp16.lResult = Callbacks->CallWndProc( func, hwnd, msg16,
2010                                            mp16.wParam, mp16.lParam );
2011     WINPROC_UnmapMsg32WTo16( msg, wParam, lParam, &mp16 );
2012     return mp16.lResult;
2013 }
2014
2015
2016 /**********************************************************************
2017  *           CallWindowProc16    (USER.122)
2018  */
2019 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
2020                                  WPARAM16 wParam, LPARAM lParam )
2021 {
2022     WINDOWPROC *proc = WINPROC_GetPtr( func );
2023
2024     if (!proc)
2025         return Callbacks->CallWndProc( func, hwnd, msg, wParam, lParam );
2026
2027 #if testing
2028     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16 );
2029     return Callbacks->CallWndProc( func, hwnd, msg, wParam, lParam );
2030 #endif
2031     
2032     switch(proc->type)
2033     {
2034     case WIN_PROC_16:
2035         if (!proc->thunk.t_from32.proc) return 0;
2036         return Callbacks->CallWndProc( proc->thunk.t_from32.proc,
2037                                        hwnd, msg, wParam, lParam );
2038     case WIN_PROC_32A:
2039         if (!proc->thunk.t_from16.proc) return 0;
2040         return WINPROC_CallProc16To32A( hwnd, msg, wParam, lParam,
2041                                         proc->thunk.t_from16.proc );
2042     case WIN_PROC_32W:
2043         if (!proc->thunk.t_from16.proc) return 0;
2044         return WINPROC_CallProc16To32W( hwnd, msg, wParam, lParam,
2045                                         proc->thunk.t_from16.proc );
2046     default:
2047         WARN( relay, "Invalid proc %p\n", proc );
2048         return 0;
2049     }
2050 }
2051
2052
2053 /**********************************************************************
2054  *           CallWindowProc32A    (USER32.18) 
2055  *
2056  * The CallWindowProc() function invokes the windows procedure _func_,
2057  * with _hwnd_ as the target window, the message specified by _msg_, and
2058  * the message parameters _wParam_ and _lParam_.
2059  *
2060  * Some kinds of argument conversion may be done, I'm not sure what.
2061  *
2062  * CallWindowProc() may be used for windows subclassing. Use
2063  * SetWindowLong() to set a new windows procedure for windows of the
2064  * subclass, and handle subclassed messages in the new windows
2065  * procedure. The new windows procedure may then use CallWindowProc()
2066  * with _func_ set to the parent class's windows procedure to dispatch
2067  * the message to the superclass.
2068  *
2069  * RETURNS
2070  *
2071  *    The return value is message dependent.
2072  *
2073  * CONFORMANCE
2074  *
2075  *   ECMA-234, Win32 
2076  */
2077 LRESULT WINAPI CallWindowProc32A( 
2078     WNDPROC32 func, /* window procedure */
2079     HWND32 hwnd, /* target window */
2080     UINT32 msg,  /* message */
2081     WPARAM32 wParam, /* message dependent parameter */
2082     LPARAM lParam    /* message dependent parameter */
2083 ) {
2084     WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2085
2086     if (!proc) return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2087
2088 #if testing
2089     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32A );
2090     return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2091 #endif
2092
2093     switch(proc->type)
2094     {
2095     case WIN_PROC_16:
2096         if (!proc->thunk.t_from32.proc) return 0;
2097         return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
2098                                         hwnd, msg, wParam, lParam );
2099     case WIN_PROC_32A:
2100         if (!proc->thunk.t_from16.proc) return 0;
2101         return WINPROC_CallWndProc32( proc->thunk.t_from16.proc,
2102                                       hwnd, msg, wParam, lParam );
2103     case WIN_PROC_32W:
2104         if (!proc->thunk.t_from16.proc) return 0;
2105         return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
2106                                          hwnd, msg, wParam, lParam );
2107     default:
2108         WARN( relay, "Invalid proc %p\n", proc );
2109         return 0;
2110     }
2111 }
2112
2113
2114 /**********************************************************************
2115  *           CallWindowProc32W    (USER32.19)
2116  */
2117 LRESULT WINAPI CallWindowProc32W( WNDPROC32 func, HWND32 hwnd, UINT32 msg,
2118                                   WPARAM32 wParam, LPARAM lParam )
2119 {
2120     WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2121
2122     if (!proc) return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2123
2124 #if testing
2125     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32W );
2126     return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2127 #endif
2128
2129     switch(proc->type)
2130     {
2131     case WIN_PROC_16:
2132         if (!proc->thunk.t_from32.proc) return 0;
2133         return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
2134                                         hwnd, msg, wParam, lParam );
2135     case WIN_PROC_32A:
2136         if (!proc->thunk.t_from16.proc) return 0;
2137         return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
2138                                          hwnd, msg, wParam, lParam );
2139     case WIN_PROC_32W:
2140         if (!proc->thunk.t_from16.proc) return 0;
2141         return WINPROC_CallWndProc32( proc->thunk.t_from16.proc,
2142                                       hwnd, msg, wParam, lParam );
2143     default:
2144         WARN( relay, "Invalid proc %p\n", proc );
2145         return 0;
2146     }
2147 }