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