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