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