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