Fixes: LB_/CB_/EM_ messages for getting/setting text and a bug in
[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  *           WINPROC_TestCBForStr
387  *
388  * Return TRUE if the lparam is a string
389  */
390 BOOL32 WINPROC_TestCBForStr ( HWND32 hwnd )
391 {       WND * wnd = WIN_FindWndPtr(hwnd); 
392         return ( !(LOWORD(wnd->dwStyle) & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) ||
393               (LOWORD(wnd->dwStyle) & CBS_HASSTRINGS) );
394 }
395 /**********************************************************************
396  *           WINPROC_TestLBForStr
397  *
398  * Return TRUE if the lparam is a string
399  */
400 BOOL32 WINPROC_TestLBForStr ( HWND32 hwnd )
401 {       WND * wnd = WIN_FindWndPtr(hwnd); 
402         return ( !(LOWORD(wnd->dwStyle) & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || 
403             (LOWORD(wnd->dwStyle) & LBS_HASSTRINGS) );
404 }
405 /**********************************************************************
406  *           WINPROC_MapMsg32ATo32W
407  *
408  * Map a message from Ansi to Unicode.
409  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
410  * fixme WM_CHAR, WM_CHARTOITEM, WM_DEADCHAR, WM_MENUCHAR, WM_SYSCHAR,
411  * WM_SYSDEADCHAR ???
412  */
413 INT32 WINPROC_MapMsg32ATo32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM *plparam )
414 {   switch(msg)
415     {
416     case WM_GETTEXT:
417         {
418             LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
419                                      wParam * sizeof(WCHAR) + sizeof(LPARAM) );
420             if (!ptr) return -1;
421             *ptr++ = *plparam;  /* Store previous lParam */
422             *plparam = (LPARAM)ptr;
423         }
424         return 1;
425
426     case WM_SETTEXT:
427     case CB_DIR32:
428     case CB_FINDSTRING32:
429     case CB_FINDSTRINGEXACT32:
430     case CB_SELECTSTRING32:
431         *plparam = (LPARAM)HEAP_strdupAtoW( SystemHeap, 0, (LPCSTR)*plparam );
432         return (*plparam ? 1 : -1);
433
434     case WM_NCCREATE:
435     case WM_CREATE:
436         {
437             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
438                                                                 sizeof(*cs) );
439             if (!cs) return -1;
440             *cs = *(CREATESTRUCT32W *)*plparam;
441             if (HIWORD(cs->lpszName))
442                 cs->lpszName = HEAP_strdupAtoW( SystemHeap, 0,
443                                                 (LPCSTR)cs->lpszName );
444             if (HIWORD(cs->lpszClass))
445                 cs->lpszClass = HEAP_strdupAtoW( SystemHeap, 0,
446                                                  (LPCSTR)cs->lpszClass );
447             *plparam = (LPARAM)cs;
448         }
449         return 1;
450     case WM_MDICREATE:
451         {
452             MDICREATESTRUCT32W *cs =
453                 (MDICREATESTRUCT32W *)HeapAlloc( SystemHeap, 0, sizeof(*cs) );
454             if (!cs) return -1;
455             *cs = *(MDICREATESTRUCT32W *)*plparam;
456             if (HIWORD(cs->szClass))
457                 cs->szClass = HEAP_strdupAtoW( SystemHeap, 0,
458                                                (LPCSTR)cs->szClass );
459             if (HIWORD(cs->szTitle))
460                 cs->szTitle = HEAP_strdupAtoW( SystemHeap, 0,
461                                                (LPCSTR)cs->szTitle );
462             *plparam = (LPARAM)cs;
463         }
464         return 1;
465
466 /* Listbox */
467     case LB_ADDSTRING32:
468     case LB_INSERTSTRING32:
469         if ( WINPROC_TestLBForStr( hwnd ))
470           *plparam = (LPARAM)HEAP_strdupAtoW( SystemHeap, 0, (LPCSTR)*plparam );
471         return (*plparam ? 1 : -1);
472
473     case LB_GETTEXT32:              /* fixme: fixed sized buffer */
474         { if ( WINPROC_TestLBForStr( hwnd ))
475           { LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
476             if (!ptr) return -1;
477             *ptr++ = *plparam;  /* Store previous lParam */
478             *plparam = (LPARAM)ptr;
479           }
480         }
481         return 1;
482
483 /* Combobox */
484     case CB_ADDSTRING32:
485     case CB_INSERTSTRING32:
486         if ( WINPROC_TestCBForStr( hwnd ))
487           *plparam = (LPARAM)HEAP_strdupAtoW( SystemHeap, 0, (LPCSTR)*plparam );
488         return (*plparam ? 1 : -1);
489
490     case CB_GETLBTEXT32:    /* fixme: fixed sized buffer */
491         { if ( WINPROC_TestCBForStr( hwnd ))
492           { LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
493             if (!ptr) return -1;
494             *ptr++ = *plparam;  /* Store previous lParam */
495             *plparam = (LPARAM)ptr;
496           }
497         }
498         return 1;
499
500 /* Multiline edit */
501     case EM_GETLINE32:
502         { WORD len = (WORD)*plparam;
503           LPARAM *ptr = (LPARAM *) HEAP_xalloc( SystemHeap, 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
504           if (!ptr) return -1;
505           *ptr++ = *plparam;  /* Store previous lParam */
506           (WORD)*ptr = len;   /* Store the lenght */
507           *plparam = (LPARAM)ptr;
508         }
509         return 1;
510
511     case WM_ASKCBFORMATNAME:
512     case WM_DEVMODECHANGE:
513     case WM_PAINTCLIPBOARD:
514     case WM_SIZECLIPBOARD:
515     case WM_WININICHANGE:
516     case EM_REPLACESEL32:
517     case EM_SETPASSWORDCHAR32:
518     case LB_ADDFILE32:
519     case LB_DIR32:
520     case LB_FINDSTRING32:
521     case LB_SELECTSTRING32:
522         FIXME(msg, "message %s (0x%x) needs translation\n", SPY_GetMsgName(msg), msg );
523         return -1;
524     default:  /* No translation needed */
525         return 0;
526     }
527 }
528
529
530 /**********************************************************************
531  *           WINPROC_UnmapMsg32ATo32W
532  *
533  * Unmap a message that was mapped from Ansi to Unicode.
534  */
535 void WINPROC_UnmapMsg32ATo32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam )
536 {   switch(msg)
537     {
538     case WM_GETTEXT:
539         {
540             LPARAM *ptr = (LPARAM *)lParam - 1;
541             lstrcpynWtoA( (LPSTR)*ptr, (LPWSTR)(ptr + 1), wParam ); /* fixme: shouldn't be there lParam instead of ptr ???*/
542             HeapFree( SystemHeap, 0, ptr );
543         }
544         break;
545
546     case WM_NCCREATE:
547     case WM_CREATE:
548         {
549             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
550             if (HIWORD(cs->lpszName))
551                 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszName );
552             if (HIWORD(cs->lpszClass))
553                 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszClass );
554             HeapFree( SystemHeap, 0, cs );
555         }
556         break;
557
558     case WM_MDICREATE:
559         {
560             MDICREATESTRUCT32W *cs = (MDICREATESTRUCT32W *)lParam;
561             if (HIWORD(cs->szTitle))
562                 HeapFree( SystemHeap, 0, (LPVOID)cs->szTitle );
563             if (HIWORD(cs->szClass))
564                 HeapFree( SystemHeap, 0, (LPVOID)cs->szClass );
565             HeapFree( SystemHeap, 0, cs );
566         }
567         break;
568
569     case WM_SETTEXT:
570     case CB_DIR32:
571     case CB_FINDSTRING32:
572     case CB_FINDSTRINGEXACT32:
573     case CB_SELECTSTRING32:
574         HeapFree( SystemHeap, 0, (void *)lParam );
575         break;
576
577 /* Listbox */
578     case LB_ADDSTRING32:
579     case LB_INSERTSTRING32:
580         if ( WINPROC_TestLBForStr( hwnd ))
581           HeapFree( SystemHeap, 0, (void *)lParam );
582         break;
583
584     case LB_GETTEXT32:
585         { if ( WINPROC_TestLBForStr( hwnd ))
586           { LPARAM *ptr = (LPARAM *)lParam - 1;
587             lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(lParam) );
588             HeapFree( SystemHeap, 0, ptr );
589           }
590         }
591         break;
592
593 /* Combobox */
594     case CB_ADDSTRING32:
595     case CB_INSERTSTRING32:
596         if ( WINPROC_TestCBForStr( hwnd ))
597           HeapFree( SystemHeap, 0, (void *)lParam );
598         break;
599
600     case CB_GETLBTEXT32:
601         { if ( WINPROC_TestCBForStr( hwnd ))
602           { LPARAM *ptr = (LPARAM *)lParam - 1;
603             lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(lParam) );
604             HeapFree( SystemHeap, 0, ptr );
605           }
606         }
607         break;
608
609 /* Multiline edit */
610     case EM_GETLINE32:
611         { LPARAM *ptr = (LPARAM *)lParam - 1;  /* get the old lParam */
612           WORD len = *(WORD *)ptr;
613           lstrcpynWtoA( ((LPSTR)*ptr)+2, ((LPWSTR)(lParam + 1))+1, len );
614           HeapFree( SystemHeap, 0, ptr );
615         }
616         break;
617     }
618 }
619
620
621 /**********************************************************************
622  *           WINPROC_MapMsg32WTo32A
623  *
624  * Map a message from Unicode to Ansi.
625  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
626  */
627 INT32 WINPROC_MapMsg32WTo32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM *plparam )
628 {   switch(msg)
629     {
630     case WM_GETTEXT:
631         {
632             LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
633                                                wParam + sizeof(LPARAM) );
634             if (!ptr) return -1;
635             *ptr++ = *plparam;  /* Store previous lParam */
636             *plparam = (LPARAM)ptr;
637         }
638         return 1;
639
640     case WM_SETTEXT:
641     case CB_DIR32:
642     case CB_FINDSTRING32:
643     case CB_FINDSTRINGEXACT32:
644     case CB_SELECTSTRING32:
645         *plparam = (LPARAM)HEAP_strdupWtoA( SystemHeap, 0, (LPCWSTR)*plparam );
646         return (*plparam ? 1 : -1);
647
648     case WM_NCCREATE:
649     case WM_CREATE:
650         {
651             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
652                                                                 sizeof(*cs) );
653             if (!cs) return -1;
654             *cs = *(CREATESTRUCT32A *)*plparam;
655             if (HIWORD(cs->lpszName))
656                 cs->lpszName  = HEAP_strdupWtoA( SystemHeap, 0,
657                                                  (LPCWSTR)cs->lpszName );
658             if (HIWORD(cs->lpszClass))
659                 cs->lpszClass = HEAP_strdupWtoA( SystemHeap, 0,
660                                                  (LPCWSTR)cs->lpszClass);
661             *plparam = (LPARAM)cs;
662         }
663         return 1;
664     case WM_MDICREATE:
665         {
666             MDICREATESTRUCT32A *cs =
667                 (MDICREATESTRUCT32A *)HeapAlloc( SystemHeap, 0, sizeof(*cs) );
668             if (!cs) return -1;
669             *cs = *(MDICREATESTRUCT32A *)*plparam;
670             if (HIWORD(cs->szTitle))
671                 cs->szTitle = HEAP_strdupWtoA( SystemHeap, 0,
672                                                (LPCWSTR)cs->szTitle );
673             if (HIWORD(cs->szClass))
674                 cs->szClass = HEAP_strdupWtoA( SystemHeap, 0,
675                                                (LPCWSTR)cs->szClass );
676             *plparam = (LPARAM)cs;
677         }
678         return 1;
679
680 /* Listbox */
681     case LB_ADDSTRING32:
682     case LB_INSERTSTRING32:
683         if ( WINPROC_TestLBForStr( hwnd ))
684           *plparam = (LPARAM)HEAP_strdupWtoA( SystemHeap, 0, (LPCWSTR)*plparam );
685         return (*plparam ? 1 : -1);
686
687     case LB_GETTEXT32:                  /* fixme: fixed sized buffer */
688         { if ( WINPROC_TestLBForStr( hwnd ))
689           { LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0, 256 + sizeof(LPARAM) );
690             if (!ptr) return -1;
691             *ptr++ = *plparam;  /* Store previous lParam */
692             *plparam = (LPARAM)ptr;
693           }
694         }
695         return 1;
696
697 /* Combobox */
698     case CB_ADDSTRING32:
699     case CB_INSERTSTRING32:
700         if ( WINPROC_TestCBForStr( hwnd ))
701           *plparam = (LPARAM)HEAP_strdupWtoA( SystemHeap, 0, (LPCWSTR)*plparam );
702         return (*plparam ? 1 : -1);
703
704     case CB_GETLBTEXT32:                /* fixme: fixed sized buffer */
705         { if ( WINPROC_TestCBForStr( hwnd ))
706           { LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0, 256 + sizeof(LPARAM) );
707             if (!ptr) return -1;
708             *ptr++ = *plparam;  /* Store previous lParam */
709             *plparam = (LPARAM)ptr;
710           }
711         }
712         return 1;
713
714 /* Multiline edit */
715     case EM_GETLINE32:
716         { WORD len = (WORD)*plparam;
717           LPARAM *ptr = (LPARAM *) HEAP_xalloc( SystemHeap, 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(CHAR) );
718           if (!ptr) return -1;
719           *ptr++ = *plparam;  /* Store previous lParam */
720           (WORD)*ptr = len;   /* Store the lenght */
721           *plparam = (LPARAM)ptr;
722         }
723         return 1;
724
725     case WM_ASKCBFORMATNAME:
726     case WM_DEVMODECHANGE:
727     case WM_PAINTCLIPBOARD:
728     case WM_SIZECLIPBOARD:
729     case WM_WININICHANGE:
730     case EM_REPLACESEL32:
731     case EM_SETPASSWORDCHAR32:
732     case LB_ADDFILE32:
733     case LB_DIR32:
734     case LB_FINDSTRING32:
735     case LB_SELECTSTRING32:
736         FIXME(msg, "message %04x needs translation\n",msg );
737         return -1;
738     default:  /* No translation needed */
739         return 0;
740     }
741 }
742
743
744 /**********************************************************************
745  *           WINPROC_UnmapMsg32WTo32A
746  *
747  * Unmap a message that was mapped from Unicode to Ansi.
748  */
749 void WINPROC_UnmapMsg32WTo32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam )
750 {   switch(msg)
751     {
752     case WM_GETTEXT:
753         {
754             LPARAM *ptr = (LPARAM *)lParam - 1;
755             lstrcpynAtoW( (LPWSTR)*ptr, (LPSTR)(ptr + 1), wParam ); /* fixme: shouldn't be there lParam instead of ptr ???*/
756             HeapFree( SystemHeap, 0, ptr );
757         }
758         break;
759
760     case WM_SETTEXT:
761     case CB_DIR32:
762     case CB_FINDSTRING32:
763     case CB_FINDSTRINGEXACT32:
764     case CB_SELECTSTRING32:
765         HeapFree( SystemHeap, 0, (void *)lParam );
766         break;
767
768     case WM_NCCREATE:
769     case WM_CREATE:
770         {
771             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
772             if (HIWORD(cs->lpszName))
773                 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszName );
774             if (HIWORD(cs->lpszClass))
775                 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszClass );
776             HeapFree( SystemHeap, 0, cs );
777         }
778         break;
779
780     case WM_MDICREATE:
781         {
782             MDICREATESTRUCT32A *cs = (MDICREATESTRUCT32A *)lParam;
783             if (HIWORD(cs->szTitle))
784                 HeapFree( SystemHeap, 0, (LPVOID)cs->szTitle );
785             if (HIWORD(cs->szClass))
786                 HeapFree( SystemHeap, 0, (LPVOID)cs->szClass );
787             HeapFree( SystemHeap, 0, cs );
788         }
789         break;
790
791 /* Listbox */
792     case LB_ADDSTRING32:
793     case LB_INSERTSTRING32:
794         if ( WINPROC_TestLBForStr( hwnd ))
795           HeapFree( SystemHeap, 0, (void *)lParam );
796         break;
797
798     case LB_GETTEXT32:
799         { if ( WINPROC_TestLBForStr( hwnd ))
800           { LPARAM *ptr = (LPARAM *)lParam - 1;
801             lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(lParam) );
802             HeapFree( SystemHeap, 0, ptr );
803           }
804         }
805         break;
806
807 /* Combobox */
808     case CB_ADDSTRING32:
809     case CB_INSERTSTRING32:
810         if ( WINPROC_TestCBForStr( hwnd ))
811           HeapFree( SystemHeap, 0, (void *)lParam );
812         break;
813
814     case CB_GETLBTEXT32:
815         { if ( WINPROC_TestCBForStr( hwnd ))
816           { LPARAM *ptr = (LPARAM *)lParam - 1;
817             lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(lParam) );
818             HeapFree( SystemHeap, 0, ptr );
819           }
820         }
821         break;
822
823 /* Multiline edit */
824     case EM_GETLINE32:
825         { LPARAM *ptr = (LPARAM *)lParam - 1;  /* get the old lParam */
826           WORD len = *(WORD *)ptr;
827           lstrcpynAtoW( ((LPWSTR)*ptr)+1, ((LPSTR)(lParam + 1))+2, len );
828           HeapFree( SystemHeap, 0, ptr );
829         }
830         break;
831     }
832 }
833
834
835 /**********************************************************************
836  *           WINPROC_MapMsg16To32A
837  *
838  * Map a message from 16- to 32-bit Ansi.
839  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
840  */
841 INT32 WINPROC_MapMsg16To32A( UINT16 msg16, WPARAM16 wParam16, UINT32 *pmsg32,
842                              WPARAM32 *pwparam32, LPARAM *plparam )
843 {
844     *pmsg32 = (UINT32)msg16;
845     *pwparam32 = (WPARAM32)wParam16;
846     switch(msg16)
847     {
848     case WM_ACTIVATE:
849     case WM_CHARTOITEM:
850     case WM_COMMAND:
851     case WM_VKEYTOITEM:
852         *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
853         *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
854         return 0;
855     case WM_HSCROLL:
856     case WM_VSCROLL:
857         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
858         *plparam   = (LPARAM)(HWND32)HIWORD(*plparam);
859         return 0;
860     case WM_CTLCOLOR:
861         if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
862         *pmsg32    = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
863         *pwparam32 = (WPARAM32)(HDC32)wParam16;
864         *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
865         return 0;
866     case WM_COMPAREITEM:
867         {
868             COMPAREITEMSTRUCT16* cis16 = (COMPAREITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
869             COMPAREITEMSTRUCT32 *cis = (COMPAREITEMSTRUCT32 *)
870                                         HeapAlloc(SystemHeap, 0, sizeof(*cis));
871             if (!cis) return -1;
872             cis->CtlType    = cis16->CtlType;
873             cis->CtlID      = cis16->CtlID;
874             cis->hwndItem   = cis16->hwndItem;
875             cis->itemID1    = cis16->itemID1;
876             cis->itemData1  = cis16->itemData1;
877             cis->itemID2    = cis16->itemID2;
878             cis->itemData2  = cis16->itemData2;
879             cis->dwLocaleId = 0;  /* FIXME */
880             *plparam = (LPARAM)cis;
881         }
882         return 1;
883     case WM_DELETEITEM:
884         {
885             DELETEITEMSTRUCT16* dis16 = (DELETEITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
886             DELETEITEMSTRUCT32 *dis = (DELETEITEMSTRUCT32 *)
887                                         HeapAlloc(SystemHeap, 0, sizeof(*dis));
888             if (!dis) return -1;
889             dis->CtlType  = dis16->CtlType;
890             dis->CtlID    = dis16->CtlID;
891             dis->hwndItem = dis16->hwndItem;
892             dis->itemData = dis16->itemData;
893             *plparam = (LPARAM)dis;
894         }
895         return 1;
896     case WM_MEASUREITEM:
897         {
898             MEASUREITEMSTRUCT16* mis16 = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
899             MEASUREITEMSTRUCT32 *mis = (MEASUREITEMSTRUCT32 *)
900                                         HeapAlloc(SystemHeap, 0,
901                                                 sizeof(*mis) + sizeof(LPARAM));
902             if (!mis) return -1;
903             mis->CtlType    = mis16->CtlType;
904             mis->CtlID      = mis16->CtlID;
905             mis->itemID     = mis16->itemID;
906             mis->itemWidth  = mis16->itemWidth;
907             mis->itemHeight = mis16->itemHeight;
908             mis->itemData   = mis16->itemData;
909             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
910             *plparam = (LPARAM)mis;
911         }
912         return 1;
913     case WM_DRAWITEM:
914         {
915             DRAWITEMSTRUCT16* dis16 = (DRAWITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
916             DRAWITEMSTRUCT32 *dis = (DRAWITEMSTRUCT32*)HeapAlloc(SystemHeap, 0,
917                                                                  sizeof(*dis));
918             if (!dis) return -1;
919             dis->CtlType    = dis16->CtlType;
920             dis->CtlID      = dis16->CtlID;
921             dis->itemID     = dis16->itemID;
922             dis->itemAction = dis16->itemAction;
923             dis->itemState  = dis16->itemState;
924             dis->hwndItem   = dis16->hwndItem;
925             dis->hDC        = dis16->hDC;
926             dis->itemData   = dis16->itemData;
927             CONV_RECT16TO32( &dis16->rcItem, &dis->rcItem );
928             *plparam = (LPARAM)dis;
929         }
930         return 1;
931     case WM_GETMINMAXINFO:
932         {
933             MINMAXINFO32 *mmi = (MINMAXINFO32 *)HeapAlloc( SystemHeap, 0,
934                                                 sizeof(*mmi) + sizeof(LPARAM));
935             if (!mmi) return -1;
936             STRUCT32_MINMAXINFO16to32( (MINMAXINFO16*)PTR_SEG_TO_LIN(*plparam),
937                                        mmi );
938             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
939             *plparam = (LPARAM)mmi;
940         }
941         return 1;
942     case WM_GETTEXT:
943     case WM_SETTEXT:
944         *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
945         return 0;
946     case WM_MDICREATE:
947         {
948             MDICREATESTRUCT16 *cs16 =
949                 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
950             MDICREATESTRUCT32A *cs =
951                 (MDICREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
952                                                 sizeof(*cs) + sizeof(LPARAM) );
953             if (!cs) return -1;
954             STRUCT32_MDICREATESTRUCT16to32A( cs16, cs );
955             cs->szTitle = (LPCSTR)PTR_SEG_TO_LIN(cs16->szTitle);
956             cs->szClass = (LPCSTR)PTR_SEG_TO_LIN(cs16->szClass);
957             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
958             *plparam = (LPARAM)cs;
959         }
960         return 1;
961     case WM_MDIGETACTIVE:
962         *plparam = (LPARAM)HeapAlloc( SystemHeap, 0, sizeof(BOOL32) );
963         return 1;
964     case WM_MDISETMENU:
965         if(wParam16==TRUE)
966            *pmsg32=WM_MDIREFRESHMENU;
967         *pwparam32 = (WPARAM32)(HMENU32)LOWORD(*plparam);
968         *plparam   = (LPARAM)(HMENU32)HIWORD(*plparam);
969         return 0;
970     case WM_MENUCHAR:
971     case WM_MENUSELECT:
972         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
973         *plparam   = (LPARAM)(HMENU32)HIWORD(*plparam);
974         return 0;
975     case WM_MDIACTIVATE:
976         if( *plparam )
977         {
978             *pwparam32 = (WPARAM32)(HWND32)HIWORD(*plparam);
979             *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
980         }
981         else /* message sent to MDI client */
982             *pwparam32 = wParam16;
983         return 0;
984     case WM_NCCALCSIZE:
985         {
986             NCCALCSIZE_PARAMS16 *nc16;
987             NCCALCSIZE_PARAMS32 *nc;
988
989             nc = (NCCALCSIZE_PARAMS32 *)HeapAlloc( SystemHeap, 0,
990                                                 sizeof(*nc) + sizeof(LPARAM) );
991             if (!nc) return -1;
992             nc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(*plparam);
993             CONV_RECT16TO32( &nc16->rgrc[0], &nc->rgrc[0] );
994             if (wParam16)
995             {
996                 nc->lppos = (WINDOWPOS32 *)HeapAlloc( SystemHeap, 0,
997                                                       sizeof(*nc->lppos) );
998                 CONV_RECT16TO32( &nc16->rgrc[1], &nc->rgrc[1] );
999                 CONV_RECT16TO32( &nc16->rgrc[2], &nc->rgrc[2] );
1000                 if (nc->lppos) STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc16->lppos), nc->lppos );
1001             }
1002             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
1003             *plparam = (LPARAM)nc;
1004         }
1005         return 1;
1006     case WM_NCCREATE:
1007     case WM_CREATE:
1008         {
1009             CREATESTRUCT16 *cs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
1010             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
1011                                                 sizeof(*cs) + sizeof(LPARAM) );
1012             if (!cs) return -1;
1013             STRUCT32_CREATESTRUCT16to32A( cs16, cs );
1014             cs->lpszName  = (LPCSTR)PTR_SEG_TO_LIN(cs16->lpszName);
1015             cs->lpszClass = (LPCSTR)PTR_SEG_TO_LIN(cs16->lpszClass);
1016             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1017             *plparam = (LPARAM)cs;
1018         }
1019         return 1;
1020     case WM_PARENTNOTIFY:
1021         if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
1022         {
1023             *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1024             *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
1025         }
1026         return 0;
1027     case WM_WINDOWPOSCHANGING:
1028     case WM_WINDOWPOSCHANGED:
1029         {
1030             WINDOWPOS32 *wp = (WINDOWPOS32 *)HeapAlloc( SystemHeap, 0,
1031                                                 sizeof(*wp) + sizeof(LPARAM) );
1032             if (!wp) return -1;
1033             STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(*plparam),
1034                                       wp );
1035             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
1036             *plparam = (LPARAM)wp;
1037         }
1038         return 1;
1039     case WM_GETDLGCODE:
1040         if (*plparam)
1041         {
1042             LPMSG16 msg16 = (LPMSG16)PTR_SEG_TO_LIN(*plparam);
1043             LPMSG32 msg32 = (LPMSG32)HeapAlloc( SystemHeap, 0, sizeof(MSG32) );
1044
1045             if (!msg32) return -1;
1046             msg32->hwnd = msg16->hwnd;
1047             msg32->lParam = msg16->lParam;
1048             msg32->time = msg16->time;
1049             CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1050             /* this is right, right? */
1051             if (WINPROC_MapMsg16To32A(msg16->message,msg16->wParam,
1052                                      &msg32->message,&msg32->wParam,
1053                                      &msg32->lParam)<0) {
1054                 HeapFree( SystemHeap, 0, msg32 );
1055                 return -1;
1056             }
1057             *plparam = (LPARAM)msg32;
1058             return 1;
1059         }
1060         else return 0;
1061     case WM_NOTIFY:
1062         *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
1063         return 1;
1064     case WM_ASKCBFORMATNAME:
1065     case WM_DEVMODECHANGE:
1066     case WM_PAINTCLIPBOARD:
1067     case WM_SIZECLIPBOARD:
1068     case WM_WININICHANGE:
1069         FIXME( msg, "message %04x needs translation\n",msg16 );
1070         return -1;
1071
1072     default:  /* No translation needed */
1073         return 0;
1074     }
1075 }
1076
1077
1078 /**********************************************************************
1079  *           WINPROC_UnmapMsg16To32A
1080  *
1081  * Unmap a message that was mapped from 16- to 32-bit Ansi.
1082  */
1083 LRESULT WINPROC_UnmapMsg16To32A( HWND16 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam,
1084                                  LRESULT result )
1085 {
1086     switch(msg)
1087     {
1088     case WM_COMPAREITEM:
1089     case WM_DELETEITEM:
1090     case WM_DRAWITEM:
1091         HeapFree( SystemHeap, 0, (LPVOID)lParam );
1092         break;
1093     case WM_MEASUREITEM:
1094         {
1095             MEASUREITEMSTRUCT16 *mis16;
1096             MEASUREITEMSTRUCT32 *mis = (MEASUREITEMSTRUCT32 *)lParam;
1097             lParam = *(LPARAM *)(mis + 1);
1098             mis16 = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(lParam);
1099             mis16->itemWidth  = (UINT16)mis->itemWidth;
1100             mis16->itemHeight = (UINT16)mis->itemHeight;
1101             HeapFree( SystemHeap, 0, mis );
1102         }
1103         break;
1104     case WM_GETMINMAXINFO:
1105         {
1106             MINMAXINFO32 *mmi = (MINMAXINFO32 *)lParam;
1107             lParam = *(LPARAM *)(mmi + 1);
1108             STRUCT32_MINMAXINFO32to16( mmi,
1109                                        (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam));
1110             HeapFree( SystemHeap, 0, mmi );
1111         }
1112         break;
1113     case WM_MDICREATE:
1114         {
1115             MDICREATESTRUCT32A *cs = (MDICREATESTRUCT32A *)lParam;
1116             lParam = *(LPARAM *)(cs + 1);
1117             STRUCT32_MDICREATESTRUCT32Ato16( cs,
1118                                  (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1119             HeapFree( SystemHeap, 0, cs );
1120         }
1121         break;
1122     case WM_MDIGETACTIVE:
1123         result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL32 *)lParam) );
1124         HeapFree( SystemHeap, 0, (BOOL32 *)lParam );
1125         break;
1126     case WM_NCCALCSIZE:
1127         {
1128             NCCALCSIZE_PARAMS16 *nc16;
1129             NCCALCSIZE_PARAMS32 *nc = (NCCALCSIZE_PARAMS32 *)lParam;
1130             lParam = *(LPARAM *)(nc + 1);
1131             nc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam);
1132             CONV_RECT32TO16( &nc->rgrc[0], &nc16->rgrc[0] );
1133             if (wParam)
1134             {
1135                 CONV_RECT32TO16( &nc->rgrc[1], &nc16->rgrc[1] );
1136                 CONV_RECT32TO16( &nc->rgrc[2], &nc16->rgrc[2] );
1137                 if (nc->lppos)
1138                 {
1139                     STRUCT32_WINDOWPOS32to16( nc->lppos,
1140                                    (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc16->lppos));
1141                     HeapFree( SystemHeap, 0, nc->lppos );
1142                 }
1143             }
1144             HeapFree( SystemHeap, 0, nc );
1145         }
1146         break;
1147     case WM_NCCREATE:
1148     case WM_CREATE:
1149         {
1150             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
1151             lParam = *(LPARAM *)(cs + 1);
1152             STRUCT32_CREATESTRUCT32Ato16( cs,
1153                                     (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1154             HeapFree( SystemHeap, 0, cs );
1155         }
1156         break;
1157     case WM_WINDOWPOSCHANGING:
1158     case WM_WINDOWPOSCHANGED:
1159         {
1160             WINDOWPOS32 *wp = (WINDOWPOS32 *)lParam;
1161             lParam = *(LPARAM *)(wp + 1);
1162             STRUCT32_WINDOWPOS32to16(wp,(WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam));
1163             HeapFree( SystemHeap, 0, wp );
1164         }
1165         break;
1166     case WM_GETDLGCODE:
1167         if (lParam)
1168         {
1169             LPMSG32 msg32 = (LPMSG32)lParam;
1170
1171             WINPROC_UnmapMsg16To32A( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1172                                      result);
1173             HeapFree( SystemHeap, 0, msg32 );
1174         }
1175         break;
1176     }
1177     return result;
1178 }
1179
1180
1181 /**********************************************************************
1182  *           WINPROC_MapMsg16To32W
1183  *
1184  * Map a message from 16- to 32-bit Unicode.
1185  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1186  */
1187 INT32 WINPROC_MapMsg16To32W( HWND16 hwnd, UINT16 msg16, WPARAM16 wParam16, UINT32 *pmsg32,
1188                              WPARAM32 *pwparam32, LPARAM *plparam )
1189 {
1190     switch(msg16)
1191     {
1192     case WM_GETTEXT:
1193     case WM_SETTEXT:
1194         *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
1195         return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, *pwparam32, plparam );
1196     case WM_NCCREATE:
1197     case WM_CREATE:
1198         {
1199             CREATESTRUCT16 *cs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
1200             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
1201                                                 sizeof(*cs) + sizeof(LPARAM) );
1202             if (!cs) return -1;
1203             STRUCT32_CREATESTRUCT16to32A( cs16, (CREATESTRUCT32A *)cs );
1204             cs->lpszName  = (LPCWSTR)PTR_SEG_TO_LIN(cs16->lpszName);
1205             cs->lpszClass = (LPCWSTR)PTR_SEG_TO_LIN(cs16->lpszClass);
1206             if (HIWORD(cs->lpszName))
1207                 cs->lpszName = HEAP_strdupAtoW( SystemHeap, 0,
1208                                                 (LPCSTR)cs->lpszName );
1209             if (HIWORD(cs->lpszClass))
1210                 cs->lpszClass = HEAP_strdupAtoW( SystemHeap, 0,
1211                                                  (LPCSTR)cs->lpszClass );
1212             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1213             *plparam = (LPARAM)cs;
1214         }
1215         return 1;
1216     case WM_MDICREATE:
1217         {
1218             MDICREATESTRUCT16 *cs16 =
1219                 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
1220             MDICREATESTRUCT32W *cs =
1221                 (MDICREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
1222                                                 sizeof(*cs) + sizeof(LPARAM) );
1223             if (!cs) return -1;
1224             STRUCT32_MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCT32A *)cs );
1225             cs->szTitle = (LPCWSTR)PTR_SEG_TO_LIN(cs16->szTitle);
1226             cs->szClass = (LPCWSTR)PTR_SEG_TO_LIN(cs16->szClass);
1227             if (HIWORD(cs->szTitle))
1228                 cs->szTitle = HEAP_strdupAtoW( SystemHeap, 0,
1229                                                (LPCSTR)cs->szTitle );
1230             if (HIWORD(cs->szClass))
1231                 cs->szClass = HEAP_strdupAtoW( SystemHeap, 0,
1232                                                (LPCSTR)cs->szClass );
1233             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1234             *plparam = (LPARAM)cs;
1235         }
1236         return 1;
1237     case WM_GETDLGCODE:
1238         if (*plparam)
1239         {
1240             LPMSG16 msg16 = (LPMSG16)PTR_SEG_TO_LIN(*plparam);
1241             LPMSG32 msg32 = (LPMSG32)HeapAlloc( SystemHeap, 0, sizeof(MSG32) );
1242
1243             if (!msg32) return -1;
1244             msg32->hwnd = msg16->hwnd;
1245             msg32->lParam = msg16->lParam;
1246             msg32->time = msg16->time;
1247             CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1248             /* this is right, right? */
1249             if (WINPROC_MapMsg16To32W(hwnd, msg16->message,msg16->wParam,
1250                                      &msg32->message,&msg32->wParam,
1251                                      &msg32->lParam)<0) {
1252                 HeapFree( SystemHeap, 0, msg32 );
1253                 return -1;
1254             }
1255             *plparam = (LPARAM)msg32;
1256             return 1;
1257         }
1258         else return 0;
1259     default:  /* No Unicode translation needed */
1260         return WINPROC_MapMsg16To32A( msg16, wParam16, pmsg32,
1261                                       pwparam32, plparam );
1262     }
1263 }
1264
1265
1266 /**********************************************************************
1267  *           WINPROC_UnmapMsg16To32W
1268  *
1269  * Unmap a message that was mapped from 16- to 32-bit Unicode.
1270  */
1271 LRESULT WINPROC_UnmapMsg16To32W( HWND16 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam,
1272                                  LRESULT result )
1273 {
1274     switch(msg)
1275     {
1276     case WM_GETTEXT:
1277     case WM_SETTEXT:
1278         WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam );
1279         break;
1280     case WM_NCCREATE:
1281     case WM_CREATE:
1282         {
1283             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
1284             lParam = *(LPARAM *)(cs + 1);
1285             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCT32A *)cs,
1286                                     (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1287             if (HIWORD(cs->lpszName))
1288                 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszName );
1289             if (HIWORD(cs->lpszClass))
1290                 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszClass );
1291             HeapFree( SystemHeap, 0, cs );
1292         }
1293         break;
1294     case WM_MDICREATE:
1295         {
1296             MDICREATESTRUCT32W *cs = (MDICREATESTRUCT32W *)lParam;
1297             lParam = *(LPARAM *)(cs + 1);
1298             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCT32A *)cs,
1299                                  (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1300             if (HIWORD(cs->szTitle))
1301                 HeapFree( SystemHeap, 0, (LPVOID)cs->szTitle );
1302             if (HIWORD(cs->szClass))
1303                 HeapFree( SystemHeap, 0, (LPVOID)cs->szClass );
1304             HeapFree( SystemHeap, 0, cs );
1305         }
1306         break;
1307     case WM_GETDLGCODE:
1308         if (lParam)
1309         {
1310             LPMSG32 msg32 = (LPMSG32)lParam;
1311
1312             WINPROC_UnmapMsg16To32W( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1313                                      result);
1314             HeapFree( SystemHeap, 0, msg32 );
1315         }
1316         break;
1317     default:
1318         return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1319     }
1320     return result;
1321 }
1322
1323
1324 /**********************************************************************
1325  *           WINPROC_MapMsg32ATo16
1326  *
1327  * Map a message from 32-bit Ansi to 16-bit.
1328  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1329  */
1330 INT32 WINPROC_MapMsg32ATo16( HWND32 hwnd, UINT32 msg32, WPARAM32 wParam32,
1331                              UINT16 *pmsg16, WPARAM16 *pwparam16,
1332                              LPARAM *plparam )
1333 {
1334     *pmsg16 = (UINT16)msg32;
1335     *pwparam16 = (WPARAM16)LOWORD(wParam32);
1336     switch(msg32)
1337     {
1338     case BM_GETCHECK32:
1339     case BM_SETCHECK32:
1340     case BM_GETSTATE32:
1341     case BM_SETSTATE32:
1342     case BM_SETSTYLE32:
1343         *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK32);
1344         return 0;
1345
1346     case EM_GETSEL32:
1347     case EM_GETRECT32:
1348     case EM_SETRECT32:
1349     case EM_SETRECTNP32:
1350     case EM_SCROLL32:
1351     case EM_LINESCROLL32:
1352     case EM_SCROLLCARET32:
1353     case EM_GETMODIFY32:
1354     case EM_SETMODIFY32:
1355     case EM_GETLINECOUNT32:
1356     case EM_LINEINDEX32:
1357     case EM_SETHANDLE32:
1358     case EM_GETHANDLE32:
1359     case EM_GETTHUMB32:
1360     case EM_LINELENGTH32:
1361     case EM_REPLACESEL32:
1362     case EM_GETLINE32:
1363     case EM_LIMITTEXT32:
1364     case EM_CANUNDO32:
1365     case EM_UNDO32:
1366     case EM_FMTLINES32:
1367     case EM_LINEFROMCHAR32:
1368     case EM_SETTABSTOPS32:
1369     case EM_SETPASSWORDCHAR32:
1370     case EM_EMPTYUNDOBUFFER32:
1371     case EM_GETFIRSTVISIBLELINE32:
1372     case EM_SETREADONLY32:
1373     case EM_SETWORDBREAKPROC32:
1374     case EM_GETWORDBREAKPROC32:
1375     case EM_GETPASSWORDCHAR32:
1376         *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL32);
1377         return 0;
1378
1379     case LB_CARETOFF32:
1380     case LB_CARETON32:
1381     case LB_DELETESTRING32:
1382     case LB_GETANCHORINDEX32:
1383     case LB_GETCARETINDEX32:
1384     case LB_GETCOUNT32:
1385     case LB_GETCURSEL32:
1386     case LB_GETHORIZONTALEXTENT32:
1387     case LB_GETITEMDATA32:
1388     case LB_GETITEMHEIGHT32:
1389     case LB_GETSEL32:
1390     case LB_GETSELCOUNT32:
1391     case LB_GETTEXTLEN32:
1392     case LB_GETTOPINDEX32:
1393     case LB_RESETCONTENT32:
1394     case LB_SELITEMRANGE32:
1395     case LB_SELITEMRANGEEX32:
1396     case LB_SETANCHORINDEX32:
1397     case LB_SETCARETINDEX32:
1398     case LB_SETCOLUMNWIDTH32:
1399     case LB_SETCURSEL32:
1400     case LB_SETHORIZONTALEXTENT32:
1401     case LB_SETITEMDATA32:
1402     case LB_SETITEMHEIGHT32:
1403     case LB_SETSEL32:
1404     case LB_SETTOPINDEX32:
1405         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
1406         return 0;
1407     case CB_DELETESTRING32:
1408     case CB_GETCOUNT32:
1409     case CB_GETLBTEXTLEN32:
1410     case CB_LIMITTEXT32:
1411     case CB_RESETCONTENT32:
1412     case CB_SETEDITSEL32:
1413     case CB_GETCURSEL32:
1414     case CB_SETCURSEL32:
1415     case CB_SHOWDROPDOWN32:
1416     case CB_SETITEMDATA32:
1417     case CB_SETITEMHEIGHT32:
1418     case CB_GETITEMHEIGHT32:
1419     case CB_SETEXTENDEDUI32:
1420     case CB_GETEXTENDEDUI32:
1421     case CB_GETDROPPEDSTATE32:
1422         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL32);
1423         return 0;
1424     case CB_GETEDITSEL32:
1425         *pmsg16 = CB_GETEDITSEL16;
1426         return 1;
1427
1428     case LB_ADDSTRING32:
1429     case LB_FINDSTRING32:
1430     case LB_FINDSTRINGEXACT32:
1431     case LB_INSERTSTRING32:
1432     case LB_SELECTSTRING32:
1433     case LB_DIR32:
1434     case LB_ADDFILE32:
1435         {
1436             LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1437             if (!str) return -1;
1438             *plparam = (LPARAM)SEGPTR_GET(str);
1439         }
1440         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
1441         return 1;
1442
1443     case CB_ADDSTRING32:
1444     case CB_FINDSTRING32:
1445     case CB_FINDSTRINGEXACT32:
1446     case CB_INSERTSTRING32:
1447     case CB_SELECTSTRING32:
1448     case CB_DIR32:
1449         {
1450             LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1451             if (!str) return -1;
1452             *plparam = (LPARAM)SEGPTR_GET(str);
1453         }
1454         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL32);
1455         return 1;
1456
1457     case LB_GETITEMRECT32:
1458         {
1459             RECT16 *rect;
1460             rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
1461             if (!rect) return -1;
1462             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
1463             *plparam = (LPARAM)SEGPTR_GET(rect);
1464         }
1465         *pmsg16 = LB_GETITEMRECT16;
1466         return 1;
1467     case LB_GETSELITEMS32:
1468         {
1469             LPINT16 items;
1470             *pwparam16 = (WPARAM16)MIN( wParam32, 0x7f80 ); /* Must be < 64K */
1471             if (!(items = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
1472                                         + sizeof(LPARAM)))) return -1;
1473             *((LPARAM *)items)++ = *plparam;  /* Store the previous lParam */
1474             *plparam = (LPARAM)SEGPTR_GET(items);
1475         }
1476         *pmsg16 = LB_GETSELITEMS16;
1477         return 1;
1478     case LB_SETTABSTOPS32:
1479         if (wParam32)
1480         {
1481             INT32 i;
1482             LPINT16 stops;
1483             *pwparam16 = (WPARAM16)MIN( wParam32, 0x7f80 ); /* Must be < 64K */
1484             if (!(stops = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
1485                                         + sizeof(LPARAM)))) return -1;
1486             for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT32)*plparam+i);
1487             *plparam = (LPARAM)SEGPTR_GET(stops);
1488             return 1;
1489         }
1490         *pmsg16 = LB_SETTABSTOPS16;
1491         return 0;
1492
1493     case CB_GETDROPPEDCONTROLRECT32:
1494         {
1495             RECT16 *rect;
1496             rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
1497             if (!rect) return -1;
1498             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
1499             *plparam = (LPARAM)SEGPTR_GET(rect);
1500         }
1501         *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
1502         return 1;
1503
1504     case LB_GETTEXT32:
1505         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1506         *pmsg16 = LB_GETTEXT16;
1507         return 1;
1508
1509     case CB_GETLBTEXT32:
1510         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1511         *pmsg16 = CB_GETLBTEXT16;
1512         return 1;
1513
1514     case EM_SETSEL32:
1515         *pwparam16 = 0;
1516         *plparam = MAKELONG( (INT16)(INT32)wParam32, (INT16)*plparam );
1517         *pmsg16 = EM_SETSEL16;
1518         return 0;
1519
1520     case WM_ACTIVATE:
1521     case WM_CHARTOITEM:
1522     case WM_COMMAND:
1523     case WM_VKEYTOITEM:
1524         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
1525         return 0;
1526     case WM_HSCROLL:
1527     case WM_VSCROLL:
1528         *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
1529         return 0;
1530     case WM_CTLCOLORMSGBOX:
1531     case WM_CTLCOLOREDIT:
1532     case WM_CTLCOLORLISTBOX:
1533     case WM_CTLCOLORBTN:
1534     case WM_CTLCOLORDLG:
1535     case WM_CTLCOLORSCROLLBAR:
1536     case WM_CTLCOLORSTATIC:
1537         *pmsg16  = WM_CTLCOLOR;
1538         *plparam = MAKELPARAM( (HWND16)*plparam,
1539                                (WORD)msg32 - WM_CTLCOLORMSGBOX );
1540         return 0;
1541     case WM_COMPAREITEM:
1542         {
1543             COMPAREITEMSTRUCT32 *cis32 = (COMPAREITEMSTRUCT32 *)*plparam;
1544             COMPAREITEMSTRUCT16 *cis = SEGPTR_NEW(COMPAREITEMSTRUCT16);
1545             if (!cis) return -1;
1546             cis->CtlType    = (UINT16)cis32->CtlType;
1547             cis->CtlID      = (UINT16)cis32->CtlID;
1548             cis->hwndItem   = (HWND16)cis32->hwndItem;
1549             cis->itemID1    = (UINT16)cis32->itemID1;
1550             cis->itemData1  = cis32->itemData1;
1551             cis->itemID2    = (UINT16)cis32->itemID2;
1552             cis->itemData2  = cis32->itemData2;
1553             *plparam = (LPARAM)SEGPTR_GET(cis);
1554         }
1555         return 1;
1556     case WM_DELETEITEM:
1557         {
1558             DELETEITEMSTRUCT32 *dis32 = (DELETEITEMSTRUCT32 *)*plparam;
1559             DELETEITEMSTRUCT16 *dis = SEGPTR_NEW(DELETEITEMSTRUCT16);
1560             if (!dis) return -1;
1561             dis->CtlType  = (UINT16)dis32->CtlType;
1562             dis->CtlID    = (UINT16)dis32->CtlID;
1563             dis->itemID   = (UINT16)dis32->itemID;
1564             dis->hwndItem = (HWND16)dis32->hwndItem;
1565             dis->itemData = dis32->itemData;
1566             *plparam = (LPARAM)SEGPTR_GET(dis);
1567         }
1568         return 1;
1569     case WM_DRAWITEM:
1570         {
1571             DRAWITEMSTRUCT32 *dis32 = (DRAWITEMSTRUCT32 *)*plparam;
1572             DRAWITEMSTRUCT16 *dis = SEGPTR_NEW(DRAWITEMSTRUCT16);
1573             if (!dis) return -1;
1574             dis->CtlType    = (UINT16)dis32->CtlType;
1575             dis->CtlID      = (UINT16)dis32->CtlID;
1576             dis->itemID     = (UINT16)dis32->itemID;
1577             dis->itemAction = (UINT16)dis32->itemAction;
1578             dis->itemState  = (UINT16)dis32->itemState;
1579             dis->hwndItem   = (HWND16)dis32->hwndItem;
1580             dis->hDC        = (HDC16)dis32->hDC;
1581             dis->itemData   = dis32->itemData;
1582             CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
1583             *plparam = (LPARAM)SEGPTR_GET(dis);
1584         }
1585         return 1;
1586     case WM_MEASUREITEM:
1587         {
1588             MEASUREITEMSTRUCT32 *mis32 = (MEASUREITEMSTRUCT32 *)*plparam;
1589             MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)
1590                                      SEGPTR_ALLOC(sizeof(*mis)+sizeof(LPARAM));
1591             if (!mis) return -1;
1592             mis->CtlType    = (UINT16)mis32->CtlType;
1593             mis->CtlID      = (UINT16)mis32->CtlID;
1594             mis->itemID     = (UINT16)mis32->itemID;
1595             mis->itemWidth  = (UINT16)mis32->itemWidth;
1596             mis->itemHeight = (UINT16)mis32->itemHeight;
1597             mis->itemData   = mis32->itemData;
1598             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
1599             *plparam = (LPARAM)SEGPTR_GET(mis);
1600         }
1601         return 1;
1602     case WM_GETMINMAXINFO:
1603         {
1604             MINMAXINFO16 *mmi = (MINMAXINFO16 *)SEGPTR_ALLOC( sizeof(*mmi) +
1605                                                               sizeof(LPARAM) );
1606             if (!mmi) return -1;
1607             STRUCT32_MINMAXINFO32to16( (MINMAXINFO32 *)*plparam, mmi );
1608             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
1609             *plparam = (LPARAM)SEGPTR_GET(mmi);
1610         }
1611         return 1;
1612     case WM_GETTEXT:
1613         {
1614             LPSTR str;
1615             *pwparam16 = (WPARAM16)MIN( wParam32, 0xff80 ); /* Must be < 64K */
1616             if (!(str = SEGPTR_ALLOC(*pwparam16 + sizeof(LPARAM)))) return -1;
1617             *((LPARAM *)str)++ = *plparam;  /* Store the previous lParam */
1618             *plparam = (LPARAM)SEGPTR_GET(str);
1619         }
1620         return 1;
1621     case WM_MDICREATE:
1622         {
1623             MDICREATESTRUCT16 *cs;
1624             MDICREATESTRUCT32A *cs32 = (MDICREATESTRUCT32A *)*plparam;
1625             LPSTR name, cls;
1626
1627             if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
1628             STRUCT32_MDICREATESTRUCT32Ato16( cs32, cs );
1629             name = SEGPTR_STRDUP( cs32->szTitle );
1630             cls  = SEGPTR_STRDUP( cs32->szClass );
1631             cs->szTitle = SEGPTR_GET(name);
1632             cs->szClass = SEGPTR_GET(cls);
1633             *plparam = (LPARAM)SEGPTR_GET(cs);
1634         }
1635         return 1;
1636     case WM_MDIGETACTIVE:
1637         return 1;
1638     case WM_MDISETMENU:
1639         *plparam   = MAKELPARAM( (HMENU16)LOWORD(wParam32),
1640                                  (HMENU16)LOWORD(*plparam) );
1641         *pwparam16 = (*plparam == 0);
1642         return 0;
1643     case WM_MENUCHAR:
1644     case WM_MENUSELECT:
1645         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
1646         return 0;
1647     case WM_MDIACTIVATE:
1648         if( WIDGETS_IsControl32(WIN_FindWndPtr(hwnd), BIC32_MDICLIENT) )
1649         {
1650             *pwparam16 = (HWND32)wParam32;
1651             *plparam = 0;
1652         }
1653         else
1654         {
1655             *pwparam16 = ((HWND32)*plparam == hwnd);
1656             *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
1657                                    (HWND16)LOWORD(wParam32) );
1658         }
1659         return 0;
1660     case WM_NCCALCSIZE:
1661         {
1662             NCCALCSIZE_PARAMS32 *nc32 = (NCCALCSIZE_PARAMS32 *)*plparam;
1663             NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)SEGPTR_ALLOC( sizeof(*nc) + sizeof(LPARAM) );
1664             if (!nc) return -1;
1665
1666             CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
1667             if (wParam32)
1668             {
1669                 WINDOWPOS16 *wp;
1670                 CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
1671                 CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
1672                 if (!(wp = SEGPTR_NEW(WINDOWPOS16)))
1673                 {
1674                     SEGPTR_FREE(nc);
1675                     return -1;
1676                 }
1677                 STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
1678                 nc->lppos = SEGPTR_GET(wp);
1679             }
1680             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
1681             *plparam = (LPARAM)SEGPTR_GET(nc);
1682         }
1683         return 1;
1684     case WM_NCCREATE:
1685     case WM_CREATE:
1686         {
1687             CREATESTRUCT16 *cs;
1688             CREATESTRUCT32A *cs32 = (CREATESTRUCT32A *)*plparam;
1689             LPSTR name, cls;
1690
1691             if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
1692             STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
1693             name = SEGPTR_STRDUP( cs32->lpszName );
1694             cls  = SEGPTR_STRDUP( cs32->lpszClass );
1695             cs->lpszName  = SEGPTR_GET(name);
1696             cs->lpszClass = SEGPTR_GET(cls);
1697             *plparam = (LPARAM)SEGPTR_GET(cs);
1698         }
1699         return 1;
1700     case WM_PARENTNOTIFY:
1701         if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
1702             *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
1703         /* else nothing to do */
1704         return 0;
1705     case WM_NOTIFY:
1706         *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
1707         return 1;
1708     case WM_SETTEXT:
1709         {
1710             LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1711             if (!str) return -1;
1712             *plparam = (LPARAM)SEGPTR_GET(str);
1713         }
1714         return 1;
1715     case WM_WINDOWPOSCHANGING:
1716     case WM_WINDOWPOSCHANGED:
1717         {
1718             WINDOWPOS16 *wp = (WINDOWPOS16 *)SEGPTR_ALLOC( sizeof(*wp) +
1719                                                            sizeof(LPARAM) );
1720             if (!wp) return -1;
1721             STRUCT32_WINDOWPOS32to16( (WINDOWPOS32 *)*plparam, wp );
1722             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
1723             *plparam = (LPARAM)SEGPTR_GET(wp);
1724         }
1725         return 1;
1726     case WM_GETDLGCODE:
1727          if (*plparam) {
1728             LPMSG32 msg32 = (LPMSG32) *plparam;
1729             LPMSG16 msg16 = (LPMSG16) SEGPTR_NEW( MSG16 );
1730
1731             if (!msg16) return -1;
1732             msg16->hwnd = msg32->hwnd;
1733             msg16->lParam = msg32->lParam;
1734             msg16->time = msg32->time;
1735             CONV_POINT32TO16(&msg32->pt,&msg16->pt);
1736             /* this is right, right? */
1737             if (WINPROC_MapMsg32ATo16(msg32->hwnd,msg32->message,msg32->wParam,
1738                          &msg16->message,&msg16->wParam, &msg16->lParam)<0) {
1739                 SEGPTR_FREE( msg16 );
1740                 return -1;
1741             }
1742             *plparam = (LPARAM)SEGPTR_GET(msg16);
1743             return 1;
1744         }
1745         return 0;
1746
1747     case WM_ASKCBFORMATNAME:
1748     case WM_DEVMODECHANGE:
1749     case WM_PAINTCLIPBOARD:
1750     case WM_SIZECLIPBOARD:
1751     case WM_WININICHANGE:
1752         FIXME( msg, "message %04x needs translation\n", msg32 );
1753         return -1;
1754     default:  /* No translation needed */
1755         return 0;
1756     }
1757 }
1758
1759
1760 /**********************************************************************
1761  *           WINPROC_UnmapMsg32ATo16
1762  *
1763  * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
1764  */
1765 void WINPROC_UnmapMsg32ATo16( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam,
1766                               MSGPARAM16* p16 ) 
1767 {
1768     switch(msg)
1769     {
1770     case LB_ADDFILE32:
1771     case LB_ADDSTRING32:
1772     case LB_DIR32:
1773     case LB_FINDSTRING32:
1774     case LB_FINDSTRINGEXACT32:
1775     case LB_INSERTSTRING32:
1776     case LB_SELECTSTRING32:
1777     case LB_SETTABSTOPS32:
1778     case CB_ADDSTRING32:
1779     case CB_FINDSTRING32:
1780     case CB_FINDSTRINGEXACT32:
1781     case CB_INSERTSTRING32:
1782     case CB_SELECTSTRING32:
1783     case CB_DIR32:
1784     case WM_COMPAREITEM:
1785     case WM_DELETEITEM:
1786     case WM_DRAWITEM:
1787     case WM_SETTEXT:
1788         SEGPTR_FREE( PTR_SEG_TO_LIN(p16->lParam) );
1789         break;
1790
1791     case CB_GETDROPPEDCONTROLRECT32:
1792     case LB_GETITEMRECT32:
1793         {
1794             RECT16 *rect = (RECT16 *)PTR_SEG_TO_LIN(p16->lParam);
1795             p16->lParam = *(LPARAM *)(rect + 1);
1796             CONV_RECT16TO32( rect, (RECT32 *)(p16->lParam));
1797             SEGPTR_FREE( rect );
1798         }
1799         break;
1800     case LB_GETSELITEMS32:
1801         {
1802             INT32 i;
1803             LPINT16 items = (LPINT16)PTR_SEG_TO_LIN(lParam);
1804             p16->lParam = *((LPARAM *)items - 1);
1805             for (i = 0; i < p16->wParam; i++) *((LPINT32)(p16->lParam) + i) = items[i];
1806             SEGPTR_FREE( (LPARAM *)items - 1 );
1807         }
1808         break;
1809
1810     case CB_GETEDITSEL32:
1811         if( wParam )
1812             *((LPUINT32)(wParam)) = LOWORD(p16->lResult);
1813         if( lParam )
1814             *((LPUINT32)(lParam)) = HIWORD(p16->lResult);       /* FIXME: substract 1? */
1815         break;
1816
1817     case LB_GETTEXT32:
1818     case CB_GETLBTEXT32:
1819         UnMapLS( (SEGPTR)(p16->lParam) );
1820         break;
1821
1822     case WM_MEASUREITEM:
1823         {
1824             MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(p16->lParam);
1825             MEASUREITEMSTRUCT32 *mis32 = *(MEASUREITEMSTRUCT32 **)(mis + 1);
1826             mis32->itemWidth  = mis->itemWidth;
1827             mis32->itemHeight = mis->itemHeight;
1828             SEGPTR_FREE(mis);
1829         }
1830         break;
1831     case WM_GETMINMAXINFO:
1832         {
1833             MINMAXINFO16 *mmi = (MINMAXINFO16 *)PTR_SEG_TO_LIN(p16->lParam);
1834             p16->lParam = *(LPARAM *)(mmi + 1);
1835             STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO32 *)(p16->lParam) );
1836             SEGPTR_FREE(mmi);
1837         }
1838         break;
1839     case WM_GETTEXT:
1840         {
1841             LPSTR str = (LPSTR)PTR_SEG_TO_LIN(p16->lParam);
1842             p16->lParam = *((LPARAM *)str - 1);
1843             lstrcpyn32A( (LPSTR)(p16->lParam), str, p16->wParam );
1844             SEGPTR_FREE( (LPARAM *)str - 1 );
1845         }
1846         break;
1847     case WM_MDICREATE:
1848         {
1849             MDICREATESTRUCT16 *cs = (MDICREATESTRUCT16*)PTR_SEG_TO_LIN(p16->lParam);
1850             SEGPTR_FREE( PTR_SEG_TO_LIN(cs->szTitle) );
1851             SEGPTR_FREE( PTR_SEG_TO_LIN(cs->szClass) );
1852             SEGPTR_FREE( cs );
1853         }
1854         break;
1855     case WM_MDIGETACTIVE:
1856         if (lParam) *(BOOL32 *)lParam = (BOOL16)HIWORD(p16->lResult);
1857         p16->lResult = (HWND32)LOWORD(p16->lResult);
1858         break;
1859     case WM_NCCALCSIZE:
1860         {
1861             NCCALCSIZE_PARAMS32 *nc32;
1862             NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(p16->lParam);
1863             p16->lParam = *(LPARAM *)(nc + 1);
1864             nc32 = (NCCALCSIZE_PARAMS32 *)(p16->lParam);
1865             CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
1866             if (p16->wParam)
1867             {
1868                 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
1869                 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
1870                 STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc->lppos),
1871                                           nc32->lppos );
1872                 SEGPTR_FREE( PTR_SEG_TO_LIN(nc->lppos) );
1873             }
1874             SEGPTR_FREE(nc);
1875         }
1876         break;
1877     case WM_NCCREATE:
1878     case WM_CREATE:
1879         {
1880             CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(p16->lParam);
1881             SEGPTR_FREE( PTR_SEG_TO_LIN(cs->lpszName) );
1882             SEGPTR_FREE( PTR_SEG_TO_LIN(cs->lpszClass) );
1883             SEGPTR_FREE( cs );
1884         }
1885         break;
1886     case WM_WINDOWPOSCHANGING:
1887     case WM_WINDOWPOSCHANGED:
1888         {
1889             WINDOWPOS16 *wp = (WINDOWPOS16 *)PTR_SEG_TO_LIN(p16->lParam);
1890             p16->lParam = *(LPARAM *)(wp + 1);
1891             STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS32 *)p16->lParam );
1892             SEGPTR_FREE(wp);
1893         }
1894         break;
1895     case WM_NOTIFY:
1896         UnMapLS(p16->lParam);
1897         break;
1898     case WM_GETDLGCODE:
1899         if (p16->lParam)
1900         {
1901             LPMSG16 msg16 = (LPMSG16)PTR_SEG_TO_LIN(p16->lParam);
1902             MSGPARAM16 msgp16;
1903             msgp16.wParam=msg16->wParam;
1904             msgp16.lParam=msg16->lParam;
1905             WINPROC_UnmapMsg32ATo16(((LPMSG32)lParam)->hwnd, ((LPMSG32)lParam)->message,
1906                     ((LPMSG32)lParam)->wParam, ((LPMSG32)lParam)->lParam,
1907                     &msgp16 );
1908             SEGPTR_FREE(msg16);
1909         }
1910         break;
1911     }
1912 }
1913
1914
1915 /**********************************************************************
1916  *           WINPROC_MapMsg32WTo16
1917  *
1918  * Map a message from 32-bit Unicode to 16-bit.
1919  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1920  */
1921 INT32 WINPROC_MapMsg32WTo16( HWND32 hwnd, UINT32 msg32, WPARAM32 wParam32,
1922                              UINT16 *pmsg16, WPARAM16 *pwparam16,
1923                              LPARAM *plparam )
1924 {
1925     switch(msg32)
1926     {
1927     case LB_ADDSTRING32:
1928     case LB_FINDSTRING32:
1929     case LB_FINDSTRINGEXACT32:
1930     case LB_INSERTSTRING32:
1931     case LB_SELECTSTRING32:
1932     case LB_DIR32:
1933     case LB_ADDFILE32:
1934         {
1935             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
1936             if (!str) return -1;
1937             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1938             *plparam   = (LPARAM)SEGPTR_GET(str);
1939         }
1940         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
1941         return 1;
1942
1943     case CB_ADDSTRING32:
1944     case CB_FINDSTRING32:
1945     case CB_FINDSTRINGEXACT32:
1946     case CB_INSERTSTRING32:
1947     case CB_SELECTSTRING32:
1948     case CB_DIR32:
1949         {
1950             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
1951             if (!str) return -1;
1952             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1953             *plparam   = (LPARAM)SEGPTR_GET(str);
1954         }
1955         *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING32);
1956         return 1;
1957
1958     case WM_NCCREATE:
1959     case WM_CREATE:
1960         {
1961             CREATESTRUCT16 *cs;
1962             CREATESTRUCT32W *cs32 = (CREATESTRUCT32W *)*plparam;
1963             LPSTR name, cls;
1964
1965             if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
1966             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCT32A *)cs32, cs );
1967             name = SEGPTR_STRDUP_WtoA( cs32->lpszName );
1968             cls  = SEGPTR_STRDUP_WtoA( cs32->lpszClass );
1969             cs->lpszName  = SEGPTR_GET(name);
1970             cs->lpszClass = SEGPTR_GET(cls);
1971             *pmsg16    = (UINT16)msg32;
1972             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1973             *plparam   = (LPARAM)SEGPTR_GET(cs);
1974         }
1975         return 1;
1976     case WM_MDICREATE:
1977         {
1978             MDICREATESTRUCT16 *cs;
1979             MDICREATESTRUCT32W *cs32 = (MDICREATESTRUCT32W *)*plparam;
1980             LPSTR name, cls;
1981
1982             if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
1983             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCT32A *)cs32, cs );
1984             name = SEGPTR_STRDUP_WtoA( cs32->szTitle );
1985             cls  = SEGPTR_STRDUP_WtoA( cs32->szClass );
1986             cs->szTitle = SEGPTR_GET(name);
1987             cs->szClass = SEGPTR_GET(cls);
1988             *pmsg16    = (UINT16)msg32;
1989             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1990             *plparam   = (LPARAM)SEGPTR_GET(cs);
1991         }
1992         return 1;
1993     case WM_SETTEXT:
1994         {
1995             LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
1996             if (!str) return -1;
1997             *pmsg16    = (UINT16)msg32;
1998             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1999             *plparam   = (LPARAM)SEGPTR_GET(str);
2000         }
2001         return 1;
2002     default:  /* No Unicode translation needed */
2003         return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2004                                       pwparam16, plparam );
2005     }
2006 }
2007
2008
2009 /**********************************************************************
2010  *           WINPROC_UnmapMsg32WTo16
2011  *
2012  * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2013  */
2014 void WINPROC_UnmapMsg32WTo16( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam,
2015                               MSGPARAM16* p16 )
2016 {
2017     switch(msg)
2018     {
2019     case WM_GETTEXT:
2020         {
2021             LPSTR str = (LPSTR)PTR_SEG_TO_LIN(p16->lParam);
2022             p16->lParam = *((LPARAM *)str - 1);
2023             lstrcpyAtoW( (LPWSTR)(p16->lParam), str );
2024             SEGPTR_FREE( (LPARAM *)str - 1 );
2025         }
2026         break;
2027     default:
2028         WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, p16 );
2029         break;
2030     }
2031 }
2032
2033
2034 /**********************************************************************
2035  *           WINPROC_CallProc32ATo32W
2036  *
2037  * Call a window procedure, translating args from Ansi to Unicode.
2038  */
2039 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC32 func, HWND32 hwnd,
2040                                          UINT32 msg, WPARAM32 wParam,
2041                                          LPARAM lParam )
2042 {
2043     LRESULT result;
2044
2045     if (WINPROC_MapMsg32ATo32W( hwnd, msg, wParam, &lParam ) == -1) return 0;
2046     result = WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2047     WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam );
2048     return result;
2049 }
2050
2051
2052 /**********************************************************************
2053  *           WINPROC_CallProc32WTo32A
2054  *
2055  * Call a window procedure, translating args from Unicode to Ansi.
2056  */
2057 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC32 func, HWND32 hwnd,
2058                                          UINT32 msg, WPARAM32 wParam,
2059                                          LPARAM lParam )
2060 {
2061     LRESULT result;
2062
2063     if (WINPROC_MapMsg32WTo32A( hwnd, msg, wParam, &lParam ) == -1) return 0;
2064     result = WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2065     WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam );
2066     return result;
2067 }
2068
2069
2070 /**********************************************************************
2071  *           WINPROC_CallProc16To32A
2072  *
2073  * Call a 32-bit window procedure, translating the 16-bit args.
2074  */
2075 LRESULT WINPROC_CallProc16To32A( HWND16 hwnd, UINT16 msg,
2076                                  WPARAM16 wParam, LPARAM lParam,
2077                                  WNDPROC32 func )
2078 {
2079     LRESULT result;
2080     UINT32 msg32;
2081     WPARAM32 wParam32;
2082
2083     if (WINPROC_MapMsg16To32A( msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2084         return 0;
2085     result = WINPROC_CallWndProc32( func, hwnd, msg32, wParam32, lParam );
2086     return WINPROC_UnmapMsg16To32A( hwnd, msg32, wParam32, lParam, result );
2087 }
2088
2089
2090 /**********************************************************************
2091  *           WINPROC_CallProc16To32W
2092  *
2093  * Call a 32-bit window procedure, translating the 16-bit args.
2094  */
2095 LRESULT WINPROC_CallProc16To32W( HWND16 hwnd, UINT16 msg,
2096                                  WPARAM16 wParam, LPARAM lParam,
2097                                  WNDPROC32 func )
2098 {
2099     LRESULT result;
2100     UINT32 msg32;
2101     WPARAM32 wParam32;
2102
2103     if (WINPROC_MapMsg16To32W( hwnd, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2104         return 0;
2105     result = WINPROC_CallWndProc32( func, hwnd, msg32, wParam32, lParam );
2106     return WINPROC_UnmapMsg16To32W( hwnd, msg32, wParam32, lParam, result );
2107 }
2108
2109
2110 /**********************************************************************
2111  *           WINPROC_CallProc32ATo16
2112  *
2113  * Call a 16-bit window procedure, translating the 32-bit args.
2114  */
2115 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND32 hwnd,
2116                                                UINT32 msg, WPARAM32 wParam,
2117                                                LPARAM lParam )
2118 {
2119     UINT16 msg16;
2120     MSGPARAM16 mp16;
2121
2122     mp16.lParam = lParam;
2123     if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, 
2124                                &msg16, &mp16.wParam, &mp16.lParam ) == -1)
2125         return 0;
2126     mp16.lResult = Callbacks->CallWndProc( func, hwnd, msg16,
2127                                            mp16.wParam, mp16.lParam );
2128     WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, &mp16 );
2129     return mp16.lResult;
2130 }
2131
2132
2133 /**********************************************************************
2134  *           WINPROC_CallProc32WTo16
2135  *
2136  * Call a 16-bit window procedure, translating the 32-bit args.
2137  */
2138 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND32 hwnd,
2139                                                UINT32 msg, WPARAM32 wParam,
2140                                                LPARAM lParam )
2141 {
2142     UINT16 msg16;
2143     MSGPARAM16 mp16;
2144
2145     mp16.lParam = lParam;
2146     if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &mp16.wParam,
2147                                &mp16.lParam ) == -1)
2148         return 0;
2149     mp16.lResult = Callbacks->CallWndProc( func, hwnd, msg16,
2150                                            mp16.wParam, mp16.lParam );
2151     WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, &mp16 );
2152     return mp16.lResult;
2153 }
2154
2155
2156 /**********************************************************************
2157  *           CallWindowProc16    (USER.122)
2158  */
2159 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
2160                                  WPARAM16 wParam, LPARAM lParam )
2161 {
2162     WINDOWPROC *proc = WINPROC_GetPtr( func );
2163
2164     if (!proc)
2165         return Callbacks->CallWndProc( func, hwnd, msg, wParam, lParam );
2166
2167 #if testing
2168     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16 );
2169     return Callbacks->CallWndProc( func, hwnd, msg, wParam, lParam );
2170 #endif
2171     
2172     switch(proc->type)
2173     {
2174     case WIN_PROC_16:
2175         if (!proc->thunk.t_from32.proc) return 0;
2176         return Callbacks->CallWndProc( proc->thunk.t_from32.proc,
2177                                        hwnd, msg, wParam, lParam );
2178     case WIN_PROC_32A:
2179         if (!proc->thunk.t_from16.proc) return 0;
2180         return WINPROC_CallProc16To32A( hwnd, msg, wParam, lParam,
2181                                         proc->thunk.t_from16.proc );
2182     case WIN_PROC_32W:
2183         if (!proc->thunk.t_from16.proc) return 0;
2184         return WINPROC_CallProc16To32W( hwnd, msg, wParam, lParam,
2185                                         proc->thunk.t_from16.proc );
2186     default:
2187         WARN( relay, "Invalid proc %p\n", proc );
2188         return 0;
2189     }
2190 }
2191
2192
2193 /**********************************************************************
2194  *           CallWindowProc32A    (USER32.18) 
2195  *
2196  * The CallWindowProc() function invokes the windows procedure _func_,
2197  * with _hwnd_ as the target window, the message specified by _msg_, and
2198  * the message parameters _wParam_ and _lParam_.
2199  *
2200  * Some kinds of argument conversion may be done, I'm not sure what.
2201  *
2202  * CallWindowProc() may be used for windows subclassing. Use
2203  * SetWindowLong() to set a new windows procedure for windows of the
2204  * subclass, and handle subclassed messages in the new windows
2205  * procedure. The new windows procedure may then use CallWindowProc()
2206  * with _func_ set to the parent class's windows procedure to dispatch
2207  * the message to the superclass.
2208  *
2209  * RETURNS
2210  *
2211  *    The return value is message dependent.
2212  *
2213  * CONFORMANCE
2214  *
2215  *   ECMA-234, Win32 
2216  */
2217 LRESULT WINAPI CallWindowProc32A( 
2218     WNDPROC32 func, /* window procedure */
2219     HWND32 hwnd, /* target window */
2220     UINT32 msg,  /* message */
2221     WPARAM32 wParam, /* message dependent parameter */
2222     LPARAM lParam    /* message dependent parameter */
2223 ) {
2224     WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2225
2226     if (!proc) return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2227
2228 #if testing
2229     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32A );
2230     return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2231 #endif
2232
2233     switch(proc->type)
2234     {
2235     case WIN_PROC_16:
2236         if (!proc->thunk.t_from32.proc) return 0;
2237         return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
2238                                         hwnd, msg, wParam, lParam );
2239     case WIN_PROC_32A:
2240         if (!proc->thunk.t_from16.proc) return 0;
2241         return WINPROC_CallWndProc32( proc->thunk.t_from16.proc,
2242                                       hwnd, msg, wParam, lParam );
2243     case WIN_PROC_32W:
2244         if (!proc->thunk.t_from16.proc) return 0;
2245         return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
2246                                          hwnd, msg, wParam, lParam );
2247     default:
2248         WARN( relay, "Invalid proc %p\n", proc );
2249         return 0;
2250     }
2251 }
2252
2253
2254 /**********************************************************************
2255  *           CallWindowProc32W    (USER32.19)
2256  */
2257 LRESULT WINAPI CallWindowProc32W( WNDPROC32 func, HWND32 hwnd, UINT32 msg,
2258                                   WPARAM32 wParam, LPARAM lParam )
2259 {
2260     WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2261
2262     if (!proc) return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2263
2264 #if testing
2265     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32W );
2266     return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2267 #endif
2268
2269     switch(proc->type)
2270     {
2271     case WIN_PROC_16:
2272         if (!proc->thunk.t_from32.proc) return 0;
2273         return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
2274                                         hwnd, msg, wParam, lParam );
2275     case WIN_PROC_32A:
2276         if (!proc->thunk.t_from16.proc) return 0;
2277         return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
2278                                          hwnd, msg, wParam, lParam );
2279     case WIN_PROC_32W:
2280         if (!proc->thunk.t_from16.proc) return 0;
2281         return WINPROC_CallWndProc32( proc->thunk.t_from16.proc,
2282                                       hwnd, msg, wParam, lParam );
2283     default:
2284         WARN( relay, "Invalid proc %p\n", proc );
2285         return 0;
2286     }
2287 }