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