| /* |
| * Window procedure callbacks |
| * |
| * Copyright 1995 Martin von Loewis |
| * Copyright 1996 Alexandre Julliard |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "config.h" |
| #include "wine/port.h" |
| |
| #include <assert.h> |
| #include <stdarg.h> |
| #include <string.h> |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "wingdi.h" |
| #include "wownt32.h" |
| #include "wine/winbase16.h" |
| #include "wine/winuser16.h" |
| #include "controls.h" |
| #include "win.h" |
| #include "winproc.h" |
| #include "user_private.h" |
| #include "dde.h" |
| #include "winternl.h" |
| #include "wine/unicode.h" |
| #include "wine/debug.h" |
| |
| WINE_DECLARE_DEBUG_CHANNEL(msg); |
| WINE_DECLARE_DEBUG_CHANNEL(relay); |
| WINE_DEFAULT_DEBUG_CHANNEL(win); |
| |
| typedef struct tagWINDOWPROC |
| { |
| WNDPROC16 proc16; /* 16-bit window proc */ |
| WNDPROC procA; /* ASCII window proc */ |
| WNDPROC procW; /* Unicode window proc */ |
| } WINDOWPROC; |
| |
| #define WINPROC_HANDLE (~0UL >> 16) |
| #define MAX_WINPROCS 8192 |
| |
| static WINDOWPROC winproc_array[MAX_WINPROCS]; |
| static UINT winproc_used; |
| |
| static CRITICAL_SECTION winproc_cs; |
| static CRITICAL_SECTION_DEBUG critsect_debug = |
| { |
| 0, 0, &winproc_cs, |
| { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, |
| 0, 0, { (DWORD_PTR)(__FILE__ ": winproc_cs") } |
| }; |
| static CRITICAL_SECTION winproc_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; |
| |
| static inline void *get_buffer( void *static_buffer, size_t size, size_t need ) |
| { |
| if (size >= need) return static_buffer; |
| return HeapAlloc( GetProcessHeap(), 0, need ); |
| } |
| |
| static inline void free_buffer( void *static_buffer, void *buffer ) |
| { |
| if (buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer ); |
| } |
| |
| /* find an existing winproc for a given 16-bit function and type */ |
| /* FIXME: probably should do something more clever than a linear search */ |
| static inline WINDOWPROC *find_winproc16( WNDPROC16 func ) |
| { |
| unsigned int i; |
| |
| for (i = 0; i < winproc_used; i++) |
| { |
| if (winproc_array[i].proc16 == func) return &winproc_array[i]; |
| } |
| return NULL; |
| } |
| |
| /* find an existing winproc for a given function and type */ |
| /* FIXME: probably should do something more clever than a linear search */ |
| static inline WINDOWPROC *find_winproc( WNDPROC funcA, WNDPROC funcW ) |
| { |
| unsigned int i; |
| |
| for (i = 0; i < winproc_used; i++) |
| { |
| if (funcA && winproc_array[i].procA != funcA) continue; |
| if (funcW && winproc_array[i].procW != funcW) continue; |
| return &winproc_array[i]; |
| } |
| return NULL; |
| } |
| |
| /* return the window proc for a given handle, or NULL for an invalid handle */ |
| static inline WINDOWPROC *handle_to_proc( WNDPROC handle ) |
| { |
| UINT index = LOWORD(handle); |
| if ((ULONG_PTR)handle >> 16 != WINPROC_HANDLE) return NULL; |
| if (index >= winproc_used) return NULL; |
| return &winproc_array[index]; |
| } |
| |
| /* create a handle for a given window proc */ |
| static inline WNDPROC proc_to_handle( WINDOWPROC *proc ) |
| { |
| return (WNDPROC)(ULONG_PTR)((proc - winproc_array) | (WINPROC_HANDLE << 16)); |
| } |
| |
| /* allocate and initialize a new winproc */ |
| static inline WINDOWPROC *alloc_winproc( WNDPROC funcA, WNDPROC funcW ) |
| { |
| WINDOWPROC *proc; |
| |
| /* check if the function is already a win proc */ |
| if (funcA && (proc = handle_to_proc( funcA ))) return proc; |
| if (funcW && (proc = handle_to_proc( funcW ))) return proc; |
| if (!funcA && !funcW) return NULL; |
| |
| EnterCriticalSection( &winproc_cs ); |
| |
| /* check if we already have a winproc for that function */ |
| if (!(proc = find_winproc( funcA, funcW ))) |
| { |
| if (winproc_used < MAX_WINPROCS) |
| { |
| proc = &winproc_array[winproc_used++]; |
| proc->procA = funcA; |
| proc->procW = funcW; |
| TRACE( "allocated %p for %p/%p (%d/%d used)\n", |
| proc_to_handle(proc), funcA, funcW, winproc_used, MAX_WINPROCS ); |
| } |
| else FIXME( "too many winprocs, cannot allocate one for %p/%p\n", funcA, funcW ); |
| } |
| else TRACE( "reusing %p for %p/%p\n", proc_to_handle(proc), funcA, funcW ); |
| |
| LeaveCriticalSection( &winproc_cs ); |
| return proc; |
| } |
| |
| |
| #ifdef __i386__ |
| |
| #include "pshpack1.h" |
| |
| /* Window procedure 16-to-32-bit thunk */ |
| typedef struct |
| { |
| BYTE popl_eax; /* popl %eax (return address) */ |
| BYTE pushl_func; /* pushl $proc */ |
| WINDOWPROC *proc; |
| BYTE pushl_eax; /* pushl %eax */ |
| BYTE ljmp; /* ljmp relay*/ |
| DWORD relay_offset; /* __wine_call_wndproc */ |
| WORD relay_sel; |
| } WINPROC_THUNK; |
| |
| #include "poppack.h" |
| |
| #define MAX_THUNKS (0x10000 / sizeof(WINPROC_THUNK)) |
| |
| static WINPROC_THUNK *thunk_array; |
| static UINT thunk_selector; |
| static UINT thunk_used; |
| |
| /* return the window proc for a given handle, or NULL for an invalid handle */ |
| static inline WINDOWPROC *handle16_to_proc( WNDPROC16 handle ) |
| { |
| if (HIWORD(handle) == thunk_selector) |
| { |
| UINT index = LOWORD(handle) / sizeof(WINPROC_THUNK); |
| /* check alignment */ |
| if (index * sizeof(WINPROC_THUNK) != LOWORD(handle)) return NULL; |
| /* check array limits */ |
| if (index >= thunk_used) return NULL; |
| return thunk_array[index].proc; |
| } |
| return handle_to_proc( (WNDPROC)handle ); |
| } |
| |
| /* allocate a 16-bit thunk for an existing window proc */ |
| static WNDPROC16 alloc_win16_thunk( WINDOWPROC *proc ) |
| { |
| static FARPROC16 relay; |
| UINT i; |
| |
| if (proc->proc16) return proc->proc16; |
| |
| EnterCriticalSection( &winproc_cs ); |
| |
| if (!thunk_array) /* allocate the array and its selector */ |
| { |
| LDT_ENTRY entry; |
| |
| if (!(thunk_selector = wine_ldt_alloc_entries(1))) goto done; |
| if (!(thunk_array = VirtualAlloc( NULL, MAX_THUNKS * sizeof(WINPROC_THUNK), MEM_COMMIT, |
| PAGE_EXECUTE_READWRITE ))) goto done; |
| wine_ldt_set_base( &entry, thunk_array ); |
| wine_ldt_set_limit( &entry, MAX_THUNKS * sizeof(WINPROC_THUNK) - 1 ); |
| wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT ); |
| wine_ldt_set_entry( thunk_selector, &entry ); |
| relay = GetProcAddress16( GetModuleHandle16("user"), "__wine_call_wndproc" ); |
| } |
| |
| /* check if it already exists */ |
| for (i = 0; i < thunk_used; i++) if (thunk_array[i].proc == proc) break; |
| |
| if (i == thunk_used) /* create a new one */ |
| { |
| WINPROC_THUNK *thunk; |
| |
| if (thunk_used >= MAX_THUNKS) goto done; |
| thunk = &thunk_array[thunk_used++]; |
| thunk->popl_eax = 0x58; /* popl %eax */ |
| thunk->pushl_func = 0x68; /* pushl $proc */ |
| thunk->proc = proc; |
| thunk->pushl_eax = 0x50; /* pushl %eax */ |
| thunk->ljmp = 0xea; /* ljmp relay*/ |
| thunk->relay_offset = OFFSETOF(relay); |
| thunk->relay_sel = SELECTOROF(relay); |
| } |
| proc->proc16 = (WNDPROC16)MAKESEGPTR( thunk_selector, i * sizeof(WINPROC_THUNK) ); |
| done: |
| LeaveCriticalSection( &winproc_cs ); |
| return proc->proc16; |
| } |
| |
| #else /* __i386__ */ |
| |
| static inline WINDOWPROC *handle16_to_proc( WNDPROC16 handle ) |
| { |
| return handle_to_proc( (WNDPROC)handle ); |
| } |
| |
| static inline WNDPROC16 alloc_win16_thunk( WINDOWPROC *proc ) |
| { |
| return 0; |
| } |
| |
| #endif /* __i386__ */ |
| |
| |
| #ifdef __i386__ |
| /* Some window procedures modify register they shouldn't, or are not |
| * properly declared stdcall; so we need a small assembly wrapper to |
| * call them. */ |
| extern LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg, |
| WPARAM wParam, LPARAM lParam ); |
| __ASM_GLOBAL_FUNC( WINPROC_wrapper, |
| "pushl %ebp\n\t" |
| "movl %esp,%ebp\n\t" |
| "pushl %edi\n\t" |
| "pushl %esi\n\t" |
| "pushl %ebx\n\t" |
| "subl $12,%esp\n\t" |
| "pushl 24(%ebp)\n\t" |
| "pushl 20(%ebp)\n\t" |
| "pushl 16(%ebp)\n\t" |
| "pushl 12(%ebp)\n\t" |
| "movl 8(%ebp),%eax\n\t" |
| "call *%eax\n\t" |
| "leal -12(%ebp),%esp\n\t" |
| "popl %ebx\n\t" |
| "popl %esi\n\t" |
| "popl %edi\n\t" |
| "leave\n\t" |
| "ret" ); |
| #else |
| static inline LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg, |
| WPARAM wParam, LPARAM lParam ) |
| { |
| return proc( hwnd, msg, wParam, lParam ); |
| } |
| #endif /* __i386__ */ |
| |
| static void RECT16to32( const RECT16 *from, RECT *to ) |
| { |
| to->left = from->left; |
| to->top = from->top; |
| to->right = from->right; |
| to->bottom = from->bottom; |
| } |
| |
| static void RECT32to16( const RECT *from, RECT16 *to ) |
| { |
| to->left = from->left; |
| to->top = from->top; |
| to->right = from->right; |
| to->bottom = from->bottom; |
| } |
| |
| static void MINMAXINFO32to16( const MINMAXINFO *from, MINMAXINFO16 *to ) |
| { |
| to->ptReserved.x = from->ptReserved.x; |
| to->ptReserved.y = from->ptReserved.y; |
| to->ptMaxSize.x = from->ptMaxSize.x; |
| to->ptMaxSize.y = from->ptMaxSize.y; |
| to->ptMaxPosition.x = from->ptMaxPosition.x; |
| to->ptMaxPosition.y = from->ptMaxPosition.y; |
| to->ptMinTrackSize.x = from->ptMinTrackSize.x; |
| to->ptMinTrackSize.y = from->ptMinTrackSize.y; |
| to->ptMaxTrackSize.x = from->ptMaxTrackSize.x; |
| to->ptMaxTrackSize.y = from->ptMaxTrackSize.y; |
| } |
| |
| static void MINMAXINFO16to32( const MINMAXINFO16 *from, MINMAXINFO *to ) |
| { |
| to->ptReserved.x = from->ptReserved.x; |
| to->ptReserved.y = from->ptReserved.y; |
| to->ptMaxSize.x = from->ptMaxSize.x; |
| to->ptMaxSize.y = from->ptMaxSize.y; |
| to->ptMaxPosition.x = from->ptMaxPosition.x; |
| to->ptMaxPosition.y = from->ptMaxPosition.y; |
| to->ptMinTrackSize.x = from->ptMinTrackSize.x; |
| to->ptMinTrackSize.y = from->ptMinTrackSize.y; |
| to->ptMaxTrackSize.x = from->ptMaxTrackSize.x; |
| to->ptMaxTrackSize.y = from->ptMaxTrackSize.y; |
| } |
| |
| static void WINDOWPOS32to16( const WINDOWPOS* from, WINDOWPOS16* to ) |
| { |
| to->hwnd = HWND_16(from->hwnd); |
| to->hwndInsertAfter = HWND_16(from->hwndInsertAfter); |
| to->x = from->x; |
| to->y = from->y; |
| to->cx = from->cx; |
| to->cy = from->cy; |
| to->flags = from->flags; |
| } |
| |
| static void WINDOWPOS16to32( const WINDOWPOS16* from, WINDOWPOS* to ) |
| { |
| to->hwnd = WIN_Handle32(from->hwnd); |
| to->hwndInsertAfter = (from->hwndInsertAfter == (HWND16)-1) ? |
| HWND_TOPMOST : WIN_Handle32(from->hwndInsertAfter); |
| to->x = from->x; |
| to->y = from->y; |
| to->cx = from->cx; |
| to->cy = from->cy; |
| to->flags = from->flags; |
| } |
| |
| /* The strings are not copied */ |
| static void CREATESTRUCT32Ato16( const CREATESTRUCTA* from, CREATESTRUCT16* to ) |
| { |
| to->lpCreateParams = (SEGPTR)from->lpCreateParams; |
| to->hInstance = HINSTANCE_16(from->hInstance); |
| to->hMenu = HMENU_16(from->hMenu); |
| to->hwndParent = HWND_16(from->hwndParent); |
| to->cy = from->cy; |
| to->cx = from->cx; |
| to->y = from->y; |
| to->x = from->x; |
| to->style = from->style; |
| to->dwExStyle = from->dwExStyle; |
| } |
| |
| static void CREATESTRUCT16to32A( const CREATESTRUCT16* from, CREATESTRUCTA *to ) |
| |
| { |
| to->lpCreateParams = (LPVOID)from->lpCreateParams; |
| to->hInstance = HINSTANCE_32(from->hInstance); |
| to->hMenu = HMENU_32(from->hMenu); |
| to->hwndParent = WIN_Handle32(from->hwndParent); |
| to->cy = from->cy; |
| to->cx = from->cx; |
| to->y = from->y; |
| to->x = from->x; |
| to->style = from->style; |
| to->dwExStyle = from->dwExStyle; |
| to->lpszName = MapSL(from->lpszName); |
| to->lpszClass = MapSL(from->lpszClass); |
| } |
| |
| /* The strings are not copied */ |
| static void MDICREATESTRUCT32Ato16( const MDICREATESTRUCTA* from, MDICREATESTRUCT16* to ) |
| { |
| to->hOwner = HINSTANCE_16(from->hOwner); |
| to->x = from->x; |
| to->y = from->y; |
| to->cx = from->cx; |
| to->cy = from->cy; |
| to->style = from->style; |
| to->lParam = from->lParam; |
| } |
| |
| static void MDICREATESTRUCT16to32A( const MDICREATESTRUCT16* from, MDICREATESTRUCTA *to ) |
| { |
| to->hOwner = HINSTANCE_32(from->hOwner); |
| to->x = from->x; |
| to->y = from->y; |
| to->cx = from->cx; |
| to->cy = from->cy; |
| to->style = from->style; |
| to->lParam = from->lParam; |
| to->szTitle = MapSL(from->szTitle); |
| to->szClass = MapSL(from->szClass); |
| } |
| |
| static WPARAM map_wparam_char_AtoW( WPARAM wParam, DWORD len ) |
| { |
| CHAR ch[2]; |
| WCHAR wch; |
| |
| ch[0] = (wParam >> 8); |
| ch[1] = wParam & 0xff; |
| if (len > 1 && ch[0]) |
| RtlMultiByteToUnicodeN( &wch, sizeof(wch), NULL, ch, 2 ); |
| else |
| RtlMultiByteToUnicodeN( &wch, sizeof(wch), NULL, ch + 1, 1 ); |
| return MAKEWPARAM( wch, HIWORD(wParam) ); |
| } |
| |
| static WPARAM map_wparam_char_WtoA( WPARAM wParam, DWORD len ) |
| { |
| WCHAR wch = wParam; |
| BYTE ch[2]; |
| |
| RtlUnicodeToMultiByteN( (LPSTR)ch, len, &len, &wch, sizeof(wch) ); |
| if (len == 2) |
| return MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(wParam) ); |
| else |
| return MAKEWPARAM( ch[0], HIWORD(wParam) ); |
| } |
| |
| /* call a 32-bit window procedure */ |
| static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result, void *arg ) |
| { |
| WNDPROC proc = arg; |
| |
| USER_CheckNotLock(); |
| |
| hwnd = WIN_GetFullHandle( hwnd ); |
| if (TRACE_ON(relay)) |
| DPRINTF( "%04x:Call window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n", |
| GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp ); |
| |
| *result = WINPROC_wrapper( proc, hwnd, msg, wp, lp ); |
| |
| if (TRACE_ON(relay)) |
| DPRINTF( "%04x:Ret window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx\n", |
| GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp, *result ); |
| return *result; |
| } |
| |
| /* call a 32-bit dialog procedure */ |
| static LRESULT call_dialog_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result, void *arg ) |
| { |
| WNDPROC proc = arg; |
| LRESULT ret; |
| |
| USER_CheckNotLock(); |
| |
| hwnd = WIN_GetFullHandle( hwnd ); |
| if (TRACE_ON(relay)) |
| DPRINTF( "%04x:Call dialog proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n", |
| GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp ); |
| |
| ret = WINPROC_wrapper( proc, hwnd, msg, wp, lp ); |
| *result = GetWindowLongPtrW( hwnd, DWLP_MSGRESULT ); |
| |
| if (TRACE_ON(relay)) |
| DPRINTF( "%04x:Ret dialog proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx result=%08lx\n", |
| GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp, ret, *result ); |
| return ret; |
| } |
| |
| /* call a 16-bit window procedure */ |
| static LRESULT call_window_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam, |
| LRESULT *result, void *arg ) |
| { |
| WNDPROC16 proc = arg; |
| CONTEXT86 context; |
| size_t size = 0; |
| struct |
| { |
| WORD params[5]; |
| union |
| { |
| CREATESTRUCT16 cs16; |
| DRAWITEMSTRUCT16 dis16; |
| COMPAREITEMSTRUCT16 cis16; |
| } u; |
| } args; |
| |
| USER_CheckNotLock(); |
| |
| /* Window procedures want ax = hInstance, ds = es = ss */ |
| |
| memset(&context, 0, sizeof(context)); |
| context.SegDs = context.SegEs = SELECTOROF(NtCurrentTeb()->WOW32Reserved); |
| context.SegFs = wine_get_fs(); |
| context.SegGs = wine_get_gs(); |
| if (!(context.Eax = GetWindowWord( HWND_32(hwnd), GWLP_HINSTANCE ))) context.Eax = context.SegDs; |
| context.SegCs = SELECTOROF(proc); |
| context.Eip = OFFSETOF(proc); |
| context.Ebp = OFFSETOF(NtCurrentTeb()->WOW32Reserved) + (WORD)&((STACK16FRAME*)0)->bp; |
| |
| if (lParam) |
| { |
| /* Some programs (eg. the "Undocumented Windows" examples, JWP) only |
| work if structures passed in lParam are placed in the stack/data |
| segment. Programmers easily make the mistake of converting lParam |
| to a near rather than a far pointer, since Windows apparently |
| allows this. We copy the structures to the 16 bit stack; this is |
| ugly but makes these programs work. */ |
| switch (msg) |
| { |
| case WM_CREATE: |
| case WM_NCCREATE: |
| size = sizeof(CREATESTRUCT16); break; |
| case WM_DRAWITEM: |
| size = sizeof(DRAWITEMSTRUCT16); break; |
| case WM_COMPAREITEM: |
| size = sizeof(COMPAREITEMSTRUCT16); break; |
| } |
| if (size) |
| { |
| memcpy( &args.u, MapSL(lParam), size ); |
| lParam = (SEGPTR)NtCurrentTeb()->WOW32Reserved - size; |
| } |
| } |
| |
| args.params[4] = hwnd; |
| args.params[3] = msg; |
| args.params[2] = wParam; |
| args.params[1] = HIWORD(lParam); |
| args.params[0] = LOWORD(lParam); |
| WOWCallback16Ex( 0, WCB16_REGS, sizeof(args.params) + size, &args, (DWORD *)&context ); |
| *result = MAKELONG( LOWORD(context.Eax), LOWORD(context.Edx) ); |
| return *result; |
| } |
| |
| /* call a 16-bit dialog procedure */ |
| static LRESULT call_dialog_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp, |
| LRESULT *result, void *arg ) |
| { |
| LRESULT ret = call_window_proc16( hwnd, msg, wp, lp, result, arg ); |
| *result = GetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT ); |
| return LOWORD(ret); |
| } |
| |
| /* helper callback for 32W->16 conversion */ |
| static LRESULT call_window_proc_Ato16( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, |
| LRESULT *result, void *arg ) |
| { |
| return WINPROC_CallProc32ATo16( call_window_proc16, hwnd, msg, wp, lp, result, arg ); |
| } |
| |
| /* helper callback for 32W->16 conversion */ |
| static LRESULT call_dialog_proc_Ato16( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, |
| LRESULT *result, void *arg ) |
| { |
| return WINPROC_CallProc32ATo16( call_dialog_proc16, hwnd, msg, wp, lp, result, arg ); |
| } |
| |
| /* helper callback for 16->32W conversion */ |
| static LRESULT call_window_proc_AtoW( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, |
| LRESULT *result, void *arg ) |
| { |
| return WINPROC_CallProcAtoW( call_window_proc, hwnd, msg, wp, lp, result, arg ); |
| } |
| |
| /* helper callback for 16->32W conversion */ |
| static LRESULT call_dialog_proc_AtoW( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, |
| LRESULT *result, void *arg ) |
| { |
| return WINPROC_CallProcAtoW( call_dialog_proc, hwnd, msg, wp, lp, result, arg ); |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_GetProc16 |
| * |
| * Get a window procedure pointer that can be passed to the Windows program. |
| */ |
| WNDPROC16 WINPROC_GetProc16( WNDPROC proc, BOOL unicode ) |
| { |
| WINDOWPROC *ptr; |
| |
| if (unicode) ptr = alloc_winproc( NULL, proc ); |
| else ptr = alloc_winproc( proc, NULL ); |
| |
| if (!ptr) return 0; |
| return alloc_win16_thunk( ptr ); |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_GetProc |
| * |
| * Get a window procedure pointer that can be passed to the Windows program. |
| */ |
| WNDPROC WINPROC_GetProc( WNDPROC proc, BOOL unicode ) |
| { |
| WINDOWPROC *ptr = handle_to_proc( proc ); |
| |
| if (!ptr) return proc; |
| if (unicode) |
| { |
| if (ptr->procW) return ptr->procW; |
| return proc; |
| } |
| else |
| { |
| if (ptr->procA) return ptr->procA; |
| return proc; |
| } |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_AllocProc16 |
| * |
| * Allocate a window procedure for a window or class. |
| * |
| * Note that allocated winprocs are never freed; the idea is that even if an app creates a |
| * lot of windows, it will usually only have a limited number of window procedures, so the |
| * array won't grow too large, and this way we avoid the need to track allocations per window. |
| */ |
| WNDPROC WINPROC_AllocProc16( WNDPROC16 func ) |
| { |
| WINDOWPROC *proc; |
| |
| if (!func) return NULL; |
| |
| /* check if the function is already a win proc */ |
| if (!(proc = handle16_to_proc( func ))) |
| { |
| EnterCriticalSection( &winproc_cs ); |
| |
| /* then check if we already have a winproc for that function */ |
| if (!(proc = find_winproc16( func ))) |
| { |
| if (winproc_used < MAX_WINPROCS) |
| { |
| proc = &winproc_array[winproc_used++]; |
| proc->proc16 = func; |
| TRACE( "allocated %p for %p/16-bit (%d/%d used)\n", |
| proc_to_handle(proc), func, winproc_used, MAX_WINPROCS ); |
| } |
| else FIXME( "too many winprocs, cannot allocate one for 16-bit %p\n", func ); |
| } |
| else TRACE( "reusing %p for %p/16-bit\n", proc_to_handle(proc), func ); |
| |
| LeaveCriticalSection( &winproc_cs ); |
| } |
| return proc_to_handle( proc ); |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_AllocProc |
| * |
| * Allocate a window procedure for a window or class. |
| * |
| * Note that allocated winprocs are never freed; the idea is that even if an app creates a |
| * lot of windows, it will usually only have a limited number of window procedures, so the |
| * array won't grow too large, and this way we avoid the need to track allocations per window. |
| */ |
| WNDPROC WINPROC_AllocProc( WNDPROC funcA, WNDPROC funcW ) |
| { |
| WINDOWPROC *proc; |
| |
| if (!(proc = alloc_winproc( funcA, funcW ))) return NULL; |
| return proc_to_handle( proc ); |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_IsUnicode |
| * |
| * Return the window procedure type, or the default value if not a winproc handle. |
| */ |
| BOOL WINPROC_IsUnicode( WNDPROC proc, BOOL def_val ) |
| { |
| WINDOWPROC *ptr = handle_to_proc( proc ); |
| |
| if (!ptr) return def_val; |
| if (ptr->procA && ptr->procW) return def_val; /* can be both */ |
| return (ptr->procW != NULL); |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_TestLBForStr |
| * |
| * Return TRUE if the lparam is a string |
| */ |
| inline static BOOL WINPROC_TestLBForStr( HWND hwnd, UINT msg ) |
| { |
| DWORD style = GetWindowLongA( hwnd, GWL_STYLE ); |
| if (msg <= CB_MSGMAX) |
| return (!(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) || (style & CBS_HASSTRINGS)); |
| else |
| return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS)); |
| |
| } |
| |
| |
| static UINT convert_handle_16_to_32(HANDLE16 src, unsigned int flags) |
| { |
| HANDLE dst; |
| UINT sz = GlobalSize16(src); |
| LPSTR ptr16, ptr32; |
| |
| if (!(dst = GlobalAlloc(flags, sz))) |
| return 0; |
| ptr16 = GlobalLock16(src); |
| ptr32 = GlobalLock(dst); |
| if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr32, ptr16, sz); |
| GlobalUnlock16(src); |
| GlobalUnlock(dst); |
| |
| return (UINT)dst; |
| } |
| |
| static HANDLE16 convert_handle_32_to_16(UINT src, unsigned int flags) |
| { |
| HANDLE16 dst; |
| UINT sz = GlobalSize((HANDLE)src); |
| LPSTR ptr16, ptr32; |
| |
| if (!(dst = GlobalAlloc16(flags, sz))) |
| return 0; |
| ptr32 = GlobalLock((HANDLE)src); |
| ptr16 = GlobalLock16(dst); |
| if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr16, ptr32, sz); |
| GlobalUnlock((HANDLE)src); |
| GlobalUnlock16(dst); |
| |
| return dst; |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallProcAtoW |
| * |
| * Call a window procedure, translating args from Ansi to Unicode. |
| */ |
| LRESULT WINPROC_CallProcAtoW( winproc_callback_t callback, HWND hwnd, UINT msg, WPARAM wParam, |
| LPARAM lParam, LRESULT *result, void *arg ) |
| { |
| LRESULT ret = 0; |
| |
| TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n", |
| hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam); |
| |
| switch(msg) |
| { |
| case WM_NCCREATE: |
| case WM_CREATE: |
| { |
| WCHAR *ptr, buffer[512]; |
| CREATESTRUCTA *csA = (CREATESTRUCTA *)lParam; |
| CREATESTRUCTW csW = *(CREATESTRUCTW *)csA; |
| MDICREATESTRUCTW mdi_cs; |
| DWORD name_lenA = 0, name_lenW = 0, class_lenA = 0, class_lenW = 0; |
| |
| if (HIWORD(csA->lpszClass)) |
| { |
| class_lenA = strlen(csA->lpszClass) + 1; |
| RtlMultiByteToUnicodeSize( &class_lenW, csA->lpszClass, class_lenA ); |
| } |
| if (HIWORD(csA->lpszName)) |
| { |
| name_lenA = strlen(csA->lpszName) + 1; |
| RtlMultiByteToUnicodeSize( &name_lenW, csA->lpszName, name_lenA ); |
| } |
| |
| if (!(ptr = get_buffer( buffer, sizeof(buffer), class_lenW + name_lenW ))) break; |
| |
| if (class_lenW) |
| { |
| csW.lpszClass = ptr; |
| RtlMultiByteToUnicodeN( ptr, class_lenW, NULL, csA->lpszClass, class_lenA ); |
| } |
| if (name_lenW) |
| { |
| csW.lpszName = ptr + class_lenW/sizeof(WCHAR); |
| RtlMultiByteToUnicodeN( ptr + class_lenW/sizeof(WCHAR), name_lenW, NULL, |
| csA->lpszName, name_lenA ); |
| } |
| |
| if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD) |
| { |
| mdi_cs = *(MDICREATESTRUCTW *)csA->lpCreateParams; |
| mdi_cs.szTitle = csW.lpszName; |
| mdi_cs.szClass = csW.lpszClass; |
| csW.lpCreateParams = &mdi_cs; |
| } |
| |
| ret = callback( hwnd, msg, wParam, (LPARAM)&csW, result, arg ); |
| free_buffer( buffer, ptr ); |
| } |
| break; |
| |
| case WM_MDICREATE: |
| { |
| WCHAR *ptr, buffer[512]; |
| DWORD title_lenA = 0, title_lenW = 0, class_lenA = 0, class_lenW = 0; |
| MDICREATESTRUCTA *csA = (MDICREATESTRUCTA *)lParam; |
| MDICREATESTRUCTW csW; |
| |
| memcpy( &csW, csA, sizeof(csW) ); |
| |
| if (HIWORD(csA->szTitle)) |
| { |
| title_lenA = strlen(csA->szTitle) + 1; |
| RtlMultiByteToUnicodeSize( &title_lenW, csA->szTitle, title_lenA ); |
| } |
| if (HIWORD(csA->szClass)) |
| { |
| class_lenA = strlen(csA->szClass) + 1; |
| RtlMultiByteToUnicodeSize( &class_lenW, csA->szClass, class_lenA ); |
| } |
| |
| if (!(ptr = get_buffer( buffer, sizeof(buffer), title_lenW + class_lenW ))) break; |
| |
| if (title_lenW) |
| { |
| csW.szTitle = ptr; |
| RtlMultiByteToUnicodeN( ptr, title_lenW, NULL, csA->szTitle, title_lenA ); |
| } |
| if (class_lenW) |
| { |
| csW.szClass = ptr + title_lenW/sizeof(WCHAR); |
| RtlMultiByteToUnicodeN( ptr + title_lenW/sizeof(WCHAR), class_lenW, NULL, |
| csA->szClass, class_lenA ); |
| } |
| ret = callback( hwnd, msg, wParam, (LPARAM)&csW, result, arg ); |
| free_buffer( buffer, ptr ); |
| } |
| break; |
| |
| case WM_GETTEXT: |
| case WM_ASKCBFORMATNAME: |
| { |
| WCHAR *ptr, buffer[512]; |
| LPSTR str = (LPSTR)lParam; |
| DWORD len = wParam * sizeof(WCHAR); |
| |
| if (!(ptr = get_buffer( buffer, sizeof(buffer), len ))) break; |
| ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg ); |
| if (*result && wParam) |
| { |
| RtlUnicodeToMultiByteN( str, wParam - 1, &len, ptr, strlenW(ptr) * sizeof(WCHAR) ); |
| str[len] = 0; |
| *result = len; |
| } |
| free_buffer( buffer, ptr ); |
| } |
| break; |
| |
| case LB_ADDSTRING: |
| case LB_INSERTSTRING: |
| case LB_FINDSTRING: |
| case LB_FINDSTRINGEXACT: |
| case LB_SELECTSTRING: |
| case CB_ADDSTRING: |
| case CB_INSERTSTRING: |
| case CB_FINDSTRING: |
| case CB_FINDSTRINGEXACT: |
| case CB_SELECTSTRING: |
| if (!lParam || !WINPROC_TestLBForStr( hwnd, msg )) |
| { |
| ret = callback( hwnd, msg, wParam, lParam, result, arg ); |
| break; |
| } |
| /* fall through */ |
| case WM_SETTEXT: |
| case WM_WININICHANGE: |
| case WM_DEVMODECHANGE: |
| case CB_DIR: |
| case LB_DIR: |
| case LB_ADDFILE: |
| case EM_REPLACESEL: |
| if (!lParam) ret = callback( hwnd, msg, wParam, lParam, result, arg ); |
| else |
| { |
| WCHAR *ptr, buffer[512]; |
| LPCSTR strA = (LPCSTR)lParam; |
| DWORD lenW, lenA = strlen(strA) + 1; |
| |
| RtlMultiByteToUnicodeSize( &lenW, strA, lenA ); |
| if ((ptr = get_buffer( buffer, sizeof(buffer), lenW ))) |
| { |
| RtlMultiByteToUnicodeN( ptr, lenW, NULL, strA, lenA ); |
| ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg ); |
| free_buffer( buffer, ptr ); |
| } |
| } |
| break; |
| |
| case LB_GETTEXT: |
| case CB_GETLBTEXT: |
| if (lParam && WINPROC_TestLBForStr( hwnd, msg )) |
| { |
| WCHAR buffer[512]; /* FIXME: fixed sized buffer */ |
| |
| ret = callback( hwnd, msg, wParam, (LPARAM)buffer, result, arg ); |
| if (*result >= 0) |
| { |
| DWORD len; |
| RtlUnicodeToMultiByteN( (LPSTR)lParam, ~0u, &len, |
| buffer, (strlenW(buffer) + 1) * sizeof(WCHAR) ); |
| *result = len - 1; |
| } |
| } |
| else ret = callback( hwnd, msg, wParam, lParam, result, arg ); |
| break; |
| |
| case EM_GETLINE: |
| { |
| WCHAR *ptr, buffer[512]; |
| WORD len = *(WORD *)lParam; |
| |
| if (!(ptr = get_buffer( buffer, sizeof(buffer), len * sizeof(WCHAR) ))) break; |
| *((WORD *)ptr) = len; /* store the length */ |
| ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg ); |
| if (*result) |
| { |
| DWORD reslen; |
| RtlUnicodeToMultiByteN( (LPSTR)lParam, len, &reslen, ptr, *result * sizeof(WCHAR) ); |
| if (reslen < len) ((LPSTR)lParam)[reslen] = 0; |
| *result = reslen; |
| } |
| free_buffer( buffer, ptr ); |
| } |
| break; |
| |
| case WM_GETDLGCODE: |
| if (lParam) |
| { |
| MSG newmsg = *(MSG *)lParam; |
| switch(newmsg.message) |
| { |
| case WM_CHAR: |
| case WM_DEADCHAR: |
| case WM_SYSCHAR: |
| case WM_SYSDEADCHAR: |
| newmsg.wParam = map_wparam_char_AtoW( newmsg.wParam, 1 ); |
| break; |
| case WM_IME_CHAR: |
| newmsg.wParam = map_wparam_char_AtoW( newmsg.wParam, 2 ); |
| break; |
| } |
| ret = callback( hwnd, msg, wParam, (LPARAM)&newmsg, result, arg ); |
| } |
| else ret = callback( hwnd, msg, wParam, lParam, result, arg ); |
| break; |
| |
| case WM_CHARTOITEM: |
| case WM_MENUCHAR: |
| case WM_CHAR: |
| case WM_DEADCHAR: |
| case WM_SYSCHAR: |
| case WM_SYSDEADCHAR: |
| case EM_SETPASSWORDCHAR: |
| ret = callback( hwnd, msg, map_wparam_char_AtoW(wParam,1), lParam, result, arg ); |
| break; |
| |
| case WM_IME_CHAR: |
| ret = callback( hwnd, msg, map_wparam_char_AtoW(wParam,2), lParam, result, arg ); |
| break; |
| |
| case WM_GETTEXTLENGTH: |
| case CB_GETLBTEXTLEN: |
| case LB_GETTEXTLEN: |
| ret = callback( hwnd, msg, wParam, lParam, result, arg ); |
| if (*result >= 0) |
| { |
| WCHAR *ptr, buffer[512]; |
| LRESULT tmp; |
| DWORD len = *result + 1; |
| /* Determine respective GETTEXT message */ |
| UINT msgGetText = (msg == WM_GETTEXTLENGTH) ? WM_GETTEXT : |
| ((msg == CB_GETLBTEXTLEN) ? CB_GETLBTEXT : LB_GETTEXT); |
| /* wParam differs between the messages */ |
| WPARAM wp = (msg == WM_GETTEXTLENGTH) ? len : wParam; |
| |
| if (!(ptr = get_buffer( buffer, sizeof(buffer), len * sizeof(WCHAR) ))) break; |
| |
| if (callback == call_window_proc) /* FIXME: hack */ |
| callback( hwnd, msgGetText, wp, (LPARAM)ptr, &tmp, arg ); |
| else |
| tmp = SendMessageW( hwnd, msgGetText, wp, (LPARAM)ptr ); |
| RtlUnicodeToMultiByteSize( &len, ptr, tmp * sizeof(WCHAR) ); |
| *result = len; |
| free_buffer( buffer, ptr ); |
| } |
| break; |
| |
| case WM_PAINTCLIPBOARD: |
| case WM_SIZECLIPBOARD: |
| FIXME_(msg)( "message %s (0x%x) needs translation, please report\n", |
| SPY_GetMsgName(msg, hwnd), msg ); |
| break; |
| |
| default: |
| ret = callback( hwnd, msg, wParam, lParam, result, arg ); |
| break; |
| } |
| return ret; |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallProcWtoA |
| * |
| * Call a window procedure, translating args from Unicode to Ansi. |
| */ |
| static LRESULT WINPROC_CallProcWtoA( winproc_callback_t callback, HWND hwnd, UINT msg, WPARAM wParam, |
| LPARAM lParam, LRESULT *result, void *arg ) |
| { |
| LRESULT ret = 0; |
| |
| TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n", |
| hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam); |
| |
| switch(msg) |
| { |
| case WM_NCCREATE: |
| case WM_CREATE: |
| { /* csW->lpszName and csW->lpszClass are NOT supposed to be atoms |
| * at this point. |
| */ |
| char buffer[1024], *cls, *name; |
| CREATESTRUCTW *csW = (CREATESTRUCTW *)lParam; |
| CREATESTRUCTA csA = *(CREATESTRUCTA *)csW; |
| MDICREATESTRUCTA mdi_cs; |
| DWORD name_lenA, name_lenW, class_lenA, class_lenW; |
| |
| class_lenW = strlenW(csW->lpszClass) * sizeof(WCHAR); |
| RtlUnicodeToMultiByteSize(&class_lenA, csW->lpszClass, class_lenW); |
| |
| if (csW->lpszName) |
| { |
| name_lenW = strlenW(csW->lpszName) * sizeof(WCHAR); |
| RtlUnicodeToMultiByteSize(&name_lenA, csW->lpszName, name_lenW); |
| } |
| else |
| name_lenW = name_lenA = 0; |
| |
| if (!(cls = get_buffer( buffer, sizeof(buffer), class_lenA + name_lenA + 2 ))) break; |
| |
| RtlUnicodeToMultiByteN(cls, class_lenA, NULL, csW->lpszClass, class_lenW); |
| cls[class_lenA] = 0; |
| csA.lpszClass = cls; |
| |
| if (csW->lpszName) |
| { |
| name = cls + class_lenA + 1; |
| RtlUnicodeToMultiByteN(name, name_lenA, NULL, csW->lpszName, name_lenW); |
| name[name_lenA] = 0; |
| csA.lpszName = name; |
| } |
| |
| if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD) |
| { |
| mdi_cs = *(MDICREATESTRUCTA *)csW->lpCreateParams; |
| mdi_cs.szTitle = csA.lpszName; |
| mdi_cs.szClass = csA.lpszClass; |
| csA.lpCreateParams = &mdi_cs; |
| } |
| |
| ret = callback( hwnd, msg, wParam, (LPARAM)&csA, result, arg ); |
| free_buffer( buffer, cls ); |
| } |
| break; |
| |
| case WM_GETTEXT: |
| case WM_ASKCBFORMATNAME: |
| { |
| char *ptr, buffer[512]; |
| DWORD len = wParam * 2; |
| |
| if (!(ptr = get_buffer( buffer, sizeof(buffer), len ))) break; |
| ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg ); |
| if (*result && len) |
| { |
| RtlMultiByteToUnicodeN( (LPWSTR)lParam, wParam*sizeof(WCHAR), &len, ptr, strlen(ptr)+1 ); |
| *result = len/sizeof(WCHAR) - 1; /* do not count terminating null */ |
| ((LPWSTR)lParam)[*result] = 0; |
| } |
| free_buffer( buffer, ptr ); |
| } |
| break; |
| |
| case LB_ADDSTRING: |
| case LB_INSERTSTRING: |
| case LB_FINDSTRING: |
| case LB_FINDSTRINGEXACT: |
| case LB_SELECTSTRING: |
| case CB_ADDSTRING: |
| case CB_INSERTSTRING: |
| case CB_FINDSTRING: |
| case CB_FINDSTRINGEXACT: |
| case CB_SELECTSTRING: |
| if (!lParam || !WINPROC_TestLBForStr( hwnd, msg )) |
| { |
| ret = callback( hwnd, msg, wParam, lParam, result, arg ); |
| break; |
| } |
| /* fall through */ |
| case WM_SETTEXT: |
| case WM_WININICHANGE: |
| case WM_DEVMODECHANGE: |
| case CB_DIR: |
| case LB_DIR: |
| case LB_ADDFILE: |
| case EM_REPLACESEL: |
| if (!lParam) ret = callback( hwnd, msg, wParam, lParam, result, arg ); |
| else |
| { |
| char *ptr, buffer[512]; |
| LPCWSTR strW = (LPCWSTR)lParam; |
| DWORD lenA, lenW = (strlenW(strW) + 1) * sizeof(WCHAR); |
| |
| RtlUnicodeToMultiByteSize( &lenA, strW, lenW ); |
| if ((ptr = get_buffer( buffer, sizeof(buffer), lenA ))) |
| { |
| RtlUnicodeToMultiByteN( ptr, lenA, NULL, strW, lenW ); |
| ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg ); |
| free_buffer( buffer, ptr ); |
| } |
| } |
| break; |
| |
| case WM_MDICREATE: |
| { |
| char *ptr, buffer[1024]; |
| DWORD title_lenA = 0, title_lenW = 0, class_lenA = 0, class_lenW = 0; |
| MDICREATESTRUCTW *csW = (MDICREATESTRUCTW *)lParam; |
| MDICREATESTRUCTA csA; |
| |
| memcpy( &csA, csW, sizeof(csA) ); |
| |
| if (HIWORD(csW->szTitle)) |
| { |
| title_lenW = (strlenW(csW->szTitle) + 1) * sizeof(WCHAR); |
| RtlUnicodeToMultiByteSize( &title_lenA, csW->szTitle, title_lenW ); |
| } |
| if (HIWORD(csW->szClass)) |
| { |
| class_lenW = (strlenW(csW->szClass) + 1) * sizeof(WCHAR); |
| RtlUnicodeToMultiByteSize( &class_lenA, csW->szClass, class_lenW ); |
| } |
| |
| if (!(ptr = get_buffer( buffer, sizeof(buffer), title_lenA + class_lenA ))) break; |
| |
| if (title_lenA) |
| { |
| RtlUnicodeToMultiByteN( ptr, title_lenA, NULL, csW->szTitle, title_lenW ); |
| csA.szTitle = ptr; |
| } |
| if (class_lenA) |
| { |
| RtlUnicodeToMultiByteN( ptr + title_lenA, class_lenA, NULL, csW->szClass, class_lenW ); |
| csA.szClass = ptr + title_lenA; |
| } |
| ret = callback( hwnd, msg, wParam, (LPARAM)&csA, result, arg ); |
| free_buffer( buffer, ptr ); |
| } |
| break; |
| |
| case LB_GETTEXT: |
| case CB_GETLBTEXT: |
| if (lParam && WINPROC_TestLBForStr( hwnd, msg )) |
| { |
| char buffer[512]; /* FIXME: fixed sized buffer */ |
| |
| ret = callback( hwnd, msg, wParam, (LPARAM)buffer, result, arg ); |
| if (*result >= 0) |
| { |
| DWORD len; |
| RtlMultiByteToUnicodeN( (LPWSTR)lParam, ~0u, &len, buffer, strlen(buffer) + 1 ); |
| *result = len / sizeof(WCHAR) - 1; |
| } |
| } |
| else ret = callback( hwnd, msg, wParam, lParam, result, arg ); |
| break; |
| |
| case EM_GETLINE: |
| { |
| char *ptr, buffer[512]; |
| WORD len = *(WORD *)lParam; |
| |
| if (!(ptr = get_buffer( buffer, sizeof(buffer), len * 2 ))) break; |
| *((WORD *)ptr) = len * 2; /* store the length */ |
| ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg ); |
| if (*result) |
| { |
| DWORD reslen; |
| RtlMultiByteToUnicodeN( (LPWSTR)lParam, len*sizeof(WCHAR), &reslen, ptr, *result ); |
| *result = reslen / sizeof(WCHAR); |
| if (*result < len) ((LPWSTR)lParam)[*result] = 0; |
| } |
| free_buffer( buffer, ptr ); |
| } |
| break; |
| |
| case WM_GETDLGCODE: |
| if (lParam) |
| { |
| MSG newmsg = *(MSG *)lParam; |
| switch(newmsg.message) |
| { |
| case WM_CHAR: |
| case WM_DEADCHAR: |
| case WM_SYSCHAR: |
| case WM_SYSDEADCHAR: |
| newmsg.wParam = map_wparam_char_WtoA( newmsg.wParam, 1 ); |
| break; |
| case WM_IME_CHAR: |
| newmsg.wParam = map_wparam_char_WtoA( newmsg.wParam, 2 ); |
| break; |
| } |
| ret = callback( hwnd, msg, wParam, (LPARAM)&newmsg, result, arg ); |
| } |
| else ret = callback( hwnd, msg, wParam, lParam, result, arg ); |
| break; |
| |
| case WM_CHARTOITEM: |
| case WM_MENUCHAR: |
| case WM_CHAR: |
| case WM_DEADCHAR: |
| case WM_SYSCHAR: |
| case WM_SYSDEADCHAR: |
| case EM_SETPASSWORDCHAR: |
| ret = callback( hwnd, msg, map_wparam_char_WtoA(wParam,1), lParam, result, arg ); |
| break; |
| |
| case WM_IME_CHAR: |
| ret = callback( hwnd, msg, map_wparam_char_WtoA(wParam,2), lParam, result, arg ); |
| break; |
| |
| case WM_PAINTCLIPBOARD: |
| case WM_SIZECLIPBOARD: |
| FIXME_(msg)( "message %s (%04x) needs translation, please report\n", |
| SPY_GetMsgName(msg, hwnd), msg ); |
| break; |
| |
| default: |
| ret = callback( hwnd, msg, wParam, lParam, result, arg ); |
| break; |
| } |
| |
| return ret; |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallProc16To32A |
| */ |
| LRESULT WINPROC_CallProc16To32A( winproc_callback_t callback, HWND16 hwnd, UINT16 msg, |
| WPARAM16 wParam, LPARAM lParam, LRESULT *result, void *arg ) |
| { |
| LRESULT ret = 0; |
| HWND hwnd32 = WIN_Handle32( hwnd ); |
| |
| TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n", |
| hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam); |
| |
| switch(msg) |
| { |
| case WM_NCCREATE: |
| case WM_CREATE: |
| { |
| CREATESTRUCT16 *cs16 = MapSL(lParam); |
| CREATESTRUCTA cs; |
| MDICREATESTRUCTA mdi_cs; |
| |
| CREATESTRUCT16to32A( cs16, &cs ); |
| if (GetWindowLongW(hwnd32, GWL_EXSTYLE) & WS_EX_MDICHILD) |
| { |
| MDICREATESTRUCT16 *mdi_cs16 = MapSL(cs16->lpCreateParams); |
| MDICREATESTRUCT16to32A(mdi_cs16, &mdi_cs); |
| cs.lpCreateParams = &mdi_cs; |
| } |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&cs, result, arg ); |
| CREATESTRUCT32Ato16( &cs, cs16 ); |
| } |
| break; |
| case WM_MDICREATE: |
| { |
| MDICREATESTRUCT16 *cs16 = MapSL(lParam); |
| MDICREATESTRUCTA cs; |
| |
| MDICREATESTRUCT16to32A( cs16, &cs ); |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&cs, result, arg ); |
| MDICREATESTRUCT32Ato16( &cs, cs16 ); |
| } |
| break; |
| case WM_MDIACTIVATE: |
| if (lParam) |
| ret = callback( hwnd32, msg, (WPARAM)WIN_Handle32( HIWORD(lParam) ), |
| (LPARAM)WIN_Handle32( LOWORD(lParam) ), result, arg ); |
| else /* message sent to MDI client */ |
| ret = callback( hwnd32, msg, wParam, lParam, result, arg ); |
| break; |
| case WM_MDIGETACTIVE: |
| { |
| BOOL maximized = FALSE; |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&maximized, result, arg ); |
| *result = MAKELRESULT( LOWORD(*result), maximized ); |
| } |
| break; |
| case WM_MDISETMENU: |
| ret = callback( hwnd32, wParam ? WM_MDIREFRESHMENU : WM_MDISETMENU, |
| (WPARAM)HMENU_32(LOWORD(lParam)), (LPARAM)HMENU_32(HIWORD(lParam)), |
| result, arg ); |
| break; |
| case WM_GETMINMAXINFO: |
| { |
| MINMAXINFO16 *mmi16 = MapSL(lParam); |
| MINMAXINFO mmi; |
| |
| MINMAXINFO16to32( mmi16, &mmi ); |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&mmi, result, arg ); |
| MINMAXINFO32to16( &mmi, mmi16 ); |
| } |
| break; |
| case WM_WINDOWPOSCHANGING: |
| case WM_WINDOWPOSCHANGED: |
| { |
| WINDOWPOS16 *winpos16 = MapSL(lParam); |
| WINDOWPOS winpos; |
| |
| WINDOWPOS16to32( winpos16, &winpos ); |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&winpos, result, arg ); |
| WINDOWPOS32to16( &winpos, winpos16 ); |
| } |
| break; |
| case WM_NCCALCSIZE: |
| { |
| NCCALCSIZE_PARAMS16 *nc16 = MapSL(lParam); |
| NCCALCSIZE_PARAMS nc; |
| WINDOWPOS winpos; |
| |
| RECT16to32( &nc16->rgrc[0], &nc.rgrc[0] ); |
| if (wParam) |
| { |
| RECT16to32( &nc16->rgrc[1], &nc.rgrc[1] ); |
| RECT16to32( &nc16->rgrc[2], &nc.rgrc[2] ); |
| WINDOWPOS16to32( MapSL(nc16->lppos), &winpos ); |
| nc.lppos = &winpos; |
| } |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&nc, result, arg ); |
| RECT32to16( &nc.rgrc[0], &nc16->rgrc[0] ); |
| if (wParam) |
| { |
| RECT32to16( &nc.rgrc[1], &nc16->rgrc[1] ); |
| RECT32to16( &nc.rgrc[2], &nc16->rgrc[2] ); |
| WINDOWPOS32to16( &winpos, MapSL(nc16->lppos) ); |
| } |
| } |
| break; |
| case WM_COMPAREITEM: |
| { |
| COMPAREITEMSTRUCT16* cis16 = MapSL(lParam); |
| COMPAREITEMSTRUCT cis; |
| cis.CtlType = cis16->CtlType; |
| cis.CtlID = cis16->CtlID; |
| cis.hwndItem = WIN_Handle32( cis16->hwndItem ); |
| cis.itemID1 = cis16->itemID1; |
| cis.itemData1 = cis16->itemData1; |
| cis.itemID2 = cis16->itemID2; |
| cis.itemData2 = cis16->itemData2; |
| cis.dwLocaleId = 0; /* FIXME */ |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&cis, result, arg ); |
| } |
| break; |
| case WM_DELETEITEM: |
| { |
| DELETEITEMSTRUCT16* dis16 = MapSL(lParam); |
| DELETEITEMSTRUCT dis; |
| dis.CtlType = dis16->CtlType; |
| dis.CtlID = dis16->CtlID; |
| dis.hwndItem = WIN_Handle32( dis16->hwndItem ); |
| dis.itemData = dis16->itemData; |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&dis, result, arg ); |
| } |
| break; |
| case WM_MEASUREITEM: |
| { |
| MEASUREITEMSTRUCT16* mis16 = MapSL(lParam); |
| MEASUREITEMSTRUCT mis; |
| mis.CtlType = mis16->CtlType; |
| mis.CtlID = mis16->CtlID; |
| mis.itemID = mis16->itemID; |
| mis.itemWidth = mis16->itemWidth; |
| mis.itemHeight = mis16->itemHeight; |
| mis.itemData = mis16->itemData; |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&mis, result, arg ); |
| mis16->itemWidth = (UINT16)mis.itemWidth; |
| mis16->itemHeight = (UINT16)mis.itemHeight; |
| } |
| break; |
| case WM_DRAWITEM: |
| { |
| DRAWITEMSTRUCT16* dis16 = MapSL(lParam); |
| DRAWITEMSTRUCT dis; |
| dis.CtlType = dis16->CtlType; |
| dis.CtlID = dis16->CtlID; |
| dis.itemID = dis16->itemID; |
| dis.itemAction = dis16->itemAction; |
| dis.itemState = dis16->itemState; |
| dis.hwndItem = (dis.CtlType == ODT_MENU) ? (HWND)HMENU_32(dis16->hwndItem) |
| : WIN_Handle32( dis16->hwndItem ); |
| dis.hDC = HDC_32(dis16->hDC); |
| dis.itemData = dis16->itemData; |
| dis.rcItem.left = dis16->rcItem.left; |
| dis.rcItem.top = dis16->rcItem.top; |
| dis.rcItem.right = dis16->rcItem.right; |
| dis.rcItem.bottom = dis16->rcItem.bottom; |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&dis, result, arg ); |
| } |
| break; |
| case WM_COPYDATA: |
| { |
| COPYDATASTRUCT16 *cds16 = MapSL(lParam); |
| COPYDATASTRUCT cds; |
| cds.dwData = cds16->dwData; |
| cds.cbData = cds16->cbData; |
| cds.lpData = MapSL(cds16->lpData); |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&cds, result, arg ); |
| } |
| break; |
| case WM_GETDLGCODE: |
| if (lParam) |
| { |
| MSG16 *msg16 = MapSL(lParam); |
| MSG msg32; |
| msg32.hwnd = WIN_Handle32( msg16->hwnd ); |
| msg32.message = msg16->message; |
| msg32.wParam = msg16->wParam; |
| msg32.lParam = msg16->lParam; |
| msg32.time = msg16->time; |
| msg32.pt.x = msg16->pt.x; |
| msg32.pt.y = msg16->pt.y; |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&msg32, result, arg ); |
| } |
| else |
| ret = callback( hwnd32, msg, wParam, lParam, result, arg ); |
| break; |
| case WM_NEXTMENU: |
| { |
| MDINEXTMENU next; |
| next.hmenuIn = (HMENU)lParam; |
| next.hmenuNext = 0; |
| next.hwndNext = 0; |
| ret = callback( hwnd32, msg, wParam, (LPARAM)&next, result, arg ); |
| *result = MAKELONG( HMENU_16(next.hmenuNext), HWND_16(next.hwndNext) ); |
| } |
| break; |
| case WM_ACTIVATE: |
| case WM_CHARTOITEM: |
| case WM_COMMAND: |
| case WM_VKEYTOITEM: |
| ret = callback( hwnd32, msg, MAKEWPARAM( wParam, HIWORD(lParam) ), |
| (LPARAM)WIN_Handle32( LOWORD(lParam) ), result, arg ); |
| break; |
| case WM_HSCROLL: |
| case WM_VSCROLL: |
| ret = callback( hwnd32, msg, MAKEWPARAM( wParam, LOWORD(lParam) ), |
| (LPARAM)WIN_Handle32( HIWORD(lParam) ), result, arg ); |
| break; |
| case WM_CTLCOLOR: |
| if (HIWORD(lParam) <= CTLCOLOR_STATIC) |
| ret = callback( hwnd32, WM_CTLCOLORMSGBOX + HIWORD(lParam), |
| (WPARAM)HDC_32(wParam), (LPARAM)WIN_Handle32( LOWORD(lParam) ), |
| result, arg ); |
| break; |
| case WM_GETTEXT: |
| case WM_SETTEXT: |
| case WM_WININICHANGE: |
| case WM_DEVMODECHANGE: |
| case WM_ASKCBFORMATNAME: |
| case WM_NOTIFY: |
| ret = callback( hwnd32, msg, wParam, (LPARAM)MapSL(lParam), result, arg ); |
| break; |
| case WM_MENUCHAR: |
| ret = callback( hwnd32, msg, MAKEWPARAM( wParam, LOWORD(lParam) ), |
| (LPARAM)HMENU_32(HIWORD(lParam)), result, arg ); |
| break; |
| case WM_MENUSELECT: |
| if((LOWORD(lParam) & MF_POPUP) && (LOWORD(lParam) != 0xFFFF)) |
| { |
| HMENU hmenu = HMENU_32(HIWORD(lParam)); |
| UINT pos = MENU_FindSubMenu( &hmenu, HMENU_32(wParam) ); |
| if (pos == 0xffff) pos = 0; /* NO_SELECTED_ITEM */ |
| wParam = pos; |
| } |
| ret = callback( hwnd32, msg, MAKEWPARAM( wParam, LOWORD(lParam) ), |
| (LPARAM)HMENU_32(HIWORD(lParam)), result, arg ); |
| break; |
| case WM_PARENTNOTIFY: |
| if ((wParam == WM_CREATE) || (wParam == WM_DESTROY)) |
| ret = callback( hwnd32, msg, MAKEWPARAM( wParam, HIWORD(lParam) ), |
| (LPARAM)WIN_Handle32( LOWORD(lParam) ), result, arg ); |
| else |
| ret = callback( hwnd32, msg, wParam, lParam, result, arg ); |
| break; |
| case WM_ACTIVATEAPP: |
| /* We need this when SetActiveWindow sends a Sendmessage16() to |
| * a 32bit window. Might be superflous with 32bit interprocess |
| * message queues. */ |
| if (lParam) lParam = HTASK_32(lParam); |
| ret = callback( hwnd32, msg, wParam, lParam, result, arg ); |
| break; |
| case WM_DDE_INITIATE: |
| case WM_DDE_TERMINATE: |
| case WM_DDE_UNADVISE: |
| case WM_DDE_REQUEST: |
| ret = callback( hwnd32, msg, (WPARAM)WIN_Handle32(wParam), lParam, result, arg ); |
| break; |
| case WM_DDE_ADVISE: |
| case WM_DDE_DATA: |
| case WM_DDE_POKE: |
| { |
| HANDLE16 lo16 = LOWORD(lParam); |
| UINT lo32 = 0; |
| if (lo16 && !(lo32 = convert_handle_16_to_32(lo16, GMEM_DDESHARE))) break; |
| lParam = PackDDElParam( msg, lo32, HIWORD(lParam) ); |
| ret = callback( hwnd32, msg, (WPARAM)WIN_Handle32(wParam), lParam, result, arg ); |
| } |
| break; /* FIXME don't know how to free allocated memory (handle) !! */ |
| case WM_DDE_ACK: |
| { |
| UINT lo = LOWORD(lParam); |
| UINT hi = HIWORD(lParam); |
| int flag = 0; |
| char buf[2]; |
| |
| if (GlobalGetAtomNameA(hi, buf, 2) > 0) flag |= 1; |
| if (GlobalSize16(hi) != 0) flag |= 2; |
| switch (flag) |
| { |
| case 0: |
| if (hi) |
| { |
| MESSAGE("DDE_ACK: neither atom nor handle!!!\n"); |
| hi = 0; |
| } |
| break; |
| case 1: |
| break; /* atom, nothing to do */ |
| case 3: |
| MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi); |
| /* fall thru */ |
| case 2: |
| hi = convert_handle_16_to_32(hi, GMEM_DDESHARE); |
| break; |
| } |
| lParam = PackDDElParam( WM_DDE_ACK, lo, hi ); |
| ret = callback( hwnd32, msg, (WPARAM)WIN_Handle32(wParam), lParam, result, arg ); |
| } |
| break; /* FIXME don't know how to free allocated memory (handle) !! */ |
| case WM_DDE_EXECUTE: |
| lParam = convert_handle_16_to_32( lParam, GMEM_DDESHARE ); |
| ret = callback( hwnd32, msg, wParam, lParam, result, arg ); |
| break; /* FIXME don't know how to free allocated memory (handle) !! */ |
| case WM_PAINTCLIPBOARD: |
| case WM_SIZECLIPBOARD: |
| FIXME_(msg)( "message %04x needs translation\n", msg ); |
| break; |
| default: |
| ret = callback( hwnd32, msg, wParam, lParam, result, arg ); |
| break; |
| } |
| return ret; |
| } |
| |
| |
| /********************************************************************** |
| * __wine_call_wndproc (USER.1010) |
| */ |
| LRESULT WINAPI __wine_call_wndproc( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam, |
| WINDOWPROC *proc ) |
| { |
| LRESULT result; |
| |
| if (proc->procA) |
| WINPROC_CallProc16To32A( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA ); |
| else |
| WINPROC_CallProc16To32A( call_window_proc_AtoW, hwnd, msg, wParam, lParam, &result, proc->procW ); |
| return result; |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallProc32ATo16 |
| * |
| * Call a 16-bit window procedure, translating the 32-bit args. |
| */ |
| LRESULT WINPROC_CallProc32ATo16( winproc_callback16_t callback, HWND hwnd, UINT msg, |
| WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg ) |
| { |
| LRESULT ret = 0; |
| |
| TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n", |
| hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam); |
| |
| switch(msg) |
| { |
| case WM_NCCREATE: |
| case WM_CREATE: |
| { |
| CREATESTRUCTA *cs32 = (CREATESTRUCTA *)lParam; |
| CREATESTRUCT16 cs; |
| MDICREATESTRUCT16 mdi_cs16; |
| BOOL mdi_child = (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD); |
| |
| CREATESTRUCT32Ato16( cs32, &cs ); |
| cs.lpszName = MapLS( cs32->lpszName ); |
| cs.lpszClass = MapLS( cs32->lpszClass ); |
| |
| if (mdi_child) |
| { |
| MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs32->lpCreateParams; |
| MDICREATESTRUCT32Ato16( mdi_cs, &mdi_cs16 ); |
| mdi_cs16.szTitle = MapLS( mdi_cs->szTitle ); |
| mdi_cs16.szClass = MapLS( mdi_cs->szClass ); |
| cs.lpCreateParams = MapLS( &mdi_cs16 ); |
| } |
| lParam = MapLS( &cs ); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| UnMapLS( cs.lpszName ); |
| UnMapLS( cs.lpszClass ); |
| if (mdi_child) |
| { |
| UnMapLS( cs.lpCreateParams ); |
| UnMapLS( mdi_cs16.szTitle ); |
| UnMapLS( mdi_cs16.szClass ); |
| } |
| } |
| break; |
| case WM_MDICREATE: |
| { |
| MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)lParam; |
| MDICREATESTRUCT16 cs; |
| |
| MDICREATESTRUCT32Ato16( cs32, &cs ); |
| cs.szTitle = MapLS( cs32->szTitle ); |
| cs.szClass = MapLS( cs32->szClass ); |
| lParam = MapLS( &cs ); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| UnMapLS( cs.szTitle ); |
| UnMapLS( cs.szClass ); |
| } |
| break; |
| case WM_MDIACTIVATE: |
| if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD) |
| ret = callback( HWND_16(hwnd), msg, ((HWND)lParam == hwnd), |
| MAKELPARAM( LOWORD(lParam), LOWORD(wParam) ), result, arg ); |
| else |
| ret = callback( HWND_16(hwnd), msg, HWND_16( (HWND)wParam ), 0, result, arg ); |
| break; |
| case WM_MDIGETACTIVE: |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(*result); |
| *result = (LRESULT)WIN_Handle32( LOWORD(*result) ); |
| break; |
| case WM_MDISETMENU: |
| ret = callback( HWND_16(hwnd), msg, (lParam == 0), |
| MAKELPARAM( LOWORD(wParam), LOWORD(lParam) ), result, arg ); |
| break; |
| case WM_GETMINMAXINFO: |
| { |
| MINMAXINFO *mmi32 = (MINMAXINFO *)lParam; |
| MINMAXINFO16 mmi; |
| |
| MINMAXINFO32to16( mmi32, &mmi ); |
| lParam = MapLS( &mmi ); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| MINMAXINFO16to32( &mmi, mmi32 ); |
| } |
| break; |
| case WM_NCCALCSIZE: |
| { |
| NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)lParam; |
| NCCALCSIZE_PARAMS16 nc; |
| WINDOWPOS16 winpos; |
| |
| RECT32to16( &nc32->rgrc[0], &nc.rgrc[0] ); |
| if (wParam) |
| { |
| RECT32to16( &nc32->rgrc[1], &nc.rgrc[1] ); |
| RECT32to16( &nc32->rgrc[2], &nc.rgrc[2] ); |
| WINDOWPOS32to16( nc32->lppos, &winpos ); |
| nc.lppos = MapLS( &winpos ); |
| } |
| lParam = MapLS( &nc ); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| RECT16to32( &nc.rgrc[0], &nc32->rgrc[0] ); |
| if (wParam) |
| { |
| RECT16to32( &nc.rgrc[1], &nc32->rgrc[1] ); |
| RECT16to32( &nc.rgrc[2], &nc32->rgrc[2] ); |
| WINDOWPOS16to32( &winpos, nc32->lppos ); |
| UnMapLS( nc.lppos ); |
| } |
| } |
| break; |
| case WM_WINDOWPOSCHANGING: |
| case WM_WINDOWPOSCHANGED: |
| { |
| WINDOWPOS *winpos32 = (WINDOWPOS *)lParam; |
| WINDOWPOS16 winpos; |
| |
| WINDOWPOS32to16( winpos32, &winpos ); |
| lParam = MapLS( &winpos ); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| WINDOWPOS16to32( &winpos, winpos32 ); |
| } |
| break; |
| case WM_COMPAREITEM: |
| { |
| COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)lParam; |
| COMPAREITEMSTRUCT16 cis; |
| cis.CtlType = cis32->CtlType; |
| cis.CtlID = cis32->CtlID; |
| cis.hwndItem = HWND_16( cis32->hwndItem ); |
| cis.itemID1 = cis32->itemID1; |
| cis.itemData1 = cis32->itemData1; |
| cis.itemID2 = cis32->itemID2; |
| cis.itemData2 = cis32->itemData2; |
| lParam = MapLS( &cis ); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| } |
| break; |
| case WM_DELETEITEM: |
| { |
| DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)lParam; |
| DELETEITEMSTRUCT16 dis; |
| dis.CtlType = dis32->CtlType; |
| dis.CtlID = dis32->CtlID; |
| dis.itemID = dis32->itemID; |
| dis.hwndItem = (dis.CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem) |
| : HWND_16( dis32->hwndItem ); |
| dis.itemData = dis32->itemData; |
| lParam = MapLS( &dis ); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| } |
| break; |
| case WM_DRAWITEM: |
| { |
| DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)lParam; |
| DRAWITEMSTRUCT16 dis; |
| dis.CtlType = dis32->CtlType; |
| dis.CtlID = dis32->CtlID; |
| dis.itemID = dis32->itemID; |
| dis.itemAction = dis32->itemAction; |
| dis.itemState = dis32->itemState; |
| dis.hwndItem = HWND_16( dis32->hwndItem ); |
| dis.hDC = HDC_16(dis32->hDC); |
| dis.itemData = dis32->itemData; |
| dis.rcItem.left = dis32->rcItem.left; |
| dis.rcItem.top = dis32->rcItem.top; |
| dis.rcItem.right = dis32->rcItem.right; |
| dis.rcItem.bottom = dis32->rcItem.bottom; |
| lParam = MapLS( &dis ); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| } |
| break; |
| case WM_MEASUREITEM: |
| { |
| MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)lParam; |
| MEASUREITEMSTRUCT16 mis; |
| mis.CtlType = mis32->CtlType; |
| mis.CtlID = mis32->CtlID; |
| mis.itemID = mis32->itemID; |
| mis.itemWidth = mis32->itemWidth; |
| mis.itemHeight = mis32->itemHeight; |
| mis.itemData = mis32->itemData; |
| lParam = MapLS( &mis ); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| mis32->itemWidth = mis.itemWidth; |
| mis32->itemHeight = mis.itemHeight; |
| } |
| break; |
| case WM_COPYDATA: |
| { |
| COPYDATASTRUCT *cds32 = (COPYDATASTRUCT *)lParam; |
| COPYDATASTRUCT16 cds; |
| |
| cds.dwData = cds32->dwData; |
| cds.cbData = cds32->cbData; |
| cds.lpData = MapLS( cds32->lpData ); |
| lParam = MapLS( &cds ); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| UnMapLS( cds.lpData ); |
| } |
| break; |
| case WM_GETDLGCODE: |
| if (lParam) |
| { |
| MSG *msg32 = (MSG *)lParam; |
| MSG16 msg16; |
| |
| msg16.hwnd = HWND_16( msg32->hwnd ); |
| msg16.message = msg32->message; |
| msg16.wParam = msg32->wParam; |
| msg16.lParam = msg32->lParam; |
| msg16.time = msg32->time; |
| msg16.pt.x = msg32->pt.x; |
| msg16.pt.y = msg32->pt.y; |
| lParam = MapLS( &msg16 ); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| } |
| else |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| break; |
| case WM_NEXTMENU: |
| { |
| MDINEXTMENU *next = (MDINEXTMENU *)lParam; |
| ret = callback( HWND_16(hwnd), msg, wParam, (LPARAM)next->hmenuIn, result, arg ); |
| next->hmenuNext = HMENU_32( LOWORD(*result) ); |
| next->hwndNext = WIN_Handle32( HIWORD(*result) ); |
| *result = 0; |
| } |
| break; |
| case WM_GETTEXT: |
| case WM_ASKCBFORMATNAME: |
| wParam = min( wParam, 0xff80 ); /* Must be < 64K */ |
| /* fall through */ |
| case WM_NOTIFY: |
| case WM_SETTEXT: |
| case WM_WININICHANGE: |
| case WM_DEVMODECHANGE: |
| lParam = MapLS( (void *)lParam ); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| break; |
| case WM_ACTIVATE: |
| case WM_CHARTOITEM: |
| case WM_COMMAND: |
| case WM_VKEYTOITEM: |
| ret = callback( HWND_16(hwnd), msg, wParam, MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ), |
| result, arg ); |
| break; |
| case WM_HSCROLL: |
| case WM_VSCROLL: |
| ret = callback( HWND_16(hwnd), msg, wParam, MAKELPARAM( HIWORD(wParam), (HWND16)lParam ), |
| result, arg ); |
| break; |
| case WM_CTLCOLORMSGBOX: |
| case WM_CTLCOLOREDIT: |
| case WM_CTLCOLORLISTBOX: |
| case WM_CTLCOLORBTN: |
| case WM_CTLCOLORDLG: |
| case WM_CTLCOLORSCROLLBAR: |
| case WM_CTLCOLORSTATIC: |
| ret = callback( HWND_16(hwnd), WM_CTLCOLOR, wParam, |
| MAKELPARAM( (HWND16)lParam, msg - WM_CTLCOLORMSGBOX ), result, arg ); |
| break; |
| case WM_MENUSELECT: |
| if(HIWORD(wParam) & MF_POPUP) |
| { |
| HMENU hmenu; |
| if ((HIWORD(wParam) != 0xffff) || lParam) |
| { |
| if ((hmenu = GetSubMenu( (HMENU)lParam, LOWORD(wParam) ))) |
| { |
| ret = callback( HWND_16(hwnd), msg, HMENU_16(hmenu), |
| MAKELPARAM( HIWORD(wParam), (HMENU16)lParam ), result, arg ); |
| break; |
| } |
| } |
| } |
| /* fall through */ |
| case WM_MENUCHAR: |
| ret = callback( HWND_16(hwnd), msg, wParam, |
| MAKELPARAM( HIWORD(wParam), (HMENU16)lParam ), result, arg ); |
| break; |
| case WM_PARENTNOTIFY: |
| if ((LOWORD(wParam) == WM_CREATE) || (LOWORD(wParam) == WM_DESTROY)) |
| ret = callback( HWND_16(hwnd), msg, wParam, |
| MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ), result, arg ); |
| else |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| break; |
| case WM_ACTIVATEAPP: |
| ret = callback( HWND_16(hwnd), msg, wParam, HTASK_16( (HANDLE)lParam ), result, arg ); |
| break; |
| case WM_PAINT: |
| if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON )) |
| ret = callback( HWND_16(hwnd), WM_PAINTICON, 1, lParam, result, arg ); |
| else |
| ret = callback( HWND_16(hwnd), WM_PAINT, wParam, lParam, result, arg ); |
| break; |
| case WM_ERASEBKGND: |
| if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON )) msg = WM_ICONERASEBKGND; |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| break; |
| case WM_DDE_INITIATE: |
| case WM_DDE_TERMINATE: |
| case WM_DDE_UNADVISE: |
| case WM_DDE_REQUEST: |
| ret = callback( HWND_16(hwnd), msg, HWND_16((HWND)wParam), lParam, result, arg ); |
| break; |
| case WM_DDE_ADVISE: |
| case WM_DDE_DATA: |
| case WM_DDE_POKE: |
| { |
| UINT_PTR lo32, hi; |
| HANDLE16 lo16 = 0; |
| |
| UnpackDDElParam( msg, lParam, &lo32, &hi ); |
| if (lo32 && !(lo16 = convert_handle_32_to_16(lo32, GMEM_DDESHARE))) break; |
| ret = callback( HWND_16(hwnd), msg, HWND_16((HWND)wParam), |
| MAKELPARAM(lo16, hi), result, arg ); |
| } |
| break; /* FIXME don't know how to free allocated memory (handle) !! */ |
| case WM_DDE_ACK: |
| { |
| UINT_PTR lo, hi; |
| int flag = 0; |
| char buf[2]; |
| |
| UnpackDDElParam( msg, lParam, &lo, &hi ); |
| |
| if (GlobalGetAtomNameA((ATOM)hi, buf, sizeof(buf)) > 0) flag |= 1; |
| if (GlobalSize((HANDLE)hi) != 0) flag |= 2; |
| switch (flag) |
| { |
| case 0: |
| if (hi) |
| { |
| MESSAGE("DDE_ACK: neither atom nor handle!!!\n"); |
| hi = 0; |
| } |
| break; |
| case 1: |
| break; /* atom, nothing to do */ |
| case 3: |
| MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi); |
| /* fall thru */ |
| case 2: |
| hi = convert_handle_32_to_16(hi, GMEM_DDESHARE); |
| break; |
| } |
| ret = callback( HWND_16(hwnd), msg, HWND_16((HWND)wParam), |
| MAKELPARAM(lo, hi), result, arg ); |
| } |
| break; /* FIXME don't know how to free allocated memory (handle) !! */ |
| case WM_DDE_EXECUTE: |
| lParam = convert_handle_32_to_16(lParam, GMEM_DDESHARE); |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| break; /* FIXME don't know how to free allocated memory (handle) !! */ |
| case SBM_SETRANGE: |
| ret = callback( HWND_16(hwnd), SBM_SETRANGE16, 0, MAKELPARAM(wParam, lParam), result, arg ); |
| break; |
| case SBM_GETRANGE: |
| ret = callback( HWND_16(hwnd), SBM_GETRANGE16, wParam, lParam, result, arg ); |
| *(LPINT)wParam = LOWORD(*result); |
| *(LPINT)lParam = HIWORD(*result); |
| break; |
| case BM_GETCHECK: |
| case BM_SETCHECK: |
| case BM_GETSTATE: |
| case BM_SETSTATE: |
| case BM_SETSTYLE: |
| ret = callback( HWND_16(hwnd), msg + BM_GETCHECK16 - BM_GETCHECK, wParam, lParam, result, arg ); |
| break; |
| case EM_GETSEL: |
| case EM_GETRECT: |
| case EM_SETRECT: |
| case EM_SETRECTNP: |
| case EM_SCROLL: |
| case EM_LINESCROLL: |
| case EM_SCROLLCARET: |
| case EM_GETMODIFY: |
| case EM_SETMODIFY: |
| case EM_GETLINECOUNT: |
| case EM_LINEINDEX: |
| case EM_SETHANDLE: |
| case EM_GETHANDLE: |
| case EM_GETTHUMB: |
| case EM_LINELENGTH: |
| case EM_REPLACESEL: |
| case EM_GETLINE: |
| case EM_LIMITTEXT: |
| case EM_CANUNDO: |
| case EM_UNDO: |
| case EM_FMTLINES: |
| case EM_LINEFROMCHAR: |
| case EM_SETTABSTOPS: |
| case EM_SETPASSWORDCHAR: |
| case EM_EMPTYUNDOBUFFER: |
| case EM_GETFIRSTVISIBLELINE: |
| case EM_SETREADONLY: |
| case EM_SETWORDBREAKPROC: |
| case EM_GETWORDBREAKPROC: |
| case EM_GETPASSWORDCHAR: |
| ret = callback( HWND_16(hwnd), msg + EM_GETSEL16 - EM_GETSEL, wParam, lParam, result, arg ); |
| break; |
| case EM_SETSEL: |
| ret = callback( HWND_16(hwnd), EM_SETSEL16, 0, MAKELPARAM( wParam, lParam ), result, arg ); |
| break; |
| case LB_CARETOFF: |
| case LB_CARETON: |
| case LB_DELETESTRING: |
| case LB_GETANCHORINDEX: |
| case LB_GETCARETINDEX: |
| case LB_GETCOUNT: |
| case LB_GETCURSEL: |
| case LB_GETHORIZONTALEXTENT: |
| case LB_GETITEMDATA: |
| case LB_GETITEMHEIGHT: |
| case LB_GETSEL: |
| case LB_GETSELCOUNT: |
| case LB_GETTEXTLEN: |
| case LB_GETTOPINDEX: |
| case LB_RESETCONTENT: |
| case LB_SELITEMRANGE: |
| case LB_SELITEMRANGEEX: |
| case LB_SETANCHORINDEX: |
| case LB_SETCARETINDEX: |
| case LB_SETCOLUMNWIDTH: |
| case LB_SETCURSEL: |
| case LB_SETHORIZONTALEXTENT: |
| case LB_SETITEMDATA: |
| case LB_SETITEMHEIGHT: |
| case LB_SETSEL: |
| case LB_SETTOPINDEX: |
| ret = callback( HWND_16(hwnd), msg + LB_ADDSTRING16 - LB_ADDSTRING, wParam, lParam, result, arg ); |
| break; |
| case LB_ADDSTRING: |
| case LB_FINDSTRING: |
| case LB_FINDSTRINGEXACT: |
| case LB_INSERTSTRING: |
| case LB_SELECTSTRING: |
| case LB_GETTEXT: |
| case LB_DIR: |
| case LB_ADDFILE: |
| lParam = MapLS( (LPSTR)lParam ); |
| ret = callback( HWND_16(hwnd), msg + LB_ADDSTRING16 - LB_ADDSTRING, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| break; |
| case LB_GETSELITEMS: |
| { |
| INT *items32 = (INT *)lParam; |
| INT16 *items, buffer[512]; |
| unsigned int i; |
| |
| wParam = min( wParam, 0x7f80 ); /* Must be < 64K */ |
| if (!(items = get_buffer( buffer, sizeof(buffer), wParam * sizeof(INT16) ))) break; |
| lParam = MapLS( items ); |
| ret = callback( HWND_16(hwnd), LB_GETSELITEMS16, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| for (i = 0; i < wParam; i++) items32[i] = items[i]; |
| free_buffer( buffer, items ); |
| } |
| break; |
| case LB_SETTABSTOPS: |
| if (wParam) |
| { |
| INT *stops32 = (INT *)lParam; |
| INT16 *stops, buffer[512]; |
| unsigned int i; |
| |
| wParam = min( wParam, 0x7f80 ); /* Must be < 64K */ |
| if (!(stops = get_buffer( buffer, sizeof(buffer), wParam * sizeof(INT16) ))) break; |
| for (i = 0; i < wParam; i++) stops[i] = stops32[i]; |
| lParam = MapLS( stops ); |
| ret = callback( HWND_16(hwnd), LB_SETTABSTOPS16, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| free_buffer( buffer, stops ); |
| } |
| else ret = callback( HWND_16(hwnd), LB_SETTABSTOPS16, wParam, lParam, result, arg ); |
| break; |
| case CB_DELETESTRING: |
| case CB_GETCOUNT: |
| case CB_GETLBTEXTLEN: |
| case CB_LIMITTEXT: |
| case CB_RESETCONTENT: |
| case CB_SETEDITSEL: |
| case CB_GETCURSEL: |
| case CB_SETCURSEL: |
| case CB_SHOWDROPDOWN: |
| case CB_SETITEMDATA: |
| case CB_SETITEMHEIGHT: |
| case CB_GETITEMHEIGHT: |
| case CB_SETEXTENDEDUI: |
| case CB_GETEXTENDEDUI: |
| case CB_GETDROPPEDSTATE: |
| ret = callback( HWND_16(hwnd), msg + CB_GETEDITSEL16 - CB_GETEDITSEL, wParam, lParam, result, arg ); |
| break; |
| case CB_GETEDITSEL: |
| ret = callback( HWND_16(hwnd), CB_GETEDITSEL16, wParam, lParam, result, arg ); |
| if (wParam) *((PUINT)(wParam)) = LOWORD(*result); |
| if (lParam) *((PUINT)(lParam)) = HIWORD(*result); /* FIXME: substract 1? */ |
| break; |
| case CB_ADDSTRING: |
| case CB_FINDSTRING: |
| case CB_FINDSTRINGEXACT: |
| case CB_INSERTSTRING: |
| case CB_SELECTSTRING: |
| case CB_DIR: |
| case CB_GETLBTEXT: |
| lParam = MapLS( (LPSTR)lParam ); |
| ret = callback( HWND_16(hwnd), msg + CB_GETEDITSEL16 - CB_GETEDITSEL, wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| break; |
| case LB_GETITEMRECT: |
| case CB_GETDROPPEDCONTROLRECT: |
| { |
| RECT *r32 = (RECT *)lParam; |
| RECT16 rect; |
| lParam = MapLS( &rect ); |
| ret = callback( HWND_16(hwnd), |
| (msg == LB_GETITEMRECT) ? LB_GETITEMRECT16 : CB_GETDROPPEDCONTROLRECT16, |
| wParam, lParam, result, arg ); |
| UnMapLS( lParam ); |
| RECT16to32( &rect, r32 ); |
| } |
| break; |
| case WM_PAINTCLIPBOARD: |
| case WM_SIZECLIPBOARD: |
| FIXME_(msg)( "message %04x needs translation\n", msg ); |
| break; |
| /* the following messages should not be sent to 16-bit apps */ |
| case WM_SIZING: |
| case WM_MOVING: |
| case WM_CAPTURECHANGED: |
| case WM_STYLECHANGING: |
| case WM_STYLECHANGED: |
| break; |
| default: |
| ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg ); |
| break; |
| } |
| return ret; |
| } |
| |
| |
| /********************************************************************** |
| * CallWindowProc (USER.122) |
| */ |
| LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg, |
| WPARAM16 wParam, LPARAM lParam ) |
| { |
| WINDOWPROC *proc; |
| LRESULT result; |
| |
| if (!func) return 0; |
| |
| if (!(proc = handle16_to_proc( func ))) |
| call_window_proc16( hwnd, msg, wParam, lParam, &result, func ); |
| else if (proc->procA) |
| WINPROC_CallProc16To32A( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA ); |
| else if (proc->procW) |
| WINPROC_CallProc16To32A( call_window_proc_AtoW, hwnd, msg, wParam, lParam, &result, proc->procW ); |
| else |
| call_window_proc16( hwnd, msg, wParam, lParam, &result, proc->proc16 ); |
| |
| return result; |
| } |
| |
| |
| /********************************************************************** |
| * CallWindowProcA (USER32.@) |
| * |
| * The CallWindowProc() function invokes the windows procedure _func_, |
| * with _hwnd_ as the target window, the message specified by _msg_, and |
| * the message parameters _wParam_ and _lParam_. |
| * |
| * Some kinds of argument conversion may be done, I'm not sure what. |
| * |
| * CallWindowProc() may be used for windows subclassing. Use |
| * SetWindowLong() to set a new windows procedure for windows of the |
| * subclass, and handle subclassed messages in the new windows |
| * procedure. The new windows procedure may then use CallWindowProc() |
| * with _func_ set to the parent class's windows procedure to dispatch |
| * the message to the superclass. |
| * |
| * RETURNS |
| * |
| * The return value is message dependent. |
| * |
| * CONFORMANCE |
| * |
| * ECMA-234, Win32 |
| */ |
| LRESULT WINAPI CallWindowProcA( |
| WNDPROC func, /* [in] window procedure */ |
| HWND hwnd, /* [in] target window */ |
| UINT msg, /* [in] message */ |
| WPARAM wParam, /* [in] message dependent parameter */ |
| LPARAM lParam /* [in] message dependent parameter */ |
| ) { |
| WINDOWPROC *proc; |
| LRESULT result; |
| |
| if (!func) return 0; |
| |
| if (!(proc = handle_to_proc( func ))) |
| call_window_proc( hwnd, msg, wParam, lParam, &result, func ); |
| else if (proc->procA) |
| call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procA ); |
| else if (proc->procW) |
| WINPROC_CallProcAtoW( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW ); |
| else |
| WINPROC_CallProc32ATo16( call_window_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 ); |
| return result; |
| } |
| |
| |
| /********************************************************************** |
| * CallWindowProcW (USER32.@) |
| * |
| * See CallWindowProcA. |
| */ |
| LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg, |
| WPARAM wParam, LPARAM lParam ) |
| { |
| WINDOWPROC *proc; |
| LRESULT result; |
| |
| if (!func) return 0; |
| |
| if (!(proc = handle_to_proc( func ))) |
| call_window_proc( hwnd, msg, wParam, lParam, &result, func ); |
| else if (proc->procW) |
| call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procW ); |
| else if (proc->procA) |
| WINPROC_CallProcWtoA( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA ); |
| else |
| WINPROC_CallProcWtoA( call_window_proc_Ato16, hwnd, msg, wParam, lParam, &result, proc->proc16 ); |
| return result; |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallDlgProc16 |
| */ |
| INT_PTR WINPROC_CallDlgProc16( DLGPROC16 func, HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam ) |
| { |
| WINDOWPROC *proc; |
| LRESULT result; |
| INT_PTR ret; |
| |
| if (!func) return 0; |
| |
| if (!(proc = handle16_to_proc( (WNDPROC16)func ))) |
| { |
| ret = call_dialog_proc16( hwnd, msg, wParam, lParam, &result, func ); |
| } |
| else if (proc->procA) |
| { |
| ret = WINPROC_CallProc16To32A( call_dialog_proc, hwnd, msg, wParam, lParam, |
| &result, proc->procA ); |
| SetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT, result ); |
| } |
| else if (proc->procW) |
| { |
| ret = WINPROC_CallProc16To32A( call_dialog_proc_AtoW, hwnd, msg, wParam, lParam, |
| &result, proc->procW ); |
| SetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT, result ); |
| } |
| else |
| { |
| ret = call_dialog_proc16( hwnd, msg, wParam, lParam, &result, proc->proc16 ); |
| } |
| return ret; |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallDlgProcA |
| */ |
| INT_PTR WINPROC_CallDlgProcA( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) |
| { |
| WINDOWPROC *proc; |
| LRESULT result; |
| INT_PTR ret; |
| |
| if (!func) return 0; |
| |
| if (!(proc = handle_to_proc( (WNDPROC)func ))) |
| ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, func ); |
| else if (proc->procA) |
| ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procA ); |
| else if (proc->procW) |
| { |
| ret = WINPROC_CallProcAtoW( call_dialog_proc, hwnd, msg, wParam, lParam, &result, proc->procW ); |
| SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result ); |
| } |
| else |
| { |
| ret = WINPROC_CallProc32ATo16( call_dialog_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 ); |
| SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result ); |
| } |
| return ret; |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallDlgProcW |
| */ |
| INT_PTR WINPROC_CallDlgProcW( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) |
| { |
| WINDOWPROC *proc; |
| LRESULT result; |
| INT_PTR ret; |
| |
| if (!func) return 0; |
| |
| if (!(proc = handle_to_proc( (WNDPROC)func ))) |
| ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, func ); |
| else if (proc->procW) |
| ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procW ); |
| else if (proc->procA) |
| { |
| ret = WINPROC_CallProcWtoA( call_dialog_proc, hwnd, msg, wParam, lParam, &result, proc->procA ); |
| SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result ); |
| } |
| else |
| { |
| ret = WINPROC_CallProcWtoA( call_dialog_proc_Ato16, hwnd, msg, wParam, lParam, &result, proc->proc16 ); |
| SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result ); |
| } |
| return ret; |
| } |