- some TRACEing fixes
[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             DWORD len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*plparam, -1, NULL, 0);
599             WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
600             len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*plparam, -1, buf, len);
601             *plparam = (LPARAM)buf;
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_IME_CHAR:
733         {
734             BYTE ch[2];
735             WCHAR wch;
736             ch[0] = (*pwparam >> 8);
737             ch[1] = *pwparam & 0xff;
738             MultiByteToWideChar(CP_ACP, 0, ch, 2, &wch, 1);
739             *pwparam = MAKEWPARAM( wch, HIWORD(*pwparam) );
740         }
741         return 0;
742
743     case WM_PAINTCLIPBOARD:
744     case WM_SIZECLIPBOARD:
745         FIXME_(msg)("message %s (0x%x) needs translation, please report\n", SPY_GetMsgName(msg, hwnd), msg );
746         return -1;
747     default:  /* No translation needed */
748         return 0;
749     }
750 }
751
752
753 /**********************************************************************
754  *           WINPROC_UnmapMsg32ATo32W
755  *
756  * Unmap a message that was mapped from Ansi to Unicode.
757  */
758 LRESULT WINPROC_UnmapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
759                                   LRESULT result )
760 {
761     switch(msg)
762     {
763     case WM_GETTEXT:
764     case WM_ASKCBFORMATNAME:
765         {
766             LPARAM *ptr = (LPARAM *)lParam - 1;
767             if (wParam > 0 && !WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
768                                                     (LPSTR)*ptr, wParam, NULL, NULL ))
769                 ((LPSTR)*ptr)[wParam-1] = 0;
770             HeapFree( GetProcessHeap(), 0, ptr );
771         }
772         break;
773     case WM_GETTEXTLENGTH:
774     case CB_GETLBTEXTLEN:
775     case LB_GETTEXTLEN:
776         /* there may be one DBCS char for each Unicode char */
777         return result * 2;
778     case WM_NCCREATE:
779     case WM_CREATE:
780         {
781             struct s
782             { CREATESTRUCTW cs;         /* new structure */
783               LPWSTR lpszName;          /* allocated Name */
784               LPWSTR lpszClass;         /* allocated Class */
785             };
786             struct s *xs = (struct s *)lParam;
787             if (xs->lpszName)  HeapFree( GetProcessHeap(), 0, xs->lpszName );
788             if (xs->lpszClass) HeapFree( GetProcessHeap(), 0, xs->lpszClass );
789             HeapFree( GetProcessHeap(), 0, xs );
790         }
791         break;
792
793     case WM_MDICREATE:
794         {
795             MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
796             if (HIWORD(cs->szTitle))
797                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
798             if (HIWORD(cs->szClass))
799                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
800             HeapFree( GetProcessHeap(), 0, cs );
801         }
802         break;
803
804     case WM_SETTEXT:
805     case WM_WININICHANGE:
806     case WM_DEVMODECHANGE:
807     case CB_DIR:
808     case LB_DIR:
809     case LB_ADDFILE:
810     case EM_REPLACESEL:
811         HeapFree( GetProcessHeap(), 0, (void *)lParam );
812         break;
813
814 /* Listbox */
815     case LB_ADDSTRING:
816     case LB_INSERTSTRING:
817     case LB_FINDSTRING:
818     case LB_FINDSTRINGEXACT:
819     case LB_SELECTSTRING:
820         if ( WINPROC_TestLBForStr( hwnd ))
821           HeapFree( GetProcessHeap(), 0, (void *)lParam );
822         break;
823
824     case LB_GETTEXT:
825         { if ( WINPROC_TestLBForStr( hwnd ))
826           { LPARAM *ptr = (LPARAM *)lParam - 1;
827             WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1, (LPSTR)*ptr, 0x7fffffff, NULL, NULL );
828             HeapFree( GetProcessHeap(), 0, ptr );
829           }
830         }
831         break;
832
833 /* Combobox */
834     case CB_ADDSTRING:
835     case CB_INSERTSTRING:
836     case CB_FINDSTRING:
837     case CB_FINDSTRINGEXACT:
838     case CB_SELECTSTRING:
839         if ( WINPROC_TestCBForStr( hwnd ))
840           HeapFree( GetProcessHeap(), 0, (void *)lParam );
841         break;
842
843     case CB_GETLBTEXT:
844         { if ( WINPROC_TestCBForStr( hwnd ))
845           { LPARAM *ptr = (LPARAM *)lParam - 1;
846             WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1, (LPSTR)*ptr, 0x7fffffff, NULL, NULL );
847             HeapFree( GetProcessHeap(), 0, ptr );
848           }
849         }
850         break;
851
852 /* Multiline edit */
853     case EM_GETLINE:
854         { LPARAM * ptr = (LPARAM *)lParam - 1;  /* get the old lParam */
855           WORD len = *(WORD *) lParam;
856           if (len > 0 && !WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
857                                                (LPSTR)*ptr, len, NULL, NULL ))
858               ((LPSTR)*ptr)[len-1] = 0;
859           HeapFree( GetProcessHeap(), 0, ptr );
860         }
861         break;
862     }
863     return result;
864 }
865
866
867 /**********************************************************************
868  *           WINPROC_MapMsg32WTo32A
869  *
870  * Map a message from Unicode to Ansi.
871  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
872  */
873 INT WINPROC_MapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
874 {
875     switch(msg)
876     {
877     case WM_GETTEXT:
878     case WM_ASKCBFORMATNAME:
879         {
880             LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
881                                                *pwparam + sizeof(LPARAM) );
882             if (!ptr) return -1;
883             *ptr++ = *plparam;  /* Store previous lParam */
884             *plparam = (LPARAM)ptr;
885         }
886         return 1;
887
888     case WM_SETTEXT:
889     case WM_WININICHANGE:
890     case WM_DEVMODECHANGE:
891     case CB_DIR:
892     case LB_DIR:
893     case LB_ADDFILE:
894     case EM_REPLACESEL:
895         if(!*plparam) return 0;
896         *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
897         return (*plparam ? 1 : -1);
898
899     case WM_NCCREATE:
900     case WM_CREATE:
901         {
902             CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
903                                                                 sizeof(*cs) );
904             if (!cs) return -1;
905             *cs = *(CREATESTRUCTA *)*plparam;
906             if (HIWORD(cs->lpszName))
907                 cs->lpszName  = HEAP_strdupWtoA( GetProcessHeap(), 0,
908                                                  (LPCWSTR)cs->lpszName );
909             if (HIWORD(cs->lpszClass))
910                 cs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
911                                                  (LPCWSTR)cs->lpszClass);
912             *plparam = (LPARAM)cs;
913         }
914         return 1;
915     case WM_MDICREATE:
916         {
917             MDICREATESTRUCTA *cs =
918                 (MDICREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
919             if (!cs) return -1;
920             *cs = *(MDICREATESTRUCTA *)*plparam;
921             if (HIWORD(cs->szTitle))
922                 cs->szTitle = HEAP_strdupWtoA( GetProcessHeap(), 0,
923                                                (LPCWSTR)cs->szTitle );
924             if (HIWORD(cs->szClass))
925                 cs->szClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
926                                                (LPCWSTR)cs->szClass );
927             *plparam = (LPARAM)cs;
928         }
929         return 1;
930
931 /* Listbox */
932     case LB_ADDSTRING:
933     case LB_INSERTSTRING:
934     case LB_FINDSTRING:
935     case LB_FINDSTRINGEXACT:
936     case LB_SELECTSTRING:
937         if(!*plparam) return 0;
938         if ( WINPROC_TestLBForStr( hwnd ))
939           *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
940         return (*plparam ? 1 : -1);
941
942     case LB_GETTEXT:                    /* FIXME: fixed sized buffer */
943         { if ( WINPROC_TestLBForStr( hwnd ))
944           { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
945             if (!ptr) return -1;
946             *ptr++ = *plparam;  /* Store previous lParam */
947             *plparam = (LPARAM)ptr;
948           }
949         }
950         return 1;
951
952 /* Combobox */
953     case CB_ADDSTRING:
954     case CB_INSERTSTRING:
955     case CB_FINDSTRING:
956     case CB_FINDSTRINGEXACT:
957     case CB_SELECTSTRING:
958         if(!*plparam) return 0;
959         if ( WINPROC_TestCBForStr( hwnd ))
960           *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
961         return (*plparam ? 1 : -1);
962
963     case CB_GETLBTEXT:          /* FIXME: fixed sized buffer */
964         { if ( WINPROC_TestCBForStr( hwnd ))
965           { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
966             if (!ptr) return -1;
967             *ptr++ = *plparam;  /* Store previous lParam */
968             *plparam = (LPARAM)ptr;
969           }
970         }
971         return 1;
972
973 /* Multiline edit */
974     case EM_GETLINE:
975         { WORD len = (WORD)*plparam;
976           LPARAM *ptr = (LPARAM *) HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(CHAR) );
977           if (!ptr) return -1;
978           *ptr++ = *plparam;  /* Store previous lParam */
979           *((WORD *) ptr) = len;   /* Store the length */
980           *plparam = (LPARAM)ptr;
981         }
982         return 1;
983
984     case WM_CHARTOITEM:
985     case WM_MENUCHAR:
986     case WM_CHAR:
987     case WM_DEADCHAR:
988     case WM_SYSCHAR:
989     case WM_SYSDEADCHAR:
990     case EM_SETPASSWORDCHAR:
991         {
992             WCHAR wch = LOWORD(*pwparam);
993             BYTE ch;
994             WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL );
995             *pwparam = MAKEWPARAM( ch, HIWORD(*pwparam) );
996         }
997         return 0;
998
999     case WM_IME_CHAR:
1000         {
1001             WCHAR wch = LOWORD(*pwparam);
1002             BYTE ch[2];
1003
1004             ch[1] = 0;
1005             WideCharToMultiByte( CP_ACP, 0, &wch, 1, ch, 2, NULL, NULL );
1006             *pwparam = MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(*pwparam) );
1007         }
1008         return 0;
1009
1010     case WM_PAINTCLIPBOARD:
1011     case WM_SIZECLIPBOARD:
1012         FIXME_(msg)("message %s (%04x) needs translation, please report\n",SPY_GetMsgName(msg, hwnd),msg );
1013         return -1;
1014     default:  /* No translation needed */
1015         return 0;
1016     }
1017 }
1018
1019
1020 /**********************************************************************
1021  *           WINPROC_UnmapMsg32WTo32A
1022  *
1023  * Unmap a message that was mapped from Unicode to Ansi.
1024  */
1025 void WINPROC_UnmapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
1026 {
1027     switch(msg)
1028     {
1029     case WM_GETTEXT:
1030     case WM_ASKCBFORMATNAME:
1031         {
1032             LPARAM *ptr = (LPARAM *)lParam - 1;
1033             if (wParam)
1034             {
1035                 if (!MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, wParam ))
1036                     ((LPWSTR)*ptr)[wParam-1] = 0;
1037             }
1038             HeapFree( GetProcessHeap(), 0, ptr );
1039         }
1040         break;
1041
1042     case WM_SETTEXT:
1043     case WM_WININICHANGE:
1044     case WM_DEVMODECHANGE:
1045     case CB_DIR:
1046     case LB_DIR:
1047     case LB_ADDFILE:
1048     case EM_REPLACESEL:
1049         HeapFree( GetProcessHeap(), 0, (void *)lParam );
1050         break;
1051
1052     case WM_NCCREATE:
1053     case WM_CREATE:
1054         {
1055             CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1056             if (HIWORD(cs->lpszName))
1057                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
1058             if (HIWORD(cs->lpszClass))
1059                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
1060             HeapFree( GetProcessHeap(), 0, cs );
1061         }
1062         break;
1063
1064     case WM_MDICREATE:
1065         {
1066             MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1067             if (HIWORD(cs->szTitle))
1068                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
1069             if (HIWORD(cs->szClass))
1070                 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
1071             HeapFree( GetProcessHeap(), 0, cs );
1072         }
1073         break;
1074
1075 /* Listbox */
1076     case LB_ADDSTRING:
1077     case LB_INSERTSTRING:
1078     case LB_FINDSTRING:
1079     case LB_FINDSTRINGEXACT:
1080     case LB_SELECTSTRING:
1081         if ( WINPROC_TestLBForStr( hwnd ))
1082           HeapFree( GetProcessHeap(), 0, (void *)lParam );
1083         break;
1084
1085     case LB_GETTEXT:
1086         if ( WINPROC_TestLBForStr( hwnd ))
1087         {
1088             LPARAM *ptr = (LPARAM *)lParam - 1;
1089             MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, 0x7fffffff );
1090             HeapFree( GetProcessHeap(), 0, ptr );
1091         }
1092         break;
1093
1094 /* Combobox */
1095     case CB_ADDSTRING:
1096     case CB_INSERTSTRING:
1097     case CB_FINDSTRING:
1098     case CB_FINDSTRINGEXACT:
1099     case CB_SELECTSTRING:
1100         if ( WINPROC_TestCBForStr( hwnd ))
1101           HeapFree( GetProcessHeap(), 0, (void *)lParam );
1102         break;
1103
1104     case CB_GETLBTEXT:
1105         if ( WINPROC_TestCBForStr( hwnd ))
1106         {
1107             LPARAM *ptr = (LPARAM *)lParam - 1;
1108             MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, 0x7fffffff );
1109             HeapFree( GetProcessHeap(), 0, ptr );
1110         }
1111         break;
1112
1113 /* Multiline edit */
1114     case EM_GETLINE:
1115         { LPARAM * ptr = (LPARAM *)lParam - 1;  /* get the old lparam */
1116           WORD len = *(WORD *)ptr;
1117           if (len)
1118           {
1119               if (!MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, len ))
1120                   ((LPWSTR)*ptr)[len-1] = 0;
1121           }
1122           HeapFree( GetProcessHeap(), 0, ptr );
1123         }
1124         break;
1125     }
1126 }
1127
1128 static UINT convert_handle_16_to_32(HANDLE16 src, unsigned int flags)
1129 {
1130     HANDLE      dst;
1131     UINT        sz = GlobalSize16(src);
1132     LPSTR       ptr16, ptr32;
1133
1134     if (!(dst = GlobalAlloc(flags, sz)))
1135         return 0;
1136     ptr16 = GlobalLock16(src);
1137     ptr32 = GlobalLock(dst);
1138     if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr32, ptr16, sz);
1139     GlobalUnlock16(src);
1140     GlobalUnlock(dst);
1141
1142     return (UINT)dst;
1143 }
1144
1145 /**********************************************************************
1146  *           WINPROC_MapMsg16To32A
1147  *
1148  * Map a message from 16- to 32-bit Ansi.
1149  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1150  */
1151 INT WINPROC_MapMsg16To32A( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1152                              WPARAM *pwparam32, LPARAM *plparam )
1153 {
1154     *pmsg32 = (UINT)msg16;
1155     *pwparam32 = (WPARAM)wParam16;
1156     switch(msg16)
1157     {
1158     case WM_ACTIVATE:
1159     case WM_CHARTOITEM:
1160     case WM_COMMAND:
1161     case WM_VKEYTOITEM:
1162         *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1163         *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1164         return 0;
1165     case WM_HSCROLL:
1166     case WM_VSCROLL:
1167         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1168         *plparam   = (LPARAM)WIN_Handle32( HIWORD(*plparam) );
1169         return 0;
1170     case WM_CTLCOLOR:
1171         if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
1172         *pmsg32    = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
1173         *pwparam32 = (WPARAM)HDC_32(wParam16);
1174         *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1175         return 0;
1176     case WM_COMPAREITEM:
1177         {
1178             COMPAREITEMSTRUCT16* cis16 = MapSL(*plparam);
1179             COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)
1180                                         HeapAlloc(GetProcessHeap(), 0, sizeof(*cis));
1181             if (!cis) return -1;
1182             cis->CtlType    = cis16->CtlType;
1183             cis->CtlID      = cis16->CtlID;
1184             cis->hwndItem   = WIN_Handle32( cis16->hwndItem );
1185             cis->itemID1    = cis16->itemID1;
1186             cis->itemData1  = cis16->itemData1;
1187             cis->itemID2    = cis16->itemID2;
1188             cis->itemData2  = cis16->itemData2;
1189             cis->dwLocaleId = 0;  /* FIXME */
1190             *plparam = (LPARAM)cis;
1191         }
1192         return 1;
1193     case WM_DELETEITEM:
1194         {
1195             DELETEITEMSTRUCT16* dis16 = MapSL(*plparam);
1196             DELETEITEMSTRUCT *dis = (DELETEITEMSTRUCT *)
1197                                         HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
1198             if (!dis) return -1;
1199             dis->CtlType  = dis16->CtlType;
1200             dis->CtlID    = dis16->CtlID;
1201             dis->hwndItem = WIN_Handle32( dis16->hwndItem );
1202             dis->itemData = dis16->itemData;
1203             *plparam = (LPARAM)dis;
1204         }
1205         return 1;
1206     case WM_MEASUREITEM:
1207         {
1208             MEASUREITEMSTRUCT16* mis16 = MapSL(*plparam);
1209             MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)
1210                                         HeapAlloc(GetProcessHeap(), 0,
1211                                                 sizeof(*mis) + sizeof(LPARAM));
1212             if (!mis) return -1;
1213             mis->CtlType    = mis16->CtlType;
1214             mis->CtlID      = mis16->CtlID;
1215             mis->itemID     = mis16->itemID;
1216             mis->itemWidth  = mis16->itemWidth;
1217             mis->itemHeight = mis16->itemHeight;
1218             mis->itemData   = mis16->itemData;
1219             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
1220             *plparam = (LPARAM)mis;
1221         }
1222         return 1;
1223     case WM_DRAWITEM:
1224         {
1225             DRAWITEMSTRUCT16* dis16 = MapSL(*plparam);
1226             DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT*)HeapAlloc(GetProcessHeap(), 0,
1227                                                                  sizeof(*dis));
1228             if (!dis) return -1;
1229             dis->CtlType    = dis16->CtlType;
1230             dis->CtlID      = dis16->CtlID;
1231             dis->itemID     = dis16->itemID;
1232             dis->itemAction = dis16->itemAction;
1233             dis->itemState  = dis16->itemState;
1234             dis->hwndItem   = (dis->CtlType == ODT_MENU) ? (HWND)HMENU_32(dis16->hwndItem)
1235                                                          : WIN_Handle32( dis16->hwndItem );
1236             dis->hDC        = HDC_32(dis16->hDC);
1237             dis->itemData   = dis16->itemData;
1238             CONV_RECT16TO32( &dis16->rcItem, &dis->rcItem );
1239             *plparam = (LPARAM)dis;
1240         }
1241         return 1;
1242     case WM_GETMINMAXINFO:
1243         {
1244             MINMAXINFO *mmi = (MINMAXINFO *)HeapAlloc( GetProcessHeap(), 0,
1245                                                 sizeof(*mmi) + sizeof(LPARAM));
1246             if (!mmi) return -1;
1247             STRUCT32_MINMAXINFO16to32( MapSL(*plparam), mmi );
1248             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
1249             *plparam = (LPARAM)mmi;
1250         }
1251         return 1;
1252     case WM_GETTEXT:
1253     case WM_SETTEXT:
1254     case WM_WININICHANGE:
1255     case WM_DEVMODECHANGE:
1256     case WM_ASKCBFORMATNAME:
1257         *plparam = (LPARAM)MapSL(*plparam);
1258         return 0;
1259     case WM_MDICREATE:
1260         {
1261             MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1262             MDICREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1263             if (!cs) return -1;
1264             STRUCT32_MDICREATESTRUCT16to32A( cs16, cs );
1265             cs->szTitle = MapSL(cs16->szTitle);
1266             cs->szClass = MapSL(cs16->szClass);
1267             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1268             *plparam = (LPARAM)cs;
1269         }
1270         return 1;
1271     case WM_MDIGETACTIVE:
1272         *plparam = (LPARAM)HeapAlloc( GetProcessHeap(), 0, sizeof(BOOL) );
1273         *(BOOL*)(*plparam) = 0;
1274         return 1;
1275     case WM_MDISETMENU:
1276         if(wParam16==TRUE)
1277            *pmsg32=WM_MDIREFRESHMENU;
1278         *pwparam32 = (WPARAM)HMENU_32(LOWORD(*plparam));
1279         *plparam   = (LPARAM)HMENU_32(HIWORD(*plparam));
1280         return 0;
1281     case WM_MENUCHAR:
1282         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1283         *plparam   = (LPARAM)HMENU_32(HIWORD(*plparam));
1284         return 0;
1285     case WM_MENUSELECT:
1286         if((LOWORD(*plparam) & MF_POPUP) && (LOWORD(*plparam) != 0xFFFF))
1287         {
1288             HMENU hmenu=HMENU_32(HIWORD(*plparam));
1289             UINT Pos=MENU_FindSubMenu( &hmenu, HMENU_32(wParam16));
1290             if(Pos==0xFFFF) Pos=0; /* NO_SELECTED_ITEM */
1291             *pwparam32 = MAKEWPARAM( Pos, LOWORD(*plparam) );
1292         }
1293         else *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1294         *plparam   = (LPARAM)HMENU_32(HIWORD(*plparam));
1295         return 0;
1296     case WM_MDIACTIVATE:
1297         if( *plparam )
1298         {
1299             *pwparam32 = (WPARAM)WIN_Handle32( HIWORD(*plparam) );
1300             *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1301         }
1302         else /* message sent to MDI client */
1303             *pwparam32 = wParam16;
1304         return 0;
1305     case WM_NCCALCSIZE:
1306         {
1307             NCCALCSIZE_PARAMS16 *nc16;
1308             NCCALCSIZE_PARAMS *nc;
1309
1310             nc = (NCCALCSIZE_PARAMS *)HeapAlloc( GetProcessHeap(), 0,
1311                                                 sizeof(*nc) + sizeof(LPARAM) );
1312             if (!nc) return -1;
1313             nc16 = MapSL(*plparam);
1314             CONV_RECT16TO32( &nc16->rgrc[0], &nc->rgrc[0] );
1315             if (wParam16)
1316             {
1317                 nc->lppos = (WINDOWPOS *)HeapAlloc( GetProcessHeap(), 0,
1318                                                       sizeof(*nc->lppos) );
1319                 CONV_RECT16TO32( &nc16->rgrc[1], &nc->rgrc[1] );
1320                 CONV_RECT16TO32( &nc16->rgrc[2], &nc->rgrc[2] );
1321                 if (nc->lppos) STRUCT32_WINDOWPOS16to32( MapSL(nc16->lppos), nc->lppos );
1322             }
1323             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
1324             *plparam = (LPARAM)nc;
1325         }
1326         return 1;
1327     case WM_NCCREATE:
1328     case WM_CREATE:
1329         {
1330             CREATESTRUCT16 *cs16 = MapSL(*plparam);
1331             CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
1332                                                 sizeof(*cs) + sizeof(LPARAM) );
1333             if (!cs) return -1;
1334             STRUCT32_CREATESTRUCT16to32A( cs16, cs );
1335             cs->lpszName  = MapSL(cs16->lpszName);
1336             cs->lpszClass = MapSL(cs16->lpszClass);
1337             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1338             *plparam = (LPARAM)cs;
1339         }
1340         return 1;
1341     case WM_PARENTNOTIFY:
1342         if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
1343         {
1344             *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1345             *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1346         }
1347         return 0;
1348     case WM_WINDOWPOSCHANGING:
1349     case WM_WINDOWPOSCHANGED:
1350         {
1351             WINDOWPOS *wp = (WINDOWPOS *)HeapAlloc( GetProcessHeap(), 0,
1352                                                 sizeof(*wp) + sizeof(LPARAM) );
1353             if (!wp) return -1;
1354             STRUCT32_WINDOWPOS16to32( MapSL(*plparam), wp );
1355             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
1356             *plparam = (LPARAM)wp;
1357         }
1358         return 1;
1359     case WM_GETDLGCODE:
1360         if (*plparam)
1361         {
1362             LPMSG16 msg16 = MapSL(*plparam);
1363             LPMSG msg32 = (LPMSG)HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1364
1365             if (!msg32) return -1;
1366             msg32->hwnd = WIN_Handle32( msg16->hwnd );
1367             msg32->lParam = msg16->lParam;
1368             msg32->time = msg16->time;
1369             CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1370             /* this is right, right? */
1371             if (WINPROC_MapMsg16To32A( msg32->hwnd, msg16->message,msg16->wParam,
1372                                      &msg32->message,&msg32->wParam,
1373                                      &msg32->lParam)<0) {
1374                 HeapFree( GetProcessHeap(), 0, msg32 );
1375                 return -1;
1376             }
1377             *plparam = (LPARAM)msg32;
1378             return 1;
1379         }
1380         else return 0;
1381     case WM_NOTIFY:
1382         *plparam = (LPARAM)MapSL(*plparam);
1383         return 0;
1384     case WM_ACTIVATEAPP:
1385         /* We need this when SetActiveWindow sends a Sendmessage16() to
1386          * a 32bit window. Might be superflous with 32bit interprocess
1387          * message queues. */
1388         if (*plparam) *plparam = HTASK_32( *plparam );
1389         return 0;
1390     case WM_NEXTMENU:
1391         {
1392             MDINEXTMENU *next = HeapAlloc( GetProcessHeap(), 0, sizeof(*next) );
1393             if (!next) return -1;
1394             next->hmenuIn = (HMENU)*plparam;
1395             next->hmenuNext = 0;
1396             next->hwndNext = 0;
1397             *plparam = (LPARAM)next;
1398             return 1;
1399         }
1400     case WM_PAINTCLIPBOARD:
1401     case WM_SIZECLIPBOARD:
1402         FIXME_(msg)("message %04x needs translation\n",msg16 );
1403         return -1;
1404     case WM_DDE_INITIATE:
1405     case WM_DDE_TERMINATE:
1406     case WM_DDE_UNADVISE:
1407     case WM_DDE_REQUEST:
1408         *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1409         return 0;
1410     case WM_DDE_ADVISE:
1411     case WM_DDE_DATA:
1412     case WM_DDE_POKE:
1413         {
1414             HANDLE16    lo16;
1415             ATOM        hi;
1416             UINT lo32 = 0;
1417
1418             *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1419             lo16 = LOWORD(*plparam);
1420             hi = HIWORD(*plparam);
1421             if (lo16 && !(lo32 = convert_handle_16_to_32(lo16, GMEM_DDESHARE)))
1422                 return -1;
1423             *plparam = PackDDElParam(msg16, lo32, hi);
1424         }
1425         return 0; /* FIXME don't know how to free allocated memory (handle)  !! */
1426     case WM_DDE_ACK:
1427         {
1428             UINT        lo, hi;
1429             int         flag = 0;
1430             char        buf[2];
1431
1432             *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1433
1434             lo = LOWORD(*plparam);
1435             hi = HIWORD(*plparam);
1436
1437             if (GlobalGetAtomNameA(hi, buf, 2) > 0) flag |= 1;
1438             if (GlobalSize16(hi) != 0) flag |= 2;
1439             switch (flag)
1440             {
1441             case 0:
1442                 if (hi)
1443                 {
1444                     MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1445                     hi = 0;
1446                 }
1447                 break;
1448             case 1:
1449                 break; /* atom, nothing to do */
1450             case 3:
1451                 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
1452                 /* fall thru */
1453             case 2:
1454                 hi = convert_handle_16_to_32(hi, GMEM_DDESHARE);
1455                 break;
1456             }
1457             *plparam = PackDDElParam(WM_DDE_ACK, lo, hi);
1458         }
1459         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1460     case WM_DDE_EXECUTE:
1461         *plparam = convert_handle_16_to_32(*plparam, GMEM_DDESHARE);
1462         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1463     default:  /* No translation needed */
1464         return 0;
1465     }
1466 }
1467
1468
1469 /**********************************************************************
1470  *           WINPROC_UnmapMsg16To32A
1471  *
1472  * Unmap a message that was mapped from 16- to 32-bit Ansi.
1473  */
1474 LRESULT WINPROC_UnmapMsg16To32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1475                                  LRESULT result )
1476 {
1477     switch(msg)
1478     {
1479     case WM_COMPAREITEM:
1480     case WM_DELETEITEM:
1481     case WM_DRAWITEM:
1482         HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
1483         break;
1484     case WM_MEASUREITEM:
1485         {
1486             MEASUREITEMSTRUCT16 *mis16;
1487             MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam;
1488             lParam = *(LPARAM *)(mis + 1);
1489             mis16 = MapSL(lParam);
1490             mis16->itemWidth  = (UINT16)mis->itemWidth;
1491             mis16->itemHeight = (UINT16)mis->itemHeight;
1492             HeapFree( GetProcessHeap(), 0, mis );
1493         }
1494         break;
1495     case WM_GETMINMAXINFO:
1496         {
1497             MINMAXINFO *mmi = (MINMAXINFO *)lParam;
1498             lParam = *(LPARAM *)(mmi + 1);
1499             STRUCT32_MINMAXINFO32to16( mmi, MapSL(lParam));
1500             HeapFree( GetProcessHeap(), 0, mmi );
1501         }
1502         break;
1503     case WM_MDICREATE:
1504         {
1505             MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1506             lParam = *(LPARAM *)(cs + 1);
1507             STRUCT32_MDICREATESTRUCT32Ato16( cs, MapSL(lParam) );
1508             HeapFree( GetProcessHeap(), 0, cs );
1509         }
1510         break;
1511     case WM_MDIGETACTIVE:
1512         result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL *)lParam) );
1513         HeapFree( GetProcessHeap(), 0, (BOOL *)lParam );
1514         break;
1515     case WM_NCCALCSIZE:
1516         {
1517             NCCALCSIZE_PARAMS16 *nc16;
1518             NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lParam;
1519             lParam = *(LPARAM *)(nc + 1);
1520             nc16 = MapSL(lParam);
1521             CONV_RECT32TO16( &nc->rgrc[0], &nc16->rgrc[0] );
1522             if (wParam)
1523             {
1524                 CONV_RECT32TO16( &nc->rgrc[1], &nc16->rgrc[1] );
1525                 CONV_RECT32TO16( &nc->rgrc[2], &nc16->rgrc[2] );
1526                 if (nc->lppos)
1527                 {
1528                     STRUCT32_WINDOWPOS32to16( nc->lppos, MapSL(nc16->lppos));
1529                     HeapFree( GetProcessHeap(), 0, nc->lppos );
1530                 }
1531             }
1532             HeapFree( GetProcessHeap(), 0, nc );
1533         }
1534         break;
1535     case WM_NCCREATE:
1536     case WM_CREATE:
1537         {
1538             CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1539             lParam = *(LPARAM *)(cs + 1);
1540             STRUCT32_CREATESTRUCT32Ato16( cs, MapSL(lParam) );
1541             HeapFree( GetProcessHeap(), 0, cs );
1542         }
1543         break;
1544     case WM_WINDOWPOSCHANGING:
1545     case WM_WINDOWPOSCHANGED:
1546         {
1547             WINDOWPOS *wp = (WINDOWPOS *)lParam;
1548             lParam = *(LPARAM *)(wp + 1);
1549             STRUCT32_WINDOWPOS32to16(wp, MapSL(lParam));
1550             HeapFree( GetProcessHeap(), 0, wp );
1551         }
1552         break;
1553     case WM_GETDLGCODE:
1554         if (lParam)
1555         {
1556             LPMSG msg32 = (LPMSG)lParam;
1557
1558             WINPROC_UnmapMsg16To32A( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1559                                      result);
1560             HeapFree( GetProcessHeap(), 0, msg32 );
1561         }
1562         break;
1563     case WM_NEXTMENU:
1564         {
1565             MDINEXTMENU *next = (MDINEXTMENU *)lParam;
1566             result = MAKELONG( HMENU_16(next->hmenuNext), HWND_16(next->hwndNext) );
1567             HeapFree( GetProcessHeap(), 0, next );
1568         }
1569         break;
1570     }
1571     return result;
1572 }
1573
1574
1575 /**********************************************************************
1576  *           WINPROC_MapMsg16To32W
1577  *
1578  * Map a message from 16- to 32-bit Unicode.
1579  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1580  */
1581 INT WINPROC_MapMsg16To32W( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1582                            WPARAM *pwparam32, LPARAM *plparam )
1583 {
1584     BYTE ch;
1585     WCHAR wch;
1586
1587     *pmsg32=(UINT)msg16;
1588     *pwparam32 = (WPARAM)wParam16;
1589     switch(msg16)
1590     {
1591     case WM_GETTEXT:
1592     case WM_SETTEXT:
1593     case WM_WININICHANGE:
1594     case WM_DEVMODECHANGE:
1595     case WM_ASKCBFORMATNAME:
1596         *plparam = (LPARAM)MapSL(*plparam);
1597         return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, pwparam32, plparam );
1598     case WM_GETTEXTLENGTH:
1599     case CB_GETLBTEXTLEN:
1600     case LB_GETTEXTLEN:
1601         return 1;  /* need to map result */
1602     case WM_NCCREATE:
1603     case WM_CREATE:
1604         {
1605             CREATESTRUCT16 *cs16 = MapSL(*plparam);
1606             CREATESTRUCTW *cs = (CREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
1607                                                 sizeof(*cs) + sizeof(LPARAM) );
1608             if (!cs) return -1;
1609             STRUCT32_CREATESTRUCT16to32A( cs16, (CREATESTRUCTA *)cs );
1610             cs->lpszName  = map_str_16_to_32W(cs16->lpszName);
1611             cs->lpszClass = map_str_16_to_32W(cs16->lpszClass);
1612             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1613             *plparam = (LPARAM)cs;
1614         }
1615         return 1;
1616     case WM_MDICREATE:
1617         {
1618             MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1619             MDICREATESTRUCTW *cs =
1620                 (MDICREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
1621                                                 sizeof(*cs) + sizeof(LPARAM) );
1622             if (!cs) return -1;
1623             STRUCT32_MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCTA *)cs );
1624             cs->szTitle = map_str_16_to_32W(cs16->szTitle);
1625             cs->szClass = map_str_16_to_32W(cs16->szClass);
1626             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
1627             *plparam = (LPARAM)cs;
1628         }
1629         return 1;
1630     case WM_GETDLGCODE:
1631         if (*plparam)
1632         {
1633             LPMSG16 msg16 = MapSL(*plparam);
1634             LPMSG msg32 = (LPMSG)HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1635
1636             if (!msg32) return -1;
1637             msg32->hwnd = WIN_Handle32( msg16->hwnd );
1638             msg32->lParam = msg16->lParam;
1639             msg32->time = msg16->time;
1640             CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1641             /* this is right, right? */
1642             if (WINPROC_MapMsg16To32W(hwnd, msg16->message,msg16->wParam,
1643                                      &msg32->message,&msg32->wParam,
1644                                      &msg32->lParam)<0) {
1645                 HeapFree( GetProcessHeap(), 0, msg32 );
1646                 return -1;
1647             }
1648             *plparam = (LPARAM)msg32;
1649             return 1;
1650         }
1651         else return 0;
1652
1653     case WM_CHARTOITEM:
1654         ch = wParam16;
1655         MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1656         *pwparam32 = MAKEWPARAM( wch, HIWORD(*plparam) );
1657         *plparam   = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1658         return 0;
1659     case WM_MENUCHAR:
1660         ch = wParam16;
1661         MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1662         *pwparam32 = MAKEWPARAM( wch, LOWORD(*plparam) );
1663         *plparam   = (LPARAM)HMENU_32(HIWORD(*plparam));
1664         return 0;
1665     case WM_CHAR:
1666     case WM_DEADCHAR:
1667     case WM_SYSCHAR:
1668     case WM_SYSDEADCHAR:
1669         ch = wParam16;
1670         MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1671         *pwparam32 = wch;
1672         return 0;
1673     case WM_IME_CHAR:
1674         {
1675             char ch[2];
1676             ch[0] = (wParam16 >> 8);
1677             ch[1] = wParam16 & 0xff;
1678             MultiByteToWideChar(CP_ACP, 0, ch, 2, &wch, 1);
1679             *pwparam32 = wch;
1680         }
1681         return 0;
1682
1683     default:  /* No Unicode translation needed */
1684         return WINPROC_MapMsg16To32A( hwnd, msg16, wParam16, pmsg32,
1685                                       pwparam32, plparam );
1686     }
1687 }
1688
1689
1690 /**********************************************************************
1691  *           WINPROC_UnmapMsg16To32W
1692  *
1693  * Unmap a message that was mapped from 16- to 32-bit Unicode.
1694  */
1695 LRESULT WINPROC_UnmapMsg16To32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1696                                  LRESULT result )
1697 {
1698     switch(msg)
1699     {
1700     case WM_GETTEXT:
1701     case WM_SETTEXT:
1702     case WM_GETTEXTLENGTH:
1703     case CB_GETLBTEXTLEN:
1704     case LB_GETTEXTLEN:
1705     case WM_ASKCBFORMATNAME:
1706         return WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result );
1707     case WM_NCCREATE:
1708     case WM_CREATE:
1709         {
1710             CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
1711             lParam = *(LPARAM *)(cs + 1);
1712             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs, MapSL(lParam) );
1713             unmap_str_16_to_32W( cs->lpszName );
1714             unmap_str_16_to_32W( cs->lpszClass );
1715             HeapFree( GetProcessHeap(), 0, cs );
1716         }
1717         break;
1718     case WM_MDICREATE:
1719         {
1720             MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
1721             lParam = *(LPARAM *)(cs + 1);
1722             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs, MapSL(lParam) );
1723             unmap_str_16_to_32W( cs->szTitle );
1724             unmap_str_16_to_32W( cs->szClass );
1725             HeapFree( GetProcessHeap(), 0, cs );
1726         }
1727         break;
1728     case WM_GETDLGCODE:
1729         if (lParam)
1730         {
1731             LPMSG msg32 = (LPMSG)lParam;
1732
1733             WINPROC_UnmapMsg16To32W( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1734                                      result);
1735             HeapFree( GetProcessHeap(), 0, msg32 );
1736         }
1737         break;
1738     default:
1739         return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1740     }
1741     return result;
1742 }
1743
1744 static HANDLE16 convert_handle_32_to_16(UINT src, unsigned int flags)
1745 {
1746     HANDLE16    dst;
1747     UINT        sz = GlobalSize((HANDLE)src);
1748     LPSTR       ptr16, ptr32;
1749
1750     if (!(dst = GlobalAlloc16(flags, sz)))
1751         return 0;
1752     ptr32 = GlobalLock((HANDLE)src);
1753     ptr16 = GlobalLock16(dst);
1754     if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr16, ptr32, sz);
1755     GlobalUnlock((HANDLE)src);
1756     GlobalUnlock16(dst);
1757
1758     return dst;
1759 }
1760
1761
1762 /**********************************************************************
1763  *           WINPROC_MapMsg32ATo16
1764  *
1765  * Map a message from 32-bit Ansi to 16-bit.
1766  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1767  */
1768 INT WINPROC_MapMsg32ATo16( HWND hwnd, UINT msg32, WPARAM wParam32,
1769                              UINT16 *pmsg16, WPARAM16 *pwparam16,
1770                              LPARAM *plparam )
1771 {
1772     *pmsg16 = (UINT16)msg32;
1773     *pwparam16 = (WPARAM16)LOWORD(wParam32);
1774     switch(msg32)
1775     {
1776     case BM_GETCHECK:
1777     case BM_SETCHECK:
1778     case BM_GETSTATE:
1779     case BM_SETSTATE:
1780     case BM_SETSTYLE:
1781         *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK);
1782         return 0;
1783
1784     case EM_GETSEL:
1785     case EM_GETRECT:
1786     case EM_SETRECT:
1787     case EM_SETRECTNP:
1788     case EM_SCROLL:
1789     case EM_LINESCROLL:
1790     case EM_SCROLLCARET:
1791     case EM_GETMODIFY:
1792     case EM_SETMODIFY:
1793     case EM_GETLINECOUNT:
1794     case EM_LINEINDEX:
1795     case EM_SETHANDLE:
1796     case EM_GETHANDLE:
1797     case EM_GETTHUMB:
1798     case EM_LINELENGTH:
1799     case EM_REPLACESEL:
1800     case EM_GETLINE:
1801     case EM_LIMITTEXT:
1802     case EM_CANUNDO:
1803     case EM_UNDO:
1804     case EM_FMTLINES:
1805     case EM_LINEFROMCHAR:
1806     case EM_SETTABSTOPS:
1807     case EM_SETPASSWORDCHAR:
1808     case EM_EMPTYUNDOBUFFER:
1809     case EM_GETFIRSTVISIBLELINE:
1810     case EM_SETREADONLY:
1811     case EM_SETWORDBREAKPROC:
1812     case EM_GETWORDBREAKPROC:
1813     case EM_GETPASSWORDCHAR:
1814         *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL);
1815         return 0;
1816
1817     case LB_CARETOFF:
1818     case LB_CARETON:
1819     case LB_DELETESTRING:
1820     case LB_GETANCHORINDEX:
1821     case LB_GETCARETINDEX:
1822     case LB_GETCOUNT:
1823     case LB_GETCURSEL:
1824     case LB_GETHORIZONTALEXTENT:
1825     case LB_GETITEMDATA:
1826     case LB_GETITEMHEIGHT:
1827     case LB_GETSEL:
1828     case LB_GETSELCOUNT:
1829     case LB_GETTEXTLEN:
1830     case LB_GETTOPINDEX:
1831     case LB_RESETCONTENT:
1832     case LB_SELITEMRANGE:
1833     case LB_SELITEMRANGEEX:
1834     case LB_SETANCHORINDEX:
1835     case LB_SETCARETINDEX:
1836     case LB_SETCOLUMNWIDTH:
1837     case LB_SETCURSEL:
1838     case LB_SETHORIZONTALEXTENT:
1839     case LB_SETITEMDATA:
1840     case LB_SETITEMHEIGHT:
1841     case LB_SETSEL:
1842     case LB_SETTOPINDEX:
1843         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1844         return 0;
1845     case CB_DELETESTRING:
1846     case CB_GETCOUNT:
1847     case CB_GETLBTEXTLEN:
1848     case CB_LIMITTEXT:
1849     case CB_RESETCONTENT:
1850     case CB_SETEDITSEL:
1851     case CB_GETCURSEL:
1852     case CB_SETCURSEL:
1853     case CB_SHOWDROPDOWN:
1854     case CB_SETITEMDATA:
1855     case CB_SETITEMHEIGHT:
1856     case CB_GETITEMHEIGHT:
1857     case CB_SETEXTENDEDUI:
1858     case CB_GETEXTENDEDUI:
1859     case CB_GETDROPPEDSTATE:
1860         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1861         return 0;
1862     case CB_GETEDITSEL:
1863         *pmsg16 = CB_GETEDITSEL16;
1864         return 1;
1865
1866     case LB_ADDSTRING:
1867     case LB_FINDSTRING:
1868     case LB_FINDSTRINGEXACT:
1869     case LB_INSERTSTRING:
1870     case LB_SELECTSTRING:
1871     case LB_DIR:
1872     case LB_ADDFILE:
1873         *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1874         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1875         return 1;
1876
1877     case CB_ADDSTRING:
1878     case CB_FINDSTRING:
1879     case CB_FINDSTRINGEXACT:
1880     case CB_INSERTSTRING:
1881     case CB_SELECTSTRING:
1882     case CB_DIR:
1883         *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1884         *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1885         return 1;
1886
1887     case LB_GETITEMRECT:
1888         {
1889             RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1890             if (!rect) return -1;
1891             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
1892             *plparam = MapLS( rect );
1893         }
1894         *pmsg16 = LB_GETITEMRECT16;
1895         return 1;
1896     case LB_GETSELITEMS:
1897         {
1898             LPINT16 items;
1899             *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1900             if (!(items = HeapAlloc( GetProcessHeap(), 0,
1901                                      *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
1902             *((LPARAM *)items)++ = *plparam;  /* Store the previous lParam */
1903             *plparam = MapLS( items );
1904         }
1905         *pmsg16 = LB_GETSELITEMS16;
1906         return 1;
1907     case LB_SETTABSTOPS:
1908         if (wParam32)
1909         {
1910             INT i;
1911             LPINT16 stops;
1912             *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1913             if (!(stops = HeapAlloc( GetProcessHeap(), 0,
1914                                      *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
1915             for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT)*plparam+i);
1916             *plparam = MapLS( stops );
1917             return 1;
1918         }
1919         *pmsg16 = LB_SETTABSTOPS16;
1920         return 0;
1921
1922     case CB_GETDROPPEDCONTROLRECT:
1923         {
1924             RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1925             if (!rect) return -1;
1926             *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
1927             *plparam = (LPARAM)MapLS(rect);
1928         }
1929         *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
1930         return 1;
1931
1932     case LB_GETTEXT:
1933         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1934         *pmsg16 = LB_GETTEXT16;
1935         return 1;
1936
1937     case CB_GETLBTEXT:
1938         *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1939         *pmsg16 = CB_GETLBTEXT16;
1940         return 1;
1941
1942     case EM_SETSEL:
1943         *pwparam16 = 0;
1944         *plparam = MAKELONG( (INT16)(INT)wParam32, (INT16)*plparam );
1945         *pmsg16 = EM_SETSEL16;
1946         return 0;
1947
1948     case WM_ACTIVATE:
1949     case WM_CHARTOITEM:
1950     case WM_COMMAND:
1951     case WM_VKEYTOITEM:
1952         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
1953         return 0;
1954     case WM_HSCROLL:
1955     case WM_VSCROLL:
1956         *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
1957         return 0;
1958     case WM_CTLCOLORMSGBOX:
1959     case WM_CTLCOLOREDIT:
1960     case WM_CTLCOLORLISTBOX:
1961     case WM_CTLCOLORBTN:
1962     case WM_CTLCOLORDLG:
1963     case WM_CTLCOLORSCROLLBAR:
1964     case WM_CTLCOLORSTATIC:
1965         *pmsg16  = WM_CTLCOLOR;
1966         *plparam = MAKELPARAM( (HWND16)*plparam,
1967                                (WORD)msg32 - WM_CTLCOLORMSGBOX );
1968         return 0;
1969     case WM_COMPAREITEM:
1970         {
1971             COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)*plparam;
1972             COMPAREITEMSTRUCT16 *cis = HeapAlloc( GetProcessHeap(), 0, sizeof(COMPAREITEMSTRUCT16));
1973             if (!cis) return -1;
1974             cis->CtlType    = (UINT16)cis32->CtlType;
1975             cis->CtlID      = (UINT16)cis32->CtlID;
1976             cis->hwndItem   = HWND_16( cis32->hwndItem );
1977             cis->itemID1    = (UINT16)cis32->itemID1;
1978             cis->itemData1  = cis32->itemData1;
1979             cis->itemID2    = (UINT16)cis32->itemID2;
1980             cis->itemData2  = cis32->itemData2;
1981             *plparam = MapLS( cis );
1982         }
1983         return 1;
1984     case WM_DELETEITEM:
1985         {
1986             DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)*plparam;
1987             DELETEITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DELETEITEMSTRUCT16) );
1988             if (!dis) return -1;
1989             dis->CtlType  = (UINT16)dis32->CtlType;
1990             dis->CtlID    = (UINT16)dis32->CtlID;
1991             dis->itemID   = (UINT16)dis32->itemID;
1992             dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem)
1993                                                        : HWND_16( dis32->hwndItem );
1994             dis->itemData = dis32->itemData;
1995             *plparam = MapLS( dis );
1996         }
1997         return 1;
1998     case WM_DRAWITEM:
1999         {
2000             DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)*plparam;
2001             DRAWITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DRAWITEMSTRUCT16) );
2002             if (!dis) return -1;
2003             dis->CtlType    = (UINT16)dis32->CtlType;
2004             dis->CtlID      = (UINT16)dis32->CtlID;
2005             dis->itemID     = (UINT16)dis32->itemID;
2006             dis->itemAction = (UINT16)dis32->itemAction;
2007             dis->itemState  = (UINT16)dis32->itemState;
2008             dis->hwndItem   = HWND_16( dis32->hwndItem );
2009             dis->hDC        = HDC_16(dis32->hDC);
2010             dis->itemData   = dis32->itemData;
2011             CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
2012             *plparam = MapLS( dis );
2013         }
2014         return 1;
2015     case WM_MEASUREITEM:
2016         {
2017             MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)*plparam;
2018             MEASUREITEMSTRUCT16 *mis = HeapAlloc( GetProcessHeap(), 0, sizeof(*mis)+sizeof(LPARAM));
2019             if (!mis) return -1;
2020             mis->CtlType    = (UINT16)mis32->CtlType;
2021             mis->CtlID      = (UINT16)mis32->CtlID;
2022             mis->itemID     = (UINT16)mis32->itemID;
2023             mis->itemWidth  = (UINT16)mis32->itemWidth;
2024             mis->itemHeight = (UINT16)mis32->itemHeight;
2025             mis->itemData   = mis32->itemData;
2026             *(LPARAM *)(mis + 1) = *plparam;  /* Store the previous lParam */
2027             *plparam = MapLS( mis );
2028         }
2029         return 1;
2030     case WM_GETMINMAXINFO:
2031         {
2032             MINMAXINFO16 *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM) );
2033             if (!mmi) return -1;
2034             STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)*plparam, mmi );
2035             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
2036             *plparam = MapLS( mmi );
2037         }
2038         return 1;
2039     case WM_GETTEXT:
2040     case WM_ASKCBFORMATNAME:
2041         {
2042             LPSTR str;
2043             *pwparam16 = (WPARAM16)min( wParam32, 0xff80 ); /* Must be < 64K */
2044             if (!(str = HeapAlloc( GetProcessHeap(), 0, *pwparam16 + sizeof(LPARAM)))) return -1;
2045             *((LPARAM *)str)++ = *plparam;  /* Store the previous lParam */
2046             *plparam = MapLS( str );
2047         }
2048         return 1;
2049     case WM_MDICREATE:
2050         {
2051             MDICREATESTRUCT16 *cs;
2052             MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)*plparam;
2053
2054             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2055             STRUCT32_MDICREATESTRUCT32Ato16( cs32, cs );
2056             cs->szTitle = MapLS( cs32->szTitle );
2057             cs->szClass = MapLS( cs32->szClass );
2058             *plparam = MapLS( cs );
2059         }
2060         return 1;
2061     case WM_MDIGETACTIVE:
2062         return 1;
2063     case WM_MDISETMENU:
2064         *plparam   = MAKELPARAM( (HMENU16)LOWORD(wParam32),
2065                                  (HMENU16)LOWORD(*plparam) );
2066         *pwparam16 = (*plparam == 0);
2067         return 0;
2068     case WM_MENUSELECT:
2069         if(HIWORD(wParam32) & MF_POPUP)
2070         {
2071             HMENU hmenu;
2072             if (((UINT)HIWORD(wParam32) != 0xFFFF) || (*plparam))
2073             {
2074                 if((hmenu = GetSubMenu((HMENU)*plparam, *pwparam16)))
2075                     *pwparam16=HMENU_16(hmenu);
2076             }
2077         }
2078         /* fall through */
2079     case WM_MENUCHAR:
2080         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2081         return 0;
2082     case WM_MDIACTIVATE:
2083         if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
2084         {
2085             *pwparam16 = ((HWND)*plparam == hwnd);
2086             *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
2087                                    (HWND16)LOWORD(wParam32) );
2088         }
2089         else
2090         {
2091             *pwparam16 = HWND_16( (HWND)wParam32 );
2092             *plparam = 0;
2093         }
2094         return 0;
2095     case WM_NCCALCSIZE:
2096         {
2097             NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)*plparam;
2098             NCCALCSIZE_PARAMS16 *nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM));
2099             if (!nc) return -1;
2100
2101             CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
2102             if (wParam32)
2103             {
2104                 WINDOWPOS16 *wp;
2105                 CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
2106                 CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
2107                 if (!(wp = HeapAlloc( GetProcessHeap(), 0, sizeof(WINDOWPOS16) )))
2108                 {
2109                     HeapFree( GetProcessHeap(), 0, nc );
2110                     return -1;
2111                 }
2112                 STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
2113                 nc->lppos = MapLS( wp );
2114             }
2115             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
2116             *plparam = MapLS( nc );
2117         }
2118         return 1;
2119     case WM_NCCREATE:
2120     case WM_CREATE:
2121         {
2122             CREATESTRUCT16 *cs;
2123             CREATESTRUCTA *cs32 = (CREATESTRUCTA *)*plparam;
2124
2125             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2126             STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
2127             cs->lpszName  = MapLS( cs32->lpszName );
2128             cs->lpszClass = MapLS( cs32->lpszClass );
2129             *plparam = MapLS( cs );
2130         }
2131         return 1;
2132     case WM_PARENTNOTIFY:
2133         if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
2134             *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
2135         /* else nothing to do */
2136         return 0;
2137     case WM_NOTIFY:
2138         *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
2139         return 1;
2140     case WM_SETTEXT:
2141     case WM_WININICHANGE:
2142     case WM_DEVMODECHANGE:
2143         *plparam = MapLS( (LPSTR)*plparam );
2144         return 1;
2145     case WM_WINDOWPOSCHANGING:
2146     case WM_WINDOWPOSCHANGED:
2147         {
2148             WINDOWPOS16 *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
2149             if (!wp) return -1;
2150             STRUCT32_WINDOWPOS32to16( (WINDOWPOS *)*plparam, wp );
2151             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
2152             *plparam = MapLS( wp );
2153         }
2154         return 1;
2155     case WM_GETDLGCODE:
2156          if (*plparam) {
2157             LPMSG msg32 = (LPMSG) *plparam;
2158             LPMSG16 msg16 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG16) );
2159
2160             if (!msg16) return -1;
2161             msg16->hwnd = HWND_16( msg32->hwnd );
2162             msg16->lParam = msg32->lParam;
2163             msg16->time = msg32->time;
2164             CONV_POINT32TO16(&msg32->pt,&msg16->pt);
2165             /* this is right, right? */
2166             if (WINPROC_MapMsg32ATo16(msg32->hwnd,msg32->message,msg32->wParam,
2167                          &msg16->message,&msg16->wParam, &msg16->lParam)<0)
2168             {
2169                 HeapFree( GetProcessHeap(), 0, msg16 );
2170                 return -1;
2171             }
2172             *plparam = MapLS( msg16 );
2173             return 1;
2174         }
2175         return 0;
2176
2177     case WM_ACTIVATEAPP:
2178         if (*plparam) *plparam = HTASK_16( (HANDLE)*plparam );
2179         return 0;
2180     case WM_NEXTMENU:
2181         {
2182             MDINEXTMENU *next = (MDINEXTMENU *)*plparam;
2183             *plparam = (LPARAM)next->hmenuIn;
2184             return 1;
2185         }
2186     case WM_PAINTCLIPBOARD:
2187     case WM_SIZECLIPBOARD:
2188         FIXME_(msg)("message %04x needs translation\n", msg32 );
2189         return -1;
2190     /* following messages should not be sent to 16-bit apps */
2191     case WM_SIZING:
2192     case WM_MOVING:
2193     case WM_CAPTURECHANGED:
2194     case WM_STYLECHANGING:
2195     case WM_STYLECHANGED:
2196         return -1;
2197     case WM_DDE_INITIATE:
2198     case WM_DDE_TERMINATE:
2199     case WM_DDE_UNADVISE:
2200     case WM_DDE_REQUEST:
2201         *pwparam16 = HWND_16((HWND)wParam32);
2202         return 0;
2203     case WM_DDE_ADVISE:
2204     case WM_DDE_DATA:
2205     case WM_DDE_POKE:
2206         {
2207             UINT lo32, hi;
2208             HANDLE16    lo16 = 0;
2209
2210             *pwparam16 = HWND_16((HWND)wParam32);
2211             UnpackDDElParam(msg32, *plparam, &lo32, &hi);
2212             if (lo32 && !(lo16 = convert_handle_32_to_16(lo32, GMEM_DDESHARE)))
2213                 return -1;
2214             *plparam = MAKELPARAM(lo16, hi);
2215         }
2216         return 0; /* FIXME don't know how to free allocated memory (handle)  !! */
2217     case WM_DDE_ACK:
2218         {
2219             UINT        lo, hi;
2220             int         flag = 0;
2221             char        buf[2];
2222
2223             *pwparam16 = HWND_16((HWND)wParam32);
2224
2225             UnpackDDElParam(msg32, *plparam, &lo, &hi);
2226
2227             if (GlobalGetAtomNameA((ATOM)hi, buf, sizeof(buf)) > 0) flag |= 1;
2228             if (GlobalSize((HANDLE)hi) != 0) flag |= 2;
2229             switch (flag)
2230             {
2231             case 0:
2232                 if (hi)
2233                 {
2234                     MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
2235                     hi = 0;
2236                 }
2237                 break;
2238             case 1:
2239                 break; /* atom, nothing to do */
2240             case 3:
2241                 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
2242                 /* fall thru */
2243             case 2:
2244                 hi = convert_handle_32_to_16(hi, GMEM_DDESHARE);
2245                 break;
2246             }
2247             *plparam = MAKELPARAM(lo, hi);
2248         }
2249         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2250     case WM_DDE_EXECUTE:
2251         *plparam = convert_handle_32_to_16(*plparam, GMEM_DDESHARE);
2252         return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2253     default:  /* No translation needed */
2254         return 0;
2255     }
2256 }
2257
2258
2259 /**********************************************************************
2260  *           WINPROC_UnmapMsg32ATo16
2261  *
2262  * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
2263  */
2264 void WINPROC_UnmapMsg32ATo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2265                               MSGPARAM16* p16 )
2266 {
2267     switch(msg)
2268     {
2269     case LB_ADDFILE:
2270     case LB_ADDSTRING:
2271     case LB_DIR:
2272     case LB_FINDSTRING:
2273     case LB_FINDSTRINGEXACT:
2274     case LB_INSERTSTRING:
2275     case LB_SELECTSTRING:
2276     case LB_GETTEXT:
2277     case CB_ADDSTRING:
2278     case CB_FINDSTRING:
2279     case CB_FINDSTRINGEXACT:
2280     case CB_INSERTSTRING:
2281     case CB_SELECTSTRING:
2282     case CB_DIR:
2283     case CB_GETLBTEXT:
2284     case WM_SETTEXT:
2285     case WM_WININICHANGE:
2286     case WM_DEVMODECHANGE:
2287         UnMapLS( (SEGPTR)p16->lParam );
2288         break;
2289     case LB_SETTABSTOPS:
2290     case WM_COMPAREITEM:
2291     case WM_DELETEITEM:
2292     case WM_DRAWITEM:
2293         {
2294             void *ptr = MapSL( p16->lParam );
2295             UnMapLS( p16->lParam );
2296             HeapFree( GetProcessHeap(), 0, ptr );
2297         }
2298         break;
2299     case CB_GETDROPPEDCONTROLRECT:
2300     case LB_GETITEMRECT:
2301         {
2302             RECT16 *rect = MapSL(p16->lParam);
2303             UnMapLS( p16->lParam );
2304             p16->lParam = *(LPARAM *)(rect + 1);
2305             CONV_RECT16TO32( rect, (RECT *)(p16->lParam));
2306             HeapFree( GetProcessHeap(), 0, rect );
2307         }
2308         break;
2309     case LB_GETSELITEMS:
2310         {
2311             INT i;
2312             LPINT16 items = MapSL(p16->lParam);
2313             UnMapLS( p16->lParam );
2314             p16->lParam = *((LPARAM *)items - 1);
2315             for (i = 0; i < p16->wParam; i++) *((LPINT)(p16->lParam) + i) = items[i];
2316             HeapFree( GetProcessHeap(), 0, (LPARAM *)items - 1 );
2317         }
2318         break;
2319
2320     case CB_GETEDITSEL:
2321         if( wParam )
2322             *((PUINT)(wParam)) = LOWORD(p16->lResult);
2323         if( lParam )
2324             *((PUINT)(lParam)) = HIWORD(p16->lResult);  /* FIXME: substract 1? */
2325         break;
2326
2327     case WM_MEASUREITEM:
2328         {
2329             MEASUREITEMSTRUCT16 *mis = MapSL(p16->lParam);
2330             MEASUREITEMSTRUCT *mis32 = *(MEASUREITEMSTRUCT **)(mis + 1);
2331             mis32->itemWidth  = mis->itemWidth;
2332             mis32->itemHeight = mis->itemHeight;
2333             UnMapLS( p16->lParam );
2334             HeapFree( GetProcessHeap(), 0, mis );
2335         }
2336         break;
2337     case WM_GETMINMAXINFO:
2338         {
2339             MINMAXINFO16 *mmi = MapSL(p16->lParam);
2340             UnMapLS( p16->lParam );
2341             p16->lParam = *(LPARAM *)(mmi + 1);
2342             STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO *)(p16->lParam) );
2343             HeapFree( GetProcessHeap(), 0, mmi );
2344         }
2345         break;
2346     case WM_GETTEXT:
2347     case WM_ASKCBFORMATNAME:
2348         {
2349             LPSTR str = MapSL(p16->lParam);
2350             UnMapLS( p16->lParam );
2351             p16->lParam = *((LPARAM *)str - 1);
2352             lstrcpynA( (LPSTR)(p16->lParam), str, p16->wParam );
2353             HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2354         }
2355         break;
2356     case WM_MDICREATE:
2357         {
2358             MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2359             UnMapLS( cs->szTitle );
2360             UnMapLS( cs->szClass );
2361             UnMapLS( p16->lParam );
2362             HeapFree( GetProcessHeap(), 0, cs );
2363         }
2364         break;
2365     case WM_MDIGETACTIVE:
2366         if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(p16->lResult);
2367         p16->lResult = (LRESULT)WIN_Handle32( LOWORD(p16->lResult) );
2368         break;
2369     case WM_NCCALCSIZE:
2370         {
2371             NCCALCSIZE_PARAMS *nc32;
2372             NCCALCSIZE_PARAMS16 *nc = MapSL(p16->lParam);
2373             UnMapLS( p16->lParam );
2374             p16->lParam = *(LPARAM *)(nc + 1);
2375             nc32 = (NCCALCSIZE_PARAMS *)(p16->lParam);
2376             CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
2377             if (p16->wParam)
2378             {
2379                 WINDOWPOS16 *pos = MapSL(nc->lppos);
2380                 UnMapLS( nc->lppos );
2381                 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
2382                 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
2383                 STRUCT32_WINDOWPOS16to32( pos, nc32->lppos );
2384                 HeapFree( GetProcessHeap(), 0, pos );
2385             }
2386             HeapFree( GetProcessHeap(), 0, nc );
2387         }
2388         break;
2389     case WM_NCCREATE:
2390     case WM_CREATE:
2391         {
2392             CREATESTRUCT16 *cs = MapSL(p16->lParam);
2393             UnMapLS( p16->lParam );
2394             UnMapLS( cs->lpszName );
2395             UnMapLS( cs->lpszClass );
2396             HeapFree( GetProcessHeap(), 0, cs );
2397         }
2398         break;
2399     case WM_WINDOWPOSCHANGING:
2400     case WM_WINDOWPOSCHANGED:
2401         {
2402             WINDOWPOS16 *wp = MapSL(p16->lParam);
2403             UnMapLS( p16->lParam );
2404             p16->lParam = *(LPARAM *)(wp + 1);
2405             STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS *)p16->lParam );
2406             HeapFree( GetProcessHeap(), 0, wp );
2407         }
2408         break;
2409     case WM_NOTIFY:
2410         UnMapLS(p16->lParam);
2411         break;
2412     case WM_GETDLGCODE:
2413         if (p16->lParam)
2414         {
2415             LPMSG16 msg16 = MapSL(p16->lParam);
2416             MSGPARAM16 msgp16;
2417             UnMapLS( p16->lParam );
2418             msgp16.wParam=msg16->wParam;
2419             msgp16.lParam=msg16->lParam;
2420             WINPROC_UnmapMsg32ATo16(((LPMSG)lParam)->hwnd, ((LPMSG)lParam)->message,
2421                     ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam,
2422                     &msgp16 );
2423             HeapFree( GetProcessHeap(), 0, msg16 );
2424         }
2425         break;
2426     case WM_NEXTMENU:
2427         {
2428             MDINEXTMENU *next = (MDINEXTMENU *)lParam;
2429             next->hmenuNext = HMENU_32( LOWORD(p16->lResult) );
2430             next->hwndNext = WIN_Handle32( HIWORD(p16->lResult) );
2431             p16->lResult = 0;
2432         }
2433         break;
2434     }
2435 }
2436
2437
2438 /**********************************************************************
2439  *           WINPROC_MapMsg32WTo16
2440  *
2441  * Map a message from 32-bit Unicode to 16-bit.
2442  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
2443  */
2444 INT WINPROC_MapMsg32WTo16( HWND hwnd, UINT msg32, WPARAM wParam32,
2445                              UINT16 *pmsg16, WPARAM16 *pwparam16,
2446                              LPARAM *plparam )
2447 {
2448     BYTE ch;
2449     WCHAR wch;
2450
2451     *pmsg16    = LOWORD(msg32);
2452     *pwparam16 = LOWORD(wParam32);
2453     switch(msg32)
2454     {
2455     case LB_ADDSTRING:
2456     case LB_FINDSTRING:
2457     case LB_FINDSTRINGEXACT:
2458     case LB_INSERTSTRING:
2459     case LB_SELECTSTRING:
2460     case LB_DIR:
2461     case LB_ADDFILE:
2462         *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2463         *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2464         return 1;
2465
2466     case CB_ADDSTRING:
2467     case CB_FINDSTRING:
2468     case CB_FINDSTRINGEXACT:
2469     case CB_INSERTSTRING:
2470     case CB_SELECTSTRING:
2471     case CB_DIR:
2472         *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2473         *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING);
2474         return 1;
2475
2476     case WM_NCCREATE:
2477     case WM_CREATE:
2478         {
2479             CREATESTRUCT16 *cs;
2480             CREATESTRUCTW *cs32 = (CREATESTRUCTW *)*plparam;
2481
2482             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2483             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs32, cs );
2484             cs->lpszName  = map_str_32W_to_16( cs32->lpszName );
2485             cs->lpszClass = map_str_32W_to_16( cs32->lpszClass );
2486             *plparam   = MapLS(cs);
2487         }
2488         return 1;
2489     case WM_MDICREATE:
2490         {
2491             MDICREATESTRUCT16 *cs;
2492             MDICREATESTRUCTW *cs32 = (MDICREATESTRUCTW *)*plparam;
2493
2494             if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2495             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs32, cs );
2496             cs->szTitle = map_str_32W_to_16( cs32->szTitle );
2497             cs->szClass = map_str_32W_to_16( cs32->szClass );
2498             *plparam   = MapLS(cs);
2499         }
2500         return 1;
2501     case WM_SETTEXT:
2502     case WM_WININICHANGE:
2503     case WM_DEVMODECHANGE:
2504         *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2505         return 1;
2506     case LB_GETTEXT:
2507     case CB_GETLBTEXT:
2508         if ( WINPROC_TestLBForStr( hwnd ))
2509         {
2510             LPSTR str = HeapAlloc( GetProcessHeap(), 0, 256 ); /* FIXME: fixed sized buffer */
2511             if (!str) return -1;
2512             *pmsg16    = (msg32 == LB_GETTEXT)? LB_GETTEXT16 : CB_GETLBTEXT16;
2513             *plparam   = (LPARAM)MapLS(str);
2514         }
2515         return 1;
2516
2517     case WM_CHARTOITEM:
2518         wch = LOWORD(wParam32);
2519         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2520         *pwparam16 = ch;
2521         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2522         return 0;
2523     case WM_MENUCHAR:
2524         wch = LOWORD(wParam32);
2525         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2526         *pwparam16 = ch;
2527         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2528         return 0;
2529     case WM_CHAR:
2530     case WM_DEADCHAR:
2531     case WM_SYSCHAR:
2532     case WM_SYSDEADCHAR:
2533         wch = wParam32;
2534         WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2535         *pwparam16 = ch;
2536         return 0;
2537
2538     case WM_IME_CHAR:
2539         {
2540             BYTE ch[2];
2541
2542             wch = wParam32;
2543             ch[1] = 0;
2544             WideCharToMultiByte( CP_ACP, 0, &wch, 1, ch, 2, NULL, NULL );
2545             *pwparam16 = (ch[0] << 8) | ch[1];
2546         }
2547         return 0;
2548
2549     default:  /* No Unicode translation needed (?) */
2550         return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2551                                       pwparam16, plparam );
2552     }
2553 }
2554
2555
2556 /**********************************************************************
2557  *           WINPROC_UnmapMsg32WTo16
2558  *
2559  * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2560  */
2561 void WINPROC_UnmapMsg32WTo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2562                               MSGPARAM16* p16 )
2563 {
2564     switch(msg)
2565     {
2566     case LB_ADDSTRING:
2567     case LB_FINDSTRING:
2568     case LB_FINDSTRINGEXACT:
2569     case LB_INSERTSTRING:
2570     case LB_SELECTSTRING:
2571     case LB_DIR:
2572     case LB_ADDFILE:
2573     case CB_ADDSTRING:
2574     case CB_FINDSTRING:
2575     case CB_FINDSTRINGEXACT:
2576     case CB_INSERTSTRING:
2577     case CB_SELECTSTRING:
2578     case CB_DIR:
2579     case WM_SETTEXT:
2580     case WM_WININICHANGE:
2581     case WM_DEVMODECHANGE:
2582         unmap_str_32W_to_16( p16->lParam );
2583         break;
2584     case WM_NCCREATE:
2585     case WM_CREATE:
2586         {
2587             CREATESTRUCT16 *cs = MapSL(p16->lParam);
2588             UnMapLS( p16->lParam );
2589             unmap_str_32W_to_16( cs->lpszName );
2590             unmap_str_32W_to_16( cs->lpszClass );
2591             HeapFree( GetProcessHeap(), 0, cs );
2592         }
2593         break;
2594     case WM_MDICREATE:
2595         {
2596             MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2597             UnMapLS( p16->lParam );
2598             unmap_str_32W_to_16( cs->szTitle );
2599             unmap_str_32W_to_16( cs->szClass );
2600             HeapFree( GetProcessHeap(), 0, cs );
2601         }
2602         break;
2603     case WM_GETTEXT:
2604     case WM_ASKCBFORMATNAME:
2605         {
2606             LPSTR str = MapSL(p16->lParam);
2607             UnMapLS( p16->lParam );
2608             p16->lParam = *((LPARAM *)str - 1);
2609             MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)p16->lParam, 0x7fffffff );
2610             HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2611         }
2612         break;
2613     case LB_GETTEXT:
2614     case CB_GETLBTEXT:
2615         if ( WINPROC_TestLBForStr( hwnd ))
2616         {
2617             LPSTR str = MapSL(p16->lParam);
2618             UnMapLS( p16->lParam );
2619             MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff );
2620             HeapFree( GetProcessHeap(), 0, (LPARAM *)str );
2621         }
2622         break;
2623     default:
2624         WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, p16 );
2625         break;
2626     }
2627 }
2628
2629
2630 /**********************************************************************
2631  *           WINPROC_CallProc32ATo32W
2632  *
2633  * Call a window procedure, translating args from Ansi to Unicode.
2634  */
2635 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC func, HWND hwnd,
2636                                          UINT msg, WPARAM wParam,
2637                                          LPARAM lParam )
2638 {
2639     LRESULT result;
2640     int unmap;
2641
2642     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2643         func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2644
2645     if( (unmap = WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam )) == -1) {
2646         ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2647                        SPY_GetMsgName(msg, hwnd), wParam, lParam );
2648         return 0;
2649     }
2650     result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2651     if (unmap) result = WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result );
2652     return result;
2653 }
2654
2655
2656 /**********************************************************************
2657  *           WINPROC_CallProc32WTo32A
2658  *
2659  * Call a window procedure, translating args from Unicode to Ansi.
2660  */
2661 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC func, HWND hwnd,
2662                                          UINT msg, WPARAM wParam,
2663                                          LPARAM lParam )
2664 {
2665     LRESULT result;
2666     int unmap;
2667
2668     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2669         func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2670
2671     if ((unmap = WINPROC_MapMsg32WTo32A( hwnd, msg, &wParam, &lParam )) == -1) {
2672         ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2673                        SPY_GetMsgName(msg, hwnd), wParam, lParam );
2674         return 0;
2675     }
2676     result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2677     if( unmap ) WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam );
2678     return result;
2679 }
2680
2681
2682 /**********************************************************************
2683  *           __wine_call_wndproc_32A   (USER.1010)
2684  */
2685 LRESULT WINAPI __wine_call_wndproc_32A( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2686                                         WNDPROC func )
2687 {
2688     LRESULT result;
2689     UINT msg32;
2690     WPARAM wParam32;
2691     HWND hwnd32 = WIN_Handle32( hwnd );
2692
2693     if (WINPROC_MapMsg16To32A( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2694         return 0;
2695     result = WINPROC_CallWndProc( func, hwnd32, msg32, wParam32, lParam );
2696     return WINPROC_UnmapMsg16To32A( hwnd32, msg32, wParam32, lParam, result );
2697 }
2698
2699
2700 /**********************************************************************
2701  *           __wine_call_wndproc_32W   (USER.1011)
2702  */
2703 LRESULT WINAPI  __wine_call_wndproc_32W( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2704                                          WNDPROC func )
2705 {
2706     LRESULT result;
2707     UINT msg32;
2708     WPARAM wParam32;
2709     HWND hwnd32 = WIN_Handle32( hwnd );
2710
2711     if (WINPROC_MapMsg16To32W( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2712         return 0;
2713     result = WINPROC_CallWndProc( func, hwnd32, msg32, wParam32, lParam );
2714     return WINPROC_UnmapMsg16To32W( hwnd32, msg32, wParam32, lParam, result );
2715 }
2716
2717
2718 /**********************************************************************
2719  *           WINPROC_CallProc32ATo16
2720  *
2721  * Call a 16-bit window procedure, translating the 32-bit args.
2722  */
2723 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd,
2724                                                UINT msg, WPARAM wParam,
2725                                                LPARAM lParam )
2726 {
2727     UINT16 msg16;
2728     MSGPARAM16 mp16;
2729
2730     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2731         func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2732
2733     mp16.lParam = lParam;
2734     if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, &msg16, &mp16.wParam, &mp16.lParam ) == -1)
2735         return 0;
2736     mp16.lResult = WINPROC_CallWndProc16( func, HWND_16(hwnd), msg16,
2737                                           mp16.wParam, mp16.lParam );
2738     WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, &mp16 );
2739     return mp16.lResult;
2740 }
2741
2742
2743 /**********************************************************************
2744  *           WINPROC_CallProc32WTo16
2745  *
2746  * Call a 16-bit window procedure, translating the 32-bit args.
2747  */
2748 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd,
2749                                                UINT msg, WPARAM wParam,
2750                                                LPARAM lParam )
2751 {
2752     UINT16 msg16;
2753     MSGPARAM16 mp16;
2754
2755     TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2756         func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2757
2758     mp16.lParam = lParam;
2759     if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &mp16.wParam,
2760                                &mp16.lParam ) == -1)
2761         return 0;
2762     mp16.lResult = WINPROC_CallWndProc16( func, HWND_16(hwnd), msg16,
2763                                           mp16.wParam, mp16.lParam );
2764     WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, &mp16 );
2765     return mp16.lResult;
2766 }
2767
2768
2769 /**********************************************************************
2770  *              CallWindowProc (USER.122)
2771  */
2772 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
2773                                  WPARAM16 wParam, LPARAM lParam )
2774 {
2775     WINDOWPROC *proc;
2776
2777     if (!func) return 0;
2778
2779     if (!(proc = WINPROC_GetPtr( (WNDPROC)func )))
2780         return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
2781
2782 #if testing
2783     func = WINPROC_GetProc( (WNDPROC)proc, WIN_PROC_16 );
2784     return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
2785 #endif
2786
2787     switch(proc->type)
2788     {
2789     case WIN_PROC_16:
2790         if (!proc->thunk.t_from32.proc) return 0;
2791         return WINPROC_CallWndProc16( proc->thunk.t_from32.proc,
2792                                       hwnd, msg, wParam, lParam );
2793     case WIN_PROC_32A:
2794         if (!proc->thunk.t_from16.proc) return 0;
2795         return __wine_call_wndproc_32A( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc );
2796     case WIN_PROC_32W:
2797         if (!proc->thunk.t_from16.proc) return 0;
2798         return __wine_call_wndproc_32W( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc );
2799     default:
2800         WARN_(relay)("Invalid proc %p\n", proc );
2801         return 0;
2802     }
2803 }
2804
2805
2806 /**********************************************************************
2807  *              CallWindowProcA (USER32.@)
2808  *
2809  * The CallWindowProc() function invokes the windows procedure _func_,
2810  * with _hwnd_ as the target window, the message specified by _msg_, and
2811  * the message parameters _wParam_ and _lParam_.
2812  *
2813  * Some kinds of argument conversion may be done, I'm not sure what.
2814  *
2815  * CallWindowProc() may be used for windows subclassing. Use
2816  * SetWindowLong() to set a new windows procedure for windows of the
2817  * subclass, and handle subclassed messages in the new windows
2818  * procedure. The new windows procedure may then use CallWindowProc()
2819  * with _func_ set to the parent class's windows procedure to dispatch
2820  * the message to the superclass.
2821  *
2822  * RETURNS
2823  *
2824  *    The return value is message dependent.
2825  *
2826  * CONFORMANCE
2827  *
2828  *   ECMA-234, Win32
2829  */
2830 LRESULT WINAPI CallWindowProcA(
2831     WNDPROC func,  /* [in] window procedure */
2832     HWND hwnd,     /* [in] target window */
2833     UINT msg,      /* [in] message */
2834     WPARAM wParam, /* [in] message dependent parameter */
2835     LPARAM lParam  /* [in] message dependent parameter */
2836 ) {
2837     WINDOWPROC *proc = WINPROC_GetPtr( func );
2838
2839     if (!proc) return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2840
2841 #if testing
2842     func = WINPROC_GetProc( (WNDPROC)proc, WIN_PROC_32A );
2843     return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2844 #endif
2845
2846     switch(proc->type)
2847     {
2848     case WIN_PROC_16:
2849         if (!proc->thunk.t_from32.proc) return 0;
2850         return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
2851                                         hwnd, msg, wParam, lParam );
2852     case WIN_PROC_32A:
2853         if (!proc->thunk.t_from16.proc) return 0;
2854         return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
2855                                       hwnd, msg, wParam, lParam );
2856     case WIN_PROC_32W:
2857         if (!proc->thunk.t_from16.proc) return 0;
2858         return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
2859                                          hwnd, msg, wParam, lParam );
2860     default:
2861         WARN_(relay)("Invalid proc %p\n", proc );
2862         return 0;
2863     }
2864 }
2865
2866
2867 /**********************************************************************
2868  *              CallWindowProcW (USER32.@)
2869  */
2870 LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
2871                                   WPARAM wParam, LPARAM lParam )
2872 {
2873     WINDOWPROC *proc = WINPROC_GetPtr( func );
2874
2875     if (!proc) return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2876
2877 #if testing
2878     func = WINPROC_GetProc( (WNDPROC)proc, WIN_PROC_32W );
2879     return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2880 #endif
2881
2882     switch(proc->type)
2883     {
2884     case WIN_PROC_16:
2885         if (!proc->thunk.t_from32.proc) return 0;
2886         return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
2887                                         hwnd, msg, wParam, lParam );
2888     case WIN_PROC_32A:
2889         if (!proc->thunk.t_from16.proc) return 0;
2890         return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
2891                                          hwnd, msg, wParam, lParam );
2892     case WIN_PROC_32W:
2893         if (!proc->thunk.t_from16.proc) return 0;
2894         return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
2895                                       hwnd, msg, wParam, lParam );
2896     default:
2897         WARN_(relay)("Invalid proc %p\n", proc );
2898         return 0;
2899     }
2900 }