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