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