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