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