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