Changed winproc allocation to be based only on the procedure address,
[wine/wine64.git] / windows / winproc.c
blobca145253c1f19f9fee7d347d76b6aa564b140e8d
1 /*
2 * Window procedure callbacks
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1996 Alexandre Julliard
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.
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.
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
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
26 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "wownt32.h"
32 #include "wine/winbase16.h"
33 #include "wine/winuser16.h"
34 #include "stackframe.h"
35 #include "controls.h"
36 #include "heap.h"
37 #include "win.h"
38 #include "winproc.h"
39 #include "message.h"
40 #include "thread.h"
41 #include "dde.h"
42 #include "winternl.h"
43 #include "wine/unicode.h"
44 #include "wine/debug.h"
46 WINE_DECLARE_DEBUG_CHANNEL(msg);
47 WINE_DECLARE_DEBUG_CHANNEL(relay);
48 WINE_DEFAULT_DEBUG_CHANNEL(win);
50 #ifdef __i386__
52 #include "pshpack1.h"
54 /* Window procedure 16-to-32-bit thunk */
55 typedef struct
57 BYTE popl_eax; /* popl %eax (return address) */
58 BYTE pushl_func; /* pushl $proc */
59 WNDPROC proc;
60 BYTE pushl_eax; /* pushl %eax */
61 BYTE ljmp; /* ljmp relay*/
62 DWORD relay_offset; /* __wine_call_wndproc_32A/W */
63 WORD relay_sel;
64 } WINPROC_THUNK_FROM16;
66 /* Window procedure 32-to-16-bit thunk */
67 typedef struct
69 BYTE popl_eax; /* popl %eax (return address) */
70 BYTE pushl_func; /* pushl $proc */
71 WNDPROC16 proc;
72 BYTE pushl_eax; /* pushl %eax */
73 BYTE jmp; /* jmp relay (relative jump)*/
74 void (*relay)(); /* WINPROC_CallProc32ATo16() */
75 } WINPROC_THUNK_FROM32;
77 /* Simple jmp to call 32-bit procedure directly */
78 typedef struct
80 BYTE jmp; /* jmp proc (relative jump) */
81 WNDPROC proc;
82 } WINPROC_JUMP;
84 #include "poppack.h"
86 #else /* __i386__ */
88 typedef struct
90 WNDPROC proc;
91 } WINPROC_THUNK_FROM16;
93 typedef struct
95 WNDPROC16 proc;
96 } WINPROC_THUNK_FROM32;
98 typedef struct
100 WNDPROC proc;
101 } WINPROC_JUMP;
103 #endif /* __i386__ */
105 typedef union
107 WINPROC_THUNK_FROM16 t_from16;
108 WINPROC_THUNK_FROM32 t_from32;
109 } WINPROC_THUNK;
111 typedef struct tagWINDOWPROC
113 WINPROC_THUNK thunk; /* Thunk */
114 WINPROC_JUMP jmp; /* Jump */
115 BYTE type; /* Function type */
116 } WINDOWPROC;
118 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd,
119 UINT msg, WPARAM wParam,
120 LPARAM lParam );
121 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd,
122 UINT msg, WPARAM wParam,
123 LPARAM lParam );
125 #define MAX_WINPROCS (0x10000 / sizeof(WINDOWPROC))
127 static WINDOWPROC winproc_array[MAX_WINPROCS];
128 static UINT winproc_used;
130 static CRITICAL_SECTION winproc_cs;
131 static CRITICAL_SECTION_DEBUG critsect_debug =
133 0, 0, &winproc_cs,
134 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
135 0, 0, { 0, (DWORD)(__FILE__ ": winproc_cs") }
137 static CRITICAL_SECTION winproc_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
139 static BOOL is_valid_winproc( WINDOWPROC *proc )
141 /* check array limits */
142 if (proc < winproc_array || proc >= winproc_array + winproc_used) return FALSE;
143 /* check alignment */
144 if (proc != winproc_array + (proc - winproc_array)) return FALSE;
145 return (proc->type != WIN_PROC_INVALID);
148 /* find an existing winproc for a given function and type */
149 /* FIXME: probably should do something more clever than a linear search */
150 static inline WINDOWPROC *find_winproc( WNDPROC func, WINDOWPROCTYPE type )
152 unsigned int i;
154 if (type == WIN_PROC_16)
156 for (i = 0; i < winproc_used; i++)
158 if (winproc_array[i].type == type &&
159 winproc_array[i].thunk.t_from32.proc == (WNDPROC16)func)
160 return &winproc_array[i];
163 else
165 for (i = 0; i < winproc_used; i++)
167 if (winproc_array[i].type == type &&
168 winproc_array[i].thunk.t_from16.proc == func)
169 return &winproc_array[i];
172 return NULL;
175 /* initialize a new winproc */
176 static inline void set_winproc( WINDOWPROC *proc, WNDPROC func, WINDOWPROCTYPE type )
178 #ifdef __i386__
179 static FARPROC16 relay_32A, relay_32W;
181 switch(type)
183 case WIN_PROC_16:
184 proc->thunk.t_from32.popl_eax = 0x58; /* popl %eax */
185 proc->thunk.t_from32.pushl_func = 0x68; /* pushl $proc */
186 proc->thunk.t_from32.proc = (WNDPROC16)func;
187 proc->thunk.t_from32.pushl_eax = 0x50; /* pushl %eax */
188 proc->thunk.t_from32.jmp = 0xe9; /* jmp relay*/
189 proc->thunk.t_from32.relay = /* relative jump */
190 (void(*)())((DWORD)WINPROC_CallProc32ATo16 -
191 (DWORD)(&proc->thunk.t_from32.relay + 1));
192 break;
193 case WIN_PROC_32A:
194 if (!relay_32A) relay_32A = GetProcAddress16( GetModuleHandle16("user"),
195 "__wine_call_wndproc_32A" );
196 proc->thunk.t_from16.popl_eax = 0x58; /* popl %eax */
197 proc->thunk.t_from16.pushl_func = 0x68; /* pushl $proc */
198 proc->thunk.t_from16.proc = func;
199 proc->thunk.t_from16.pushl_eax = 0x50; /* pushl %eax */
200 proc->thunk.t_from16.ljmp = 0xea; /* ljmp relay*/
201 proc->thunk.t_from16.relay_offset = OFFSETOF(relay_32A);
202 proc->thunk.t_from16.relay_sel = SELECTOROF(relay_32A);
203 proc->jmp.jmp = 0xe9;
204 /* Fixup relative jump */
205 proc->jmp.proc = (WNDPROC)((DWORD)func - (DWORD)(&proc->jmp.proc + 1));
206 break;
207 case WIN_PROC_32W:
208 if (!relay_32W) relay_32W = GetProcAddress16( GetModuleHandle16("user"),
209 "__wine_call_wndproc_32W" );
210 proc->thunk.t_from16.popl_eax = 0x58; /* popl %eax */
211 proc->thunk.t_from16.pushl_func = 0x68; /* pushl $proc */
212 proc->thunk.t_from16.proc = func;
213 proc->thunk.t_from16.pushl_eax = 0x50; /* pushl %eax */
214 proc->thunk.t_from16.ljmp = 0xea; /* ljmp relay*/
215 proc->thunk.t_from16.relay_offset = OFFSETOF(relay_32W);
216 proc->thunk.t_from16.relay_sel = SELECTOROF(relay_32W);
217 proc->jmp.jmp = 0xe9;
218 /* Fixup relative jump */
219 proc->jmp.proc = (WNDPROC)((char *)func - (char *)(&proc->jmp.proc + 1));
220 break;
221 default:
222 /* Should not happen */
223 break;
225 #else /* __i386__ */
226 switch(type)
228 case WIN_PROC_16:
229 proc->thunk.t_from32.proc = (WNDPROC16)func;
230 break;
231 case WIN_PROC_32A:
232 case WIN_PROC_32W:
233 proc->thunk.t_from16.proc = func;
234 break;
235 default:
236 /* Should not happen */
237 break;
239 #endif /* __i386__ */
241 proc->type = type;
244 static WORD get_winproc_selector(void)
246 static LONG winproc_selector;
247 WORD ret;
249 if (!(ret = winproc_selector))
251 LDT_ENTRY entry;
252 WORD sel = wine_ldt_alloc_entries(1);
253 wine_ldt_set_base( &entry, winproc_array );
254 wine_ldt_set_limit( &entry, sizeof(winproc_array) - 1 );
255 wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
256 wine_ldt_set_entry( sel, &entry );
257 if (!(ret = InterlockedCompareExchange( &winproc_selector, sel, 0 ))) ret = sel;
258 else wine_ldt_free_entries( sel, 1 ); /* somebody beat us to it */
260 return ret;
264 #ifdef __i386__
265 /* Some window procedures modify register they shouldn't, or are not
266 * properly declared stdcall; so we need a small assembly wrapper to
267 * call them. */
268 extern LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
269 WPARAM wParam, LPARAM lParam );
270 __ASM_GLOBAL_FUNC( WINPROC_wrapper,
271 "pushl %ebp\n\t"
272 "movl %esp,%ebp\n\t"
273 "pushl %edi\n\t"
274 "pushl %esi\n\t"
275 "pushl %ebx\n\t"
276 "pushl 24(%ebp)\n\t"
277 "pushl 20(%ebp)\n\t"
278 "pushl 16(%ebp)\n\t"
279 "pushl 12(%ebp)\n\t"
280 "movl 8(%ebp),%eax\n\t"
281 "call *%eax\n\t"
282 "leal -12(%ebp),%esp\n\t"
283 "popl %ebx\n\t"
284 "popl %esi\n\t"
285 "popl %edi\n\t"
286 "leave\n\t"
287 "ret" );
288 #else
289 static inline LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
290 WPARAM wParam, LPARAM lParam )
292 return proc( hwnd, msg, wParam, lParam );
294 #endif /* __i386__ */
297 static void MINMAXINFO32to16( const MINMAXINFO *from, MINMAXINFO16 *to )
299 to->ptReserved.x = from->ptReserved.x;
300 to->ptReserved.y = from->ptReserved.y;
301 to->ptMaxSize.x = from->ptMaxSize.x;
302 to->ptMaxSize.y = from->ptMaxSize.y;
303 to->ptMaxPosition.x = from->ptMaxPosition.x;
304 to->ptMaxPosition.y = from->ptMaxPosition.y;
305 to->ptMinTrackSize.x = from->ptMinTrackSize.x;
306 to->ptMinTrackSize.y = from->ptMinTrackSize.y;
307 to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
308 to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
311 static void MINMAXINFO16to32( const MINMAXINFO16 *from, MINMAXINFO *to )
313 to->ptReserved.x = from->ptReserved.x;
314 to->ptReserved.y = from->ptReserved.y;
315 to->ptMaxSize.x = from->ptMaxSize.x;
316 to->ptMaxSize.y = from->ptMaxSize.y;
317 to->ptMaxPosition.x = from->ptMaxPosition.x;
318 to->ptMaxPosition.y = from->ptMaxPosition.y;
319 to->ptMinTrackSize.x = from->ptMinTrackSize.x;
320 to->ptMinTrackSize.y = from->ptMinTrackSize.y;
321 to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
322 to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
325 static void WINDOWPOS32to16( const WINDOWPOS* from, WINDOWPOS16* to )
327 to->hwnd = HWND_16(from->hwnd);
328 to->hwndInsertAfter = HWND_16(from->hwndInsertAfter);
329 to->x = from->x;
330 to->y = from->y;
331 to->cx = from->cx;
332 to->cy = from->cy;
333 to->flags = from->flags;
336 static void WINDOWPOS16to32( const WINDOWPOS16* from, WINDOWPOS* to )
338 to->hwnd = WIN_Handle32(from->hwnd);
339 to->hwndInsertAfter = (from->hwndInsertAfter == (HWND16)-1) ?
340 HWND_TOPMOST : WIN_Handle32(from->hwndInsertAfter);
341 to->x = from->x;
342 to->y = from->y;
343 to->cx = from->cx;
344 to->cy = from->cy;
345 to->flags = from->flags;
348 /* The strings are not copied */
349 static void CREATESTRUCT32Ato16( const CREATESTRUCTA* from, CREATESTRUCT16* to )
351 to->lpCreateParams = (SEGPTR)from->lpCreateParams;
352 to->hInstance = HINSTANCE_16(from->hInstance);
353 to->hMenu = HMENU_16(from->hMenu);
354 to->hwndParent = HWND_16(from->hwndParent);
355 to->cy = from->cy;
356 to->cx = from->cx;
357 to->y = from->y;
358 to->x = from->x;
359 to->style = from->style;
360 to->dwExStyle = from->dwExStyle;
363 static void CREATESTRUCT16to32A( const CREATESTRUCT16* from, CREATESTRUCTA *to )
366 to->lpCreateParams = (LPVOID)from->lpCreateParams;
367 to->hInstance = HINSTANCE_32(from->hInstance);
368 to->hMenu = HMENU_32(from->hMenu);
369 to->hwndParent = WIN_Handle32(from->hwndParent);
370 to->cy = from->cy;
371 to->cx = from->cx;
372 to->y = from->y;
373 to->x = from->x;
374 to->style = from->style;
375 to->dwExStyle = from->dwExStyle;
378 /* The strings are not copied */
379 static void MDICREATESTRUCT32Ato16( const MDICREATESTRUCTA* from, MDICREATESTRUCT16* to )
381 to->hOwner = HINSTANCE_16(from->hOwner);
382 to->x = from->x;
383 to->y = from->y;
384 to->cx = from->cx;
385 to->cy = from->cy;
386 to->style = from->style;
387 to->lParam = from->lParam;
390 static void MDICREATESTRUCT16to32A( const MDICREATESTRUCT16* from, MDICREATESTRUCTA *to )
392 to->hOwner = HINSTANCE_32(from->hOwner);
393 to->x = from->x;
394 to->y = from->y;
395 to->cx = from->cx;
396 to->cy = from->cy;
397 to->style = from->style;
398 to->lParam = from->lParam;
401 /**********************************************************************
402 * WINPROC_CallWndProc32
404 * Call a 32-bit WndProc.
406 static LRESULT WINPROC_CallWndProc( WNDPROC proc, HWND hwnd, UINT msg,
407 WPARAM wParam, LPARAM lParam )
409 LRESULT retvalue;
410 int iWndsLocks;
412 hwnd = WIN_GetFullHandle( hwnd );
413 if (TRACE_ON(relay))
414 DPRINTF( "%04lx:Call window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
415 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
416 /* To avoid any deadlocks, all the locks on the windows structures
417 must be suspended before the control is passed to the application */
418 iWndsLocks = WIN_SuspendWndsLock();
419 retvalue = WINPROC_wrapper( proc, hwnd, msg, wParam, lParam );
420 WIN_RestoreWndsLock(iWndsLocks);
422 if (TRACE_ON(relay))
423 DPRINTF( "%04lx:Ret window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx\n",
424 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam, retvalue );
425 return retvalue;
428 /***********************************************************************
429 * WINPROC_CallWndProc16
431 * Call a 16-bit window procedure
433 static LRESULT WINAPI WINPROC_CallWndProc16( WNDPROC16 proc, HWND16 hwnd,
434 UINT16 msg, WPARAM16 wParam,
435 LPARAM lParam )
437 CONTEXT86 context;
438 LRESULT ret;
439 WORD args[5];
440 DWORD offset = 0;
441 TEB *teb = NtCurrentTeb();
442 int iWndsLocks;
444 /* Window procedures want ax = hInstance, ds = es = ss */
446 memset(&context, 0, sizeof(context));
447 context.SegDs = context.SegEs = SELECTOROF(teb->cur_stack);
448 context.SegFs = wine_get_fs();
449 context.SegGs = wine_get_gs();
450 if (!(context.Eax = GetWindowWord( HWND_32(hwnd), GWLP_HINSTANCE ))) context.Eax = context.SegDs;
451 context.SegCs = SELECTOROF(proc);
452 context.Eip = OFFSETOF(proc);
453 context.Ebp = OFFSETOF(teb->cur_stack)
454 + (WORD)&((STACK16FRAME*)0)->bp;
456 if (lParam)
458 /* Some programs (eg. the "Undocumented Windows" examples, JWP) only
459 work if structures passed in lParam are placed in the stack/data
460 segment. Programmers easily make the mistake of converting lParam
461 to a near rather than a far pointer, since Windows apparently
462 allows this. We copy the structures to the 16 bit stack; this is
463 ugly but makes these programs work. */
464 switch (msg)
466 case WM_CREATE:
467 case WM_NCCREATE:
468 offset = sizeof(CREATESTRUCT16); break;
469 case WM_DRAWITEM:
470 offset = sizeof(DRAWITEMSTRUCT16); break;
471 case WM_COMPAREITEM:
472 offset = sizeof(COMPAREITEMSTRUCT16); break;
474 if (offset)
476 void *s = MapSL(lParam);
477 lParam = stack16_push( offset );
478 memcpy( MapSL(lParam), s, offset );
482 iWndsLocks = WIN_SuspendWndsLock();
484 args[4] = hwnd;
485 args[3] = msg;
486 args[2] = wParam;
487 args[1] = HIWORD(lParam);
488 args[0] = LOWORD(lParam);
489 WOWCallback16Ex( 0, WCB16_REGS, sizeof(args), args, (DWORD *)&context );
490 ret = MAKELONG( LOWORD(context.Eax), LOWORD(context.Edx) );
492 if (offset) stack16_pop( offset );
494 WIN_RestoreWndsLock(iWndsLocks);
496 return ret;
500 /**********************************************************************
501 * WINPROC_GetPtr
503 * Return a pointer to the win proc.
505 static WINDOWPROC *WINPROC_GetPtr( WNDPROC handle )
507 BYTE *ptr;
508 WINDOWPROC *proc;
510 /* ptr cannot be < 64K */
511 if (!HIWORD(handle)) return NULL;
513 /* Check for a linear pointer */
515 ptr = (BYTE *)handle;
516 /* First check if it is the jmp address */
517 proc = (WINDOWPROC *)(ptr - (int)&((WINDOWPROC *)0)->jmp);
518 if (is_valid_winproc(proc)) return proc;
520 /* Now it must be the thunk address */
521 proc = (WINDOWPROC *)(ptr - (int)&((WINDOWPROC *)0)->thunk);
522 if (is_valid_winproc(proc)) return proc;
524 /* Check for a segmented pointer */
526 ptr = MapSL( (SEGPTR)handle );
527 /* It must be the thunk address */
528 proc = (WINDOWPROC *)(ptr - (int)&((WINDOWPROC *)0)->thunk);
529 if (is_valid_winproc(proc)) return proc;
531 return NULL;
535 /**********************************************************************
536 * WINPROC_GetProc
538 * Get a window procedure pointer that can be passed to the Windows program.
540 WNDPROC16 WINPROC_GetProc( WNDPROC proc, WINDOWPROCTYPE type )
542 WINDOWPROC *ptr = (WINDOWPROC *)proc;
544 if (!proc) return NULL;
545 if (type == WIN_PROC_16) /* We want a 16:16 address */
547 if (ptr->type == WIN_PROC_16)
548 return ptr->thunk.t_from32.proc;
549 else
550 return (WNDPROC16)MAKESEGPTR( get_winproc_selector(),
551 (char *)&ptr->thunk - (char *)winproc_array );
553 else /* We want a 32-bit address */
555 if (ptr->type == WIN_PROC_16)
556 return (WNDPROC16)&ptr->thunk;
557 else if (type != ptr->type)
558 /* Have to return the jmp address if types don't match */
559 return (WNDPROC16)&ptr->jmp;
560 else
561 /* Some Win16 programs want to get back the proc they set */
562 return (WNDPROC16)ptr->thunk.t_from16.proc;
567 /**********************************************************************
568 * WINPROC_AllocProc
570 * Allocate a window procedure for a window or class.
572 * Note that allocated winprocs are never freed; the idea is that even if an app creates a
573 * lot of windows, it will usually only have a limited number of window procedures, so the
574 * array won't grow too large, and this way we avoid the need to track allocations per window.
576 WNDPROC WINPROC_AllocProc( WNDPROC func, WINDOWPROCTYPE type )
578 WINDOWPROC *proc;
580 if (!func) return NULL;
582 EnterCriticalSection( &winproc_cs );
584 /* check if the function is already a win proc */
585 if (!(proc = WINPROC_GetPtr( func )))
587 /* then check if we already have a winproc for that function */
588 if (!(proc = find_winproc( func, type )))
590 if (winproc_used >= MAX_WINPROCS)
591 FIXME( "too many winprocs, cannot allocate one for %p/%d\n", func, type );
592 else
594 proc = &winproc_array[winproc_used++];
595 set_winproc( proc, func, type );
596 TRACE( "allocated %p for %p/%d (%d/%d used)\n",
597 proc, func, type, winproc_used, MAX_WINPROCS );
600 else TRACE( "reusing %p for %p/%d\n", proc, func, type );
603 LeaveCriticalSection( &winproc_cs );
604 return (WNDPROC)proc;
608 /**********************************************************************
609 * WINPROC_GetProcType
611 * Return the window procedure type.
613 WINDOWPROCTYPE WINPROC_GetProcType( WNDPROC proc )
615 if (!proc) return WIN_PROC_INVALID;
616 return ((WINDOWPROC *)proc)->type;
618 /**********************************************************************
619 * WINPROC_TestCBForStr
621 * Return TRUE if the lparam is a string
623 inline static BOOL WINPROC_TestCBForStr( HWND hwnd )
625 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
626 return (!(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) || (style & CBS_HASSTRINGS));
628 /**********************************************************************
629 * WINPROC_TestLBForStr
631 * Return TRUE if the lparam is a string
633 inline static BOOL WINPROC_TestLBForStr( HWND hwnd )
635 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
636 return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS));
639 /**********************************************************************
640 * WINPROC_MapMsg32ATo32W
642 * Map a message from Ansi to Unicode.
643 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
645 * FIXME:
646 * WM_GETTEXT/WM_SETTEXT and static control with SS_ICON style:
647 * the first four bytes are the handle of the icon
648 * when the WM_SETTEXT message has been used to set the icon
650 INT WINPROC_MapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
652 switch(msg)
654 case WM_GETTEXT:
655 case WM_ASKCBFORMATNAME:
657 LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
658 *pwparam * sizeof(WCHAR) + sizeof(LPARAM) );
659 if (!ptr) return -1;
660 *ptr++ = *plparam; /* Store previous lParam */
661 *plparam = (LPARAM)ptr;
663 return 1;
664 /* lparam is string (0-terminated) */
665 case WM_SETTEXT:
666 case WM_WININICHANGE:
667 case WM_DEVMODECHANGE:
668 case CB_DIR:
669 case LB_DIR:
670 case LB_ADDFILE:
671 case EM_REPLACESEL:
673 DWORD len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*plparam, -1, NULL, 0);
674 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
675 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*plparam, -1, buf, len);
676 *plparam = (LPARAM)buf;
677 return (*plparam ? 1 : -1);
679 case WM_GETTEXTLENGTH:
680 case CB_GETLBTEXTLEN:
681 case LB_GETTEXTLEN:
682 return 1; /* need to map result */
683 case WM_NCCREATE:
684 case WM_CREATE:
686 UNICODE_STRING usBuffer;
687 struct s
688 { CREATESTRUCTW cs; /* new structure */
689 LPCWSTR lpszName; /* allocated Name */
690 LPCWSTR lpszClass; /* allocated Class */
693 struct s *xs = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct s));
694 if (!xs) return -1;
695 xs->cs = *(CREATESTRUCTW *)*plparam;
696 if (HIWORD(xs->cs.lpszName))
698 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)xs->cs.lpszName);
699 xs->lpszName = xs->cs.lpszName = usBuffer.Buffer;
701 if (HIWORD(xs->cs.lpszClass))
703 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)xs->cs.lpszClass);
704 xs->lpszClass = xs->cs.lpszClass = usBuffer.Buffer;
707 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
709 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)HeapAlloc(GetProcessHeap(), 0,
710 sizeof(*mdi_cs));
711 *mdi_cs = *(MDICREATESTRUCTW *)xs->cs.lpCreateParams;
712 if (HIWORD(mdi_cs->szTitle))
714 RtlCreateUnicodeStringFromAsciiz(&usBuffer, (LPCSTR)mdi_cs->szTitle);
715 mdi_cs->szTitle = usBuffer.Buffer;
717 if (HIWORD(mdi_cs->szClass))
719 RtlCreateUnicodeStringFromAsciiz(&usBuffer, (LPCSTR)mdi_cs->szClass);
720 mdi_cs->szClass = usBuffer.Buffer;
722 xs->cs.lpCreateParams = mdi_cs;
725 *plparam = (LPARAM)xs;
727 return 1;
728 case WM_MDICREATE:
730 MDICREATESTRUCTW *cs =
731 (MDICREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
732 if (!cs) return -1;
733 *cs = *(MDICREATESTRUCTW *)*plparam;
734 if (HIWORD(cs->szClass))
736 UNICODE_STRING usBuffer;
737 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)cs->szClass);
738 cs->szClass = usBuffer.Buffer;
740 if (HIWORD(cs->szTitle))
742 UNICODE_STRING usBuffer;
743 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)cs->szTitle);
744 cs->szTitle = usBuffer.Buffer;
746 *plparam = (LPARAM)cs;
748 return 1;
750 /* Listbox */
751 case LB_ADDSTRING:
752 case LB_INSERTSTRING:
753 case LB_FINDSTRING:
754 case LB_FINDSTRINGEXACT:
755 case LB_SELECTSTRING:
756 if(!*plparam) return 0;
757 if ( WINPROC_TestLBForStr( hwnd ))
759 UNICODE_STRING usBuffer;
760 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)*plparam);
761 *plparam = (LPARAM)usBuffer.Buffer;
763 return (*plparam ? 1 : -1);
765 case LB_GETTEXT: /* FIXME: fixed sized buffer */
766 { if ( WINPROC_TestLBForStr( hwnd ))
767 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
768 if (!ptr) return -1;
769 *ptr++ = *plparam; /* Store previous lParam */
770 *plparam = (LPARAM)ptr;
773 return 1;
775 /* Combobox */
776 case CB_ADDSTRING:
777 case CB_INSERTSTRING:
778 case CB_FINDSTRINGEXACT:
779 case CB_FINDSTRING:
780 case CB_SELECTSTRING:
781 if(!*plparam) return 0;
782 if ( WINPROC_TestCBForStr( hwnd ))
784 UNICODE_STRING usBuffer;
785 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)*plparam);
786 *plparam = (LPARAM)usBuffer.Buffer;
788 return (*plparam ? 1 : -1);
790 case CB_GETLBTEXT: /* FIXME: fixed sized buffer */
791 { if ( WINPROC_TestCBForStr( hwnd ))
792 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
793 if (!ptr) return -1;
794 *ptr++ = *plparam; /* Store previous lParam */
795 *plparam = (LPARAM)ptr;
798 return 1;
800 /* Multiline edit */
801 case EM_GETLINE:
802 { WORD len = (WORD)*plparam;
803 LPARAM *ptr = (LPARAM *) HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
804 if (!ptr) return -1;
805 *ptr++ = *plparam; /* Store previous lParam */
806 *((WORD *) ptr) = len; /* Store the length */
807 *plparam = (LPARAM)ptr;
809 return 1;
811 case WM_CHARTOITEM:
812 case WM_MENUCHAR:
813 case WM_CHAR:
814 case WM_DEADCHAR:
815 case WM_SYSCHAR:
816 case WM_SYSDEADCHAR:
817 case EM_SETPASSWORDCHAR:
819 BYTE ch = LOWORD(*pwparam);
820 WCHAR wch;
821 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
822 *pwparam = MAKEWPARAM( wch, HIWORD(*pwparam) );
824 return 0;
826 case WM_IME_CHAR:
828 BYTE ch[2];
829 WCHAR wch;
830 ch[0] = (*pwparam >> 8);
831 ch[1] = *pwparam & 0xff;
832 if (ch[0])
833 MultiByteToWideChar(CP_ACP, 0, ch, 2, &wch, 1);
834 else
835 MultiByteToWideChar(CP_ACP, 0, &ch[1], 1, &wch, 1);
836 *pwparam = MAKEWPARAM( wch, HIWORD(*pwparam) );
838 return 0;
840 case WM_PAINTCLIPBOARD:
841 case WM_SIZECLIPBOARD:
842 FIXME_(msg)("message %s (0x%x) needs translation, please report\n", SPY_GetMsgName(msg, hwnd), msg );
843 return -1;
844 default: /* No translation needed */
845 return 0;
850 /**********************************************************************
851 * WINPROC_UnmapMsg32ATo32W
853 * Unmap a message that was mapped from Ansi to Unicode.
855 LRESULT WINPROC_UnmapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
856 LRESULT result )
858 switch(msg)
860 case WM_GETTEXT:
861 case WM_ASKCBFORMATNAME:
863 LPARAM *ptr = (LPARAM *)lParam - 1;
864 if (!wParam) result = 0;
865 else if (!(result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
866 (LPSTR)*ptr, wParam, NULL, NULL )))
868 ((LPSTR)*ptr)[wParam-1] = 0;
869 result = wParam - 1;
871 else result--; /* do not count terminating null */
872 HeapFree( GetProcessHeap(), 0, ptr );
874 break;
875 case WM_GETTEXTLENGTH:
876 case CB_GETLBTEXTLEN:
877 case LB_GETTEXTLEN:
878 /* there may be one DBCS char for each Unicode char */
879 return result * 2;
880 case WM_NCCREATE:
881 case WM_CREATE:
883 struct s
884 { CREATESTRUCTW cs; /* new structure */
885 LPWSTR lpszName; /* allocated Name */
886 LPWSTR lpszClass; /* allocated Class */
888 struct s *xs = (struct s *)lParam;
889 if (xs->lpszName) HeapFree( GetProcessHeap(), 0, xs->lpszName );
890 if (xs->lpszClass) HeapFree( GetProcessHeap(), 0, xs->lpszClass );
892 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
894 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)xs->cs.lpCreateParams;
895 if (HIWORD(mdi_cs->szTitle))
896 HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szTitle);
897 if (HIWORD(mdi_cs->szClass))
898 HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szClass);
899 HeapFree(GetProcessHeap(), 0, mdi_cs);
901 HeapFree( GetProcessHeap(), 0, xs );
903 break;
905 case WM_MDICREATE:
907 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
908 if (HIWORD(cs->szTitle))
909 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
910 if (HIWORD(cs->szClass))
911 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
912 HeapFree( GetProcessHeap(), 0, cs );
914 break;
916 case WM_SETTEXT:
917 case WM_WININICHANGE:
918 case WM_DEVMODECHANGE:
919 case CB_DIR:
920 case LB_DIR:
921 case LB_ADDFILE:
922 case EM_REPLACESEL:
923 HeapFree( GetProcessHeap(), 0, (void *)lParam );
924 break;
926 /* Listbox */
927 case LB_ADDSTRING:
928 case LB_INSERTSTRING:
929 case LB_FINDSTRING:
930 case LB_FINDSTRINGEXACT:
931 case LB_SELECTSTRING:
932 if ( WINPROC_TestLBForStr( hwnd ))
933 HeapFree( GetProcessHeap(), 0, (void *)lParam );
934 break;
936 case LB_GETTEXT:
937 if ( WINPROC_TestLBForStr( hwnd ))
939 LPARAM *ptr = (LPARAM *)lParam - 1;
940 result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
941 (LPSTR)*ptr, 0x7fffffff, NULL, NULL ) - 1;
942 HeapFree( GetProcessHeap(), 0, ptr );
944 break;
946 /* Combobox */
947 case CB_ADDSTRING:
948 case CB_INSERTSTRING:
949 case CB_FINDSTRING:
950 case CB_FINDSTRINGEXACT:
951 case CB_SELECTSTRING:
952 if ( WINPROC_TestCBForStr( hwnd ))
953 HeapFree( GetProcessHeap(), 0, (void *)lParam );
954 break;
956 case CB_GETLBTEXT:
957 if ( WINPROC_TestCBForStr( hwnd ))
959 LPARAM *ptr = (LPARAM *)lParam - 1;
960 result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
961 (LPSTR)*ptr, 0x7fffffff, NULL, NULL ) - 1;
962 HeapFree( GetProcessHeap(), 0, ptr );
964 break;
966 /* Multiline edit */
967 case EM_GETLINE:
969 LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lParam */
970 WORD len = *(WORD *) lParam;
971 result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, result,
972 (LPSTR)*ptr, len, NULL, NULL );
973 if (result < len) ((LPSTR)*ptr)[result] = 0;
974 HeapFree( GetProcessHeap(), 0, ptr );
976 break;
978 return result;
982 /**********************************************************************
983 * WINPROC_MapMsg32WTo32A
985 * Map a message from Unicode to Ansi.
986 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
988 static INT WINPROC_MapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
990 switch(msg)
992 case WM_GETTEXT:
993 case WM_ASKCBFORMATNAME:
995 LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
996 *pwparam + sizeof(LPARAM) );
997 if (!ptr) return -1;
998 *ptr++ = *plparam; /* Store previous lParam */
999 *plparam = (LPARAM)ptr;
1001 return 1;
1003 case WM_SETTEXT:
1004 case WM_WININICHANGE:
1005 case WM_DEVMODECHANGE:
1006 case CB_DIR:
1007 case LB_DIR:
1008 case LB_ADDFILE:
1009 case EM_REPLACESEL:
1010 if(!*plparam) return 0;
1011 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
1012 return (*plparam ? 1 : -1);
1014 case WM_MDICREATE:
1016 MDICREATESTRUCTA *cs =
1017 (MDICREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
1018 if (!cs) return -1;
1019 *cs = *(MDICREATESTRUCTA *)*plparam;
1020 if (HIWORD(cs->szTitle))
1021 cs->szTitle = HEAP_strdupWtoA( GetProcessHeap(), 0,
1022 (LPCWSTR)cs->szTitle );
1023 if (HIWORD(cs->szClass))
1024 cs->szClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
1025 (LPCWSTR)cs->szClass );
1026 *plparam = (LPARAM)cs;
1028 return 1;
1030 /* Listbox */
1031 case LB_ADDSTRING:
1032 case LB_INSERTSTRING:
1033 case LB_FINDSTRING:
1034 case LB_FINDSTRINGEXACT:
1035 case LB_SELECTSTRING:
1036 if(!*plparam) return 0;
1037 if ( WINPROC_TestLBForStr( hwnd ))
1038 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
1039 return (*plparam ? 1 : -1);
1041 case LB_GETTEXT: /* FIXME: fixed sized buffer */
1042 { if ( WINPROC_TestLBForStr( hwnd ))
1043 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
1044 if (!ptr) return -1;
1045 *ptr++ = *plparam; /* Store previous lParam */
1046 *plparam = (LPARAM)ptr;
1049 return 1;
1051 /* Combobox */
1052 case CB_ADDSTRING:
1053 case CB_INSERTSTRING:
1054 case CB_FINDSTRING:
1055 case CB_FINDSTRINGEXACT:
1056 case CB_SELECTSTRING:
1057 if(!*plparam) return 0;
1058 if ( WINPROC_TestCBForStr( hwnd ))
1059 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
1060 return (*plparam ? 1 : -1);
1062 case CB_GETLBTEXT: /* FIXME: fixed sized buffer */
1063 { if ( WINPROC_TestCBForStr( hwnd ))
1064 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
1065 if (!ptr) return -1;
1066 *ptr++ = *plparam; /* Store previous lParam */
1067 *plparam = (LPARAM)ptr;
1070 return 1;
1072 /* Multiline edit */
1073 case EM_GETLINE:
1074 { WORD len = (WORD)*plparam;
1075 LPARAM *ptr = (LPARAM *) HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(CHAR) );
1076 if (!ptr) return -1;
1077 *ptr++ = *plparam; /* Store previous lParam */
1078 *((WORD *) ptr) = len; /* Store the length */
1079 *plparam = (LPARAM)ptr;
1081 return 1;
1083 case WM_CHARTOITEM:
1084 case WM_MENUCHAR:
1085 case WM_CHAR:
1086 case WM_DEADCHAR:
1087 case WM_SYSCHAR:
1088 case WM_SYSDEADCHAR:
1089 case EM_SETPASSWORDCHAR:
1091 WCHAR wch = LOWORD(*pwparam);
1092 BYTE ch;
1093 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL );
1094 *pwparam = MAKEWPARAM( ch, HIWORD(*pwparam) );
1096 return 0;
1098 case WM_IME_CHAR:
1100 WCHAR wch = LOWORD(*pwparam);
1101 BYTE ch[2];
1103 if (WideCharToMultiByte( CP_ACP, 0, &wch, 1, ch, 2, NULL, NULL ) == 2)
1104 *pwparam = MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(*pwparam) );
1105 else
1106 *pwparam = MAKEWPARAM( ch[0], HIWORD(*pwparam) );
1108 return 0;
1110 case WM_PAINTCLIPBOARD:
1111 case WM_SIZECLIPBOARD:
1112 FIXME_(msg)("message %s (%04x) needs translation, please report\n",SPY_GetMsgName(msg, hwnd),msg );
1113 return -1;
1114 default: /* No translation needed */
1115 return 0;
1120 /**********************************************************************
1121 * WINPROC_UnmapMsg32WTo32A
1123 * Unmap a message that was mapped from Unicode to Ansi.
1125 static LRESULT WINPROC_UnmapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT result )
1127 switch(msg)
1129 case WM_GETTEXT:
1130 case WM_ASKCBFORMATNAME:
1132 LPARAM *ptr = (LPARAM *)lParam - 1;
1133 if (!wParam) result = 0;
1134 else if (!(result = MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1,
1135 (LPWSTR)*ptr, wParam )))
1137 ((LPWSTR)*ptr)[wParam-1] = 0;
1138 result = wParam - 1;
1140 else result--; /* do not count terminating null */
1141 HeapFree( GetProcessHeap(), 0, ptr );
1143 break;
1145 case WM_SETTEXT:
1146 case WM_WININICHANGE:
1147 case WM_DEVMODECHANGE:
1148 case CB_DIR:
1149 case LB_DIR:
1150 case LB_ADDFILE:
1151 case EM_REPLACESEL:
1152 HeapFree( GetProcessHeap(), 0, (void *)lParam );
1153 break;
1155 case WM_MDICREATE:
1157 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1158 if (HIWORD(cs->szTitle))
1159 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
1160 if (HIWORD(cs->szClass))
1161 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
1162 HeapFree( GetProcessHeap(), 0, cs );
1164 break;
1166 /* Listbox */
1167 case LB_ADDSTRING:
1168 case LB_INSERTSTRING:
1169 case LB_FINDSTRING:
1170 case LB_FINDSTRINGEXACT:
1171 case LB_SELECTSTRING:
1172 if ( WINPROC_TestLBForStr( hwnd ))
1173 HeapFree( GetProcessHeap(), 0, (void *)lParam );
1174 break;
1176 case LB_GETTEXT:
1177 if ( WINPROC_TestLBForStr( hwnd ))
1179 LPARAM *ptr = (LPARAM *)lParam - 1;
1180 result = MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, 0x7fffffff ) - 1;
1181 HeapFree( GetProcessHeap(), 0, ptr );
1183 break;
1185 /* Combobox */
1186 case CB_ADDSTRING:
1187 case CB_INSERTSTRING:
1188 case CB_FINDSTRING:
1189 case CB_FINDSTRINGEXACT:
1190 case CB_SELECTSTRING:
1191 if ( WINPROC_TestCBForStr( hwnd ))
1192 HeapFree( GetProcessHeap(), 0, (void *)lParam );
1193 break;
1195 case CB_GETLBTEXT:
1196 if ( WINPROC_TestCBForStr( hwnd ))
1198 LPARAM *ptr = (LPARAM *)lParam - 1;
1199 result = MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, 0x7fffffff ) - 1;
1200 HeapFree( GetProcessHeap(), 0, ptr );
1202 break;
1204 /* Multiline edit */
1205 case EM_GETLINE:
1207 LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lparam */
1208 WORD len = *(WORD *)ptr;
1209 if (len)
1211 result = MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, result, (LPWSTR)*ptr, len );
1212 if (result < len) ((LPWSTR)*ptr)[result] = 0;
1214 HeapFree( GetProcessHeap(), 0, ptr );
1216 break;
1218 return result;
1221 static UINT convert_handle_16_to_32(HANDLE16 src, unsigned int flags)
1223 HANDLE dst;
1224 UINT sz = GlobalSize16(src);
1225 LPSTR ptr16, ptr32;
1227 if (!(dst = GlobalAlloc(flags, sz)))
1228 return 0;
1229 ptr16 = GlobalLock16(src);
1230 ptr32 = GlobalLock(dst);
1231 if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr32, ptr16, sz);
1232 GlobalUnlock16(src);
1233 GlobalUnlock(dst);
1235 return (UINT)dst;
1238 /**********************************************************************
1239 * WINPROC_MapMsg16To32A
1241 * Map a message from 16- to 32-bit Ansi.
1242 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1244 INT WINPROC_MapMsg16To32A( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1245 WPARAM *pwparam32, LPARAM *plparam )
1247 *pmsg32 = (UINT)msg16;
1248 *pwparam32 = (WPARAM)wParam16;
1249 switch(msg16)
1251 case WM_ACTIVATE:
1252 case WM_CHARTOITEM:
1253 case WM_COMMAND:
1254 case WM_VKEYTOITEM:
1255 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1256 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1257 return 0;
1258 case WM_HSCROLL:
1259 case WM_VSCROLL:
1260 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1261 *plparam = (LPARAM)WIN_Handle32( HIWORD(*plparam) );
1262 return 0;
1263 case WM_CTLCOLOR:
1264 if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
1265 *pmsg32 = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
1266 *pwparam32 = (WPARAM)HDC_32(wParam16);
1267 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1268 return 0;
1269 case WM_COMPAREITEM:
1271 COMPAREITEMSTRUCT16* cis16 = MapSL(*plparam);
1272 COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)
1273 HeapAlloc(GetProcessHeap(), 0, sizeof(*cis));
1274 if (!cis) return -1;
1275 cis->CtlType = cis16->CtlType;
1276 cis->CtlID = cis16->CtlID;
1277 cis->hwndItem = WIN_Handle32( cis16->hwndItem );
1278 cis->itemID1 = cis16->itemID1;
1279 cis->itemData1 = cis16->itemData1;
1280 cis->itemID2 = cis16->itemID2;
1281 cis->itemData2 = cis16->itemData2;
1282 cis->dwLocaleId = 0; /* FIXME */
1283 *plparam = (LPARAM)cis;
1285 return 1;
1286 case WM_DELETEITEM:
1288 DELETEITEMSTRUCT16* dis16 = MapSL(*plparam);
1289 DELETEITEMSTRUCT *dis = (DELETEITEMSTRUCT *)
1290 HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
1291 if (!dis) return -1;
1292 dis->CtlType = dis16->CtlType;
1293 dis->CtlID = dis16->CtlID;
1294 dis->hwndItem = WIN_Handle32( dis16->hwndItem );
1295 dis->itemData = dis16->itemData;
1296 *plparam = (LPARAM)dis;
1298 return 1;
1299 case WM_MEASUREITEM:
1301 MEASUREITEMSTRUCT16* mis16 = MapSL(*plparam);
1302 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)
1303 HeapAlloc(GetProcessHeap(), 0,
1304 sizeof(*mis) + sizeof(LPARAM));
1305 if (!mis) return -1;
1306 mis->CtlType = mis16->CtlType;
1307 mis->CtlID = mis16->CtlID;
1308 mis->itemID = mis16->itemID;
1309 mis->itemWidth = mis16->itemWidth;
1310 mis->itemHeight = mis16->itemHeight;
1311 mis->itemData = mis16->itemData;
1312 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
1313 *plparam = (LPARAM)mis;
1315 return 1;
1316 case WM_DRAWITEM:
1318 DRAWITEMSTRUCT16* dis16 = MapSL(*plparam);
1319 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT*)HeapAlloc(GetProcessHeap(), 0,
1320 sizeof(*dis));
1321 if (!dis) return -1;
1322 dis->CtlType = dis16->CtlType;
1323 dis->CtlID = dis16->CtlID;
1324 dis->itemID = dis16->itemID;
1325 dis->itemAction = dis16->itemAction;
1326 dis->itemState = dis16->itemState;
1327 dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND)HMENU_32(dis16->hwndItem)
1328 : WIN_Handle32( dis16->hwndItem );
1329 dis->hDC = HDC_32(dis16->hDC);
1330 dis->itemData = dis16->itemData;
1331 dis->rcItem.left = dis16->rcItem.left;
1332 dis->rcItem.top = dis16->rcItem.top;
1333 dis->rcItem.right = dis16->rcItem.right;
1334 dis->rcItem.bottom = dis16->rcItem.bottom;
1335 *plparam = (LPARAM)dis;
1337 return 1;
1338 case WM_GETMINMAXINFO:
1340 MINMAXINFO *mmi = (MINMAXINFO *)HeapAlloc( GetProcessHeap(), 0,
1341 sizeof(*mmi) + sizeof(LPARAM));
1342 if (!mmi) return -1;
1343 MINMAXINFO16to32( MapSL(*plparam), mmi );
1344 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
1345 *plparam = (LPARAM)mmi;
1347 return 1;
1348 case WM_GETTEXT:
1349 case WM_SETTEXT:
1350 case WM_WININICHANGE:
1351 case WM_DEVMODECHANGE:
1352 case WM_ASKCBFORMATNAME:
1353 *plparam = (LPARAM)MapSL(*plparam);
1354 return 0;
1355 case WM_MDICREATE:
1357 MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1358 MDICREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1359 if (!cs) return -1;
1360 MDICREATESTRUCT16to32A( cs16, cs );
1361 cs->szTitle = MapSL(cs16->szTitle);
1362 cs->szClass = MapSL(cs16->szClass);
1363 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1364 *plparam = (LPARAM)cs;
1366 return 1;
1367 case WM_MDIGETACTIVE:
1368 *plparam = (LPARAM)HeapAlloc( GetProcessHeap(), 0, sizeof(BOOL) );
1369 *(BOOL*)(*plparam) = 0;
1370 return 1;
1371 case WM_MDISETMENU:
1372 if(wParam16==TRUE)
1373 *pmsg32=WM_MDIREFRESHMENU;
1374 *pwparam32 = (WPARAM)HMENU_32(LOWORD(*plparam));
1375 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1376 return 0;
1377 case WM_MENUCHAR:
1378 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1379 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1380 return 0;
1381 case WM_MENUSELECT:
1382 if((LOWORD(*plparam) & MF_POPUP) && (LOWORD(*plparam) != 0xFFFF))
1384 HMENU hmenu=HMENU_32(HIWORD(*plparam));
1385 UINT Pos=MENU_FindSubMenu( &hmenu, HMENU_32(wParam16));
1386 if(Pos==0xFFFF) Pos=0; /* NO_SELECTED_ITEM */
1387 *pwparam32 = MAKEWPARAM( Pos, LOWORD(*plparam) );
1389 else *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1390 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1391 return 0;
1392 case WM_MDIACTIVATE:
1393 if( *plparam )
1395 *pwparam32 = (WPARAM)WIN_Handle32( HIWORD(*plparam) );
1396 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1398 else /* message sent to MDI client */
1399 *pwparam32 = wParam16;
1400 return 0;
1401 case WM_NCCALCSIZE:
1403 NCCALCSIZE_PARAMS16 *nc16;
1404 NCCALCSIZE_PARAMS *nc;
1406 nc = (NCCALCSIZE_PARAMS *)HeapAlloc( GetProcessHeap(), 0,
1407 sizeof(*nc) + sizeof(LPARAM) );
1408 if (!nc) return -1;
1409 nc16 = MapSL(*plparam);
1410 nc->rgrc[0].left = nc16->rgrc[0].left;
1411 nc->rgrc[0].top = nc16->rgrc[0].top;
1412 nc->rgrc[0].right = nc16->rgrc[0].right;
1413 nc->rgrc[0].bottom = nc16->rgrc[0].bottom;
1414 if (wParam16)
1416 nc->lppos = (WINDOWPOS *)HeapAlloc( GetProcessHeap(), 0,
1417 sizeof(*nc->lppos) );
1418 nc->rgrc[1].left = nc16->rgrc[1].left;
1419 nc->rgrc[1].top = nc16->rgrc[1].top;
1420 nc->rgrc[1].right = nc16->rgrc[1].right;
1421 nc->rgrc[1].bottom = nc16->rgrc[1].bottom;
1422 nc->rgrc[2].left = nc16->rgrc[2].left;
1423 nc->rgrc[2].top = nc16->rgrc[2].top;
1424 nc->rgrc[2].right = nc16->rgrc[2].right;
1425 nc->rgrc[2].bottom = nc16->rgrc[2].bottom;
1426 if (nc->lppos) WINDOWPOS16to32( MapSL(nc16->lppos), nc->lppos );
1428 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
1429 *plparam = (LPARAM)nc;
1431 return 1;
1432 case WM_NCCREATE:
1433 case WM_CREATE:
1435 CREATESTRUCT16 *cs16 = MapSL(*plparam);
1436 CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
1437 sizeof(*cs) + sizeof(LPARAM) );
1438 if (!cs) return -1;
1439 CREATESTRUCT16to32A( cs16, cs );
1440 cs->lpszName = MapSL(cs16->lpszName);
1441 cs->lpszClass = MapSL(cs16->lpszClass);
1443 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1445 MDICREATESTRUCT16 *mdi_cs16;
1446 MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)HeapAlloc(GetProcessHeap(), 0,
1447 sizeof(*mdi_cs));
1448 if (!mdi_cs)
1450 HeapFree(GetProcessHeap(), 0, cs);
1451 return -1;
1453 mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs16->lpCreateParams);
1454 MDICREATESTRUCT16to32A(mdi_cs16, mdi_cs);
1455 mdi_cs->szTitle = MapSL(mdi_cs16->szTitle);
1456 mdi_cs->szClass = MapSL(mdi_cs16->szClass);
1458 cs->lpCreateParams = mdi_cs;
1460 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1461 *plparam = (LPARAM)cs;
1463 return 1;
1464 case WM_PARENTNOTIFY:
1465 if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
1467 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1468 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1470 return 0;
1471 case WM_WINDOWPOSCHANGING:
1472 case WM_WINDOWPOSCHANGED:
1474 WINDOWPOS *wp = (WINDOWPOS *)HeapAlloc( GetProcessHeap(), 0,
1475 sizeof(*wp) + sizeof(LPARAM) );
1476 if (!wp) return -1;
1477 WINDOWPOS16to32( MapSL(*plparam), wp );
1478 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
1479 *plparam = (LPARAM)wp;
1481 return 1;
1482 case WM_GETDLGCODE:
1483 if (*plparam)
1485 LPMSG16 msg16 = MapSL(*plparam);
1486 LPMSG msg32 = (LPMSG)HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1488 if (!msg32) return -1;
1489 msg32->hwnd = WIN_Handle32( msg16->hwnd );
1490 msg32->lParam = msg16->lParam;
1491 msg32->time = msg16->time;
1492 msg32->pt.x = msg16->pt.x;
1493 msg32->pt.y = msg16->pt.y;
1494 /* this is right, right? */
1495 if (WINPROC_MapMsg16To32A( msg32->hwnd, msg16->message,msg16->wParam,
1496 &msg32->message,&msg32->wParam,
1497 &msg32->lParam)<0) {
1498 HeapFree( GetProcessHeap(), 0, msg32 );
1499 return -1;
1501 *plparam = (LPARAM)msg32;
1502 return 1;
1504 else return 0;
1505 case WM_NOTIFY:
1506 *plparam = (LPARAM)MapSL(*plparam);
1507 return 0;
1508 case WM_ACTIVATEAPP:
1509 /* We need this when SetActiveWindow sends a Sendmessage16() to
1510 * a 32bit window. Might be superflous with 32bit interprocess
1511 * message queues. */
1512 if (*plparam) *plparam = HTASK_32( *plparam );
1513 return 0;
1514 case WM_NEXTMENU:
1516 MDINEXTMENU *next = HeapAlloc( GetProcessHeap(), 0, sizeof(*next) );
1517 if (!next) return -1;
1518 next->hmenuIn = (HMENU)*plparam;
1519 next->hmenuNext = 0;
1520 next->hwndNext = 0;
1521 *plparam = (LPARAM)next;
1522 return 1;
1524 case WM_PAINTCLIPBOARD:
1525 case WM_SIZECLIPBOARD:
1526 FIXME_(msg)("message %04x needs translation\n",msg16 );
1527 return -1;
1528 case WM_DDE_INITIATE:
1529 case WM_DDE_TERMINATE:
1530 case WM_DDE_UNADVISE:
1531 case WM_DDE_REQUEST:
1532 *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1533 return 0;
1534 case WM_DDE_ADVISE:
1535 case WM_DDE_DATA:
1536 case WM_DDE_POKE:
1538 HANDLE16 lo16;
1539 ATOM hi;
1540 UINT lo32 = 0;
1542 *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1543 lo16 = LOWORD(*plparam);
1544 hi = HIWORD(*plparam);
1545 if (lo16 && !(lo32 = convert_handle_16_to_32(lo16, GMEM_DDESHARE)))
1546 return -1;
1547 *plparam = PackDDElParam(msg16, lo32, hi);
1549 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1550 case WM_DDE_ACK:
1552 UINT lo, hi;
1553 int flag = 0;
1554 char buf[2];
1556 *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1558 lo = LOWORD(*plparam);
1559 hi = HIWORD(*plparam);
1561 if (GlobalGetAtomNameA(hi, buf, 2) > 0) flag |= 1;
1562 if (GlobalSize16(hi) != 0) flag |= 2;
1563 switch (flag)
1565 case 0:
1566 if (hi)
1568 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1569 hi = 0;
1571 break;
1572 case 1:
1573 break; /* atom, nothing to do */
1574 case 3:
1575 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
1576 /* fall thru */
1577 case 2:
1578 hi = convert_handle_16_to_32(hi, GMEM_DDESHARE);
1579 break;
1581 *plparam = PackDDElParam(WM_DDE_ACK, lo, hi);
1583 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1584 case WM_DDE_EXECUTE:
1585 *plparam = convert_handle_16_to_32(*plparam, GMEM_DDESHARE);
1586 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1587 default: /* No translation needed */
1588 return 0;
1593 /**********************************************************************
1594 * WINPROC_UnmapMsg16To32A
1596 * Unmap a message that was mapped from 16- to 32-bit Ansi.
1598 LRESULT WINPROC_UnmapMsg16To32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1599 LRESULT result )
1601 switch(msg)
1603 case WM_COMPAREITEM:
1604 case WM_DELETEITEM:
1605 case WM_DRAWITEM:
1606 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
1607 break;
1608 case WM_MEASUREITEM:
1610 MEASUREITEMSTRUCT16 *mis16;
1611 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam;
1612 lParam = *(LPARAM *)(mis + 1);
1613 mis16 = MapSL(lParam);
1614 mis16->itemWidth = (UINT16)mis->itemWidth;
1615 mis16->itemHeight = (UINT16)mis->itemHeight;
1616 HeapFree( GetProcessHeap(), 0, mis );
1618 break;
1619 case WM_GETMINMAXINFO:
1621 MINMAXINFO *mmi = (MINMAXINFO *)lParam;
1622 lParam = *(LPARAM *)(mmi + 1);
1623 MINMAXINFO32to16( mmi, MapSL(lParam));
1624 HeapFree( GetProcessHeap(), 0, mmi );
1626 break;
1627 case WM_MDICREATE:
1629 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1630 lParam = *(LPARAM *)(cs + 1);
1631 MDICREATESTRUCT32Ato16( cs, MapSL(lParam) );
1632 HeapFree( GetProcessHeap(), 0, cs );
1634 break;
1635 case WM_MDIGETACTIVE:
1636 result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL *)lParam) );
1637 HeapFree( GetProcessHeap(), 0, (BOOL *)lParam );
1638 break;
1639 case WM_NCCALCSIZE:
1641 NCCALCSIZE_PARAMS16 *nc16;
1642 NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lParam;
1643 lParam = *(LPARAM *)(nc + 1);
1644 nc16 = MapSL(lParam);
1645 nc16->rgrc[0].left = nc->rgrc[0].left;
1646 nc16->rgrc[0].top = nc->rgrc[0].top;
1647 nc16->rgrc[0].right = nc->rgrc[0].right;
1648 nc16->rgrc[0].bottom = nc->rgrc[0].bottom;
1649 if (wParam)
1651 nc16->rgrc[1].left = nc->rgrc[1].left;
1652 nc16->rgrc[1].top = nc->rgrc[1].top;
1653 nc16->rgrc[1].right = nc->rgrc[1].right;
1654 nc16->rgrc[1].bottom = nc->rgrc[1].bottom;
1655 nc16->rgrc[2].left = nc->rgrc[2].left;
1656 nc16->rgrc[2].top = nc->rgrc[2].top;
1657 nc16->rgrc[2].right = nc->rgrc[2].right;
1658 nc16->rgrc[2].bottom = nc->rgrc[2].bottom;
1659 if (nc->lppos)
1661 WINDOWPOS32to16( nc->lppos, MapSL(nc16->lppos));
1662 HeapFree( GetProcessHeap(), 0, nc->lppos );
1665 HeapFree( GetProcessHeap(), 0, nc );
1667 break;
1668 case WM_NCCREATE:
1669 case WM_CREATE:
1671 CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1672 lParam = *(LPARAM *)(cs + 1);
1673 CREATESTRUCT32Ato16( cs, MapSL(lParam) );
1675 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1676 HeapFree(GetProcessHeap(), 0, cs->lpCreateParams);
1678 HeapFree( GetProcessHeap(), 0, cs );
1680 break;
1681 case WM_WINDOWPOSCHANGING:
1682 case WM_WINDOWPOSCHANGED:
1684 WINDOWPOS *wp = (WINDOWPOS *)lParam;
1685 lParam = *(LPARAM *)(wp + 1);
1686 WINDOWPOS32to16(wp, MapSL(lParam));
1687 HeapFree( GetProcessHeap(), 0, wp );
1689 break;
1690 case WM_GETDLGCODE:
1691 if (lParam)
1693 LPMSG msg32 = (LPMSG)lParam;
1695 WINPROC_UnmapMsg16To32A( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1696 result);
1697 HeapFree( GetProcessHeap(), 0, msg32 );
1699 break;
1700 case WM_NEXTMENU:
1702 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
1703 result = MAKELONG( HMENU_16(next->hmenuNext), HWND_16(next->hwndNext) );
1704 HeapFree( GetProcessHeap(), 0, next );
1706 break;
1708 return result;
1712 /**********************************************************************
1713 * WINPROC_MapMsg16To32W
1715 * Map a message from 16- to 32-bit Unicode.
1716 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1718 INT WINPROC_MapMsg16To32W( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1719 WPARAM *pwparam32, LPARAM *plparam )
1721 BYTE ch;
1722 WCHAR wch;
1724 *pmsg32=(UINT)msg16;
1725 *pwparam32 = (WPARAM)wParam16;
1726 switch(msg16)
1728 case WM_GETTEXT:
1729 case WM_SETTEXT:
1730 case WM_WININICHANGE:
1731 case WM_DEVMODECHANGE:
1732 case WM_ASKCBFORMATNAME:
1733 *plparam = (LPARAM)MapSL(*plparam);
1734 return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, pwparam32, plparam );
1735 case WM_GETTEXTLENGTH:
1736 case CB_GETLBTEXTLEN:
1737 case LB_GETTEXTLEN:
1738 return 1; /* need to map result */
1739 case WM_NCCREATE:
1740 case WM_CREATE:
1742 CREATESTRUCT16 *cs16 = MapSL(*plparam);
1743 CREATESTRUCTW *cs = (CREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
1744 sizeof(*cs) + sizeof(LPARAM) );
1745 if (!cs) return -1;
1746 CREATESTRUCT16to32A( cs16, (CREATESTRUCTA *)cs );
1747 cs->lpszName = map_str_16_to_32W(cs16->lpszName);
1748 cs->lpszClass = map_str_16_to_32W(cs16->lpszClass);
1750 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1752 MDICREATESTRUCT16 *mdi_cs16;
1753 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)HeapAlloc(GetProcessHeap(), 0,
1754 sizeof(*mdi_cs));
1755 if (!mdi_cs)
1757 HeapFree(GetProcessHeap(), 0, cs);
1758 return -1;
1760 mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs16->lpCreateParams);
1761 MDICREATESTRUCT16to32A(mdi_cs16, (MDICREATESTRUCTA *)mdi_cs);
1762 mdi_cs->szTitle = map_str_16_to_32W(mdi_cs16->szTitle);
1763 mdi_cs->szClass = map_str_16_to_32W(mdi_cs16->szClass);
1765 cs->lpCreateParams = mdi_cs;
1767 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1768 *plparam = (LPARAM)cs;
1770 return 1;
1771 case WM_MDICREATE:
1773 MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1774 MDICREATESTRUCTW *cs =
1775 (MDICREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
1776 sizeof(*cs) + sizeof(LPARAM) );
1777 if (!cs) return -1;
1778 MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCTA *)cs );
1779 cs->szTitle = map_str_16_to_32W(cs16->szTitle);
1780 cs->szClass = map_str_16_to_32W(cs16->szClass);
1781 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1782 *plparam = (LPARAM)cs;
1784 return 1;
1785 case WM_GETDLGCODE:
1786 if (*plparam)
1788 LPMSG16 msg16 = MapSL(*plparam);
1789 LPMSG msg32 = (LPMSG)HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1791 if (!msg32) return -1;
1792 msg32->hwnd = WIN_Handle32( msg16->hwnd );
1793 msg32->lParam = msg16->lParam;
1794 msg32->time = msg16->time;
1795 msg32->pt.x = msg16->pt.x;
1796 msg32->pt.y = msg16->pt.y;
1797 /* this is right, right? */
1798 if (WINPROC_MapMsg16To32W(hwnd, msg16->message,msg16->wParam,
1799 &msg32->message,&msg32->wParam,
1800 &msg32->lParam)<0) {
1801 HeapFree( GetProcessHeap(), 0, msg32 );
1802 return -1;
1804 *plparam = (LPARAM)msg32;
1805 return 1;
1807 else return 0;
1809 case WM_CHARTOITEM:
1810 ch = wParam16;
1811 MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1812 *pwparam32 = MAKEWPARAM( wch, HIWORD(*plparam) );
1813 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1814 return 0;
1815 case WM_MENUCHAR:
1816 ch = wParam16;
1817 MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1818 *pwparam32 = MAKEWPARAM( wch, LOWORD(*plparam) );
1819 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1820 return 0;
1821 case WM_CHAR:
1822 case WM_DEADCHAR:
1823 case WM_SYSCHAR:
1824 case WM_SYSDEADCHAR:
1825 ch = wParam16;
1826 MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1827 *pwparam32 = wch;
1828 return 0;
1829 case WM_IME_CHAR:
1830 return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, pwparam32, plparam );
1832 default: /* No Unicode translation needed */
1833 return WINPROC_MapMsg16To32A( hwnd, msg16, wParam16, pmsg32,
1834 pwparam32, plparam );
1839 /**********************************************************************
1840 * WINPROC_UnmapMsg16To32W
1842 * Unmap a message that was mapped from 16- to 32-bit Unicode.
1844 LRESULT WINPROC_UnmapMsg16To32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1845 LRESULT result )
1847 switch(msg)
1849 case WM_GETTEXT:
1850 case WM_SETTEXT:
1851 case WM_GETTEXTLENGTH:
1852 case CB_GETLBTEXTLEN:
1853 case LB_GETTEXTLEN:
1854 case WM_ASKCBFORMATNAME:
1855 return WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result );
1856 case WM_NCCREATE:
1857 case WM_CREATE:
1859 CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
1860 lParam = *(LPARAM *)(cs + 1);
1861 CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs, MapSL(lParam) );
1862 unmap_str_16_to_32W( cs->lpszName );
1863 unmap_str_16_to_32W( cs->lpszClass );
1865 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1867 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)cs->lpCreateParams;
1868 unmap_str_16_to_32W( mdi_cs->szTitle );
1869 unmap_str_16_to_32W( mdi_cs->szClass );
1870 HeapFree(GetProcessHeap(), 0, cs->lpCreateParams);
1872 HeapFree( GetProcessHeap(), 0, cs );
1874 break;
1875 case WM_MDICREATE:
1877 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
1878 lParam = *(LPARAM *)(cs + 1);
1879 MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs, MapSL(lParam) );
1880 unmap_str_16_to_32W( cs->szTitle );
1881 unmap_str_16_to_32W( cs->szClass );
1882 HeapFree( GetProcessHeap(), 0, cs );
1884 break;
1885 case WM_GETDLGCODE:
1886 if (lParam)
1888 LPMSG msg32 = (LPMSG)lParam;
1890 WINPROC_UnmapMsg16To32W( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1891 result);
1892 HeapFree( GetProcessHeap(), 0, msg32 );
1894 break;
1895 default:
1896 return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1898 return result;
1901 static HANDLE16 convert_handle_32_to_16(UINT src, unsigned int flags)
1903 HANDLE16 dst;
1904 UINT sz = GlobalSize((HANDLE)src);
1905 LPSTR ptr16, ptr32;
1907 if (!(dst = GlobalAlloc16(flags, sz)))
1908 return 0;
1909 ptr32 = GlobalLock((HANDLE)src);
1910 ptr16 = GlobalLock16(dst);
1911 if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr16, ptr32, sz);
1912 GlobalUnlock((HANDLE)src);
1913 GlobalUnlock16(dst);
1915 return dst;
1919 /**********************************************************************
1920 * WINPROC_MapMsg32ATo16
1922 * Map a message from 32-bit Ansi to 16-bit.
1923 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1925 INT WINPROC_MapMsg32ATo16( HWND hwnd, UINT msg32, WPARAM wParam32,
1926 UINT16 *pmsg16, WPARAM16 *pwparam16,
1927 LPARAM *plparam )
1929 *pmsg16 = (UINT16)msg32;
1930 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1931 switch(msg32)
1933 case SBM_SETRANGE:
1934 *pmsg16 = SBM_SETRANGE16;
1935 *plparam = MAKELPARAM(wParam32, *plparam);
1936 *pwparam16 = 0;
1937 return 0;
1939 case SBM_GETRANGE:
1940 *pmsg16 = SBM_GETRANGE16;
1941 return 1;
1943 case BM_GETCHECK:
1944 case BM_SETCHECK:
1945 case BM_GETSTATE:
1946 case BM_SETSTATE:
1947 case BM_SETSTYLE:
1948 *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK);
1949 return 0;
1951 case EM_GETSEL:
1952 case EM_GETRECT:
1953 case EM_SETRECT:
1954 case EM_SETRECTNP:
1955 case EM_SCROLL:
1956 case EM_LINESCROLL:
1957 case EM_SCROLLCARET:
1958 case EM_GETMODIFY:
1959 case EM_SETMODIFY:
1960 case EM_GETLINECOUNT:
1961 case EM_LINEINDEX:
1962 case EM_SETHANDLE:
1963 case EM_GETHANDLE:
1964 case EM_GETTHUMB:
1965 case EM_LINELENGTH:
1966 case EM_REPLACESEL:
1967 case EM_GETLINE:
1968 case EM_LIMITTEXT:
1969 case EM_CANUNDO:
1970 case EM_UNDO:
1971 case EM_FMTLINES:
1972 case EM_LINEFROMCHAR:
1973 case EM_SETTABSTOPS:
1974 case EM_SETPASSWORDCHAR:
1975 case EM_EMPTYUNDOBUFFER:
1976 case EM_GETFIRSTVISIBLELINE:
1977 case EM_SETREADONLY:
1978 case EM_SETWORDBREAKPROC:
1979 case EM_GETWORDBREAKPROC:
1980 case EM_GETPASSWORDCHAR:
1981 *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL);
1982 return 0;
1984 case LB_CARETOFF:
1985 case LB_CARETON:
1986 case LB_DELETESTRING:
1987 case LB_GETANCHORINDEX:
1988 case LB_GETCARETINDEX:
1989 case LB_GETCOUNT:
1990 case LB_GETCURSEL:
1991 case LB_GETHORIZONTALEXTENT:
1992 case LB_GETITEMDATA:
1993 case LB_GETITEMHEIGHT:
1994 case LB_GETSEL:
1995 case LB_GETSELCOUNT:
1996 case LB_GETTEXTLEN:
1997 case LB_GETTOPINDEX:
1998 case LB_RESETCONTENT:
1999 case LB_SELITEMRANGE:
2000 case LB_SELITEMRANGEEX:
2001 case LB_SETANCHORINDEX:
2002 case LB_SETCARETINDEX:
2003 case LB_SETCOLUMNWIDTH:
2004 case LB_SETCURSEL:
2005 case LB_SETHORIZONTALEXTENT:
2006 case LB_SETITEMDATA:
2007 case LB_SETITEMHEIGHT:
2008 case LB_SETSEL:
2009 case LB_SETTOPINDEX:
2010 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2011 return 0;
2012 case CB_DELETESTRING:
2013 case CB_GETCOUNT:
2014 case CB_GETLBTEXTLEN:
2015 case CB_LIMITTEXT:
2016 case CB_RESETCONTENT:
2017 case CB_SETEDITSEL:
2018 case CB_GETCURSEL:
2019 case CB_SETCURSEL:
2020 case CB_SHOWDROPDOWN:
2021 case CB_SETITEMDATA:
2022 case CB_SETITEMHEIGHT:
2023 case CB_GETITEMHEIGHT:
2024 case CB_SETEXTENDEDUI:
2025 case CB_GETEXTENDEDUI:
2026 case CB_GETDROPPEDSTATE:
2027 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
2028 return 0;
2029 case CB_GETEDITSEL:
2030 *pmsg16 = CB_GETEDITSEL16;
2031 return 1;
2033 case LB_ADDSTRING:
2034 case LB_FINDSTRING:
2035 case LB_FINDSTRINGEXACT:
2036 case LB_INSERTSTRING:
2037 case LB_SELECTSTRING:
2038 case LB_DIR:
2039 case LB_ADDFILE:
2040 *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
2041 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2042 return 1;
2044 case CB_ADDSTRING:
2045 case CB_FINDSTRING:
2046 case CB_FINDSTRINGEXACT:
2047 case CB_INSERTSTRING:
2048 case CB_SELECTSTRING:
2049 case CB_DIR:
2050 *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
2051 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
2052 return 1;
2054 case LB_GETITEMRECT:
2056 RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
2057 if (!rect) return -1;
2058 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
2059 *plparam = MapLS( rect );
2061 *pmsg16 = LB_GETITEMRECT16;
2062 return 1;
2063 case LB_GETSELITEMS:
2065 LPARAM *items; /* old LPARAM first, then *pwparam16 x INT16 entries */
2067 *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
2068 if (!(items = HeapAlloc( GetProcessHeap(), 0,
2069 *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
2070 *items++ = *plparam; /* Store the previous lParam */
2071 *plparam = MapLS( items );
2073 *pmsg16 = LB_GETSELITEMS16;
2074 return 1;
2075 case LB_SETTABSTOPS:
2076 if (wParam32)
2078 INT i;
2079 LPINT16 stops;
2080 *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
2081 if (!(stops = HeapAlloc( GetProcessHeap(), 0,
2082 *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
2083 for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT)*plparam+i);
2084 *plparam = MapLS( stops );
2085 return 1;
2087 *pmsg16 = LB_SETTABSTOPS16;
2088 return 0;
2090 case CB_GETDROPPEDCONTROLRECT:
2092 RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
2093 if (!rect) return -1;
2094 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
2095 *plparam = (LPARAM)MapLS(rect);
2097 *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
2098 return 1;
2100 case LB_GETTEXT:
2101 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
2102 *pmsg16 = LB_GETTEXT16;
2103 return 1;
2105 case CB_GETLBTEXT:
2106 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
2107 *pmsg16 = CB_GETLBTEXT16;
2108 return 1;
2110 case EM_SETSEL:
2111 *pwparam16 = 0;
2112 *plparam = MAKELONG( (INT16)(INT)wParam32, (INT16)*plparam );
2113 *pmsg16 = EM_SETSEL16;
2114 return 0;
2116 case WM_ACTIVATE:
2117 case WM_CHARTOITEM:
2118 case WM_COMMAND:
2119 case WM_VKEYTOITEM:
2120 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2121 return 0;
2122 case WM_HSCROLL:
2123 case WM_VSCROLL:
2124 *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
2125 return 0;
2126 case WM_CTLCOLORMSGBOX:
2127 case WM_CTLCOLOREDIT:
2128 case WM_CTLCOLORLISTBOX:
2129 case WM_CTLCOLORBTN:
2130 case WM_CTLCOLORDLG:
2131 case WM_CTLCOLORSCROLLBAR:
2132 case WM_CTLCOLORSTATIC:
2133 *pmsg16 = WM_CTLCOLOR;
2134 *plparam = MAKELPARAM( (HWND16)*plparam,
2135 (WORD)msg32 - WM_CTLCOLORMSGBOX );
2136 return 0;
2137 case WM_COMPAREITEM:
2139 COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)*plparam;
2140 COMPAREITEMSTRUCT16 *cis = HeapAlloc( GetProcessHeap(), 0, sizeof(COMPAREITEMSTRUCT16));
2141 if (!cis) return -1;
2142 cis->CtlType = (UINT16)cis32->CtlType;
2143 cis->CtlID = (UINT16)cis32->CtlID;
2144 cis->hwndItem = HWND_16( cis32->hwndItem );
2145 cis->itemID1 = (UINT16)cis32->itemID1;
2146 cis->itemData1 = cis32->itemData1;
2147 cis->itemID2 = (UINT16)cis32->itemID2;
2148 cis->itemData2 = cis32->itemData2;
2149 *plparam = MapLS( cis );
2151 return 1;
2152 case WM_DELETEITEM:
2154 DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)*plparam;
2155 DELETEITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DELETEITEMSTRUCT16) );
2156 if (!dis) return -1;
2157 dis->CtlType = (UINT16)dis32->CtlType;
2158 dis->CtlID = (UINT16)dis32->CtlID;
2159 dis->itemID = (UINT16)dis32->itemID;
2160 dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem)
2161 : HWND_16( dis32->hwndItem );
2162 dis->itemData = dis32->itemData;
2163 *plparam = MapLS( dis );
2165 return 1;
2166 case WM_DRAWITEM:
2168 DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)*plparam;
2169 DRAWITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DRAWITEMSTRUCT16) );
2170 if (!dis) return -1;
2171 dis->CtlType = (UINT16)dis32->CtlType;
2172 dis->CtlID = (UINT16)dis32->CtlID;
2173 dis->itemID = (UINT16)dis32->itemID;
2174 dis->itemAction = (UINT16)dis32->itemAction;
2175 dis->itemState = (UINT16)dis32->itemState;
2176 dis->hwndItem = HWND_16( dis32->hwndItem );
2177 dis->hDC = HDC_16(dis32->hDC);
2178 dis->itemData = dis32->itemData;
2179 dis->rcItem.left = dis32->rcItem.left;
2180 dis->rcItem.top = dis32->rcItem.top;
2181 dis->rcItem.right = dis32->rcItem.right;
2182 dis->rcItem.bottom = dis32->rcItem.bottom;
2183 *plparam = MapLS( dis );
2185 return 1;
2186 case WM_MEASUREITEM:
2188 MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)*plparam;
2189 MEASUREITEMSTRUCT16 *mis = HeapAlloc( GetProcessHeap(), 0, sizeof(*mis)+sizeof(LPARAM));
2190 if (!mis) return -1;
2191 mis->CtlType = (UINT16)mis32->CtlType;
2192 mis->CtlID = (UINT16)mis32->CtlID;
2193 mis->itemID = (UINT16)mis32->itemID;
2194 mis->itemWidth = (UINT16)mis32->itemWidth;
2195 mis->itemHeight = (UINT16)mis32->itemHeight;
2196 mis->itemData = mis32->itemData;
2197 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
2198 *plparam = MapLS( mis );
2200 return 1;
2201 case WM_GETMINMAXINFO:
2203 MINMAXINFO16 *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM) );
2204 if (!mmi) return -1;
2205 MINMAXINFO32to16( (MINMAXINFO *)*plparam, mmi );
2206 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
2207 *plparam = MapLS( mmi );
2209 return 1;
2210 case WM_GETTEXT:
2211 case WM_ASKCBFORMATNAME:
2213 LPARAM *str; /* store LPARAM, then *pwparam16 char space */
2214 *pwparam16 = (WPARAM16)min( wParam32, 0xff80 ); /* Must be < 64K */
2215 if (!(str = HeapAlloc( GetProcessHeap(), 0, *pwparam16 + sizeof(LPARAM)))) return -1;
2216 *str++ = *plparam; /* Store the previous lParam */
2217 *plparam = MapLS( str );
2219 return 1;
2220 case WM_MDICREATE:
2222 MDICREATESTRUCT16 *cs;
2223 MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)*plparam;
2225 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2226 MDICREATESTRUCT32Ato16( cs32, cs );
2227 cs->szTitle = MapLS( cs32->szTitle );
2228 cs->szClass = MapLS( cs32->szClass );
2229 *plparam = MapLS( cs );
2231 return 1;
2232 case WM_MDIGETACTIVE:
2233 return 1;
2234 case WM_MDISETMENU:
2235 *plparam = MAKELPARAM( (HMENU16)LOWORD(wParam32),
2236 (HMENU16)LOWORD(*plparam) );
2237 *pwparam16 = (*plparam == 0);
2238 return 0;
2239 case WM_MENUSELECT:
2240 if(HIWORD(wParam32) & MF_POPUP)
2242 HMENU hmenu;
2243 if (((UINT)HIWORD(wParam32) != 0xFFFF) || (*plparam))
2245 if((hmenu = GetSubMenu((HMENU)*plparam, *pwparam16)))
2246 *pwparam16=HMENU_16(hmenu);
2249 /* fall through */
2250 case WM_MENUCHAR:
2251 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2252 return 0;
2253 case WM_MDIACTIVATE:
2254 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
2256 *pwparam16 = ((HWND)*plparam == hwnd);
2257 *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
2258 (HWND16)LOWORD(wParam32) );
2260 else
2262 *pwparam16 = HWND_16( (HWND)wParam32 );
2263 *plparam = 0;
2265 return 0;
2266 case WM_NCCALCSIZE:
2268 NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)*plparam;
2269 NCCALCSIZE_PARAMS16 *nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM));
2270 if (!nc) return -1;
2272 nc->rgrc[0].left = nc32->rgrc[0].left;
2273 nc->rgrc[0].top = nc32->rgrc[0].top;
2274 nc->rgrc[0].right = nc32->rgrc[0].right;
2275 nc->rgrc[0].bottom = nc32->rgrc[0].bottom;
2276 if (wParam32)
2278 WINDOWPOS16 *wp;
2279 nc->rgrc[1].left = nc32->rgrc[1].left;
2280 nc->rgrc[1].top = nc32->rgrc[1].top;
2281 nc->rgrc[1].right = nc32->rgrc[1].right;
2282 nc->rgrc[1].bottom = nc32->rgrc[1].bottom;
2283 nc->rgrc[2].left = nc32->rgrc[2].left;
2284 nc->rgrc[2].top = nc32->rgrc[2].top;
2285 nc->rgrc[2].right = nc32->rgrc[2].right;
2286 nc->rgrc[2].bottom = nc32->rgrc[2].bottom;
2287 if (!(wp = HeapAlloc( GetProcessHeap(), 0, sizeof(WINDOWPOS16) )))
2289 HeapFree( GetProcessHeap(), 0, nc );
2290 return -1;
2292 WINDOWPOS32to16( nc32->lppos, wp );
2293 nc->lppos = MapLS( wp );
2295 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
2296 *plparam = MapLS( nc );
2298 return 1;
2299 case WM_NCCREATE:
2300 case WM_CREATE:
2302 CREATESTRUCT16 *cs;
2303 CREATESTRUCTA *cs32 = (CREATESTRUCTA *)*plparam;
2305 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2306 CREATESTRUCT32Ato16( cs32, cs );
2307 cs->lpszName = MapLS( cs32->lpszName );
2308 cs->lpszClass = MapLS( cs32->lpszClass );
2310 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2312 MDICREATESTRUCT16 *mdi_cs16;
2313 MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs32->lpCreateParams;
2314 mdi_cs16 = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs16));
2315 if (!mdi_cs16)
2317 HeapFree(GetProcessHeap(), 0, cs);
2318 return -1;
2320 MDICREATESTRUCT32Ato16(mdi_cs, mdi_cs16);
2321 mdi_cs16->szTitle = MapLS( mdi_cs->szTitle );
2322 mdi_cs16->szClass = MapLS( mdi_cs->szClass );
2323 cs->lpCreateParams = MapLS( mdi_cs16 );
2325 *plparam = MapLS( cs );
2327 return 1;
2328 case WM_PARENTNOTIFY:
2329 if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
2330 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
2331 /* else nothing to do */
2332 return 0;
2333 case WM_NOTIFY:
2334 *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
2335 return 1;
2336 case WM_SETTEXT:
2337 case WM_WININICHANGE:
2338 case WM_DEVMODECHANGE:
2339 *plparam = MapLS( (LPSTR)*plparam );
2340 return 1;
2341 case WM_WINDOWPOSCHANGING:
2342 case WM_WINDOWPOSCHANGED:
2344 WINDOWPOS16 *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
2345 if (!wp) return -1;
2346 WINDOWPOS32to16( (WINDOWPOS *)*plparam, wp );
2347 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
2348 *plparam = MapLS( wp );
2350 return 1;
2351 case WM_GETDLGCODE:
2352 if (*plparam) {
2353 LPMSG msg32 = (LPMSG) *plparam;
2354 LPMSG16 msg16 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG16) );
2356 if (!msg16) return -1;
2357 msg16->hwnd = HWND_16( msg32->hwnd );
2358 msg16->lParam = msg32->lParam;
2359 msg16->time = msg32->time;
2360 msg16->pt.x = msg32->pt.x;
2361 msg16->pt.y = msg32->pt.y;
2362 /* this is right, right? */
2363 if (WINPROC_MapMsg32ATo16(msg32->hwnd,msg32->message,msg32->wParam,
2364 &msg16->message,&msg16->wParam, &msg16->lParam)<0)
2366 HeapFree( GetProcessHeap(), 0, msg16 );
2367 return -1;
2369 *plparam = MapLS( msg16 );
2370 return 1;
2372 return 0;
2374 case WM_ACTIVATEAPP:
2375 if (*plparam) *plparam = HTASK_16( (HANDLE)*plparam );
2376 return 0;
2377 case WM_NEXTMENU:
2379 MDINEXTMENU *next = (MDINEXTMENU *)*plparam;
2380 *plparam = (LPARAM)next->hmenuIn;
2381 return 1;
2383 case WM_PAINT:
2384 if (IsIconic( hwnd ) && GetClassLongW( hwnd, GCL_HICON ))
2386 *pmsg16 = WM_PAINTICON;
2387 *pwparam16 = 1;
2389 return 0;
2390 case WM_ERASEBKGND:
2391 if (IsIconic( hwnd ) && GetClassLongW( hwnd, GCL_HICON ))
2392 *pmsg16 = WM_ICONERASEBKGND;
2393 return 0;
2394 case WM_PAINTCLIPBOARD:
2395 case WM_SIZECLIPBOARD:
2396 FIXME_(msg)("message %04x needs translation\n", msg32 );
2397 return -1;
2398 /* following messages should not be sent to 16-bit apps */
2399 case WM_SIZING:
2400 case WM_MOVING:
2401 case WM_CAPTURECHANGED:
2402 case WM_STYLECHANGING:
2403 case WM_STYLECHANGED:
2404 return -1;
2405 case WM_DDE_INITIATE:
2406 case WM_DDE_TERMINATE:
2407 case WM_DDE_UNADVISE:
2408 case WM_DDE_REQUEST:
2409 *pwparam16 = HWND_16((HWND)wParam32);
2410 return 0;
2411 case WM_DDE_ADVISE:
2412 case WM_DDE_DATA:
2413 case WM_DDE_POKE:
2415 UINT lo32, hi;
2416 HANDLE16 lo16 = 0;
2418 *pwparam16 = HWND_16((HWND)wParam32);
2419 UnpackDDElParam(msg32, *plparam, &lo32, &hi);
2420 if (lo32 && !(lo16 = convert_handle_32_to_16(lo32, GMEM_DDESHARE)))
2421 return -1;
2422 *plparam = MAKELPARAM(lo16, hi);
2424 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2425 case WM_DDE_ACK:
2427 UINT lo, hi;
2428 int flag = 0;
2429 char buf[2];
2431 *pwparam16 = HWND_16((HWND)wParam32);
2433 UnpackDDElParam(msg32, *plparam, &lo, &hi);
2435 if (GlobalGetAtomNameA((ATOM)hi, buf, sizeof(buf)) > 0) flag |= 1;
2436 if (GlobalSize((HANDLE)hi) != 0) flag |= 2;
2437 switch (flag)
2439 case 0:
2440 if (hi)
2442 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
2443 hi = 0;
2445 break;
2446 case 1:
2447 break; /* atom, nothing to do */
2448 case 3:
2449 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
2450 /* fall thru */
2451 case 2:
2452 hi = convert_handle_32_to_16(hi, GMEM_DDESHARE);
2453 break;
2455 *plparam = MAKELPARAM(lo, hi);
2457 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2458 case WM_DDE_EXECUTE:
2459 *plparam = convert_handle_32_to_16(*plparam, GMEM_DDESHARE);
2460 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2461 default: /* No translation needed */
2462 return 0;
2467 /**********************************************************************
2468 * WINPROC_UnmapMsg32ATo16
2470 * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
2472 void WINPROC_UnmapMsg32ATo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2473 MSGPARAM16* p16 )
2475 switch(msg)
2477 case SBM_GETRANGE:
2478 *(LPINT)wParam = LOWORD(p16->lResult);
2479 *(LPINT)lParam = HIWORD(p16->lResult);
2480 break;
2482 case LB_ADDFILE:
2483 case LB_ADDSTRING:
2484 case LB_DIR:
2485 case LB_FINDSTRING:
2486 case LB_FINDSTRINGEXACT:
2487 case LB_INSERTSTRING:
2488 case LB_SELECTSTRING:
2489 case LB_GETTEXT:
2490 case CB_ADDSTRING:
2491 case CB_FINDSTRING:
2492 case CB_FINDSTRINGEXACT:
2493 case CB_INSERTSTRING:
2494 case CB_SELECTSTRING:
2495 case CB_DIR:
2496 case CB_GETLBTEXT:
2497 case WM_SETTEXT:
2498 case WM_WININICHANGE:
2499 case WM_DEVMODECHANGE:
2500 UnMapLS( (SEGPTR)p16->lParam );
2501 break;
2502 case LB_SETTABSTOPS:
2503 case WM_COMPAREITEM:
2504 case WM_DELETEITEM:
2505 case WM_DRAWITEM:
2507 void *ptr = MapSL( p16->lParam );
2508 UnMapLS( p16->lParam );
2509 HeapFree( GetProcessHeap(), 0, ptr );
2511 break;
2512 case CB_GETDROPPEDCONTROLRECT:
2513 case LB_GETITEMRECT:
2515 RECT *r32;
2516 RECT16 *rect = MapSL(p16->lParam);
2517 UnMapLS( p16->lParam );
2518 p16->lParam = *(LPARAM *)(rect + 1);
2519 r32 = (RECT *)p16->lParam;
2520 r32->left = rect->left;
2521 r32->top = rect->top;
2522 r32->right = rect->right;
2523 r32->bottom = rect->bottom;
2524 HeapFree( GetProcessHeap(), 0, rect );
2526 break;
2527 case LB_GETSELITEMS:
2529 INT i;
2530 LPINT16 items = MapSL(p16->lParam);
2531 UnMapLS( p16->lParam );
2532 p16->lParam = *((LPARAM *)items - 1);
2533 for (i = 0; i < p16->wParam; i++) *((LPINT)(p16->lParam) + i) = items[i];
2534 HeapFree( GetProcessHeap(), 0, (LPARAM *)items - 1 );
2536 break;
2538 case CB_GETEDITSEL:
2539 if( wParam )
2540 *((PUINT)(wParam)) = LOWORD(p16->lResult);
2541 if( lParam )
2542 *((PUINT)(lParam)) = HIWORD(p16->lResult); /* FIXME: substract 1? */
2543 break;
2545 case WM_MEASUREITEM:
2547 MEASUREITEMSTRUCT16 *mis = MapSL(p16->lParam);
2548 MEASUREITEMSTRUCT *mis32 = *(MEASUREITEMSTRUCT **)(mis + 1);
2549 mis32->itemWidth = mis->itemWidth;
2550 mis32->itemHeight = mis->itemHeight;
2551 UnMapLS( p16->lParam );
2552 HeapFree( GetProcessHeap(), 0, mis );
2554 break;
2555 case WM_GETMINMAXINFO:
2557 MINMAXINFO16 *mmi = MapSL(p16->lParam);
2558 UnMapLS( p16->lParam );
2559 p16->lParam = *(LPARAM *)(mmi + 1);
2560 MINMAXINFO16to32( mmi, (MINMAXINFO *)(p16->lParam) );
2561 HeapFree( GetProcessHeap(), 0, mmi );
2563 break;
2564 case WM_GETTEXT:
2565 case WM_ASKCBFORMATNAME:
2567 LPSTR str = MapSL(p16->lParam);
2568 UnMapLS( p16->lParam );
2569 p16->lParam = *((LPARAM *)str - 1);
2570 lstrcpynA( (LPSTR)(p16->lParam), str, p16->wParam );
2571 HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2573 break;
2574 case WM_MDICREATE:
2576 MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2577 UnMapLS( cs->szTitle );
2578 UnMapLS( cs->szClass );
2579 UnMapLS( p16->lParam );
2580 HeapFree( GetProcessHeap(), 0, cs );
2582 break;
2583 case WM_MDIGETACTIVE:
2584 if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(p16->lResult);
2585 p16->lResult = (LRESULT)WIN_Handle32( LOWORD(p16->lResult) );
2586 break;
2587 case WM_NCCALCSIZE:
2589 NCCALCSIZE_PARAMS *nc32;
2590 NCCALCSIZE_PARAMS16 *nc = MapSL(p16->lParam);
2591 UnMapLS( p16->lParam );
2592 p16->lParam = *(LPARAM *)(nc + 1);
2593 nc32 = (NCCALCSIZE_PARAMS *)(p16->lParam);
2594 nc32->rgrc[0].left = nc->rgrc[0].left;
2595 nc32->rgrc[0].top = nc->rgrc[0].top;
2596 nc32->rgrc[0].right = nc->rgrc[0].right;
2597 nc32->rgrc[0].bottom = nc->rgrc[0].bottom;
2598 if (p16->wParam)
2600 WINDOWPOS16 *pos = MapSL(nc->lppos);
2601 UnMapLS( nc->lppos );
2602 nc32->rgrc[1].left = nc->rgrc[1].left;
2603 nc32->rgrc[1].top = nc->rgrc[1].top;
2604 nc32->rgrc[1].right = nc->rgrc[1].right;
2605 nc32->rgrc[1].bottom = nc->rgrc[1].bottom;
2606 nc32->rgrc[2].left = nc->rgrc[2].left;
2607 nc32->rgrc[2].top = nc->rgrc[2].top;
2608 nc32->rgrc[2].right = nc->rgrc[2].right;
2609 nc32->rgrc[2].bottom = nc->rgrc[2].bottom;
2610 WINDOWPOS16to32( pos, nc32->lppos );
2611 HeapFree( GetProcessHeap(), 0, pos );
2613 HeapFree( GetProcessHeap(), 0, nc );
2615 break;
2616 case WM_NCCREATE:
2617 case WM_CREATE:
2619 CREATESTRUCT16 *cs = MapSL(p16->lParam);
2620 UnMapLS( p16->lParam );
2621 UnMapLS( cs->lpszName );
2622 UnMapLS( cs->lpszClass );
2623 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2625 MDICREATESTRUCT16 *mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs->lpCreateParams);
2626 UnMapLS( cs->lpCreateParams );
2627 UnMapLS( mdi_cs16->szTitle );
2628 UnMapLS( mdi_cs16->szClass );
2629 HeapFree(GetProcessHeap(), 0, mdi_cs16);
2631 HeapFree( GetProcessHeap(), 0, cs );
2633 break;
2634 case WM_WINDOWPOSCHANGING:
2635 case WM_WINDOWPOSCHANGED:
2637 WINDOWPOS16 *wp = MapSL(p16->lParam);
2638 UnMapLS( p16->lParam );
2639 p16->lParam = *(LPARAM *)(wp + 1);
2640 WINDOWPOS16to32( wp, (WINDOWPOS *)p16->lParam );
2641 HeapFree( GetProcessHeap(), 0, wp );
2643 break;
2644 case WM_NOTIFY:
2645 UnMapLS(p16->lParam);
2646 break;
2647 case WM_GETDLGCODE:
2648 if (p16->lParam)
2650 LPMSG16 msg16 = MapSL(p16->lParam);
2651 MSGPARAM16 msgp16;
2652 UnMapLS( p16->lParam );
2653 msgp16.wParam=msg16->wParam;
2654 msgp16.lParam=msg16->lParam;
2655 WINPROC_UnmapMsg32ATo16(((LPMSG)lParam)->hwnd, ((LPMSG)lParam)->message,
2656 ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam,
2657 &msgp16 );
2658 HeapFree( GetProcessHeap(), 0, msg16 );
2660 break;
2661 case WM_NEXTMENU:
2663 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
2664 next->hmenuNext = HMENU_32( LOWORD(p16->lResult) );
2665 next->hwndNext = WIN_Handle32( HIWORD(p16->lResult) );
2666 p16->lResult = 0;
2668 break;
2673 /**********************************************************************
2674 * WINPROC_MapMsg32WTo16
2676 * Map a message from 32-bit Unicode to 16-bit.
2677 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
2679 INT WINPROC_MapMsg32WTo16( HWND hwnd, UINT msg32, WPARAM wParam32,
2680 UINT16 *pmsg16, WPARAM16 *pwparam16,
2681 LPARAM *plparam )
2683 BYTE ch;
2684 WCHAR wch;
2686 *pmsg16 = LOWORD(msg32);
2687 *pwparam16 = LOWORD(wParam32);
2688 switch(msg32)
2690 case LB_ADDSTRING:
2691 case LB_FINDSTRING:
2692 case LB_FINDSTRINGEXACT:
2693 case LB_INSERTSTRING:
2694 case LB_SELECTSTRING:
2695 case LB_DIR:
2696 case LB_ADDFILE:
2697 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2698 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2699 return 1;
2701 case CB_ADDSTRING:
2702 case CB_FINDSTRING:
2703 case CB_FINDSTRINGEXACT:
2704 case CB_INSERTSTRING:
2705 case CB_SELECTSTRING:
2706 case CB_DIR:
2707 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2708 *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING);
2709 return 1;
2711 case WM_NCCREATE:
2712 case WM_CREATE:
2714 CREATESTRUCT16 *cs;
2715 CREATESTRUCTW *cs32 = (CREATESTRUCTW *)*plparam;
2717 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2718 CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs32, cs );
2719 cs->lpszName = map_str_32W_to_16( cs32->lpszName );
2720 cs->lpszClass = map_str_32W_to_16( cs32->lpszClass );
2722 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2724 MDICREATESTRUCT16 *mdi_cs16;
2725 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)cs32->lpCreateParams;
2726 mdi_cs16 = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs16));
2727 if (!mdi_cs16)
2729 HeapFree(GetProcessHeap(), 0, cs);
2730 return -1;
2732 MDICREATESTRUCT32Ato16((MDICREATESTRUCTA *)mdi_cs, mdi_cs16);
2733 mdi_cs16->szTitle = map_str_32W_to_16(mdi_cs->szTitle);
2734 mdi_cs16->szClass = map_str_32W_to_16(mdi_cs->szClass);
2735 cs->lpCreateParams = MapLS(mdi_cs16);
2737 *plparam = MapLS(cs);
2739 return 1;
2740 case WM_MDICREATE:
2742 MDICREATESTRUCT16 *cs;
2743 MDICREATESTRUCTW *cs32 = (MDICREATESTRUCTW *)*plparam;
2745 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2746 MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs32, cs );
2747 cs->szTitle = map_str_32W_to_16( cs32->szTitle );
2748 cs->szClass = map_str_32W_to_16( cs32->szClass );
2749 *plparam = MapLS(cs);
2751 return 1;
2752 case WM_SETTEXT:
2753 case WM_WININICHANGE:
2754 case WM_DEVMODECHANGE:
2755 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2756 return 1;
2757 case LB_GETTEXT:
2758 if ( WINPROC_TestLBForStr( hwnd ))
2760 LPSTR str = HeapAlloc( GetProcessHeap(), 0, 256 ); /* FIXME: fixed sized buffer */
2761 if (!str) return -1;
2762 *pmsg16 = LB_GETTEXT16;
2763 *plparam = (LPARAM)MapLS(str);
2765 return 1;
2766 case CB_GETLBTEXT:
2767 if ( WINPROC_TestCBForStr( hwnd ))
2769 LPSTR str = HeapAlloc( GetProcessHeap(), 0, 256 ); /* FIXME: fixed sized buffer */
2770 if (!str) return -1;
2771 *pmsg16 = CB_GETLBTEXT16;
2772 *plparam = (LPARAM)MapLS(str);
2774 return 1;
2776 case WM_CHARTOITEM:
2777 wch = LOWORD(wParam32);
2778 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2779 *pwparam16 = ch;
2780 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2781 return 0;
2782 case WM_MENUCHAR:
2783 wch = LOWORD(wParam32);
2784 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2785 *pwparam16 = ch;
2786 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2787 return 0;
2788 case WM_CHAR:
2789 case WM_DEADCHAR:
2790 case WM_SYSCHAR:
2791 case WM_SYSDEADCHAR:
2792 wch = wParam32;
2793 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2794 *pwparam16 = ch;
2795 return 0;
2796 case WM_IME_CHAR:
2798 BYTE ch[2];
2800 wch = wParam32;
2801 if (WideCharToMultiByte( CP_ACP, 0, &wch, 1, ch, 2, NULL, NULL ) == 2)
2802 *pwparam16 = (ch[0] << 8) | ch[1];
2803 else
2804 *pwparam16 = ch[0];
2806 return 0;
2808 default: /* No Unicode translation needed (?) */
2809 return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2810 pwparam16, plparam );
2815 /**********************************************************************
2816 * WINPROC_UnmapMsg32WTo16
2818 * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2820 void WINPROC_UnmapMsg32WTo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2821 MSGPARAM16* p16 )
2823 switch(msg)
2825 case LB_ADDSTRING:
2826 case LB_FINDSTRING:
2827 case LB_FINDSTRINGEXACT:
2828 case LB_INSERTSTRING:
2829 case LB_SELECTSTRING:
2830 case LB_DIR:
2831 case LB_ADDFILE:
2832 case CB_ADDSTRING:
2833 case CB_FINDSTRING:
2834 case CB_FINDSTRINGEXACT:
2835 case CB_INSERTSTRING:
2836 case CB_SELECTSTRING:
2837 case CB_DIR:
2838 case WM_SETTEXT:
2839 case WM_WININICHANGE:
2840 case WM_DEVMODECHANGE:
2841 unmap_str_32W_to_16( p16->lParam );
2842 break;
2843 case WM_NCCREATE:
2844 case WM_CREATE:
2846 CREATESTRUCT16 *cs = MapSL(p16->lParam);
2847 UnMapLS( p16->lParam );
2848 unmap_str_32W_to_16( cs->lpszName );
2849 unmap_str_32W_to_16( cs->lpszClass );
2851 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2853 MDICREATESTRUCT16 *mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs->lpCreateParams);
2854 UnMapLS( cs->lpCreateParams );
2855 unmap_str_32W_to_16(mdi_cs16->szTitle);
2856 unmap_str_32W_to_16(mdi_cs16->szClass);
2857 HeapFree(GetProcessHeap(), 0, mdi_cs16);
2859 HeapFree( GetProcessHeap(), 0, cs );
2861 break;
2862 case WM_MDICREATE:
2864 MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2865 UnMapLS( p16->lParam );
2866 unmap_str_32W_to_16( cs->szTitle );
2867 unmap_str_32W_to_16( cs->szClass );
2868 HeapFree( GetProcessHeap(), 0, cs );
2870 break;
2871 case WM_GETTEXT:
2872 case WM_ASKCBFORMATNAME:
2874 LPSTR str = MapSL(p16->lParam);
2875 UnMapLS( p16->lParam );
2876 p16->lParam = *((LPARAM *)str - 1);
2877 MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)p16->lParam, 0x7fffffff );
2878 p16->lResult = strlenW( (LPWSTR)p16->lParam );
2879 HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2881 break;
2882 case LB_GETTEXT:
2883 if ( WINPROC_TestLBForStr( hwnd ))
2885 LPSTR str = MapSL(p16->lParam);
2886 UnMapLS( p16->lParam );
2887 p16->lResult = MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff ) - 1;
2888 HeapFree( GetProcessHeap(), 0, (LPARAM *)str );
2890 break;
2891 case CB_GETLBTEXT:
2892 if ( WINPROC_TestCBForStr( hwnd ))
2894 LPSTR str = MapSL(p16->lParam);
2895 UnMapLS( p16->lParam );
2896 p16->lResult = MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff ) - 1;
2897 HeapFree( GetProcessHeap(), 0, (LPARAM *)str );
2899 break;
2900 default:
2901 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, p16 );
2902 break;
2907 /**********************************************************************
2908 * WINPROC_CallProc32ATo32W
2910 * Call a window procedure, translating args from Ansi to Unicode.
2912 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC func, HWND hwnd,
2913 UINT msg, WPARAM wParam,
2914 LPARAM lParam )
2916 LRESULT result;
2917 int unmap;
2919 TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2920 func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2922 if( (unmap = WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam )) == -1) {
2923 ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2924 SPY_GetMsgName(msg, hwnd), wParam, lParam );
2925 return 0;
2927 result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2928 if (unmap) result = WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result );
2929 return result;
2933 /**********************************************************************
2934 * WINPROC_CallProc32WTo32A_fast
2937 static BOOL WINPROC_CallProc32WTo32A_fast( WNDPROC func, HWND hwnd,
2938 UINT msg, WPARAM wParam,
2939 LPARAM lParam, LRESULT *result )
2941 switch(msg)
2943 case WM_NCCREATE:
2944 case WM_CREATE:
2945 { /* csW->lpszName and csW->lpszClass are NOT supposed to be atoms
2946 * at this point.
2948 char buffer[1024];
2949 char *cls = buffer, *name;
2950 CREATESTRUCTW *csW = (CREATESTRUCTW *)lParam;
2951 CREATESTRUCTA csA = *(CREATESTRUCTA *)csW;
2952 DWORD name_lenA, name_lenW, class_lenA, class_lenW;
2954 class_lenW = strlenW(csW->lpszClass) * sizeof(WCHAR);
2955 RtlUnicodeToMultiByteSize(&class_lenA, csW->lpszClass, class_lenW);
2957 if (csW->lpszName)
2959 name_lenW = strlenW(csW->lpszName) * sizeof(WCHAR);
2960 RtlUnicodeToMultiByteSize(&name_lenA, csW->lpszName, name_lenW);
2962 else
2963 name_lenW = name_lenA = 0;
2965 if (class_lenA + name_lenA + 2 > sizeof(buffer))
2967 cls = HeapAlloc(GetProcessHeap(), 0, class_lenA + name_lenA + 2);
2968 if (!cls) return FALSE;
2971 RtlUnicodeToMultiByteN(cls, class_lenA, NULL, csW->lpszClass, class_lenW);
2972 cls[class_lenA] = 0;
2973 csA.lpszClass = cls;
2975 if (csW->lpszName)
2977 name = cls + class_lenA + 1;
2978 RtlUnicodeToMultiByteN(name, name_lenA, NULL, csW->lpszName, name_lenW);
2979 name[name_lenA] = 0;
2980 csA.lpszName = name;
2983 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2985 MDICREATESTRUCTA mdi_cs;
2987 mdi_cs = *(MDICREATESTRUCTA *)csW->lpCreateParams;
2988 mdi_cs.szTitle = csA.lpszName;
2989 mdi_cs.szClass = csA.lpszClass;
2990 csA.lpCreateParams = &mdi_cs;
2993 lParam = (LPARAM)&csA;
2994 *result = WINPROC_CallWndProc(func, hwnd, msg, wParam, lParam);
2996 if (cls != buffer) HeapFree(GetProcessHeap(), 0, cls);
2998 return TRUE;
3000 default:
3001 return FALSE;
3005 /**********************************************************************
3006 * WINPROC_CallProc32WTo32A
3008 * Call a window procedure, translating args from Unicode to Ansi.
3010 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC func, HWND hwnd,
3011 UINT msg, WPARAM wParam,
3012 LPARAM lParam )
3014 LRESULT result;
3015 int unmap;
3017 TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
3018 func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
3020 if (WINPROC_CallProc32WTo32A_fast( func, hwnd, msg, wParam, lParam, &result ))
3021 return result;
3023 if ((unmap = WINPROC_MapMsg32WTo32A( hwnd, msg, &wParam, &lParam )) == -1) {
3024 ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
3025 SPY_GetMsgName(msg, hwnd), wParam, lParam );
3026 return 0;
3028 result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
3029 if( unmap ) result = WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam, result );
3030 return result;
3034 /**********************************************************************
3035 * __wine_call_wndproc_32A (USER.1010)
3037 LRESULT WINAPI __wine_call_wndproc_32A( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
3038 WNDPROC func )
3040 LRESULT result;
3041 UINT msg32;
3042 WPARAM wParam32;
3043 HWND hwnd32 = WIN_Handle32( hwnd );
3045 TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
3046 func, hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
3048 if (WINPROC_MapMsg16To32A( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
3049 return 0;
3050 result = WINPROC_CallWndProc( func, hwnd32, msg32, wParam32, lParam );
3051 return WINPROC_UnmapMsg16To32A( hwnd32, msg32, wParam32, lParam, result );
3055 /**********************************************************************
3056 * __wine_call_wndproc_32W (USER.1011)
3058 LRESULT WINAPI __wine_call_wndproc_32W( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
3059 WNDPROC func )
3061 LRESULT result;
3062 UINT msg32;
3063 WPARAM wParam32;
3064 HWND hwnd32 = WIN_Handle32( hwnd );
3066 TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
3067 func, hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
3069 if (WINPROC_MapMsg16To32W( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
3070 return 0;
3071 result = WINPROC_CallWndProc( func, hwnd32, msg32, wParam32, lParam );
3072 return WINPROC_UnmapMsg16To32W( hwnd32, msg32, wParam32, lParam, result );
3076 /**********************************************************************
3077 * WINPROC_CallProc32ATo16
3079 * Call a 16-bit window procedure, translating the 32-bit args.
3081 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd,
3082 UINT msg, WPARAM wParam,
3083 LPARAM lParam )
3085 UINT16 msg16;
3086 MSGPARAM16 mp16;
3088 TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
3089 func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
3091 mp16.lParam = lParam;
3092 if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, &msg16, &mp16.wParam, &mp16.lParam ) == -1)
3093 return 0;
3094 mp16.lResult = WINPROC_CallWndProc16( func, HWND_16(hwnd), msg16,
3095 mp16.wParam, mp16.lParam );
3096 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, &mp16 );
3097 return mp16.lResult;
3101 /**********************************************************************
3102 * WINPROC_CallProc32WTo16
3104 * Call a 16-bit window procedure, translating the 32-bit args.
3106 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd,
3107 UINT msg, WPARAM wParam,
3108 LPARAM lParam )
3110 UINT16 msg16;
3111 MSGPARAM16 mp16;
3113 TRACE_(msg)("func %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
3114 func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
3116 mp16.lParam = lParam;
3117 if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &mp16.wParam,
3118 &mp16.lParam ) == -1)
3119 return 0;
3120 mp16.lResult = WINPROC_CallWndProc16( func, HWND_16(hwnd), msg16,
3121 mp16.wParam, mp16.lParam );
3122 WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, &mp16 );
3123 return mp16.lResult;
3127 /**********************************************************************
3128 * CallWindowProc (USER.122)
3130 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
3131 WPARAM16 wParam, LPARAM lParam )
3133 WINDOWPROC *proc;
3135 if (!func) return 0;
3137 if (!(proc = WINPROC_GetPtr( (WNDPROC)func )))
3138 return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
3140 #if testing
3141 func = WINPROC_GetProc( (WNDPROC)proc, WIN_PROC_16 );
3142 return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
3143 #endif
3145 switch(proc->type)
3147 case WIN_PROC_16:
3148 if (!proc->thunk.t_from32.proc) return 0;
3149 return WINPROC_CallWndProc16( proc->thunk.t_from32.proc,
3150 hwnd, msg, wParam, lParam );
3151 case WIN_PROC_32A:
3152 if (!proc->thunk.t_from16.proc) return 0;
3153 return __wine_call_wndproc_32A( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc );
3154 case WIN_PROC_32W:
3155 if (!proc->thunk.t_from16.proc) return 0;
3156 return __wine_call_wndproc_32W( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc );
3157 default:
3158 WARN_(relay)("Invalid proc %p\n", proc );
3159 return 0;
3164 /**********************************************************************
3165 * CallWindowProcA (USER32.@)
3167 * The CallWindowProc() function invokes the windows procedure _func_,
3168 * with _hwnd_ as the target window, the message specified by _msg_, and
3169 * the message parameters _wParam_ and _lParam_.
3171 * Some kinds of argument conversion may be done, I'm not sure what.
3173 * CallWindowProc() may be used for windows subclassing. Use
3174 * SetWindowLong() to set a new windows procedure for windows of the
3175 * subclass, and handle subclassed messages in the new windows
3176 * procedure. The new windows procedure may then use CallWindowProc()
3177 * with _func_ set to the parent class's windows procedure to dispatch
3178 * the message to the superclass.
3180 * RETURNS
3182 * The return value is message dependent.
3184 * CONFORMANCE
3186 * ECMA-234, Win32
3188 LRESULT WINAPI CallWindowProcA(
3189 WNDPROC func, /* [in] window procedure */
3190 HWND hwnd, /* [in] target window */
3191 UINT msg, /* [in] message */
3192 WPARAM wParam, /* [in] message dependent parameter */
3193 LPARAM lParam /* [in] message dependent parameter */
3195 WINDOWPROC *proc;
3197 if (!func) return 0;
3199 if (!(proc = WINPROC_GetPtr( func )))
3200 return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
3202 #if testing
3203 func = WINPROC_GetProc( (WNDPROC)proc, WIN_PROC_32A );
3204 return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
3205 #endif
3207 switch(proc->type)
3209 case WIN_PROC_16:
3210 if (!proc->thunk.t_from32.proc) return 0;
3211 return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
3212 hwnd, msg, wParam, lParam );
3213 case WIN_PROC_32A:
3214 if (!proc->thunk.t_from16.proc) return 0;
3215 return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
3216 hwnd, msg, wParam, lParam );
3217 case WIN_PROC_32W:
3218 if (!proc->thunk.t_from16.proc) return 0;
3219 return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
3220 hwnd, msg, wParam, lParam );
3221 default:
3222 WARN_(relay)("Invalid proc %p\n", proc );
3223 return 0;
3228 /**********************************************************************
3229 * CallWindowProcW (USER32.@)
3231 LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
3232 WPARAM wParam, LPARAM lParam )
3234 WINDOWPROC *proc;
3236 if (!func) return 0;
3238 if (!(proc = WINPROC_GetPtr( (WNDPROC)func )))
3239 return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
3241 #if testing
3242 func = WINPROC_GetProc( (WNDPROC)proc, WIN_PROC_32W );
3243 return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
3244 #endif
3246 switch(proc->type)
3248 case WIN_PROC_16:
3249 if (!proc->thunk.t_from32.proc) return 0;
3250 return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
3251 hwnd, msg, wParam, lParam );
3252 case WIN_PROC_32A:
3253 if (!proc->thunk.t_from16.proc) return 0;
3254 return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
3255 hwnd, msg, wParam, lParam );
3256 case WIN_PROC_32W:
3257 if (!proc->thunk.t_from16.proc) return 0;
3258 return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
3259 hwnd, msg, wParam, lParam );
3260 default:
3261 WARN_(relay)("Invalid proc %p\n", proc );
3262 return 0;