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