user: Get rid of the MSGPARAMS16 structure.
[wine/hacks.git] / dlls / user / winproc.c
blob0289664d15611ed6949d5d830eb4042edd0200e3
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 <assert.h>
26 #include <stdarg.h>
27 #include <string.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "wownt32.h"
33 #include "wine/winbase16.h"
34 #include "wine/winuser16.h"
35 #include "controls.h"
36 #include "win.h"
37 #include "winproc.h"
38 #include "user_private.h"
39 #include "dde.h"
40 #include "winternl.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
44 WINE_DECLARE_DEBUG_CHANNEL(msg);
45 WINE_DECLARE_DEBUG_CHANNEL(relay);
46 WINE_DEFAULT_DEBUG_CHANNEL(win);
48 typedef struct tagWINDOWPROC
50 WNDPROC16 proc16; /* 16-bit window proc */
51 WNDPROC procA; /* ASCII window proc */
52 WNDPROC procW; /* Unicode window proc */
53 } WINDOWPROC;
55 #define WINPROC_HANDLE (~0UL >> 16)
56 #define MAX_WINPROCS 8192
58 static WINDOWPROC winproc_array[MAX_WINPROCS];
59 static UINT winproc_used;
61 static CRITICAL_SECTION winproc_cs;
62 static CRITICAL_SECTION_DEBUG critsect_debug =
64 0, 0, &winproc_cs,
65 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
66 0, 0, { (DWORD_PTR)(__FILE__ ": winproc_cs") }
68 static CRITICAL_SECTION winproc_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
70 /* map a Unicode string to a 16-bit pointer */
71 inline static SEGPTR map_str_32W_to_16( LPCWSTR str )
73 LPSTR ret;
74 INT len;
76 if (!HIWORD(str)) return (SEGPTR)LOWORD(str);
77 len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
78 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
79 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
80 return MapLS(ret);
83 /* unmap a Unicode string that was converted to a 16-bit pointer */
84 inline static void unmap_str_32W_to_16( SEGPTR str )
86 if (!HIWORD(str)) return;
87 HeapFree( GetProcessHeap(), 0, MapSL(str) );
88 UnMapLS( str );
91 /* map a 16-bit pointer to a Unicode string */
92 inline static LPWSTR map_str_16_to_32W( SEGPTR str )
94 LPWSTR ret;
95 INT len;
97 if (!HIWORD(str)) return (LPWSTR)(ULONG_PTR)LOWORD(str);
98 len = MultiByteToWideChar( CP_ACP, 0, MapSL(str), -1, NULL, 0 );
99 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
100 MultiByteToWideChar( CP_ACP, 0, MapSL(str), -1, ret, len );
101 return ret;
104 /* unmap a 16-bit pointer that was converted to a Unicode string */
105 inline static void unmap_str_16_to_32W( LPCWSTR str )
107 if (HIWORD(str)) HeapFree( GetProcessHeap(), 0, (void *)str );
110 /* find an existing winproc for a given 16-bit function and type */
111 /* FIXME: probably should do something more clever than a linear search */
112 static inline WINDOWPROC *find_winproc16( WNDPROC16 func )
114 unsigned int i;
116 for (i = 0; i < winproc_used; i++)
118 if (winproc_array[i].proc16 == func) return &winproc_array[i];
120 return NULL;
123 /* find an existing winproc for a given function and type */
124 /* FIXME: probably should do something more clever than a linear search */
125 static inline WINDOWPROC *find_winproc( WNDPROC funcA, WNDPROC funcW )
127 unsigned int i;
129 for (i = 0; i < winproc_used; i++)
131 if (funcA && winproc_array[i].procA != funcA) continue;
132 if (funcW && winproc_array[i].procW != funcW) continue;
133 return &winproc_array[i];
135 return NULL;
138 /* return the window proc for a given handle, or NULL for an invalid handle */
139 static inline WINDOWPROC *handle_to_proc( WNDPROC handle )
141 UINT index = LOWORD(handle);
142 if ((ULONG_PTR)handle >> 16 != WINPROC_HANDLE) return NULL;
143 if (index >= winproc_used) return NULL;
144 return &winproc_array[index];
147 /* create a handle for a given window proc */
148 static inline WNDPROC proc_to_handle( WINDOWPROC *proc )
150 return (WNDPROC)(ULONG_PTR)((proc - winproc_array) | (WINPROC_HANDLE << 16));
153 /* allocate and initialize a new winproc */
154 static inline WINDOWPROC *alloc_winproc( WNDPROC funcA, WNDPROC funcW )
156 WINDOWPROC *proc;
158 /* check if the function is already a win proc */
159 if (funcA && (proc = handle_to_proc( funcA ))) return proc;
160 if (funcW && (proc = handle_to_proc( funcW ))) return proc;
161 if (!funcA && !funcW) return NULL;
163 EnterCriticalSection( &winproc_cs );
165 /* check if we already have a winproc for that function */
166 if (!(proc = find_winproc( funcA, funcW )))
168 if (winproc_used < MAX_WINPROCS)
170 proc = &winproc_array[winproc_used++];
171 proc->procA = funcA;
172 proc->procW = funcW;
173 TRACE( "allocated %p for %p/%p (%d/%d used)\n",
174 proc_to_handle(proc), funcA, funcW, winproc_used, MAX_WINPROCS );
176 else FIXME( "too many winprocs, cannot allocate one for %p/%p\n", funcA, funcW );
178 else TRACE( "reusing %p for %p/%p\n", proc_to_handle(proc), funcA, funcW );
180 LeaveCriticalSection( &winproc_cs );
181 return proc;
185 #ifdef __i386__
187 #include "pshpack1.h"
189 /* Window procedure 16-to-32-bit thunk */
190 typedef struct
192 BYTE popl_eax; /* popl %eax (return address) */
193 BYTE pushl_func; /* pushl $proc */
194 WINDOWPROC *proc;
195 BYTE pushl_eax; /* pushl %eax */
196 BYTE ljmp; /* ljmp relay*/
197 DWORD relay_offset; /* __wine_call_wndproc */
198 WORD relay_sel;
199 } WINPROC_THUNK;
201 #include "poppack.h"
203 #define MAX_THUNKS (0x10000 / sizeof(WINPROC_THUNK))
205 static WINPROC_THUNK *thunk_array;
206 static UINT thunk_selector;
207 static UINT thunk_used;
209 /* return the window proc for a given handle, or NULL for an invalid handle */
210 static inline WINDOWPROC *handle16_to_proc( WNDPROC16 handle )
212 if (HIWORD(handle) == thunk_selector)
214 UINT index = LOWORD(handle) / sizeof(WINPROC_THUNK);
215 /* check alignment */
216 if (index * sizeof(WINPROC_THUNK) != LOWORD(handle)) return NULL;
217 /* check array limits */
218 if (index >= thunk_used) return NULL;
219 return thunk_array[index].proc;
221 return handle_to_proc( (WNDPROC)handle );
224 /* allocate a 16-bit thunk for an existing window proc */
225 static WNDPROC16 alloc_win16_thunk( WINDOWPROC *proc )
227 static FARPROC16 relay;
228 UINT i;
230 if (proc->proc16) return proc->proc16;
232 EnterCriticalSection( &winproc_cs );
234 if (!thunk_array) /* allocate the array and its selector */
236 LDT_ENTRY entry;
238 if (!(thunk_selector = wine_ldt_alloc_entries(1))) goto done;
239 if (!(thunk_array = VirtualAlloc( NULL, MAX_THUNKS * sizeof(WINPROC_THUNK), MEM_COMMIT,
240 PAGE_EXECUTE_READWRITE ))) goto done;
241 wine_ldt_set_base( &entry, thunk_array );
242 wine_ldt_set_limit( &entry, MAX_THUNKS * sizeof(WINPROC_THUNK) - 1 );
243 wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
244 wine_ldt_set_entry( thunk_selector, &entry );
245 relay = GetProcAddress16( GetModuleHandle16("user"), "__wine_call_wndproc" );
248 /* check if it already exists */
249 for (i = 0; i < thunk_used; i++) if (thunk_array[i].proc == proc) break;
251 if (i == thunk_used) /* create a new one */
253 WINPROC_THUNK *thunk;
255 if (thunk_used >= MAX_THUNKS) goto done;
256 thunk = &thunk_array[thunk_used++];
257 thunk->popl_eax = 0x58; /* popl %eax */
258 thunk->pushl_func = 0x68; /* pushl $proc */
259 thunk->proc = proc;
260 thunk->pushl_eax = 0x50; /* pushl %eax */
261 thunk->ljmp = 0xea; /* ljmp relay*/
262 thunk->relay_offset = OFFSETOF(relay);
263 thunk->relay_sel = SELECTOROF(relay);
265 proc->proc16 = (WNDPROC16)MAKESEGPTR( thunk_selector, i * sizeof(WINPROC_THUNK) );
266 done:
267 LeaveCriticalSection( &winproc_cs );
268 return proc->proc16;
271 #else /* __i386__ */
273 static inline WINDOWPROC *handle16_to_proc( WNDPROC16 handle )
275 return handle_to_proc( (WNDPROC)handle );
278 static inline WNDPROC16 alloc_win16_thunk( WINDOWPROC *proc )
280 return 0;
283 #endif /* __i386__ */
286 #ifdef __i386__
287 /* Some window procedures modify register they shouldn't, or are not
288 * properly declared stdcall; so we need a small assembly wrapper to
289 * call them. */
290 extern LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
291 WPARAM wParam, LPARAM lParam );
292 __ASM_GLOBAL_FUNC( WINPROC_wrapper,
293 "pushl %ebp\n\t"
294 "movl %esp,%ebp\n\t"
295 "pushl %edi\n\t"
296 "pushl %esi\n\t"
297 "pushl %ebx\n\t"
298 "subl $12,%esp\n\t"
299 "pushl 24(%ebp)\n\t"
300 "pushl 20(%ebp)\n\t"
301 "pushl 16(%ebp)\n\t"
302 "pushl 12(%ebp)\n\t"
303 "movl 8(%ebp),%eax\n\t"
304 "call *%eax\n\t"
305 "leal -12(%ebp),%esp\n\t"
306 "popl %ebx\n\t"
307 "popl %esi\n\t"
308 "popl %edi\n\t"
309 "leave\n\t"
310 "ret" );
311 #else
312 static inline LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
313 WPARAM wParam, LPARAM lParam )
315 return proc( hwnd, msg, wParam, lParam );
317 #endif /* __i386__ */
320 static void MINMAXINFO32to16( const MINMAXINFO *from, MINMAXINFO16 *to )
322 to->ptReserved.x = from->ptReserved.x;
323 to->ptReserved.y = from->ptReserved.y;
324 to->ptMaxSize.x = from->ptMaxSize.x;
325 to->ptMaxSize.y = from->ptMaxSize.y;
326 to->ptMaxPosition.x = from->ptMaxPosition.x;
327 to->ptMaxPosition.y = from->ptMaxPosition.y;
328 to->ptMinTrackSize.x = from->ptMinTrackSize.x;
329 to->ptMinTrackSize.y = from->ptMinTrackSize.y;
330 to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
331 to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
334 static void MINMAXINFO16to32( const MINMAXINFO16 *from, MINMAXINFO *to )
336 to->ptReserved.x = from->ptReserved.x;
337 to->ptReserved.y = from->ptReserved.y;
338 to->ptMaxSize.x = from->ptMaxSize.x;
339 to->ptMaxSize.y = from->ptMaxSize.y;
340 to->ptMaxPosition.x = from->ptMaxPosition.x;
341 to->ptMaxPosition.y = from->ptMaxPosition.y;
342 to->ptMinTrackSize.x = from->ptMinTrackSize.x;
343 to->ptMinTrackSize.y = from->ptMinTrackSize.y;
344 to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
345 to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
348 static void WINDOWPOS32to16( const WINDOWPOS* from, WINDOWPOS16* to )
350 to->hwnd = HWND_16(from->hwnd);
351 to->hwndInsertAfter = HWND_16(from->hwndInsertAfter);
352 to->x = from->x;
353 to->y = from->y;
354 to->cx = from->cx;
355 to->cy = from->cy;
356 to->flags = from->flags;
359 static void WINDOWPOS16to32( const WINDOWPOS16* from, WINDOWPOS* to )
361 to->hwnd = WIN_Handle32(from->hwnd);
362 to->hwndInsertAfter = (from->hwndInsertAfter == (HWND16)-1) ?
363 HWND_TOPMOST : WIN_Handle32(from->hwndInsertAfter);
364 to->x = from->x;
365 to->y = from->y;
366 to->cx = from->cx;
367 to->cy = from->cy;
368 to->flags = from->flags;
371 /* The strings are not copied */
372 static void CREATESTRUCT32Ato16( const CREATESTRUCTA* from, CREATESTRUCT16* to )
374 to->lpCreateParams = (SEGPTR)from->lpCreateParams;
375 to->hInstance = HINSTANCE_16(from->hInstance);
376 to->hMenu = HMENU_16(from->hMenu);
377 to->hwndParent = HWND_16(from->hwndParent);
378 to->cy = from->cy;
379 to->cx = from->cx;
380 to->y = from->y;
381 to->x = from->x;
382 to->style = from->style;
383 to->dwExStyle = from->dwExStyle;
386 static void CREATESTRUCT16to32A( const CREATESTRUCT16* from, CREATESTRUCTA *to )
389 to->lpCreateParams = (LPVOID)from->lpCreateParams;
390 to->hInstance = HINSTANCE_32(from->hInstance);
391 to->hMenu = HMENU_32(from->hMenu);
392 to->hwndParent = WIN_Handle32(from->hwndParent);
393 to->cy = from->cy;
394 to->cx = from->cx;
395 to->y = from->y;
396 to->x = from->x;
397 to->style = from->style;
398 to->dwExStyle = from->dwExStyle;
401 /* The strings are not copied */
402 static void MDICREATESTRUCT32Ato16( const MDICREATESTRUCTA* from, MDICREATESTRUCT16* to )
404 to->hOwner = HINSTANCE_16(from->hOwner);
405 to->x = from->x;
406 to->y = from->y;
407 to->cx = from->cx;
408 to->cy = from->cy;
409 to->style = from->style;
410 to->lParam = from->lParam;
413 static void MDICREATESTRUCT16to32A( const MDICREATESTRUCT16* from, MDICREATESTRUCTA *to )
415 to->hOwner = HINSTANCE_32(from->hOwner);
416 to->x = from->x;
417 to->y = from->y;
418 to->cx = from->cx;
419 to->cy = from->cy;
420 to->style = from->style;
421 to->lParam = from->lParam;
424 static WPARAM map_wparam_char_AtoW( WPARAM wParam, DWORD len )
426 CHAR ch[2];
427 WCHAR wch;
429 ch[0] = (wParam >> 8);
430 ch[1] = wParam & 0xff;
431 if (len > 1 && ch[0])
432 RtlMultiByteToUnicodeN( &wch, sizeof(wch), NULL, ch, 2 );
433 else
434 RtlMultiByteToUnicodeN( &wch, sizeof(wch), NULL, ch + 1, 1 );
435 return MAKEWPARAM( wch, HIWORD(wParam) );
438 static WPARAM map_wparam_char_WtoA( WPARAM wParam, DWORD len )
440 WCHAR wch = wParam;
441 BYTE ch[2];
443 RtlUnicodeToMultiByteN( (LPSTR)ch, len, &len, &wch, sizeof(wch) );
444 if (len == 2)
445 return MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(wParam) );
446 else
447 return MAKEWPARAM( ch[0], HIWORD(wParam) );
450 /* call a 32-bit window procedure */
451 static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result, void *arg )
453 WNDPROC proc = arg;
455 USER_CheckNotLock();
457 hwnd = WIN_GetFullHandle( hwnd );
458 if (TRACE_ON(relay))
459 DPRINTF( "%04lx:Call window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
460 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp );
462 *result = WINPROC_wrapper( proc, hwnd, msg, wp, lp );
464 if (TRACE_ON(relay))
465 DPRINTF( "%04lx:Ret window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx\n",
466 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp, *result );
467 return *result;
470 /* call a 32-bit dialog procedure */
471 static LRESULT call_dialog_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result, void *arg )
473 WNDPROC proc = arg;
474 LRESULT ret;
476 USER_CheckNotLock();
478 hwnd = WIN_GetFullHandle( hwnd );
479 if (TRACE_ON(relay))
480 DPRINTF( "%04lx:Call dialog proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
481 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp );
483 ret = WINPROC_wrapper( proc, hwnd, msg, wp, lp );
484 *result = GetWindowLongPtrW( hwnd, DWLP_MSGRESULT );
486 if (TRACE_ON(relay))
487 DPRINTF( "%04lx:Ret dialog proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx result=%08lx\n",
488 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp, ret, *result );
489 return ret;
492 /**********************************************************************
493 * WINPROC_CallWndProc32
495 * Call a 32-bit WndProc.
497 static LRESULT WINPROC_CallWndProc( WNDPROC proc, HWND hwnd, UINT msg,
498 WPARAM wParam, LPARAM lParam )
500 LRESULT retvalue;
502 USER_CheckNotLock();
504 hwnd = WIN_GetFullHandle( hwnd );
505 if (TRACE_ON(relay))
506 DPRINTF( "%04lx:Call window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
507 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
509 retvalue = WINPROC_wrapper( proc, hwnd, msg, wParam, lParam );
511 if (TRACE_ON(relay))
512 DPRINTF( "%04lx:Ret window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx\n",
513 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam, retvalue );
514 return retvalue;
517 /* call a 16-bit window procedure */
518 static LRESULT call_window_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
519 LRESULT *result, void *arg )
521 WNDPROC16 proc = arg;
522 CONTEXT86 context;
523 size_t size = 0;
524 struct
526 WORD params[5];
527 union
529 CREATESTRUCT16 cs16;
530 DRAWITEMSTRUCT16 dis16;
531 COMPAREITEMSTRUCT16 cis16;
532 } u;
533 } args;
535 USER_CheckNotLock();
537 /* Window procedures want ax = hInstance, ds = es = ss */
539 memset(&context, 0, sizeof(context));
540 context.SegDs = context.SegEs = SELECTOROF(NtCurrentTeb()->WOW32Reserved);
541 context.SegFs = wine_get_fs();
542 context.SegGs = wine_get_gs();
543 if (!(context.Eax = GetWindowWord( HWND_32(hwnd), GWLP_HINSTANCE ))) context.Eax = context.SegDs;
544 context.SegCs = SELECTOROF(proc);
545 context.Eip = OFFSETOF(proc);
546 context.Ebp = OFFSETOF(NtCurrentTeb()->WOW32Reserved) + (WORD)&((STACK16FRAME*)0)->bp;
548 if (lParam)
550 /* Some programs (eg. the "Undocumented Windows" examples, JWP) only
551 work if structures passed in lParam are placed in the stack/data
552 segment. Programmers easily make the mistake of converting lParam
553 to a near rather than a far pointer, since Windows apparently
554 allows this. We copy the structures to the 16 bit stack; this is
555 ugly but makes these programs work. */
556 switch (msg)
558 case WM_CREATE:
559 case WM_NCCREATE:
560 size = sizeof(CREATESTRUCT16); break;
561 case WM_DRAWITEM:
562 size = sizeof(DRAWITEMSTRUCT16); break;
563 case WM_COMPAREITEM:
564 size = sizeof(COMPAREITEMSTRUCT16); break;
566 if (size)
568 memcpy( &args.u, MapSL(lParam), size );
569 lParam = (SEGPTR)NtCurrentTeb()->WOW32Reserved - size;
573 args.params[4] = hwnd;
574 args.params[3] = msg;
575 args.params[2] = wParam;
576 args.params[1] = HIWORD(lParam);
577 args.params[0] = LOWORD(lParam);
578 WOWCallback16Ex( 0, WCB16_REGS, sizeof(args.params) + size, &args, (DWORD *)&context );
579 *result = MAKELONG( LOWORD(context.Eax), LOWORD(context.Edx) );
580 return *result;
583 /* call a 16-bit dialog procedure */
584 static LRESULT call_dialog_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp,
585 LRESULT *result, void *arg )
587 LRESULT ret = call_window_proc16( hwnd, msg, wp, lp, result, arg );
588 *result = GetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT );
589 return LOWORD(ret);
593 /**********************************************************************
594 * WINPROC_GetProc16
596 * Get a window procedure pointer that can be passed to the Windows program.
598 WNDPROC16 WINPROC_GetProc16( WNDPROC proc, BOOL unicode )
600 WINDOWPROC *ptr;
602 if (unicode) ptr = alloc_winproc( NULL, proc );
603 else ptr = alloc_winproc( proc, NULL );
605 if (!ptr) return 0;
606 return alloc_win16_thunk( ptr );
610 /**********************************************************************
611 * WINPROC_GetProc
613 * Get a window procedure pointer that can be passed to the Windows program.
615 WNDPROC WINPROC_GetProc( WNDPROC proc, BOOL unicode )
617 WINDOWPROC *ptr = handle_to_proc( proc );
619 if (!ptr) return proc;
620 if (unicode)
622 if (ptr->procW) return ptr->procW;
623 return proc;
625 else
627 if (ptr->procA) return ptr->procA;
628 return proc;
633 /**********************************************************************
634 * WINPROC_AllocProc16
636 * Allocate a window procedure for a window or class.
638 * Note that allocated winprocs are never freed; the idea is that even if an app creates a
639 * lot of windows, it will usually only have a limited number of window procedures, so the
640 * array won't grow too large, and this way we avoid the need to track allocations per window.
642 WNDPROC WINPROC_AllocProc16( WNDPROC16 func )
644 WINDOWPROC *proc;
646 if (!func) return NULL;
648 /* check if the function is already a win proc */
649 if (!(proc = handle16_to_proc( func )))
651 EnterCriticalSection( &winproc_cs );
653 /* then check if we already have a winproc for that function */
654 if (!(proc = find_winproc16( func )))
656 if (winproc_used < MAX_WINPROCS)
658 proc = &winproc_array[winproc_used++];
659 proc->proc16 = func;
660 TRACE( "allocated %p for %p/16-bit (%d/%d used)\n",
661 proc_to_handle(proc), func, winproc_used, MAX_WINPROCS );
663 else FIXME( "too many winprocs, cannot allocate one for 16-bit %p\n", func );
665 else TRACE( "reusing %p for %p/16-bit\n", proc_to_handle(proc), func );
667 LeaveCriticalSection( &winproc_cs );
669 return proc_to_handle( proc );
673 /**********************************************************************
674 * WINPROC_AllocProc
676 * Allocate a window procedure for a window or class.
678 * Note that allocated winprocs are never freed; the idea is that even if an app creates a
679 * lot of windows, it will usually only have a limited number of window procedures, so the
680 * array won't grow too large, and this way we avoid the need to track allocations per window.
682 WNDPROC WINPROC_AllocProc( WNDPROC funcA, WNDPROC funcW )
684 WINDOWPROC *proc;
686 if (!(proc = alloc_winproc( funcA, funcW ))) return NULL;
687 return proc_to_handle( proc );
691 /**********************************************************************
692 * WINPROC_IsUnicode
694 * Return the window procedure type, or the default value if not a winproc handle.
696 BOOL WINPROC_IsUnicode( WNDPROC proc, BOOL def_val )
698 WINDOWPROC *ptr = handle_to_proc( proc );
700 if (!ptr) return def_val;
701 if (ptr->procA && ptr->procW) return def_val; /* can be both */
702 return (ptr->procW != NULL);
706 /**********************************************************************
707 * WINPROC_TestLBForStr
709 * Return TRUE if the lparam is a string
711 inline static BOOL WINPROC_TestLBForStr( HWND hwnd, UINT msg )
713 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
714 if (msg <= CB_MSGMAX)
715 return (!(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) || (style & CBS_HASSTRINGS));
716 else
717 return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS));
720 /**********************************************************************
721 * WINPROC_MapMsg32ATo32W
723 * Map a message from Ansi to Unicode.
724 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
726 * FIXME:
727 * WM_GETTEXT/WM_SETTEXT and static control with SS_ICON style:
728 * the first four bytes are the handle of the icon
729 * when the WM_SETTEXT message has been used to set the icon
731 static INT WINPROC_MapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
733 switch(msg)
735 case WM_GETTEXT:
736 case WM_ASKCBFORMATNAME:
738 LPARAM *ptr = HeapAlloc( GetProcessHeap(), 0,
739 *pwparam * sizeof(WCHAR) + sizeof(LPARAM) );
740 if (!ptr) return -1;
741 *ptr++ = *plparam; /* Store previous lParam */
742 *plparam = (LPARAM)ptr;
744 return 1;
745 /* lparam is string (0-terminated) */
746 case WM_SETTEXT:
747 case WM_WININICHANGE:
748 case WM_DEVMODECHANGE:
749 case CB_DIR:
750 case LB_DIR:
751 case LB_ADDFILE:
752 case EM_REPLACESEL:
753 if (!*plparam) return 0;
754 else
756 DWORD len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*plparam, -1, NULL, 0);
757 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
758 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*plparam, -1, buf, len);
759 *plparam = (LPARAM)buf;
760 return (*plparam ? 1 : -1);
762 case WM_GETTEXTLENGTH:
763 case CB_GETLBTEXTLEN:
764 case LB_GETTEXTLEN:
765 return 1; /* need to map result */
766 case WM_NCCREATE:
767 case WM_CREATE:
769 UNICODE_STRING usBuffer;
770 struct s
771 { CREATESTRUCTW cs; /* new structure */
772 LPCWSTR lpszName; /* allocated Name */
773 LPCWSTR lpszClass; /* allocated Class */
776 struct s *xs = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct s));
777 if (!xs) return -1;
778 xs->cs = *(CREATESTRUCTW *)*plparam;
779 if (HIWORD(xs->cs.lpszName))
781 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)xs->cs.lpszName);
782 xs->lpszName = xs->cs.lpszName = usBuffer.Buffer;
784 if (HIWORD(xs->cs.lpszClass))
786 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)xs->cs.lpszClass);
787 xs->lpszClass = xs->cs.lpszClass = usBuffer.Buffer;
790 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
792 MDICREATESTRUCTW *mdi_cs = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs));
793 *mdi_cs = *(MDICREATESTRUCTW *)xs->cs.lpCreateParams;
794 if (HIWORD(mdi_cs->szTitle))
796 RtlCreateUnicodeStringFromAsciiz(&usBuffer, (LPCSTR)mdi_cs->szTitle);
797 mdi_cs->szTitle = usBuffer.Buffer;
799 if (HIWORD(mdi_cs->szClass))
801 RtlCreateUnicodeStringFromAsciiz(&usBuffer, (LPCSTR)mdi_cs->szClass);
802 mdi_cs->szClass = usBuffer.Buffer;
804 xs->cs.lpCreateParams = mdi_cs;
807 *plparam = (LPARAM)xs;
809 return 1;
810 case WM_MDICREATE:
812 MDICREATESTRUCTW *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
813 if (!cs) return -1;
814 *cs = *(MDICREATESTRUCTW *)*plparam;
815 if (HIWORD(cs->szClass))
817 UNICODE_STRING usBuffer;
818 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)cs->szClass);
819 cs->szClass = usBuffer.Buffer;
821 if (HIWORD(cs->szTitle))
823 UNICODE_STRING usBuffer;
824 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)cs->szTitle);
825 cs->szTitle = usBuffer.Buffer;
827 *plparam = (LPARAM)cs;
829 return 1;
831 /* Listbox / Combobox */
832 case LB_ADDSTRING:
833 case LB_INSERTSTRING:
834 case LB_FINDSTRING:
835 case LB_FINDSTRINGEXACT:
836 case LB_SELECTSTRING:
837 case CB_ADDSTRING:
838 case CB_INSERTSTRING:
839 case CB_FINDSTRINGEXACT:
840 case CB_FINDSTRING:
841 case CB_SELECTSTRING:
842 if(!*plparam) return 0;
843 if ( WINPROC_TestLBForStr( hwnd, msg ))
845 UNICODE_STRING usBuffer;
846 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)*plparam);
847 *plparam = (LPARAM)usBuffer.Buffer;
849 return (*plparam ? 1 : -1);
851 case LB_GETTEXT: /* FIXME: fixed sized buffer */
852 case CB_GETLBTEXT:
853 if ( WINPROC_TestLBForStr( hwnd, msg ))
855 LPARAM *ptr = HeapAlloc( GetProcessHeap(), 0, 512 * sizeof(WCHAR) + sizeof(LPARAM) );
856 if (!ptr) return -1;
857 *ptr++ = *plparam; /* Store previous lParam */
858 *plparam = (LPARAM)ptr;
860 return 1;
862 /* Multiline edit */
863 case EM_GETLINE:
864 { WORD len = (WORD)*plparam;
865 LPARAM *ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
866 if (!ptr) return -1;
867 *ptr++ = *plparam; /* Store previous lParam */
868 *((WORD *) ptr) = len; /* Store the length */
869 *plparam = (LPARAM)ptr;
871 return 1;
873 case WM_CHARTOITEM:
874 case WM_MENUCHAR:
875 case WM_CHAR:
876 case WM_DEADCHAR:
877 case WM_SYSCHAR:
878 case WM_SYSDEADCHAR:
879 case EM_SETPASSWORDCHAR:
880 *pwparam = map_wparam_char_AtoW( *pwparam, 1 );
881 return 0;
883 case WM_IME_CHAR:
884 *pwparam = map_wparam_char_AtoW( *pwparam, 2 );
885 return 0;
887 case WM_PAINTCLIPBOARD:
888 case WM_SIZECLIPBOARD:
889 FIXME_(msg)("message %s (0x%x) needs translation, please report\n", SPY_GetMsgName(msg, hwnd), msg );
890 return -1;
891 default: /* No translation needed */
892 return 0;
897 /**********************************************************************
898 * WINPROC_UnmapMsg32ATo32W
900 * Unmap a message that was mapped from Ansi to Unicode.
902 static LRESULT WINPROC_UnmapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
903 LRESULT result, WNDPROC dispatch )
905 switch(msg)
907 case WM_GETTEXT:
908 case WM_ASKCBFORMATNAME:
910 LPARAM *ptr = (LPARAM *)lParam - 1;
911 if (!wParam) result = 0;
912 else if (!(result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
913 (LPSTR)*ptr, wParam, NULL, NULL )))
915 ((LPSTR)*ptr)[wParam-1] = 0;
916 result = wParam - 1;
918 else result--; /* do not count terminating null */
919 HeapFree( GetProcessHeap(), 0, ptr );
921 break;
922 case WM_GETTEXTLENGTH:
923 case CB_GETLBTEXTLEN:
924 case LB_GETTEXTLEN:
925 if (result >= 0)
927 /* Determine respective GETTEXT message */
928 UINT msgGetText =
929 (msg == WM_GETTEXTLENGTH) ? WM_GETTEXT :
930 ((msg == CB_GETLBTEXTLEN) ? CB_GETLBTEXT : LB_GETTEXT);
931 /* wParam differs between the messages */
932 WPARAM wp = (msg == WM_GETTEXTLENGTH) ? (WPARAM)(result + 1) : wParam;
934 WCHAR* p = HeapAlloc (GetProcessHeap(), 0, (result + 1) * sizeof(WCHAR));
936 if (p)
938 LRESULT n;
940 if (dispatch)
941 n = WINPROC_CallWndProc(dispatch, hwnd, msgGetText, wp, (LPARAM)p);
942 else
943 n = SendMessageW (hwnd, msgGetText, wp, (LPARAM)p);
945 result = WideCharToMultiByte( CP_ACP, 0, p, n, NULL, 0, 0, NULL );
946 HeapFree (GetProcessHeap(), 0, p);
949 break;
950 case WM_NCCREATE:
951 case WM_CREATE:
953 struct s
954 { CREATESTRUCTW cs; /* new structure */
955 LPWSTR lpszName; /* allocated Name */
956 LPWSTR lpszClass; /* allocated Class */
958 struct s *xs = (struct s *)lParam;
959 HeapFree( GetProcessHeap(), 0, xs->lpszName );
960 HeapFree( GetProcessHeap(), 0, xs->lpszClass );
962 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
964 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)xs->cs.lpCreateParams;
965 if (HIWORD(mdi_cs->szTitle))
966 HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szTitle);
967 if (HIWORD(mdi_cs->szClass))
968 HeapFree(GetProcessHeap(), 0, (LPVOID)mdi_cs->szClass);
969 HeapFree(GetProcessHeap(), 0, mdi_cs);
971 HeapFree( GetProcessHeap(), 0, xs );
973 break;
975 case WM_MDICREATE:
977 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
978 if (HIWORD(cs->szTitle))
979 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
980 if (HIWORD(cs->szClass))
981 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
982 HeapFree( GetProcessHeap(), 0, cs );
984 break;
986 case WM_SETTEXT:
987 case WM_WININICHANGE:
988 case WM_DEVMODECHANGE:
989 case CB_DIR:
990 case LB_DIR:
991 case LB_ADDFILE:
992 case EM_REPLACESEL:
993 HeapFree( GetProcessHeap(), 0, (void *)lParam );
994 break;
996 /* Listbox / Combobox */
997 case LB_ADDSTRING:
998 case LB_INSERTSTRING:
999 case LB_FINDSTRING:
1000 case LB_FINDSTRINGEXACT:
1001 case LB_SELECTSTRING:
1002 case CB_ADDSTRING:
1003 case CB_INSERTSTRING:
1004 case CB_FINDSTRING:
1005 case CB_FINDSTRINGEXACT:
1006 case CB_SELECTSTRING:
1007 if ( WINPROC_TestLBForStr( hwnd, msg ))
1008 HeapFree( GetProcessHeap(), 0, (void *)lParam );
1009 break;
1011 case LB_GETTEXT:
1012 case CB_GETLBTEXT:
1013 if ( WINPROC_TestLBForStr( hwnd, msg ))
1015 LPARAM *ptr = (LPARAM *)lParam - 1;
1016 if (result >= 0)
1017 result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
1018 (LPSTR)*ptr, 0x7fffffff, NULL, NULL ) - 1;
1019 HeapFree( GetProcessHeap(), 0, ptr );
1021 break;
1023 /* Multiline edit */
1024 case EM_GETLINE:
1026 LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lParam */
1027 WORD len = *(WORD *) lParam;
1028 result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, result,
1029 (LPSTR)*ptr, len, NULL, NULL );
1030 if (result < len) ((LPSTR)*ptr)[result] = 0;
1031 HeapFree( GetProcessHeap(), 0, ptr );
1033 break;
1035 return result;
1039 static UINT convert_handle_16_to_32(HANDLE16 src, unsigned int flags)
1041 HANDLE dst;
1042 UINT sz = GlobalSize16(src);
1043 LPSTR ptr16, ptr32;
1045 if (!(dst = GlobalAlloc(flags, sz)))
1046 return 0;
1047 ptr16 = GlobalLock16(src);
1048 ptr32 = GlobalLock(dst);
1049 if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr32, ptr16, sz);
1050 GlobalUnlock16(src);
1051 GlobalUnlock(dst);
1053 return (UINT)dst;
1056 /**********************************************************************
1057 * WINPROC_MapMsg16To32A
1059 * Map a message from 16- to 32-bit Ansi.
1060 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1062 INT WINPROC_MapMsg16To32A( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1063 WPARAM *pwparam32, LPARAM *plparam )
1065 *pmsg32 = (UINT)msg16;
1066 *pwparam32 = (WPARAM)wParam16;
1067 switch(msg16)
1069 case WM_ACTIVATE:
1070 case WM_CHARTOITEM:
1071 case WM_COMMAND:
1072 case WM_VKEYTOITEM:
1073 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1074 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1075 return 0;
1076 case WM_HSCROLL:
1077 case WM_VSCROLL:
1078 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1079 *plparam = (LPARAM)WIN_Handle32( HIWORD(*plparam) );
1080 return 0;
1081 case WM_CTLCOLOR:
1082 if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
1083 *pmsg32 = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
1084 *pwparam32 = (WPARAM)HDC_32(wParam16);
1085 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1086 return 0;
1087 case WM_COMPAREITEM:
1089 COMPAREITEMSTRUCT16* cis16 = MapSL(*plparam);
1090 COMPAREITEMSTRUCT *cis = HeapAlloc(GetProcessHeap(), 0, sizeof(*cis));
1091 if (!cis) return -1;
1092 cis->CtlType = cis16->CtlType;
1093 cis->CtlID = cis16->CtlID;
1094 cis->hwndItem = WIN_Handle32( cis16->hwndItem );
1095 cis->itemID1 = cis16->itemID1;
1096 cis->itemData1 = cis16->itemData1;
1097 cis->itemID2 = cis16->itemID2;
1098 cis->itemData2 = cis16->itemData2;
1099 cis->dwLocaleId = 0; /* FIXME */
1100 *plparam = (LPARAM)cis;
1102 return 1;
1103 case WM_COPYDATA:
1105 PCOPYDATASTRUCT16 pcds16 = MapSL(*plparam);
1106 PCOPYDATASTRUCT pcds = HeapAlloc ( GetProcessHeap(), 0, sizeof(*pcds));
1107 pcds->dwData = pcds16->dwData;
1108 pcds->cbData = pcds16->cbData;
1109 pcds->lpData = MapSL( pcds16->lpData);
1110 *plparam = (LPARAM)pcds;
1112 return 1;
1113 case WM_DELETEITEM:
1115 DELETEITEMSTRUCT16* dis16 = MapSL(*plparam);
1116 DELETEITEMSTRUCT *dis = HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
1117 if (!dis) return -1;
1118 dis->CtlType = dis16->CtlType;
1119 dis->CtlID = dis16->CtlID;
1120 dis->hwndItem = WIN_Handle32( dis16->hwndItem );
1121 dis->itemData = dis16->itemData;
1122 *plparam = (LPARAM)dis;
1124 return 1;
1125 case WM_MEASUREITEM:
1127 MEASUREITEMSTRUCT16* mis16 = MapSL(*plparam);
1128 MEASUREITEMSTRUCT *mis = HeapAlloc(GetProcessHeap(), 0,
1129 sizeof(*mis) + sizeof(LPARAM));
1130 if (!mis) return -1;
1131 mis->CtlType = mis16->CtlType;
1132 mis->CtlID = mis16->CtlID;
1133 mis->itemID = mis16->itemID;
1134 mis->itemWidth = mis16->itemWidth;
1135 mis->itemHeight = mis16->itemHeight;
1136 mis->itemData = mis16->itemData;
1137 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
1138 *plparam = (LPARAM)mis;
1140 return 1;
1141 case WM_DRAWITEM:
1143 DRAWITEMSTRUCT16* dis16 = MapSL(*plparam);
1144 DRAWITEMSTRUCT *dis = HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
1145 if (!dis) return -1;
1146 dis->CtlType = dis16->CtlType;
1147 dis->CtlID = dis16->CtlID;
1148 dis->itemID = dis16->itemID;
1149 dis->itemAction = dis16->itemAction;
1150 dis->itemState = dis16->itemState;
1151 dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND)HMENU_32(dis16->hwndItem)
1152 : WIN_Handle32( dis16->hwndItem );
1153 dis->hDC = HDC_32(dis16->hDC);
1154 dis->itemData = dis16->itemData;
1155 dis->rcItem.left = dis16->rcItem.left;
1156 dis->rcItem.top = dis16->rcItem.top;
1157 dis->rcItem.right = dis16->rcItem.right;
1158 dis->rcItem.bottom = dis16->rcItem.bottom;
1159 *plparam = (LPARAM)dis;
1161 return 1;
1162 case WM_GETMINMAXINFO:
1164 MINMAXINFO *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM));
1165 if (!mmi) return -1;
1166 MINMAXINFO16to32( MapSL(*plparam), mmi );
1167 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
1168 *plparam = (LPARAM)mmi;
1170 return 1;
1171 case WM_GETTEXT:
1172 case WM_SETTEXT:
1173 case WM_WININICHANGE:
1174 case WM_DEVMODECHANGE:
1175 case WM_ASKCBFORMATNAME:
1176 *plparam = (LPARAM)MapSL(*plparam);
1177 return 0;
1178 case WM_MDICREATE:
1180 MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1181 MDICREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1182 if (!cs) return -1;
1183 MDICREATESTRUCT16to32A( cs16, cs );
1184 cs->szTitle = MapSL(cs16->szTitle);
1185 cs->szClass = MapSL(cs16->szClass);
1186 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1187 *plparam = (LPARAM)cs;
1189 return 1;
1190 case WM_MDIGETACTIVE:
1191 *plparam = (LPARAM)HeapAlloc( GetProcessHeap(), 0, sizeof(BOOL) );
1192 *(BOOL*)(*plparam) = 0;
1193 return 1;
1194 case WM_MDISETMENU:
1195 if(wParam16) *pmsg32=WM_MDIREFRESHMENU;
1196 *pwparam32 = (WPARAM)HMENU_32(LOWORD(*plparam));
1197 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1198 return 0;
1199 case WM_MENUCHAR:
1200 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1201 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1202 return 0;
1203 case WM_MENUSELECT:
1204 if((LOWORD(*plparam) & MF_POPUP) && (LOWORD(*plparam) != 0xFFFF))
1206 HMENU hmenu=HMENU_32(HIWORD(*plparam));
1207 UINT Pos=MENU_FindSubMenu( &hmenu, HMENU_32(wParam16));
1208 if(Pos==0xFFFF) Pos=0; /* NO_SELECTED_ITEM */
1209 *pwparam32 = MAKEWPARAM( Pos, LOWORD(*plparam) );
1211 else *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1212 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1213 return 0;
1214 case WM_MDIACTIVATE:
1215 if( *plparam )
1217 *pwparam32 = (WPARAM)WIN_Handle32( HIWORD(*plparam) );
1218 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1220 else /* message sent to MDI client */
1221 *pwparam32 = wParam16;
1222 return 0;
1223 case WM_NCCALCSIZE:
1225 NCCALCSIZE_PARAMS16 *nc16;
1226 NCCALCSIZE_PARAMS *nc;
1228 nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM) );
1229 if (!nc) return -1;
1230 nc16 = MapSL(*plparam);
1231 nc->rgrc[0].left = nc16->rgrc[0].left;
1232 nc->rgrc[0].top = nc16->rgrc[0].top;
1233 nc->rgrc[0].right = nc16->rgrc[0].right;
1234 nc->rgrc[0].bottom = nc16->rgrc[0].bottom;
1235 if (wParam16)
1237 nc->lppos = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc->lppos) );
1238 nc->rgrc[1].left = nc16->rgrc[1].left;
1239 nc->rgrc[1].top = nc16->rgrc[1].top;
1240 nc->rgrc[1].right = nc16->rgrc[1].right;
1241 nc->rgrc[1].bottom = nc16->rgrc[1].bottom;
1242 nc->rgrc[2].left = nc16->rgrc[2].left;
1243 nc->rgrc[2].top = nc16->rgrc[2].top;
1244 nc->rgrc[2].right = nc16->rgrc[2].right;
1245 nc->rgrc[2].bottom = nc16->rgrc[2].bottom;
1246 if (nc->lppos) WINDOWPOS16to32( MapSL(nc16->lppos), nc->lppos );
1248 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
1249 *plparam = (LPARAM)nc;
1251 return 1;
1252 case WM_NCCREATE:
1253 case WM_CREATE:
1255 CREATESTRUCT16 *cs16 = MapSL(*plparam);
1256 CREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1257 if (!cs) return -1;
1258 CREATESTRUCT16to32A( cs16, cs );
1259 cs->lpszName = MapSL(cs16->lpszName);
1260 cs->lpszClass = MapSL(cs16->lpszClass);
1262 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1264 MDICREATESTRUCT16 *mdi_cs16;
1265 MDICREATESTRUCTA *mdi_cs = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs));
1266 if (!mdi_cs)
1268 HeapFree(GetProcessHeap(), 0, cs);
1269 return -1;
1271 mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs16->lpCreateParams);
1272 MDICREATESTRUCT16to32A(mdi_cs16, mdi_cs);
1273 mdi_cs->szTitle = MapSL(mdi_cs16->szTitle);
1274 mdi_cs->szClass = MapSL(mdi_cs16->szClass);
1276 cs->lpCreateParams = mdi_cs;
1278 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1279 *plparam = (LPARAM)cs;
1281 return 1;
1282 case WM_PARENTNOTIFY:
1283 if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
1285 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1286 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1288 return 0;
1289 case WM_WINDOWPOSCHANGING:
1290 case WM_WINDOWPOSCHANGED:
1292 WINDOWPOS *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
1293 if (!wp) return -1;
1294 WINDOWPOS16to32( MapSL(*plparam), wp );
1295 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
1296 *plparam = (LPARAM)wp;
1298 return 1;
1299 case WM_GETDLGCODE:
1300 if (*plparam)
1302 LPMSG16 msg16 = MapSL(*plparam);
1303 LPMSG msg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1305 if (!msg32) return -1;
1306 msg32->hwnd = WIN_Handle32( msg16->hwnd );
1307 msg32->message = msg16->message;
1308 msg32->wParam = msg16->wParam;
1309 msg32->lParam = msg16->lParam;
1310 msg32->time = msg16->time;
1311 msg32->pt.x = msg16->pt.x;
1312 msg32->pt.y = msg16->pt.y;
1313 *plparam = (LPARAM)msg32;
1314 return 1;
1316 else return 0;
1317 case WM_NOTIFY:
1318 *plparam = (LPARAM)MapSL(*plparam);
1319 return 0;
1320 case WM_ACTIVATEAPP:
1321 /* We need this when SetActiveWindow sends a Sendmessage16() to
1322 * a 32bit window. Might be superflous with 32bit interprocess
1323 * message queues. */
1324 if (*plparam) *plparam = HTASK_32( *plparam );
1325 return 0;
1326 case WM_NEXTMENU:
1328 MDINEXTMENU *next = HeapAlloc( GetProcessHeap(), 0, sizeof(*next) );
1329 if (!next) return -1;
1330 next->hmenuIn = (HMENU)*plparam;
1331 next->hmenuNext = 0;
1332 next->hwndNext = 0;
1333 *plparam = (LPARAM)next;
1334 return 1;
1336 case WM_PAINTCLIPBOARD:
1337 case WM_SIZECLIPBOARD:
1338 FIXME_(msg)("message %04x needs translation\n",msg16 );
1339 return -1;
1340 case WM_DDE_INITIATE:
1341 case WM_DDE_TERMINATE:
1342 case WM_DDE_UNADVISE:
1343 case WM_DDE_REQUEST:
1344 *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1345 return 0;
1346 case WM_DDE_ADVISE:
1347 case WM_DDE_DATA:
1348 case WM_DDE_POKE:
1350 HANDLE16 lo16;
1351 ATOM hi;
1352 UINT lo32 = 0;
1354 *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1355 lo16 = LOWORD(*plparam);
1356 hi = HIWORD(*plparam);
1357 if (lo16 && !(lo32 = convert_handle_16_to_32(lo16, GMEM_DDESHARE)))
1358 return -1;
1359 *plparam = PackDDElParam(msg16, lo32, hi);
1361 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1362 case WM_DDE_ACK:
1364 UINT lo, hi;
1365 int flag = 0;
1366 char buf[2];
1368 *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1370 lo = LOWORD(*plparam);
1371 hi = HIWORD(*plparam);
1373 if (GlobalGetAtomNameA(hi, buf, 2) > 0) flag |= 1;
1374 if (GlobalSize16(hi) != 0) flag |= 2;
1375 switch (flag)
1377 case 0:
1378 if (hi)
1380 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1381 hi = 0;
1383 break;
1384 case 1:
1385 break; /* atom, nothing to do */
1386 case 3:
1387 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
1388 /* fall thru */
1389 case 2:
1390 hi = convert_handle_16_to_32(hi, GMEM_DDESHARE);
1391 break;
1393 *plparam = PackDDElParam(WM_DDE_ACK, lo, hi);
1395 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1396 case WM_DDE_EXECUTE:
1397 *plparam = convert_handle_16_to_32(*plparam, GMEM_DDESHARE);
1398 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1399 default: /* No translation needed */
1400 return 0;
1405 /**********************************************************************
1406 * WINPROC_UnmapMsg16To32A
1408 * Unmap a message that was mapped from 16- to 32-bit Ansi.
1410 static LRESULT WINPROC_UnmapMsg16To32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1411 LRESULT result )
1413 switch(msg)
1415 case WM_COMPAREITEM:
1416 case WM_DELETEITEM:
1417 case WM_DRAWITEM:
1418 case WM_COPYDATA:
1419 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
1420 break;
1421 case WM_MEASUREITEM:
1423 MEASUREITEMSTRUCT16 *mis16;
1424 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam;
1425 lParam = *(LPARAM *)(mis + 1);
1426 mis16 = MapSL(lParam);
1427 mis16->itemWidth = (UINT16)mis->itemWidth;
1428 mis16->itemHeight = (UINT16)mis->itemHeight;
1429 HeapFree( GetProcessHeap(), 0, mis );
1431 break;
1432 case WM_GETMINMAXINFO:
1434 MINMAXINFO *mmi = (MINMAXINFO *)lParam;
1435 lParam = *(LPARAM *)(mmi + 1);
1436 MINMAXINFO32to16( mmi, MapSL(lParam));
1437 HeapFree( GetProcessHeap(), 0, mmi );
1439 break;
1440 case WM_MDICREATE:
1442 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1443 lParam = *(LPARAM *)(cs + 1);
1444 MDICREATESTRUCT32Ato16( cs, MapSL(lParam) );
1445 HeapFree( GetProcessHeap(), 0, cs );
1447 break;
1448 case WM_MDIGETACTIVE:
1449 result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL *)lParam) );
1450 HeapFree( GetProcessHeap(), 0, (BOOL *)lParam );
1451 break;
1452 case WM_NCCALCSIZE:
1454 NCCALCSIZE_PARAMS16 *nc16;
1455 NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lParam;
1456 lParam = *(LPARAM *)(nc + 1);
1457 nc16 = MapSL(lParam);
1458 nc16->rgrc[0].left = nc->rgrc[0].left;
1459 nc16->rgrc[0].top = nc->rgrc[0].top;
1460 nc16->rgrc[0].right = nc->rgrc[0].right;
1461 nc16->rgrc[0].bottom = nc->rgrc[0].bottom;
1462 if (wParam)
1464 nc16->rgrc[1].left = nc->rgrc[1].left;
1465 nc16->rgrc[1].top = nc->rgrc[1].top;
1466 nc16->rgrc[1].right = nc->rgrc[1].right;
1467 nc16->rgrc[1].bottom = nc->rgrc[1].bottom;
1468 nc16->rgrc[2].left = nc->rgrc[2].left;
1469 nc16->rgrc[2].top = nc->rgrc[2].top;
1470 nc16->rgrc[2].right = nc->rgrc[2].right;
1471 nc16->rgrc[2].bottom = nc->rgrc[2].bottom;
1472 if (nc->lppos)
1474 WINDOWPOS32to16( nc->lppos, MapSL(nc16->lppos));
1475 HeapFree( GetProcessHeap(), 0, nc->lppos );
1478 HeapFree( GetProcessHeap(), 0, nc );
1480 break;
1481 case WM_NCCREATE:
1482 case WM_CREATE:
1484 CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1485 lParam = *(LPARAM *)(cs + 1);
1486 CREATESTRUCT32Ato16( cs, MapSL(lParam) );
1488 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1489 HeapFree(GetProcessHeap(), 0, cs->lpCreateParams);
1491 HeapFree( GetProcessHeap(), 0, cs );
1493 break;
1494 case WM_WINDOWPOSCHANGING:
1495 case WM_WINDOWPOSCHANGED:
1497 WINDOWPOS *wp = (WINDOWPOS *)lParam;
1498 lParam = *(LPARAM *)(wp + 1);
1499 WINDOWPOS32to16(wp, MapSL(lParam));
1500 HeapFree( GetProcessHeap(), 0, wp );
1502 break;
1503 case WM_GETDLGCODE:
1504 if (lParam)
1506 LPMSG msg32 = (LPMSG)lParam;
1507 HeapFree( GetProcessHeap(), 0, msg32 );
1509 break;
1510 case WM_NEXTMENU:
1512 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
1513 result = MAKELONG( HMENU_16(next->hmenuNext), HWND_16(next->hwndNext) );
1514 HeapFree( GetProcessHeap(), 0, next );
1516 break;
1518 return result;
1522 /**********************************************************************
1523 * WINPROC_MapMsg16To32W
1525 * Map a message from 16- to 32-bit Unicode.
1526 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1528 static INT WINPROC_MapMsg16To32W( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1529 WPARAM *pwparam32, LPARAM *plparam )
1531 *pmsg32=(UINT)msg16;
1532 *pwparam32 = (WPARAM)wParam16;
1533 switch(msg16)
1535 case WM_GETTEXT:
1536 case WM_SETTEXT:
1537 case WM_WININICHANGE:
1538 case WM_DEVMODECHANGE:
1539 case WM_ASKCBFORMATNAME:
1540 *plparam = (LPARAM)MapSL(*plparam);
1541 return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, pwparam32, plparam );
1542 case WM_GETTEXTLENGTH:
1543 case CB_GETLBTEXTLEN:
1544 case LB_GETTEXTLEN:
1545 return 1; /* need to map result */
1546 case WM_NCCREATE:
1547 case WM_CREATE:
1549 CREATESTRUCT16 *cs16 = MapSL(*plparam);
1550 CREATESTRUCTW *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1551 if (!cs) return -1;
1552 CREATESTRUCT16to32A( cs16, (CREATESTRUCTA *)cs );
1553 cs->lpszName = map_str_16_to_32W(cs16->lpszName);
1554 cs->lpszClass = map_str_16_to_32W(cs16->lpszClass);
1556 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1558 MDICREATESTRUCT16 *mdi_cs16;
1559 MDICREATESTRUCTW *mdi_cs = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs));
1560 if (!mdi_cs)
1562 HeapFree(GetProcessHeap(), 0, cs);
1563 return -1;
1565 mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs16->lpCreateParams);
1566 MDICREATESTRUCT16to32A(mdi_cs16, (MDICREATESTRUCTA *)mdi_cs);
1567 mdi_cs->szTitle = map_str_16_to_32W(mdi_cs16->szTitle);
1568 mdi_cs->szClass = map_str_16_to_32W(mdi_cs16->szClass);
1570 cs->lpCreateParams = mdi_cs;
1572 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1573 *plparam = (LPARAM)cs;
1575 return 1;
1576 case WM_MDICREATE:
1578 MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1579 MDICREATESTRUCTW *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1580 if (!cs) return -1;
1581 MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCTA *)cs );
1582 cs->szTitle = map_str_16_to_32W(cs16->szTitle);
1583 cs->szClass = map_str_16_to_32W(cs16->szClass);
1584 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1585 *plparam = (LPARAM)cs;
1587 return 1;
1588 case WM_GETDLGCODE:
1589 if (*plparam)
1591 LPMSG16 msg16 = MapSL(*plparam);
1592 LPMSG msg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1594 if (!msg32) return -1;
1595 msg32->hwnd = WIN_Handle32( msg16->hwnd );
1596 msg32->message = msg16->message;
1597 msg32->wParam = msg16->wParam;
1598 msg32->lParam = msg16->lParam;
1599 msg32->time = msg16->time;
1600 msg32->pt.x = msg16->pt.x;
1601 msg32->pt.y = msg16->pt.y;
1602 switch(msg32->message)
1604 case WM_CHAR:
1605 case WM_DEADCHAR:
1606 case WM_SYSCHAR:
1607 case WM_SYSDEADCHAR:
1608 msg32->wParam = map_wparam_char_AtoW( msg16->wParam, 1 );
1609 break;
1611 *plparam = (LPARAM)msg32;
1612 return 1;
1614 else return 0;
1616 case WM_CHARTOITEM:
1617 *pwparam32 = MAKEWPARAM( map_wparam_char_AtoW( wParam16, 1 ), HIWORD(*plparam) );
1618 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1619 return 0;
1620 case WM_MENUCHAR:
1621 *pwparam32 = MAKEWPARAM( map_wparam_char_AtoW( wParam16, 1 ), LOWORD(*plparam) );
1622 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1623 return 0;
1624 case WM_CHAR:
1625 case WM_DEADCHAR:
1626 case WM_SYSCHAR:
1627 case WM_SYSDEADCHAR:
1628 *pwparam32 = map_wparam_char_AtoW( wParam16, 1 );
1629 return 0;
1630 case WM_IME_CHAR:
1631 *pwparam32 = map_wparam_char_AtoW( wParam16, 2 );
1632 return 0;
1634 default: /* No Unicode translation needed */
1635 return WINPROC_MapMsg16To32A( hwnd, msg16, wParam16, pmsg32,
1636 pwparam32, plparam );
1641 /**********************************************************************
1642 * WINPROC_UnmapMsg16To32W
1644 * Unmap a message that was mapped from 16- to 32-bit Unicode.
1646 static LRESULT WINPROC_UnmapMsg16To32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1647 LRESULT result, WNDPROC dispatch )
1649 switch(msg)
1651 case WM_GETTEXT:
1652 case WM_SETTEXT:
1653 case WM_GETTEXTLENGTH:
1654 case CB_GETLBTEXTLEN:
1655 case LB_GETTEXTLEN:
1656 case WM_ASKCBFORMATNAME:
1657 return WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result, dispatch );
1658 case WM_NCCREATE:
1659 case WM_CREATE:
1661 CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
1662 lParam = *(LPARAM *)(cs + 1);
1663 CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs, MapSL(lParam) );
1664 unmap_str_16_to_32W( cs->lpszName );
1665 unmap_str_16_to_32W( cs->lpszClass );
1667 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1669 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)cs->lpCreateParams;
1670 unmap_str_16_to_32W( mdi_cs->szTitle );
1671 unmap_str_16_to_32W( mdi_cs->szClass );
1672 HeapFree(GetProcessHeap(), 0, cs->lpCreateParams);
1674 HeapFree( GetProcessHeap(), 0, cs );
1676 break;
1677 case WM_MDICREATE:
1679 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
1680 lParam = *(LPARAM *)(cs + 1);
1681 MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs, MapSL(lParam) );
1682 unmap_str_16_to_32W( cs->szTitle );
1683 unmap_str_16_to_32W( cs->szClass );
1684 HeapFree( GetProcessHeap(), 0, cs );
1686 break;
1687 case WM_GETDLGCODE:
1688 if (lParam)
1690 LPMSG msg32 = (LPMSG)lParam;
1691 HeapFree( GetProcessHeap(), 0, msg32 );
1693 break;
1694 default:
1695 return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1697 return result;
1700 static HANDLE16 convert_handle_32_to_16(UINT src, unsigned int flags)
1702 HANDLE16 dst;
1703 UINT sz = GlobalSize((HANDLE)src);
1704 LPSTR ptr16, ptr32;
1706 if (!(dst = GlobalAlloc16(flags, sz)))
1707 return 0;
1708 ptr32 = GlobalLock((HANDLE)src);
1709 ptr16 = GlobalLock16(dst);
1710 if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr16, ptr32, sz);
1711 GlobalUnlock((HANDLE)src);
1712 GlobalUnlock16(dst);
1714 return dst;
1718 /**********************************************************************
1719 * WINPROC_MapMsg32ATo16
1721 * Map a message from 32-bit Ansi to 16-bit.
1722 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1724 INT WINPROC_MapMsg32ATo16( HWND hwnd, UINT msg32, WPARAM wParam32,
1725 UINT16 *pmsg16, WPARAM16 *pwparam16,
1726 LPARAM *plparam )
1728 *pmsg16 = (UINT16)msg32;
1729 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1730 switch(msg32)
1732 case SBM_SETRANGE:
1733 *pmsg16 = SBM_SETRANGE16;
1734 *plparam = MAKELPARAM(wParam32, *plparam);
1735 *pwparam16 = 0;
1736 return 0;
1738 case SBM_GETRANGE:
1739 *pmsg16 = SBM_GETRANGE16;
1740 return 1;
1742 case BM_GETCHECK:
1743 case BM_SETCHECK:
1744 case BM_GETSTATE:
1745 case BM_SETSTATE:
1746 case BM_SETSTYLE:
1747 *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK);
1748 return 0;
1750 case EM_GETSEL:
1751 case EM_GETRECT:
1752 case EM_SETRECT:
1753 case EM_SETRECTNP:
1754 case EM_SCROLL:
1755 case EM_LINESCROLL:
1756 case EM_SCROLLCARET:
1757 case EM_GETMODIFY:
1758 case EM_SETMODIFY:
1759 case EM_GETLINECOUNT:
1760 case EM_LINEINDEX:
1761 case EM_SETHANDLE:
1762 case EM_GETHANDLE:
1763 case EM_GETTHUMB:
1764 case EM_LINELENGTH:
1765 case EM_REPLACESEL:
1766 case EM_GETLINE:
1767 case EM_LIMITTEXT:
1768 case EM_CANUNDO:
1769 case EM_UNDO:
1770 case EM_FMTLINES:
1771 case EM_LINEFROMCHAR:
1772 case EM_SETTABSTOPS:
1773 case EM_SETPASSWORDCHAR:
1774 case EM_EMPTYUNDOBUFFER:
1775 case EM_GETFIRSTVISIBLELINE:
1776 case EM_SETREADONLY:
1777 case EM_SETWORDBREAKPROC:
1778 case EM_GETWORDBREAKPROC:
1779 case EM_GETPASSWORDCHAR:
1780 *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL);
1781 return 0;
1783 case LB_CARETOFF:
1784 case LB_CARETON:
1785 case LB_DELETESTRING:
1786 case LB_GETANCHORINDEX:
1787 case LB_GETCARETINDEX:
1788 case LB_GETCOUNT:
1789 case LB_GETCURSEL:
1790 case LB_GETHORIZONTALEXTENT:
1791 case LB_GETITEMDATA:
1792 case LB_GETITEMHEIGHT:
1793 case LB_GETSEL:
1794 case LB_GETSELCOUNT:
1795 case LB_GETTEXTLEN:
1796 case LB_GETTOPINDEX:
1797 case LB_RESETCONTENT:
1798 case LB_SELITEMRANGE:
1799 case LB_SELITEMRANGEEX:
1800 case LB_SETANCHORINDEX:
1801 case LB_SETCARETINDEX:
1802 case LB_SETCOLUMNWIDTH:
1803 case LB_SETCURSEL:
1804 case LB_SETHORIZONTALEXTENT:
1805 case LB_SETITEMDATA:
1806 case LB_SETITEMHEIGHT:
1807 case LB_SETSEL:
1808 case LB_SETTOPINDEX:
1809 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1810 return 0;
1811 case CB_DELETESTRING:
1812 case CB_GETCOUNT:
1813 case CB_GETLBTEXTLEN:
1814 case CB_LIMITTEXT:
1815 case CB_RESETCONTENT:
1816 case CB_SETEDITSEL:
1817 case CB_GETCURSEL:
1818 case CB_SETCURSEL:
1819 case CB_SHOWDROPDOWN:
1820 case CB_SETITEMDATA:
1821 case CB_SETITEMHEIGHT:
1822 case CB_GETITEMHEIGHT:
1823 case CB_SETEXTENDEDUI:
1824 case CB_GETEXTENDEDUI:
1825 case CB_GETDROPPEDSTATE:
1826 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1827 return 0;
1828 case CB_GETEDITSEL:
1829 *pmsg16 = CB_GETEDITSEL16;
1830 return 1;
1832 case LB_ADDSTRING:
1833 case LB_FINDSTRING:
1834 case LB_FINDSTRINGEXACT:
1835 case LB_INSERTSTRING:
1836 case LB_SELECTSTRING:
1837 case LB_DIR:
1838 case LB_ADDFILE:
1839 *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1840 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1841 return 1;
1843 case CB_ADDSTRING:
1844 case CB_FINDSTRING:
1845 case CB_FINDSTRINGEXACT:
1846 case CB_INSERTSTRING:
1847 case CB_SELECTSTRING:
1848 case CB_DIR:
1849 *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1850 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1851 return 1;
1853 case LB_GETITEMRECT:
1855 RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1856 if (!rect) return -1;
1857 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1858 *plparam = MapLS( rect );
1860 *pmsg16 = LB_GETITEMRECT16;
1861 return 1;
1862 case LB_GETSELITEMS:
1864 LPARAM *items; /* old LPARAM first, then *pwparam16 x INT16 entries */
1866 *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1867 if (!(items = HeapAlloc( GetProcessHeap(), 0,
1868 *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
1869 *items++ = *plparam; /* Store the previous lParam */
1870 *plparam = MapLS( items );
1872 *pmsg16 = LB_GETSELITEMS16;
1873 return 1;
1874 case LB_SETTABSTOPS:
1875 if (wParam32)
1877 INT i;
1878 LPINT16 stops;
1879 *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1880 if (!(stops = HeapAlloc( GetProcessHeap(), 0,
1881 *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
1882 for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT)*plparam+i);
1883 *plparam = MapLS( stops );
1884 return 1;
1886 *pmsg16 = LB_SETTABSTOPS16;
1887 return 0;
1889 case CB_GETDROPPEDCONTROLRECT:
1891 RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1892 if (!rect) return -1;
1893 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1894 *plparam = (LPARAM)MapLS(rect);
1896 *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
1897 return 1;
1899 case LB_GETTEXT:
1900 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1901 *pmsg16 = LB_GETTEXT16;
1902 return 1;
1904 case CB_GETLBTEXT:
1905 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1906 *pmsg16 = CB_GETLBTEXT16;
1907 return 1;
1909 case EM_SETSEL:
1910 *pwparam16 = 0;
1911 *plparam = MAKELONG( (INT16)(INT)wParam32, (INT16)*plparam );
1912 *pmsg16 = EM_SETSEL16;
1913 return 0;
1915 case WM_ACTIVATE:
1916 case WM_CHARTOITEM:
1917 case WM_COMMAND:
1918 case WM_VKEYTOITEM:
1919 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
1920 return 0;
1921 case WM_HSCROLL:
1922 case WM_VSCROLL:
1923 *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
1924 return 0;
1925 case WM_COPYDATA:
1927 PCOPYDATASTRUCT pcds32 = (PCOPYDATASTRUCT) *plparam;
1928 PCOPYDATASTRUCT16 pcds = HeapAlloc( GetProcessHeap(), 0, sizeof( *pcds));
1929 pcds->dwData = pcds32->dwData;
1930 pcds->cbData = pcds32->cbData;
1931 pcds->lpData = MapLS( pcds32->lpData);
1932 *plparam = MapLS( pcds );
1934 return 1;
1935 case WM_CTLCOLORMSGBOX:
1936 case WM_CTLCOLOREDIT:
1937 case WM_CTLCOLORLISTBOX:
1938 case WM_CTLCOLORBTN:
1939 case WM_CTLCOLORDLG:
1940 case WM_CTLCOLORSCROLLBAR:
1941 case WM_CTLCOLORSTATIC:
1942 *pmsg16 = WM_CTLCOLOR;
1943 *plparam = MAKELPARAM( (HWND16)*plparam,
1944 (WORD)msg32 - WM_CTLCOLORMSGBOX );
1945 return 0;
1946 case WM_COMPAREITEM:
1948 COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)*plparam;
1949 COMPAREITEMSTRUCT16 *cis = HeapAlloc( GetProcessHeap(), 0, sizeof(COMPAREITEMSTRUCT16));
1950 if (!cis) return -1;
1951 cis->CtlType = (UINT16)cis32->CtlType;
1952 cis->CtlID = (UINT16)cis32->CtlID;
1953 cis->hwndItem = HWND_16( cis32->hwndItem );
1954 cis->itemID1 = (UINT16)cis32->itemID1;
1955 cis->itemData1 = cis32->itemData1;
1956 cis->itemID2 = (UINT16)cis32->itemID2;
1957 cis->itemData2 = cis32->itemData2;
1958 *plparam = MapLS( cis );
1960 return 1;
1961 case WM_DELETEITEM:
1963 DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)*plparam;
1964 DELETEITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DELETEITEMSTRUCT16) );
1965 if (!dis) return -1;
1966 dis->CtlType = (UINT16)dis32->CtlType;
1967 dis->CtlID = (UINT16)dis32->CtlID;
1968 dis->itemID = (UINT16)dis32->itemID;
1969 dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem)
1970 : HWND_16( dis32->hwndItem );
1971 dis->itemData = dis32->itemData;
1972 *plparam = MapLS( dis );
1974 return 1;
1975 case WM_DRAWITEM:
1977 DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)*plparam;
1978 DRAWITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DRAWITEMSTRUCT16) );
1979 if (!dis) return -1;
1980 dis->CtlType = (UINT16)dis32->CtlType;
1981 dis->CtlID = (UINT16)dis32->CtlID;
1982 dis->itemID = (UINT16)dis32->itemID;
1983 dis->itemAction = (UINT16)dis32->itemAction;
1984 dis->itemState = (UINT16)dis32->itemState;
1985 dis->hwndItem = HWND_16( dis32->hwndItem );
1986 dis->hDC = HDC_16(dis32->hDC);
1987 dis->itemData = dis32->itemData;
1988 dis->rcItem.left = dis32->rcItem.left;
1989 dis->rcItem.top = dis32->rcItem.top;
1990 dis->rcItem.right = dis32->rcItem.right;
1991 dis->rcItem.bottom = dis32->rcItem.bottom;
1992 *plparam = MapLS( dis );
1994 return 1;
1995 case WM_MEASUREITEM:
1997 MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)*plparam;
1998 MEASUREITEMSTRUCT16 *mis = HeapAlloc( GetProcessHeap(), 0, sizeof(*mis)+sizeof(LPARAM));
1999 if (!mis) return -1;
2000 mis->CtlType = (UINT16)mis32->CtlType;
2001 mis->CtlID = (UINT16)mis32->CtlID;
2002 mis->itemID = (UINT16)mis32->itemID;
2003 mis->itemWidth = (UINT16)mis32->itemWidth;
2004 mis->itemHeight = (UINT16)mis32->itemHeight;
2005 mis->itemData = mis32->itemData;
2006 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
2007 *plparam = MapLS( mis );
2009 return 1;
2010 case WM_GETMINMAXINFO:
2012 MINMAXINFO16 *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM) );
2013 if (!mmi) return -1;
2014 MINMAXINFO32to16( (MINMAXINFO *)*plparam, mmi );
2015 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
2016 *plparam = MapLS( mmi );
2018 return 1;
2019 case WM_GETTEXT:
2020 case WM_ASKCBFORMATNAME:
2022 LPARAM *str; /* store LPARAM, then *pwparam16 char space */
2023 *pwparam16 = (WPARAM16)min( wParam32, 0xff80 ); /* Must be < 64K */
2024 if (!(str = HeapAlloc( GetProcessHeap(), 0, *pwparam16 + sizeof(LPARAM)))) return -1;
2025 *str++ = *plparam; /* Store the previous lParam */
2026 *plparam = MapLS( str );
2028 return 1;
2029 case WM_MDICREATE:
2031 MDICREATESTRUCT16 *cs;
2032 MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)*plparam;
2034 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2035 MDICREATESTRUCT32Ato16( cs32, cs );
2036 cs->szTitle = MapLS( cs32->szTitle );
2037 cs->szClass = MapLS( cs32->szClass );
2038 *plparam = MapLS( cs );
2040 return 1;
2041 case WM_MDIGETACTIVE:
2042 return 1;
2043 case WM_MDISETMENU:
2044 *plparam = MAKELPARAM( (HMENU16)LOWORD(wParam32),
2045 (HMENU16)LOWORD(*plparam) );
2046 *pwparam16 = (*plparam == 0);
2047 return 0;
2048 case WM_MENUSELECT:
2049 if(HIWORD(wParam32) & MF_POPUP)
2051 HMENU hmenu;
2052 if (((UINT)HIWORD(wParam32) != 0xFFFF) || (*plparam))
2054 if((hmenu = GetSubMenu((HMENU)*plparam, *pwparam16)))
2055 *pwparam16=HMENU_16(hmenu);
2058 /* fall through */
2059 case WM_MENUCHAR:
2060 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2061 return 0;
2062 case WM_MDIACTIVATE:
2063 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
2065 *pwparam16 = ((HWND)*plparam == hwnd);
2066 *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
2067 (HWND16)LOWORD(wParam32) );
2069 else
2071 *pwparam16 = HWND_16( (HWND)wParam32 );
2072 *plparam = 0;
2074 return 0;
2075 case WM_NCCALCSIZE:
2077 NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)*plparam;
2078 NCCALCSIZE_PARAMS16 *nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM));
2079 if (!nc) return -1;
2081 nc->rgrc[0].left = nc32->rgrc[0].left;
2082 nc->rgrc[0].top = nc32->rgrc[0].top;
2083 nc->rgrc[0].right = nc32->rgrc[0].right;
2084 nc->rgrc[0].bottom = nc32->rgrc[0].bottom;
2085 if (wParam32)
2087 WINDOWPOS16 *wp;
2088 nc->rgrc[1].left = nc32->rgrc[1].left;
2089 nc->rgrc[1].top = nc32->rgrc[1].top;
2090 nc->rgrc[1].right = nc32->rgrc[1].right;
2091 nc->rgrc[1].bottom = nc32->rgrc[1].bottom;
2092 nc->rgrc[2].left = nc32->rgrc[2].left;
2093 nc->rgrc[2].top = nc32->rgrc[2].top;
2094 nc->rgrc[2].right = nc32->rgrc[2].right;
2095 nc->rgrc[2].bottom = nc32->rgrc[2].bottom;
2096 if (!(wp = HeapAlloc( GetProcessHeap(), 0, sizeof(WINDOWPOS16) )))
2098 HeapFree( GetProcessHeap(), 0, nc );
2099 return -1;
2101 WINDOWPOS32to16( nc32->lppos, wp );
2102 nc->lppos = MapLS( wp );
2104 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
2105 *plparam = MapLS( nc );
2107 return 1;
2108 case WM_NCCREATE:
2109 case WM_CREATE:
2111 CREATESTRUCT16 *cs;
2112 CREATESTRUCTA *cs32 = (CREATESTRUCTA *)*plparam;
2114 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2115 CREATESTRUCT32Ato16( cs32, cs );
2116 cs->lpszName = MapLS( cs32->lpszName );
2117 cs->lpszClass = MapLS( cs32->lpszClass );
2119 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2121 MDICREATESTRUCT16 *mdi_cs16;
2122 MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs32->lpCreateParams;
2123 mdi_cs16 = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs16));
2124 if (!mdi_cs16)
2126 HeapFree(GetProcessHeap(), 0, cs);
2127 return -1;
2129 MDICREATESTRUCT32Ato16(mdi_cs, mdi_cs16);
2130 mdi_cs16->szTitle = MapLS( mdi_cs->szTitle );
2131 mdi_cs16->szClass = MapLS( mdi_cs->szClass );
2132 cs->lpCreateParams = MapLS( mdi_cs16 );
2134 *plparam = MapLS( cs );
2136 return 1;
2137 case WM_PARENTNOTIFY:
2138 if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
2139 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
2140 /* else nothing to do */
2141 return 0;
2142 case WM_NOTIFY:
2143 *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
2144 return 1;
2145 case WM_SETTEXT:
2146 case WM_WININICHANGE:
2147 case WM_DEVMODECHANGE:
2148 *plparam = MapLS( (LPSTR)*plparam );
2149 return 1;
2150 case WM_WINDOWPOSCHANGING:
2151 case WM_WINDOWPOSCHANGED:
2153 WINDOWPOS16 *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
2154 if (!wp) return -1;
2155 WINDOWPOS32to16( (WINDOWPOS *)*plparam, wp );
2156 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
2157 *plparam = MapLS( wp );
2159 return 1;
2160 case WM_GETDLGCODE:
2161 if (*plparam) {
2162 LPMSG msg32 = (LPMSG) *plparam;
2163 LPMSG16 msg16 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG16) );
2165 if (!msg16) return -1;
2166 msg16->hwnd = HWND_16( msg32->hwnd );
2167 msg16->message = msg32->message;
2168 msg16->wParam = msg32->wParam;
2169 msg16->lParam = msg32->lParam;
2170 msg16->time = msg32->time;
2171 msg16->pt.x = msg32->pt.x;
2172 msg16->pt.y = msg32->pt.y;
2173 *plparam = MapLS( msg16 );
2174 return 1;
2176 return 0;
2178 case WM_ACTIVATEAPP:
2179 if (*plparam) *plparam = HTASK_16( (HANDLE)*plparam );
2180 return 0;
2181 case WM_NEXTMENU:
2183 MDINEXTMENU *next = (MDINEXTMENU *)*plparam;
2184 *plparam = (LPARAM)next->hmenuIn;
2185 return 1;
2187 case WM_PAINT:
2188 if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON ))
2190 *pmsg16 = WM_PAINTICON;
2191 *pwparam16 = 1;
2193 return 0;
2194 case WM_ERASEBKGND:
2195 if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON ))
2196 *pmsg16 = WM_ICONERASEBKGND;
2197 return 0;
2198 case WM_PAINTCLIPBOARD:
2199 case WM_SIZECLIPBOARD:
2200 FIXME_(msg)("message %04x needs translation\n", msg32 );
2201 return -1;
2202 /* following messages should not be sent to 16-bit apps */
2203 case WM_SIZING:
2204 case WM_MOVING:
2205 case WM_CAPTURECHANGED:
2206 case WM_STYLECHANGING:
2207 case WM_STYLECHANGED:
2208 return -1;
2209 case WM_DDE_INITIATE:
2210 case WM_DDE_TERMINATE:
2211 case WM_DDE_UNADVISE:
2212 case WM_DDE_REQUEST:
2213 *pwparam16 = HWND_16((HWND)wParam32);
2214 return 0;
2215 case WM_DDE_ADVISE:
2216 case WM_DDE_DATA:
2217 case WM_DDE_POKE:
2219 UINT_PTR lo32, hi;
2220 HANDLE16 lo16 = 0;
2222 *pwparam16 = HWND_16((HWND)wParam32);
2223 UnpackDDElParam(msg32, *plparam, &lo32, &hi);
2224 if (lo32 && !(lo16 = convert_handle_32_to_16(lo32, GMEM_DDESHARE)))
2225 return -1;
2226 *plparam = MAKELPARAM(lo16, hi);
2228 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2229 case WM_DDE_ACK:
2231 UINT_PTR lo, hi;
2232 int flag = 0;
2233 char buf[2];
2235 *pwparam16 = HWND_16((HWND)wParam32);
2237 UnpackDDElParam(msg32, *plparam, &lo, &hi);
2239 if (GlobalGetAtomNameA((ATOM)hi, buf, sizeof(buf)) > 0) flag |= 1;
2240 if (GlobalSize((HANDLE)hi) != 0) flag |= 2;
2241 switch (flag)
2243 case 0:
2244 if (hi)
2246 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
2247 hi = 0;
2249 break;
2250 case 1:
2251 break; /* atom, nothing to do */
2252 case 3:
2253 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
2254 /* fall thru */
2255 case 2:
2256 hi = convert_handle_32_to_16(hi, GMEM_DDESHARE);
2257 break;
2259 *plparam = MAKELPARAM(lo, hi);
2261 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2262 case WM_DDE_EXECUTE:
2263 *plparam = convert_handle_32_to_16(*plparam, GMEM_DDESHARE);
2264 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2265 default: /* No translation needed */
2266 return 0;
2271 /**********************************************************************
2272 * WINPROC_UnmapMsg32ATo16
2274 * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
2276 static void WINPROC_UnmapMsg32ATo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2277 WPARAM16 wParam16, LPARAM lParam16, LRESULT *result )
2279 switch(msg)
2281 case SBM_GETRANGE:
2282 *(LPINT)wParam = LOWORD(*result);
2283 *(LPINT)lParam = HIWORD(*result);
2284 break;
2286 case LB_ADDFILE:
2287 case LB_ADDSTRING:
2288 case LB_DIR:
2289 case LB_FINDSTRING:
2290 case LB_FINDSTRINGEXACT:
2291 case LB_INSERTSTRING:
2292 case LB_SELECTSTRING:
2293 case LB_GETTEXT:
2294 case CB_ADDSTRING:
2295 case CB_FINDSTRING:
2296 case CB_FINDSTRINGEXACT:
2297 case CB_INSERTSTRING:
2298 case CB_SELECTSTRING:
2299 case CB_DIR:
2300 case CB_GETLBTEXT:
2301 case WM_SETTEXT:
2302 case WM_WININICHANGE:
2303 case WM_DEVMODECHANGE:
2304 UnMapLS( (SEGPTR)lParam16 );
2305 break;
2306 case LB_SETTABSTOPS:
2307 case WM_COMPAREITEM:
2308 case WM_DELETEITEM:
2309 case WM_DRAWITEM:
2311 void *ptr = MapSL( lParam16 );
2312 UnMapLS( lParam16 );
2313 HeapFree( GetProcessHeap(), 0, ptr );
2315 break;
2316 case WM_COPYDATA:
2318 PCOPYDATASTRUCT16 pcds = MapSL( lParam16 );
2319 UnMapLS( lParam16 );
2320 UnMapLS( pcds->lpData );
2321 HeapFree( GetProcessHeap(), 0, pcds );
2323 break;
2324 case CB_GETDROPPEDCONTROLRECT:
2325 case LB_GETITEMRECT:
2327 RECT *r32;
2328 RECT16 *rect = MapSL(lParam16);
2329 UnMapLS( lParam16 );
2330 lParam16 = *(LPARAM *)(rect + 1);
2331 r32 = (RECT *)lParam16;
2332 r32->left = rect->left;
2333 r32->top = rect->top;
2334 r32->right = rect->right;
2335 r32->bottom = rect->bottom;
2336 HeapFree( GetProcessHeap(), 0, rect );
2338 break;
2339 case LB_GETSELITEMS:
2341 INT i;
2342 LPINT16 items = MapSL(lParam16);
2343 UnMapLS( lParam16 );
2344 lParam16 = *((LPARAM *)items - 1);
2345 for (i = 0; i < wParam16; i++) *((LPINT)lParam16 + i) = items[i];
2346 HeapFree( GetProcessHeap(), 0, (LPARAM *)items - 1 );
2348 break;
2350 case CB_GETEDITSEL:
2351 if( wParam )
2352 *((PUINT)(wParam)) = LOWORD(*result);
2353 if( lParam )
2354 *((PUINT)(lParam)) = HIWORD(*result); /* FIXME: substract 1? */
2355 break;
2357 case WM_MEASUREITEM:
2359 MEASUREITEMSTRUCT16 *mis = MapSL(lParam16);
2360 MEASUREITEMSTRUCT *mis32 = *(MEASUREITEMSTRUCT **)(mis + 1);
2361 mis32->itemWidth = mis->itemWidth;
2362 mis32->itemHeight = mis->itemHeight;
2363 UnMapLS( lParam16 );
2364 HeapFree( GetProcessHeap(), 0, mis );
2366 break;
2367 case WM_GETMINMAXINFO:
2369 MINMAXINFO16 *mmi = MapSL(lParam16);
2370 UnMapLS( lParam16 );
2371 lParam16 = *(LPARAM *)(mmi + 1);
2372 MINMAXINFO16to32( mmi, (MINMAXINFO *)lParam16 );
2373 HeapFree( GetProcessHeap(), 0, mmi );
2375 break;
2376 case WM_GETTEXT:
2377 case WM_ASKCBFORMATNAME:
2379 LPSTR str = MapSL(lParam16);
2380 UnMapLS( lParam16 );
2381 lParam16 = *((LPARAM *)str - 1);
2382 lstrcpynA( (LPSTR)lParam16, str, wParam16 );
2383 HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2385 break;
2386 case WM_MDICREATE:
2388 MDICREATESTRUCT16 *cs = MapSL(lParam16);
2389 UnMapLS( cs->szTitle );
2390 UnMapLS( cs->szClass );
2391 UnMapLS( lParam16 );
2392 HeapFree( GetProcessHeap(), 0, cs );
2394 break;
2395 case WM_MDIGETACTIVE:
2396 if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(*result);
2397 *result = (LRESULT)WIN_Handle32( LOWORD(*result) );
2398 break;
2399 case WM_NCCALCSIZE:
2401 NCCALCSIZE_PARAMS *nc32;
2402 NCCALCSIZE_PARAMS16 *nc = MapSL(lParam16);
2403 UnMapLS( lParam16 );
2404 lParam16 = *(LPARAM *)(nc + 1);
2405 nc32 = (NCCALCSIZE_PARAMS *)lParam16;
2406 nc32->rgrc[0].left = nc->rgrc[0].left;
2407 nc32->rgrc[0].top = nc->rgrc[0].top;
2408 nc32->rgrc[0].right = nc->rgrc[0].right;
2409 nc32->rgrc[0].bottom = nc->rgrc[0].bottom;
2410 if (wParam16)
2412 WINDOWPOS16 *pos = MapSL(nc->lppos);
2413 UnMapLS( nc->lppos );
2414 nc32->rgrc[1].left = nc->rgrc[1].left;
2415 nc32->rgrc[1].top = nc->rgrc[1].top;
2416 nc32->rgrc[1].right = nc->rgrc[1].right;
2417 nc32->rgrc[1].bottom = nc->rgrc[1].bottom;
2418 nc32->rgrc[2].left = nc->rgrc[2].left;
2419 nc32->rgrc[2].top = nc->rgrc[2].top;
2420 nc32->rgrc[2].right = nc->rgrc[2].right;
2421 nc32->rgrc[2].bottom = nc->rgrc[2].bottom;
2422 WINDOWPOS16to32( pos, nc32->lppos );
2423 HeapFree( GetProcessHeap(), 0, pos );
2425 HeapFree( GetProcessHeap(), 0, nc );
2427 break;
2428 case WM_NCCREATE:
2429 case WM_CREATE:
2431 CREATESTRUCT16 *cs = MapSL(lParam16);
2432 UnMapLS( lParam16 );
2433 UnMapLS( cs->lpszName );
2434 UnMapLS( cs->lpszClass );
2435 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2437 MDICREATESTRUCT16 *mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs->lpCreateParams);
2438 UnMapLS( cs->lpCreateParams );
2439 UnMapLS( mdi_cs16->szTitle );
2440 UnMapLS( mdi_cs16->szClass );
2441 HeapFree(GetProcessHeap(), 0, mdi_cs16);
2443 HeapFree( GetProcessHeap(), 0, cs );
2445 break;
2446 case WM_WINDOWPOSCHANGING:
2447 case WM_WINDOWPOSCHANGED:
2449 WINDOWPOS16 *wp = MapSL(lParam16);
2450 UnMapLS( lParam16 );
2451 lParam16 = *(LPARAM *)(wp + 1);
2452 WINDOWPOS16to32( wp, (WINDOWPOS *)lParam16 );
2453 HeapFree( GetProcessHeap(), 0, wp );
2455 break;
2456 case WM_NOTIFY:
2457 UnMapLS(lParam16);
2458 break;
2459 case WM_GETDLGCODE:
2460 if (lParam16)
2462 LPMSG16 msg16 = MapSL(lParam16);
2463 UnMapLS( lParam16 );
2464 HeapFree( GetProcessHeap(), 0, msg16 );
2466 break;
2467 case WM_NEXTMENU:
2469 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
2470 next->hmenuNext = HMENU_32( LOWORD(*result) );
2471 next->hwndNext = WIN_Handle32( HIWORD(*result) );
2472 *result = 0;
2474 break;
2479 /**********************************************************************
2480 * WINPROC_MapMsg32WTo16
2482 * Map a message from 32-bit Unicode to 16-bit.
2483 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
2485 static INT WINPROC_MapMsg32WTo16( HWND hwnd, UINT msg32, WPARAM wParam32,
2486 UINT16 *pmsg16, WPARAM16 *pwparam16, LPARAM *plparam )
2488 *pmsg16 = LOWORD(msg32);
2489 *pwparam16 = LOWORD(wParam32);
2490 switch(msg32)
2492 case LB_ADDSTRING:
2493 case LB_FINDSTRING:
2494 case LB_FINDSTRINGEXACT:
2495 case LB_INSERTSTRING:
2496 case LB_SELECTSTRING:
2497 case LB_DIR:
2498 case LB_ADDFILE:
2499 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2500 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2501 return 1;
2503 case CB_ADDSTRING:
2504 case CB_FINDSTRING:
2505 case CB_FINDSTRINGEXACT:
2506 case CB_INSERTSTRING:
2507 case CB_SELECTSTRING:
2508 case CB_DIR:
2509 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2510 *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING);
2511 return 1;
2513 case WM_NCCREATE:
2514 case WM_CREATE:
2516 CREATESTRUCT16 *cs;
2517 CREATESTRUCTW *cs32 = (CREATESTRUCTW *)*plparam;
2519 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2520 CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs32, cs );
2521 cs->lpszName = map_str_32W_to_16( cs32->lpszName );
2522 cs->lpszClass = map_str_32W_to_16( cs32->lpszClass );
2524 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2526 MDICREATESTRUCT16 *mdi_cs16;
2527 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)cs32->lpCreateParams;
2528 mdi_cs16 = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs16));
2529 if (!mdi_cs16)
2531 HeapFree(GetProcessHeap(), 0, cs);
2532 return -1;
2534 MDICREATESTRUCT32Ato16((MDICREATESTRUCTA *)mdi_cs, mdi_cs16);
2535 mdi_cs16->szTitle = map_str_32W_to_16(mdi_cs->szTitle);
2536 mdi_cs16->szClass = map_str_32W_to_16(mdi_cs->szClass);
2537 cs->lpCreateParams = MapLS(mdi_cs16);
2539 *plparam = MapLS(cs);
2541 return 1;
2542 case WM_MDICREATE:
2544 MDICREATESTRUCT16 *cs;
2545 MDICREATESTRUCTW *cs32 = (MDICREATESTRUCTW *)*plparam;
2547 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2548 MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs32, cs );
2549 cs->szTitle = map_str_32W_to_16( cs32->szTitle );
2550 cs->szClass = map_str_32W_to_16( cs32->szClass );
2551 *plparam = MapLS(cs);
2553 return 1;
2554 case WM_SETTEXT:
2555 case WM_WININICHANGE:
2556 case WM_DEVMODECHANGE:
2557 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2558 return 1;
2559 case LB_GETTEXT:
2560 case CB_GETLBTEXT:
2561 if ( WINPROC_TestLBForStr( hwnd, msg32 ))
2563 LPSTR str = HeapAlloc( GetProcessHeap(), 0, 512 ); /* FIXME: fixed sized buffer */
2564 if (!str) return -1;
2565 *pmsg16 = (msg32 == LB_GETTEXT) ? LB_GETTEXT16 : CB_GETLBTEXT16;
2566 *plparam = (LPARAM)MapLS(str);
2568 return 1;
2570 case WM_CHARTOITEM:
2571 *pwparam16 = map_wparam_char_WtoA( wParam32, 1 );
2572 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2573 return 0;
2574 case WM_MENUCHAR:
2575 *pwparam16 = map_wparam_char_WtoA( wParam32, 1 );
2576 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2577 return 0;
2578 case WM_CHAR:
2579 case WM_DEADCHAR:
2580 case WM_SYSCHAR:
2581 case WM_SYSDEADCHAR:
2582 *pwparam16 = map_wparam_char_WtoA( wParam32, 1 );
2583 return 0;
2584 case WM_IME_CHAR:
2585 *pwparam16 = map_wparam_char_WtoA( wParam32, 2 );
2586 return 0;
2588 default: /* No Unicode translation needed (?) */
2589 return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2590 pwparam16, plparam );
2595 /**********************************************************************
2596 * WINPROC_UnmapMsg32WTo16
2598 * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2600 static void WINPROC_UnmapMsg32WTo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2601 WPARAM16 wParam16, LPARAM lParam16, LRESULT *result )
2603 switch(msg)
2605 case LB_ADDSTRING:
2606 case LB_FINDSTRING:
2607 case LB_FINDSTRINGEXACT:
2608 case LB_INSERTSTRING:
2609 case LB_SELECTSTRING:
2610 case LB_DIR:
2611 case LB_ADDFILE:
2612 case CB_ADDSTRING:
2613 case CB_FINDSTRING:
2614 case CB_FINDSTRINGEXACT:
2615 case CB_INSERTSTRING:
2616 case CB_SELECTSTRING:
2617 case CB_DIR:
2618 case WM_SETTEXT:
2619 case WM_WININICHANGE:
2620 case WM_DEVMODECHANGE:
2621 unmap_str_32W_to_16( lParam16 );
2622 break;
2623 case WM_NCCREATE:
2624 case WM_CREATE:
2626 CREATESTRUCT16 *cs = MapSL(lParam16);
2627 UnMapLS( lParam16 );
2628 unmap_str_32W_to_16( cs->lpszName );
2629 unmap_str_32W_to_16( cs->lpszClass );
2631 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2633 MDICREATESTRUCT16 *mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs->lpCreateParams);
2634 UnMapLS( cs->lpCreateParams );
2635 unmap_str_32W_to_16(mdi_cs16->szTitle);
2636 unmap_str_32W_to_16(mdi_cs16->szClass);
2637 HeapFree(GetProcessHeap(), 0, mdi_cs16);
2639 HeapFree( GetProcessHeap(), 0, cs );
2641 break;
2642 case WM_MDICREATE:
2644 MDICREATESTRUCT16 *cs = MapSL(lParam16);
2645 UnMapLS( lParam16 );
2646 unmap_str_32W_to_16( cs->szTitle );
2647 unmap_str_32W_to_16( cs->szClass );
2648 HeapFree( GetProcessHeap(), 0, cs );
2650 break;
2651 case WM_GETTEXT:
2652 case WM_ASKCBFORMATNAME:
2654 LPSTR str = MapSL(lParam16);
2655 UnMapLS( lParam16 );
2656 lParam16 = *((LPARAM *)str - 1);
2657 MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam16, 0x7fffffff );
2658 *result = strlenW( (LPWSTR)lParam16 );
2659 HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2661 break;
2662 case LB_GETTEXT:
2663 case CB_GETLBTEXT:
2664 if ( WINPROC_TestLBForStr( hwnd, msg ))
2666 LPSTR str = MapSL(lParam16);
2667 UnMapLS( lParam16 );
2668 *result = MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff ) - 1;
2669 HeapFree( GetProcessHeap(), 0, (LPARAM *)str );
2671 break;
2672 default:
2673 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, wParam16, lParam16, result );
2674 break;
2679 /**********************************************************************
2680 * WINPROC_CallProcAtoW
2682 * Call a window procedure, translating args from Ansi to Unicode.
2684 LRESULT WINPROC_CallProcAtoW( winproc_callback_t callback, HWND hwnd, UINT msg, WPARAM wParam,
2685 LPARAM lParam, LRESULT *result, void *arg )
2687 LRESULT ret;
2688 int unmap;
2690 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2691 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2693 if( (unmap = WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam )) == -1) {
2694 ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2695 SPY_GetMsgName(msg, hwnd), wParam, lParam );
2696 return 0;
2698 ret = callback( hwnd, msg, wParam, lParam, result, arg );
2699 if (unmap)
2700 *result = WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, *result,
2701 (callback == call_window_proc) ? arg : NULL /*FIXME: hack*/ );
2702 return ret;
2706 static inline void *get_buffer( void *static_buffer, size_t size, size_t need )
2708 if (size >= need) return static_buffer;
2709 return HeapAlloc( GetProcessHeap(), 0, need );
2712 static inline void free_buffer( void *static_buffer, void *buffer )
2714 if (buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer );
2717 /**********************************************************************
2718 * WINPROC_CallProcWtoA
2720 * Call a window procedure, translating args from Unicode to Ansi.
2722 static LRESULT WINPROC_CallProcWtoA( winproc_callback_t callback, HWND hwnd, UINT msg, WPARAM wParam,
2723 LPARAM lParam, LRESULT *result, void *arg )
2725 LRESULT ret = 0;
2727 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2728 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2730 switch(msg)
2732 case WM_NCCREATE:
2733 case WM_CREATE:
2734 { /* csW->lpszName and csW->lpszClass are NOT supposed to be atoms
2735 * at this point.
2737 char buffer[1024], *cls, *name;
2738 CREATESTRUCTW *csW = (CREATESTRUCTW *)lParam;
2739 CREATESTRUCTA csA = *(CREATESTRUCTA *)csW;
2740 MDICREATESTRUCTA mdi_cs;
2741 DWORD name_lenA, name_lenW, class_lenA, class_lenW;
2743 class_lenW = strlenW(csW->lpszClass) * sizeof(WCHAR);
2744 RtlUnicodeToMultiByteSize(&class_lenA, csW->lpszClass, class_lenW);
2746 if (csW->lpszName)
2748 name_lenW = strlenW(csW->lpszName) * sizeof(WCHAR);
2749 RtlUnicodeToMultiByteSize(&name_lenA, csW->lpszName, name_lenW);
2751 else
2752 name_lenW = name_lenA = 0;
2754 if (!(cls = get_buffer( buffer, sizeof(buffer), class_lenA + name_lenA + 2 ))) break;
2756 RtlUnicodeToMultiByteN(cls, class_lenA, NULL, csW->lpszClass, class_lenW);
2757 cls[class_lenA] = 0;
2758 csA.lpszClass = cls;
2760 if (csW->lpszName)
2762 name = cls + class_lenA + 1;
2763 RtlUnicodeToMultiByteN(name, name_lenA, NULL, csW->lpszName, name_lenW);
2764 name[name_lenA] = 0;
2765 csA.lpszName = name;
2768 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2770 mdi_cs = *(MDICREATESTRUCTA *)csW->lpCreateParams;
2771 mdi_cs.szTitle = csA.lpszName;
2772 mdi_cs.szClass = csA.lpszClass;
2773 csA.lpCreateParams = &mdi_cs;
2776 ret = callback( hwnd, msg, wParam, (LPARAM)&csA, result, arg );
2777 free_buffer( buffer, cls );
2779 break;
2781 case WM_GETTEXT:
2782 case WM_ASKCBFORMATNAME:
2784 char *ptr, buffer[512];
2785 DWORD len = wParam * 2;
2787 if (!(ptr = get_buffer( buffer, sizeof(buffer), len ))) break;
2788 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2789 if (*result && len)
2791 RtlMultiByteToUnicodeN( (LPWSTR)lParam, wParam*sizeof(WCHAR), &len, ptr, strlen(ptr)+1 );
2792 *result = len/sizeof(WCHAR) - 1; /* do not count terminating null */
2793 ((LPWSTR)lParam)[*result] = 0;
2795 free_buffer( buffer, ptr );
2797 break;
2799 case LB_ADDSTRING:
2800 case LB_INSERTSTRING:
2801 case LB_FINDSTRING:
2802 case LB_FINDSTRINGEXACT:
2803 case LB_SELECTSTRING:
2804 case CB_ADDSTRING:
2805 case CB_INSERTSTRING:
2806 case CB_FINDSTRING:
2807 case CB_FINDSTRINGEXACT:
2808 case CB_SELECTSTRING:
2809 if (!lParam || !WINPROC_TestLBForStr( hwnd, msg ))
2811 ret = callback( hwnd, msg, wParam, lParam, result, arg );
2812 break;
2814 /* fall through */
2815 case WM_SETTEXT:
2816 case WM_WININICHANGE:
2817 case WM_DEVMODECHANGE:
2818 case CB_DIR:
2819 case LB_DIR:
2820 case LB_ADDFILE:
2821 case EM_REPLACESEL:
2822 if (!lParam) ret = callback( hwnd, msg, wParam, lParam, result, arg );
2823 else
2825 char *ptr, buffer[512];
2826 LPCWSTR strW = (LPCWSTR)lParam;
2827 DWORD lenA, lenW = (strlenW(strW) + 1) * sizeof(WCHAR);
2829 RtlUnicodeToMultiByteSize( &lenA, strW, lenW );
2830 if ((ptr = get_buffer( buffer, sizeof(buffer), lenA )))
2832 RtlUnicodeToMultiByteN( ptr, lenA, NULL, strW, lenW );
2833 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2834 free_buffer( buffer, ptr );
2837 break;
2839 case WM_MDICREATE:
2841 char *ptr, buffer[1024];
2842 DWORD title_lenA = 0, title_lenW = 0, class_lenA = 0, class_lenW = 0;
2843 MDICREATESTRUCTW *csW = (MDICREATESTRUCTW *)lParam;
2844 MDICREATESTRUCTA csA;
2846 memcpy( &csA, csW, sizeof(csA) );
2848 if (HIWORD(csW->szTitle))
2850 title_lenW = (strlenW(csW->szTitle) + 1) * sizeof(WCHAR);
2851 RtlUnicodeToMultiByteSize( &title_lenA, csW->szTitle, title_lenW );
2853 if (HIWORD(csW->szClass))
2855 class_lenW = (strlenW(csW->szClass) + 1) * sizeof(WCHAR);
2856 RtlUnicodeToMultiByteSize( &class_lenA, csW->szClass, class_lenW );
2859 if (!(ptr = get_buffer( buffer, sizeof(buffer), title_lenA + class_lenA ))) break;
2861 if (title_lenA)
2863 RtlUnicodeToMultiByteN( ptr, title_lenA, NULL, csW->szTitle, title_lenW );
2864 csA.szTitle = ptr;
2866 if (class_lenA)
2868 RtlUnicodeToMultiByteN( ptr + title_lenA, class_lenA, NULL, csW->szClass, class_lenW );
2869 csA.szClass = ptr + title_lenA;
2871 ret = callback( hwnd, msg, wParam, (LPARAM)&csA, result, arg );
2872 free_buffer( buffer, ptr );
2874 break;
2876 case LB_GETTEXT:
2877 case CB_GETLBTEXT:
2878 if (lParam && WINPROC_TestLBForStr( hwnd, msg ))
2880 char buffer[512]; /* FIXME: fixed sized buffer */
2882 ret = callback( hwnd, msg, wParam, (LPARAM)buffer, result, arg );
2883 if (*result >= 0)
2885 DWORD len;
2886 RtlMultiByteToUnicodeN( (LPWSTR)lParam, ~0u, &len, buffer, strlen(buffer) + 1 );
2887 *result = len / sizeof(WCHAR) - 1;
2890 else ret = callback( hwnd, msg, wParam, lParam, result, arg );
2891 break;
2893 case EM_GETLINE:
2895 char *ptr, buffer[512];
2896 WORD len = *(WORD *)lParam;
2898 if (!(ptr = get_buffer( buffer, sizeof(buffer), len * 2 ))) break;
2899 *((WORD *)ptr) = len * 2; /* store the length */
2900 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2901 if (*result)
2903 DWORD reslen;
2904 RtlMultiByteToUnicodeN( (LPWSTR)lParam, len*sizeof(WCHAR), &reslen, buffer, *result );
2905 *result = reslen / sizeof(WCHAR);
2906 if (*result < len) ((LPWSTR)lParam)[*result] = 0;
2908 free_buffer( buffer, ptr );
2910 break;
2912 case WM_CHARTOITEM:
2913 case WM_MENUCHAR:
2914 case WM_CHAR:
2915 case WM_DEADCHAR:
2916 case WM_SYSCHAR:
2917 case WM_SYSDEADCHAR:
2918 case EM_SETPASSWORDCHAR:
2919 ret = callback( hwnd, msg, map_wparam_char_WtoA(wParam,1), lParam, result, arg );
2920 break;
2922 case WM_IME_CHAR:
2923 ret = callback( hwnd, msg, map_wparam_char_WtoA(wParam,2), lParam, result, arg );
2924 break;
2926 case WM_PAINTCLIPBOARD:
2927 case WM_SIZECLIPBOARD:
2928 FIXME_(msg)( "message %s (%04x) needs translation, please report\n",
2929 SPY_GetMsgName(msg, hwnd), msg );
2930 break;
2932 default:
2933 ret = callback( hwnd, msg, wParam, lParam, result, arg );
2934 break;
2937 return ret;
2941 /**********************************************************************
2942 * WINPROC_CallProc16To32A
2944 LRESULT WINPROC_CallProc16To32A( winproc_callback_t callback, HWND16 hwnd, UINT16 msg,
2945 WPARAM16 wParam, LPARAM lParam, LRESULT *result, void *arg )
2947 LRESULT ret;
2948 UINT msg32;
2949 WPARAM wParam32;
2950 HWND hwnd32 = WIN_Handle32( hwnd );
2952 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2953 hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
2955 if (WINPROC_MapMsg16To32A( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2956 return 0;
2958 ret = callback( hwnd32, msg32, wParam32, lParam, result, arg );
2959 *result = WINPROC_UnmapMsg16To32A( hwnd32, msg32, wParam32, lParam, *result );
2960 return ret;
2964 /**********************************************************************
2965 * WINPROC_CallProc16To32W
2967 static LRESULT WINPROC_CallProc16To32W( winproc_callback_t callback, HWND16 hwnd, UINT16 msg,
2968 WPARAM16 wParam, LPARAM lParam, LRESULT *result, void *arg )
2970 LRESULT ret;
2971 UINT msg32;
2972 WPARAM wParam32;
2973 HWND hwnd32 = WIN_Handle32( hwnd );
2975 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2976 hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
2978 if (WINPROC_MapMsg16To32W( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2979 return 0;
2981 ret = callback( hwnd32, msg32, wParam32, lParam, result, arg );
2982 *result = WINPROC_UnmapMsg16To32W( hwnd32, msg32, wParam32, lParam, *result,
2983 (callback == call_window_proc) ? arg : NULL /*FIXME: hack*/ );
2984 return ret;
2988 /**********************************************************************
2989 * __wine_call_wndproc (USER.1010)
2991 LRESULT WINAPI __wine_call_wndproc( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2992 WINDOWPROC *proc )
2994 LRESULT result;
2996 if (proc->procA)
2997 WINPROC_CallProc16To32A( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
2998 else
2999 WINPROC_CallProc16To32W( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3000 return result;
3004 /**********************************************************************
3005 * WINPROC_CallProc32ATo16
3007 * Call a 16-bit window procedure, translating the 32-bit args.
3009 LRESULT WINPROC_CallProc32ATo16( winproc_callback16_t callback, HWND hwnd, UINT msg,
3010 WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg )
3012 LRESULT ret;
3013 UINT16 msg16;
3014 WPARAM16 wParam16;
3015 LPARAM lParam16;
3017 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
3018 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
3020 lParam16 = lParam;
3021 if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, &msg16, &wParam16, &lParam16 ) == -1)
3022 return 0;
3023 ret = callback( HWND_16(hwnd), msg16, wParam16, lParam16, result, arg );
3024 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, wParam16, lParam16, result );
3025 return ret;
3029 /**********************************************************************
3030 * WINPROC_CallProc32WTo16
3032 * Call a 16-bit window procedure, translating the 32-bit args.
3034 static LRESULT WINPROC_CallProc32WTo16( winproc_callback16_t callback, HWND hwnd, UINT msg,
3035 WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg )
3037 LRESULT ret;
3038 UINT16 msg16;
3039 WPARAM16 wParam16;
3040 LPARAM lParam16;
3042 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
3043 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
3045 lParam16 = lParam;
3046 if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &wParam16, &lParam16 ) == -1)
3047 return 0;
3048 ret = callback( HWND_16(hwnd), msg16, wParam16, lParam16, result, arg );
3049 WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, wParam16, lParam16, result );
3050 return ret;
3054 /**********************************************************************
3055 * CallWindowProc (USER.122)
3057 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
3058 WPARAM16 wParam, LPARAM lParam )
3060 WINDOWPROC *proc;
3061 LRESULT result;
3063 if (!func) return 0;
3065 if (!(proc = handle16_to_proc( func )))
3066 call_window_proc16( hwnd, msg, wParam, lParam, &result, func );
3067 else if (proc->procA)
3068 WINPROC_CallProc16To32A( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
3069 else if (proc->procW)
3070 WINPROC_CallProc16To32W( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3071 else
3072 call_window_proc16( hwnd, msg, wParam, lParam, &result, proc->proc16 );
3074 return result;
3078 /**********************************************************************
3079 * CallWindowProcA (USER32.@)
3081 * The CallWindowProc() function invokes the windows procedure _func_,
3082 * with _hwnd_ as the target window, the message specified by _msg_, and
3083 * the message parameters _wParam_ and _lParam_.
3085 * Some kinds of argument conversion may be done, I'm not sure what.
3087 * CallWindowProc() may be used for windows subclassing. Use
3088 * SetWindowLong() to set a new windows procedure for windows of the
3089 * subclass, and handle subclassed messages in the new windows
3090 * procedure. The new windows procedure may then use CallWindowProc()
3091 * with _func_ set to the parent class's windows procedure to dispatch
3092 * the message to the superclass.
3094 * RETURNS
3096 * The return value is message dependent.
3098 * CONFORMANCE
3100 * ECMA-234, Win32
3102 LRESULT WINAPI CallWindowProcA(
3103 WNDPROC func, /* [in] window procedure */
3104 HWND hwnd, /* [in] target window */
3105 UINT msg, /* [in] message */
3106 WPARAM wParam, /* [in] message dependent parameter */
3107 LPARAM lParam /* [in] message dependent parameter */
3109 WINDOWPROC *proc;
3110 LRESULT result;
3112 if (!func) return 0;
3114 if (!(proc = handle_to_proc( func )))
3115 call_window_proc( hwnd, msg, wParam, lParam, &result, func );
3116 else if (proc->procA)
3117 call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
3118 else if (proc->procW)
3119 WINPROC_CallProcAtoW( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3120 else
3121 WINPROC_CallProc32ATo16( call_window_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3122 return result;
3126 /**********************************************************************
3127 * CallWindowProcW (USER32.@)
3129 * See CallWindowProcA.
3131 LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
3132 WPARAM wParam, LPARAM lParam )
3134 WINDOWPROC *proc;
3135 LRESULT result;
3137 if (!func) return 0;
3139 if (!(proc = handle_to_proc( func )))
3140 call_window_proc( hwnd, msg, wParam, lParam, &result, func );
3141 else if (proc->procW)
3142 call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
3143 else if (proc->procA)
3144 WINPROC_CallProcWtoA( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
3145 else
3146 WINPROC_CallProc32WTo16( call_window_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3147 return result;
3151 /**********************************************************************
3152 * WINPROC_CallDlgProc16
3154 INT_PTR WINPROC_CallDlgProc16( DLGPROC16 func, HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
3156 WINDOWPROC *proc;
3157 LRESULT result;
3158 INT_PTR ret;
3160 if (!func) return 0;
3162 if (!(proc = handle16_to_proc( (WNDPROC16)func )))
3164 ret = call_dialog_proc16( hwnd, msg, wParam, lParam, &result, func );
3166 else if (proc->procA)
3168 ret = WINPROC_CallProc16To32A( call_dialog_proc, hwnd, msg, wParam, lParam,
3169 &result, proc->procA );
3170 SetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT, result );
3172 else if (proc->procW)
3174 ret = WINPROC_CallProc16To32W( call_dialog_proc, hwnd, msg, wParam, lParam,
3175 &result, proc->procW );
3176 SetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT, result );
3178 else
3180 ret = call_dialog_proc16( hwnd, msg, wParam, lParam, &result, proc->proc16 );
3182 return ret;
3186 /**********************************************************************
3187 * WINPROC_CallDlgProcA
3189 INT_PTR WINPROC_CallDlgProcA( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
3191 WINDOWPROC *proc;
3192 LRESULT result;
3193 INT_PTR ret;
3195 if (!func) return 0;
3197 if (!(proc = handle_to_proc( (WNDPROC)func )))
3198 ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, func );
3199 else if (proc->procA)
3200 ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
3201 else if (proc->procW)
3203 ret = WINPROC_CallProcAtoW( call_dialog_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3204 SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3206 else
3208 ret = WINPROC_CallProc32ATo16( call_dialog_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3209 SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3211 return ret;
3215 /**********************************************************************
3216 * WINPROC_CallDlgProcW
3218 INT_PTR WINPROC_CallDlgProcW( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
3220 WINDOWPROC *proc;
3221 LRESULT result;
3222 INT_PTR ret;
3224 if (!func) return 0;
3226 if (!(proc = handle_to_proc( (WNDPROC)func )))
3227 ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, func );
3228 else if (proc->procW)
3229 ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
3230 else if (proc->procA)
3232 ret = WINPROC_CallProcWtoA( call_dialog_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
3233 SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3235 else
3237 ret = WINPROC_CallProc32WTo16( call_dialog_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3238 SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3240 return ret;