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