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