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