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