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