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