user: Added fast A->W mapping for WM_CREATE and WM_NCCREATE.
[wine/multimedia.git] / dlls / user / winproc.c
blob5a5532c329b425d38369de6dcb319180aea5424e
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 static inline void *get_buffer( void *static_buffer, size_t size, size_t need )
72 if (size >= need) return static_buffer;
73 return HeapAlloc( GetProcessHeap(), 0, need );
76 static inline void free_buffer( void *static_buffer, void *buffer )
78 if (buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer );
81 /* map a Unicode string to a 16-bit pointer */
82 inline static SEGPTR map_str_32W_to_16( LPCWSTR str )
84 LPSTR ret;
85 INT len;
87 if (!HIWORD(str)) return (SEGPTR)LOWORD(str);
88 len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
89 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
90 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
91 return MapLS(ret);
94 /* unmap a Unicode string that was converted to a 16-bit pointer */
95 inline static void unmap_str_32W_to_16( SEGPTR str )
97 if (!HIWORD(str)) return;
98 HeapFree( GetProcessHeap(), 0, MapSL(str) );
99 UnMapLS( str );
102 /* map a 16-bit pointer to a Unicode string */
103 inline static LPWSTR map_str_16_to_32W( SEGPTR str )
105 LPWSTR ret;
106 INT len;
108 if (!HIWORD(str)) return (LPWSTR)(ULONG_PTR)LOWORD(str);
109 len = MultiByteToWideChar( CP_ACP, 0, MapSL(str), -1, NULL, 0 );
110 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
111 MultiByteToWideChar( CP_ACP, 0, MapSL(str), -1, ret, len );
112 return ret;
115 /* unmap a 16-bit pointer that was converted to a Unicode string */
116 inline static void unmap_str_16_to_32W( LPCWSTR str )
118 if (HIWORD(str)) HeapFree( GetProcessHeap(), 0, (void *)str );
121 /* find an existing winproc for a given 16-bit function and type */
122 /* FIXME: probably should do something more clever than a linear search */
123 static inline WINDOWPROC *find_winproc16( WNDPROC16 func )
125 unsigned int i;
127 for (i = 0; i < winproc_used; i++)
129 if (winproc_array[i].proc16 == func) return &winproc_array[i];
131 return NULL;
134 /* find an existing winproc for a given function and type */
135 /* FIXME: probably should do something more clever than a linear search */
136 static inline WINDOWPROC *find_winproc( WNDPROC funcA, WNDPROC funcW )
138 unsigned int i;
140 for (i = 0; i < winproc_used; i++)
142 if (funcA && winproc_array[i].procA != funcA) continue;
143 if (funcW && winproc_array[i].procW != funcW) continue;
144 return &winproc_array[i];
146 return NULL;
149 /* return the window proc for a given handle, or NULL for an invalid handle */
150 static inline WINDOWPROC *handle_to_proc( WNDPROC handle )
152 UINT index = LOWORD(handle);
153 if ((ULONG_PTR)handle >> 16 != WINPROC_HANDLE) return NULL;
154 if (index >= winproc_used) return NULL;
155 return &winproc_array[index];
158 /* create a handle for a given window proc */
159 static inline WNDPROC proc_to_handle( WINDOWPROC *proc )
161 return (WNDPROC)(ULONG_PTR)((proc - winproc_array) | (WINPROC_HANDLE << 16));
164 /* allocate and initialize a new winproc */
165 static inline WINDOWPROC *alloc_winproc( WNDPROC funcA, WNDPROC funcW )
167 WINDOWPROC *proc;
169 /* check if the function is already a win proc */
170 if (funcA && (proc = handle_to_proc( funcA ))) return proc;
171 if (funcW && (proc = handle_to_proc( funcW ))) return proc;
172 if (!funcA && !funcW) return NULL;
174 EnterCriticalSection( &winproc_cs );
176 /* check if we already have a winproc for that function */
177 if (!(proc = find_winproc( funcA, funcW )))
179 if (winproc_used < MAX_WINPROCS)
181 proc = &winproc_array[winproc_used++];
182 proc->procA = funcA;
183 proc->procW = funcW;
184 TRACE( "allocated %p for %p/%p (%d/%d used)\n",
185 proc_to_handle(proc), funcA, funcW, winproc_used, MAX_WINPROCS );
187 else FIXME( "too many winprocs, cannot allocate one for %p/%p\n", funcA, funcW );
189 else TRACE( "reusing %p for %p/%p\n", proc_to_handle(proc), funcA, funcW );
191 LeaveCriticalSection( &winproc_cs );
192 return proc;
196 #ifdef __i386__
198 #include "pshpack1.h"
200 /* Window procedure 16-to-32-bit thunk */
201 typedef struct
203 BYTE popl_eax; /* popl %eax (return address) */
204 BYTE pushl_func; /* pushl $proc */
205 WINDOWPROC *proc;
206 BYTE pushl_eax; /* pushl %eax */
207 BYTE ljmp; /* ljmp relay*/
208 DWORD relay_offset; /* __wine_call_wndproc */
209 WORD relay_sel;
210 } WINPROC_THUNK;
212 #include "poppack.h"
214 #define MAX_THUNKS (0x10000 / sizeof(WINPROC_THUNK))
216 static WINPROC_THUNK *thunk_array;
217 static UINT thunk_selector;
218 static UINT thunk_used;
220 /* return the window proc for a given handle, or NULL for an invalid handle */
221 static inline WINDOWPROC *handle16_to_proc( WNDPROC16 handle )
223 if (HIWORD(handle) == thunk_selector)
225 UINT index = LOWORD(handle) / sizeof(WINPROC_THUNK);
226 /* check alignment */
227 if (index * sizeof(WINPROC_THUNK) != LOWORD(handle)) return NULL;
228 /* check array limits */
229 if (index >= thunk_used) return NULL;
230 return thunk_array[index].proc;
232 return handle_to_proc( (WNDPROC)handle );
235 /* allocate a 16-bit thunk for an existing window proc */
236 static WNDPROC16 alloc_win16_thunk( WINDOWPROC *proc )
238 static FARPROC16 relay;
239 UINT i;
241 if (proc->proc16) return proc->proc16;
243 EnterCriticalSection( &winproc_cs );
245 if (!thunk_array) /* allocate the array and its selector */
247 LDT_ENTRY entry;
249 if (!(thunk_selector = wine_ldt_alloc_entries(1))) goto done;
250 if (!(thunk_array = VirtualAlloc( NULL, MAX_THUNKS * sizeof(WINPROC_THUNK), MEM_COMMIT,
251 PAGE_EXECUTE_READWRITE ))) goto done;
252 wine_ldt_set_base( &entry, thunk_array );
253 wine_ldt_set_limit( &entry, MAX_THUNKS * sizeof(WINPROC_THUNK) - 1 );
254 wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
255 wine_ldt_set_entry( thunk_selector, &entry );
256 relay = GetProcAddress16( GetModuleHandle16("user"), "__wine_call_wndproc" );
259 /* check if it already exists */
260 for (i = 0; i < thunk_used; i++) if (thunk_array[i].proc == proc) break;
262 if (i == thunk_used) /* create a new one */
264 WINPROC_THUNK *thunk;
266 if (thunk_used >= MAX_THUNKS) goto done;
267 thunk = &thunk_array[thunk_used++];
268 thunk->popl_eax = 0x58; /* popl %eax */
269 thunk->pushl_func = 0x68; /* pushl $proc */
270 thunk->proc = proc;
271 thunk->pushl_eax = 0x50; /* pushl %eax */
272 thunk->ljmp = 0xea; /* ljmp relay*/
273 thunk->relay_offset = OFFSETOF(relay);
274 thunk->relay_sel = SELECTOROF(relay);
276 proc->proc16 = (WNDPROC16)MAKESEGPTR( thunk_selector, i * sizeof(WINPROC_THUNK) );
277 done:
278 LeaveCriticalSection( &winproc_cs );
279 return proc->proc16;
282 #else /* __i386__ */
284 static inline WINDOWPROC *handle16_to_proc( WNDPROC16 handle )
286 return handle_to_proc( (WNDPROC)handle );
289 static inline WNDPROC16 alloc_win16_thunk( WINDOWPROC *proc )
291 return 0;
294 #endif /* __i386__ */
297 #ifdef __i386__
298 /* Some window procedures modify register they shouldn't, or are not
299 * properly declared stdcall; so we need a small assembly wrapper to
300 * call them. */
301 extern LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
302 WPARAM wParam, LPARAM lParam );
303 __ASM_GLOBAL_FUNC( WINPROC_wrapper,
304 "pushl %ebp\n\t"
305 "movl %esp,%ebp\n\t"
306 "pushl %edi\n\t"
307 "pushl %esi\n\t"
308 "pushl %ebx\n\t"
309 "subl $12,%esp\n\t"
310 "pushl 24(%ebp)\n\t"
311 "pushl 20(%ebp)\n\t"
312 "pushl 16(%ebp)\n\t"
313 "pushl 12(%ebp)\n\t"
314 "movl 8(%ebp),%eax\n\t"
315 "call *%eax\n\t"
316 "leal -12(%ebp),%esp\n\t"
317 "popl %ebx\n\t"
318 "popl %esi\n\t"
319 "popl %edi\n\t"
320 "leave\n\t"
321 "ret" );
322 #else
323 static inline LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
324 WPARAM wParam, LPARAM lParam )
326 return proc( hwnd, msg, wParam, lParam );
328 #endif /* __i386__ */
331 static void MINMAXINFO32to16( const MINMAXINFO *from, MINMAXINFO16 *to )
333 to->ptReserved.x = from->ptReserved.x;
334 to->ptReserved.y = from->ptReserved.y;
335 to->ptMaxSize.x = from->ptMaxSize.x;
336 to->ptMaxSize.y = from->ptMaxSize.y;
337 to->ptMaxPosition.x = from->ptMaxPosition.x;
338 to->ptMaxPosition.y = from->ptMaxPosition.y;
339 to->ptMinTrackSize.x = from->ptMinTrackSize.x;
340 to->ptMinTrackSize.y = from->ptMinTrackSize.y;
341 to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
342 to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
345 static void MINMAXINFO16to32( const MINMAXINFO16 *from, MINMAXINFO *to )
347 to->ptReserved.x = from->ptReserved.x;
348 to->ptReserved.y = from->ptReserved.y;
349 to->ptMaxSize.x = from->ptMaxSize.x;
350 to->ptMaxSize.y = from->ptMaxSize.y;
351 to->ptMaxPosition.x = from->ptMaxPosition.x;
352 to->ptMaxPosition.y = from->ptMaxPosition.y;
353 to->ptMinTrackSize.x = from->ptMinTrackSize.x;
354 to->ptMinTrackSize.y = from->ptMinTrackSize.y;
355 to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
356 to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
359 static void WINDOWPOS32to16( const WINDOWPOS* from, WINDOWPOS16* to )
361 to->hwnd = HWND_16(from->hwnd);
362 to->hwndInsertAfter = HWND_16(from->hwndInsertAfter);
363 to->x = from->x;
364 to->y = from->y;
365 to->cx = from->cx;
366 to->cy = from->cy;
367 to->flags = from->flags;
370 static void WINDOWPOS16to32( const WINDOWPOS16* from, WINDOWPOS* to )
372 to->hwnd = WIN_Handle32(from->hwnd);
373 to->hwndInsertAfter = (from->hwndInsertAfter == (HWND16)-1) ?
374 HWND_TOPMOST : WIN_Handle32(from->hwndInsertAfter);
375 to->x = from->x;
376 to->y = from->y;
377 to->cx = from->cx;
378 to->cy = from->cy;
379 to->flags = from->flags;
382 /* The strings are not copied */
383 static void CREATESTRUCT32Ato16( const CREATESTRUCTA* from, CREATESTRUCT16* to )
385 to->lpCreateParams = (SEGPTR)from->lpCreateParams;
386 to->hInstance = HINSTANCE_16(from->hInstance);
387 to->hMenu = HMENU_16(from->hMenu);
388 to->hwndParent = HWND_16(from->hwndParent);
389 to->cy = from->cy;
390 to->cx = from->cx;
391 to->y = from->y;
392 to->x = from->x;
393 to->style = from->style;
394 to->dwExStyle = from->dwExStyle;
397 static void CREATESTRUCT16to32A( const CREATESTRUCT16* from, CREATESTRUCTA *to )
400 to->lpCreateParams = (LPVOID)from->lpCreateParams;
401 to->hInstance = HINSTANCE_32(from->hInstance);
402 to->hMenu = HMENU_32(from->hMenu);
403 to->hwndParent = WIN_Handle32(from->hwndParent);
404 to->cy = from->cy;
405 to->cx = from->cx;
406 to->y = from->y;
407 to->x = from->x;
408 to->style = from->style;
409 to->dwExStyle = from->dwExStyle;
412 /* The strings are not copied */
413 static void MDICREATESTRUCT32Ato16( const MDICREATESTRUCTA* from, MDICREATESTRUCT16* to )
415 to->hOwner = HINSTANCE_16(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 void MDICREATESTRUCT16to32A( const MDICREATESTRUCT16* from, MDICREATESTRUCTA *to )
426 to->hOwner = HINSTANCE_32(from->hOwner);
427 to->x = from->x;
428 to->y = from->y;
429 to->cx = from->cx;
430 to->cy = from->cy;
431 to->style = from->style;
432 to->lParam = from->lParam;
435 static WPARAM map_wparam_char_AtoW( WPARAM wParam, DWORD len )
437 CHAR ch[2];
438 WCHAR wch;
440 ch[0] = (wParam >> 8);
441 ch[1] = wParam & 0xff;
442 if (len > 1 && ch[0])
443 RtlMultiByteToUnicodeN( &wch, sizeof(wch), NULL, ch, 2 );
444 else
445 RtlMultiByteToUnicodeN( &wch, sizeof(wch), NULL, ch + 1, 1 );
446 return MAKEWPARAM( wch, HIWORD(wParam) );
449 static WPARAM map_wparam_char_WtoA( WPARAM wParam, DWORD len )
451 WCHAR wch = wParam;
452 BYTE ch[2];
454 RtlUnicodeToMultiByteN( (LPSTR)ch, len, &len, &wch, sizeof(wch) );
455 if (len == 2)
456 return MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(wParam) );
457 else
458 return MAKEWPARAM( ch[0], HIWORD(wParam) );
461 /* call a 32-bit window procedure */
462 static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result, void *arg )
464 WNDPROC proc = arg;
466 USER_CheckNotLock();
468 hwnd = WIN_GetFullHandle( hwnd );
469 if (TRACE_ON(relay))
470 DPRINTF( "%04lx:Call window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
471 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp );
473 *result = WINPROC_wrapper( proc, hwnd, msg, wp, lp );
475 if (TRACE_ON(relay))
476 DPRINTF( "%04lx:Ret window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx\n",
477 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp, *result );
478 return *result;
481 /* call a 32-bit dialog procedure */
482 static LRESULT call_dialog_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result, void *arg )
484 WNDPROC proc = arg;
485 LRESULT ret;
487 USER_CheckNotLock();
489 hwnd = WIN_GetFullHandle( hwnd );
490 if (TRACE_ON(relay))
491 DPRINTF( "%04lx:Call dialog proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
492 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp );
494 ret = WINPROC_wrapper( proc, hwnd, msg, wp, lp );
495 *result = GetWindowLongPtrW( hwnd, DWLP_MSGRESULT );
497 if (TRACE_ON(relay))
498 DPRINTF( "%04lx:Ret dialog proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx result=%08lx\n",
499 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp, ret, *result );
500 return ret;
503 /**********************************************************************
504 * WINPROC_CallWndProc32
506 * Call a 32-bit WndProc.
508 static LRESULT WINPROC_CallWndProc( WNDPROC proc, HWND hwnd, UINT msg,
509 WPARAM wParam, LPARAM lParam )
511 LRESULT retvalue;
513 USER_CheckNotLock();
515 hwnd = WIN_GetFullHandle( hwnd );
516 if (TRACE_ON(relay))
517 DPRINTF( "%04lx:Call window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
518 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
520 retvalue = WINPROC_wrapper( proc, hwnd, msg, wParam, lParam );
522 if (TRACE_ON(relay))
523 DPRINTF( "%04lx:Ret window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx\n",
524 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam, retvalue );
525 return retvalue;
528 /* call a 16-bit window procedure */
529 static LRESULT call_window_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
530 LRESULT *result, void *arg )
532 WNDPROC16 proc = arg;
533 CONTEXT86 context;
534 size_t size = 0;
535 struct
537 WORD params[5];
538 union
540 CREATESTRUCT16 cs16;
541 DRAWITEMSTRUCT16 dis16;
542 COMPAREITEMSTRUCT16 cis16;
543 } u;
544 } args;
546 USER_CheckNotLock();
548 /* Window procedures want ax = hInstance, ds = es = ss */
550 memset(&context, 0, sizeof(context));
551 context.SegDs = context.SegEs = SELECTOROF(NtCurrentTeb()->WOW32Reserved);
552 context.SegFs = wine_get_fs();
553 context.SegGs = wine_get_gs();
554 if (!(context.Eax = GetWindowWord( HWND_32(hwnd), GWLP_HINSTANCE ))) context.Eax = context.SegDs;
555 context.SegCs = SELECTOROF(proc);
556 context.Eip = OFFSETOF(proc);
557 context.Ebp = OFFSETOF(NtCurrentTeb()->WOW32Reserved) + (WORD)&((STACK16FRAME*)0)->bp;
559 if (lParam)
561 /* Some programs (eg. the "Undocumented Windows" examples, JWP) only
562 work if structures passed in lParam are placed in the stack/data
563 segment. Programmers easily make the mistake of converting lParam
564 to a near rather than a far pointer, since Windows apparently
565 allows this. We copy the structures to the 16 bit stack; this is
566 ugly but makes these programs work. */
567 switch (msg)
569 case WM_CREATE:
570 case WM_NCCREATE:
571 size = sizeof(CREATESTRUCT16); break;
572 case WM_DRAWITEM:
573 size = sizeof(DRAWITEMSTRUCT16); break;
574 case WM_COMPAREITEM:
575 size = sizeof(COMPAREITEMSTRUCT16); break;
577 if (size)
579 memcpy( &args.u, MapSL(lParam), size );
580 lParam = (SEGPTR)NtCurrentTeb()->WOW32Reserved - size;
584 args.params[4] = hwnd;
585 args.params[3] = msg;
586 args.params[2] = wParam;
587 args.params[1] = HIWORD(lParam);
588 args.params[0] = LOWORD(lParam);
589 WOWCallback16Ex( 0, WCB16_REGS, sizeof(args.params) + size, &args, (DWORD *)&context );
590 *result = MAKELONG( LOWORD(context.Eax), LOWORD(context.Edx) );
591 return *result;
594 /* call a 16-bit dialog procedure */
595 static LRESULT call_dialog_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp,
596 LRESULT *result, void *arg )
598 LRESULT ret = call_window_proc16( hwnd, msg, wp, lp, result, arg );
599 *result = GetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT );
600 return LOWORD(ret);
604 /**********************************************************************
605 * WINPROC_GetProc16
607 * Get a window procedure pointer that can be passed to the Windows program.
609 WNDPROC16 WINPROC_GetProc16( WNDPROC proc, BOOL unicode )
611 WINDOWPROC *ptr;
613 if (unicode) ptr = alloc_winproc( NULL, proc );
614 else ptr = alloc_winproc( proc, NULL );
616 if (!ptr) return 0;
617 return alloc_win16_thunk( ptr );
621 /**********************************************************************
622 * WINPROC_GetProc
624 * Get a window procedure pointer that can be passed to the Windows program.
626 WNDPROC WINPROC_GetProc( WNDPROC proc, BOOL unicode )
628 WINDOWPROC *ptr = handle_to_proc( proc );
630 if (!ptr) return proc;
631 if (unicode)
633 if (ptr->procW) return ptr->procW;
634 return proc;
636 else
638 if (ptr->procA) return ptr->procA;
639 return proc;
644 /**********************************************************************
645 * WINPROC_AllocProc16
647 * Allocate a window procedure for a window or class.
649 * Note that allocated winprocs are never freed; the idea is that even if an app creates a
650 * lot of windows, it will usually only have a limited number of window procedures, so the
651 * array won't grow too large, and this way we avoid the need to track allocations per window.
653 WNDPROC WINPROC_AllocProc16( WNDPROC16 func )
655 WINDOWPROC *proc;
657 if (!func) return NULL;
659 /* check if the function is already a win proc */
660 if (!(proc = handle16_to_proc( func )))
662 EnterCriticalSection( &winproc_cs );
664 /* then check if we already have a winproc for that function */
665 if (!(proc = find_winproc16( func )))
667 if (winproc_used < MAX_WINPROCS)
669 proc = &winproc_array[winproc_used++];
670 proc->proc16 = func;
671 TRACE( "allocated %p for %p/16-bit (%d/%d used)\n",
672 proc_to_handle(proc), func, winproc_used, MAX_WINPROCS );
674 else FIXME( "too many winprocs, cannot allocate one for 16-bit %p\n", func );
676 else TRACE( "reusing %p for %p/16-bit\n", proc_to_handle(proc), func );
678 LeaveCriticalSection( &winproc_cs );
680 return proc_to_handle( proc );
684 /**********************************************************************
685 * WINPROC_AllocProc
687 * Allocate a window procedure for a window or class.
689 * Note that allocated winprocs are never freed; the idea is that even if an app creates a
690 * lot of windows, it will usually only have a limited number of window procedures, so the
691 * array won't grow too large, and this way we avoid the need to track allocations per window.
693 WNDPROC WINPROC_AllocProc( WNDPROC funcA, WNDPROC funcW )
695 WINDOWPROC *proc;
697 if (!(proc = alloc_winproc( funcA, funcW ))) return NULL;
698 return proc_to_handle( proc );
702 /**********************************************************************
703 * WINPROC_IsUnicode
705 * Return the window procedure type, or the default value if not a winproc handle.
707 BOOL WINPROC_IsUnicode( WNDPROC proc, BOOL def_val )
709 WINDOWPROC *ptr = handle_to_proc( proc );
711 if (!ptr) return def_val;
712 if (ptr->procA && ptr->procW) return def_val; /* can be both */
713 return (ptr->procW != NULL);
717 /**********************************************************************
718 * WINPROC_TestLBForStr
720 * Return TRUE if the lparam is a string
722 inline static BOOL WINPROC_TestLBForStr( HWND hwnd, UINT msg )
724 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
725 if (msg <= CB_MSGMAX)
726 return (!(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) || (style & CBS_HASSTRINGS));
727 else
728 return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS));
731 /**********************************************************************
732 * WINPROC_MapMsg32ATo32W
734 * Map a message from Ansi to Unicode.
735 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
737 * FIXME:
738 * WM_GETTEXT/WM_SETTEXT and static control with SS_ICON style:
739 * the first four bytes are the handle of the icon
740 * when the WM_SETTEXT message has been used to set the icon
742 static INT WINPROC_MapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
744 switch(msg)
746 case WM_GETTEXT:
747 case WM_ASKCBFORMATNAME:
749 LPARAM *ptr = HeapAlloc( GetProcessHeap(), 0,
750 *pwparam * sizeof(WCHAR) + sizeof(LPARAM) );
751 if (!ptr) return -1;
752 *ptr++ = *plparam; /* Store previous lParam */
753 *plparam = (LPARAM)ptr;
755 return 1;
756 /* lparam is string (0-terminated) */
757 case WM_SETTEXT:
758 case WM_WININICHANGE:
759 case WM_DEVMODECHANGE:
760 case CB_DIR:
761 case LB_DIR:
762 case LB_ADDFILE:
763 case EM_REPLACESEL:
764 if (!*plparam) return 0;
765 else
767 DWORD len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*plparam, -1, NULL, 0);
768 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
769 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*plparam, -1, buf, len);
770 *plparam = (LPARAM)buf;
771 return (*plparam ? 1 : -1);
773 case WM_GETTEXTLENGTH:
774 case CB_GETLBTEXTLEN:
775 case LB_GETTEXTLEN:
776 return 1; /* need to map result */
777 case WM_MDICREATE:
779 MDICREATESTRUCTW *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
780 if (!cs) return -1;
781 *cs = *(MDICREATESTRUCTW *)*plparam;
782 if (HIWORD(cs->szClass))
784 UNICODE_STRING usBuffer;
785 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)cs->szClass);
786 cs->szClass = usBuffer.Buffer;
788 if (HIWORD(cs->szTitle))
790 UNICODE_STRING usBuffer;
791 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)cs->szTitle);
792 cs->szTitle = usBuffer.Buffer;
794 *plparam = (LPARAM)cs;
796 return 1;
798 /* Listbox / Combobox */
799 case LB_ADDSTRING:
800 case LB_INSERTSTRING:
801 case LB_FINDSTRING:
802 case LB_FINDSTRINGEXACT:
803 case LB_SELECTSTRING:
804 case CB_ADDSTRING:
805 case CB_INSERTSTRING:
806 case CB_FINDSTRINGEXACT:
807 case CB_FINDSTRING:
808 case CB_SELECTSTRING:
809 if(!*plparam) return 0;
810 if ( WINPROC_TestLBForStr( hwnd, msg ))
812 UNICODE_STRING usBuffer;
813 RtlCreateUnicodeStringFromAsciiz(&usBuffer,(LPCSTR)*plparam);
814 *plparam = (LPARAM)usBuffer.Buffer;
816 return (*plparam ? 1 : -1);
818 case LB_GETTEXT: /* FIXME: fixed sized buffer */
819 case CB_GETLBTEXT:
820 if ( WINPROC_TestLBForStr( hwnd, msg ))
822 LPARAM *ptr = HeapAlloc( GetProcessHeap(), 0, 512 * sizeof(WCHAR) + sizeof(LPARAM) );
823 if (!ptr) return -1;
824 *ptr++ = *plparam; /* Store previous lParam */
825 *plparam = (LPARAM)ptr;
827 return 1;
829 /* Multiline edit */
830 case EM_GETLINE:
831 { WORD len = (WORD)*plparam;
832 LPARAM *ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
833 if (!ptr) return -1;
834 *ptr++ = *plparam; /* Store previous lParam */
835 *((WORD *) ptr) = len; /* Store the length */
836 *plparam = (LPARAM)ptr;
838 return 1;
840 case WM_CHARTOITEM:
841 case WM_MENUCHAR:
842 case WM_CHAR:
843 case WM_DEADCHAR:
844 case WM_SYSCHAR:
845 case WM_SYSDEADCHAR:
846 case EM_SETPASSWORDCHAR:
847 *pwparam = map_wparam_char_AtoW( *pwparam, 1 );
848 return 0;
850 case WM_IME_CHAR:
851 *pwparam = map_wparam_char_AtoW( *pwparam, 2 );
852 return 0;
854 case WM_PAINTCLIPBOARD:
855 case WM_SIZECLIPBOARD:
856 FIXME_(msg)("message %s (0x%x) needs translation, please report\n", SPY_GetMsgName(msg, hwnd), msg );
857 return -1;
858 default: /* No translation needed */
859 return 0;
864 /**********************************************************************
865 * WINPROC_UnmapMsg32ATo32W
867 * Unmap a message that was mapped from Ansi to Unicode.
869 static LRESULT WINPROC_UnmapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
870 LRESULT result, WNDPROC dispatch )
872 switch(msg)
874 case WM_GETTEXT:
875 case WM_ASKCBFORMATNAME:
877 LPARAM *ptr = (LPARAM *)lParam - 1;
878 if (!wParam) result = 0;
879 else if (!(result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
880 (LPSTR)*ptr, wParam, NULL, NULL )))
882 ((LPSTR)*ptr)[wParam-1] = 0;
883 result = wParam - 1;
885 else result--; /* do not count terminating null */
886 HeapFree( GetProcessHeap(), 0, ptr );
888 break;
889 case WM_GETTEXTLENGTH:
890 case CB_GETLBTEXTLEN:
891 case LB_GETTEXTLEN:
892 if (result >= 0)
894 /* Determine respective GETTEXT message */
895 UINT msgGetText =
896 (msg == WM_GETTEXTLENGTH) ? WM_GETTEXT :
897 ((msg == CB_GETLBTEXTLEN) ? CB_GETLBTEXT : LB_GETTEXT);
898 /* wParam differs between the messages */
899 WPARAM wp = (msg == WM_GETTEXTLENGTH) ? (WPARAM)(result + 1) : wParam;
901 WCHAR* p = HeapAlloc (GetProcessHeap(), 0, (result + 1) * sizeof(WCHAR));
903 if (p)
905 LRESULT n;
907 if (dispatch)
908 n = WINPROC_CallWndProc(dispatch, hwnd, msgGetText, wp, (LPARAM)p);
909 else
910 n = SendMessageW (hwnd, msgGetText, wp, (LPARAM)p);
912 result = WideCharToMultiByte( CP_ACP, 0, p, n, NULL, 0, 0, NULL );
913 HeapFree (GetProcessHeap(), 0, p);
916 break;
918 case WM_MDICREATE:
920 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
921 if (HIWORD(cs->szTitle))
922 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
923 if (HIWORD(cs->szClass))
924 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
925 HeapFree( GetProcessHeap(), 0, cs );
927 break;
929 case WM_SETTEXT:
930 case WM_WININICHANGE:
931 case WM_DEVMODECHANGE:
932 case CB_DIR:
933 case LB_DIR:
934 case LB_ADDFILE:
935 case EM_REPLACESEL:
936 HeapFree( GetProcessHeap(), 0, (void *)lParam );
937 break;
939 /* Listbox / Combobox */
940 case LB_ADDSTRING:
941 case LB_INSERTSTRING:
942 case LB_FINDSTRING:
943 case LB_FINDSTRINGEXACT:
944 case LB_SELECTSTRING:
945 case CB_ADDSTRING:
946 case CB_INSERTSTRING:
947 case CB_FINDSTRING:
948 case CB_FINDSTRINGEXACT:
949 case CB_SELECTSTRING:
950 if ( WINPROC_TestLBForStr( hwnd, msg ))
951 HeapFree( GetProcessHeap(), 0, (void *)lParam );
952 break;
954 case LB_GETTEXT:
955 case CB_GETLBTEXT:
956 if ( WINPROC_TestLBForStr( hwnd, msg ))
958 LPARAM *ptr = (LPARAM *)lParam - 1;
959 if (result >= 0)
960 result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
961 (LPSTR)*ptr, 0x7fffffff, NULL, NULL ) - 1;
962 HeapFree( GetProcessHeap(), 0, ptr );
964 break;
966 /* Multiline edit */
967 case EM_GETLINE:
969 LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lParam */
970 WORD len = *(WORD *) lParam;
971 result = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, result,
972 (LPSTR)*ptr, len, NULL, NULL );
973 if (result < len) ((LPSTR)*ptr)[result] = 0;
974 HeapFree( GetProcessHeap(), 0, ptr );
976 break;
978 return result;
982 static UINT convert_handle_16_to_32(HANDLE16 src, unsigned int flags)
984 HANDLE dst;
985 UINT sz = GlobalSize16(src);
986 LPSTR ptr16, ptr32;
988 if (!(dst = GlobalAlloc(flags, sz)))
989 return 0;
990 ptr16 = GlobalLock16(src);
991 ptr32 = GlobalLock(dst);
992 if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr32, ptr16, sz);
993 GlobalUnlock16(src);
994 GlobalUnlock(dst);
996 return (UINT)dst;
999 /**********************************************************************
1000 * WINPROC_MapMsg16To32A
1002 * Map a message from 16- to 32-bit Ansi.
1003 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1005 INT WINPROC_MapMsg16To32A( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1006 WPARAM *pwparam32, LPARAM *plparam )
1008 *pmsg32 = (UINT)msg16;
1009 *pwparam32 = (WPARAM)wParam16;
1010 switch(msg16)
1012 case WM_ACTIVATE:
1013 case WM_CHARTOITEM:
1014 case WM_COMMAND:
1015 case WM_VKEYTOITEM:
1016 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1017 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1018 return 0;
1019 case WM_HSCROLL:
1020 case WM_VSCROLL:
1021 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1022 *plparam = (LPARAM)WIN_Handle32( HIWORD(*plparam) );
1023 return 0;
1024 case WM_CTLCOLOR:
1025 if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
1026 *pmsg32 = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
1027 *pwparam32 = (WPARAM)HDC_32(wParam16);
1028 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1029 return 0;
1030 case WM_COMPAREITEM:
1032 COMPAREITEMSTRUCT16* cis16 = MapSL(*plparam);
1033 COMPAREITEMSTRUCT *cis = HeapAlloc(GetProcessHeap(), 0, sizeof(*cis));
1034 if (!cis) return -1;
1035 cis->CtlType = cis16->CtlType;
1036 cis->CtlID = cis16->CtlID;
1037 cis->hwndItem = WIN_Handle32( cis16->hwndItem );
1038 cis->itemID1 = cis16->itemID1;
1039 cis->itemData1 = cis16->itemData1;
1040 cis->itemID2 = cis16->itemID2;
1041 cis->itemData2 = cis16->itemData2;
1042 cis->dwLocaleId = 0; /* FIXME */
1043 *plparam = (LPARAM)cis;
1045 return 1;
1046 case WM_COPYDATA:
1048 PCOPYDATASTRUCT16 pcds16 = MapSL(*plparam);
1049 PCOPYDATASTRUCT pcds = HeapAlloc ( GetProcessHeap(), 0, sizeof(*pcds));
1050 pcds->dwData = pcds16->dwData;
1051 pcds->cbData = pcds16->cbData;
1052 pcds->lpData = MapSL( pcds16->lpData);
1053 *plparam = (LPARAM)pcds;
1055 return 1;
1056 case WM_DELETEITEM:
1058 DELETEITEMSTRUCT16* dis16 = MapSL(*plparam);
1059 DELETEITEMSTRUCT *dis = HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
1060 if (!dis) return -1;
1061 dis->CtlType = dis16->CtlType;
1062 dis->CtlID = dis16->CtlID;
1063 dis->hwndItem = WIN_Handle32( dis16->hwndItem );
1064 dis->itemData = dis16->itemData;
1065 *plparam = (LPARAM)dis;
1067 return 1;
1068 case WM_MEASUREITEM:
1070 MEASUREITEMSTRUCT16* mis16 = MapSL(*plparam);
1071 MEASUREITEMSTRUCT *mis = HeapAlloc(GetProcessHeap(), 0,
1072 sizeof(*mis) + sizeof(LPARAM));
1073 if (!mis) return -1;
1074 mis->CtlType = mis16->CtlType;
1075 mis->CtlID = mis16->CtlID;
1076 mis->itemID = mis16->itemID;
1077 mis->itemWidth = mis16->itemWidth;
1078 mis->itemHeight = mis16->itemHeight;
1079 mis->itemData = mis16->itemData;
1080 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
1081 *plparam = (LPARAM)mis;
1083 return 1;
1084 case WM_DRAWITEM:
1086 DRAWITEMSTRUCT16* dis16 = MapSL(*plparam);
1087 DRAWITEMSTRUCT *dis = HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
1088 if (!dis) return -1;
1089 dis->CtlType = dis16->CtlType;
1090 dis->CtlID = dis16->CtlID;
1091 dis->itemID = dis16->itemID;
1092 dis->itemAction = dis16->itemAction;
1093 dis->itemState = dis16->itemState;
1094 dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND)HMENU_32(dis16->hwndItem)
1095 : WIN_Handle32( dis16->hwndItem );
1096 dis->hDC = HDC_32(dis16->hDC);
1097 dis->itemData = dis16->itemData;
1098 dis->rcItem.left = dis16->rcItem.left;
1099 dis->rcItem.top = dis16->rcItem.top;
1100 dis->rcItem.right = dis16->rcItem.right;
1101 dis->rcItem.bottom = dis16->rcItem.bottom;
1102 *plparam = (LPARAM)dis;
1104 return 1;
1105 case WM_GETMINMAXINFO:
1107 MINMAXINFO *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM));
1108 if (!mmi) return -1;
1109 MINMAXINFO16to32( MapSL(*plparam), mmi );
1110 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
1111 *plparam = (LPARAM)mmi;
1113 return 1;
1114 case WM_GETTEXT:
1115 case WM_SETTEXT:
1116 case WM_WININICHANGE:
1117 case WM_DEVMODECHANGE:
1118 case WM_ASKCBFORMATNAME:
1119 *plparam = (LPARAM)MapSL(*plparam);
1120 return 0;
1121 case WM_MDICREATE:
1123 MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1124 MDICREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1125 if (!cs) return -1;
1126 MDICREATESTRUCT16to32A( cs16, cs );
1127 cs->szTitle = MapSL(cs16->szTitle);
1128 cs->szClass = MapSL(cs16->szClass);
1129 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1130 *plparam = (LPARAM)cs;
1132 return 1;
1133 case WM_MDIGETACTIVE:
1134 *plparam = (LPARAM)HeapAlloc( GetProcessHeap(), 0, sizeof(BOOL) );
1135 *(BOOL*)(*plparam) = 0;
1136 return 1;
1137 case WM_MDISETMENU:
1138 if(wParam16) *pmsg32=WM_MDIREFRESHMENU;
1139 *pwparam32 = (WPARAM)HMENU_32(LOWORD(*plparam));
1140 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1141 return 0;
1142 case WM_MENUCHAR:
1143 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1144 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1145 return 0;
1146 case WM_MENUSELECT:
1147 if((LOWORD(*plparam) & MF_POPUP) && (LOWORD(*plparam) != 0xFFFF))
1149 HMENU hmenu=HMENU_32(HIWORD(*plparam));
1150 UINT Pos=MENU_FindSubMenu( &hmenu, HMENU_32(wParam16));
1151 if(Pos==0xFFFF) Pos=0; /* NO_SELECTED_ITEM */
1152 *pwparam32 = MAKEWPARAM( Pos, LOWORD(*plparam) );
1154 else *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1155 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1156 return 0;
1157 case WM_MDIACTIVATE:
1158 if( *plparam )
1160 *pwparam32 = (WPARAM)WIN_Handle32( HIWORD(*plparam) );
1161 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1163 else /* message sent to MDI client */
1164 *pwparam32 = wParam16;
1165 return 0;
1166 case WM_NCCALCSIZE:
1168 NCCALCSIZE_PARAMS16 *nc16;
1169 NCCALCSIZE_PARAMS *nc;
1171 nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM) );
1172 if (!nc) return -1;
1173 nc16 = MapSL(*plparam);
1174 nc->rgrc[0].left = nc16->rgrc[0].left;
1175 nc->rgrc[0].top = nc16->rgrc[0].top;
1176 nc->rgrc[0].right = nc16->rgrc[0].right;
1177 nc->rgrc[0].bottom = nc16->rgrc[0].bottom;
1178 if (wParam16)
1180 nc->lppos = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc->lppos) );
1181 nc->rgrc[1].left = nc16->rgrc[1].left;
1182 nc->rgrc[1].top = nc16->rgrc[1].top;
1183 nc->rgrc[1].right = nc16->rgrc[1].right;
1184 nc->rgrc[1].bottom = nc16->rgrc[1].bottom;
1185 nc->rgrc[2].left = nc16->rgrc[2].left;
1186 nc->rgrc[2].top = nc16->rgrc[2].top;
1187 nc->rgrc[2].right = nc16->rgrc[2].right;
1188 nc->rgrc[2].bottom = nc16->rgrc[2].bottom;
1189 if (nc->lppos) WINDOWPOS16to32( MapSL(nc16->lppos), nc->lppos );
1191 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
1192 *plparam = (LPARAM)nc;
1194 return 1;
1195 case WM_NCCREATE:
1196 case WM_CREATE:
1198 CREATESTRUCT16 *cs16 = MapSL(*plparam);
1199 CREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1200 if (!cs) return -1;
1201 CREATESTRUCT16to32A( cs16, cs );
1202 cs->lpszName = MapSL(cs16->lpszName);
1203 cs->lpszClass = MapSL(cs16->lpszClass);
1205 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1207 MDICREATESTRUCT16 *mdi_cs16;
1208 MDICREATESTRUCTA *mdi_cs = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs));
1209 if (!mdi_cs)
1211 HeapFree(GetProcessHeap(), 0, cs);
1212 return -1;
1214 mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs16->lpCreateParams);
1215 MDICREATESTRUCT16to32A(mdi_cs16, mdi_cs);
1216 mdi_cs->szTitle = MapSL(mdi_cs16->szTitle);
1217 mdi_cs->szClass = MapSL(mdi_cs16->szClass);
1219 cs->lpCreateParams = mdi_cs;
1221 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1222 *plparam = (LPARAM)cs;
1224 return 1;
1225 case WM_PARENTNOTIFY:
1226 if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
1228 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1229 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1231 return 0;
1232 case WM_WINDOWPOSCHANGING:
1233 case WM_WINDOWPOSCHANGED:
1235 WINDOWPOS *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
1236 if (!wp) return -1;
1237 WINDOWPOS16to32( MapSL(*plparam), wp );
1238 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
1239 *plparam = (LPARAM)wp;
1241 return 1;
1242 case WM_GETDLGCODE:
1243 if (*plparam)
1245 LPMSG16 msg16 = MapSL(*plparam);
1246 LPMSG msg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1248 if (!msg32) return -1;
1249 msg32->hwnd = WIN_Handle32( msg16->hwnd );
1250 msg32->message = msg16->message;
1251 msg32->wParam = msg16->wParam;
1252 msg32->lParam = msg16->lParam;
1253 msg32->time = msg16->time;
1254 msg32->pt.x = msg16->pt.x;
1255 msg32->pt.y = msg16->pt.y;
1256 *plparam = (LPARAM)msg32;
1257 return 1;
1259 else return 0;
1260 case WM_NOTIFY:
1261 *plparam = (LPARAM)MapSL(*plparam);
1262 return 0;
1263 case WM_ACTIVATEAPP:
1264 /* We need this when SetActiveWindow sends a Sendmessage16() to
1265 * a 32bit window. Might be superflous with 32bit interprocess
1266 * message queues. */
1267 if (*plparam) *plparam = HTASK_32( *plparam );
1268 return 0;
1269 case WM_NEXTMENU:
1271 MDINEXTMENU *next = HeapAlloc( GetProcessHeap(), 0, sizeof(*next) );
1272 if (!next) return -1;
1273 next->hmenuIn = (HMENU)*plparam;
1274 next->hmenuNext = 0;
1275 next->hwndNext = 0;
1276 *plparam = (LPARAM)next;
1277 return 1;
1279 case WM_PAINTCLIPBOARD:
1280 case WM_SIZECLIPBOARD:
1281 FIXME_(msg)("message %04x needs translation\n",msg16 );
1282 return -1;
1283 case WM_DDE_INITIATE:
1284 case WM_DDE_TERMINATE:
1285 case WM_DDE_UNADVISE:
1286 case WM_DDE_REQUEST:
1287 *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1288 return 0;
1289 case WM_DDE_ADVISE:
1290 case WM_DDE_DATA:
1291 case WM_DDE_POKE:
1293 HANDLE16 lo16;
1294 ATOM hi;
1295 UINT lo32 = 0;
1297 *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1298 lo16 = LOWORD(*plparam);
1299 hi = HIWORD(*plparam);
1300 if (lo16 && !(lo32 = convert_handle_16_to_32(lo16, GMEM_DDESHARE)))
1301 return -1;
1302 *plparam = PackDDElParam(msg16, lo32, hi);
1304 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1305 case WM_DDE_ACK:
1307 UINT lo, hi;
1308 int flag = 0;
1309 char buf[2];
1311 *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1313 lo = LOWORD(*plparam);
1314 hi = HIWORD(*plparam);
1316 if (GlobalGetAtomNameA(hi, buf, 2) > 0) flag |= 1;
1317 if (GlobalSize16(hi) != 0) flag |= 2;
1318 switch (flag)
1320 case 0:
1321 if (hi)
1323 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1324 hi = 0;
1326 break;
1327 case 1:
1328 break; /* atom, nothing to do */
1329 case 3:
1330 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
1331 /* fall thru */
1332 case 2:
1333 hi = convert_handle_16_to_32(hi, GMEM_DDESHARE);
1334 break;
1336 *plparam = PackDDElParam(WM_DDE_ACK, lo, hi);
1338 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1339 case WM_DDE_EXECUTE:
1340 *plparam = convert_handle_16_to_32(*plparam, GMEM_DDESHARE);
1341 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1342 default: /* No translation needed */
1343 return 0;
1348 /**********************************************************************
1349 * WINPROC_UnmapMsg16To32A
1351 * Unmap a message that was mapped from 16- to 32-bit Ansi.
1353 static LRESULT WINPROC_UnmapMsg16To32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1354 LRESULT result )
1356 switch(msg)
1358 case WM_COMPAREITEM:
1359 case WM_DELETEITEM:
1360 case WM_DRAWITEM:
1361 case WM_COPYDATA:
1362 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
1363 break;
1364 case WM_MEASUREITEM:
1366 MEASUREITEMSTRUCT16 *mis16;
1367 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam;
1368 lParam = *(LPARAM *)(mis + 1);
1369 mis16 = MapSL(lParam);
1370 mis16->itemWidth = (UINT16)mis->itemWidth;
1371 mis16->itemHeight = (UINT16)mis->itemHeight;
1372 HeapFree( GetProcessHeap(), 0, mis );
1374 break;
1375 case WM_GETMINMAXINFO:
1377 MINMAXINFO *mmi = (MINMAXINFO *)lParam;
1378 lParam = *(LPARAM *)(mmi + 1);
1379 MINMAXINFO32to16( mmi, MapSL(lParam));
1380 HeapFree( GetProcessHeap(), 0, mmi );
1382 break;
1383 case WM_MDICREATE:
1385 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1386 lParam = *(LPARAM *)(cs + 1);
1387 MDICREATESTRUCT32Ato16( cs, MapSL(lParam) );
1388 HeapFree( GetProcessHeap(), 0, cs );
1390 break;
1391 case WM_MDIGETACTIVE:
1392 result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL *)lParam) );
1393 HeapFree( GetProcessHeap(), 0, (BOOL *)lParam );
1394 break;
1395 case WM_NCCALCSIZE:
1397 NCCALCSIZE_PARAMS16 *nc16;
1398 NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lParam;
1399 lParam = *(LPARAM *)(nc + 1);
1400 nc16 = MapSL(lParam);
1401 nc16->rgrc[0].left = nc->rgrc[0].left;
1402 nc16->rgrc[0].top = nc->rgrc[0].top;
1403 nc16->rgrc[0].right = nc->rgrc[0].right;
1404 nc16->rgrc[0].bottom = nc->rgrc[0].bottom;
1405 if (wParam)
1407 nc16->rgrc[1].left = nc->rgrc[1].left;
1408 nc16->rgrc[1].top = nc->rgrc[1].top;
1409 nc16->rgrc[1].right = nc->rgrc[1].right;
1410 nc16->rgrc[1].bottom = nc->rgrc[1].bottom;
1411 nc16->rgrc[2].left = nc->rgrc[2].left;
1412 nc16->rgrc[2].top = nc->rgrc[2].top;
1413 nc16->rgrc[2].right = nc->rgrc[2].right;
1414 nc16->rgrc[2].bottom = nc->rgrc[2].bottom;
1415 if (nc->lppos)
1417 WINDOWPOS32to16( nc->lppos, MapSL(nc16->lppos));
1418 HeapFree( GetProcessHeap(), 0, nc->lppos );
1421 HeapFree( GetProcessHeap(), 0, nc );
1423 break;
1424 case WM_NCCREATE:
1425 case WM_CREATE:
1427 CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1428 lParam = *(LPARAM *)(cs + 1);
1429 CREATESTRUCT32Ato16( cs, MapSL(lParam) );
1431 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1432 HeapFree(GetProcessHeap(), 0, cs->lpCreateParams);
1434 HeapFree( GetProcessHeap(), 0, cs );
1436 break;
1437 case WM_WINDOWPOSCHANGING:
1438 case WM_WINDOWPOSCHANGED:
1440 WINDOWPOS *wp = (WINDOWPOS *)lParam;
1441 lParam = *(LPARAM *)(wp + 1);
1442 WINDOWPOS32to16(wp, MapSL(lParam));
1443 HeapFree( GetProcessHeap(), 0, wp );
1445 break;
1446 case WM_GETDLGCODE:
1447 if (lParam)
1449 LPMSG msg32 = (LPMSG)lParam;
1450 HeapFree( GetProcessHeap(), 0, msg32 );
1452 break;
1453 case WM_NEXTMENU:
1455 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
1456 result = MAKELONG( HMENU_16(next->hmenuNext), HWND_16(next->hwndNext) );
1457 HeapFree( GetProcessHeap(), 0, next );
1459 break;
1461 return result;
1465 /**********************************************************************
1466 * WINPROC_MapMsg16To32W
1468 * Map a message from 16- to 32-bit Unicode.
1469 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1471 static INT WINPROC_MapMsg16To32W( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1472 WPARAM *pwparam32, LPARAM *plparam )
1474 *pmsg32=(UINT)msg16;
1475 *pwparam32 = (WPARAM)wParam16;
1476 switch(msg16)
1478 case WM_GETTEXT:
1479 case WM_SETTEXT:
1480 case WM_WININICHANGE:
1481 case WM_DEVMODECHANGE:
1482 case WM_ASKCBFORMATNAME:
1483 *plparam = (LPARAM)MapSL(*plparam);
1484 return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, pwparam32, plparam );
1485 case WM_GETTEXTLENGTH:
1486 case CB_GETLBTEXTLEN:
1487 case LB_GETTEXTLEN:
1488 return 1; /* need to map result */
1489 case WM_NCCREATE:
1490 case WM_CREATE:
1492 CREATESTRUCT16 *cs16 = MapSL(*plparam);
1493 CREATESTRUCTW *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1494 if (!cs) return -1;
1495 CREATESTRUCT16to32A( cs16, (CREATESTRUCTA *)cs );
1496 cs->lpszName = map_str_16_to_32W(cs16->lpszName);
1497 cs->lpszClass = map_str_16_to_32W(cs16->lpszClass);
1499 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1501 MDICREATESTRUCT16 *mdi_cs16;
1502 MDICREATESTRUCTW *mdi_cs = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs));
1503 if (!mdi_cs)
1505 HeapFree(GetProcessHeap(), 0, cs);
1506 return -1;
1508 mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs16->lpCreateParams);
1509 MDICREATESTRUCT16to32A(mdi_cs16, (MDICREATESTRUCTA *)mdi_cs);
1510 mdi_cs->szTitle = map_str_16_to_32W(mdi_cs16->szTitle);
1511 mdi_cs->szClass = map_str_16_to_32W(mdi_cs16->szClass);
1513 cs->lpCreateParams = mdi_cs;
1515 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1516 *plparam = (LPARAM)cs;
1518 return 1;
1519 case WM_MDICREATE:
1521 MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1522 MDICREATESTRUCTW *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1523 if (!cs) return -1;
1524 MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCTA *)cs );
1525 cs->szTitle = map_str_16_to_32W(cs16->szTitle);
1526 cs->szClass = map_str_16_to_32W(cs16->szClass);
1527 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1528 *plparam = (LPARAM)cs;
1530 return 1;
1531 case WM_GETDLGCODE:
1532 if (*plparam)
1534 LPMSG16 msg16 = MapSL(*plparam);
1535 LPMSG msg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1537 if (!msg32) return -1;
1538 msg32->hwnd = WIN_Handle32( msg16->hwnd );
1539 msg32->message = msg16->message;
1540 msg32->wParam = msg16->wParam;
1541 msg32->lParam = msg16->lParam;
1542 msg32->time = msg16->time;
1543 msg32->pt.x = msg16->pt.x;
1544 msg32->pt.y = msg16->pt.y;
1545 switch(msg32->message)
1547 case WM_CHAR:
1548 case WM_DEADCHAR:
1549 case WM_SYSCHAR:
1550 case WM_SYSDEADCHAR:
1551 msg32->wParam = map_wparam_char_AtoW( msg16->wParam, 1 );
1552 break;
1554 *plparam = (LPARAM)msg32;
1555 return 1;
1557 else return 0;
1559 case WM_CHARTOITEM:
1560 *pwparam32 = MAKEWPARAM( map_wparam_char_AtoW( wParam16, 1 ), HIWORD(*plparam) );
1561 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1562 return 0;
1563 case WM_MENUCHAR:
1564 *pwparam32 = MAKEWPARAM( map_wparam_char_AtoW( wParam16, 1 ), LOWORD(*plparam) );
1565 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1566 return 0;
1567 case WM_CHAR:
1568 case WM_DEADCHAR:
1569 case WM_SYSCHAR:
1570 case WM_SYSDEADCHAR:
1571 *pwparam32 = map_wparam_char_AtoW( wParam16, 1 );
1572 return 0;
1573 case WM_IME_CHAR:
1574 *pwparam32 = map_wparam_char_AtoW( wParam16, 2 );
1575 return 0;
1577 default: /* No Unicode translation needed */
1578 return WINPROC_MapMsg16To32A( hwnd, msg16, wParam16, pmsg32,
1579 pwparam32, plparam );
1584 /**********************************************************************
1585 * WINPROC_UnmapMsg16To32W
1587 * Unmap a message that was mapped from 16- to 32-bit Unicode.
1589 static LRESULT WINPROC_UnmapMsg16To32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1590 LRESULT result, WNDPROC dispatch )
1592 switch(msg)
1594 case WM_GETTEXT:
1595 case WM_SETTEXT:
1596 case WM_GETTEXTLENGTH:
1597 case CB_GETLBTEXTLEN:
1598 case LB_GETTEXTLEN:
1599 case WM_ASKCBFORMATNAME:
1600 return WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result, dispatch );
1601 case WM_NCCREATE:
1602 case WM_CREATE:
1604 CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
1605 lParam = *(LPARAM *)(cs + 1);
1606 CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs, MapSL(lParam) );
1607 unmap_str_16_to_32W( cs->lpszName );
1608 unmap_str_16_to_32W( cs->lpszClass );
1610 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1612 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)cs->lpCreateParams;
1613 unmap_str_16_to_32W( mdi_cs->szTitle );
1614 unmap_str_16_to_32W( mdi_cs->szClass );
1615 HeapFree(GetProcessHeap(), 0, cs->lpCreateParams);
1617 HeapFree( GetProcessHeap(), 0, cs );
1619 break;
1620 case WM_MDICREATE:
1622 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
1623 lParam = *(LPARAM *)(cs + 1);
1624 MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs, MapSL(lParam) );
1625 unmap_str_16_to_32W( cs->szTitle );
1626 unmap_str_16_to_32W( cs->szClass );
1627 HeapFree( GetProcessHeap(), 0, cs );
1629 break;
1630 case WM_GETDLGCODE:
1631 if (lParam)
1633 LPMSG msg32 = (LPMSG)lParam;
1634 HeapFree( GetProcessHeap(), 0, msg32 );
1636 break;
1637 default:
1638 return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1640 return result;
1643 static HANDLE16 convert_handle_32_to_16(UINT src, unsigned int flags)
1645 HANDLE16 dst;
1646 UINT sz = GlobalSize((HANDLE)src);
1647 LPSTR ptr16, ptr32;
1649 if (!(dst = GlobalAlloc16(flags, sz)))
1650 return 0;
1651 ptr32 = GlobalLock((HANDLE)src);
1652 ptr16 = GlobalLock16(dst);
1653 if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr16, ptr32, sz);
1654 GlobalUnlock((HANDLE)src);
1655 GlobalUnlock16(dst);
1657 return dst;
1661 /**********************************************************************
1662 * WINPROC_MapMsg32ATo16
1664 * Map a message from 32-bit Ansi to 16-bit.
1665 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1667 INT WINPROC_MapMsg32ATo16( HWND hwnd, UINT msg32, WPARAM wParam32,
1668 UINT16 *pmsg16, WPARAM16 *pwparam16,
1669 LPARAM *plparam )
1671 *pmsg16 = (UINT16)msg32;
1672 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1673 switch(msg32)
1675 case SBM_SETRANGE:
1676 *pmsg16 = SBM_SETRANGE16;
1677 *plparam = MAKELPARAM(wParam32, *plparam);
1678 *pwparam16 = 0;
1679 return 0;
1681 case SBM_GETRANGE:
1682 *pmsg16 = SBM_GETRANGE16;
1683 return 1;
1685 case BM_GETCHECK:
1686 case BM_SETCHECK:
1687 case BM_GETSTATE:
1688 case BM_SETSTATE:
1689 case BM_SETSTYLE:
1690 *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK);
1691 return 0;
1693 case EM_GETSEL:
1694 case EM_GETRECT:
1695 case EM_SETRECT:
1696 case EM_SETRECTNP:
1697 case EM_SCROLL:
1698 case EM_LINESCROLL:
1699 case EM_SCROLLCARET:
1700 case EM_GETMODIFY:
1701 case EM_SETMODIFY:
1702 case EM_GETLINECOUNT:
1703 case EM_LINEINDEX:
1704 case EM_SETHANDLE:
1705 case EM_GETHANDLE:
1706 case EM_GETTHUMB:
1707 case EM_LINELENGTH:
1708 case EM_REPLACESEL:
1709 case EM_GETLINE:
1710 case EM_LIMITTEXT:
1711 case EM_CANUNDO:
1712 case EM_UNDO:
1713 case EM_FMTLINES:
1714 case EM_LINEFROMCHAR:
1715 case EM_SETTABSTOPS:
1716 case EM_SETPASSWORDCHAR:
1717 case EM_EMPTYUNDOBUFFER:
1718 case EM_GETFIRSTVISIBLELINE:
1719 case EM_SETREADONLY:
1720 case EM_SETWORDBREAKPROC:
1721 case EM_GETWORDBREAKPROC:
1722 case EM_GETPASSWORDCHAR:
1723 *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL);
1724 return 0;
1726 case LB_CARETOFF:
1727 case LB_CARETON:
1728 case LB_DELETESTRING:
1729 case LB_GETANCHORINDEX:
1730 case LB_GETCARETINDEX:
1731 case LB_GETCOUNT:
1732 case LB_GETCURSEL:
1733 case LB_GETHORIZONTALEXTENT:
1734 case LB_GETITEMDATA:
1735 case LB_GETITEMHEIGHT:
1736 case LB_GETSEL:
1737 case LB_GETSELCOUNT:
1738 case LB_GETTEXTLEN:
1739 case LB_GETTOPINDEX:
1740 case LB_RESETCONTENT:
1741 case LB_SELITEMRANGE:
1742 case LB_SELITEMRANGEEX:
1743 case LB_SETANCHORINDEX:
1744 case LB_SETCARETINDEX:
1745 case LB_SETCOLUMNWIDTH:
1746 case LB_SETCURSEL:
1747 case LB_SETHORIZONTALEXTENT:
1748 case LB_SETITEMDATA:
1749 case LB_SETITEMHEIGHT:
1750 case LB_SETSEL:
1751 case LB_SETTOPINDEX:
1752 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1753 return 0;
1754 case CB_DELETESTRING:
1755 case CB_GETCOUNT:
1756 case CB_GETLBTEXTLEN:
1757 case CB_LIMITTEXT:
1758 case CB_RESETCONTENT:
1759 case CB_SETEDITSEL:
1760 case CB_GETCURSEL:
1761 case CB_SETCURSEL:
1762 case CB_SHOWDROPDOWN:
1763 case CB_SETITEMDATA:
1764 case CB_SETITEMHEIGHT:
1765 case CB_GETITEMHEIGHT:
1766 case CB_SETEXTENDEDUI:
1767 case CB_GETEXTENDEDUI:
1768 case CB_GETDROPPEDSTATE:
1769 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1770 return 0;
1771 case CB_GETEDITSEL:
1772 *pmsg16 = CB_GETEDITSEL16;
1773 return 1;
1775 case LB_ADDSTRING:
1776 case LB_FINDSTRING:
1777 case LB_FINDSTRINGEXACT:
1778 case LB_INSERTSTRING:
1779 case LB_SELECTSTRING:
1780 case LB_DIR:
1781 case LB_ADDFILE:
1782 *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1783 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1784 return 1;
1786 case CB_ADDSTRING:
1787 case CB_FINDSTRING:
1788 case CB_FINDSTRINGEXACT:
1789 case CB_INSERTSTRING:
1790 case CB_SELECTSTRING:
1791 case CB_DIR:
1792 *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1793 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1794 return 1;
1796 case LB_GETITEMRECT:
1798 RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1799 if (!rect) return -1;
1800 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1801 *plparam = MapLS( rect );
1803 *pmsg16 = LB_GETITEMRECT16;
1804 return 1;
1805 case LB_GETSELITEMS:
1807 LPARAM *items; /* old LPARAM first, then *pwparam16 x INT16 entries */
1809 *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1810 if (!(items = HeapAlloc( GetProcessHeap(), 0,
1811 *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
1812 *items++ = *plparam; /* Store the previous lParam */
1813 *plparam = MapLS( items );
1815 *pmsg16 = LB_GETSELITEMS16;
1816 return 1;
1817 case LB_SETTABSTOPS:
1818 if (wParam32)
1820 INT i;
1821 LPINT16 stops;
1822 *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1823 if (!(stops = HeapAlloc( GetProcessHeap(), 0,
1824 *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
1825 for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT)*plparam+i);
1826 *plparam = MapLS( stops );
1827 return 1;
1829 *pmsg16 = LB_SETTABSTOPS16;
1830 return 0;
1832 case CB_GETDROPPEDCONTROLRECT:
1834 RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1835 if (!rect) return -1;
1836 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1837 *plparam = (LPARAM)MapLS(rect);
1839 *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
1840 return 1;
1842 case LB_GETTEXT:
1843 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1844 *pmsg16 = LB_GETTEXT16;
1845 return 1;
1847 case CB_GETLBTEXT:
1848 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1849 *pmsg16 = CB_GETLBTEXT16;
1850 return 1;
1852 case EM_SETSEL:
1853 *pwparam16 = 0;
1854 *plparam = MAKELONG( (INT16)(INT)wParam32, (INT16)*plparam );
1855 *pmsg16 = EM_SETSEL16;
1856 return 0;
1858 case WM_ACTIVATE:
1859 case WM_CHARTOITEM:
1860 case WM_COMMAND:
1861 case WM_VKEYTOITEM:
1862 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
1863 return 0;
1864 case WM_HSCROLL:
1865 case WM_VSCROLL:
1866 *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
1867 return 0;
1868 case WM_COPYDATA:
1870 PCOPYDATASTRUCT pcds32 = (PCOPYDATASTRUCT) *plparam;
1871 PCOPYDATASTRUCT16 pcds = HeapAlloc( GetProcessHeap(), 0, sizeof( *pcds));
1872 pcds->dwData = pcds32->dwData;
1873 pcds->cbData = pcds32->cbData;
1874 pcds->lpData = MapLS( pcds32->lpData);
1875 *plparam = MapLS( pcds );
1877 return 1;
1878 case WM_CTLCOLORMSGBOX:
1879 case WM_CTLCOLOREDIT:
1880 case WM_CTLCOLORLISTBOX:
1881 case WM_CTLCOLORBTN:
1882 case WM_CTLCOLORDLG:
1883 case WM_CTLCOLORSCROLLBAR:
1884 case WM_CTLCOLORSTATIC:
1885 *pmsg16 = WM_CTLCOLOR;
1886 *plparam = MAKELPARAM( (HWND16)*plparam,
1887 (WORD)msg32 - WM_CTLCOLORMSGBOX );
1888 return 0;
1889 case WM_COMPAREITEM:
1891 COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)*plparam;
1892 COMPAREITEMSTRUCT16 *cis = HeapAlloc( GetProcessHeap(), 0, sizeof(COMPAREITEMSTRUCT16));
1893 if (!cis) return -1;
1894 cis->CtlType = (UINT16)cis32->CtlType;
1895 cis->CtlID = (UINT16)cis32->CtlID;
1896 cis->hwndItem = HWND_16( cis32->hwndItem );
1897 cis->itemID1 = (UINT16)cis32->itemID1;
1898 cis->itemData1 = cis32->itemData1;
1899 cis->itemID2 = (UINT16)cis32->itemID2;
1900 cis->itemData2 = cis32->itemData2;
1901 *plparam = MapLS( cis );
1903 return 1;
1904 case WM_DELETEITEM:
1906 DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)*plparam;
1907 DELETEITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DELETEITEMSTRUCT16) );
1908 if (!dis) return -1;
1909 dis->CtlType = (UINT16)dis32->CtlType;
1910 dis->CtlID = (UINT16)dis32->CtlID;
1911 dis->itemID = (UINT16)dis32->itemID;
1912 dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem)
1913 : HWND_16( dis32->hwndItem );
1914 dis->itemData = dis32->itemData;
1915 *plparam = MapLS( dis );
1917 return 1;
1918 case WM_DRAWITEM:
1920 DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)*plparam;
1921 DRAWITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DRAWITEMSTRUCT16) );
1922 if (!dis) return -1;
1923 dis->CtlType = (UINT16)dis32->CtlType;
1924 dis->CtlID = (UINT16)dis32->CtlID;
1925 dis->itemID = (UINT16)dis32->itemID;
1926 dis->itemAction = (UINT16)dis32->itemAction;
1927 dis->itemState = (UINT16)dis32->itemState;
1928 dis->hwndItem = HWND_16( dis32->hwndItem );
1929 dis->hDC = HDC_16(dis32->hDC);
1930 dis->itemData = dis32->itemData;
1931 dis->rcItem.left = dis32->rcItem.left;
1932 dis->rcItem.top = dis32->rcItem.top;
1933 dis->rcItem.right = dis32->rcItem.right;
1934 dis->rcItem.bottom = dis32->rcItem.bottom;
1935 *plparam = MapLS( dis );
1937 return 1;
1938 case WM_MEASUREITEM:
1940 MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)*plparam;
1941 MEASUREITEMSTRUCT16 *mis = HeapAlloc( GetProcessHeap(), 0, sizeof(*mis)+sizeof(LPARAM));
1942 if (!mis) return -1;
1943 mis->CtlType = (UINT16)mis32->CtlType;
1944 mis->CtlID = (UINT16)mis32->CtlID;
1945 mis->itemID = (UINT16)mis32->itemID;
1946 mis->itemWidth = (UINT16)mis32->itemWidth;
1947 mis->itemHeight = (UINT16)mis32->itemHeight;
1948 mis->itemData = mis32->itemData;
1949 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
1950 *plparam = MapLS( mis );
1952 return 1;
1953 case WM_GETMINMAXINFO:
1955 MINMAXINFO16 *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM) );
1956 if (!mmi) return -1;
1957 MINMAXINFO32to16( (MINMAXINFO *)*plparam, mmi );
1958 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
1959 *plparam = MapLS( mmi );
1961 return 1;
1962 case WM_GETTEXT:
1963 case WM_ASKCBFORMATNAME:
1965 LPARAM *str; /* store LPARAM, then *pwparam16 char space */
1966 *pwparam16 = (WPARAM16)min( wParam32, 0xff80 ); /* Must be < 64K */
1967 if (!(str = HeapAlloc( GetProcessHeap(), 0, *pwparam16 + sizeof(LPARAM)))) return -1;
1968 *str++ = *plparam; /* Store the previous lParam */
1969 *plparam = MapLS( str );
1971 return 1;
1972 case WM_MDICREATE:
1974 MDICREATESTRUCT16 *cs;
1975 MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)*plparam;
1977 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
1978 MDICREATESTRUCT32Ato16( cs32, cs );
1979 cs->szTitle = MapLS( cs32->szTitle );
1980 cs->szClass = MapLS( cs32->szClass );
1981 *plparam = MapLS( cs );
1983 return 1;
1984 case WM_MDIGETACTIVE:
1985 return 1;
1986 case WM_MDISETMENU:
1987 *plparam = MAKELPARAM( (HMENU16)LOWORD(wParam32),
1988 (HMENU16)LOWORD(*plparam) );
1989 *pwparam16 = (*plparam == 0);
1990 return 0;
1991 case WM_MENUSELECT:
1992 if(HIWORD(wParam32) & MF_POPUP)
1994 HMENU hmenu;
1995 if (((UINT)HIWORD(wParam32) != 0xFFFF) || (*plparam))
1997 if((hmenu = GetSubMenu((HMENU)*plparam, *pwparam16)))
1998 *pwparam16=HMENU_16(hmenu);
2001 /* fall through */
2002 case WM_MENUCHAR:
2003 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2004 return 0;
2005 case WM_MDIACTIVATE:
2006 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
2008 *pwparam16 = ((HWND)*plparam == hwnd);
2009 *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
2010 (HWND16)LOWORD(wParam32) );
2012 else
2014 *pwparam16 = HWND_16( (HWND)wParam32 );
2015 *plparam = 0;
2017 return 0;
2018 case WM_NCCALCSIZE:
2020 NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)*plparam;
2021 NCCALCSIZE_PARAMS16 *nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM));
2022 if (!nc) return -1;
2024 nc->rgrc[0].left = nc32->rgrc[0].left;
2025 nc->rgrc[0].top = nc32->rgrc[0].top;
2026 nc->rgrc[0].right = nc32->rgrc[0].right;
2027 nc->rgrc[0].bottom = nc32->rgrc[0].bottom;
2028 if (wParam32)
2030 WINDOWPOS16 *wp;
2031 nc->rgrc[1].left = nc32->rgrc[1].left;
2032 nc->rgrc[1].top = nc32->rgrc[1].top;
2033 nc->rgrc[1].right = nc32->rgrc[1].right;
2034 nc->rgrc[1].bottom = nc32->rgrc[1].bottom;
2035 nc->rgrc[2].left = nc32->rgrc[2].left;
2036 nc->rgrc[2].top = nc32->rgrc[2].top;
2037 nc->rgrc[2].right = nc32->rgrc[2].right;
2038 nc->rgrc[2].bottom = nc32->rgrc[2].bottom;
2039 if (!(wp = HeapAlloc( GetProcessHeap(), 0, sizeof(WINDOWPOS16) )))
2041 HeapFree( GetProcessHeap(), 0, nc );
2042 return -1;
2044 WINDOWPOS32to16( nc32->lppos, wp );
2045 nc->lppos = MapLS( wp );
2047 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
2048 *plparam = MapLS( nc );
2050 return 1;
2051 case WM_NCCREATE:
2052 case WM_CREATE:
2054 CREATESTRUCT16 *cs;
2055 CREATESTRUCTA *cs32 = (CREATESTRUCTA *)*plparam;
2057 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2058 CREATESTRUCT32Ato16( cs32, cs );
2059 cs->lpszName = MapLS( cs32->lpszName );
2060 cs->lpszClass = MapLS( cs32->lpszClass );
2062 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2064 MDICREATESTRUCT16 *mdi_cs16;
2065 MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs32->lpCreateParams;
2066 mdi_cs16 = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs16));
2067 if (!mdi_cs16)
2069 HeapFree(GetProcessHeap(), 0, cs);
2070 return -1;
2072 MDICREATESTRUCT32Ato16(mdi_cs, mdi_cs16);
2073 mdi_cs16->szTitle = MapLS( mdi_cs->szTitle );
2074 mdi_cs16->szClass = MapLS( mdi_cs->szClass );
2075 cs->lpCreateParams = MapLS( mdi_cs16 );
2077 *plparam = MapLS( cs );
2079 return 1;
2080 case WM_PARENTNOTIFY:
2081 if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
2082 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
2083 /* else nothing to do */
2084 return 0;
2085 case WM_NOTIFY:
2086 *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
2087 return 1;
2088 case WM_SETTEXT:
2089 case WM_WININICHANGE:
2090 case WM_DEVMODECHANGE:
2091 *plparam = MapLS( (LPSTR)*plparam );
2092 return 1;
2093 case WM_WINDOWPOSCHANGING:
2094 case WM_WINDOWPOSCHANGED:
2096 WINDOWPOS16 *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
2097 if (!wp) return -1;
2098 WINDOWPOS32to16( (WINDOWPOS *)*plparam, wp );
2099 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
2100 *plparam = MapLS( wp );
2102 return 1;
2103 case WM_GETDLGCODE:
2104 if (*plparam) {
2105 LPMSG msg32 = (LPMSG) *plparam;
2106 LPMSG16 msg16 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG16) );
2108 if (!msg16) return -1;
2109 msg16->hwnd = HWND_16( msg32->hwnd );
2110 msg16->message = msg32->message;
2111 msg16->wParam = msg32->wParam;
2112 msg16->lParam = msg32->lParam;
2113 msg16->time = msg32->time;
2114 msg16->pt.x = msg32->pt.x;
2115 msg16->pt.y = msg32->pt.y;
2116 *plparam = MapLS( msg16 );
2117 return 1;
2119 return 0;
2121 case WM_ACTIVATEAPP:
2122 if (*plparam) *plparam = HTASK_16( (HANDLE)*plparam );
2123 return 0;
2124 case WM_NEXTMENU:
2126 MDINEXTMENU *next = (MDINEXTMENU *)*plparam;
2127 *plparam = (LPARAM)next->hmenuIn;
2128 return 1;
2130 case WM_PAINT:
2131 if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON ))
2133 *pmsg16 = WM_PAINTICON;
2134 *pwparam16 = 1;
2136 return 0;
2137 case WM_ERASEBKGND:
2138 if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON ))
2139 *pmsg16 = WM_ICONERASEBKGND;
2140 return 0;
2141 case WM_PAINTCLIPBOARD:
2142 case WM_SIZECLIPBOARD:
2143 FIXME_(msg)("message %04x needs translation\n", msg32 );
2144 return -1;
2145 /* following messages should not be sent to 16-bit apps */
2146 case WM_SIZING:
2147 case WM_MOVING:
2148 case WM_CAPTURECHANGED:
2149 case WM_STYLECHANGING:
2150 case WM_STYLECHANGED:
2151 return -1;
2152 case WM_DDE_INITIATE:
2153 case WM_DDE_TERMINATE:
2154 case WM_DDE_UNADVISE:
2155 case WM_DDE_REQUEST:
2156 *pwparam16 = HWND_16((HWND)wParam32);
2157 return 0;
2158 case WM_DDE_ADVISE:
2159 case WM_DDE_DATA:
2160 case WM_DDE_POKE:
2162 UINT_PTR lo32, hi;
2163 HANDLE16 lo16 = 0;
2165 *pwparam16 = HWND_16((HWND)wParam32);
2166 UnpackDDElParam(msg32, *plparam, &lo32, &hi);
2167 if (lo32 && !(lo16 = convert_handle_32_to_16(lo32, GMEM_DDESHARE)))
2168 return -1;
2169 *plparam = MAKELPARAM(lo16, hi);
2171 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2172 case WM_DDE_ACK:
2174 UINT_PTR lo, hi;
2175 int flag = 0;
2176 char buf[2];
2178 *pwparam16 = HWND_16((HWND)wParam32);
2180 UnpackDDElParam(msg32, *plparam, &lo, &hi);
2182 if (GlobalGetAtomNameA((ATOM)hi, buf, sizeof(buf)) > 0) flag |= 1;
2183 if (GlobalSize((HANDLE)hi) != 0) flag |= 2;
2184 switch (flag)
2186 case 0:
2187 if (hi)
2189 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
2190 hi = 0;
2192 break;
2193 case 1:
2194 break; /* atom, nothing to do */
2195 case 3:
2196 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
2197 /* fall thru */
2198 case 2:
2199 hi = convert_handle_32_to_16(hi, GMEM_DDESHARE);
2200 break;
2202 *plparam = MAKELPARAM(lo, hi);
2204 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2205 case WM_DDE_EXECUTE:
2206 *plparam = convert_handle_32_to_16(*plparam, GMEM_DDESHARE);
2207 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2208 default: /* No translation needed */
2209 return 0;
2214 /**********************************************************************
2215 * WINPROC_UnmapMsg32ATo16
2217 * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
2219 static void WINPROC_UnmapMsg32ATo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2220 WPARAM16 wParam16, LPARAM lParam16, LRESULT *result )
2222 switch(msg)
2224 case SBM_GETRANGE:
2225 *(LPINT)wParam = LOWORD(*result);
2226 *(LPINT)lParam = HIWORD(*result);
2227 break;
2229 case LB_ADDFILE:
2230 case LB_ADDSTRING:
2231 case LB_DIR:
2232 case LB_FINDSTRING:
2233 case LB_FINDSTRINGEXACT:
2234 case LB_INSERTSTRING:
2235 case LB_SELECTSTRING:
2236 case LB_GETTEXT:
2237 case CB_ADDSTRING:
2238 case CB_FINDSTRING:
2239 case CB_FINDSTRINGEXACT:
2240 case CB_INSERTSTRING:
2241 case CB_SELECTSTRING:
2242 case CB_DIR:
2243 case CB_GETLBTEXT:
2244 case WM_SETTEXT:
2245 case WM_WININICHANGE:
2246 case WM_DEVMODECHANGE:
2247 UnMapLS( (SEGPTR)lParam16 );
2248 break;
2249 case LB_SETTABSTOPS:
2250 case WM_COMPAREITEM:
2251 case WM_DELETEITEM:
2252 case WM_DRAWITEM:
2254 void *ptr = MapSL( lParam16 );
2255 UnMapLS( lParam16 );
2256 HeapFree( GetProcessHeap(), 0, ptr );
2258 break;
2259 case WM_COPYDATA:
2261 PCOPYDATASTRUCT16 pcds = MapSL( lParam16 );
2262 UnMapLS( lParam16 );
2263 UnMapLS( pcds->lpData );
2264 HeapFree( GetProcessHeap(), 0, pcds );
2266 break;
2267 case CB_GETDROPPEDCONTROLRECT:
2268 case LB_GETITEMRECT:
2270 RECT *r32;
2271 RECT16 *rect = MapSL(lParam16);
2272 UnMapLS( lParam16 );
2273 lParam16 = *(LPARAM *)(rect + 1);
2274 r32 = (RECT *)lParam16;
2275 r32->left = rect->left;
2276 r32->top = rect->top;
2277 r32->right = rect->right;
2278 r32->bottom = rect->bottom;
2279 HeapFree( GetProcessHeap(), 0, rect );
2281 break;
2282 case LB_GETSELITEMS:
2284 INT i;
2285 LPINT16 items = MapSL(lParam16);
2286 UnMapLS( lParam16 );
2287 lParam16 = *((LPARAM *)items - 1);
2288 for (i = 0; i < wParam16; i++) *((LPINT)lParam16 + i) = items[i];
2289 HeapFree( GetProcessHeap(), 0, (LPARAM *)items - 1 );
2291 break;
2293 case CB_GETEDITSEL:
2294 if( wParam )
2295 *((PUINT)(wParam)) = LOWORD(*result);
2296 if( lParam )
2297 *((PUINT)(lParam)) = HIWORD(*result); /* FIXME: substract 1? */
2298 break;
2300 case WM_MEASUREITEM:
2302 MEASUREITEMSTRUCT16 *mis = MapSL(lParam16);
2303 MEASUREITEMSTRUCT *mis32 = *(MEASUREITEMSTRUCT **)(mis + 1);
2304 mis32->itemWidth = mis->itemWidth;
2305 mis32->itemHeight = mis->itemHeight;
2306 UnMapLS( lParam16 );
2307 HeapFree( GetProcessHeap(), 0, mis );
2309 break;
2310 case WM_GETMINMAXINFO:
2312 MINMAXINFO16 *mmi = MapSL(lParam16);
2313 UnMapLS( lParam16 );
2314 lParam16 = *(LPARAM *)(mmi + 1);
2315 MINMAXINFO16to32( mmi, (MINMAXINFO *)lParam16 );
2316 HeapFree( GetProcessHeap(), 0, mmi );
2318 break;
2319 case WM_GETTEXT:
2320 case WM_ASKCBFORMATNAME:
2322 LPSTR str = MapSL(lParam16);
2323 UnMapLS( lParam16 );
2324 lParam16 = *((LPARAM *)str - 1);
2325 lstrcpynA( (LPSTR)lParam16, str, wParam16 );
2326 HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2328 break;
2329 case WM_MDICREATE:
2331 MDICREATESTRUCT16 *cs = MapSL(lParam16);
2332 UnMapLS( cs->szTitle );
2333 UnMapLS( cs->szClass );
2334 UnMapLS( lParam16 );
2335 HeapFree( GetProcessHeap(), 0, cs );
2337 break;
2338 case WM_MDIGETACTIVE:
2339 if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(*result);
2340 *result = (LRESULT)WIN_Handle32( LOWORD(*result) );
2341 break;
2342 case WM_NCCALCSIZE:
2344 NCCALCSIZE_PARAMS *nc32;
2345 NCCALCSIZE_PARAMS16 *nc = MapSL(lParam16);
2346 UnMapLS( lParam16 );
2347 lParam16 = *(LPARAM *)(nc + 1);
2348 nc32 = (NCCALCSIZE_PARAMS *)lParam16;
2349 nc32->rgrc[0].left = nc->rgrc[0].left;
2350 nc32->rgrc[0].top = nc->rgrc[0].top;
2351 nc32->rgrc[0].right = nc->rgrc[0].right;
2352 nc32->rgrc[0].bottom = nc->rgrc[0].bottom;
2353 if (wParam16)
2355 WINDOWPOS16 *pos = MapSL(nc->lppos);
2356 UnMapLS( nc->lppos );
2357 nc32->rgrc[1].left = nc->rgrc[1].left;
2358 nc32->rgrc[1].top = nc->rgrc[1].top;
2359 nc32->rgrc[1].right = nc->rgrc[1].right;
2360 nc32->rgrc[1].bottom = nc->rgrc[1].bottom;
2361 nc32->rgrc[2].left = nc->rgrc[2].left;
2362 nc32->rgrc[2].top = nc->rgrc[2].top;
2363 nc32->rgrc[2].right = nc->rgrc[2].right;
2364 nc32->rgrc[2].bottom = nc->rgrc[2].bottom;
2365 WINDOWPOS16to32( pos, nc32->lppos );
2366 HeapFree( GetProcessHeap(), 0, pos );
2368 HeapFree( GetProcessHeap(), 0, nc );
2370 break;
2371 case WM_NCCREATE:
2372 case WM_CREATE:
2374 CREATESTRUCT16 *cs = MapSL(lParam16);
2375 UnMapLS( lParam16 );
2376 UnMapLS( cs->lpszName );
2377 UnMapLS( cs->lpszClass );
2378 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2380 MDICREATESTRUCT16 *mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs->lpCreateParams);
2381 UnMapLS( cs->lpCreateParams );
2382 UnMapLS( mdi_cs16->szTitle );
2383 UnMapLS( mdi_cs16->szClass );
2384 HeapFree(GetProcessHeap(), 0, mdi_cs16);
2386 HeapFree( GetProcessHeap(), 0, cs );
2388 break;
2389 case WM_WINDOWPOSCHANGING:
2390 case WM_WINDOWPOSCHANGED:
2392 WINDOWPOS16 *wp = MapSL(lParam16);
2393 UnMapLS( lParam16 );
2394 lParam16 = *(LPARAM *)(wp + 1);
2395 WINDOWPOS16to32( wp, (WINDOWPOS *)lParam16 );
2396 HeapFree( GetProcessHeap(), 0, wp );
2398 break;
2399 case WM_NOTIFY:
2400 UnMapLS(lParam16);
2401 break;
2402 case WM_GETDLGCODE:
2403 if (lParam16)
2405 LPMSG16 msg16 = MapSL(lParam16);
2406 UnMapLS( lParam16 );
2407 HeapFree( GetProcessHeap(), 0, msg16 );
2409 break;
2410 case WM_NEXTMENU:
2412 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
2413 next->hmenuNext = HMENU_32( LOWORD(*result) );
2414 next->hwndNext = WIN_Handle32( HIWORD(*result) );
2415 *result = 0;
2417 break;
2422 /**********************************************************************
2423 * WINPROC_MapMsg32WTo16
2425 * Map a message from 32-bit Unicode to 16-bit.
2426 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
2428 static INT WINPROC_MapMsg32WTo16( HWND hwnd, UINT msg32, WPARAM wParam32,
2429 UINT16 *pmsg16, WPARAM16 *pwparam16, LPARAM *plparam )
2431 *pmsg16 = LOWORD(msg32);
2432 *pwparam16 = LOWORD(wParam32);
2433 switch(msg32)
2435 case LB_ADDSTRING:
2436 case LB_FINDSTRING:
2437 case LB_FINDSTRINGEXACT:
2438 case LB_INSERTSTRING:
2439 case LB_SELECTSTRING:
2440 case LB_DIR:
2441 case LB_ADDFILE:
2442 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2443 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2444 return 1;
2446 case CB_ADDSTRING:
2447 case CB_FINDSTRING:
2448 case CB_FINDSTRINGEXACT:
2449 case CB_INSERTSTRING:
2450 case CB_SELECTSTRING:
2451 case CB_DIR:
2452 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2453 *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING);
2454 return 1;
2456 case WM_NCCREATE:
2457 case WM_CREATE:
2459 CREATESTRUCT16 *cs;
2460 CREATESTRUCTW *cs32 = (CREATESTRUCTW *)*plparam;
2462 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2463 CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs32, cs );
2464 cs->lpszName = map_str_32W_to_16( cs32->lpszName );
2465 cs->lpszClass = map_str_32W_to_16( cs32->lpszClass );
2467 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2469 MDICREATESTRUCT16 *mdi_cs16;
2470 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)cs32->lpCreateParams;
2471 mdi_cs16 = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs16));
2472 if (!mdi_cs16)
2474 HeapFree(GetProcessHeap(), 0, cs);
2475 return -1;
2477 MDICREATESTRUCT32Ato16((MDICREATESTRUCTA *)mdi_cs, mdi_cs16);
2478 mdi_cs16->szTitle = map_str_32W_to_16(mdi_cs->szTitle);
2479 mdi_cs16->szClass = map_str_32W_to_16(mdi_cs->szClass);
2480 cs->lpCreateParams = MapLS(mdi_cs16);
2482 *plparam = MapLS(cs);
2484 return 1;
2485 case WM_MDICREATE:
2487 MDICREATESTRUCT16 *cs;
2488 MDICREATESTRUCTW *cs32 = (MDICREATESTRUCTW *)*plparam;
2490 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2491 MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs32, cs );
2492 cs->szTitle = map_str_32W_to_16( cs32->szTitle );
2493 cs->szClass = map_str_32W_to_16( cs32->szClass );
2494 *plparam = MapLS(cs);
2496 return 1;
2497 case WM_SETTEXT:
2498 case WM_WININICHANGE:
2499 case WM_DEVMODECHANGE:
2500 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2501 return 1;
2502 case LB_GETTEXT:
2503 case CB_GETLBTEXT:
2504 if ( WINPROC_TestLBForStr( hwnd, msg32 ))
2506 LPSTR str = HeapAlloc( GetProcessHeap(), 0, 512 ); /* FIXME: fixed sized buffer */
2507 if (!str) return -1;
2508 *pmsg16 = (msg32 == LB_GETTEXT) ? LB_GETTEXT16 : CB_GETLBTEXT16;
2509 *plparam = (LPARAM)MapLS(str);
2511 return 1;
2513 case WM_CHARTOITEM:
2514 *pwparam16 = map_wparam_char_WtoA( wParam32, 1 );
2515 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2516 return 0;
2517 case WM_MENUCHAR:
2518 *pwparam16 = map_wparam_char_WtoA( wParam32, 1 );
2519 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2520 return 0;
2521 case WM_CHAR:
2522 case WM_DEADCHAR:
2523 case WM_SYSCHAR:
2524 case WM_SYSDEADCHAR:
2525 *pwparam16 = map_wparam_char_WtoA( wParam32, 1 );
2526 return 0;
2527 case WM_IME_CHAR:
2528 *pwparam16 = map_wparam_char_WtoA( wParam32, 2 );
2529 return 0;
2531 default: /* No Unicode translation needed (?) */
2532 return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2533 pwparam16, plparam );
2538 /**********************************************************************
2539 * WINPROC_UnmapMsg32WTo16
2541 * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2543 static void WINPROC_UnmapMsg32WTo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2544 WPARAM16 wParam16, LPARAM lParam16, LRESULT *result )
2546 switch(msg)
2548 case LB_ADDSTRING:
2549 case LB_FINDSTRING:
2550 case LB_FINDSTRINGEXACT:
2551 case LB_INSERTSTRING:
2552 case LB_SELECTSTRING:
2553 case LB_DIR:
2554 case LB_ADDFILE:
2555 case CB_ADDSTRING:
2556 case CB_FINDSTRING:
2557 case CB_FINDSTRINGEXACT:
2558 case CB_INSERTSTRING:
2559 case CB_SELECTSTRING:
2560 case CB_DIR:
2561 case WM_SETTEXT:
2562 case WM_WININICHANGE:
2563 case WM_DEVMODECHANGE:
2564 unmap_str_32W_to_16( lParam16 );
2565 break;
2566 case WM_NCCREATE:
2567 case WM_CREATE:
2569 CREATESTRUCT16 *cs = MapSL(lParam16);
2570 UnMapLS( lParam16 );
2571 unmap_str_32W_to_16( cs->lpszName );
2572 unmap_str_32W_to_16( cs->lpszClass );
2574 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2576 MDICREATESTRUCT16 *mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs->lpCreateParams);
2577 UnMapLS( cs->lpCreateParams );
2578 unmap_str_32W_to_16(mdi_cs16->szTitle);
2579 unmap_str_32W_to_16(mdi_cs16->szClass);
2580 HeapFree(GetProcessHeap(), 0, mdi_cs16);
2582 HeapFree( GetProcessHeap(), 0, cs );
2584 break;
2585 case WM_MDICREATE:
2587 MDICREATESTRUCT16 *cs = MapSL(lParam16);
2588 UnMapLS( lParam16 );
2589 unmap_str_32W_to_16( cs->szTitle );
2590 unmap_str_32W_to_16( cs->szClass );
2591 HeapFree( GetProcessHeap(), 0, cs );
2593 break;
2594 case WM_GETTEXT:
2595 case WM_ASKCBFORMATNAME:
2597 LPSTR str = MapSL(lParam16);
2598 UnMapLS( lParam16 );
2599 lParam16 = *((LPARAM *)str - 1);
2600 MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam16, 0x7fffffff );
2601 *result = strlenW( (LPWSTR)lParam16 );
2602 HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2604 break;
2605 case LB_GETTEXT:
2606 case CB_GETLBTEXT:
2607 if ( WINPROC_TestLBForStr( hwnd, msg ))
2609 LPSTR str = MapSL(lParam16);
2610 UnMapLS( lParam16 );
2611 *result = MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff ) - 1;
2612 HeapFree( GetProcessHeap(), 0, (LPARAM *)str );
2614 break;
2615 default:
2616 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, wParam16, lParam16, result );
2617 break;
2622 /**********************************************************************
2623 * WINPROC_CallProcAtoW
2625 * Call a window procedure, translating args from Ansi to Unicode.
2627 LRESULT WINPROC_CallProcAtoW( winproc_callback_t callback, HWND hwnd, UINT msg, WPARAM wParam,
2628 LPARAM lParam, LRESULT *result, void *arg )
2630 LRESULT ret = 0;
2631 int unmap;
2633 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2634 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2636 switch(msg)
2638 case WM_NCCREATE:
2639 case WM_CREATE:
2641 WCHAR *ptr, buffer[512];
2642 CREATESTRUCTA *csA = (CREATESTRUCTA *)lParam;
2643 CREATESTRUCTW csW = *(CREATESTRUCTW *)csA;
2644 MDICREATESTRUCTW mdi_cs;
2645 DWORD name_lenA = 0, name_lenW = 0, class_lenA = 0, class_lenW = 0;
2647 if (HIWORD(csA->lpszClass))
2649 class_lenA = strlen(csA->lpszClass) + 1;
2650 RtlMultiByteToUnicodeSize( &class_lenW, csA->lpszClass, class_lenA );
2652 if (HIWORD(csA->lpszName))
2654 name_lenA = strlen(csA->lpszName) + 1;
2655 RtlMultiByteToUnicodeSize( &name_lenW, csA->lpszName, name_lenA );
2658 if (!(ptr = get_buffer( buffer, sizeof(buffer), class_lenW + name_lenW ))) break;
2660 if (class_lenW)
2662 csW.lpszClass = ptr;
2663 RtlMultiByteToUnicodeN( ptr, class_lenW, NULL, csA->lpszClass, class_lenA );
2665 if (name_lenW)
2667 csW.lpszName = ptr + class_lenW/sizeof(WCHAR);
2668 RtlMultiByteToUnicodeN( ptr + class_lenW/sizeof(WCHAR), name_lenW, NULL,
2669 csA->lpszName, name_lenA );
2672 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2674 mdi_cs = *(MDICREATESTRUCTW *)csA->lpCreateParams;
2675 mdi_cs.szTitle = csW.lpszName;
2676 mdi_cs.szClass = csW.lpszClass;
2677 csW.lpCreateParams = &mdi_cs;
2680 ret = callback( hwnd, msg, wParam, (LPARAM)&csW, result, arg );
2681 free_buffer( buffer, ptr );
2683 break;
2685 default:
2686 if( (unmap = WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam )) == -1) {
2687 ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2688 SPY_GetMsgName(msg, hwnd), wParam, lParam );
2689 return 0;
2691 ret = callback( hwnd, msg, wParam, lParam, result, arg );
2692 if (!unmap) break;
2693 *result = WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, *result,
2694 (callback == call_window_proc) ? arg : NULL /*FIXME: hack*/ );
2695 break;
2697 return ret;
2701 /**********************************************************************
2702 * WINPROC_CallProcWtoA
2704 * Call a window procedure, translating args from Unicode to Ansi.
2706 static LRESULT WINPROC_CallProcWtoA( winproc_callback_t callback, HWND hwnd, UINT msg, WPARAM wParam,
2707 LPARAM lParam, LRESULT *result, void *arg )
2709 LRESULT ret = 0;
2711 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2712 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2714 switch(msg)
2716 case WM_NCCREATE:
2717 case WM_CREATE:
2718 { /* csW->lpszName and csW->lpszClass are NOT supposed to be atoms
2719 * at this point.
2721 char buffer[1024], *cls, *name;
2722 CREATESTRUCTW *csW = (CREATESTRUCTW *)lParam;
2723 CREATESTRUCTA csA = *(CREATESTRUCTA *)csW;
2724 MDICREATESTRUCTA mdi_cs;
2725 DWORD name_lenA, name_lenW, class_lenA, class_lenW;
2727 class_lenW = strlenW(csW->lpszClass) * sizeof(WCHAR);
2728 RtlUnicodeToMultiByteSize(&class_lenA, csW->lpszClass, class_lenW);
2730 if (csW->lpszName)
2732 name_lenW = strlenW(csW->lpszName) * sizeof(WCHAR);
2733 RtlUnicodeToMultiByteSize(&name_lenA, csW->lpszName, name_lenW);
2735 else
2736 name_lenW = name_lenA = 0;
2738 if (!(cls = get_buffer( buffer, sizeof(buffer), class_lenA + name_lenA + 2 ))) break;
2740 RtlUnicodeToMultiByteN(cls, class_lenA, NULL, csW->lpszClass, class_lenW);
2741 cls[class_lenA] = 0;
2742 csA.lpszClass = cls;
2744 if (csW->lpszName)
2746 name = cls + class_lenA + 1;
2747 RtlUnicodeToMultiByteN(name, name_lenA, NULL, csW->lpszName, name_lenW);
2748 name[name_lenA] = 0;
2749 csA.lpszName = name;
2752 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2754 mdi_cs = *(MDICREATESTRUCTA *)csW->lpCreateParams;
2755 mdi_cs.szTitle = csA.lpszName;
2756 mdi_cs.szClass = csA.lpszClass;
2757 csA.lpCreateParams = &mdi_cs;
2760 ret = callback( hwnd, msg, wParam, (LPARAM)&csA, result, arg );
2761 free_buffer( buffer, cls );
2763 break;
2765 case WM_GETTEXT:
2766 case WM_ASKCBFORMATNAME:
2768 char *ptr, buffer[512];
2769 DWORD len = wParam * 2;
2771 if (!(ptr = get_buffer( buffer, sizeof(buffer), len ))) break;
2772 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2773 if (*result && len)
2775 RtlMultiByteToUnicodeN( (LPWSTR)lParam, wParam*sizeof(WCHAR), &len, ptr, strlen(ptr)+1 );
2776 *result = len/sizeof(WCHAR) - 1; /* do not count terminating null */
2777 ((LPWSTR)lParam)[*result] = 0;
2779 free_buffer( buffer, ptr );
2781 break;
2783 case LB_ADDSTRING:
2784 case LB_INSERTSTRING:
2785 case LB_FINDSTRING:
2786 case LB_FINDSTRINGEXACT:
2787 case LB_SELECTSTRING:
2788 case CB_ADDSTRING:
2789 case CB_INSERTSTRING:
2790 case CB_FINDSTRING:
2791 case CB_FINDSTRINGEXACT:
2792 case CB_SELECTSTRING:
2793 if (!lParam || !WINPROC_TestLBForStr( hwnd, msg ))
2795 ret = callback( hwnd, msg, wParam, lParam, result, arg );
2796 break;
2798 /* fall through */
2799 case WM_SETTEXT:
2800 case WM_WININICHANGE:
2801 case WM_DEVMODECHANGE:
2802 case CB_DIR:
2803 case LB_DIR:
2804 case LB_ADDFILE:
2805 case EM_REPLACESEL:
2806 if (!lParam) ret = callback( hwnd, msg, wParam, lParam, result, arg );
2807 else
2809 char *ptr, buffer[512];
2810 LPCWSTR strW = (LPCWSTR)lParam;
2811 DWORD lenA, lenW = (strlenW(strW) + 1) * sizeof(WCHAR);
2813 RtlUnicodeToMultiByteSize( &lenA, strW, lenW );
2814 if ((ptr = get_buffer( buffer, sizeof(buffer), lenA )))
2816 RtlUnicodeToMultiByteN( ptr, lenA, NULL, strW, lenW );
2817 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2818 free_buffer( buffer, ptr );
2821 break;
2823 case WM_MDICREATE:
2825 char *ptr, buffer[1024];
2826 DWORD title_lenA = 0, title_lenW = 0, class_lenA = 0, class_lenW = 0;
2827 MDICREATESTRUCTW *csW = (MDICREATESTRUCTW *)lParam;
2828 MDICREATESTRUCTA csA;
2830 memcpy( &csA, csW, sizeof(csA) );
2832 if (HIWORD(csW->szTitle))
2834 title_lenW = (strlenW(csW->szTitle) + 1) * sizeof(WCHAR);
2835 RtlUnicodeToMultiByteSize( &title_lenA, csW->szTitle, title_lenW );
2837 if (HIWORD(csW->szClass))
2839 class_lenW = (strlenW(csW->szClass) + 1) * sizeof(WCHAR);
2840 RtlUnicodeToMultiByteSize( &class_lenA, csW->szClass, class_lenW );
2843 if (!(ptr = get_buffer( buffer, sizeof(buffer), title_lenA + class_lenA ))) break;
2845 if (title_lenA)
2847 RtlUnicodeToMultiByteN( ptr, title_lenA, NULL, csW->szTitle, title_lenW );
2848 csA.szTitle = ptr;
2850 if (class_lenA)
2852 RtlUnicodeToMultiByteN( ptr + title_lenA, class_lenA, NULL, csW->szClass, class_lenW );
2853 csA.szClass = ptr + title_lenA;
2855 ret = callback( hwnd, msg, wParam, (LPARAM)&csA, result, arg );
2856 free_buffer( buffer, ptr );
2858 break;
2860 case LB_GETTEXT:
2861 case CB_GETLBTEXT:
2862 if (lParam && WINPROC_TestLBForStr( hwnd, msg ))
2864 char buffer[512]; /* FIXME: fixed sized buffer */
2866 ret = callback( hwnd, msg, wParam, (LPARAM)buffer, result, arg );
2867 if (*result >= 0)
2869 DWORD len;
2870 RtlMultiByteToUnicodeN( (LPWSTR)lParam, ~0u, &len, buffer, strlen(buffer) + 1 );
2871 *result = len / sizeof(WCHAR) - 1;
2874 else ret = callback( hwnd, msg, wParam, lParam, result, arg );
2875 break;
2877 case EM_GETLINE:
2879 char *ptr, buffer[512];
2880 WORD len = *(WORD *)lParam;
2882 if (!(ptr = get_buffer( buffer, sizeof(buffer), len * 2 ))) break;
2883 *((WORD *)ptr) = len * 2; /* store the length */
2884 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2885 if (*result)
2887 DWORD reslen;
2888 RtlMultiByteToUnicodeN( (LPWSTR)lParam, len*sizeof(WCHAR), &reslen, buffer, *result );
2889 *result = reslen / sizeof(WCHAR);
2890 if (*result < len) ((LPWSTR)lParam)[*result] = 0;
2892 free_buffer( buffer, ptr );
2894 break;
2896 case WM_CHARTOITEM:
2897 case WM_MENUCHAR:
2898 case WM_CHAR:
2899 case WM_DEADCHAR:
2900 case WM_SYSCHAR:
2901 case WM_SYSDEADCHAR:
2902 case EM_SETPASSWORDCHAR:
2903 ret = callback( hwnd, msg, map_wparam_char_WtoA(wParam,1), lParam, result, arg );
2904 break;
2906 case WM_IME_CHAR:
2907 ret = callback( hwnd, msg, map_wparam_char_WtoA(wParam,2), lParam, result, arg );
2908 break;
2910 case WM_PAINTCLIPBOARD:
2911 case WM_SIZECLIPBOARD:
2912 FIXME_(msg)( "message %s (%04x) needs translation, please report\n",
2913 SPY_GetMsgName(msg, hwnd), msg );
2914 break;
2916 default:
2917 ret = callback( hwnd, msg, wParam, lParam, result, arg );
2918 break;
2921 return ret;
2925 /**********************************************************************
2926 * WINPROC_CallProc16To32A
2928 LRESULT WINPROC_CallProc16To32A( winproc_callback_t callback, HWND16 hwnd, UINT16 msg,
2929 WPARAM16 wParam, LPARAM lParam, LRESULT *result, void *arg )
2931 LRESULT ret;
2932 UINT msg32;
2933 WPARAM wParam32;
2934 HWND hwnd32 = WIN_Handle32( hwnd );
2936 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2937 hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
2939 if (WINPROC_MapMsg16To32A( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2940 return 0;
2942 ret = callback( hwnd32, msg32, wParam32, lParam, result, arg );
2943 *result = WINPROC_UnmapMsg16To32A( hwnd32, msg32, wParam32, lParam, *result );
2944 return ret;
2948 /**********************************************************************
2949 * WINPROC_CallProc16To32W
2951 static LRESULT WINPROC_CallProc16To32W( winproc_callback_t callback, HWND16 hwnd, UINT16 msg,
2952 WPARAM16 wParam, LPARAM lParam, LRESULT *result, void *arg )
2954 LRESULT ret;
2955 UINT msg32;
2956 WPARAM wParam32;
2957 HWND hwnd32 = WIN_Handle32( hwnd );
2959 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2960 hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
2962 if (WINPROC_MapMsg16To32W( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2963 return 0;
2965 ret = callback( hwnd32, msg32, wParam32, lParam, result, arg );
2966 *result = WINPROC_UnmapMsg16To32W( hwnd32, msg32, wParam32, lParam, *result,
2967 (callback == call_window_proc) ? arg : NULL /*FIXME: hack*/ );
2968 return ret;
2972 /**********************************************************************
2973 * __wine_call_wndproc (USER.1010)
2975 LRESULT WINAPI __wine_call_wndproc( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2976 WINDOWPROC *proc )
2978 LRESULT result;
2980 if (proc->procA)
2981 WINPROC_CallProc16To32A( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
2982 else
2983 WINPROC_CallProc16To32W( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
2984 return result;
2988 /**********************************************************************
2989 * WINPROC_CallProc32ATo16
2991 * Call a 16-bit window procedure, translating the 32-bit args.
2993 LRESULT WINPROC_CallProc32ATo16( winproc_callback16_t callback, HWND hwnd, UINT msg,
2994 WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg )
2996 LRESULT ret;
2997 UINT16 msg16;
2998 WPARAM16 wParam16;
2999 LPARAM lParam16;
3001 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
3002 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
3004 lParam16 = lParam;
3005 if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, &msg16, &wParam16, &lParam16 ) == -1)
3006 return 0;
3007 ret = callback( HWND_16(hwnd), msg16, wParam16, lParam16, result, arg );
3008 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, wParam16, lParam16, result );
3009 return ret;
3013 /**********************************************************************
3014 * WINPROC_CallProc32WTo16
3016 * Call a 16-bit window procedure, translating the 32-bit args.
3018 static LRESULT WINPROC_CallProc32WTo16( winproc_callback16_t callback, HWND hwnd, UINT msg,
3019 WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg )
3021 LRESULT ret;
3022 UINT16 msg16;
3023 WPARAM16 wParam16;
3024 LPARAM lParam16;
3026 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
3027 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
3029 lParam16 = lParam;
3030 if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &wParam16, &lParam16 ) == -1)
3031 return 0;
3032 ret = callback( HWND_16(hwnd), msg16, wParam16, lParam16, result, arg );
3033 WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, wParam16, lParam16, result );
3034 return ret;
3038 /**********************************************************************
3039 * CallWindowProc (USER.122)
3041 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
3042 WPARAM16 wParam, LPARAM lParam )
3044 WINDOWPROC *proc;
3045 LRESULT result;
3047 if (!func) return 0;
3049 if (!(proc = handle16_to_proc( func )))
3050 call_window_proc16( hwnd, msg, wParam, lParam, &result, func );
3051 else if (proc->procA)
3052 WINPROC_CallProc16To32A( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
3053 else if (proc->procW)
3054 WINPROC_CallProc16To32W( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3055 else
3056 call_window_proc16( hwnd, msg, wParam, lParam, &result, proc->proc16 );
3058 return result;
3062 /**********************************************************************
3063 * CallWindowProcA (USER32.@)
3065 * The CallWindowProc() function invokes the windows procedure _func_,
3066 * with _hwnd_ as the target window, the message specified by _msg_, and
3067 * the message parameters _wParam_ and _lParam_.
3069 * Some kinds of argument conversion may be done, I'm not sure what.
3071 * CallWindowProc() may be used for windows subclassing. Use
3072 * SetWindowLong() to set a new windows procedure for windows of the
3073 * subclass, and handle subclassed messages in the new windows
3074 * procedure. The new windows procedure may then use CallWindowProc()
3075 * with _func_ set to the parent class's windows procedure to dispatch
3076 * the message to the superclass.
3078 * RETURNS
3080 * The return value is message dependent.
3082 * CONFORMANCE
3084 * ECMA-234, Win32
3086 LRESULT WINAPI CallWindowProcA(
3087 WNDPROC func, /* [in] window procedure */
3088 HWND hwnd, /* [in] target window */
3089 UINT msg, /* [in] message */
3090 WPARAM wParam, /* [in] message dependent parameter */
3091 LPARAM lParam /* [in] message dependent parameter */
3093 WINDOWPROC *proc;
3094 LRESULT result;
3096 if (!func) return 0;
3098 if (!(proc = handle_to_proc( func )))
3099 call_window_proc( hwnd, msg, wParam, lParam, &result, func );
3100 else if (proc->procA)
3101 call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
3102 else if (proc->procW)
3103 WINPROC_CallProcAtoW( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3104 else
3105 WINPROC_CallProc32ATo16( call_window_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3106 return result;
3110 /**********************************************************************
3111 * CallWindowProcW (USER32.@)
3113 * See CallWindowProcA.
3115 LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
3116 WPARAM wParam, LPARAM lParam )
3118 WINDOWPROC *proc;
3119 LRESULT result;
3121 if (!func) return 0;
3123 if (!(proc = handle_to_proc( func )))
3124 call_window_proc( hwnd, msg, wParam, lParam, &result, func );
3125 else if (proc->procW)
3126 call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
3127 else if (proc->procA)
3128 WINPROC_CallProcWtoA( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
3129 else
3130 WINPROC_CallProc32WTo16( call_window_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3131 return result;
3135 /**********************************************************************
3136 * WINPROC_CallDlgProc16
3138 INT_PTR WINPROC_CallDlgProc16( DLGPROC16 func, HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
3140 WINDOWPROC *proc;
3141 LRESULT result;
3142 INT_PTR ret;
3144 if (!func) return 0;
3146 if (!(proc = handle16_to_proc( (WNDPROC16)func )))
3148 ret = call_dialog_proc16( hwnd, msg, wParam, lParam, &result, func );
3150 else if (proc->procA)
3152 ret = WINPROC_CallProc16To32A( call_dialog_proc, hwnd, msg, wParam, lParam,
3153 &result, proc->procA );
3154 SetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT, result );
3156 else if (proc->procW)
3158 ret = WINPROC_CallProc16To32W( call_dialog_proc, hwnd, msg, wParam, lParam,
3159 &result, proc->procW );
3160 SetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT, result );
3162 else
3164 ret = call_dialog_proc16( hwnd, msg, wParam, lParam, &result, proc->proc16 );
3166 return ret;
3170 /**********************************************************************
3171 * WINPROC_CallDlgProcA
3173 INT_PTR WINPROC_CallDlgProcA( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
3175 WINDOWPROC *proc;
3176 LRESULT result;
3177 INT_PTR ret;
3179 if (!func) return 0;
3181 if (!(proc = handle_to_proc( (WNDPROC)func )))
3182 ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, func );
3183 else if (proc->procA)
3184 ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
3185 else if (proc->procW)
3187 ret = WINPROC_CallProcAtoW( call_dialog_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3188 SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3190 else
3192 ret = WINPROC_CallProc32ATo16( call_dialog_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3193 SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3195 return ret;
3199 /**********************************************************************
3200 * WINPROC_CallDlgProcW
3202 INT_PTR WINPROC_CallDlgProcW( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
3204 WINDOWPROC *proc;
3205 LRESULT result;
3206 INT_PTR ret;
3208 if (!func) return 0;
3210 if (!(proc = handle_to_proc( (WNDPROC)func )))
3211 ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, func );
3212 else if (proc->procW)
3213 ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
3214 else if (proc->procA)
3216 ret = WINPROC_CallProcWtoA( call_dialog_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
3217 SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3219 else
3221 ret = WINPROC_CallProc32WTo16( call_dialog_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3222 SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3224 return ret;